diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index a4f3bbefac2..fc52559a318 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -549,8 +549,8 @@ namespace ts { * Create the builder to manage semantic diagnostics and cache them */ export function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; - export function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; - export function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | ReadonlyArray, hostOrOptions: BuilderProgramHost | CompilerOptions, oldProgramOrHost?: CompilerHost | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray) { + export function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; + export function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray) { return createBuilderProgram(BuilderProgramKind.SemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics)); } @@ -559,8 +559,8 @@ namespace ts { * to emit the those files and manage semantic diagnostics cache as well */ export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; - export function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; - export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | ReadonlyArray, hostOrOptions: BuilderProgramHost | CompilerOptions, oldProgramOrHost?: CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray) { + export function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; + export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray) { return createBuilderProgram(BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics)); } @@ -568,8 +568,8 @@ namespace ts { * Creates a builder thats just abstraction over program and can be used with watch */ export function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; - export function createAbstractBuilder(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; - export function createAbstractBuilder(newProgramOrRootNames: Program | ReadonlyArray, hostOrOptions: BuilderProgramHost | CompilerOptions, oldProgramOrHost?: CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram { + export function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; + export function createAbstractBuilder(newProgramOrRootNames: Program | ReadonlyArray | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: ReadonlyArray | BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram { const { newProgram: program } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics); return { // Only return program, all other methods are not implemented diff --git a/tests/baselines/reference/APISample_Watch.js b/tests/baselines/reference/APISample_Watch.js new file mode 100644 index 00000000000..5e3a67e827d --- /dev/null +++ b/tests/baselines/reference/APISample_Watch.js @@ -0,0 +1,133 @@ +//// [APISample_Watch.ts] +/* + * Note: This test is a public API sample. The sample sources can be found + at: https://github.com/Microsoft/TypeScript-wiki/blob/master/Using-the-Compiler-API.md#writing-an-incremental-program-watcher + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var process: any; +declare var console: any; +declare var os: any; + +import ts = require("typescript"); + +const formatHost: ts.FormatDiagnosticsHost = { + getCanonicalFileName: path => path, + getCurrentDirectory: ts.sys.getCurrentDirectory, + getNewLine: () => ts.sys.newLine, +} + +function watchMain() { + const configPath = ts.findConfigFile(/*searchPath*/ "./", ts.sys.fileExists, "tsconfig.json"); + if (!configPath) { + throw new Error("Could not find a valid 'tsconfig.json'."); + } + + // TypeScript can use several different program creation "strategies": + // * ts.createEmitAndSemanticDiagnosticsBuilderProgram, + // * ts.createSemanticDiagnosticsBuilderProgram + // * ts.createAbstractBuilder + // The first two produce "builder programs". These use an incremental strategy to only re-check and emit files whose + // contents may have changed, or whose dependencies may have changes which may impact change the result of prior type-check and emit. + // The last uses an ordinary program which does a full type check after every change. + // Between `createEmitAndSemanticDiagnosticsBuilderProgram` and `createSemanticDiagnosticsBuilderProgram`, the only difference is emit. + // For pure type-checking scenarios, or when another tool/process handles emit, using `createSemanticDiagnosticsBuilderProgram` may be more desirable. + + // Note that there is another overload for `createWatchCompilerHost` that takes a set of root files. + const host = ts.createWatchCompilerHost(configPath, {}, ts.sys, + ts.createSemanticDiagnosticsBuilderProgram, + reportDiagnostic, + reportWatchStatusChanged, + ); + + // You can technically override any given hook on the host, though you probably don't need to. + // Note that we're assuming `origCreateProgram` and `origPostProgramCreate` doesn't use `this` at all. + const origCreateProgram = host.createProgram; + host.createProgram = (rootNames: ReadonlyArray, options, host, oldProgram) => { + console.log("** We're about to create the program! **"); + return origCreateProgram(rootNames, options, host, oldProgram); + } + const origPostProgramCreate = host.afterProgramCreate; + + host.afterProgramCreate = program => { + console.log("** We finished making the program! **"); + origPostProgramCreate!(program); + }; + + // `createWatchProgram` creates an initial program, watches files, and updates the program over time. + ts.createWatchProgram(host); +} + +function reportDiagnostic(diagnostic: ts.Diagnostic) { + console.error("Error", diagnostic.code, ":", + ts.flattenDiagnosticMessageText(diagnostic.messageText, formatHost.getNewLine()) + ); +} + +/** + * Prints a diagnostic every time the watch status changes. + * This is mainly for messages like "Starting compilation" or "Compilation completed". + */ +function reportWatchStatusChanged(diagnostic: ts.Diagnostic) { + console.info(ts.formatDiagnostic(diagnostic, formatHost)); +} + +watchMain(); + + +//// [APISample_Watch.js] +"use strict"; +/* + * Note: This test is a public API sample. The sample sources can be found + at: https://github.com/Microsoft/TypeScript-wiki/blob/master/Using-the-Compiler-API.md#writing-an-incremental-program-watcher + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ +exports.__esModule = true; +var ts = require("typescript"); +var formatHost = { + getCanonicalFileName: function (path) { return path; }, + getCurrentDirectory: ts.sys.getCurrentDirectory, + getNewLine: function () { return ts.sys.newLine; } +}; +function watchMain() { + var configPath = ts.findConfigFile(/*searchPath*/ "./", ts.sys.fileExists, "tsconfig.json"); + if (!configPath) { + throw new Error("Could not find a valid 'tsconfig.json'."); + } + // TypeScript can use several different program creation "strategies": + // * ts.createEmitAndSemanticDiagnosticsBuilderProgram, + // * ts.createSemanticDiagnosticsBuilderProgram + // * ts.createAbstractBuilder + // The first two produce "builder programs". These use an incremental strategy to only re-check and emit files whose + // contents may have changed, or whose dependencies may have changes which may impact change the result of prior type-check and emit. + // The last uses an ordinary program which does a full type check after every change. + // Between `createEmitAndSemanticDiagnosticsBuilderProgram` and `createSemanticDiagnosticsBuilderProgram`, the only difference is emit. + // For pure type-checking scenarios, or when another tool/process handles emit, using `createSemanticDiagnosticsBuilderProgram` may be more desirable. + // Note that there is another overload for `createWatchCompilerHost` that takes a set of root files. + var host = ts.createWatchCompilerHost(configPath, {}, ts.sys, ts.createSemanticDiagnosticsBuilderProgram, reportDiagnostic, reportWatchStatusChanged); + // You can technically override any given hook on the host, though you probably don't need to. + // Note that we're assuming `origCreateProgram` and `origPostProgramCreate` doesn't use `this` at all. + var origCreateProgram = host.createProgram; + host.createProgram = function (rootNames, options, host, oldProgram) { + console.log("** We're about to create the program! **"); + return origCreateProgram(rootNames, options, host, oldProgram); + }; + var origPostProgramCreate = host.afterProgramCreate; + host.afterProgramCreate = function (program) { + console.log("** We finished making the program! **"); + origPostProgramCreate(program); + }; + // `createWatchProgram` creates an initial program, watches files, and updates the program over time. + ts.createWatchProgram(host); +} +function reportDiagnostic(diagnostic) { + console.error("Error", diagnostic.code, ":", ts.flattenDiagnosticMessageText(diagnostic.messageText, formatHost.getNewLine())); +} +/** + * Prints a diagnostic every time the watch status changes. + * This is mainly for messages like "Starting compilation" or "Compilation completed". + */ +function reportWatchStatusChanged(diagnostic) { + console.info(ts.formatDiagnostic(diagnostic, formatHost)); +} +watchMain(); diff --git a/tests/baselines/reference/APISample_WatchWithDefaults.js b/tests/baselines/reference/APISample_WatchWithDefaults.js new file mode 100644 index 00000000000..493bef221f6 --- /dev/null +++ b/tests/baselines/reference/APISample_WatchWithDefaults.js @@ -0,0 +1,90 @@ +//// [APISample_WatchWithDefaults.ts] +/* + * Note: This test is a public API sample. This uses default sys interface without having to pass anything + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var console: any; + +import ts = require("typescript"); + +function watchMain() { + const configPath = ts.findConfigFile(/*searchPath*/ "./", ts.sys.fileExists, "tsconfig.json"); + if (!configPath) { + throw new Error("Could not find a valid 'tsconfig.json'."); + } + + // TypeScript can use several different program creation "strategies": + // * ts.createEmitAndSemanticDiagnosticsBuilderProgram, + // * ts.createSemanticDiagnosticsBuilderProgram + // * ts.createAbstractBuilder + // The first two produce "builder programs". These use an incremental strategy to only re-check and emit files whose + // contents may have changed, or whose dependencies may have changes which may impact change the result of prior type-check and emit. + // The last uses an ordinary program which does a full type check after every change. + // Between `createEmitAndSemanticDiagnosticsBuilderProgram` and `createSemanticDiagnosticsBuilderProgram`, the only difference is emit. + // For pure type-checking scenarios, or when another tool/process handles emit, using `createSemanticDiagnosticsBuilderProgram` may be more desirable. + + // Note that there is another overload for `createWatchCompilerHost` that takes a set of root files. + const host = ts.createWatchCompilerHost(configPath, {}, ts.sys); + + // You can technically override any given hook on the host, though you probably don't need to. + // Note that we're assuming `origCreateProgram` and `origPostProgramCreate` doesn't use `this` at all. + const origCreateProgram = host.createProgram; + host.createProgram = (rootNames, options, host, oldProgram) => { + console.log("** We're about to create the program! **"); + return origCreateProgram(rootNames, options, host, oldProgram); + } + const origPostProgramCreate = host.afterProgramCreate; + + host.afterProgramCreate = program => { + console.log("** We finished making the program! **"); + origPostProgramCreate!(program); + }; + + // `createWatchProgram` creates an initial program, watches files, and updates the program over time. + ts.createWatchProgram(host); +} + +watchMain(); + + +//// [APISample_WatchWithDefaults.js] +"use strict"; +/* + * Note: This test is a public API sample. This uses default sys interface without having to pass anything + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ +exports.__esModule = true; +var ts = require("typescript"); +function watchMain() { + var configPath = ts.findConfigFile(/*searchPath*/ "./", ts.sys.fileExists, "tsconfig.json"); + if (!configPath) { + throw new Error("Could not find a valid 'tsconfig.json'."); + } + // TypeScript can use several different program creation "strategies": + // * ts.createEmitAndSemanticDiagnosticsBuilderProgram, + // * ts.createSemanticDiagnosticsBuilderProgram + // * ts.createAbstractBuilder + // The first two produce "builder programs". These use an incremental strategy to only re-check and emit files whose + // contents may have changed, or whose dependencies may have changes which may impact change the result of prior type-check and emit. + // The last uses an ordinary program which does a full type check after every change. + // Between `createEmitAndSemanticDiagnosticsBuilderProgram` and `createSemanticDiagnosticsBuilderProgram`, the only difference is emit. + // For pure type-checking scenarios, or when another tool/process handles emit, using `createSemanticDiagnosticsBuilderProgram` may be more desirable. + // Note that there is another overload for `createWatchCompilerHost` that takes a set of root files. + var host = ts.createWatchCompilerHost(configPath, {}, ts.sys); + // You can technically override any given hook on the host, though you probably don't need to. + // Note that we're assuming `origCreateProgram` and `origPostProgramCreate` doesn't use `this` at all. + var origCreateProgram = host.createProgram; + host.createProgram = function (rootNames, options, host, oldProgram) { + console.log("** We're about to create the program! **"); + return origCreateProgram(rootNames, options, host, oldProgram); + }; + var origPostProgramCreate = host.afterProgramCreate; + host.afterProgramCreate = function (program) { + console.log("** We finished making the program! **"); + origPostProgramCreate(program); + }; + // `createWatchProgram` creates an initial program, watches files, and updates the program over time. + ts.createWatchProgram(host); +} +watchMain(); diff --git a/tests/baselines/reference/APISample_WatchWithOwnWatchHost.js b/tests/baselines/reference/APISample_WatchWithOwnWatchHost.js new file mode 100644 index 00000000000..95f6df3fb51 --- /dev/null +++ b/tests/baselines/reference/APISample_WatchWithOwnWatchHost.js @@ -0,0 +1,102 @@ +//// [APISample_WatchWithOwnWatchHost.ts] +/* + * Note: This test is a public API sample. This sample verifies creating abstract builder to watch list of root files + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var console: any; + +import ts = require("typescript"); + +function watchMain() { + // get list of files and compiler options somehow + const files: string[] = []; + const options: ts.CompilerOptions = {}; + + const host: ts.WatchCompilerHostOfFilesAndCompilerOptions = { + rootFiles: files, + options, + + useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, + getNewLine: () => ts.sys.newLine, + getCurrentDirectory: ts.sys.getCurrentDirectory, + getDefaultLibFileName: options => ts.getDefaultLibFilePath(options), + + fileExists: ts.sys.fileExists, + readFile: ts.sys.readFile, + directoryExists: ts.sys.directoryExists, + getDirectories: ts.sys.getDirectories, + readDirectory: ts.sys.readDirectory, + realpath: ts.sys.realpath, + + watchFile: ts.sys.watchFile!, + watchDirectory: ts.sys.watchDirectory!, + createProgram: ts.createAbstractBuilder + }; + + // You can technically override any given hook on the host, though you probably don't need to. + // Note that we're assuming `origCreateProgram` and `origPostProgramCreate` doesn't use `this` at all. + const origCreateProgram = host.createProgram; + host.createProgram = (rootNames, options, host, oldProgram) => { + console.log("** We're about to create the program! **"); + return origCreateProgram(rootNames, options, host, oldProgram); + } + const origPostProgramCreate = host.afterProgramCreate; + + host.afterProgramCreate = program => { + console.log("** We finished making the program! **"); + origPostProgramCreate!(program); + }; + + // `createWatchProgram` creates an initial program, watches files, and updates the program over time. + ts.createWatchProgram(host); +} + +watchMain(); + + +//// [APISample_WatchWithOwnWatchHost.js] +"use strict"; +/* + * Note: This test is a public API sample. This sample verifies creating abstract builder to watch list of root files + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ +exports.__esModule = true; +var ts = require("typescript"); +function watchMain() { + // get list of files and compiler options somehow + var files = []; + var options = {}; + var host = { + rootFiles: files, + options: options, + useCaseSensitiveFileNames: function () { return ts.sys.useCaseSensitiveFileNames; }, + getNewLine: function () { return ts.sys.newLine; }, + getCurrentDirectory: ts.sys.getCurrentDirectory, + getDefaultLibFileName: function (options) { return ts.getDefaultLibFilePath(options); }, + fileExists: ts.sys.fileExists, + readFile: ts.sys.readFile, + directoryExists: ts.sys.directoryExists, + getDirectories: ts.sys.getDirectories, + readDirectory: ts.sys.readDirectory, + realpath: ts.sys.realpath, + watchFile: ts.sys.watchFile, + watchDirectory: ts.sys.watchDirectory, + createProgram: ts.createAbstractBuilder + }; + // You can technically override any given hook on the host, though you probably don't need to. + // Note that we're assuming `origCreateProgram` and `origPostProgramCreate` doesn't use `this` at all. + var origCreateProgram = host.createProgram; + host.createProgram = function (rootNames, options, host, oldProgram) { + console.log("** We're about to create the program! **"); + return origCreateProgram(rootNames, options, host, oldProgram); + }; + var origPostProgramCreate = host.afterProgramCreate; + host.afterProgramCreate = function (program) { + console.log("** We finished making the program! **"); + origPostProgramCreate(program); + }; + // `createWatchProgram` creates an initial program, watches files, and updates the program over time. + ts.createWatchProgram(host); +} +watchMain(); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index b88ebf8b118..76a5d890fa7 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4172,18 +4172,18 @@ declare namespace ts { * Create the builder to manage semantic diagnostics and cache them */ function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; - function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; + function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; /** * Create the builder that can handle the changes in program and iterate through changed files * to emit the those files and manage semantic diagnostics cache as well */ function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; - function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; + function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; /** * Creates a builder thats just abstraction over program and can be used with watch */ function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; - function createAbstractBuilder(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; + function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; } declare namespace ts { type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 3368c6347cd..51bd949ae4d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4172,18 +4172,18 @@ declare namespace ts { * Create the builder to manage semantic diagnostics and cache them */ function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; - function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; + function createSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): SemanticDiagnosticsBuilderProgram; /** * Create the builder that can handle the changes in program and iterate through changed files * to emit the those files and manage semantic diagnostics cache as well */ function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; - function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; + function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): EmitAndSemanticDiagnosticsBuilderProgram; /** * Creates a builder thats just abstraction over program and can be used with watch */ function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; - function createAbstractBuilder(rootNames: ReadonlyArray, options: CompilerOptions, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; + function createAbstractBuilder(rootNames: ReadonlyArray | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray): BuilderProgram; } declare namespace ts { type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void; diff --git a/tests/cases/compiler/APISample_Watch.ts b/tests/cases/compiler/APISample_Watch.ts new file mode 100644 index 00000000000..e1506676426 --- /dev/null +++ b/tests/cases/compiler/APISample_Watch.ts @@ -0,0 +1,80 @@ +// @module: commonjs +// @skipLibCheck: true +// @includebuiltfile: typescript_standalone.d.ts +// @noImplicitAny:true +// @strictNullChecks:true + +/* + * Note: This test is a public API sample. The sample sources can be found + at: https://github.com/Microsoft/TypeScript-wiki/blob/master/Using-the-Compiler-API.md#writing-an-incremental-program-watcher + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var process: any; +declare var console: any; +declare var os: any; + +import ts = require("typescript"); + +const formatHost: ts.FormatDiagnosticsHost = { + getCanonicalFileName: path => path, + getCurrentDirectory: ts.sys.getCurrentDirectory, + getNewLine: () => ts.sys.newLine, +} + +function watchMain() { + const configPath = ts.findConfigFile(/*searchPath*/ "./", ts.sys.fileExists, "tsconfig.json"); + if (!configPath) { + throw new Error("Could not find a valid 'tsconfig.json'."); + } + + // TypeScript can use several different program creation "strategies": + // * ts.createEmitAndSemanticDiagnosticsBuilderProgram, + // * ts.createSemanticDiagnosticsBuilderProgram + // * ts.createAbstractBuilder + // The first two produce "builder programs". These use an incremental strategy to only re-check and emit files whose + // contents may have changed, or whose dependencies may have changes which may impact change the result of prior type-check and emit. + // The last uses an ordinary program which does a full type check after every change. + // Between `createEmitAndSemanticDiagnosticsBuilderProgram` and `createSemanticDiagnosticsBuilderProgram`, the only difference is emit. + // For pure type-checking scenarios, or when another tool/process handles emit, using `createSemanticDiagnosticsBuilderProgram` may be more desirable. + + // Note that there is another overload for `createWatchCompilerHost` that takes a set of root files. + const host = ts.createWatchCompilerHost(configPath, {}, ts.sys, + ts.createSemanticDiagnosticsBuilderProgram, + reportDiagnostic, + reportWatchStatusChanged, + ); + + // You can technically override any given hook on the host, though you probably don't need to. + // Note that we're assuming `origCreateProgram` and `origPostProgramCreate` doesn't use `this` at all. + const origCreateProgram = host.createProgram; + host.createProgram = (rootNames: ReadonlyArray, options, host, oldProgram) => { + console.log("** We're about to create the program! **"); + return origCreateProgram(rootNames, options, host, oldProgram); + } + const origPostProgramCreate = host.afterProgramCreate; + + host.afterProgramCreate = program => { + console.log("** We finished making the program! **"); + origPostProgramCreate!(program); + }; + + // `createWatchProgram` creates an initial program, watches files, and updates the program over time. + ts.createWatchProgram(host); +} + +function reportDiagnostic(diagnostic: ts.Diagnostic) { + console.error("Error", diagnostic.code, ":", + ts.flattenDiagnosticMessageText(diagnostic.messageText, formatHost.getNewLine()) + ); +} + +/** + * Prints a diagnostic every time the watch status changes. + * This is mainly for messages like "Starting compilation" or "Compilation completed". + */ +function reportWatchStatusChanged(diagnostic: ts.Diagnostic) { + console.info(ts.formatDiagnostic(diagnostic, formatHost)); +} + +watchMain(); diff --git a/tests/cases/compiler/APISample_WatchWithDefaults.ts b/tests/cases/compiler/APISample_WatchWithDefaults.ts new file mode 100644 index 00000000000..24f251daca2 --- /dev/null +++ b/tests/cases/compiler/APISample_WatchWithDefaults.ts @@ -0,0 +1,53 @@ +// @module: commonjs +// @skipLibCheck: true +// @includebuiltfile: typescript_standalone.d.ts +// @noImplicitAny:true +// @strict:true + +/* + * Note: This test is a public API sample. This uses default sys interface without having to pass anything + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var console: any; + +import ts = require("typescript"); + +function watchMain() { + const configPath = ts.findConfigFile(/*searchPath*/ "./", ts.sys.fileExists, "tsconfig.json"); + if (!configPath) { + throw new Error("Could not find a valid 'tsconfig.json'."); + } + + // TypeScript can use several different program creation "strategies": + // * ts.createEmitAndSemanticDiagnosticsBuilderProgram, + // * ts.createSemanticDiagnosticsBuilderProgram + // * ts.createAbstractBuilder + // The first two produce "builder programs". These use an incremental strategy to only re-check and emit files whose + // contents may have changed, or whose dependencies may have changes which may impact change the result of prior type-check and emit. + // The last uses an ordinary program which does a full type check after every change. + // Between `createEmitAndSemanticDiagnosticsBuilderProgram` and `createSemanticDiagnosticsBuilderProgram`, the only difference is emit. + // For pure type-checking scenarios, or when another tool/process handles emit, using `createSemanticDiagnosticsBuilderProgram` may be more desirable. + + // Note that there is another overload for `createWatchCompilerHost` that takes a set of root files. + const host = ts.createWatchCompilerHost(configPath, {}, ts.sys); + + // You can technically override any given hook on the host, though you probably don't need to. + // Note that we're assuming `origCreateProgram` and `origPostProgramCreate` doesn't use `this` at all. + const origCreateProgram = host.createProgram; + host.createProgram = (rootNames, options, host, oldProgram) => { + console.log("** We're about to create the program! **"); + return origCreateProgram(rootNames, options, host, oldProgram); + } + const origPostProgramCreate = host.afterProgramCreate; + + host.afterProgramCreate = program => { + console.log("** We finished making the program! **"); + origPostProgramCreate!(program); + }; + + // `createWatchProgram` creates an initial program, watches files, and updates the program over time. + ts.createWatchProgram(host); +} + +watchMain(); diff --git a/tests/cases/compiler/APISample_WatchWithOwnWatchHost.ts b/tests/cases/compiler/APISample_WatchWithOwnWatchHost.ts new file mode 100644 index 00000000000..18f170bd5f6 --- /dev/null +++ b/tests/cases/compiler/APISample_WatchWithOwnWatchHost.ts @@ -0,0 +1,60 @@ +// @module: commonjs +// @skipLibCheck: true +// @includebuiltfile: typescript_standalone.d.ts +// @noImplicitAny:true +// @strict:true + +/* + * Note: This test is a public API sample. This sample verifies creating abstract builder to watch list of root files + * Please log a "breaking change" issue for any API breaking change affecting this issue + */ + +declare var console: any; + +import ts = require("typescript"); + +function watchMain() { + // get list of files and compiler options somehow + const files: string[] = []; + const options: ts.CompilerOptions = {}; + + const host: ts.WatchCompilerHostOfFilesAndCompilerOptions = { + rootFiles: files, + options, + + useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, + getNewLine: () => ts.sys.newLine, + getCurrentDirectory: ts.sys.getCurrentDirectory, + getDefaultLibFileName: options => ts.getDefaultLibFilePath(options), + + fileExists: ts.sys.fileExists, + readFile: ts.sys.readFile, + directoryExists: ts.sys.directoryExists, + getDirectories: ts.sys.getDirectories, + readDirectory: ts.sys.readDirectory, + realpath: ts.sys.realpath, + + watchFile: ts.sys.watchFile!, + watchDirectory: ts.sys.watchDirectory!, + createProgram: ts.createAbstractBuilder + }; + + // You can technically override any given hook on the host, though you probably don't need to. + // Note that we're assuming `origCreateProgram` and `origPostProgramCreate` doesn't use `this` at all. + const origCreateProgram = host.createProgram; + host.createProgram = (rootNames, options, host, oldProgram) => { + console.log("** We're about to create the program! **"); + return origCreateProgram(rootNames, options, host, oldProgram); + } + const origPostProgramCreate = host.afterProgramCreate; + + host.afterProgramCreate = program => { + console.log("** We finished making the program! **"); + origPostProgramCreate!(program); + }; + + // `createWatchProgram` creates an initial program, watches files, and updates the program over time. + ts.createWatchProgram(host); +} + +watchMain();