@rushstack/heft-typescript-plugin 0.1.0-rc.2 → 0.1.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,7 @@ export interface ICachedEmitModuleKind {
17
17
  export declare class EmitFilesPatch {
18
18
  private static _patchedTs;
19
19
  private static _baseEmitFiles;
20
- static install(ts: ExtendedTypeScript, tsconfig: TTypescript.ParsedCommandLine, moduleKindsToEmit: ICachedEmitModuleKind[], changedFiles?: Set<TTypescript.SourceFile>): void;
20
+ static install(ts: ExtendedTypeScript, baseCompilerOptions: TTypescript.CompilerOptions, moduleKindsToEmit: ICachedEmitModuleKind[], changedFiles?: Set<TTypescript.SourceFile>): void;
21
21
  static get isInstalled(): boolean;
22
22
  /**
23
23
  * Wraps the writeFile callback on the IEmitHost to override the .js extension, if applicable
@@ -1 +1 @@
1
- {"version":3,"file":"EmitFilesPatch.d.ts","sourceRoot":"","sources":["../src/EmitFilesPatch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,WAAW,MAAM,YAAY,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAInB,MAAM,uCAAuC,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC;IAEnC,aAAa,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;IAExC;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,UAAU,CAA6C;IAEtE,OAAO,CAAC,MAAM,CAAC,cAAc,CAA8B;WAE7C,OAAO,CACnB,EAAE,EAAE,kBAAkB,EACtB,QAAQ,EAAE,WAAW,CAAC,iBAAiB,EACvC,iBAAiB,EAAE,qBAAqB,EAAE,EAC1C,YAAY,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,GACzC,IAAI;IAsHP,WAAkB,WAAW,IAAI,OAAO,CAEvC;IAED;;OAEG;WACW,aAAa,CACzB,aAAa,EAAE,WAAW,CAAC,iBAAiB,EAC5C,mBAAmB,EAAE,MAAM,GAAG,SAAS,GACtC,WAAW,CAAC,iBAAiB;WAuBlB,SAAS,CAAC,EAAE,EAAE,kBAAkB,GAAG,IAAI;CAatD"}
1
+ {"version":3,"file":"EmitFilesPatch.d.ts","sourceRoot":"","sources":["../src/EmitFilesPatch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,WAAW,MAAM,YAAY,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAInB,MAAM,uCAAuC,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC;IAEnC,aAAa,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,mBAAmB,EAAE,MAAM,GAAG,SAAS,CAAC;IAExC;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,UAAU,CAA6C;IAEtE,OAAO,CAAC,MAAM,CAAC,cAAc,CAA8B;WAE7C,OAAO,CACnB,EAAE,EAAE,kBAAkB,EACtB,mBAAmB,EAAE,WAAW,CAAC,eAAe,EAChD,iBAAiB,EAAE,qBAAqB,EAAE,EAC1C,YAAY,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,GACzC,IAAI;IAsHP,WAAkB,WAAW,IAAI,OAAO,CAEvC;IAED;;OAEG;WACW,aAAa,CACzB,aAAa,EAAE,WAAW,CAAC,iBAAiB,EAC5C,mBAAmB,EAAE,MAAM,GAAG,SAAS,GACtC,WAAW,CAAC,iBAAiB;WAuBlB,SAAS,CAAC,EAAE,EAAE,kBAAkB,GAAG,IAAI;CAatD"}
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.EmitFilesPatch = void 0;
6
6
  const node_core_library_1 = require("@rushstack/node-core-library");
7
7
  class EmitFilesPatch {
8
- static install(ts, tsconfig, moduleKindsToEmit, changedFiles) {
8
+ static install(ts, baseCompilerOptions, moduleKindsToEmit, changedFiles) {
9
9
  if (EmitFilesPatch._patchedTs === ts) {
10
10
  // We already patched this instance of TS
11
11
  return;
@@ -42,7 +42,7 @@ class EmitFilesPatch {
42
42
  let emitSkipped = false;
43
43
  for (const moduleKindToEmit of moduleKindsToEmit) {
44
44
  const compilerOptions = moduleKindToEmit.isPrimary
45
- ? Object.assign({}, tsconfig.options) : Object.assign(Object.assign({}, tsconfig.options), { module: moduleKindToEmit.moduleKind, outDir: moduleKindToEmit.outFolderPath,
45
+ ? Object.assign({}, baseCompilerOptions) : Object.assign(Object.assign({}, baseCompilerOptions), { module: moduleKindToEmit.moduleKind, outDir: moduleKindToEmit.outFolderPath,
46
46
  // Don't emit declarations for secondary module kinds
47
47
  declaration: false, declarationMap: false });
48
48
  if (!compilerOptions.outDir) {
@@ -1 +1 @@
1
- {"version":3,"file":"EmitFilesPatch.js","sourceRoot":"","sources":["../src/EmitFilesPatch.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { InternalError } from '@rushstack/node-core-library';\nimport type * as TTypescript from 'typescript';\nimport {\n ExtendedTypeScript,\n IEmitResolver,\n IEmitHost,\n IEmitTransformers\n} from './internalTypings/TypeScriptInternals';\n\nexport interface ICachedEmitModuleKind {\n moduleKind: TTypescript.ModuleKind;\n\n outFolderPath: string;\n\n /**\n * File extension to use instead of '.js' for emitted ECMAScript files.\n * For example, '.cjs' to indicate commonjs content, or '.mjs' to indicate ECMAScript modules.\n */\n jsExtensionOverride: string | undefined;\n\n /**\n * Set to true if this is the emit kind that is specified in the tsconfig.json.\n * Declarations are only emitted for the primary module kind.\n */\n isPrimary: boolean;\n}\n\nexport class EmitFilesPatch {\n private static _patchedTs: ExtendedTypeScript | undefined = undefined;\n\n private static _baseEmitFiles: any | undefined = undefined; // eslint-disable-line\n\n public static install(\n ts: ExtendedTypeScript,\n tsconfig: TTypescript.ParsedCommandLine,\n moduleKindsToEmit: ICachedEmitModuleKind[],\n changedFiles?: Set<TTypescript.SourceFile>\n ): void {\n if (EmitFilesPatch._patchedTs === ts) {\n // We already patched this instance of TS\n return;\n }\n\n if (EmitFilesPatch._patchedTs !== undefined) {\n throw new InternalError(\n 'EmitFilesPatch.install() cannot be called without first uninstalling the existing patch'\n );\n }\n\n EmitFilesPatch._patchedTs = ts;\n EmitFilesPatch._baseEmitFiles = ts.emitFiles;\n\n let foundPrimary: boolean = false;\n let defaultModuleKind: TTypescript.ModuleKind;\n\n for (const moduleKindToEmit of moduleKindsToEmit) {\n if (moduleKindToEmit.isPrimary) {\n if (foundPrimary) {\n throw new Error('Multiple primary module emit kinds encountered.');\n } else {\n foundPrimary = true;\n }\n\n defaultModuleKind = moduleKindToEmit.moduleKind;\n }\n }\n\n const patchedEmitFiles = (\n resolver: IEmitResolver,\n host: IEmitHost,\n targetSourceFile: TTypescript.SourceFile | undefined,\n emitTransformers: IEmitTransformers,\n emitOnlyDtsFiles?: boolean,\n onlyBuildInfo?: boolean,\n forceDtsEmit?: boolean\n ): TTypescript.EmitResult => {\n if (onlyBuildInfo || emitOnlyDtsFiles) {\n // There should only be one tsBuildInfo and one set of declaration files\n return EmitFilesPatch._baseEmitFiles(\n resolver,\n host,\n targetSourceFile,\n emitTransformers,\n emitOnlyDtsFiles,\n onlyBuildInfo,\n forceDtsEmit\n );\n } else {\n if (targetSourceFile && changedFiles) {\n changedFiles.add(targetSourceFile);\n }\n\n let defaultModuleKindResult: TTypescript.EmitResult;\n const diagnostics: TTypescript.Diagnostic[] = [];\n let emitSkipped: boolean = false;\n for (const moduleKindToEmit of moduleKindsToEmit) {\n const compilerOptions: TTypescript.CompilerOptions = moduleKindToEmit.isPrimary\n ? {\n ...tsconfig.options\n }\n : {\n ...tsconfig.options,\n module: moduleKindToEmit.moduleKind,\n outDir: moduleKindToEmit.outFolderPath,\n\n // Don't emit declarations for secondary module kinds\n declaration: false,\n declarationMap: false\n };\n\n if (!compilerOptions.outDir) {\n throw new InternalError('Expected compilerOptions.outDir to be assigned');\n }\n\n const flavorResult: TTypescript.EmitResult = EmitFilesPatch._baseEmitFiles(\n resolver,\n {\n ...host,\n writeFile: EmitFilesPatch.wrapWriteFile(host.writeFile, moduleKindToEmit.jsExtensionOverride),\n getCompilerOptions: () => compilerOptions\n },\n targetSourceFile,\n ts.getTransformers(compilerOptions, undefined, emitOnlyDtsFiles),\n emitOnlyDtsFiles,\n onlyBuildInfo,\n forceDtsEmit\n );\n\n emitSkipped = emitSkipped || flavorResult.emitSkipped;\n for (const diagnostic of flavorResult.diagnostics) {\n diagnostics.push(diagnostic);\n }\n\n if (moduleKindToEmit.moduleKind === defaultModuleKind) {\n defaultModuleKindResult = flavorResult;\n }\n // Should results be aggregated, in case for whatever reason the diagnostics are not the same?\n }\n\n const mergedDiagnostics: readonly TTypescript.Diagnostic[] =\n ts.sortAndDeduplicateDiagnostics(diagnostics);\n\n return {\n ...defaultModuleKindResult!,\n diagnostics: mergedDiagnostics,\n emitSkipped\n };\n }\n };\n\n // Override the underlying file emitter to run itself once for each flavor\n // This is a rather inelegant way to convince the TypeScript compiler not to duplicate parse/link/check\n ts.emitFiles = patchedEmitFiles;\n }\n\n public static get isInstalled(): boolean {\n return this._patchedTs !== undefined;\n }\n\n /**\n * Wraps the writeFile callback on the IEmitHost to override the .js extension, if applicable\n */\n public static wrapWriteFile(\n baseWriteFile: TTypescript.WriteFileCallback,\n jsExtensionOverride: string | undefined\n ): TTypescript.WriteFileCallback {\n if (!jsExtensionOverride) {\n return baseWriteFile;\n }\n\n const replacementExtension: string = `${jsExtensionOverride}$1`;\n return (\n fileName: string,\n data: string,\n writeBOM: boolean,\n onError?: ((message: string) => void) | undefined,\n sourceFiles?: readonly TTypescript.SourceFile[] | undefined\n ) => {\n return baseWriteFile(\n fileName.replace(/\\.js(\\.map)?$/g, replacementExtension),\n data,\n writeBOM,\n onError,\n sourceFiles\n );\n };\n }\n\n public static uninstall(ts: ExtendedTypeScript): void {\n if (EmitFilesPatch._patchedTs === undefined) {\n throw new InternalError('EmitFilesPatch.uninstall() cannot be called if no patch was installed');\n }\n if (ts !== EmitFilesPatch._patchedTs) {\n throw new InternalError('EmitFilesPatch.uninstall() called for the wrong object');\n }\n\n ts.emitFiles = EmitFilesPatch._baseEmitFiles;\n\n EmitFilesPatch._patchedTs = undefined;\n EmitFilesPatch._baseEmitFiles = undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"EmitFilesPatch.js","sourceRoot":"","sources":["../src/EmitFilesPatch.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\n// See LICENSE in the project root for license information.\n\nimport { InternalError } from '@rushstack/node-core-library';\nimport type * as TTypescript from 'typescript';\nimport {\n ExtendedTypeScript,\n IEmitResolver,\n IEmitHost,\n IEmitTransformers\n} from './internalTypings/TypeScriptInternals';\n\nexport interface ICachedEmitModuleKind {\n moduleKind: TTypescript.ModuleKind;\n\n outFolderPath: string;\n\n /**\n * File extension to use instead of '.js' for emitted ECMAScript files.\n * For example, '.cjs' to indicate commonjs content, or '.mjs' to indicate ECMAScript modules.\n */\n jsExtensionOverride: string | undefined;\n\n /**\n * Set to true if this is the emit kind that is specified in the tsconfig.json.\n * Declarations are only emitted for the primary module kind.\n */\n isPrimary: boolean;\n}\n\nexport class EmitFilesPatch {\n private static _patchedTs: ExtendedTypeScript | undefined = undefined;\n\n private static _baseEmitFiles: any | undefined = undefined; // eslint-disable-line\n\n public static install(\n ts: ExtendedTypeScript,\n baseCompilerOptions: TTypescript.CompilerOptions,\n moduleKindsToEmit: ICachedEmitModuleKind[],\n changedFiles?: Set<TTypescript.SourceFile>\n ): void {\n if (EmitFilesPatch._patchedTs === ts) {\n // We already patched this instance of TS\n return;\n }\n\n if (EmitFilesPatch._patchedTs !== undefined) {\n throw new InternalError(\n 'EmitFilesPatch.install() cannot be called without first uninstalling the existing patch'\n );\n }\n\n EmitFilesPatch._patchedTs = ts;\n EmitFilesPatch._baseEmitFiles = ts.emitFiles;\n\n let foundPrimary: boolean = false;\n let defaultModuleKind: TTypescript.ModuleKind;\n\n for (const moduleKindToEmit of moduleKindsToEmit) {\n if (moduleKindToEmit.isPrimary) {\n if (foundPrimary) {\n throw new Error('Multiple primary module emit kinds encountered.');\n } else {\n foundPrimary = true;\n }\n\n defaultModuleKind = moduleKindToEmit.moduleKind;\n }\n }\n\n const patchedEmitFiles = (\n resolver: IEmitResolver,\n host: IEmitHost,\n targetSourceFile: TTypescript.SourceFile | undefined,\n emitTransformers: IEmitTransformers,\n emitOnlyDtsFiles?: boolean,\n onlyBuildInfo?: boolean,\n forceDtsEmit?: boolean\n ): TTypescript.EmitResult => {\n if (onlyBuildInfo || emitOnlyDtsFiles) {\n // There should only be one tsBuildInfo and one set of declaration files\n return EmitFilesPatch._baseEmitFiles(\n resolver,\n host,\n targetSourceFile,\n emitTransformers,\n emitOnlyDtsFiles,\n onlyBuildInfo,\n forceDtsEmit\n );\n } else {\n if (targetSourceFile && changedFiles) {\n changedFiles.add(targetSourceFile);\n }\n\n let defaultModuleKindResult: TTypescript.EmitResult;\n const diagnostics: TTypescript.Diagnostic[] = [];\n let emitSkipped: boolean = false;\n for (const moduleKindToEmit of moduleKindsToEmit) {\n const compilerOptions: TTypescript.CompilerOptions = moduleKindToEmit.isPrimary\n ? {\n ...baseCompilerOptions\n }\n : {\n ...baseCompilerOptions,\n module: moduleKindToEmit.moduleKind,\n outDir: moduleKindToEmit.outFolderPath,\n\n // Don't emit declarations for secondary module kinds\n declaration: false,\n declarationMap: false\n };\n\n if (!compilerOptions.outDir) {\n throw new InternalError('Expected compilerOptions.outDir to be assigned');\n }\n\n const flavorResult: TTypescript.EmitResult = EmitFilesPatch._baseEmitFiles(\n resolver,\n {\n ...host,\n writeFile: EmitFilesPatch.wrapWriteFile(host.writeFile, moduleKindToEmit.jsExtensionOverride),\n getCompilerOptions: () => compilerOptions\n },\n targetSourceFile,\n ts.getTransformers(compilerOptions, undefined, emitOnlyDtsFiles),\n emitOnlyDtsFiles,\n onlyBuildInfo,\n forceDtsEmit\n );\n\n emitSkipped = emitSkipped || flavorResult.emitSkipped;\n for (const diagnostic of flavorResult.diagnostics) {\n diagnostics.push(diagnostic);\n }\n\n if (moduleKindToEmit.moduleKind === defaultModuleKind) {\n defaultModuleKindResult = flavorResult;\n }\n // Should results be aggregated, in case for whatever reason the diagnostics are not the same?\n }\n\n const mergedDiagnostics: readonly TTypescript.Diagnostic[] =\n ts.sortAndDeduplicateDiagnostics(diagnostics);\n\n return {\n ...defaultModuleKindResult!,\n diagnostics: mergedDiagnostics,\n emitSkipped\n };\n }\n };\n\n // Override the underlying file emitter to run itself once for each flavor\n // This is a rather inelegant way to convince the TypeScript compiler not to duplicate parse/link/check\n ts.emitFiles = patchedEmitFiles;\n }\n\n public static get isInstalled(): boolean {\n return this._patchedTs !== undefined;\n }\n\n /**\n * Wraps the writeFile callback on the IEmitHost to override the .js extension, if applicable\n */\n public static wrapWriteFile(\n baseWriteFile: TTypescript.WriteFileCallback,\n jsExtensionOverride: string | undefined\n ): TTypescript.WriteFileCallback {\n if (!jsExtensionOverride) {\n return baseWriteFile;\n }\n\n const replacementExtension: string = `${jsExtensionOverride}$1`;\n return (\n fileName: string,\n data: string,\n writeBOM: boolean,\n onError?: ((message: string) => void) | undefined,\n sourceFiles?: readonly TTypescript.SourceFile[] | undefined\n ) => {\n return baseWriteFile(\n fileName.replace(/\\.js(\\.map)?$/g, replacementExtension),\n data,\n writeBOM,\n onError,\n sourceFiles\n );\n };\n }\n\n public static uninstall(ts: ExtendedTypeScript): void {\n if (EmitFilesPatch._patchedTs === undefined) {\n throw new InternalError('EmitFilesPatch.uninstall() cannot be called if no patch was installed');\n }\n if (ts !== EmitFilesPatch._patchedTs) {\n throw new InternalError('EmitFilesPatch.uninstall() called for the wrong object');\n }\n\n ts.emitFiles = EmitFilesPatch._baseEmitFiles;\n\n EmitFilesPatch._patchedTs = undefined;\n EmitFilesPatch._baseEmitFiles = undefined;\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type * as TTypescript from 'typescript';
2
- import type { IChangedFileState, IScopedLogger } from '@rushstack/heft';
3
- import type { ExtendedTypeScript } from './internalTypings/TypeScriptInternals';
2
+ import type { IScopedLogger } from '@rushstack/heft';
3
+ import type { ExtendedTypeScript, IExtendedSolutionBuilder } from './internalTypings/TypeScriptInternals';
4
4
  import type { ITypeScriptConfigurationJson } from './TypeScriptPlugin';
5
5
  import type { PerformanceMeasurer, PerformanceMeasurerAsync } from './Performance';
6
6
  export interface ITypeScriptBuilderConfiguration extends ITypeScriptConfigurationJson {
@@ -34,13 +34,23 @@ export interface ITypeScriptBuilderConfiguration extends ITypeScriptConfiguratio
34
34
  */
35
35
  emitChangedFilesCallback: (program: TTypescript.Program, changedFiles?: Set<TTypescript.SourceFile>) => void;
36
36
  }
37
+ declare type TWatchProgram = TTypescript.WatchOfFilesAndCompilerOptions<TTypescript.EmitAndSemanticDiagnosticsBuilderProgram>;
38
+ interface IPendingWork {
39
+ (): void;
40
+ }
37
41
  interface ITypeScriptTool {
38
42
  ts: ExtendedTypeScript;
39
43
  measureSync: PerformanceMeasurer;
40
44
  measureAsync: PerformanceMeasurerAsync;
41
45
  sourceFileCache: Map<string, TTypescript.SourceFile>;
42
- oldBuilderProgram: TTypescript.EmitAndSemanticDiagnosticsBuilderProgram | undefined;
43
- oldProgram: TTypescript.Program | undefined;
46
+ watchProgram: TWatchProgram | undefined;
47
+ solutionBuilder: IExtendedSolutionBuilder | undefined;
48
+ rawDiagnostics: TTypescript.Diagnostic[];
49
+ pendingOperations: Set<IPendingWork>;
50
+ executing: boolean;
51
+ reportDiagnostic: TTypescript.DiagnosticReporter;
52
+ clearTimeout: (timeout: IPendingWork) => void;
53
+ setTimeout: <T extends unknown[]>(timeout: (...args: T) => void, ms: number, ...args: T) => IPendingWork;
44
54
  }
45
55
  export declare class TypeScriptBuilder {
46
56
  private readonly _configuration;
@@ -57,7 +67,8 @@ export declare class TypeScriptBuilder {
57
67
  private _tool;
58
68
  private get _tsCacheFilePath();
59
69
  constructor(configuration: ITypeScriptBuilderConfiguration);
60
- invokeAsync(changedFiles?: ReadonlyMap<string, IChangedFileState> | undefined): Promise<void>;
70
+ invokeAsync(onChangeDetected?: () => void): Promise<void>;
71
+ _runWatch(tool: ITypeScriptTool): void;
61
72
  _runBuildAsync(tool: ITypeScriptTool): Promise<void>;
62
73
  _runSolutionBuild(tool: ITypeScriptTool): void;
63
74
  private _logDiagnostics;
@@ -69,9 +80,12 @@ export declare class TypeScriptBuilder {
69
80
  private _validateTsconfig;
70
81
  private _addModuleKindToEmit;
71
82
  private _loadTsconfig;
83
+ private _getCreateBuilderProgram;
72
84
  private _buildSolutionBuilderHost;
73
85
  private _buildIncrementalCompilerHost;
74
- private _getCachingTypeScriptSystem;
86
+ private _buildWatchCompilerHost;
87
+ private _changeCompilerHostToUseCache;
88
+ private _buildWatchSolutionBuilderHost;
75
89
  private _overrideTypeScriptReadJson;
76
90
  private _parseModuleKind;
77
91
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TypeScriptBuilder.d.ts","sourceRoot":"","sources":["../src/TypeScriptBuilder.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,WAAW,MAAM,YAAY,CAAC;AAW/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAExE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAGhF,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEnF,MAAM,WAAW,+BAAgC,SAAQ,4BAA4B;IACnF;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,uBAAuB,EAAE,MAAM,CAAC;IAEhC;;OAEG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAI3B;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,YAAY,EAAE,aAAa,CAAC;IAE5B;;OAEG;IACH,wBAAwB,EAAE,CACxB,OAAO,EAAE,WAAW,CAAC,OAAO,EAC5B,YAAY,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,KACvC,IAAI,CAAC;CACX;AA+CD,UAAU,eAAe;IACvB,EAAE,EAAE,kBAAkB,CAAC;IACvB,WAAW,EAAE,mBAAmB,CAAC;IACjC,YAAY,EAAE,wBAAwB,CAAC;IAEvC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAErD,iBAAiB,EAAE,WAAW,CAAC,wCAAwC,GAAG,SAAS,CAAC;IACpF,UAAU,EAAE,WAAW,CAAC,OAAO,GAAG,SAAS,CAAC;CAC7C;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAkC;IACjE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAY;IAEhD,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,wBAAwB,CAAiB;IAEjD,OAAO,CAAC,aAAa,CAAyB;IAC9C,OAAO,CAAC,mBAAmB,CAAW;IAEtC,OAAO,CAAC,kBAAkB,CAA2B;IAErD,OAAO,CAAC,iBAAiB,CAAiC;IAC1D,OAAO,CAAC,gBAAgB,CAAkD;IAC1E,OAAO,CAAC,iBAAiB,CAAgE;IAEzF,OAAO,CAAC,KAAK,CAA0C;IAEvD,OAAO,KAAK,gBAAgB,GAuB3B;gBAEkB,aAAa,EAAE,+BAA+B;IAMpD,WAAW,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAyK7F,cAAc,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAkH1D,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI;IAkErD,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,mBAAmB;IAc3B,OAAO,CAAC,uBAAuB;IA0C/B,OAAO,CAAC,8BAA8B;IA2BtC,OAAO,CAAC,KAAK;IA8Bb,OAAO,CAAC,iBAAiB;IAyHzB,OAAO,CAAC,oBAAoB;IA8D5B,OAAO,CAAC,aAAa;IA6CrB,OAAO,CAAC,yBAAyB;IAqBjC,OAAO,CAAC,6BAA6B;IAiDrC,OAAO,CAAC,2BAA2B;IAiGnC,OAAO,CAAC,2BAA2B;IAgCnC,OAAO,CAAC,gBAAgB;CAwBzB"}
1
+ {"version":3,"file":"TypeScriptBuilder.d.ts","sourceRoot":"","sources":["../src/TypeScriptBuilder.ts"],"names":[],"mappings":"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"}
@@ -32,10 +32,6 @@ const semver = __importStar(require("semver"));
32
32
  const node_core_library_1 = require("@rushstack/node-core-library");
33
33
  const EmitFilesPatch_1 = require("./EmitFilesPatch");
34
34
  const TypeScriptCachedFileSystem_1 = require("./fileSystem/TypeScriptCachedFileSystem");
35
- // type TWatchCompilerHost =
36
- // TTypescript.WatchCompilerHostOfFilesAndCompilerOptions<TTypescript.EmitAndSemanticDiagnosticsBuilderProgram>;
37
- // type TWatchSolutionHost =
38
- // TTypescript.SolutionBuilderWithWatchHost<TTypescript.EmitAndSemanticDiagnosticsBuilderProgram>;
39
35
  const EMPTY_JSON = {};
40
36
  const OLDEST_SUPPORTED_TS_MAJOR_VERSION = 2;
41
37
  const OLDEST_SUPPORTED_TS_MINOR_VERSION = 9;
@@ -70,7 +66,7 @@ class TypeScriptBuilder {
70
66
  }
71
67
  return this.__tsCacheFilePath;
72
68
  }
73
- async invokeAsync(changedFiles) {
69
+ async invokeAsync(onChangeDetected) {
74
70
  if (!this._tool) {
75
71
  // Determine the compiler version
76
72
  const compilerPackageJsonFilename = path.join(this._configuration.typeScriptToolPath, 'package.json');
@@ -135,61 +131,85 @@ class TypeScriptBuilder {
135
131
  return Object.assign(Object.assign({}, result), { duration: ts.performance.getDuration(measurementName) });
136
132
  };
137
133
  this._typescriptTerminal.writeLine(`Using TypeScript version ${ts.version}`);
134
+ const rawDiagnostics = [];
135
+ const pendingOperations = new Set();
138
136
  this._tool = {
139
137
  ts,
140
138
  measureSync: measureTsPerformance,
141
139
  measureAsync: measureTsPerformanceAsync,
142
140
  sourceFileCache: new Map(),
143
- oldBuilderProgram: undefined,
144
- oldProgram: undefined
141
+ watchProgram: undefined,
142
+ solutionBuilder: undefined,
143
+ rawDiagnostics,
144
+ pendingOperations,
145
+ executing: false,
146
+ reportDiagnostic: (diagnostic) => {
147
+ rawDiagnostics.push(diagnostic);
148
+ },
149
+ clearTimeout(timeout) {
150
+ pendingOperations.delete(timeout);
151
+ },
152
+ setTimeout(fn, ms, ...args) {
153
+ const timeout = () => {
154
+ fn(...args);
155
+ };
156
+ pendingOperations.add(timeout);
157
+ if (!this.executing && onChangeDetected) {
158
+ onChangeDetected();
159
+ }
160
+ return timeout;
161
+ }
145
162
  };
146
163
  }
147
164
  const { performance } = this._tool.ts;
148
165
  // Reset the performance counters to 0 to avoid contamination from previous runs
149
166
  performance.disable();
150
167
  performance.enable();
151
- if (changedFiles) {
152
- const { sourceFileCache } = this._tool;
153
- for (const file of changedFiles.keys()) {
154
- // There might need to be a transform to the format of `file` here.
155
- sourceFileCache.delete(file);
156
- }
168
+ if (onChangeDetected !== undefined) {
169
+ this._runWatch(this._tool);
157
170
  }
158
- // if (this._configuration.watchMode) {
159
- // await this._runWatch(ts, measureTsPerformance);
160
- // } else if (this._useSolutionBuilder) {
161
- if (this._useSolutionBuilder) {
171
+ else if (this._useSolutionBuilder) {
162
172
  this._runSolutionBuild(this._tool);
163
173
  }
164
174
  else {
165
175
  await this._runBuildAsync(this._tool);
166
176
  }
167
177
  }
168
- // public async _runWatch(ts: ExtendedTypeScript, measureTsPerformance: PerformanceMeasurer): Promise<void> {
169
- // //#region CONFIGURE
170
- // const { duration: configureDurationMs, tsconfig } = measureTsPerformance('Configure', () => {
171
- // const _tsconfig: TTypescript.ParsedCommandLine = this._loadTsconfig(ts);
172
- // this._validateTsconfig(ts, _tsconfig);
173
- // EmitFilesPatch.install(ts, _tsconfig, this._moduleKindsToEmit);
174
- // return {
175
- // tsconfig: _tsconfig
176
- // };
177
- // });
178
- // this._typescriptTerminal.writeVerboseLine(`Configure: ${configureDurationMs}ms`);
179
- // //#endregion
180
- // if (this._useSolutionBuilder) {
181
- // const solutionHost: TWatchSolutionHost = this._buildWatchSolutionBuilderHost(ts);
182
- // const watchBuilder: TTypescript.SolutionBuilder<TTypescript.EmitAndSemanticDiagnosticsBuilderProgram> =
183
- // ts.createSolutionBuilderWithWatch(solutionHost, [this._configuration.tsconfigPath], {});
184
- // watchBuilder.build();
185
- // } else {
186
- // const compilerHost: TWatchCompilerHost = this._buildWatchCompilerHost(ts, tsconfig);
187
- // ts.createWatchProgram(compilerHost);
188
- // }
189
- // return new Promise(() => {
190
- // /* never terminate */
191
- // });
192
- // }
178
+ _runWatch(tool) {
179
+ const { ts, measureSync: measureTsPerformance, pendingOperations, rawDiagnostics } = tool;
180
+ if (!tool.solutionBuilder && !tool.watchProgram) {
181
+ //#region CONFIGURE
182
+ const { duration: configureDurationMs, tsconfig } = measureTsPerformance('Configure', () => {
183
+ const _tsconfig = this._loadTsconfig(ts);
184
+ this._validateTsconfig(ts, _tsconfig);
185
+ return {
186
+ tsconfig: _tsconfig
187
+ };
188
+ });
189
+ this._typescriptTerminal.writeVerboseLine(`Configure: ${configureDurationMs}ms`);
190
+ //#endregion
191
+ if (this._useSolutionBuilder) {
192
+ const solutionHost = this._buildWatchSolutionBuilderHost(tool);
193
+ const builder = ts.createSolutionBuilderWithWatch(solutionHost, [this._configuration.tsconfigPath], {});
194
+ tool.solutionBuilder = builder;
195
+ builder.build();
196
+ }
197
+ else {
198
+ const compilerHost = this._buildWatchCompilerHost(tool, tsconfig);
199
+ tool.watchProgram = ts.createWatchProgram(compilerHost);
200
+ }
201
+ }
202
+ if (pendingOperations.size > 0) {
203
+ rawDiagnostics.length = 0;
204
+ tool.executing = true;
205
+ for (const operation of pendingOperations) {
206
+ pendingOperations.delete(operation);
207
+ operation();
208
+ }
209
+ tool.executing = false;
210
+ }
211
+ this._logDiagnostics(ts, rawDiagnostics);
212
+ }
193
213
  async _runBuildAsync(tool) {
194
214
  const { ts, measureSync: measureTsPerformance, measureAsync: measureTsPerformanceAsync } = tool;
195
215
  //#region CONFIGURE
@@ -210,11 +230,7 @@ class TypeScriptBuilder {
210
230
  let builderProgram = undefined;
211
231
  let tsProgram;
212
232
  if (tsconfig.options.incremental) {
213
- if (!tool.oldBuilderProgram) {
214
- tool.oldBuilderProgram = ts.readBuilderProgram(tsconfig.options, compilerHost);
215
- }
216
- builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(tsconfig.fileNames, tsconfig.options, compilerHost, tool.oldBuilderProgram, ts.getConfigFileParsingDiagnostics(tsconfig), tsconfig.projectReferences);
217
- tool.oldBuilderProgram = builderProgram;
233
+ builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(tsconfig.fileNames, tsconfig.options, compilerHost, ts.readBuilderProgram(tsconfig.options, compilerHost), ts.getConfigFileParsingDiagnostics(tsconfig), tsconfig.projectReferences);
218
234
  tsProgram = builderProgram.getProgram();
219
235
  }
220
236
  else {
@@ -223,10 +239,9 @@ class TypeScriptBuilder {
223
239
  options: tsconfig.options,
224
240
  projectReferences: tsconfig.projectReferences,
225
241
  host: compilerHost,
226
- oldProgram: tool.oldProgram,
242
+ oldProgram: undefined,
227
243
  configFileParsingDiagnostics: ts.getConfigFileParsingDiagnostics(tsconfig)
228
244
  });
229
- tool.oldProgram = tsProgram;
230
245
  }
231
246
  // Prefer the builder program, since it is what gives us incremental builds
232
247
  const genericProgram = builderProgram || tsProgram;
@@ -246,7 +261,7 @@ class TypeScriptBuilder {
246
261
  this._typescriptTerminal.writeVerboseLine(`Analyze: ${diagnosticsDurationMs}ms`);
247
262
  //#endregion
248
263
  //#region EMIT
249
- const emitResult = this._emit(ts, tsconfig, genericProgram);
264
+ const emitResult = this._emit(ts, genericProgram);
250
265
  //#endregion
251
266
  this._logEmitPerformance(ts);
252
267
  //#region FINAL_ANALYSIS
@@ -268,64 +283,43 @@ class TypeScriptBuilder {
268
283
  }
269
284
  _runSolutionBuild(tool) {
270
285
  this._typescriptTerminal.writeVerboseLine(`Using solution mode`);
271
- const { ts, measureSync } = tool;
272
- try {
286
+ const { ts, measureSync, rawDiagnostics } = tool;
287
+ rawDiagnostics.length = 0;
288
+ if (!tool.solutionBuilder) {
273
289
  //#region CONFIGURE
274
- const { duration: configureDurationMs, rawDiagnostics, solutionBuilderHost } = measureSync('Configure', () => {
275
- this._overrideTypeScriptReadJson(ts);
290
+ const { duration: configureDurationMs, solutionBuilderHost } = measureSync('Configure', () => {
276
291
  const _tsconfig = this._loadTsconfig(ts);
277
292
  this._validateTsconfig(ts, _tsconfig);
278
- const _rawDiagnostics = [];
279
- const reportDiagnostic = (diagnostic) => {
280
- _rawDiagnostics.push(diagnostic);
281
- };
282
- // TypeScript doesn't have a way to find out when a given program starts emitting in solution mode
283
- EmitFilesPatch_1.EmitFilesPatch.install(ts, _tsconfig, this._moduleKindsToEmit);
284
- const _solutionBuilderHost = this._buildSolutionBuilderHost(ts, reportDiagnostic);
285
- _solutionBuilderHost.afterProgramEmitAndDiagnostics = (program) => {
286
- const tsProgram = program.getProgram();
287
- if (tsProgram) {
288
- this._configuration.emitChangedFilesCallback(tsProgram);
289
- }
290
- };
293
+ const _solutionBuilderHost = this._buildSolutionBuilderHost(tool);
291
294
  return {
292
- rawDiagnostics: _rawDiagnostics,
293
295
  solutionBuilderHost: _solutionBuilderHost
294
296
  };
295
297
  });
296
298
  this._typescriptTerminal.writeVerboseLine(`Configure: ${configureDurationMs}ms`);
297
299
  //#endregion
298
- const solutionBuilder = ts.createSolutionBuilder(solutionBuilderHost, [this._configuration.tsconfigPath], {});
299
- //#region EMIT
300
- // Ignoring the exit status because we only care about presence of diagnostics
301
- solutionBuilder.build();
302
- //#endregion
303
- this._logReadPerformance(ts);
304
- this._logEmitPerformance(ts);
305
- // Use the native metric since we aren't overwriting the writer
306
- this._typescriptTerminal.writeVerboseLine(`I/O Write: ${ts.performance.getDuration('I/O Write')}ms (${ts.performance.getCount('beforeIOWrite')} files)`);
307
- this._logDiagnostics(ts, rawDiagnostics);
300
+ tool.solutionBuilder = ts.createSolutionBuilder(solutionBuilderHost, [this._configuration.tsconfigPath], {});
308
301
  }
309
- finally {
310
- EmitFilesPatch_1.EmitFilesPatch.uninstall(ts);
302
+ else {
303
+ // Force reload everything from disk
304
+ for (const project of tool.solutionBuilder.getBuildOrder()) {
305
+ tool.solutionBuilder.invalidateProject(project, 1);
306
+ }
311
307
  }
308
+ //#region EMIT
309
+ // Ignoring the exit status because we only care about presence of diagnostics
310
+ tool.solutionBuilder.build();
311
+ //#endregion
312
+ this._logDiagnostics(ts, rawDiagnostics);
312
313
  }
313
314
  _logDiagnostics(ts, rawDiagnostics) {
314
315
  const diagnostics = ts.sortAndDeduplicateDiagnostics(rawDiagnostics);
315
- let typeScriptErrorCount = 0;
316
316
  if (diagnostics.length > 0) {
317
317
  this._typescriptTerminal.writeLine(`Encountered ${diagnostics.length} TypeScript issue${diagnostics.length > 1 ? 's' : ''}:`);
318
318
  for (const diagnostic of diagnostics) {
319
319
  const diagnosticCategory = this._getAdjustedDiagnosticCategory(diagnostic, ts);
320
- if (diagnosticCategory === ts.DiagnosticCategory.Error) {
321
- typeScriptErrorCount++;
322
- }
323
320
  this._printDiagnosticMessage(ts, diagnostic, diagnosticCategory);
324
321
  }
325
322
  }
326
- if (typeScriptErrorCount > 0) {
327
- throw new Error(`Encountered TypeScript error${typeScriptErrorCount > 1 ? 's' : ''}`);
328
- }
329
323
  }
330
324
  _logEmitPerformance(ts) {
331
325
  this._typescriptTerminal.writeVerboseLine(`Bind: ${ts.performance.getDuration('Bind')}ms`);
@@ -397,10 +391,10 @@ class TypeScriptBuilder {
397
391
  }
398
392
  return diagnostic.category;
399
393
  }
400
- _emit(ts, tsconfig, genericProgram) {
394
+ _emit(ts, genericProgram) {
401
395
  const filesToWrite = [];
402
396
  const changedFiles = new Set();
403
- EmitFilesPatch_1.EmitFilesPatch.install(ts, tsconfig, this._moduleKindsToEmit, changedFiles);
397
+ EmitFilesPatch_1.EmitFilesPatch.install(ts, genericProgram.getCompilerOptions(), this._moduleKindsToEmit, changedFiles);
404
398
  const writeFileCallback = (filePath, data) => {
405
399
  filesToWrite.push({ filePath, data });
406
400
  };
@@ -558,24 +552,83 @@ class TypeScriptBuilder {
558
552
  }
559
553
  return tsconfig;
560
554
  }
561
- _buildSolutionBuilderHost(ts, reportDiagnostic) {
562
- const reportSolutionBuilderStatus = reportDiagnostic;
555
+ _getCreateBuilderProgram(tool) {
556
+ const { _moduleKindsToEmit: moduleKindsToEmit, _configuration: { emitChangedFilesCallback } } = this;
557
+ const { ts } = tool;
558
+ const createMultiEmitProgram = (fileNames, compilerOptions, host, oldProgram, configFileParsingDiagnostics, projectReferences) => {
559
+ // Reset performance counters
560
+ ts.performance.disable();
561
+ ts.performance.enable();
562
+ this._typescriptTerminal.writeVerboseLine(`Reading program "${compilerOptions.configFilePath}"`);
563
+ const newProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(fileNames, compilerOptions, host, oldProgram, configFileParsingDiagnostics, projectReferences);
564
+ this._logReadPerformance(ts);
565
+ const { emit: originalEmit } = newProgram;
566
+ if (!compilerOptions) {
567
+ throw new Error(`Expected compilerOptions!`);
568
+ }
569
+ const emit = (targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) => {
570
+ const changedFiles = new Set();
571
+ try {
572
+ EmitFilesPatch_1.EmitFilesPatch.install(ts, compilerOptions, moduleKindsToEmit, changedFiles);
573
+ const result = originalEmit.call(newProgram, targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
574
+ this._typescriptTerminal.writeVerboseLine(`Emitting program "${compilerOptions.configFilePath}"`);
575
+ this._logEmitPerformance(ts);
576
+ // Reset performance counters
577
+ ts.performance.disable();
578
+ ts.performance.enable();
579
+ emitChangedFilesCallback(newProgram.getProgram(), changedFiles);
580
+ return result;
581
+ }
582
+ finally {
583
+ EmitFilesPatch_1.EmitFilesPatch.uninstall(ts);
584
+ }
585
+ };
586
+ newProgram.emit = emit;
587
+ return newProgram;
588
+ };
589
+ return createMultiEmitProgram;
590
+ }
591
+ _buildSolutionBuilderHost(tool) {
592
+ const reportSolutionBuilderStatus = tool.reportDiagnostic;
563
593
  const reportEmitErrorSummary = (errorCount) => {
564
594
  // Do nothing
565
595
  };
566
- const compilerHost = ts.createSolutionBuilderHost(this._getCachingTypeScriptSystem(ts), ts.createEmitAndSemanticDiagnosticsBuilderProgram, reportDiagnostic, reportSolutionBuilderStatus, reportEmitErrorSummary);
567
- return compilerHost;
596
+ const { ts } = tool;
597
+ const solutionBuilderHost = ts.createSolutionBuilderHost(ts.sys, this._getCreateBuilderProgram(tool), tool.reportDiagnostic, reportSolutionBuilderStatus, reportEmitErrorSummary);
598
+ solutionBuilderHost.afterProgramEmitAndDiagnostics = (program) => {
599
+ // Use the native metric since we aren't overwriting the writer
600
+ this._typescriptTerminal.writeVerboseLine(`I/O Write: ${ts.performance.getDuration('I/O Write')}ms (${ts.performance.getCount('beforeIOWrite')} files)`);
601
+ };
602
+ return solutionBuilderHost;
568
603
  }
569
604
  _buildIncrementalCompilerHost(tool, tsconfig) {
570
- const { ts, sourceFileCache } = tool;
605
+ const { ts } = tool;
571
606
  let compilerHost;
572
607
  if (tsconfig.options.incremental) {
573
- compilerHost = ts.createIncrementalCompilerHost(tsconfig.options, this._getCachingTypeScriptSystem(ts));
608
+ compilerHost = ts.createIncrementalCompilerHost(tsconfig.options, ts.sys);
574
609
  }
575
610
  else {
576
611
  compilerHost = ts.createCompilerHost(tsconfig.options);
577
612
  }
613
+ this._changeCompilerHostToUseCache(compilerHost, tool);
614
+ return compilerHost;
615
+ }
616
+ _buildWatchCompilerHost(tool, tsconfig) {
617
+ const { ts } = tool;
618
+ const reportWatchStatus = (diagnostic) => {
619
+ this._printDiagnosticMessage(ts, diagnostic);
620
+ };
621
+ const compilerHost = ts.createWatchCompilerHost(tsconfig.fileNames, tsconfig.options, ts.sys, this._getCreateBuilderProgram(tool), tool.reportDiagnostic, reportWatchStatus, tsconfig.projectReferences);
622
+ compilerHost.clearTimeout = tool.clearTimeout;
623
+ compilerHost.setTimeout = tool.setTimeout;
624
+ return compilerHost;
625
+ }
626
+ _changeCompilerHostToUseCache(compilerHost, tool) {
627
+ const { sourceFileCache } = tool;
578
628
  const { getSourceFile: innerGetSourceFile } = compilerHost;
629
+ if (innerGetSourceFile.cache === sourceFileCache) {
630
+ return;
631
+ }
579
632
  // Enable source file persistence
580
633
  const getSourceFile = (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => {
581
634
  if (!shouldCreateNewSourceFile) {
@@ -593,97 +646,16 @@ class TypeScriptBuilder {
593
646
  }
594
647
  return result;
595
648
  };
649
+ getSourceFile.cache = sourceFileCache;
596
650
  compilerHost.getSourceFile = getSourceFile;
597
- return compilerHost;
598
651
  }
599
- _getCachingTypeScriptSystem(ts) {
600
- const sys = Object.assign(Object.assign({}, ts.sys), { deleteFile: this._cachedFileSystem.deleteFile.bind(this._cachedFileSystem),
601
- /** Check if the path exists and is a directory */
602
- directoryExists: (directoryPath) => {
603
- try {
604
- const stats = this._cachedFileSystem.getStatistics(directoryPath);
605
- return stats.isDirectory() || stats.isSymbolicLink();
606
- }
607
- catch (error) {
608
- if (node_core_library_1.FileSystem.isNotExistError(error)) {
609
- return false;
610
- }
611
- else {
612
- throw error;
613
- }
614
- }
615
- },
616
- /** Check if the path exists and is a file */
617
- fileExists: (filePath) => {
618
- try {
619
- const stats = this._cachedFileSystem.getStatistics(filePath);
620
- return stats.isFile();
621
- }
622
- catch (error) {
623
- if (node_core_library_1.FileSystem.isNotExistError(error)) {
624
- return false;
625
- }
626
- else {
627
- throw error;
628
- }
629
- }
630
- },
631
- /* Use the Heft config's build folder because it has corrected casing */
632
- getCurrentDirectory: () => this._configuration.buildFolderPath, getDirectories: (folderPath) => {
633
- return this._cachedFileSystem.readFolderFilesAndDirectories(folderPath).directories;
634
- }, realpath: this._cachedFileSystem.getRealPath.bind(this._cachedFileSystem) });
635
- return sys;
652
+ _buildWatchSolutionBuilderHost(tool) {
653
+ const { reportDiagnostic, ts } = tool;
654
+ const host = ts.createSolutionBuilderWithWatchHost(ts.sys, this._getCreateBuilderProgram(tool), reportDiagnostic, reportDiagnostic, reportDiagnostic);
655
+ host.clearTimeout = tool.clearTimeout;
656
+ host.setTimeout = tool.setTimeout;
657
+ return host;
636
658
  }
637
- // private _buildWatchCompilerHost(
638
- // ts: ExtendedTypeScript,
639
- // tsconfig: TTypescript.ParsedCommandLine
640
- // ): TWatchCompilerHost {
641
- // const reportDiagnostic: TTypescript.DiagnosticReporter = (diagnostic: TTypescript.Diagnostic): void => {
642
- // this._printDiagnosticMessage(ts, diagnostic);
643
- // };
644
- // const reportWatchStatus: TTypescript.DiagnosticReporter = (diagnostic: TTypescript.Diagnostic) => {
645
- // this._printDiagnosticMessage(ts, diagnostic);
646
- // // In watch mode, notify EmitCompletedCallbackManager every time we finish recompiling.
647
- // if (
648
- // diagnostic.code === ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code ||
649
- // diagnostic.code === ts.Diagnostics.Found_1_error_Watching_for_file_changes.code
650
- // ) {
651
- // this._emitCompletedCallbackManager.callback();
652
- // }
653
- // };
654
- // return ts.createWatchCompilerHost(
655
- // tsconfig.fileNames,
656
- // tsconfig.options,
657
- // this._getCachingTypeScriptSystem(ts),
658
- // ts.createEmitAndSemanticDiagnosticsBuilderProgram,
659
- // reportDiagnostic,
660
- // reportWatchStatus,
661
- // tsconfig.projectReferences
662
- // );
663
- // }
664
- // private _buildWatchSolutionBuilderHost(ts: ExtendedTypeScript): TWatchSolutionHost {
665
- // const reportDiagnostic: TTypescript.DiagnosticReporter = (diagnostic: TTypescript.Diagnostic): void => {
666
- // this._printDiagnosticMessage(ts, diagnostic);
667
- // };
668
- // const reportSolutionBuilderStatus: TTypescript.DiagnosticReporter = reportDiagnostic;
669
- // const reportWatchStatus: TTypescript.DiagnosticReporter = (diagnostic: TTypescript.Diagnostic) => {
670
- // this._printDiagnosticMessage(ts, diagnostic);
671
- // // In watch mode, notify EmitCompletedCallbackManager every time we finish recompiling.
672
- // if (
673
- // diagnostic.code === ts.Diagnostics.Found_0_errors_Watching_for_file_changes.code ||
674
- // diagnostic.code === ts.Diagnostics.Found_1_error_Watching_for_file_changes.code
675
- // ) {
676
- // this._emitCompletedCallbackManager.callback();
677
- // }
678
- // };
679
- // return ts.createSolutionBuilderWithWatchHost(
680
- // this._getCachingTypeScriptSystem(ts),
681
- // ts.createEmitAndSemanticDiagnosticsBuilderProgram,
682
- // reportDiagnostic,
683
- // reportSolutionBuilderStatus,
684
- // reportWatchStatus
685
- // );
686
- // }
687
659
  _overrideTypeScriptReadJson(ts) {
688
660
  const cachedReadJson = (filePath) => {
689
661
  let jsonData = this._tsReadJsonCache.get(filePath);