Project References Core support

This commit is contained in:
Ryan Cavanaugh
2018-05-07 15:12:50 -07:00
parent 8fc4242097
commit ffa0ccba2a
64 changed files with 1293 additions and 224 deletions
+16 -1
View File
@@ -2220,7 +2220,22 @@ namespace ts {
}
if (moduleNotFoundError) {
// report errors only if it was requested
// For relative paths, see if this was possibly a projectReference redirect
if (pathIsRelative(moduleReference)) {
const sourceFile = getSourceFileOfNode(location);
const redirects = sourceFile.redirectedReferences;
if (redirects) {
const normalizedTargetPath = getNormalizedAbsolutePath(moduleReference, getDirectoryPath(sourceFile.fileName));
for (const ext of [Extension.Ts, Extension.Tsx]) {
const probePath = normalizedTargetPath + ext;
if (redirects.indexOf(probePath) >= 0) {
error(errorNode, Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, moduleReference, probePath);
return undefined;
}
}
}
}
if (resolutionDiagnostic) {
error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName);
}
+100 -5
View File
@@ -235,6 +235,13 @@ namespace ts {
category: Diagnostics.Basic_Options,
description: Diagnostics.Specify_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir,
},
{
name: "composite",
type: "boolean",
isTSConfigOnly: true,
category: Diagnostics.Basic_Options,
description: Diagnostics.Enable_project_compilation,
},
{
name: "removeComments",
type: "boolean",
@@ -814,12 +821,14 @@ namespace ts {
export function parseCommandLine(commandLine: ReadonlyArray<string>, readFile?: (path: string) => string | undefined): ParsedCommandLine {
const options: CompilerOptions = {};
const fileNames: string[] = [];
const projectReferences: ProjectReference[] | undefined = undefined;
const errors: Diagnostic[] = [];
parseStrings(commandLine);
return {
options,
fileNames,
projectReferences,
errors
};
@@ -933,6 +942,49 @@ namespace ts {
return optionNameMap.get(optionName);
}
export type DiagnosticReporter = (diagnostic: Diagnostic) => void;
/**
* Reports config file diagnostics
*/
export interface ConfigFileDiagnosticsReporter {
/**
* Reports unrecoverable error when parsing config file
*/
onUnRecoverableConfigFileDiagnostic: DiagnosticReporter;
}
/**
* Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors
*/
export interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter {
getCurrentDirectory(): string;
}
/**
* Reads the config file, reports errors if any and exits if the config file cannot be found
*/
export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined {
let configFileText: string;
try {
configFileText = host.readFile(configFileName);
}
catch (e) {
const error = createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message);
host.onUnRecoverableConfigFileDiagnostic(error);
return undefined;
}
if (!configFileText) {
const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, configFileName);
host.onUnRecoverableConfigFileDiagnostic(error);
return undefined;
}
const result = parseJsonText(configFileName, configFileText);
const cwd = host.getCurrentDirectory();
return parseJsonSourceFileConfigFileContent(result, host, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), optionsToExtend, getNormalizedAbsolutePath(configFileName, cwd));
}
/**
* Read tsconfig.json file
* @param fileName The path to the config file
@@ -1008,6 +1060,14 @@ namespace ts {
name: "extends",
type: "string"
},
{
name: "references",
type: "list",
element: {
name: "references",
type: "object"
}
},
{
name: "files",
type: "list",
@@ -1415,7 +1475,7 @@ namespace ts {
for (let i = 0; i < nameColumn.length; i++) {
const optionName = nameColumn[i];
const description = descriptionColumn[i];
result.push(optionName && `${tab}${tab}${optionName}${ description && (makePadding(marginLength - optionName.length + 2) + description)}`);
result.push(optionName && `${tab}${tab}${optionName}${description && (makePadding(marginLength - optionName.length + 2) + description)}`);
}
if (fileNames.length) {
result.push(`${tab}},`);
@@ -1499,12 +1559,13 @@ namespace ts {
const parsedConfig = parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors);
const { raw } = parsedConfig;
const options = extend(existingOptions, parsedConfig.options || {});
options.configFilePath = configFileName;
options.configFilePath = configFileName && normalizeSlashes(configFileName);
setConfigFileInOptions(options, sourceFile);
const { fileNames, wildcardDirectories, spec } = getFileNames();
const { fileNames, wildcardDirectories, spec, projectReferences } = getFileNames();
return {
options,
fileNames,
projectReferences,
typeAcquisition: parsedConfig.typeAcquisition || getDefaultTypeAcquisition(),
raw,
errors,
@@ -1558,10 +1619,33 @@ namespace ts {
}
const result = matchFileNames(filesSpecs, includeSpecs, excludeSpecs, configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath, options, host, errors, extraFileExtensions, sourceFile);
if (result.fileNames.length === 0 && !hasProperty(raw, "files") && resolutionStack.length === 0) {
if (result.fileNames.length === 0 && !hasProperty(raw, "files") && resolutionStack.length === 0 && !hasProperty(raw, "references")) {
errors.push(getErrorForNoInputFiles(result.spec, configFileName));
}
if (hasProperty(raw, "references") && !isNullOrUndefined(raw.references)) {
if (isArray(raw.references)) {
const references: ProjectReference[] = [];
for (const ref of raw.references) {
if (typeof ref.path !== "string") {
createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "reference.path", "string");
}
else {
references.push({
path: getNormalizedAbsolutePath(ref.path, basePath),
originalPath: ref.path,
prepend: ref.prepend,
circular: ref.circular
});
}
}
result.projectReferences = references;
}
else {
createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "references", "Array");
}
}
return result;
}
@@ -1850,6 +1934,9 @@ namespace ts {
const options = getDefaultCompilerOptions(configFileName);
convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors);
if (configFileName) {
options.configFilePath = normalizeSlashes(configFileName);
}
return options;
}
@@ -2048,7 +2135,7 @@ namespace ts {
// new entries in these paths.
const wildcardDirectories = getWildcardDirectories(validatedIncludeSpecs, validatedExcludeSpecs, basePath, host.useCaseSensitiveFileNames);
const spec: ConfigFileSpecs = { filesSpecs, includeSpecs, excludeSpecs, validatedIncludeSpecs, validatedExcludeSpecs, wildcardDirectories };
const spec: ConfigFileSpecs = { filesSpecs, referencesSpecs: undefined, includeSpecs, excludeSpecs, validatedIncludeSpecs, validatedExcludeSpecs, wildcardDirectories };
return getFileNamesFromConfigSpecs(spec, basePath, options, host, extraFileExtensions);
}
@@ -2119,8 +2206,16 @@ namespace ts {
const literalFiles = arrayFrom(literalFileMap.values());
const wildcardFiles = arrayFrom(wildcardFileMap.values());
const projectReferences = spec.referencesSpecs && spec.referencesSpecs.map((r): ProjectReference => {
return {
...r,
path: getNormalizedAbsolutePath(r.path, basePath)
};
});
return {
fileNames: literalFiles.concat(wildcardFiles),
projectReferences,
wildcardDirectories,
spec
};
+4
View File
@@ -1963,6 +1963,10 @@ namespace ts {
: moduleKind === ModuleKind.System;
}
export function getEmitDeclarations(compilerOptions: CompilerOptions): boolean {
return !!(compilerOptions.declaration || compilerOptions.composite);
}
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict";
export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean {
+37
View File
@@ -3552,6 +3552,43 @@
"code": 6197
},
"Projects to reference": {
"category": "Message",
"code": 6300
},
"Enable project compilation": {
"category": "Message",
"code": 6302
},
"Project references may not form a circular graph. Cycle detected: {0}": {
"category": "Error",
"code": 6202
},
"Composite projects may not disable declaration emit.": {
"category": "Error",
"code": 6304
},
"Output file '{0}' has not been built from source file '{1}'.": {
"category": "Error",
"code": 6305
},
"Referenced project '{0}' must have setting \"composite\": true.": {
"category": "Error",
"code": 6306
},
"File '{0}' is not in project file list. Projects must list all files or use an 'include' pattern.": {
"category": "Error",
"code": 6307
},
"Cannot prepend project '{0}' because it does not have 'outFile' set": {
"category": "Error",
"code": 6308
},
"Output file '{0}' from project '{1}' does not exist": {
"category": "Error",
"code": 6309
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
+69 -16
View File
@@ -1,4 +1,5 @@
namespace ts {
const infoExtension = ".tsbundleinfo";
const brackets = createBracketsMap();
/*@internal*/
@@ -15,12 +16,11 @@ namespace ts {
host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) => T,
sourceFilesOrTargetSourceFile?: ReadonlyArray<SourceFile> | SourceFile,
emitOnlyDtsFiles?: boolean) {
const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile);
const options = host.getCompilerOptions();
if (options.outFile || options.out) {
if (sourceFiles.length) {
const bundle = createBundle(sourceFiles);
const bundle = createBundle(sourceFiles, host.getPrependNodes());
const result = action(getOutputPathsFor(bundle, host, emitOnlyDtsFiles), bundle);
if (result) {
return result;
@@ -45,7 +45,8 @@ namespace ts {
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = (forceDtsPaths || options.declaration) ? removeFileExtension(jsFilePath) + Extension.Dts : undefined;
const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath };
const bundleInfoPath = options.references && jsFilePath && (removeFileExtension(jsFilePath) + infoExtension);
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath };
}
else {
const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options));
@@ -54,7 +55,7 @@ namespace ts {
const isJs = isSourceFileJavaScript(sourceFile);
const declarationFilePath = ((forceDtsPaths || options.declaration) && !isJs) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
const declarationMapPath = getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined;
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath };
return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath: undefined };
}
}
@@ -62,6 +63,13 @@ namespace ts {
return (options.sourceMap && !options.inlineSourceMap) ? jsFilePath + ".map" : undefined;
}
function createDefaultBundleInfo(): BundleInfo {
return {
originalOffset: -1,
totalLength: -1
};
}
// JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
// So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
// For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
@@ -87,7 +95,7 @@ namespace ts {
/*@internal*/
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory<SourceFile>[]): EmitResult {
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory<SourceFile | Bundle>[]): EmitResult {
const compilerOptions = host.getCompilerOptions();
const sourceMapDataList: SourceMapData[] = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined;
const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined;
@@ -103,6 +111,7 @@ namespace ts {
// Explicitly do not passthru either `inline` option
});
let bundleInfo: BundleInfo = createDefaultBundleInfo();
let emitSkipped = false;
// Emit each output file
@@ -118,8 +127,8 @@ namespace ts {
sourceMaps: sourceMapDataList
};
function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath);
function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath, bundleInfoPath);
emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath, declarationMapPath);
if (!emitSkipped && emittedFilesList) {
@@ -132,11 +141,13 @@ namespace ts {
if (declarationFilePath) {
emittedFilesList.push(declarationFilePath);
}
if (bundleInfoPath) {
emittedFilesList.push(bundleInfoPath);
}
}
}
function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string, sourceMapFilePath: string) {
const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles;
function emitJsFileOrBundle(sourceFileOrBundle: SourceFile | Bundle, jsFilePath: string, sourceMapFilePath: string, bundleInfoPath: string | undefined) {
// Make sure not to write js file and source map file if any of them cannot be written
if (host.isEmitBlocked(jsFilePath) || compilerOptions.noEmit || compilerOptions.emitDeclarationOnly) {
emitSkipped = true;
@@ -146,7 +157,7 @@ namespace ts {
return;
}
// Transform the source files
const transform = transformNodes(resolver, host, compilerOptions, sourceFiles, transformers, /*allowDtsFiles*/ false);
const transform = transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], transformers, /*allowDtsFiles*/ false);
// Create a printer to print the nodes
const printer = createPrinter({ ...compilerOptions, noEmitHelpers: compilerOptions.noEmitHelpers } as PrinterOptions, {
@@ -166,7 +177,8 @@ namespace ts {
onSetSourceFile: setSourceFile,
});
printSourceFileOrBundle(jsFilePath, sourceMapFilePath, isSourceFile(sourceFileOrBundle) ? transform.transformed[0] : createBundle(transform.transformed), printer, sourceMap);
Debug.assert(transform.transformed.length === 1, "Should only see one output from the transform");
printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform.transformed[0], bundleInfoPath, printer, sourceMap);
// Clean up emit nodes on parse tree
transform.dispose();
@@ -179,7 +191,7 @@ namespace ts {
const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles;
// Setup and perform the transformation to retrieve declarations from the input files
const nonJsFiles = filter(sourceFiles, isSourceFileNotJavaScript);
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles)] : nonJsFiles;
const inputListOrBundle = (compilerOptions.outFile || compilerOptions.out) ? [createBundle(nonJsFiles, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : nonJsFiles;
const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, [transformDeclarations], /*allowDtsFiles*/ false);
if (length(declarationTransform.diagnostics)) {
for (const diagnostic of declarationTransform.diagnostics) {
@@ -203,19 +215,20 @@ namespace ts {
const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!compilerOptions.noEmit;
emitSkipped = emitSkipped || declBlocked;
if (!declBlocked || emitOnlyDtsFiles) {
printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], declarationPrinter, declarationSourceMap);
Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform");
printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], /* bundleInfopath*/ undefined, declarationPrinter, declarationSourceMap);
}
declarationTransform.dispose();
}
function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, printer: Printer, mapRecorder: SourceMapWriter) {
function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, sourceFileOrBundle: SourceFile | Bundle, bundleInfoPath: string | undefined, printer: Printer, mapRecorder: SourceMapWriter) {
const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined;
const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined;
const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile];
mapRecorder.initialize(jsFilePath, sourceMapFilePath || "", sourceFileOrBundle, sourceMapDataList);
if (bundle) {
printer.writeBundle(bundle, writer);
printer.writeBundle(bundle, writer, bundleInfo);
}
else {
printer.writeFile(sourceFile, writer);
@@ -236,9 +249,17 @@ namespace ts {
// Write the output file
writeFile(host, emitterDiagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM, sourceFiles);
// Write bundled offset information if applicable
if (bundleInfoPath) {
bundleInfo.totalLength = writer.getTextPos();
writeFile(host, emitterDiagnostics, bundleInfoPath, JSON.stringify(bundleInfo, undefined, 2), /*writeByteOrderMark*/ false);
}
// Reset state
mapRecorder.reset();
writer.clear();
bundleInfo = createDefaultBundleInfo();
}
function setSourceFile(node: SourceFile) {
@@ -335,6 +356,7 @@ namespace ts {
switch (node.kind) {
case SyntaxKind.SourceFile: return printFile(<SourceFile>node);
case SyntaxKind.Bundle: return printBundle(<Bundle>node);
case SyntaxKind.UnparsedSource: return printUnparsedSource(<UnparsedSource>node);
}
writeNode(hint, node, sourceFile, beginPrint());
return endPrint();
@@ -355,6 +377,11 @@ namespace ts {
return endPrint();
}
function printUnparsedSource(unparsed: UnparsedSource): string {
writeUnparsedSource(unparsed, beginPrint());
return endPrint();
}
/**
* If `sourceFile` is `undefined`, `node` must be a synthesized `TypeNode`.
*/
@@ -379,7 +406,7 @@ namespace ts {
writer = previousWriter;
}
function writeBundle(bundle: Bundle, output: EmitTextWriter) {
function writeBundle(bundle: Bundle, output: EmitTextWriter, bundleInfo?: BundleInfo) {
isOwnFileEmit = false;
const previousWriter = writer;
setWriter(output);
@@ -387,6 +414,16 @@ namespace ts {
emitPrologueDirectivesIfNeeded(bundle);
emitHelpers(bundle);
emitSyntheticTripleSlashReferencesIfNeeded(bundle);
for (const prepend of bundle.prepends) {
print(EmitHint.Unspecified, prepend, /*sourceFile*/ undefined);
writeLine();
}
if (bundleInfo) {
bundleInfo.originalOffset = writer.getTextPos();
}
for (const sourceFile of bundle.sourceFiles) {
print(EmitHint.SourceFile, sourceFile, sourceFile);
}
@@ -394,6 +431,14 @@ namespace ts {
writer = previousWriter;
}
function writeUnparsedSource(unparsed: UnparsedSource, output: EmitTextWriter) {
const previousWriter = writer;
setWriter(output);
print(EmitHint.Unspecified, unparsed, /*sourceFile*/ undefined);
reset();
writer = previousWriter;
}
function writeFile(sourceFile: SourceFile, output: EmitTextWriter) {
isOwnFileEmit = true;
const previousWriter = writer;
@@ -534,6 +579,9 @@ namespace ts {
case SyntaxKind.TemplateTail:
return emitLiteral(<LiteralExpression>node);
case SyntaxKind.UnparsedSource:
return emitUnparsedSource(<UnparsedSource>node);
// Identifiers
case SyntaxKind.Identifier:
return emitIdentifier(<Identifier>node);
@@ -978,6 +1026,11 @@ namespace ts {
}
}
// SyntaxKind.UnparsedSource
function emitUnparsedSource(unparsed: UnparsedSource) {
write(unparsed.text);
}
//
// Identifiers
//
+18 -4
View File
@@ -2562,15 +2562,29 @@ namespace ts {
: node;
}
export function createBundle(sourceFiles: ReadonlyArray<SourceFile>) {
export function createBundle(sourceFiles: ReadonlyArray<SourceFile>, prepends: ReadonlyArray<UnparsedSource | InputFiles> = emptyArray) {
const node = <Bundle>createNode(SyntaxKind.Bundle);
node.prepends = prepends;
node.sourceFiles = sourceFiles;
return node;
}
export function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>) {
if (node.sourceFiles !== sourceFiles) {
return createBundle(sourceFiles);
export function createUnparsedSourceFile(text: string): UnparsedSource {
const node = <UnparsedSource>createNode(SyntaxKind.UnparsedSource);
node.text = text;
return node;
}
export function createInputFiles(javascript: string, declaration: string): InputFiles {
const node = <InputFiles>createNode(SyntaxKind.InputFiles);
node.javascriptText = javascript;
node.declarationText = declaration;
return node;
}
export function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>, prepends: ReadonlyArray<UnparsedSource> = emptyArray) {
if (node.sourceFiles !== sourceFiles || node.prepends !== prepends) {
return createBundle(sourceFiles, prepends);
}
return node;
}
+7 -1
View File
@@ -503,7 +503,13 @@ namespace ts {
export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
performance.mark("beforeParse");
const result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
let result: SourceFile;
if (languageVersion === ScriptTarget.JSON) {
result = Parser.parseJsonText(fileName, sourceText);
}
else {
result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
}
performance.mark("afterParse");
performance.measure("Parse", "beforeParse", "afterParse");
return result;
+284 -10
View File
@@ -188,7 +188,8 @@ namespace ts {
directoryExists: directoryName => sys.directoryExists(directoryName),
getEnvironmentVariable: name => sys.getEnvironmentVariable ? sys.getEnvironmentVariable(name) : "",
getDirectories: (path: string) => sys.getDirectories(path),
realpath
realpath,
readDirectory: (path, extensions, include, exclude, depth) => sys.readDirectory(path, extensions, include, exclude, depth)
};
}
@@ -328,14 +329,14 @@ namespace ts {
output += formatColorAndReset(relativeFileName, ForegroundColorEscapeSequences.Cyan);
output += ":";
output += formatColorAndReset(`${ firstLine + 1 }`, ForegroundColorEscapeSequences.Yellow);
output += formatColorAndReset(`${firstLine + 1}`, ForegroundColorEscapeSequences.Yellow);
output += ":";
output += formatColorAndReset(`${ firstLineChar + 1 }`, ForegroundColorEscapeSequences.Yellow);
output += formatColorAndReset(`${firstLineChar + 1}`, ForegroundColorEscapeSequences.Yellow);
output += " - ";
}
output += formatColorAndReset(diagnosticCategoryName(diagnostic), getCategoryFormat(diagnostic.category));
output += formatColorAndReset(` TS${ diagnostic.code }: `, ForegroundColorEscapeSequences.Grey);
output += formatColorAndReset(` TS${diagnostic.code}: `, ForegroundColorEscapeSequences.Grey);
output += flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine());
if (diagnostic.file) {
@@ -477,6 +478,16 @@ namespace ts {
);
}
function createCreateProgramOptions(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): CreateProgramOptions {
return {
rootNames,
options,
host,
oldProgram,
configFileParsingDiagnostics
};
}
/**
* Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
* that represent a compilation unit.
@@ -491,7 +502,13 @@ namespace ts {
* @param configFileParsingDiagnostics - error during config file parsing
* @returns A 'Program' object.
*/
export function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program {
export function createProgram(createProgramOptions: CreateProgramOptions): Program;
export function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
export function createProgram(rootNamesOrOptions: ReadonlyArray<string> | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program {
const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions;
const { rootNames, options, configFileParsingDiagnostics, projectReferences } = createProgramOptions;
let { host, oldProgram } = createProgramOptions;
let program: Program;
let files: SourceFile[] = [];
let commonSourceDirectory: string;
@@ -526,6 +543,7 @@ namespace ts {
performance.mark("beforeProgram");
host = host || createCompilerHost(options);
const configParsingHost = parseConfigHostFromCompilerHost(host);
let skipDefaultLib = options.noLib;
const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options));
@@ -537,6 +555,7 @@ namespace ts {
// Map storing if there is emit blocking diagnostics for given input
const hasEmitBlockingDiagnostics = createMap<boolean>();
let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression;
let _referencesArrayLiteralSyntax: ArrayLiteralExpression;
let moduleResolutionCache: ModuleResolutionCache;
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string, reusedNames?: string[]) => ResolvedModuleFull[];
@@ -581,6 +600,23 @@ namespace ts {
// used to track cases when two file names differ only in casing
const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? createMap<SourceFile>() : undefined;
// A parallel array to projectReferences storing the results of reading in the referenced tsconfig files
const resolvedProjectReferences: (ResolvedProjectReference | undefined)[] | undefined = projectReferences ? [] : undefined;
const projectReferenceRedirects: Map<string> = createMap();
if (projectReferences) {
for (const ref of projectReferences) {
const parsedRef = parseProjectReferenceConfigFile(ref);
resolvedProjectReferences.push(parsedRef);
if (parsedRef) {
if (parsedRef.commandLine.options.outFile) {
const dtsOutfile = changeExtension(parsedRef.commandLine.options.outFile, ".d.ts");
processSourceFile(dtsOutfile, /*isDefaultLib*/ false, /*packageId*/ undefined);
}
addProjectReferenceRedirects(parsedRef.commandLine, projectReferenceRedirects);
}
}
}
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
const structuralIsReused = tryReuseStructureFromOldProgram();
if (structuralIsReused !== StructureIsReused.Completely) {
@@ -669,6 +705,7 @@ namespace ts {
isEmittedFile,
getConfigFileParsingDiagnostics,
getResolvedModuleWithFailedLookupLocationsFromCache,
getProjectReferences
};
verifyCompilerOptions();
@@ -689,12 +726,18 @@ namespace ts {
if (commonSourceDirectory === undefined) {
const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, options, isSourceFileFromExternalLibrary));
if (options.rootDir && checkSourceFilesBelongToPath(emittedFiles, options.rootDir)) {
// If a rootDir is specified and is valid use it as the commonSourceDirectory
// If a rootDir is specified use it as the commonSourceDirectory
commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory);
}
else if (options.composite) {
// Project compilations never infer their root from the input source paths
commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath));
checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory);
}
else {
commonSourceDirectory = computeCommonSourceDirectory(emittedFiles);
}
if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) {
// Make sure directory path ends with directory separator so this string can directly
// used to replace with "" to get the relative path of the source file and the relative path doesn't
@@ -896,6 +939,35 @@ namespace ts {
return oldProgram.structureIsReused = StructureIsReused.Not;
}
// Check if any referenced project tsconfig files are different
const oldRefs = oldProgram.getProjectReferences();
if (projectReferences) {
if (!oldRefs) {
return oldProgram.structureIsReused = StructureIsReused.Not;
}
for (let i = 0; i < projectReferences.length; i++) {
const oldRef = oldRefs[i];
if (oldRef) {
const newRef = parseProjectReferenceConfigFile(projectReferences[i]);
if (!newRef || newRef.sourceFile !== oldRef.sourceFile) {
// Resolved project reference has gone missing or changed
return oldProgram.structureIsReused = StructureIsReused.Not;
}
}
else {
// A previously-unresolved reference may be resolved now
if (parseProjectReferenceConfigFile(projectReferences[i]) !== undefined) {
return oldProgram.structureIsReused = StructureIsReused.Not;
}
}
}
}
else {
if (oldRefs) {
return oldProgram.structureIsReused = StructureIsReused.Not;
}
}
// check if program source files has changed in the way that can affect structure of the program
const newSourceFiles: SourceFile[] = [];
const filePaths: Path[] = [];
@@ -1083,6 +1155,7 @@ namespace ts {
function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost {
return {
getPrependNodes,
getCanonicalFileName,
getCommonSourceDirectory: program.getCommonSourceDirectory,
getCompilerOptions: program.getCompilerOptions,
@@ -1098,6 +1171,35 @@ namespace ts {
};
}
function getProjectReferences() {
if (!resolvedProjectReferences) return;
return resolvedProjectReferences;
}
function getPrependNodes(): InputFiles[] {
if (!projectReferences) {
return emptyArray;
}
const nodes: InputFiles[] = [];
for (let i = 0; i < projectReferences.length; i++) {
const ref = projectReferences[i];
const resolvedRefOpts = resolvedProjectReferences[i].commandLine;
if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) {
// Upstream project didn't have outFile set -- skip (error will have been issued earlier)
if (!resolvedRefOpts.options.outFile) continue;
const dtsFilename = changeExtension(resolvedRefOpts.options.outFile, ".d.ts");
const js = host.readFile(resolvedRefOpts.options.outFile) || `/* Input file ${resolvedRefOpts.options.outFile} was missing */\r\n`;
const dts = host.readFile(dtsFilename) || `/* Input file ${dtsFilename} was missing */\r\n`;
const node = createInputFiles(js, dts);
nodes.push(node);
}
}
return nodes;
}
function isSourceFileFromExternalLibrary(file: SourceFile): boolean {
return sourceFilesFoundSearchingNodeModules.get(file.path);
}
@@ -1723,7 +1825,13 @@ namespace ts {
const sourceFile = getSourceFile(fileName);
if (fail) {
if (!sourceFile) {
fail(Diagnostics.File_0_not_found, fileName);
const redirect = getProjectReferenceRedirect(fileName);
if (redirect) {
fail(Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect, fileName);
}
else {
fail(Diagnostics.File_0_not_found, fileName);
}
}
else if (refFile && host.getCanonicalFileName(fileName) === host.getCanonicalFileName(refFile.fileName)) {
fail(Diagnostics.A_file_cannot_have_a_reference_to_itself);
@@ -1819,6 +1927,21 @@ namespace ts {
return file;
}
let redirectedPath: string | undefined;
if (refFile) {
const redirect = getProjectReferenceRedirect(fileName);
if (redirect) {
((refFile.redirectedReferences || (refFile.redirectedReferences = [])) as string[]).push(fileName);
fileName = redirect;
// Once we start redirecting to a file, we can potentially come back to it
// via a back-reference from another file in the .d.ts folder. If that happens we'll
// end up trying to add it to the program *again* because we were tracking it via its
// original (un-redirected) name. So we have to map both the original path and the redirected path
// to the source file we're about to find/create
redirectedPath = toPath(redirect);
}
}
// We haven't looked for this file, do so now and cache result
const file = host.getSourceFile(fileName, options.target, hostErrorMessage => {
if (refFile !== undefined && refPos !== undefined && refEnd !== undefined) {
@@ -1851,6 +1974,10 @@ namespace ts {
}
filesByName.set(path, file);
if (redirectedPath) {
filesByName.set(redirectedPath, file);
}
if (file) {
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
file.path = path;
@@ -1888,6 +2015,23 @@ namespace ts {
return file;
}
function getProjectReferenceRedirect(fileName: string): string | undefined {
const path = toPath(fileName);
// If this file is produced by a referenced project, we need to rewrite it to
// look in the output folder of the referenced project rather than the input
const normalized = getNormalizedAbsolutePath(fileName, path);
let result: string | undefined;
projectReferenceRedirects.forEach((v, k) => {
if (result !== undefined) {
return undefined;
}
if (normalized.indexOf(k) === 0) {
result = changeExtension(fileName.replace(k, v), ".d.ts");
}
});
return result;
}
function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) {
forEach(file.referencedFiles, ref => {
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
@@ -1898,6 +2042,10 @@ namespace ts {
function processTypeReferenceDirectives(file: SourceFile) {
// We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
const typeDirectives = map(file.typeReferenceDirectives, ref => ref.fileName.toLocaleLowerCase());
if (!typeDirectives) {
return;
}
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName);
for (let i = 0; i < typeDirectives.length; i++) {
@@ -2061,6 +2209,31 @@ namespace ts {
return allFilesBelongToPath;
}
function parseProjectReferenceConfigFile(ref: ProjectReference): { commandLine: ParsedCommandLine, sourceFile: SourceFile } | undefined {
// The actual filename (i.e. add "/tsconfig.json" if necessary)
const refPath = resolveProjectReferencePath(host, ref);
// An absolute path pointing to the containing directory of the config file
const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), host.getCurrentDirectory());
const sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile;
if (sourceFile === undefined) {
return undefined;
}
const commandLine = parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, /*existingOptions*/ undefined, refPath);
return { commandLine, sourceFile };
}
function addProjectReferenceRedirects(referencedProject: ParsedCommandLine, target: Map<string>) {
const rootDir = normalizePath(referencedProject.options.rootDir || getDirectoryPath(referencedProject.options.configFilePath));
target.set(rootDir, getDeclarationOutputDirectory(referencedProject));
}
function getDeclarationOutputDirectory(proj: ParsedCommandLine) {
return proj.options.declarationDir ||
proj.options.outDir ||
getDirectoryPath(proj.options.configFilePath);
}
function verifyCompilerOptions() {
if (options.strictPropertyInitialization && !options.strictNullChecks) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks");
@@ -2097,6 +2270,47 @@ namespace ts {
createDiagnosticForOptionName(Diagnostics.Option_paths_cannot_be_used_without_specifying_baseUrl_option, "paths");
}
if (options.composite) {
if (options.declaration === false) {
createDiagnosticForOptionName(Diagnostics.Composite_projects_may_not_disable_declaration_emit, "declaration");
}
}
if (projectReferences) {
for (let i = 0; i < projectReferences.length; i++) {
const ref = projectReferences[i];
const resolvedRefOpts = resolvedProjectReferences[i] && resolvedProjectReferences[i].commandLine.options;
if (resolvedRefOpts === undefined) {
createDiagnosticForReference(i, Diagnostics.File_0_does_not_exist, ref.path);
continue;
}
if (!resolvedRefOpts.composite) {
createDiagnosticForReference(i, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path);
}
if (ref.prepend) {
if (resolvedRefOpts.outFile) {
if (!host.fileExists(resolvedRefOpts.outFile)) {
createDiagnosticForReference(i, Diagnostics.Output_file_0_from_project_1_does_not_exist, resolvedRefOpts.outFile, ref.path);
}
}
else {
createDiagnosticForReference(i, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, ref.path);
}
}
}
}
// List of collected files is complete; validate exhautiveness if this is a project with a file list
if (options.composite && rootNames.length < files.length) {
const normalizedRootNames = rootNames.map(r => normalizePath(r).toLowerCase());
const sourceFiles = files.filter(f => !f.isDeclarationFile).map(f => normalizePath(f.path).toLowerCase());
for (const file of sourceFiles) {
if (normalizedRootNames.every(r => r !== file)) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern, file));
}
}
}
if (options.paths) {
for (const key in options.paths) {
if (!hasProperty(options.paths, key)) {
@@ -2332,12 +2546,16 @@ namespace ts {
}
}
function getOptionPathsSyntax() {
function getOptionsSyntaxByName(name: string): object | undefined {
const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax();
if (compilerOptionsObjectLiteralSyntax) {
return getPropertyAssignment(compilerOptionsObjectLiteralSyntax, "paths");
return getPropertyAssignment(compilerOptionsObjectLiteralSyntax, name);
}
return emptyArray;
return undefined;
}
function getOptionPathsSyntax(): PropertyAssignment[] {
return getOptionsSyntaxByName("paths") as PropertyAssignment[] || emptyArray;
}
function createDiagnosticForOptionName(message: DiagnosticMessage, option1: string, option2?: string, option3?: string) {
@@ -2348,6 +2566,16 @@ namespace ts {
createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, arg0);
}
function createDiagnosticForReference(index: number, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number) {
const referencesSyntax = getProjectReferencesSyntax();
if (referencesSyntax) {
if (createOptionDiagnosticInArrayLiteralSyntax(referencesSyntax, index, message, arg0, arg1)) {
return;
}
}
programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1));
}
function createDiagnosticForOption(onKey: boolean, option1: string, option2: string, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number) {
const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax();
const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax ||
@@ -2358,6 +2586,22 @@ namespace ts {
}
}
function getProjectReferencesSyntax(): ArrayLiteralExpression | null {
if (_referencesArrayLiteralSyntax === undefined) {
_referencesArrayLiteralSyntax = null; // tslint:disable-line:no-null-keyword
if (options.configFile) {
const jsonObjectLiteral = getTsConfigObjectLiteralExpression(options.configFile);
for (const prop of getPropertyAssignment(jsonObjectLiteral, "references")) {
if (isArrayLiteralExpression(prop.initializer)) {
_referencesArrayLiteralSyntax = prop.initializer;
break;
}
}
}
}
return _referencesArrayLiteralSyntax;
}
function getCompilerOptionsObjectLiteralSyntax() {
if (_compilerOptionsObjectLiteralSyntax === undefined) {
_compilerOptionsObjectLiteralSyntax = null; // tslint:disable-line:no-null-keyword
@@ -2382,6 +2626,14 @@ namespace ts {
return !!props.length;
}
function createOptionDiagnosticInArrayLiteralSyntax(arrayLiteral: ArrayLiteralExpression, index: number, message: DiagnosticMessage, arg0: string | number, arg1?: string | number, arg2?: string | number): boolean {
if (arrayLiteral.elements.length <= index) {
// Out-of-bounds
return false;
}
programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile, arrayLiteral.elements[index], message, arg0, arg1, arg2));
}
function blockEmittingOfFile(emitFileName: string, diag: Diagnostic) {
hasEmitBlockingDiagnostics.set(toPath(emitFileName), true);
programDiagnostics.add(diag);
@@ -2423,6 +2675,28 @@ namespace ts {
}
}
/* @internal */
export function parseConfigHostFromCompilerHost(host: CompilerHost): ParseConfigFileHost {
return {
fileExists: f => host.fileExists(f),
readDirectory: (root, extensions, includes, depth?) => host.readDirectory ? host.readDirectory(root, extensions, includes, depth) : [],
readFile: f => host.readFile(f),
useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(),
getCurrentDirectory: () => host.getCurrentDirectory(),
onUnRecoverableConfigFileDiagnostic: () => undefined
};
}
/**
* Returns the target config filename of a project reference
*/
function resolveProjectReferencePath(host: CompilerHost, ref: ProjectReference): string | undefined {
if (!host.fileExists(ref.path)) {
return combinePaths(ref.path, "tsconfig.json");
}
return ref.path;
}
/* @internal */
/**
* Returns a DiagnosticMessage if we won't include a resolved module due to its extension.
+2 -2
View File
@@ -1,6 +1,6 @@
/* @internal */
namespace ts {
function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<SourceFile> {
function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<SourceFile | Bundle> {
switch (moduleKind) {
case ModuleKind.ESNext:
case ModuleKind.ES2015:
@@ -28,7 +28,7 @@ namespace ts {
const jsx = compilerOptions.jsx;
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
const transformers: TransformerFactory<SourceFile>[] = [];
const transformers: TransformerFactory<SourceFile | Bundle>[] = [];
addRange(transformers, customTransformers && customTransformers.before);
+5 -1
View File
@@ -163,7 +163,11 @@ namespace ts {
const updated = visitNodes(sourceFile.statements, visitDeclarationStatements);
return updateSourceFileNode(sourceFile, filterCandidateImports(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false);
}
));
), mapDefined(node.prepends, prepend => {
if (prepend.kind === SyntaxKind.InputFiles) {
return createUnparsedSourceFile(prepend.declarationText);
}
}));
bundle.syntheticFileReferences = [];
bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences();
bundle.hasNoDefaultLib = hasNoDefaultLib;
+1 -1
View File
@@ -295,7 +295,7 @@ namespace ts {
*/
let enabledSubstitutions: ES2015SubstitutionFlags;
return transformSourceFile;
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
+1 -1
View File
@@ -3,7 +3,7 @@ namespace ts {
export function transformES2016(context: TransformationContext) {
const { hoistVariableDeclaration } = context;
return transformSourceFile;
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
+1 -1
View File
@@ -40,7 +40,7 @@ namespace ts {
context.onEmitNode = onEmitNode;
context.onSubstituteNode = onSubstituteNode;
return transformSourceFile;
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
+1 -1
View File
@@ -24,7 +24,7 @@ namespace ts {
context.onSubstituteNode = onSubstituteNode;
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
context.enableSubstitution(SyntaxKind.PropertyAssignment);
return transformSourceFile;
return chainBundle(transformSourceFile);
/**
* Transforms an ES5 source file to ES3.
+1 -1
View File
@@ -26,7 +26,7 @@ namespace ts {
let enclosingFunctionFlags: FunctionFlags;
let enclosingSuperContainerFlags: NodeCheckFlags = 0;
return transformSourceFile;
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
+1 -1
View File
@@ -289,7 +289,7 @@ namespace ts {
let currentExceptionBlock: ExceptionBlock; // The current exception block.
let withBlockStack: WithBlock[]; // A stack containing `with` blocks.
return transformSourceFile;
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile || (node.transformFlags & TransformFlags.ContainsGenerator) === 0) {
+1 -1
View File
@@ -4,7 +4,7 @@ namespace ts {
const compilerOptions = context.getCompilerOptions();
let currentSourceFile: SourceFile;
return transformSourceFile;
return chainBundle(transformSourceFile);
/**
* Transform JSX-specific syntax in a SourceFile.
+1 -1
View File
@@ -10,7 +10,7 @@ namespace ts {
context.enableSubstitution(SyntaxKind.Identifier);
let currentSourceFile: SourceFile;
return transformSourceFile;
return chainBundle(transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
+1 -1
View File
@@ -45,7 +45,7 @@ namespace ts {
let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored.
let needUMDDynamicImportHelper: boolean;
return transformSourceFile;
return chainBundle(transformSourceFile);
/**
* Transforms the module aspects of a SourceFile.
+1 -1
View File
@@ -39,7 +39,7 @@ namespace ts {
let enclosingBlockScopedContainer: Node;
let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored.
return transformSourceFile;
return chainBundle(transformSourceFile);
/**
* Transforms the module aspects of a SourceFile.
+17 -1
View File
@@ -88,7 +88,23 @@ namespace ts {
*/
let pendingExpressions: Expression[] | undefined;
return transformSourceFile;
return transformSourceFileOrBundle;
function transformSourceFileOrBundle(node: SourceFile | Bundle) {
if (node.kind === SyntaxKind.Bundle) {
return transformBundle(node);
}
return transformSourceFile(node);
}
function transformBundle(node: Bundle) {
return createBundle(node.sourceFiles.map(transformSourceFile), mapDefined(node.prepends, prepend => {
if (prepend.kind === SyntaxKind.InputFiles) {
return createUnparsedSourceFile(prepend.javascriptText);
}
return prepend;
}));
}
/**
* Transform TypeScript-specific syntax in a SourceFile.
+12
View File
@@ -25,6 +25,18 @@ namespace ts {
return e.propertyName && e.propertyName.escapedText === InternalSymbolName.Default;
}
export function chainBundle(transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle {
return transformSourceFileOrBundle;
function transformSourceFileOrBundle(node: SourceFile | Bundle) {
return node.kind === SyntaxKind.SourceFile ? transformSourceFile(node) : transformBundle(node);
}
function transformBundle(node: Bundle) {
return createBundle(map(node.sourceFiles, transformSourceFile), node.prepends);
}
}
export function getImportNeedsImportStarHelper(node: ImportDeclaration) {
if (!!getNamespaceDeclarationNode(node)) {
return true;
+13 -6
View File
@@ -120,7 +120,7 @@ namespace ts {
createWatchOfConfigFile(configParseResult, commandLineOptions);
}
else {
performCompilation(configParseResult.fileNames, configParseResult.options, getConfigFileParsingDiagnostics(configParseResult));
performCompilation(configParseResult.fileNames, configParseResult.projectReferences, configParseResult.options, getConfigFileParsingDiagnostics(configParseResult));
}
}
else {
@@ -130,7 +130,7 @@ namespace ts {
createWatchOfFilesAndCompilerOptions(commandLine.fileNames, commandLineOptions);
}
else {
performCompilation(commandLine.fileNames, commandLineOptions);
performCompilation(commandLine.fileNames, /*references*/ undefined, commandLineOptions);
}
}
}
@@ -142,11 +142,18 @@ namespace ts {
}
}
function performCompilation(rootFileNames: string[], compilerOptions: CompilerOptions, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) {
const compilerHost = createCompilerHost(compilerOptions);
enableStatistics(compilerOptions);
function performCompilation(rootNames: string[], projectReferences: ReadonlyArray<ProjectReference> | undefined, options: CompilerOptions, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) {
const host = createCompilerHost(options);
enableStatistics(options);
const program = createProgram(rootFileNames, compilerOptions, compilerHost, /*oldProgram*/ undefined, configFileParsingDiagnostics);
const programOptions: CreateProgramOptions = {
rootNames,
options,
projectReferences,
host,
configFileParsingDiagnostics
};
const program = createProgram(programOptions);
const exitStatus = emitFilesAndReportErrors(program, reportDiagnostic, s => sys.write(s + sys.newLine));
reportStatistics(program);
return sys.exit(exitStatus);
+74 -3
View File
@@ -397,6 +397,8 @@ namespace ts {
// Top-level nodes
SourceFile,
Bundle,
UnparsedSource,
InputFiles,
// JSDoc nodes
JSDocTypeExpression,
@@ -2601,6 +2603,12 @@ namespace ts {
/* @internal */ resolvedModules: Map<ResolvedModuleFull | undefined>;
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
/* @internal */ imports: ReadonlyArray<StringLiteralLike>;
/**
* When a file's references are redirected due to project reference directives,
* the original names of the references are stored in this array
*/
/* @internal*/
redirectedReferences?: ReadonlyArray<string>;
// Identifier only if `declare global`
/* @internal */ moduleAugmentations: ReadonlyArray<StringLiteral | Identifier>;
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
@@ -2614,12 +2622,24 @@ namespace ts {
export interface Bundle extends Node {
kind: SyntaxKind.Bundle;
prepends: ReadonlyArray<InputFiles | UnparsedSource>;
sourceFiles: ReadonlyArray<SourceFile>;
/* @internal */ syntheticFileReferences?: ReadonlyArray<FileReference>;
/* @internal */ syntheticTypeReferences?: ReadonlyArray<FileReference>;
/* @internal */ hasNoDefaultLib?: boolean;
}
export interface InputFiles extends Node {
kind: SyntaxKind.InputFiles;
javascriptText: string;
declarationText: string;
}
export interface UnparsedSource extends Node {
kind: SyntaxKind.UnparsedSource;
text: string;
}
export interface JsonSourceFile extends SourceFile {
statements: NodeArray<JsonObjectExpressionStatement>;
}
@@ -2751,6 +2771,13 @@ namespace ts {
/* @internal */ isEmittedFile(file: string): boolean;
/* @internal */ getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
}
export interface ResolvedProjectReference {
commandLine: ParsedCommandLine;
sourceFile: SourceFile;
}
/* @internal */
@@ -4175,7 +4202,18 @@ namespace ts {
name: string;
}
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | null | undefined;
export interface ProjectReference {
/** A normalized path on disk */
path: string;
/** The path as the user originally wrote it */
originalPath?: string;
/** True if the output of this reference should be prepended to the output of this project. Only valid for --outFile compilations */
prepend?: boolean;
/** True if it is intended that this reference form a circularity */
circular?: boolean;
}
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | ProjectReference[] | null | undefined;
export interface CompilerOptions {
/*@internal*/ all?: boolean;
@@ -4247,6 +4285,7 @@ namespace ts {
/* @internal */ pretty?: boolean;
reactNamespace?: string;
jsxFactory?: string;
composite?: boolean;
removeComments?: boolean;
rootDir?: string;
rootDirs?: string[];
@@ -4340,12 +4379,13 @@ namespace ts {
ES2017 = 4,
ES2018 = 5,
ESNext = 6,
JSON = 100,
Latest = ESNext,
}
export const enum LanguageVariant {
Standard,
JSX,
JSX
}
/** Either a parsed command line or a parsed tsconfig.json */
@@ -4353,6 +4393,7 @@ namespace ts {
options: CompilerOptions;
typeAcquisition?: TypeAcquisition;
fileNames: string[];
projectReferences?: ReadonlyArray<ProjectReference>;
raw?: any;
errors: Diagnostic[];
wildcardDirectories?: MapLike<WatchDirectoryFlags>;
@@ -4368,6 +4409,7 @@ namespace ts {
/* @internal */
export interface ConfigFileSpecs {
filesSpecs: ReadonlyArray<string>;
referencesSpecs: ReadonlyArray<ProjectReference> | undefined;
/**
* Present to report errors (user specified specs), validatedIncludeSpecs are used for file name matching
*/
@@ -4383,10 +4425,20 @@ namespace ts {
export interface ExpandResult {
fileNames: string[];
projectReferences: ReadonlyArray<ProjectReference> | undefined;
wildcardDirectories: MapLike<WatchDirectoryFlags>;
/* @internal */ spec: ConfigFileSpecs;
}
export interface CreateProgramOptions {
rootNames: ReadonlyArray<string>;
options: CompilerOptions;
projectReferences?: ReadonlyArray<ProjectReference>;
host?: CompilerHost;
oldProgram?: Program;
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
}
/* @internal */
export interface CommandLineOptionBase {
name: string;
@@ -4673,6 +4725,7 @@ namespace ts {
getCanonicalFileName(fileName: string): string;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
readDirectory?(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): string[];
/*
* CompilerHost must either implement resolveModuleNames (in case if it wants to be completely in charge of
@@ -4911,6 +4964,8 @@ namespace ts {
isEmitBlocked(emitFileName: string): boolean;
getPrependNodes(): ReadonlyArray<InputFiles>;
writeFile: WriteFileCallback;
}
@@ -5062,7 +5117,23 @@ namespace ts {
/*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
/*@internal*/ writeList<T extends Node>(format: ListFormat, list: NodeArray<T>, sourceFile: SourceFile | undefined, writer: EmitTextWriter): void;
/*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void;
/*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter): void;
/*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter, info?: BundleInfo): void;
}
/**
* When a bundle contains prepended content, we store a file on disk indicating where the non-prepended
* content of that file starts. On a subsequent build where there are no upstream .d.ts changes, we
* read the bundle info file and the original .js file to quickly re-use portion of the file
* that didn't originate in prepended content.
*/
/* @internal */
export interface BundleInfo {
// The offset (in characters, i.e. suitable for .substr) at which the
// non-prepended portion of the emitted file starts.
originalOffset: number;
// The total length of this bundle. Used to ensure we're pulling from
// the same source as we originally wrote.
totalLength: number;
}
export interface PrintHandlers {
+1
View File
@@ -2915,6 +2915,7 @@ namespace ts {
sourceMapFilePath: string | undefined;
declarationFilePath: string | undefined;
declarationMapPath: string | undefined;
bundleInfoPath: string | undefined;
}
/**
-42
View File
@@ -86,13 +86,6 @@ namespace ts {
};
}
/**
* Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors
*/
export interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter {
getCurrentDirectory(): string;
}
/** Parses config file using System interface */
export function parseConfigFileWithSystem(configFileName: string, optionsToExtend: CompilerOptions, system: System, reportDiagnostic: DiagnosticReporter) {
const host: ParseConfigFileHost = <any>system;
@@ -102,30 +95,6 @@ namespace ts {
return result;
}
/**
* Reads the config file, reports errors if any and exits if the config file cannot be found
*/
export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined {
let configFileText: string;
try {
configFileText = host.readFile(configFileName);
}
catch (e) {
const error = createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, configFileName, e.message);
host.onUnRecoverableConfigFileDiagnostic(error);
return undefined;
}
if (!configFileText) {
const error = createCompilerDiagnostic(Diagnostics.File_0_not_found, configFileName);
host.onUnRecoverableConfigFileDiagnostic(error);
return undefined;
}
const result = parseJsonText(configFileName, configFileText);
const cwd = host.getCurrentDirectory();
return parseJsonSourceFileConfigFileContent(result, host, getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), optionsToExtend, getNormalizedAbsolutePath(configFileName, cwd));
}
/**
* Program structure needed to emit the files and report diagnostics
*/
@@ -297,7 +266,6 @@ namespace ts {
}
namespace ts {
export type DiagnosticReporter = (diagnostic: Diagnostic) => void;
export type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => 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: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) => T;
@@ -382,16 +350,6 @@ namespace ts {
options: CompilerOptions;
}
/**
* Reports config file diagnostics
*/
export interface ConfigFileDiagnosticsReporter {
/**
* Reports unrecoverable error when parsing config file
*/
onUnRecoverableConfigFileDiagnostic: DiagnosticReporter;
}
/**
* Host to create watch with config file
*/
+4
View File
@@ -256,6 +256,10 @@ namespace fakes {
return this.sys.getDirectories(path);
}
public readDirectory(path: string, extensions?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[] {
return this.sys.readDirectory(path, extensions, exclude, include, depth);
}
public readFile(path: string): string | undefined {
return this.sys.readFile(path);
}
@@ -14,7 +14,7 @@ namespace ts {
const { options: actualCompilerOptions, errors: actualErrors} = convertCompilerOptionsFromJson(json.compilerOptions, "/apath/", configFileName);
const parsedCompilerOptions = JSON.stringify(actualCompilerOptions);
const expectedCompilerOptions = JSON.stringify(expectedResult.compilerOptions);
const expectedCompilerOptions = JSON.stringify({ ...expectedResult.compilerOptions, configFilePath: configFileName });
assert.equal(parsedCompilerOptions, expectedCompilerOptions);
const expectedErrors = expectedResult.errors;
+291
View File
@@ -0,0 +1,291 @@
/// <reference path="../harness.ts" />
/// <reference path="../../compiler/commandLineParser.ts" />
namespace ts {
interface TestProjectSpecification {
configFileName?: string;
references?: ReadonlyArray<string | ProjectReference>;
files: { [fileName: string]: string };
outputFiles?: { [fileName: string]: string };
config?: object;
options?: Partial<CompilerOptions>;
}
interface TestSpecification {
[path: string]: TestProjectSpecification;
}
function assertHasError(message: string, errors: ReadonlyArray<Diagnostic>, diag: DiagnosticMessage) {
if (!errors.some(e => e.code === diag.code)) {
const errorString = errors.map(e => ` ${e.file ? e.file.fileName : "[global]"}: ${e.messageText}`).join("\r\n");
assert(false, `${message}: Did not find any diagnostic for ${diag.message} in:\r\n${errorString}`);
}
}
function assertNoErrors(message: string, errors: ReadonlyArray<Diagnostic>) {
if (errors && errors.length > 0) {
assert(false, `${message}: Expected no errors, but found:\r\n${errors.map(e => ` ${e.messageText}`).join("\r\n")}`);
}
}
function combineAllPaths(...paths: string[]) {
let result = paths[0];
for (let i = 1; i < paths.length; i++) {
result = combinePaths(result, paths[i]);
}
return result;
}
const emptyModule = "export { };";
/**
* Produces the text of a source file which imports all of the
* specified module names
*/
function moduleImporting(...names: string[]) {
return names.map((n, i) => `import * as mod_${i} from ${n}`).join("\r\n");
}
function testProjectReferences(spec: TestSpecification, entryPointConfigFileName: string, checkResult: (prog: Program, host: fakes.CompilerHost) => void) {
const files = createMap<string>();
for (const key in spec) {
const sp = spec[key];
const configFileName = combineAllPaths("/", key, sp.configFileName || "tsconfig.json");
const options = {
compilerOptions: {
composite: true,
outDir: "bin",
...sp.options
},
references: (sp.references || []).map(r => {
if (typeof r === "string") {
return { path: r };
}
return r;
}),
...sp.config
};
const configContent = JSON.stringify(options);
const outDir = options.compilerOptions.outDir;
files.set(configFileName, configContent);
for (const sourceFile of Object.keys(sp.files)) {
files.set(sourceFile, sp.files[sourceFile]);
}
if (sp.outputFiles) {
for (const outFile of Object.keys(sp.outputFiles)) {
files.set(combineAllPaths("/", key, outDir, outFile), sp.outputFiles[outFile]);
}
}
}
const vfsys = new vfs.FileSystem(false, { files: { "/lib.d.ts": TestFSWithWatch.libFile.content! } });
files.forEach((v, k) => {
vfsys.mkdirpSync(getDirectoryPath(k));
vfsys.writeFileSync(k, v);
});
const host = new fakes.CompilerHost(new fakes.System(vfsys));
const { config, error } = readConfigFile(entryPointConfigFileName, name => host.readFile(name));
// We shouldn't have any errors about invalid tsconfig files in these tests
assert(config && !error, flattenDiagnosticMessageText(error && error.messageText, "\n"));
const file = parseJsonConfigFileContent(config, parseConfigHostFromCompilerHost(host), getDirectoryPath(entryPointConfigFileName), {}, entryPointConfigFileName);
file.options.configFilePath = entryPointConfigFileName;
const prog = createProgram({
rootNames: file.fileNames,
options: file.options,
host,
projectReferences: file.projectReferences
});
checkResult(prog, host);
}
describe("project-references meta check", () => {
it("default setup was created correctly", () => {
const spec: TestSpecification = {
"/primary": {
files: { "/primary/a.ts": emptyModule },
references: []
},
"/reference": {
files: { "/secondary/b.ts": moduleImporting("../primary/a") },
references: ["../primary"]
}
};
testProjectReferences(spec, "/primary/tsconfig.json", prog => {
assert.isTrue(!!prog, "Program should exist");
assertNoErrors("Sanity check should not produce errors", prog.getOptionsDiagnostics());
});
});
});
/**
* Validate that we enforce the basic settings constraints for referenced projects
*/
describe("project-references constraint checking for settings", () => {
it("errors when declaration = false", () => {
const spec: TestSpecification = {
"/primary": {
files: { "/primary/a.ts": emptyModule },
references: [],
options: {
declaration: false
}
}
};
testProjectReferences(spec, "/primary/tsconfig.json", program => {
const errs = program.getOptionsDiagnostics();
assertHasError("Reports an error about the wrong decl setting", errs, Diagnostics.Composite_projects_may_not_disable_declaration_emit);
});
});
it("errors when the referenced project doesn't have composite:true", () => {
const spec: TestSpecification = {
"/primary": {
files: { "/primary/a.ts": emptyModule },
references: [],
options: {
composite: false
}
},
"/reference": {
files: { "/secondary/b.ts": moduleImporting("../primary/a") },
references: ["../primary"]
}
};
testProjectReferences(spec, "/reference/tsconfig.json", program => {
const errs = program.getOptionsDiagnostics();
assertHasError("Reports an error about 'composite' not being set", errs, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true);
});
});
it("errors when the file list is not exhaustive", () => {
const spec: TestSpecification = {
"/primary": {
files: {
"/primary/a.ts": "import * as b from './b'",
"/primary/b.ts": "export {}"
},
config: {
files: ["a.ts"]
}
}
};
testProjectReferences(spec, "/primary/tsconfig.json", program => {
const errs = program.getOptionsDiagnostics();
assertHasError("Reports an error about b.ts not being in the list", errs, Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern);
});
});
it("errors when the referenced project doesn't exist", () => {
const spec: TestSpecification = {
"/primary": {
files: { "/primary/a.ts": emptyModule },
references: ["../foo"]
}
};
testProjectReferences(spec, "/primary/tsconfig.json", program => {
const errs = program.getOptionsDiagnostics();
assertHasError("Reports an error about a missing file", errs, Diagnostics.File_0_does_not_exist);
});
});
it("errors when a prepended project reference doesn't set outFile", () => {
const spec: TestSpecification = {
"/primary": {
files: { "/primary/a.ts": emptyModule },
references: [{ path: "../someProj", prepend: true }]
},
"/someProj": {
files: { "/someProj/b.ts": "const x = 100;" }
}
};
testProjectReferences(spec, "/primary/tsconfig.json", program => {
const errs = program.getOptionsDiagnostics();
assertHasError("Reports an error about outFile not being set", errs, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set);
});
});
it("errors when a prepended project reference output doesn't exist", () => {
const spec: TestSpecification = {
"/primary": {
files: { "/primary/a.ts": "const y = x;" },
references: [{ path: "../someProj", prepend: true }]
},
"/someProj": {
files: { "/someProj/b.ts": "const x = 100;" },
options: { outFile: "foo.js" }
}
};
testProjectReferences(spec, "/primary/tsconfig.json", program => {
const errs = program.getOptionsDiagnostics();
assertHasError("Reports an error about outFile being missing", errs, Diagnostics.Output_file_0_from_project_1_does_not_exist);
});
});
});
/**
* Path mapping behavior
*/
describe("project-references path mapping", () => {
it("redirects to the output .d.ts file", () => {
const spec: TestSpecification = {
"/alpha": {
files: { "/alpha/a.ts": "export const m: number = 3;" },
references: [],
outputFiles: { "a.d.ts": emptyModule }
},
"/beta": {
files: { "/beta/b.ts": "import { m } from '../alpha/a'" },
references: ["../alpha"]
}
};
testProjectReferences(spec, "/beta/tsconfig.json", program => {
assertNoErrors("File setup should be correct", program.getOptionsDiagnostics());
assertHasError("Found a type error", program.getSemanticDiagnostics(), Diagnostics.Module_0_has_no_exported_member_1);
});
});
});
describe("project-references nice-behavior", () => {
it("issues a nice error when the input file is missing", () => {
const spec: TestSpecification = {
"/alpha": {
files: { "/alpha/a.ts": "export const m: number = 3;" },
references: []
},
"/beta": {
files: { "/beta/b.ts": "import { m } from '../alpha/a'" },
references: ["../alpha"]
}
};
testProjectReferences(spec, "/beta/tsconfig.json", program => {
assertHasError("Issues a useful error", program.getSemanticDiagnostics(), Diagnostics.Output_file_0_has_not_been_built_from_source_file_1);
});
});
});
/**
* 'composite' behavior
*/
describe("project-references behavior changes under composite: true", () => {
it("doesn't infer the rootDir from source paths", () => {
const spec: TestSpecification = {
"/alpha": {
files: { "/alpha/src/a.ts": "export const m: number = 3;" },
options: {
declaration: true,
outDir: "bin"
},
references: []
}
};
testProjectReferences(spec, "/alpha/tsconfig.json", (program, host) => {
program.emit();
assert.deepEqual(host.outputs.map(e => e.file).sort(), ["/alpha/bin/src/a.d.ts", "/alpha/bin/src/a.js"]);
});
});
});
}
+5
View File
@@ -139,6 +139,11 @@ namespace ts.server {
this.processRequest(CommandNames.Change, args);
}
toLineColumnOffset(fileName: string, position: number) {
const { line, offset } = this.positionToOneBasedLineOffset(fileName, position);
return { line, character: offset };
}
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo {
const args = this.createFileLocationRequestArgs(fileName, position);
+5 -2
View File
@@ -1331,7 +1331,8 @@ namespace ts.server {
configHasExcludeProperty: parsedCommandLine.raw.exclude !== undefined,
wildcardDirectories: createMapFromTemplate(parsedCommandLine.wildcardDirectories),
typeAcquisition: parsedCommandLine.typeAcquisition,
compileOnSave: parsedCommandLine.compileOnSave
compileOnSave: parsedCommandLine.compileOnSave,
projectReferences: parsedCommandLine.projectReferences
};
return { projectOptions, configFileErrors: errors, configFileSpecs: parsedCommandLine.configFileSpecs };
@@ -1464,7 +1465,8 @@ namespace ts.server {
projectOptions.compilerOptions,
lastFileExceededProgramSize,
projectOptions.compileOnSave === undefined ? false : projectOptions.compileOnSave,
cachedDirectoryStructureHost);
cachedDirectoryStructureHost,
projectOptions.projectReferences);
project.configFileSpecs = configFileSpecs;
// TODO: We probably should also watch the configFiles that are extended
@@ -1589,6 +1591,7 @@ namespace ts.server {
// Update the project
project.configFileSpecs = configFileSpecs;
project.setProjectErrors(configFileErrors);
project.updateReferences(projectOptions.projectReferences);
const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader);
if (lastFileExceededProgramSize) {
project.disableLanguageService(lastFileExceededProgramSize);
+14 -1
View File
@@ -265,6 +265,10 @@ namespace ts.server {
return this.projectStateVersion.toString();
}
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined {
return undefined;
}
getScriptFileNames() {
if (!this.rootFiles) {
return ts.emptyArray;
@@ -1288,7 +1292,8 @@ namespace ts.server {
compilerOptions: CompilerOptions,
lastFileExceededProgramSize: string | undefined,
public compileOnSaveEnabled: boolean,
cachedDirectoryStructureHost: CachedDirectoryStructureHost) {
cachedDirectoryStructureHost: CachedDirectoryStructureHost,
private projectReferences: ReadonlyArray<ProjectReference> | undefined) {
super(configFileName,
ProjectKind.Configured,
projectService,
@@ -1330,6 +1335,14 @@ namespace ts.server {
return asNormalizedPath(this.getProjectName());
}
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined {
return this.projectReferences;
}
updateReferences(refs: ReadonlyArray<ProjectReference> | undefined) {
this.projectReferences = refs;
}
enablePlugins() {
const host = this.projectService.host;
const options = this.getCompilationSettings();
+1
View File
@@ -2734,6 +2734,7 @@ namespace ts.server.protocol {
project?: string;
reactNamespace?: string;
removeComments?: boolean;
references?: ProjectReference[];
rootDir?: string;
rootDirs?: string[];
skipLibCheck?: boolean;
+5 -3
View File
@@ -699,12 +699,14 @@ namespace ts.server {
}
private toFileSpan(fileName: string, textSpan: TextSpan, project: Project): protocol.FileSpan {
const scriptInfo = project.getScriptInfo(fileName);
const ls = project.getLanguageService();
const start = ls.toLineColumnOffset(fileName, textSpan.start);
const end = ls.toLineColumnOffset(fileName, textSpanEnd(textSpan));
return {
file: fileName,
start: scriptInfo.positionToLineOffset(textSpan.start),
end: scriptInfo.positionToLineOffset(textSpanEnd(textSpan))
start: { line: start.line + 1, offset: start.character + 1 },
end: { line: end.line + 1, offset: end.character + 1 }
};
}
+2
View File
@@ -128,6 +128,8 @@ namespace ts.server {
configHasFilesProperty: boolean;
configHasIncludeProperty: boolean;
configHasExcludeProperty: boolean;
projectReferences: ReadonlyArray<ProjectReference> | undefined;
/**
* these fields can be present in the project file
*/
+2 -1
View File
@@ -172,9 +172,10 @@ namespace ts {
const bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true);
let entry = bucket.get(path);
const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON : compilationSettings.target;
if (!entry) {
// Have never seen this file with these settings. Create a new source file for it.
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind);
const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, /*setNodeParents*/ false, scriptKind);
entry = {
sourceFile,
+1 -1
View File
@@ -45,7 +45,7 @@ namespace ts {
if (checker.getSymbolAtLocation(importStringLiteral)) continue;
const resolved = program.getResolvedModuleWithFailedLookupLocationsFromCache(importStringLiteral.text, sourceFile.fileName);
if (contains(resolved.failedLookupLocations, oldFilePath)) {
if (resolved && contains(resolved.failedLookupLocations, oldFilePath)) {
result.push({ sourceFile, toUpdate: importStringLiteral });
}
}
+30 -3
View File
@@ -878,6 +878,10 @@ namespace ts {
return this._compilationSettings;
}
public getProjectReferences(): ReadonlyArray<ProjectReference> | undefined {
return this.host.getProjectReferences && this.host.getProjectReferences();
}
private createEntry(fileName: string, path: Path) {
let entry: CachedHostFileInformation;
const scriptSnapshot = this.host.getScriptSnapshot(fileName);
@@ -912,9 +916,18 @@ namespace ts {
}
public getRootFileNames(): string[] {
return arrayFrom(this.fileNameToEntry.values(), entry => {
return isString(entry) ? entry : entry.hostFileName;
const names: string[] = [];
this.fileNameToEntry.forEach(entry => {
if (isString(entry)) {
names.push(entry);
}
else {
if (entry.scriptKind !== ScriptKind.JSON) {
names.push(entry.hostFileName);
}
}
});
return names;
}
public getVersion(path: Path): string {
@@ -1241,7 +1254,14 @@ namespace ts {
}
const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);
program = createProgram(rootFileNames, newSettings, compilerHost, program);
const options: CreateProgramOptions = {
rootNames: rootFileNames,
options: newSettings,
host: compilerHost,
oldProgram: program,
projectReferences: hostCache.getProjectReferences()
};
program = createProgram(options);
// hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point.
// It needs to be cleared to allow all collected snapshots to be released
@@ -1501,6 +1521,12 @@ namespace ts {
return checker.getSymbolAtLocation(node);
}
function toLineColumnOffset(fileName: string, position: number) {
const path = toPath(fileName, currentDirectory, getCanonicalFileName);
const file = program.getSourceFile(path) || sourcemappedFileCache.get(path);
return file.getLineAndCharacterOfPosition(position);
}
// Sometimes tools can sometimes see the following line as a source mapping url comment, so we mangle it a bit (the [M])
const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)$/gm;
const base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+\/=]+)$)?/;
@@ -2265,6 +2291,7 @@ namespace ts {
getProgram,
getApplicableRefactors,
getEditsForRefactor,
toLineColumnOffset
};
}
+3
View File
@@ -179,6 +179,7 @@ namespace ts {
getScriptKind?(fileName: string): ScriptKind;
getScriptVersion(fileName: string): string;
getScriptSnapshot(fileName: string): IScriptSnapshot | undefined;
getProjectReferences?(): ReadonlyArray<ProjectReference> | undefined;
getLocalizedDiagnosticMessages?(): any;
getCancellationToken?(): HostCancellationToken;
getCurrentDirectory(): string;
@@ -320,6 +321,8 @@ namespace ts {
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan;
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
+104 -43
View File
@@ -337,32 +337,34 @@ declare namespace ts {
EnumMember = 272,
SourceFile = 273,
Bundle = 274,
JSDocTypeExpression = 275,
JSDocAllType = 276,
JSDocUnknownType = 277,
JSDocNullableType = 278,
JSDocNonNullableType = 279,
JSDocOptionalType = 280,
JSDocFunctionType = 281,
JSDocVariadicType = 282,
JSDocComment = 283,
JSDocTypeLiteral = 284,
JSDocTag = 285,
JSDocAugmentsTag = 286,
JSDocClassTag = 287,
JSDocParameterTag = 288,
JSDocReturnTag = 289,
JSDocTypeTag = 290,
JSDocTemplateTag = 291,
JSDocTypedefTag = 292,
JSDocPropertyTag = 293,
SyntaxList = 294,
NotEmittedStatement = 295,
PartiallyEmittedExpression = 296,
CommaListExpression = 297,
MergeDeclarationMarker = 298,
EndOfDeclarationMarker = 299,
Count = 300,
UnparsedSource = 275,
InputFiles = 276,
JSDocTypeExpression = 277,
JSDocAllType = 278,
JSDocUnknownType = 279,
JSDocNullableType = 280,
JSDocNonNullableType = 281,
JSDocOptionalType = 282,
JSDocFunctionType = 283,
JSDocVariadicType = 284,
JSDocComment = 285,
JSDocTypeLiteral = 286,
JSDocTag = 287,
JSDocAugmentsTag = 288,
JSDocClassTag = 289,
JSDocParameterTag = 290,
JSDocReturnTag = 291,
JSDocTypeTag = 292,
JSDocTemplateTag = 293,
JSDocTypedefTag = 294,
JSDocPropertyTag = 295,
SyntaxList = 296,
NotEmittedStatement = 297,
PartiallyEmittedExpression = 298,
CommaListExpression = 299,
MergeDeclarationMarker = 300,
EndOfDeclarationMarker = 301,
Count = 302,
FirstAssignment = 58,
LastAssignment = 70,
FirstCompoundAssignment = 59,
@@ -388,10 +390,10 @@ declare namespace ts {
FirstBinaryOperator = 27,
LastBinaryOperator = 70,
FirstNode = 145,
FirstJSDocNode = 275,
LastJSDocNode = 293,
FirstJSDocTagNode = 285,
LastJSDocTagNode = 293
FirstJSDocNode = 277,
LastJSDocNode = 295,
FirstJSDocTagNode = 287,
LastJSDocTagNode = 295
}
enum NodeFlags {
None = 0,
@@ -1645,8 +1647,18 @@ declare namespace ts {
}
interface Bundle extends Node {
kind: SyntaxKind.Bundle;
prepends: ReadonlyArray<InputFiles | UnparsedSource>;
sourceFiles: ReadonlyArray<SourceFile>;
}
interface InputFiles extends Node {
kind: SyntaxKind.InputFiles;
javascriptText: string;
declarationText: string;
}
interface UnparsedSource extends Node {
kind: SyntaxKind.UnparsedSource;
text: string;
}
interface JsonSourceFile extends SourceFile {
statements: NodeArray<JsonObjectExpressionStatement>;
}
@@ -1716,6 +1728,11 @@ declare namespace ts {
*/
getTypeChecker(): TypeChecker;
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
}
interface ResolvedProjectReference {
commandLine: ParsedCommandLine;
sourceFile: SourceFile;
}
interface CustomTransformers {
/** Custom transformers to evaluate before built-in transformations. */
@@ -2335,7 +2352,17 @@ declare namespace ts {
interface PluginImport {
name: string;
}
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | null | undefined;
interface ProjectReference {
/** A normalized path on disk */
path: string;
/** The path as the user originally wrote it */
originalPath?: string;
/** True if the output of this reference should be prepended to the output of this project. Only valid for --outFile compilations */
prepend?: boolean;
/** True if it is intended that this reference form a circularity */
circular?: boolean;
}
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | ProjectReference[] | null | undefined;
interface CompilerOptions {
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
@@ -2391,6 +2418,7 @@ declare namespace ts {
project?: string;
reactNamespace?: string;
jsxFactory?: string;
composite?: boolean;
removeComments?: boolean;
rootDir?: string;
rootDirs?: string[];
@@ -2466,6 +2494,7 @@ declare namespace ts {
ES2017 = 4,
ES2018 = 5,
ESNext = 6,
JSON = 100,
Latest = 6
}
enum LanguageVariant {
@@ -2477,6 +2506,7 @@ declare namespace ts {
options: CompilerOptions;
typeAcquisition?: TypeAcquisition;
fileNames: string[];
projectReferences?: ReadonlyArray<ProjectReference>;
raw?: any;
errors: Diagnostic[];
wildcardDirectories?: MapLike<WatchDirectoryFlags>;
@@ -2488,8 +2518,17 @@ declare namespace ts {
}
interface ExpandResult {
fileNames: string[];
projectReferences: ReadonlyArray<ProjectReference> | undefined;
wildcardDirectories: MapLike<WatchDirectoryFlags>;
}
interface CreateProgramOptions {
rootNames: ReadonlyArray<string>;
options: CompilerOptions;
projectReferences?: ReadonlyArray<ProjectReference>;
host?: CompilerHost;
oldProgram?: Program;
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
}
interface ModuleResolutionHost {
fileExists(fileName: string): boolean;
readFile(fileName: string): string | undefined;
@@ -2580,6 +2619,7 @@ declare namespace ts {
getCanonicalFileName(fileName: string): string;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
readDirectory?(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): string[];
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): (ResolvedModule | undefined)[];
/**
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
@@ -3746,8 +3786,10 @@ declare namespace ts {
function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression;
function createCommaList(elements: ReadonlyArray<Expression>): CommaListExpression;
function updateCommaList(node: CommaListExpression, elements: ReadonlyArray<Expression>): CommaListExpression;
function createBundle(sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function createBundle(sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource | InputFiles>): Bundle;
function createUnparsedSourceFile(text: string): UnparsedSource;
function createInputFiles(javascript: string, declaration: string): InputFiles;
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource>): Bundle;
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>): CallExpression;
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>, param: ParameterDeclaration, paramValue: Expression): CallExpression;
function createImmediatelyInvokedArrowFunction(statements: ReadonlyArray<Statement>): CallExpression;
@@ -3954,6 +3996,7 @@ declare namespace ts {
* @param configFileParsingDiagnostics - error during config file parsing
* @returns A 'Program' object.
*/
function createProgram(createProgramOptions: CreateProgramOptions): Program;
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
}
declare namespace ts {
@@ -4093,7 +4136,6 @@ declare namespace ts {
function createAbstractBuilder(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): BuilderProgram;
}
declare namespace ts {
type DiagnosticReporter = (diagnostic: Diagnostic) => void;
type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) => T;
@@ -4156,15 +4198,6 @@ declare namespace ts {
/** Compiler options */
options: CompilerOptions;
}
/**
* Reports config file diagnostics
*/
interface ConfigFileDiagnosticsReporter {
/**
* Reports unrecoverable error when parsing config file
*/
onUnRecoverableConfigFileDiagnostic: DiagnosticReporter;
}
/**
* Host to create watch with config file
*/
@@ -4211,6 +4244,26 @@ declare namespace ts {
}
declare namespace ts {
function parseCommandLine(commandLine: ReadonlyArray<string>, readFile?: (path: string) => string | undefined): ParsedCommandLine;
type DiagnosticReporter = (diagnostic: Diagnostic) => void;
/**
* Reports config file diagnostics
*/
interface ConfigFileDiagnosticsReporter {
/**
* Reports unrecoverable error when parsing config file
*/
onUnRecoverableConfigFileDiagnostic: DiagnosticReporter;
}
/**
* Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors
*/
interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter {
getCurrentDirectory(): string;
}
/**
* Reads the config file, reports errors if any and exits if the config file cannot be found
*/
function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined;
/**
* Read tsconfig.json file
* @param fileName The path to the config file
@@ -4383,6 +4436,7 @@ declare namespace ts {
getScriptKind?(fileName: string): ScriptKind;
getScriptVersion(fileName: string): string;
getScriptSnapshot(fileName: string): IScriptSnapshot | undefined;
getProjectReferences?(): ReadonlyArray<ProjectReference> | undefined;
getLocalizedDiagnosticMessages?(): any;
getCancellationToken?(): HostCancellationToken;
getCurrentDirectory(): string;
@@ -4460,6 +4514,7 @@ declare namespace ts {
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion;
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan;
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
@@ -5383,6 +5438,7 @@ declare namespace ts.server {
configHasFilesProperty: boolean;
configHasIncludeProperty: boolean;
configHasExcludeProperty: boolean;
projectReferences: ReadonlyArray<ProjectReference> | undefined;
/**
* these fields can be present in the project file
*/
@@ -7562,6 +7618,7 @@ declare namespace ts.server.protocol {
project?: string;
reactNamespace?: string;
removeComments?: boolean;
references?: ProjectReference[];
rootDir?: string;
rootDirs?: string[];
skipLibCheck?: boolean;
@@ -7758,6 +7815,7 @@ declare namespace ts.server {
getCompilerOptions(): CompilerOptions;
getNewLine(): string;
getProjectVersion(): string;
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined;
getScriptFileNames(): string[];
private getOrCreateScriptInfoAndAttachToProject;
getScriptKind(fileName: string): ScriptKind;
@@ -7859,6 +7917,7 @@ declare namespace ts.server {
*/
class ConfiguredProject extends Project {
compileOnSaveEnabled: boolean;
private projectReferences;
private typeAcquisition;
private directoriesWatchedForWildcards;
readonly canonicalConfigFilePath: NormalizedPath;
@@ -7871,6 +7930,8 @@ declare namespace ts.server {
*/
updateGraph(): boolean;
getConfigFilePath(): NormalizedPath;
getProjectReferences(): ReadonlyArray<ProjectReference> | undefined;
updateReferences(refs: ReadonlyArray<ProjectReference> | undefined): void;
enablePlugins(): void;
/**
* Get the errors that dont have any file name associated
+98 -43
View File
@@ -337,32 +337,34 @@ declare namespace ts {
EnumMember = 272,
SourceFile = 273,
Bundle = 274,
JSDocTypeExpression = 275,
JSDocAllType = 276,
JSDocUnknownType = 277,
JSDocNullableType = 278,
JSDocNonNullableType = 279,
JSDocOptionalType = 280,
JSDocFunctionType = 281,
JSDocVariadicType = 282,
JSDocComment = 283,
JSDocTypeLiteral = 284,
JSDocTag = 285,
JSDocAugmentsTag = 286,
JSDocClassTag = 287,
JSDocParameterTag = 288,
JSDocReturnTag = 289,
JSDocTypeTag = 290,
JSDocTemplateTag = 291,
JSDocTypedefTag = 292,
JSDocPropertyTag = 293,
SyntaxList = 294,
NotEmittedStatement = 295,
PartiallyEmittedExpression = 296,
CommaListExpression = 297,
MergeDeclarationMarker = 298,
EndOfDeclarationMarker = 299,
Count = 300,
UnparsedSource = 275,
InputFiles = 276,
JSDocTypeExpression = 277,
JSDocAllType = 278,
JSDocUnknownType = 279,
JSDocNullableType = 280,
JSDocNonNullableType = 281,
JSDocOptionalType = 282,
JSDocFunctionType = 283,
JSDocVariadicType = 284,
JSDocComment = 285,
JSDocTypeLiteral = 286,
JSDocTag = 287,
JSDocAugmentsTag = 288,
JSDocClassTag = 289,
JSDocParameterTag = 290,
JSDocReturnTag = 291,
JSDocTypeTag = 292,
JSDocTemplateTag = 293,
JSDocTypedefTag = 294,
JSDocPropertyTag = 295,
SyntaxList = 296,
NotEmittedStatement = 297,
PartiallyEmittedExpression = 298,
CommaListExpression = 299,
MergeDeclarationMarker = 300,
EndOfDeclarationMarker = 301,
Count = 302,
FirstAssignment = 58,
LastAssignment = 70,
FirstCompoundAssignment = 59,
@@ -388,10 +390,10 @@ declare namespace ts {
FirstBinaryOperator = 27,
LastBinaryOperator = 70,
FirstNode = 145,
FirstJSDocNode = 275,
LastJSDocNode = 293,
FirstJSDocTagNode = 285,
LastJSDocTagNode = 293
FirstJSDocNode = 277,
LastJSDocNode = 295,
FirstJSDocTagNode = 287,
LastJSDocTagNode = 295
}
enum NodeFlags {
None = 0,
@@ -1645,8 +1647,18 @@ declare namespace ts {
}
interface Bundle extends Node {
kind: SyntaxKind.Bundle;
prepends: ReadonlyArray<InputFiles | UnparsedSource>;
sourceFiles: ReadonlyArray<SourceFile>;
}
interface InputFiles extends Node {
kind: SyntaxKind.InputFiles;
javascriptText: string;
declarationText: string;
}
interface UnparsedSource extends Node {
kind: SyntaxKind.UnparsedSource;
text: string;
}
interface JsonSourceFile extends SourceFile {
statements: NodeArray<JsonObjectExpressionStatement>;
}
@@ -1716,6 +1728,11 @@ declare namespace ts {
*/
getTypeChecker(): TypeChecker;
isSourceFileFromExternalLibrary(file: SourceFile): boolean;
getProjectReferences(): (ResolvedProjectReference | undefined)[] | undefined;
}
interface ResolvedProjectReference {
commandLine: ParsedCommandLine;
sourceFile: SourceFile;
}
interface CustomTransformers {
/** Custom transformers to evaluate before built-in transformations. */
@@ -2335,7 +2352,17 @@ declare namespace ts {
interface PluginImport {
name: string;
}
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | null | undefined;
interface ProjectReference {
/** A normalized path on disk */
path: string;
/** The path as the user originally wrote it */
originalPath?: string;
/** True if the output of this reference should be prepended to the output of this project. Only valid for --outFile compilations */
prepend?: boolean;
/** True if it is intended that this reference form a circularity */
circular?: boolean;
}
type CompilerOptionsValue = string | number | boolean | (string | number)[] | string[] | MapLike<string[]> | PluginImport[] | ProjectReference[] | null | undefined;
interface CompilerOptions {
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
@@ -2391,6 +2418,7 @@ declare namespace ts {
project?: string;
reactNamespace?: string;
jsxFactory?: string;
composite?: boolean;
removeComments?: boolean;
rootDir?: string;
rootDirs?: string[];
@@ -2466,6 +2494,7 @@ declare namespace ts {
ES2017 = 4,
ES2018 = 5,
ESNext = 6,
JSON = 100,
Latest = 6
}
enum LanguageVariant {
@@ -2477,6 +2506,7 @@ declare namespace ts {
options: CompilerOptions;
typeAcquisition?: TypeAcquisition;
fileNames: string[];
projectReferences?: ReadonlyArray<ProjectReference>;
raw?: any;
errors: Diagnostic[];
wildcardDirectories?: MapLike<WatchDirectoryFlags>;
@@ -2488,8 +2518,17 @@ declare namespace ts {
}
interface ExpandResult {
fileNames: string[];
projectReferences: ReadonlyArray<ProjectReference> | undefined;
wildcardDirectories: MapLike<WatchDirectoryFlags>;
}
interface CreateProgramOptions {
rootNames: ReadonlyArray<string>;
options: CompilerOptions;
projectReferences?: ReadonlyArray<ProjectReference>;
host?: CompilerHost;
oldProgram?: Program;
configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>;
}
interface ModuleResolutionHost {
fileExists(fileName: string): boolean;
readFile(fileName: string): string | undefined;
@@ -2580,6 +2619,7 @@ declare namespace ts {
getCanonicalFileName(fileName: string): string;
useCaseSensitiveFileNames(): boolean;
getNewLine(): string;
readDirectory?(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): string[];
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[]): (ResolvedModule | undefined)[];
/**
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
@@ -3746,8 +3786,10 @@ declare namespace ts {
function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression): PartiallyEmittedExpression;
function createCommaList(elements: ReadonlyArray<Expression>): CommaListExpression;
function updateCommaList(node: CommaListExpression, elements: ReadonlyArray<Expression>): CommaListExpression;
function createBundle(sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>): Bundle;
function createBundle(sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource | InputFiles>): Bundle;
function createUnparsedSourceFile(text: string): UnparsedSource;
function createInputFiles(javascript: string, declaration: string): InputFiles;
function updateBundle(node: Bundle, sourceFiles: ReadonlyArray<SourceFile>, prepends?: ReadonlyArray<UnparsedSource>): Bundle;
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>): CallExpression;
function createImmediatelyInvokedFunctionExpression(statements: ReadonlyArray<Statement>, param: ParameterDeclaration, paramValue: Expression): CallExpression;
function createImmediatelyInvokedArrowFunction(statements: ReadonlyArray<Statement>): CallExpression;
@@ -3954,6 +3996,7 @@ declare namespace ts {
* @param configFileParsingDiagnostics - error during config file parsing
* @returns A 'Program' object.
*/
function createProgram(createProgramOptions: CreateProgramOptions): Program;
function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
}
declare namespace ts {
@@ -4093,7 +4136,6 @@ declare namespace ts {
function createAbstractBuilder(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): BuilderProgram;
}
declare namespace ts {
type DiagnosticReporter = (diagnostic: Diagnostic) => void;
type WatchStatusReporter = (diagnostic: Diagnostic, newLine: string, options: CompilerOptions) => void;
/** Create the program with rootNames and options, if they are undefined, oldProgram and new configFile diagnostics create new program */
type CreateProgram<T extends BuilderProgram> = (rootNames: ReadonlyArray<string> | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: T, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>) => T;
@@ -4156,15 +4198,6 @@ declare namespace ts {
/** Compiler options */
options: CompilerOptions;
}
/**
* Reports config file diagnostics
*/
interface ConfigFileDiagnosticsReporter {
/**
* Reports unrecoverable error when parsing config file
*/
onUnRecoverableConfigFileDiagnostic: DiagnosticReporter;
}
/**
* Host to create watch with config file
*/
@@ -4211,6 +4244,26 @@ declare namespace ts {
}
declare namespace ts {
function parseCommandLine(commandLine: ReadonlyArray<string>, readFile?: (path: string) => string | undefined): ParsedCommandLine;
type DiagnosticReporter = (diagnostic: Diagnostic) => void;
/**
* Reports config file diagnostics
*/
interface ConfigFileDiagnosticsReporter {
/**
* Reports unrecoverable error when parsing config file
*/
onUnRecoverableConfigFileDiagnostic: DiagnosticReporter;
}
/**
* Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors
*/
interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter {
getCurrentDirectory(): string;
}
/**
* Reads the config file, reports errors if any and exits if the config file cannot be found
*/
function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost): ParsedCommandLine | undefined;
/**
* Read tsconfig.json file
* @param fileName The path to the config file
@@ -4383,6 +4436,7 @@ declare namespace ts {
getScriptKind?(fileName: string): ScriptKind;
getScriptVersion(fileName: string): string;
getScriptSnapshot(fileName: string): IScriptSnapshot | undefined;
getProjectReferences?(): ReadonlyArray<ProjectReference> | undefined;
getLocalizedDiagnosticMessages?(): any;
getCancellationToken?(): HostCancellationToken;
getCurrentDirectory(): string;
@@ -4460,6 +4514,7 @@ declare namespace ts {
getDocCommentTemplateAtPosition(fileName: string, position: number): TextInsertion;
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan;
toLineColumnOffset?(fileName: string, position: number): LineAndCharacter;
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: ReadonlyArray<number>, formatOptions: FormatCodeSettings, preferences: UserPreferences): ReadonlyArray<CodeFixAction>;
getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions;
applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
@@ -1,2 +1,2 @@
//// [bundle.d.ts.map]
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":";IAAA,MAAM;QACF,OAAO,CAAC,CAAC,EAAE;YAAC,CAAC,EAAE,MAAM,CAAA;SAAC;;;QAGtB,MAAM,CAAC,IAAI;KAGd;;;ICPD,OAAO,EAAC,GAAG,EAAC,UAAY;IAExB,MAAM,CAAC,KAAY,CAAC;IAGpB,MAAM,CAAC,IAAI,CAAC;;KAAqB,CAAC;IAClC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC"}
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":";IAAA,MAAM;QACF,OAAO,CAAC,GAAG;YAAC,CAAC,EAAE,MAAM,CAAA;SAAC;;;QAGtB,MAAM,CAAC,IAAI;KAGd;;;ICPD,OAAO,EAAC,GAAG,EAAC,UAAY;IAExB,MAAM,CAAC,KAAY,CAAC;IAGpB,MAAM,CAAC,IAAI,CAAC;;KAAqB,CAAC;IAClC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC"}
@@ -22,20 +22,17 @@ sourceFile:tests/cases/compiler/a.ts
1->^^^^^^^^
2 > ^^^^^^^
3 > ^
4 > ^
5 > ^^
6 > ^^^^->
4 > ^^^
5 > ^^^^->
1-> class Foo {
>
2 > doThing
3 > (
4 > x
5 > :
4 > x:
1->Emitted(3, 9) Source(2, 5) + SourceIndex(0)
2 >Emitted(3, 16) Source(2, 12) + SourceIndex(0)
3 >Emitted(3, 17) Source(2, 13) + SourceIndex(0)
4 >Emitted(3, 18) Source(2, 14) + SourceIndex(0)
5 >Emitted(3, 20) Source(2, 16) + SourceIndex(0)
4 >Emitted(3, 20) Source(2, 16) + SourceIndex(0)
---
>>> a: number;
1->^^^^^^^^^^^^
@@ -1,2 +1,2 @@
//// [bundle.d.ts.map]
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IACI,OAAO,CAAC,CAAC,EAAE;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd;ACPD,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,QAAA,IAAI,CAAC;;CAAqB,CAAC"}
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IACI,OAAO,CAAC,GAAG;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd;ACPD,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,QAAA,IAAI,CAAC;;CAAqB,CAAC"}
@@ -18,20 +18,17 @@ sourceFile:tests/cases/compiler/a.ts
1->^^^^
2 > ^^^^^^^
3 > ^
4 > ^
5 > ^^
6 > ^^^^->
4 > ^^^
5 > ^^^^->
1->class Foo {
>
2 > doThing
3 > (
4 > x
5 > :
4 > x:
1->Emitted(2, 5) Source(2, 5) + SourceIndex(0)
2 >Emitted(2, 12) Source(2, 12) + SourceIndex(0)
3 >Emitted(2, 13) Source(2, 13) + SourceIndex(0)
4 >Emitted(2, 14) Source(2, 14) + SourceIndex(0)
5 >Emitted(2, 16) Source(2, 16) + SourceIndex(0)
4 >Emitted(2, 16) Source(2, 16) + SourceIndex(0)
---
>>> a: number;
1->^^^^^^^^
@@ -1,3 +1,3 @@
//// [bundle.js.map]
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IAAA;IAOA,CAAC;IANG,qBAAO,GAAP,UAAQ,CAAc;QAClB,OAAO,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAC,CAAC;IACpB,CAAC;IACM,QAAI,GAAX;QACI,OAAO,IAAI,GAAG,EAAE,CAAC;IACrB,CAAC;IACL,UAAC;AAAD,CAAC,AAPD,IAOC;ACPD,IAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;AACpB,CAAC,CAAC,OAAO,CAAC,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC,CAAC;AAEnB,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAC,CAAC,EAAE,EAAE,EAAC,CAAC,CAAC"}//// [bundle.d.ts.map]
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IACI,OAAO,CAAC,CAAC,EAAE;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd;ACPD,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,QAAA,IAAI,CAAC;;CAAqB,CAAC"}
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["tests/cases/compiler/a.ts","tests/cases/compiler/index.ts"],"names":[],"mappings":"AAAA;IACI,OAAO,CAAC,GAAG;QAAC,CAAC,EAAE,MAAM,CAAA;KAAC;;;IAGtB,MAAM,CAAC,IAAI;CAGd;ACPD,QAAA,MAAM,CAAC,KAAY,CAAC;AAGpB,QAAA,IAAI,CAAC;;CAAqB,CAAC"}
@@ -312,20 +312,17 @@ sourceFile:tests/cases/compiler/a.ts
1->^^^^
2 > ^^^^^^^
3 > ^
4 > ^
5 > ^^
6 > ^^^^->
4 > ^^^
5 > ^^^^->
1->class Foo {
>
2 > doThing
3 > (
4 > x
5 > :
4 > x:
1->Emitted(2, 5) Source(2, 5) + SourceIndex(0)
2 >Emitted(2, 12) Source(2, 12) + SourceIndex(0)
3 >Emitted(2, 13) Source(2, 13) + SourceIndex(0)
4 >Emitted(2, 14) Source(2, 14) + SourceIndex(0)
5 >Emitted(2, 16) Source(2, 16) + SourceIndex(0)
4 >Emitted(2, 16) Source(2, 16) + SourceIndex(0)
---
>>> a: number;
1->^^^^^^^^
@@ -0,0 +1,4 @@
/// <reference path="../../outdir/simple/fileC.d.ts" />
declare class B {
c: C;
}
@@ -0,0 +1,6 @@
/// <reference path='FolderC/fileC.ts'/>
var B = /** @class */ (function () {
function B() {
}
return B;
}());
@@ -0,0 +1,2 @@
declare class C {
}
@@ -0,0 +1,5 @@
var C = /** @class */ (function () {
function C() {
}
return C;
}());
@@ -0,0 +1,4 @@
/// <reference path="../../outdir/simple/fileC.d.ts" />
declare class B {
c: C;
}
@@ -0,0 +1,6 @@
/// <reference path='FolderC/fileC.ts'/>
var B = /** @class */ (function () {
function B() {
}
return B;
}());
@@ -0,0 +1,2 @@
declare class C {
}
@@ -0,0 +1,5 @@
var C = /** @class */ (function () {
function C() {
}
return C;
}());
@@ -13,6 +13,7 @@
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
@@ -13,6 +13,7 @@
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
@@ -13,6 +13,7 @@
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
@@ -13,6 +13,7 @@
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
@@ -13,6 +13,7 @@
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
@@ -13,6 +13,7 @@
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
@@ -13,6 +13,7 @@
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
@@ -13,6 +13,7 @@
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
@@ -13,6 +13,7 @@
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */