Refactor: No more than 1 namespace declaration per file (#35373)
* Refactor: No more than 1 namespace declaration per file * Simplify refs where possible
This commit is contained in:
parent
1320c36165
commit
c447ebc59c
|
@ -54,6 +54,7 @@
|
|||
"simple-indent": "error",
|
||||
"debug-assert": "error",
|
||||
"no-keywords": "error",
|
||||
"one-namespace-per-file": "error",
|
||||
|
||||
// eslint-plugin-import
|
||||
"import/no-extraneous-dependencies": ["error", { "optionalDependencies": false }],
|
||||
|
|
|
@ -587,15 +587,15 @@ task("generate-spec").description = "Generates a Markdown version of the Languag
|
|||
task("clean", series(parallel(cleanTasks), cleanBuilt));
|
||||
task("clean").description = "Cleans build outputs";
|
||||
|
||||
const configureNightly = () => exec(process.execPath, ["scripts/configurePrerelease.js", "dev", "package.json", "src/compiler/core.ts"]);
|
||||
const configureNightly = () => exec(process.execPath, ["scripts/configurePrerelease.js", "dev", "package.json", "src/compiler/corePublic.ts"]);
|
||||
task("configure-nightly", series(buildScripts, configureNightly));
|
||||
task("configure-nightly").description = "Runs scripts/configurePrerelease.ts to prepare a build for nightly publishing";
|
||||
|
||||
const configureInsiders = () => exec(process.execPath, ["scripts/configurePrerelease.js", "insiders", "package.json", "src/compiler/core.ts"]);
|
||||
const configureInsiders = () => exec(process.execPath, ["scripts/configurePrerelease.js", "insiders", "package.json", "src/compiler/corePublic.ts"]);
|
||||
task("configure-insiders", series(buildScripts, configureInsiders));
|
||||
task("configure-insiders").description = "Runs scripts/configurePrerelease.ts to prepare a build for insiders publishing";
|
||||
|
||||
const configureExperimental = () => exec(process.execPath, ["scripts/configurePrerelease.js", "experimental", "package.json", "src/compiler/core.ts"]);
|
||||
const configureExperimental = () => exec(process.execPath, ["scripts/configurePrerelease.js", "experimental", "package.json", "src/compiler/corePublic.ts"]);
|
||||
task("configure-experimental", series(buildScripts, configureExperimental));
|
||||
task("configure-experimental").description = "Runs scripts/configurePrerelease.ts to prepare a build for experimental publishing";
|
||||
|
||||
|
|
44
scripts/eslint/rules/one-namespace-per-file.ts
Normal file
44
scripts/eslint/rules/one-namespace-per-file.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/experimental-utils";
|
||||
import { createRule } from "./utils";
|
||||
|
||||
export = createRule({
|
||||
name: "one-namespace-per-file",
|
||||
meta: {
|
||||
docs: {
|
||||
description: `Limits each file to having at most one top-level namespace declaration`,
|
||||
category: "Possible Errors",
|
||||
recommended: "error",
|
||||
},
|
||||
messages: {
|
||||
excessNamespaceError: `All but one of these namespaces should be moved into seperate files.`,
|
||||
},
|
||||
schema: [],
|
||||
type: "problem",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const isNamespaceDeclaration = (node: TSESTree.Node): node is TSESTree.TSModuleDeclaration => node.type === AST_NODE_TYPES.TSModuleDeclaration;
|
||||
|
||||
const checkSourceFile = (node: TSESTree.Program) => {
|
||||
if (context.getFilename().endsWith(".d.ts")) {
|
||||
return;
|
||||
}
|
||||
const members = node.body;
|
||||
const namespaces = members.filter(isNamespaceDeclaration);
|
||||
if (namespaces.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
namespaces.forEach(n => {
|
||||
context.report({
|
||||
messageId: "excessNamespaceError", node: n
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
Program: checkSourceFile,
|
||||
};
|
||||
},
|
||||
});
|
|
@ -1183,165 +1183,4 @@ namespace ts {
|
|||
return Debug.assertDefined(state.program);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace ts {
|
||||
export type AffectedFileResult<T> = { result: T; affected: SourceFile | Program; } | undefined;
|
||||
|
||||
export interface BuilderProgramHost {
|
||||
/**
|
||||
* return true if file names are treated with case sensitivity
|
||||
*/
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
/**
|
||||
* If provided this would be used this hash instead of actual file shape text for detecting changes
|
||||
*/
|
||||
createHash?: (data: string) => string;
|
||||
/**
|
||||
* When emit or emitNextAffectedFile are called without writeFile,
|
||||
* this callback if present would be used to write files
|
||||
*/
|
||||
writeFile?: WriteFileCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder to manage the program state changes
|
||||
*/
|
||||
export interface BuilderProgram {
|
||||
/*@internal*/
|
||||
getState(): ReusableBuilderProgramState;
|
||||
/*@internal*/
|
||||
backupState(): void;
|
||||
/*@internal*/
|
||||
restoreState(): void;
|
||||
/**
|
||||
* Returns current program
|
||||
*/
|
||||
getProgram(): Program;
|
||||
/**
|
||||
* Returns current program that could be undefined if the program was released
|
||||
*/
|
||||
/*@internal*/
|
||||
getProgramOrUndefined(): Program | undefined;
|
||||
/**
|
||||
* Releases reference to the program, making all the other operations that need program to fail.
|
||||
*/
|
||||
/*@internal*/
|
||||
releaseProgram(): void;
|
||||
/**
|
||||
* Get compiler options of the program
|
||||
*/
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
/**
|
||||
* Get the source file in the program with file name
|
||||
*/
|
||||
getSourceFile(fileName: string): SourceFile | undefined;
|
||||
/**
|
||||
* Get a list of files in the program
|
||||
*/
|
||||
getSourceFiles(): readonly SourceFile[];
|
||||
/**
|
||||
* Get the diagnostics for compiler options
|
||||
*/
|
||||
getOptionsDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
/**
|
||||
* Get the diagnostics that dont belong to any file
|
||||
*/
|
||||
getGlobalDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
/**
|
||||
* Get the diagnostics from config file parsing
|
||||
*/
|
||||
getConfigFileParsingDiagnostics(): readonly Diagnostic[];
|
||||
/**
|
||||
* Get the syntax diagnostics, for all source files if source file is not supplied
|
||||
*/
|
||||
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
/**
|
||||
* Get the declaration diagnostics, for all source files if source file is not supplied
|
||||
*/
|
||||
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[];
|
||||
/**
|
||||
* Get all the dependencies of the file
|
||||
*/
|
||||
getAllDependencies(sourceFile: SourceFile): readonly string[];
|
||||
|
||||
/**
|
||||
* Gets the semantic diagnostics from the program corresponding to this state of file (if provided) or whole program
|
||||
* The semantic diagnostics are cached and managed here
|
||||
* Note that it is assumed that when asked about semantic diagnostics through this API,
|
||||
* the file has been taken out of affected files so it is safe to use cache or get from program and cache the diagnostics
|
||||
* In case of SemanticDiagnosticsBuilderProgram if the source file is not provided,
|
||||
* it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics
|
||||
*/
|
||||
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
/**
|
||||
* Emits the JavaScript and declaration files.
|
||||
* When targetSource file is specified, emits the files corresponding to that source file,
|
||||
* otherwise for the whole program.
|
||||
* In case of EmitAndSemanticDiagnosticsBuilderProgram, when targetSourceFile is specified,
|
||||
* it is assumed that that file is handled from affected file list. If targetSourceFile is not specified,
|
||||
* it will only emit all the affected files instead of whole program
|
||||
*
|
||||
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
|
||||
* in that order would be used to write the files
|
||||
*/
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
|
||||
/**
|
||||
* Get the current directory of the program
|
||||
*/
|
||||
getCurrentDirectory(): string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The builder that caches the semantic diagnostics for the program and handles the changed files and affected files
|
||||
*/
|
||||
export interface SemanticDiagnosticsBuilderProgram extends BuilderProgram {
|
||||
/**
|
||||
* Gets the semantic diagnostics from the program for the next affected file and caches it
|
||||
* Returns undefined if the iteration is complete
|
||||
*/
|
||||
getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult<readonly Diagnostic[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The builder that can handle the changes in program and iterate through changed file to emit the files
|
||||
* The semantic diagnostics are cached per file and managed by clearing for the changed/affected files
|
||||
*/
|
||||
export interface EmitAndSemanticDiagnosticsBuilderProgram extends SemanticDiagnosticsBuilderProgram {
|
||||
/**
|
||||
* Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete
|
||||
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
|
||||
* in that order would be used to write the files
|
||||
*/
|
||||
emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult<EmitResult>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the builder to manage semantic diagnostics and cache them
|
||||
*/
|
||||
export function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): SemanticDiagnosticsBuilderProgram;
|
||||
export function createSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): SemanticDiagnosticsBuilderProgram;
|
||||
export function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]) {
|
||||
return createBuilderProgram(BuilderProgramKind.SemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): EmitAndSemanticDiagnosticsBuilderProgram;
|
||||
export function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): EmitAndSemanticDiagnosticsBuilderProgram;
|
||||
export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]) {
|
||||
return createBuilderProgram(BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a builder thats just abstraction over program and can be used with watch
|
||||
*/
|
||||
export function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): BuilderProgram;
|
||||
export function createAbstractBuilder(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram;
|
||||
export function createAbstractBuilder(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram {
|
||||
const { newProgram, configFileParsingDiagnostics: newConfigFileParsingDiagnostics } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
return createRedirectedBuilderProgram({ program: newProgram, compilerOptions: newProgram.getCompilerOptions() }, newConfigFileParsingDiagnostics);
|
||||
}
|
||||
}
|
||||
}
|
160
src/compiler/builderPublic.ts
Normal file
160
src/compiler/builderPublic.ts
Normal file
|
@ -0,0 +1,160 @@
|
|||
namespace ts {
|
||||
export type AffectedFileResult<T> = { result: T; affected: SourceFile | Program; } | undefined;
|
||||
|
||||
export interface BuilderProgramHost {
|
||||
/**
|
||||
* return true if file names are treated with case sensitivity
|
||||
*/
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
/**
|
||||
* If provided this would be used this hash instead of actual file shape text for detecting changes
|
||||
*/
|
||||
createHash?: (data: string) => string;
|
||||
/**
|
||||
* When emit or emitNextAffectedFile are called without writeFile,
|
||||
* this callback if present would be used to write files
|
||||
*/
|
||||
writeFile?: WriteFileCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder to manage the program state changes
|
||||
*/
|
||||
export interface BuilderProgram {
|
||||
/*@internal*/
|
||||
getState(): ReusableBuilderProgramState;
|
||||
/*@internal*/
|
||||
backupState(): void;
|
||||
/*@internal*/
|
||||
restoreState(): void;
|
||||
/**
|
||||
* Returns current program
|
||||
*/
|
||||
getProgram(): Program;
|
||||
/**
|
||||
* Returns current program that could be undefined if the program was released
|
||||
*/
|
||||
/*@internal*/
|
||||
getProgramOrUndefined(): Program | undefined;
|
||||
/**
|
||||
* Releases reference to the program, making all the other operations that need program to fail.
|
||||
*/
|
||||
/*@internal*/
|
||||
releaseProgram(): void;
|
||||
/**
|
||||
* Get compiler options of the program
|
||||
*/
|
||||
getCompilerOptions(): CompilerOptions;
|
||||
/**
|
||||
* Get the source file in the program with file name
|
||||
*/
|
||||
getSourceFile(fileName: string): SourceFile | undefined;
|
||||
/**
|
||||
* Get a list of files in the program
|
||||
*/
|
||||
getSourceFiles(): readonly SourceFile[];
|
||||
/**
|
||||
* Get the diagnostics for compiler options
|
||||
*/
|
||||
getOptionsDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
/**
|
||||
* Get the diagnostics that dont belong to any file
|
||||
*/
|
||||
getGlobalDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
/**
|
||||
* Get the diagnostics from config file parsing
|
||||
*/
|
||||
getConfigFileParsingDiagnostics(): readonly Diagnostic[];
|
||||
/**
|
||||
* Get the syntax diagnostics, for all source files if source file is not supplied
|
||||
*/
|
||||
getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
/**
|
||||
* Get the declaration diagnostics, for all source files if source file is not supplied
|
||||
*/
|
||||
getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[];
|
||||
/**
|
||||
* Get all the dependencies of the file
|
||||
*/
|
||||
getAllDependencies(sourceFile: SourceFile): readonly string[];
|
||||
|
||||
/**
|
||||
* Gets the semantic diagnostics from the program corresponding to this state of file (if provided) or whole program
|
||||
* The semantic diagnostics are cached and managed here
|
||||
* Note that it is assumed that when asked about semantic diagnostics through this API,
|
||||
* the file has been taken out of affected files so it is safe to use cache or get from program and cache the diagnostics
|
||||
* In case of SemanticDiagnosticsBuilderProgram if the source file is not provided,
|
||||
* it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics
|
||||
*/
|
||||
getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[];
|
||||
/**
|
||||
* Emits the JavaScript and declaration files.
|
||||
* When targetSource file is specified, emits the files corresponding to that source file,
|
||||
* otherwise for the whole program.
|
||||
* In case of EmitAndSemanticDiagnosticsBuilderProgram, when targetSourceFile is specified,
|
||||
* it is assumed that that file is handled from affected file list. If targetSourceFile is not specified,
|
||||
* it will only emit all the affected files instead of whole program
|
||||
*
|
||||
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
|
||||
* in that order would be used to write the files
|
||||
*/
|
||||
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
|
||||
/**
|
||||
* Get the current directory of the program
|
||||
*/
|
||||
getCurrentDirectory(): string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The builder that caches the semantic diagnostics for the program and handles the changed files and affected files
|
||||
*/
|
||||
export interface SemanticDiagnosticsBuilderProgram extends BuilderProgram {
|
||||
/**
|
||||
* Gets the semantic diagnostics from the program for the next affected file and caches it
|
||||
* Returns undefined if the iteration is complete
|
||||
*/
|
||||
getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult<readonly Diagnostic[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The builder that can handle the changes in program and iterate through changed file to emit the files
|
||||
* The semantic diagnostics are cached per file and managed by clearing for the changed/affected files
|
||||
*/
|
||||
export interface EmitAndSemanticDiagnosticsBuilderProgram extends SemanticDiagnosticsBuilderProgram {
|
||||
/**
|
||||
* Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete
|
||||
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
|
||||
* in that order would be used to write the files
|
||||
*/
|
||||
emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult<EmitResult>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the builder to manage semantic diagnostics and cache them
|
||||
*/
|
||||
export function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): SemanticDiagnosticsBuilderProgram;
|
||||
export function createSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): SemanticDiagnosticsBuilderProgram;
|
||||
export function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]) {
|
||||
return createBuilderProgram(BuilderProgramKind.SemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): EmitAndSemanticDiagnosticsBuilderProgram;
|
||||
export function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): EmitAndSemanticDiagnosticsBuilderProgram;
|
||||
export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]) {
|
||||
return createBuilderProgram(BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a builder thats just abstraction over program and can be used with watch
|
||||
*/
|
||||
export function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): BuilderProgram;
|
||||
export function createAbstractBuilder(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram;
|
||||
export function createAbstractBuilder(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram {
|
||||
const { newProgram, configFileParsingDiagnostics: newConfigFileParsingDiagnostics } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
return createRedirectedBuilderProgram({ program: newProgram, compilerOptions: newProgram.getCompilerOptions() }, newConfigFileParsingDiagnostics);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
13
src/compiler/builderStatePublic.ts
Normal file
13
src/compiler/builderStatePublic.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
namespace ts {
|
||||
export interface EmitOutput {
|
||||
outputFiles: OutputFile[];
|
||||
emitSkipped: boolean;
|
||||
/* @internal */ exportedModulesFromDeclarationEmit?: ExportedModulesFromDeclarationEmit;
|
||||
}
|
||||
|
||||
export interface OutputFile {
|
||||
name: string;
|
||||
writeByteOrderMark: boolean;
|
||||
text: string;
|
||||
}
|
||||
}
|
|
@ -1,95 +1,22 @@
|
|||
namespace ts {
|
||||
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
|
||||
// If changing the text in this section, be sure to test `configureNightly` too.
|
||||
export const versionMajorMinor = "3.8";
|
||||
/** The version of the TypeScript compiler release */
|
||||
export const version = `${versionMajorMinor}.0-dev`;
|
||||
}
|
||||
|
||||
namespace ts {
|
||||
/**
|
||||
* Type of objects whose values are all of the same type.
|
||||
* The `in` and `for-in` operators can *not* be safely used,
|
||||
* since `Object.prototype` may be modified by outside code.
|
||||
*/
|
||||
export interface MapLike<T> {
|
||||
[index: string]: T;
|
||||
}
|
||||
|
||||
export interface SortedReadonlyArray<T> extends ReadonlyArray<T> {
|
||||
" __sortedArrayBrand": any;
|
||||
}
|
||||
|
||||
export interface SortedArray<T> extends Array<T> {
|
||||
" __sortedArrayBrand": any;
|
||||
}
|
||||
|
||||
/** ES6 Map interface, only read methods included. */
|
||||
export interface ReadonlyMap<T> {
|
||||
get(key: string): T | undefined;
|
||||
has(key: string): boolean;
|
||||
forEach(action: (value: T, key: string) => void): void;
|
||||
readonly size: number;
|
||||
keys(): Iterator<string>;
|
||||
values(): Iterator<T>;
|
||||
entries(): Iterator<[string, T]>;
|
||||
}
|
||||
|
||||
/** ES6 Map interface. */
|
||||
export interface Map<T> extends ReadonlyMap<T> {
|
||||
set(key: string, value: T): this;
|
||||
delete(key: string): boolean;
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface MapConstructor {
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-function-type
|
||||
new <T>(): Map<T>;
|
||||
}
|
||||
|
||||
/** ES6 Iterator type. */
|
||||
export interface Iterator<T> {
|
||||
next(): { value: T, done?: false } | { value: never, done: true };
|
||||
}
|
||||
|
||||
/** Array that is only intended to be pushed to, never read. */
|
||||
export interface Push<T> {
|
||||
push(...values: T[]): void;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export type EqualityComparer<T> = (a: T, b: T) => boolean;
|
||||
|
||||
/* @internal */
|
||||
export type Comparer<T> = (a: T, b: T) => Comparison;
|
||||
|
||||
/* @internal */
|
||||
export const enum Comparison {
|
||||
LessThan = -1,
|
||||
EqualTo = 0,
|
||||
GreaterThan = 1
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
// Natives
|
||||
// NOTE: This must be declared in a separate block from the one below so that we don't collide with the exported definition of `Map`.
|
||||
declare const Map: (new <T>() => Map<T>) | undefined;
|
||||
|
||||
/**
|
||||
* Returns the native Map implementation if it is available and compatible (i.e. supports iteration).
|
||||
*/
|
||||
export function tryGetNativeMap(): MapConstructor | undefined {
|
||||
// Internet Explorer's Map doesn't support iteration, so don't use it.
|
||||
// Natives
|
||||
// NOTE: TS doesn't strictly allow in-line declares, but if we suppress the error, the declaration
|
||||
// is still used for typechecking _and_ correctly elided, which is out goal, as this prevents us from
|
||||
// needing to pollute an outer scope with a declaration of `Map` just to satisfy the checks in this function
|
||||
//@ts-ignore
|
||||
declare const Map: (new <T>() => Map<T>) | undefined;
|
||||
// eslint-disable-next-line no-in-operator
|
||||
return typeof Map !== "undefined" && "entries" in Map.prototype ? Map : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export const emptyArray: never[] = [] as never[];
|
||||
|
||||
export const Map: MapConstructor = tryGetNativeMap() || (() => {
|
||||
|
@ -2074,4 +2001,4 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
71
src/compiler/corePublic.ts
Normal file
71
src/compiler/corePublic.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
namespace ts {
|
||||
// WARNING: The script `configureNightly.ts` uses a regexp to parse out these values.
|
||||
// If changing the text in this section, be sure to test `configureNightly` too.
|
||||
export const versionMajorMinor = "3.8";
|
||||
/** The version of the TypeScript compiler release */
|
||||
export const version = `${versionMajorMinor}.0-dev`;
|
||||
|
||||
/**
|
||||
* Type of objects whose values are all of the same type.
|
||||
* The `in` and `for-in` operators can *not* be safely used,
|
||||
* since `Object.prototype` may be modified by outside code.
|
||||
*/
|
||||
export interface MapLike<T> {
|
||||
[index: string]: T;
|
||||
}
|
||||
|
||||
export interface SortedReadonlyArray<T> extends ReadonlyArray<T> {
|
||||
" __sortedArrayBrand": any;
|
||||
}
|
||||
|
||||
export interface SortedArray<T> extends Array<T> {
|
||||
" __sortedArrayBrand": any;
|
||||
}
|
||||
|
||||
/** ES6 Map interface, only read methods included. */
|
||||
export interface ReadonlyMap<T> {
|
||||
get(key: string): T | undefined;
|
||||
has(key: string): boolean;
|
||||
forEach(action: (value: T, key: string) => void): void;
|
||||
readonly size: number;
|
||||
keys(): Iterator<string>;
|
||||
values(): Iterator<T>;
|
||||
entries(): Iterator<[string, T]>;
|
||||
}
|
||||
|
||||
/** ES6 Map interface. */
|
||||
export interface Map<T> extends ReadonlyMap<T> {
|
||||
set(key: string, value: T): this;
|
||||
delete(key: string): boolean;
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface MapConstructor {
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-function-type
|
||||
new <T>(): Map<T>;
|
||||
}
|
||||
|
||||
/** ES6 Iterator type. */
|
||||
export interface Iterator<T> {
|
||||
next(): { value: T, done?: false } | { value: never, done: true };
|
||||
}
|
||||
|
||||
/** Array that is only intended to be pushed to, never read. */
|
||||
export interface Push<T> {
|
||||
push(...values: T[]): void;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export type EqualityComparer<T> = (a: T, b: T) => boolean;
|
||||
|
||||
/* @internal */
|
||||
export type Comparer<T> = (a: T, b: T) => Comparison;
|
||||
|
||||
/* @internal */
|
||||
export const enum Comparison {
|
||||
LessThan = -1,
|
||||
EqualTo = 0,
|
||||
GreaterThan = 1
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
3669
src/compiler/factoryPublic.ts
Normal file
3669
src/compiler/factoryPublic.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,3 @@
|
|||
/*@internal*/
|
||||
namespace ts {
|
||||
declare const performance: { now?(): number } | undefined;
|
||||
/** Gets a timestamp with (at least) ms resolution */
|
||||
export const timestamp = typeof performance !== "undefined" && performance.now ? () => performance.now!() : Date.now ? Date.now : () => +(new Date());
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
/** Performance measurements for the compiler. */
|
||||
namespace ts.performance {
|
||||
|
|
6
src/compiler/performanceTimestamp.ts
Normal file
6
src/compiler/performanceTimestamp.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
/*@internal*/
|
||||
namespace ts {
|
||||
declare const performance: { now?(): number } | undefined;
|
||||
/** Gets a timestamp with (at least) ms resolution */
|
||||
export const timestamp = typeof performance !== "undefined" && performance.now ? () => performance.now!() : Date.now ? Date.now : () => +(new Date());
|
||||
}
|
File diff suppressed because it is too large
Load diff
2069
src/compiler/tsbuildPublic.ts
Normal file
2069
src/compiler/tsbuildPublic.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -9,8 +9,10 @@
|
|||
],
|
||||
|
||||
"files": [
|
||||
"corePublic.ts",
|
||||
"core.ts",
|
||||
"debug.ts",
|
||||
"performanceTimestamp.ts",
|
||||
"performance.ts",
|
||||
"perfLogger.ts",
|
||||
"semver.ts",
|
||||
|
@ -20,6 +22,7 @@
|
|||
"path.ts",
|
||||
"diagnosticInformationMap.generated.ts",
|
||||
"scanner.ts",
|
||||
"utilitiesPublic.ts",
|
||||
"utilities.ts",
|
||||
"parser.ts",
|
||||
"commandLineParser.ts",
|
||||
|
@ -28,7 +31,9 @@
|
|||
"binder.ts",
|
||||
"symbolWalker.ts",
|
||||
"checker.ts",
|
||||
"factoryPublic.ts",
|
||||
"factory.ts",
|
||||
"visitorPublic.ts",
|
||||
"visitor.ts",
|
||||
"sourcemap.ts",
|
||||
"transformers/utilities.ts",
|
||||
|
@ -53,11 +58,15 @@
|
|||
"emitter.ts",
|
||||
"watchUtilities.ts",
|
||||
"program.ts",
|
||||
"builderStatePublic.ts",
|
||||
"builderState.ts",
|
||||
"builder.ts",
|
||||
"builderPublic.ts",
|
||||
"resolutionCache.ts",
|
||||
"moduleSpecifiers.ts",
|
||||
"watch.ts",
|
||||
"watchPublic.ts",
|
||||
"tsbuild.ts",
|
||||
"tsbuildPublic.ts",
|
||||
]
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
2473
src/compiler/utilitiesPublic.ts
Normal file
2473
src/compiler/utilitiesPublic.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,957 +1,3 @@
|
|||
namespace ts {
|
||||
const isTypeNodeOrTypeParameterDeclaration = or(isTypeNode, isTypeParameterDeclaration);
|
||||
|
||||
/**
|
||||
* Visits a Node using the supplied visitor, possibly returning a new Node in its place.
|
||||
*
|
||||
* @param node The Node to visit.
|
||||
* @param visitor The callback used to visit the Node.
|
||||
* @param test A callback to execute to verify the Node is valid.
|
||||
* @param lift An optional callback to execute to lift a NodeArray into a valid Node.
|
||||
*/
|
||||
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T;
|
||||
|
||||
/**
|
||||
* Visits a Node using the supplied visitor, possibly returning a new Node in its place.
|
||||
*
|
||||
* @param node The Node to visit.
|
||||
* @param visitor The callback used to visit the Node.
|
||||
* @param test A callback to execute to verify the Node is valid.
|
||||
* @param lift An optional callback to execute to lift a NodeArray into a valid Node.
|
||||
*/
|
||||
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T | undefined;
|
||||
|
||||
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T | undefined {
|
||||
if (node === undefined || visitor === undefined) {
|
||||
return node;
|
||||
}
|
||||
|
||||
aggregateTransformFlags(node);
|
||||
const visited = visitor(node);
|
||||
if (visited === node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
let visitedNode: Node | undefined;
|
||||
if (visited === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
else if (isArray(visited)) {
|
||||
visitedNode = (lift || extractSingleNode)(visited);
|
||||
}
|
||||
else {
|
||||
visitedNode = visited;
|
||||
}
|
||||
|
||||
Debug.assertNode(visitedNode, test);
|
||||
aggregateTransformFlags(visitedNode!);
|
||||
return <T>visitedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place.
|
||||
*
|
||||
* @param nodes The NodeArray to visit.
|
||||
* @param visitor The callback used to visit a Node.
|
||||
* @param test A node test to execute for each node.
|
||||
* @param start An optional value indicating the starting offset at which to start visiting.
|
||||
* @param count An optional value indicating the maximum number of nodes to visit.
|
||||
*/
|
||||
export function visitNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
|
||||
|
||||
/**
|
||||
* Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place.
|
||||
*
|
||||
* @param nodes The NodeArray to visit.
|
||||
* @param visitor The callback used to visit a Node.
|
||||
* @param test A node test to execute for each node.
|
||||
* @param start An optional value indicating the starting offset at which to start visiting.
|
||||
* @param count An optional value indicating the maximum number of nodes to visit.
|
||||
*/
|
||||
export function visitNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> | undefined;
|
||||
|
||||
/**
|
||||
* Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place.
|
||||
*
|
||||
* @param nodes The NodeArray to visit.
|
||||
* @param visitor The callback used to visit a Node.
|
||||
* @param test A node test to execute for each node.
|
||||
* @param start An optional value indicating the starting offset at which to start visiting.
|
||||
* @param count An optional value indicating the maximum number of nodes to visit.
|
||||
*/
|
||||
export function visitNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> | undefined {
|
||||
if (nodes === undefined || visitor === undefined) {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
let updated: MutableNodeArray<T> | undefined;
|
||||
|
||||
// Ensure start and count have valid values
|
||||
const length = nodes.length;
|
||||
if (start === undefined || start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (count === undefined || count > length - start) {
|
||||
count = length - start;
|
||||
}
|
||||
|
||||
if (start > 0 || count < length) {
|
||||
// If we are not visiting all of the original nodes, we must always create a new array.
|
||||
// Since this is a fragment of a node array, we do not copy over the previous location
|
||||
// and will only copy over `hasTrailingComma` if we are including the last element.
|
||||
updated = createNodeArray<T>([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length);
|
||||
}
|
||||
|
||||
// Visit each original node.
|
||||
for (let i = 0; i < count; i++) {
|
||||
const node = nodes[i + start];
|
||||
aggregateTransformFlags(node);
|
||||
const visited = node !== undefined ? visitor(node) : undefined;
|
||||
if (updated !== undefined || visited === undefined || visited !== node) {
|
||||
if (updated === undefined) {
|
||||
// Ensure we have a copy of `nodes`, up to the current index.
|
||||
updated = createNodeArray(nodes.slice(0, i), nodes.hasTrailingComma);
|
||||
setTextRange(updated, nodes);
|
||||
}
|
||||
if (visited) {
|
||||
if (isArray(visited)) {
|
||||
for (const visitedNode of visited) {
|
||||
Debug.assertNode(visitedNode, test);
|
||||
aggregateTransformFlags(visitedNode);
|
||||
updated.push(<T>visitedNode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.assertNode(visited, test);
|
||||
aggregateTransformFlags(visited);
|
||||
updated.push(<T>visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updated || nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new lexical environment and visits a statement list, ending the lexical environment
|
||||
* and merging hoisted declarations upon completion.
|
||||
*/
|
||||
export function visitLexicalEnvironment(statements: NodeArray<Statement>, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean) {
|
||||
context.startLexicalEnvironment();
|
||||
statements = visitNodes(statements, visitor, isStatement, start);
|
||||
if (ensureUseStrict) statements = ts.ensureUseStrict(statements); // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier
|
||||
return mergeLexicalEnvironment(statements, context.endLexicalEnvironment());
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new lexical environment and visits a parameter list, suspending the lexical
|
||||
* environment upon completion.
|
||||
*/
|
||||
export function visitParameterList(nodes: NodeArray<ParameterDeclaration> | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) {
|
||||
context.startLexicalEnvironment();
|
||||
const updated = nodesVisitor(nodes, visitor, isParameterDeclaration);
|
||||
context.suspendLexicalEnvironment();
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes a suspended lexical environment and visits a function body, ending the lexical
|
||||
* environment and merging hoisted declarations upon completion.
|
||||
*/
|
||||
export function visitFunctionBody(node: FunctionBody, visitor: Visitor, context: TransformationContext): FunctionBody;
|
||||
/**
|
||||
* Resumes a suspended lexical environment and visits a function body, ending the lexical
|
||||
* environment and merging hoisted declarations upon completion.
|
||||
*/
|
||||
export function visitFunctionBody(node: FunctionBody | undefined, visitor: Visitor, context: TransformationContext): FunctionBody | undefined;
|
||||
/**
|
||||
* Resumes a suspended lexical environment and visits a concise body, ending the lexical
|
||||
* environment and merging hoisted declarations upon completion.
|
||||
*/
|
||||
export function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody;
|
||||
export function visitFunctionBody(node: ConciseBody | undefined, visitor: Visitor, context: TransformationContext): ConciseBody | undefined {
|
||||
context.resumeLexicalEnvironment();
|
||||
const updated = visitNode(node, visitor, isConciseBody);
|
||||
const declarations = context.endLexicalEnvironment();
|
||||
if (some(declarations)) {
|
||||
const block = convertToFunctionBody(updated);
|
||||
const statements = mergeLexicalEnvironment(block.statements, declarations);
|
||||
return updateBlock(block, statements);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
|
||||
*
|
||||
* @param node The Node whose children will be visited.
|
||||
* @param visitor The callback used to visit each child.
|
||||
* @param context A lexical environment context for the visitor.
|
||||
*/
|
||||
export function visitEachChild<T extends Node>(node: T, visitor: Visitor, context: TransformationContext): T;
|
||||
|
||||
/**
|
||||
* Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
|
||||
*
|
||||
* @param node The Node whose children will be visited.
|
||||
* @param visitor The callback used to visit each child.
|
||||
* @param context A lexical environment context for the visitor.
|
||||
*/
|
||||
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined;
|
||||
|
||||
export function visitEachChild(node: Node | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor): Node | undefined {
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const kind = node.kind;
|
||||
|
||||
// No need to visit nodes with no children.
|
||||
if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken) || kind === SyntaxKind.ThisType) {
|
||||
return node;
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
// Names
|
||||
|
||||
case SyntaxKind.Identifier:
|
||||
return updateIdentifier(<Identifier>node, nodesVisitor((<Identifier>node).typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration));
|
||||
|
||||
case SyntaxKind.QualifiedName:
|
||||
return updateQualifiedName(<QualifiedName>node,
|
||||
visitNode((<QualifiedName>node).left, visitor, isEntityName),
|
||||
visitNode((<QualifiedName>node).right, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
return updateComputedPropertyName(<ComputedPropertyName>node,
|
||||
visitNode((<ComputedPropertyName>node).expression, visitor, isExpression));
|
||||
|
||||
// Signature elements
|
||||
case SyntaxKind.TypeParameter:
|
||||
return updateTypeParameterDeclaration(<TypeParameterDeclaration>node,
|
||||
visitNode((<TypeParameterDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<TypeParameterDeclaration>node).constraint, visitor, isTypeNode),
|
||||
visitNode((<TypeParameterDeclaration>node).default, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.Parameter:
|
||||
return updateParameter(<ParameterDeclaration>node,
|
||||
nodesVisitor((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ParameterDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ParameterDeclaration>node).dotDotDotToken, tokenVisitor, isToken),
|
||||
visitNode((<ParameterDeclaration>node).name, visitor, isBindingName),
|
||||
visitNode((<ParameterDeclaration>node).questionToken, tokenVisitor, isToken),
|
||||
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode),
|
||||
visitNode((<ParameterDeclaration>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
return updateDecorator(<Decorator>node,
|
||||
visitNode((<Decorator>node).expression, visitor, isExpression));
|
||||
|
||||
// Type elements
|
||||
case SyntaxKind.PropertySignature:
|
||||
return updatePropertySignature((<PropertySignature>node),
|
||||
nodesVisitor((<PropertySignature>node).modifiers, visitor, isToken),
|
||||
visitNode((<PropertySignature>node).name, visitor, isPropertyName),
|
||||
visitNode((<PropertySignature>node).questionToken, tokenVisitor, isToken),
|
||||
visitNode((<PropertySignature>node).type, visitor, isTypeNode),
|
||||
visitNode((<PropertySignature>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return updateProperty(<PropertyDeclaration>node,
|
||||
nodesVisitor((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<PropertyDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<PropertyDeclaration>node).name, visitor, isPropertyName),
|
||||
// QuestionToken and ExclamationToken is uniqued in Property Declaration and the signature of 'updateProperty' is that too
|
||||
visitNode((<PropertyDeclaration>node).questionToken || (<PropertyDeclaration>node).exclamationToken, tokenVisitor, isToken),
|
||||
visitNode((<PropertyDeclaration>node).type, visitor, isTypeNode),
|
||||
visitNode((<PropertyDeclaration>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.MethodSignature:
|
||||
return updateMethodSignature(<MethodSignature>node,
|
||||
nodesVisitor((<MethodSignature>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<MethodSignature>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<MethodSignature>node).type, visitor, isTypeNode),
|
||||
visitNode((<MethodSignature>node).name, visitor, isPropertyName),
|
||||
visitNode((<MethodSignature>node).questionToken, tokenVisitor, isToken));
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return updateMethod(<MethodDeclaration>node,
|
||||
nodesVisitor((<MethodDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<MethodDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<MethodDeclaration>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
|
||||
visitNode((<MethodDeclaration>node).questionToken, tokenVisitor, isToken),
|
||||
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<MethodDeclaration>node).body!, visitor, context));
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
return updateConstructor(<ConstructorDeclaration>node,
|
||||
nodesVisitor((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitFunctionBody((<ConstructorDeclaration>node).body!, visitor, context));
|
||||
|
||||
case SyntaxKind.GetAccessor:
|
||||
return updateGetAccessor(<GetAccessorDeclaration>node,
|
||||
nodesVisitor((<GetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<GetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<GetAccessorDeclaration>node).name, visitor, isPropertyName),
|
||||
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<GetAccessorDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<GetAccessorDeclaration>node).body!, visitor, context));
|
||||
|
||||
case SyntaxKind.SetAccessor:
|
||||
return updateSetAccessor(<SetAccessorDeclaration>node,
|
||||
nodesVisitor((<SetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<SetAccessorDeclaration>node).name, visitor, isPropertyName),
|
||||
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitFunctionBody((<SetAccessorDeclaration>node).body!, visitor, context));
|
||||
|
||||
case SyntaxKind.CallSignature:
|
||||
return updateCallSignature(<CallSignatureDeclaration>node,
|
||||
nodesVisitor((<CallSignatureDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<CallSignatureDeclaration>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<CallSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ConstructSignature:
|
||||
return updateConstructSignature(<ConstructSignatureDeclaration>node,
|
||||
nodesVisitor((<ConstructSignatureDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ConstructSignatureDeclaration>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<ConstructSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.IndexSignature:
|
||||
return updateIndexSignature(<IndexSignatureDeclaration>node,
|
||||
nodesVisitor((<IndexSignatureDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<IndexSignatureDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<IndexSignatureDeclaration>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<IndexSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
// Types
|
||||
case SyntaxKind.TypePredicate:
|
||||
return updateTypePredicateNodeWithModifier(<TypePredicateNode>node,
|
||||
visitNode((<TypePredicateNode>node).assertsModifier, visitor),
|
||||
visitNode((<TypePredicateNode>node).parameterName, visitor),
|
||||
visitNode((<TypePredicateNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TypeReference:
|
||||
return updateTypeReferenceNode(<TypeReferenceNode>node,
|
||||
visitNode((<TypeReferenceNode>node).typeName, visitor, isEntityName),
|
||||
nodesVisitor((<TypeReferenceNode>node).typeArguments, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.FunctionType:
|
||||
return updateFunctionTypeNode(<FunctionTypeNode>node,
|
||||
nodesVisitor((<FunctionTypeNode>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<FunctionTypeNode>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<FunctionTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ConstructorType:
|
||||
return updateConstructorTypeNode(<ConstructorTypeNode>node,
|
||||
nodesVisitor((<ConstructorTypeNode>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ConstructorTypeNode>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<ConstructorTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TypeQuery:
|
||||
return updateTypeQueryNode((<TypeQueryNode>node),
|
||||
visitNode((<TypeQueryNode>node).exprName, visitor, isEntityName));
|
||||
|
||||
case SyntaxKind.TypeLiteral:
|
||||
return updateTypeLiteralNode((<TypeLiteralNode>node),
|
||||
nodesVisitor((<TypeLiteralNode>node).members, visitor, isTypeElement));
|
||||
|
||||
case SyntaxKind.ArrayType:
|
||||
return updateArrayTypeNode(<ArrayTypeNode>node,
|
||||
visitNode((<ArrayTypeNode>node).elementType, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TupleType:
|
||||
return updateTupleTypeNode((<TupleTypeNode>node),
|
||||
nodesVisitor((<TupleTypeNode>node).elementTypes, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.OptionalType:
|
||||
return updateOptionalTypeNode((<OptionalTypeNode>node),
|
||||
visitNode((<OptionalTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.RestType:
|
||||
return updateRestTypeNode((<RestTypeNode>node),
|
||||
visitNode((<RestTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.UnionType:
|
||||
return updateUnionTypeNode(<UnionTypeNode>node,
|
||||
nodesVisitor((<UnionTypeNode>node).types, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.IntersectionType:
|
||||
return updateIntersectionTypeNode(<IntersectionTypeNode>node,
|
||||
nodesVisitor((<IntersectionTypeNode>node).types, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ConditionalType:
|
||||
return updateConditionalTypeNode(<ConditionalTypeNode>node,
|
||||
visitNode((<ConditionalTypeNode>node).checkType, visitor, isTypeNode),
|
||||
visitNode((<ConditionalTypeNode>node).extendsType, visitor, isTypeNode),
|
||||
visitNode((<ConditionalTypeNode>node).trueType, visitor, isTypeNode),
|
||||
visitNode((<ConditionalTypeNode>node).falseType, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.InferType:
|
||||
return updateInferTypeNode(<InferTypeNode>node,
|
||||
visitNode((<InferTypeNode>node).typeParameter, visitor, isTypeParameterDeclaration));
|
||||
|
||||
case SyntaxKind.ImportType:
|
||||
return updateImportTypeNode(<ImportTypeNode>node,
|
||||
visitNode((<ImportTypeNode>node).argument, visitor, isTypeNode),
|
||||
visitNode((<ImportTypeNode>node).qualifier, visitor, isEntityName),
|
||||
visitNodes((<ImportTypeNode>node).typeArguments, visitor, isTypeNode),
|
||||
(<ImportTypeNode>node).isTypeOf
|
||||
);
|
||||
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return updateParenthesizedType(<ParenthesizedTypeNode>node,
|
||||
visitNode((<ParenthesizedTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TypeOperator:
|
||||
return updateTypeOperatorNode(<TypeOperatorNode>node,
|
||||
visitNode((<TypeOperatorNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.IndexedAccessType:
|
||||
return updateIndexedAccessTypeNode((<IndexedAccessTypeNode>node),
|
||||
visitNode((<IndexedAccessTypeNode>node).objectType, visitor, isTypeNode),
|
||||
visitNode((<IndexedAccessTypeNode>node).indexType, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.MappedType:
|
||||
return updateMappedTypeNode((<MappedTypeNode>node),
|
||||
visitNode((<MappedTypeNode>node).readonlyToken, tokenVisitor, isToken),
|
||||
visitNode((<MappedTypeNode>node).typeParameter, visitor, isTypeParameterDeclaration),
|
||||
visitNode((<MappedTypeNode>node).questionToken, tokenVisitor, isToken),
|
||||
visitNode((<MappedTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.LiteralType:
|
||||
return updateLiteralTypeNode(<LiteralTypeNode>node,
|
||||
visitNode((<LiteralTypeNode>node).literal, visitor, isExpression));
|
||||
|
||||
// Binding patterns
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return updateObjectBindingPattern(<ObjectBindingPattern>node,
|
||||
nodesVisitor((<ObjectBindingPattern>node).elements, visitor, isBindingElement));
|
||||
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return updateArrayBindingPattern(<ArrayBindingPattern>node,
|
||||
nodesVisitor((<ArrayBindingPattern>node).elements, visitor, isArrayBindingElement));
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
return updateBindingElement(<BindingElement>node,
|
||||
visitNode((<BindingElement>node).dotDotDotToken, tokenVisitor, isToken),
|
||||
visitNode((<BindingElement>node).propertyName, visitor, isPropertyName),
|
||||
visitNode((<BindingElement>node).name, visitor, isBindingName),
|
||||
visitNode((<BindingElement>node).initializer, visitor, isExpression));
|
||||
|
||||
// Expression
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return updateArrayLiteral(<ArrayLiteralExpression>node,
|
||||
nodesVisitor((<ArrayLiteralExpression>node).elements, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return updateObjectLiteral(<ObjectLiteralExpression>node,
|
||||
nodesVisitor((<ObjectLiteralExpression>node).properties, visitor, isObjectLiteralElementLike));
|
||||
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
if (node.flags & NodeFlags.OptionalChain) {
|
||||
return updatePropertyAccessChain(<PropertyAccessChain>node,
|
||||
visitNode((<PropertyAccessChain>node).expression, visitor, isExpression),
|
||||
visitNode((<PropertyAccessChain>node).questionDotToken, visitor, isToken),
|
||||
visitNode((<PropertyAccessChain>node).name, visitor, isIdentifier));
|
||||
}
|
||||
return updatePropertyAccess(<PropertyAccessExpression>node,
|
||||
visitNode((<PropertyAccessExpression>node).expression, visitor, isExpression),
|
||||
visitNode((<PropertyAccessExpression>node).name, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
if (node.flags & NodeFlags.OptionalChain) {
|
||||
return updateElementAccessChain(<ElementAccessChain>node,
|
||||
visitNode((<ElementAccessChain>node).expression, visitor, isExpression),
|
||||
visitNode((<ElementAccessChain>node).questionDotToken, visitor, isToken),
|
||||
visitNode((<ElementAccessChain>node).argumentExpression, visitor, isExpression));
|
||||
}
|
||||
return updateElementAccess(<ElementAccessExpression>node,
|
||||
visitNode((<ElementAccessExpression>node).expression, visitor, isExpression),
|
||||
visitNode((<ElementAccessExpression>node).argumentExpression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.CallExpression:
|
||||
if (node.flags & NodeFlags.OptionalChain) {
|
||||
return updateCallChain(<CallChain>node,
|
||||
visitNode((<CallChain>node).expression, visitor, isExpression),
|
||||
visitNode((<CallChain>node).questionDotToken, visitor, isToken),
|
||||
nodesVisitor((<CallChain>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<CallChain>node).arguments, visitor, isExpression));
|
||||
}
|
||||
return updateCall(<CallExpression>node,
|
||||
visitNode((<CallExpression>node).expression, visitor, isExpression),
|
||||
nodesVisitor((<CallExpression>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<CallExpression>node).arguments, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.NewExpression:
|
||||
return updateNew(<NewExpression>node,
|
||||
visitNode((<NewExpression>node).expression, visitor, isExpression),
|
||||
nodesVisitor((<NewExpression>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<NewExpression>node).arguments, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
return updateTaggedTemplate(<TaggedTemplateExpression>node,
|
||||
visitNode((<TaggedTemplateExpression>node).tag, visitor, isExpression),
|
||||
visitNodes((<TaggedTemplateExpression>node).typeArguments, visitor, isExpression),
|
||||
visitNode((<TaggedTemplateExpression>node).template, visitor, isTemplateLiteral));
|
||||
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
return updateTypeAssertion(<TypeAssertion>node,
|
||||
visitNode((<TypeAssertion>node).type, visitor, isTypeNode),
|
||||
visitNode((<TypeAssertion>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
return updateParen(<ParenthesizedExpression>node,
|
||||
visitNode((<ParenthesizedExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return updateFunctionExpression(<FunctionExpression>node,
|
||||
nodesVisitor((<FunctionExpression>node).modifiers, visitor, isModifier),
|
||||
visitNode((<FunctionExpression>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<FunctionExpression>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<FunctionExpression>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<FunctionExpression>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionExpression>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return updateArrowFunction(<ArrowFunction>node,
|
||||
nodesVisitor((<ArrowFunction>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ArrowFunction>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<ArrowFunction>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<ArrowFunction>node).type, visitor, isTypeNode),
|
||||
visitNode((<ArrowFunction>node).equalsGreaterThanToken, visitor, isToken),
|
||||
visitFunctionBody((<ArrowFunction>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.DeleteExpression:
|
||||
return updateDelete(<DeleteExpression>node,
|
||||
visitNode((<DeleteExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
return updateTypeOf(<TypeOfExpression>node,
|
||||
visitNode((<TypeOfExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.VoidExpression:
|
||||
return updateVoid(<VoidExpression>node,
|
||||
visitNode((<VoidExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.AwaitExpression:
|
||||
return updateAwait(<AwaitExpression>node,
|
||||
visitNode((<AwaitExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
return updatePrefix(<PrefixUnaryExpression>node,
|
||||
visitNode((<PrefixUnaryExpression>node).operand, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
return updatePostfix(<PostfixUnaryExpression>node,
|
||||
visitNode((<PostfixUnaryExpression>node).operand, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return updateBinary(<BinaryExpression>node,
|
||||
visitNode((<BinaryExpression>node).left, visitor, isExpression),
|
||||
visitNode((<BinaryExpression>node).right, visitor, isExpression),
|
||||
visitNode((<BinaryExpression>node).operatorToken, visitor, isToken));
|
||||
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
return updateConditional(<ConditionalExpression>node,
|
||||
visitNode((<ConditionalExpression>node).condition, visitor, isExpression),
|
||||
visitNode((<ConditionalExpression>node).questionToken, visitor, isToken),
|
||||
visitNode((<ConditionalExpression>node).whenTrue, visitor, isExpression),
|
||||
visitNode((<ConditionalExpression>node).colonToken, visitor, isToken),
|
||||
visitNode((<ConditionalExpression>node).whenFalse, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TemplateExpression:
|
||||
return updateTemplateExpression(<TemplateExpression>node,
|
||||
visitNode((<TemplateExpression>node).head, visitor, isTemplateHead),
|
||||
nodesVisitor((<TemplateExpression>node).templateSpans, visitor, isTemplateSpan));
|
||||
|
||||
case SyntaxKind.YieldExpression:
|
||||
return updateYield(<YieldExpression>node,
|
||||
visitNode((<YieldExpression>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<YieldExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.SpreadElement:
|
||||
return updateSpread(<SpreadElement>node,
|
||||
visitNode((<SpreadElement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ClassExpression:
|
||||
return updateClassExpression(<ClassExpression>node,
|
||||
nodesVisitor((<ClassExpression>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassExpression>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<ClassExpression>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ClassExpression>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassExpression>node).members, visitor, isClassElement));
|
||||
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return updateExpressionWithTypeArguments(<ExpressionWithTypeArguments>node,
|
||||
nodesVisitor((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
|
||||
visitNode((<ExpressionWithTypeArguments>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.AsExpression:
|
||||
return updateAsExpression(<AsExpression>node,
|
||||
visitNode((<AsExpression>node).expression, visitor, isExpression),
|
||||
visitNode((<AsExpression>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.NonNullExpression:
|
||||
return updateNonNullExpression(<NonNullExpression>node,
|
||||
visitNode((<NonNullExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.MetaProperty:
|
||||
return updateMetaProperty(<MetaProperty>node,
|
||||
visitNode((<MetaProperty>node).name, visitor, isIdentifier));
|
||||
|
||||
// Misc
|
||||
case SyntaxKind.TemplateSpan:
|
||||
return updateTemplateSpan(<TemplateSpan>node,
|
||||
visitNode((<TemplateSpan>node).expression, visitor, isExpression),
|
||||
visitNode((<TemplateSpan>node).literal, visitor, isTemplateMiddleOrTemplateTail));
|
||||
|
||||
// Element
|
||||
case SyntaxKind.Block:
|
||||
return updateBlock(<Block>node,
|
||||
nodesVisitor((<Block>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
return updateVariableStatement(<VariableStatement>node,
|
||||
nodesVisitor((<VariableStatement>node).modifiers, visitor, isModifier),
|
||||
visitNode((<VariableStatement>node).declarationList, visitor, isVariableDeclarationList));
|
||||
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
return updateExpressionStatement(<ExpressionStatement>node,
|
||||
visitNode((<ExpressionStatement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.IfStatement:
|
||||
return updateIf(<IfStatement>node,
|
||||
visitNode((<IfStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<IfStatement>node).thenStatement, visitor, isStatement, liftToBlock),
|
||||
visitNode((<IfStatement>node).elseStatement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.DoStatement:
|
||||
return updateDo(<DoStatement>node,
|
||||
visitNode((<DoStatement>node).statement, visitor, isStatement, liftToBlock),
|
||||
visitNode((<DoStatement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.WhileStatement:
|
||||
return updateWhile(<WhileStatement>node,
|
||||
visitNode((<WhileStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<WhileStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ForStatement:
|
||||
return updateFor(<ForStatement>node,
|
||||
visitNode((<ForStatement>node).initializer, visitor, isForInitializer),
|
||||
visitNode((<ForStatement>node).condition, visitor, isExpression),
|
||||
visitNode((<ForStatement>node).incrementor, visitor, isExpression),
|
||||
visitNode((<ForStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ForInStatement:
|
||||
return updateForIn(<ForInStatement>node,
|
||||
visitNode((<ForInStatement>node).initializer, visitor, isForInitializer),
|
||||
visitNode((<ForInStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<ForInStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
return updateForOf(<ForOfStatement>node,
|
||||
visitNode((<ForOfStatement>node).awaitModifier, visitor, isToken),
|
||||
visitNode((<ForOfStatement>node).initializer, visitor, isForInitializer),
|
||||
visitNode((<ForOfStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<ForOfStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ContinueStatement:
|
||||
return updateContinue(<ContinueStatement>node,
|
||||
visitNode((<ContinueStatement>node).label, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.BreakStatement:
|
||||
return updateBreak(<BreakStatement>node,
|
||||
visitNode((<BreakStatement>node).label, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ReturnStatement:
|
||||
return updateReturn(<ReturnStatement>node,
|
||||
visitNode((<ReturnStatement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.WithStatement:
|
||||
return updateWith(<WithStatement>node,
|
||||
visitNode((<WithStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<WithStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.SwitchStatement:
|
||||
return updateSwitch(<SwitchStatement>node,
|
||||
visitNode((<SwitchStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<SwitchStatement>node).caseBlock, visitor, isCaseBlock));
|
||||
|
||||
case SyntaxKind.LabeledStatement:
|
||||
return updateLabel(<LabeledStatement>node,
|
||||
visitNode((<LabeledStatement>node).label, visitor, isIdentifier),
|
||||
visitNode((<LabeledStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ThrowStatement:
|
||||
return updateThrow(<ThrowStatement>node,
|
||||
visitNode((<ThrowStatement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TryStatement:
|
||||
return updateTry(<TryStatement>node,
|
||||
visitNode((<TryStatement>node).tryBlock, visitor, isBlock),
|
||||
visitNode((<TryStatement>node).catchClause, visitor, isCatchClause),
|
||||
visitNode((<TryStatement>node).finallyBlock, visitor, isBlock));
|
||||
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return updateTypeScriptVariableDeclaration(<VariableDeclaration>node,
|
||||
visitNode((<VariableDeclaration>node).name, visitor, isBindingName),
|
||||
visitNode((<VariableDeclaration>node).exclamationToken, tokenVisitor, isToken),
|
||||
visitNode((<VariableDeclaration>node).type, visitor, isTypeNode),
|
||||
visitNode((<VariableDeclaration>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
return updateVariableDeclarationList(<VariableDeclarationList>node,
|
||||
nodesVisitor((<VariableDeclarationList>node).declarations, visitor, isVariableDeclaration));
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return updateFunctionDeclaration(<FunctionDeclaration>node,
|
||||
nodesVisitor((<FunctionDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<FunctionDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<FunctionDeclaration>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<FunctionDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return updateClassDeclaration(<ClassDeclaration>node,
|
||||
nodesVisitor((<ClassDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ClassDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<ClassDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassDeclaration>node).members, visitor, isClassElement));
|
||||
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return updateInterfaceDeclaration(<InterfaceDeclaration>node,
|
||||
nodesVisitor((<InterfaceDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<InterfaceDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<InterfaceDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<InterfaceDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<InterfaceDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<InterfaceDeclaration>node).members, visitor, isTypeElement));
|
||||
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
return updateTypeAliasDeclaration(<TypeAliasDeclaration>node,
|
||||
nodesVisitor((<TypeAliasDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<TypeAliasDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<TypeAliasDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<TypeAliasDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitNode((<TypeAliasDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return updateEnumDeclaration(<EnumDeclaration>node,
|
||||
nodesVisitor((<EnumDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<EnumDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<EnumDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<EnumDeclaration>node).members, visitor, isEnumMember));
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return updateModuleDeclaration(<ModuleDeclaration>node,
|
||||
nodesVisitor((<ModuleDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ModuleDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ModuleDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<ModuleDeclaration>node).body, visitor, isModuleBody));
|
||||
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return updateModuleBlock(<ModuleBlock>node,
|
||||
nodesVisitor((<ModuleBlock>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.CaseBlock:
|
||||
return updateCaseBlock(<CaseBlock>node,
|
||||
nodesVisitor((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
|
||||
|
||||
case SyntaxKind.NamespaceExportDeclaration:
|
||||
return updateNamespaceExportDeclaration(<NamespaceExportDeclaration>node,
|
||||
visitNode((<NamespaceExportDeclaration>node).name, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
return updateImportEqualsDeclaration(<ImportEqualsDeclaration>node,
|
||||
nodesVisitor((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ImportEqualsDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<ImportEqualsDeclaration>node).moduleReference, visitor, isModuleReference));
|
||||
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
return updateImportDeclaration(<ImportDeclaration>node,
|
||||
nodesVisitor((<ImportDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ImportDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ImportDeclaration>node).importClause, visitor, isImportClause),
|
||||
visitNode((<ImportDeclaration>node).moduleSpecifier, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ImportClause:
|
||||
return updateImportClause(<ImportClause>node,
|
||||
visitNode((<ImportClause>node).name, visitor, isIdentifier),
|
||||
visitNode((<ImportClause>node).namedBindings, visitor, isNamedImportBindings));
|
||||
|
||||
case SyntaxKind.NamespaceImport:
|
||||
return updateNamespaceImport(<NamespaceImport>node,
|
||||
visitNode((<NamespaceImport>node).name, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.NamedImports:
|
||||
return updateNamedImports(<NamedImports>node,
|
||||
nodesVisitor((<NamedImports>node).elements, visitor, isImportSpecifier));
|
||||
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
return updateImportSpecifier(<ImportSpecifier>node,
|
||||
visitNode((<ImportSpecifier>node).propertyName, visitor, isIdentifier),
|
||||
visitNode((<ImportSpecifier>node).name, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return updateExportAssignment(<ExportAssignment>node,
|
||||
nodesVisitor((<ExportAssignment>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ExportAssignment>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ExportAssignment>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return updateExportDeclaration(<ExportDeclaration>node,
|
||||
nodesVisitor((<ExportDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ExportDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ExportDeclaration>node).exportClause, visitor, isNamedExports),
|
||||
visitNode((<ExportDeclaration>node).moduleSpecifier, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.NamedExports:
|
||||
return updateNamedExports(<NamedExports>node,
|
||||
nodesVisitor((<NamedExports>node).elements, visitor, isExportSpecifier));
|
||||
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
return updateExportSpecifier(<ExportSpecifier>node,
|
||||
visitNode((<ExportSpecifier>node).propertyName, visitor, isIdentifier),
|
||||
visitNode((<ExportSpecifier>node).name, visitor, isIdentifier));
|
||||
|
||||
// Module references
|
||||
case SyntaxKind.ExternalModuleReference:
|
||||
return updateExternalModuleReference(<ExternalModuleReference>node,
|
||||
visitNode((<ExternalModuleReference>node).expression, visitor, isExpression));
|
||||
|
||||
// JSX
|
||||
case SyntaxKind.JsxElement:
|
||||
return updateJsxElement(<JsxElement>node,
|
||||
visitNode((<JsxElement>node).openingElement, visitor, isJsxOpeningElement),
|
||||
nodesVisitor((<JsxElement>node).children, visitor, isJsxChild),
|
||||
visitNode((<JsxElement>node).closingElement, visitor, isJsxClosingElement));
|
||||
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
return updateJsxSelfClosingElement(<JsxSelfClosingElement>node,
|
||||
visitNode((<JsxSelfClosingElement>node).tagName, visitor, isJsxTagNameExpression),
|
||||
nodesVisitor((<JsxSelfClosingElement>node).typeArguments, visitor, isTypeNode),
|
||||
visitNode((<JsxSelfClosingElement>node).attributes, visitor, isJsxAttributes));
|
||||
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
return updateJsxOpeningElement(<JsxOpeningElement>node,
|
||||
visitNode((<JsxOpeningElement>node).tagName, visitor, isJsxTagNameExpression),
|
||||
nodesVisitor((<JsxSelfClosingElement>node).typeArguments, visitor, isTypeNode),
|
||||
visitNode((<JsxOpeningElement>node).attributes, visitor, isJsxAttributes));
|
||||
|
||||
case SyntaxKind.JsxClosingElement:
|
||||
return updateJsxClosingElement(<JsxClosingElement>node,
|
||||
visitNode((<JsxClosingElement>node).tagName, visitor, isJsxTagNameExpression));
|
||||
|
||||
case SyntaxKind.JsxFragment:
|
||||
return updateJsxFragment(<JsxFragment>node,
|
||||
visitNode((<JsxFragment>node).openingFragment, visitor, isJsxOpeningFragment),
|
||||
nodesVisitor((<JsxFragment>node).children, visitor, isJsxChild),
|
||||
visitNode((<JsxFragment>node).closingFragment, visitor, isJsxClosingFragment));
|
||||
|
||||
case SyntaxKind.JsxAttribute:
|
||||
return updateJsxAttribute(<JsxAttribute>node,
|
||||
visitNode((<JsxAttribute>node).name, visitor, isIdentifier),
|
||||
visitNode((<JsxAttribute>node).initializer, visitor, isStringLiteralOrJsxExpression));
|
||||
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return updateJsxAttributes(<JsxAttributes>node,
|
||||
nodesVisitor((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
|
||||
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
return updateJsxSpreadAttribute(<JsxSpreadAttribute>node,
|
||||
visitNode((<JsxSpreadAttribute>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.JsxExpression:
|
||||
return updateJsxExpression(<JsxExpression>node,
|
||||
visitNode((<JsxExpression>node).expression, visitor, isExpression));
|
||||
|
||||
// Clauses
|
||||
case SyntaxKind.CaseClause:
|
||||
return updateCaseClause(<CaseClause>node,
|
||||
visitNode((<CaseClause>node).expression, visitor, isExpression),
|
||||
nodesVisitor((<CaseClause>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.DefaultClause:
|
||||
return updateDefaultClause(<DefaultClause>node,
|
||||
nodesVisitor((<DefaultClause>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.HeritageClause:
|
||||
return updateHeritageClause(<HeritageClause>node,
|
||||
nodesVisitor((<HeritageClause>node).types, visitor, isExpressionWithTypeArguments));
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
return updateCatchClause(<CatchClause>node,
|
||||
visitNode((<CatchClause>node).variableDeclaration, visitor, isVariableDeclaration),
|
||||
visitNode((<CatchClause>node).block, visitor, isBlock));
|
||||
|
||||
// Property assignments
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
return updatePropertyAssignment(<PropertyAssignment>node,
|
||||
visitNode((<PropertyAssignment>node).name, visitor, isPropertyName),
|
||||
visitNode((<PropertyAssignment>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
return updateShorthandPropertyAssignment(<ShorthandPropertyAssignment>node,
|
||||
visitNode((<ShorthandPropertyAssignment>node).name, visitor, isIdentifier),
|
||||
visitNode((<ShorthandPropertyAssignment>node).objectAssignmentInitializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
return updateSpreadAssignment(<SpreadAssignment>node,
|
||||
visitNode((<SpreadAssignment>node).expression, visitor, isExpression));
|
||||
|
||||
// Enum
|
||||
case SyntaxKind.EnumMember:
|
||||
return updateEnumMember(<EnumMember>node,
|
||||
visitNode((<EnumMember>node).name, visitor, isPropertyName),
|
||||
visitNode((<EnumMember>node).initializer, visitor, isExpression));
|
||||
|
||||
// Top-level nodes
|
||||
case SyntaxKind.SourceFile:
|
||||
return updateSourceFileNode(<SourceFile>node,
|
||||
visitLexicalEnvironment((<SourceFile>node).statements, visitor, context));
|
||||
|
||||
// Transformation nodes
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
return updatePartiallyEmittedExpression(<PartiallyEmittedExpression>node,
|
||||
visitNode((<PartiallyEmittedExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.CommaListExpression:
|
||||
return updateCommaList(<CommaListExpression>node,
|
||||
nodesVisitor((<CommaListExpression>node).elements, visitor, isExpression));
|
||||
|
||||
default:
|
||||
// No need to visit nodes with no children.
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the single node from a NodeArray.
|
||||
*
|
||||
* @param nodes The NodeArray.
|
||||
*/
|
||||
function extractSingleNode(nodes: readonly Node[]): Node | undefined {
|
||||
Debug.assert(nodes.length <= 1, "Too many nodes written to output.");
|
||||
return singleOrUndefined(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
function reduceNode<T>(node: Node | undefined, f: (memo: T, node: Node) => T, initial: T) {
|
||||
|
@ -1564,4 +610,4 @@ namespace ts {
|
|||
function aggregateTransformFlagsForChildNodes(transformFlags: TransformFlags, nodes: NodeArray<Node>): TransformFlags {
|
||||
return transformFlags | aggregateTransformFlagsForNodeArray(nodes);
|
||||
}
|
||||
}
|
||||
}
|
953
src/compiler/visitorPublic.ts
Normal file
953
src/compiler/visitorPublic.ts
Normal file
|
@ -0,0 +1,953 @@
|
|||
namespace ts {
|
||||
const isTypeNodeOrTypeParameterDeclaration = or(isTypeNode, isTypeParameterDeclaration);
|
||||
|
||||
/**
|
||||
* Visits a Node using the supplied visitor, possibly returning a new Node in its place.
|
||||
*
|
||||
* @param node The Node to visit.
|
||||
* @param visitor The callback used to visit the Node.
|
||||
* @param test A callback to execute to verify the Node is valid.
|
||||
* @param lift An optional callback to execute to lift a NodeArray into a valid Node.
|
||||
*/
|
||||
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T;
|
||||
|
||||
/**
|
||||
* Visits a Node using the supplied visitor, possibly returning a new Node in its place.
|
||||
*
|
||||
* @param node The Node to visit.
|
||||
* @param visitor The callback used to visit the Node.
|
||||
* @param test A callback to execute to verify the Node is valid.
|
||||
* @param lift An optional callback to execute to lift a NodeArray into a valid Node.
|
||||
*/
|
||||
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T | undefined;
|
||||
|
||||
export function visitNode<T extends Node>(node: T | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, lift?: (node: NodeArray<Node>) => T): T | undefined {
|
||||
if (node === undefined || visitor === undefined) {
|
||||
return node;
|
||||
}
|
||||
|
||||
aggregateTransformFlags(node);
|
||||
const visited = visitor(node);
|
||||
if (visited === node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
let visitedNode: Node | undefined;
|
||||
if (visited === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
else if (isArray(visited)) {
|
||||
visitedNode = (lift || extractSingleNode)(visited);
|
||||
}
|
||||
else {
|
||||
visitedNode = visited;
|
||||
}
|
||||
|
||||
Debug.assertNode(visitedNode, test);
|
||||
aggregateTransformFlags(visitedNode!);
|
||||
return <T>visitedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place.
|
||||
*
|
||||
* @param nodes The NodeArray to visit.
|
||||
* @param visitor The callback used to visit a Node.
|
||||
* @param test A node test to execute for each node.
|
||||
* @param start An optional value indicating the starting offset at which to start visiting.
|
||||
* @param count An optional value indicating the maximum number of nodes to visit.
|
||||
*/
|
||||
export function visitNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
|
||||
|
||||
/**
|
||||
* Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place.
|
||||
*
|
||||
* @param nodes The NodeArray to visit.
|
||||
* @param visitor The callback used to visit a Node.
|
||||
* @param test A node test to execute for each node.
|
||||
* @param start An optional value indicating the starting offset at which to start visiting.
|
||||
* @param count An optional value indicating the maximum number of nodes to visit.
|
||||
*/
|
||||
export function visitNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> | undefined;
|
||||
|
||||
/**
|
||||
* Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place.
|
||||
*
|
||||
* @param nodes The NodeArray to visit.
|
||||
* @param visitor The callback used to visit a Node.
|
||||
* @param test A node test to execute for each node.
|
||||
* @param start An optional value indicating the starting offset at which to start visiting.
|
||||
* @param count An optional value indicating the maximum number of nodes to visit.
|
||||
*/
|
||||
export function visitNodes<T extends Node>(nodes: NodeArray<T> | undefined, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> | undefined {
|
||||
if (nodes === undefined || visitor === undefined) {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
let updated: MutableNodeArray<T> | undefined;
|
||||
|
||||
// Ensure start and count have valid values
|
||||
const length = nodes.length;
|
||||
if (start === undefined || start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (count === undefined || count > length - start) {
|
||||
count = length - start;
|
||||
}
|
||||
|
||||
if (start > 0 || count < length) {
|
||||
// If we are not visiting all of the original nodes, we must always create a new array.
|
||||
// Since this is a fragment of a node array, we do not copy over the previous location
|
||||
// and will only copy over `hasTrailingComma` if we are including the last element.
|
||||
updated = createNodeArray<T>([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length);
|
||||
}
|
||||
|
||||
// Visit each original node.
|
||||
for (let i = 0; i < count; i++) {
|
||||
const node = nodes[i + start];
|
||||
aggregateTransformFlags(node);
|
||||
const visited = node !== undefined ? visitor(node) : undefined;
|
||||
if (updated !== undefined || visited === undefined || visited !== node) {
|
||||
if (updated === undefined) {
|
||||
// Ensure we have a copy of `nodes`, up to the current index.
|
||||
updated = createNodeArray(nodes.slice(0, i), nodes.hasTrailingComma);
|
||||
setTextRange(updated, nodes);
|
||||
}
|
||||
if (visited) {
|
||||
if (isArray(visited)) {
|
||||
for (const visitedNode of visited) {
|
||||
Debug.assertNode(visitedNode, test);
|
||||
aggregateTransformFlags(visitedNode);
|
||||
updated.push(<T>visitedNode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.assertNode(visited, test);
|
||||
aggregateTransformFlags(visited);
|
||||
updated.push(<T>visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updated || nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new lexical environment and visits a statement list, ending the lexical environment
|
||||
* and merging hoisted declarations upon completion.
|
||||
*/
|
||||
export function visitLexicalEnvironment(statements: NodeArray<Statement>, visitor: Visitor, context: TransformationContext, start?: number, ensureUseStrict?: boolean) {
|
||||
context.startLexicalEnvironment();
|
||||
statements = visitNodes(statements, visitor, isStatement, start);
|
||||
if (ensureUseStrict) statements = ts.ensureUseStrict(statements); // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier
|
||||
return mergeLexicalEnvironment(statements, context.endLexicalEnvironment());
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new lexical environment and visits a parameter list, suspending the lexical
|
||||
* environment upon completion.
|
||||
*/
|
||||
export function visitParameterList(nodes: NodeArray<ParameterDeclaration> | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes) {
|
||||
context.startLexicalEnvironment();
|
||||
const updated = nodesVisitor(nodes, visitor, isParameterDeclaration);
|
||||
context.suspendLexicalEnvironment();
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resumes a suspended lexical environment and visits a function body, ending the lexical
|
||||
* environment and merging hoisted declarations upon completion.
|
||||
*/
|
||||
export function visitFunctionBody(node: FunctionBody, visitor: Visitor, context: TransformationContext): FunctionBody;
|
||||
/**
|
||||
* Resumes a suspended lexical environment and visits a function body, ending the lexical
|
||||
* environment and merging hoisted declarations upon completion.
|
||||
*/
|
||||
export function visitFunctionBody(node: FunctionBody | undefined, visitor: Visitor, context: TransformationContext): FunctionBody | undefined;
|
||||
/**
|
||||
* Resumes a suspended lexical environment and visits a concise body, ending the lexical
|
||||
* environment and merging hoisted declarations upon completion.
|
||||
*/
|
||||
export function visitFunctionBody(node: ConciseBody, visitor: Visitor, context: TransformationContext): ConciseBody;
|
||||
export function visitFunctionBody(node: ConciseBody | undefined, visitor: Visitor, context: TransformationContext): ConciseBody | undefined {
|
||||
context.resumeLexicalEnvironment();
|
||||
const updated = visitNode(node, visitor, isConciseBody);
|
||||
const declarations = context.endLexicalEnvironment();
|
||||
if (some(declarations)) {
|
||||
const block = convertToFunctionBody(updated);
|
||||
const statements = mergeLexicalEnvironment(block.statements, declarations);
|
||||
return updateBlock(block, statements);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
|
||||
*
|
||||
* @param node The Node whose children will be visited.
|
||||
* @param visitor The callback used to visit each child.
|
||||
* @param context A lexical environment context for the visitor.
|
||||
*/
|
||||
export function visitEachChild<T extends Node>(node: T, visitor: Visitor, context: TransformationContext): T;
|
||||
|
||||
/**
|
||||
* Visits each child of a Node using the supplied visitor, possibly returning a new Node of the same kind in its place.
|
||||
*
|
||||
* @param node The Node whose children will be visited.
|
||||
* @param visitor The callback used to visit each child.
|
||||
* @param context A lexical environment context for the visitor.
|
||||
*/
|
||||
export function visitEachChild<T extends Node>(node: T | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor?: typeof visitNodes, tokenVisitor?: Visitor): T | undefined;
|
||||
|
||||
export function visitEachChild(node: Node | undefined, visitor: Visitor, context: TransformationContext, nodesVisitor = visitNodes, tokenVisitor?: Visitor): Node | undefined {
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const kind = node.kind;
|
||||
|
||||
// No need to visit nodes with no children.
|
||||
if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken) || kind === SyntaxKind.ThisType) {
|
||||
return node;
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
// Names
|
||||
|
||||
case SyntaxKind.Identifier:
|
||||
return updateIdentifier(<Identifier>node, nodesVisitor((<Identifier>node).typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration));
|
||||
|
||||
case SyntaxKind.QualifiedName:
|
||||
return updateQualifiedName(<QualifiedName>node,
|
||||
visitNode((<QualifiedName>node).left, visitor, isEntityName),
|
||||
visitNode((<QualifiedName>node).right, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
return updateComputedPropertyName(<ComputedPropertyName>node,
|
||||
visitNode((<ComputedPropertyName>node).expression, visitor, isExpression));
|
||||
|
||||
// Signature elements
|
||||
case SyntaxKind.TypeParameter:
|
||||
return updateTypeParameterDeclaration(<TypeParameterDeclaration>node,
|
||||
visitNode((<TypeParameterDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<TypeParameterDeclaration>node).constraint, visitor, isTypeNode),
|
||||
visitNode((<TypeParameterDeclaration>node).default, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.Parameter:
|
||||
return updateParameter(<ParameterDeclaration>node,
|
||||
nodesVisitor((<ParameterDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ParameterDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ParameterDeclaration>node).dotDotDotToken, tokenVisitor, isToken),
|
||||
visitNode((<ParameterDeclaration>node).name, visitor, isBindingName),
|
||||
visitNode((<ParameterDeclaration>node).questionToken, tokenVisitor, isToken),
|
||||
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode),
|
||||
visitNode((<ParameterDeclaration>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
return updateDecorator(<Decorator>node,
|
||||
visitNode((<Decorator>node).expression, visitor, isExpression));
|
||||
|
||||
// Type elements
|
||||
case SyntaxKind.PropertySignature:
|
||||
return updatePropertySignature((<PropertySignature>node),
|
||||
nodesVisitor((<PropertySignature>node).modifiers, visitor, isToken),
|
||||
visitNode((<PropertySignature>node).name, visitor, isPropertyName),
|
||||
visitNode((<PropertySignature>node).questionToken, tokenVisitor, isToken),
|
||||
visitNode((<PropertySignature>node).type, visitor, isTypeNode),
|
||||
visitNode((<PropertySignature>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return updateProperty(<PropertyDeclaration>node,
|
||||
nodesVisitor((<PropertyDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<PropertyDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<PropertyDeclaration>node).name, visitor, isPropertyName),
|
||||
// QuestionToken and ExclamationToken is uniqued in Property Declaration and the signature of 'updateProperty' is that too
|
||||
visitNode((<PropertyDeclaration>node).questionToken || (<PropertyDeclaration>node).exclamationToken, tokenVisitor, isToken),
|
||||
visitNode((<PropertyDeclaration>node).type, visitor, isTypeNode),
|
||||
visitNode((<PropertyDeclaration>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.MethodSignature:
|
||||
return updateMethodSignature(<MethodSignature>node,
|
||||
nodesVisitor((<MethodSignature>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<MethodSignature>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<MethodSignature>node).type, visitor, isTypeNode),
|
||||
visitNode((<MethodSignature>node).name, visitor, isPropertyName),
|
||||
visitNode((<MethodSignature>node).questionToken, tokenVisitor, isToken));
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return updateMethod(<MethodDeclaration>node,
|
||||
nodesVisitor((<MethodDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<MethodDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<MethodDeclaration>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
|
||||
visitNode((<MethodDeclaration>node).questionToken, tokenVisitor, isToken),
|
||||
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<MethodDeclaration>node).body!, visitor, context));
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
return updateConstructor(<ConstructorDeclaration>node,
|
||||
nodesVisitor((<ConstructorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ConstructorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitParameterList((<ConstructorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitFunctionBody((<ConstructorDeclaration>node).body!, visitor, context));
|
||||
|
||||
case SyntaxKind.GetAccessor:
|
||||
return updateGetAccessor(<GetAccessorDeclaration>node,
|
||||
nodesVisitor((<GetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<GetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<GetAccessorDeclaration>node).name, visitor, isPropertyName),
|
||||
visitParameterList((<GetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<GetAccessorDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<GetAccessorDeclaration>node).body!, visitor, context));
|
||||
|
||||
case SyntaxKind.SetAccessor:
|
||||
return updateSetAccessor(<SetAccessorDeclaration>node,
|
||||
nodesVisitor((<SetAccessorDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<SetAccessorDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<SetAccessorDeclaration>node).name, visitor, isPropertyName),
|
||||
visitParameterList((<SetAccessorDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitFunctionBody((<SetAccessorDeclaration>node).body!, visitor, context));
|
||||
|
||||
case SyntaxKind.CallSignature:
|
||||
return updateCallSignature(<CallSignatureDeclaration>node,
|
||||
nodesVisitor((<CallSignatureDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<CallSignatureDeclaration>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<CallSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ConstructSignature:
|
||||
return updateConstructSignature(<ConstructSignatureDeclaration>node,
|
||||
nodesVisitor((<ConstructSignatureDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ConstructSignatureDeclaration>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<ConstructSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.IndexSignature:
|
||||
return updateIndexSignature(<IndexSignatureDeclaration>node,
|
||||
nodesVisitor((<IndexSignatureDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<IndexSignatureDeclaration>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<IndexSignatureDeclaration>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<IndexSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
// Types
|
||||
case SyntaxKind.TypePredicate:
|
||||
return updateTypePredicateNodeWithModifier(<TypePredicateNode>node,
|
||||
visitNode((<TypePredicateNode>node).assertsModifier, visitor),
|
||||
visitNode((<TypePredicateNode>node).parameterName, visitor),
|
||||
visitNode((<TypePredicateNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TypeReference:
|
||||
return updateTypeReferenceNode(<TypeReferenceNode>node,
|
||||
visitNode((<TypeReferenceNode>node).typeName, visitor, isEntityName),
|
||||
nodesVisitor((<TypeReferenceNode>node).typeArguments, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.FunctionType:
|
||||
return updateFunctionTypeNode(<FunctionTypeNode>node,
|
||||
nodesVisitor((<FunctionTypeNode>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<FunctionTypeNode>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<FunctionTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ConstructorType:
|
||||
return updateConstructorTypeNode(<ConstructorTypeNode>node,
|
||||
nodesVisitor((<ConstructorTypeNode>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ConstructorTypeNode>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<ConstructorTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TypeQuery:
|
||||
return updateTypeQueryNode((<TypeQueryNode>node),
|
||||
visitNode((<TypeQueryNode>node).exprName, visitor, isEntityName));
|
||||
|
||||
case SyntaxKind.TypeLiteral:
|
||||
return updateTypeLiteralNode((<TypeLiteralNode>node),
|
||||
nodesVisitor((<TypeLiteralNode>node).members, visitor, isTypeElement));
|
||||
|
||||
case SyntaxKind.ArrayType:
|
||||
return updateArrayTypeNode(<ArrayTypeNode>node,
|
||||
visitNode((<ArrayTypeNode>node).elementType, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TupleType:
|
||||
return updateTupleTypeNode((<TupleTypeNode>node),
|
||||
nodesVisitor((<TupleTypeNode>node).elementTypes, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.OptionalType:
|
||||
return updateOptionalTypeNode((<OptionalTypeNode>node),
|
||||
visitNode((<OptionalTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.RestType:
|
||||
return updateRestTypeNode((<RestTypeNode>node),
|
||||
visitNode((<RestTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.UnionType:
|
||||
return updateUnionTypeNode(<UnionTypeNode>node,
|
||||
nodesVisitor((<UnionTypeNode>node).types, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.IntersectionType:
|
||||
return updateIntersectionTypeNode(<IntersectionTypeNode>node,
|
||||
nodesVisitor((<IntersectionTypeNode>node).types, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ConditionalType:
|
||||
return updateConditionalTypeNode(<ConditionalTypeNode>node,
|
||||
visitNode((<ConditionalTypeNode>node).checkType, visitor, isTypeNode),
|
||||
visitNode((<ConditionalTypeNode>node).extendsType, visitor, isTypeNode),
|
||||
visitNode((<ConditionalTypeNode>node).trueType, visitor, isTypeNode),
|
||||
visitNode((<ConditionalTypeNode>node).falseType, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.InferType:
|
||||
return updateInferTypeNode(<InferTypeNode>node,
|
||||
visitNode((<InferTypeNode>node).typeParameter, visitor, isTypeParameterDeclaration));
|
||||
|
||||
case SyntaxKind.ImportType:
|
||||
return updateImportTypeNode(<ImportTypeNode>node,
|
||||
visitNode((<ImportTypeNode>node).argument, visitor, isTypeNode),
|
||||
visitNode((<ImportTypeNode>node).qualifier, visitor, isEntityName),
|
||||
visitNodes((<ImportTypeNode>node).typeArguments, visitor, isTypeNode),
|
||||
(<ImportTypeNode>node).isTypeOf
|
||||
);
|
||||
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return updateParenthesizedType(<ParenthesizedTypeNode>node,
|
||||
visitNode((<ParenthesizedTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TypeOperator:
|
||||
return updateTypeOperatorNode(<TypeOperatorNode>node,
|
||||
visitNode((<TypeOperatorNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.IndexedAccessType:
|
||||
return updateIndexedAccessTypeNode((<IndexedAccessTypeNode>node),
|
||||
visitNode((<IndexedAccessTypeNode>node).objectType, visitor, isTypeNode),
|
||||
visitNode((<IndexedAccessTypeNode>node).indexType, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.MappedType:
|
||||
return updateMappedTypeNode((<MappedTypeNode>node),
|
||||
visitNode((<MappedTypeNode>node).readonlyToken, tokenVisitor, isToken),
|
||||
visitNode((<MappedTypeNode>node).typeParameter, visitor, isTypeParameterDeclaration),
|
||||
visitNode((<MappedTypeNode>node).questionToken, tokenVisitor, isToken),
|
||||
visitNode((<MappedTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.LiteralType:
|
||||
return updateLiteralTypeNode(<LiteralTypeNode>node,
|
||||
visitNode((<LiteralTypeNode>node).literal, visitor, isExpression));
|
||||
|
||||
// Binding patterns
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return updateObjectBindingPattern(<ObjectBindingPattern>node,
|
||||
nodesVisitor((<ObjectBindingPattern>node).elements, visitor, isBindingElement));
|
||||
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return updateArrayBindingPattern(<ArrayBindingPattern>node,
|
||||
nodesVisitor((<ArrayBindingPattern>node).elements, visitor, isArrayBindingElement));
|
||||
|
||||
case SyntaxKind.BindingElement:
|
||||
return updateBindingElement(<BindingElement>node,
|
||||
visitNode((<BindingElement>node).dotDotDotToken, tokenVisitor, isToken),
|
||||
visitNode((<BindingElement>node).propertyName, visitor, isPropertyName),
|
||||
visitNode((<BindingElement>node).name, visitor, isBindingName),
|
||||
visitNode((<BindingElement>node).initializer, visitor, isExpression));
|
||||
|
||||
// Expression
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return updateArrayLiteral(<ArrayLiteralExpression>node,
|
||||
nodesVisitor((<ArrayLiteralExpression>node).elements, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return updateObjectLiteral(<ObjectLiteralExpression>node,
|
||||
nodesVisitor((<ObjectLiteralExpression>node).properties, visitor, isObjectLiteralElementLike));
|
||||
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
if (node.flags & NodeFlags.OptionalChain) {
|
||||
return updatePropertyAccessChain(<PropertyAccessChain>node,
|
||||
visitNode((<PropertyAccessChain>node).expression, visitor, isExpression),
|
||||
visitNode((<PropertyAccessChain>node).questionDotToken, visitor, isToken),
|
||||
visitNode((<PropertyAccessChain>node).name, visitor, isIdentifier));
|
||||
}
|
||||
return updatePropertyAccess(<PropertyAccessExpression>node,
|
||||
visitNode((<PropertyAccessExpression>node).expression, visitor, isExpression),
|
||||
visitNode((<PropertyAccessExpression>node).name, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
if (node.flags & NodeFlags.OptionalChain) {
|
||||
return updateElementAccessChain(<ElementAccessChain>node,
|
||||
visitNode((<ElementAccessChain>node).expression, visitor, isExpression),
|
||||
visitNode((<ElementAccessChain>node).questionDotToken, visitor, isToken),
|
||||
visitNode((<ElementAccessChain>node).argumentExpression, visitor, isExpression));
|
||||
}
|
||||
return updateElementAccess(<ElementAccessExpression>node,
|
||||
visitNode((<ElementAccessExpression>node).expression, visitor, isExpression),
|
||||
visitNode((<ElementAccessExpression>node).argumentExpression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.CallExpression:
|
||||
if (node.flags & NodeFlags.OptionalChain) {
|
||||
return updateCallChain(<CallChain>node,
|
||||
visitNode((<CallChain>node).expression, visitor, isExpression),
|
||||
visitNode((<CallChain>node).questionDotToken, visitor, isToken),
|
||||
nodesVisitor((<CallChain>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<CallChain>node).arguments, visitor, isExpression));
|
||||
}
|
||||
return updateCall(<CallExpression>node,
|
||||
visitNode((<CallExpression>node).expression, visitor, isExpression),
|
||||
nodesVisitor((<CallExpression>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<CallExpression>node).arguments, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.NewExpression:
|
||||
return updateNew(<NewExpression>node,
|
||||
visitNode((<NewExpression>node).expression, visitor, isExpression),
|
||||
nodesVisitor((<NewExpression>node).typeArguments, visitor, isTypeNode),
|
||||
nodesVisitor((<NewExpression>node).arguments, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
return updateTaggedTemplate(<TaggedTemplateExpression>node,
|
||||
visitNode((<TaggedTemplateExpression>node).tag, visitor, isExpression),
|
||||
visitNodes((<TaggedTemplateExpression>node).typeArguments, visitor, isExpression),
|
||||
visitNode((<TaggedTemplateExpression>node).template, visitor, isTemplateLiteral));
|
||||
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
return updateTypeAssertion(<TypeAssertion>node,
|
||||
visitNode((<TypeAssertion>node).type, visitor, isTypeNode),
|
||||
visitNode((<TypeAssertion>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
return updateParen(<ParenthesizedExpression>node,
|
||||
visitNode((<ParenthesizedExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return updateFunctionExpression(<FunctionExpression>node,
|
||||
nodesVisitor((<FunctionExpression>node).modifiers, visitor, isModifier),
|
||||
visitNode((<FunctionExpression>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<FunctionExpression>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<FunctionExpression>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<FunctionExpression>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionExpression>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return updateArrowFunction(<ArrowFunction>node,
|
||||
nodesVisitor((<ArrowFunction>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ArrowFunction>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<ArrowFunction>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<ArrowFunction>node).type, visitor, isTypeNode),
|
||||
visitNode((<ArrowFunction>node).equalsGreaterThanToken, visitor, isToken),
|
||||
visitFunctionBody((<ArrowFunction>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.DeleteExpression:
|
||||
return updateDelete(<DeleteExpression>node,
|
||||
visitNode((<DeleteExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
return updateTypeOf(<TypeOfExpression>node,
|
||||
visitNode((<TypeOfExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.VoidExpression:
|
||||
return updateVoid(<VoidExpression>node,
|
||||
visitNode((<VoidExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.AwaitExpression:
|
||||
return updateAwait(<AwaitExpression>node,
|
||||
visitNode((<AwaitExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
return updatePrefix(<PrefixUnaryExpression>node,
|
||||
visitNode((<PrefixUnaryExpression>node).operand, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
return updatePostfix(<PostfixUnaryExpression>node,
|
||||
visitNode((<PostfixUnaryExpression>node).operand, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return updateBinary(<BinaryExpression>node,
|
||||
visitNode((<BinaryExpression>node).left, visitor, isExpression),
|
||||
visitNode((<BinaryExpression>node).right, visitor, isExpression),
|
||||
visitNode((<BinaryExpression>node).operatorToken, visitor, isToken));
|
||||
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
return updateConditional(<ConditionalExpression>node,
|
||||
visitNode((<ConditionalExpression>node).condition, visitor, isExpression),
|
||||
visitNode((<ConditionalExpression>node).questionToken, visitor, isToken),
|
||||
visitNode((<ConditionalExpression>node).whenTrue, visitor, isExpression),
|
||||
visitNode((<ConditionalExpression>node).colonToken, visitor, isToken),
|
||||
visitNode((<ConditionalExpression>node).whenFalse, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TemplateExpression:
|
||||
return updateTemplateExpression(<TemplateExpression>node,
|
||||
visitNode((<TemplateExpression>node).head, visitor, isTemplateHead),
|
||||
nodesVisitor((<TemplateExpression>node).templateSpans, visitor, isTemplateSpan));
|
||||
|
||||
case SyntaxKind.YieldExpression:
|
||||
return updateYield(<YieldExpression>node,
|
||||
visitNode((<YieldExpression>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<YieldExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.SpreadElement:
|
||||
return updateSpread(<SpreadElement>node,
|
||||
visitNode((<SpreadElement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ClassExpression:
|
||||
return updateClassExpression(<ClassExpression>node,
|
||||
nodesVisitor((<ClassExpression>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassExpression>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<ClassExpression>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ClassExpression>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassExpression>node).members, visitor, isClassElement));
|
||||
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return updateExpressionWithTypeArguments(<ExpressionWithTypeArguments>node,
|
||||
nodesVisitor((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
|
||||
visitNode((<ExpressionWithTypeArguments>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.AsExpression:
|
||||
return updateAsExpression(<AsExpression>node,
|
||||
visitNode((<AsExpression>node).expression, visitor, isExpression),
|
||||
visitNode((<AsExpression>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.NonNullExpression:
|
||||
return updateNonNullExpression(<NonNullExpression>node,
|
||||
visitNode((<NonNullExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.MetaProperty:
|
||||
return updateMetaProperty(<MetaProperty>node,
|
||||
visitNode((<MetaProperty>node).name, visitor, isIdentifier));
|
||||
|
||||
// Misc
|
||||
case SyntaxKind.TemplateSpan:
|
||||
return updateTemplateSpan(<TemplateSpan>node,
|
||||
visitNode((<TemplateSpan>node).expression, visitor, isExpression),
|
||||
visitNode((<TemplateSpan>node).literal, visitor, isTemplateMiddleOrTemplateTail));
|
||||
|
||||
// Element
|
||||
case SyntaxKind.Block:
|
||||
return updateBlock(<Block>node,
|
||||
nodesVisitor((<Block>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
return updateVariableStatement(<VariableStatement>node,
|
||||
nodesVisitor((<VariableStatement>node).modifiers, visitor, isModifier),
|
||||
visitNode((<VariableStatement>node).declarationList, visitor, isVariableDeclarationList));
|
||||
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
return updateExpressionStatement(<ExpressionStatement>node,
|
||||
visitNode((<ExpressionStatement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.IfStatement:
|
||||
return updateIf(<IfStatement>node,
|
||||
visitNode((<IfStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<IfStatement>node).thenStatement, visitor, isStatement, liftToBlock),
|
||||
visitNode((<IfStatement>node).elseStatement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.DoStatement:
|
||||
return updateDo(<DoStatement>node,
|
||||
visitNode((<DoStatement>node).statement, visitor, isStatement, liftToBlock),
|
||||
visitNode((<DoStatement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.WhileStatement:
|
||||
return updateWhile(<WhileStatement>node,
|
||||
visitNode((<WhileStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<WhileStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ForStatement:
|
||||
return updateFor(<ForStatement>node,
|
||||
visitNode((<ForStatement>node).initializer, visitor, isForInitializer),
|
||||
visitNode((<ForStatement>node).condition, visitor, isExpression),
|
||||
visitNode((<ForStatement>node).incrementor, visitor, isExpression),
|
||||
visitNode((<ForStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ForInStatement:
|
||||
return updateForIn(<ForInStatement>node,
|
||||
visitNode((<ForInStatement>node).initializer, visitor, isForInitializer),
|
||||
visitNode((<ForInStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<ForInStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
return updateForOf(<ForOfStatement>node,
|
||||
visitNode((<ForOfStatement>node).awaitModifier, visitor, isToken),
|
||||
visitNode((<ForOfStatement>node).initializer, visitor, isForInitializer),
|
||||
visitNode((<ForOfStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<ForOfStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ContinueStatement:
|
||||
return updateContinue(<ContinueStatement>node,
|
||||
visitNode((<ContinueStatement>node).label, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.BreakStatement:
|
||||
return updateBreak(<BreakStatement>node,
|
||||
visitNode((<BreakStatement>node).label, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ReturnStatement:
|
||||
return updateReturn(<ReturnStatement>node,
|
||||
visitNode((<ReturnStatement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.WithStatement:
|
||||
return updateWith(<WithStatement>node,
|
||||
visitNode((<WithStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<WithStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.SwitchStatement:
|
||||
return updateSwitch(<SwitchStatement>node,
|
||||
visitNode((<SwitchStatement>node).expression, visitor, isExpression),
|
||||
visitNode((<SwitchStatement>node).caseBlock, visitor, isCaseBlock));
|
||||
|
||||
case SyntaxKind.LabeledStatement:
|
||||
return updateLabel(<LabeledStatement>node,
|
||||
visitNode((<LabeledStatement>node).label, visitor, isIdentifier),
|
||||
visitNode((<LabeledStatement>node).statement, visitor, isStatement, liftToBlock));
|
||||
|
||||
case SyntaxKind.ThrowStatement:
|
||||
return updateThrow(<ThrowStatement>node,
|
||||
visitNode((<ThrowStatement>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.TryStatement:
|
||||
return updateTry(<TryStatement>node,
|
||||
visitNode((<TryStatement>node).tryBlock, visitor, isBlock),
|
||||
visitNode((<TryStatement>node).catchClause, visitor, isCatchClause),
|
||||
visitNode((<TryStatement>node).finallyBlock, visitor, isBlock));
|
||||
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return updateTypeScriptVariableDeclaration(<VariableDeclaration>node,
|
||||
visitNode((<VariableDeclaration>node).name, visitor, isBindingName),
|
||||
visitNode((<VariableDeclaration>node).exclamationToken, tokenVisitor, isToken),
|
||||
visitNode((<VariableDeclaration>node).type, visitor, isTypeNode),
|
||||
visitNode((<VariableDeclaration>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
return updateVariableDeclarationList(<VariableDeclarationList>node,
|
||||
nodesVisitor((<VariableDeclarationList>node).declarations, visitor, isVariableDeclaration));
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return updateFunctionDeclaration(<FunctionDeclaration>node,
|
||||
nodesVisitor((<FunctionDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<FunctionDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<FunctionDeclaration>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<FunctionDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return updateClassDeclaration(<ClassDeclaration>node,
|
||||
nodesVisitor((<ClassDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ClassDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<ClassDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassDeclaration>node).members, visitor, isClassElement));
|
||||
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return updateInterfaceDeclaration(<InterfaceDeclaration>node,
|
||||
nodesVisitor((<InterfaceDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<InterfaceDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<InterfaceDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<InterfaceDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<InterfaceDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<InterfaceDeclaration>node).members, visitor, isTypeElement));
|
||||
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
return updateTypeAliasDeclaration(<TypeAliasDeclaration>node,
|
||||
nodesVisitor((<TypeAliasDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<TypeAliasDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<TypeAliasDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<TypeAliasDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitNode((<TypeAliasDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return updateEnumDeclaration(<EnumDeclaration>node,
|
||||
nodesVisitor((<EnumDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<EnumDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<EnumDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<EnumDeclaration>node).members, visitor, isEnumMember));
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return updateModuleDeclaration(<ModuleDeclaration>node,
|
||||
nodesVisitor((<ModuleDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ModuleDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ModuleDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<ModuleDeclaration>node).body, visitor, isModuleBody));
|
||||
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return updateModuleBlock(<ModuleBlock>node,
|
||||
nodesVisitor((<ModuleBlock>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.CaseBlock:
|
||||
return updateCaseBlock(<CaseBlock>node,
|
||||
nodesVisitor((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
|
||||
|
||||
case SyntaxKind.NamespaceExportDeclaration:
|
||||
return updateNamespaceExportDeclaration(<NamespaceExportDeclaration>node,
|
||||
visitNode((<NamespaceExportDeclaration>node).name, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
return updateImportEqualsDeclaration(<ImportEqualsDeclaration>node,
|
||||
nodesVisitor((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ImportEqualsDeclaration>node).name, visitor, isIdentifier),
|
||||
visitNode((<ImportEqualsDeclaration>node).moduleReference, visitor, isModuleReference));
|
||||
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
return updateImportDeclaration(<ImportDeclaration>node,
|
||||
nodesVisitor((<ImportDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ImportDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ImportDeclaration>node).importClause, visitor, isImportClause),
|
||||
visitNode((<ImportDeclaration>node).moduleSpecifier, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ImportClause:
|
||||
return updateImportClause(<ImportClause>node,
|
||||
visitNode((<ImportClause>node).name, visitor, isIdentifier),
|
||||
visitNode((<ImportClause>node).namedBindings, visitor, isNamedImportBindings));
|
||||
|
||||
case SyntaxKind.NamespaceImport:
|
||||
return updateNamespaceImport(<NamespaceImport>node,
|
||||
visitNode((<NamespaceImport>node).name, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.NamedImports:
|
||||
return updateNamedImports(<NamedImports>node,
|
||||
nodesVisitor((<NamedImports>node).elements, visitor, isImportSpecifier));
|
||||
|
||||
case SyntaxKind.ImportSpecifier:
|
||||
return updateImportSpecifier(<ImportSpecifier>node,
|
||||
visitNode((<ImportSpecifier>node).propertyName, visitor, isIdentifier),
|
||||
visitNode((<ImportSpecifier>node).name, visitor, isIdentifier));
|
||||
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return updateExportAssignment(<ExportAssignment>node,
|
||||
nodesVisitor((<ExportAssignment>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ExportAssignment>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ExportAssignment>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return updateExportDeclaration(<ExportDeclaration>node,
|
||||
nodesVisitor((<ExportDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ExportDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ExportDeclaration>node).exportClause, visitor, isNamedExports),
|
||||
visitNode((<ExportDeclaration>node).moduleSpecifier, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.NamedExports:
|
||||
return updateNamedExports(<NamedExports>node,
|
||||
nodesVisitor((<NamedExports>node).elements, visitor, isExportSpecifier));
|
||||
|
||||
case SyntaxKind.ExportSpecifier:
|
||||
return updateExportSpecifier(<ExportSpecifier>node,
|
||||
visitNode((<ExportSpecifier>node).propertyName, visitor, isIdentifier),
|
||||
visitNode((<ExportSpecifier>node).name, visitor, isIdentifier));
|
||||
|
||||
// Module references
|
||||
case SyntaxKind.ExternalModuleReference:
|
||||
return updateExternalModuleReference(<ExternalModuleReference>node,
|
||||
visitNode((<ExternalModuleReference>node).expression, visitor, isExpression));
|
||||
|
||||
// JSX
|
||||
case SyntaxKind.JsxElement:
|
||||
return updateJsxElement(<JsxElement>node,
|
||||
visitNode((<JsxElement>node).openingElement, visitor, isJsxOpeningElement),
|
||||
nodesVisitor((<JsxElement>node).children, visitor, isJsxChild),
|
||||
visitNode((<JsxElement>node).closingElement, visitor, isJsxClosingElement));
|
||||
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
return updateJsxSelfClosingElement(<JsxSelfClosingElement>node,
|
||||
visitNode((<JsxSelfClosingElement>node).tagName, visitor, isJsxTagNameExpression),
|
||||
nodesVisitor((<JsxSelfClosingElement>node).typeArguments, visitor, isTypeNode),
|
||||
visitNode((<JsxSelfClosingElement>node).attributes, visitor, isJsxAttributes));
|
||||
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
return updateJsxOpeningElement(<JsxOpeningElement>node,
|
||||
visitNode((<JsxOpeningElement>node).tagName, visitor, isJsxTagNameExpression),
|
||||
nodesVisitor((<JsxSelfClosingElement>node).typeArguments, visitor, isTypeNode),
|
||||
visitNode((<JsxOpeningElement>node).attributes, visitor, isJsxAttributes));
|
||||
|
||||
case SyntaxKind.JsxClosingElement:
|
||||
return updateJsxClosingElement(<JsxClosingElement>node,
|
||||
visitNode((<JsxClosingElement>node).tagName, visitor, isJsxTagNameExpression));
|
||||
|
||||
case SyntaxKind.JsxFragment:
|
||||
return updateJsxFragment(<JsxFragment>node,
|
||||
visitNode((<JsxFragment>node).openingFragment, visitor, isJsxOpeningFragment),
|
||||
nodesVisitor((<JsxFragment>node).children, visitor, isJsxChild),
|
||||
visitNode((<JsxFragment>node).closingFragment, visitor, isJsxClosingFragment));
|
||||
|
||||
case SyntaxKind.JsxAttribute:
|
||||
return updateJsxAttribute(<JsxAttribute>node,
|
||||
visitNode((<JsxAttribute>node).name, visitor, isIdentifier),
|
||||
visitNode((<JsxAttribute>node).initializer, visitor, isStringLiteralOrJsxExpression));
|
||||
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return updateJsxAttributes(<JsxAttributes>node,
|
||||
nodesVisitor((<JsxAttributes>node).properties, visitor, isJsxAttributeLike));
|
||||
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
return updateJsxSpreadAttribute(<JsxSpreadAttribute>node,
|
||||
visitNode((<JsxSpreadAttribute>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.JsxExpression:
|
||||
return updateJsxExpression(<JsxExpression>node,
|
||||
visitNode((<JsxExpression>node).expression, visitor, isExpression));
|
||||
|
||||
// Clauses
|
||||
case SyntaxKind.CaseClause:
|
||||
return updateCaseClause(<CaseClause>node,
|
||||
visitNode((<CaseClause>node).expression, visitor, isExpression),
|
||||
nodesVisitor((<CaseClause>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.DefaultClause:
|
||||
return updateDefaultClause(<DefaultClause>node,
|
||||
nodesVisitor((<DefaultClause>node).statements, visitor, isStatement));
|
||||
|
||||
case SyntaxKind.HeritageClause:
|
||||
return updateHeritageClause(<HeritageClause>node,
|
||||
nodesVisitor((<HeritageClause>node).types, visitor, isExpressionWithTypeArguments));
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
return updateCatchClause(<CatchClause>node,
|
||||
visitNode((<CatchClause>node).variableDeclaration, visitor, isVariableDeclaration),
|
||||
visitNode((<CatchClause>node).block, visitor, isBlock));
|
||||
|
||||
// Property assignments
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
return updatePropertyAssignment(<PropertyAssignment>node,
|
||||
visitNode((<PropertyAssignment>node).name, visitor, isPropertyName),
|
||||
visitNode((<PropertyAssignment>node).initializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
return updateShorthandPropertyAssignment(<ShorthandPropertyAssignment>node,
|
||||
visitNode((<ShorthandPropertyAssignment>node).name, visitor, isIdentifier),
|
||||
visitNode((<ShorthandPropertyAssignment>node).objectAssignmentInitializer, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.SpreadAssignment:
|
||||
return updateSpreadAssignment(<SpreadAssignment>node,
|
||||
visitNode((<SpreadAssignment>node).expression, visitor, isExpression));
|
||||
|
||||
// Enum
|
||||
case SyntaxKind.EnumMember:
|
||||
return updateEnumMember(<EnumMember>node,
|
||||
visitNode((<EnumMember>node).name, visitor, isPropertyName),
|
||||
visitNode((<EnumMember>node).initializer, visitor, isExpression));
|
||||
|
||||
// Top-level nodes
|
||||
case SyntaxKind.SourceFile:
|
||||
return updateSourceFileNode(<SourceFile>node,
|
||||
visitLexicalEnvironment((<SourceFile>node).statements, visitor, context));
|
||||
|
||||
// Transformation nodes
|
||||
case SyntaxKind.PartiallyEmittedExpression:
|
||||
return updatePartiallyEmittedExpression(<PartiallyEmittedExpression>node,
|
||||
visitNode((<PartiallyEmittedExpression>node).expression, visitor, isExpression));
|
||||
|
||||
case SyntaxKind.CommaListExpression:
|
||||
return updateCommaList(<CommaListExpression>node,
|
||||
nodesVisitor((<CommaListExpression>node).elements, visitor, isExpression));
|
||||
|
||||
default:
|
||||
// No need to visit nodes with no children.
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the single node from a NodeArray.
|
||||
*
|
||||
* @param nodes The NodeArray.
|
||||
*/
|
||||
function extractSingleNode(nodes: readonly Node[]): Node | undefined {
|
||||
Debug.assert(nodes.length <= 1, "Too many nodes written to output.");
|
||||
return singleOrUndefined(nodes);
|
||||
}
|
||||
}
|
|
@ -454,720 +454,3 @@ namespace ts {
|
|||
return exitStatus;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ts {
|
||||
export interface ReadBuildProgramHost {
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getCurrentDirectory(): string;
|
||||
readFile(fileName: string): string | undefined;
|
||||
}
|
||||
export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost) {
|
||||
if (compilerOptions.out || compilerOptions.outFile) return undefined;
|
||||
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(compilerOptions);
|
||||
if (!buildInfoPath) return undefined;
|
||||
const content = host.readFile(buildInfoPath);
|
||||
if (!content) return undefined;
|
||||
const buildInfo = getBuildInfo(content);
|
||||
if (buildInfo.version !== version) return undefined;
|
||||
if (!buildInfo.program) return undefined;
|
||||
return createBuildProgramUsingProgramBuildInfo(buildInfo.program, buildInfoPath, host);
|
||||
}
|
||||
|
||||
export function createIncrementalCompilerHost(options: CompilerOptions, system = sys): CompilerHost {
|
||||
const host = createCompilerHostWorker(options, /*setParentNodes*/ undefined, system);
|
||||
host.createHash = maybeBind(system, system.createHash);
|
||||
setGetSourceFileAsHashVersioned(host, system);
|
||||
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName));
|
||||
return host;
|
||||
}
|
||||
|
||||
export interface IncrementalProgramOptions<T extends BuilderProgram> {
|
||||
rootNames: readonly string[];
|
||||
options: CompilerOptions;
|
||||
configFileParsingDiagnostics?: readonly Diagnostic[];
|
||||
projectReferences?: readonly ProjectReference[];
|
||||
host?: CompilerHost;
|
||||
createProgram?: CreateProgram<T>;
|
||||
}
|
||||
|
||||
export function createIncrementalProgram<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>({
|
||||
rootNames, options, configFileParsingDiagnostics, projectReferences, host, createProgram
|
||||
}: IncrementalProgramOptions<T>): T {
|
||||
host = host || createIncrementalCompilerHost(options);
|
||||
createProgram = createProgram || createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>;
|
||||
const oldProgram = readBuilderProgram(options, host) as any as T;
|
||||
return createProgram(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
}
|
||||
|
||||
export type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions, errorCount?: number) => void;
|
||||
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
|
||||
export type CreateProgram<T extends BuilderProgram> = (rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[] | undefined) => T;
|
||||
|
||||
/** Host that has watch functionality used in --watch mode */
|
||||
export interface WatchHost {
|
||||
/** If provided, called with Diagnostic message that informs about change in watch status */
|
||||
onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions, errorCount?: number): void;
|
||||
|
||||
/** Used to watch changes in source files, missing files needed to update the program or config file */
|
||||
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
|
||||
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
|
||||
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
|
||||
/** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
|
||||
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
|
||||
/** If provided, will be used to reset existing delayed compilation */
|
||||
clearTimeout?(timeoutId: any): void;
|
||||
}
|
||||
export interface ProgramHost<T extends BuilderProgram> {
|
||||
/**
|
||||
* Used to create the program when need for program creation or recreation detected
|
||||
*/
|
||||
createProgram: CreateProgram<T>;
|
||||
|
||||
// Sub set of compiler host methods to read and generate new program
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getNewLine(): string;
|
||||
getCurrentDirectory(): string;
|
||||
getDefaultLibFileName(options: CompilerOptions): string;
|
||||
getDefaultLibLocation?(): string;
|
||||
createHash?(data: string): string;
|
||||
|
||||
/**
|
||||
* Use to check file presence for source files and
|
||||
* if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well
|
||||
*/
|
||||
fileExists(path: string): boolean;
|
||||
/**
|
||||
* Use to read file text for source files and
|
||||
* if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well
|
||||
*/
|
||||
readFile(path: string, encoding?: string): string | undefined;
|
||||
|
||||
/** If provided, used for module resolution as well as to handle directory structure */
|
||||
directoryExists?(path: string): boolean;
|
||||
/** If provided, used in resolutions as well as handling directory structure */
|
||||
getDirectories?(path: string): string[];
|
||||
/** If provided, used to cache and handle directory structure modifications */
|
||||
readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[];
|
||||
|
||||
/** Symbol links resolution */
|
||||
realpath?(path: string): string;
|
||||
/** If provided would be used to write log about compilation */
|
||||
trace?(s: string): void;
|
||||
/** If provided is used to get the environment variable */
|
||||
getEnvironmentVariable?(name: string): string | undefined;
|
||||
|
||||
/** If provided, used to resolve the module names, otherwise typescript's default module resolution */
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedModule | undefined)[];
|
||||
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
}
|
||||
/** Internal interface used to wire emit through same host */
|
||||
|
||||
/*@internal*/
|
||||
export interface ProgramHost<T extends BuilderProgram> {
|
||||
// TODO: GH#18217 Optional methods are frequently asserted
|
||||
createDirectory?(path: string): void;
|
||||
writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
onCachedDirectoryStructureHostCreate?(host: CachedDirectoryStructureHost): void;
|
||||
}
|
||||
|
||||
export interface WatchCompilerHost<T extends BuilderProgram> extends ProgramHost<T>, WatchHost {
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
|
||||
// Only for testing
|
||||
/*@internal*/
|
||||
maxNumberOfFilesToIterateForInvalidation?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Host to create watch with root files and options
|
||||
*/
|
||||
export interface WatchCompilerHostOfFilesAndCompilerOptions<T extends BuilderProgram> extends WatchCompilerHost<T> {
|
||||
/** root files to use to generate program */
|
||||
rootFiles: string[];
|
||||
|
||||
/** Compiler options */
|
||||
options: CompilerOptions;
|
||||
|
||||
/** Project References */
|
||||
projectReferences?: readonly ProjectReference[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Host to create watch with config file
|
||||
*/
|
||||
export interface WatchCompilerHostOfConfigFile<T extends BuilderProgram> extends WatchCompilerHost<T>, ConfigFileDiagnosticsReporter {
|
||||
/** Name of the config file to compile */
|
||||
configFileName: string;
|
||||
|
||||
/** Options to extend */
|
||||
optionsToExtend?: CompilerOptions;
|
||||
|
||||
/**
|
||||
* Used to generate source file names from the config file and its include, exclude, files rules
|
||||
* and also to cache the directory stucture
|
||||
*/
|
||||
readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Host to create watch with config file that is already parsed (from tsc)
|
||||
*/
|
||||
/*@internal*/
|
||||
export interface WatchCompilerHostOfConfigFile<T extends BuilderProgram> extends WatchCompilerHost<T> {
|
||||
optionsToExtend?: CompilerOptions;
|
||||
configFileParsingResult?: ParsedCommandLine;
|
||||
}
|
||||
|
||||
export interface Watch<T> {
|
||||
/** Synchronize with host and get updated program */
|
||||
getProgram(): T;
|
||||
/** Gets the existing program without synchronizing with changes on host */
|
||||
/*@internal*/
|
||||
getCurrentProgram(): T;
|
||||
/** Closes the watch */
|
||||
close(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the watch what generates program using the config file
|
||||
*/
|
||||
export interface WatchOfConfigFile<T> extends Watch<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the watch that generates program using the root files and compiler options
|
||||
*/
|
||||
export interface WatchOfFilesAndCompilerOptions<T> extends Watch<T> {
|
||||
/** Updates the root files in the program, only if this is not config file compilation */
|
||||
updateRootFileNames(fileNames: string[]): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the watch compiler host for either configFile or fileNames and its options
|
||||
*/
|
||||
export function createWatchCompilerHost<T extends BuilderProgram>(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile<T>;
|
||||
export function createWatchCompilerHost<T extends BuilderProgram>(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: readonly ProjectReference[]): WatchCompilerHostOfFilesAndCompilerOptions<T>;
|
||||
export function createWatchCompilerHost<T extends BuilderProgram>(rootFilesOrConfigFileName: string | string[], options: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: readonly ProjectReference[]): WatchCompilerHostOfFilesAndCompilerOptions<T> | WatchCompilerHostOfConfigFile<T> {
|
||||
if (isArray(rootFilesOrConfigFileName)) {
|
||||
return createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options!, system, createProgram, reportDiagnostic, reportWatchStatus, projectReferences); // TODO: GH#18217
|
||||
}
|
||||
else {
|
||||
return createWatchCompilerHostOfConfigFile(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the watch from the host for root files and compiler options
|
||||
*/
|
||||
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfFilesAndCompilerOptions<T>): WatchOfFilesAndCompilerOptions<T>;
|
||||
/**
|
||||
* Creates the watch from the host for config file
|
||||
*/
|
||||
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfConfigFile<T>): WatchOfConfigFile<T>;
|
||||
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfFilesAndCompilerOptions<T> & WatchCompilerHostOfConfigFile<T>): WatchOfFilesAndCompilerOptions<T> | WatchOfConfigFile<T> {
|
||||
interface FilePresentOnHost {
|
||||
version: string;
|
||||
sourceFile: SourceFile;
|
||||
fileWatcher: FileWatcher;
|
||||
}
|
||||
type FileMissingOnHost = false;
|
||||
interface FilePresenceUnknownOnHost {
|
||||
version: false;
|
||||
fileWatcher?: FileWatcher;
|
||||
}
|
||||
type FileMayBePresentOnHost = FilePresentOnHost | FilePresenceUnknownOnHost;
|
||||
type HostFileInfo = FilePresentOnHost | FileMissingOnHost | FilePresenceUnknownOnHost;
|
||||
|
||||
let builderProgram: T;
|
||||
let reloadLevel: ConfigFileProgramReloadLevel; // level to indicate if the program needs to be reloaded from config file/just filenames etc
|
||||
let missingFilesMap: Map<FileWatcher>; // Map of file watchers for the missing files
|
||||
let watchedWildcardDirectories: Map<WildcardDirectoryWatcher>; // map of watchers for the wild card directories in the config file
|
||||
let timerToUpdateProgram: any; // timer callback to recompile the program
|
||||
|
||||
const sourceFilesCache = createMap<HostFileInfo>(); // Cache that stores the source file and version info
|
||||
let missingFilePathsRequestedForRelease: Path[] | undefined; // These paths are held temparirly so that we can remove the entry from source file cache if the file is not tracked by missing files
|
||||
let hasChangedCompilerOptions = false; // True if the compiler options have changed between compilations
|
||||
let hasChangedAutomaticTypeDirectiveNames = false; // True if the automatic type directives have changed
|
||||
|
||||
const useCaseSensitiveFileNames = host.useCaseSensitiveFileNames();
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const { configFileName, optionsToExtend: optionsToExtendForConfigFile = {}, createProgram } = host;
|
||||
let { rootFiles: rootFileNames, options: compilerOptions, projectReferences } = host;
|
||||
let configFileSpecs: ConfigFileSpecs;
|
||||
let configFileParsingDiagnostics: Diagnostic[] | undefined;
|
||||
let canConfigFileJsonReportNoInputFiles = false;
|
||||
let hasChangedConfigFileParsingErrors = false;
|
||||
|
||||
const cachedDirectoryStructureHost = configFileName === undefined ? undefined : createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames);
|
||||
if (cachedDirectoryStructureHost && host.onCachedDirectoryStructureHostCreate) {
|
||||
host.onCachedDirectoryStructureHostCreate(cachedDirectoryStructureHost);
|
||||
}
|
||||
const directoryStructureHost: DirectoryStructureHost = cachedDirectoryStructureHost || host;
|
||||
const parseConfigFileHost = parseConfigHostFromCompilerHostLike(host, directoryStructureHost);
|
||||
|
||||
// From tsc we want to get already parsed result and hence check for rootFileNames
|
||||
let newLine = updateNewLine();
|
||||
if (configFileName && host.configFileParsingResult) {
|
||||
setConfigFileParsingResult(host.configFileParsingResult);
|
||||
newLine = updateNewLine();
|
||||
}
|
||||
reportWatchDiagnostic(Diagnostics.Starting_compilation_in_watch_mode);
|
||||
if (configFileName && !host.configFileParsingResult) {
|
||||
newLine = getNewLineCharacter(optionsToExtendForConfigFile, () => host.getNewLine());
|
||||
Debug.assert(!rootFileNames);
|
||||
parseConfigFile();
|
||||
newLine = updateNewLine();
|
||||
}
|
||||
|
||||
const { watchFile, watchFilePath, watchDirectory, writeLog } = createWatchFactory<string>(host, compilerOptions);
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
|
||||
writeLog(`Current directory: ${currentDirectory} CaseSensitiveFileNames: ${useCaseSensitiveFileNames}`);
|
||||
let configFileWatcher: FileWatcher | undefined;
|
||||
if (configFileName) {
|
||||
configFileWatcher = watchFile(host, configFileName, scheduleProgramReload, PollingInterval.High, WatchType.ConfigFile);
|
||||
}
|
||||
|
||||
const compilerHost = createCompilerHostFromProgramHost(host, () => compilerOptions, directoryStructureHost) as CompilerHost & ResolutionCacheHost;
|
||||
setGetSourceFileAsHashVersioned(compilerHost, host);
|
||||
// Members for CompilerHost
|
||||
const getNewSourceFile = compilerHost.getSourceFile;
|
||||
compilerHost.getSourceFile = (fileName, ...args) => getVersionedSourceFileByPath(fileName, toPath(fileName), ...args);
|
||||
compilerHost.getSourceFileByPath = getVersionedSourceFileByPath;
|
||||
compilerHost.getNewLine = () => newLine;
|
||||
compilerHost.fileExists = fileExists;
|
||||
compilerHost.onReleaseOldSourceFile = onReleaseOldSourceFile;
|
||||
// Members for ResolutionCacheHost
|
||||
compilerHost.toPath = toPath;
|
||||
compilerHost.getCompilationSettings = () => compilerOptions;
|
||||
compilerHost.watchDirectoryOfFailedLookupLocation = (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.FailedLookupLocations);
|
||||
compilerHost.watchTypeRootsDirectory = (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.TypeRoots);
|
||||
compilerHost.getCachedDirectoryStructureHost = () => cachedDirectoryStructureHost;
|
||||
compilerHost.onInvalidatedResolution = scheduleProgramUpdate;
|
||||
compilerHost.onChangedAutomaticTypeDirectiveNames = () => {
|
||||
hasChangedAutomaticTypeDirectiveNames = true;
|
||||
scheduleProgramUpdate();
|
||||
};
|
||||
compilerHost.fileIsOpen = returnFalse;
|
||||
compilerHost.maxNumberOfFilesToIterateForInvalidation = host.maxNumberOfFilesToIterateForInvalidation;
|
||||
compilerHost.getCurrentProgram = getCurrentProgram;
|
||||
compilerHost.writeLog = writeLog;
|
||||
|
||||
// Cache for the module resolution
|
||||
const resolutionCache = createResolutionCache(compilerHost,
|
||||
configFileName ?
|
||||
getDirectoryPath(getNormalizedAbsolutePath(configFileName, currentDirectory)) :
|
||||
currentDirectory,
|
||||
/*logChangesWhenResolvingModule*/ false
|
||||
);
|
||||
// Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names
|
||||
compilerHost.resolveModuleNames = host.resolveModuleNames ?
|
||||
((...args) => host.resolveModuleNames!(...args)) :
|
||||
((moduleNames, containingFile, reusedNames, redirectedReference) => resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference));
|
||||
compilerHost.resolveTypeReferenceDirectives = host.resolveTypeReferenceDirectives ?
|
||||
((...args) => host.resolveTypeReferenceDirectives!(...args)) :
|
||||
((typeDirectiveNames, containingFile, redirectedReference) => resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile, redirectedReference));
|
||||
const userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives;
|
||||
|
||||
builderProgram = readBuilderProgram(compilerOptions, compilerHost) as any as T;
|
||||
synchronizeProgram();
|
||||
|
||||
// Update the wild card directory watch
|
||||
watchConfigFileWildCardDirectories();
|
||||
|
||||
return configFileName ?
|
||||
{ getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram, close } :
|
||||
{ getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram, updateRootFileNames, close };
|
||||
|
||||
function close() {
|
||||
resolutionCache.clear();
|
||||
clearMap(sourceFilesCache, value => {
|
||||
if (value && value.fileWatcher) {
|
||||
value.fileWatcher.close();
|
||||
value.fileWatcher = undefined;
|
||||
}
|
||||
});
|
||||
if (configFileWatcher) {
|
||||
configFileWatcher.close();
|
||||
configFileWatcher = undefined;
|
||||
}
|
||||
if (watchedWildcardDirectories) {
|
||||
clearMap(watchedWildcardDirectories, closeFileWatcherOf);
|
||||
watchedWildcardDirectories = undefined!;
|
||||
}
|
||||
if (missingFilesMap) {
|
||||
clearMap(missingFilesMap, closeFileWatcher);
|
||||
missingFilesMap = undefined!;
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentBuilderProgram() {
|
||||
return builderProgram;
|
||||
}
|
||||
|
||||
function getCurrentProgram() {
|
||||
return builderProgram && builderProgram.getProgramOrUndefined();
|
||||
}
|
||||
|
||||
function synchronizeProgram() {
|
||||
writeLog(`Synchronizing program`);
|
||||
|
||||
const program = getCurrentBuilderProgram();
|
||||
if (hasChangedCompilerOptions) {
|
||||
newLine = updateNewLine();
|
||||
if (program && changesAffectModuleResolution(program.getCompilerOptions(), compilerOptions)) {
|
||||
resolutionCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// All resolutions are invalid if user provided resolutions
|
||||
const hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution);
|
||||
if (isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, projectReferences)) {
|
||||
if (hasChangedConfigFileParsingErrors) {
|
||||
builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences);
|
||||
hasChangedConfigFileParsingErrors = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
createNewProgram(hasInvalidatedResolution);
|
||||
}
|
||||
|
||||
if (host.afterProgramCreate) {
|
||||
host.afterProgramCreate(builderProgram);
|
||||
}
|
||||
|
||||
return builderProgram;
|
||||
}
|
||||
|
||||
function createNewProgram(hasInvalidatedResolution: HasInvalidatedResolution) {
|
||||
// Compile the program
|
||||
writeLog("CreatingProgramWith::");
|
||||
writeLog(` roots: ${JSON.stringify(rootFileNames)}`);
|
||||
writeLog(` options: ${JSON.stringify(compilerOptions)}`);
|
||||
|
||||
const needsUpdateInTypeRootWatch = hasChangedCompilerOptions || !getCurrentProgram();
|
||||
hasChangedCompilerOptions = false;
|
||||
hasChangedConfigFileParsingErrors = false;
|
||||
resolutionCache.startCachingPerDirectoryResolution();
|
||||
compilerHost.hasInvalidatedResolution = hasInvalidatedResolution;
|
||||
compilerHost.hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames;
|
||||
builderProgram = createProgram(rootFileNames, compilerOptions, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences);
|
||||
resolutionCache.finishCachingPerDirectoryResolution();
|
||||
|
||||
// Update watches
|
||||
updateMissingFilePathsWatch(builderProgram.getProgram(), missingFilesMap || (missingFilesMap = createMap()), watchMissingFilePath);
|
||||
if (needsUpdateInTypeRootWatch) {
|
||||
resolutionCache.updateTypeRootsWatch();
|
||||
}
|
||||
|
||||
if (missingFilePathsRequestedForRelease) {
|
||||
// These are the paths that program creater told us as not in use any more but were missing on the disk.
|
||||
// We didnt remove the entry for them from sourceFiles cache so that we dont have to do File IO,
|
||||
// if there is already watcher for it (for missing files)
|
||||
// At this point our watches were updated, hence now we know that these paths are not tracked and need to be removed
|
||||
// so that at later time we have correct result of their presence
|
||||
for (const missingFilePath of missingFilePathsRequestedForRelease) {
|
||||
if (!missingFilesMap.has(missingFilePath)) {
|
||||
sourceFilesCache.delete(missingFilePath);
|
||||
}
|
||||
}
|
||||
missingFilePathsRequestedForRelease = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function updateRootFileNames(files: string[]) {
|
||||
Debug.assert(!configFileName, "Cannot update root file names with config file watch mode");
|
||||
rootFileNames = files;
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
|
||||
function updateNewLine() {
|
||||
return getNewLineCharacter(compilerOptions || optionsToExtendForConfigFile, () => host.getNewLine());
|
||||
}
|
||||
|
||||
function toPath(fileName: string) {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
function isFileMissingOnHost(hostSourceFile: HostFileInfo | undefined): hostSourceFile is FileMissingOnHost {
|
||||
return typeof hostSourceFile === "boolean";
|
||||
}
|
||||
|
||||
function isFilePresenceUnknownOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresenceUnknownOnHost {
|
||||
return typeof (hostSourceFile as FilePresenceUnknownOnHost).version === "boolean";
|
||||
}
|
||||
|
||||
function fileExists(fileName: string) {
|
||||
const path = toPath(fileName);
|
||||
// If file is missing on host from cache, we can definitely say file doesnt exist
|
||||
// otherwise we need to ensure from the disk
|
||||
if (isFileMissingOnHost(sourceFilesCache.get(path))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return directoryStructureHost.fileExists(fileName);
|
||||
}
|
||||
|
||||
function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
// No source file on the host
|
||||
if (isFileMissingOnHost(hostSourceFile)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Create new source file if requested or the versions dont match
|
||||
if (hostSourceFile === undefined || shouldCreateNewSourceFile || isFilePresenceUnknownOnHost(hostSourceFile)) {
|
||||
const sourceFile = getNewSourceFile(fileName, languageVersion, onError);
|
||||
if (hostSourceFile) {
|
||||
if (sourceFile) {
|
||||
// Set the source file and create file watcher now that file was present on the disk
|
||||
(hostSourceFile as FilePresentOnHost).sourceFile = sourceFile;
|
||||
hostSourceFile.version = sourceFile.version;
|
||||
if (!hostSourceFile.fileWatcher) {
|
||||
hostSourceFile.fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// There is no source file on host any more, close the watch, missing file paths will track it
|
||||
if (hostSourceFile.fileWatcher) {
|
||||
hostSourceFile.fileWatcher.close();
|
||||
}
|
||||
sourceFilesCache.set(path, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sourceFile) {
|
||||
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
|
||||
sourceFilesCache.set(path, { sourceFile, version: sourceFile.version, fileWatcher });
|
||||
}
|
||||
else {
|
||||
sourceFilesCache.set(path, false);
|
||||
}
|
||||
}
|
||||
return sourceFile;
|
||||
}
|
||||
return hostSourceFile.sourceFile;
|
||||
}
|
||||
|
||||
function nextSourceFileVersion(path: Path) {
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
if (hostSourceFile !== undefined) {
|
||||
if (isFileMissingOnHost(hostSourceFile)) {
|
||||
// The next version, lets set it as presence unknown file
|
||||
sourceFilesCache.set(path, { version: false });
|
||||
}
|
||||
else {
|
||||
(hostSourceFile as FilePresenceUnknownOnHost).version = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceVersion(path: Path): string | undefined {
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
return !hostSourceFile || !hostSourceFile.version ? undefined : hostSourceFile.version;
|
||||
}
|
||||
|
||||
function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions, hasSourceFileByPath: boolean) {
|
||||
const hostSourceFileInfo = sourceFilesCache.get(oldSourceFile.resolvedPath);
|
||||
// If this is the source file thats in the cache and new program doesnt need it,
|
||||
// remove the cached entry.
|
||||
// Note we arent deleting entry if file became missing in new program or
|
||||
// there was version update and new source file was created.
|
||||
if (hostSourceFileInfo !== undefined) {
|
||||
// record the missing file paths so they can be removed later if watchers arent tracking them
|
||||
if (isFileMissingOnHost(hostSourceFileInfo)) {
|
||||
(missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push(oldSourceFile.path);
|
||||
}
|
||||
else if ((hostSourceFileInfo as FilePresentOnHost).sourceFile === oldSourceFile) {
|
||||
if (hostSourceFileInfo.fileWatcher) {
|
||||
hostSourceFileInfo.fileWatcher.close();
|
||||
}
|
||||
sourceFilesCache.delete(oldSourceFile.resolvedPath);
|
||||
if (!hasSourceFileByPath) {
|
||||
resolutionCache.removeResolutionsOfFile(oldSourceFile.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function reportWatchDiagnostic(message: DiagnosticMessage) {
|
||||
if (host.onWatchStatusChange) {
|
||||
host.onWatchStatusChange(createCompilerDiagnostic(message), newLine, compilerOptions || optionsToExtendForConfigFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch
|
||||
// operations (such as saving all modified files in an editor) a chance to complete before we kick
|
||||
// off a new compilation.
|
||||
function scheduleProgramUpdate() {
|
||||
if (!host.setTimeout || !host.clearTimeout) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (timerToUpdateProgram) {
|
||||
host.clearTimeout(timerToUpdateProgram);
|
||||
}
|
||||
writeLog("Scheduling update");
|
||||
timerToUpdateProgram = host.setTimeout(updateProgram, 250);
|
||||
}
|
||||
|
||||
function scheduleProgramReload() {
|
||||
Debug.assert(!!configFileName);
|
||||
reloadLevel = ConfigFileProgramReloadLevel.Full;
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
|
||||
function updateProgram() {
|
||||
timerToUpdateProgram = undefined;
|
||||
reportWatchDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation);
|
||||
|
||||
switch (reloadLevel) {
|
||||
case ConfigFileProgramReloadLevel.Partial:
|
||||
perfLogger.logStartUpdateProgram("PartialConfigReload");
|
||||
reloadFileNamesFromConfigFile();
|
||||
break;
|
||||
case ConfigFileProgramReloadLevel.Full:
|
||||
perfLogger.logStartUpdateProgram("FullConfigReload");
|
||||
reloadConfigFile();
|
||||
break;
|
||||
default:
|
||||
perfLogger.logStartUpdateProgram("SynchronizeProgram");
|
||||
synchronizeProgram();
|
||||
break;
|
||||
}
|
||||
perfLogger.logStopUpdateProgram("Done");
|
||||
}
|
||||
|
||||
function reloadFileNamesFromConfigFile() {
|
||||
writeLog("Reloading new file names and options");
|
||||
const result = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), compilerOptions, parseConfigFileHost);
|
||||
if (updateErrorForNoInputFiles(result, configFileName, configFileSpecs, configFileParsingDiagnostics!, canConfigFileJsonReportNoInputFiles)) {
|
||||
hasChangedConfigFileParsingErrors = true;
|
||||
}
|
||||
rootFileNames = result.fileNames;
|
||||
|
||||
// Update the program
|
||||
synchronizeProgram();
|
||||
}
|
||||
|
||||
function reloadConfigFile() {
|
||||
writeLog(`Reloading config file: ${configFileName}`);
|
||||
reloadLevel = ConfigFileProgramReloadLevel.None;
|
||||
|
||||
if (cachedDirectoryStructureHost) {
|
||||
cachedDirectoryStructureHost.clearCache();
|
||||
}
|
||||
parseConfigFile();
|
||||
hasChangedCompilerOptions = true;
|
||||
synchronizeProgram();
|
||||
|
||||
// Update the wild card directory watch
|
||||
watchConfigFileWildCardDirectories();
|
||||
}
|
||||
|
||||
function parseConfigFile() {
|
||||
setConfigFileParsingResult(getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost)!); // TODO: GH#18217
|
||||
}
|
||||
|
||||
function setConfigFileParsingResult(configFileParseResult: ParsedCommandLine) {
|
||||
rootFileNames = configFileParseResult.fileNames;
|
||||
compilerOptions = configFileParseResult.options;
|
||||
configFileSpecs = configFileParseResult.configFileSpecs!; // TODO: GH#18217
|
||||
projectReferences = configFileParseResult.projectReferences;
|
||||
configFileParsingDiagnostics = getConfigFileParsingDiagnostics(configFileParseResult).slice();
|
||||
canConfigFileJsonReportNoInputFiles = canJsonReportNoInutFiles(configFileParseResult.raw);
|
||||
hasChangedConfigFileParsingErrors = true;
|
||||
}
|
||||
|
||||
function onSourceFileChange(fileName: string, eventKind: FileWatcherEventKind, path: Path) {
|
||||
updateCachedSystemWithFile(fileName, path, eventKind);
|
||||
|
||||
// Update the source file cache
|
||||
if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.has(path)) {
|
||||
resolutionCache.invalidateResolutionOfFile(path);
|
||||
}
|
||||
resolutionCache.removeResolutionsFromProjectReferenceRedirects(path);
|
||||
nextSourceFileVersion(path);
|
||||
|
||||
// Update the program
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
|
||||
function updateCachedSystemWithFile(fileName: string, path: Path, eventKind: FileWatcherEventKind) {
|
||||
if (cachedDirectoryStructureHost) {
|
||||
cachedDirectoryStructureHost.addOrDeleteFile(fileName, path, eventKind);
|
||||
}
|
||||
}
|
||||
|
||||
function watchMissingFilePath(missingFilePath: Path) {
|
||||
return watchFilePath(host, missingFilePath, onMissingFileChange, PollingInterval.Medium, missingFilePath, WatchType.MissingFile);
|
||||
}
|
||||
|
||||
function onMissingFileChange(fileName: string, eventKind: FileWatcherEventKind, missingFilePath: Path) {
|
||||
updateCachedSystemWithFile(fileName, missingFilePath, eventKind);
|
||||
|
||||
if (eventKind === FileWatcherEventKind.Created && missingFilesMap.has(missingFilePath)) {
|
||||
missingFilesMap.get(missingFilePath)!.close();
|
||||
missingFilesMap.delete(missingFilePath);
|
||||
|
||||
// Delete the entry in the source files cache so that new source file is created
|
||||
nextSourceFileVersion(missingFilePath);
|
||||
|
||||
// When a missing file is created, we should update the graph.
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
function watchConfigFileWildCardDirectories() {
|
||||
if (configFileSpecs) {
|
||||
updateWatchingWildcardDirectories(
|
||||
watchedWildcardDirectories || (watchedWildcardDirectories = createMap()),
|
||||
createMapFromTemplate(configFileSpecs.wildcardDirectories),
|
||||
watchWildcardDirectory
|
||||
);
|
||||
}
|
||||
else if (watchedWildcardDirectories) {
|
||||
clearMap(watchedWildcardDirectories, closeFileWatcherOf);
|
||||
}
|
||||
}
|
||||
|
||||
function watchWildcardDirectory(directory: string, flags: WatchDirectoryFlags) {
|
||||
return watchDirectory(
|
||||
host,
|
||||
directory,
|
||||
fileOrDirectory => {
|
||||
Debug.assert(!!configFileName);
|
||||
|
||||
const fileOrDirectoryPath = toPath(fileOrDirectory);
|
||||
|
||||
// Since the file existance changed, update the sourceFiles cache
|
||||
if (cachedDirectoryStructureHost) {
|
||||
cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
|
||||
}
|
||||
nextSourceFileVersion(fileOrDirectoryPath);
|
||||
|
||||
if (isPathIgnored(fileOrDirectoryPath)) return;
|
||||
|
||||
// If the the added or created file or directory is not supported file name, ignore the file
|
||||
// But when watched directory is added/removed, we need to reload the file list
|
||||
if (fileOrDirectoryPath !== directory && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, compilerOptions)) {
|
||||
writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reload is pending, do the reload
|
||||
if (reloadLevel !== ConfigFileProgramReloadLevel.Full) {
|
||||
reloadLevel = ConfigFileProgramReloadLevel.Partial;
|
||||
|
||||
// Schedule Update the program
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
},
|
||||
flags,
|
||||
WatchType.WildcardDirectory
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
716
src/compiler/watchPublic.ts
Normal file
716
src/compiler/watchPublic.ts
Normal file
|
@ -0,0 +1,716 @@
|
|||
namespace ts {
|
||||
export interface ReadBuildProgramHost {
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getCurrentDirectory(): string;
|
||||
readFile(fileName: string): string | undefined;
|
||||
}
|
||||
export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost) {
|
||||
if (compilerOptions.out || compilerOptions.outFile) return undefined;
|
||||
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(compilerOptions);
|
||||
if (!buildInfoPath) return undefined;
|
||||
const content = host.readFile(buildInfoPath);
|
||||
if (!content) return undefined;
|
||||
const buildInfo = getBuildInfo(content);
|
||||
if (buildInfo.version !== version) return undefined;
|
||||
if (!buildInfo.program) return undefined;
|
||||
return createBuildProgramUsingProgramBuildInfo(buildInfo.program, buildInfoPath, host);
|
||||
}
|
||||
|
||||
export function createIncrementalCompilerHost(options: CompilerOptions, system = sys): CompilerHost {
|
||||
const host = createCompilerHostWorker(options, /*setParentNodes*/ undefined, system);
|
||||
host.createHash = maybeBind(system, system.createHash);
|
||||
setGetSourceFileAsHashVersioned(host, system);
|
||||
changeCompilerHostLikeToUseCache(host, fileName => toPath(fileName, host.getCurrentDirectory(), host.getCanonicalFileName));
|
||||
return host;
|
||||
}
|
||||
|
||||
export interface IncrementalProgramOptions<T extends BuilderProgram> {
|
||||
rootNames: readonly string[];
|
||||
options: CompilerOptions;
|
||||
configFileParsingDiagnostics?: readonly Diagnostic[];
|
||||
projectReferences?: readonly ProjectReference[];
|
||||
host?: CompilerHost;
|
||||
createProgram?: CreateProgram<T>;
|
||||
}
|
||||
|
||||
export function createIncrementalProgram<T extends BuilderProgram = EmitAndSemanticDiagnosticsBuilderProgram>({
|
||||
rootNames, options, configFileParsingDiagnostics, projectReferences, host, createProgram
|
||||
}: IncrementalProgramOptions<T>): T {
|
||||
host = host || createIncrementalCompilerHost(options);
|
||||
createProgram = createProgram || createEmitAndSemanticDiagnosticsBuilderProgram as any as CreateProgram<T>;
|
||||
const oldProgram = readBuilderProgram(options, host) as any as T;
|
||||
return createProgram(rootNames, options, host, oldProgram, configFileParsingDiagnostics, projectReferences);
|
||||
}
|
||||
|
||||
export type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions, errorCount?: number) => void;
|
||||
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
|
||||
export type CreateProgram<T extends BuilderProgram> = (rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[] | undefined) => T;
|
||||
|
||||
/** Host that has watch functionality used in --watch mode */
|
||||
export interface WatchHost {
|
||||
/** If provided, called with Diagnostic message that informs about change in watch status */
|
||||
onWatchStatusChange?(diagnostic: Diagnostic, newLine: string, options: CompilerOptions, errorCount?: number): void;
|
||||
|
||||
/** Used to watch changes in source files, missing files needed to update the program or config file */
|
||||
watchFile(path: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher;
|
||||
/** Used to watch resolved module's failed lookup locations, config file specs, type roots where auto type reference directives are added */
|
||||
watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
|
||||
/** If provided, will be used to set delayed compilation, so that multiple changes in short span are compiled together */
|
||||
setTimeout?(callback: (...args: any[]) => void, ms: number, ...args: any[]): any;
|
||||
/** If provided, will be used to reset existing delayed compilation */
|
||||
clearTimeout?(timeoutId: any): void;
|
||||
}
|
||||
export interface ProgramHost<T extends BuilderProgram> {
|
||||
/**
|
||||
* Used to create the program when need for program creation or recreation detected
|
||||
*/
|
||||
createProgram: CreateProgram<T>;
|
||||
|
||||
// Sub set of compiler host methods to read and generate new program
|
||||
useCaseSensitiveFileNames(): boolean;
|
||||
getNewLine(): string;
|
||||
getCurrentDirectory(): string;
|
||||
getDefaultLibFileName(options: CompilerOptions): string;
|
||||
getDefaultLibLocation?(): string;
|
||||
createHash?(data: string): string;
|
||||
|
||||
/**
|
||||
* Use to check file presence for source files and
|
||||
* if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well
|
||||
*/
|
||||
fileExists(path: string): boolean;
|
||||
/**
|
||||
* Use to read file text for source files and
|
||||
* if resolveModuleNames is not provided (complier is in charge of module resolution) then module files as well
|
||||
*/
|
||||
readFile(path: string, encoding?: string): string | undefined;
|
||||
|
||||
/** If provided, used for module resolution as well as to handle directory structure */
|
||||
directoryExists?(path: string): boolean;
|
||||
/** If provided, used in resolutions as well as handling directory structure */
|
||||
getDirectories?(path: string): string[];
|
||||
/** If provided, used to cache and handle directory structure modifications */
|
||||
readDirectory?(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[];
|
||||
|
||||
/** Symbol links resolution */
|
||||
realpath?(path: string): string;
|
||||
/** If provided would be used to write log about compilation */
|
||||
trace?(s: string): void;
|
||||
/** If provided is used to get the environment variable */
|
||||
getEnvironmentVariable?(name: string): string | undefined;
|
||||
|
||||
/** If provided, used to resolve the module names, otherwise typescript's default module resolution */
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedModule | undefined)[];
|
||||
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
}
|
||||
/** Internal interface used to wire emit through same host */
|
||||
|
||||
/*@internal*/
|
||||
export interface ProgramHost<T extends BuilderProgram> {
|
||||
// TODO: GH#18217 Optional methods are frequently asserted
|
||||
createDirectory?(path: string): void;
|
||||
writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void;
|
||||
onCachedDirectoryStructureHostCreate?(host: CachedDirectoryStructureHost): void;
|
||||
}
|
||||
|
||||
export interface WatchCompilerHost<T extends BuilderProgram> extends ProgramHost<T>, WatchHost {
|
||||
/** If provided, callback to invoke after every new program creation */
|
||||
afterProgramCreate?(program: T): void;
|
||||
|
||||
// Only for testing
|
||||
/*@internal*/
|
||||
maxNumberOfFilesToIterateForInvalidation?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Host to create watch with root files and options
|
||||
*/
|
||||
export interface WatchCompilerHostOfFilesAndCompilerOptions<T extends BuilderProgram> extends WatchCompilerHost<T> {
|
||||
/** root files to use to generate program */
|
||||
rootFiles: string[];
|
||||
|
||||
/** Compiler options */
|
||||
options: CompilerOptions;
|
||||
|
||||
/** Project References */
|
||||
projectReferences?: readonly ProjectReference[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Host to create watch with config file
|
||||
*/
|
||||
export interface WatchCompilerHostOfConfigFile<T extends BuilderProgram> extends WatchCompilerHost<T>, ConfigFileDiagnosticsReporter {
|
||||
/** Name of the config file to compile */
|
||||
configFileName: string;
|
||||
|
||||
/** Options to extend */
|
||||
optionsToExtend?: CompilerOptions;
|
||||
|
||||
/**
|
||||
* Used to generate source file names from the config file and its include, exclude, files rules
|
||||
* and also to cache the directory stucture
|
||||
*/
|
||||
readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Host to create watch with config file that is already parsed (from tsc)
|
||||
*/
|
||||
/*@internal*/
|
||||
export interface WatchCompilerHostOfConfigFile<T extends BuilderProgram> extends WatchCompilerHost<T> {
|
||||
optionsToExtend?: CompilerOptions;
|
||||
configFileParsingResult?: ParsedCommandLine;
|
||||
}
|
||||
|
||||
export interface Watch<T> {
|
||||
/** Synchronize with host and get updated program */
|
||||
getProgram(): T;
|
||||
/** Gets the existing program without synchronizing with changes on host */
|
||||
/*@internal*/
|
||||
getCurrentProgram(): T;
|
||||
/** Closes the watch */
|
||||
close(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the watch what generates program using the config file
|
||||
*/
|
||||
export interface WatchOfConfigFile<T> extends Watch<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the watch that generates program using the root files and compiler options
|
||||
*/
|
||||
export interface WatchOfFilesAndCompilerOptions<T> extends Watch<T> {
|
||||
/** Updates the root files in the program, only if this is not config file compilation */
|
||||
updateRootFileNames(fileNames: string[]): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the watch compiler host for either configFile or fileNames and its options
|
||||
*/
|
||||
export function createWatchCompilerHost<T extends BuilderProgram>(configFileName: string, optionsToExtend: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter): WatchCompilerHostOfConfigFile<T>;
|
||||
export function createWatchCompilerHost<T extends BuilderProgram>(rootFiles: string[], options: CompilerOptions, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: readonly ProjectReference[]): WatchCompilerHostOfFilesAndCompilerOptions<T>;
|
||||
export function createWatchCompilerHost<T extends BuilderProgram>(rootFilesOrConfigFileName: string | string[], options: CompilerOptions | undefined, system: System, createProgram?: CreateProgram<T>, reportDiagnostic?: DiagnosticReporter, reportWatchStatus?: WatchStatusReporter, projectReferences?: readonly ProjectReference[]): WatchCompilerHostOfFilesAndCompilerOptions<T> | WatchCompilerHostOfConfigFile<T> {
|
||||
if (isArray(rootFilesOrConfigFileName)) {
|
||||
return createWatchCompilerHostOfFilesAndCompilerOptions(rootFilesOrConfigFileName, options!, system, createProgram, reportDiagnostic, reportWatchStatus, projectReferences); // TODO: GH#18217
|
||||
}
|
||||
else {
|
||||
return createWatchCompilerHostOfConfigFile(rootFilesOrConfigFileName, options, system, createProgram, reportDiagnostic, reportWatchStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the watch from the host for root files and compiler options
|
||||
*/
|
||||
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfFilesAndCompilerOptions<T>): WatchOfFilesAndCompilerOptions<T>;
|
||||
/**
|
||||
* Creates the watch from the host for config file
|
||||
*/
|
||||
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfConfigFile<T>): WatchOfConfigFile<T>;
|
||||
export function createWatchProgram<T extends BuilderProgram>(host: WatchCompilerHostOfFilesAndCompilerOptions<T> & WatchCompilerHostOfConfigFile<T>): WatchOfFilesAndCompilerOptions<T> | WatchOfConfigFile<T> {
|
||||
interface FilePresentOnHost {
|
||||
version: string;
|
||||
sourceFile: SourceFile;
|
||||
fileWatcher: FileWatcher;
|
||||
}
|
||||
type FileMissingOnHost = false;
|
||||
interface FilePresenceUnknownOnHost {
|
||||
version: false;
|
||||
fileWatcher?: FileWatcher;
|
||||
}
|
||||
type FileMayBePresentOnHost = FilePresentOnHost | FilePresenceUnknownOnHost;
|
||||
type HostFileInfo = FilePresentOnHost | FileMissingOnHost | FilePresenceUnknownOnHost;
|
||||
|
||||
let builderProgram: T;
|
||||
let reloadLevel: ConfigFileProgramReloadLevel; // level to indicate if the program needs to be reloaded from config file/just filenames etc
|
||||
let missingFilesMap: Map<FileWatcher>; // Map of file watchers for the missing files
|
||||
let watchedWildcardDirectories: Map<WildcardDirectoryWatcher>; // map of watchers for the wild card directories in the config file
|
||||
let timerToUpdateProgram: any; // timer callback to recompile the program
|
||||
|
||||
const sourceFilesCache = createMap<HostFileInfo>(); // Cache that stores the source file and version info
|
||||
let missingFilePathsRequestedForRelease: Path[] | undefined; // These paths are held temparirly so that we can remove the entry from source file cache if the file is not tracked by missing files
|
||||
let hasChangedCompilerOptions = false; // True if the compiler options have changed between compilations
|
||||
let hasChangedAutomaticTypeDirectiveNames = false; // True if the automatic type directives have changed
|
||||
|
||||
const useCaseSensitiveFileNames = host.useCaseSensitiveFileNames();
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
const { configFileName, optionsToExtend: optionsToExtendForConfigFile = {}, createProgram } = host;
|
||||
let { rootFiles: rootFileNames, options: compilerOptions, projectReferences } = host;
|
||||
let configFileSpecs: ConfigFileSpecs;
|
||||
let configFileParsingDiagnostics: Diagnostic[] | undefined;
|
||||
let canConfigFileJsonReportNoInputFiles = false;
|
||||
let hasChangedConfigFileParsingErrors = false;
|
||||
|
||||
const cachedDirectoryStructureHost = configFileName === undefined ? undefined : createCachedDirectoryStructureHost(host, currentDirectory, useCaseSensitiveFileNames);
|
||||
if (cachedDirectoryStructureHost && host.onCachedDirectoryStructureHostCreate) {
|
||||
host.onCachedDirectoryStructureHostCreate(cachedDirectoryStructureHost);
|
||||
}
|
||||
const directoryStructureHost: DirectoryStructureHost = cachedDirectoryStructureHost || host;
|
||||
const parseConfigFileHost = parseConfigHostFromCompilerHostLike(host, directoryStructureHost);
|
||||
|
||||
// From tsc we want to get already parsed result and hence check for rootFileNames
|
||||
let newLine = updateNewLine();
|
||||
if (configFileName && host.configFileParsingResult) {
|
||||
setConfigFileParsingResult(host.configFileParsingResult);
|
||||
newLine = updateNewLine();
|
||||
}
|
||||
reportWatchDiagnostic(Diagnostics.Starting_compilation_in_watch_mode);
|
||||
if (configFileName && !host.configFileParsingResult) {
|
||||
newLine = getNewLineCharacter(optionsToExtendForConfigFile, () => host.getNewLine());
|
||||
Debug.assert(!rootFileNames);
|
||||
parseConfigFile();
|
||||
newLine = updateNewLine();
|
||||
}
|
||||
|
||||
const { watchFile, watchFilePath, watchDirectory, writeLog } = createWatchFactory<string>(host, compilerOptions);
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
|
||||
writeLog(`Current directory: ${currentDirectory} CaseSensitiveFileNames: ${useCaseSensitiveFileNames}`);
|
||||
let configFileWatcher: FileWatcher | undefined;
|
||||
if (configFileName) {
|
||||
configFileWatcher = watchFile(host, configFileName, scheduleProgramReload, PollingInterval.High, WatchType.ConfigFile);
|
||||
}
|
||||
|
||||
const compilerHost = createCompilerHostFromProgramHost(host, () => compilerOptions, directoryStructureHost) as CompilerHost & ResolutionCacheHost;
|
||||
setGetSourceFileAsHashVersioned(compilerHost, host);
|
||||
// Members for CompilerHost
|
||||
const getNewSourceFile = compilerHost.getSourceFile;
|
||||
compilerHost.getSourceFile = (fileName, ...args) => getVersionedSourceFileByPath(fileName, toPath(fileName), ...args);
|
||||
compilerHost.getSourceFileByPath = getVersionedSourceFileByPath;
|
||||
compilerHost.getNewLine = () => newLine;
|
||||
compilerHost.fileExists = fileExists;
|
||||
compilerHost.onReleaseOldSourceFile = onReleaseOldSourceFile;
|
||||
// Members for ResolutionCacheHost
|
||||
compilerHost.toPath = toPath;
|
||||
compilerHost.getCompilationSettings = () => compilerOptions;
|
||||
compilerHost.watchDirectoryOfFailedLookupLocation = (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.FailedLookupLocations);
|
||||
compilerHost.watchTypeRootsDirectory = (dir, cb, flags) => watchDirectory(host, dir, cb, flags, WatchType.TypeRoots);
|
||||
compilerHost.getCachedDirectoryStructureHost = () => cachedDirectoryStructureHost;
|
||||
compilerHost.onInvalidatedResolution = scheduleProgramUpdate;
|
||||
compilerHost.onChangedAutomaticTypeDirectiveNames = () => {
|
||||
hasChangedAutomaticTypeDirectiveNames = true;
|
||||
scheduleProgramUpdate();
|
||||
};
|
||||
compilerHost.fileIsOpen = returnFalse;
|
||||
compilerHost.maxNumberOfFilesToIterateForInvalidation = host.maxNumberOfFilesToIterateForInvalidation;
|
||||
compilerHost.getCurrentProgram = getCurrentProgram;
|
||||
compilerHost.writeLog = writeLog;
|
||||
|
||||
// Cache for the module resolution
|
||||
const resolutionCache = createResolutionCache(compilerHost,
|
||||
configFileName ?
|
||||
getDirectoryPath(getNormalizedAbsolutePath(configFileName, currentDirectory)) :
|
||||
currentDirectory,
|
||||
/*logChangesWhenResolvingModule*/ false
|
||||
);
|
||||
// Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names
|
||||
compilerHost.resolveModuleNames = host.resolveModuleNames ?
|
||||
((...args) => host.resolveModuleNames!(...args)) :
|
||||
((moduleNames, containingFile, reusedNames, redirectedReference) => resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference));
|
||||
compilerHost.resolveTypeReferenceDirectives = host.resolveTypeReferenceDirectives ?
|
||||
((...args) => host.resolveTypeReferenceDirectives!(...args)) :
|
||||
((typeDirectiveNames, containingFile, redirectedReference) => resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile, redirectedReference));
|
||||
const userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives;
|
||||
|
||||
builderProgram = readBuilderProgram(compilerOptions, compilerHost) as any as T;
|
||||
synchronizeProgram();
|
||||
|
||||
// Update the wild card directory watch
|
||||
watchConfigFileWildCardDirectories();
|
||||
|
||||
return configFileName ?
|
||||
{ getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram, close } :
|
||||
{ getCurrentProgram: getCurrentBuilderProgram, getProgram: synchronizeProgram, updateRootFileNames, close };
|
||||
|
||||
function close() {
|
||||
resolutionCache.clear();
|
||||
clearMap(sourceFilesCache, value => {
|
||||
if (value && value.fileWatcher) {
|
||||
value.fileWatcher.close();
|
||||
value.fileWatcher = undefined;
|
||||
}
|
||||
});
|
||||
if (configFileWatcher) {
|
||||
configFileWatcher.close();
|
||||
configFileWatcher = undefined;
|
||||
}
|
||||
if (watchedWildcardDirectories) {
|
||||
clearMap(watchedWildcardDirectories, closeFileWatcherOf);
|
||||
watchedWildcardDirectories = undefined!;
|
||||
}
|
||||
if (missingFilesMap) {
|
||||
clearMap(missingFilesMap, closeFileWatcher);
|
||||
missingFilesMap = undefined!;
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentBuilderProgram() {
|
||||
return builderProgram;
|
||||
}
|
||||
|
||||
function getCurrentProgram() {
|
||||
return builderProgram && builderProgram.getProgramOrUndefined();
|
||||
}
|
||||
|
||||
function synchronizeProgram() {
|
||||
writeLog(`Synchronizing program`);
|
||||
|
||||
const program = getCurrentBuilderProgram();
|
||||
if (hasChangedCompilerOptions) {
|
||||
newLine = updateNewLine();
|
||||
if (program && changesAffectModuleResolution(program.getCompilerOptions(), compilerOptions)) {
|
||||
resolutionCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// All resolutions are invalid if user provided resolutions
|
||||
const hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution);
|
||||
if (isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, projectReferences)) {
|
||||
if (hasChangedConfigFileParsingErrors) {
|
||||
builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences);
|
||||
hasChangedConfigFileParsingErrors = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
createNewProgram(hasInvalidatedResolution);
|
||||
}
|
||||
|
||||
if (host.afterProgramCreate) {
|
||||
host.afterProgramCreate(builderProgram);
|
||||
}
|
||||
|
||||
return builderProgram;
|
||||
}
|
||||
|
||||
function createNewProgram(hasInvalidatedResolution: HasInvalidatedResolution) {
|
||||
// Compile the program
|
||||
writeLog("CreatingProgramWith::");
|
||||
writeLog(` roots: ${JSON.stringify(rootFileNames)}`);
|
||||
writeLog(` options: ${JSON.stringify(compilerOptions)}`);
|
||||
|
||||
const needsUpdateInTypeRootWatch = hasChangedCompilerOptions || !getCurrentProgram();
|
||||
hasChangedCompilerOptions = false;
|
||||
hasChangedConfigFileParsingErrors = false;
|
||||
resolutionCache.startCachingPerDirectoryResolution();
|
||||
compilerHost.hasInvalidatedResolution = hasInvalidatedResolution;
|
||||
compilerHost.hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames;
|
||||
builderProgram = createProgram(rootFileNames, compilerOptions, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences);
|
||||
resolutionCache.finishCachingPerDirectoryResolution();
|
||||
|
||||
// Update watches
|
||||
updateMissingFilePathsWatch(builderProgram.getProgram(), missingFilesMap || (missingFilesMap = createMap()), watchMissingFilePath);
|
||||
if (needsUpdateInTypeRootWatch) {
|
||||
resolutionCache.updateTypeRootsWatch();
|
||||
}
|
||||
|
||||
if (missingFilePathsRequestedForRelease) {
|
||||
// These are the paths that program creater told us as not in use any more but were missing on the disk.
|
||||
// We didnt remove the entry for them from sourceFiles cache so that we dont have to do File IO,
|
||||
// if there is already watcher for it (for missing files)
|
||||
// At this point our watches were updated, hence now we know that these paths are not tracked and need to be removed
|
||||
// so that at later time we have correct result of their presence
|
||||
for (const missingFilePath of missingFilePathsRequestedForRelease) {
|
||||
if (!missingFilesMap.has(missingFilePath)) {
|
||||
sourceFilesCache.delete(missingFilePath);
|
||||
}
|
||||
}
|
||||
missingFilePathsRequestedForRelease = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function updateRootFileNames(files: string[]) {
|
||||
Debug.assert(!configFileName, "Cannot update root file names with config file watch mode");
|
||||
rootFileNames = files;
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
|
||||
function updateNewLine() {
|
||||
return getNewLineCharacter(compilerOptions || optionsToExtendForConfigFile, () => host.getNewLine());
|
||||
}
|
||||
|
||||
function toPath(fileName: string) {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
function isFileMissingOnHost(hostSourceFile: HostFileInfo | undefined): hostSourceFile is FileMissingOnHost {
|
||||
return typeof hostSourceFile === "boolean";
|
||||
}
|
||||
|
||||
function isFilePresenceUnknownOnHost(hostSourceFile: FileMayBePresentOnHost): hostSourceFile is FilePresenceUnknownOnHost {
|
||||
return typeof (hostSourceFile as FilePresenceUnknownOnHost).version === "boolean";
|
||||
}
|
||||
|
||||
function fileExists(fileName: string) {
|
||||
const path = toPath(fileName);
|
||||
// If file is missing on host from cache, we can definitely say file doesnt exist
|
||||
// otherwise we need to ensure from the disk
|
||||
if (isFileMissingOnHost(sourceFilesCache.get(path))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return directoryStructureHost.fileExists(fileName);
|
||||
}
|
||||
|
||||
function getVersionedSourceFileByPath(fileName: string, path: Path, languageVersion: ScriptTarget, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined {
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
// No source file on the host
|
||||
if (isFileMissingOnHost(hostSourceFile)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Create new source file if requested or the versions dont match
|
||||
if (hostSourceFile === undefined || shouldCreateNewSourceFile || isFilePresenceUnknownOnHost(hostSourceFile)) {
|
||||
const sourceFile = getNewSourceFile(fileName, languageVersion, onError);
|
||||
if (hostSourceFile) {
|
||||
if (sourceFile) {
|
||||
// Set the source file and create file watcher now that file was present on the disk
|
||||
(hostSourceFile as FilePresentOnHost).sourceFile = sourceFile;
|
||||
hostSourceFile.version = sourceFile.version;
|
||||
if (!hostSourceFile.fileWatcher) {
|
||||
hostSourceFile.fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// There is no source file on host any more, close the watch, missing file paths will track it
|
||||
if (hostSourceFile.fileWatcher) {
|
||||
hostSourceFile.fileWatcher.close();
|
||||
}
|
||||
sourceFilesCache.set(path, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sourceFile) {
|
||||
const fileWatcher = watchFilePath(host, fileName, onSourceFileChange, PollingInterval.Low, path, WatchType.SourceFile);
|
||||
sourceFilesCache.set(path, { sourceFile, version: sourceFile.version, fileWatcher });
|
||||
}
|
||||
else {
|
||||
sourceFilesCache.set(path, false);
|
||||
}
|
||||
}
|
||||
return sourceFile;
|
||||
}
|
||||
return hostSourceFile.sourceFile;
|
||||
}
|
||||
|
||||
function nextSourceFileVersion(path: Path) {
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
if (hostSourceFile !== undefined) {
|
||||
if (isFileMissingOnHost(hostSourceFile)) {
|
||||
// The next version, lets set it as presence unknown file
|
||||
sourceFilesCache.set(path, { version: false });
|
||||
}
|
||||
else {
|
||||
(hostSourceFile as FilePresenceUnknownOnHost).version = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSourceVersion(path: Path): string | undefined {
|
||||
const hostSourceFile = sourceFilesCache.get(path);
|
||||
return !hostSourceFile || !hostSourceFile.version ? undefined : hostSourceFile.version;
|
||||
}
|
||||
|
||||
function onReleaseOldSourceFile(oldSourceFile: SourceFile, _oldOptions: CompilerOptions, hasSourceFileByPath: boolean) {
|
||||
const hostSourceFileInfo = sourceFilesCache.get(oldSourceFile.resolvedPath);
|
||||
// If this is the source file thats in the cache and new program doesnt need it,
|
||||
// remove the cached entry.
|
||||
// Note we arent deleting entry if file became missing in new program or
|
||||
// there was version update and new source file was created.
|
||||
if (hostSourceFileInfo !== undefined) {
|
||||
// record the missing file paths so they can be removed later if watchers arent tracking them
|
||||
if (isFileMissingOnHost(hostSourceFileInfo)) {
|
||||
(missingFilePathsRequestedForRelease || (missingFilePathsRequestedForRelease = [])).push(oldSourceFile.path);
|
||||
}
|
||||
else if ((hostSourceFileInfo as FilePresentOnHost).sourceFile === oldSourceFile) {
|
||||
if (hostSourceFileInfo.fileWatcher) {
|
||||
hostSourceFileInfo.fileWatcher.close();
|
||||
}
|
||||
sourceFilesCache.delete(oldSourceFile.resolvedPath);
|
||||
if (!hasSourceFileByPath) {
|
||||
resolutionCache.removeResolutionsOfFile(oldSourceFile.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function reportWatchDiagnostic(message: DiagnosticMessage) {
|
||||
if (host.onWatchStatusChange) {
|
||||
host.onWatchStatusChange(createCompilerDiagnostic(message), newLine, compilerOptions || optionsToExtendForConfigFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Upon detecting a file change, wait for 250ms and then perform a recompilation. This gives batch
|
||||
// operations (such as saving all modified files in an editor) a chance to complete before we kick
|
||||
// off a new compilation.
|
||||
function scheduleProgramUpdate() {
|
||||
if (!host.setTimeout || !host.clearTimeout) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (timerToUpdateProgram) {
|
||||
host.clearTimeout(timerToUpdateProgram);
|
||||
}
|
||||
writeLog("Scheduling update");
|
||||
timerToUpdateProgram = host.setTimeout(updateProgram, 250);
|
||||
}
|
||||
|
||||
function scheduleProgramReload() {
|
||||
Debug.assert(!!configFileName);
|
||||
reloadLevel = ConfigFileProgramReloadLevel.Full;
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
|
||||
function updateProgram() {
|
||||
timerToUpdateProgram = undefined;
|
||||
reportWatchDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation);
|
||||
|
||||
switch (reloadLevel) {
|
||||
case ConfigFileProgramReloadLevel.Partial:
|
||||
perfLogger.logStartUpdateProgram("PartialConfigReload");
|
||||
reloadFileNamesFromConfigFile();
|
||||
break;
|
||||
case ConfigFileProgramReloadLevel.Full:
|
||||
perfLogger.logStartUpdateProgram("FullConfigReload");
|
||||
reloadConfigFile();
|
||||
break;
|
||||
default:
|
||||
perfLogger.logStartUpdateProgram("SynchronizeProgram");
|
||||
synchronizeProgram();
|
||||
break;
|
||||
}
|
||||
perfLogger.logStopUpdateProgram("Done");
|
||||
}
|
||||
|
||||
function reloadFileNamesFromConfigFile() {
|
||||
writeLog("Reloading new file names and options");
|
||||
const result = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), compilerOptions, parseConfigFileHost);
|
||||
if (updateErrorForNoInputFiles(result, configFileName, configFileSpecs, configFileParsingDiagnostics!, canConfigFileJsonReportNoInputFiles)) {
|
||||
hasChangedConfigFileParsingErrors = true;
|
||||
}
|
||||
rootFileNames = result.fileNames;
|
||||
|
||||
// Update the program
|
||||
synchronizeProgram();
|
||||
}
|
||||
|
||||
function reloadConfigFile() {
|
||||
writeLog(`Reloading config file: ${configFileName}`);
|
||||
reloadLevel = ConfigFileProgramReloadLevel.None;
|
||||
|
||||
if (cachedDirectoryStructureHost) {
|
||||
cachedDirectoryStructureHost.clearCache();
|
||||
}
|
||||
parseConfigFile();
|
||||
hasChangedCompilerOptions = true;
|
||||
synchronizeProgram();
|
||||
|
||||
// Update the wild card directory watch
|
||||
watchConfigFileWildCardDirectories();
|
||||
}
|
||||
|
||||
function parseConfigFile() {
|
||||
setConfigFileParsingResult(getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost)!); // TODO: GH#18217
|
||||
}
|
||||
|
||||
function setConfigFileParsingResult(configFileParseResult: ParsedCommandLine) {
|
||||
rootFileNames = configFileParseResult.fileNames;
|
||||
compilerOptions = configFileParseResult.options;
|
||||
configFileSpecs = configFileParseResult.configFileSpecs!; // TODO: GH#18217
|
||||
projectReferences = configFileParseResult.projectReferences;
|
||||
configFileParsingDiagnostics = getConfigFileParsingDiagnostics(configFileParseResult).slice();
|
||||
canConfigFileJsonReportNoInputFiles = canJsonReportNoInutFiles(configFileParseResult.raw);
|
||||
hasChangedConfigFileParsingErrors = true;
|
||||
}
|
||||
|
||||
function onSourceFileChange(fileName: string, eventKind: FileWatcherEventKind, path: Path) {
|
||||
updateCachedSystemWithFile(fileName, path, eventKind);
|
||||
|
||||
// Update the source file cache
|
||||
if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.has(path)) {
|
||||
resolutionCache.invalidateResolutionOfFile(path);
|
||||
}
|
||||
resolutionCache.removeResolutionsFromProjectReferenceRedirects(path);
|
||||
nextSourceFileVersion(path);
|
||||
|
||||
// Update the program
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
|
||||
function updateCachedSystemWithFile(fileName: string, path: Path, eventKind: FileWatcherEventKind) {
|
||||
if (cachedDirectoryStructureHost) {
|
||||
cachedDirectoryStructureHost.addOrDeleteFile(fileName, path, eventKind);
|
||||
}
|
||||
}
|
||||
|
||||
function watchMissingFilePath(missingFilePath: Path) {
|
||||
return watchFilePath(host, missingFilePath, onMissingFileChange, PollingInterval.Medium, missingFilePath, WatchType.MissingFile);
|
||||
}
|
||||
|
||||
function onMissingFileChange(fileName: string, eventKind: FileWatcherEventKind, missingFilePath: Path) {
|
||||
updateCachedSystemWithFile(fileName, missingFilePath, eventKind);
|
||||
|
||||
if (eventKind === FileWatcherEventKind.Created && missingFilesMap.has(missingFilePath)) {
|
||||
missingFilesMap.get(missingFilePath)!.close();
|
||||
missingFilesMap.delete(missingFilePath);
|
||||
|
||||
// Delete the entry in the source files cache so that new source file is created
|
||||
nextSourceFileVersion(missingFilePath);
|
||||
|
||||
// When a missing file is created, we should update the graph.
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
function watchConfigFileWildCardDirectories() {
|
||||
if (configFileSpecs) {
|
||||
updateWatchingWildcardDirectories(
|
||||
watchedWildcardDirectories || (watchedWildcardDirectories = createMap()),
|
||||
createMapFromTemplate(configFileSpecs.wildcardDirectories),
|
||||
watchWildcardDirectory
|
||||
);
|
||||
}
|
||||
else if (watchedWildcardDirectories) {
|
||||
clearMap(watchedWildcardDirectories, closeFileWatcherOf);
|
||||
}
|
||||
}
|
||||
|
||||
function watchWildcardDirectory(directory: string, flags: WatchDirectoryFlags) {
|
||||
return watchDirectory(
|
||||
host,
|
||||
directory,
|
||||
fileOrDirectory => {
|
||||
Debug.assert(!!configFileName);
|
||||
|
||||
const fileOrDirectoryPath = toPath(fileOrDirectory);
|
||||
|
||||
// Since the file existance changed, update the sourceFiles cache
|
||||
if (cachedDirectoryStructureHost) {
|
||||
cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath);
|
||||
}
|
||||
nextSourceFileVersion(fileOrDirectoryPath);
|
||||
|
||||
if (isPathIgnored(fileOrDirectoryPath)) return;
|
||||
|
||||
// If the the added or created file or directory is not supported file name, ignore the file
|
||||
// But when watched directory is added/removed, we need to reload the file list
|
||||
if (fileOrDirectoryPath !== directory && hasExtension(fileOrDirectoryPath) && !isSupportedSourceFileName(fileOrDirectory, compilerOptions)) {
|
||||
writeLog(`Project: ${configFileName} Detected file add/remove of non supported extension: ${fileOrDirectory}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reload is pending, do the reload
|
||||
if (reloadLevel !== ConfigFileProgramReloadLevel.Full) {
|
||||
reloadLevel = ConfigFileProgramReloadLevel.Partial;
|
||||
|
||||
// Schedule Update the program
|
||||
scheduleProgramUpdate();
|
||||
}
|
||||
},
|
||||
flags,
|
||||
WatchType.WildcardDirectory
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
1605
src/harness/fourslashInterface.ts
Normal file
1605
src/harness/fourslashInterface.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,444 +1,3 @@
|
|||
// Block scoped definitions work poorly for global variables, temporarily enable var
|
||||
/* eslint-disable no-var */
|
||||
|
||||
// this will work in the browser via browserify
|
||||
var _chai: typeof chai = require("chai");
|
||||
var assert: typeof _chai.assert = _chai.assert;
|
||||
{
|
||||
// chai's builtin `assert.isFalse` is featureful but slow - we don't use those features,
|
||||
// so we'll just overwrite it as an alterative to migrating a bunch of code off of chai
|
||||
assert.isFalse = (expr: any, msg: string) => { if (expr !== false) throw new Error(msg); };
|
||||
|
||||
const assertDeepImpl = assert.deepEqual;
|
||||
assert.deepEqual = (a, b, msg) => {
|
||||
if (ts.isArray(a) && ts.isArray(b)) {
|
||||
assertDeepImpl(arrayExtraKeysObject(a), arrayExtraKeysObject(b), "Array extra keys differ");
|
||||
}
|
||||
assertDeepImpl(a, b, msg);
|
||||
|
||||
function arrayExtraKeysObject(a: readonly ({} | null | undefined)[]): object {
|
||||
const obj: { [key: string]: {} | null | undefined } = {};
|
||||
for (const key in a) {
|
||||
if (Number.isNaN(Number(key))) {
|
||||
obj[key] = a[key];
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var global: NodeJS.Global = Function("return this").call(undefined); // eslint-disable-line no-new-func
|
||||
|
||||
declare var window: {};
|
||||
declare var XMLHttpRequest: new() => XMLHttpRequest;
|
||||
|
||||
interface XMLHttpRequest {
|
||||
readonly readyState: number;
|
||||
readonly responseText: string;
|
||||
readonly status: number;
|
||||
readonly statusText: string;
|
||||
open(method: string, url: string, async?: boolean, user?: string, password?: string): void;
|
||||
send(data?: string): void;
|
||||
setRequestHeader(header: string, value: string): void;
|
||||
getAllResponseHeaders(): string;
|
||||
getResponseHeader(header: string): string | null;
|
||||
overrideMimeType(mime: string): void;
|
||||
}
|
||||
/* eslint-enable no-var */
|
||||
|
||||
namespace Utils {
|
||||
export function encodeString(s: string): string {
|
||||
return ts.sys.bufferFrom!(s).toString("utf8");
|
||||
}
|
||||
|
||||
export function byteLength(s: string, encoding?: string): number {
|
||||
// stub implementation if Buffer is not available (in-browser case)
|
||||
return Buffer.byteLength(s, encoding as ts.BufferEncoding | undefined);
|
||||
}
|
||||
|
||||
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
|
||||
const vm = require("vm");
|
||||
if (nodeContext) {
|
||||
vm.runInNewContext(fileContents, nodeContext, fileName);
|
||||
}
|
||||
else {
|
||||
vm.runInThisContext(fileContents, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/** Splits the given string on \r\n, or on only \n if that fails, or on only \r if *that* fails. */
|
||||
export function splitContentByNewlines(content: string) {
|
||||
// Split up the input file by line
|
||||
// Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so
|
||||
// we have to use string-based splitting instead and try to figure out the delimiting chars
|
||||
let lines = content.split("\r\n");
|
||||
if (lines.length === 1) {
|
||||
lines = content.split("\n");
|
||||
|
||||
if (lines.length === 1) {
|
||||
lines = content.split("\r");
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
/** Reads a file under /tests */
|
||||
export function readTestFile(path: string) {
|
||||
if (path.indexOf("tests") < 0) {
|
||||
path = "tests/" + path;
|
||||
}
|
||||
|
||||
let content: string | undefined;
|
||||
try {
|
||||
content = Harness.IO.readFile(Harness.userSpecifiedRoot + path);
|
||||
}
|
||||
catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
export function memoize<T extends ts.AnyFunction>(f: T, memoKey: (...anything: any[]) => string): T {
|
||||
const cache = ts.createMap<any>();
|
||||
|
||||
return <any>(function(this: any, ...args: any[]) {
|
||||
const key = memoKey(...args);
|
||||
if (cache.has(key)) {
|
||||
return cache.get(key);
|
||||
}
|
||||
else {
|
||||
const value = f.apply(this, args);
|
||||
cache.set(key, value);
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const canonicalizeForHarness = ts.createGetCanonicalFileName(/*caseSensitive*/ false); // This is done so tests work on windows _and_ linux
|
||||
|
||||
export function assertInvariants(node: ts.Node | undefined, parent: ts.Node | undefined): void {
|
||||
if (node) {
|
||||
assert.isFalse(node.pos < 0, "node.pos < 0");
|
||||
assert.isFalse(node.end < 0, "node.end < 0");
|
||||
assert.isFalse(node.end < node.pos, "node.end < node.pos");
|
||||
assert.equal(node.parent, parent, "node.parent !== parent");
|
||||
|
||||
if (parent) {
|
||||
// Make sure each child is contained within the parent.
|
||||
assert.isFalse(node.pos < parent.pos, "node.pos < parent.pos");
|
||||
assert.isFalse(node.end > parent.end, "node.end > parent.end");
|
||||
}
|
||||
|
||||
ts.forEachChild(node, child => {
|
||||
assertInvariants(child, node);
|
||||
});
|
||||
|
||||
// Make sure each of the children is in order.
|
||||
let currentPos = 0;
|
||||
ts.forEachChild(node,
|
||||
child => {
|
||||
assert.isFalse(child.pos < currentPos, "child.pos < currentPos");
|
||||
currentPos = child.end;
|
||||
},
|
||||
array => {
|
||||
assert.isFalse(array.pos < node.pos, "array.pos < node.pos");
|
||||
assert.isFalse(array.end > node.end, "array.end > node.end");
|
||||
assert.isFalse(array.pos < currentPos, "array.pos < currentPos");
|
||||
|
||||
for (const item of array) {
|
||||
assert.isFalse(item.pos < currentPos, "array[i].pos < currentPos");
|
||||
currentPos = item.end;
|
||||
}
|
||||
|
||||
currentPos = array.end;
|
||||
});
|
||||
|
||||
const childNodesAndArrays: any[] = [];
|
||||
ts.forEachChild(node, child => { childNodesAndArrays.push(child); }, array => { childNodesAndArrays.push(array); });
|
||||
|
||||
for (const childName in node) {
|
||||
if (childName === "parent" || childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator" ||
|
||||
// for now ignore jsdoc comments
|
||||
childName === "jsDocComment" || childName === "checkJsDirective" || childName === "commonJsModuleIndicator") {
|
||||
continue;
|
||||
}
|
||||
const child = (<any>node)[childName];
|
||||
if (isNodeOrArray(child)) {
|
||||
assert.isFalse(childNodesAndArrays.indexOf(child) < 0,
|
||||
"Missing child when forEach'ing over node: " + (<any>ts).SyntaxKind[node.kind] + "-" + childName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isNodeOrArray(a: any): boolean {
|
||||
return a !== undefined && typeof a.pos === "number";
|
||||
}
|
||||
|
||||
export function convertDiagnostics(diagnostics: readonly ts.Diagnostic[]) {
|
||||
return diagnostics.map(convertDiagnostic);
|
||||
}
|
||||
|
||||
function convertDiagnostic(diagnostic: ts.Diagnostic) {
|
||||
return {
|
||||
start: diagnostic.start,
|
||||
length: diagnostic.length,
|
||||
messageText: ts.flattenDiagnosticMessageText(diagnostic.messageText, Harness.IO.newLine()),
|
||||
category: ts.diagnosticCategoryName(diagnostic, /*lowerCase*/ false),
|
||||
code: diagnostic.code
|
||||
};
|
||||
}
|
||||
|
||||
export function sourceFileToJSON(file: ts.Node): string {
|
||||
return JSON.stringify(file, (_, v) => isNodeOrArray(v) ? serializeNode(v) : v, " ");
|
||||
|
||||
function getKindName(k: number | string): string {
|
||||
if (ts.isString(k)) {
|
||||
return k;
|
||||
}
|
||||
|
||||
// For some markers in SyntaxKind, we should print its original syntax name instead of
|
||||
// the marker name in tests.
|
||||
if (k === (<any>ts).SyntaxKind.FirstJSDocNode ||
|
||||
k === (<any>ts).SyntaxKind.LastJSDocNode ||
|
||||
k === (<any>ts).SyntaxKind.FirstJSDocTagNode ||
|
||||
k === (<any>ts).SyntaxKind.LastJSDocTagNode) {
|
||||
for (const kindName in (<any>ts).SyntaxKind) {
|
||||
if ((<any>ts).SyntaxKind[kindName] === k) {
|
||||
return kindName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (<any>ts).SyntaxKind[k];
|
||||
}
|
||||
|
||||
function getFlagName(flags: any, f: number): any {
|
||||
if (f === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let result = "";
|
||||
ts.forEach(Object.getOwnPropertyNames(flags), (v: any) => {
|
||||
if (isFinite(v)) {
|
||||
v = +v;
|
||||
if (f === +v) {
|
||||
result = flags[v];
|
||||
return true;
|
||||
}
|
||||
else if ((f & v) > 0) {
|
||||
if (result.length) {
|
||||
result += " | ";
|
||||
}
|
||||
result += flags[v];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function getNodeFlagName(f: number) { return getFlagName((<any>ts).NodeFlags, f); }
|
||||
|
||||
function serializeNode(n: ts.Node): any {
|
||||
const o: any = { kind: getKindName(n.kind) };
|
||||
if (ts.containsParseError(n)) {
|
||||
o.containsParseError = true;
|
||||
}
|
||||
|
||||
for (const propertyName of Object.getOwnPropertyNames(n) as readonly (keyof ts.SourceFile | keyof ts.Identifier)[]) {
|
||||
switch (propertyName) {
|
||||
case "parent":
|
||||
case "symbol":
|
||||
case "locals":
|
||||
case "localSymbol":
|
||||
case "kind":
|
||||
case "id":
|
||||
case "nodeCount":
|
||||
case "symbolCount":
|
||||
case "identifierCount":
|
||||
case "scriptSnapshot":
|
||||
// Blacklist of items we never put in the baseline file.
|
||||
break;
|
||||
|
||||
case "originalKeywordKind":
|
||||
o[propertyName] = getKindName((<any>n)[propertyName]);
|
||||
break;
|
||||
|
||||
case "flags":
|
||||
// Clear the flags that are produced by aggregating child values. That is ephemeral
|
||||
// data we don't care about in the dump. We only care what the parser set directly
|
||||
// on the AST.
|
||||
const flags = n.flags & ~(ts.NodeFlags.JavaScriptFile | ts.NodeFlags.HasAggregatedChildData);
|
||||
if (flags) {
|
||||
o[propertyName] = getNodeFlagName(flags);
|
||||
}
|
||||
break;
|
||||
|
||||
case "parseDiagnostics":
|
||||
o[propertyName] = convertDiagnostics((<any>n)[propertyName]);
|
||||
break;
|
||||
|
||||
case "nextContainer":
|
||||
if (n.nextContainer) {
|
||||
o[propertyName] = { kind: n.nextContainer.kind, pos: n.nextContainer.pos, end: n.nextContainer.end };
|
||||
}
|
||||
break;
|
||||
|
||||
case "text":
|
||||
// Include 'text' field for identifiers/literals, but not for source files.
|
||||
if (n.kind !== ts.SyntaxKind.SourceFile) {
|
||||
o[propertyName] = (<any>n)[propertyName];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
o[propertyName] = (<any>n)[propertyName];
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
export function assertDiagnosticsEquals(array1: readonly ts.Diagnostic[], array2: readonly ts.Diagnostic[]) {
|
||||
if (array1 === array2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(array1, "array1");
|
||||
assert(array2, "array2");
|
||||
|
||||
assert.equal(array1.length, array2.length, "array1.length !== array2.length");
|
||||
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
const d1 = array1[i];
|
||||
const d2 = array2[i];
|
||||
|
||||
assert.equal(d1.start, d2.start, "d1.start !== d2.start");
|
||||
assert.equal(d1.length, d2.length, "d1.length !== d2.length");
|
||||
assert.equal(
|
||||
ts.flattenDiagnosticMessageText(d1.messageText, Harness.IO.newLine()),
|
||||
ts.flattenDiagnosticMessageText(d2.messageText, Harness.IO.newLine()), "d1.messageText !== d2.messageText");
|
||||
assert.equal(d1.category, d2.category, "d1.category !== d2.category");
|
||||
assert.equal(d1.code, d2.code, "d1.code !== d2.code");
|
||||
}
|
||||
}
|
||||
|
||||
export function assertStructuralEquals(node1: ts.Node, node2: ts.Node) {
|
||||
if (node1 === node2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(node1, "node1");
|
||||
assert(node2, "node2");
|
||||
assert.equal(node1.pos, node2.pos, "node1.pos !== node2.pos");
|
||||
assert.equal(node1.end, node2.end, "node1.end !== node2.end");
|
||||
assert.equal(node1.kind, node2.kind, "node1.kind !== node2.kind");
|
||||
|
||||
// call this on both nodes to ensure all propagated flags have been set (and thus can be
|
||||
// compared).
|
||||
assert.equal(ts.containsParseError(node1), ts.containsParseError(node2));
|
||||
assert.equal(node1.flags & ~ts.NodeFlags.ReachabilityAndEmitFlags, node2.flags & ~ts.NodeFlags.ReachabilityAndEmitFlags, "node1.flags !== node2.flags");
|
||||
|
||||
ts.forEachChild(node1,
|
||||
child1 => {
|
||||
const childName = findChildName(node1, child1);
|
||||
const child2: ts.Node = (<any>node2)[childName];
|
||||
|
||||
assertStructuralEquals(child1, child2);
|
||||
},
|
||||
array1 => {
|
||||
const childName = findChildName(node1, array1);
|
||||
const array2: ts.NodeArray<ts.Node> = (<any>node2)[childName];
|
||||
|
||||
assertArrayStructuralEquals(array1, array2);
|
||||
});
|
||||
}
|
||||
|
||||
function assertArrayStructuralEquals(array1: ts.NodeArray<ts.Node>, array2: ts.NodeArray<ts.Node>) {
|
||||
if (array1 === array2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(array1, "array1");
|
||||
assert(array2, "array2");
|
||||
assert.equal(array1.pos, array2.pos, "array1.pos !== array2.pos");
|
||||
assert.equal(array1.end, array2.end, "array1.end !== array2.end");
|
||||
assert.equal(array1.length, array2.length, "array1.length !== array2.length");
|
||||
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
assertStructuralEquals(array1[i], array2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function findChildName(parent: any, child: any) {
|
||||
for (const name in parent) {
|
||||
if (parent.hasOwnProperty(name) && parent[name] === child) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Could not find child in parent");
|
||||
}
|
||||
|
||||
const maxHarnessFrames = 1;
|
||||
|
||||
export function filterStack(error: Error, stackTraceLimit = Infinity) {
|
||||
const stack = <string>(<any>error).stack;
|
||||
if (stack) {
|
||||
const lines = stack.split(/\r\n?|\n/g);
|
||||
const filtered: string[] = [];
|
||||
let frameCount = 0;
|
||||
let harnessFrameCount = 0;
|
||||
for (let line of lines) {
|
||||
if (isStackFrame(line)) {
|
||||
if (frameCount >= stackTraceLimit
|
||||
|| isMocha(line)
|
||||
|| isNode(line)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isHarness(line)) {
|
||||
if (harnessFrameCount >= maxHarnessFrames) {
|
||||
continue;
|
||||
}
|
||||
|
||||
harnessFrameCount++;
|
||||
}
|
||||
|
||||
line = line.replace(/\bfile:\/\/\/(.*?)(?=(:\d+)*($|\)))/, (_, path) => ts.sys.resolvePath(path));
|
||||
frameCount++;
|
||||
}
|
||||
|
||||
filtered.push(line);
|
||||
}
|
||||
|
||||
(<any>error).stack = filtered.join(Harness.IO.newLine());
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
function isStackFrame(line: string) {
|
||||
return /^\s+at\s/.test(line);
|
||||
}
|
||||
|
||||
function isMocha(line: string) {
|
||||
return /[\\/](node_modules|components)[\\/]mocha(js)?[\\/]|[\\/]mocha\.js/.test(line);
|
||||
}
|
||||
|
||||
function isNode(line: string) {
|
||||
return /\((timers|events|node|module)\.js:/.test(line);
|
||||
}
|
||||
|
||||
function isHarness(line: string) {
|
||||
return /[\\/]src[\\/]harness[\\/]|[\\/]run\.js/.test(line);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Harness {
|
||||
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
|
||||
export interface IO {
|
||||
|
@ -602,13 +161,11 @@ namespace Harness {
|
|||
}
|
||||
|
||||
IO = createNodeIO();
|
||||
}
|
||||
|
||||
if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable!("NODE_ENV"))) {
|
||||
Harness.IO.tryEnableSourceMapsForHost();
|
||||
}
|
||||
if (IO.tryEnableSourceMapsForHost && /^development$/i.test(IO.getEnvironmentVariable!("NODE_ENV"))) {
|
||||
IO.tryEnableSourceMapsForHost();
|
||||
}
|
||||
|
||||
namespace Harness {
|
||||
export const libFolder = "built/local/";
|
||||
const tcServicesFileName = ts.combinePaths(libFolder, "typescriptServices.js");
|
||||
export const tcServicesFile = IO.readFile(tcServicesFileName) + IO.newLine() + `//# sourceURL=${IO.resolvePath(tcServicesFileName)}`;
|
||||
|
|
48
src/harness/harnessGlobals.ts
Normal file
48
src/harness/harnessGlobals.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
// Block scoped definitions work poorly for global variables, temporarily enable var
|
||||
/* eslint-disable no-var */
|
||||
|
||||
// this will work in the browser via browserify
|
||||
var _chai: typeof chai = require("chai");
|
||||
var assert: typeof _chai.assert = _chai.assert;
|
||||
{
|
||||
// chai's builtin `assert.isFalse` is featureful but slow - we don't use those features,
|
||||
// so we'll just overwrite it as an alterative to migrating a bunch of code off of chai
|
||||
assert.isFalse = (expr: any, msg: string) => { if (expr !== false) throw new Error(msg); };
|
||||
|
||||
const assertDeepImpl = assert.deepEqual;
|
||||
assert.deepEqual = (a, b, msg) => {
|
||||
if (ts.isArray(a) && ts.isArray(b)) {
|
||||
assertDeepImpl(arrayExtraKeysObject(a), arrayExtraKeysObject(b), "Array extra keys differ");
|
||||
}
|
||||
assertDeepImpl(a, b, msg);
|
||||
|
||||
function arrayExtraKeysObject(a: readonly ({} | null | undefined)[]): object {
|
||||
const obj: { [key: string]: {} | null | undefined } = {};
|
||||
for (const key in a) {
|
||||
if (Number.isNaN(Number(key))) {
|
||||
obj[key] = a[key];
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var global: NodeJS.Global = Function("return this").call(undefined); // eslint-disable-line no-new-func
|
||||
|
||||
declare var window: {};
|
||||
declare var XMLHttpRequest: new() => XMLHttpRequest;
|
||||
|
||||
interface XMLHttpRequest {
|
||||
readonly readyState: number;
|
||||
readonly responseText: string;
|
||||
readonly status: number;
|
||||
readonly statusText: string;
|
||||
open(method: string, url: string, async?: boolean, user?: string, password?: string): void;
|
||||
send(data?: string): void;
|
||||
setRequestHeader(header: string, value: string): void;
|
||||
getAllResponseHeaders(): string;
|
||||
getResponseHeader(header: string): string | null;
|
||||
overrideMimeType(mime: string): void;
|
||||
}
|
||||
/* eslint-enable no-var */
|
|
@ -597,7 +597,7 @@ namespace Harness.LanguageService {
|
|||
private factory: ts.TypeScriptServicesFactory;
|
||||
constructor(preprocessToResolve: boolean, cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
|
||||
this.host = new ShimLanguageServiceHost(preprocessToResolve, cancellationToken, options);
|
||||
this.factory = new TypeScript.Services.TypeScriptServicesFactory();
|
||||
this.factory = new ts.TypeScriptServicesFactory();
|
||||
}
|
||||
getHost() { return this.host; }
|
||||
getLanguageService(): ts.LanguageService { return new LanguageServiceShimProxy(this.factory.createLanguageServiceShim(this.host)); }
|
||||
|
|
391
src/harness/harnessUtils.ts
Normal file
391
src/harness/harnessUtils.ts
Normal file
|
@ -0,0 +1,391 @@
|
|||
namespace Utils {
|
||||
export function encodeString(s: string): string {
|
||||
return ts.sys.bufferFrom!(s).toString("utf8");
|
||||
}
|
||||
|
||||
export function byteLength(s: string, encoding?: string): number {
|
||||
// stub implementation if Buffer is not available (in-browser case)
|
||||
return Buffer.byteLength(s, encoding as ts.BufferEncoding | undefined);
|
||||
}
|
||||
|
||||
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
|
||||
const vm = require("vm");
|
||||
if (nodeContext) {
|
||||
vm.runInNewContext(fileContents, nodeContext, fileName);
|
||||
}
|
||||
else {
|
||||
vm.runInThisContext(fileContents, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/** Splits the given string on \r\n, or on only \n if that fails, or on only \r if *that* fails. */
|
||||
export function splitContentByNewlines(content: string) {
|
||||
// Split up the input file by line
|
||||
// Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so
|
||||
// we have to use string-based splitting instead and try to figure out the delimiting chars
|
||||
let lines = content.split("\r\n");
|
||||
if (lines.length === 1) {
|
||||
lines = content.split("\n");
|
||||
|
||||
if (lines.length === 1) {
|
||||
lines = content.split("\r");
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
/** Reads a file under /tests */
|
||||
export function readTestFile(path: string) {
|
||||
if (path.indexOf("tests") < 0) {
|
||||
path = "tests/" + path;
|
||||
}
|
||||
|
||||
let content: string | undefined;
|
||||
try {
|
||||
content = Harness.IO.readFile(Harness.userSpecifiedRoot + path);
|
||||
}
|
||||
catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
export function memoize<T extends ts.AnyFunction>(f: T, memoKey: (...anything: any[]) => string): T {
|
||||
const cache = ts.createMap<any>();
|
||||
|
||||
return <any>(function(this: any, ...args: any[]) {
|
||||
const key = memoKey(...args);
|
||||
if (cache.has(key)) {
|
||||
return cache.get(key);
|
||||
}
|
||||
else {
|
||||
const value = f.apply(this, args);
|
||||
cache.set(key, value);
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const canonicalizeForHarness = ts.createGetCanonicalFileName(/*caseSensitive*/ false); // This is done so tests work on windows _and_ linux
|
||||
|
||||
export function assertInvariants(node: ts.Node | undefined, parent: ts.Node | undefined): void {
|
||||
if (node) {
|
||||
assert.isFalse(node.pos < 0, "node.pos < 0");
|
||||
assert.isFalse(node.end < 0, "node.end < 0");
|
||||
assert.isFalse(node.end < node.pos, "node.end < node.pos");
|
||||
assert.equal(node.parent, parent, "node.parent !== parent");
|
||||
|
||||
if (parent) {
|
||||
// Make sure each child is contained within the parent.
|
||||
assert.isFalse(node.pos < parent.pos, "node.pos < parent.pos");
|
||||
assert.isFalse(node.end > parent.end, "node.end > parent.end");
|
||||
}
|
||||
|
||||
ts.forEachChild(node, child => {
|
||||
assertInvariants(child, node);
|
||||
});
|
||||
|
||||
// Make sure each of the children is in order.
|
||||
let currentPos = 0;
|
||||
ts.forEachChild(node,
|
||||
child => {
|
||||
assert.isFalse(child.pos < currentPos, "child.pos < currentPos");
|
||||
currentPos = child.end;
|
||||
},
|
||||
array => {
|
||||
assert.isFalse(array.pos < node.pos, "array.pos < node.pos");
|
||||
assert.isFalse(array.end > node.end, "array.end > node.end");
|
||||
assert.isFalse(array.pos < currentPos, "array.pos < currentPos");
|
||||
|
||||
for (const item of array) {
|
||||
assert.isFalse(item.pos < currentPos, "array[i].pos < currentPos");
|
||||
currentPos = item.end;
|
||||
}
|
||||
|
||||
currentPos = array.end;
|
||||
});
|
||||
|
||||
const childNodesAndArrays: any[] = [];
|
||||
ts.forEachChild(node, child => { childNodesAndArrays.push(child); }, array => { childNodesAndArrays.push(array); });
|
||||
|
||||
for (const childName in node) {
|
||||
if (childName === "parent" || childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator" ||
|
||||
// for now ignore jsdoc comments
|
||||
childName === "jsDocComment" || childName === "checkJsDirective" || childName === "commonJsModuleIndicator") {
|
||||
continue;
|
||||
}
|
||||
const child = (<any>node)[childName];
|
||||
if (isNodeOrArray(child)) {
|
||||
assert.isFalse(childNodesAndArrays.indexOf(child) < 0,
|
||||
"Missing child when forEach'ing over node: " + (<any>ts).SyntaxKind[node.kind] + "-" + childName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isNodeOrArray(a: any): boolean {
|
||||
return a !== undefined && typeof a.pos === "number";
|
||||
}
|
||||
|
||||
export function convertDiagnostics(diagnostics: readonly ts.Diagnostic[]) {
|
||||
return diagnostics.map(convertDiagnostic);
|
||||
}
|
||||
|
||||
function convertDiagnostic(diagnostic: ts.Diagnostic) {
|
||||
return {
|
||||
start: diagnostic.start,
|
||||
length: diagnostic.length,
|
||||
messageText: ts.flattenDiagnosticMessageText(diagnostic.messageText, Harness.IO.newLine()),
|
||||
category: ts.diagnosticCategoryName(diagnostic, /*lowerCase*/ false),
|
||||
code: diagnostic.code
|
||||
};
|
||||
}
|
||||
|
||||
export function sourceFileToJSON(file: ts.Node): string {
|
||||
return JSON.stringify(file, (_, v) => isNodeOrArray(v) ? serializeNode(v) : v, " ");
|
||||
|
||||
function getKindName(k: number | string): string {
|
||||
if (ts.isString(k)) {
|
||||
return k;
|
||||
}
|
||||
|
||||
// For some markers in SyntaxKind, we should print its original syntax name instead of
|
||||
// the marker name in tests.
|
||||
if (k === (<any>ts).SyntaxKind.FirstJSDocNode ||
|
||||
k === (<any>ts).SyntaxKind.LastJSDocNode ||
|
||||
k === (<any>ts).SyntaxKind.FirstJSDocTagNode ||
|
||||
k === (<any>ts).SyntaxKind.LastJSDocTagNode) {
|
||||
for (const kindName in (<any>ts).SyntaxKind) {
|
||||
if ((<any>ts).SyntaxKind[kindName] === k) {
|
||||
return kindName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (<any>ts).SyntaxKind[k];
|
||||
}
|
||||
|
||||
function getFlagName(flags: any, f: number): any {
|
||||
if (f === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let result = "";
|
||||
ts.forEach(Object.getOwnPropertyNames(flags), (v: any) => {
|
||||
if (isFinite(v)) {
|
||||
v = +v;
|
||||
if (f === +v) {
|
||||
result = flags[v];
|
||||
return true;
|
||||
}
|
||||
else if ((f & v) > 0) {
|
||||
if (result.length) {
|
||||
result += " | ";
|
||||
}
|
||||
result += flags[v];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function getNodeFlagName(f: number) { return getFlagName((<any>ts).NodeFlags, f); }
|
||||
|
||||
function serializeNode(n: ts.Node): any {
|
||||
const o: any = { kind: getKindName(n.kind) };
|
||||
if (ts.containsParseError(n)) {
|
||||
o.containsParseError = true;
|
||||
}
|
||||
|
||||
for (const propertyName of Object.getOwnPropertyNames(n) as readonly (keyof ts.SourceFile | keyof ts.Identifier)[]) {
|
||||
switch (propertyName) {
|
||||
case "parent":
|
||||
case "symbol":
|
||||
case "locals":
|
||||
case "localSymbol":
|
||||
case "kind":
|
||||
case "id":
|
||||
case "nodeCount":
|
||||
case "symbolCount":
|
||||
case "identifierCount":
|
||||
case "scriptSnapshot":
|
||||
// Blacklist of items we never put in the baseline file.
|
||||
break;
|
||||
|
||||
case "originalKeywordKind":
|
||||
o[propertyName] = getKindName((<any>n)[propertyName]);
|
||||
break;
|
||||
|
||||
case "flags":
|
||||
// Clear the flags that are produced by aggregating child values. That is ephemeral
|
||||
// data we don't care about in the dump. We only care what the parser set directly
|
||||
// on the AST.
|
||||
const flags = n.flags & ~(ts.NodeFlags.JavaScriptFile | ts.NodeFlags.HasAggregatedChildData);
|
||||
if (flags) {
|
||||
o[propertyName] = getNodeFlagName(flags);
|
||||
}
|
||||
break;
|
||||
|
||||
case "parseDiagnostics":
|
||||
o[propertyName] = convertDiagnostics((<any>n)[propertyName]);
|
||||
break;
|
||||
|
||||
case "nextContainer":
|
||||
if (n.nextContainer) {
|
||||
o[propertyName] = { kind: n.nextContainer.kind, pos: n.nextContainer.pos, end: n.nextContainer.end };
|
||||
}
|
||||
break;
|
||||
|
||||
case "text":
|
||||
// Include 'text' field for identifiers/literals, but not for source files.
|
||||
if (n.kind !== ts.SyntaxKind.SourceFile) {
|
||||
o[propertyName] = (<any>n)[propertyName];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
o[propertyName] = (<any>n)[propertyName];
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
export function assertDiagnosticsEquals(array1: readonly ts.Diagnostic[], array2: readonly ts.Diagnostic[]) {
|
||||
if (array1 === array2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(array1, "array1");
|
||||
assert(array2, "array2");
|
||||
|
||||
assert.equal(array1.length, array2.length, "array1.length !== array2.length");
|
||||
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
const d1 = array1[i];
|
||||
const d2 = array2[i];
|
||||
|
||||
assert.equal(d1.start, d2.start, "d1.start !== d2.start");
|
||||
assert.equal(d1.length, d2.length, "d1.length !== d2.length");
|
||||
assert.equal(
|
||||
ts.flattenDiagnosticMessageText(d1.messageText, Harness.IO.newLine()),
|
||||
ts.flattenDiagnosticMessageText(d2.messageText, Harness.IO.newLine()), "d1.messageText !== d2.messageText");
|
||||
assert.equal(d1.category, d2.category, "d1.category !== d2.category");
|
||||
assert.equal(d1.code, d2.code, "d1.code !== d2.code");
|
||||
}
|
||||
}
|
||||
|
||||
export function assertStructuralEquals(node1: ts.Node, node2: ts.Node) {
|
||||
if (node1 === node2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(node1, "node1");
|
||||
assert(node2, "node2");
|
||||
assert.equal(node1.pos, node2.pos, "node1.pos !== node2.pos");
|
||||
assert.equal(node1.end, node2.end, "node1.end !== node2.end");
|
||||
assert.equal(node1.kind, node2.kind, "node1.kind !== node2.kind");
|
||||
|
||||
// call this on both nodes to ensure all propagated flags have been set (and thus can be
|
||||
// compared).
|
||||
assert.equal(ts.containsParseError(node1), ts.containsParseError(node2));
|
||||
assert.equal(node1.flags & ~ts.NodeFlags.ReachabilityAndEmitFlags, node2.flags & ~ts.NodeFlags.ReachabilityAndEmitFlags, "node1.flags !== node2.flags");
|
||||
|
||||
ts.forEachChild(node1,
|
||||
child1 => {
|
||||
const childName = findChildName(node1, child1);
|
||||
const child2: ts.Node = (<any>node2)[childName];
|
||||
|
||||
assertStructuralEquals(child1, child2);
|
||||
},
|
||||
array1 => {
|
||||
const childName = findChildName(node1, array1);
|
||||
const array2: ts.NodeArray<ts.Node> = (<any>node2)[childName];
|
||||
|
||||
assertArrayStructuralEquals(array1, array2);
|
||||
});
|
||||
}
|
||||
|
||||
function assertArrayStructuralEquals(array1: ts.NodeArray<ts.Node>, array2: ts.NodeArray<ts.Node>) {
|
||||
if (array1 === array2) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(array1, "array1");
|
||||
assert(array2, "array2");
|
||||
assert.equal(array1.pos, array2.pos, "array1.pos !== array2.pos");
|
||||
assert.equal(array1.end, array2.end, "array1.end !== array2.end");
|
||||
assert.equal(array1.length, array2.length, "array1.length !== array2.length");
|
||||
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
assertStructuralEquals(array1[i], array2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function findChildName(parent: any, child: any) {
|
||||
for (const name in parent) {
|
||||
if (parent.hasOwnProperty(name) && parent[name] === child) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Could not find child in parent");
|
||||
}
|
||||
|
||||
const maxHarnessFrames = 1;
|
||||
|
||||
export function filterStack(error: Error, stackTraceLimit = Infinity) {
|
||||
const stack = <string>(<any>error).stack;
|
||||
if (stack) {
|
||||
const lines = stack.split(/\r\n?|\n/g);
|
||||
const filtered: string[] = [];
|
||||
let frameCount = 0;
|
||||
let harnessFrameCount = 0;
|
||||
for (let line of lines) {
|
||||
if (isStackFrame(line)) {
|
||||
if (frameCount >= stackTraceLimit
|
||||
|| isMocha(line)
|
||||
|| isNode(line)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isHarness(line)) {
|
||||
if (harnessFrameCount >= maxHarnessFrames) {
|
||||
continue;
|
||||
}
|
||||
|
||||
harnessFrameCount++;
|
||||
}
|
||||
|
||||
line = line.replace(/\bfile:\/\/\/(.*?)(?=(:\d+)*($|\)))/, (_, path) => ts.sys.resolvePath(path));
|
||||
frameCount++;
|
||||
}
|
||||
|
||||
filtered.push(line);
|
||||
}
|
||||
|
||||
(<any>error).stack = filtered.join(Harness.IO.newLine());
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
function isStackFrame(line: string) {
|
||||
return /^\s+at\s/.test(line);
|
||||
}
|
||||
|
||||
function isMocha(line: string) {
|
||||
return /[\\/](node_modules|components)[\\/]mocha(js)?[\\/]|[\\/]mocha\.js/.test(line);
|
||||
}
|
||||
|
||||
function isNode(line: string) {
|
||||
return /\((timers|events|node|module)\.js:/.test(line);
|
||||
}
|
||||
|
||||
function isHarness(line: string) {
|
||||
return /[\\/]src[\\/]harness[\\/]|[\\/]run\.js/.test(line);
|
||||
}
|
||||
}
|
|
@ -31,10 +31,13 @@
|
|||
|
||||
"runnerbase.ts",
|
||||
"sourceMapRecorder.ts",
|
||||
"harnessGlobals.ts",
|
||||
"harnessUtils.ts",
|
||||
"harness.ts",
|
||||
"harnessLanguageService.ts",
|
||||
"virtualFileSystemWithWatch.ts",
|
||||
"fourslash.ts",
|
||||
"fourslashInterface.ts",
|
||||
"typeWriter.ts",
|
||||
"loggedIO.ts"
|
||||
]
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
],
|
||||
"files": [
|
||||
"types.ts",
|
||||
"utilitiesPublic.ts",
|
||||
"utilities.ts",
|
||||
"watchType.ts"
|
||||
"protocol.ts",
|
||||
"scriptInfo.ts",
|
||||
"typingsCache.ts",
|
||||
|
|
|
@ -1,126 +1,3 @@
|
|||
namespace ts.server {
|
||||
export enum LogLevel {
|
||||
terse,
|
||||
normal,
|
||||
requestTime,
|
||||
verbose
|
||||
}
|
||||
|
||||
export const emptyArray: SortedReadonlyArray<never> = createSortedArray<never>();
|
||||
|
||||
export interface Logger {
|
||||
close(): void;
|
||||
hasLevel(level: LogLevel): boolean;
|
||||
loggingEnabled(): boolean;
|
||||
perftrc(s: string): void;
|
||||
info(s: string): void;
|
||||
startGroup(): void;
|
||||
endGroup(): void;
|
||||
msg(s: string, type?: Msg): void;
|
||||
getLogFileName(): string | undefined;
|
||||
}
|
||||
|
||||
// TODO: Use a const enum (https://github.com/Microsoft/TypeScript/issues/16804)
|
||||
export enum Msg {
|
||||
Err = "Err",
|
||||
Info = "Info",
|
||||
Perf = "Perf",
|
||||
}
|
||||
export namespace Msg {
|
||||
/** @deprecated Only here for backwards-compatibility. Prefer just `Msg`. */
|
||||
export type Types = Msg;
|
||||
}
|
||||
|
||||
export function createInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string>, cachePath?: string): DiscoverTypings {
|
||||
return {
|
||||
projectName: project.getProjectName(),
|
||||
fileNames: project.getFileNames(/*excludeFilesFromExternalLibraries*/ true, /*excludeConfigFiles*/ true).concat(project.getExcludedFiles() as NormalizedPath[]),
|
||||
compilerOptions: project.getCompilationSettings(),
|
||||
typeAcquisition,
|
||||
unresolvedImports,
|
||||
projectRootPath: project.getCurrentDirectory() as Path,
|
||||
cachePath,
|
||||
kind: "discover"
|
||||
};
|
||||
}
|
||||
|
||||
export namespace Errors {
|
||||
export function ThrowNoProject(): never {
|
||||
throw new Error("No Project.");
|
||||
}
|
||||
export function ThrowProjectLanguageServiceDisabled(): never {
|
||||
throw new Error("The project's language service is disabled.");
|
||||
}
|
||||
export function ThrowProjectDoesNotContainDocument(fileName: string, project: Project): never {
|
||||
throw new Error(`Project '${project.getProjectName()}' does not contain document '${fileName}'`);
|
||||
}
|
||||
}
|
||||
|
||||
export type NormalizedPath = string & { __normalizedPathTag: any };
|
||||
|
||||
export function toNormalizedPath(fileName: string): NormalizedPath {
|
||||
return <NormalizedPath>normalizePath(fileName);
|
||||
}
|
||||
|
||||
export function normalizedPathToPath(normalizedPath: NormalizedPath, currentDirectory: string, getCanonicalFileName: (f: string) => string): Path {
|
||||
const f = isRootedDiskPath(normalizedPath) ? normalizedPath : getNormalizedAbsolutePath(normalizedPath, currentDirectory);
|
||||
return <Path>getCanonicalFileName(f);
|
||||
}
|
||||
|
||||
export function asNormalizedPath(fileName: string): NormalizedPath {
|
||||
return <NormalizedPath>fileName;
|
||||
}
|
||||
|
||||
export interface NormalizedPathMap<T> {
|
||||
get(path: NormalizedPath): T | undefined;
|
||||
set(path: NormalizedPath, value: T): void;
|
||||
contains(path: NormalizedPath): boolean;
|
||||
remove(path: NormalizedPath): void;
|
||||
}
|
||||
|
||||
export function createNormalizedPathMap<T>(): NormalizedPathMap<T> {
|
||||
const map = createMap<T>();
|
||||
return {
|
||||
get(path) {
|
||||
return map.get(path);
|
||||
},
|
||||
set(path, value) {
|
||||
map.set(path, value);
|
||||
},
|
||||
contains(path) {
|
||||
return map.has(path);
|
||||
},
|
||||
remove(path) {
|
||||
map.delete(path);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface ProjectOptions {
|
||||
configHasExtendsProperty: boolean;
|
||||
/**
|
||||
* true if config file explicitly listed files
|
||||
*/
|
||||
configHasFilesProperty: boolean;
|
||||
configHasIncludeProperty: boolean;
|
||||
configHasExcludeProperty: boolean;
|
||||
}
|
||||
|
||||
export function isInferredProjectName(name: string) {
|
||||
// POSIX defines /dev/null as a device - there should be no file with this prefix
|
||||
return /dev\/null\/inferredProject\d+\*/.test(name);
|
||||
}
|
||||
|
||||
export function makeInferredProjectName(counter: number) {
|
||||
return `/dev/null/inferredProject${counter}*`;
|
||||
}
|
||||
|
||||
export function createSortedArray<T>(): SortedArray<T> {
|
||||
return [] as any as SortedArray<T>; // TODO: GH#19873
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
namespace ts.server {
|
||||
export class ThrottledOperations {
|
||||
|
@ -221,17 +98,3 @@ namespace ts.server {
|
|||
return indentStr + JSON.stringify(json);
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
// Additional tsserver specific watch information
|
||||
export const enum WatchType {
|
||||
ClosedScriptInfo = "Closed Script info",
|
||||
ConfigFileForInferredRoot = "Config file for the inferred project root",
|
||||
NodeModulesForClosedScriptInfo = "node_modules for closed script infos in them",
|
||||
MissingSourceMapFile = "Missing source map file",
|
||||
NoopConfigFileForInferredRoot = "Noop Config file for the inferred project root",
|
||||
MissingGeneratedFile = "Missing generated file",
|
||||
PackageJsonFile = "package.json file for import suggestions"
|
||||
}
|
||||
}
|
||||
|
|
122
src/server/utilitiesPublic.ts
Normal file
122
src/server/utilitiesPublic.ts
Normal file
|
@ -0,0 +1,122 @@
|
|||
namespace ts.server {
|
||||
export enum LogLevel {
|
||||
terse,
|
||||
normal,
|
||||
requestTime,
|
||||
verbose
|
||||
}
|
||||
|
||||
export const emptyArray: SortedReadonlyArray<never> = createSortedArray<never>();
|
||||
|
||||
export interface Logger {
|
||||
close(): void;
|
||||
hasLevel(level: LogLevel): boolean;
|
||||
loggingEnabled(): boolean;
|
||||
perftrc(s: string): void;
|
||||
info(s: string): void;
|
||||
startGroup(): void;
|
||||
endGroup(): void;
|
||||
msg(s: string, type?: Msg): void;
|
||||
getLogFileName(): string | undefined;
|
||||
}
|
||||
|
||||
// TODO: Use a const enum (https://github.com/Microsoft/TypeScript/issues/16804)
|
||||
export enum Msg {
|
||||
Err = "Err",
|
||||
Info = "Info",
|
||||
Perf = "Perf",
|
||||
}
|
||||
export namespace Msg {
|
||||
/** @deprecated Only here for backwards-compatibility. Prefer just `Msg`. */
|
||||
export type Types = Msg;
|
||||
}
|
||||
|
||||
export function createInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray<string>, cachePath?: string): DiscoverTypings {
|
||||
return {
|
||||
projectName: project.getProjectName(),
|
||||
fileNames: project.getFileNames(/*excludeFilesFromExternalLibraries*/ true, /*excludeConfigFiles*/ true).concat(project.getExcludedFiles() as NormalizedPath[]),
|
||||
compilerOptions: project.getCompilationSettings(),
|
||||
typeAcquisition,
|
||||
unresolvedImports,
|
||||
projectRootPath: project.getCurrentDirectory() as Path,
|
||||
cachePath,
|
||||
kind: "discover"
|
||||
};
|
||||
}
|
||||
|
||||
export namespace Errors {
|
||||
export function ThrowNoProject(): never {
|
||||
throw new Error("No Project.");
|
||||
}
|
||||
export function ThrowProjectLanguageServiceDisabled(): never {
|
||||
throw new Error("The project's language service is disabled.");
|
||||
}
|
||||
export function ThrowProjectDoesNotContainDocument(fileName: string, project: Project): never {
|
||||
throw new Error(`Project '${project.getProjectName()}' does not contain document '${fileName}'`);
|
||||
}
|
||||
}
|
||||
|
||||
export type NormalizedPath = string & { __normalizedPathTag: any };
|
||||
|
||||
export function toNormalizedPath(fileName: string): NormalizedPath {
|
||||
return <NormalizedPath>normalizePath(fileName);
|
||||
}
|
||||
|
||||
export function normalizedPathToPath(normalizedPath: NormalizedPath, currentDirectory: string, getCanonicalFileName: (f: string) => string): Path {
|
||||
const f = isRootedDiskPath(normalizedPath) ? normalizedPath : getNormalizedAbsolutePath(normalizedPath, currentDirectory);
|
||||
return <Path>getCanonicalFileName(f);
|
||||
}
|
||||
|
||||
export function asNormalizedPath(fileName: string): NormalizedPath {
|
||||
return <NormalizedPath>fileName;
|
||||
}
|
||||
|
||||
export interface NormalizedPathMap<T> {
|
||||
get(path: NormalizedPath): T | undefined;
|
||||
set(path: NormalizedPath, value: T): void;
|
||||
contains(path: NormalizedPath): boolean;
|
||||
remove(path: NormalizedPath): void;
|
||||
}
|
||||
|
||||
export function createNormalizedPathMap<T>(): NormalizedPathMap<T> {
|
||||
const map = createMap<T>();
|
||||
return {
|
||||
get(path) {
|
||||
return map.get(path);
|
||||
},
|
||||
set(path, value) {
|
||||
map.set(path, value);
|
||||
},
|
||||
contains(path) {
|
||||
return map.has(path);
|
||||
},
|
||||
remove(path) {
|
||||
map.delete(path);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export interface ProjectOptions {
|
||||
configHasExtendsProperty: boolean;
|
||||
/**
|
||||
* true if config file explicitly listed files
|
||||
*/
|
||||
configHasFilesProperty: boolean;
|
||||
configHasIncludeProperty: boolean;
|
||||
configHasExcludeProperty: boolean;
|
||||
}
|
||||
|
||||
export function isInferredProjectName(name: string) {
|
||||
// POSIX defines /dev/null as a device - there should be no file with this prefix
|
||||
return /dev\/null\/inferredProject\d+\*/.test(name);
|
||||
}
|
||||
|
||||
export function makeInferredProjectName(counter: number) {
|
||||
return `/dev/null/inferredProject${counter}*`;
|
||||
}
|
||||
|
||||
export function createSortedArray<T>(): SortedArray<T> {
|
||||
return [] as any as SortedArray<T>; // TODO: GH#19873
|
||||
}
|
||||
}
|
13
src/server/watchType.ts
Normal file
13
src/server/watchType.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* @internal */
|
||||
namespace ts {
|
||||
// Additional tsserver specific watch information
|
||||
export const enum WatchType {
|
||||
ClosedScriptInfo = "Closed Script info",
|
||||
ConfigFileForInferredRoot = "Config file for the inferred project root",
|
||||
NodeModulesForClosedScriptInfo = "node_modules for closed script infos in them",
|
||||
MissingSourceMapFile = "Missing source map file",
|
||||
NoopConfigFileForInferredRoot = "Noop Config file for the inferred project root",
|
||||
MissingGeneratedFile = "Missing generated file",
|
||||
PackageJsonFile = "package.json file for import suggestions"
|
||||
}
|
||||
}
|
7
src/services/exportAsModule.ts
Normal file
7
src/services/exportAsModule.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Here we expose the TypeScript services as an external module
|
||||
// so that it may be consumed easily like a node module.
|
||||
// @ts-ignore
|
||||
/* @internal */ declare const module: { exports: {} };
|
||||
if (typeof module !== "undefined" && module.exports) {
|
||||
module.exports = ts;
|
||||
}
|
File diff suppressed because it is too large
Load diff
50
src/services/globalThisShim.ts
Normal file
50
src/services/globalThisShim.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
// We polyfill `globalThis` here so re can reliably patch the global scope
|
||||
// in the contexts we want to in the same way across script and module formats
|
||||
|
||||
// https://mathiasbynens.be/notes/globalthis
|
||||
|
||||
// #region The polyfill starts here.
|
||||
((() => {
|
||||
if (typeof globalThis === "object") return;
|
||||
try {
|
||||
Object.defineProperty(Object.prototype, "__magic__", {
|
||||
get() {
|
||||
return this;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
//@ts-ignore
|
||||
__magic__.globalThis = __magic__;
|
||||
// The previous line should have made `globalThis` globally
|
||||
// available, but it fails in Internet Explorer 10 and older.
|
||||
// Detect this failure and fall back.
|
||||
if (typeof globalThis === "undefined") {
|
||||
// Assume `window` exists.
|
||||
//@ts-ignore
|
||||
window.globalThis = window;
|
||||
}
|
||||
//@ts-ignore
|
||||
delete Object.prototype.__magic__;
|
||||
}
|
||||
catch (error) {
|
||||
// In IE8, Object.defineProperty only works on DOM objects.
|
||||
// If we hit this code path, assume `window` exists.
|
||||
//@ts-ignore
|
||||
window.globalThis = window;
|
||||
}
|
||||
})());
|
||||
// #endregion The polyfill ends here.
|
||||
|
||||
// if `process` is undefined, we're probably not running in node - patch legacy members onto the global scope
|
||||
// @ts-ignore
|
||||
if (typeof process === "undefined" || process.browser) {
|
||||
/// TODO: this is used by VS, clean this up on both sides of the interface
|
||||
//@ts-ignore
|
||||
globalThis.TypeScript.Services.TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
|
||||
|
||||
// 'toolsVersion' gets consumed by the managed side, so it's not unused.
|
||||
// TODO: it should be moved into a namespace though.
|
||||
|
||||
//@ts-ignore
|
||||
globalThis.toolsVersion = ts.versionMajorMinor;
|
||||
}
|
|
@ -1266,25 +1266,6 @@ namespace ts {
|
|||
throw new Error("Invalid operation");
|
||||
}
|
||||
}
|
||||
|
||||
// Here we expose the TypeScript services as an external module
|
||||
// so that it may be consumed easily like a node module.
|
||||
declare const module: { exports: {} };
|
||||
if (typeof module !== "undefined" && module.exports) {
|
||||
module.exports = ts;
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable no-in-operator */
|
||||
|
||||
/// TODO: this is used by VS, clean this up on both sides of the interface
|
||||
/* @internal */
|
||||
namespace TypeScript.Services {
|
||||
export const TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
|
||||
}
|
||||
|
||||
// 'toolsVersion' gets consumed by the managed side, so it's not unused.
|
||||
// TODO: it should be moved into a namespace though.
|
||||
|
||||
/* @internal */
|
||||
const toolsVersion = ts.versionMajorMinor;
|
||||
/* eslint-enable no-in-operator */
|
|
@ -98,5 +98,7 @@
|
|||
"breakpoints.ts",
|
||||
"transform.ts",
|
||||
"shims.ts",
|
||||
"globalThisShim.ts",
|
||||
"exportAsModule.ts"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -8,9 +8,10 @@ interface PromiseConstructor {
|
|||
/* @internal */
|
||||
declare let Promise: PromiseConstructor;
|
||||
|
||||
// These utilities are common to multiple language service features.
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
// These utilities are common to multiple language service features.
|
||||
//#region
|
||||
export const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
|
||||
|
||||
export const enum SemanticMeaning {
|
||||
|
@ -1477,11 +1478,11 @@ namespace ts {
|
|||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Display-part writer helpers
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
// #endregion
|
||||
|
||||
// Display-part writer helpers
|
||||
// #region
|
||||
export function isFirstDeclarationOfSymbolParameter(symbol: Symbol) {
|
||||
return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter;
|
||||
}
|
||||
|
@ -2290,4 +2291,5 @@ namespace ts {
|
|||
export function isInsideNodeModules(fileOrDirectory: string): boolean {
|
||||
return contains(getPathComponents(fileOrDirectory), "node_modules");
|
||||
}
|
||||
}
|
||||
// #endregion
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
namespace ts {
|
||||
namespace ts.tscWatch {
|
||||
export const projects = `/user/username/projects`;
|
||||
export const projectRoot = `${projects}/myproject`;
|
||||
}
|
||||
namespace ts.tscWatch {
|
||||
export import WatchedSystem = TestFSWithWatch.TestServerHost;
|
||||
export type File = TestFSWithWatch.File;
|
||||
export type SymLink = TestFSWithWatch.SymLink;
|
||||
|
|
|
@ -803,19 +803,19 @@ namespace ts.projectSystem {
|
|||
|
||||
describe("unittests:: tsserver:: compileOnSave:: CompileOnSaveAffectedFileListRequest with and without projectFileName in request", () => {
|
||||
const core: File = {
|
||||
path: `${projectRoot}/core/core.ts`,
|
||||
path: `${tscWatch.projectRoot}/core/core.ts`,
|
||||
content: "let z = 10;"
|
||||
};
|
||||
const app1: File = {
|
||||
path: `${projectRoot}/app1/app.ts`,
|
||||
path: `${tscWatch.projectRoot}/app1/app.ts`,
|
||||
content: "let x = 10;"
|
||||
};
|
||||
const app2: File = {
|
||||
path: `${projectRoot}/app2/app.ts`,
|
||||
path: `${tscWatch.projectRoot}/app2/app.ts`,
|
||||
content: "let y = 10;"
|
||||
};
|
||||
const app1Config: File = {
|
||||
path: `${projectRoot}/app1/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/app1/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
files: ["app.ts", "../core/core.ts"],
|
||||
compilerOptions: { outFile: "build/output.js" },
|
||||
|
@ -823,7 +823,7 @@ namespace ts.projectSystem {
|
|||
})
|
||||
};
|
||||
const app2Config: File = {
|
||||
path: `${projectRoot}/app2/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/app2/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
files: ["app.ts", "../core/core.ts"],
|
||||
compilerOptions: { outFile: "build/output.js" },
|
||||
|
|
|
@ -83,17 +83,17 @@ namespace ts.projectSystem {
|
|||
|
||||
it("add and then remove a config file in a folder with loose files", () => {
|
||||
const configFile: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: `{
|
||||
"files": ["commonFile1.ts"]
|
||||
}`
|
||||
};
|
||||
const commonFile1: File = {
|
||||
path: `${projectRoot}/commonFile1.ts`,
|
||||
path: `${tscWatch.projectRoot}/commonFile1.ts`,
|
||||
content: "let x = 1"
|
||||
};
|
||||
const commonFile2: File = {
|
||||
path: `${projectRoot}/commonFile2.ts`,
|
||||
path: `${tscWatch.projectRoot}/commonFile2.ts`,
|
||||
content: "let y = 1"
|
||||
};
|
||||
|
||||
|
@ -109,7 +109,7 @@ namespace ts.projectSystem {
|
|||
checkProjectActualFiles(projectService.inferredProjects[0], [commonFile1.path, libFile.path]);
|
||||
checkProjectActualFiles(projectService.inferredProjects[1], [commonFile2.path, libFile.path]);
|
||||
|
||||
const watchedFiles = getConfigFilesToWatch(projectRoot).concat(libFile.path);
|
||||
const watchedFiles = getConfigFilesToWatch(tscWatch.projectRoot).concat(libFile.path);
|
||||
checkWatchedFiles(host, watchedFiles);
|
||||
|
||||
// Add a tsconfig file
|
||||
|
@ -440,19 +440,19 @@ namespace ts.projectSystem {
|
|||
|
||||
it("open file become a part of configured project if it is referenced from root file", () => {
|
||||
const file1 = {
|
||||
path: `${projectRoot}/a/b/f1.ts`,
|
||||
path: `${tscWatch.projectRoot}/a/b/f1.ts`,
|
||||
content: "export let x = 5"
|
||||
};
|
||||
const file2 = {
|
||||
path: `${projectRoot}/a/c/f2.ts`,
|
||||
path: `${tscWatch.projectRoot}/a/c/f2.ts`,
|
||||
content: `import {x} from "../b/f1"`
|
||||
};
|
||||
const file3 = {
|
||||
path: `${projectRoot}/a/c/f3.ts`,
|
||||
path: `${tscWatch.projectRoot}/a/c/f3.ts`,
|
||||
content: "export let y = 1"
|
||||
};
|
||||
const configFile = {
|
||||
path: `${projectRoot}/a/c/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/a/c/tsconfig.json`,
|
||||
content: JSON.stringify({ compilerOptions: {}, files: ["f2.ts", "f3.ts"] })
|
||||
};
|
||||
|
||||
|
@ -847,7 +847,7 @@ namespace ts.projectSystem {
|
|||
|
||||
it("when multiple projects are open, detects correct default project", () => {
|
||||
const barConfig: File = {
|
||||
path: `${projectRoot}/bar/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/bar/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
include: ["index.ts"],
|
||||
compilerOptions: {
|
||||
|
@ -856,14 +856,14 @@ namespace ts.projectSystem {
|
|||
})
|
||||
};
|
||||
const barIndex: File = {
|
||||
path: `${projectRoot}/bar/index.ts`,
|
||||
path: `${tscWatch.projectRoot}/bar/index.ts`,
|
||||
content: `
|
||||
export function bar() {
|
||||
console.log("hello world");
|
||||
}`
|
||||
};
|
||||
const fooConfig: File = {
|
||||
path: `${projectRoot}/foo/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/foo/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
include: ["index.ts"],
|
||||
compilerOptions: {
|
||||
|
@ -872,14 +872,14 @@ export function bar() {
|
|||
})
|
||||
};
|
||||
const fooIndex: File = {
|
||||
path: `${projectRoot}/foo/index.ts`,
|
||||
path: `${tscWatch.projectRoot}/foo/index.ts`,
|
||||
content: `
|
||||
import { bar } from "bar";
|
||||
bar();`
|
||||
};
|
||||
const barSymLink: SymLink = {
|
||||
path: `${projectRoot}/foo/node_modules/bar`,
|
||||
symLink: `${projectRoot}/bar`
|
||||
path: `${tscWatch.projectRoot}/foo/node_modules/bar`,
|
||||
symLink: `${tscWatch.projectRoot}/bar`
|
||||
};
|
||||
|
||||
const lib2017: File = {
|
||||
|
@ -963,11 +963,11 @@ declare var console: {
|
|||
|
||||
it("should tolerate invalid include files that start in subDirectory", () => {
|
||||
const f = {
|
||||
path: `${projectRoot}/src/server/index.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/server/index.ts`,
|
||||
content: "let x = 1"
|
||||
};
|
||||
const config = {
|
||||
path: `${projectRoot}/src/server/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/src/server/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compiler: {
|
||||
module: "commonjs",
|
||||
|
|
|
@ -2,15 +2,15 @@ namespace ts.projectSystem {
|
|||
describe("unittests:: tsserver:: document registry in project service", () => {
|
||||
const importModuleContent = `import {a} from "./module1"`;
|
||||
const file: File = {
|
||||
path: `${projectRoot}/index.ts`,
|
||||
path: `${tscWatch.projectRoot}/index.ts`,
|
||||
content: importModuleContent
|
||||
};
|
||||
const moduleFile: File = {
|
||||
path: `${projectRoot}/module1.d.ts`,
|
||||
path: `${tscWatch.projectRoot}/module1.d.ts`,
|
||||
content: "export const a: number;"
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({ files: ["index.ts"] })
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace ts.projectSystem {
|
|||
|
||||
function createSessionWithEventHandler(files: File[], useLargeTsFile: boolean) {
|
||||
const largeFile: File = {
|
||||
path: `${projectRoot}/${getLargeFile(useLargeTsFile)}`,
|
||||
path: `${tscWatch.projectRoot}/${getLargeFile(useLargeTsFile)}`,
|
||||
content: "export var x = 10;",
|
||||
fileSize: server.maxFileSize + 1
|
||||
};
|
||||
|
@ -35,11 +35,11 @@ namespace ts.projectSystem {
|
|||
function verifyLargeFile(useLargeTsFile: boolean) {
|
||||
it("when large file is included by tsconfig", () => {
|
||||
const file: File = {
|
||||
path: `${projectRoot}/src/file.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/file.ts`,
|
||||
content: "export var y = 10;"
|
||||
};
|
||||
const tsconfig: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({ files: ["src/file.ts", getLargeFile(useLargeTsFile)], compilerOptions: { target: 1, allowJs: true } })
|
||||
};
|
||||
const files = [file, libFile, tsconfig];
|
||||
|
@ -52,7 +52,7 @@ namespace ts.projectSystem {
|
|||
|
||||
it("when large file is included by module resolution", () => {
|
||||
const file: File = {
|
||||
path: `${projectRoot}/src/file.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/file.ts`,
|
||||
content: `export var y = 10;import {x} from "./large"`
|
||||
};
|
||||
const files = [file, libFile];
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: events:: ProjectLoadingStart and ProjectLoadingFinish events", () => {
|
||||
const aTs: File = {
|
||||
path: `${projects}/a/a.ts`,
|
||||
path: `${tscWatch.projects}/a/a.ts`,
|
||||
content: "export class A { }"
|
||||
};
|
||||
const configA: File = {
|
||||
path: `${projects}/a/tsconfig.json`,
|
||||
path: `${tscWatch.projects}/a/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const bTsPath = `${projects}/b/b.ts`;
|
||||
const configBPath = `${projects}/b/tsconfig.json`;
|
||||
const bTsPath = `${tscWatch.projects}/b/b.ts`;
|
||||
const configBPath = `${tscWatch.projects}/b/tsconfig.json`;
|
||||
const files = [libFile, aTs, configA];
|
||||
|
||||
function verifyProjectLoadingStartAndFinish(createSession: (host: TestServerHost) => {
|
||||
|
@ -83,14 +83,14 @@ namespace ts.projectSystem {
|
|||
|
||||
function verify(disableSourceOfProjectReferenceRedirect?: true) {
|
||||
const aDTs: File = {
|
||||
path: `${projects}/a/a.d.ts`,
|
||||
path: `${tscWatch.projects}/a/a.d.ts`,
|
||||
content: `export declare class A {
|
||||
}
|
||||
//# sourceMappingURL=a.d.ts.map
|
||||
`
|
||||
};
|
||||
const aDTsMap: File = {
|
||||
path: `${projects}/a/a.d.ts.map`,
|
||||
path: `${tscWatch.projects}/a/a.d.ts.map`,
|
||||
content: `{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["./a.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;CAAI"}`
|
||||
};
|
||||
const bTs: File = {
|
||||
|
@ -133,7 +133,7 @@ namespace ts.projectSystem {
|
|||
});
|
||||
|
||||
describe("with external projects and config files ", () => {
|
||||
const projectFileName = `${projects}/a/project.csproj`;
|
||||
const projectFileName = `${tscWatch.projects}/a/project.csproj`;
|
||||
|
||||
function createSession(lazyConfiguredProjectsFromExternalProject: boolean) {
|
||||
const { session, service, verifyEvent: verifyEventWorker, getNumberOfEvents } = createSessionToVerifyEvent(files);
|
||||
|
|
|
@ -824,9 +824,9 @@ namespace ts.projectSystem {
|
|||
});
|
||||
|
||||
it("handles creation of external project with jsconfig before jsconfig creation watcher is invoked", () => {
|
||||
const projectFileName = `${projectRoot}/WebApplication36.csproj`;
|
||||
const projectFileName = `${tscWatch.projectRoot}/WebApplication36.csproj`;
|
||||
const tsconfig: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const files = [libFile, tsconfig];
|
||||
|
@ -844,7 +844,7 @@ namespace ts.projectSystem {
|
|||
checkProjectActualFiles(configProject, [tsconfig.path]);
|
||||
|
||||
// write js file, open external project and open it for edit
|
||||
const jsFilePath = `${projectRoot}/javascript.js`;
|
||||
const jsFilePath = `${tscWatch.projectRoot}/javascript.js`;
|
||||
host.writeFile(jsFilePath, "");
|
||||
service.openExternalProjects([{
|
||||
projectFileName,
|
||||
|
@ -859,7 +859,7 @@ namespace ts.projectSystem {
|
|||
|
||||
// write jsconfig file
|
||||
const jsConfig: File = {
|
||||
path: `${projectRoot}/jsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/jsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
// Dont invoke file creation watchers as the repro suggests
|
||||
|
|
|
@ -2,7 +2,7 @@ namespace ts.projectSystem {
|
|||
describe("unittests:: tsserver:: Inferred projects", () => {
|
||||
it("create inferred project", () => {
|
||||
const appFile: File = {
|
||||
path: `${projectRoot}/app.ts`,
|
||||
path: `${tscWatch.projectRoot}/app.ts`,
|
||||
content: `
|
||||
import {f} from "./module"
|
||||
console.log(f)
|
||||
|
@ -10,7 +10,7 @@ namespace ts.projectSystem {
|
|||
};
|
||||
|
||||
const moduleFile: File = {
|
||||
path: `${projectRoot}/module.d.ts`,
|
||||
path: `${tscWatch.projectRoot}/module.d.ts`,
|
||||
content: `export let x: number`
|
||||
};
|
||||
const host = createServerHost([appFile, moduleFile, libFile]);
|
||||
|
@ -24,18 +24,18 @@ namespace ts.projectSystem {
|
|||
const project = projectService.inferredProjects[0];
|
||||
|
||||
checkArray("inferred project", project.getFileNames(), [appFile.path, libFile.path, moduleFile.path]);
|
||||
checkWatchedFiles(host, getConfigFilesToWatch(projectRoot).concat(libFile.path, moduleFile.path));
|
||||
checkWatchedDirectories(host, [projectRoot], /*recursive*/ false);
|
||||
checkWatchedDirectories(host, [combinePaths(projectRoot, nodeModulesAtTypes)], /*recursive*/ true);
|
||||
checkWatchedFiles(host, getConfigFilesToWatch(tscWatch.projectRoot).concat(libFile.path, moduleFile.path));
|
||||
checkWatchedDirectories(host, [tscWatch.projectRoot], /*recursive*/ false);
|
||||
checkWatchedDirectories(host, [combinePaths(tscWatch.projectRoot, nodeModulesAtTypes)], /*recursive*/ true);
|
||||
});
|
||||
|
||||
it("should use only one inferred project if 'useOneInferredProject' is set", () => {
|
||||
const file1 = {
|
||||
path: `${projectRoot}/a/b/main.ts`,
|
||||
path: `${tscWatch.projectRoot}/a/b/main.ts`,
|
||||
content: "let x =1;"
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${projectRoot}/a/b/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/a/b/tsconfig.json`,
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"target": "es6"
|
||||
|
@ -44,12 +44,12 @@ namespace ts.projectSystem {
|
|||
}`
|
||||
};
|
||||
const file2 = {
|
||||
path: `${projectRoot}/a/c/main.ts`,
|
||||
path: `${tscWatch.projectRoot}/a/c/main.ts`,
|
||||
content: "let x =1;"
|
||||
};
|
||||
|
||||
const file3 = {
|
||||
path: `${projectRoot}/a/d/main.ts`,
|
||||
path: `${tscWatch.projectRoot}/a/d/main.ts`,
|
||||
content: "let x =1;"
|
||||
};
|
||||
|
||||
|
@ -346,19 +346,19 @@ namespace ts.projectSystem {
|
|||
|
||||
it("should still retain configured project created while opening the file", () => {
|
||||
const appFile: File = {
|
||||
path: `${projectRoot}/app.ts`,
|
||||
path: `${tscWatch.projectRoot}/app.ts`,
|
||||
content: `const app = 20;`
|
||||
};
|
||||
const config: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const jsFile1: File = {
|
||||
path: `${projectRoot}/jsFile1.js`,
|
||||
path: `${tscWatch.projectRoot}/jsFile1.js`,
|
||||
content: `const jsFile1 = 10;`
|
||||
};
|
||||
const jsFile2: File = {
|
||||
path: `${projectRoot}/jsFile2.js`,
|
||||
path: `${tscWatch.projectRoot}/jsFile2.js`,
|
||||
content: `const jsFile2 = 10;`
|
||||
};
|
||||
const host = createServerHost([appFile, libFile, config, jsFile1, jsFile2]);
|
||||
|
|
|
@ -390,31 +390,31 @@ namespace ts.projectSystem {
|
|||
|
||||
it("Reports errors correctly when file referenced by inferred project root, is opened right after closing the root file", () => {
|
||||
const app: File = {
|
||||
path: `${projectRoot}/src/client/app.js`,
|
||||
path: `${tscWatch.projectRoot}/src/client/app.js`,
|
||||
content: ""
|
||||
};
|
||||
const serverUtilities: File = {
|
||||
path: `${projectRoot}/src/server/utilities.js`,
|
||||
path: `${tscWatch.projectRoot}/src/server/utilities.js`,
|
||||
content: `function getHostName() { return "hello"; } export { getHostName };`
|
||||
};
|
||||
const backendTest: File = {
|
||||
path: `${projectRoot}/test/backend/index.js`,
|
||||
path: `${tscWatch.projectRoot}/test/backend/index.js`,
|
||||
content: `import { getHostName } from '../../src/server/utilities';export default getHostName;`
|
||||
};
|
||||
const files = [libFile, app, serverUtilities, backendTest];
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true, canUseEvents: true });
|
||||
openFilesForSession([{ file: app, projectRootPath: projectRoot }], session);
|
||||
openFilesForSession([{ file: app, projectRootPath: tscWatch.projectRoot }], session);
|
||||
const service = session.getProjectService();
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [libFile.path, app.path]);
|
||||
openFilesForSession([{ file: backendTest, projectRootPath: projectRoot }], session);
|
||||
openFilesForSession([{ file: backendTest, projectRootPath: tscWatch.projectRoot }], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
checkProjectActualFiles(project, files.map(f => f.path));
|
||||
checkErrors([backendTest.path, app.path]);
|
||||
closeFilesForSession([backendTest], session);
|
||||
openFilesForSession([{ file: serverUtilities.path, projectRootPath: projectRoot }], session);
|
||||
openFilesForSession([{ file: serverUtilities.path, projectRootPath: tscWatch.projectRoot }], session);
|
||||
checkErrors([serverUtilities.path, app.path]);
|
||||
|
||||
function checkErrors(openFiles: [string, string]) {
|
||||
|
@ -865,17 +865,17 @@ declare module '@custom/plugin' {
|
|||
describe("unittests:: tsserver:: Project Errors with resolveJsonModule", () => {
|
||||
function createSessionForTest({ include }: { include: readonly string[]; }) {
|
||||
const test: File = {
|
||||
path: `${projectRoot}/src/test.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/test.ts`,
|
||||
content: `import * as blabla from "./blabla.json";
|
||||
declare var console: any;
|
||||
console.log(blabla);`
|
||||
};
|
||||
const blabla: File = {
|
||||
path: `${projectRoot}/src/blabla.json`,
|
||||
path: `${tscWatch.projectRoot}/src/blabla.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const tsconfig: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
resolveJsonModule: true,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: with project references and compile on save", () => {
|
||||
const dependecyLocation = `${projectRoot}/dependency`;
|
||||
const usageLocation = `${projectRoot}/usage`;
|
||||
const dependecyLocation = `${tscWatch.projectRoot}/dependency`;
|
||||
const usageLocation = `${tscWatch.projectRoot}/usage`;
|
||||
const dependencyTs: File = {
|
||||
path: `${dependecyLocation}/fns.ts`,
|
||||
content: `export function fn1() { }
|
||||
|
@ -293,7 +293,7 @@ exports.fn2 = fn2;
|
|||
${appendJs}`
|
||||
},
|
||||
{
|
||||
path: `${projectRoot}/decls/fns.d.ts`,
|
||||
path: `${tscWatch.projectRoot}/decls/fns.d.ts`,
|
||||
content: `export declare function fn1(): void;
|
||||
export declare function fn2(): void;
|
||||
${appendDts}`
|
||||
|
|
|
@ -85,8 +85,8 @@ namespace ts.projectSystem {
|
|||
}
|
||||
|
||||
describe("unittests:: tsserver:: with project references and error reporting", () => {
|
||||
const dependecyLocation = `${projectRoot}/dependency`;
|
||||
const usageLocation = `${projectRoot}/usage`;
|
||||
const dependecyLocation = `${tscWatch.projectRoot}/dependency`;
|
||||
const usageLocation = `${tscWatch.projectRoot}/usage`;
|
||||
|
||||
function verifyErrorsUsingGeterr({ allFiles, openFiles, expectedGetErr }: VerifyScenario) {
|
||||
it("verifies the errors in open file", () => {
|
||||
|
|
|
@ -92,9 +92,9 @@ namespace ts.projectSystem {
|
|||
});
|
||||
|
||||
describe("with main and depedency project", () => {
|
||||
const dependecyLocation = `${projectRoot}/dependency`;
|
||||
const dependecyDeclsLocation = `${projectRoot}/decls`;
|
||||
const mainLocation = `${projectRoot}/main`;
|
||||
const dependecyLocation = `${tscWatch.projectRoot}/dependency`;
|
||||
const dependecyDeclsLocation = `${tscWatch.projectRoot}/decls`;
|
||||
const mainLocation = `${tscWatch.projectRoot}/main`;
|
||||
const dependencyTs: File = {
|
||||
path: `${dependecyLocation}/FnS.ts`,
|
||||
content: `export function fn1() { }
|
||||
|
@ -136,11 +136,11 @@ fn5();
|
|||
};
|
||||
|
||||
const randomFile: File = {
|
||||
path: `${projectRoot}/random/random.ts`,
|
||||
path: `${tscWatch.projectRoot}/random/random.ts`,
|
||||
content: "let a = 10;"
|
||||
};
|
||||
const randomConfig: File = {
|
||||
path: `${projectRoot}/random/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/random/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const dtsLocation = `${dependecyDeclsLocation}/FnS.d.ts`;
|
||||
|
@ -1302,7 +1302,7 @@ function foo() {
|
|||
|
||||
it("reusing d.ts files from composite and non composite projects", () => {
|
||||
const configA: File = {
|
||||
path: `${projectRoot}/compositea/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/compositea/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
|
@ -1314,27 +1314,27 @@ function foo() {
|
|||
})
|
||||
};
|
||||
const aTs: File = {
|
||||
path: `${projectRoot}/compositea/a.ts`,
|
||||
path: `${tscWatch.projectRoot}/compositea/a.ts`,
|
||||
content: `import { b } from "@ref/compositeb/b";`
|
||||
};
|
||||
const a2Ts: File = {
|
||||
path: `${projectRoot}/compositea/a2.ts`,
|
||||
path: `${tscWatch.projectRoot}/compositea/a2.ts`,
|
||||
content: `export const x = 10;`
|
||||
};
|
||||
const configB: File = {
|
||||
path: `${projectRoot}/compositeb/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/compositeb/tsconfig.json`,
|
||||
content: configA.content
|
||||
};
|
||||
const bTs: File = {
|
||||
path: `${projectRoot}/compositeb/b.ts`,
|
||||
path: `${tscWatch.projectRoot}/compositeb/b.ts`,
|
||||
content: "export function b() {}"
|
||||
};
|
||||
const bDts: File = {
|
||||
path: `${projectRoot}/dist/compositeb/b.d.ts`,
|
||||
path: `${tscWatch.projectRoot}/dist/compositeb/b.d.ts`,
|
||||
content: "export declare function b(): void;"
|
||||
};
|
||||
const configC: File = {
|
||||
path: `${projectRoot}/compositec/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/compositec/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
|
@ -1347,7 +1347,7 @@ function foo() {
|
|||
})
|
||||
};
|
||||
const cTs: File = {
|
||||
path: `${projectRoot}/compositec/c.ts`,
|
||||
path: `${tscWatch.projectRoot}/compositec/c.ts`,
|
||||
content: aTs.content
|
||||
};
|
||||
const files = [libFile, aTs, a2Ts, configA, bDts, bTs, configB, cTs, configC];
|
||||
|
@ -1407,8 +1407,8 @@ function foo() {
|
|||
const aConfig = config("A", extraOptions, ["../B"]);
|
||||
const bConfig = config("B", extraOptions);
|
||||
const bSymlink: SymLink = {
|
||||
path: `${projectRoot}/node_modules/b`,
|
||||
symLink: `${projectRoot}/packages/B`
|
||||
path: `${tscWatch.projectRoot}/node_modules/b`,
|
||||
symLink: `${tscWatch.projectRoot}/packages/B`
|
||||
};
|
||||
const files = [libFile, bPackageJson, aConfig, bConfig, aTest, bFoo, bBar, bSymlink];
|
||||
const host = alreadyBuilt ?
|
||||
|
@ -1436,7 +1436,7 @@ function foo() {
|
|||
|
||||
function config(packageName: string, extraOptions: CompilerOptions, references?: string[]): File {
|
||||
return {
|
||||
path: `${projectRoot}/packages/${packageName}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/packages/${packageName}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
outDir: "lib",
|
||||
|
@ -1452,7 +1452,7 @@ function foo() {
|
|||
|
||||
function file(packageName: string, fileName: string, content: string): File {
|
||||
return {
|
||||
path: `${projectRoot}/packages/${packageName}/src/${fileName}`,
|
||||
path: `${tscWatch.projectRoot}/packages/${packageName}/src/${fileName}`,
|
||||
content
|
||||
};
|
||||
}
|
||||
|
@ -1460,7 +1460,7 @@ function foo() {
|
|||
describe("when packageJson has types field and has index.ts", () => {
|
||||
verifySymlinkScenario(() => ({
|
||||
bPackageJson: {
|
||||
path: `${projectRoot}/packages/B/package.json`,
|
||||
path: `${tscWatch.projectRoot}/packages/B/package.json`,
|
||||
content: JSON.stringify({
|
||||
main: "lib/index.js",
|
||||
types: "lib/index.d.ts"
|
||||
|
@ -1478,7 +1478,7 @@ bar();`),
|
|||
describe("when referencing file from subFolder", () => {
|
||||
verifySymlinkScenario(() => ({
|
||||
bPackageJson: {
|
||||
path: `${projectRoot}/packages/B/package.json`,
|
||||
path: `${tscWatch.projectRoot}/packages/B/package.json`,
|
||||
content: "{}"
|
||||
},
|
||||
aTest: file("A", "test.ts", `import { foo } from 'b/lib/foo';
|
||||
|
|
|
@ -1137,17 +1137,17 @@ var x = 10;`
|
|||
content: "var x = 10;"
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const configProjectFile: File = {
|
||||
path: `${projectRoot}/a.ts`,
|
||||
path: `${tscWatch.projectRoot}/a.ts`,
|
||||
content: "let y = 10;"
|
||||
};
|
||||
it("with useInferredProjectPerProjectRoot", () => {
|
||||
const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true });
|
||||
const session = createSession(host, { useInferredProjectPerProjectRoot: true });
|
||||
openFilesForSession([{ file: file.path, projectRootPath: projectRoot }], session);
|
||||
openFilesForSession([{ file: file.path, projectRootPath: tscWatch.projectRoot }], session);
|
||||
|
||||
const projectService = session.getProjectService();
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1 });
|
||||
|
@ -1172,7 +1172,7 @@ var x = 10;`
|
|||
const host = createServerHost([libFile, configFile, configProjectFile], { useCaseSensitiveFileNames: true });
|
||||
const projectService = createProjectService(host);
|
||||
try {
|
||||
projectService.openClientFile(file.path, file.content, /*scriptKind*/ undefined, projectRoot);
|
||||
projectService.openClientFile(file.path, file.content, /*scriptKind*/ undefined, tscWatch.projectRoot);
|
||||
}
|
||||
catch (e) {
|
||||
assert.strictEqual(
|
||||
|
@ -1266,15 +1266,15 @@ var x = 10;`
|
|||
|
||||
it("requests are done on file on pendingReload but has svc for previous version", () => {
|
||||
const file1: File = {
|
||||
path: `${projectRoot}/src/file1.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/file1.ts`,
|
||||
content: `import { y } from "./file2"; let x = 10;`
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectRoot}/src/file2.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/file2.ts`,
|
||||
content: "export let y = 10;"
|
||||
};
|
||||
const config: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const files = [file1, file2, libFile, config];
|
||||
|
@ -1365,18 +1365,18 @@ var x = 10;`
|
|||
|
||||
it("Orphan source files are handled correctly on watch trigger", () => {
|
||||
const file1: File = {
|
||||
path: `${projectRoot}/src/file1.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/file1.ts`,
|
||||
content: `export let x = 10;`
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectRoot}/src/file2.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/file2.ts`,
|
||||
content: "export let y = 10;"
|
||||
};
|
||||
const configContent1 = JSON.stringify({
|
||||
files: ["src/file1.ts", "src/file2.ts"]
|
||||
});
|
||||
const config: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: configContent1
|
||||
};
|
||||
const files = [file1, file2, libFile, config];
|
||||
|
|
|
@ -451,7 +451,7 @@ namespace ts.projectSystem {
|
|||
|
||||
describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem module resolution caching", () => {
|
||||
const configFile: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: JSON.stringify({ compilerOptions: { traceResolution: true } })
|
||||
};
|
||||
|
||||
|
@ -558,7 +558,7 @@ namespace ts.projectSystem {
|
|||
}
|
||||
|
||||
function verifyWatchesWithConfigFile(host: TestServerHost, files: File[], openFile: File, extraExpectedDirectories?: readonly string[]) {
|
||||
const expectedRecursiveDirectories = arrayToSet([projectRoot, `${projectRoot}/${nodeModulesAtTypes}`, ...(extraExpectedDirectories || emptyArray)]);
|
||||
const expectedRecursiveDirectories = arrayToSet([tscWatch.projectRoot, `${tscWatch.projectRoot}/${nodeModulesAtTypes}`, ...(extraExpectedDirectories || emptyArray)]);
|
||||
checkWatchedFiles(host, mapDefined(files, f => {
|
||||
if (f === openFile) {
|
||||
return undefined;
|
||||
|
@ -577,11 +577,11 @@ namespace ts.projectSystem {
|
|||
describe("from files in same folder", () => {
|
||||
function getFiles(fileContent: string) {
|
||||
const file1: File = {
|
||||
path: `${projectRoot}/src/file1.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/file1.ts`,
|
||||
content: fileContent
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectRoot}/src/file2.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/file2.ts`,
|
||||
content: fileContent
|
||||
};
|
||||
return { file1, file2 };
|
||||
|
@ -592,7 +592,7 @@ namespace ts.projectSystem {
|
|||
const module2Name = "../module2";
|
||||
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2 } = getFiles(fileContent);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/src/module1.ts`, `${projectRoot}/module2.ts`);
|
||||
const { module1, module2 } = getModules(`${tscWatch.projectRoot}/src/module1.ts`, `${tscWatch.projectRoot}/module2.ts`);
|
||||
const files = [module1, module2, file1, file2, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
|
@ -615,12 +615,12 @@ namespace ts.projectSystem {
|
|||
});
|
||||
|
||||
it("non relative module name", () => {
|
||||
const expectedNonRelativeDirectories = [`${projectRoot}/node_modules`, `${projectRoot}/src`];
|
||||
const expectedNonRelativeDirectories = [`${tscWatch.projectRoot}/node_modules`, `${tscWatch.projectRoot}/src`];
|
||||
const module1Name = "module1";
|
||||
const module2Name = "module2";
|
||||
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2 } = getFiles(fileContent);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/src/node_modules/module1/index.ts`, `${projectRoot}/node_modules/module2/index.ts`);
|
||||
const { module1, module2 } = getModules(`${tscWatch.projectRoot}/src/node_modules/module1/index.ts`, `${tscWatch.projectRoot}/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, file2, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
|
@ -646,19 +646,19 @@ namespace ts.projectSystem {
|
|||
describe("from files in different folders", () => {
|
||||
function getFiles(fileContent1: string, fileContent2 = fileContent1, fileContent3 = fileContent1, fileContent4 = fileContent1) {
|
||||
const file1: File = {
|
||||
path: `${projectRoot}/product/src/file1.ts`,
|
||||
path: `${tscWatch.projectRoot}/product/src/file1.ts`,
|
||||
content: fileContent1
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectRoot}/product/src/feature/file2.ts`,
|
||||
path: `${tscWatch.projectRoot}/product/src/feature/file2.ts`,
|
||||
content: fileContent2
|
||||
};
|
||||
const file3: File = {
|
||||
path: `${projectRoot}/product/test/src/file3.ts`,
|
||||
path: `${tscWatch.projectRoot}/product/test/src/file3.ts`,
|
||||
content: fileContent3
|
||||
};
|
||||
const file4: File = {
|
||||
path: `${projectRoot}/product/test/file4.ts`,
|
||||
path: `${tscWatch.projectRoot}/product/test/file4.ts`,
|
||||
content: fileContent4
|
||||
};
|
||||
return { file1, file2, file3, file4 };
|
||||
|
@ -676,7 +676,7 @@ namespace ts.projectSystem {
|
|||
const fileContent3 = `import { module1 } from "${module5Name}";import { module2 } from "${module4Name}";`;
|
||||
const fileContent4 = `import { module1 } from "${module6Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2, file3, file4 } = getFiles(fileContent1, fileContent2, fileContent3, fileContent4);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/product/src/module1.ts`, `${projectRoot}/product/module2.ts`);
|
||||
const { module1, module2 } = getModules(`${tscWatch.projectRoot}/product/src/module1.ts`, `${tscWatch.projectRoot}/product/module2.ts`);
|
||||
const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
|
@ -708,12 +708,12 @@ namespace ts.projectSystem {
|
|||
});
|
||||
|
||||
it("non relative module name", () => {
|
||||
const expectedNonRelativeDirectories = [`${projectRoot}/node_modules`, `${projectRoot}/product`];
|
||||
const expectedNonRelativeDirectories = [`${tscWatch.projectRoot}/node_modules`, `${tscWatch.projectRoot}/product`];
|
||||
const module1Name = "module1";
|
||||
const module2Name = "module2";
|
||||
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2, file3, file4 } = getFiles(fileContent);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/product/node_modules/module1/index.ts`, `${projectRoot}/node_modules/module2/index.ts`);
|
||||
const { module1, module2 } = getModules(`${tscWatch.projectRoot}/product/node_modules/module1/index.ts`, `${tscWatch.projectRoot}/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, file2, file3, file4, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
|
@ -723,8 +723,8 @@ namespace ts.projectSystem {
|
|||
getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module1, module1Name, getDirectoryPath(file1.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module2, module2Name, getDirectoryPath(file1.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${tscWatch.projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${tscWatch.projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module1, module1Name, getDirectoryPath(file4.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module2, module2Name, getDirectoryPath(file4.path), expectedTrace);
|
||||
verifyTrace(resolutionTrace, expectedTrace);
|
||||
|
@ -752,7 +752,7 @@ namespace ts.projectSystem {
|
|||
const file4Name = "../test/file4";
|
||||
const importModuleContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const { file1, file2, file3, file4 } = getFiles(`import "${file2Name}"; import "${file4Name}"; import "${file3Name}"; ${importModuleContent}`, importModuleContent, importModuleContent, importModuleContent);
|
||||
const { module1, module2 } = getModules(`${projectRoot}/product/node_modules/module1/index.ts`, `${projectRoot}/node_modules/module2/index.ts`);
|
||||
const { module1, module2 } = getModules(`${tscWatch.projectRoot}/product/node_modules/module1/index.ts`, `${tscWatch.projectRoot}/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, file2, file3, file4, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
|
@ -766,19 +766,19 @@ namespace ts.projectSystem {
|
|||
getExpectedNonRelativeModuleResolutionTrace(host, file1, module2, module2Name, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module1, module1Name, getDirectoryPath(file1.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file2, module2, module2Name, getDirectoryPath(file1.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module1, module1Name, `${tscWatch.projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file4, module2, module2Name, `${tscWatch.projectRoot}/product`, expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module1, module1Name, getDirectoryPath(file4.path), expectedTrace);
|
||||
getExpectedNonRelativeModuleResolutionFromCacheTrace(host, file3, module2, module2Name, getDirectoryPath(file4.path), expectedTrace);
|
||||
verifyTrace(resolutionTrace, expectedTrace);
|
||||
|
||||
const currentDirectory = getDirectoryPath(file1.path);
|
||||
const watchedFiles = mapDefined(files, f => f === file1 || f.path.indexOf("/node_modules/") !== -1 ? undefined : f.path)
|
||||
.concat(getConfigFilesToWatch(`${projectRoot}/product/src`));
|
||||
.concat(getConfigFilesToWatch(`${tscWatch.projectRoot}/product/src`));
|
||||
const watchedRecursiveDirectories = getTypeRootsFromLocation(currentDirectory).concat([
|
||||
`${currentDirectory}/node_modules`, `${currentDirectory}/feature`, `${projectRoot}/product/${nodeModules}`,
|
||||
`${projectRoot}/${nodeModules}`, `${projectRoot}/product/test/${nodeModules}`,
|
||||
`${projectRoot}/product/test/src/${nodeModules}`
|
||||
`${currentDirectory}/node_modules`, `${currentDirectory}/feature`, `${tscWatch.projectRoot}/product/${nodeModules}`,
|
||||
`${tscWatch.projectRoot}/${nodeModules}`, `${tscWatch.projectRoot}/product/test/${nodeModules}`,
|
||||
`${tscWatch.projectRoot}/product/test/src/${nodeModules}`
|
||||
]);
|
||||
checkWatches();
|
||||
|
||||
|
@ -808,7 +808,7 @@ namespace ts.projectSystem {
|
|||
|
||||
describe("when watching directories for failed lookup locations in amd resolution", () => {
|
||||
const nodeFile: File = {
|
||||
path: `${projectRoot}/src/typings/node.d.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/typings/node.d.ts`,
|
||||
content: `
|
||||
declare module "fs" {
|
||||
export interface something {
|
||||
|
@ -816,7 +816,7 @@ declare module "fs" {
|
|||
}`
|
||||
};
|
||||
const electronFile: File = {
|
||||
path: `${projectRoot}/src/typings/electron.d.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/typings/electron.d.ts`,
|
||||
content: `
|
||||
declare module 'original-fs' {
|
||||
import * as fs from 'fs';
|
||||
|
@ -824,19 +824,19 @@ declare module 'original-fs' {
|
|||
}`
|
||||
};
|
||||
const srcFile: File = {
|
||||
path: `${projectRoot}/src/somefolder/srcfile.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/somefolder/srcfile.ts`,
|
||||
content: `
|
||||
import { x } from "somefolder/module1";
|
||||
import { x } from "somefolder/module2";
|
||||
const y = x;`
|
||||
};
|
||||
const moduleFile: File = {
|
||||
path: `${projectRoot}/src/somefolder/module1.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/somefolder/module1.ts`,
|
||||
content: `
|
||||
export const x = 10;`
|
||||
};
|
||||
const configFile: File = {
|
||||
path: `${projectRoot}/src/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/src/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: {
|
||||
module: "amd",
|
||||
|
@ -853,22 +853,22 @@ export const x = 10;`
|
|||
const files = [...(useNodeFile ? [nodeFile] : []), electronFile, srcFile, moduleFile, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host);
|
||||
service.openClientFile(srcFile.path, srcFile.content, ScriptKind.TS, projectRoot);
|
||||
service.openClientFile(srcFile.path, srcFile.content, ScriptKind.TS, tscWatch.projectRoot);
|
||||
checkProjectActualFiles(service.configuredProjects.get(configFile.path)!, files.map(f => f.path));
|
||||
checkWatchedFilesDetailed(host, mapDefined(files, f => f === srcFile ? undefined : f.path), 1);
|
||||
if (useNodeFile) {
|
||||
checkWatchedDirectories(host, emptyArray, /*recursive*/ false); // since fs resolves to ambient module, shouldnt watch failed lookup
|
||||
}
|
||||
else {
|
||||
checkWatchedDirectoriesDetailed(host, [`${projectRoot}`, `${projectRoot}/src`], 1, /*recursive*/ false); // failed lookup for fs
|
||||
checkWatchedDirectoriesDetailed(host, [`${tscWatch.projectRoot}`, `${tscWatch.projectRoot}/src`], 1, /*recursive*/ false); // failed lookup for fs
|
||||
}
|
||||
const expectedWatchedDirectories = createMap<number>();
|
||||
expectedWatchedDirectories.set(`${projectRoot}/src`, 1); // Wild card
|
||||
expectedWatchedDirectories.set(`${projectRoot}/src/somefolder`, 1); // failedLookup for somefolder/module2
|
||||
expectedWatchedDirectories.set(`${projectRoot}/src/node_modules`, 1); // failed lookup for somefolder/module2
|
||||
expectedWatchedDirectories.set(`${projectRoot}/somefolder`, 1); // failed lookup for somefolder/module2
|
||||
expectedWatchedDirectories.set(`${projectRoot}/node_modules`, 1); // failed lookup for with node_modules/@types/fs
|
||||
expectedWatchedDirectories.set(`${projectRoot}/src/typings`, useNodeFile ? 1 : 2); // typeroot directory + failed lookup if not using node file
|
||||
expectedWatchedDirectories.set(`${tscWatch.projectRoot}/src`, 1); // Wild card
|
||||
expectedWatchedDirectories.set(`${tscWatch.projectRoot}/src/somefolder`, 1); // failedLookup for somefolder/module2
|
||||
expectedWatchedDirectories.set(`${tscWatch.projectRoot}/src/node_modules`, 1); // failed lookup for somefolder/module2
|
||||
expectedWatchedDirectories.set(`${tscWatch.projectRoot}/somefolder`, 1); // failed lookup for somefolder/module2
|
||||
expectedWatchedDirectories.set(`${tscWatch.projectRoot}/node_modules`, 1); // failed lookup for with node_modules/@types/fs
|
||||
expectedWatchedDirectories.set(`${tscWatch.projectRoot}/src/typings`, useNodeFile ? 1 : 2); // typeroot directory + failed lookup if not using node file
|
||||
checkWatchedDirectoriesDetailed(host, expectedWatchedDirectories, /*recursive*/ true);
|
||||
}
|
||||
|
||||
|
@ -883,15 +883,15 @@ export const x = 10;`
|
|||
|
||||
describe("ignores files/folder changes in node_modules that start with '.'", () => {
|
||||
const npmCacheFile: File = {
|
||||
path: `${projectRoot}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`,
|
||||
path: `${tscWatch.projectRoot}/node_modules/.cache/babel-loader/89c02171edab901b9926470ba6d5677e.ts`,
|
||||
content: JSON.stringify({ something: 10 })
|
||||
};
|
||||
const file1: File = {
|
||||
path: `${projectRoot}/test.ts`,
|
||||
path: `${tscWatch.projectRoot}/test.ts`,
|
||||
content: `import { x } from "somemodule";`
|
||||
};
|
||||
const file2: File = {
|
||||
path: `${projectRoot}/node_modules/somemodule/index.d.ts`,
|
||||
path: `${tscWatch.projectRoot}/node_modules/somemodule/index.d.ts`,
|
||||
content: `export const x = 10;`
|
||||
};
|
||||
it("when watching node_modules in inferred project for failed lookup/closed script infos", () => {
|
||||
|
@ -910,7 +910,7 @@ export const x = 10;`
|
|||
});
|
||||
it("when watching node_modules as part of wild card directories in config project", () => {
|
||||
const config: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const files = [libFile, file1, file2, config];
|
||||
|
@ -929,15 +929,15 @@ export const x = 10;`
|
|||
|
||||
describe("avoid unnecessary invalidation", () => {
|
||||
it("unnecessary lookup invalidation on save", () => {
|
||||
const expectedNonRelativeDirectories = [`${projectRoot}/node_modules`, `${projectRoot}/src`];
|
||||
const expectedNonRelativeDirectories = [`${tscWatch.projectRoot}/node_modules`, `${tscWatch.projectRoot}/src`];
|
||||
const module1Name = "module1";
|
||||
const module2Name = "module2";
|
||||
const fileContent = `import { module1 } from "${module1Name}";import { module2 } from "${module2Name}";`;
|
||||
const file1: File = {
|
||||
path: `${projectRoot}/src/file1.ts`,
|
||||
path: `${tscWatch.projectRoot}/src/file1.ts`,
|
||||
content: fileContent
|
||||
};
|
||||
const { module1, module2 } = getModules(`${projectRoot}/src/node_modules/module1/index.ts`, `${projectRoot}/node_modules/module2/index.ts`);
|
||||
const { module1, module2 } = getModules(`${tscWatch.projectRoot}/src/node_modules/module1/index.ts`, `${tscWatch.projectRoot}/node_modules/module2/index.ts`);
|
||||
const files = [module1, module2, file1, configFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const resolutionTrace = createHostModuleResolutionTrace(host);
|
||||
|
|
|
@ -16,11 +16,11 @@ namespace ts.projectSystem {
|
|||
|
||||
it("works when file is removed and added with different content", () => {
|
||||
const app: File = {
|
||||
path: `${projectRoot}/app.ts`,
|
||||
path: `${tscWatch.projectRoot}/app.ts`,
|
||||
content: "console.log('Hello world');"
|
||||
};
|
||||
const unitTest1: File = {
|
||||
path: `${projectRoot}/unitTest1.ts`,
|
||||
path: `${tscWatch.projectRoot}/unitTest1.ts`,
|
||||
content: `import assert = require('assert');
|
||||
|
||||
describe("Test Suite 1", () => {
|
||||
|
@ -35,7 +35,7 @@ describe("Test Suite 1", () => {
|
|||
});`
|
||||
};
|
||||
const tsconfig: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
path: `${tscWatch.projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const files = [app, libFile, tsconfig];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: typeReferenceDirectives", () => {
|
||||
it("when typeReferenceDirective contains UpperCasePackage", () => {
|
||||
const libProjectLocation = `${projectRoot}/lib`;
|
||||
const libProjectLocation = `${tscWatch.projectRoot}/lib`;
|
||||
const typeLib: File = {
|
||||
path: `${libProjectLocation}/@types/UpperCasePackage/index.d.ts`,
|
||||
content: `declare class BrokenTest {
|
||||
|
@ -19,7 +19,7 @@ declare class TestLib {
|
|||
test(): void;
|
||||
}`
|
||||
};
|
||||
const testProjectLocation = `${projectRoot}/test`;
|
||||
const testProjectLocation = `${tscWatch.projectRoot}/test`;
|
||||
const testFile: File = {
|
||||
path: `${testProjectLocation}/test.ts`,
|
||||
content: `class TestClass1 {
|
||||
|
@ -57,7 +57,7 @@ declare class TestLib {
|
|||
});
|
||||
|
||||
it("when typeReferenceDirective is relative path and in a sibling folder", () => {
|
||||
const projectPath = `${projectRoot}/background`;
|
||||
const projectPath = `${tscWatch.projectRoot}/background`;
|
||||
const file: File = {
|
||||
path: `${projectPath}/a.ts`,
|
||||
content: "let x = 10;"
|
||||
|
@ -73,7 +73,7 @@ declare class TestLib {
|
|||
})
|
||||
};
|
||||
const filesystem: File = {
|
||||
path: `${projectRoot}/typedefs/filesystem.d.ts`,
|
||||
path: `${tscWatch.projectRoot}/typedefs/filesystem.d.ts`,
|
||||
content: `interface LocalFileSystem { someProperty: string; }`
|
||||
};
|
||||
const files = [file, tsconfig, filesystem, libFile];
|
||||
|
|
|
@ -995,13 +995,13 @@ namespace ts.projectSystem {
|
|||
|
||||
it("should redo resolution that resolved to '.js' file after typings are installed", () => {
|
||||
const file: TestFSWithWatch.File = {
|
||||
path: `${projects}/a/b/app.js`,
|
||||
path: `${tscWatch.projects}/a/b/app.js`,
|
||||
content: `
|
||||
import * as commander from "commander";`
|
||||
};
|
||||
const cachePath = `${projects}/a/cache`;
|
||||
const cachePath = `${tscWatch.projects}/a/cache`;
|
||||
const commanderJS: TestFSWithWatch.File = {
|
||||
path: `${projects}/node_modules/commander/index.js`,
|
||||
path: `${tscWatch.projects}/node_modules/commander/index.js`,
|
||||
content: "module.exports = 0",
|
||||
};
|
||||
|
||||
|
@ -1025,12 +1025,12 @@ namespace ts.projectSystem {
|
|||
checkWatchedDirectories(host, [], /*recursive*/ false);
|
||||
// Does not include cachePath because that is handled by typingsInstaller
|
||||
checkWatchedDirectories(host, [
|
||||
`${projects}/node_modules`,
|
||||
`${projects}/a/node_modules`,
|
||||
`${projects}/a/b/node_modules`,
|
||||
`${projects}/a/node_modules/@types`,
|
||||
`${projects}/a/b/node_modules/@types`,
|
||||
`${projects}/a/b/bower_components`
|
||||
`${tscWatch.projects}/node_modules`,
|
||||
`${tscWatch.projects}/a/node_modules`,
|
||||
`${tscWatch.projects}/a/b/node_modules`,
|
||||
`${tscWatch.projects}/a/node_modules/@types`,
|
||||
`${tscWatch.projects}/a/b/node_modules/@types`,
|
||||
`${tscWatch.projects}/a/b/bower_components`
|
||||
], /*recursive*/ true);
|
||||
|
||||
service.checkNumberOfProjects({ inferredProjects: 1 });
|
||||
|
|
|
@ -17,8 +17,6 @@ declare namespace ts {
|
|||
const versionMajorMinor = "3.8";
|
||||
/** The version of the TypeScript compiler release */
|
||||
const version: string;
|
||||
}
|
||||
declare namespace ts {
|
||||
/**
|
||||
* Type of objects whose values are all of the same type.
|
||||
* The `in` and `for-in` operators can *not* be safely used,
|
||||
|
@ -3307,8 +3305,6 @@ declare namespace ts {
|
|||
declare namespace ts {
|
||||
function isExternalModuleNameRelative(moduleName: string): boolean;
|
||||
function sortAndDeduplicateDiagnostics<T extends Diagnostic>(diagnostics: readonly T[]): SortedReadonlyArray<T>;
|
||||
}
|
||||
declare namespace ts {
|
||||
function getDefaultLibFileName(options: CompilerOptions): string;
|
||||
function textSpanEnd(span: TextSpan): number;
|
||||
function textSpanIsEmpty(span: TextSpan): boolean;
|
||||
|
@ -3469,8 +3465,6 @@ declare namespace ts {
|
|||
*/
|
||||
function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[];
|
||||
function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined;
|
||||
}
|
||||
declare namespace ts {
|
||||
function isNumericLiteral(node: Node): node is NumericLiteral;
|
||||
function isBigIntLiteral(node: Node): node is BigIntLiteral;
|
||||
function isStringLiteral(node: Node): node is StringLiteral;
|
||||
|
@ -3648,8 +3642,6 @@ declare namespace ts {
|
|||
function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral;
|
||||
function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag;
|
||||
function isJSDocSignature(node: Node): node is JSDocSignature;
|
||||
}
|
||||
declare namespace ts {
|
||||
/**
|
||||
* True if node is of some token syntax kind.
|
||||
* For example, this is true for an IfKeyword but not for an IfStatement.
|
||||
|
@ -4265,7 +4257,7 @@ declare namespace ts {
|
|||
/**
|
||||
* Sets the constant value to emit for an expression.
|
||||
*/
|
||||
function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): ElementAccessExpression | PropertyAccessExpression;
|
||||
function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): PropertyAccessExpression | ElementAccessExpression;
|
||||
/**
|
||||
* Adds an EmitHelper to a node.
|
||||
*/
|
||||
|
|
10
tests/baselines/reference/api/typescript.d.ts
vendored
10
tests/baselines/reference/api/typescript.d.ts
vendored
|
@ -17,8 +17,6 @@ declare namespace ts {
|
|||
const versionMajorMinor = "3.8";
|
||||
/** The version of the TypeScript compiler release */
|
||||
const version: string;
|
||||
}
|
||||
declare namespace ts {
|
||||
/**
|
||||
* Type of objects whose values are all of the same type.
|
||||
* The `in` and `for-in` operators can *not* be safely used,
|
||||
|
@ -3307,8 +3305,6 @@ declare namespace ts {
|
|||
declare namespace ts {
|
||||
function isExternalModuleNameRelative(moduleName: string): boolean;
|
||||
function sortAndDeduplicateDiagnostics<T extends Diagnostic>(diagnostics: readonly T[]): SortedReadonlyArray<T>;
|
||||
}
|
||||
declare namespace ts {
|
||||
function getDefaultLibFileName(options: CompilerOptions): string;
|
||||
function textSpanEnd(span: TextSpan): number;
|
||||
function textSpanIsEmpty(span: TextSpan): boolean;
|
||||
|
@ -3469,8 +3465,6 @@ declare namespace ts {
|
|||
*/
|
||||
function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[];
|
||||
function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined;
|
||||
}
|
||||
declare namespace ts {
|
||||
function isNumericLiteral(node: Node): node is NumericLiteral;
|
||||
function isBigIntLiteral(node: Node): node is BigIntLiteral;
|
||||
function isStringLiteral(node: Node): node is StringLiteral;
|
||||
|
@ -3648,8 +3642,6 @@ declare namespace ts {
|
|||
function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral;
|
||||
function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag;
|
||||
function isJSDocSignature(node: Node): node is JSDocSignature;
|
||||
}
|
||||
declare namespace ts {
|
||||
/**
|
||||
* True if node is of some token syntax kind.
|
||||
* For example, this is true for an IfKeyword but not for an IfStatement.
|
||||
|
@ -4265,7 +4257,7 @@ declare namespace ts {
|
|||
/**
|
||||
* Sets the constant value to emit for an expression.
|
||||
*/
|
||||
function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): ElementAccessExpression | PropertyAccessExpression;
|
||||
function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: string | number): PropertyAccessExpression | ElementAccessExpression;
|
||||
/**
|
||||
* Adds an EmitHelper to a node.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue