mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge remote-tracking branch 'origin/master' into release-3.6
This commit is contained in:
+20
-20
@@ -41,7 +41,7 @@ const generateLibs = () => {
|
||||
.pipe(concat(relativeTarget, { newLine: "\n\n" }))
|
||||
.pipe(dest("built/local"))));
|
||||
};
|
||||
task("lib", generateLibs)
|
||||
task("lib", generateLibs);
|
||||
task("lib").description = "Builds the library targets";
|
||||
|
||||
const cleanLib = () => del(libs.map(lib => lib.target));
|
||||
@@ -168,7 +168,7 @@ task("services", series(preBuild, buildServices));
|
||||
task("services").description = "Builds the language service";
|
||||
task("services").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
const cleanServices = async () => {
|
||||
if (fs.existsSync("built/local/typescriptServices.tsconfig.json")) {
|
||||
@@ -200,14 +200,14 @@ task("watch-services", series(preBuild, parallel(watchLib, watchDiagnostics, wat
|
||||
task("watch-services").description = "Watches for changes and rebuild language service only";
|
||||
task("watch-services").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
const buildServer = () => buildProject("src/tsserver", cmdLineOptions);
|
||||
task("tsserver", series(preBuild, buildServer));
|
||||
task("tsserver").description = "Builds the language server";
|
||||
task("tsserver").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
const cleanServer = () => cleanProject("src/tsserver");
|
||||
cleanTasks.push(cleanServer);
|
||||
@@ -219,13 +219,13 @@ task("watch-tsserver", series(preBuild, parallel(watchLib, watchDiagnostics, wat
|
||||
task("watch-tsserver").description = "Watch for changes and rebuild the language server only";
|
||||
task("watch-tsserver").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
task("min", series(preBuild, parallel(buildTsc, buildServer)));
|
||||
task("min").description = "Builds only tsc and tsserver";
|
||||
task("min").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
task("clean-min", series(cleanTsc, cleanServer));
|
||||
task("clean-min").description = "Cleans outputs for tsc and tsserver";
|
||||
@@ -234,7 +234,7 @@ task("watch-min", series(preBuild, parallel(watchLib, watchDiagnostics, watchTsc
|
||||
task("watch-min").description = "Watches for changes to a tsc and tsserver only";
|
||||
task("watch-min").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
const buildLssl = (() => {
|
||||
// build tsserverlibrary.out.js
|
||||
@@ -268,7 +268,7 @@ task("lssl", series(preBuild, buildLssl));
|
||||
task("lssl").description = "Builds language service server library";
|
||||
task("lssl").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
const cleanLssl = async () => {
|
||||
if (fs.existsSync("built/local/tsserverlibrary.tsconfig.json")) {
|
||||
@@ -302,14 +302,14 @@ task("watch-lssl", series(preBuild, parallel(watchLib, watchDiagnostics, watchLs
|
||||
task("watch-lssl").description = "Watch for changes and rebuild tsserverlibrary only";
|
||||
task("watch-lssl").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
const buildTests = () => buildProject("src/testRunner");
|
||||
task("tests", series(preBuild, parallel(buildLssl, buildTests)));
|
||||
task("tests").description = "Builds the test infrastructure";
|
||||
task("tests").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
const cleanTests = () => cleanProject("src/testRunner");
|
||||
cleanTasks.push(cleanTests);
|
||||
@@ -381,13 +381,13 @@ task("local", series(buildFoldStart, preBuild, parallel(localize, buildTsc, buil
|
||||
task("local").description = "Builds the full compiler and services";
|
||||
task("local").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
task("watch-local", series(preBuild, parallel(watchLib, watchDiagnostics, watchTsc, watchServices, watchServer, watchLssl)));
|
||||
task("watch-local").description = "Watches for changes to projects in src/ (but does not execute tests).";
|
||||
task("watch-local").flags = {
|
||||
" --built": "Compile using the built version of the compiler."
|
||||
}
|
||||
};
|
||||
|
||||
const generateCodeCoverage = () => exec("istanbul", ["cover", "node_modules/mocha/bin/_mocha", "--", "-R", "min", "-t", "" + cmdLineOptions.testTimeout, "built/local/run.js"]);
|
||||
task("generate-code-coverage", series(preBuild, buildTests, generateCodeCoverage));
|
||||
@@ -417,7 +417,7 @@ task("runtests").flags = {
|
||||
" --built": "Compile using the built version of the compiler.",
|
||||
" --shards": "Total number of shards running tests (default: 1)",
|
||||
" --shardId": "1-based ID of this shard (default: 1)",
|
||||
}
|
||||
};
|
||||
|
||||
const runTestsParallel = () => runConsoleTests("built/local/run.js", "min", /*runInParallel*/ true, /*watchMode*/ false);
|
||||
task("runtests-parallel", series(preBuild, preTest, runTestsParallel, postTest));
|
||||
@@ -436,10 +436,10 @@ task("runtests-parallel").flags = {
|
||||
" --shardId": "1-based ID of this shard (default: 1)",
|
||||
};
|
||||
|
||||
task("diff", () => exec(getDiffTool(), [refBaseline, localBaseline], { ignoreExitCode: true }));
|
||||
task("diff", () => exec(getDiffTool(), [refBaseline, localBaseline], { ignoreExitCode: true, waitForExit: false }));
|
||||
task("diff").description = "Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable";
|
||||
|
||||
task("diff-rwc", () => exec(getDiffTool(), [refRwcBaseline, localRwcBaseline], { ignoreExitCode: true }));
|
||||
task("diff-rwc", () => exec(getDiffTool(), [refRwcBaseline, localRwcBaseline], { ignoreExitCode: true, waitForExit: false }));
|
||||
task("diff-rwc").description = "Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable";
|
||||
|
||||
/**
|
||||
@@ -478,7 +478,7 @@ task("tsc-instrumented", series(lkgPreBuild, parallel(localize, buildTsc, buildS
|
||||
task("tsc-instrumented").description = "Builds an instrumented tsc.js";
|
||||
task("tsc-instrumented").flags = {
|
||||
"-t --tests=<testname>": "The test to run."
|
||||
}
|
||||
};
|
||||
|
||||
// TODO(rbuckton): Determine if we still need this task. Depending on a relative
|
||||
// path here seems like a bad idea.
|
||||
@@ -533,7 +533,7 @@ task("LKG", series(lkgPreBuild, parallel(localize, buildTsc, buildServer, buildS
|
||||
task("LKG").description = "Makes a new LKG out of the built js files";
|
||||
task("LKG").flags = {
|
||||
" --built": "Compile using the built version of the compiler.",
|
||||
}
|
||||
};
|
||||
|
||||
const generateSpec = () => exec("cscript", ["//nologo", "scripts/word2md.js", path.resolve("doc/TypeScript Language Specification.docx"), path.resolve("doc/spec.md")]);
|
||||
task("generate-spec", series(buildScripts, generateSpec));
|
||||
@@ -542,15 +542,15 @@ task("generate-spec").description = "Generates a Markdown version of the Languag
|
||||
task("clean", series(parallel(cleanTasks), cleanBuilt));
|
||||
task("clean").description = "Cleans build outputs";
|
||||
|
||||
const configureNightly = () => exec(process.execPath, ["scripts/configurePrerelease.js", "dev", "package.json", "src/compiler/core.ts"])
|
||||
const configureNightly = () => exec(process.execPath, ["scripts/configurePrerelease.js", "dev", "package.json", "src/compiler/core.ts"]);
|
||||
task("configure-nightly", series(buildScripts, configureNightly));
|
||||
task("configure-nightly").description = "Runs scripts/configurePrerelease.ts to prepare a build for nightly publishing";
|
||||
|
||||
const configureInsiders = () => exec(process.execPath, ["scripts/configurePrerelease.js", "insiders", "package.json", "src/compiler/core.ts"])
|
||||
const configureInsiders = () => exec(process.execPath, ["scripts/configurePrerelease.js", "insiders", "package.json", "src/compiler/core.ts"]);
|
||||
task("configure-insiders", series(buildScripts, configureInsiders));
|
||||
task("configure-insiders").description = "Runs scripts/configurePrerelease.ts to prepare a build for insiders publishing";
|
||||
|
||||
const configureExperimental = () => exec(process.execPath, ["scripts/configurePrerelease.js", "experimental", "package.json", "src/compiler/core.ts"])
|
||||
const configureExperimental = () => exec(process.execPath, ["scripts/configurePrerelease.js", "experimental", "package.json", "src/compiler/core.ts"]);
|
||||
task("configure-experimental", series(buildScripts, configureExperimental));
|
||||
task("configure-experimental").description = "Runs scripts/configurePrerelease.ts to prepare a build for experimental publishing";
|
||||
|
||||
|
||||
+4
-2
@@ -42,12 +42,13 @@
|
||||
"@types/gulp-sourcemaps": "0.0.32",
|
||||
"@types/jake": "latest",
|
||||
"@types/merge2": "latest",
|
||||
"@types/microsoft__typescript-etw": "latest",
|
||||
"@types/minimatch": "latest",
|
||||
"@types/minimist": "latest",
|
||||
"@types/mkdirp": "latest",
|
||||
"@types/mocha": "latest",
|
||||
"@types/ms": "latest",
|
||||
"@types/node": "^8.10.51",
|
||||
"@types/node": "latest",
|
||||
"@types/node-fetch": "^2.3.4",
|
||||
"@types/q": "latest",
|
||||
"@types/source-map-support": "latest",
|
||||
@@ -109,7 +110,8 @@
|
||||
"browser": {
|
||||
"fs": false,
|
||||
"os": false,
|
||||
"path": false
|
||||
"path": false,
|
||||
"@microsoft/typescript-etw": false
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
||||
+23
-15
@@ -25,10 +25,11 @@ const isWindows = /^win/.test(process.platform);
|
||||
* @property {boolean} [ignoreExitCode]
|
||||
* @property {import("prex").CancellationToken} [cancelToken]
|
||||
* @property {boolean} [hidePrompt]
|
||||
* @property {boolean} [waitForExit=true]
|
||||
*/
|
||||
function exec(cmd, args, options = {}) {
|
||||
return /**@type {Promise<{exitCode: number}>}*/(new Promise((resolve, reject) => {
|
||||
const { ignoreExitCode, cancelToken = CancellationToken.none } = options;
|
||||
const { ignoreExitCode, cancelToken = CancellationToken.none, waitForExit = true } = options;
|
||||
cancelToken.throwIfCancellationRequested();
|
||||
|
||||
// TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition
|
||||
@@ -36,26 +37,33 @@ function exec(cmd, args, options = {}) {
|
||||
const command = isWindows ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`];
|
||||
|
||||
if (!options.hidePrompt) log(`> ${chalk.green(cmd)} ${args.join(" ")}`);
|
||||
const proc = spawn(isWindows ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true });
|
||||
const proc = spawn(isWindows ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: waitForExit ? "inherit" : "ignore", windowsVerbatimArguments: true });
|
||||
const registration = cancelToken.register(() => {
|
||||
log(`${chalk.red("killing")} '${chalk.green(cmd)} ${args.join(" ")}'...`);
|
||||
proc.kill("SIGINT");
|
||||
proc.kill("SIGTERM");
|
||||
reject(new CancelError());
|
||||
});
|
||||
proc.on("exit", exitCode => {
|
||||
registration.unregister();
|
||||
if (exitCode === 0 || ignoreExitCode) {
|
||||
resolve({ exitCode });
|
||||
}
|
||||
else {
|
||||
reject(new Error(`Process exited with code: ${exitCode}`));
|
||||
}
|
||||
});
|
||||
proc.on("error", error => {
|
||||
registration.unregister();
|
||||
reject(error);
|
||||
});
|
||||
if (waitForExit) {
|
||||
proc.on("exit", exitCode => {
|
||||
registration.unregister();
|
||||
if (exitCode === 0 || ignoreExitCode) {
|
||||
resolve({ exitCode });
|
||||
}
|
||||
else {
|
||||
reject(new Error(`Process exited with code: ${exitCode}`));
|
||||
}
|
||||
});
|
||||
proc.on("error", error => {
|
||||
registration.unregister();
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
else {
|
||||
proc.unref();
|
||||
// wait a short period in order to allow the process to start successfully before Node exits.
|
||||
setTimeout(() => resolve({ exitCode: undefined }), 100);
|
||||
}
|
||||
}));
|
||||
}
|
||||
exports.exec = exec;
|
||||
|
||||
@@ -30,7 +30,7 @@ async function copyLocalizedDiagnostics() {
|
||||
for (const d of dir) {
|
||||
const fileName = path.join(source, d);
|
||||
if (fs.statSync(fileName).isDirectory()) {
|
||||
if (d === 'tslint') continue;
|
||||
if (d === 'tslint' || d === 'enu') continue;
|
||||
await fs.copy(fileName, path.join(dest, d));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
const MAX_UNICODE_CODEPOINT = 0x10FFFF;
|
||||
const isStart = c => /[\p{ID_Start}\u{2118}\u{212E}\u{309B}\u{309C}]/u.test(c); // Other_ID_Start explicitly included for back compat - see http://www.unicode.org/reports/tr31/#Introduction
|
||||
const isPart = c => /[\p{ID_Continue}\u{00B7}\u{0387}\u{19DA}\u{1369}\u{136A}\u{136B}\u{136C}\u{136D}\u{136E}\u{136F}\u{1370}\u{1371}]/u.test(c) || isStart(c); // Likewise for Other_ID_Continue
|
||||
const parts = [];
|
||||
let partsActive = false;
|
||||
let startsActive = false;
|
||||
const starts = [];
|
||||
|
||||
for (let i = 0; i < MAX_UNICODE_CODEPOINT; i++) {
|
||||
if (isStart(String.fromCodePoint(i)) !== startsActive) {
|
||||
starts.push(i - +startsActive);
|
||||
startsActive = !startsActive;
|
||||
}
|
||||
if (isPart(String.fromCodePoint(i)) !== partsActive) {
|
||||
parts.push(i - +partsActive);
|
||||
partsActive = !partsActive;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`/**
|
||||
* Generated by scripts/regenerate-unicode-identifier-parts.js on node ${process.version} with unicode ${process.versions.unicode}
|
||||
* based on http://www.unicode.org/reports/tr31/ and https://www.ecma-international.org/ecma-262/6.0/#sec-names-and-keywords
|
||||
* unicodeESNextIdentifierStart corresponds to the ID_Start and Other_ID_Start property, and
|
||||
* unicodeESNextIdentifierPart corresponds to ID_Continue, Other_ID_Continue, plus ID_Start and Other_ID_Start
|
||||
*/`);
|
||||
console.log(`const unicodeESNextIdentifierStart = [${starts.join(", ")}];`);
|
||||
console.log(`const unicodeESNextIdentifierPart = [${parts.join(", ")}];`);
|
||||
+36
-18
@@ -106,7 +106,9 @@ namespace ts {
|
||||
|
||||
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
|
||||
performance.mark("beforeBind");
|
||||
perfLogger.logStartBindFile("" + file.fileName);
|
||||
binder(file, options);
|
||||
perfLogger.logStopBindFile();
|
||||
performance.mark("afterBind");
|
||||
performance.measure("Bind", "beforeBind", "afterBind");
|
||||
}
|
||||
@@ -120,7 +122,7 @@ namespace ts {
|
||||
let thisParentContainer: Node; // Container one level up
|
||||
let blockScopeContainer: Node;
|
||||
let lastContainer: Node;
|
||||
let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag)[];
|
||||
let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag)[];
|
||||
let seenThisKeyword: boolean;
|
||||
|
||||
// state used by control flow analysis
|
||||
@@ -490,11 +492,11 @@ namespace ts {
|
||||
// and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed.
|
||||
if (isJSDocTypeAlias(node)) Debug.assert(isInJSFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file.
|
||||
if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypeAlias(node)) {
|
||||
if (hasModifier(node, ModifierFlags.Default) && !getDeclarationName(node)) {
|
||||
if (!container.locals || (hasModifier(node, ModifierFlags.Default) && !getDeclarationName(node))) {
|
||||
return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default!
|
||||
}
|
||||
const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0;
|
||||
const local = declareSymbol(container.locals!, /*parent*/ undefined, node, exportKind, symbolExcludes);
|
||||
const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes);
|
||||
local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes);
|
||||
node.localSymbol = local;
|
||||
return local;
|
||||
@@ -732,7 +734,8 @@ namespace ts {
|
||||
break;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag);
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
|
||||
break;
|
||||
// In source files and blocks, bind functions first to match hoisting that occurs at runtime
|
||||
case SyntaxKind.SourceFile: {
|
||||
@@ -1436,9 +1439,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag) {
|
||||
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag) {
|
||||
node.tagName.parent = node;
|
||||
if (node.fullName) {
|
||||
if (node.kind !== SyntaxKind.JSDocEnumTag && node.fullName) {
|
||||
setParentPointers(node, node.fullName);
|
||||
}
|
||||
}
|
||||
@@ -1805,7 +1808,19 @@ namespace ts {
|
||||
currentFlow = { flags: FlowFlags.Start };
|
||||
parent = typeAlias;
|
||||
bind(typeAlias.typeExpression);
|
||||
if (!typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) {
|
||||
const declName = getNameOfDeclaration(typeAlias);
|
||||
if ((isJSDocEnumTag(typeAlias) || !typeAlias.fullName) && declName && isPropertyAccessEntityNameExpression(declName.parent)) {
|
||||
// typedef anchored to an A.B.C assignment - we need to bind into B's namespace under name C
|
||||
const isTopLevel = isTopLevelNamespaceAssignment(declName.parent);
|
||||
if (isTopLevel) {
|
||||
bindPotentiallyMissingNamespaces(file.symbol, declName.parent, isTopLevel, !!findAncestor(declName, d => isPropertyAccessExpression(d) && d.name.escapedText === "prototype"));
|
||||
const oldContainer = container;
|
||||
container = isPropertyAccessExpression(declName.parent.expression) ? declName.parent.expression.name : declName.parent.expression;
|
||||
declareModuleMember(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
container = oldContainer;
|
||||
}
|
||||
}
|
||||
else if (isJSDocEnumTag(typeAlias) || !typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) {
|
||||
parent = typeAlias.parent;
|
||||
bindBlockScopedDeclaration(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
}
|
||||
@@ -1827,7 +1842,8 @@ namespace ts {
|
||||
node.originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord &&
|
||||
node.originalKeywordKind! <= SyntaxKind.LastFutureReservedWord &&
|
||||
!isIdentifierName(node) &&
|
||||
!(node.flags & NodeFlags.Ambient)) {
|
||||
!(node.flags & NodeFlags.Ambient) &&
|
||||
!(node.flags & NodeFlags.JSDoc)) {
|
||||
|
||||
// Report error only if there are no parse errors in file
|
||||
if (!file.parseDiagnostics.length) {
|
||||
@@ -2319,7 +2335,8 @@ namespace ts {
|
||||
return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag);
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2605,7 +2622,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function bindPotentiallyMissingNamespaces(namespaceSymbol: Symbol | undefined, entityName: EntityNameExpression, isToplevel: boolean, isPrototypeProperty: boolean) {
|
||||
if (isToplevel && !isPrototypeProperty && (!namespaceSymbol || !(namespaceSymbol.flags & SymbolFlags.Namespace))) {
|
||||
if (isToplevel && !isPrototypeProperty) {
|
||||
// make symbols or add declarations for intermediate containers
|
||||
const flags = SymbolFlags.Module | SymbolFlags.Assignment;
|
||||
const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.Assignment;
|
||||
@@ -2640,11 +2657,15 @@ namespace ts {
|
||||
declareSymbol(symbolTable, namespaceSymbol, declaration, includes | SymbolFlags.Assignment, excludes & ~SymbolFlags.Assignment);
|
||||
}
|
||||
|
||||
function bindPropertyAssignment(name: EntityNameExpression, propertyAccess: PropertyAccessEntityNameExpression, isPrototypeProperty: boolean) {
|
||||
let namespaceSymbol = lookupSymbolForPropertyAccess(name);
|
||||
const isToplevel = isBinaryExpression(propertyAccess.parent)
|
||||
function isTopLevelNamespaceAssignment(propertyAccess: PropertyAccessEntityNameExpression) {
|
||||
return isBinaryExpression(propertyAccess.parent)
|
||||
? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === SyntaxKind.SourceFile
|
||||
: propertyAccess.parent.parent.kind === SyntaxKind.SourceFile;
|
||||
}
|
||||
|
||||
function bindPropertyAssignment(name: EntityNameExpression, propertyAccess: PropertyAccessEntityNameExpression, isPrototypeProperty: boolean) {
|
||||
let namespaceSymbol = lookupSymbolForPropertyAccess(name);
|
||||
const isToplevel = isTopLevelNamespaceAssignment(propertyAccess);
|
||||
namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty);
|
||||
bindPotentiallyNewExpandoMemberToNamespace(propertyAccess, namespaceSymbol, isPrototypeProperty);
|
||||
}
|
||||
@@ -2766,11 +2787,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (!isBindingPattern(node.name)) {
|
||||
const isEnum = isInJSFile(node) && !!getJSDocEnumTag(node);
|
||||
const enumFlags = (isEnum ? SymbolFlags.RegularEnum : SymbolFlags.None);
|
||||
const enumExcludes = (isEnum ? SymbolFlags.RegularEnumExcludes : SymbolFlags.None);
|
||||
if (isBlockOrCatchScoped(node)) {
|
||||
bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable | enumFlags, SymbolFlags.BlockScopedVariableExcludes | enumExcludes);
|
||||
bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes);
|
||||
}
|
||||
else if (isParameterDeclaration(node)) {
|
||||
// It is safe to walk up parent chain to find whether the node is a destructuring parameter declaration
|
||||
@@ -2785,7 +2803,7 @@ namespace ts {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes);
|
||||
}
|
||||
else {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable | enumFlags, SymbolFlags.FunctionScopedVariableExcludes | enumExcludes);
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+653
-510
File diff suppressed because it is too large
Load Diff
@@ -1743,6 +1743,16 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface TSConfig {
|
||||
compilerOptions: CompilerOptions;
|
||||
compileOnSave: boolean | undefined;
|
||||
exclude?: ReadonlyArray<string>;
|
||||
files: ReadonlyArray<string> | undefined;
|
||||
include?: ReadonlyArray<string>;
|
||||
references: ReadonlyArray<ProjectReference> | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an uncommented, complete tsconfig for use with "--showConfig"
|
||||
* @param configParseResult options to be generated into tsconfig.json
|
||||
@@ -1750,7 +1760,7 @@ namespace ts {
|
||||
* @param host provides current directory and case sensitivity services
|
||||
*/
|
||||
/** @internal */
|
||||
export function convertToTSConfig(configParseResult: ParsedCommandLine, configFileName: string, host: { getCurrentDirectory(): string, useCaseSensitiveFileNames: boolean }): object {
|
||||
export function convertToTSConfig(configParseResult: ParsedCommandLine, configFileName: string, host: { getCurrentDirectory(): string, useCaseSensitiveFileNames: boolean }): TSConfig {
|
||||
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
|
||||
const files = map(
|
||||
filter(
|
||||
@@ -1778,13 +1788,13 @@ namespace ts {
|
||||
build: undefined,
|
||||
version: undefined,
|
||||
},
|
||||
references: map(configParseResult.projectReferences, r => ({ ...r, path: r.originalPath, originalPath: undefined })),
|
||||
references: map(configParseResult.projectReferences, r => ({ ...r, path: r.originalPath ? r.originalPath : "", originalPath: undefined })),
|
||||
files: length(files) ? files : undefined,
|
||||
...(configParseResult.configFileSpecs ? {
|
||||
include: filterSameAsDefaultInclude(configParseResult.configFileSpecs.validatedIncludeSpecs),
|
||||
exclude: configParseResult.configFileSpecs.validatedExcludeSpecs
|
||||
} : {}),
|
||||
compilerOnSave: !!configParseResult.compileOnSave ? true : undefined
|
||||
compileOnSave: !!configParseResult.compileOnSave ? true : undefined
|
||||
};
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -1381,6 +1381,17 @@ namespace ts {
|
||||
return keys;
|
||||
}
|
||||
|
||||
export function getAllKeys(obj: object): string[] {
|
||||
const result: string[] = [];
|
||||
do {
|
||||
const names = Object.getOwnPropertyNames(obj);
|
||||
for (const name of names) {
|
||||
pushIfUnique(result, name);
|
||||
}
|
||||
} while (obj = Object.getPrototypeOf(obj));
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getOwnValues<T>(sparseArray: T[]): T[] {
|
||||
const values: T[] = [];
|
||||
for (const key in sparseArray) {
|
||||
|
||||
@@ -258,4 +258,4 @@ namespace ts {
|
||||
isDebugInfoEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,10 +243,6 @@
|
||||
"category": "Error",
|
||||
"code": 1085
|
||||
},
|
||||
"An accessor cannot be declared in an ambient context.": {
|
||||
"category": "Error",
|
||||
"code": 1086
|
||||
},
|
||||
"'{0}' modifier cannot appear on a constructor declaration.": {
|
||||
"category": "Error",
|
||||
"code": 1089
|
||||
@@ -855,6 +851,10 @@
|
||||
"category": "Error",
|
||||
"code": 1259
|
||||
},
|
||||
"Keywords cannot contain escape characters.": {
|
||||
"category": "Error",
|
||||
"code": 1260
|
||||
},
|
||||
"'with' statements are not allowed in an async function block.": {
|
||||
"category": "Error",
|
||||
"code": 1300
|
||||
@@ -983,7 +983,7 @@
|
||||
"category": "Error",
|
||||
"code": 1342
|
||||
},
|
||||
"The 'import.meta' meta-property is only allowed using 'ESNext' for the 'target' and 'module' compiler options.": {
|
||||
"The 'import.meta' meta-property is only allowed when the '--module' option is 'esnext' or 'system'.": {
|
||||
"category": "Error",
|
||||
"code": 1343
|
||||
},
|
||||
|
||||
@@ -1605,7 +1605,7 @@ namespace ts {
|
||||
for (let i = 0; i < numNodes; i++) {
|
||||
const currentNode = bundle ? i < numPrepends ? bundle.prepends[i] : bundle.sourceFiles[i - numPrepends] : node;
|
||||
const sourceFile = isSourceFile(currentNode) ? currentNode : isUnparsedSource(currentNode) ? undefined : currentSourceFile!;
|
||||
const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && getExternalHelpersModuleName(sourceFile) !== undefined);
|
||||
const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && hasRecordedExternalHelpers(sourceFile));
|
||||
const shouldBundle = (isSourceFile(currentNode) || isUnparsedSource(currentNode)) && !isOwnFileEmit;
|
||||
const helpers = isUnparsedSource(currentNode) ? currentNode.helpers : getSortedEmitHelpers(currentNode);
|
||||
if (helpers) {
|
||||
|
||||
+75
-8
@@ -3628,23 +3628,28 @@ namespace ts {
|
||||
|
||||
// Helpers
|
||||
|
||||
export function getHelperName(name: string) {
|
||||
/**
|
||||
* Gets an identifier for the name of an *unscoped* emit helper.
|
||||
*/
|
||||
export function getUnscopedHelperName(name: string) {
|
||||
return setEmitFlags(createIdentifier(name), EmitFlags.HelperName | EmitFlags.AdviseOnEmitNode);
|
||||
}
|
||||
|
||||
export const valuesHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:values",
|
||||
importName: "__values",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __values = (this && this.__values) || function (o) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
||||
var __values = (this && this.__values) || function(o) {
|
||||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
if (m) return m.call(o);
|
||||
return {
|
||||
if (o && typeof o.length === "number") return {
|
||||
next: function () {
|
||||
if (o && i >= o.length) o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
}
|
||||
};
|
||||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
};`
|
||||
};
|
||||
|
||||
@@ -3652,7 +3657,7 @@ namespace ts {
|
||||
context.requestEmitHelper(valuesHelper);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__values"),
|
||||
getUnscopedHelperName("__values"),
|
||||
/*typeArguments*/ undefined,
|
||||
[expression]
|
||||
),
|
||||
@@ -3662,6 +3667,7 @@ namespace ts {
|
||||
|
||||
export const readHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:read",
|
||||
importName: "__read",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __read = (this && this.__read) || function (o, n) {
|
||||
@@ -3686,7 +3692,7 @@ namespace ts {
|
||||
context.requestEmitHelper(readHelper);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__read"),
|
||||
getUnscopedHelperName("__read"),
|
||||
/*typeArguments*/ undefined,
|
||||
count !== undefined
|
||||
? [iteratorRecord, createLiteral(count)]
|
||||
@@ -3698,6 +3704,7 @@ namespace ts {
|
||||
|
||||
export const spreadHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:spread",
|
||||
importName: "__spread",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __spread = (this && this.__spread) || function () {
|
||||
@@ -3711,7 +3718,7 @@ namespace ts {
|
||||
context.requestEmitHelper(spreadHelper);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__spread"),
|
||||
getUnscopedHelperName("__spread"),
|
||||
/*typeArguments*/ undefined,
|
||||
argumentList
|
||||
),
|
||||
@@ -3721,6 +3728,7 @@ namespace ts {
|
||||
|
||||
export const spreadArraysHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:spreadArrays",
|
||||
importName: "__spreadArrays",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
@@ -3736,7 +3744,7 @@ namespace ts {
|
||||
context.requestEmitHelper(spreadArraysHelper);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__spreadArrays"),
|
||||
getUnscopedHelperName("__spreadArrays"),
|
||||
/*typeArguments*/ undefined,
|
||||
argumentList
|
||||
),
|
||||
@@ -4862,6 +4870,65 @@ namespace ts {
|
||||
return emitNode && emitNode.externalHelpersModuleName;
|
||||
}
|
||||
|
||||
export function hasRecordedExternalHelpers(sourceFile: SourceFile) {
|
||||
const parseNode = getOriginalNode(sourceFile, isSourceFile);
|
||||
const emitNode = parseNode && parseNode.emitNode;
|
||||
return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers);
|
||||
}
|
||||
|
||||
export function createExternalHelpersImportDeclarationIfNeeded(sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) {
|
||||
if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) {
|
||||
let namedBindings: NamedImportBindings | undefined;
|
||||
const moduleKind = getEmitModuleKind(compilerOptions);
|
||||
if (moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) {
|
||||
// use named imports
|
||||
const helpers = getEmitHelpers(sourceFile);
|
||||
if (helpers) {
|
||||
const helperNames: string[] = [];
|
||||
for (const helper of helpers) {
|
||||
if (!helper.scoped) {
|
||||
const importName = (helper as UnscopedEmitHelper).importName;
|
||||
if (importName) {
|
||||
pushIfUnique(helperNames, importName);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (some(helperNames)) {
|
||||
helperNames.sort(compareStringsCaseSensitive);
|
||||
// Alias the imports if the names are used somewhere in the file.
|
||||
// NOTE: We don't need to care about global import collisions as this is a module.
|
||||
namedBindings = createNamedImports(
|
||||
map(helperNames, name => isFileLevelUniqueName(sourceFile, name)
|
||||
? createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name))
|
||||
: createImportSpecifier(createIdentifier(name), getUnscopedHelperName(name))
|
||||
)
|
||||
);
|
||||
const parseNode = getOriginalNode(sourceFile, isSourceFile);
|
||||
const emitNode = getOrCreateEmitNode(parseNode);
|
||||
emitNode.externalHelpers = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// use a namespace import
|
||||
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar || hasImportDefault);
|
||||
if (externalHelpersModuleName) {
|
||||
namedBindings = createNamespaceImport(externalHelpersModuleName);
|
||||
}
|
||||
}
|
||||
if (namedBindings) {
|
||||
const externalHelpersImportDeclaration = createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, namedBindings),
|
||||
createLiteral(externalHelpersModuleNameText)
|
||||
);
|
||||
addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper);
|
||||
return externalHelpersImportDeclaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) {
|
||||
if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) {
|
||||
const externalHelpersModuleName = getExternalHelpersModuleName(node);
|
||||
|
||||
@@ -665,6 +665,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
perfLogger.logStartResolveModule(moduleName /* , containingFile, ModuleResolutionKind[moduleResolution]*/);
|
||||
switch (moduleResolution) {
|
||||
case ModuleResolutionKind.NodeJs:
|
||||
result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference);
|
||||
@@ -675,6 +676,8 @@ namespace ts {
|
||||
default:
|
||||
return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`);
|
||||
}
|
||||
if (result && result.resolvedModule) perfLogger.logInfoEvent(`Module "${moduleName}" resolved to "${result.resolvedModule.resolvedFileName}"`);
|
||||
perfLogger.logStopResolveModule((result && result.resolvedModule) ? "" + result.resolvedModule.resolvedFileName : "null");
|
||||
|
||||
if (perFolderCache) {
|
||||
perFolderCache.set(moduleName, result);
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace ts.moduleSpecifiers {
|
||||
|
||||
const info = getInfo(importingSourceFile.path, host);
|
||||
const moduleSourceFile = getSourceFileOfNode(moduleSymbol.valueDeclaration || getNonAugmentationDeclaration(moduleSymbol));
|
||||
const modulePaths = getAllModulePaths(files, importingSourceFile.path, moduleSourceFile.fileName, info.getCanonicalFileName, host, redirectTargetsMap);
|
||||
const modulePaths = getAllModulePaths(files, importingSourceFile.path, moduleSourceFile.originalFileName, info.getCanonicalFileName, host, redirectTargetsMap);
|
||||
|
||||
const preferences = getPreferences(userPreferences, compilerOptions, importingSourceFile);
|
||||
const global = mapDefined(modulePaths, moduleFileName => tryGetModuleNameAsNodeModule(moduleFileName, info, host, compilerOptions));
|
||||
@@ -114,7 +114,7 @@ namespace ts.moduleSpecifiers {
|
||||
function getLocalModuleSpecifier(moduleFileName: string, { getCanonicalFileName, sourceDirectory }: Info, compilerOptions: CompilerOptions, { ending, relativePreference }: Preferences): string {
|
||||
const { baseUrl, paths, rootDirs } = compilerOptions;
|
||||
|
||||
const relativePath = rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName) ||
|
||||
const relativePath = rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName, ending, compilerOptions) ||
|
||||
removeExtensionAndIndexPostFix(ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName)), ending, compilerOptions);
|
||||
if (!baseUrl || relativePreference === RelativePreference.Relative) {
|
||||
return relativePath;
|
||||
@@ -248,7 +248,7 @@ namespace ts.moduleSpecifiers {
|
||||
}
|
||||
}
|
||||
|
||||
function tryGetModuleNameFromRootDirs(rootDirs: ReadonlyArray<string>, moduleFileName: string, sourceDirectory: string, getCanonicalFileName: (file: string) => string): string | undefined {
|
||||
function tryGetModuleNameFromRootDirs(rootDirs: ReadonlyArray<string>, moduleFileName: string, sourceDirectory: string, getCanonicalFileName: (file: string) => string, ending: Ending, compilerOptions: CompilerOptions): string | undefined {
|
||||
const normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, rootDirs, getCanonicalFileName);
|
||||
if (normalizedTargetPath === undefined) {
|
||||
return undefined;
|
||||
@@ -256,7 +256,9 @@ namespace ts.moduleSpecifiers {
|
||||
|
||||
const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, rootDirs, getCanonicalFileName);
|
||||
const relativePath = normalizedSourcePath !== undefined ? ensurePathIsNonModuleName(getRelativePathFromDirectory(normalizedSourcePath, normalizedTargetPath, getCanonicalFileName)) : normalizedTargetPath;
|
||||
return removeFileExtension(relativePath);
|
||||
return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs
|
||||
? removeExtensionAndIndexPostFix(relativePath, ending, compilerOptions)
|
||||
: removeFileExtension(relativePath);
|
||||
}
|
||||
|
||||
function tryGetModuleNameAsNodeModule(moduleFileName: string, { getCanonicalFileName, sourceDirectory }: Info, host: ModuleSpecifierResolutionHost, options: CompilerOptions): string | undefined {
|
||||
|
||||
+56
-7
@@ -512,12 +512,16 @@ namespace ts {
|
||||
export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
|
||||
performance.mark("beforeParse");
|
||||
let result: SourceFile;
|
||||
|
||||
perfLogger.logStartParseSourceFile(fileName);
|
||||
if (languageVersion === ScriptTarget.JSON) {
|
||||
result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, ScriptKind.JSON);
|
||||
}
|
||||
else {
|
||||
result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
|
||||
}
|
||||
perfLogger.logStopParseSourceFile();
|
||||
|
||||
performance.mark("afterParse");
|
||||
performance.measure("Parse", "beforeParse", "afterParse");
|
||||
return result;
|
||||
@@ -605,6 +609,8 @@ namespace ts {
|
||||
|
||||
let parsingContext: ParsingContext;
|
||||
|
||||
let notParenthesizedArrow: Map<true> | undefined;
|
||||
|
||||
// Flags that dictate what parsing context we're in. For example:
|
||||
// Whether or not we are in strict parsing mode. All that changes in strict parsing mode is
|
||||
// that some tokens that would be considered identifiers may be considered keywords.
|
||||
@@ -826,6 +832,7 @@ namespace ts {
|
||||
identifiers = undefined!;
|
||||
syntaxCursor = undefined;
|
||||
sourceText = undefined!;
|
||||
notParenthesizedArrow = undefined!;
|
||||
}
|
||||
|
||||
function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile {
|
||||
@@ -1079,10 +1086,19 @@ namespace ts {
|
||||
return currentToken;
|
||||
}
|
||||
|
||||
function nextToken(): SyntaxKind {
|
||||
function nextTokenWithoutCheck() {
|
||||
return currentToken = scanner.scan();
|
||||
}
|
||||
|
||||
function nextToken(): SyntaxKind {
|
||||
// if the keyword had an escape
|
||||
if (isKeyword(currentToken) && (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape())) {
|
||||
// issue a parse error for the escape
|
||||
parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), Diagnostics.Keywords_cannot_contain_escape_characters);
|
||||
}
|
||||
return nextTokenWithoutCheck();
|
||||
}
|
||||
|
||||
function nextTokenJSDoc(): JSDocSyntaxKind {
|
||||
return currentToken = scanner.scanJsDocToken();
|
||||
}
|
||||
@@ -1373,7 +1389,7 @@ namespace ts {
|
||||
node.originalKeywordKind = token();
|
||||
}
|
||||
node.escapedText = escapeLeadingUnderscores(internIdentifier(scanner.getTokenValue()));
|
||||
nextToken();
|
||||
nextTokenWithoutCheck();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@@ -2428,6 +2444,25 @@ namespace ts {
|
||||
|
||||
function parseJSDocType(): TypeNode {
|
||||
scanner.setInJSDocType(true);
|
||||
const moduleSpecifier = parseOptionalToken(SyntaxKind.ModuleKeyword);
|
||||
if (moduleSpecifier) {
|
||||
const moduleTag = createNode(SyntaxKind.JSDocNamepathType, moduleSpecifier.pos) as JSDocNamepathType;
|
||||
terminate: while (true) {
|
||||
switch (token()) {
|
||||
case SyntaxKind.CloseBraceToken:
|
||||
case SyntaxKind.EndOfFileToken:
|
||||
case SyntaxKind.CommaToken:
|
||||
case SyntaxKind.WhitespaceTrivia:
|
||||
break terminate;
|
||||
default:
|
||||
nextTokenJSDoc();
|
||||
}
|
||||
}
|
||||
|
||||
scanner.setInJSDocType(false);
|
||||
return finishNode(moduleTag);
|
||||
}
|
||||
|
||||
const dotdotdot = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
let type = parseTypeOrTypePredicate();
|
||||
scanner.setInJSDocType(false);
|
||||
@@ -3676,7 +3711,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
function parsePossibleParenthesizedArrowFunctionExpressionHead(): ArrowFunction | undefined {
|
||||
return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false);
|
||||
const tokenPos = scanner.getTokenPos();
|
||||
if (notParenthesizedArrow && notParenthesizedArrow.has(tokenPos.toString())) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result = parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity*/ false);
|
||||
if (!result) {
|
||||
(notParenthesizedArrow || (notParenthesizedArrow = createMap())).set(tokenPos.toString(), true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function tryParseAsyncSimpleArrowFunctionExpression(): ArrowFunction | undefined {
|
||||
@@ -6417,7 +6462,7 @@ namespace ts {
|
||||
export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined {
|
||||
initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
|
||||
sourceFile = <SourceFile>{ languageVariant: LanguageVariant.Standard, text: content }; // tslint:disable-line no-object-literal-type-assertion
|
||||
const jsDoc = parseJSDocCommentWorker(start, length);
|
||||
const jsDoc = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length));
|
||||
const diagnostics = parseDiagnostics;
|
||||
clearState();
|
||||
|
||||
@@ -6429,7 +6474,7 @@ namespace ts {
|
||||
const saveParseDiagnosticsLength = parseDiagnostics.length;
|
||||
const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
|
||||
|
||||
const comment = parseJSDocCommentWorker(start, length);
|
||||
const comment = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length));
|
||||
if (comment) {
|
||||
comment.parent = parent;
|
||||
}
|
||||
@@ -6460,7 +6505,7 @@ namespace ts {
|
||||
CallbackParameter = 1 << 2,
|
||||
}
|
||||
|
||||
export function parseJSDocCommentWorker(start = 0, length: number | undefined): JSDoc | undefined {
|
||||
function parseJSDocCommentWorker(start = 0, length: number | undefined): JSDoc | undefined {
|
||||
const content = sourceText;
|
||||
const end = length === undefined ? content.length : start + length;
|
||||
length = end - start;
|
||||
@@ -7288,10 +7333,14 @@ namespace ts {
|
||||
return createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected);
|
||||
}
|
||||
|
||||
identifierCount++;
|
||||
const pos = scanner.getTokenPos();
|
||||
const end = scanner.getTextPos();
|
||||
const result = <Identifier>createNode(SyntaxKind.Identifier, pos);
|
||||
result.escapedText = escapeLeadingUnderscores(scanner.getTokenText());
|
||||
if (token() !== SyntaxKind.Identifier) {
|
||||
result.originalKeywordKind = token();
|
||||
}
|
||||
result.escapedText = escapeLeadingUnderscores(internIdentifier(scanner.getTokenValue()));
|
||||
finishNode(result, end);
|
||||
|
||||
nextTokenJSDoc();
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
type PerfLogger = typeof import("@microsoft/typescript-etw"); // tslint:disable-line:no-implicit-dependencies
|
||||
const nullLogger: PerfLogger = {
|
||||
logEvent: noop,
|
||||
logErrEvent: noop,
|
||||
logPerfEvent: noop,
|
||||
logInfoEvent: noop,
|
||||
logStartCommand: noop,
|
||||
logStopCommand: noop,
|
||||
logStartUpdateProgram: noop,
|
||||
logStopUpdateProgram: noop,
|
||||
logStartUpdateGraph: noop,
|
||||
logStopUpdateGraph: noop,
|
||||
logStartResolveModule: noop,
|
||||
logStopResolveModule: noop,
|
||||
logStartParseSourceFile: noop,
|
||||
logStopParseSourceFile: noop,
|
||||
logStartReadFile: noop,
|
||||
logStopReadFile: noop,
|
||||
logStartBindFile: noop,
|
||||
logStopBindFile: noop,
|
||||
logStartScheduledOperation: noop,
|
||||
logStopScheduledOperation: noop,
|
||||
};
|
||||
|
||||
// Load optional module to enable Event Tracing for Windows
|
||||
// See https://github.com/microsoft/typescript-etw for more information
|
||||
let etwModule;
|
||||
try {
|
||||
// require() will throw an exception if the module is not installed
|
||||
// It may also return undefined if not installed properly
|
||||
etwModule = require("@microsoft/typescript-etw"); // tslint:disable-line:no-implicit-dependencies
|
||||
}
|
||||
catch (e) {
|
||||
etwModule = undefined;
|
||||
}
|
||||
|
||||
/** Performance logger that will generate ETW events if possible */
|
||||
export const perfLogger: PerfLogger = etwModule ? etwModule : nullLogger;
|
||||
|
||||
perfLogger.logInfoEvent(`Starting TypeScript v${versionMajorMinor} with command line: ${JSON.stringify(process.argv)}`);
|
||||
}
|
||||
@@ -762,7 +762,7 @@ namespace ts {
|
||||
let resolveModuleNamesWorker: (moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference) => ResolvedModuleFull[];
|
||||
const hasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse;
|
||||
if (host.resolveModuleNames) {
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile, reusedNames, redirectedReference) => host.resolveModuleNames!(Debug.assertEachDefined(moduleNames), containingFile, reusedNames, redirectedReference).map(resolved => {
|
||||
resolveModuleNamesWorker = (moduleNames, containingFile, reusedNames, redirectedReference) => host.resolveModuleNames!(Debug.assertEachDefined(moduleNames), containingFile, reusedNames, redirectedReference, options).map(resolved => {
|
||||
// An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName.
|
||||
if (!resolved || (resolved as ResolvedModuleFull).extension !== undefined) {
|
||||
return resolved as ResolvedModuleFull;
|
||||
@@ -780,7 +780,7 @@ namespace ts {
|
||||
|
||||
let resolveTypeReferenceDirectiveNamesWorker: (typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference) => (ResolvedTypeReferenceDirective | undefined)[];
|
||||
if (host.resolveTypeReferenceDirectives) {
|
||||
resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference) => host.resolveTypeReferenceDirectives!(Debug.assertEachDefined(typeDirectiveNames), containingFile, redirectedReference);
|
||||
resolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference) => host.resolveTypeReferenceDirectives!(Debug.assertEachDefined(typeDirectiveNames), containingFile, redirectedReference, options);
|
||||
}
|
||||
else {
|
||||
const loader = (typesRef: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined) => resolveTypeReferenceDirective(typesRef, containingFile, options, host, redirectedReference).resolvedTypeReferenceDirective!; // TODO: GH#18217
|
||||
@@ -814,7 +814,10 @@ namespace ts {
|
||||
let mapFromFileToProjectReferenceRedirects: Map<Path> | undefined;
|
||||
|
||||
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
|
||||
const structuralIsReused = tryReuseStructureFromOldProgram();
|
||||
// We set `structuralIsReused` to `undefined` because `tryReuseStructureFromOldProgram` calls `tryReuseStructureFromOldProgram` which checks
|
||||
// `structuralIsReused`, which would be a TDZ violation if it was not set in advance to `undefined`.
|
||||
let structuralIsReused: StructureIsReused | undefined;
|
||||
structuralIsReused = tryReuseStructureFromOldProgram();
|
||||
if (structuralIsReused !== StructureIsReused.Completely) {
|
||||
processingDefaultLibFiles = [];
|
||||
processingOtherFiles = [];
|
||||
|
||||
+131
-29
File diff suppressed because one or more lines are too long
+156
-51
@@ -304,6 +304,53 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function createSingleFileWatcherPerName(
|
||||
watchFile: HostWatchFile,
|
||||
useCaseSensitiveFileNames: boolean
|
||||
): HostWatchFile {
|
||||
interface SingleFileWatcher {
|
||||
watcher: FileWatcher;
|
||||
refCount: number;
|
||||
}
|
||||
const cache = createMap<SingleFileWatcher>();
|
||||
const callbacksCache = createMultiMap<FileWatcherCallback>();
|
||||
const toCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
|
||||
return (fileName, callback, pollingInterval) => {
|
||||
const path = toCanonicalFileName(fileName);
|
||||
const existing = cache.get(path);
|
||||
if (existing) {
|
||||
existing.refCount++;
|
||||
}
|
||||
else {
|
||||
cache.set(path, {
|
||||
watcher: watchFile(
|
||||
fileName,
|
||||
(fileName, eventKind) => forEach(
|
||||
callbacksCache.get(path),
|
||||
cb => cb(fileName, eventKind)
|
||||
),
|
||||
pollingInterval
|
||||
),
|
||||
refCount: 1
|
||||
});
|
||||
}
|
||||
callbacksCache.add(path, callback);
|
||||
|
||||
return {
|
||||
close: () => {
|
||||
const watcher = Debug.assertDefined(cache.get(path));
|
||||
callbacksCache.remove(path, callback);
|
||||
watcher.refCount--;
|
||||
if (watcher.refCount) return;
|
||||
cache.delete(path);
|
||||
closeFileWatcherOf(watcher);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if file status changed
|
||||
*/
|
||||
@@ -332,6 +379,9 @@ namespace ts {
|
||||
/*@internal*/
|
||||
export const ignoredPaths = ["/node_modules/.", "/.git", "/.#"];
|
||||
|
||||
/*@internal*/
|
||||
export let sysLog: (s: string) => void = noop;
|
||||
|
||||
/*@internal*/
|
||||
export interface RecursiveDirectoryWatcherHost {
|
||||
watchDirectory: HostWatchDirectory;
|
||||
@@ -472,59 +522,81 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/*@internal*/
|
||||
export type BufferEncoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "latin1" | "binary" | "hex";
|
||||
|
||||
/*@internal*/
|
||||
interface NodeBuffer extends Uint8Array {
|
||||
write(str: string, offset?: number, length?: number, encoding?: string): number;
|
||||
constructor: any;
|
||||
write(str: string, encoding?: BufferEncoding): number;
|
||||
write(str: string, offset: number, encoding?: BufferEncoding): number;
|
||||
write(str: string, offset: number, length: number, encoding?: BufferEncoding): number;
|
||||
toString(encoding?: string, start?: number, end?: number): string;
|
||||
toJSON(): { type: "Buffer", data: any[] };
|
||||
equals(otherBuffer: Buffer): boolean;
|
||||
compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
|
||||
copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
|
||||
slice(start?: number, end?: number): Buffer;
|
||||
writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
|
||||
readUInt8(offset: number, noAssert?: boolean): number;
|
||||
readUInt16LE(offset: number, noAssert?: boolean): number;
|
||||
readUInt16BE(offset: number, noAssert?: boolean): number;
|
||||
readUInt32LE(offset: number, noAssert?: boolean): number;
|
||||
readUInt32BE(offset: number, noAssert?: boolean): number;
|
||||
readInt8(offset: number, noAssert?: boolean): number;
|
||||
readInt16LE(offset: number, noAssert?: boolean): number;
|
||||
readInt16BE(offset: number, noAssert?: boolean): number;
|
||||
readInt32LE(offset: number, noAssert?: boolean): number;
|
||||
readInt32BE(offset: number, noAssert?: boolean): number;
|
||||
readFloatLE(offset: number, noAssert?: boolean): number;
|
||||
readFloatBE(offset: number, noAssert?: boolean): number;
|
||||
readDoubleLE(offset: number, noAssert?: boolean): number;
|
||||
readDoubleBE(offset: number, noAssert?: boolean): number;
|
||||
toJSON(): { type: "Buffer"; data: number[] };
|
||||
equals(otherBuffer: Uint8Array): boolean;
|
||||
compare(
|
||||
otherBuffer: Uint8Array,
|
||||
targetStart?: number,
|
||||
targetEnd?: number,
|
||||
sourceStart?: number,
|
||||
sourceEnd?: number
|
||||
): number;
|
||||
copy(targetBuffer: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
|
||||
slice(begin?: number, end?: number): Buffer;
|
||||
subarray(begin?: number, end?: number): Buffer;
|
||||
writeUIntLE(value: number, offset: number, byteLength: number): number;
|
||||
writeUIntBE(value: number, offset: number, byteLength: number): number;
|
||||
writeIntLE(value: number, offset: number, byteLength: number): number;
|
||||
writeIntBE(value: number, offset: number, byteLength: number): number;
|
||||
readUIntLE(offset: number, byteLength: number): number;
|
||||
readUIntBE(offset: number, byteLength: number): number;
|
||||
readIntLE(offset: number, byteLength: number): number;
|
||||
readIntBE(offset: number, byteLength: number): number;
|
||||
readUInt8(offset: number): number;
|
||||
readUInt16LE(offset: number): number;
|
||||
readUInt16BE(offset: number): number;
|
||||
readUInt32LE(offset: number): number;
|
||||
readUInt32BE(offset: number): number;
|
||||
readInt8(offset: number): number;
|
||||
readInt16LE(offset: number): number;
|
||||
readInt16BE(offset: number): number;
|
||||
readInt32LE(offset: number): number;
|
||||
readInt32BE(offset: number): number;
|
||||
readFloatLE(offset: number): number;
|
||||
readFloatBE(offset: number): number;
|
||||
readDoubleLE(offset: number): number;
|
||||
readDoubleBE(offset: number): number;
|
||||
reverse(): this;
|
||||
swap16(): Buffer;
|
||||
swap32(): Buffer;
|
||||
swap64(): Buffer;
|
||||
writeUInt8(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt8(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt16LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt16BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt32LE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeInt32BE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeFloatLE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeFloatBE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;
|
||||
writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;
|
||||
fill(value: any, offset?: number, end?: number): this;
|
||||
indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
|
||||
lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
|
||||
writeUInt8(value: number, offset: number): number;
|
||||
writeUInt16LE(value: number, offset: number): number;
|
||||
writeUInt16BE(value: number, offset: number): number;
|
||||
writeUInt32LE(value: number, offset: number): number;
|
||||
writeUInt32BE(value: number, offset: number): number;
|
||||
writeInt8(value: number, offset: number): number;
|
||||
writeInt16LE(value: number, offset: number): number;
|
||||
writeInt16BE(value: number, offset: number): number;
|
||||
writeInt32LE(value: number, offset: number): number;
|
||||
writeInt32BE(value: number, offset: number): number;
|
||||
writeFloatLE(value: number, offset: number): number;
|
||||
writeFloatBE(value: number, offset: number): number;
|
||||
writeDoubleLE(value: number, offset: number): number;
|
||||
writeDoubleBE(value: number, offset: number): number;
|
||||
readBigUInt64BE(offset?: number): bigint;
|
||||
readBigUInt64LE(offset?: number): bigint;
|
||||
readBigInt64BE(offset?: number): bigint;
|
||||
readBigInt64LE(offset?: number): bigint;
|
||||
writeBigInt64BE(value: bigint, offset?: number): number;
|
||||
writeBigInt64LE(value: bigint, offset?: number): number;
|
||||
writeBigUInt64BE(value: bigint, offset?: number): number;
|
||||
writeBigUInt64LE(value: bigint, offset?: number): number;
|
||||
fill(value: string | Uint8Array | number, offset?: number, end?: number, encoding?: BufferEncoding): this;
|
||||
indexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number;
|
||||
lastIndexOf(value: string | number | Uint8Array, byteOffset?: number, encoding?: BufferEncoding): number;
|
||||
entries(): IterableIterator<[number, number]>;
|
||||
includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;
|
||||
includes(value: string | number | Buffer, byteOffset?: number, encoding?: BufferEncoding): boolean;
|
||||
keys(): IterableIterator<number>;
|
||||
values(): IterableIterator<number>;
|
||||
}
|
||||
@@ -661,6 +733,7 @@ namespace ts {
|
||||
|
||||
const nodeVersion = getNodeMajorVersion();
|
||||
const isNode4OrLater = nodeVersion! >= 4;
|
||||
const isLinuxOrMacOs = process.platform === "linux" || process.platform === "darwin";
|
||||
|
||||
const platform: string = _os.platform();
|
||||
const useCaseSensitiveFileNames = isFileSystemCaseSensitive();
|
||||
@@ -673,6 +746,7 @@ namespace ts {
|
||||
const useNonPollingWatchers = process.env.TSC_NONPOLLING_WATCHER;
|
||||
const tscWatchFile = process.env.TSC_WATCHFILE;
|
||||
const tscWatchDirectory = process.env.TSC_WATCHDIRECTORY;
|
||||
const fsWatchFile = createSingleFileWatcherPerName(fsWatchFileWorker, useCaseSensitiveFileNames);
|
||||
let dynamicPollingWatchFile: HostWatchFile | undefined;
|
||||
const nodeSystem: System = {
|
||||
args: process.argv.slice(2),
|
||||
@@ -813,7 +887,7 @@ namespace ts {
|
||||
return useNonPollingWatchers ?
|
||||
createNonPollingWatchFile() :
|
||||
// Default to do not use polling interval as it is before this experiment branch
|
||||
(fileName, callback) => fsWatchFile(fileName, callback);
|
||||
(fileName, callback) => fsWatchFile(fileName, callback, /*pollingInterval*/ undefined);
|
||||
}
|
||||
|
||||
function getWatchDirectory(): HostWatchDirectory {
|
||||
@@ -894,7 +968,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function fsWatchFile(fileName: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher {
|
||||
function fsWatchFileWorker(fileName: string, callback: FileWatcherCallback, pollingInterval?: number): FileWatcher {
|
||||
_fs.watchFile(fileName, { persistent: true, interval: pollingInterval || 250 }, fileChanged);
|
||||
let eventKind: FileWatcherEventKind;
|
||||
return {
|
||||
@@ -959,6 +1033,12 @@ namespace ts {
|
||||
|
||||
function fsWatch(fileOrDirectory: string, entryKind: FileSystemEntryKind.File | FileSystemEntryKind.Directory, callback: FsWatchCallback, recursive: boolean, fallbackPollingWatchFile: HostWatchFile, pollingInterval?: number): FileWatcher {
|
||||
let options: any;
|
||||
let lastDirectoryPartWithDirectorySeparator: string | undefined;
|
||||
let lastDirectoryPart: string | undefined;
|
||||
if (isLinuxOrMacOs) {
|
||||
lastDirectoryPartWithDirectorySeparator = fileOrDirectory.substr(fileOrDirectory.lastIndexOf(directorySeparator));
|
||||
lastDirectoryPart = lastDirectoryPartWithDirectorySeparator.slice(directorySeparator.length);
|
||||
}
|
||||
/** Watcher for the file system entry depending on whether it is missing or present */
|
||||
let watcher = !fileSystemEntryExists(fileOrDirectory, entryKind) ?
|
||||
watchMissingFileSystemEntry() :
|
||||
@@ -976,6 +1056,7 @@ namespace ts {
|
||||
* @param createWatcher
|
||||
*/
|
||||
function invokeCallbackAndUpdateWatcher(createWatcher: () => FileWatcher) {
|
||||
sysLog(`sysLog:: ${fileOrDirectory}:: Changing watcher to ${createWatcher === watchPresentFileSystemEntry ? "Present" : "Missing"}FileSystemEntryWatcher`);
|
||||
// Call the callback for current directory
|
||||
callback("rename", "");
|
||||
|
||||
@@ -1002,11 +1083,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
||||
const presentWatcher = _fs.watch(
|
||||
fileOrDirectory,
|
||||
options,
|
||||
callback
|
||||
isLinuxOrMacOs ?
|
||||
callbackChangingToMissingFileSystemEntry :
|
||||
callback
|
||||
);
|
||||
// Watch the missing file or directory or error
|
||||
presentWatcher.on("error", () => invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry));
|
||||
@@ -1020,11 +1102,24 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function callbackChangingToMissingFileSystemEntry(event: "rename" | "change", relativeName: string | undefined) {
|
||||
// because relativeName is not guaranteed to be correct we need to check on each rename with few combinations
|
||||
// Eg on ubuntu while watching app/node_modules the relativeName is "node_modules" which is neither relative nor full path
|
||||
return event === "rename" &&
|
||||
(!relativeName ||
|
||||
relativeName === lastDirectoryPart ||
|
||||
relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) === relativeName.length - lastDirectoryPartWithDirectorySeparator!.length) &&
|
||||
!fileSystemEntryExists(fileOrDirectory, entryKind) ?
|
||||
invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry) :
|
||||
callback(event, relativeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch the file or directory using fs.watchFile since fs.watch threw exception
|
||||
* Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point
|
||||
*/
|
||||
function watchPresentFileSystemEntryWithFsWatchFile(): FileWatcher {
|
||||
sysLog(`sysLog:: ${fileOrDirectory}:: Changing to fsWatchFile`);
|
||||
return fallbackPollingWatchFile(fileOrDirectory, createFileWatcherCallback(callback), pollingInterval);
|
||||
}
|
||||
|
||||
@@ -1064,7 +1159,7 @@ namespace ts {
|
||||
return (directoryName, callback) => fsWatchFile(directoryName, () => callback(directoryName), PollingInterval.Medium);
|
||||
}
|
||||
|
||||
function readFile(fileName: string, _encoding?: string): string | undefined {
|
||||
function readFileWorker(fileName: string, _encoding?: string): string | undefined {
|
||||
if (!fileExists(fileName)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1093,7 +1188,15 @@ namespace ts {
|
||||
return buffer.toString("utf8");
|
||||
}
|
||||
|
||||
function readFile(fileName: string, _encoding?: string): string | undefined {
|
||||
perfLogger.logStartReadFile(fileName);
|
||||
const file = readFileWorker(fileName, _encoding);
|
||||
perfLogger.logStopReadFile();
|
||||
return file;
|
||||
}
|
||||
|
||||
function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void {
|
||||
perfLogger.logEvent("WriteFile: " + fileName);
|
||||
// If a BOM is required, emit one
|
||||
if (writeByteOrderMark) {
|
||||
data = byteOrderMarkIndicator + data;
|
||||
@@ -1113,6 +1216,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getAccessibleFileSystemEntries(path: string): FileSystemEntries {
|
||||
perfLogger.logEvent("ReadDir: " + (path || "."));
|
||||
try {
|
||||
const entries = _fs.readdirSync(path || ".").sort();
|
||||
const files: string[] = [];
|
||||
@@ -1174,6 +1278,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getDirectories(path: string): string[] {
|
||||
perfLogger.logEvent("ReadDir: " + path);
|
||||
return filter<string>(_fs.readdirSync(path), dir => fileSystemEntryExists(combinePaths(path, dir), FileSystemEntryKind.Directory));
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ namespace ts {
|
||||
let currentSourceFile: SourceFile;
|
||||
let refs: Map<SourceFile>;
|
||||
let libs: Map<boolean>;
|
||||
let emittedImports: readonly AnyImportSyntax[] | undefined; // must be declared in container so it can be `undefined` while transformer's first pass
|
||||
const resolver = context.getEmitResolver();
|
||||
const options = context.getCompilerOptions();
|
||||
const newLine = getNewLineCharacter(options);
|
||||
@@ -279,7 +280,7 @@ namespace ts {
|
||||
const statements = visitNodes(node.statements, visitDeclarationStatements);
|
||||
let combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
|
||||
refs.forEach(referenceVisitor);
|
||||
const emittedImports = filter(combinedStatements, isAnyImportSyntax);
|
||||
emittedImports = filter(combinedStatements, isAnyImportSyntax);
|
||||
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
|
||||
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createEmptyExports()]), combinedStatements);
|
||||
}
|
||||
@@ -392,7 +393,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function ensureParameter(p: ParameterDeclaration, modifierMask?: ModifierFlags): ParameterDeclaration {
|
||||
function ensureParameter(p: ParameterDeclaration, modifierMask?: ModifierFlags, type?: TypeNode): ParameterDeclaration {
|
||||
let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined;
|
||||
if (!suppressNewDiagnosticContexts) {
|
||||
oldDiag = getSymbolAccessibilityDiagnostic;
|
||||
@@ -405,7 +406,7 @@ namespace ts {
|
||||
p.dotDotDotToken,
|
||||
filterBindingPatternInitializers(p.name),
|
||||
resolver.isOptionalParameter(p) ? (p.questionToken || createToken(SyntaxKind.QuestionToken)) : undefined,
|
||||
ensureType(p, p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param
|
||||
ensureType(p, type || p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param
|
||||
ensureNoInitializer(p)
|
||||
);
|
||||
if (!suppressNewDiagnosticContexts) {
|
||||
@@ -534,6 +535,36 @@ namespace ts {
|
||||
return createNodeArray(newParams, params.hasTrailingComma);
|
||||
}
|
||||
|
||||
function updateAccessorParamsList(input: AccessorDeclaration, isPrivate: boolean) {
|
||||
let newParams: ParameterDeclaration[] | undefined;
|
||||
if (!isPrivate) {
|
||||
const thisParameter = getThisParameter(input);
|
||||
if (thisParameter) {
|
||||
newParams = [ensureParameter(thisParameter)];
|
||||
}
|
||||
}
|
||||
if (isSetAccessorDeclaration(input)) {
|
||||
let newValueParameter: ParameterDeclaration | undefined;
|
||||
if (!isPrivate) {
|
||||
const valueParameter = getSetAccessorValueParameter(input);
|
||||
if (valueParameter) {
|
||||
const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input));
|
||||
newValueParameter = ensureParameter(valueParameter, /*modifierMask*/ undefined, accessorType);
|
||||
}
|
||||
}
|
||||
if (!newValueParameter) {
|
||||
newValueParameter = createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
"value"
|
||||
);
|
||||
}
|
||||
newParams = append(newParams, newValueParameter);
|
||||
}
|
||||
return createNodeArray(newParams || emptyArray) as NodeArray<ParameterDeclaration>;
|
||||
}
|
||||
|
||||
function ensureTypeParams(node: Node, params: NodeArray<TypeParameterDeclaration> | undefined) {
|
||||
return hasModifier(node, ModifierFlags.Private) ? undefined : visitNodes(params, visitDeclarationSubtree);
|
||||
}
|
||||
@@ -736,6 +767,12 @@ namespace ts {
|
||||
}
|
||||
const oldDiag = getSymbolAccessibilityDiagnostic;
|
||||
|
||||
// Setup diagnostic-related flags before first potential `cleanup` call, otherwise
|
||||
// We'd see a TDZ violation at runtime
|
||||
const canProduceDiagnostic = canProduceDiagnostics(input);
|
||||
const oldWithinObjectLiteralType = suppressNewDiagnosticContexts;
|
||||
let shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === SyntaxKind.TypeLiteral || input.kind === SyntaxKind.MappedType) && input.parent.kind !== SyntaxKind.TypeAliasDeclaration);
|
||||
|
||||
// Emit methods which are private as properties with no type information
|
||||
if (isMethodDeclaration(input) || isMethodSignature(input)) {
|
||||
if (hasModifier(input, ModifierFlags.Private)) {
|
||||
@@ -744,8 +781,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const canProdiceDiagnostic = canProduceDiagnostics(input);
|
||||
if (canProdiceDiagnostic && !suppressNewDiagnosticContexts) {
|
||||
if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
|
||||
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing);
|
||||
}
|
||||
|
||||
@@ -753,8 +789,6 @@ namespace ts {
|
||||
checkEntityNameVisibility(input.exprName, enclosingDeclaration);
|
||||
}
|
||||
|
||||
const oldWithinObjectLiteralType = suppressNewDiagnosticContexts;
|
||||
let shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === SyntaxKind.TypeLiteral || input.kind === SyntaxKind.MappedType) && input.parent.kind !== SyntaxKind.TypeAliasDeclaration);
|
||||
if (shouldEnterSuppressNewDiagnosticsContextContext) {
|
||||
// We stop making new diagnostic contexts within object literal types. Unless it's an object type on the RHS of a type alias declaration. Then we do.
|
||||
suppressNewDiagnosticContexts = true;
|
||||
@@ -807,10 +841,33 @@ namespace ts {
|
||||
return cleanup(sig);
|
||||
}
|
||||
case SyntaxKind.GetAccessor: {
|
||||
// For now, only emit class accessors as accessors if they were already declared in an ambient context.
|
||||
if (input.flags & NodeFlags.Ambient) {
|
||||
const isPrivate = hasModifier(input, ModifierFlags.Private);
|
||||
const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input));
|
||||
return cleanup(updateGetAccessor(
|
||||
input,
|
||||
/*decorators*/ undefined,
|
||||
ensureModifiers(input),
|
||||
input.name,
|
||||
updateAccessorParamsList(input, isPrivate),
|
||||
!isPrivate ? ensureType(input, accessorType) : undefined,
|
||||
/*body*/ undefined));
|
||||
}
|
||||
const newNode = ensureAccessor(input);
|
||||
return cleanup(newNode);
|
||||
}
|
||||
case SyntaxKind.SetAccessor: {
|
||||
// For now, only emit class accessors as accessors if they were already declared in an ambient context.
|
||||
if (input.flags & NodeFlags.Ambient) {
|
||||
return cleanup(updateSetAccessor(
|
||||
input,
|
||||
/*decorators*/ undefined,
|
||||
ensureModifiers(input),
|
||||
input.name,
|
||||
updateAccessorParamsList(input, hasModifier(input, ModifierFlags.Private)),
|
||||
/*body*/ undefined));
|
||||
}
|
||||
const newNode = ensureAccessor(input);
|
||||
return cleanup(newNode);
|
||||
}
|
||||
@@ -909,13 +966,13 @@ namespace ts {
|
||||
return cleanup(visitEachChild(input, visitDeclarationSubtree, context));
|
||||
|
||||
function cleanup<T extends Node>(returnValue: T | undefined): T | undefined {
|
||||
if (returnValue && canProdiceDiagnostic && hasDynamicName(input as Declaration)) {
|
||||
if (returnValue && canProduceDiagnostic && hasDynamicName(input as Declaration)) {
|
||||
checkName(input as DeclarationDiagnosticProducing);
|
||||
}
|
||||
if (isEnclosingDeclaration(input)) {
|
||||
enclosingDeclaration = previousEnclosingDeclaration;
|
||||
}
|
||||
if (canProdiceDiagnostic && !suppressNewDiagnosticContexts) {
|
||||
if (canProduceDiagnostic && !suppressNewDiagnosticContexts) {
|
||||
getSymbolAccessibilityDiagnostic = oldDiag;
|
||||
}
|
||||
if (shouldEnterSuppressNewDiagnosticsContextContext) {
|
||||
@@ -1370,17 +1427,27 @@ namespace ts {
|
||||
return maskModifierFlags(node, mask, additions);
|
||||
}
|
||||
|
||||
function getTypeAnnotationFromAllAccessorDeclarations(node: AccessorDeclaration, accessors: AllAccessorDeclarations) {
|
||||
let accessorType = getTypeAnnotationFromAccessor(node);
|
||||
if (!accessorType && node !== accessors.firstAccessor) {
|
||||
accessorType = getTypeAnnotationFromAccessor(accessors.firstAccessor);
|
||||
// If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message
|
||||
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.firstAccessor);
|
||||
}
|
||||
if (!accessorType && accessors.secondAccessor && node !== accessors.secondAccessor) {
|
||||
accessorType = getTypeAnnotationFromAccessor(accessors.secondAccessor);
|
||||
// If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message
|
||||
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor);
|
||||
}
|
||||
return accessorType;
|
||||
}
|
||||
|
||||
function ensureAccessor(node: AccessorDeclaration): PropertyDeclaration | undefined {
|
||||
const accessors = resolver.getAllAccessorDeclarations(node);
|
||||
if (node.kind !== accessors.firstAccessor.kind) {
|
||||
return;
|
||||
}
|
||||
let accessorType = getTypeAnnotationFromAccessor(node);
|
||||
if (!accessorType && accessors.secondAccessor) {
|
||||
accessorType = getTypeAnnotationFromAccessor(accessors.secondAccessor);
|
||||
// If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message
|
||||
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor);
|
||||
}
|
||||
const accessorType = getTypeAnnotationFromAllAccessorDeclarations(node, accessors);
|
||||
const prop = createProperty(/*decorators*/ undefined, maskModifiers(node, /*mask*/ undefined, (!accessors.setAccessor) ? ModifierFlags.Readonly : ModifierFlags.None), node.name, node.questionToken, ensureType(node, accessorType), /*initializer*/ undefined);
|
||||
const leadingsSyntheticCommentRanges = accessors.secondAccessor && getLeadingCommentRangesOfNode(accessors.secondAccessor, currentSourceFile);
|
||||
if (leadingsSyntheticCommentRanges) {
|
||||
|
||||
@@ -514,6 +514,7 @@ namespace ts {
|
||||
|
||||
export const restHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:rest",
|
||||
importName: "__rest",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
@@ -557,7 +558,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
return createCall(
|
||||
getHelperName("__rest"),
|
||||
getUnscopedHelperName("__rest"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
value,
|
||||
|
||||
@@ -4339,7 +4339,7 @@ namespace ts {
|
||||
function createExtendsHelper(context: TransformationContext, name: Identifier) {
|
||||
context.requestEmitHelper(extendsHelper);
|
||||
return createCall(
|
||||
getHelperName("__extends"),
|
||||
getUnscopedHelperName("__extends"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
name,
|
||||
@@ -4351,7 +4351,7 @@ namespace ts {
|
||||
function createTemplateObjectHelper(context: TransformationContext, cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) {
|
||||
context.requestEmitHelper(templateObjectHelper);
|
||||
return createCall(
|
||||
getHelperName("__makeTemplateObject"),
|
||||
getUnscopedHelperName("__makeTemplateObject"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
cooked,
|
||||
@@ -4362,6 +4362,7 @@ namespace ts {
|
||||
|
||||
export const extendsHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:extends",
|
||||
importName: "__extends",
|
||||
scoped: false,
|
||||
priority: 0,
|
||||
text: `
|
||||
@@ -4383,6 +4384,7 @@ namespace ts {
|
||||
|
||||
export const templateObjectHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:makeTemplateObject",
|
||||
importName: "__makeTemplateObject",
|
||||
scoped: false,
|
||||
priority: 0,
|
||||
text: `
|
||||
|
||||
@@ -41,6 +41,8 @@ namespace ts {
|
||||
/** A set of node IDs for generated super accessors (variable statements). */
|
||||
const substitutedSuperAccessors: boolean[] = [];
|
||||
|
||||
let topLevel: boolean;
|
||||
|
||||
// Save the previous transformation hooks.
|
||||
const previousOnEmitNode = context.onEmitNode;
|
||||
const previousOnSubstituteNode = context.onSubstituteNode;
|
||||
@@ -56,11 +58,26 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
topLevel = isEffectiveStrictModeSourceFile(node, compilerOptions);
|
||||
const visited = visitEachChild(node, visitor, context);
|
||||
addEmitHelpers(visited, context.readEmitHelpers());
|
||||
return visited;
|
||||
}
|
||||
|
||||
function doOutsideOfTopLevel<T, U>(cb: (value: T) => U, value: T) {
|
||||
if (topLevel) {
|
||||
topLevel = false;
|
||||
const result = cb(value);
|
||||
topLevel = true;
|
||||
return result;
|
||||
}
|
||||
return cb(value);
|
||||
}
|
||||
|
||||
function visitDefault(node: Node): VisitResult<Node> {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function visitor(node: Node): VisitResult<Node> {
|
||||
if ((node.transformFlags & TransformFlags.ContainsES2017) === 0) {
|
||||
return node;
|
||||
@@ -74,13 +91,13 @@ namespace ts {
|
||||
return visitAwaitExpression(<AwaitExpression>node);
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return visitMethodDeclaration(<MethodDeclaration>node);
|
||||
return doOutsideOfTopLevel(visitMethodDeclaration, <MethodDeclaration>node);
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return visitFunctionDeclaration(<FunctionDeclaration>node);
|
||||
return doOutsideOfTopLevel(visitFunctionDeclaration, <FunctionDeclaration>node);
|
||||
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return visitFunctionExpression(<FunctionExpression>node);
|
||||
return doOutsideOfTopLevel(visitFunctionExpression, <FunctionExpression>node);
|
||||
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return visitArrowFunction(<ArrowFunction>node);
|
||||
@@ -97,6 +114,13 @@ namespace ts {
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
return doOutsideOfTopLevel(visitDefault, node);
|
||||
|
||||
default:
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
@@ -433,6 +457,7 @@ namespace ts {
|
||||
createReturn(
|
||||
createAwaiterHelper(
|
||||
context,
|
||||
!topLevel,
|
||||
hasLexicalArguments,
|
||||
promiseConstructor,
|
||||
transformAsyncFunctionBodyWorker(<Block>node.body, statementOffset)
|
||||
@@ -473,6 +498,7 @@ namespace ts {
|
||||
else {
|
||||
const expression = createAwaiterHelper(
|
||||
context,
|
||||
!topLevel,
|
||||
hasLexicalArguments,
|
||||
promiseConstructor,
|
||||
transformAsyncFunctionBodyWorker(node.body!)
|
||||
@@ -771,20 +797,22 @@ namespace ts {
|
||||
|
||||
export const awaiterHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:awaiter",
|
||||
importName: "__awaiter",
|
||||
scoped: false,
|
||||
priority: 5,
|
||||
text: `
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};`
|
||||
};
|
||||
|
||||
function createAwaiterHelper(context: TransformationContext, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) {
|
||||
function createAwaiterHelper(context: TransformationContext, hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) {
|
||||
context.requestEmitHelper(awaiterHelper);
|
||||
|
||||
const generatorFunc = createFunctionExpression(
|
||||
@@ -801,10 +829,10 @@ namespace ts {
|
||||
(generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope;
|
||||
|
||||
return createCall(
|
||||
getHelperName("__awaiter"),
|
||||
getUnscopedHelperName("__awaiter"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
hasLexicalThis ? createThis() : createVoidZero(),
|
||||
hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(),
|
||||
promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(),
|
||||
generatorFunc
|
||||
|
||||
@@ -22,9 +22,11 @@ namespace ts {
|
||||
const previousOnSubstituteNode = context.onSubstituteNode;
|
||||
context.onSubstituteNode = onSubstituteNode;
|
||||
|
||||
let exportedVariableStatement = false;
|
||||
let enabledSubstitutions: ESNextSubstitutionFlags;
|
||||
let enclosingFunctionFlags: FunctionFlags;
|
||||
let enclosingSuperContainerFlags: NodeCheckFlags = 0;
|
||||
let topLevel: boolean;
|
||||
|
||||
/** Keeps track of property names accessed on super (`super.x`) within async functions. */
|
||||
let capturedSuperProperties: UnderscoreEscapedMap<true>;
|
||||
@@ -40,6 +42,8 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
exportedVariableStatement = false;
|
||||
topLevel = isEffectiveStrictModeSourceFile(node, compilerOptions);
|
||||
const visited = visitEachChild(node, visitor, context);
|
||||
addEmitHelpers(visited, context.readEmitHelpers());
|
||||
return visited;
|
||||
@@ -60,6 +64,20 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
function doOutsideOfTopLevel<T, U>(cb: (value: T) => U, value: T) {
|
||||
if (topLevel) {
|
||||
topLevel = false;
|
||||
const result = cb(value);
|
||||
topLevel = true;
|
||||
return result;
|
||||
}
|
||||
return cb(value);
|
||||
}
|
||||
|
||||
function visitDefault(node: Node): VisitResult<Node> {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function visitorWorker(node: Node, noDestructuringValue: boolean): VisitResult<Node> {
|
||||
if ((node.transformFlags & TransformFlags.ContainsES2018) === 0) {
|
||||
return node;
|
||||
@@ -79,6 +97,8 @@ namespace ts {
|
||||
return visitBinaryExpression(node as BinaryExpression, noDestructuringValue);
|
||||
case SyntaxKind.CatchClause:
|
||||
return visitCatchClause(node as CatchClause);
|
||||
case SyntaxKind.VariableStatement:
|
||||
return visitVariableStatement(node as VariableStatement);
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
return visitVariableDeclaration(node as VariableDeclaration);
|
||||
case SyntaxKind.ForOfStatement:
|
||||
@@ -88,17 +108,17 @@ namespace ts {
|
||||
case SyntaxKind.VoidExpression:
|
||||
return visitVoidExpression(node as VoidExpression);
|
||||
case SyntaxKind.Constructor:
|
||||
return visitConstructorDeclaration(node as ConstructorDeclaration);
|
||||
return doOutsideOfTopLevel(visitConstructorDeclaration, node as ConstructorDeclaration);
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return visitMethodDeclaration(node as MethodDeclaration);
|
||||
return doOutsideOfTopLevel(visitMethodDeclaration, node as MethodDeclaration);
|
||||
case SyntaxKind.GetAccessor:
|
||||
return visitGetAccessorDeclaration(node as GetAccessorDeclaration);
|
||||
return doOutsideOfTopLevel(visitGetAccessorDeclaration, node as GetAccessorDeclaration);
|
||||
case SyntaxKind.SetAccessor:
|
||||
return visitSetAccessorDeclaration(node as SetAccessorDeclaration);
|
||||
return doOutsideOfTopLevel(visitSetAccessorDeclaration, node as SetAccessorDeclaration);
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return visitFunctionDeclaration(node as FunctionDeclaration);
|
||||
return doOutsideOfTopLevel(visitFunctionDeclaration, node as FunctionDeclaration);
|
||||
case SyntaxKind.FunctionExpression:
|
||||
return visitFunctionExpression(node as FunctionExpression);
|
||||
return doOutsideOfTopLevel(visitFunctionExpression, node as FunctionExpression);
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return visitArrowFunction(node as ArrowFunction);
|
||||
case SyntaxKind.Parameter:
|
||||
@@ -117,6 +137,9 @@ namespace ts {
|
||||
hasSuperElementAccess = true;
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
return doOutsideOfTopLevel(visitDefault, node);
|
||||
default:
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
@@ -229,14 +252,39 @@ namespace ts {
|
||||
if (node.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
// spread elements emit like so:
|
||||
// non-spread elements are chunked together into object literals, and then all are passed to __assign:
|
||||
// { a, ...o, b } => __assign({a}, o, {b});
|
||||
// { a, ...o, b } => __assign(__assign({a}, o), {b});
|
||||
// If the first element is a spread element, then the first argument to __assign is {}:
|
||||
// { ...o, a, b, ...o2 } => __assign({}, o, {a, b}, o2)
|
||||
// { ...o, a, b, ...o2 } => __assign(__assign(__assign({}, o), {a, b}), o2)
|
||||
//
|
||||
// We cannot call __assign with more than two elements, since any element could cause side effects. For
|
||||
// example:
|
||||
// var k = { a: 1, b: 2 };
|
||||
// var o = { a: 3, ...k, b: k.a++ };
|
||||
// // expected: { a: 1, b: 1 }
|
||||
// If we translate the above to `__assign({ a: 3 }, k, { b: k.a++ })`, the `k.a++` will evaluate before
|
||||
// `k` is spread and we end up with `{ a: 2, b: 1 }`.
|
||||
//
|
||||
// This also occurs for spread elements, not just property assignments:
|
||||
// var k = { a: 1, get b() { l = { z: 9 }; return 2; } };
|
||||
// var l = { c: 3 };
|
||||
// var o = { ...k, ...l };
|
||||
// // expected: { a: 1, b: 2, z: 9 }
|
||||
// If we translate the above to `__assign({}, k, l)`, the `l` will evaluate before `k` is spread and we
|
||||
// end up with `{ a: 1, b: 2, c: 3 }`
|
||||
const objects = chunkObjectLiteralElements(node.properties);
|
||||
if (objects.length && objects[0].kind !== SyntaxKind.ObjectLiteralExpression) {
|
||||
objects.unshift(createObjectLiteral());
|
||||
}
|
||||
return createAssignHelper(context, objects);
|
||||
let expression: Expression = objects[0];
|
||||
if (objects.length > 1) {
|
||||
for (let i = 1; i < objects.length; i++) {
|
||||
expression = createAssignHelper(context, [expression, objects[i]]);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
else {
|
||||
return createAssignHelper(context, objects);
|
||||
}
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
@@ -296,19 +344,43 @@ namespace ts {
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function visitVariableStatement(node: VariableStatement): VisitResult<VariableStatement> {
|
||||
if (hasModifier(node, ModifierFlags.Export)) {
|
||||
const savedExportedVariableStatement = exportedVariableStatement;
|
||||
exportedVariableStatement = true;
|
||||
const visited = visitEachChild(node, visitor, context);
|
||||
exportedVariableStatement = savedExportedVariableStatement;
|
||||
return visited;
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a VariableDeclaration node with a binding pattern.
|
||||
*
|
||||
* @param node A VariableDeclaration node.
|
||||
*/
|
||||
function visitVariableDeclaration(node: VariableDeclaration): VisitResult<VariableDeclaration> {
|
||||
if (exportedVariableStatement) {
|
||||
const savedExportedVariableStatement = exportedVariableStatement;
|
||||
exportedVariableStatement = false;
|
||||
const visited = visitVariableDeclarationWorker(node, /*exportedVariableStatement*/ true);
|
||||
exportedVariableStatement = savedExportedVariableStatement;
|
||||
return visited;
|
||||
}
|
||||
return visitVariableDeclarationWorker(node, /*exportedVariableStatement*/ false);
|
||||
}
|
||||
|
||||
function visitVariableDeclarationWorker(node: VariableDeclaration, exportedVariableStatement: boolean): VisitResult<VariableDeclaration> {
|
||||
// If we are here it is because the name contains a binding pattern with a rest somewhere in it.
|
||||
if (isBindingPattern(node.name) && node.name.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
|
||||
return flattenDestructuringBinding(
|
||||
node,
|
||||
visitor,
|
||||
context,
|
||||
FlattenLevel.ObjectRest
|
||||
FlattenLevel.ObjectRest,
|
||||
/*rval*/ undefined,
|
||||
exportedVariableStatement
|
||||
);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
@@ -701,7 +773,8 @@ namespace ts {
|
||||
node.body!,
|
||||
visitLexicalEnvironment(node.body!.statements, visitor, context, statementOffset)
|
||||
)
|
||||
)
|
||||
),
|
||||
!topLevel
|
||||
)
|
||||
);
|
||||
|
||||
@@ -942,6 +1015,7 @@ namespace ts {
|
||||
|
||||
export const assignHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:assign",
|
||||
importName: "__assign",
|
||||
scoped: false,
|
||||
priority: 1,
|
||||
text: `
|
||||
@@ -966,7 +1040,7 @@ namespace ts {
|
||||
}
|
||||
context.requestEmitHelper(assignHelper);
|
||||
return createCall(
|
||||
getHelperName("__assign"),
|
||||
getUnscopedHelperName("__assign"),
|
||||
/*typeArguments*/ undefined,
|
||||
attributesSegments
|
||||
);
|
||||
@@ -974,6 +1048,7 @@ namespace ts {
|
||||
|
||||
export const awaitHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:await",
|
||||
importName: "__await",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }`
|
||||
@@ -981,11 +1056,12 @@ namespace ts {
|
||||
|
||||
function createAwaitHelper(context: TransformationContext, expression: Expression) {
|
||||
context.requestEmitHelper(awaitHelper);
|
||||
return createCall(getHelperName("__await"), /*typeArguments*/ undefined, [expression]);
|
||||
return createCall(getUnscopedHelperName("__await"), /*typeArguments*/ undefined, [expression]);
|
||||
}
|
||||
|
||||
export const asyncGeneratorHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:asyncGenerator",
|
||||
importName: "__asyncGenerator",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
||||
@@ -1001,7 +1077,7 @@ namespace ts {
|
||||
};`
|
||||
};
|
||||
|
||||
function createAsyncGeneratorHelper(context: TransformationContext, generatorFunc: FunctionExpression) {
|
||||
function createAsyncGeneratorHelper(context: TransformationContext, generatorFunc: FunctionExpression, hasLexicalThis: boolean) {
|
||||
context.requestEmitHelper(awaitHelper);
|
||||
context.requestEmitHelper(asyncGeneratorHelper);
|
||||
|
||||
@@ -1009,10 +1085,10 @@ namespace ts {
|
||||
(generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody;
|
||||
|
||||
return createCall(
|
||||
getHelperName("__asyncGenerator"),
|
||||
getUnscopedHelperName("__asyncGenerator"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createThis(),
|
||||
hasLexicalThis ? createThis() : createVoidZero(),
|
||||
createIdentifier("arguments"),
|
||||
generatorFunc
|
||||
]
|
||||
@@ -1021,6 +1097,7 @@ namespace ts {
|
||||
|
||||
export const asyncDelegator: UnscopedEmitHelper = {
|
||||
name: "typescript:asyncDelegator",
|
||||
importName: "__asyncDelegator",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
|
||||
@@ -1035,7 +1112,7 @@ namespace ts {
|
||||
context.requestEmitHelper(asyncDelegator);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__asyncDelegator"),
|
||||
getUnscopedHelperName("__asyncDelegator"),
|
||||
/*typeArguments*/ undefined,
|
||||
[expression]
|
||||
),
|
||||
@@ -1045,6 +1122,7 @@ namespace ts {
|
||||
|
||||
export const asyncValues: UnscopedEmitHelper = {
|
||||
name: "typescript:asyncValues",
|
||||
importName: "__asyncValues",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
||||
@@ -1060,7 +1138,7 @@ namespace ts {
|
||||
context.requestEmitHelper(asyncValues);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__asyncValues"),
|
||||
getUnscopedHelperName("__asyncValues"),
|
||||
/*typeArguments*/ undefined,
|
||||
[expression]
|
||||
),
|
||||
|
||||
@@ -3176,7 +3176,7 @@ namespace ts {
|
||||
function createGeneratorHelper(context: TransformationContext, body: FunctionExpression) {
|
||||
context.requestEmitHelper(generatorHelper);
|
||||
return createCall(
|
||||
getHelperName("__generator"),
|
||||
getUnscopedHelperName("__generator"),
|
||||
/*typeArguments*/ undefined,
|
||||
[createThis(), body]);
|
||||
}
|
||||
@@ -3242,6 +3242,7 @@ namespace ts {
|
||||
// For examples of how these are used, see the comments in ./transformers/generators.ts
|
||||
export const generatorHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:generator",
|
||||
importName: "__generator",
|
||||
scoped: false,
|
||||
priority: 6,
|
||||
text: `
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ts {
|
||||
context.enableEmitNotification(SyntaxKind.SourceFile);
|
||||
context.enableSubstitution(SyntaxKind.Identifier);
|
||||
|
||||
let currentSourceFile: SourceFile | undefined;
|
||||
let helperNameSubstitutions: Map<Identifier> | undefined;
|
||||
return chainBundle(transformSourceFile);
|
||||
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
@@ -18,18 +18,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (isExternalModule(node) || compilerOptions.isolatedModules) {
|
||||
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(node, compilerOptions);
|
||||
if (externalHelpersModuleName) {
|
||||
const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(node, compilerOptions);
|
||||
if (externalHelpersImportDeclaration) {
|
||||
const statements: Statement[] = [];
|
||||
const statementOffset = addPrologue(statements, node.statements);
|
||||
const tslibImport = createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText)
|
||||
);
|
||||
addEmitFlags(tslibImport, EmitFlags.NeverApplyImportHelper);
|
||||
append(statements, tslibImport);
|
||||
append(statements, externalHelpersImportDeclaration);
|
||||
|
||||
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
|
||||
return updateSourceFileNode(
|
||||
@@ -74,9 +67,9 @@ namespace ts {
|
||||
*/
|
||||
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
|
||||
if (isSourceFile(node)) {
|
||||
currentSourceFile = node;
|
||||
helperNameSubstitutions = createMap<Identifier>();
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
currentSourceFile = undefined;
|
||||
helperNameSubstitutions = undefined;
|
||||
}
|
||||
else {
|
||||
previousOnEmitNode(hint, node, emitCallback);
|
||||
@@ -95,21 +88,20 @@ namespace ts {
|
||||
*/
|
||||
function onSubstituteNode(hint: EmitHint, node: Node) {
|
||||
node = previousOnSubstituteNode(hint, node);
|
||||
if (isIdentifier(node) && hint === EmitHint.Expression) {
|
||||
return substituteExpressionIdentifier(node);
|
||||
if (helperNameSubstitutions && isIdentifier(node) && getEmitFlags(node) & EmitFlags.HelperName) {
|
||||
return substituteHelperName(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteExpressionIdentifier(node: Identifier): Expression {
|
||||
if (getEmitFlags(node) & EmitFlags.HelperName) {
|
||||
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile!);
|
||||
if (externalHelpersModuleName) {
|
||||
return createPropertyAccess(externalHelpersModuleName, node);
|
||||
}
|
||||
function substituteHelperName(node: Identifier): Expression {
|
||||
const name = idText(node);
|
||||
let substitution = helperNameSubstitutions!.get(name);
|
||||
if (!substitution) {
|
||||
helperNameSubstitutions!.set(name, substitution = createFileLevelUniqueName(name));
|
||||
}
|
||||
return node;
|
||||
return substitution;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -698,7 +698,7 @@ namespace ts {
|
||||
const promise = createNew(createIdentifier("Promise"), /*typeArguments*/ undefined, [func]);
|
||||
if (compilerOptions.esModuleInterop) {
|
||||
context.requestEmitHelper(importStarHelper);
|
||||
return createCall(createPropertyAccess(promise, createIdentifier("then")), /*typeArguments*/ undefined, [getHelperName("__importStar")]);
|
||||
return createCall(createPropertyAccess(promise, createIdentifier("then")), /*typeArguments*/ undefined, [getUnscopedHelperName("__importStar")]);
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
@@ -713,7 +713,7 @@ namespace ts {
|
||||
let requireCall = createCall(createIdentifier("require"), /*typeArguments*/ undefined, arg ? [arg] : []);
|
||||
if (compilerOptions.esModuleInterop) {
|
||||
context.requestEmitHelper(importStarHelper);
|
||||
requireCall = createCall(getHelperName("__importStar"), /*typeArguments*/ undefined, [requireCall]);
|
||||
requireCall = createCall(getUnscopedHelperName("__importStar"), /*typeArguments*/ undefined, [requireCall]);
|
||||
}
|
||||
|
||||
let func: FunctionExpression | ArrowFunction;
|
||||
@@ -753,11 +753,11 @@ namespace ts {
|
||||
}
|
||||
if (getImportNeedsImportStarHelper(node)) {
|
||||
context.requestEmitHelper(importStarHelper);
|
||||
return createCall(getHelperName("__importStar"), /*typeArguments*/ undefined, [innerExpr]);
|
||||
return createCall(getUnscopedHelperName("__importStar"), /*typeArguments*/ undefined, [innerExpr]);
|
||||
}
|
||||
if (getImportNeedsImportDefaultHelper(node)) {
|
||||
context.requestEmitHelper(importDefaultHelper);
|
||||
return createCall(getHelperName("__importDefault"), /*typeArguments*/ undefined, [innerExpr]);
|
||||
return createCall(getUnscopedHelperName("__importDefault"), /*typeArguments*/ undefined, [innerExpr]);
|
||||
}
|
||||
return innerExpr;
|
||||
}
|
||||
@@ -1793,7 +1793,7 @@ namespace ts {
|
||||
function createExportStarHelper(context: TransformationContext, module: Expression) {
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
return compilerOptions.importHelpers
|
||||
? createCall(getHelperName("__exportStar"), /*typeArguments*/ undefined, [module, createIdentifier("exports")])
|
||||
? createCall(getUnscopedHelperName("__exportStar"), /*typeArguments*/ undefined, [module, createIdentifier("exports")])
|
||||
: createCall(createIdentifier("__export"), /*typeArguments*/ undefined, [module]);
|
||||
}
|
||||
|
||||
@@ -1808,6 +1808,7 @@ namespace ts {
|
||||
// emit helper for `import * as Name from "foo"`
|
||||
export const importStarHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:commonjsimportstar",
|
||||
importName: "__importStar",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
@@ -1822,6 +1823,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
// emit helper for `import Name from "foo"`
|
||||
export const importDefaultHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:commonjsimportdefault",
|
||||
importName: "__importDefault",
|
||||
scoped: false,
|
||||
text: `
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
|
||||
@@ -24,12 +24,14 @@ namespace ts {
|
||||
context.enableSubstitution(SyntaxKind.BinaryExpression); // Substitutes assignments to exported symbols.
|
||||
context.enableSubstitution(SyntaxKind.PrefixUnaryExpression); // Substitutes updates to exported symbols.
|
||||
context.enableSubstitution(SyntaxKind.PostfixUnaryExpression); // Substitutes updates to exported symbols.
|
||||
context.enableSubstitution(SyntaxKind.MetaProperty); // Substitutes 'import.meta'
|
||||
context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file.
|
||||
|
||||
const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file.
|
||||
const deferredExports: (Statement[] | undefined)[] = []; // Exports to defer until an EndOfDeclarationMarker is found.
|
||||
const exportFunctionsMap: Identifier[] = []; // The export function associated with a source file.
|
||||
const noSubstitutionMap: boolean[][] = []; // Set of nodes for which substitution rules should be ignored for each file.
|
||||
const contextObjectMap: Identifier[] = []; // The context object associated with a source file.
|
||||
|
||||
let currentSourceFile: SourceFile; // The current file.
|
||||
let moduleInfo: ExternalModuleInfo; // ExternalModuleInfo for the current file.
|
||||
@@ -75,7 +77,7 @@ namespace ts {
|
||||
// existing identifiers.
|
||||
exportFunction = createUniqueName("exports");
|
||||
exportFunctionsMap[id] = exportFunction;
|
||||
contextObject = createUniqueName("context");
|
||||
contextObject = contextObjectMap[id] = createUniqueName("context");
|
||||
|
||||
// Add the body of the module.
|
||||
const dependencyGroups = collectDependencyGroups(moduleInfo.externalImports);
|
||||
@@ -1586,6 +1588,7 @@ namespace ts {
|
||||
moduleInfo = moduleInfoMap[id];
|
||||
exportFunction = exportFunctionsMap[id];
|
||||
noSubstitution = noSubstitutionMap[id];
|
||||
contextObject = contextObjectMap[id];
|
||||
|
||||
if (noSubstitution) {
|
||||
delete noSubstitutionMap[id];
|
||||
@@ -1596,6 +1599,7 @@ namespace ts {
|
||||
currentSourceFile = undefined!;
|
||||
moduleInfo = undefined!;
|
||||
exportFunction = undefined!;
|
||||
contextObject = undefined!;
|
||||
noSubstitution = undefined;
|
||||
}
|
||||
else {
|
||||
@@ -1641,6 +1645,7 @@ namespace ts {
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitution for a ShorthandPropertyAssignment whose name that may contain an imported or exported symbol.
|
||||
*
|
||||
@@ -1694,6 +1699,8 @@ namespace ts {
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
return substituteUnaryExpression(<PrefixUnaryExpression | PostfixUnaryExpression>node);
|
||||
case SyntaxKind.MetaProperty:
|
||||
return substituteMetaProperty(<MetaProperty>node);
|
||||
}
|
||||
|
||||
return node;
|
||||
@@ -1830,6 +1837,13 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteMetaProperty(node: MetaProperty) {
|
||||
if (isImportMeta(node)) {
|
||||
return createPropertyAccess(contextObject, createIdentifier("meta"));
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exports of a name.
|
||||
*
|
||||
|
||||
@@ -3282,7 +3282,7 @@ namespace ts {
|
||||
context.requestEmitHelper(decorateHelper);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__decorate"),
|
||||
getUnscopedHelperName("__decorate"),
|
||||
/*typeArguments*/ undefined,
|
||||
argumentsArray
|
||||
),
|
||||
@@ -3292,6 +3292,7 @@ namespace ts {
|
||||
|
||||
export const decorateHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:decorate",
|
||||
importName: "__decorate",
|
||||
scoped: false,
|
||||
priority: 2,
|
||||
text: `
|
||||
@@ -3306,7 +3307,7 @@ namespace ts {
|
||||
function createMetadataHelper(context: TransformationContext, metadataKey: string, metadataValue: Expression) {
|
||||
context.requestEmitHelper(metadataHelper);
|
||||
return createCall(
|
||||
getHelperName("__metadata"),
|
||||
getUnscopedHelperName("__metadata"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(metadataKey),
|
||||
@@ -3317,6 +3318,7 @@ namespace ts {
|
||||
|
||||
export const metadataHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:metadata",
|
||||
importName: "__metadata",
|
||||
scoped: false,
|
||||
priority: 3,
|
||||
text: `
|
||||
@@ -3329,7 +3331,7 @@ namespace ts {
|
||||
context.requestEmitHelper(paramHelper);
|
||||
return setTextRange(
|
||||
createCall(
|
||||
getHelperName("__param"),
|
||||
getUnscopedHelperName("__param"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
createLiteral(parameterOffset),
|
||||
@@ -3342,6 +3344,7 @@ namespace ts {
|
||||
|
||||
export const paramHelper: UnscopedEmitHelper = {
|
||||
name: "typescript:param",
|
||||
importName: "__param",
|
||||
scoped: false,
|
||||
priority: 4,
|
||||
text: `
|
||||
|
||||
@@ -70,7 +70,8 @@ namespace ts {
|
||||
let hasExportDefault = false;
|
||||
let exportEquals: ExportAssignment | undefined;
|
||||
let hasExportStarsToExportValues = false;
|
||||
let hasImportStarOrImportDefault = false;
|
||||
let hasImportStar = false;
|
||||
let hasImportDefault = false;
|
||||
|
||||
for (const node of sourceFile.statements) {
|
||||
switch (node.kind) {
|
||||
@@ -80,7 +81,12 @@ namespace ts {
|
||||
// import * as x from "mod"
|
||||
// import { x, y } from "mod"
|
||||
externalImports.push(<ImportDeclaration>node);
|
||||
hasImportStarOrImportDefault = hasImportStarOrImportDefault || getImportNeedsImportStarHelper(<ImportDeclaration>node) || getImportNeedsImportDefaultHelper(<ImportDeclaration>node);
|
||||
if (!hasImportStar && getImportNeedsImportStarHelper(<ImportDeclaration>node)) {
|
||||
hasImportStar = true;
|
||||
}
|
||||
if (!hasImportDefault && getImportNeedsImportDefaultHelper(<ImportDeclaration>node)) {
|
||||
hasImportDefault = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
@@ -183,15 +189,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStarOrImportDefault);
|
||||
const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText));
|
||||
|
||||
const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar, hasImportDefault);
|
||||
if (externalHelpersImportDeclaration) {
|
||||
addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper);
|
||||
externalImports.unshift(externalHelpersImportDeclaration);
|
||||
}
|
||||
|
||||
|
||||
+45
-2
@@ -564,8 +564,51 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getBuildOrder(state: SolutionBuilderState) {
|
||||
return state.buildOrder ||
|
||||
(state.buildOrder = createBuildOrder(state, state.rootNames.map(f => resolveProjectName(state, f))));
|
||||
return state.buildOrder || createStateBuildOrder(state);
|
||||
}
|
||||
|
||||
function createStateBuildOrder(state: SolutionBuilderState) {
|
||||
const buildOrder = createBuildOrder(state, state.rootNames.map(f => resolveProjectName(state, f)));
|
||||
if (arrayIsEqualTo(state.buildOrder, buildOrder)) return state.buildOrder!;
|
||||
|
||||
// Clear all to ResolvedConfigFilePaths cache to start fresh
|
||||
state.resolvedConfigFilePaths.clear();
|
||||
const currentProjects = arrayToSet(
|
||||
buildOrder,
|
||||
resolved => toResolvedConfigFilePath(state, resolved)
|
||||
) as ConfigFileMap<true>;
|
||||
|
||||
const noopOnDelete = { onDeleteValue: noop };
|
||||
// Config file cache
|
||||
mutateMapSkippingNewValues(state.configFileCache, currentProjects, noopOnDelete);
|
||||
mutateMapSkippingNewValues(state.projectStatus, currentProjects, noopOnDelete);
|
||||
mutateMapSkippingNewValues(state.buildInfoChecked, currentProjects, noopOnDelete);
|
||||
mutateMapSkippingNewValues(state.builderPrograms, currentProjects, noopOnDelete);
|
||||
mutateMapSkippingNewValues(state.diagnostics, currentProjects, noopOnDelete);
|
||||
mutateMapSkippingNewValues(state.projectPendingBuild, currentProjects, noopOnDelete);
|
||||
mutateMapSkippingNewValues(state.projectErrorsReported, currentProjects, noopOnDelete);
|
||||
|
||||
// Remove watches for the program no longer in the solution
|
||||
if (state.watch) {
|
||||
mutateMapSkippingNewValues(
|
||||
state.allWatchedConfigFiles,
|
||||
currentProjects,
|
||||
{ onDeleteValue: closeFileWatcher }
|
||||
);
|
||||
|
||||
mutateMapSkippingNewValues(
|
||||
state.allWatchedWildcardDirectories,
|
||||
currentProjects,
|
||||
{ onDeleteValue: existingMap => existingMap.forEach(closeFileWatcherOf) }
|
||||
);
|
||||
|
||||
mutateMapSkippingNewValues(
|
||||
state.allWatchedInputFiles,
|
||||
currentProjects,
|
||||
{ onDeleteValue: existingMap => existingMap.forEach(closeFileWatcher) }
|
||||
);
|
||||
}
|
||||
return state.buildOrder = buildOrder;
|
||||
}
|
||||
|
||||
function getBuildOrderFor(state: SolutionBuilderState, project: string | undefined, onlyReferences: boolean | undefined) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"core.ts",
|
||||
"debug.ts",
|
||||
"performance.ts",
|
||||
"perfLogger.ts",
|
||||
"semver.ts",
|
||||
|
||||
"types.ts",
|
||||
|
||||
+34
-11
@@ -455,6 +455,8 @@ namespace ts {
|
||||
JSDocOptionalType,
|
||||
JSDocFunctionType,
|
||||
JSDocVariadicType,
|
||||
// https://jsdoc.app/about-namepaths.html
|
||||
JSDocNamepathType,
|
||||
JSDocComment,
|
||||
JSDocTypeLiteral,
|
||||
JSDocSignature,
|
||||
@@ -1677,6 +1679,8 @@ namespace ts {
|
||||
/* @internal */
|
||||
ContainsSeparator = 1 << 9, // e.g. `0b1100_0101`
|
||||
/* @internal */
|
||||
UnicodeEscape = 1 << 10,
|
||||
/* @internal */
|
||||
BinaryOrOctalSpecifier = BinarySpecifier | OctalSpecifier,
|
||||
/* @internal */
|
||||
NumericLiteralFlags = Scientific | Octal | HexSpecifier | BinaryOrOctalSpecifier | ContainsSeparator
|
||||
@@ -1862,6 +1866,12 @@ namespace ts {
|
||||
name: Identifier;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface ImportMetaProperty extends MetaProperty {
|
||||
keywordToken: SyntaxKind.ImportKeyword;
|
||||
name: Identifier & { escapedText: __String & "meta" };
|
||||
}
|
||||
|
||||
/// A JSX expression of the form <TagName attrs>...</TagName>
|
||||
export interface JsxElement extends PrimaryExpression {
|
||||
kind: SyntaxKind.JsxElement;
|
||||
@@ -2430,6 +2440,11 @@ namespace ts {
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export interface JSDocNamepathType extends JSDocType {
|
||||
kind: SyntaxKind.JSDocNamepathType;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export type JSDocTypeReferencingNode = JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
|
||||
|
||||
export interface JSDoc extends Node {
|
||||
@@ -2466,7 +2481,8 @@ namespace ts {
|
||||
kind: SyntaxKind.JSDocClassTag;
|
||||
}
|
||||
|
||||
export interface JSDocEnumTag extends JSDocTag {
|
||||
export interface JSDocEnumTag extends JSDocTag, Declaration {
|
||||
parent: JSDoc;
|
||||
kind: SyntaxKind.JSDocEnumTag;
|
||||
typeExpression?: JSDocTypeExpression;
|
||||
}
|
||||
@@ -3660,8 +3676,8 @@ namespace ts {
|
||||
|
||||
Enum = RegularEnum | ConstEnum,
|
||||
Variable = FunctionScopedVariable | BlockScopedVariable,
|
||||
Value = Variable | Property | EnumMember | ObjectLiteral | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor | Assignment,
|
||||
Type = Class | Interface | Enum | EnumMember | TypeLiteral | TypeParameter | TypeAlias | Assignment,
|
||||
Value = Variable | Property | EnumMember | ObjectLiteral | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
|
||||
Type = Class | Interface | Enum | EnumMember | TypeLiteral | TypeParameter | TypeAlias,
|
||||
Namespace = ValueModule | NamespaceModule | Enum,
|
||||
Module = ValueModule | NamespaceModule,
|
||||
Accessor = GetAccessor | SetAccessor,
|
||||
@@ -3677,12 +3693,12 @@ namespace ts {
|
||||
ParameterExcludes = Value,
|
||||
PropertyExcludes = None,
|
||||
EnumMemberExcludes = Value | Type,
|
||||
FunctionExcludes = Value & ~(Function | ValueModule),
|
||||
ClassExcludes = (Value | Type) & ~(ValueModule | Interface), // class-interface mergability done in checker.ts
|
||||
FunctionExcludes = Value & ~(Function | ValueModule | Class),
|
||||
ClassExcludes = (Value | Type) & ~(ValueModule | Interface | Function), // class-interface mergability done in checker.ts
|
||||
InterfaceExcludes = Type & ~(Interface | Class),
|
||||
RegularEnumExcludes = (Value | Type) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules
|
||||
ConstEnumExcludes = (Value | Type) & ~ConstEnum, // const enums merge only with const enums
|
||||
ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule | Assignment),
|
||||
ValueModuleExcludes = Value & ~(Function | Class | RegularEnum | ValueModule),
|
||||
NamespaceModuleExcludes = 0,
|
||||
MethodExcludes = Value & ~Method,
|
||||
GetAccessorExcludes = Value & ~SetAccessor,
|
||||
@@ -4759,8 +4775,12 @@ namespace ts {
|
||||
AMD = 2,
|
||||
UMD = 3,
|
||||
System = 4,
|
||||
|
||||
// NOTE: ES module kinds should be contiguous to more easily check whether a module kind is *any* ES module kind.
|
||||
// Non-ES module kinds should not come between ES2015 (the earliest ES module kind) and ESNext (the last ES
|
||||
// module kind).
|
||||
ES2015 = 5,
|
||||
ESNext = 6
|
||||
ESNext = 99
|
||||
}
|
||||
|
||||
export const enum JsxEmit {
|
||||
@@ -4808,7 +4828,7 @@ namespace ts {
|
||||
ES2018 = 5,
|
||||
ES2019 = 6,
|
||||
ES2020 = 7,
|
||||
ESNext = 8,
|
||||
ESNext = 99,
|
||||
JSON = 100,
|
||||
Latest = ESNext,
|
||||
}
|
||||
@@ -5172,11 +5192,11 @@ namespace ts {
|
||||
* If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just
|
||||
* 'throw new Error("NotImplemented")'
|
||||
*/
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference): (ResolvedModule | undefined)[];
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedModule | undefined)[];
|
||||
/**
|
||||
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
|
||||
*/
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
getEnvironmentVariable?(name: string): string | undefined;
|
||||
/* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean): void;
|
||||
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
|
||||
@@ -5288,6 +5308,7 @@ namespace ts {
|
||||
tokenSourceMapRanges?: (SourceMapRange | undefined)[]; // The text range to use when emitting source mappings for tokens
|
||||
constantValue?: string | number; // The constant value of an expression
|
||||
externalHelpersModuleName?: Identifier; // The local name for an imported helpers module
|
||||
externalHelpers?: boolean;
|
||||
helpers?: EmitHelper[]; // Emit helpers for the node
|
||||
startsOnNewLine?: boolean; // If the node should begin on a new line
|
||||
}
|
||||
@@ -5309,7 +5330,7 @@ namespace ts {
|
||||
NoTrailingComments = 1 << 10, // Do not emit trailing comments for this node.
|
||||
NoComments = NoLeadingComments | NoTrailingComments, // Do not emit comments for this node.
|
||||
NoNestedComments = 1 << 11,
|
||||
HelperName = 1 << 12,
|
||||
HelperName = 1 << 12, // The Identifier refers to an *unscoped* emit helper (one that is emitted at the top of the file)
|
||||
ExportName = 1 << 13, // Ensure an export prefix is added for an identifier that points to an exported declaration with a local name (see SymbolFlags.ExportHasLocal).
|
||||
LocalName = 1 << 14, // Ensure an export prefix is not added for an identifier that points to an exported declaration.
|
||||
InternalName = 1 << 15, // The name is internal to an ES5 class body function.
|
||||
@@ -5335,6 +5356,8 @@ namespace ts {
|
||||
|
||||
export interface UnscopedEmitHelper extends EmitHelper {
|
||||
readonly scoped: false; // Indicates whether the helper MUST be emitted in the current scope.
|
||||
/* @internal */
|
||||
readonly importName?: string; // The name of the helper to use when importing via `--importHelpers`.
|
||||
readonly text: string; // ES3-compatible raw script text, or a function yielding such a string
|
||||
}
|
||||
|
||||
|
||||
+91
-12
@@ -566,6 +566,8 @@ namespace ts {
|
||||
return emitNode && emitNode.flags || 0;
|
||||
}
|
||||
|
||||
const escapeNoSubstitutionTemplateLiteralText = compose(escapeString, escapeTemplateSubstitution);
|
||||
const escapeNonAsciiNoSubstitutionTemplateLiteralText = compose(escapeNonAsciiString, escapeTemplateSubstitution);
|
||||
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, neverAsciiEscape: boolean | undefined) {
|
||||
// If we don't need to downlevel and we can reach the original source text using
|
||||
// the node's parent reference, then simply get the text as it was originally written.
|
||||
@@ -576,7 +578,11 @@ namespace ts {
|
||||
return getSourceTextOfNodeFromSourceFile(sourceFile, node);
|
||||
}
|
||||
|
||||
const escapeText = neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : escapeNonAsciiString;
|
||||
// If a NoSubstitutionTemplateLiteral appears to have a substitution in it, the original text
|
||||
// had to include a backslash: `not \${a} substitution`.
|
||||
const escapeText = neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ?
|
||||
node.kind === SyntaxKind.NoSubstitutionTemplateLiteral ? escapeNoSubstitutionTemplateLiteralText : escapeString :
|
||||
node.kind === SyntaxKind.NoSubstitutionTemplateLiteral ? escapeNonAsciiNoSubstitutionTemplateLiteralText : escapeNonAsciiString;
|
||||
|
||||
// If we can't reach the original source text, use the canonical form if it's a number,
|
||||
// or a (possibly escaped) quoted form of the original text if it's string-like.
|
||||
@@ -694,6 +700,43 @@ namespace ts {
|
||||
return isExternalModule(node) || compilerOptions.isolatedModules || ((getEmitModuleKind(compilerOptions) === ModuleKind.CommonJS) && !!node.commonJsModuleIndicator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the source file will be treated as if it were in strict mode at runtime.
|
||||
*/
|
||||
export function isEffectiveStrictModeSourceFile(node: SourceFile, compilerOptions: CompilerOptions) {
|
||||
// We can only verify strict mode for JS/TS files
|
||||
switch (node.scriptKind) {
|
||||
case ScriptKind.JS:
|
||||
case ScriptKind.TS:
|
||||
case ScriptKind.JSX:
|
||||
case ScriptKind.TSX:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
// Strict mode does not matter for declaration files.
|
||||
if (node.isDeclarationFile) {
|
||||
return false;
|
||||
}
|
||||
// If `alwaysStrict` is set, then treat the file as strict.
|
||||
if (getStrictOptionValue(compilerOptions, "alwaysStrict")) {
|
||||
return true;
|
||||
}
|
||||
// Starting with a "use strict" directive indicates the file is strict.
|
||||
if (startsWithUseStrict(node.statements)) {
|
||||
return true;
|
||||
}
|
||||
if (isExternalModule(node) || compilerOptions.isolatedModules) {
|
||||
// ECMAScript Modules are always strict.
|
||||
if (getEmitModuleKind(compilerOptions) >= ModuleKind.ES2015) {
|
||||
return true;
|
||||
}
|
||||
// Other modules are strict unless otherwise specified.
|
||||
return !compilerOptions.noImplicitUseStrict;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isBlockScope(node: Node, parentNode: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
@@ -981,6 +1024,12 @@ namespace ts {
|
||||
return n.kind === SyntaxKind.CallExpression && (<CallExpression>n).expression.kind === SyntaxKind.ImportKeyword;
|
||||
}
|
||||
|
||||
export function isImportMeta(n: Node): n is ImportMetaProperty {
|
||||
return isMetaProperty(n)
|
||||
&& n.keywordToken === SyntaxKind.ImportKeyword
|
||||
&& n.name.escapedText === "meta";
|
||||
}
|
||||
|
||||
export function isLiteralImportTypeNode(n: Node): n is LiteralImportTypeNode {
|
||||
return isImportTypeNode(n) && isLiteralTypeNode(n.argument) && isStringLiteral(n.argument.literal);
|
||||
}
|
||||
@@ -2147,11 +2196,11 @@ namespace ts {
|
||||
return !!name && name.escapedText === "new";
|
||||
}
|
||||
|
||||
export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag {
|
||||
return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag;
|
||||
export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag {
|
||||
return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag || node.kind === SyntaxKind.JSDocEnumTag;
|
||||
}
|
||||
|
||||
export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | TypeAliasDeclaration {
|
||||
export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | TypeAliasDeclaration {
|
||||
return isJSDocTypeAlias(node) || isTypeAliasDeclaration(node);
|
||||
}
|
||||
|
||||
@@ -2633,6 +2682,10 @@ namespace ts {
|
||||
return isKeyword(token) && !isContextualKeyword(token);
|
||||
}
|
||||
|
||||
export function isFutureReservedKeyword(token: SyntaxKind): boolean {
|
||||
return SyntaxKind.FirstFutureReservedWord <= token && token <= SyntaxKind.LastFutureReservedWord;
|
||||
}
|
||||
|
||||
export function isStringANonContextualKeyword(name: string) {
|
||||
const token = stringToToken(name);
|
||||
return token !== undefined && isNonContextualKeyword(token);
|
||||
@@ -3113,6 +3166,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const templateSubstitutionRegExp = /\$\{/g;
|
||||
function escapeTemplateSubstitution(str: string): string {
|
||||
return str.replace(templateSubstitutionRegExp, "\\${");
|
||||
}
|
||||
|
||||
// This consists of the first 19 unprintable ASCII characters, canonical escapes, lineSeparator,
|
||||
// paragraphSeparator, and nextLine. The latter three are just desirable to suppress new lines in
|
||||
// the language service. These characters should be escaped when printing, and if any characters are added,
|
||||
@@ -3507,7 +3565,7 @@ namespace ts {
|
||||
return find(node.members, (member): member is ConstructorDeclaration & { body: FunctionBody } => isConstructorDeclaration(member) && nodeIsPresent(member.body));
|
||||
}
|
||||
|
||||
function getSetAccessorValueParameter(accessor: SetAccessorDeclaration): ParameterDeclaration | undefined {
|
||||
export function getSetAccessorValueParameter(accessor: SetAccessorDeclaration): ParameterDeclaration | undefined {
|
||||
if (accessor && accessor.parameters.length > 0) {
|
||||
const hasThis = accessor.parameters.length === 2 && parameterIsThisKeyword(accessor.parameters[0]);
|
||||
return accessor.parameters[hasThis ? 1 : 0];
|
||||
@@ -3542,7 +3600,7 @@ namespace ts {
|
||||
return id.originalKeywordKind === SyntaxKind.ThisKeyword;
|
||||
}
|
||||
|
||||
export function getAllAccessorDeclarations(declarations: NodeArray<Declaration>, accessor: AccessorDeclaration): AllAccessorDeclarations {
|
||||
export function getAllAccessorDeclarations(declarations: readonly Declaration[], accessor: AccessorDeclaration): AllAccessorDeclarations {
|
||||
// TODO: GH#18217
|
||||
let firstAccessor!: AccessorDeclaration;
|
||||
let secondAccessor!: AccessorDeclaration;
|
||||
@@ -4466,8 +4524,7 @@ namespace ts {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
export interface MutateMapOptions<T, U> {
|
||||
createNewValue(key: string, valueInNewMap: U): T;
|
||||
export interface MutateMapSkippingNewValuesOptions<T, U> {
|
||||
onDeleteValue(existingValue: T, key: string): void;
|
||||
|
||||
/**
|
||||
@@ -4482,8 +4539,12 @@ namespace ts {
|
||||
/**
|
||||
* Mutates the map with newMap such that keys in map will be same as newMap.
|
||||
*/
|
||||
export function mutateMap<T, U>(map: Map<T>, newMap: ReadonlyMap<U>, options: MutateMapOptions<T, U>) {
|
||||
const { createNewValue, onDeleteValue, onExistingValue } = options;
|
||||
export function mutateMapSkippingNewValues<T, U>(
|
||||
map: Map<T>,
|
||||
newMap: ReadonlyMap<U>,
|
||||
options: MutateMapSkippingNewValuesOptions<T, U>
|
||||
) {
|
||||
const { onDeleteValue, onExistingValue } = options;
|
||||
// Needs update
|
||||
map.forEach((existingValue, key) => {
|
||||
const valueInNewMap = newMap.get(key);
|
||||
@@ -4497,7 +4558,20 @@ namespace ts {
|
||||
onExistingValue(existingValue, valueInNewMap, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export interface MutateMapOptions<T, U> extends MutateMapSkippingNewValuesOptions<T, U> {
|
||||
createNewValue(key: string, valueInNewMap: U): T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutates the map with newMap such that keys in map will be same as newMap.
|
||||
*/
|
||||
export function mutateMap<T, U>(map: Map<T>, newMap: ReadonlyMap<U>, options: MutateMapOptions<T, U>) {
|
||||
// Needs update
|
||||
mutateMapSkippingNewValues(map, newMap, options);
|
||||
|
||||
const { createNewValue } = options;
|
||||
// Add new values that are not already present
|
||||
newMap.forEach((valueInNewMap, key) => {
|
||||
if (!map.has(key)) {
|
||||
@@ -5091,7 +5165,7 @@ namespace ts {
|
||||
* attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol
|
||||
* will be merged with)
|
||||
*/
|
||||
function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined {
|
||||
function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag | JSDocEnumTag): Identifier | undefined {
|
||||
const hostNode = declaration.parent.parent;
|
||||
if (!hostNode) {
|
||||
return undefined;
|
||||
@@ -5108,7 +5182,10 @@ namespace ts {
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
const expr = hostNode.expression;
|
||||
let expr = hostNode.expression;
|
||||
if (expr.kind === SyntaxKind.BinaryExpression && (expr as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
expr = (expr as BinaryExpression).left;
|
||||
}
|
||||
switch (expr.kind) {
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return (expr as PropertyAccessExpression).name;
|
||||
@@ -5177,6 +5254,8 @@ namespace ts {
|
||||
}
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return getNameOfJSDocTypedef(declaration as JSDocTypedefTag);
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
return nameForNamelessJSDocTypedef(declaration as JSDocEnumTag);
|
||||
case SyntaxKind.ExportAssignment: {
|
||||
const { expression } = declaration as ExportAssignment;
|
||||
return isIdentifier(expression) ? expression : undefined;
|
||||
|
||||
+13
-7
@@ -538,9 +538,9 @@ namespace ts {
|
||||
getEnvironmentVariable?(name: string): string | undefined;
|
||||
|
||||
/** If provided, used to resolve the module names, otherwise typescript's default module resolution */
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference): (ResolvedModule | undefined)[];
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedModule | undefined)[];
|
||||
/** If provided, used to resolve type reference directives, otherwise typescript's default resolution */
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
}
|
||||
/** Internal interface used to wire emit through same host */
|
||||
|
||||
@@ -744,10 +744,10 @@ namespace ts {
|
||||
);
|
||||
// Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names
|
||||
compilerHost.resolveModuleNames = host.resolveModuleNames ?
|
||||
((moduleNames, containingFile, reusedNames, redirectedReference) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames, redirectedReference)) :
|
||||
((...args) => host.resolveModuleNames!(...args)) :
|
||||
((moduleNames, containingFile, reusedNames, redirectedReference) => resolutionCache.resolveModuleNames(moduleNames, containingFile, reusedNames, redirectedReference));
|
||||
compilerHost.resolveTypeReferenceDirectives = host.resolveTypeReferenceDirectives ?
|
||||
((typeDirectiveNames, containingFile, redirectedReference) => host.resolveTypeReferenceDirectives!(typeDirectiveNames, containingFile, redirectedReference)) :
|
||||
((...args) => host.resolveTypeReferenceDirectives!(...args)) :
|
||||
((typeDirectiveNames, containingFile, redirectedReference) => resolutionCache.resolveTypeReferenceDirectives(typeDirectiveNames, containingFile, redirectedReference));
|
||||
const userProvidedResolution = !!host.resolveModuleNames || !!host.resolveTypeReferenceDirectives;
|
||||
|
||||
@@ -1005,13 +1005,19 @@ namespace ts {
|
||||
|
||||
switch (reloadLevel) {
|
||||
case ConfigFileProgramReloadLevel.Partial:
|
||||
return reloadFileNamesFromConfigFile();
|
||||
perfLogger.logStartUpdateProgram("PartialConfigReload");
|
||||
reloadFileNamesFromConfigFile();
|
||||
break;
|
||||
case ConfigFileProgramReloadLevel.Full:
|
||||
return reloadConfigFile();
|
||||
perfLogger.logStartUpdateProgram("FullConfigReload");
|
||||
reloadConfigFile();
|
||||
break;
|
||||
default:
|
||||
perfLogger.logStartUpdateProgram("SynchronizeProgram");
|
||||
synchronizeProgram();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
perfLogger.logStopUpdateProgram("Done");
|
||||
}
|
||||
|
||||
function reloadFileNamesFromConfigFile() {
|
||||
|
||||
@@ -370,6 +370,9 @@ namespace ts {
|
||||
const createFileWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, never, X, Y> = getCreateFileWatcher(watchLogLevel, watchFile);
|
||||
const createFilePathWatcher: CreateFileWatcher<WatchFileHost, PollingInterval, FileWatcherEventKind, Path, X, Y> = watchLogLevel === WatchLogLevel.None ? watchFilePath : createFileWatcher;
|
||||
const createDirectoryWatcher: CreateFileWatcher<WatchDirectoryHost, WatchDirectoryFlags, undefined, never, X, Y> = getCreateFileWatcher(watchLogLevel, watchDirectory);
|
||||
if (watchLogLevel === WatchLogLevel.Verbose && sysLog === noop) {
|
||||
sysLog = s => log(s);
|
||||
}
|
||||
return {
|
||||
watchFile: (host, file, callback, pollingInterval, detailInfo1, detailInfo2) =>
|
||||
createFileWatcher(host, file, callback, pollingInterval, /*passThrough*/ undefined, detailInfo1, detailInfo2, watchFile, log, "FileWatcher", getDetailWatchInfo),
|
||||
|
||||
+29
-64
@@ -344,7 +344,8 @@ namespace FourSlash {
|
||||
"getDocumentHighlights",
|
||||
];
|
||||
const proxy = {} as ts.LanguageService;
|
||||
for (const k in ls) {
|
||||
const keys = ts.getAllKeys(ls);
|
||||
for (const k of keys) {
|
||||
const key = k as keyof typeof ls;
|
||||
if (cacheableMembers.indexOf(key) === -1) {
|
||||
proxy[key] = (...args: any[]) => (ls[key] as Function)(...args);
|
||||
@@ -797,7 +798,7 @@ namespace FourSlash {
|
||||
for (const include of toArray(options.includes)) {
|
||||
const name = typeof include === "string" ? include : include.name;
|
||||
const found = nameToEntries.get(name);
|
||||
if (!found) throw this.raiseError(`No completion ${name} found`);
|
||||
if (!found) throw this.raiseError(`Includes: completion '${name}' not found.`);
|
||||
assert(found.length === 1); // Must use 'exact' for multiple completions with same name
|
||||
this.verifyCompletionEntry(ts.first(found), include);
|
||||
}
|
||||
@@ -806,7 +807,7 @@ namespace FourSlash {
|
||||
for (const exclude of toArray(options.excludes)) {
|
||||
assert(typeof exclude === "string");
|
||||
if (nameToEntries.has(exclude)) {
|
||||
this.raiseError(`Did not expect to get a completion named ${exclude}`);
|
||||
this.raiseError(`Excludes: unexpected completion '${exclude}' found.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -948,7 +949,7 @@ namespace FourSlash {
|
||||
|
||||
const actual = checker.typeToString(type);
|
||||
if (actual !== expected) {
|
||||
this.raiseError(`Expected: '${expected}', actual: '${actual}'`);
|
||||
this.raiseError(displayExpectedAndActualString(expected, actual));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,9 +1025,7 @@ namespace FourSlash {
|
||||
private assertObjectsEqual<T>(fullActual: T, fullExpected: T, msgPrefix = ""): void {
|
||||
const recur = <U>(actual: U, expected: U, path: string) => {
|
||||
const fail = (msg: string) => {
|
||||
this.raiseError(`${msgPrefix} At ${path}: ${msg}
|
||||
Expected: ${stringify(fullExpected)}
|
||||
Actual: ${stringify(fullActual)}`);
|
||||
this.raiseError(`${msgPrefix} At ${path}: ${msg} ${displayExpectedAndActualString(stringify(fullExpected), stringify(fullActual))}`);
|
||||
};
|
||||
|
||||
if ((actual === undefined) !== (expected === undefined)) {
|
||||
@@ -1058,9 +1057,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
if (fullActual === fullExpected) {
|
||||
return;
|
||||
}
|
||||
this.raiseError(`${msgPrefix}
|
||||
Expected: ${stringify(fullExpected)}
|
||||
Actual: ${stringify(fullActual)}`);
|
||||
this.raiseError(`${msgPrefix} ${displayExpectedAndActualString(stringify(fullExpected), stringify(fullActual))}`);
|
||||
}
|
||||
recur(fullActual, fullExpected, "");
|
||||
|
||||
@@ -1272,6 +1269,10 @@ Actual: ${stringify(fullActual)}`);
|
||||
|
||||
private verifySignatureHelpWorker(options: FourSlashInterface.VerifySignatureHelpOptions) {
|
||||
const help = this.getSignatureHelp({ triggerReason: options.triggerReason })!;
|
||||
if (!help) {
|
||||
this.raiseError("Could not get a help signature");
|
||||
}
|
||||
|
||||
const selectedItem = help.items[help.selectedItemIndex];
|
||||
// Argument index may exceed number of parameters
|
||||
const currentParameter = selectedItem.parameters[help.argumentIndex] as ts.SignatureHelpParameter | undefined;
|
||||
@@ -2111,9 +2112,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
public verifyCurrentLineContent(text: string) {
|
||||
const actual = this.getCurrentLineContent();
|
||||
if (actual !== text) {
|
||||
throw new Error("verifyCurrentLineContent\n" +
|
||||
"\tExpected: \"" + text + "\"\n" +
|
||||
"\t Actual: \"" + actual + "\"");
|
||||
throw new Error("verifyCurrentLineContent\n" + displayExpectedAndActualString(text, actual, /* quoted */ true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2139,25 +2138,19 @@ Actual: ${stringify(fullActual)}`);
|
||||
public verifyTextAtCaretIs(text: string) {
|
||||
const actual = this.getFileContent(this.activeFile.fileName).substring(this.currentCaretPosition, this.currentCaretPosition + text.length);
|
||||
if (actual !== text) {
|
||||
throw new Error("verifyTextAtCaretIs\n" +
|
||||
"\tExpected: \"" + text + "\"\n" +
|
||||
"\t Actual: \"" + actual + "\"");
|
||||
throw new Error("verifyTextAtCaretIs\n" + displayExpectedAndActualString(text, actual, /* quoted */ true));
|
||||
}
|
||||
}
|
||||
|
||||
public verifyCurrentNameOrDottedNameSpanText(text: string) {
|
||||
const span = this.languageService.getNameOrDottedNameSpan(this.activeFile.fileName, this.currentCaretPosition, this.currentCaretPosition);
|
||||
if (!span) {
|
||||
return this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" +
|
||||
"\tExpected: \"" + text + "\"\n" +
|
||||
"\t Actual: undefined");
|
||||
return this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" + displayExpectedAndActualString("\"" + text + "\"", "undefined"));
|
||||
}
|
||||
|
||||
const actual = this.getFileContent(this.activeFile.fileName).substring(span.start, ts.textSpanEnd(span));
|
||||
if (actual !== text) {
|
||||
this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" +
|
||||
"\tExpected: \"" + text + "\"\n" +
|
||||
"\t Actual: \"" + actual + "\"");
|
||||
this.raiseError("verifyCurrentNameOrDottedNameSpanText\n" + displayExpectedAndActualString(text, actual, /* quoted */ true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2333,7 +2326,10 @@ Actual: ${stringify(fullActual)}`);
|
||||
public applyCodeActionFromCompletion(markerName: string, options: FourSlashInterface.VerifyCompletionActionOptions) {
|
||||
this.goToMarker(markerName);
|
||||
|
||||
const details = this.getCompletionEntryDetails(options.name, options.source, options.preferences)!;
|
||||
const details = this.getCompletionEntryDetails(options.name, options.source, options.preferences);
|
||||
if (!details) {
|
||||
return this.raiseError(`No completions were found for the given name, source, and preferences.`);
|
||||
}
|
||||
const codeActions = details.codeActions!;
|
||||
if (codeActions.length !== 1) {
|
||||
this.raiseError(`Expected one code action, got ${codeActions.length}`);
|
||||
@@ -2442,7 +2438,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
const oldText = this.tryGetFileContent(change.fileName);
|
||||
ts.Debug.assert(!!change.isNewFile === (oldText === undefined));
|
||||
const newContent = change.isNewFile ? ts.first(change.textChanges).newText : ts.textChanges.applyChanges(oldText!, change.textChanges);
|
||||
assert.equal(newContent, expectedNewContent);
|
||||
assert.equal(newContent, expectedNewContent, `String mis-matched in file ${change.fileName}`);
|
||||
}
|
||||
for (const newFileName in newFileContent) {
|
||||
ts.Debug.assert(changes.some(c => c.fileName === newFileName), "No change in file", () => newFileName);
|
||||
@@ -3690,7 +3686,7 @@ ${code}
|
||||
expected = makeWhitespaceVisible(expected);
|
||||
actual = makeWhitespaceVisible(actual);
|
||||
}
|
||||
return `Expected:\n${expected}\nActual:\n${actual}`;
|
||||
return displayExpectedAndActualString(expected, actual);
|
||||
}
|
||||
|
||||
function differOnlyByWhitespace(a: string, b: string) {
|
||||
@@ -3710,6 +3706,14 @@ ${code}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function displayExpectedAndActualString(expected: string, actual: string, quoted = false) {
|
||||
const expectMsg = "\x1b[1mExpected\x1b[0m\x1b[31m";
|
||||
const actualMsg = "\x1b[1mActual\x1b[0m\x1b[31m";
|
||||
const expectedString = quoted ? "\"" + expected + "\"" : expected;
|
||||
const actualString = quoted ? "\"" + actual + "\"" : actual;
|
||||
return `\n${expectMsg}:\n${expectedString}\n\n${actualMsg}:\n${actualString}`;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FourSlashInterface {
|
||||
@@ -4831,40 +4835,23 @@ namespace FourSlashInterface {
|
||||
"interface",
|
||||
"let",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"static",
|
||||
"yield",
|
||||
"abstract",
|
||||
"as",
|
||||
"any",
|
||||
"async",
|
||||
"await",
|
||||
"boolean",
|
||||
"constructor",
|
||||
"declare",
|
||||
"get",
|
||||
"infer",
|
||||
"is",
|
||||
"keyof",
|
||||
"module",
|
||||
"namespace",
|
||||
"never",
|
||||
"readonly",
|
||||
"require",
|
||||
"number",
|
||||
"object",
|
||||
"set",
|
||||
"string",
|
||||
"symbol",
|
||||
"type",
|
||||
"unique",
|
||||
"unknown",
|
||||
"from",
|
||||
"global",
|
||||
"bigint",
|
||||
"of",
|
||||
].map(keywordEntry);
|
||||
|
||||
export const statementKeywords: ReadonlyArray<ExpectedCompletionEntryObject> = statementKeywordsWithTypes.filter(k => {
|
||||
@@ -5045,40 +5032,23 @@ namespace FourSlashInterface {
|
||||
"interface",
|
||||
"let",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"static",
|
||||
"yield",
|
||||
"abstract",
|
||||
"as",
|
||||
"any",
|
||||
"async",
|
||||
"await",
|
||||
"boolean",
|
||||
"constructor",
|
||||
"declare",
|
||||
"get",
|
||||
"infer",
|
||||
"is",
|
||||
"keyof",
|
||||
"module",
|
||||
"namespace",
|
||||
"never",
|
||||
"readonly",
|
||||
"require",
|
||||
"number",
|
||||
"object",
|
||||
"set",
|
||||
"string",
|
||||
"symbol",
|
||||
"type",
|
||||
"unique",
|
||||
"unknown",
|
||||
"from",
|
||||
"global",
|
||||
"bigint",
|
||||
"of",
|
||||
].map(keywordEntry);
|
||||
|
||||
export const globalInJsKeywords = getInJsKeywords(globalKeywords);
|
||||
@@ -5131,11 +5101,6 @@ namespace FourSlashInterface {
|
||||
|
||||
export const insideMethodInJsKeywords = getInJsKeywords(insideMethodKeywords);
|
||||
|
||||
export const globalKeywordsPlusUndefined: ReadonlyArray<ExpectedCompletionEntryObject> = (() => {
|
||||
const i = ts.findIndex(globalKeywords, x => x.name === "unique");
|
||||
return [...globalKeywords.slice(0, i), keywordEntry("undefined"), ...globalKeywords.slice(i)];
|
||||
})();
|
||||
|
||||
export const globals: ReadonlyArray<ExpectedCompletionEntryObject> = [
|
||||
globalThisEntry,
|
||||
...globalsVars,
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Utils {
|
||||
|
||||
export function byteLength(s: string, encoding?: string): number {
|
||||
// stub implementation if Buffer is not available (in-browser case)
|
||||
return Buffer.byteLength(s, encoding);
|
||||
return Buffer.byteLength(s, encoding as ts.BufferEncoding | undefined);
|
||||
}
|
||||
|
||||
export function evalFile(fileContents: string, fileName: string, nodeContext?: any) {
|
||||
@@ -726,6 +726,7 @@ namespace Harness {
|
||||
includeBuiltFile?: string;
|
||||
baselineFile?: string;
|
||||
libFiles?: string;
|
||||
noTypesAndSymbols?: boolean;
|
||||
}
|
||||
|
||||
// Additional options not already in ts.optionDeclarations
|
||||
@@ -742,6 +743,7 @@ namespace Harness {
|
||||
{ name: "currentDirectory", type: "string" },
|
||||
{ name: "symlink", type: "string" },
|
||||
{ name: "link", type: "string" },
|
||||
{ name: "noTypesAndSymbols", type: "boolean" },
|
||||
// Emitted js baseline will print full paths for every output file
|
||||
{ name: "fullEmitPaths", type: "boolean" }
|
||||
];
|
||||
|
||||
@@ -97,7 +97,7 @@ class TypeWriterWalker {
|
||||
if (!isSymbolWalk) {
|
||||
// Don't try to get the type of something that's already a type.
|
||||
// Exception for `T` in `type T = something` because that may evaluate to some interesting type.
|
||||
if (ts.isPartOfTypeNode(node) || ts.isIdentifier(node) && !(ts.getMeaningFromDeclaration(node.parent) & ts.SemanticMeaning.Value) && !(ts.isTypeAlias(node.parent) && node.parent.name === node)) {
|
||||
if (ts.isPartOfTypeNode(node) || ts.isIdentifier(node) && !(ts.getMeaningFromDeclaration(node.parent) & ts.SemanticMeaning.Value) && !(ts.isTypeAliasDeclaration(node.parent) && node.parent.name === node)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
+24
-2
@@ -1525,8 +1525,11 @@ namespace vfs {
|
||||
return typeof value === "string" || Buffer.isBuffer(value) ? new File(value) : new Directory(value);
|
||||
}
|
||||
|
||||
export function formatPatch(patch: FileSet) {
|
||||
return formatPatchWorker("", patch);
|
||||
export function formatPatch(patch: FileSet): string;
|
||||
export function formatPatch(patch: FileSet | undefined): string | null;
|
||||
export function formatPatch(patch: FileSet | undefined) {
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
return patch ? formatPatchWorker("", patch) : null;
|
||||
}
|
||||
|
||||
function formatPatchWorker(dirname: string, container: FileSet): string {
|
||||
@@ -1559,5 +1562,24 @@ namespace vfs {
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
export function iteratePatch(patch: FileSet | undefined): IterableIterator<[string, string]> | null {
|
||||
// tslint:disable-next-line:no-null-keyword
|
||||
return patch ? Harness.Compiler.iterateOutputs(iteratePatchWorker("", patch)) : null;
|
||||
}
|
||||
|
||||
function* iteratePatchWorker(dirname: string, container: FileSet): IterableIterator<documents.TextDocument> {
|
||||
for (const name of Object.keys(container)) {
|
||||
const entry = normalizeFileSetEntry(container[name]);
|
||||
const file = dirname ? vpath.combine(dirname, name) : name;
|
||||
if (entry instanceof Directory) {
|
||||
yield* ts.arrayFrom(iteratePatchWorker(file, entry.files));
|
||||
}
|
||||
else if (entry instanceof File) {
|
||||
const content = typeof entry.data === "string" ? entry.data : entry.data.toString("utf8");
|
||||
yield new documents.TextDocument(file, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// tslint:enable:no-null-keyword
|
||||
@@ -314,6 +314,11 @@ interface Array<T> {}`
|
||||
invokeFileDeleteCreateAsPartInsteadOfChange: boolean;
|
||||
}
|
||||
|
||||
export enum Tsc_WatchFile {
|
||||
DynamicPolling = "DynamicPriorityPolling",
|
||||
SingleFileWatcherPerName = "SingleFileWatcherPerName"
|
||||
}
|
||||
|
||||
export enum Tsc_WatchDirectory {
|
||||
WatchFile = "RecursiveDirectoryUsingFsWatchFile",
|
||||
NonRecursiveWatchDirectory = "RecursiveDirectoryUsingNonRecursiveWatchDirectory",
|
||||
@@ -339,7 +344,7 @@ interface Array<T> {}`
|
||||
readonly watchedFiles = createMultiMap<TestFileWatcher>();
|
||||
private readonly executingFilePath: string;
|
||||
private readonly currentDirectory: string;
|
||||
private readonly dynamicPriorityWatchFile: HostWatchFile | undefined;
|
||||
private readonly customWatchFile: HostWatchFile | undefined;
|
||||
private readonly customRecursiveWatchDirectory: HostWatchDirectory | undefined;
|
||||
public require: ((initialPath: string, moduleName: string) => server.RequireResult) | undefined;
|
||||
|
||||
@@ -349,9 +354,23 @@ interface Array<T> {}`
|
||||
this.executingFilePath = this.getHostSpecificPath(executingFilePath);
|
||||
this.currentDirectory = this.getHostSpecificPath(currentDirectory);
|
||||
this.reloadFS(fileOrFolderorSymLinkList);
|
||||
this.dynamicPriorityWatchFile = this.environmentVariables && this.environmentVariables.get("TSC_WATCHFILE") === "DynamicPriorityPolling" ?
|
||||
createDynamicPriorityPollingWatchFile(this) :
|
||||
undefined;
|
||||
const tscWatchFile = this.environmentVariables && this.environmentVariables.get("TSC_WATCHFILE") as Tsc_WatchFile;
|
||||
switch (tscWatchFile) {
|
||||
case Tsc_WatchFile.DynamicPolling:
|
||||
this.customWatchFile = createDynamicPriorityPollingWatchFile(this);
|
||||
break;
|
||||
case Tsc_WatchFile.SingleFileWatcherPerName:
|
||||
this.customWatchFile = createSingleFileWatcherPerName(
|
||||
this.watchFileWorker.bind(this),
|
||||
this.useCaseSensitiveFileNames
|
||||
);
|
||||
break;
|
||||
case undefined:
|
||||
break;
|
||||
default:
|
||||
Debug.assertNever(tscWatchFile);
|
||||
}
|
||||
|
||||
const tscWatchDirectory = this.environmentVariables && this.environmentVariables.get("TSC_WATCHDIRECTORY") as Tsc_WatchDirectory;
|
||||
if (tscWatchDirectory === Tsc_WatchDirectory.WatchFile) {
|
||||
const watchDirectory: HostWatchDirectory = (directory, cb) => this.watchFile(directory, () => cb(directory), PollingInterval.Medium);
|
||||
@@ -405,7 +424,7 @@ interface Array<T> {}`
|
||||
return s;
|
||||
}
|
||||
|
||||
private now() {
|
||||
now() {
|
||||
this.time += timeIncrements;
|
||||
return new Date(this.time);
|
||||
}
|
||||
@@ -854,10 +873,14 @@ interface Array<T> {}`
|
||||
}
|
||||
|
||||
watchFile(fileName: string, cb: FileWatcherCallback, pollingInterval: number) {
|
||||
if (this.dynamicPriorityWatchFile) {
|
||||
return this.dynamicPriorityWatchFile(fileName, cb, pollingInterval);
|
||||
if (this.customWatchFile) {
|
||||
return this.customWatchFile(fileName, cb, pollingInterval);
|
||||
}
|
||||
|
||||
return this.watchFileWorker(fileName, cb);
|
||||
}
|
||||
|
||||
private watchFileWorker(fileName: string, cb: FileWatcherCallback) {
|
||||
const path = this.toFullPath(fileName);
|
||||
const callback: TestFileWatcher = { fileName, cb };
|
||||
this.watchedFiles.add(path, callback);
|
||||
|
||||
+51
-24
@@ -289,9 +289,8 @@ namespace ts.JsTyping {
|
||||
|
||||
}
|
||||
|
||||
export const enum PackageNameValidationResult {
|
||||
export const enum NameValidationResult {
|
||||
Ok,
|
||||
ScopedPackagesNotSupported,
|
||||
EmptyName,
|
||||
NameTooLong,
|
||||
NameStartsWithDot,
|
||||
@@ -301,49 +300,77 @@ namespace ts.JsTyping {
|
||||
|
||||
const maxPackageNameLength = 214;
|
||||
|
||||
export interface ScopedPackageNameValidationResult {
|
||||
name: string;
|
||||
isScopeName: boolean;
|
||||
result: NameValidationResult;
|
||||
}
|
||||
export type PackageNameValidationResult = NameValidationResult | ScopedPackageNameValidationResult;
|
||||
|
||||
/**
|
||||
* Validates package name using rules defined at https://docs.npmjs.com/files/package.json
|
||||
*/
|
||||
export function validatePackageName(packageName: string): PackageNameValidationResult {
|
||||
return validatePackageNameWorker(packageName, /*supportScopedPackage*/ true);
|
||||
}
|
||||
|
||||
function validatePackageNameWorker(packageName: string, supportScopedPackage: false): NameValidationResult;
|
||||
function validatePackageNameWorker(packageName: string, supportScopedPackage: true): PackageNameValidationResult;
|
||||
function validatePackageNameWorker(packageName: string, supportScopedPackage: boolean): PackageNameValidationResult {
|
||||
if (!packageName) {
|
||||
return PackageNameValidationResult.EmptyName;
|
||||
return NameValidationResult.EmptyName;
|
||||
}
|
||||
if (packageName.length > maxPackageNameLength) {
|
||||
return PackageNameValidationResult.NameTooLong;
|
||||
return NameValidationResult.NameTooLong;
|
||||
}
|
||||
if (packageName.charCodeAt(0) === CharacterCodes.dot) {
|
||||
return PackageNameValidationResult.NameStartsWithDot;
|
||||
return NameValidationResult.NameStartsWithDot;
|
||||
}
|
||||
if (packageName.charCodeAt(0) === CharacterCodes._) {
|
||||
return PackageNameValidationResult.NameStartsWithUnderscore;
|
||||
return NameValidationResult.NameStartsWithUnderscore;
|
||||
}
|
||||
// check if name is scope package like: starts with @ and has one '/' in the middle
|
||||
// scoped packages are not currently supported
|
||||
// TODO: when support will be added we'll need to split and check both scope and package name
|
||||
if (/^@[^/]+\/[^/]+$/.test(packageName)) {
|
||||
return PackageNameValidationResult.ScopedPackagesNotSupported;
|
||||
if (supportScopedPackage) {
|
||||
const matches = /^@([^/]+)\/([^/]+)$/.exec(packageName);
|
||||
if (matches) {
|
||||
const scopeResult = validatePackageNameWorker(matches[1], /*supportScopedPackage*/ false);
|
||||
if (scopeResult !== NameValidationResult.Ok) {
|
||||
return { name: matches[1], isScopeName: true, result: scopeResult };
|
||||
}
|
||||
const packageResult = validatePackageNameWorker(matches[2], /*supportScopedPackage*/ false);
|
||||
if (packageResult !== NameValidationResult.Ok) {
|
||||
return { name: matches[2], isScopeName: false, result: packageResult };
|
||||
}
|
||||
return NameValidationResult.Ok;
|
||||
}
|
||||
}
|
||||
if (encodeURIComponent(packageName) !== packageName) {
|
||||
return PackageNameValidationResult.NameContainsNonURISafeCharacters;
|
||||
return NameValidationResult.NameContainsNonURISafeCharacters;
|
||||
}
|
||||
return PackageNameValidationResult.Ok;
|
||||
return NameValidationResult.Ok;
|
||||
}
|
||||
|
||||
export function renderPackageNameValidationFailure(result: PackageNameValidationResult, typing: string): string {
|
||||
return typeof result === "object" ?
|
||||
renderPackageNameValidationFailureWorker(typing, result.result, result.name, result.isScopeName) :
|
||||
renderPackageNameValidationFailureWorker(typing, result, typing, /*isScopeName*/ false);
|
||||
}
|
||||
|
||||
function renderPackageNameValidationFailureWorker(typing: string, result: NameValidationResult, name: string, isScopeName: boolean): string {
|
||||
const kind = isScopeName ? "Scope" : "Package";
|
||||
switch (result) {
|
||||
case PackageNameValidationResult.EmptyName:
|
||||
return `Package name '${typing}' cannot be empty`;
|
||||
case PackageNameValidationResult.NameTooLong:
|
||||
return `Package name '${typing}' should be less than ${maxPackageNameLength} characters`;
|
||||
case PackageNameValidationResult.NameStartsWithDot:
|
||||
return `Package name '${typing}' cannot start with '.'`;
|
||||
case PackageNameValidationResult.NameStartsWithUnderscore:
|
||||
return `Package name '${typing}' cannot start with '_'`;
|
||||
case PackageNameValidationResult.ScopedPackagesNotSupported:
|
||||
return `Package '${typing}' is scoped and currently is not supported`;
|
||||
case PackageNameValidationResult.NameContainsNonURISafeCharacters:
|
||||
return `Package name '${typing}' contains non URI safe characters`;
|
||||
case PackageNameValidationResult.Ok:
|
||||
case NameValidationResult.EmptyName:
|
||||
return `'${typing}':: ${kind} name '${name}' cannot be empty`;
|
||||
case NameValidationResult.NameTooLong:
|
||||
return `'${typing}':: ${kind} name '${name}' should be less than ${maxPackageNameLength} characters`;
|
||||
case NameValidationResult.NameStartsWithDot:
|
||||
return `'${typing}':: ${kind} name '${name}' cannot start with '.'`;
|
||||
case NameValidationResult.NameStartsWithUnderscore:
|
||||
return `'${typing}':: ${kind} name '${name}' cannot start with '_'`;
|
||||
case NameValidationResult.NameContainsNonURISafeCharacters:
|
||||
return `'${typing}':: ${kind} name '${name}' contains non URI safe characters`;
|
||||
case NameValidationResult.Ok:
|
||||
return Debug.fail(); // Shouldn't have called this.
|
||||
default:
|
||||
throw Debug.assertNever(result);
|
||||
|
||||
Vendored
+1
-1
@@ -12,7 +12,7 @@ declare var Infinity: number;
|
||||
declare function eval(x: string): any;
|
||||
|
||||
/**
|
||||
* Converts A string to an integer.
|
||||
* Converts a string to an integer.
|
||||
* @param s A string to convert into a number.
|
||||
* @param radix A value between 2 and 36 that specifies the base of the number in numString.
|
||||
* If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LCX SchemaVersion="6.0" Name="f:\ddSetup\sources\typescript\localization\compiler2.resx" PsrId="306" FileType="1" SrcCul="en-US" TgtCul="it-IT" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
|
||||
<Props>
|
||||
<Str Name="CustomName1" Val="Custom 1" />
|
||||
@@ -3301,7 +3301,7 @@
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Crea l'origine unitamente alle mappe di origine all'interno di un unico file. Richiede l'impostazione di '--inlineSourceMap' o '--sourceMap'.]]></Val>
|
||||
<Val><![CDATA[Crea l'origine unitamente ai mapping di origine all'interno di un unico file. Richiede l'impostazione di '--inlineSourceMap' o '--sourceMap'.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
@@ -4123,7 +4123,7 @@
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Generates a sourcemap for each corresponding '.d.ts' file.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Genera un sourcemap per ogni file '.d.ts' corrispondente.]]></Val>
|
||||
<Val><![CDATA[Genera un mapping di origine per ogni file '.d.ts' corrispondente.]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LCX SchemaVersion="6.0" Name="f:\ddSetup\sources\typescript\localization\compiler2.resx" PsrId="306" FileType="1" SrcCul="en-US" TgtCul="ru-RU" xmlns="http://schemas.microsoft.com/locstudio/2006/6/lcx">
|
||||
<Props>
|
||||
<Str Name="CustomName1" Val="Custom 1" />
|
||||
@@ -3300,7 +3300,7 @@
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Порождать источник вместе с sourcemap в одном файле (нужно задать параметр --inlineSourceMap или --sourceMap).]]></Val>
|
||||
<Val><![CDATA[Порождать источник вместе с сопоставителями с исходным кодом в одном файле (нужно задать параметр --inlineSourceMap или --sourceMap).]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
@@ -4122,7 +4122,7 @@
|
||||
<Str Cat="Text">
|
||||
<Val><![CDATA[Generates a sourcemap for each corresponding '.d.ts' file.]]></Val>
|
||||
<Tgt Cat="Text" Stat="Loc" Orig="New">
|
||||
<Val><![CDATA[Создает sourcemap для каждого соответствующего файла ".d.ts".]]></Val>
|
||||
<Val><![CDATA[Создает сопоставитель с исходным кодом для каждого соответствующего файла ".d.ts".]]></Val>
|
||||
</Tgt>
|
||||
</Str>
|
||||
<Disp Icon="Str" />
|
||||
|
||||
@@ -284,6 +284,10 @@ namespace ts.server {
|
||||
configFileErrors?: ReadonlyArray<Diagnostic>;
|
||||
}
|
||||
|
||||
interface AssignProjectResult extends OpenConfiguredProjectResult {
|
||||
defaultConfigProject: ConfiguredProject | undefined;
|
||||
}
|
||||
|
||||
interface FilePropertyReader<T> {
|
||||
getFileName(f: T): string;
|
||||
getScriptKind(f: T, extraFileExtensions?: FileExtensionInfo[]): ScriptKind;
|
||||
@@ -1087,7 +1091,24 @@ namespace ts.server {
|
||||
|
||||
project.close();
|
||||
if (Debug.shouldAssert(AssertionLevel.Normal)) {
|
||||
this.filenameToScriptInfo.forEach(info => Debug.assert(!info.isAttached(project), "Found script Info still attached to project", () => `${project.projectName}: ScriptInfos still attached: ${JSON.stringify(mapDefined(arrayFrom(this.filenameToScriptInfo.values()), info => info.isAttached(project) ? info : undefined))}`));
|
||||
this.filenameToScriptInfo.forEach(info => Debug.assert(
|
||||
!info.isAttached(project),
|
||||
"Found script Info still attached to project",
|
||||
() => `${project.projectName}: ScriptInfos still attached: ${JSON.stringify(
|
||||
arrayFrom(
|
||||
mapDefinedIterator(
|
||||
this.filenameToScriptInfo.values(),
|
||||
info => info.isAttached(project) ?
|
||||
{
|
||||
fileName: info.fileName,
|
||||
projects: info.containingProjects.map(p => p.projectName),
|
||||
hasMixedContent: info.hasMixedContent
|
||||
} : undefined
|
||||
)
|
||||
),
|
||||
/*replacer*/ undefined,
|
||||
" "
|
||||
)}`));
|
||||
}
|
||||
// Remove the project from pending project updates
|
||||
this.pendingProjectUpdates.delete(project.getProjectName());
|
||||
@@ -2618,10 +2639,11 @@ namespace ts.server {
|
||||
return info;
|
||||
}
|
||||
|
||||
private assignProjectToOpenedScriptInfo(info: ScriptInfo): OpenConfiguredProjectResult {
|
||||
private assignProjectToOpenedScriptInfo(info: ScriptInfo): AssignProjectResult {
|
||||
let configFileName: NormalizedPath | undefined;
|
||||
let configFileErrors: ReadonlyArray<Diagnostic> | undefined;
|
||||
let project: ConfiguredProject | ExternalProject | undefined = this.findExternalProjectContainingOpenScriptInfo(info);
|
||||
let defaultConfigProject: ConfiguredProject | undefined;
|
||||
if (!project && !this.syntaxOnly) { // Checking syntaxOnly is an optimization
|
||||
configFileName = this.getConfigFileNameForFile(info);
|
||||
if (configFileName) {
|
||||
@@ -2642,6 +2664,7 @@ namespace ts.server {
|
||||
// Ensure project is ready to check if it contains opened script info
|
||||
updateProjectIfDirty(project);
|
||||
}
|
||||
defaultConfigProject = project;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2661,13 +2684,13 @@ namespace ts.server {
|
||||
this.assignOrphanScriptInfoToInferredProject(info, this.openFiles.get(info.path));
|
||||
}
|
||||
Debug.assert(!info.isOrphan());
|
||||
return { configFileName, configFileErrors };
|
||||
return { configFileName, configFileErrors, defaultConfigProject };
|
||||
}
|
||||
|
||||
private cleanupAfterOpeningFile() {
|
||||
private cleanupAfterOpeningFile(toRetainConfigProjects: ConfiguredProject[] | ConfiguredProject | undefined) {
|
||||
// This was postponed from closeOpenFile to after opening next file,
|
||||
// so that we can reuse the project if we need to right away
|
||||
this.removeOrphanConfiguredProjects();
|
||||
this.removeOrphanConfiguredProjects(toRetainConfigProjects);
|
||||
|
||||
// Remove orphan inferred projects now that we have reused projects
|
||||
// We need to create a duplicate because we cant guarantee order after removal
|
||||
@@ -2688,14 +2711,22 @@ namespace ts.server {
|
||||
|
||||
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult {
|
||||
const info = this.getOrCreateOpenScriptInfo(fileName, fileContent, scriptKind, hasMixedContent, projectRootPath);
|
||||
const result = this.assignProjectToOpenedScriptInfo(info);
|
||||
this.cleanupAfterOpeningFile();
|
||||
const { defaultConfigProject, ...result } = this.assignProjectToOpenedScriptInfo(info);
|
||||
this.cleanupAfterOpeningFile(defaultConfigProject);
|
||||
this.telemetryOnOpenFile(info);
|
||||
return result;
|
||||
}
|
||||
|
||||
private removeOrphanConfiguredProjects() {
|
||||
private removeOrphanConfiguredProjects(toRetainConfiguredProjects: ConfiguredProject[] | ConfiguredProject | undefined) {
|
||||
const toRemoveConfiguredProjects = cloneMap(this.configuredProjects);
|
||||
if (toRetainConfiguredProjects) {
|
||||
if (isArray(toRetainConfiguredProjects)) {
|
||||
toRetainConfiguredProjects.forEach(retainConfiguredProject);
|
||||
}
|
||||
else {
|
||||
retainConfiguredProject(toRetainConfiguredProjects);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not remove configured projects that are used as original projects of other
|
||||
this.inferredProjects.forEach(markOriginalProjectsAsUsed);
|
||||
@@ -2703,7 +2734,7 @@ namespace ts.server {
|
||||
this.configuredProjects.forEach(project => {
|
||||
// If project has open ref (there are more than zero references from external project/open file), keep it alive as well as any project it references
|
||||
if (project.hasOpenRef()) {
|
||||
toRemoveConfiguredProjects.delete(project.canonicalConfigFilePath);
|
||||
retainConfiguredProject(project);
|
||||
markOriginalProjectsAsUsed(project);
|
||||
}
|
||||
else {
|
||||
@@ -2712,7 +2743,7 @@ namespace ts.server {
|
||||
if (ref) {
|
||||
const refProject = this.configuredProjects.get(ref.sourceFile.path);
|
||||
if (refProject && refProject.hasOpenRef()) {
|
||||
toRemoveConfiguredProjects.delete(project.canonicalConfigFilePath);
|
||||
retainConfiguredProject(project);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -2727,6 +2758,10 @@ namespace ts.server {
|
||||
project.originalConfiguredProjects.forEach((_value, configuredProjectPath) => toRemoveConfiguredProjects.delete(configuredProjectPath));
|
||||
}
|
||||
}
|
||||
|
||||
function retainConfiguredProject(project: ConfiguredProject) {
|
||||
toRemoveConfiguredProjects.delete(project.canonicalConfigFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
private removeOrphanScriptInfos() {
|
||||
@@ -2869,8 +2904,9 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
// All the script infos now exist, so ok to go update projects for open files
|
||||
let defaultConfigProjects: ConfiguredProject[] | undefined;
|
||||
if (openScriptInfos) {
|
||||
openScriptInfos.forEach(info => this.assignProjectToOpenedScriptInfo(info));
|
||||
defaultConfigProjects = mapDefined(openScriptInfos, info => this.assignProjectToOpenedScriptInfo(info).defaultConfigProject);
|
||||
}
|
||||
|
||||
// While closing files there could be open files that needed assigning new inferred projects, do it now
|
||||
@@ -2879,7 +2915,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
// Cleanup projects
|
||||
this.cleanupAfterOpeningFile();
|
||||
this.cleanupAfterOpeningFile(defaultConfigProjects);
|
||||
|
||||
// Telemetry
|
||||
forEach(openScriptInfos, info => this.telemetryOnOpenFile(info));
|
||||
|
||||
@@ -851,6 +851,7 @@ namespace ts.server {
|
||||
* @returns: true if set of files in the project stays the same and false - otherwise.
|
||||
*/
|
||||
updateGraph(): boolean {
|
||||
perfLogger.logStartUpdateGraph();
|
||||
this.resolutionCache.startRecordingFilesWithChangedResolutions();
|
||||
|
||||
const hasNewProgram = this.updateGraphWorker();
|
||||
@@ -886,6 +887,7 @@ namespace ts.server {
|
||||
if (hasNewProgram) {
|
||||
this.projectProgramVersion++;
|
||||
}
|
||||
perfLogger.logStopUpdateGraph();
|
||||
return !hasNewProgram;
|
||||
}
|
||||
|
||||
@@ -1007,9 +1009,12 @@ namespace ts.server {
|
||||
);
|
||||
const elapsed = timestamp() - start;
|
||||
this.writeLog(`Finishing updateGraphWorker: Project: ${this.getProjectName()} Version: ${this.getProjectVersion()} structureChanged: ${hasNewProgram} Elapsed: ${elapsed}ms`);
|
||||
if (this.program !== oldProgram) {
|
||||
if (this.hasAddedorRemovedFiles) {
|
||||
this.print();
|
||||
}
|
||||
else if (this.program !== oldProgram) {
|
||||
this.writeLog(`Different program with same set of files:: oldProgram.structureIsReused:: ${oldProgram && oldProgram.structureIsReused}`);
|
||||
}
|
||||
return hasNewProgram;
|
||||
}
|
||||
|
||||
@@ -1275,7 +1280,7 @@ namespace ts.server {
|
||||
private enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: PluginImport) {
|
||||
try {
|
||||
if (typeof pluginModuleFactory !== "function") {
|
||||
this.projectService.logger.info(`Skipped loading plugin ${configEntry.name} because it did expose a proper factory function`);
|
||||
this.projectService.logger.info(`Skipped loading plugin ${configEntry.name} because it did not expose a proper factory function`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+35
-11
@@ -42,6 +42,11 @@ namespace ts.server {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function dtsChangeCanAffectEmit(compilationSettings: CompilerOptions) {
|
||||
return getEmitDeclarations(compilationSettings) || !!compilationSettings.emitDecoratorMetadata;
|
||||
}
|
||||
|
||||
function formatDiag(fileName: NormalizedPath, project: Project, diag: Diagnostic): protocol.Diagnostic {
|
||||
const scriptInfo = project.getScriptInfoForNormalizedPath(fileName)!; // TODO: GH#18217
|
||||
return {
|
||||
@@ -684,7 +689,7 @@ namespace ts.server {
|
||||
this.logErrorWorker(err, cmd);
|
||||
}
|
||||
|
||||
private logErrorWorker(err: Error, cmd: string, fileRequest?: protocol.FileRequestArgs): void {
|
||||
private logErrorWorker(err: Error & PossibleProgramFileInfo, cmd: string, fileRequest?: protocol.FileRequestArgs): void {
|
||||
let msg = "Exception on executing command " + cmd;
|
||||
if (err.message) {
|
||||
msg += ":\n" + indent(err.message);
|
||||
@@ -706,7 +711,9 @@ namespace ts.server {
|
||||
catch { } // tslint:disable-line no-empty
|
||||
}
|
||||
|
||||
if (err.message && err.message.indexOf(`Could not find sourceFile:`) !== -1) {
|
||||
|
||||
if (err.ProgramFiles) {
|
||||
msg += `\n\nProgram files: ${JSON.stringify(err.ProgramFiles)}\n`;
|
||||
msg += `\n\nProjects::\n`;
|
||||
let counter = 0;
|
||||
const addProjectInfo = (project: Project) => {
|
||||
@@ -731,7 +738,9 @@ namespace ts.server {
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.host.write(formatMessage(msg, this.logger, this.byteLength, this.host.newLine));
|
||||
const msgText = formatMessage(msg, this.logger, this.byteLength, this.host.newLine);
|
||||
perfLogger.logEvent(`Response message size: ${msgText.length}`);
|
||||
this.host.write(msgText);
|
||||
}
|
||||
|
||||
public event<T extends object>(body: T, eventName: string): void {
|
||||
@@ -1604,15 +1613,22 @@ namespace ts.server {
|
||||
path => this.projectService.getScriptInfoForPath(path)!,
|
||||
projects,
|
||||
(project, info) => {
|
||||
let result: protocol.CompileOnSaveAffectedFileListSingleProject | undefined;
|
||||
if (project.compileOnSaveEnabled && project.languageServiceEnabled && !project.isOrphan() && !project.getCompilationSettings().noEmit) {
|
||||
result = {
|
||||
projectFileName: project.getProjectName(),
|
||||
fileNames: project.getCompileOnSaveAffectedFileList(info),
|
||||
projectUsesOutFile: !!project.getCompilationSettings().outFile || !!project.getCompilationSettings().out
|
||||
};
|
||||
if (!project.compileOnSaveEnabled || !project.languageServiceEnabled || project.isOrphan()) {
|
||||
return undefined;
|
||||
}
|
||||
return result;
|
||||
|
||||
const compilationSettings = project.getCompilationSettings();
|
||||
|
||||
if (!!compilationSettings.noEmit || fileExtensionIs(info.fileName, Extension.Dts) && !dtsChangeCanAffectEmit(compilationSettings)) {
|
||||
// avoid triggering emit when a change is made in a .d.ts when declaration emit and decorator metadata emit are disabled
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
projectFileName: project.getProjectName(),
|
||||
fileNames: project.getCompileOnSaveAffectedFileList(info),
|
||||
projectUsesOutFile: !!compilationSettings.outFile || !!compilationSettings.out
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -2509,6 +2525,8 @@ namespace ts.server {
|
||||
try {
|
||||
request = <protocol.Request>JSON.parse(message);
|
||||
relevantFile = request.arguments && (request as protocol.FileRequest).arguments.file ? (request as protocol.FileRequest).arguments : undefined;
|
||||
|
||||
perfLogger.logStartCommand("" + request.command, message.substring(0, 100));
|
||||
const { response, responseRequired } = this.executeCommand(request);
|
||||
|
||||
if (this.logger.hasLevel(LogLevel.requestTime)) {
|
||||
@@ -2521,6 +2539,8 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Log before writing the response, else the editor can complete its activity before the server does
|
||||
perfLogger.logStopCommand("" + request.command, "Success");
|
||||
if (response) {
|
||||
this.doOutput(response, request.command, request.seq, /*success*/ true);
|
||||
}
|
||||
@@ -2531,10 +2551,14 @@ namespace ts.server {
|
||||
catch (err) {
|
||||
if (err instanceof OperationCanceledException) {
|
||||
// Handle cancellation exceptions
|
||||
perfLogger.logStopCommand("" + (request && request.command), "Canceled: " + err);
|
||||
this.doOutput({ canceled: true }, request!.command, request!.seq, /*success*/ true);
|
||||
return;
|
||||
}
|
||||
|
||||
this.logErrorWorker(err, message, relevantFile);
|
||||
perfLogger.logStopCommand("" + (request && request.command), "Error: " + err);
|
||||
|
||||
this.doOutput(
|
||||
/*info*/ undefined,
|
||||
request ? request.command : CommandNames.Unknown,
|
||||
|
||||
@@ -150,11 +150,13 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private static run(self: ThrottledOperations, operationId: string, cb: () => void) {
|
||||
perfLogger.logStartScheduledOperation(operationId);
|
||||
self.pendingTimeouts.delete(operationId);
|
||||
if (self.logger) {
|
||||
self.logger.info(`Running: ${operationId}`);
|
||||
}
|
||||
cb();
|
||||
perfLogger.logStopScheduledOperation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +176,7 @@ namespace ts.server {
|
||||
private static run(self: GcTimer) {
|
||||
self.timerId = undefined;
|
||||
|
||||
perfLogger.logStartScheduledOperation("GC collect");
|
||||
const log = self.logger.hasLevel(LogLevel.requestTime);
|
||||
const before = log && self.host.getMemoryUsage!(); // TODO: GH#18217
|
||||
|
||||
@@ -182,6 +185,7 @@ namespace ts.server {
|
||||
const after = self.host.getMemoryUsage!(); // TODO: GH#18217
|
||||
self.logger.perftrc(`GC::before ${before}, after ${after}`);
|
||||
}
|
||||
perfLogger.logStopScheduledOperation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
namespace ts {
|
||||
/** The classifier is used for syntactic highlighting in editors via the TSServer */
|
||||
export function createClassifier(): Classifier {
|
||||
const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false);
|
||||
|
||||
@@ -683,6 +684,11 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (kind === SyntaxKind.SingleLineCommentTrivia) {
|
||||
if (tryClassifyTripleSlashComment(start, width)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple comment. Just add as is.
|
||||
pushCommentRange(start, width);
|
||||
@@ -755,6 +761,84 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function tryClassifyTripleSlashComment(start: number, width: number): boolean {
|
||||
const tripleSlashXMLCommentRegEx = /^(\/\/\/\s*)(<)(?:(\S+)((?:[^/]|\/[^>])*)(\/>)?)?/im;
|
||||
const attributeRegex = /(\S+)(\s*)(=)(\s*)('[^']+'|"[^"]+")/img;
|
||||
|
||||
const text = sourceFile.text.substr(start, width);
|
||||
const match = tripleSlashXMLCommentRegEx.exec(text);
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let pos = start;
|
||||
|
||||
pushCommentRange(pos, match[1].length); // ///
|
||||
pos += match[1].length;
|
||||
|
||||
pushClassification(pos, match[2].length, ClassificationType.punctuation); // <
|
||||
pos += match[2].length;
|
||||
|
||||
if (!match[3]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
pushClassification(pos, match[3].length, ClassificationType.jsxSelfClosingTagName); // element name
|
||||
pos += match[3].length;
|
||||
|
||||
const attrText = match[4];
|
||||
let attrPos = pos;
|
||||
while (true) {
|
||||
const attrMatch = attributeRegex.exec(attrText);
|
||||
if (!attrMatch) {
|
||||
break;
|
||||
}
|
||||
|
||||
const newAttrPos = pos + attrMatch.index;
|
||||
if (newAttrPos > attrPos) {
|
||||
pushCommentRange(attrPos, newAttrPos - attrPos);
|
||||
attrPos = newAttrPos;
|
||||
}
|
||||
|
||||
pushClassification(attrPos, attrMatch[1].length, ClassificationType.jsxAttribute); // attribute name
|
||||
attrPos += attrMatch[1].length;
|
||||
|
||||
if (attrMatch[2].length) {
|
||||
pushCommentRange(attrPos, attrMatch[2].length); // whitespace
|
||||
attrPos += attrMatch[2].length;
|
||||
}
|
||||
|
||||
pushClassification(attrPos, attrMatch[3].length, ClassificationType.operator); // =
|
||||
attrPos += attrMatch[3].length;
|
||||
|
||||
if (attrMatch[4].length) {
|
||||
pushCommentRange(attrPos, attrMatch[4].length); // whitespace
|
||||
attrPos += attrMatch[4].length;
|
||||
}
|
||||
|
||||
pushClassification(attrPos, attrMatch[5].length, ClassificationType.jsxAttributeStringLiteralValue); // attribute value
|
||||
attrPos += attrMatch[5].length;
|
||||
}
|
||||
|
||||
pos += match[4].length;
|
||||
|
||||
if (pos > attrPos) {
|
||||
pushCommentRange(attrPos, pos - attrPos);
|
||||
}
|
||||
|
||||
if (match[5]) {
|
||||
pushClassification(pos, match[5].length, ClassificationType.punctuation); // />
|
||||
pos += match[5].length;
|
||||
}
|
||||
|
||||
const end = start + width;
|
||||
if (pos < end) {
|
||||
pushCommentRange(pos, end - pos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function processJSDocTemplateTag(tag: JSDocTemplateTag) {
|
||||
for (const child of tag.getChildren()) {
|
||||
processElement(child);
|
||||
|
||||
@@ -55,10 +55,9 @@ namespace ts.codefix {
|
||||
const modifiers = visibilityModifier ? createNodeArray([visibilityModifier]) : undefined;
|
||||
const type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration));
|
||||
const optional = !!(symbol.flags & SymbolFlags.Optional);
|
||||
const ambient = !!(enclosingDeclaration.flags & NodeFlags.Ambient);
|
||||
|
||||
switch (declaration.kind) {
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.PropertySignature:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
const typeNode = checker.typeToTypeNode(type, enclosingDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context));
|
||||
@@ -70,6 +69,37 @@ namespace ts.codefix {
|
||||
typeNode,
|
||||
/*initializer*/ undefined));
|
||||
break;
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor: {
|
||||
const allAccessors = getAllAccessorDeclarations(declarations, declaration as AccessorDeclaration);
|
||||
const typeNode = checker.typeToTypeNode(type, enclosingDeclaration, /*flags*/ undefined, getNoopSymbolTrackerWithResolver(context));
|
||||
const orderedAccessors = allAccessors.secondAccessor
|
||||
? [allAccessors.firstAccessor, allAccessors.secondAccessor]
|
||||
: [allAccessors.firstAccessor];
|
||||
for (const accessor of orderedAccessors) {
|
||||
if (isGetAccessorDeclaration(accessor)) {
|
||||
out(createGetAccessor(
|
||||
/*decorators*/ undefined,
|
||||
modifiers,
|
||||
name,
|
||||
emptyArray,
|
||||
typeNode,
|
||||
ambient ? undefined : createStubbedMethodBody(preferences)));
|
||||
}
|
||||
else {
|
||||
Debug.assertNode(accessor, isSetAccessorDeclaration);
|
||||
const parameter = getSetAccessorValueParameter(accessor);
|
||||
const parameterName = parameter && isIdentifier(parameter.name) ? idText(parameter.name) : undefined;
|
||||
out(createSetAccessor(
|
||||
/*decorators*/ undefined,
|
||||
modifiers,
|
||||
name,
|
||||
createDummyParameters(1, [parameterName], [typeNode], 1, /*inJs*/ false),
|
||||
ambient ? undefined : createStubbedMethodBody(preferences)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
// The signature for the implementation appears as an entry in `signatures` iff
|
||||
@@ -87,7 +117,7 @@ namespace ts.codefix {
|
||||
if (declarations.length === 1) {
|
||||
Debug.assert(signatures.length === 1);
|
||||
const signature = signatures[0];
|
||||
outputMethod(signature, modifiers, name, createStubbedMethodBody(preferences));
|
||||
outputMethod(signature, modifiers, name, ambient ? undefined : createStubbedMethodBody(preferences));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -96,13 +126,15 @@ namespace ts.codefix {
|
||||
outputMethod(signature, getSynthesizedDeepClones(modifiers, /*includeTrivia*/ false), getSynthesizedDeepClone(name, /*includeTrivia*/ false));
|
||||
}
|
||||
|
||||
if (declarations.length > signatures.length) {
|
||||
const signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration)!;
|
||||
outputMethod(signature, modifiers, name, createStubbedMethodBody(preferences));
|
||||
}
|
||||
else {
|
||||
Debug.assert(declarations.length === signatures.length);
|
||||
out(createMethodImplementingSignatures(signatures, name, optional, modifiers, preferences));
|
||||
if (!ambient) {
|
||||
if (declarations.length > signatures.length) {
|
||||
const signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1] as SignatureDeclaration)!;
|
||||
outputMethod(signature, modifiers, name, createStubbedMethodBody(preferences));
|
||||
}
|
||||
else {
|
||||
Debug.assert(declarations.length === signatures.length);
|
||||
out(createMethodImplementingSignatures(signatures, name, optional, modifiers, preferences));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -135,7 +135,8 @@ namespace ts.codefix {
|
||||
Named,
|
||||
Default,
|
||||
Namespace,
|
||||
Equals
|
||||
Equals,
|
||||
ConstEquals
|
||||
}
|
||||
|
||||
/** Information about how a symbol is exported from a module. (We don't need to store the exported symbol, just its module.) */
|
||||
@@ -163,7 +164,7 @@ namespace ts.codefix {
|
||||
position: number,
|
||||
preferences: UserPreferences,
|
||||
): { readonly moduleSpecifier: string, readonly codeAction: CodeAction } {
|
||||
const exportInfos = getAllReExportingModules(exportedSymbol, moduleSymbol, symbolName, sourceFile, program.getCompilerOptions(), program.getTypeChecker(), program.getSourceFiles());
|
||||
const exportInfos = getAllReExportingModules(sourceFile, exportedSymbol, moduleSymbol, symbolName, sourceFile, program.getCompilerOptions(), program.getTypeChecker(), program.getSourceFiles());
|
||||
Debug.assert(exportInfos.some(info => info.moduleSymbol === moduleSymbol));
|
||||
// We sort the best codefixes first, so taking `first` is best for completions.
|
||||
const moduleSpecifier = first(getNewImportInfos(program, sourceFile, position, exportInfos, host, preferences)).moduleSpecifier;
|
||||
@@ -175,7 +176,7 @@ namespace ts.codefix {
|
||||
return { description, changes, commands };
|
||||
}
|
||||
|
||||
function getAllReExportingModules(exportedSymbol: Symbol, exportingModuleSymbol: Symbol, symbolName: string, sourceFile: SourceFile, compilerOptions: CompilerOptions, checker: TypeChecker, allSourceFiles: ReadonlyArray<SourceFile>): ReadonlyArray<SymbolExportInfo> {
|
||||
function getAllReExportingModules(importingFile: SourceFile, exportedSymbol: Symbol, exportingModuleSymbol: Symbol, symbolName: string, sourceFile: SourceFile, compilerOptions: CompilerOptions, checker: TypeChecker, allSourceFiles: ReadonlyArray<SourceFile>): ReadonlyArray<SymbolExportInfo> {
|
||||
const result: SymbolExportInfo[] = [];
|
||||
forEachExternalModule(checker, allSourceFiles, (moduleSymbol, moduleFile) => {
|
||||
// Don't import from a re-export when looking "up" like to `./index` or `../index`.
|
||||
@@ -183,7 +184,7 @@ namespace ts.codefix {
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions);
|
||||
const defaultInfo = getDefaultLikeExportInfo(importingFile, moduleSymbol, checker, compilerOptions);
|
||||
if (defaultInfo && defaultInfo.name === symbolName && skipAlias(defaultInfo.symbol, checker) === exportedSymbol) {
|
||||
result.push({ moduleSymbol, importKind: defaultInfo.kind, exportedSymbolIsTypeOnly: isTypeOnlySymbol(defaultInfo.symbol, checker) });
|
||||
}
|
||||
@@ -329,7 +330,7 @@ namespace ts.codefix {
|
||||
if (!umdSymbol) return undefined;
|
||||
const symbol = checker.getAliasedSymbol(umdSymbol);
|
||||
const symbolName = umdSymbol.name;
|
||||
const exportInfos: ReadonlyArray<SymbolExportInfo> = [{ moduleSymbol: symbol, importKind: getUmdImportKind(program.getCompilerOptions()), exportedSymbolIsTypeOnly: false }];
|
||||
const exportInfos: ReadonlyArray<SymbolExportInfo> = [{ moduleSymbol: symbol, importKind: getUmdImportKind(sourceFile, program.getCompilerOptions()), exportedSymbolIsTypeOnly: false }];
|
||||
const fixes = getFixForImport(exportInfos, symbolName, isIdentifier(token) ? token.getStart(sourceFile) : undefined, program, sourceFile, host, preferences);
|
||||
return { fixes, symbolName };
|
||||
}
|
||||
@@ -345,7 +346,7 @@ namespace ts.codefix {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function getUmdImportKind(compilerOptions: CompilerOptions): ImportKind {
|
||||
function getUmdImportKind(importingFile: SourceFile, compilerOptions: CompilerOptions): ImportKind {
|
||||
// Import a synthetic `default` if enabled.
|
||||
if (getAllowSyntheticDefaultImports(compilerOptions)) {
|
||||
return ImportKind.Default;
|
||||
@@ -357,7 +358,10 @@ namespace ts.codefix {
|
||||
case ModuleKind.AMD:
|
||||
case ModuleKind.CommonJS:
|
||||
case ModuleKind.UMD:
|
||||
return ImportKind.Equals;
|
||||
if (isInJSFile(importingFile)) {
|
||||
return isExternalModule(importingFile) ? ImportKind.Namespace : ImportKind.ConstEquals;
|
||||
}
|
||||
return ImportKind.Equals;
|
||||
case ModuleKind.System:
|
||||
case ModuleKind.ES2015:
|
||||
case ModuleKind.ESNext:
|
||||
@@ -403,7 +407,7 @@ namespace ts.codefix {
|
||||
forEachExternalModuleToImportFrom(checker, sourceFile, program.getSourceFiles(), moduleSymbol => {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, program.getCompilerOptions());
|
||||
const defaultInfo = getDefaultLikeExportInfo(sourceFile, moduleSymbol, checker, program.getCompilerOptions());
|
||||
if (defaultInfo && defaultInfo.name === symbolName && symbolHasMeaning(defaultInfo.symbolForMeaning, currentTokenMeaning)) {
|
||||
addSymbol(moduleSymbol, defaultInfo.symbol, defaultInfo.kind);
|
||||
}
|
||||
@@ -418,20 +422,41 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function getDefaultLikeExportInfo(
|
||||
moduleSymbol: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions,
|
||||
): { readonly symbol: Symbol, readonly symbolForMeaning: Symbol, readonly name: string, readonly kind: ImportKind.Default | ImportKind.Equals } | undefined {
|
||||
const exported = getDefaultLikeExportWorker(moduleSymbol, checker);
|
||||
importingFile: SourceFile, moduleSymbol: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions,
|
||||
): { readonly symbol: Symbol, readonly symbolForMeaning: Symbol, readonly name: string, readonly kind: ImportKind } | undefined {
|
||||
const exported = getDefaultLikeExportWorker(importingFile, moduleSymbol, checker, compilerOptions);
|
||||
if (!exported) return undefined;
|
||||
const { symbol, kind } = exported;
|
||||
const info = getDefaultExportInfoWorker(symbol, moduleSymbol, checker, compilerOptions);
|
||||
return info && { symbol, kind, ...info };
|
||||
}
|
||||
|
||||
function getDefaultLikeExportWorker(moduleSymbol: Symbol, checker: TypeChecker): { readonly symbol: Symbol, readonly kind: ImportKind.Default | ImportKind.Equals } | undefined {
|
||||
function getDefaultLikeExportWorker(importingFile: SourceFile, moduleSymbol: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions): { readonly symbol: Symbol, readonly kind: ImportKind } | undefined {
|
||||
const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol);
|
||||
if (defaultExport) return { symbol: defaultExport, kind: ImportKind.Default };
|
||||
const exportEquals = checker.resolveExternalModuleSymbol(moduleSymbol);
|
||||
return exportEquals === moduleSymbol ? undefined : { symbol: exportEquals, kind: ImportKind.Equals };
|
||||
return exportEquals === moduleSymbol ? undefined : { symbol: exportEquals, kind: getExportEqualsImportKind(importingFile, compilerOptions, checker) };
|
||||
}
|
||||
|
||||
function getExportEqualsImportKind(importingFile: SourceFile, compilerOptions: CompilerOptions, checker: TypeChecker): ImportKind {
|
||||
if (getAllowSyntheticDefaultImports(compilerOptions) && getEmitModuleKind(compilerOptions) >= ModuleKind.ES2015) {
|
||||
return ImportKind.Default;
|
||||
}
|
||||
if (isInJSFile(importingFile)) {
|
||||
return isExternalModule(importingFile) ? ImportKind.Default : ImportKind.ConstEquals;
|
||||
}
|
||||
for (const statement of importingFile.statements) {
|
||||
if (isImportEqualsDeclaration(statement)) {
|
||||
return ImportKind.Equals;
|
||||
}
|
||||
if (isImportDeclaration(statement) && statement.importClause && statement.importClause.name) {
|
||||
const moduleSymbol = checker.getImmediateAliasedSymbol(statement.importClause.symbol);
|
||||
if (moduleSymbol && moduleSymbol.name !== InternalSymbolName.Default) {
|
||||
return ImportKind.Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ImportKind.Equals;
|
||||
}
|
||||
|
||||
function getDefaultExportInfoWorker(defaultExport: Symbol, moduleSymbol: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions): { readonly symbolForMeaning: Symbol, readonly name: string } | undefined {
|
||||
@@ -445,9 +470,12 @@ namespace ts.codefix {
|
||||
const aliased = checker.getImmediateAliasedSymbol(defaultExport);
|
||||
return aliased && getDefaultExportInfoWorker(aliased, Debug.assertDefined(aliased.parent), checker, compilerOptions);
|
||||
}
|
||||
else {
|
||||
return { symbolForMeaning: defaultExport, name: moduleSymbolToValidIdentifier(moduleSymbol, compilerOptions.target!) };
|
||||
|
||||
if (defaultExport.escapedName !== InternalSymbolName.Default &&
|
||||
defaultExport.escapedName !== InternalSymbolName.ExportEquals) {
|
||||
return { symbolForMeaning: defaultExport, name: defaultExport.getName() };
|
||||
}
|
||||
return { symbolForMeaning: defaultExport, name: moduleSymbolToValidIdentifier(moduleSymbol, compilerOptions.target!) };
|
||||
}
|
||||
|
||||
function getNameForExportDefault(symbol: Symbol): string | undefined {
|
||||
@@ -540,7 +568,10 @@ namespace ts.codefix {
|
||||
interface ImportsCollection {
|
||||
readonly defaultImport: string | undefined;
|
||||
readonly namedImports: string[];
|
||||
readonly namespaceLikeImport: { readonly importKind: ImportKind.Equals | ImportKind.Namespace, readonly name: string } | undefined;
|
||||
readonly namespaceLikeImport: {
|
||||
readonly importKind: ImportKind.Equals | ImportKind.Namespace | ImportKind.ConstEquals;
|
||||
readonly name: string;
|
||||
} | undefined;
|
||||
}
|
||||
function addNewImports(changes: textChanges.ChangeTracker, sourceFile: SourceFile, moduleSpecifier: string, quotePreference: QuotePreference, { defaultImport, namedImports, namespaceLikeImport }: ImportsCollection): void {
|
||||
const quotedModuleSpecifier = makeStringLiteral(moduleSpecifier, quotePreference);
|
||||
@@ -551,12 +582,25 @@ namespace ts.codefix {
|
||||
namedImports.map(n => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(n))), moduleSpecifier, quotePreference));
|
||||
}
|
||||
if (namespaceLikeImport) {
|
||||
insertImport(changes, sourceFile, namespaceLikeImport.importKind === ImportKind.Equals
|
||||
? createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier(namespaceLikeImport.name), createExternalModuleReference(quotedModuleSpecifier))
|
||||
: createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(namespaceLikeImport.name))), quotedModuleSpecifier));
|
||||
insertImport(
|
||||
changes,
|
||||
sourceFile,
|
||||
namespaceLikeImport.importKind === ImportKind.Equals ? createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier(namespaceLikeImport.name), createExternalModuleReference(quotedModuleSpecifier)) :
|
||||
namespaceLikeImport.importKind === ImportKind.ConstEquals ? createConstEqualsRequireDeclaration(namespaceLikeImport.name, quotedModuleSpecifier) :
|
||||
createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(namespaceLikeImport.name))), quotedModuleSpecifier));
|
||||
}
|
||||
}
|
||||
|
||||
function createConstEqualsRequireDeclaration(name: string, quotedModuleSpecifier: StringLiteral): VariableStatement {
|
||||
return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([
|
||||
createVariableDeclaration(
|
||||
createIdentifier(name),
|
||||
/*type*/ undefined,
|
||||
createCall(createIdentifier("require"), /*typeArguments*/ undefined, [quotedModuleSpecifier])
|
||||
)
|
||||
], NodeFlags.Const));
|
||||
}
|
||||
|
||||
function symbolHasMeaning({ declarations }: Symbol, meaning: SemanticMeaning): boolean {
|
||||
return some(declarations, decl => !!(getMeaningFromDeclaration(decl) & meaning));
|
||||
}
|
||||
|
||||
+22
-16
@@ -947,11 +947,13 @@ namespace ts.Completions {
|
||||
// Right of dot member completion list
|
||||
completionKind = CompletionKind.PropertyAccess;
|
||||
|
||||
// Since this is qualified name check its a type node location
|
||||
// Since this is qualified name check it's a type node location
|
||||
const isImportType = isLiteralImportTypeNode(node);
|
||||
const isTypeLocation = insideJsDocTagTypeExpression || (isImportType && !(node as ImportTypeNode).isTypeOf) || isPartOfTypeNode(node.parent);
|
||||
const isTypeLocation = insideJsDocTagTypeExpression
|
||||
|| (isImportType && !(node as ImportTypeNode).isTypeOf)
|
||||
|| isPartOfTypeNode(node.parent)
|
||||
|| isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker);
|
||||
const isRhsOfImportDeclaration = isInRightSideOfInternalImportEqualsDeclaration(node);
|
||||
const allowTypeOrValue = isRhsOfImportDeclaration || (!isTypeLocation && isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker));
|
||||
if (isEntityName(node) || isImportType) {
|
||||
const isNamespaceName = isModuleDeclaration(node.parent);
|
||||
if (isNamespaceName) isNewIdentifierLocation = true;
|
||||
@@ -968,7 +970,7 @@ namespace ts.Completions {
|
||||
isNamespaceName
|
||||
// At `namespace N.M/**/`, if this is the only declaration of `M`, don't include `M` as a completion.
|
||||
? symbol => !!(symbol.flags & SymbolFlags.Namespace) && !symbol.declarations.every(d => d.parent === node.parent)
|
||||
: allowTypeOrValue ?
|
||||
: isRhsOfImportDeclaration ?
|
||||
// Any kind is allowed when dotting off namespace in internal import equals declaration
|
||||
symbol => isValidTypeAccess(symbol) || isValidValueAccess(symbol) :
|
||||
isTypeLocation ? isValidTypeAccess : isValidValueAccess;
|
||||
@@ -1181,7 +1183,6 @@ namespace ts.Completions {
|
||||
|
||||
function filterGlobalCompletion(symbols: Symbol[]): void {
|
||||
const isTypeOnly = isTypeOnlyCompletion();
|
||||
const allowTypes = isTypeOnly || !isContextTokenValueLocation(contextToken) && isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker);
|
||||
if (isTypeOnly) {
|
||||
keywordFilters = isTypeAssertion()
|
||||
? KeywordCompletionFilters.TypeAssertionKeywords
|
||||
@@ -1202,12 +1203,9 @@ namespace ts.Completions {
|
||||
return !!(symbol.flags & SymbolFlags.Namespace);
|
||||
}
|
||||
|
||||
if (allowTypes) {
|
||||
// Its a type, but you can reach it by namespace.type as well
|
||||
const symbolAllowedAsType = symbolCanBeReferencedAtTypeLocation(symbol);
|
||||
if (symbolAllowedAsType || isTypeOnly) {
|
||||
return symbolAllowedAsType;
|
||||
}
|
||||
if (isTypeOnly) {
|
||||
// It's a type, but you can reach it by namespace.type as well
|
||||
return symbolCanBeReferencedAtTypeLocation(symbol);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1221,7 +1219,11 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
function isTypeOnlyCompletion(): boolean {
|
||||
return insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken));
|
||||
return insideJsDocTagTypeExpression
|
||||
|| !isContextTokenValueLocation(contextToken) &&
|
||||
(isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker)
|
||||
|| isPartOfTypeNode(location)
|
||||
|| isContextTokenTypeLocation(contextToken));
|
||||
}
|
||||
|
||||
function isContextTokenValueLocation(contextToken: Node) {
|
||||
@@ -2060,16 +2062,18 @@ namespace ts.Completions {
|
||||
case KeywordCompletionFilters.None:
|
||||
return false;
|
||||
case KeywordCompletionFilters.All:
|
||||
return kind === SyntaxKind.AsyncKeyword || SyntaxKind.AwaitKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind) || kind === SyntaxKind.DeclareKeyword || kind === SyntaxKind.ModuleKeyword
|
||||
return isFunctionLikeBodyKeyword(kind)
|
||||
|| kind === SyntaxKind.DeclareKeyword
|
||||
|| kind === SyntaxKind.ModuleKeyword
|
||||
|| isTypeKeyword(kind) && kind !== SyntaxKind.UndefinedKeyword;
|
||||
case KeywordCompletionFilters.FunctionLikeBodyKeywords:
|
||||
return isFunctionLikeBodyKeyword(kind);
|
||||
case KeywordCompletionFilters.ClassElementKeywords:
|
||||
return isClassMemberCompletionKeyword(kind);
|
||||
case KeywordCompletionFilters.InterfaceElementKeywords:
|
||||
return isInterfaceOrTypeLiteralCompletionKeyword(kind);
|
||||
case KeywordCompletionFilters.ConstructorParameterKeywords:
|
||||
return isParameterPropertyModifier(kind);
|
||||
case KeywordCompletionFilters.FunctionLikeBodyKeywords:
|
||||
return isFunctionLikeBodyKeyword(kind);
|
||||
case KeywordCompletionFilters.TypeAssertionKeywords:
|
||||
return isTypeKeyword(kind) || kind === SyntaxKind.ConstKeyword;
|
||||
case KeywordCompletionFilters.TypeKeywords:
|
||||
@@ -2132,7 +2136,9 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
function isFunctionLikeBodyKeyword(kind: SyntaxKind) {
|
||||
return kind === SyntaxKind.AsyncKeyword || kind === SyntaxKind.AwaitKeyword || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind);
|
||||
return kind === SyntaxKind.AsyncKeyword
|
||||
|| kind === SyntaxKind.AwaitKeyword
|
||||
|| !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind);
|
||||
}
|
||||
|
||||
function keywordForNode(node: Node): SyntaxKind {
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace ts.DocumentHighlights {
|
||||
|
||||
function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): ReadonlyArray<Node> | undefined {
|
||||
// Types of node whose children might have modifiers.
|
||||
const container = declaration.parent as ModuleBlock | SourceFile | Block | CaseClause | DefaultClause | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | ClassLikeDeclaration;
|
||||
const container = declaration.parent as ModuleBlock | SourceFile | Block | CaseClause | DefaultClause | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | ObjectTypeDeclaration;
|
||||
switch (container.kind) {
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.SourceFile:
|
||||
@@ -213,11 +213,13 @@ namespace ts.DocumentHighlights {
|
||||
return [...container.parameters, ...(isClassLike(container.parent) ? container.parent.members : [])];
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
const nodes = container.members;
|
||||
|
||||
// If we're an accessibility modifier, we're in an instance member and should search
|
||||
// the constructor's parameter list for instance members as well.
|
||||
if (modifierFlag & ModifierFlags.AccessibilityModifier) {
|
||||
if (modifierFlag & (ModifierFlags.AccessibilityModifier | ModifierFlags.Readonly)) {
|
||||
const constructor = find(container.members, isConstructorDeclaration);
|
||||
if (constructor) {
|
||||
return [...nodes, ...constructor.parameters];
|
||||
|
||||
@@ -709,10 +709,28 @@ namespace ts.FindAllReferences.Core {
|
||||
return references.length ? [{ definition: { type: DefinitionKind.Symbol, symbol }, references }] : emptyArray;
|
||||
}
|
||||
|
||||
/** As in a `readonly prop: any` or `constructor(readonly prop: any)`, not a `readonly any[]`. */
|
||||
function isReadonlyTypeOperator(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.ReadonlyKeyword
|
||||
&& isTypeOperatorNode(node.parent)
|
||||
&& node.parent.operator === SyntaxKind.ReadonlyKeyword;
|
||||
}
|
||||
|
||||
/** getReferencedSymbols for special node kinds. */
|
||||
function getReferencedSymbolsSpecial(node: Node, sourceFiles: ReadonlyArray<SourceFile>, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined {
|
||||
if (isTypeKeyword(node.kind)) {
|
||||
return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken);
|
||||
// A modifier readonly (like on a property declaration) is not special;
|
||||
// a readonly type keyword (like `readonly string[]`) is.
|
||||
if (node.kind === SyntaxKind.ReadonlyKeyword && !isReadonlyTypeOperator(node)) {
|
||||
return undefined;
|
||||
}
|
||||
// Likewise, when we *are* looking for a special keyword, make sure we
|
||||
// *don’t* include readonly member modifiers.
|
||||
return getAllReferencesForKeyword(
|
||||
sourceFiles,
|
||||
node.kind,
|
||||
cancellationToken,
|
||||
node.kind === SyntaxKind.ReadonlyKeyword ? isReadonlyTypeOperator : undefined);
|
||||
}
|
||||
|
||||
// Labels
|
||||
@@ -1235,11 +1253,14 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
}
|
||||
|
||||
function getAllReferencesForKeyword(sourceFiles: ReadonlyArray<SourceFile>, keywordKind: SyntaxKind, cancellationToken: CancellationToken): SymbolAndEntries[] | undefined {
|
||||
function getAllReferencesForKeyword(sourceFiles: ReadonlyArray<SourceFile>, keywordKind: SyntaxKind, cancellationToken: CancellationToken, filter?: (node: Node) => boolean): SymbolAndEntries[] | undefined {
|
||||
const references = flatMap(sourceFiles, sourceFile => {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind)!, sourceFile), referenceLocation =>
|
||||
referenceLocation.kind === keywordKind ? nodeEntry(referenceLocation) : undefined);
|
||||
return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind)!, sourceFile), referenceLocation => {
|
||||
if (referenceLocation.kind === keywordKind && (!filter || filter(referenceLocation))) {
|
||||
return nodeEntry(referenceLocation);
|
||||
}
|
||||
});
|
||||
});
|
||||
return references.length ? [{ definition: { type: DefinitionKind.Keyword, node: references[0].node }, references }] : undefined;
|
||||
}
|
||||
|
||||
@@ -233,20 +233,23 @@ namespace ts.GoToDefinition {
|
||||
}
|
||||
|
||||
function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node): DefinitionInfo[] | undefined {
|
||||
return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(symbol.declarations, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node));
|
||||
// There are cases when you extend a function by adding properties to it afterwards,
|
||||
// we want to strip those extra properties
|
||||
const filteredDeclarations = filter(symbol.declarations, d => !isAssignmentDeclaration(d) || d === symbol.valueDeclaration) || undefined;
|
||||
return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(filteredDeclarations, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node));
|
||||
|
||||
function getConstructSignatureDefinition(): DefinitionInfo[] | undefined {
|
||||
// Applicable only if we are in a new expression, or we are on a constructor declaration
|
||||
// and in either case the symbol has a construct signature definition, i.e. class
|
||||
if (symbol.flags & SymbolFlags.Class && (isNewExpressionTarget(node) || node.kind === SyntaxKind.ConstructorKeyword)) {
|
||||
const cls = find(symbol.declarations, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration");
|
||||
const cls = find(filteredDeclarations, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration");
|
||||
return getSignatureDefinition(cls.members, /*selectConstructors*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
function getCallSignatureDefinition(): DefinitionInfo[] | undefined {
|
||||
return isCallOrNewExpressionTarget(node) || isNameOfFunctionDeclaration(node)
|
||||
? getSignatureDefinition(symbol.declarations, /*selectConstructors*/ false)
|
||||
? getSignatureDefinition(filteredDeclarations, /*selectConstructors*/ false)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -434,7 +434,7 @@ namespace ts.FindAllReferences {
|
||||
/**
|
||||
* Given a local reference, we might notice that it's an import/export and recursively search for references of that.
|
||||
* If at an import, look locally for the symbol it imports.
|
||||
* If an an export, look for all imports of it.
|
||||
* If at an export, look for all imports of it.
|
||||
* This doesn't handle export specifiers; that is done in `getReferencesAtExportSpecifier`.
|
||||
* @param comingFromExport If we are doing a search for all exports, don't bother looking backwards for the imported symbol, since that's the reason we're here.
|
||||
*/
|
||||
@@ -577,10 +577,10 @@ namespace ts.FindAllReferences {
|
||||
// If a reference is a class expression, the exported node would be its parent.
|
||||
// If a reference is a variable declaration, the exported node would be the variable statement.
|
||||
function getExportNode(parent: Node, node: Node): Node | undefined {
|
||||
if (parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
const p = parent as VariableDeclaration;
|
||||
return p.name !== node ? undefined :
|
||||
p.parent.kind === SyntaxKind.CatchClause ? undefined : p.parent.parent.kind === SyntaxKind.VariableStatement ? p.parent.parent : undefined;
|
||||
const declaration = isVariableDeclaration(parent) ? parent : isBindingElement(parent) ? walkUpBindingElementsAndPatterns(parent) : undefined;
|
||||
if (declaration) {
|
||||
return (parent as VariableDeclaration | BindingElement).name !== node ? undefined :
|
||||
isCatchClause(declaration.parent) ? undefined : isVariableStatement(declaration.parent.parent) ? declaration.parent.parent : undefined;
|
||||
}
|
||||
else {
|
||||
return parent;
|
||||
|
||||
@@ -71,9 +71,8 @@ namespace ts.OutliningElementsCollector {
|
||||
function addRegionOutliningSpans(sourceFile: SourceFile, out: Push<OutliningSpan>): void {
|
||||
const regions: OutliningSpan[] = [];
|
||||
const lineStarts = sourceFile.getLineStarts();
|
||||
for (let i = 0; i < lineStarts.length; i++) {
|
||||
const currentLineStart = lineStarts[i];
|
||||
const lineEnd = i + 1 === lineStarts.length ? sourceFile.getEnd() : lineStarts[i + 1] - 1;
|
||||
for (const currentLineStart of lineStarts) {
|
||||
const lineEnd = sourceFile.getLineEndOfPosition(currentLineStart);
|
||||
const lineText = sourceFile.text.substring(currentLineStart, lineEnd);
|
||||
const result = isRegionDelimiter(lineText);
|
||||
if (!result || isInComment(sourceFile, currentLineStart)) {
|
||||
|
||||
@@ -350,7 +350,11 @@ namespace ts.refactor {
|
||||
}
|
||||
if (namedBindings) {
|
||||
if (namedBindingsUnused) {
|
||||
changes.delete(sourceFile, namedBindings);
|
||||
changes.replaceNode(
|
||||
sourceFile,
|
||||
importDecl.importClause,
|
||||
updateImportClause(importDecl.importClause, name, /*namedBindings*/ undefined)
|
||||
);
|
||||
}
|
||||
else if (namedBindings.kind === SyntaxKind.NamedImports) {
|
||||
for (const element of namedBindings.elements) {
|
||||
|
||||
@@ -1158,7 +1158,13 @@ namespace ts {
|
||||
function getValidSourceFile(fileName: string): SourceFile {
|
||||
const sourceFile = program.getSourceFile(fileName);
|
||||
if (!sourceFile) {
|
||||
throw new Error(`Could not find sourceFile: '${fileName}' in ${program && JSON.stringify(program.getSourceFiles().map(f => f.fileName))}.`);
|
||||
const error: Error & PossibleProgramFileInfo = new Error(`Could not find source file: '${fileName}'.`);
|
||||
|
||||
// We've been having trouble debugging this, so attach sidecar data for the tsserver log.
|
||||
// See https://github.com/microsoft/TypeScript/issues/30180.
|
||||
error.ProgramFiles = program.getSourceFiles().map(f => f.fileName);
|
||||
|
||||
throw error;
|
||||
}
|
||||
return sourceFile;
|
||||
}
|
||||
@@ -1238,12 +1244,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (host.resolveModuleNames) {
|
||||
compilerHost.resolveModuleNames = (moduleNames, containingFile, reusedNames, redirectedReference) => host.resolveModuleNames!(moduleNames, containingFile, reusedNames, redirectedReference);
|
||||
compilerHost.resolveModuleNames = (...args) => host.resolveModuleNames!(...args);
|
||||
}
|
||||
if (host.resolveTypeReferenceDirectives) {
|
||||
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile, redirectedReference) => {
|
||||
return host.resolveTypeReferenceDirectives!(typeReferenceDirectiveNames, containingFile, redirectedReference);
|
||||
};
|
||||
compilerHost.resolveTypeReferenceDirectives = (...args) => host.resolveTypeReferenceDirectives!(...args);
|
||||
}
|
||||
|
||||
const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);
|
||||
@@ -1561,7 +1565,7 @@ namespace ts {
|
||||
const normalizedFileName = normalizePath(fileName);
|
||||
Debug.assert(filesToSearch.some(f => normalizePath(f) === normalizedFileName));
|
||||
synchronizeHostData();
|
||||
const sourceFilesToSearch = filesToSearch.map(getValidSourceFile);
|
||||
const sourceFilesToSearch = mapDefined(filesToSearch, fileName => program.getSourceFile(fileName));
|
||||
const sourceFile = getValidSourceFile(fileName);
|
||||
return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace ts.SmartSelectionRange {
|
||||
break outer;
|
||||
}
|
||||
|
||||
if (positionShouldSnapToNode(pos, node, nextNode)) {
|
||||
if (positionShouldSnapToNode(sourceFile, pos, node)) {
|
||||
// 1. Blocks are effectively redundant with SyntaxLists.
|
||||
// 2. TemplateSpans, along with the SyntaxLists containing them, are a somewhat unintuitive grouping
|
||||
// of things that should be considered independently.
|
||||
@@ -64,6 +64,13 @@ namespace ts.SmartSelectionRange {
|
||||
parentNode = node;
|
||||
break;
|
||||
}
|
||||
|
||||
// If we made it to the end of the for loop, we’re done.
|
||||
// In practice, I’ve only seen this happen at the very end
|
||||
// of a SourceFile.
|
||||
if (i === children.length - 1) {
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,12 +97,11 @@ namespace ts.SmartSelectionRange {
|
||||
* count too, unless that position belongs to the next node. In effect, makes
|
||||
* selections able to snap to preceding tokens when the cursor is on the tail
|
||||
* end of them with only whitespace ahead.
|
||||
* @param sourceFile The source file containing the nodes.
|
||||
* @param pos The position to check.
|
||||
* @param node The candidate node to snap to.
|
||||
* @param nextNode The next sibling node in the tree.
|
||||
* @param sourceFile The source file containing the nodes.
|
||||
*/
|
||||
function positionShouldSnapToNode(pos: number, node: Node, nextNode: Node | undefined) {
|
||||
function positionShouldSnapToNode(sourceFile: SourceFile, pos: number, node: Node) {
|
||||
// Can’t use 'ts.positionBelongsToNode()' here because it cleverly accounts
|
||||
// for missing nodes, which can’t really be considered when deciding what
|
||||
// to select.
|
||||
@@ -104,9 +110,8 @@ namespace ts.SmartSelectionRange {
|
||||
return true;
|
||||
}
|
||||
const nodeEnd = node.getEnd();
|
||||
const nextNodeStart = nextNode && nextNode.getStart();
|
||||
if (nodeEnd === pos) {
|
||||
return pos !== nextNodeStart;
|
||||
return getTouchingPropertyName(sourceFile, pos).pos < node.end;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,15 @@ namespace ts {
|
||||
export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput {
|
||||
const diagnostics: Diagnostic[] = [];
|
||||
|
||||
const options: CompilerOptions = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : getDefaultCompilerOptions();
|
||||
const options: CompilerOptions = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : {};
|
||||
|
||||
// mix in default options
|
||||
const defaultOptions = getDefaultCompilerOptions();
|
||||
for (const key in defaultOptions) {
|
||||
if (hasProperty(defaultOptions, key) && options[key] === undefined) {
|
||||
options[key] = defaultOptions[key];
|
||||
}
|
||||
}
|
||||
|
||||
options.isolatedModules = true;
|
||||
|
||||
|
||||
@@ -211,9 +211,9 @@ namespace ts {
|
||||
*
|
||||
* If this is implemented, `getResolvedModuleWithFailedLookupLocationsFromCache` should be too.
|
||||
*/
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference): (ResolvedModule | undefined)[];
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedModule | undefined)[];
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedTypeReferenceDirective | undefined)[];
|
||||
/* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution;
|
||||
/* @internal */ hasChangedAutomaticTypeDirectiveNames?: boolean;
|
||||
|
||||
|
||||
@@ -967,6 +967,11 @@ namespace ts {
|
||||
readonly called: Identifier;
|
||||
readonly nTypeArguments: number;
|
||||
}
|
||||
|
||||
export interface PossibleProgramFileInfo {
|
||||
ProgramFiles?: string[];
|
||||
}
|
||||
|
||||
// Get info for an expression like `f <` that may be the start of type arguments.
|
||||
export function getPossibleTypeArgumentsInfo(tokenIn: Node, sourceFile: SourceFile): PossibleTypeArgumentInfo | undefined {
|
||||
let token: Node | undefined = tokenIn;
|
||||
|
||||
@@ -58,16 +58,18 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
public checkTestCodeOutput(fileName: string, test?: CompilerFileBasedTest) {
|
||||
if (test && test.configurations) {
|
||||
if (test && ts.some(test.configurations)) {
|
||||
test.configurations.forEach(configuration => {
|
||||
describe(`${this.testSuiteName} tests for ${fileName}${configuration ? ` (${Harness.getFileBasedTestConfigurationDescription(configuration)})` : ``}`, () => {
|
||||
this.runSuite(fileName, test, configuration);
|
||||
});
|
||||
});
|
||||
}
|
||||
describe(`${this.testSuiteName} tests for ${fileName}`, () => {
|
||||
this.runSuite(fileName, test);
|
||||
});
|
||||
else {
|
||||
describe(`${this.testSuiteName} tests for ${fileName}`, () => {
|
||||
this.runSuite(fileName, test);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private runSuite(fileName: string, test?: CompilerFileBasedTest, configuration?: Harness.FileBasedTestConfiguration) {
|
||||
@@ -112,6 +114,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
class CompilerTest {
|
||||
private fileName: string;
|
||||
private justName: string;
|
||||
private configuredName: string;
|
||||
private lastUnit: Harness.TestCaseParser.TestUnitData;
|
||||
private harnessSettings: Harness.TestCaseParser.CompilerSettings;
|
||||
private hasNonDtsFiles: boolean;
|
||||
@@ -126,6 +129,25 @@ class CompilerTest {
|
||||
constructor(fileName: string, testCaseContent?: Harness.TestCaseParser.TestCaseContent, configurationOverrides?: Harness.TestCaseParser.CompilerSettings) {
|
||||
this.fileName = fileName;
|
||||
this.justName = vpath.basename(fileName);
|
||||
this.configuredName = this.justName;
|
||||
if (configurationOverrides) {
|
||||
let configuredName = "";
|
||||
const keys = Object
|
||||
.keys(configurationOverrides)
|
||||
.map(k => k.toLowerCase())
|
||||
.sort();
|
||||
for (const key of keys) {
|
||||
if (configuredName) {
|
||||
configuredName += ",";
|
||||
}
|
||||
configuredName += `${key}=${configurationOverrides[key].toLowerCase()}`;
|
||||
}
|
||||
if (configuredName) {
|
||||
const extname = vpath.extname(this.justName);
|
||||
const basename = vpath.basename(this.justName, extname, /*ignoreCase*/ true);
|
||||
this.configuredName = `${basename}(${configuredName})${extname}`;
|
||||
}
|
||||
}
|
||||
|
||||
const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(fileName) + "/";
|
||||
|
||||
@@ -205,7 +227,7 @@ class CompilerTest {
|
||||
public verifyDiagnostics() {
|
||||
// check errors
|
||||
Harness.Compiler.doErrorBaseline(
|
||||
this.justName,
|
||||
this.configuredName,
|
||||
this.tsConfigFiles.concat(this.toBeCompiled, this.otherFiles),
|
||||
this.result.diagnostics,
|
||||
!!this.options.pretty);
|
||||
@@ -213,7 +235,7 @@ class CompilerTest {
|
||||
|
||||
public verifyModuleResolution() {
|
||||
if (this.options.traceResolution) {
|
||||
Harness.Baseline.runBaseline(this.justName.replace(/\.tsx?$/, ".trace.json"),
|
||||
Harness.Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".trace.json"),
|
||||
JSON.stringify(this.result.traces.map(utils.sanitizeTraceResolutionLogEntry), undefined, 4));
|
||||
}
|
||||
}
|
||||
@@ -225,14 +247,14 @@ class CompilerTest {
|
||||
// Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required.
|
||||
? null // tslint:disable-line no-null-keyword
|
||||
: record;
|
||||
Harness.Baseline.runBaseline(this.justName.replace(/\.tsx?$/, ".sourcemap.txt"), baseline);
|
||||
Harness.Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".sourcemap.txt"), baseline);
|
||||
}
|
||||
}
|
||||
|
||||
public verifyJavaScriptOutput() {
|
||||
if (this.hasNonDtsFiles) {
|
||||
Harness.Compiler.doJsEmitBaseline(
|
||||
this.justName,
|
||||
this.configuredName,
|
||||
this.fileName,
|
||||
this.options,
|
||||
this.result,
|
||||
@@ -245,7 +267,7 @@ class CompilerTest {
|
||||
|
||||
public verifySourceMapOutput() {
|
||||
Harness.Compiler.doSourcemapBaseline(
|
||||
this.justName,
|
||||
this.configuredName,
|
||||
this.options,
|
||||
this.result,
|
||||
this.harnessSettings);
|
||||
@@ -256,8 +278,15 @@ class CompilerTest {
|
||||
return;
|
||||
}
|
||||
|
||||
const noTypesAndSymbols =
|
||||
this.harnessSettings.noTypesAndSymbols &&
|
||||
this.harnessSettings.noTypesAndSymbols.toLowerCase() === "true";
|
||||
if (noTypesAndSymbols) {
|
||||
return;
|
||||
}
|
||||
|
||||
Harness.Compiler.doTypeAndSymbolBaseline(
|
||||
this.justName,
|
||||
this.configuredName,
|
||||
this.result.program!,
|
||||
this.toBeCompiled.concat(this.otherFiles).filter(file => !!this.result.program!.getSourceFile(file.unitName)),
|
||||
/*opts*/ undefined,
|
||||
|
||||
@@ -5,7 +5,7 @@ const del: typeof import("del") = require("del");
|
||||
interface ExecResult {
|
||||
stdout: Buffer;
|
||||
stderr: Buffer;
|
||||
status: number;
|
||||
status: number | null;
|
||||
}
|
||||
|
||||
interface UserConfig {
|
||||
@@ -185,7 +185,8 @@ function stripRushStageNumbers(result: string): string {
|
||||
* so we purge as much of the gulp output as we can
|
||||
*/
|
||||
function sanitizeUnimportantGulpOutput(result: string): string {
|
||||
return result.replace(/^.*(\] (Starting)|(Finished)).*$/gm, "") // task start/end messages (nondeterministic order)
|
||||
return result.replace(/^.*(\] (Starting)|(Finished)).*$/gm, "") // "gulp" task start/end messages (nondeterministic order)
|
||||
.replace(/^.*(\] . (finished)|(started)).*$/gm, "") // "just" task start/end messages (nondeterministic order)
|
||||
.replace(/^.*\] Respawned to PID: \d+.*$/gm, "") // PID of child is OS and system-load dependent (likely stableish in a container but still dangerous)
|
||||
.replace(/\n+/g, "\n");
|
||||
}
|
||||
@@ -193,14 +194,17 @@ function sanitizeUnimportantGulpOutput(result: string): string {
|
||||
function sanitizeTimestamps(result: string): string {
|
||||
return result.replace(/\[\d?\d:\d\d:\d\d (A|P)M\]/g, "[XX:XX:XX XM]")
|
||||
.replace(/\[\d?\d:\d\d:\d\d\]/g, "[XX:XX:XX]")
|
||||
.replace(/\/\d+-\d+-[\d_TZ]+-debug.log/g, "\/XXXX-XX-XXXXXXXXX-debug.log")
|
||||
.replace(/\d+(\.\d+)? sec(onds?)?/g, "? seconds")
|
||||
.replace(/\d+(\.\d+)? min(utes?)?/g, "")
|
||||
.replace(/\d+(\.\d+)?( m)?s/g, "?s");
|
||||
.replace(/\d+(\.\d+)? ?m?s/g, "?s")
|
||||
.replace(/ \(\?s\)/g, "");
|
||||
}
|
||||
|
||||
function sanitizeVersionSpecifiers(result: string): string {
|
||||
return result
|
||||
.replace(/\d+.\d+.\d+-insiders.\d\d\d\d\d\d\d\d/g, "X.X.X-insiders.xxxxxxxx")
|
||||
.replace(/Rush Multi-Project Build Tool (\d+)\.\d+\.\d+/g, "Rush Multi-Project Build Tool $1.X.X")
|
||||
.replace(/([@v\()])\d+\.\d+\.\d+/g, "$1X.X.X");
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
"unittests/semver.ts",
|
||||
"unittests/shimMap.ts",
|
||||
"unittests/transform.ts",
|
||||
"unittests/tsbuildWatchMode.ts",
|
||||
"unittests/config/commandLineParsing.ts",
|
||||
"unittests/config/configurationExtension.ts",
|
||||
"unittests/config/convertCompilerOptionsFromJson.ts",
|
||||
@@ -73,7 +72,10 @@
|
||||
"unittests/config/tsconfigParsing.ts",
|
||||
"unittests/evaluation/asyncArrow.ts",
|
||||
"unittests/evaluation/asyncGenerator.ts",
|
||||
"unittests/evaluation/awaiter.ts",
|
||||
"unittests/evaluation/forAwaitOf.ts",
|
||||
"unittests/evaluation/forOf.ts",
|
||||
"unittests/evaluation/objectRest.ts",
|
||||
"unittests/services/cancellableLanguageServiceOperations.ts",
|
||||
"unittests/services/colorization.ts",
|
||||
"unittests/services/convertToAsyncFunction.ts",
|
||||
@@ -96,11 +98,14 @@
|
||||
"unittests/tsbuild/inferredTypeFromTransitiveModule.ts",
|
||||
"unittests/tsbuild/lateBoundSymbol.ts",
|
||||
"unittests/tsbuild/missingExtendedFile.ts",
|
||||
"unittests/tsbuild/moduleSpecifiers.ts",
|
||||
"unittests/tsbuild/outFile.ts",
|
||||
"unittests/tsbuild/referencesWithRootDirInParent.ts",
|
||||
"unittests/tsbuild/resolveJsonModule.ts",
|
||||
"unittests/tsbuild/sample.ts",
|
||||
"unittests/tsbuild/transitiveReferences.ts",
|
||||
"unittests/tsbuild/watchEnvironment.ts",
|
||||
"unittests/tsbuild/watchMode.ts",
|
||||
"unittests/tscWatch/consoleClearing.ts",
|
||||
"unittests/tscWatch/emit.ts",
|
||||
"unittests/tscWatch/emitAndErrorUpdates.ts",
|
||||
@@ -128,6 +133,7 @@
|
||||
"unittests/tsserver/formatSettings.ts",
|
||||
"unittests/tsserver/getApplicableRefactors.ts",
|
||||
"unittests/tsserver/getEditsForFileRename.ts",
|
||||
"unittests/tsserver/getExportReferences.ts",
|
||||
"unittests/tsserver/importHelpers.ts",
|
||||
"unittests/tsserver/inferredProjects.ts",
|
||||
"unittests/tsserver/languageService.ts",
|
||||
|
||||
@@ -348,5 +348,4 @@ namespace ts {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,26 @@ namespace ts {
|
||||
|
||||
showTSConfigCorrectly("Show TSConfig with advanced options", ["--showConfig", "--declaration", "--declarationDir", "lib", "--skipLibCheck", "--noErrorTruncation"]);
|
||||
|
||||
showTSConfigCorrectly("Show TSConfig with compileOnSave and more", ["-p", "tsconfig.json"], {
|
||||
compilerOptions: {
|
||||
esModuleInterop: true,
|
||||
target: "es5",
|
||||
module: "commonjs",
|
||||
strict: true,
|
||||
},
|
||||
compileOnSave: true,
|
||||
exclude: [
|
||||
"dist"
|
||||
],
|
||||
files: [],
|
||||
include: [
|
||||
"src/*"
|
||||
],
|
||||
references: [
|
||||
{ path: "./test" }
|
||||
],
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/Microsoft/TypeScript/issues/28836
|
||||
showTSConfigCorrectly("Show TSConfig with paths and more", ["-p", "tsconfig.json"], {
|
||||
compilerOptions: {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
describe("unittests:: evaluation:: awaiter", () => {
|
||||
// NOTE: This could break if the ECMAScript spec ever changes the timing behavior for Promises (again)
|
||||
it("await (es5)", async () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
async function a(msg: string) {
|
||||
await Promise.resolve();
|
||||
output.push(msg);
|
||||
}
|
||||
function b(msg: string) {
|
||||
return Promise.resolve().then(() => {
|
||||
output.push(msg);
|
||||
});
|
||||
}
|
||||
export const output: string[] = [];
|
||||
export async function main() {
|
||||
const p1 = a('1');
|
||||
const p2 = b('2');
|
||||
await Promise.all([p1, p2]);
|
||||
}
|
||||
`);
|
||||
await result.main();
|
||||
assert.deepEqual(result.output, ["1", "2"]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,119 @@
|
||||
describe("unittests:: evaluation:: forOfEvaluation", () => {
|
||||
it("es5 over a array with no Symbol", () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
Symbol = undefined;
|
||||
export var output = [];
|
||||
export function main() {
|
||||
let x = [1,2,3];
|
||||
|
||||
for (let value of x) {
|
||||
output.push(value);
|
||||
}
|
||||
}
|
||||
`, { downlevelIteration: true, target: ts.ScriptTarget.ES5 });
|
||||
|
||||
result.main();
|
||||
|
||||
assert.strictEqual(result.output[0], 1);
|
||||
assert.strictEqual(result.output[1], 2);
|
||||
assert.strictEqual(result.output[2], 3);
|
||||
|
||||
});
|
||||
|
||||
it("es5 over a string with no Symbol", () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
Symbol = undefined;
|
||||
export var output = [];
|
||||
export function main() {
|
||||
let x = "hello";
|
||||
|
||||
for (let value of x) {
|
||||
output.push(value);
|
||||
}
|
||||
}
|
||||
`, { downlevelIteration: true, target: ts.ScriptTarget.ES5 });
|
||||
|
||||
result.main();
|
||||
|
||||
assert.strictEqual(result.output[0], "h");
|
||||
assert.strictEqual(result.output[1], "e");
|
||||
assert.strictEqual(result.output[2], "l");
|
||||
assert.strictEqual(result.output[3], "l");
|
||||
assert.strictEqual(result.output[4], "o");
|
||||
});
|
||||
|
||||
it("es5 over undefined with no Symbol", () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
Symbol = undefined;
|
||||
export function main() {
|
||||
let x = undefined;
|
||||
|
||||
for (let value of x) {
|
||||
}
|
||||
}
|
||||
`, { downlevelIteration: true, target: ts.ScriptTarget.ES5 });
|
||||
|
||||
assert.throws(() => result.main(), "Symbol.iterator is not defined");
|
||||
});
|
||||
|
||||
it("es5 over undefined with Symbol", () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
export function main() {
|
||||
let x = undefined;
|
||||
|
||||
for (let value of x) {
|
||||
}
|
||||
}
|
||||
`, { downlevelIteration: true, target: ts.ScriptTarget.ES5 });
|
||||
|
||||
assert.throws(() => result.main(), /cannot read property.*Symbol\(Symbol\.iterator\).*/i);
|
||||
});
|
||||
|
||||
it("es5 over object with no Symbol.iterator with no Symbol", () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
Symbol = undefined;
|
||||
export function main() {
|
||||
let x = {} as any;
|
||||
|
||||
for (let value of x) {
|
||||
}
|
||||
}
|
||||
`, { downlevelIteration: true, target: ts.ScriptTarget.ES5 });
|
||||
|
||||
assert.throws(() => result.main(), "Symbol.iterator is not defined");
|
||||
});
|
||||
|
||||
it("es5 over object with no Symbol.iterator with Symbol", () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
export function main() {
|
||||
let x = {} as any;
|
||||
|
||||
for (let value of x) {
|
||||
}
|
||||
}
|
||||
`, { downlevelIteration: true, target: ts.ScriptTarget.ES5 });
|
||||
|
||||
assert.throws(() => result.main(), "Object is not iterable");
|
||||
});
|
||||
|
||||
it("es5 over object with Symbol.iterator", () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
export var output = [];
|
||||
export function main() {
|
||||
let thing : any = {};
|
||||
thing[Symbol.iterator] = () => {
|
||||
let i = 0;
|
||||
return { next() { i++; return this; }, value: i, done: i < 10 };
|
||||
};
|
||||
|
||||
for (let value of thing)
|
||||
{
|
||||
output.push(value)
|
||||
}
|
||||
|
||||
}`, { downlevelIteration: true, target: ts.ScriptTarget.ES5 });
|
||||
|
||||
result.main();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
describe("unittests:: evaluation:: objectRest", () => {
|
||||
// https://github.com/microsoft/TypeScript/issues/31469
|
||||
it("side effects in property assignment", async () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
const k = { a: 1, b: 2 };
|
||||
const o = { a: 3, ...k, b: k.a++ };
|
||||
export const output = o;
|
||||
`);
|
||||
assert.deepEqual(result.output, { a: 1, b: 1 });
|
||||
});
|
||||
it("side effects in during spread", async () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
const k = { a: 1, get b() { l = { c: 9 }; return 2; } };
|
||||
let l = { c: 3 };
|
||||
const o = { ...k, ...l };
|
||||
export const output = o;
|
||||
`);
|
||||
assert.deepEqual(result.output, { a: 1, b: 2, c: 9 });
|
||||
});
|
||||
it("trailing literal-valued object-literal", async () => {
|
||||
const result = evaluator.evaluateTypeScript(`
|
||||
const k = { a: 1 }
|
||||
const o = { ...k, ...{ b: 2 } };
|
||||
export const output = o;
|
||||
`);
|
||||
assert.deepEqual(result.output, { a: 1, b: 2 });
|
||||
});
|
||||
});
|
||||
@@ -31,3 +31,18 @@ describe("Public APIs", () => {
|
||||
verifyApi("tsserverlibrary.d.ts");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Public APIs:: token to string", () => {
|
||||
function assertDefinedTokenToString(initial: ts.SyntaxKind, last: ts.SyntaxKind) {
|
||||
for (let t = initial; t <= last; t++) {
|
||||
assert.isDefined(ts.tokenToString(t), `Expected tokenToString defined for ${ts.Debug.formatSyntaxKind(t)}`);
|
||||
}
|
||||
}
|
||||
|
||||
it("for punctuations", () => {
|
||||
assertDefinedTokenToString(ts.SyntaxKind.FirstPunctuation, ts.SyntaxKind.LastPunctuation);
|
||||
});
|
||||
it("for keywords", () => {
|
||||
assertDefinedTokenToString(ts.SyntaxKind.FirstKeyword, ts.SyntaxKind.LastKeyword);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,6 +38,18 @@ namespace ts {
|
||||
verifyNewLines(content, { newLine: NewLineKind.LineFeed });
|
||||
}
|
||||
|
||||
function verifyOutliningSpanNewLines(content: string, options: CompilerOptions) {
|
||||
const ls = testLSWithFiles(options, [{
|
||||
content,
|
||||
fileOptions: {},
|
||||
unitName: "input.ts"
|
||||
}]);
|
||||
const span = ls.getOutliningSpans("input.ts")[0];
|
||||
const textAfterSpanCollapse = content.substring(span.textSpan.start + span.textSpan.length);
|
||||
assert(textAfterSpanCollapse.match(options.newLine === NewLineKind.CarriageReturnLineFeed ? /\r\n/ : /[^\r]\n/), "expected to find appropriate newlines");
|
||||
assert(!textAfterSpanCollapse.match(options.newLine === NewLineKind.CarriageReturnLineFeed ? /[^\r]\n/ : /\r\n/), "expected not to find inappropriate newlines");
|
||||
}
|
||||
|
||||
it("should exist and respect provided compiler options", () => {
|
||||
verifyBothNewLines(`
|
||||
function foo() {
|
||||
@@ -45,5 +57,15 @@ namespace ts {
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it("should respect CRLF line endings around outlining spans", () => {
|
||||
verifyOutliningSpanNewLines("// comment not included\r\n// #region name\r\nlet x: string = \"x\";\r\n// #endregion name\r\n",
|
||||
{ newLine: NewLineKind.CarriageReturnLineFeed });
|
||||
});
|
||||
|
||||
it("should respect LF line endings around outlining spans", () => {
|
||||
verifyOutliningSpanNewLines("// comment not included\n// #region name\nlet x: string = \"x\";\n// #endregion name\n\n",
|
||||
{ newLine: NewLineKind.LineFeed });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@ namespace ts {
|
||||
|
||||
transpileOptions = testSettings.options || {};
|
||||
if (!transpileOptions.compilerOptions) {
|
||||
transpileOptions.compilerOptions = {};
|
||||
transpileOptions.compilerOptions = { };
|
||||
}
|
||||
if (transpileOptions.compilerOptions.target === undefined) {
|
||||
transpileOptions.compilerOptions.target = ScriptTarget.ES3;
|
||||
}
|
||||
|
||||
if (transpileOptions.compilerOptions.newLine === undefined) {
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
namespace ts {
|
||||
// https://github.com/microsoft/TypeScript/issues/31696
|
||||
it("unittests:: tsbuild:: moduleSpecifiers:: synthesized module specifiers to referenced projects resolve correctly", () => {
|
||||
const baseFs = vfs.createFromFileSystem(Harness.IO, /*ignoreCase*/ false, {
|
||||
files: {
|
||||
"/src/common/nominal.ts": utils.dedent`
|
||||
export declare type Nominal<T, Name extends string> = T & {
|
||||
[Symbol.species]: Name;
|
||||
};
|
||||
`,
|
||||
"/src/common/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"include": ["nominal.ts"]
|
||||
}`,
|
||||
"/src/sub-project/index.ts": utils.dedent`
|
||||
import { Nominal } from '../common/nominal';
|
||||
|
||||
export type MyNominal = Nominal<string, 'MyNominal'>;
|
||||
`,
|
||||
"/src/sub-project/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../common" }
|
||||
],
|
||||
"include": ["./index.ts"]
|
||||
}`,
|
||||
"/src/sub-project-2/index.ts": utils.dedent`
|
||||
import { MyNominal } from '../sub-project/index';
|
||||
|
||||
const variable = {
|
||||
key: 'value' as MyNominal,
|
||||
};
|
||||
|
||||
export function getVar(): keyof typeof variable {
|
||||
return 'key';
|
||||
}
|
||||
`,
|
||||
"/src/sub-project-2/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../sub-project" }
|
||||
],
|
||||
"include": ["./index.ts"]
|
||||
}`,
|
||||
"/src/tsconfig.json": utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "./sub-project" },
|
||||
{ "path": "./sub-project-2" }
|
||||
],
|
||||
"include": []
|
||||
}`,
|
||||
"/tsconfig.base.json": utils.dedent`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"rootDir": "./",
|
||||
"outDir": "lib",
|
||||
"lib": ["dom", "es2015", "es2015.symbol.wellknown"]
|
||||
}
|
||||
}`,
|
||||
"/tsconfig.json": utils.dedent`{
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{ "path": "./src" }
|
||||
],
|
||||
"include": []
|
||||
}`
|
||||
},
|
||||
cwd: "/"
|
||||
});
|
||||
const fs = baseFs.makeReadonly().shadow();
|
||||
const sys = new fakes.System(fs, { executingFilePath: "/", newLine: "\n" });
|
||||
const host = new fakes.SolutionBuilderHost(sys);
|
||||
const builder = createSolutionBuilder(host, ["/tsconfig.json"], { dry: false, force: false, verbose: false });
|
||||
builder.build();
|
||||
|
||||
// Prior to fixing GH31696 the import in `/lib/src/sub-project-2/index.d.ts` was `import("../../lib/src/common/nonterminal")`, which was invalid.
|
||||
Harness.Baseline.runBaseline("tsbuild/moduleSpecifiers/initial-build/resolves-correctly.js", vfs.formatPatch(fs.diff(baseFs)));
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
namespace ts.tscWatch {
|
||||
describe("unittests:: tsbuild:: watchEnvironment:: tsbuild:: watchMode:: with different watch environments", () => {
|
||||
describe("when watchFile can create multiple watchers per file", () => {
|
||||
verifyWatchFileOnMultipleProjects(/*singleWatchPerFile*/ false);
|
||||
});
|
||||
|
||||
describe("when watchFile is single watcher per file", () => {
|
||||
verifyWatchFileOnMultipleProjects(
|
||||
/*singleWatchPerFile*/ true,
|
||||
arrayToMap(["TSC_WATCHFILE"], identity, () => TestFSWithWatch.Tsc_WatchFile.SingleFileWatcherPerName)
|
||||
);
|
||||
});
|
||||
|
||||
function verifyWatchFileOnMultipleProjects(singleWatchPerFile: boolean, environmentVariables?: Map<string>) {
|
||||
it("watchFile on same file multiple times because file is part of multiple projects", () => {
|
||||
const project = `${TestFSWithWatch.tsbuildProjectsLocation}/myproject`;
|
||||
let maxPkgs = 4;
|
||||
const configPath = `${project}/tsconfig.json`;
|
||||
const typing: File = {
|
||||
path: `${project}/typings/xterm.d.ts`,
|
||||
content: "export const typing = 10;"
|
||||
};
|
||||
|
||||
const allPkgFiles = pkgs(pkgFiles);
|
||||
const system = createWatchedSystem([libFile, typing, ...flatArray(allPkgFiles)], { currentDirectory: project, environmentVariables });
|
||||
writePkgReferences();
|
||||
const host = createSolutionBuilderWithWatchHost(system);
|
||||
const solutionBuilder = createSolutionBuilderWithWatch(host, ["tsconfig.json"], { watch: true, verbose: true });
|
||||
solutionBuilder.build();
|
||||
checkOutputErrorsInitial(system, emptyArray, /*disableConsoleClears*/ undefined, [
|
||||
`Projects in this build: \r\n${
|
||||
concatenate(
|
||||
pkgs(index => ` * pkg${index}/tsconfig.json`),
|
||||
[" * tsconfig.json"]
|
||||
).join("\r\n")}\n\n`,
|
||||
...flatArray(pkgs(index => [
|
||||
`Project 'pkg${index}/tsconfig.json' is out of date because output file 'pkg${index}/index.js' does not exist\n\n`,
|
||||
`Building project '${project}/pkg${index}/tsconfig.json'...\n\n`
|
||||
]))
|
||||
]);
|
||||
|
||||
const watchFilesDetailed = arrayToMap(flatArray(allPkgFiles), f => f.path, () => 1);
|
||||
watchFilesDetailed.set(configPath, 1);
|
||||
watchFilesDetailed.set(typing.path, singleWatchPerFile ? 1 : maxPkgs);
|
||||
checkWatchedFilesDetailed(system, watchFilesDetailed);
|
||||
system.writeFile(typing.path, `${typing.content}export const typing1 = 10;`);
|
||||
verifyInvoke();
|
||||
|
||||
// Make change
|
||||
maxPkgs--;
|
||||
writePkgReferences();
|
||||
system.checkTimeoutQueueLengthAndRun(1);
|
||||
checkOutputErrorsIncremental(system, emptyArray);
|
||||
const lastFiles = last(allPkgFiles);
|
||||
lastFiles.forEach(f => watchFilesDetailed.delete(f.path));
|
||||
watchFilesDetailed.set(typing.path, singleWatchPerFile ? 1 : maxPkgs);
|
||||
checkWatchedFilesDetailed(system, watchFilesDetailed);
|
||||
system.writeFile(typing.path, typing.content);
|
||||
verifyInvoke();
|
||||
|
||||
// Make change to remove all the watches
|
||||
maxPkgs = 0;
|
||||
writePkgReferences();
|
||||
system.checkTimeoutQueueLengthAndRun(1);
|
||||
checkOutputErrorsIncremental(system, [
|
||||
`tsconfig.json(1,10): error TS18002: The 'files' list in config file '${configPath}' is empty.\n`
|
||||
]);
|
||||
checkWatchedFilesDetailed(system, [configPath], 1);
|
||||
|
||||
system.writeFile(typing.path, `${typing.content}export const typing1 = 10;`);
|
||||
system.checkTimeoutQueueLength(0);
|
||||
|
||||
function flatArray<T>(arr: T[][]): readonly T[] {
|
||||
return flatMap(arr, identity);
|
||||
}
|
||||
function pkgs<T>(cb: (index: number) => T): T[] {
|
||||
const result: T[] = [];
|
||||
for (let index = 0; index < maxPkgs; index++) {
|
||||
result.push(cb(index));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function createPkgReference(index: number) {
|
||||
return { path: `./pkg${index}` };
|
||||
}
|
||||
function pkgFiles(index: number): File[] {
|
||||
return [
|
||||
{
|
||||
path: `${project}/pkg${index}/index.ts`,
|
||||
content: `export const pkg${index} = ${index};`
|
||||
},
|
||||
{
|
||||
path: `${project}/pkg${index}/tsconfig.json`,
|
||||
content: JSON.stringify({
|
||||
complerOptions: { composite: true },
|
||||
include: [
|
||||
"**/*.ts",
|
||||
"../typings/xterm.d.ts"
|
||||
]
|
||||
})
|
||||
}
|
||||
];
|
||||
}
|
||||
function writePkgReferences() {
|
||||
system.writeFile(configPath, JSON.stringify({
|
||||
files: [],
|
||||
include: [],
|
||||
references: pkgs(createPkgReference)
|
||||
}));
|
||||
}
|
||||
function verifyInvoke() {
|
||||
pkgs(() => system.checkTimeoutQueueLengthAndRun(1));
|
||||
checkOutputErrorsIncremental(system, emptyArray, /*disableConsoleClears*/ undefined, /*logsBeforeWatchDiagnostics*/ undefined, [
|
||||
...flatArray(pkgs(index => [
|
||||
`Project 'pkg${index}/tsconfig.json' is out of date because oldest output 'pkg${index}/index.js' is older than newest input 'typings/xterm.d.ts'\n\n`,
|
||||
`Building project '${project}/pkg${index}/tsconfig.json'...\n\n`,
|
||||
`Updating unchanged output timestamps of project '${project}/pkg${index}/tsconfig.json'...\n\n`
|
||||
]))
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
+58
-28
@@ -16,11 +16,19 @@ namespace ts.tscWatch {
|
||||
return host;
|
||||
}
|
||||
|
||||
|
||||
export function createSolutionBuilder(system: WatchedSystem, rootNames: ReadonlyArray<string>, defaultOptions?: BuildOptions) {
|
||||
const host = createSolutionBuilderHost(system);
|
||||
host.now = system.now.bind(system);
|
||||
return ts.createSolutionBuilder(host, rootNames, defaultOptions || {});
|
||||
}
|
||||
|
||||
export function createSolutionBuilderWithWatchHost(system: WatchedSystem) {
|
||||
const host = ts.createSolutionBuilderWithWatchHost(system);
|
||||
host.now = system.now.bind(system);
|
||||
return host;
|
||||
}
|
||||
|
||||
function createSolutionBuilderWithWatch(system: TsBuildWatchSystem, rootNames: ReadonlyArray<string>, defaultOptions?: BuildOptions) {
|
||||
const host = createSolutionBuilderWithWatchHost(system);
|
||||
const solutionBuilder = ts.createSolutionBuilderWithWatch(host, rootNames, defaultOptions || { watch: true });
|
||||
@@ -33,7 +41,7 @@ namespace ts.tscWatch {
|
||||
return [f, host.getModifiedTime(f), host.writtenFiles.has(host.toFullPath(f))] as OutputFileStamp;
|
||||
}
|
||||
|
||||
describe("unittests:: tsbuild-watch program updates", () => {
|
||||
describe("unittests:: tsbuild:: watchMode:: program updates", () => {
|
||||
const project = "sample1";
|
||||
const enum SubProject {
|
||||
core = "core",
|
||||
@@ -113,13 +121,33 @@ namespace ts.tscWatch {
|
||||
}
|
||||
}
|
||||
|
||||
const core = subProjectFiles(SubProject.core, /*anotherModuleAndSomeDecl*/ true);
|
||||
const logic = subProjectFiles(SubProject.logic);
|
||||
const tests = subProjectFiles(SubProject.tests);
|
||||
const ui = subProjectFiles(SubProject.ui);
|
||||
const allFiles: ReadonlyArray<File> = [libFile, ...core, ...logic, ...tests, ...ui];
|
||||
const testProjectExpectedWatchedFiles = [core[0], core[1], core[2]!, ...logic, ...tests].map(f => f.path.toLowerCase()); // tslint:disable-line no-unnecessary-type-assertion (TODO: type assertion should be necessary)
|
||||
const testProjectExpectedWatchedDirectoriesRecursive = [projectPath(SubProject.core), projectPath(SubProject.logic)];
|
||||
let core: SubProjectFiles;
|
||||
let logic: SubProjectFiles;
|
||||
let tests: SubProjectFiles;
|
||||
let ui: SubProjectFiles;
|
||||
let allFiles: ReadonlyArray<File>;
|
||||
let testProjectExpectedWatchedFiles: string[];
|
||||
let testProjectExpectedWatchedDirectoriesRecursive: string[];
|
||||
|
||||
before(() => {
|
||||
core = subProjectFiles(SubProject.core, /*anotherModuleAndSomeDecl*/ true);
|
||||
logic = subProjectFiles(SubProject.logic);
|
||||
tests = subProjectFiles(SubProject.tests);
|
||||
ui = subProjectFiles(SubProject.ui);
|
||||
allFiles = [libFile, ...core, ...logic, ...tests, ...ui];
|
||||
testProjectExpectedWatchedFiles = [core[0], core[1], core[2]!, ...logic, ...tests].map(f => f.path.toLowerCase()); // tslint:disable-line no-unnecessary-type-assertion (TODO: type assertion should be necessary)
|
||||
testProjectExpectedWatchedDirectoriesRecursive = [projectPath(SubProject.core), projectPath(SubProject.logic)];
|
||||
});
|
||||
|
||||
after(() => {
|
||||
core = undefined!;
|
||||
logic = undefined!;
|
||||
tests = undefined!;
|
||||
ui = undefined!;
|
||||
allFiles = undefined!;
|
||||
testProjectExpectedWatchedFiles = undefined!;
|
||||
testProjectExpectedWatchedDirectoriesRecursive = undefined!;
|
||||
});
|
||||
|
||||
function createSolutionInWatchMode(allFiles: ReadonlyArray<File>, defaultOptions?: BuildOptions, disableConsoleClears?: boolean) {
|
||||
const host = createTsBuildWatchSystem(allFiles, { currentDirectory: projectsLocation });
|
||||
@@ -172,9 +200,9 @@ namespace ts.tscWatch {
|
||||
content: `export const newFileConst = 30;`
|
||||
};
|
||||
|
||||
function verifyProjectChanges(allFiles: ReadonlyArray<File>) {
|
||||
function verifyProjectChanges(allFilesGetter: () => ReadonlyArray<File>) {
|
||||
function createSolutionInWatchModeToVerifyChanges(additionalFiles?: ReadonlyArray<[SubProject, string]>) {
|
||||
const host = createSolutionInWatchMode(allFiles);
|
||||
const host = createSolutionInWatchMode(allFilesGetter());
|
||||
return { host, verifyChangeWithFile, verifyChangeAfterTimeout, verifyWatches };
|
||||
|
||||
function verifyChangeWithFile(fileName: string, content: string, local?: boolean) {
|
||||
@@ -277,19 +305,21 @@ export class someClass2 { }`);
|
||||
}
|
||||
|
||||
describe("with simple project reference graph", () => {
|
||||
verifyProjectChanges(allFiles);
|
||||
verifyProjectChanges(() => allFiles);
|
||||
});
|
||||
|
||||
describe("with circular project reference", () => {
|
||||
const [coreTsconfig, ...otherCoreFiles] = core;
|
||||
const circularCoreConfig: File = {
|
||||
path: coreTsconfig.path,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: { composite: true, declaration: true },
|
||||
references: [{ path: "../tests", circular: true }]
|
||||
})
|
||||
};
|
||||
verifyProjectChanges([libFile, circularCoreConfig, ...otherCoreFiles, ...logic, ...tests]);
|
||||
verifyProjectChanges(() => {
|
||||
const [coreTsconfig, ...otherCoreFiles] = core;
|
||||
const circularCoreConfig: File = {
|
||||
path: coreTsconfig.path,
|
||||
content: JSON.stringify({
|
||||
compilerOptions: { composite: true, declaration: true },
|
||||
references: [{ path: "../tests", circular: true }]
|
||||
})
|
||||
};
|
||||
return [libFile, circularCoreConfig, ...otherCoreFiles, ...logic, ...tests];
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -681,9 +711,9 @@ let x: string = 10;`);
|
||||
const coreIndexDts = projectFileName(SubProject.core, "index.d.ts");
|
||||
const coreAnotherModuleDts = projectFileName(SubProject.core, "anotherModule.d.ts");
|
||||
const logicIndexDts = projectFileName(SubProject.logic, "index.d.ts");
|
||||
const expectedWatchedFiles = [core[0], logic[0], ...tests, libFile].map(f => f.path).concat([coreIndexDts, coreAnotherModuleDts, logicIndexDts].map(f => f.toLowerCase()));
|
||||
const expectedWatchedFiles = () => [core[0], logic[0], ...tests, libFile].map(f => f.path).concat([coreIndexDts, coreAnotherModuleDts, logicIndexDts].map(f => f.toLowerCase()));
|
||||
const expectedWatchedDirectoriesRecursive = projectSystem.getTypeRootsFromLocation(projectPath(SubProject.tests));
|
||||
const expectedProgramFiles = [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, logicIndexDts];
|
||||
const expectedProgramFiles = () => [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, logicIndexDts];
|
||||
|
||||
function createSolutionAndWatchMode() {
|
||||
return createSolutionAndWatchModeOfProject(allFiles, projectsLocation, `${project}/${SubProject.tests}`, tests[0].path, getOutputFileStamps);
|
||||
@@ -694,12 +724,12 @@ let x: string = 10;`);
|
||||
}
|
||||
|
||||
function verifyWatches(host: TsBuildWatchSystem, withTsserver?: boolean) {
|
||||
verifyWatchesOfProject(host, withTsserver ? expectedWatchedFiles.filter(f => f !== tests[1].path.toLowerCase()) : expectedWatchedFiles, expectedWatchedDirectoriesRecursive);
|
||||
verifyWatchesOfProject(host, withTsserver ? expectedWatchedFiles().filter(f => f !== tests[1].path.toLowerCase()) : expectedWatchedFiles(), expectedWatchedDirectoriesRecursive);
|
||||
}
|
||||
|
||||
function verifyScenario(
|
||||
edit: (host: TsBuildWatchSystem, solutionBuilder: SolutionBuilder<EmitAndSemanticDiagnosticsBuilderProgram>) => void,
|
||||
expectedFilesAfterEdit: ReadonlyArray<string>
|
||||
expectedFilesAfterEdit: () => ReadonlyArray<string>
|
||||
) {
|
||||
it("with tsc-watch", () => {
|
||||
const { host, solutionBuilder, watch } = createSolutionAndWatchMode();
|
||||
@@ -708,7 +738,7 @@ let x: string = 10;`);
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(1);
|
||||
checkOutputErrorsIncremental(host, emptyArray);
|
||||
checkProgramActualFiles(watch(), expectedFilesAfterEdit);
|
||||
checkProgramActualFiles(watch(), expectedFilesAfterEdit());
|
||||
|
||||
});
|
||||
|
||||
@@ -718,7 +748,7 @@ let x: string = 10;`);
|
||||
edit(host, solutionBuilder);
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(2);
|
||||
checkProjectActualFiles(service, tests[0].path, [tests[0].path, ...expectedFilesAfterEdit]);
|
||||
checkProjectActualFiles(service, tests[0].path, [tests[0].path, ...expectedFilesAfterEdit()]);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -729,7 +759,7 @@ let x: string = 10;`);
|
||||
verifyDependencies(watch, coreIndexDts, [coreIndexDts]);
|
||||
verifyDependencies(watch, coreAnotherModuleDts, [coreAnotherModuleDts]);
|
||||
verifyDependencies(watch, logicIndexDts, [logicIndexDts, coreAnotherModuleDts]);
|
||||
verifyDependencies(watch, tests[1].path, expectedProgramFiles.filter(f => f !== libFile.path));
|
||||
verifyDependencies(watch, tests[1].path, expectedProgramFiles().filter(f => f !== libFile.path));
|
||||
});
|
||||
|
||||
it("with tsserver", () => {
|
||||
@@ -769,7 +799,7 @@ export function gfoo() {
|
||||
}));
|
||||
solutionBuilder.invalidateProject(logic[0].path.toLowerCase() as ResolvedConfigFilePath, ConfigFileProgramReloadLevel.Full);
|
||||
solutionBuilder.buildNextInvalidatedProject();
|
||||
}, [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, projectFilePath(SubProject.logic, "decls/index.d.ts")]);
|
||||
}, () => [tests[1].path, libFile.path, coreIndexDts, coreAnotherModuleDts, projectFilePath(SubProject.logic, "decls/index.d.ts")]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ts.tscWatch {
|
||||
};
|
||||
const files = [file1, libFile];
|
||||
const environmentVariables = createMap<string>();
|
||||
environmentVariables.set("TSC_WATCHFILE", "DynamicPriorityPolling");
|
||||
environmentVariables.set("TSC_WATCHFILE", TestFSWithWatch.Tsc_WatchFile.DynamicPolling);
|
||||
const host = createWatchedSystem(files, { environmentVariables });
|
||||
const watch = createWatchOfFilesAndCompilerOptions([file1.path], host);
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace ts.projectSystem {
|
||||
assert.isTrue(false, `should not find file '${imported.path}'`);
|
||||
}
|
||||
catch (e) {
|
||||
assert.isTrue(e.message.indexOf(`Could not find sourceFile: '${imported.path}' in ["${root.path}"].`) === 0, `Actual: ${e.message}`);
|
||||
assert.isTrue(e.message.indexOf(`Could not find source file: '${imported.path}'.`) === 0, `Actual: ${e.message}`);
|
||||
}
|
||||
const f2Lookups = getLocationsForModuleLookup("f2");
|
||||
callsTrackingHost.verifyCalledOnEachEntryNTimes(CalledMapsWithSingleArg.fileExists, f2Lookups, 1);
|
||||
|
||||
@@ -503,6 +503,112 @@ namespace ts.projectSystem {
|
||||
});
|
||||
});
|
||||
|
||||
describe("for changes in declaration files", () => {
|
||||
function testDTS(dtsFileContents: string, tsFileContents: string, opts: CompilerOptions, expectDTSEmit: boolean) {
|
||||
const dtsFile = {
|
||||
path: "/a/runtime/a.d.ts",
|
||||
content: dtsFileContents
|
||||
};
|
||||
const f2 = {
|
||||
path: "/a/b.ts",
|
||||
content: tsFileContents
|
||||
};
|
||||
const config = {
|
||||
path: "/a/tsconfig.json",
|
||||
content: JSON.stringify({
|
||||
compilerOptions: opts,
|
||||
compileOnSave: true
|
||||
})
|
||||
};
|
||||
const host = createServerHost([dtsFile, f2, config]);
|
||||
const session = projectSystem.createSession(host);
|
||||
session.executeCommand(<protocol.OpenRequest>{
|
||||
seq: 1,
|
||||
type: "request",
|
||||
command: "open",
|
||||
arguments: { file: dtsFile.path }
|
||||
});
|
||||
const projectService = session.getProjectService();
|
||||
checkNumberOfProjects(projectService, { configuredProjects: 1 });
|
||||
const project = projectService.configuredProjects.get(config.path)!;
|
||||
checkProjectRootFiles(project, [dtsFile.path, f2.path]);
|
||||
session.executeCommand(<protocol.OpenRequest>{
|
||||
seq: 2,
|
||||
type: "request",
|
||||
command: "open",
|
||||
arguments: { file: f2.path }
|
||||
});
|
||||
checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 });
|
||||
const { response } = session.executeCommand(<protocol.CompileOnSaveAffectedFileListRequest>{
|
||||
seq: 3,
|
||||
type: "request",
|
||||
command: "compileOnSaveAffectedFileList",
|
||||
arguments: { file: dtsFile.path }
|
||||
});
|
||||
if (expectDTSEmit) {
|
||||
assert.equal((response as protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output from 1 project");
|
||||
assert.equal((response as protocol.CompileOnSaveAffectedFileListSingleProject[])[0].fileNames.length, 2, "expected to affect 2 files");
|
||||
}
|
||||
else {
|
||||
assert.equal((response as protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 0, "expected no output");
|
||||
}
|
||||
|
||||
|
||||
const { response: response2 } = session.executeCommand(<protocol.CompileOnSaveAffectedFileListRequest>{
|
||||
seq: 4,
|
||||
type: "request",
|
||||
command: "compileOnSaveAffectedFileList",
|
||||
arguments: { file: f2.path }
|
||||
});
|
||||
assert.equal((response2 as protocol.CompileOnSaveAffectedFileListSingleProject[]).length, 1, "expected output from 1 project");
|
||||
}
|
||||
|
||||
it("should return empty array if change is made in a global declaration file", () => {
|
||||
testDTS(
|
||||
/*dtsFileContents*/ "declare const x: string;",
|
||||
/*tsFileContents*/ "var y = 1;",
|
||||
/*opts*/ {},
|
||||
/*expectDTSEmit*/ false
|
||||
);
|
||||
});
|
||||
|
||||
it("should return empty array if change is made in a module declaration file", () => {
|
||||
testDTS(
|
||||
/*dtsFileContents*/ "export const x: string;",
|
||||
/*tsFileContents*/ "import { x } from './runtime/a;",
|
||||
/*opts*/ {},
|
||||
/*expectDTSEmit*/ false
|
||||
);
|
||||
});
|
||||
|
||||
it("should return results if change is made in a global declaration file with declaration emit", () => {
|
||||
testDTS(
|
||||
/*dtsFileContents*/ "declare const x: string;",
|
||||
/*tsFileContents*/ "var y = 1;",
|
||||
/*opts*/ { declaration: true },
|
||||
/*expectDTSEmit*/ true
|
||||
);
|
||||
});
|
||||
|
||||
it("should return results if change is made in a global declaration file with composite enabled", () => {
|
||||
testDTS(
|
||||
/*dtsFileContents*/ "declare const x: string;",
|
||||
/*tsFileContents*/ "var y = 1;",
|
||||
/*opts*/ { composite: true },
|
||||
/*expectDTSEmit*/ true
|
||||
);
|
||||
});
|
||||
|
||||
it("should return results if change is made in a global declaration file with decorator emit enabled", () => {
|
||||
testDTS(
|
||||
/*dtsFileContents*/ "declare const x: string;",
|
||||
/*tsFileContents*/ "var y = 1;",
|
||||
/*opts*/ { experimentalDecorators: true, emitDecoratorMetadata: true },
|
||||
/*expectDTSEmit*/ true
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("tsserverProjectSystem emit with outFile or out setting", () => {
|
||||
function test(opts: CompilerOptions, expectedUsesOutFile: boolean) {
|
||||
const f1 = {
|
||||
|
||||
@@ -866,12 +866,12 @@ namespace ts.projectSystem {
|
||||
const projectService = createProjectService(host);
|
||||
projectService.openClientFile(file1.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
// Since there is no file open from configFile it would be closed
|
||||
checkNumberOfConfiguredProjects(projectService, 0);
|
||||
checkNumberOfInferredProjects(projectService, 1);
|
||||
|
||||
// Since file1 refers to config file as the default project, it needs to be kept alive
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 });
|
||||
const inferredProject = projectService.inferredProjects[0];
|
||||
assert.isTrue(inferredProject.containsFile(<server.NormalizedPath>file1.path));
|
||||
assert.isFalse(projectService.configuredProjects.get(configFile.path)!.containsFile(<server.NormalizedPath>file1.path));
|
||||
});
|
||||
|
||||
it("should be able to handle @types if input file list is empty", () => {
|
||||
@@ -898,8 +898,8 @@ namespace ts.projectSystem {
|
||||
const projectService = createProjectService(host);
|
||||
|
||||
projectService.openClientFile(f.path);
|
||||
// Since no file from the configured project is open, it would be closed immediately
|
||||
projectService.checkNumberOfProjects({ configuredProjects: 0, inferredProjects: 1 });
|
||||
// Since f refers to config file as the default project, it needs to be kept alive
|
||||
projectService.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: 1 });
|
||||
});
|
||||
|
||||
it("should tolerate invalid include files that start in subDirectory", () => {
|
||||
@@ -924,8 +924,8 @@ namespace ts.projectSystem {
|
||||
const projectService = createProjectService(host);
|
||||
|
||||
projectService.openClientFile(f.path);
|
||||
// Since no file from the configured project is open, it would be closed immediately
|
||||
projectService.checkNumberOfProjects({ configuredProjects: 0, inferredProjects: 1 });
|
||||
// Since f refers to config file as the default project, it needs to be kept alive
|
||||
projectService.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: 1 });
|
||||
});
|
||||
|
||||
it("Changed module resolution reflected when specifying files list", () => {
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
namespace ts.projectSystem {
|
||||
interface DocumentSpanFromSubstring {
|
||||
file: File;
|
||||
text: string;
|
||||
options?: SpanFromSubstringOptions;
|
||||
contextText?: string;
|
||||
contextOptions?: SpanFromSubstringOptions;
|
||||
}
|
||||
function documentSpanFromSubstring({ file, text, contextText, options, contextOptions }: DocumentSpanFromSubstring): DocumentSpan {
|
||||
const contextSpan = contextText !== undefined ? documentSpanFromSubstring({ file, text: contextText, options: contextOptions }) : undefined;
|
||||
return {
|
||||
@@ -19,19 +12,6 @@ namespace ts.projectSystem {
|
||||
return documentSpanFromSubstring(input);
|
||||
}
|
||||
|
||||
interface MakeReferenceItem extends DocumentSpanFromSubstring {
|
||||
isDefinition: boolean;
|
||||
lineText: string;
|
||||
}
|
||||
function makeReferenceItem({ isDefinition, lineText, ...rest }: MakeReferenceItem): protocol.ReferencesResponseItem {
|
||||
return {
|
||||
...protocolFileSpanWithContextFromSubstring(rest),
|
||||
isDefinition,
|
||||
isWriteAccess: isDefinition,
|
||||
lineText,
|
||||
};
|
||||
}
|
||||
|
||||
interface MakeReferenceEntry extends DocumentSpanFromSubstring {
|
||||
isDefinition: boolean;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: getExportReferences", () => {
|
||||
const exportVariable = "export const value = 0;";
|
||||
const exportArrayDestructured = "export const [valueA, valueB] = [0, 1];";
|
||||
const exportObjectDestructured = "export const { valueC, valueD: renamedD } = { valueC: 0, valueD: 1 };";
|
||||
const exportNestedObject = "export const { nest: [valueE, { valueF }] } = { nest: [0, { valueF: 1 }] };";
|
||||
|
||||
const mainTs: File = {
|
||||
path: "/main.ts",
|
||||
content: 'import { value, valueA, valueB, valueC, renamedD, valueE, valueF } from "./mod";',
|
||||
};
|
||||
const modTs: File = {
|
||||
path: "/mod.ts",
|
||||
content: `${exportVariable}
|
||||
${exportArrayDestructured}
|
||||
${exportObjectDestructured}
|
||||
${exportNestedObject}
|
||||
`,
|
||||
};
|
||||
const tsconfig: File = {
|
||||
path: "/tsconfig.json",
|
||||
content: "{}",
|
||||
};
|
||||
|
||||
function makeSampleSession() {
|
||||
const host = createServerHost([mainTs, modTs, tsconfig]);
|
||||
const session = createSession(host);
|
||||
openFilesForSession([mainTs, modTs], session);
|
||||
return session;
|
||||
}
|
||||
|
||||
const referenceMainTs = (mainTs: File, text: string): protocol.ReferencesResponseItem =>
|
||||
makeReferenceItem({
|
||||
file: mainTs,
|
||||
isDefinition: true,
|
||||
lineText: mainTs.content,
|
||||
contextText: mainTs.content,
|
||||
text,
|
||||
});
|
||||
|
||||
const referenceModTs = (
|
||||
texts: { text: string; lineText: string; contextText?: string },
|
||||
override: Partial<MakeReferenceItem> = {},
|
||||
): protocol.ReferencesResponseItem =>
|
||||
makeReferenceItem({
|
||||
file: modTs,
|
||||
isDefinition: true,
|
||||
...texts,
|
||||
...override,
|
||||
});
|
||||
|
||||
it("should get const variable declaration references", () => {
|
||||
const session = makeSampleSession();
|
||||
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(
|
||||
session,
|
||||
protocol.CommandTypes.References,
|
||||
protocolFileLocationFromSubstring(modTs, "value"),
|
||||
);
|
||||
|
||||
const expectResponse = {
|
||||
refs: [
|
||||
referenceModTs({ text: "value", lineText: exportVariable, contextText: exportVariable }),
|
||||
referenceMainTs(mainTs, "value"),
|
||||
],
|
||||
symbolDisplayString: "const value: 0",
|
||||
symbolName: "value",
|
||||
symbolStartOffset: protocolLocationFromSubstring(modTs.content, "value").offset,
|
||||
};
|
||||
|
||||
assert.deepEqual(response, expectResponse);
|
||||
});
|
||||
|
||||
it("should get array destructuring declaration references", () => {
|
||||
const session = makeSampleSession();
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(
|
||||
session,
|
||||
protocol.CommandTypes.References,
|
||||
protocolFileLocationFromSubstring(modTs, "valueA"),
|
||||
);
|
||||
|
||||
const expectResponse = {
|
||||
refs: [
|
||||
referenceModTs({
|
||||
text: "valueA",
|
||||
lineText: exportArrayDestructured,
|
||||
contextText: exportArrayDestructured,
|
||||
}),
|
||||
referenceMainTs(mainTs, "valueA"),
|
||||
],
|
||||
symbolDisplayString: "const valueA: number",
|
||||
symbolName: "valueA",
|
||||
symbolStartOffset: protocolLocationFromSubstring(modTs.content, "valueA").offset,
|
||||
};
|
||||
|
||||
assert.deepEqual(response, expectResponse);
|
||||
});
|
||||
|
||||
it("should get object destructuring declaration references", () => {
|
||||
const session = makeSampleSession();
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(
|
||||
session,
|
||||
protocol.CommandTypes.References,
|
||||
protocolFileLocationFromSubstring(modTs, "valueC"),
|
||||
);
|
||||
const expectResponse = {
|
||||
refs: [
|
||||
referenceModTs({
|
||||
text: "valueC",
|
||||
lineText: exportObjectDestructured,
|
||||
contextText: exportObjectDestructured,
|
||||
}),
|
||||
referenceMainTs(mainTs, "valueC"),
|
||||
referenceModTs(
|
||||
{ text: "valueC", lineText: exportObjectDestructured, contextText: "valueC: 0" },
|
||||
{ options: { index: 1 } },
|
||||
),
|
||||
],
|
||||
symbolDisplayString: "const valueC: number",
|
||||
symbolName: "valueC",
|
||||
symbolStartOffset: protocolLocationFromSubstring(modTs.content, "valueC").offset,
|
||||
};
|
||||
|
||||
assert.deepEqual(response, expectResponse);
|
||||
});
|
||||
|
||||
it("should get object declaration references that renames destructured property", () => {
|
||||
const session = makeSampleSession();
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(
|
||||
session,
|
||||
protocol.CommandTypes.References,
|
||||
protocolFileLocationFromSubstring(modTs, "renamedD"),
|
||||
);
|
||||
|
||||
const expectResponse = {
|
||||
refs: [
|
||||
referenceModTs({
|
||||
text: "renamedD",
|
||||
lineText: exportObjectDestructured,
|
||||
contextText: exportObjectDestructured,
|
||||
}),
|
||||
referenceMainTs(mainTs, "renamedD"),
|
||||
],
|
||||
symbolDisplayString: "const renamedD: number",
|
||||
symbolName: "renamedD",
|
||||
symbolStartOffset: protocolLocationFromSubstring(modTs.content, "renamedD").offset,
|
||||
};
|
||||
|
||||
assert.deepEqual(response, expectResponse);
|
||||
});
|
||||
|
||||
it("should get nested object declaration references", () => {
|
||||
const session = makeSampleSession();
|
||||
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(
|
||||
session,
|
||||
protocol.CommandTypes.References,
|
||||
protocolFileLocationFromSubstring(modTs, "valueF"),
|
||||
);
|
||||
|
||||
const expectResponse = {
|
||||
refs: [
|
||||
referenceModTs({
|
||||
text: "valueF",
|
||||
lineText: exportNestedObject,
|
||||
contextText: exportNestedObject,
|
||||
}),
|
||||
referenceMainTs(mainTs, "valueF"),
|
||||
referenceModTs(
|
||||
{
|
||||
text: "valueF",
|
||||
lineText: exportNestedObject,
|
||||
contextText: "valueF: 1",
|
||||
},
|
||||
{ options: { index: 1 } },
|
||||
),
|
||||
],
|
||||
symbolDisplayString: "const valueF: number",
|
||||
symbolName: "valueF",
|
||||
symbolStartOffset: protocolLocationFromSubstring(modTs.content, "valueF").offset,
|
||||
};
|
||||
|
||||
assert.deepEqual(response, expectResponse);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -519,6 +519,8 @@ namespace ts.projectSystem {
|
||||
file: File;
|
||||
text: string;
|
||||
options?: SpanFromSubstringOptions;
|
||||
contextText?: string;
|
||||
contextOptions?: SpanFromSubstringOptions;
|
||||
}
|
||||
export function protocolFileSpanFromSubstring({ file, text, options }: DocumentSpanFromSubstring): protocol.FileSpan {
|
||||
return { file: file.path, ...protocolTextSpanFromSubstring(file.content, text, options) };
|
||||
@@ -727,4 +729,18 @@ namespace ts.projectSystem {
|
||||
assert.strictEqual(outputs.length, index + 1, JSON.stringify(outputs));
|
||||
}
|
||||
}
|
||||
|
||||
export interface MakeReferenceItem extends DocumentSpanFromSubstring {
|
||||
isDefinition: boolean;
|
||||
lineText: string;
|
||||
}
|
||||
|
||||
export function makeReferenceItem({ isDefinition, lineText, ...rest }: MakeReferenceItem): protocol.ReferencesResponseItem {
|
||||
return {
|
||||
...protocolFileSpanWithContextFromSubstring(rest),
|
||||
isDefinition,
|
||||
isWriteAccess: isDefinition,
|
||||
lineText,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,5 +345,92 @@ namespace ts.projectSystem {
|
||||
it("inferred projects per project root with case insensitive system", () => {
|
||||
verifyProjectRootWithCaseSensitivity(/*useCaseSensitiveFileNames*/ false);
|
||||
});
|
||||
|
||||
it("should still retain configured project created while opening the file", () => {
|
||||
const projectRoot = "/user/username/projects/project";
|
||||
const appFile: File = {
|
||||
path: `${projectRoot}/app.ts`,
|
||||
content: `const app = 20;`
|
||||
};
|
||||
const config: File = {
|
||||
path: `${projectRoot}/tsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
const jsFile1: File = {
|
||||
path: `${projectRoot}/jsFile1.js`,
|
||||
content: `const jsFile1 = 10;`
|
||||
};
|
||||
const jsFile2: File = {
|
||||
path: `${projectRoot}/jsFile2.js`,
|
||||
content: `const jsFile2 = 10;`
|
||||
};
|
||||
const host = createServerHost([appFile, libFile, config, jsFile1, jsFile2]);
|
||||
const projectService = createProjectService(host);
|
||||
const originalSet = projectService.configuredProjects.set;
|
||||
const originalDelete = projectService.configuredProjects.delete;
|
||||
const configuredCreated = createMap<true>();
|
||||
const configuredRemoved = createMap<true>();
|
||||
projectService.configuredProjects.set = (key, value) => {
|
||||
assert.isFalse(configuredCreated.has(key));
|
||||
configuredCreated.set(key, true);
|
||||
return originalSet.call(projectService.configuredProjects, key, value);
|
||||
};
|
||||
projectService.configuredProjects.delete = key => {
|
||||
assert.isFalse(configuredRemoved.has(key));
|
||||
configuredRemoved.set(key, true);
|
||||
return originalDelete.call(projectService.configuredProjects, key);
|
||||
};
|
||||
|
||||
// Do not remove config project when opening jsFile that is not present as part of config project
|
||||
projectService.openClientFile(jsFile1.path);
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 });
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [jsFile1.path, libFile.path]);
|
||||
const project = projectService.configuredProjects.get(config.path)!;
|
||||
checkProjectActualFiles(project, [appFile.path, config.path, libFile.path]);
|
||||
checkConfiguredProjectCreatedAndNotDeleted();
|
||||
|
||||
// Do not remove config project when opening jsFile that is not present as part of config project
|
||||
projectService.closeClientFile(jsFile1.path);
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 });
|
||||
projectService.openClientFile(jsFile2.path);
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 1, configuredProjects: 1 });
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [jsFile2.path, libFile.path]);
|
||||
checkProjectActualFiles(project, [appFile.path, config.path, libFile.path]);
|
||||
checkConfiguredProjectNotCreatedAndNotDeleted();
|
||||
|
||||
// Do not remove config project when opening jsFile that is not present as part of config project
|
||||
projectService.openClientFile(jsFile1.path);
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 2, configuredProjects: 1 });
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [jsFile2.path, libFile.path]);
|
||||
checkProjectActualFiles(projectService.inferredProjects[1], [jsFile1.path, libFile.path]);
|
||||
checkProjectActualFiles(project, [appFile.path, config.path, libFile.path]);
|
||||
checkConfiguredProjectNotCreatedAndNotDeleted();
|
||||
|
||||
// When opening file that doesnt fall back to the config file, we remove the config project
|
||||
projectService.openClientFile(libFile.path);
|
||||
checkNumberOfProjects(projectService, { inferredProjects: 2 });
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [jsFile2.path, libFile.path]);
|
||||
checkProjectActualFiles(projectService.inferredProjects[1], [jsFile1.path, libFile.path]);
|
||||
checkConfiguredProjectNotCreatedButDeleted();
|
||||
|
||||
function checkConfiguredProjectCreatedAndNotDeleted() {
|
||||
assert.equal(configuredCreated.size, 1);
|
||||
assert.isTrue(configuredCreated.has(config.path));
|
||||
assert.equal(configuredRemoved.size, 0);
|
||||
configuredCreated.clear();
|
||||
}
|
||||
|
||||
function checkConfiguredProjectNotCreatedAndNotDeleted() {
|
||||
assert.equal(configuredCreated.size, 0);
|
||||
assert.equal(configuredRemoved.size, 0);
|
||||
}
|
||||
|
||||
function checkConfiguredProjectNotCreatedButDeleted() {
|
||||
assert.equal(configuredCreated.size, 0);
|
||||
assert.equal(configuredRemoved.size, 1);
|
||||
assert.isTrue(configuredRemoved.has(config.path));
|
||||
configuredRemoved.clear();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -634,13 +634,17 @@ namespace ts.projectSystem {
|
||||
path: "/a/main.js",
|
||||
content: "var y = 1"
|
||||
};
|
||||
const f3 = {
|
||||
path: "/main.js",
|
||||
content: "var y = 1"
|
||||
};
|
||||
const config = {
|
||||
path: "/a/tsconfig.json",
|
||||
content: JSON.stringify({
|
||||
compilerOptions: { allowJs: true }
|
||||
})
|
||||
};
|
||||
const host = createServerHost([f1, f2, config]);
|
||||
const host = createServerHost([f1, f2, f3, config]);
|
||||
const projectService = createProjectService(host);
|
||||
projectService.setHostConfiguration({
|
||||
extraFileExtensions: [
|
||||
@@ -652,13 +656,19 @@ namespace ts.projectSystem {
|
||||
projectService.checkNumberOfProjects({ configuredProjects: 1 });
|
||||
checkProjectActualFiles(configuredProjectAt(projectService, 0), [f1.path, config.path]);
|
||||
|
||||
// Should close configured project with next file open
|
||||
// Since f2 refers to config file as the default project, it needs to be kept alive
|
||||
projectService.closeClientFile(f1.path);
|
||||
|
||||
projectService.openClientFile(f2.path);
|
||||
projectService.checkNumberOfProjects({ inferredProjects: 1, configuredProjects: 1 });
|
||||
assert.isDefined(projectService.configuredProjects.get(config.path));
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [f2.path]);
|
||||
|
||||
// Should close configured project with next file open
|
||||
projectService.closeClientFile(f2.path);
|
||||
projectService.openClientFile(f3.path);
|
||||
projectService.checkNumberOfProjects({ inferredProjects: 1 });
|
||||
assert.isUndefined(projectService.configuredProjects.get(config.path));
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [f2.path]);
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [f3.path]);
|
||||
});
|
||||
|
||||
it("tsconfig script block support", () => {
|
||||
@@ -1467,5 +1477,22 @@ var x = 10;`
|
||||
openFilesForSession([{ file, projectRootPath }], session);
|
||||
}
|
||||
});
|
||||
|
||||
it("assert when removing project", () => {
|
||||
const host = createServerHost([commonFile1, commonFile2, libFile]);
|
||||
const service = createProjectService(host);
|
||||
service.openClientFile(commonFile1.path);
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [commonFile1.path, libFile.path]);
|
||||
// Intentionally create scriptinfo and attach it to project
|
||||
const info = service.getOrCreateScriptInfoForNormalizedPath(commonFile2.path as server.NormalizedPath, /*openedByClient*/ false)!;
|
||||
info.attachToProject(project);
|
||||
try {
|
||||
service.applyChangesInOpenFiles(/*openFiles*/ undefined, /*changedFiles*/ undefined, [commonFile1.path]);
|
||||
}
|
||||
catch (e) {
|
||||
assert.isTrue(e.message.indexOf("Debug Failure. False expression: Found script Info still attached to project") === 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace ts.projectSystem {
|
||||
import validatePackageName = JsTyping.validatePackageName;
|
||||
import PackageNameValidationResult = JsTyping.PackageNameValidationResult;
|
||||
import NameValidationResult = JsTyping.NameValidationResult;
|
||||
|
||||
interface InstallerParams {
|
||||
globalTypingsCacheLocation?: string;
|
||||
@@ -948,7 +948,8 @@ namespace ts.projectSystem {
|
||||
path: "/a/b/app.js",
|
||||
content: `
|
||||
import * as fs from "fs";
|
||||
import * as commander from "commander";`
|
||||
import * as commander from "commander";
|
||||
import * as component from "@ember/component";`
|
||||
};
|
||||
const cachePath = "/a/cache";
|
||||
const node = {
|
||||
@@ -959,14 +960,19 @@ namespace ts.projectSystem {
|
||||
path: cachePath + "/node_modules/@types/commander/index.d.ts",
|
||||
content: "export let y: string"
|
||||
};
|
||||
const emberComponentDirectory = "ember__component";
|
||||
const emberComponent = {
|
||||
path: `${cachePath}/node_modules/@types/${emberComponentDirectory}/index.d.ts`,
|
||||
content: "export let x: number"
|
||||
};
|
||||
const host = createServerHost([file]);
|
||||
const installer = new (class extends Installer {
|
||||
constructor() {
|
||||
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("node", "commander") });
|
||||
}
|
||||
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
|
||||
const installedTypings = ["@types/node", "@types/commander"];
|
||||
const typingFiles = [node, commander];
|
||||
const installedTypings = ["@types/node", "@types/commander", `@types/${emberComponentDirectory}`];
|
||||
const typingFiles = [node, commander, emberComponent];
|
||||
executeCommand(this, host, installedTypings, typingFiles, cb);
|
||||
}
|
||||
})();
|
||||
@@ -980,9 +986,10 @@ namespace ts.projectSystem {
|
||||
|
||||
assert.isTrue(host.fileExists(node.path), "typings for 'node' should be created");
|
||||
assert.isTrue(host.fileExists(commander.path), "typings for 'commander' should be created");
|
||||
assert.isTrue(host.fileExists(emberComponent.path), "typings for 'commander' should be created");
|
||||
|
||||
host.checkTimeoutQueueLengthAndRun(2);
|
||||
checkProjectActualFiles(service.inferredProjects[0], [file.path, node.path, commander.path]);
|
||||
checkProjectActualFiles(service.inferredProjects[0], [file.path, node.path, commander.path, emberComponent.path]);
|
||||
});
|
||||
|
||||
it("should redo resolution that resolved to '.js' file after typings are installed", () => {
|
||||
@@ -1263,21 +1270,44 @@ namespace ts.projectSystem {
|
||||
for (let i = 0; i < 8; i++) {
|
||||
packageName += packageName;
|
||||
}
|
||||
assert.equal(validatePackageName(packageName), PackageNameValidationResult.NameTooLong);
|
||||
assert.equal(validatePackageName(packageName), NameValidationResult.NameTooLong);
|
||||
});
|
||||
it("name cannot start with dot", () => {
|
||||
assert.equal(validatePackageName(".foo"), PackageNameValidationResult.NameStartsWithDot);
|
||||
it("package name cannot start with dot", () => {
|
||||
assert.equal(validatePackageName(".foo"), NameValidationResult.NameStartsWithDot);
|
||||
});
|
||||
it("name cannot start with underscore", () => {
|
||||
assert.equal(validatePackageName("_foo"), PackageNameValidationResult.NameStartsWithUnderscore);
|
||||
it("package name cannot start with underscore", () => {
|
||||
assert.equal(validatePackageName("_foo"), NameValidationResult.NameStartsWithUnderscore);
|
||||
});
|
||||
it("scoped packages not supported", () => {
|
||||
assert.equal(validatePackageName("@scope/bar"), PackageNameValidationResult.ScopedPackagesNotSupported);
|
||||
it("package non URI safe characters are not supported", () => {
|
||||
assert.equal(validatePackageName(" scope "), NameValidationResult.NameContainsNonURISafeCharacters);
|
||||
assert.equal(validatePackageName("; say ‘Hello from TypeScript!’ #"), NameValidationResult.NameContainsNonURISafeCharacters);
|
||||
assert.equal(validatePackageName("a/b/c"), NameValidationResult.NameContainsNonURISafeCharacters);
|
||||
});
|
||||
it("non URI safe characters are not supported", () => {
|
||||
assert.equal(validatePackageName(" scope "), PackageNameValidationResult.NameContainsNonURISafeCharacters);
|
||||
assert.equal(validatePackageName("; say ‘Hello from TypeScript!’ #"), PackageNameValidationResult.NameContainsNonURISafeCharacters);
|
||||
assert.equal(validatePackageName("a/b/c"), PackageNameValidationResult.NameContainsNonURISafeCharacters);
|
||||
it("scoped package name is supported", () => {
|
||||
assert.equal(validatePackageName("@scope/bar"), NameValidationResult.Ok);
|
||||
});
|
||||
it("scoped name in scoped package name cannot start with dot", () => {
|
||||
assert.deepEqual(validatePackageName("@.scope/bar"), { name: ".scope", isScopeName: true, result: NameValidationResult.NameStartsWithDot });
|
||||
assert.deepEqual(validatePackageName("@.scope/.bar"), { name: ".scope", isScopeName: true, result: NameValidationResult.NameStartsWithDot });
|
||||
});
|
||||
it("scope name in scoped package name cannot start with underscore", () => {
|
||||
assert.deepEqual(validatePackageName("@_scope/bar"), { name: "_scope", isScopeName: true, result: NameValidationResult.NameStartsWithUnderscore });
|
||||
assert.deepEqual(validatePackageName("@_scope/_bar"), { name: "_scope", isScopeName: true, result: NameValidationResult.NameStartsWithUnderscore });
|
||||
});
|
||||
it("scope name in scoped package name with non URI safe characters are not supported", () => {
|
||||
assert.deepEqual(validatePackageName("@ scope /bar"), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters });
|
||||
assert.deepEqual(validatePackageName("@; say ‘Hello from TypeScript!’ #/bar"), { name: "; say ‘Hello from TypeScript!’ #", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters });
|
||||
assert.deepEqual(validatePackageName("@ scope / bar "), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters });
|
||||
});
|
||||
it("package name in scoped package name cannot start with dot", () => {
|
||||
assert.deepEqual(validatePackageName("@scope/.bar"), { name: ".bar", isScopeName: false, result: NameValidationResult.NameStartsWithDot });
|
||||
});
|
||||
it("package name in scoped package name cannot start with underscore", () => {
|
||||
assert.deepEqual(validatePackageName("@scope/_bar"), { name: "_bar", isScopeName: false, result: NameValidationResult.NameStartsWithUnderscore });
|
||||
});
|
||||
it("package name in scoped package name with non URI safe characters are not supported", () => {
|
||||
assert.deepEqual(validatePackageName("@scope/ bar "), { name: " bar ", isScopeName: false, result: NameValidationResult.NameContainsNonURISafeCharacters });
|
||||
assert.deepEqual(validatePackageName("@scope/; say ‘Hello from TypeScript!’ #"), { name: "; say ‘Hello from TypeScript!’ #", isScopeName: false, result: NameValidationResult.NameContainsNonURISafeCharacters });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1309,7 +1339,7 @@ namespace ts.projectSystem {
|
||||
projectService.openClientFile(f1.path);
|
||||
|
||||
installer.checkPendingCommands(/*expectedCount*/ 0);
|
||||
assert.isTrue(messages.indexOf("Package name '; say ‘Hello from TypeScript!’ #' contains non URI safe characters") > 0, "should find package with invalid name");
|
||||
assert.isTrue(messages.indexOf("'; say ‘Hello from TypeScript!’ #':: Package name '; say ‘Hello from TypeScript!’ #' contains non URI safe characters") > 0, "should find package with invalid name");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+21
-1
@@ -180,6 +180,18 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
msg(s: string, type: Msg = Msg.Err) {
|
||||
switch (type) {
|
||||
case Msg.Info:
|
||||
perfLogger.logInfoEvent(s);
|
||||
break;
|
||||
case Msg.Perf:
|
||||
perfLogger.logPerfEvent(s);
|
||||
break;
|
||||
default: // Msg.Err
|
||||
perfLogger.logErrEvent(s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!this.canWrite) return;
|
||||
|
||||
s = `[${nowString()}] ${s}\n`;
|
||||
@@ -248,7 +260,7 @@ namespace ts.server {
|
||||
isKnownTypesPackageName(name: string): boolean {
|
||||
// We want to avoid looking this up in the registry as that is expensive. So first check that it's actually an NPM package.
|
||||
const validationResult = JsTyping.validatePackageName(name);
|
||||
if (validationResult !== JsTyping.PackageNameValidationResult.Ok) {
|
||||
if (validationResult !== JsTyping.NameValidationResult.Ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -970,4 +982,12 @@ namespace ts.server {
|
||||
if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
|
||||
ts.sys.tryEnableSourceMapsForHost();
|
||||
}
|
||||
|
||||
// Overwrites the current console messages to instead write to
|
||||
// the log. This is so that language service plugins which use
|
||||
// console.log don't break the message passing between tsserver
|
||||
// and the client
|
||||
console.log = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), Msg.Info);
|
||||
console.warn = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), Msg.Err);
|
||||
console.error = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), Msg.Err);
|
||||
}
|
||||
|
||||
@@ -268,27 +268,28 @@ namespace ts.server.typingsInstaller {
|
||||
}
|
||||
|
||||
private filterTypings(typingsToInstall: ReadonlyArray<string>): ReadonlyArray<string> {
|
||||
return typingsToInstall.filter(typing => {
|
||||
if (this.missingTypingsSet.get(typing)) {
|
||||
if (this.log.isEnabled()) this.log.writeLine(`'${typing}' is in missingTypingsSet - skipping...`);
|
||||
return false;
|
||||
return mapDefined(typingsToInstall, typing => {
|
||||
const typingKey = mangleScopedPackageName(typing);
|
||||
if (this.missingTypingsSet.get(typingKey)) {
|
||||
if (this.log.isEnabled()) this.log.writeLine(`'${typing}':: '${typingKey}' is in missingTypingsSet - skipping...`);
|
||||
return undefined;
|
||||
}
|
||||
const validationResult = JsTyping.validatePackageName(typing);
|
||||
if (validationResult !== JsTyping.PackageNameValidationResult.Ok) {
|
||||
if (validationResult !== JsTyping.NameValidationResult.Ok) {
|
||||
// add typing name to missing set so we won't process it again
|
||||
this.missingTypingsSet.set(typing, true);
|
||||
this.missingTypingsSet.set(typingKey, true);
|
||||
if (this.log.isEnabled()) this.log.writeLine(JsTyping.renderPackageNameValidationFailure(validationResult, typing));
|
||||
return false;
|
||||
return undefined;
|
||||
}
|
||||
if (!this.typesRegistry.has(typing)) {
|
||||
if (this.log.isEnabled()) this.log.writeLine(`Entry for package '${typing}' does not exist in local types registry - skipping...`);
|
||||
return false;
|
||||
if (!this.typesRegistry.has(typingKey)) {
|
||||
if (this.log.isEnabled()) this.log.writeLine(`'${typing}':: Entry for package '${typingKey}' does not exist in local types registry - skipping...`);
|
||||
return undefined;
|
||||
}
|
||||
if (this.packageNameToTypingLocation.get(typing) && JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typing)!, this.typesRegistry.get(typing)!)) {
|
||||
if (this.log.isEnabled()) this.log.writeLine(`'${typing}' already has an up-to-date typing - skipping...`);
|
||||
return false;
|
||||
if (this.packageNameToTypingLocation.get(typingKey) && JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typingKey)!, this.typesRegistry.get(typingKey)!)) {
|
||||
if (this.log.isEnabled()) this.log.writeLine(`'${typing}':: '${typingKey}' already has an up-to-date typing - skipping...`);
|
||||
return undefined;
|
||||
}
|
||||
return true;
|
||||
return typingKey;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,15 +4,16 @@ for (var v of ['a', 'b', 'c']) {
|
||||
}
|
||||
|
||||
//// [ES5For-of33.js]
|
||||
var __values = (this && this.__values) || function (o) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
||||
var __values = (this && this.__values) || function(o) {
|
||||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
if (m) return m.call(o);
|
||||
return {
|
||||
if (o && typeof o.length === "number") return {
|
||||
next: function () {
|
||||
if (o && i >= o.length) o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
}
|
||||
};
|
||||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
};
|
||||
var e_1, _a;
|
||||
try {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
//// [ES5For-of33.js.map]
|
||||
{"version":3,"file":"ES5For-of33.js","sourceRoot":"","sources":["ES5For-of33.ts"],"names":[],"mappings":";;;;;;;;;;;;IAAA,KAAc,IAAA,KAAA,SAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA,gBAAA,4BAAE;QAA1B,IAAI,CAAC,WAAA;QACN,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAClB"}
|
||||
{"version":3,"file":"ES5For-of33.js","sourceRoot":"","sources":["ES5For-of33.ts"],"names":[],"mappings":";;;;;;;;;;;;;IAAA,KAAc,IAAA,KAAA,SAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA,gBAAA,4BAAE;QAA1B,IAAI,CAAC,WAAA;QACN,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAClB"}
|
||||
@@ -8,15 +8,16 @@ sources: ES5For-of33.ts
|
||||
emittedFile:tests/cases/conformance/statements/for-ofStatements/ES5For-of33.js
|
||||
sourceFile:ES5For-of33.ts
|
||||
-------------------------------------------------------------------
|
||||
>>>var __values = (this && this.__values) || function (o) {
|
||||
>>> var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
||||
>>>var __values = (this && this.__values) || function(o) {
|
||||
>>> var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
>>> if (m) return m.call(o);
|
||||
>>> return {
|
||||
>>> if (o && typeof o.length === "number") return {
|
||||
>>> next: function () {
|
||||
>>> if (o && i >= o.length) o = void 0;
|
||||
>>> return { value: o && o[i++], done: !o };
|
||||
>>> }
|
||||
>>> };
|
||||
>>> throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
>>>};
|
||||
>>>var e_1, _a;
|
||||
>>>try {
|
||||
@@ -51,21 +52,21 @@ sourceFile:ES5For-of33.ts
|
||||
13>
|
||||
14>
|
||||
15> )
|
||||
1 >Emitted(13, 5) Source(1, 1) + SourceIndex(0)
|
||||
2 >Emitted(13, 10) Source(1, 15) + SourceIndex(0)
|
||||
3 >Emitted(13, 14) Source(1, 15) + SourceIndex(0)
|
||||
4 >Emitted(13, 19) Source(1, 15) + SourceIndex(0)
|
||||
5 >Emitted(13, 28) Source(1, 15) + SourceIndex(0)
|
||||
6 >Emitted(13, 29) Source(1, 16) + SourceIndex(0)
|
||||
7 >Emitted(13, 32) Source(1, 19) + SourceIndex(0)
|
||||
8 >Emitted(13, 34) Source(1, 21) + SourceIndex(0)
|
||||
9 >Emitted(13, 37) Source(1, 24) + SourceIndex(0)
|
||||
10>Emitted(13, 39) Source(1, 26) + SourceIndex(0)
|
||||
11>Emitted(13, 42) Source(1, 29) + SourceIndex(0)
|
||||
12>Emitted(13, 43) Source(1, 30) + SourceIndex(0)
|
||||
13>Emitted(13, 44) Source(1, 30) + SourceIndex(0)
|
||||
14>Emitted(13, 60) Source(1, 30) + SourceIndex(0)
|
||||
15>Emitted(13, 88) Source(1, 32) + SourceIndex(0)
|
||||
1 >Emitted(14, 5) Source(1, 1) + SourceIndex(0)
|
||||
2 >Emitted(14, 10) Source(1, 15) + SourceIndex(0)
|
||||
3 >Emitted(14, 14) Source(1, 15) + SourceIndex(0)
|
||||
4 >Emitted(14, 19) Source(1, 15) + SourceIndex(0)
|
||||
5 >Emitted(14, 28) Source(1, 15) + SourceIndex(0)
|
||||
6 >Emitted(14, 29) Source(1, 16) + SourceIndex(0)
|
||||
7 >Emitted(14, 32) Source(1, 19) + SourceIndex(0)
|
||||
8 >Emitted(14, 34) Source(1, 21) + SourceIndex(0)
|
||||
9 >Emitted(14, 37) Source(1, 24) + SourceIndex(0)
|
||||
10>Emitted(14, 39) Source(1, 26) + SourceIndex(0)
|
||||
11>Emitted(14, 42) Source(1, 29) + SourceIndex(0)
|
||||
12>Emitted(14, 43) Source(1, 30) + SourceIndex(0)
|
||||
13>Emitted(14, 44) Source(1, 30) + SourceIndex(0)
|
||||
14>Emitted(14, 60) Source(1, 30) + SourceIndex(0)
|
||||
15>Emitted(14, 88) Source(1, 32) + SourceIndex(0)
|
||||
---
|
||||
>>> var v = _c.value;
|
||||
1 >^^^^^^^^
|
||||
@@ -76,10 +77,10 @@ sourceFile:ES5For-of33.ts
|
||||
2 > var
|
||||
3 > v
|
||||
4 >
|
||||
1 >Emitted(14, 9) Source(1, 6) + SourceIndex(0)
|
||||
2 >Emitted(14, 13) Source(1, 10) + SourceIndex(0)
|
||||
3 >Emitted(14, 14) Source(1, 11) + SourceIndex(0)
|
||||
4 >Emitted(14, 25) Source(1, 11) + SourceIndex(0)
|
||||
1 >Emitted(15, 9) Source(1, 6) + SourceIndex(0)
|
||||
2 >Emitted(15, 13) Source(1, 10) + SourceIndex(0)
|
||||
3 >Emitted(15, 14) Source(1, 11) + SourceIndex(0)
|
||||
4 >Emitted(15, 25) Source(1, 11) + SourceIndex(0)
|
||||
---
|
||||
>>> console.log(v);
|
||||
1 >^^^^^^^^
|
||||
@@ -99,20 +100,20 @@ sourceFile:ES5For-of33.ts
|
||||
6 > v
|
||||
7 > )
|
||||
8 > ;
|
||||
1 >Emitted(15, 9) Source(2, 5) + SourceIndex(0)
|
||||
2 >Emitted(15, 16) Source(2, 12) + SourceIndex(0)
|
||||
3 >Emitted(15, 17) Source(2, 13) + SourceIndex(0)
|
||||
4 >Emitted(15, 20) Source(2, 16) + SourceIndex(0)
|
||||
5 >Emitted(15, 21) Source(2, 17) + SourceIndex(0)
|
||||
6 >Emitted(15, 22) Source(2, 18) + SourceIndex(0)
|
||||
7 >Emitted(15, 23) Source(2, 19) + SourceIndex(0)
|
||||
8 >Emitted(15, 24) Source(2, 20) + SourceIndex(0)
|
||||
1 >Emitted(16, 9) Source(2, 5) + SourceIndex(0)
|
||||
2 >Emitted(16, 16) Source(2, 12) + SourceIndex(0)
|
||||
3 >Emitted(16, 17) Source(2, 13) + SourceIndex(0)
|
||||
4 >Emitted(16, 20) Source(2, 16) + SourceIndex(0)
|
||||
5 >Emitted(16, 21) Source(2, 17) + SourceIndex(0)
|
||||
6 >Emitted(16, 22) Source(2, 18) + SourceIndex(0)
|
||||
7 >Emitted(16, 23) Source(2, 19) + SourceIndex(0)
|
||||
8 >Emitted(16, 24) Source(2, 20) + SourceIndex(0)
|
||||
---
|
||||
>>> }
|
||||
1 >^^^^^
|
||||
1 >
|
||||
>}
|
||||
1 >Emitted(16, 6) Source(3, 2) + SourceIndex(0)
|
||||
1 >Emitted(17, 6) Source(3, 2) + SourceIndex(0)
|
||||
---
|
||||
>>>}
|
||||
>>>catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
|
||||
@@ -7,15 +7,16 @@ for (foo().x of ['a', 'b', 'c']) {
|
||||
}
|
||||
|
||||
//// [ES5For-of34.js]
|
||||
var __values = (this && this.__values) || function (o) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
||||
var __values = (this && this.__values) || function(o) {
|
||||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
if (m) return m.call(o);
|
||||
return {
|
||||
if (o && typeof o.length === "number") return {
|
||||
next: function () {
|
||||
if (o && i >= o.length) o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
}
|
||||
};
|
||||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
};
|
||||
var e_1, _a;
|
||||
function foo() {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
//// [ES5For-of34.js.map]
|
||||
{"version":3,"file":"ES5For-of34.js","sourceRoot":"","sources":["ES5For-of34.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,SAAS,GAAG;IACR,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACpB,CAAC;;IACD,KAAgB,IAAA,KAAA,SAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA,gBAAA,4BAAE;QAA5B,GAAG,EAAE,CAAC,CAAC,WAAA;QACR,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;KACnB"}
|
||||
{"version":3,"file":"ES5For-of34.js","sourceRoot":"","sources":["ES5For-of34.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,SAAS,GAAG;IACR,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACpB,CAAC;;IACD,KAAgB,IAAA,KAAA,SAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA,gBAAA,4BAAE;QAA5B,GAAG,EAAE,CAAC,CAAC,WAAA;QACR,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;KACnB"}
|
||||
@@ -8,15 +8,16 @@ sources: ES5For-of34.ts
|
||||
emittedFile:tests/cases/conformance/statements/for-ofStatements/ES5For-of34.js
|
||||
sourceFile:ES5For-of34.ts
|
||||
-------------------------------------------------------------------
|
||||
>>>var __values = (this && this.__values) || function (o) {
|
||||
>>> var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
||||
>>>var __values = (this && this.__values) || function(o) {
|
||||
>>> var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
>>> if (m) return m.call(o);
|
||||
>>> return {
|
||||
>>> if (o && typeof o.length === "number") return {
|
||||
>>> next: function () {
|
||||
>>> if (o && i >= o.length) o = void 0;
|
||||
>>> return { value: o && o[i++], done: !o };
|
||||
>>> }
|
||||
>>> };
|
||||
>>> throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
>>>};
|
||||
>>>var e_1, _a;
|
||||
>>>function foo() {
|
||||
@@ -27,9 +28,9 @@ sourceFile:ES5For-of34.ts
|
||||
1 >
|
||||
2 >function
|
||||
3 > foo
|
||||
1 >Emitted(12, 1) Source(1, 1) + SourceIndex(0)
|
||||
2 >Emitted(12, 10) Source(1, 10) + SourceIndex(0)
|
||||
3 >Emitted(12, 13) Source(1, 13) + SourceIndex(0)
|
||||
1 >Emitted(13, 1) Source(1, 1) + SourceIndex(0)
|
||||
2 >Emitted(13, 10) Source(1, 10) + SourceIndex(0)
|
||||
3 >Emitted(13, 13) Source(1, 13) + SourceIndex(0)
|
||||
---
|
||||
>>> return { x: 0 };
|
||||
1->^^^^
|
||||
@@ -49,14 +50,14 @@ sourceFile:ES5For-of34.ts
|
||||
6 > 0
|
||||
7 > }
|
||||
8 > ;
|
||||
1->Emitted(13, 5) Source(2, 5) + SourceIndex(0)
|
||||
2 >Emitted(13, 12) Source(2, 12) + SourceIndex(0)
|
||||
3 >Emitted(13, 14) Source(2, 14) + SourceIndex(0)
|
||||
4 >Emitted(13, 15) Source(2, 15) + SourceIndex(0)
|
||||
5 >Emitted(13, 17) Source(2, 17) + SourceIndex(0)
|
||||
6 >Emitted(13, 18) Source(2, 18) + SourceIndex(0)
|
||||
7 >Emitted(13, 20) Source(2, 20) + SourceIndex(0)
|
||||
8 >Emitted(13, 21) Source(2, 21) + SourceIndex(0)
|
||||
1->Emitted(14, 5) Source(2, 5) + SourceIndex(0)
|
||||
2 >Emitted(14, 12) Source(2, 12) + SourceIndex(0)
|
||||
3 >Emitted(14, 14) Source(2, 14) + SourceIndex(0)
|
||||
4 >Emitted(14, 15) Source(2, 15) + SourceIndex(0)
|
||||
5 >Emitted(14, 17) Source(2, 17) + SourceIndex(0)
|
||||
6 >Emitted(14, 18) Source(2, 18) + SourceIndex(0)
|
||||
7 >Emitted(14, 20) Source(2, 20) + SourceIndex(0)
|
||||
8 >Emitted(14, 21) Source(2, 21) + SourceIndex(0)
|
||||
---
|
||||
>>>}
|
||||
1 >
|
||||
@@ -65,8 +66,8 @@ sourceFile:ES5For-of34.ts
|
||||
1 >
|
||||
>
|
||||
2 >}
|
||||
1 >Emitted(14, 1) Source(3, 1) + SourceIndex(0)
|
||||
2 >Emitted(14, 2) Source(3, 2) + SourceIndex(0)
|
||||
1 >Emitted(15, 1) Source(3, 1) + SourceIndex(0)
|
||||
2 >Emitted(15, 2) Source(3, 2) + SourceIndex(0)
|
||||
---
|
||||
>>>try {
|
||||
>>> for (var _b = __values(['a', 'b', 'c']), _c = _b.next(); !_c.done; _c = _b.next()) {
|
||||
@@ -101,21 +102,21 @@ sourceFile:ES5For-of34.ts
|
||||
13>
|
||||
14>
|
||||
15> )
|
||||
1->Emitted(16, 5) Source(4, 1) + SourceIndex(0)
|
||||
2 >Emitted(16, 10) Source(4, 17) + SourceIndex(0)
|
||||
3 >Emitted(16, 14) Source(4, 17) + SourceIndex(0)
|
||||
4 >Emitted(16, 19) Source(4, 17) + SourceIndex(0)
|
||||
5 >Emitted(16, 28) Source(4, 17) + SourceIndex(0)
|
||||
6 >Emitted(16, 29) Source(4, 18) + SourceIndex(0)
|
||||
7 >Emitted(16, 32) Source(4, 21) + SourceIndex(0)
|
||||
8 >Emitted(16, 34) Source(4, 23) + SourceIndex(0)
|
||||
9 >Emitted(16, 37) Source(4, 26) + SourceIndex(0)
|
||||
10>Emitted(16, 39) Source(4, 28) + SourceIndex(0)
|
||||
11>Emitted(16, 42) Source(4, 31) + SourceIndex(0)
|
||||
12>Emitted(16, 43) Source(4, 32) + SourceIndex(0)
|
||||
13>Emitted(16, 44) Source(4, 32) + SourceIndex(0)
|
||||
14>Emitted(16, 60) Source(4, 32) + SourceIndex(0)
|
||||
15>Emitted(16, 88) Source(4, 34) + SourceIndex(0)
|
||||
1->Emitted(17, 5) Source(4, 1) + SourceIndex(0)
|
||||
2 >Emitted(17, 10) Source(4, 17) + SourceIndex(0)
|
||||
3 >Emitted(17, 14) Source(4, 17) + SourceIndex(0)
|
||||
4 >Emitted(17, 19) Source(4, 17) + SourceIndex(0)
|
||||
5 >Emitted(17, 28) Source(4, 17) + SourceIndex(0)
|
||||
6 >Emitted(17, 29) Source(4, 18) + SourceIndex(0)
|
||||
7 >Emitted(17, 32) Source(4, 21) + SourceIndex(0)
|
||||
8 >Emitted(17, 34) Source(4, 23) + SourceIndex(0)
|
||||
9 >Emitted(17, 37) Source(4, 26) + SourceIndex(0)
|
||||
10>Emitted(17, 39) Source(4, 28) + SourceIndex(0)
|
||||
11>Emitted(17, 42) Source(4, 31) + SourceIndex(0)
|
||||
12>Emitted(17, 43) Source(4, 32) + SourceIndex(0)
|
||||
13>Emitted(17, 44) Source(4, 32) + SourceIndex(0)
|
||||
14>Emitted(17, 60) Source(4, 32) + SourceIndex(0)
|
||||
15>Emitted(17, 88) Source(4, 34) + SourceIndex(0)
|
||||
---
|
||||
>>> foo().x = _c.value;
|
||||
1 >^^^^^^^^
|
||||
@@ -130,12 +131,12 @@ sourceFile:ES5For-of34.ts
|
||||
4 > .
|
||||
5 > x
|
||||
6 >
|
||||
1 >Emitted(17, 9) Source(4, 6) + SourceIndex(0)
|
||||
2 >Emitted(17, 12) Source(4, 9) + SourceIndex(0)
|
||||
3 >Emitted(17, 14) Source(4, 11) + SourceIndex(0)
|
||||
4 >Emitted(17, 15) Source(4, 12) + SourceIndex(0)
|
||||
5 >Emitted(17, 16) Source(4, 13) + SourceIndex(0)
|
||||
6 >Emitted(17, 27) Source(4, 13) + SourceIndex(0)
|
||||
1 >Emitted(18, 9) Source(4, 6) + SourceIndex(0)
|
||||
2 >Emitted(18, 12) Source(4, 9) + SourceIndex(0)
|
||||
3 >Emitted(18, 14) Source(4, 11) + SourceIndex(0)
|
||||
4 >Emitted(18, 15) Source(4, 12) + SourceIndex(0)
|
||||
5 >Emitted(18, 16) Source(4, 13) + SourceIndex(0)
|
||||
6 >Emitted(18, 27) Source(4, 13) + SourceIndex(0)
|
||||
---
|
||||
>>> var p = foo().x;
|
||||
1 >^^^^^^^^
|
||||
@@ -157,21 +158,21 @@ sourceFile:ES5For-of34.ts
|
||||
7 > .
|
||||
8 > x
|
||||
9 > ;
|
||||
1 >Emitted(18, 9) Source(5, 5) + SourceIndex(0)
|
||||
2 >Emitted(18, 13) Source(5, 9) + SourceIndex(0)
|
||||
3 >Emitted(18, 14) Source(5, 10) + SourceIndex(0)
|
||||
4 >Emitted(18, 17) Source(5, 13) + SourceIndex(0)
|
||||
5 >Emitted(18, 20) Source(5, 16) + SourceIndex(0)
|
||||
6 >Emitted(18, 22) Source(5, 18) + SourceIndex(0)
|
||||
7 >Emitted(18, 23) Source(5, 19) + SourceIndex(0)
|
||||
8 >Emitted(18, 24) Source(5, 20) + SourceIndex(0)
|
||||
9 >Emitted(18, 25) Source(5, 21) + SourceIndex(0)
|
||||
1 >Emitted(19, 9) Source(5, 5) + SourceIndex(0)
|
||||
2 >Emitted(19, 13) Source(5, 9) + SourceIndex(0)
|
||||
3 >Emitted(19, 14) Source(5, 10) + SourceIndex(0)
|
||||
4 >Emitted(19, 17) Source(5, 13) + SourceIndex(0)
|
||||
5 >Emitted(19, 20) Source(5, 16) + SourceIndex(0)
|
||||
6 >Emitted(19, 22) Source(5, 18) + SourceIndex(0)
|
||||
7 >Emitted(19, 23) Source(5, 19) + SourceIndex(0)
|
||||
8 >Emitted(19, 24) Source(5, 20) + SourceIndex(0)
|
||||
9 >Emitted(19, 25) Source(5, 21) + SourceIndex(0)
|
||||
---
|
||||
>>> }
|
||||
1 >^^^^^
|
||||
1 >
|
||||
>}
|
||||
1 >Emitted(19, 6) Source(6, 2) + SourceIndex(0)
|
||||
1 >Emitted(20, 6) Source(6, 2) + SourceIndex(0)
|
||||
---
|
||||
>>>}
|
||||
>>>catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
|
||||
@@ -5,15 +5,16 @@ for (const {x: a = 0, y: b = 1} of [2, 3]) {
|
||||
}
|
||||
|
||||
//// [ES5For-of35.js]
|
||||
var __values = (this && this.__values) || function (o) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
||||
var __values = (this && this.__values) || function(o) {
|
||||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
if (m) return m.call(o);
|
||||
return {
|
||||
if (o && typeof o.length === "number") return {
|
||||
next: function () {
|
||||
if (o && i >= o.length) o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
}
|
||||
};
|
||||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
};
|
||||
var e_1, _a;
|
||||
try {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
//// [ES5For-of35.js.map]
|
||||
{"version":3,"file":"ES5For-of35.js","sourceRoot":"","sources":["ES5For-of35.ts"],"names":[],"mappings":";;;;;;;;;;;;IAAA,KAAmC,IAAA,KAAA,SAAA,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA,gBAAA,4BAAE;QAAhC,IAAA,aAAoB,EAAnB,SAAQ,EAAR,0BAAQ,EAAE,SAAQ,EAAR,0BAAQ;QAC1B,CAAC,CAAC;QACF,CAAC,CAAC;KACL"}
|
||||
{"version":3,"file":"ES5For-of35.js","sourceRoot":"","sources":["ES5For-of35.ts"],"names":[],"mappings":";;;;;;;;;;;;;IAAA,KAAmC,IAAA,KAAA,SAAA,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA,gBAAA,4BAAE;QAAhC,IAAA,aAAoB,EAAnB,SAAQ,EAAR,0BAAQ,EAAE,SAAQ,EAAR,0BAAQ;QAC1B,CAAC,CAAC;QACF,CAAC,CAAC;KACL"}
|
||||
@@ -8,15 +8,16 @@ sources: ES5For-of35.ts
|
||||
emittedFile:tests/cases/conformance/statements/for-ofStatements/ES5For-of35.js
|
||||
sourceFile:ES5For-of35.ts
|
||||
-------------------------------------------------------------------
|
||||
>>>var __values = (this && this.__values) || function (o) {
|
||||
>>> var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
|
||||
>>>var __values = (this && this.__values) || function(o) {
|
||||
>>> var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
>>> if (m) return m.call(o);
|
||||
>>> return {
|
||||
>>> if (o && typeof o.length === "number") return {
|
||||
>>> next: function () {
|
||||
>>> if (o && i >= o.length) o = void 0;
|
||||
>>> return { value: o && o[i++], done: !o };
|
||||
>>> }
|
||||
>>> };
|
||||
>>> throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
>>>};
|
||||
>>>var e_1, _a;
|
||||
>>>try {
|
||||
@@ -48,19 +49,19 @@ sourceFile:ES5For-of35.ts
|
||||
11>
|
||||
12>
|
||||
13> )
|
||||
1 >Emitted(13, 5) Source(1, 1) + SourceIndex(0)
|
||||
2 >Emitted(13, 10) Source(1, 36) + SourceIndex(0)
|
||||
3 >Emitted(13, 14) Source(1, 36) + SourceIndex(0)
|
||||
4 >Emitted(13, 19) Source(1, 36) + SourceIndex(0)
|
||||
5 >Emitted(13, 28) Source(1, 36) + SourceIndex(0)
|
||||
6 >Emitted(13, 29) Source(1, 37) + SourceIndex(0)
|
||||
7 >Emitted(13, 30) Source(1, 38) + SourceIndex(0)
|
||||
8 >Emitted(13, 32) Source(1, 40) + SourceIndex(0)
|
||||
9 >Emitted(13, 33) Source(1, 41) + SourceIndex(0)
|
||||
10>Emitted(13, 34) Source(1, 42) + SourceIndex(0)
|
||||
11>Emitted(13, 35) Source(1, 42) + SourceIndex(0)
|
||||
12>Emitted(13, 51) Source(1, 42) + SourceIndex(0)
|
||||
13>Emitted(13, 79) Source(1, 44) + SourceIndex(0)
|
||||
1 >Emitted(14, 5) Source(1, 1) + SourceIndex(0)
|
||||
2 >Emitted(14, 10) Source(1, 36) + SourceIndex(0)
|
||||
3 >Emitted(14, 14) Source(1, 36) + SourceIndex(0)
|
||||
4 >Emitted(14, 19) Source(1, 36) + SourceIndex(0)
|
||||
5 >Emitted(14, 28) Source(1, 36) + SourceIndex(0)
|
||||
6 >Emitted(14, 29) Source(1, 37) + SourceIndex(0)
|
||||
7 >Emitted(14, 30) Source(1, 38) + SourceIndex(0)
|
||||
8 >Emitted(14, 32) Source(1, 40) + SourceIndex(0)
|
||||
9 >Emitted(14, 33) Source(1, 41) + SourceIndex(0)
|
||||
10>Emitted(14, 34) Source(1, 42) + SourceIndex(0)
|
||||
11>Emitted(14, 35) Source(1, 42) + SourceIndex(0)
|
||||
12>Emitted(14, 51) Source(1, 42) + SourceIndex(0)
|
||||
13>Emitted(14, 79) Source(1, 44) + SourceIndex(0)
|
||||
---
|
||||
>>> var _d = _c.value, _e = _d.x, a = _e === void 0 ? 0 : _e, _f = _d.y, b = _f === void 0 ? 1 : _f;
|
||||
1->^^^^^^^^
|
||||
@@ -85,17 +86,17 @@ sourceFile:ES5For-of35.ts
|
||||
9 > y: b = 1
|
||||
10>
|
||||
11> y: b = 1
|
||||
1->Emitted(14, 9) Source(1, 12) + SourceIndex(0)
|
||||
2 >Emitted(14, 13) Source(1, 12) + SourceIndex(0)
|
||||
3 >Emitted(14, 26) Source(1, 32) + SourceIndex(0)
|
||||
4 >Emitted(14, 28) Source(1, 13) + SourceIndex(0)
|
||||
5 >Emitted(14, 37) Source(1, 21) + SourceIndex(0)
|
||||
6 >Emitted(14, 39) Source(1, 13) + SourceIndex(0)
|
||||
7 >Emitted(14, 65) Source(1, 21) + SourceIndex(0)
|
||||
8 >Emitted(14, 67) Source(1, 23) + SourceIndex(0)
|
||||
9 >Emitted(14, 76) Source(1, 31) + SourceIndex(0)
|
||||
10>Emitted(14, 78) Source(1, 23) + SourceIndex(0)
|
||||
11>Emitted(14, 104) Source(1, 31) + SourceIndex(0)
|
||||
1->Emitted(15, 9) Source(1, 12) + SourceIndex(0)
|
||||
2 >Emitted(15, 13) Source(1, 12) + SourceIndex(0)
|
||||
3 >Emitted(15, 26) Source(1, 32) + SourceIndex(0)
|
||||
4 >Emitted(15, 28) Source(1, 13) + SourceIndex(0)
|
||||
5 >Emitted(15, 37) Source(1, 21) + SourceIndex(0)
|
||||
6 >Emitted(15, 39) Source(1, 13) + SourceIndex(0)
|
||||
7 >Emitted(15, 65) Source(1, 21) + SourceIndex(0)
|
||||
8 >Emitted(15, 67) Source(1, 23) + SourceIndex(0)
|
||||
9 >Emitted(15, 76) Source(1, 31) + SourceIndex(0)
|
||||
10>Emitted(15, 78) Source(1, 23) + SourceIndex(0)
|
||||
11>Emitted(15, 104) Source(1, 31) + SourceIndex(0)
|
||||
---
|
||||
>>> a;
|
||||
1 >^^^^^^^^
|
||||
@@ -106,9 +107,9 @@ sourceFile:ES5For-of35.ts
|
||||
>
|
||||
2 > a
|
||||
3 > ;
|
||||
1 >Emitted(15, 9) Source(2, 5) + SourceIndex(0)
|
||||
2 >Emitted(15, 10) Source(2, 6) + SourceIndex(0)
|
||||
3 >Emitted(15, 11) Source(2, 7) + SourceIndex(0)
|
||||
1 >Emitted(16, 9) Source(2, 5) + SourceIndex(0)
|
||||
2 >Emitted(16, 10) Source(2, 6) + SourceIndex(0)
|
||||
3 >Emitted(16, 11) Source(2, 7) + SourceIndex(0)
|
||||
---
|
||||
>>> b;
|
||||
1->^^^^^^^^
|
||||
@@ -118,15 +119,15 @@ sourceFile:ES5For-of35.ts
|
||||
>
|
||||
2 > b
|
||||
3 > ;
|
||||
1->Emitted(16, 9) Source(3, 5) + SourceIndex(0)
|
||||
2 >Emitted(16, 10) Source(3, 6) + SourceIndex(0)
|
||||
3 >Emitted(16, 11) Source(3, 7) + SourceIndex(0)
|
||||
1->Emitted(17, 9) Source(3, 5) + SourceIndex(0)
|
||||
2 >Emitted(17, 10) Source(3, 6) + SourceIndex(0)
|
||||
3 >Emitted(17, 11) Source(3, 7) + SourceIndex(0)
|
||||
---
|
||||
>>> }
|
||||
1 >^^^^^
|
||||
1 >
|
||||
>}
|
||||
1 >Emitted(17, 6) Source(4, 2) + SourceIndex(0)
|
||||
1 >Emitted(18, 6) Source(4, 2) + SourceIndex(0)
|
||||
---
|
||||
>>>}
|
||||
>>>catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user