@@ -24,6 +24,7 @@ import {
2424import { Options , BindOption } from "./utils" ;
2525import { TypeDocOptions } from "./utils/options/declaration" ;
2626import { flatMap } from "./utils/array" ;
27+ import { basename } from "path" ;
2728
2829// eslint-disable-next-line @typescript-eslint/no-var-requires
2930const packageInfo = require ( "../../package.json" ) as {
@@ -238,12 +239,133 @@ export class Application extends ChildableComponent<
238239 return ;
239240 }
240241
242+ if ( this . application . options . getValue ( "emit" ) ) {
243+ for ( const program of programs ) {
244+ program . emit ( ) ;
245+ }
246+ }
247+
241248 return this . converter . convert (
242249 this . expandInputFiles ( this . entryPoints ) ,
243250 programs
244251 ) ;
245252 }
246253
254+ public convertAndWatch (
255+ success : ( project : ProjectReflection ) => Promise < void >
256+ ) : void {
257+ if (
258+ ! this . options . getValue ( "preserveWatchOutput" ) &&
259+ this . logger instanceof ConsoleLogger
260+ ) {
261+ ts . sys . clearScreen ?.( ) ;
262+ }
263+
264+ this . logger . verbose (
265+ "Using TypeScript %s from %s" ,
266+ this . getTypeScriptVersion ( ) ,
267+ this . getTypeScriptPath ( )
268+ ) ;
269+
270+ if (
271+ ! supportedVersionMajorMinor . some (
272+ ( version ) => version == ts . versionMajorMinor
273+ )
274+ ) {
275+ this . logger . warn (
276+ `You are running with an unsupported TypeScript version! TypeDoc supports ${ supportedVersionMajorMinor . join (
277+ ", "
278+ ) } `
279+ ) ;
280+ }
281+
282+ if ( Object . keys ( this . options . getCompilerOptions ( ) ) . length === 0 ) {
283+ this . logger . warn (
284+ `No compiler options set. This likely means that TypeDoc did not find your tsconfig.json. Generated documentation will probably be empty.`
285+ ) ;
286+ }
287+
288+ // Doing this is considerably more complicated, we'd need to manage an array of programs, not convert until all programs
289+ // have reported in the first time... just error out for now. I'm not convinced anyone will actually notice.
290+ if ( this . application . options . getFileNames ( ) . length === 0 ) {
291+ this . logger . error (
292+ "The provided tsconfig file looks like a solution style tsconfig, which is not supported in watch mode."
293+ ) ;
294+ return ;
295+ }
296+
297+ // Matches the behavior of the tsconfig option reader.
298+ let tsconfigFile = this . options . getValue ( "tsconfig" ) ;
299+ tsconfigFile =
300+ ts . findConfigFile (
301+ tsconfigFile ,
302+ ts . sys . fileExists ,
303+ tsconfigFile . toLowerCase ( ) . endsWith ( ".json" )
304+ ? basename ( tsconfigFile )
305+ : undefined
306+ ) ?? "tsconfig.json" ;
307+
308+ // We don't want to do it the first time to preserve initial debug status messages. They'll be lost
309+ // after the user saves a file, but better than nothing...
310+ let firstStatusReport = true ;
311+
312+ const host = ts . createWatchCompilerHost (
313+ tsconfigFile ,
314+ { noEmit : ! this . application . options . getValue ( "emit" ) } ,
315+ ts . sys ,
316+ ts . createEmitAndSemanticDiagnosticsBuilderProgram ,
317+ ( diagnostic ) => this . logger . diagnostic ( diagnostic ) ,
318+ ( status , newLine , _options , errorCount ) => {
319+ if (
320+ ! firstStatusReport &&
321+ errorCount === void 0 &&
322+ ! this . options . getValue ( "preserveWatchOutput" ) &&
323+ this . logger instanceof ConsoleLogger
324+ ) {
325+ ts . sys . clearScreen ?.( ) ;
326+ }
327+ firstStatusReport = false ;
328+ this . logger . write (
329+ ts . flattenDiagnosticMessageText ( status . messageText , newLine )
330+ ) ;
331+ }
332+ ) ;
333+
334+ let successFinished = true ;
335+ let currentProgram : ts . Program | undefined ;
336+
337+ const runSuccess = ( ) => {
338+ if ( ! currentProgram ) {
339+ return ;
340+ }
341+
342+ if ( successFinished ) {
343+ this . logger . resetErrors ( ) ;
344+ const project = this . converter . convert (
345+ this . expandInputFiles ( this . entryPoints ) ,
346+ currentProgram
347+ ) ;
348+ currentProgram = undefined ;
349+ successFinished = false ;
350+ success ( project ) . then ( ( ) => {
351+ successFinished = true ;
352+ runSuccess ( ) ;
353+ } ) ;
354+ }
355+ } ;
356+
357+ const origAfterProgramCreate = host . afterProgramCreate ;
358+ host . afterProgramCreate = ( program ) => {
359+ if ( ts . getPreEmitDiagnostics ( program . getProgram ( ) ) . length === 0 ) {
360+ currentProgram = program . getProgram ( ) ;
361+ runSuccess ( ) ;
362+ }
363+ origAfterProgramCreate ?.( program ) ;
364+ } ;
365+
366+ ts . createWatchProgram ( host ) ;
367+ }
368+
247369 /**
248370 * Render HTML for the given project
249371 */
0 commit comments