mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into completionWithMeaning
This commit is contained in:
@@ -248,4 +248,23 @@ rdosanjh <me@rajdeep.io> # Raj Dosanjh
|
||||
gdh1995 <gdh1995@qq.com> # Dahan Gong
|
||||
cedvdb <cedvandenbosch@gmail.com> # @cedvdb
|
||||
kpreisser <kpreisser@users.noreply.github.com> # K. Preißer
|
||||
e-cloud <saintscott119@gmail.com> # @e-cloud
|
||||
e-cloud <saintscott119@gmail.com> # @e-cloud
|
||||
Andrew Casey <amcasey@users.noreply.github.com> Andrew Casey <andrew.casey@microsoft.com>
|
||||
Andrew Stegmaier <andrew.stegmaier@gmail.com>
|
||||
Benny Neugebauer <bn@bennyn.de>
|
||||
Blaine Bublitz <blaine.bublitz@gmail.com>
|
||||
Charles Pierce <cpierce.grad@gmail.com>
|
||||
Daniel Król <daniel@krol.me>
|
||||
Diogo Franco (Kovensky) <diogomfranco@gmail.com>
|
||||
Donald Pipowitch <pipo@senaeh.de>
|
||||
Halasi Tamás <trusted.tomato@gmail.com>
|
||||
Ika <ikatyang@gmail.com>
|
||||
Joe Chung <joechung@microsoft.com>
|
||||
Kate Miháliková <kate@katemihalikova.cz>
|
||||
Mohsen Azimi <mazimi@lyft.com>
|
||||
Noel Varanda <ncwvaranda@gmail.com>
|
||||
Reiner Dolp <reiner-dolp@users.noreply.github.com>
|
||||
t_ <t-mrt@users.noreply.github.com> # @t_
|
||||
TravCav <xurrux@gmail.com> # @TravCav
|
||||
Vladimir Kurchatkin <vladimir.kurchatkin@gmail.com>
|
||||
William Orr <will@worrbase.com>
|
||||
+19
@@ -15,7 +15,9 @@ TypeScript is authored by:
|
||||
* Anders Hejlsberg
|
||||
* Andreas Martin
|
||||
* Andrej Baran
|
||||
* Andrew Casey
|
||||
* Andrew Ochsner
|
||||
* Andrew Stegmaier
|
||||
* Andrew Z Allen
|
||||
* András Parditka
|
||||
* Andy Hanson
|
||||
@@ -31,7 +33,9 @@ TypeScript is authored by:
|
||||
* Ben Duffield
|
||||
* Ben Mosher
|
||||
* Benjamin Bock
|
||||
* Benny Neugebauer
|
||||
* Bill Ticehurst
|
||||
* Blaine Bublitz
|
||||
* Blake Embrey
|
||||
* @bootstraponline
|
||||
* Bowden Kelly
|
||||
@@ -39,6 +43,7 @@ TypeScript is authored by:
|
||||
* Bryan Forbes
|
||||
* Caitlin Potter
|
||||
* @cedvdb
|
||||
* Charles Pierce
|
||||
* Charly POLY
|
||||
* Chris Bubernak
|
||||
* Christophe Vidal
|
||||
@@ -52,6 +57,7 @@ TypeScript is authored by:
|
||||
* Dan Corder
|
||||
* Dan Quirk
|
||||
* Daniel Hollocher
|
||||
* Daniel Król
|
||||
* Daniel Lehenbauer
|
||||
* Daniel Rosenwasser
|
||||
* David Kmenta
|
||||
@@ -60,9 +66,11 @@ TypeScript is authored by:
|
||||
* David Souther
|
||||
* Denis Nedelyaev
|
||||
* Dick van den Brink
|
||||
* Diogo Franco (Kovensky)
|
||||
* Dirk Bäumer
|
||||
* Dirk Holtwick
|
||||
* Dom Chen
|
||||
* Donald Pipowitch
|
||||
* Doug Ilijev
|
||||
* @e-cloud
|
||||
* Elisée Maurer
|
||||
@@ -89,12 +97,14 @@ TypeScript is authored by:
|
||||
* Guilherme Oenning
|
||||
* Guillaume Salles
|
||||
* Guy Bedford
|
||||
* Halasi Tamás
|
||||
* Harald Niesche
|
||||
* Hendrik Liebau
|
||||
* Herrington Darkholme
|
||||
* Homa Wong
|
||||
* Iain Monro
|
||||
* Igor Novozhilov
|
||||
* Ika
|
||||
* Ingvar Stepanyan
|
||||
* Isiah Meadows
|
||||
* Ivo Gabe de Wolff
|
||||
@@ -111,6 +121,7 @@ TypeScript is authored by:
|
||||
* Jeffrey Morlan
|
||||
* Jesse Schalken
|
||||
* Jiri Tobisek
|
||||
* Joe Chung
|
||||
* Joel Day
|
||||
* Joey Wilson
|
||||
* Johannes Rieken
|
||||
@@ -131,6 +142,7 @@ TypeScript is authored by:
|
||||
* K. Preißer
|
||||
* Kagami Sascha Rosylight
|
||||
* Kanchalai Tanglertsampan
|
||||
* Kate Miháliková
|
||||
* Keith Mashinter
|
||||
* Ken Howard
|
||||
* Kenji Imamula
|
||||
@@ -159,6 +171,7 @@ TypeScript is authored by:
|
||||
* Mike Busyrev
|
||||
* Mine Starks
|
||||
* Mohamed Hegazy
|
||||
* Mohsen Azimi
|
||||
* Myles Megyesi
|
||||
* Natalie Coley
|
||||
* Nathan Shively-Sanders
|
||||
@@ -166,6 +179,7 @@ TypeScript is authored by:
|
||||
* Nicolas Henry
|
||||
* Nima Zahedi
|
||||
* Noah Chen
|
||||
* Noel Varanda
|
||||
* Noj Vek
|
||||
* Oleg Mihailik
|
||||
* Oleksandr Chekhovskyi
|
||||
@@ -186,6 +200,7 @@ TypeScript is authored by:
|
||||
* Punya Biswal
|
||||
* Rado Kirov
|
||||
* Raj Dosanjh
|
||||
* Reiner Dolp
|
||||
* Richard Karmazín
|
||||
* Richard Knoll
|
||||
* Richard Sentino
|
||||
@@ -213,6 +228,7 @@ TypeScript is authored by:
|
||||
* Sudheesh Singanamalla
|
||||
* Sébastien Arod
|
||||
* @T18970237136
|
||||
* @t_
|
||||
* Tarik Ozket
|
||||
* Tetsuharu Ohzeki
|
||||
* Thomas Loubiou
|
||||
@@ -225,13 +241,16 @@ TypeScript is authored by:
|
||||
* togru
|
||||
* Tomas Grubliauskas
|
||||
* Torben Fitschen
|
||||
* @TravCav
|
||||
* TruongSinh Tran-Nguyen
|
||||
* Vadi Taslim
|
||||
* Vidar Tonaas Fauske
|
||||
* Viktor Zozulyak
|
||||
* Vilic Vane
|
||||
* Vladimir Kurchatkin
|
||||
* Vladimir Matveev
|
||||
* Wesley Wigham
|
||||
* William Orr
|
||||
* York Yao
|
||||
* @yortus
|
||||
* Yuichi Nukiyama
|
||||
|
||||
+20
-17
@@ -39,25 +39,25 @@ Error.stackTraceLimit = 1000;
|
||||
|
||||
const cmdLineOptions = minimist(process.argv.slice(2), {
|
||||
boolean: ["debug", "inspect", "light", "colors", "lint", "soft"],
|
||||
string: ["browser", "tests", "host", "reporter", "stackTraceLimit"],
|
||||
string: ["browser", "tests", "host", "reporter", "stackTraceLimit", "timeout"],
|
||||
alias: {
|
||||
b: "browser",
|
||||
d: "debug",
|
||||
t: "tests",
|
||||
test: "tests",
|
||||
d: "debug", "debug-brk": "debug",
|
||||
i: "inspect", "inspect-brk": "inspect",
|
||||
t: "tests", test: "tests",
|
||||
r: "reporter",
|
||||
color: "colors",
|
||||
f: "files",
|
||||
file: "files",
|
||||
c: "colors", color: "colors",
|
||||
f: "files", file: "files",
|
||||
w: "workers",
|
||||
},
|
||||
default: {
|
||||
soft: false,
|
||||
colors: process.env.colors || process.env.color || true,
|
||||
debug: process.env.debug || process.env.d,
|
||||
inspect: process.env.inspect,
|
||||
debug: process.env.debug || process.env["debug-brk"] || process.env.d,
|
||||
inspect: process.env.inspect || process.env["inspect-brk"] || process.env.i,
|
||||
host: process.env.TYPESCRIPT_HOST || process.env.host || "node",
|
||||
browser: process.env.browser || process.env.b || "IE",
|
||||
timeout: process.env.timeout || 40000,
|
||||
tests: process.env.test || process.env.tests || process.env.t,
|
||||
light: process.env.light || false,
|
||||
reporter: process.env.reporter || process.env.r,
|
||||
@@ -594,11 +594,11 @@ function restoreSavedNodeEnv() {
|
||||
process.env.NODE_ENV = savedNodeEnv;
|
||||
}
|
||||
|
||||
let testTimeout = 40000;
|
||||
function runConsoleTests(defaultReporter: string, runInParallel: boolean, done: (e?: any) => void) {
|
||||
const lintFlag = cmdLineOptions["lint"];
|
||||
cleanTestDirs((err) => {
|
||||
if (err) { console.error(err); failWithStatus(err, 1); }
|
||||
let testTimeout = cmdLineOptions["timeout"];
|
||||
const debug = cmdLineOptions["debug"];
|
||||
const inspect = cmdLineOptions["inspect"];
|
||||
const tests = cmdLineOptions["tests"];
|
||||
@@ -637,12 +637,6 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
|
||||
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
|
||||
if (!runInParallel) {
|
||||
const args = [];
|
||||
if (inspect) {
|
||||
args.push("--inspect");
|
||||
}
|
||||
if (inspect || debug) {
|
||||
args.push("--debug-brk");
|
||||
}
|
||||
args.push("-R", reporter);
|
||||
if (tests) {
|
||||
args.push("-g", `"${tests}"`);
|
||||
@@ -653,7 +647,15 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
|
||||
else {
|
||||
args.push("--no-colors");
|
||||
}
|
||||
args.push("-t", testTimeout);
|
||||
if (inspect) {
|
||||
args.unshift("--inspect-brk");
|
||||
}
|
||||
else if (debug) {
|
||||
args.unshift("--debug-brk");
|
||||
}
|
||||
else {
|
||||
args.push("-t", testTimeout);
|
||||
}
|
||||
args.push(run);
|
||||
setNodeEnvToDevelopment();
|
||||
exec(mocha, args, lintThenFinish, function(e, status) {
|
||||
@@ -838,6 +840,7 @@ gulp.task("runtests-browser", "Runs the tests using the built run.js file like '
|
||||
});
|
||||
|
||||
gulp.task("generate-code-coverage", "Generates code coverage data via istanbul", ["tests"], (done) => {
|
||||
const testTimeout = cmdLineOptions["timeout"];
|
||||
exec("istanbul", ["cover", "node_modules/mocha/bin/_mocha", "--", "-R", "min", "-t", testTimeout.toString(), run], done, done);
|
||||
});
|
||||
|
||||
|
||||
+24
-19
@@ -25,6 +25,8 @@ var LKGDirectory = "lib/";
|
||||
var copyright = "CopyrightNotice.txt";
|
||||
var thirdParty = "ThirdPartyNoticeText.txt";
|
||||
|
||||
var defaultTestTimeout = 40000;
|
||||
|
||||
// add node_modules to path so we don't need global modules, prefer the modules by adding them first
|
||||
var nodeModulesPathPrefix = path.resolve("./node_modules/.bin/") + path.delimiter;
|
||||
if (process.env.path !== undefined) {
|
||||
@@ -74,6 +76,10 @@ function measure(marker) {
|
||||
console.log("travis_time:end:" + marker.id + ":start=" + toNs(marker.stamp) + ",finish=" + toNs(total) + ",duration=" + toNs(diff) + "\r");
|
||||
}
|
||||
|
||||
function removeConstModifierFromEnumDeclarations(text) {
|
||||
return text.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
|
||||
}
|
||||
|
||||
var compilerSources = filesFromConfig("./src/compiler/tsconfig.json");
|
||||
var servicesSources = filesFromConfig("./src/services/tsconfig.json");
|
||||
var cancellationTokenSources = filesFromConfig(path.join(serverDirectory, "cancellationToken/tsconfig.json"));
|
||||
@@ -268,7 +274,6 @@ var builtLocalCompiler = path.join(builtLocalDirectory, compilerFilename);
|
||||
* @param {boolean} opts.preserveConstEnums: true if compiler should keep const enums in code
|
||||
* @param {boolean} opts.noResolve: true if compiler should not include non-rooted files in compilation
|
||||
* @param {boolean} opts.stripInternal: true if compiler should remove declarations marked as @internal
|
||||
* @param {boolean} opts.noMapRoot: true if compiler omit mapRoot option
|
||||
* @param {boolean} opts.inlineSourceMap: true if compiler should inline sourceMap
|
||||
* @param {Array} opts.types: array of types to include in compilation
|
||||
* @param callback: a function to execute after the compilation process ends
|
||||
@@ -321,9 +326,6 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
}
|
||||
else {
|
||||
options += " -sourcemap";
|
||||
if (!opts.noMapRoot) {
|
||||
options += " -mapRoot file:///" + path.resolve(path.dirname(outFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -527,7 +529,7 @@ task("importDefinitelyTypedTests", [importDefinitelyTypedTestsJs], function () {
|
||||
|
||||
// Local target to build the compiler and services
|
||||
var tscFile = path.join(builtLocalDirectory, compilerFilename);
|
||||
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false, { noMapRoot: true });
|
||||
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false);
|
||||
|
||||
var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js");
|
||||
var servicesFileInBrowserTest = path.join(builtLocalDirectory, "typescriptServicesInBrowserTest.js");
|
||||
@@ -555,7 +557,7 @@ compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].conc
|
||||
// Stanalone/web definition file using global 'ts' namespace
|
||||
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, { silent: true });
|
||||
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
|
||||
definitionFileContents = definitionFileContents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
|
||||
definitionFileContents = removeConstModifierFromEnumDeclarations(definitionFileContents)
|
||||
fs.writeFileSync(standaloneDefinitionsFile, definitionFileContents);
|
||||
|
||||
// Official node package definition file, pointed to by 'typings' in package.json
|
||||
@@ -582,7 +584,6 @@ compileFile(
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true,
|
||||
noMapRoot: true,
|
||||
inlineSourceMap: true
|
||||
});
|
||||
|
||||
@@ -616,6 +617,7 @@ compileFile(
|
||||
fs.readFileSync(tsserverLibraryDefinitionFile).toString() +
|
||||
"\r\nexport = ts;" +
|
||||
"\r\nexport as namespace ts;";
|
||||
tsserverLibraryDefinitionFileContents = removeConstModifierFromEnumDeclarations(tsserverLibraryDefinitionFileContents);
|
||||
|
||||
fs.writeFileSync(tsserverLibraryDefinitionFile, tsserverLibraryDefinitionFileContents);
|
||||
});
|
||||
@@ -805,9 +807,10 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
cleanTestDirs();
|
||||
}
|
||||
|
||||
var debug = process.env.debug || process.env.d;
|
||||
var inspect = process.env.inspect;
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var debug = process.env.debug || process.env["debug-brk"] || process.env.d;
|
||||
var inspect = process.env.inspect || process.env["inspect-brk"] || process.env.i;
|
||||
var testTimeout = process.env.timeout || defaultTestTimeout;
|
||||
var tests = process.env.test || process.env.tests || process.env.t;
|
||||
var light = process.env.light || false;
|
||||
var stackTraceLimit = process.env.stackTraceLimit;
|
||||
var testConfigFile = 'test.config';
|
||||
@@ -825,7 +828,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
} while (fs.existsSync(taskConfigsFolder));
|
||||
fs.mkdirSync(taskConfigsFolder);
|
||||
|
||||
workerCount = process.env.workerCount || os.cpus().length;
|
||||
workerCount = process.env.workerCount || process.env.p || os.cpus().length;
|
||||
}
|
||||
|
||||
if (tests || light || taskConfigsFolder) {
|
||||
@@ -846,12 +849,6 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
if (!runInParallel) {
|
||||
var startTime = mark();
|
||||
var args = [];
|
||||
if (inspect) {
|
||||
args.push("--inspect");
|
||||
}
|
||||
if (inspect || debug) {
|
||||
args.push("--debug-brk");
|
||||
}
|
||||
args.push("-R", reporter);
|
||||
if (tests) {
|
||||
args.push("-g", `"${tests}"`);
|
||||
@@ -865,7 +862,15 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
if (bail) {
|
||||
args.push("--bail");
|
||||
}
|
||||
args.push("-t", testTimeout);
|
||||
if (inspect) {
|
||||
args.unshift("--inspect-brk");
|
||||
}
|
||||
else if (debug) {
|
||||
args.unshift("--debug-brk");
|
||||
}
|
||||
else {
|
||||
args.push("-t", testTimeout);
|
||||
}
|
||||
args.push(run);
|
||||
|
||||
var cmd = "mocha " + args.join(" ");
|
||||
@@ -930,7 +935,6 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
}
|
||||
}
|
||||
|
||||
var testTimeout = 20000;
|
||||
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
|
||||
task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function () {
|
||||
runConsoleTests('min', /*runInParallel*/ true);
|
||||
@@ -943,6 +947,7 @@ task("runtests", ["build-rules", "tests", builtLocalDirectory], function() {
|
||||
|
||||
desc("Generates code coverage data via instanbul");
|
||||
task("generate-code-coverage", ["tests", builtLocalDirectory], function () {
|
||||
var testTimeout = process.env.timeout || defaultTestTimeout;
|
||||
var cmd = 'istanbul cover node_modules/mocha/bin/_mocha -- -R min -t ' + testTimeout + ' ' + run;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
|
||||
@@ -113,7 +113,7 @@ class DeclarationsWalker {
|
||||
}
|
||||
}
|
||||
|
||||
function generateProtocolFile(protocolTs: string, typeScriptServicesDts: string): string {
|
||||
function writeProtocolFile(outputFile: string, protocolTs: string, typeScriptServicesDts: string) {
|
||||
const options = { target: ts.ScriptTarget.ES5, declaration: true, noResolve: true, types: <string[]>[], stripInternal: true };
|
||||
|
||||
/**
|
||||
@@ -163,14 +163,17 @@ function generateProtocolFile(protocolTs: string, typeScriptServicesDts: string)
|
||||
protocolDts += "\nimport protocol = ts.server.protocol;";
|
||||
protocolDts += "\nexport = protocol;";
|
||||
protocolDts += "\nexport as namespace protocol;";
|
||||
|
||||
// do sanity check and try to compile generated text as standalone program
|
||||
const sanityCheckProgram = getProgramWithProtocolText(protocolDts, /*includeTypeScriptServices*/ false);
|
||||
const diagnostics = [...sanityCheckProgram.getSyntacticDiagnostics(), ...sanityCheckProgram.getSemanticDiagnostics(), ...sanityCheckProgram.getGlobalDiagnostics()];
|
||||
|
||||
ts.sys.writeFile(outputFile, protocolDts);
|
||||
|
||||
if (diagnostics.length) {
|
||||
const flattenedDiagnostics = diagnostics.map(d => `${ts.flattenDiagnosticMessageText(d.messageText, "\n")} at ${d.file.fileName} line ${d.start}`).join("\n");
|
||||
throw new Error(`Unexpected errors during sanity check: ${flattenedDiagnostics}`);
|
||||
}
|
||||
return protocolDts;
|
||||
}
|
||||
|
||||
if (process.argv.length < 5) {
|
||||
@@ -181,5 +184,4 @@ if (process.argv.length < 5) {
|
||||
const protocolTs = process.argv[2];
|
||||
const typeScriptServicesDts = process.argv[3];
|
||||
const outputFile = process.argv[4];
|
||||
const generatedProtocolDts = generateProtocolFile(protocolTs, typeScriptServicesDts);
|
||||
ts.sys.writeFile(outputFile, generatedProtocolDts);
|
||||
writeProtocolFile(outputFile, protocolTs, typeScriptServicesDts);
|
||||
|
||||
@@ -18,7 +18,7 @@ export class Rule extends Lint.Rules.AbstractRule {
|
||||
|
||||
function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boolean): void {
|
||||
const { sourceFile } = ctx;
|
||||
function recur(node: ts.Node): void {
|
||||
ts.forEachChild(sourceFile, function recur(node) {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.IfStatement:
|
||||
checkIf(node as ts.IfStatement);
|
||||
@@ -28,7 +28,7 @@ function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boole
|
||||
break;
|
||||
}
|
||||
ts.forEachChild(node, recur);
|
||||
}
|
||||
});
|
||||
|
||||
function checkIf(node: ts.IfStatement): void {
|
||||
const { thenStatement, elseStatement } = node;
|
||||
|
||||
+17
-8
@@ -612,7 +612,7 @@ namespace ts {
|
||||
break;
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
bindForInOrForOfStatement(<ForInStatement | ForOfStatement>node);
|
||||
bindForInOrForOfStatement(<ForInOrOfStatement>node);
|
||||
break;
|
||||
case SyntaxKind.IfStatement:
|
||||
bindIfStatement(<IfStatement>node);
|
||||
@@ -950,7 +950,7 @@ namespace ts {
|
||||
currentFlow = finishFlowLabel(postLoopLabel);
|
||||
}
|
||||
|
||||
function bindForInOrForOfStatement(node: ForInStatement | ForOfStatement): void {
|
||||
function bindForInOrForOfStatement(node: ForInOrOfStatement): void {
|
||||
const preLoopLabel = createLoopLabel();
|
||||
const postLoopLabel = createBranchLabel();
|
||||
addAntecedent(preLoopLabel, currentFlow);
|
||||
@@ -1328,7 +1328,7 @@ namespace ts {
|
||||
|
||||
function bindVariableDeclarationFlow(node: VariableDeclaration) {
|
||||
bindEachChild(node);
|
||||
if (node.initializer || node.parent.parent.kind === SyntaxKind.ForInStatement || node.parent.parent.kind === SyntaxKind.ForOfStatement) {
|
||||
if (node.initializer || isForInOrOfStatement(node.parent.parent)) {
|
||||
bindInitializedVariableFlow(node);
|
||||
}
|
||||
}
|
||||
@@ -1521,7 +1521,7 @@ namespace ts {
|
||||
// All the children of these container types are never visible through another
|
||||
// symbol (i.e. through another symbol's 'exports' or 'members'). Instead,
|
||||
// they're only accessed 'lexically' (i.e. from code that exists underneath
|
||||
// their container in the tree. To accomplish this, we simply add their declared
|
||||
// their container in the tree). To accomplish this, we simply add their declared
|
||||
// symbol to the 'locals' of the container. These symbols can then be found as
|
||||
// the type checker walks up the containers, checking them for matching names.
|
||||
return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
|
||||
@@ -2053,7 +2053,10 @@ namespace ts {
|
||||
case SyntaxKind.TypePredicate:
|
||||
return checkTypePredicate(node as TypePredicateNode);
|
||||
case SyntaxKind.TypeParameter:
|
||||
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
|
||||
if (node.parent.kind !== ts.SyntaxKind.JSDocTemplateTag || isInJavaScriptFile(node)) {
|
||||
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.Parameter:
|
||||
return bindParameter(<ParameterDeclaration>node);
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
@@ -2135,8 +2138,10 @@ namespace ts {
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
return bindEnumDeclaration(<EnumDeclaration>node);
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return bindModuleDeclaration(<ModuleDeclaration>node);
|
||||
|
||||
if (node.parent.kind !== ts.SyntaxKind.JSDocTypedefTag || isInJavaScriptFile(node)) {
|
||||
return bindModuleDeclaration(<ModuleDeclaration>node);
|
||||
}
|
||||
return undefined;
|
||||
// Jsx-attributes
|
||||
case SyntaxKind.JsxAttributes:
|
||||
return bindJsxAttributes(<JsxAttributes>node);
|
||||
@@ -2333,7 +2338,7 @@ namespace ts {
|
||||
// A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports'
|
||||
// is still pointing to 'module.exports'.
|
||||
// We do not want to consider this as 'export=' since a module can have only one of these.
|
||||
// Similarlly we do not want to treat 'module.exports = exports' as an 'export='.
|
||||
// Similarly we do not want to treat 'module.exports = exports' as an 'export='.
|
||||
const assignedExpression = getRightMostAssignedExpression(node.right);
|
||||
if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) {
|
||||
// Mark it as a module in case there are no other exports in the file
|
||||
@@ -2741,6 +2746,10 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertES2015;
|
||||
}
|
||||
|
||||
if (expression.kind === SyntaxKind.ImportKeyword) {
|
||||
transformFlags |= TransformFlags.ContainsDynamicImport;
|
||||
}
|
||||
|
||||
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
|
||||
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
|
||||
}
|
||||
|
||||
+475
-311
File diff suppressed because it is too large
Load Diff
@@ -100,11 +100,12 @@ namespace ts {
|
||||
"umd": ModuleKind.UMD,
|
||||
"es6": ModuleKind.ES2015,
|
||||
"es2015": ModuleKind.ES2015,
|
||||
"esnext": ModuleKind.ESNext
|
||||
}),
|
||||
paramType: Diagnostics.KIND,
|
||||
showInSimplifiedHelpView: true,
|
||||
category: Diagnostics.Basic_Options,
|
||||
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
|
||||
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_es2015_or_ESNext,
|
||||
},
|
||||
{
|
||||
name: "lib",
|
||||
@@ -619,6 +620,12 @@ namespace ts {
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.The_maximum_dependency_depth_to_search_under_node_modules_and_load_JavaScript_files
|
||||
},
|
||||
{
|
||||
name: "noStrictGenericChecks",
|
||||
type: "boolean",
|
||||
category: Diagnostics.Advanced_Options,
|
||||
description: Diagnostics.Disable_strict_checking_of_generic_signatures_in_function_types,
|
||||
},
|
||||
{
|
||||
// A list of plugins to load in the language service
|
||||
name: "plugins",
|
||||
@@ -1042,7 +1049,7 @@ namespace ts {
|
||||
for (let i = 0; i < nameColumn.length; i++) {
|
||||
const optionName = nameColumn[i];
|
||||
const description = descriptionColumn[i];
|
||||
result.push(tab + tab + optionName + makePadding(marginLength - optionName.length + 2) + description);
|
||||
result.push(optionName && `${tab}${tab}${optionName}${ description && (makePadding(marginLength - optionName.length + 2) + description)}`);
|
||||
}
|
||||
if (configurations.files && configurations.files.length) {
|
||||
result.push(`${tab}},`);
|
||||
@@ -1625,10 +1632,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Remove any subpaths under an existing recursively watched directory.
|
||||
for (const key in wildcardDirectories) if (hasProperty(wildcardDirectories, key)) {
|
||||
for (const recursiveKey of recursiveKeys) {
|
||||
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
|
||||
delete wildcardDirectories[key];
|
||||
for (const key in wildcardDirectories) {
|
||||
if (hasProperty(wildcardDirectories, key)) {
|
||||
for (const recursiveKey of recursiveKeys) {
|
||||
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
|
||||
delete wildcardDirectories[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1716,10 +1725,12 @@ namespace ts {
|
||||
/* @internal */
|
||||
export function convertCompilerOptionsForTelemetry(opts: ts.CompilerOptions): ts.CompilerOptions {
|
||||
const out: ts.CompilerOptions = {};
|
||||
for (const key in opts) if (opts.hasOwnProperty(key)) {
|
||||
const type = getOptionFromName(key);
|
||||
if (type !== undefined) { // Ignore unknown options
|
||||
out[key] = getOptionValueWithEmptyStrings(opts[key], type);
|
||||
for (const key in opts) {
|
||||
if (opts.hasOwnProperty(key)) {
|
||||
const type = getOptionFromName(key);
|
||||
if (type !== undefined) { // Ignore unknown options
|
||||
out[key] = getOptionValueWithEmptyStrings(opts[key], type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
|
||||
+57
-44
@@ -51,8 +51,10 @@ namespace ts {
|
||||
|
||||
// Copies keys/values from template. Note that for..in will not throw if
|
||||
// template is undefined, and instead will just exit the loop.
|
||||
for (const key in template) if (hasOwnProperty.call(template, key)) {
|
||||
map.set(key, template[key]);
|
||||
for (const key in template) {
|
||||
if (hasOwnProperty.call(template, key)) {
|
||||
map.set(key, template[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
@@ -473,7 +475,7 @@ namespace ts {
|
||||
* @param array The array to map.
|
||||
* @param mapfn The callback used to map the result into one or more values.
|
||||
*/
|
||||
export function flatMap<T, U>(array: T[], mapfn: (x: T, i: number) => U | U[]): U[] {
|
||||
export function flatMap<T, U>(array: T[] | undefined, mapfn: (x: T, i: number) => U | U[] | undefined): U[] | undefined {
|
||||
let result: U[];
|
||||
if (array) {
|
||||
result = [];
|
||||
@@ -521,8 +523,8 @@ namespace ts {
|
||||
return result || array;
|
||||
}
|
||||
|
||||
export function mapDefined<T>(array: ReadonlyArray<T>, mapFn: (x: T, i: number) => T | undefined): ReadonlyArray<T> {
|
||||
const result: T[] = [];
|
||||
export function mapDefined<T, U>(array: ReadonlyArray<T>, mapFn: (x: T, i: number) => U | undefined): U[] {
|
||||
const result: U[] = [];
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const item = array[i];
|
||||
const mapped = mapFn(item, i);
|
||||
@@ -977,9 +979,12 @@ namespace ts {
|
||||
*/
|
||||
export function getOwnKeys<T>(map: MapLike<T>): string[] {
|
||||
const keys: string[] = [];
|
||||
for (const key in map) if (hasOwnProperty.call(map, key)) {
|
||||
keys.push(key);
|
||||
for (const key in map) {
|
||||
if (hasOwnProperty.call(map, key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
@@ -1042,8 +1047,10 @@ namespace ts {
|
||||
export function assign<T1 extends MapLike<{}>>(t: T1, ...args: any[]): any;
|
||||
export function assign<T1 extends MapLike<{}>>(t: T1, ...args: any[]) {
|
||||
for (const arg of args) {
|
||||
for (const p in arg) if (hasProperty(arg, p)) {
|
||||
t[p] = arg[p];
|
||||
for (const p in arg) {
|
||||
if (hasProperty(arg, p)) {
|
||||
t[p] = arg[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
return t;
|
||||
@@ -1058,13 +1065,19 @@ namespace ts {
|
||||
export function equalOwnProperties<T>(left: MapLike<T>, right: MapLike<T>, equalityComparer?: (left: T, right: T) => boolean) {
|
||||
if (left === right) return true;
|
||||
if (!left || !right) return false;
|
||||
for (const key in left) if (hasOwnProperty.call(left, key)) {
|
||||
if (!hasOwnProperty.call(right, key) === undefined) return false;
|
||||
if (equalityComparer ? !equalityComparer(left[key], right[key]) : left[key] !== right[key]) return false;
|
||||
for (const key in left) {
|
||||
if (hasOwnProperty.call(left, key)) {
|
||||
if (!hasOwnProperty.call(right, key) === undefined) return false;
|
||||
if (equalityComparer ? !equalityComparer(left[key], right[key]) : left[key] !== right[key]) return false;
|
||||
}
|
||||
}
|
||||
for (const key in right) if (hasOwnProperty.call(right, key)) {
|
||||
if (!hasOwnProperty.call(left, key)) return false;
|
||||
|
||||
for (const key in right) {
|
||||
if (hasOwnProperty.call(right, key)) {
|
||||
if (!hasOwnProperty.call(left, key)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1106,12 +1119,18 @@ namespace ts {
|
||||
|
||||
export function extend<T1, T2>(first: T1, second: T2): T1 & T2 {
|
||||
const result: T1 & T2 = <any>{};
|
||||
for (const id in second) if (hasOwnProperty.call(second, id)) {
|
||||
(result as any)[id] = (second as any)[id];
|
||||
for (const id in second) {
|
||||
if (hasOwnProperty.call(second, id)) {
|
||||
(result as any)[id] = (second as any)[id];
|
||||
}
|
||||
}
|
||||
for (const id in first) if (hasOwnProperty.call(first, id)) {
|
||||
(result as any)[id] = (first as any)[id];
|
||||
|
||||
for (const id in first) {
|
||||
if (hasOwnProperty.call(first, id)) {
|
||||
(result as any)[id] = (first as any)[id];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2112,13 +2131,13 @@ namespace ts {
|
||||
export function getScriptKindFromFileName(fileName: string): ScriptKind {
|
||||
const ext = fileName.substr(fileName.lastIndexOf("."));
|
||||
switch (ext.toLowerCase()) {
|
||||
case ".js":
|
||||
case Extension.Js:
|
||||
return ScriptKind.JS;
|
||||
case ".jsx":
|
||||
case Extension.Jsx:
|
||||
return ScriptKind.JSX;
|
||||
case ".ts":
|
||||
case Extension.Ts:
|
||||
return ScriptKind.TS;
|
||||
case ".tsx":
|
||||
case Extension.Tsx:
|
||||
return ScriptKind.TSX;
|
||||
default:
|
||||
return ScriptKind.Unknown;
|
||||
@@ -2128,10 +2147,10 @@ namespace ts {
|
||||
/**
|
||||
* List of supported extensions in order of file resolution precedence.
|
||||
*/
|
||||
export const supportedTypeScriptExtensions = [".ts", ".tsx", ".d.ts"];
|
||||
export const supportedTypeScriptExtensions = [Extension.Ts, Extension.Tsx, Extension.Dts];
|
||||
/** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */
|
||||
export const supportedTypescriptExtensionsForExtractExtension = [".d.ts", ".ts", ".tsx"];
|
||||
export const supportedJavascriptExtensions = [".js", ".jsx"];
|
||||
export const supportedTypescriptExtensionsForExtractExtension = [Extension.Dts, Extension.Ts, Extension.Tsx];
|
||||
export const supportedJavascriptExtensions = [Extension.Js, Extension.Jsx];
|
||||
const allSupportedExtensions = supportedTypeScriptExtensions.concat(supportedJavascriptExtensions);
|
||||
|
||||
export function getSupportedExtensions(options?: CompilerOptions, extraFileExtensions?: JsFileExtensionInfo[]): string[] {
|
||||
@@ -2139,7 +2158,7 @@ namespace ts {
|
||||
if (!extraFileExtensions || extraFileExtensions.length === 0 || !needAllExtensions) {
|
||||
return needAllExtensions ? allSupportedExtensions : supportedTypeScriptExtensions;
|
||||
}
|
||||
const extensions = allSupportedExtensions.slice(0);
|
||||
const extensions: string[] = allSupportedExtensions.slice(0);
|
||||
for (const extInfo of extraFileExtensions) {
|
||||
if (extensions.indexOf(extInfo.extension) === -1) {
|
||||
extensions.push(extInfo.extension);
|
||||
@@ -2218,7 +2237,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"];
|
||||
const extensionsToRemove = [Extension.Dts, Extension.Ts, Extension.Js, Extension.Tsx, Extension.Jsx];
|
||||
export function removeFileExtension(path: string): string {
|
||||
for (const ext of extensionsToRemove) {
|
||||
const extensionless = tryRemoveExtension(path, ext);
|
||||
@@ -2249,6 +2268,7 @@ namespace ts {
|
||||
getSymbolConstructor(): new (flags: SymbolFlags, name: string) => Symbol;
|
||||
getTypeConstructor(): new (checker: TypeChecker, flags: TypeFlags) => Type;
|
||||
getSignatureConstructor(): new (checker: TypeChecker) => Signature;
|
||||
getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource;
|
||||
}
|
||||
|
||||
function Symbol(this: Symbol, flags: SymbolFlags, name: string) {
|
||||
@@ -2279,6 +2299,12 @@ namespace ts {
|
||||
this.original = undefined;
|
||||
}
|
||||
|
||||
function SourceMapSource(this: SourceMapSource, fileName: string, text: string, skipTrivia?: (pos: number) => number) {
|
||||
this.fileName = fileName;
|
||||
this.text = text;
|
||||
this.skipTrivia = skipTrivia || (pos => pos);
|
||||
}
|
||||
|
||||
export let objectAllocator: ObjectAllocator = {
|
||||
getNodeConstructor: () => <any>Node,
|
||||
getTokenConstructor: () => <any>Node,
|
||||
@@ -2286,7 +2312,8 @@ namespace ts {
|
||||
getSourceFileConstructor: () => <any>Node,
|
||||
getSymbolConstructor: () => <any>Symbol,
|
||||
getTypeConstructor: () => <any>Type,
|
||||
getSignatureConstructor: () => <any>Signature
|
||||
getSignatureConstructor: () => <any>Signature,
|
||||
getSourceMapSourceConstructor: () => <any>SourceMapSource,
|
||||
};
|
||||
|
||||
export const enum AssertionLevel {
|
||||
@@ -2464,7 +2491,7 @@ namespace ts {
|
||||
|
||||
/** True if an extension is one of the supported TypeScript extensions. */
|
||||
export function extensionIsTypeScript(ext: Extension): boolean {
|
||||
return ext <= Extension.LastTypeScriptExtension;
|
||||
return ext === Extension.Ts || ext === Extension.Tsx || ext === Extension.Dts;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2479,21 +2506,7 @@ namespace ts {
|
||||
Debug.fail(`File ${path} has unknown extension.`);
|
||||
}
|
||||
export function tryGetExtensionFromPath(path: string): Extension | undefined {
|
||||
if (fileExtensionIs(path, ".d.ts")) {
|
||||
return Extension.Dts;
|
||||
}
|
||||
if (fileExtensionIs(path, ".ts")) {
|
||||
return Extension.Ts;
|
||||
}
|
||||
if (fileExtensionIs(path, ".tsx")) {
|
||||
return Extension.Tsx;
|
||||
}
|
||||
if (fileExtensionIs(path, ".js")) {
|
||||
return Extension.Js;
|
||||
}
|
||||
if (fileExtensionIs(path, ".jsx")) {
|
||||
return Extension.Jsx;
|
||||
}
|
||||
return find(supportedTypescriptExtensionsForExtractExtension, e => fileExtensionIs(path, e)) || find(supportedJavascriptExtensions, e => fileExtensionIs(path, e));
|
||||
}
|
||||
|
||||
export function isCheckJsEnabledForFile(sourceFile: SourceFile, compilerOptions: CompilerOptions) {
|
||||
|
||||
@@ -596,7 +596,7 @@ namespace ts {
|
||||
currentIdentifiers = node.identifiers;
|
||||
isCurrentFileExternalModule = isExternalModule(node);
|
||||
enclosingDeclaration = node;
|
||||
emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, /*removeComents*/ true);
|
||||
emitDetachedComments(currentText, currentLineMap, writer, writeCommentRange, node, newLine, /*removeComments*/ true);
|
||||
emitLines(node.statements);
|
||||
}
|
||||
|
||||
|
||||
@@ -883,6 +883,23 @@
|
||||
"category": "Error",
|
||||
"code": 1322
|
||||
},
|
||||
"Dynamic import cannot be used when targeting ECMAScript 2015 modules.": {
|
||||
"category": "Error",
|
||||
"code": 1323
|
||||
},
|
||||
"Dynamic import must have one specifier as an argument.": {
|
||||
"category": "Error",
|
||||
"code": 1324
|
||||
},
|
||||
"Specifier of dynamic import cannot be spread element.": {
|
||||
"category": "Error",
|
||||
"code": 1325
|
||||
},
|
||||
"Dynamic import cannot have type arguments": {
|
||||
"category": "Error",
|
||||
"code": 1326
|
||||
},
|
||||
|
||||
"Duplicate identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2300
|
||||
@@ -1879,6 +1896,10 @@
|
||||
"category": "Error",
|
||||
"code": 2558
|
||||
},
|
||||
"Type '{0}' has no properties in common with type '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2559
|
||||
},
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
@@ -1923,10 +1944,6 @@
|
||||
"category": "Error",
|
||||
"code": 2649
|
||||
},
|
||||
"Cannot emit namespaced JSX elements in React.": {
|
||||
"category": "Error",
|
||||
"code": 2650
|
||||
},
|
||||
"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": {
|
||||
"category": "Error",
|
||||
"code": 2651
|
||||
@@ -2159,6 +2176,14 @@
|
||||
"category": "Error",
|
||||
"code": 2710
|
||||
},
|
||||
"A dynamic import call returns a 'Promise'. Make sure you have a declaration for 'Promise' or include 'ES2015' in your `--lib` option.": {
|
||||
"category": "Error",
|
||||
"code": 2711
|
||||
},
|
||||
"A dynamic import call in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option.": {
|
||||
"category": "Error",
|
||||
"code": 2712
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
@@ -2625,7 +2650,7 @@
|
||||
"category": "Message",
|
||||
"code": 6015
|
||||
},
|
||||
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'.": {
|
||||
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": {
|
||||
"category": "Message",
|
||||
"code": 6016
|
||||
},
|
||||
@@ -3253,6 +3278,10 @@
|
||||
"category": "Message",
|
||||
"code": 6184
|
||||
},
|
||||
"Disable strict checking of generic signatures in function types.": {
|
||||
"category": "Message",
|
||||
"code": 6185
|
||||
},
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
"code": 7005
|
||||
@@ -3361,6 +3390,11 @@
|
||||
"category": "Error",
|
||||
"code": 7035
|
||||
},
|
||||
"Dynamic import's specifier must be of type 'string', but here has type '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 7036
|
||||
},
|
||||
|
||||
"You cannot rename this element.": {
|
||||
"category": "Error",
|
||||
"code": 8000
|
||||
@@ -3555,11 +3589,11 @@
|
||||
"category": "Message",
|
||||
"code": 90015
|
||||
},
|
||||
"Add declaration for missing property '{0}'.": {
|
||||
"Declare property '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90016
|
||||
},
|
||||
"Add index signature for missing property '{0}'.": {
|
||||
"Add index signature for property '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90017
|
||||
},
|
||||
@@ -3583,7 +3617,15 @@
|
||||
"category": "Message",
|
||||
"code": 90022
|
||||
},
|
||||
|
||||
"Declare method '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90023
|
||||
},
|
||||
"Declare static method '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90024
|
||||
},
|
||||
|
||||
"Convert function to an ES2015 class": {
|
||||
"category": "Message",
|
||||
"code": 95001
|
||||
|
||||
+21
-6
@@ -676,6 +676,7 @@ namespace ts {
|
||||
case SyntaxKind.SuperKeyword:
|
||||
case SyntaxKind.TrueKeyword:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.ImportKeyword:
|
||||
writeTokenNode(node);
|
||||
return;
|
||||
|
||||
@@ -958,7 +959,7 @@ namespace ts {
|
||||
function emitConstructorType(node: ConstructorTypeNode) {
|
||||
write("new ");
|
||||
emitTypeParameters(node, node.typeParameters);
|
||||
emitParametersForArrow(node, node.parameters);
|
||||
emitParameters(node, node.parameters);
|
||||
write(" => ");
|
||||
emit(node.type);
|
||||
}
|
||||
@@ -2282,11 +2283,25 @@ namespace ts {
|
||||
emitList(parentNode, parameters, ListFormat.Parameters);
|
||||
}
|
||||
|
||||
function emitParametersForArrow(parentNode: Node, parameters: NodeArray<ParameterDeclaration>) {
|
||||
if (parameters &&
|
||||
parameters.length === 1 &&
|
||||
parameters[0].type === undefined &&
|
||||
parameters[0].pos === parentNode.pos) {
|
||||
function canEmitSimpleArrowHead(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray<ParameterDeclaration>) {
|
||||
const parameter = singleOrUndefined(parameters);
|
||||
return parameter
|
||||
&& parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter
|
||||
&& !(isArrowFunction(parentNode) && parentNode.type) // arrow function may not have return type annotation
|
||||
&& !some(parentNode.decorators) // parent may not have decorators
|
||||
&& !some(parentNode.modifiers) // parent may not have modifiers
|
||||
&& !some(parentNode.typeParameters) // parent may not have type parameters
|
||||
&& !some(parameter.decorators) // parameter may not have decorators
|
||||
&& !some(parameter.modifiers) // parameter may not have modifiers
|
||||
&& !parameter.dotDotDotToken // parameter may not be rest
|
||||
&& !parameter.questionToken // parameter may not be optional
|
||||
&& !parameter.type // parameter may not have a type annotation
|
||||
&& !parameter.initializer // parameter may not have an initializer
|
||||
&& isIdentifier(parameter.name); // parameter name must be identifier
|
||||
}
|
||||
|
||||
function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray<ParameterDeclaration>) {
|
||||
if (canEmitSimpleArrowHead(parentNode, parameters)) {
|
||||
emit(parameters[0]);
|
||||
}
|
||||
else {
|
||||
|
||||
+45
-24
@@ -228,7 +228,7 @@ namespace ts {
|
||||
|
||||
// Signature elements
|
||||
|
||||
export function createTypeParameterDeclaration(name: string | Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) {
|
||||
export function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode) {
|
||||
const node = createSynthesizedNode(SyntaxKind.TypeParameter) as TypeParameterDeclaration;
|
||||
node.name = asName(name);
|
||||
node.constraint = constraint;
|
||||
@@ -2314,15 +2314,24 @@ namespace ts {
|
||||
/**
|
||||
* Sets a custom text range to use when emitting source maps.
|
||||
*/
|
||||
export function setSourceMapRange<T extends Node>(node: T, range: TextRange | undefined) {
|
||||
export function setSourceMapRange<T extends Node>(node: T, range: SourceMapRange | undefined) {
|
||||
getOrCreateEmitNode(node).sourceMapRange = range;
|
||||
return node;
|
||||
}
|
||||
|
||||
let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource;
|
||||
|
||||
/**
|
||||
* Create an external source map source file reference
|
||||
*/
|
||||
export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource {
|
||||
return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TextRange to use for source maps for a token of a node.
|
||||
*/
|
||||
export function getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange | undefined {
|
||||
export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined {
|
||||
const emitNode = node.emitNode;
|
||||
const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges;
|
||||
return tokenSourceMapRanges && tokenSourceMapRanges[token];
|
||||
@@ -2331,7 +2340,7 @@ namespace ts {
|
||||
/**
|
||||
* Sets the TextRange to use for source maps for a token of a node.
|
||||
*/
|
||||
export function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: TextRange | undefined) {
|
||||
export function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: SourceMapRange | undefined) {
|
||||
const emitNode = getOrCreateEmitNode(node);
|
||||
const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []);
|
||||
tokenSourceMapRanges[token] = range;
|
||||
@@ -2503,6 +2512,7 @@ namespace ts {
|
||||
helpers
|
||||
} = sourceEmitNode;
|
||||
if (!destEmitNode) destEmitNode = {};
|
||||
// We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later.
|
||||
if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments);
|
||||
if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments);
|
||||
if (flags) destEmitNode.flags = flags;
|
||||
@@ -3840,23 +3850,34 @@ namespace ts {
|
||||
return emitNode && emitNode.externalHelpersModuleName;
|
||||
}
|
||||
|
||||
export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions) {
|
||||
if (compilerOptions.importHelpers && (isExternalModule(node) || compilerOptions.isolatedModules)) {
|
||||
export function getOrCreateExternalHelpersModuleNameIfNeeded(node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean) {
|
||||
if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) {
|
||||
const externalHelpersModuleName = getExternalHelpersModuleName(node);
|
||||
if (externalHelpersModuleName) {
|
||||
return externalHelpersModuleName;
|
||||
}
|
||||
|
||||
const helpers = getEmitHelpers(node);
|
||||
if (helpers) {
|
||||
for (const helper of helpers) {
|
||||
if (!helper.scoped) {
|
||||
const parseNode = getOriginalNode(node, isSourceFile);
|
||||
const emitNode = getOrCreateEmitNode(parseNode);
|
||||
return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText));
|
||||
const moduleKind = getEmitModuleKind(compilerOptions);
|
||||
let create = hasExportStarsToExportValues
|
||||
&& moduleKind !== ModuleKind.System
|
||||
&& moduleKind !== ModuleKind.ES2015;
|
||||
if (!create) {
|
||||
const helpers = getEmitHelpers(node);
|
||||
if (helpers) {
|
||||
for (const helper of helpers) {
|
||||
if (!helper.scoped) {
|
||||
create = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (create) {
|
||||
const parseNode = getOriginalNode(node, isSourceFile);
|
||||
const emitNode = getOrCreateEmitNode(parseNode);
|
||||
return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = createUniqueName(externalHelpersModuleNameText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4239,17 +4260,6 @@ namespace ts {
|
||||
let exportEquals: ExportAssignment = undefined;
|
||||
let hasExportStarsToExportValues = false;
|
||||
|
||||
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions);
|
||||
const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText));
|
||||
|
||||
if (externalHelpersImportDeclaration) {
|
||||
externalImports.push(externalHelpersImportDeclaration);
|
||||
}
|
||||
|
||||
for (const node of sourceFile.statements) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
@@ -4360,6 +4370,17 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues);
|
||||
const externalHelpersImportDeclaration = externalHelpersModuleName && createImportDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createImportClause(/*name*/ undefined, createNamespaceImport(externalHelpersModuleName)),
|
||||
createLiteral(externalHelpersModuleNameText));
|
||||
|
||||
if (externalHelpersImportDeclaration) {
|
||||
externalImports.unshift(externalHelpersImportDeclaration);
|
||||
}
|
||||
|
||||
return { externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues, exportedBindings, exportedNames, externalHelpersImportDeclaration };
|
||||
}
|
||||
|
||||
|
||||
@@ -815,15 +815,15 @@ namespace ts {
|
||||
|
||||
switch (extensions) {
|
||||
case Extensions.DtsOnly:
|
||||
return tryExtension(".d.ts", Extension.Dts);
|
||||
return tryExtension(Extension.Dts);
|
||||
case Extensions.TypeScript:
|
||||
return tryExtension(".ts", Extension.Ts) || tryExtension(".tsx", Extension.Tsx) || tryExtension(".d.ts", Extension.Dts);
|
||||
return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx) || tryExtension(Extension.Dts);
|
||||
case Extensions.JavaScript:
|
||||
return tryExtension(".js", Extension.Js) || tryExtension(".jsx", Extension.Jsx);
|
||||
return tryExtension(Extension.Js) || tryExtension(Extension.Jsx);
|
||||
}
|
||||
|
||||
function tryExtension(ext: string, extension: Extension): Resolved | undefined {
|
||||
const path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state);
|
||||
function tryExtension(extension: Extension): Resolved | undefined {
|
||||
const path = tryFile(candidate + extension, failedLookupLocations, onlyRecordFailures, state);
|
||||
return path && { path, extension };
|
||||
}
|
||||
}
|
||||
|
||||
+80
-49
@@ -15,7 +15,7 @@ namespace ts {
|
||||
else if (kind === SyntaxKind.Identifier) {
|
||||
return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, pos, end);
|
||||
}
|
||||
else if (kind < SyntaxKind.FirstNode) {
|
||||
else if (!isNodeKind(kind)) {
|
||||
return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, pos, end);
|
||||
}
|
||||
else {
|
||||
@@ -46,10 +46,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
// Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
|
||||
// stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
|
||||
// embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
|
||||
// a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
|
||||
/**
|
||||
* Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
|
||||
* stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
|
||||
* embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
|
||||
* a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
|
||||
*
|
||||
* @param node a given node to visit its children
|
||||
* @param cbNode a callback to be invoked for all child nodes
|
||||
* @param cbNodeArray a callback to be invoked for embedded array
|
||||
*/
|
||||
export function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
|
||||
if (!node) {
|
||||
return;
|
||||
@@ -475,7 +481,11 @@ namespace ts {
|
||||
// becoming detached from any SourceFile). It is recommended that this SourceFile not
|
||||
// be used once 'update' is called on it.
|
||||
export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks?: boolean): SourceFile {
|
||||
return IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
|
||||
const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
|
||||
// Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import.
|
||||
// We will manually port the flag to the new source file.
|
||||
newSourceFile.flags |= (sourceFile.flags & NodeFlags.PossiblyContainsDynamicImport);
|
||||
return newSourceFile;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -754,7 +764,7 @@ namespace ts {
|
||||
sourceFile.languageVersion = languageVersion;
|
||||
sourceFile.fileName = normalizePath(fileName);
|
||||
sourceFile.languageVariant = getLanguageVariant(scriptKind);
|
||||
sourceFile.isDeclarationFile = fileExtensionIs(sourceFile.fileName, ".d.ts");
|
||||
sourceFile.isDeclarationFile = fileExtensionIs(sourceFile.fileName, Extension.Dts);
|
||||
sourceFile.scriptKind = scriptKind;
|
||||
|
||||
return sourceFile;
|
||||
@@ -1093,7 +1103,7 @@ namespace ts {
|
||||
pos = scanner.getStartPos();
|
||||
}
|
||||
|
||||
return kind >= SyntaxKind.FirstNode ? new NodeConstructor(kind, pos, pos) :
|
||||
return isNodeKind(kind) ? new NodeConstructor(kind, pos, pos) :
|
||||
kind === SyntaxKind.Identifier ? new IdentifierConstructor(kind, pos, pos) :
|
||||
new TokenConstructor(kind, pos, pos);
|
||||
}
|
||||
@@ -2409,7 +2419,7 @@ namespace ts {
|
||||
if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
|
||||
return parseSignatureMember(SyntaxKind.CallSignature);
|
||||
}
|
||||
if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) {
|
||||
if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
|
||||
return parseSignatureMember(SyntaxKind.ConstructSignature);
|
||||
}
|
||||
const fullStart = getNodePos();
|
||||
@@ -2420,7 +2430,7 @@ namespace ts {
|
||||
return parsePropertyOrMethodSignature(fullStart, modifiers);
|
||||
}
|
||||
|
||||
function isStartOfConstructSignature() {
|
||||
function nextTokenIsOpenParenOrLessThan() {
|
||||
nextToken();
|
||||
return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;
|
||||
}
|
||||
@@ -2777,6 +2787,8 @@ namespace ts {
|
||||
case SyntaxKind.SlashEqualsToken:
|
||||
case SyntaxKind.Identifier:
|
||||
return true;
|
||||
case SyntaxKind.ImportKeyword:
|
||||
return lookAhead(nextTokenIsOpenParenOrLessThan);
|
||||
default:
|
||||
return isIdentifier();
|
||||
}
|
||||
@@ -3509,10 +3521,10 @@ namespace ts {
|
||||
* 5) --UnaryExpression[?Yield]
|
||||
*/
|
||||
if (isUpdateExpression()) {
|
||||
const incrementExpression = parseIncrementExpression();
|
||||
const updateExpression = parseUpdateExpression();
|
||||
return token() === SyntaxKind.AsteriskAsteriskToken ?
|
||||
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), incrementExpression) :
|
||||
incrementExpression;
|
||||
<BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(), updateExpression) :
|
||||
updateExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3578,7 +3590,7 @@ namespace ts {
|
||||
}
|
||||
// falls through
|
||||
default:
|
||||
return parseIncrementExpression();
|
||||
return parseUpdateExpression();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3594,7 +3606,7 @@ namespace ts {
|
||||
*/
|
||||
function isUpdateExpression(): boolean {
|
||||
// This function is called inside parseUnaryExpression to decide
|
||||
// whether to call parseSimpleUnaryExpression or call parseIncrementExpression directly
|
||||
// whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly
|
||||
switch (token()) {
|
||||
case SyntaxKind.PlusToken:
|
||||
case SyntaxKind.MinusToken:
|
||||
@@ -3618,9 +3630,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse ES7 IncrementExpression. IncrementExpression is used instead of ES6's PostFixExpression.
|
||||
* Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression.
|
||||
*
|
||||
* ES7 IncrementExpression[yield]:
|
||||
* ES7 UpdateExpression[yield]:
|
||||
* 1) LeftHandSideExpression[?yield]
|
||||
* 2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++
|
||||
* 3) LeftHandSideExpression[?yield] [[no LineTerminator here]]--
|
||||
@@ -3628,7 +3640,7 @@ namespace ts {
|
||||
* 5) --LeftHandSideExpression[?yield]
|
||||
* In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression
|
||||
*/
|
||||
function parseIncrementExpression(): IncrementExpression {
|
||||
function parseUpdateExpression(): UpdateExpression {
|
||||
if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) {
|
||||
const node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression);
|
||||
node.operator = <PrefixUnaryOperator>token();
|
||||
@@ -3678,17 +3690,27 @@ namespace ts {
|
||||
// CallExpression Arguments
|
||||
// CallExpression[Expression]
|
||||
// CallExpression.IdentifierName
|
||||
// super ( ArgumentListopt )
|
||||
// import (AssignmentExpression)
|
||||
// super Arguments
|
||||
// super.IdentifierName
|
||||
//
|
||||
// Because of the recursion in these calls, we need to bottom out first. There are two
|
||||
// bottom out states we can run into. Either we see 'super' which must start either of
|
||||
// the last two CallExpression productions. Or we have a MemberExpression which either
|
||||
// completes the LeftHandSideExpression, or starts the beginning of the first four
|
||||
// CallExpression productions.
|
||||
const expression = token() === SyntaxKind.SuperKeyword
|
||||
? parseSuperExpression()
|
||||
: parseMemberExpressionOrHigher();
|
||||
// Because of the recursion in these calls, we need to bottom out first. There are three
|
||||
// bottom out states we can run into: 1) We see 'super' which must start either of
|
||||
// the last two CallExpression productions. 2) We see 'import' which must start import call.
|
||||
// 3)we have a MemberExpression which either completes the LeftHandSideExpression,
|
||||
// or starts the beginning of the first four CallExpression productions.
|
||||
let expression: MemberExpression;
|
||||
if (token() === SyntaxKind.ImportKeyword) {
|
||||
// We don't want to eagerly consume all import keyword as import call expression so we look a head to find "("
|
||||
// For example:
|
||||
// var foo3 = require("subfolder
|
||||
// import * as foo1 from "module-from-node -> we want this import to be a statement rather than import call expression
|
||||
sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport;
|
||||
expression = parseTokenNode<PrimaryExpression>();
|
||||
}
|
||||
else {
|
||||
expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher();
|
||||
}
|
||||
|
||||
// Now, we *may* be complete. However, we might have consumed the start of a
|
||||
// CallExpression. As such, we need to consume the rest of it here to be complete.
|
||||
@@ -3696,7 +3718,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function parseMemberExpressionOrHigher(): MemberExpression {
|
||||
// Note: to make our lives simpler, we decompose the the NewExpression productions and
|
||||
// Note: to make our lives simpler, we decompose the NewExpression productions and
|
||||
// place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
|
||||
// like so:
|
||||
//
|
||||
@@ -4792,9 +4814,11 @@ namespace ts {
|
||||
case SyntaxKind.FinallyKeyword:
|
||||
return true;
|
||||
|
||||
case SyntaxKind.ImportKeyword:
|
||||
return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThan);
|
||||
|
||||
case SyntaxKind.ConstKeyword:
|
||||
case SyntaxKind.ExportKeyword:
|
||||
case SyntaxKind.ImportKeyword:
|
||||
return isStartOfDeclaration();
|
||||
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
@@ -6513,6 +6537,10 @@ namespace ts {
|
||||
case "augments":
|
||||
tag = parseAugmentsTag(atToken, tagName);
|
||||
break;
|
||||
case "class":
|
||||
case "constructor":
|
||||
tag = parseClassTag(atToken, tagName);
|
||||
break;
|
||||
case "arg":
|
||||
case "argument":
|
||||
case "param":
|
||||
@@ -6639,14 +6667,12 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
function parseBracketNameInPropertyAndParamTag() {
|
||||
let name: Identifier;
|
||||
let isBracketed: boolean;
|
||||
function parseBracketNameInPropertyAndParamTag(): { name: Identifier, isBracketed: boolean } {
|
||||
// Looking for something like '[foo]' or 'foo'
|
||||
if (parseOptionalToken(SyntaxKind.OpenBracketToken)) {
|
||||
name = parseJSDocIdentifierName();
|
||||
const isBracketed = parseOptional(SyntaxKind.OpenBracketToken);
|
||||
const name = parseJSDocIdentifierName(/*createIfMissing*/ true);
|
||||
if (isBracketed) {
|
||||
skipWhitespace();
|
||||
isBracketed = true;
|
||||
|
||||
// May have an optional default, e.g. '[foo = 42]'
|
||||
if (parseOptionalToken(SyntaxKind.EqualsToken)) {
|
||||
@@ -6655,9 +6681,7 @@ namespace ts {
|
||||
|
||||
parseExpected(SyntaxKind.CloseBracketToken);
|
||||
}
|
||||
else if (tokenIsIdentifierOrKeyword(token())) {
|
||||
name = parseJSDocIdentifierName();
|
||||
}
|
||||
|
||||
return { name, isBracketed };
|
||||
}
|
||||
|
||||
@@ -6668,11 +6692,6 @@ namespace ts {
|
||||
const { name, isBracketed } = parseBracketNameInPropertyAndParamTag();
|
||||
skipWhitespace();
|
||||
|
||||
if (!name) {
|
||||
parseErrorAtPosition(scanner.getStartPos(), 0, Diagnostics.Identifier_expected);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let preName: Identifier, postName: Identifier;
|
||||
if (typeExpression) {
|
||||
postName = name;
|
||||
@@ -6732,6 +6751,13 @@ namespace ts {
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function parseClassTag(atToken: AtToken, tagName: Identifier): JSDocClassTag {
|
||||
const tag = <JSDocClassTag>createNode(SyntaxKind.JSDocClassTag, atToken.pos);
|
||||
tag.atToken = atToken;
|
||||
tag.tagName = tagName;
|
||||
return finishNode(tag);
|
||||
}
|
||||
|
||||
function parseTypedefTag(atToken: AtToken, tagName: Identifier): JSDocTypedefTag {
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
@@ -6825,7 +6851,7 @@ namespace ts {
|
||||
jsDocNamespaceNode.flags |= flags;
|
||||
jsDocNamespaceNode.name = typeNameOrNamespaceName;
|
||||
jsDocNamespaceNode.body = parseJSDocTypeNameWithNamespace(NodeFlags.NestedNamespace);
|
||||
return jsDocNamespaceNode;
|
||||
return finishNode(jsDocNamespaceNode);
|
||||
}
|
||||
|
||||
if (typeNameOrNamespaceName && flags & NodeFlags.NestedNamespace) {
|
||||
@@ -6916,14 +6942,19 @@ namespace ts {
|
||||
return currentToken = scanner.scanJSDocToken();
|
||||
}
|
||||
|
||||
function parseJSDocIdentifierName(): Identifier {
|
||||
return createJSDocIdentifier(tokenIsIdentifierOrKeyword(token()));
|
||||
function parseJSDocIdentifierName(createIfMissing = false): Identifier {
|
||||
return createJSDocIdentifier(tokenIsIdentifierOrKeyword(token()), createIfMissing);
|
||||
}
|
||||
|
||||
function createJSDocIdentifier(isIdentifier: boolean): Identifier {
|
||||
function createJSDocIdentifier(isIdentifier: boolean, createIfMissing: boolean): Identifier {
|
||||
if (!isIdentifier) {
|
||||
parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
|
||||
return undefined;
|
||||
if (createIfMissing) {
|
||||
return <Identifier>createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected);
|
||||
}
|
||||
else {
|
||||
parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const pos = scanner.getTokenPos();
|
||||
|
||||
+22
-23
@@ -984,16 +984,12 @@ namespace ts {
|
||||
if (sourceFile) {
|
||||
return getDiagnostics(sourceFile, cancellationToken);
|
||||
}
|
||||
|
||||
const allDiagnostics: Diagnostic[] = [];
|
||||
forEach(program.getSourceFiles(), sourceFile => {
|
||||
return sortAndDeduplicateDiagnostics(flatMap(program.getSourceFiles(), sourceFile => {
|
||||
if (cancellationToken) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
}
|
||||
addRange(allDiagnostics, getDiagnostics(sourceFile, cancellationToken));
|
||||
});
|
||||
|
||||
return sortAndDeduplicateDiagnostics(allDiagnostics);
|
||||
return getDiagnostics(sourceFile, cancellationToken);
|
||||
}));
|
||||
}
|
||||
|
||||
function getSyntacticDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
|
||||
@@ -1069,10 +1065,10 @@ namespace ts {
|
||||
const typeChecker = getDiagnosticsProducingTypeChecker();
|
||||
|
||||
Debug.assert(!!sourceFile.bindDiagnostics);
|
||||
const bindDiagnostics = sourceFile.bindDiagnostics;
|
||||
// For JavaScript files, we don't want to report semantic errors unless explicitly requested.
|
||||
const includeCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || isCheckJsEnabledForFile(sourceFile, options);
|
||||
const checkDiagnostics = includeCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : [];
|
||||
const includeBindAndCheckDiagnostics = !isSourceFileJavaScript(sourceFile) || isCheckJsEnabledForFile(sourceFile, options);
|
||||
const bindDiagnostics = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray;
|
||||
const checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray;
|
||||
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
|
||||
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
|
||||
|
||||
@@ -1330,16 +1326,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getOptionsDiagnostics(): Diagnostic[] {
|
||||
const allDiagnostics: Diagnostic[] = [];
|
||||
addRange(allDiagnostics, fileProcessingDiagnostics.getGlobalDiagnostics());
|
||||
addRange(allDiagnostics, programDiagnostics.getGlobalDiagnostics());
|
||||
return sortAndDeduplicateDiagnostics(allDiagnostics);
|
||||
return sortAndDeduplicateDiagnostics(concatenate(
|
||||
fileProcessingDiagnostics.getGlobalDiagnostics(),
|
||||
programDiagnostics.getGlobalDiagnostics()));
|
||||
}
|
||||
|
||||
function getGlobalDiagnostics(): Diagnostic[] {
|
||||
const allDiagnostics: Diagnostic[] = [];
|
||||
addRange(allDiagnostics, getDiagnosticsProducingTypeChecker().getGlobalDiagnostics());
|
||||
return sortAndDeduplicateDiagnostics(allDiagnostics);
|
||||
return sortAndDeduplicateDiagnostics(getDiagnosticsProducingTypeChecker().getGlobalDiagnostics().slice());
|
||||
}
|
||||
|
||||
function processRootFile(fileName: string, isDefaultLib: boolean) {
|
||||
@@ -1366,6 +1359,7 @@ namespace ts {
|
||||
const isJavaScriptFile = isSourceFileJavaScript(file);
|
||||
const isExternalModuleFile = isExternalModule(file);
|
||||
|
||||
// file.imports may not be undefined if there exists dynamic import
|
||||
let imports: LiteralExpression[];
|
||||
let moduleAugmentations: LiteralExpression[];
|
||||
let ambientModules: string[];
|
||||
@@ -1385,8 +1379,8 @@ namespace ts {
|
||||
|
||||
for (const node of file.statements) {
|
||||
collectModuleReferences(node, /*inAmbientModule*/ false);
|
||||
if (isJavaScriptFile) {
|
||||
collectRequireCalls(node);
|
||||
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) {
|
||||
collectDynamicImportOrRequireCalls(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1449,12 +1443,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function collectRequireCalls(node: Node): void {
|
||||
function collectDynamicImportOrRequireCalls(node: Node): void {
|
||||
if (isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) {
|
||||
(imports || (imports = [])).push(<StringLiteral>(<CallExpression>node).arguments[0]);
|
||||
}
|
||||
// we have to check the argument list has length of 1. We will still have to process these even though we have parsing error.
|
||||
else if (isImportCall(node) && node.arguments.length === 1 && node.arguments[0].kind === SyntaxKind.StringLiteral) {
|
||||
(imports || (imports = [])).push(<StringLiteral>(<CallExpression>node).arguments[0]);
|
||||
}
|
||||
else {
|
||||
forEachChild(node, collectRequireCalls);
|
||||
forEachChild(node, collectDynamicImportOrRequireCalls);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1486,7 +1484,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
return sourceFile;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
const sourceFileNoExtension = options.allowNonTsExtensions && getSourceFile(fileName);
|
||||
if (sourceFileNoExtension) return sourceFileNoExtension;
|
||||
|
||||
@@ -1496,7 +1495,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
const sourceFileWithAddedExtension = forEach(supportedExtensions, extension => getSourceFile(fileName + extension));
|
||||
if (fail && !sourceFileWithAddedExtension) fail(Diagnostics.File_0_not_found, fileName + ".ts");
|
||||
if (fail && !sourceFileWithAddedExtension) fail(Diagnostics.File_0_not_found, fileName + Extension.Ts);
|
||||
return sourceFileWithAddedExtension;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ namespace ts {
|
||||
|
||||
const tokenStrings = makeReverseMap(textToToken);
|
||||
|
||||
export function tokenToString(t: SyntaxKind): string {
|
||||
export function tokenToString(t: SyntaxKind): string | undefined {
|
||||
return tokenStrings[t];
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function getLineAndCharacterOfPosition(sourceFile: SourceFile, position: number): LineAndCharacter {
|
||||
export function getLineAndCharacterOfPosition(sourceFile: SourceFileLike, position: number): LineAndCharacter {
|
||||
return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position);
|
||||
}
|
||||
|
||||
|
||||
+33
-14
@@ -22,7 +22,7 @@ namespace ts {
|
||||
*
|
||||
* @param sourceFile The source file.
|
||||
*/
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
setSourceFile(sourceFile: SourceMapSource): void;
|
||||
|
||||
/**
|
||||
* Emits a mapping.
|
||||
@@ -81,7 +81,7 @@ namespace ts {
|
||||
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
|
||||
const compilerOptions = host.getCompilerOptions();
|
||||
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
|
||||
let currentSourceFile: SourceFile;
|
||||
let currentSource: SourceMapSource;
|
||||
let currentSourceText: string;
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
|
||||
@@ -109,6 +109,13 @@ namespace ts {
|
||||
getSourceMappingURL,
|
||||
};
|
||||
|
||||
/**
|
||||
* Skips trivia such as comments and white-space that can optionally overriden by the source map source
|
||||
*/
|
||||
function skipSourceTrivia(pos: number): number {
|
||||
return currentSource.skipTrivia ? currentSource.skipTrivia(pos) : skipTrivia(currentSourceText, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the SourceMapWriter for a new output file.
|
||||
*
|
||||
@@ -125,7 +132,7 @@ namespace ts {
|
||||
reset();
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentSource = undefined;
|
||||
currentSourceText = undefined;
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
@@ -192,7 +199,7 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentSource = undefined;
|
||||
sourceMapDir = undefined;
|
||||
sourceMapSourceIndex = undefined;
|
||||
lastRecordedSourceMapSpan = undefined;
|
||||
@@ -263,7 +270,7 @@ namespace ts {
|
||||
performance.mark("beforeSourcemap");
|
||||
}
|
||||
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
|
||||
const sourceLinePos = getLineAndCharacterOfPosition(currentSource, pos);
|
||||
|
||||
// Convert the location to be one-based.
|
||||
sourceLinePos.line++;
|
||||
@@ -320,14 +327,22 @@ namespace ts {
|
||||
if (node) {
|
||||
const emitNode = node.emitNode;
|
||||
const emitFlags = emitNode && emitNode.flags;
|
||||
const { pos, end } = emitNode && emitNode.sourceMapRange || node;
|
||||
const range = emitNode && emitNode.sourceMapRange;
|
||||
const { pos, end } = range || node;
|
||||
let source = range && range.source;
|
||||
const oldSource = currentSource;
|
||||
if (source === oldSource) source = undefined;
|
||||
|
||||
if (source) setSourceFile(source);
|
||||
|
||||
if (node.kind !== SyntaxKind.NotEmittedStatement
|
||||
&& (emitFlags & EmitFlags.NoLeadingSourceMap) === 0
|
||||
&& pos >= 0) {
|
||||
emitPos(skipTrivia(currentSourceText, pos));
|
||||
emitPos(skipSourceTrivia(pos));
|
||||
}
|
||||
|
||||
if (source) setSourceFile(oldSource);
|
||||
|
||||
if (emitFlags & EmitFlags.NoNestedSourceMaps) {
|
||||
disabled = true;
|
||||
emitCallback(hint, node);
|
||||
@@ -337,11 +352,15 @@ namespace ts {
|
||||
emitCallback(hint, node);
|
||||
}
|
||||
|
||||
if (source) setSourceFile(source);
|
||||
|
||||
if (node.kind !== SyntaxKind.NotEmittedStatement
|
||||
&& (emitFlags & EmitFlags.NoTrailingSourceMap) === 0
|
||||
&& end >= 0) {
|
||||
emitPos(end);
|
||||
}
|
||||
|
||||
if (source) setSourceFile(oldSource);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +381,7 @@ namespace ts {
|
||||
const emitFlags = emitNode && emitNode.flags;
|
||||
const range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token];
|
||||
|
||||
tokenPos = skipTrivia(currentSourceText, range ? range.pos : tokenPos);
|
||||
tokenPos = skipSourceTrivia(range ? range.pos : tokenPos);
|
||||
if ((emitFlags & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) {
|
||||
emitPos(tokenPos);
|
||||
}
|
||||
@@ -382,13 +401,13 @@ namespace ts {
|
||||
*
|
||||
* @param sourceFile The source file.
|
||||
*/
|
||||
function setSourceFile(sourceFile: SourceFile) {
|
||||
function setSourceFile(sourceFile: SourceMapSource) {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentSourceFile = sourceFile;
|
||||
currentSourceText = currentSourceFile.text;
|
||||
currentSource = sourceFile;
|
||||
currentSourceText = currentSource.text;
|
||||
|
||||
// Add the file to tsFilePaths
|
||||
// If sourceroot option: Use the relative path corresponding to the common directory path
|
||||
@@ -396,7 +415,7 @@ namespace ts {
|
||||
const sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
|
||||
|
||||
const source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
|
||||
currentSourceFile.fileName,
|
||||
currentSource.fileName,
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ true);
|
||||
@@ -407,10 +426,10 @@ namespace ts {
|
||||
sourceMapData.sourceMapSources.push(source);
|
||||
|
||||
// The one that can be used from program to get the actual source file
|
||||
sourceMapData.inputSourceFileNames.push(currentSourceFile.fileName);
|
||||
sourceMapData.inputSourceFileNames.push(currentSource.fileName);
|
||||
|
||||
if (compilerOptions.inlineSources) {
|
||||
sourceMapData.sourceMapSourcesContent.push(currentSourceFile.text);
|
||||
sourceMapData.sourceMapSourcesContent.push(currentSource.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ namespace ts {
|
||||
getDirectories(path: string): string[];
|
||||
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[];
|
||||
getModifiedTime?(path: string): Date;
|
||||
/**
|
||||
* This should be cryptographically secure.
|
||||
* A good implementation is node.js' `crypto.createHash`. (https://nodejs.org/api/crypto.html#crypto_crypto_createhash_algorithm)
|
||||
*/
|
||||
createHash?(data: string): string;
|
||||
getMemoryUsage?(): number;
|
||||
exit(exitCode?: number): void;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
namespace ts {
|
||||
function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<SourceFile> {
|
||||
switch (moduleKind) {
|
||||
case ModuleKind.ESNext:
|
||||
case ModuleKind.ES2015:
|
||||
return transformES2015Module;
|
||||
case ModuleKind.System:
|
||||
@@ -238,7 +239,7 @@ namespace ts {
|
||||
function hoistVariableDeclaration(name: Identifier): void {
|
||||
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
|
||||
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
|
||||
const decl = createVariableDeclaration(name);
|
||||
const decl = setEmitFlags(createVariableDeclaration(name), EmitFlags.NoNestedSourceMaps);
|
||||
if (!lexicalEnvironmentVariableDeclarations) {
|
||||
lexicalEnvironmentVariableDeclarations = [decl];
|
||||
}
|
||||
|
||||
@@ -2095,9 +2095,9 @@ namespace ts {
|
||||
enableSubstitutionsForBlockScopedBindings();
|
||||
}
|
||||
|
||||
const declarations = flatten(map(node.declarations, node.flags & NodeFlags.Let
|
||||
const declarations = flatMap(node.declarations, node.flags & NodeFlags.Let
|
||||
? visitVariableDeclarationInLetDeclarationList
|
||||
: visitVariableDeclaration));
|
||||
: visitVariableDeclaration);
|
||||
|
||||
const declarationList = createVariableDeclarationList(declarations);
|
||||
setOriginalNode(declarationList, node);
|
||||
|
||||
@@ -351,8 +351,10 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
function awaitAsYield(expression: Expression) {
|
||||
return createYield(/*asteriskToken*/ undefined, enclosingFunctionFlags & FunctionFlags.Generator ? createAwaitHelper(context, expression) : expression);
|
||||
function createDownlevelAwait(expression: Expression) {
|
||||
return enclosingFunctionFlags & FunctionFlags.Generator
|
||||
? createYield(/*asteriskToken*/ undefined, createAwaitHelper(context, expression))
|
||||
: createAwait(expression);
|
||||
}
|
||||
|
||||
function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement) {
|
||||
@@ -385,11 +387,11 @@ namespace ts {
|
||||
EmitFlags.NoHoisting
|
||||
),
|
||||
/*condition*/ createComma(
|
||||
createAssignment(result, awaitAsYield(callNext)),
|
||||
createAssignment(result, createDownlevelAwait(callNext)),
|
||||
createLogicalNot(getDone)
|
||||
),
|
||||
/*incrementor*/ undefined,
|
||||
/*statement*/ convertForOfStatementHead(node, awaitAsYield(getValue))
|
||||
/*statement*/ convertForOfStatementHead(node, createDownlevelAwait(getValue))
|
||||
),
|
||||
/*location*/ node
|
||||
),
|
||||
@@ -434,7 +436,7 @@ namespace ts {
|
||||
createPropertyAccess(iterator, "return")
|
||||
)
|
||||
),
|
||||
createStatement(awaitAsYield(callReturn))
|
||||
createStatement(createDownlevelAwait(callReturn))
|
||||
),
|
||||
EmitFlags.SingleLine
|
||||
)
|
||||
|
||||
@@ -640,10 +640,13 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return createStatement(
|
||||
inlineExpressions(
|
||||
map(variables, transformInitializedVariable)
|
||||
)
|
||||
return setSourceMapRange(
|
||||
createStatement(
|
||||
inlineExpressions(
|
||||
map(variables, transformInitializedVariable)
|
||||
)
|
||||
),
|
||||
node
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1281,9 +1284,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function transformInitializedVariable(node: VariableDeclaration) {
|
||||
return createAssignment(
|
||||
<Identifier>getSynthesizedClone(node.name),
|
||||
visitNode(node.initializer, visitor, isExpression)
|
||||
return setSourceMapRange(
|
||||
createAssignment(
|
||||
setSourceMapRange(<Identifier>getSynthesizedClone(node.name), node.name),
|
||||
visitNode(node.initializer, visitor, isExpression)
|
||||
),
|
||||
node
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace ts {
|
||||
let currentSourceFile: SourceFile; // The current file.
|
||||
let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file.
|
||||
let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored.
|
||||
let needUMDDynamicImportHelper: boolean;
|
||||
|
||||
return transformSourceFile;
|
||||
|
||||
@@ -55,7 +56,7 @@ namespace ts {
|
||||
* @param node The SourceFile node.
|
||||
*/
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
if (node.isDeclarationFile || !(isExternalModule(node) || compilerOptions.isolatedModules)) {
|
||||
if (node.isDeclarationFile || !(isExternalModule(node) || compilerOptions.isolatedModules || node.transformFlags & TransformFlags.ContainsDynamicImport)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -66,9 +67,9 @@ namespace ts {
|
||||
// Perform the transformation.
|
||||
const transformModule = getTransformModuleDelegate(moduleKind);
|
||||
const updated = transformModule(node);
|
||||
|
||||
currentSourceFile = undefined;
|
||||
currentModuleInfo = undefined;
|
||||
needUMDDynamicImportHelper = false;
|
||||
return aggregateTransformFlags(updated);
|
||||
}
|
||||
|
||||
@@ -102,11 +103,12 @@ namespace ts {
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
|
||||
const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements));
|
||||
if (currentModuleInfo.hasExportStarsToExportValues) {
|
||||
if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) {
|
||||
// If we have any `export * from ...` declarations
|
||||
// we need to inform the emitter to add the __export helper.
|
||||
addEmitHelper(updated, exportStarHelper);
|
||||
}
|
||||
addEmitHelpers(updated, context.readEmitHelpers());
|
||||
return updated;
|
||||
}
|
||||
|
||||
@@ -406,11 +408,14 @@ namespace ts {
|
||||
addRange(statements, endLexicalEnvironment());
|
||||
|
||||
const body = createBlock(statements, /*multiLine*/ true);
|
||||
if (currentModuleInfo.hasExportStarsToExportValues) {
|
||||
if (currentModuleInfo.hasExportStarsToExportValues && !compilerOptions.importHelpers) {
|
||||
// If we have any `export * from ...` declarations
|
||||
// we need to inform the emitter to add the __export helper.
|
||||
addEmitHelper(body, exportStarHelper);
|
||||
}
|
||||
if (needUMDDynamicImportHelper) {
|
||||
addEmitHelper(body, dynamicImportUMDHelper);
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
@@ -488,12 +493,110 @@ namespace ts {
|
||||
return visitEndOfDeclarationMarker(<EndOfDeclarationMarker>node);
|
||||
|
||||
default:
|
||||
// This visitor does not descend into the tree, as export/import statements
|
||||
// are only transformed at the top level of a file.
|
||||
return node;
|
||||
return visitEachChild(node, importCallExpressionVisitor, context);
|
||||
}
|
||||
}
|
||||
|
||||
function importCallExpressionVisitor(node: Node): VisitResult<Node> {
|
||||
// This visitor does not need to descend into the tree if there is no dynamic import,
|
||||
// as export/import statements are only transformed at the top level of a file.
|
||||
if (!(node.transformFlags & TransformFlags.ContainsDynamicImport)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (isImportCall(node)) {
|
||||
return visitImportCallExpression(<ImportCall>node);
|
||||
}
|
||||
else {
|
||||
return visitEachChild(node, importCallExpressionVisitor, context);
|
||||
}
|
||||
}
|
||||
|
||||
function visitImportCallExpression(node: ImportCall): Expression {
|
||||
switch (compilerOptions.module) {
|
||||
case ModuleKind.AMD:
|
||||
return transformImportCallExpressionAMD(node);
|
||||
case ModuleKind.UMD:
|
||||
return transformImportCallExpressionUMD(node);
|
||||
case ModuleKind.CommonJS:
|
||||
default:
|
||||
return transformImportCallExpressionCommonJS(node);
|
||||
}
|
||||
}
|
||||
|
||||
function transformImportCallExpressionUMD(node: ImportCall): Expression {
|
||||
// (function (factory) {
|
||||
// ... (regular UMD)
|
||||
// }
|
||||
// })(function (require, exports, useSyncRequire) {
|
||||
// "use strict";
|
||||
// Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// var __syncRequire = typeof module === "object" && typeof module.exports === "object";
|
||||
// var __resolved = new Promise(function (resolve) { resolve(); });
|
||||
// .....
|
||||
// __syncRequire
|
||||
// ? __resolved.then(function () { return require(x); }) /*CommonJs Require*/
|
||||
// : new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/
|
||||
// });
|
||||
needUMDDynamicImportHelper = true;
|
||||
return createConditional(
|
||||
/*condition*/ createIdentifier("__syncRequire"),
|
||||
/*whenTrue*/ transformImportCallExpressionCommonJS(node),
|
||||
/*whenFalse*/ transformImportCallExpressionAMD(node)
|
||||
);
|
||||
}
|
||||
|
||||
function transformImportCallExpressionAMD(node: ImportCall): Expression {
|
||||
// improt("./blah")
|
||||
// emit as
|
||||
// define(["require", "exports", "blah"], function (require, exports) {
|
||||
// ...
|
||||
// new Promise(function (_a, _b) { require([x], _a, _b); }); /*Amd Require*/
|
||||
// });
|
||||
const resolve = createUniqueName("resolve");
|
||||
const reject = createUniqueName("reject");
|
||||
return createNew(
|
||||
createIdentifier("Promise"),
|
||||
/*typeArguments*/ undefined,
|
||||
[createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
[createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ resolve),
|
||||
createParameter(/*decorator*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ reject)],
|
||||
/*type*/ undefined,
|
||||
createBlock([createStatement(
|
||||
createCall(
|
||||
createIdentifier("require"),
|
||||
/*typeArguments*/ undefined,
|
||||
[createArrayLiteral([firstOrUndefined(node.arguments) || createOmittedExpression()]), resolve, reject]
|
||||
))])
|
||||
)]);
|
||||
}
|
||||
|
||||
function transformImportCallExpressionCommonJS(node: ImportCall): Expression {
|
||||
// import("./blah")
|
||||
// emit as
|
||||
// Promise.resolve().then(function () { return require(x); }) /*CommonJs Require*/
|
||||
// We have to wrap require in then callback so that require is done in asynchronously
|
||||
// if we simply do require in resolve callback in Promise constructor. We will execute the loading immediately
|
||||
return createCall(
|
||||
createPropertyAccess(
|
||||
createCall(createPropertyAccess(createIdentifier("Promise"), "resolve"), /*typeArguments*/ undefined, /*argumentsArray*/ []),
|
||||
"then"),
|
||||
/*typeArguments*/ undefined,
|
||||
[createFunctionExpression(
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
/*parameters*/ undefined,
|
||||
/*type*/ undefined,
|
||||
createBlock([createReturn(createCall(createIdentifier("require"), /*typeArguments*/ undefined, node.arguments))])
|
||||
)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an ImportDeclaration node.
|
||||
*
|
||||
@@ -730,15 +833,7 @@ namespace ts {
|
||||
// export * from "mod";
|
||||
return setTextRange(
|
||||
createStatement(
|
||||
createCall(
|
||||
createIdentifier("__export"),
|
||||
/*typeArguments*/ undefined,
|
||||
[
|
||||
moduleKind !== ModuleKind.AMD
|
||||
? createRequireCall(node)
|
||||
: generatedName
|
||||
]
|
||||
)
|
||||
createExportStarHelper(context, moduleKind !== ModuleKind.AMD ? createRequireCall(node) : generatedName)
|
||||
),
|
||||
node
|
||||
);
|
||||
@@ -786,9 +881,9 @@ namespace ts {
|
||||
node.asteriskToken,
|
||||
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
|
||||
/*typeParameters*/ undefined,
|
||||
node.parameters,
|
||||
visitNodes(node.parameters, importCallExpressionVisitor),
|
||||
/*type*/ undefined,
|
||||
node.body
|
||||
visitEachChild(node.body, importCallExpressionVisitor, context)
|
||||
),
|
||||
/*location*/ node
|
||||
),
|
||||
@@ -797,7 +892,7 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
else {
|
||||
statements = append(statements, node);
|
||||
statements = append(statements, visitEachChild(node, importCallExpressionVisitor, context));
|
||||
}
|
||||
|
||||
if (hasAssociatedEndOfDeclarationMarker(node)) {
|
||||
@@ -828,7 +923,7 @@ namespace ts {
|
||||
visitNodes(node.modifiers, modifierVisitor, isModifier),
|
||||
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
|
||||
/*typeParameters*/ undefined,
|
||||
node.heritageClauses,
|
||||
visitNodes(node.heritageClauses, importCallExpressionVisitor),
|
||||
node.members
|
||||
),
|
||||
node
|
||||
@@ -838,7 +933,7 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
else {
|
||||
statements = append(statements, node);
|
||||
statements = append(statements, visitEachChild(node, importCallExpressionVisitor, context));
|
||||
}
|
||||
|
||||
if (hasAssociatedEndOfDeclarationMarker(node)) {
|
||||
@@ -890,7 +985,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
statements = append(statements, node);
|
||||
statements = append(statements, visitEachChild(node, importCallExpressionVisitor, context));
|
||||
}
|
||||
|
||||
if (hasAssociatedEndOfDeclarationMarker(node)) {
|
||||
@@ -913,7 +1008,7 @@ namespace ts {
|
||||
function transformInitializedVariable(node: VariableDeclaration): Expression {
|
||||
if (isBindingPattern(node.name)) {
|
||||
return flattenDestructuringAssignment(
|
||||
node,
|
||||
visitNode(node, importCallExpressionVisitor),
|
||||
/*visitor*/ undefined,
|
||||
context,
|
||||
FlattenLevel.All,
|
||||
@@ -930,7 +1025,7 @@ namespace ts {
|
||||
),
|
||||
/*location*/ node.name
|
||||
),
|
||||
node.initializer
|
||||
visitNode(node.initializer, importCallExpressionVisitor)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1495,6 +1590,22 @@ namespace ts {
|
||||
text: `
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}`
|
||||
}
|
||||
`
|
||||
};
|
||||
|
||||
function createExportStarHelper(context: TransformationContext, module: Expression) {
|
||||
const compilerOptions = context.getCompilerOptions();
|
||||
return compilerOptions.importHelpers
|
||||
? createCall(getHelperName("__exportStar"), /*typeArguments*/ undefined, [module, createIdentifier("exports")])
|
||||
: createCall(createIdentifier("__export"), /*typeArguments*/ undefined, [module]);
|
||||
}
|
||||
|
||||
// emit helper for dynamic import
|
||||
const dynamicImportUMDHelper: EmitHelper = {
|
||||
name: "typescript:dynamicimport-sync-require",
|
||||
scoped: true,
|
||||
text: `
|
||||
var __syncRequire = typeof module === "object" && typeof module.exports === "object";`
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace ts {
|
||||
* @param node The SourceFile node.
|
||||
*/
|
||||
function transformSourceFile(node: SourceFile) {
|
||||
if (node.isDeclarationFile || !(isExternalModule(node) || compilerOptions.isolatedModules)) {
|
||||
if (node.isDeclarationFile || !(isEffectiveExternalModule(node, compilerOptions) || node.transformFlags & TransformFlags.ContainsDynamicImport)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -646,7 +646,7 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const expression = visitNode(node.expression, destructuringVisitor, isExpression);
|
||||
const expression = visitNode(node.expression, destructuringAndImportCallVisitor, isExpression);
|
||||
const original = node.original;
|
||||
if (original && hasAssociatedEndOfDeclarationMarker(original)) {
|
||||
// Defer exports until we encounter an EndOfDeclarationMarker node
|
||||
@@ -673,12 +673,12 @@ namespace ts {
|
||||
node.asteriskToken,
|
||||
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.parameters, destructuringVisitor, isParameterDeclaration),
|
||||
visitNodes(node.parameters, destructuringAndImportCallVisitor, isParameterDeclaration),
|
||||
/*type*/ undefined,
|
||||
visitNode(node.body, destructuringVisitor, isBlock)));
|
||||
visitNode(node.body, destructuringAndImportCallVisitor, isBlock)));
|
||||
}
|
||||
else {
|
||||
hoistedStatements = append(hoistedStatements, node);
|
||||
hoistedStatements = append(hoistedStatements, visitEachChild(node, destructuringAndImportCallVisitor, context));
|
||||
}
|
||||
|
||||
if (hasAssociatedEndOfDeclarationMarker(node)) {
|
||||
@@ -716,8 +716,8 @@ namespace ts {
|
||||
/*modifiers*/ undefined,
|
||||
node.name,
|
||||
/*typeParameters*/ undefined,
|
||||
visitNodes(node.heritageClauses, destructuringVisitor, isHeritageClause),
|
||||
visitNodes(node.members, destructuringVisitor, isClassElement)
|
||||
visitNodes(node.heritageClauses, destructuringAndImportCallVisitor, isHeritageClause),
|
||||
visitNodes(node.members, destructuringAndImportCallVisitor, isClassElement)
|
||||
),
|
||||
node
|
||||
)
|
||||
@@ -747,7 +747,7 @@ namespace ts {
|
||||
*/
|
||||
function visitVariableStatement(node: VariableStatement): VisitResult<Statement> {
|
||||
if (!shouldHoistVariableDeclarationList(node.declarationList)) {
|
||||
return visitNode(node, destructuringVisitor, isStatement);
|
||||
return visitNode(node, destructuringAndImportCallVisitor, isStatement);
|
||||
}
|
||||
|
||||
let expressions: Expression[];
|
||||
@@ -820,13 +820,13 @@ namespace ts {
|
||||
return isBindingPattern(node.name)
|
||||
? flattenDestructuringAssignment(
|
||||
node,
|
||||
destructuringVisitor,
|
||||
destructuringAndImportCallVisitor,
|
||||
context,
|
||||
FlattenLevel.All,
|
||||
/*needsValue*/ false,
|
||||
createAssignment
|
||||
)
|
||||
: createAssignment(node.name, visitNode(node.initializer, destructuringVisitor, isExpression));
|
||||
: createAssignment(node.name, visitNode(node.initializer, destructuringAndImportCallVisitor, isExpression));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1204,7 +1204,7 @@ namespace ts {
|
||||
return visitEndOfDeclarationMarker(<EndOfDeclarationMarker>node);
|
||||
|
||||
default:
|
||||
return destructuringVisitor(node);
|
||||
return destructuringAndImportCallVisitor(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1220,8 +1220,8 @@ namespace ts {
|
||||
node = updateFor(
|
||||
node,
|
||||
visitForInitializer(node.initializer),
|
||||
visitNode(node.condition, destructuringVisitor, isExpression),
|
||||
visitNode(node.incrementor, destructuringVisitor, isExpression),
|
||||
visitNode(node.condition, destructuringAndImportCallVisitor, isExpression),
|
||||
visitNode(node.incrementor, destructuringAndImportCallVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement)
|
||||
);
|
||||
|
||||
@@ -1241,7 +1241,7 @@ namespace ts {
|
||||
node = updateForIn(
|
||||
node,
|
||||
visitForInitializer(node.initializer),
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
|
||||
);
|
||||
|
||||
@@ -1262,7 +1262,7 @@ namespace ts {
|
||||
node,
|
||||
node.awaitModifier,
|
||||
visitForInitializer(node.initializer),
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
|
||||
);
|
||||
|
||||
@@ -1313,7 +1313,7 @@ namespace ts {
|
||||
return updateDo(
|
||||
node,
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock),
|
||||
visitNode(node.expression, destructuringVisitor, isExpression)
|
||||
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1325,7 +1325,7 @@ namespace ts {
|
||||
function visitWhileStatement(node: WhileStatement): VisitResult<Statement> {
|
||||
return updateWhile(
|
||||
node,
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
|
||||
);
|
||||
}
|
||||
@@ -1351,7 +1351,7 @@ namespace ts {
|
||||
function visitWithStatement(node: WithStatement): VisitResult<Statement> {
|
||||
return updateWith(
|
||||
node,
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
|
||||
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
|
||||
);
|
||||
}
|
||||
@@ -1364,7 +1364,7 @@ namespace ts {
|
||||
function visitSwitchStatement(node: SwitchStatement): VisitResult<Statement> {
|
||||
return updateSwitch(
|
||||
node,
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
|
||||
visitNode(node.caseBlock, nestedElementVisitor, isCaseBlock)
|
||||
);
|
||||
}
|
||||
@@ -1395,7 +1395,7 @@ namespace ts {
|
||||
function visitCaseClause(node: CaseClause): VisitResult<CaseOrDefaultClause> {
|
||||
return updateCaseClause(
|
||||
node,
|
||||
visitNode(node.expression, destructuringVisitor, isExpression),
|
||||
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
|
||||
visitNodes(node.statements, nestedElementVisitor, isStatement)
|
||||
);
|
||||
}
|
||||
@@ -1461,19 +1461,43 @@ namespace ts {
|
||||
*
|
||||
* @param node The node to visit.
|
||||
*/
|
||||
function destructuringVisitor(node: Node): VisitResult<Node> {
|
||||
function destructuringAndImportCallVisitor(node: Node): VisitResult<Node> {
|
||||
if (node.transformFlags & TransformFlags.DestructuringAssignment
|
||||
&& node.kind === SyntaxKind.BinaryExpression) {
|
||||
return visitDestructuringAssignment(<DestructuringAssignment>node);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.ContainsDestructuringAssignment) {
|
||||
return visitEachChild(node, destructuringVisitor, context);
|
||||
else if (isImportCall(node)) {
|
||||
return visitImportCallExpression(node);
|
||||
}
|
||||
else if ((node.transformFlags & TransformFlags.ContainsDestructuringAssignment) || (node.transformFlags & TransformFlags.ContainsDynamicImport)) {
|
||||
return visitEachChild(node, destructuringAndImportCallVisitor, context);
|
||||
}
|
||||
else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
function visitImportCallExpression(node: ImportCall): Expression {
|
||||
// import("./blah")
|
||||
// emit as
|
||||
// System.register([], function (_export, _context) {
|
||||
// return {
|
||||
// setters: [],
|
||||
// execute: () => {
|
||||
// _context.import('./blah');
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
return createCall(
|
||||
createPropertyAccess(
|
||||
contextObject,
|
||||
createIdentifier("import")
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
node.arguments
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a DestructuringAssignment to flatten destructuring to exported symbols.
|
||||
*
|
||||
@@ -1483,14 +1507,14 @@ namespace ts {
|
||||
if (hasExportedReferenceInDestructuringTarget(node.left)) {
|
||||
return flattenDestructuringAssignment(
|
||||
node,
|
||||
destructuringVisitor,
|
||||
destructuringAndImportCallVisitor,
|
||||
context,
|
||||
FlattenLevel.All,
|
||||
/*needsValue*/ true
|
||||
);
|
||||
}
|
||||
|
||||
return visitEachChild(node, destructuringVisitor, context);
|
||||
return visitEachChild(node, destructuringAndImportCallVisitor, context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -662,6 +662,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (ts.Debug.isDebugging) {
|
||||
ts.Debug.enableDebugInfo();
|
||||
}
|
||||
|
||||
if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) {
|
||||
ts.sys.tryEnableSourceMapsForHost();
|
||||
}
|
||||
|
||||
+76
-31
@@ -374,6 +374,7 @@ namespace ts {
|
||||
JSDocComment,
|
||||
JSDocTag,
|
||||
JSDocAugmentsTag,
|
||||
JSDocClassTag,
|
||||
JSDocParameterTag,
|
||||
JSDocReturnTag,
|
||||
JSDocTypeTag,
|
||||
@@ -395,6 +396,7 @@ namespace ts {
|
||||
|
||||
// Enum value count
|
||||
Count,
|
||||
|
||||
// Markers
|
||||
FirstAssignment = EqualsToken,
|
||||
LastAssignment = CaretEqualsToken,
|
||||
@@ -423,7 +425,7 @@ namespace ts {
|
||||
FirstNode = QualifiedName,
|
||||
FirstJSDocNode = JSDocTypeExpression,
|
||||
LastJSDocNode = JSDocLiteralType,
|
||||
FirstJSDocTagNode = JSDocComment,
|
||||
FirstJSDocTagNode = JSDocTag,
|
||||
LastJSDocTagNode = JSDocLiteralType
|
||||
}
|
||||
|
||||
@@ -449,6 +451,17 @@ namespace ts {
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 17, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 18, // If we've computed data from children and cached it in this node
|
||||
|
||||
// This flag will be set when the parser encounters a dynamic import expression so that module resolution
|
||||
// will not have to walk the tree if the flag is not set. However, this flag is just a approximation because
|
||||
// once it is set, the flag never gets cleared (hence why it's named "PossiblyContainsDynamicImport").
|
||||
// During editing, if dynamic import is removed, incremental parsing will *NOT* update this flag. This means that the tree will always be traversed
|
||||
// during module resolution. However, the removal operation should not occur often and in the case of the
|
||||
// removal, it is likely that users will add the import anyway.
|
||||
// The advantage of this approach is its simplicity. For the case of batch compilation,
|
||||
// we guarantee that users won't have to pay the price of walking the tree if a dynamic import isn't used.
|
||||
/* @internal */
|
||||
PossiblyContainsDynamicImport = 1 << 19,
|
||||
|
||||
BlockScoped = Let | Const,
|
||||
|
||||
ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn,
|
||||
@@ -1001,8 +1014,10 @@ namespace ts {
|
||||
_unaryExpressionBrand: any;
|
||||
}
|
||||
|
||||
export interface IncrementExpression extends UnaryExpression {
|
||||
_incrementExpressionBrand: any;
|
||||
/** Deprecated, please use UpdateExpression */
|
||||
export type IncrementExpression = UpdateExpression;
|
||||
export interface UpdateExpression extends UnaryExpression {
|
||||
_updateExpressionBrand: any;
|
||||
}
|
||||
|
||||
// see: https://tc39.github.io/ecma262/#prod-UpdateExpression
|
||||
@@ -1013,10 +1028,9 @@ namespace ts {
|
||||
| SyntaxKind.PlusToken
|
||||
| SyntaxKind.MinusToken
|
||||
| SyntaxKind.TildeToken
|
||||
| SyntaxKind.ExclamationToken
|
||||
;
|
||||
| SyntaxKind.ExclamationToken;
|
||||
|
||||
export interface PrefixUnaryExpression extends IncrementExpression {
|
||||
export interface PrefixUnaryExpression extends UpdateExpression {
|
||||
kind: SyntaxKind.PrefixUnaryExpression;
|
||||
operator: PrefixUnaryOperator;
|
||||
operand: UnaryExpression;
|
||||
@@ -1028,13 +1042,13 @@ namespace ts {
|
||||
| SyntaxKind.MinusMinusToken
|
||||
;
|
||||
|
||||
export interface PostfixUnaryExpression extends IncrementExpression {
|
||||
export interface PostfixUnaryExpression extends UpdateExpression {
|
||||
kind: SyntaxKind.PostfixUnaryExpression;
|
||||
operand: LeftHandSideExpression;
|
||||
operator: PostfixUnaryOperator;
|
||||
}
|
||||
|
||||
export interface LeftHandSideExpression extends IncrementExpression {
|
||||
export interface LeftHandSideExpression extends UpdateExpression {
|
||||
_leftHandSideExpressionBrand: any;
|
||||
}
|
||||
|
||||
@@ -1062,6 +1076,10 @@ namespace ts {
|
||||
kind: SyntaxKind.SuperKeyword;
|
||||
}
|
||||
|
||||
export interface ImportExpression extends PrimaryExpression {
|
||||
kind: SyntaxKind.ImportKeyword;
|
||||
}
|
||||
|
||||
export interface DeleteExpression extends UnaryExpression {
|
||||
kind: SyntaxKind.DeleteExpression;
|
||||
expression: UnaryExpression;
|
||||
@@ -1454,10 +1472,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// see: https://tc39.github.io/ecma262/#prod-SuperProperty
|
||||
export type SuperProperty
|
||||
= SuperPropertyAccessExpression
|
||||
| SuperElementAccessExpression
|
||||
;
|
||||
export type SuperProperty = SuperPropertyAccessExpression | SuperElementAccessExpression;
|
||||
|
||||
export interface CallExpression extends LeftHandSideExpression, Declaration {
|
||||
kind: SyntaxKind.CallExpression;
|
||||
@@ -1471,6 +1486,10 @@ namespace ts {
|
||||
expression: SuperExpression;
|
||||
}
|
||||
|
||||
export interface ImportCall extends CallExpression {
|
||||
expression: ImportExpression;
|
||||
}
|
||||
|
||||
export interface ExpressionWithTypeArguments extends TypeNode {
|
||||
kind: SyntaxKind.ExpressionWithTypeArguments;
|
||||
parent?: HeritageClause;
|
||||
@@ -1689,6 +1708,8 @@ namespace ts {
|
||||
incrementor?: Expression;
|
||||
}
|
||||
|
||||
export type ForInOrOfStatement = ForInStatement | ForOfStatement;
|
||||
|
||||
export interface ForInStatement extends IterationStatement {
|
||||
kind: SyntaxKind.ForInStatement;
|
||||
initializer: ForInitializer;
|
||||
@@ -1778,7 +1799,7 @@ namespace ts {
|
||||
block: Block;
|
||||
}
|
||||
|
||||
export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration;
|
||||
export type DeclarationWithTypeParameters = SignatureDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag;
|
||||
|
||||
export interface ClassLikeDeclaration extends NamedDeclaration {
|
||||
name?: Identifier;
|
||||
@@ -2117,6 +2138,10 @@ namespace ts {
|
||||
typeExpression: JSDocTypeExpression;
|
||||
}
|
||||
|
||||
export interface JSDocClassTag extends JSDocTag {
|
||||
kind: SyntaxKind.JSDocClassTag;
|
||||
}
|
||||
|
||||
export interface JSDocTemplateTag extends JSDocTag {
|
||||
kind: SyntaxKind.JSDocTemplateTag;
|
||||
typeParameters: NodeArray<TypeParameterDeclaration>;
|
||||
@@ -2535,7 +2560,6 @@ namespace ts {
|
||||
getNonNullableType(type: Type): Type;
|
||||
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
|
||||
typeToTypeNode(type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): TypeNode;
|
||||
/** Note that the resulting nodes cannot be checked. */
|
||||
signatureToSignatureDeclaration(signature: Signature, kind: SyntaxKind, enclosingDeclaration?: Node, flags?: NodeBuilderFlags): SignatureDeclaration;
|
||||
@@ -2605,6 +2629,9 @@ namespace ts {
|
||||
* Does not include properties of primitive types.
|
||||
*/
|
||||
/* @internal */ getAllPossiblePropertiesOfType(type: Type): Symbol[];
|
||||
|
||||
/* @internal */ getJsxNamespace(): string;
|
||||
/* @internal */ resolveNameAtLocation(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined;
|
||||
}
|
||||
|
||||
export enum NodeBuilderFlags {
|
||||
@@ -3497,6 +3524,7 @@ namespace ts {
|
||||
noImplicitAny?: boolean; // Always combine with strict property
|
||||
noImplicitReturns?: boolean;
|
||||
noImplicitThis?: boolean; // Always combine with strict property
|
||||
noStrictGenericChecks?: boolean;
|
||||
noUnusedLocals?: boolean;
|
||||
noUnusedParameters?: boolean;
|
||||
noImplicitUseStrict?: boolean;
|
||||
@@ -3564,6 +3592,7 @@ namespace ts {
|
||||
UMD = 3,
|
||||
System = 4,
|
||||
ES2015 = 5,
|
||||
ESNext = 6
|
||||
}
|
||||
|
||||
export const enum JsxEmit {
|
||||
@@ -3855,13 +3884,12 @@ namespace ts {
|
||||
extension: Extension;
|
||||
}
|
||||
|
||||
export enum Extension {
|
||||
Ts,
|
||||
Tsx,
|
||||
Dts,
|
||||
Js,
|
||||
Jsx,
|
||||
LastTypeScriptExtension = Dts
|
||||
export const enum Extension {
|
||||
Ts = ".ts",
|
||||
Tsx = ".tsx",
|
||||
Dts = ".d.ts",
|
||||
Js = ".js",
|
||||
Jsx = ".jsx"
|
||||
}
|
||||
|
||||
export interface ResolvedModuleWithFailedLookupLocations {
|
||||
@@ -3948,6 +3976,11 @@ namespace ts {
|
||||
ContainsYield = 1 << 24,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 25,
|
||||
|
||||
ContainsDynamicImport = 1 << 26,
|
||||
|
||||
// Please leave this as 1 << 29.
|
||||
// It is the maximum bit we can set before we outgrow the size of a v8 small integer (SMI) on an x86 system.
|
||||
// It is a good reminder of how much room we have left
|
||||
HasComputedFlags = 1 << 29, // Transform flags have been computed.
|
||||
|
||||
// Assertions
|
||||
@@ -3985,18 +4018,29 @@ namespace ts {
|
||||
ES2015FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments,
|
||||
}
|
||||
|
||||
export interface SourceMapRange extends TextRange {
|
||||
source?: SourceMapSource;
|
||||
}
|
||||
|
||||
export interface SourceMapSource {
|
||||
fileName: string;
|
||||
text: string;
|
||||
/* @internal */ lineMap: number[];
|
||||
skipTrivia?: (pos: number) => number;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface EmitNode {
|
||||
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
|
||||
flags?: EmitFlags; // Flags that customize emit
|
||||
leadingComments?: SynthesizedComment[]; // Synthesized leading comments
|
||||
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
|
||||
flags?: EmitFlags; // Flags that customize emit
|
||||
leadingComments?: SynthesizedComment[]; // Synthesized leading comments
|
||||
trailingComments?: SynthesizedComment[]; // Synthesized trailing comments
|
||||
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
|
||||
sourceMapRange?: TextRange; // The text range to use when emitting leading or trailing source mappings
|
||||
tokenSourceMapRanges?: TextRange[]; // 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
|
||||
helpers?: EmitHelper[]; // Emit helpers for the node
|
||||
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
|
||||
sourceMapRange?: SourceMapRange; // The text range to use when emitting leading or trailing source mappings
|
||||
tokenSourceMapRanges?: SourceMapRange[]; // 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
|
||||
helpers?: EmitHelper[]; // Emit helpers for the node
|
||||
}
|
||||
|
||||
export const enum EmitFlags {
|
||||
@@ -4058,6 +4102,7 @@ namespace ts {
|
||||
AsyncGenerator = 1 << 12, // __asyncGenerator (used by ES2017 async generator transformation)
|
||||
AsyncDelegator = 1 << 13, // __asyncDelegator (used by ES2017 async generator yield* transformation)
|
||||
AsyncValues = 1 << 14, // __asyncValues (used by ES2017 for..await..of transformation)
|
||||
ExportStar = 1 << 15, // __exportStar (used by CommonJS/AMD/UMD module transformation)
|
||||
|
||||
// Helpers included by ES2015 for..of
|
||||
ForOfIncludes = Values,
|
||||
@@ -4075,7 +4120,7 @@ namespace ts {
|
||||
SpreadIncludes = Read | Spread,
|
||||
|
||||
FirstEmitHelper = Extends,
|
||||
LastEmitHelper = AsyncValues
|
||||
LastEmitHelper = ExportStar
|
||||
}
|
||||
|
||||
export const enum EmitHint {
|
||||
|
||||
+114
-31
@@ -596,6 +596,10 @@ namespace ts {
|
||||
return n.kind === SyntaxKind.CallExpression && (<CallExpression>n).expression.kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
|
||||
export function isImportCall(n: Node): n is ImportCall {
|
||||
return n.kind === SyntaxKind.CallExpression && (<CallExpression>n).expression.kind === SyntaxKind.ImportKeyword;
|
||||
}
|
||||
|
||||
export function isPrologueDirective(node: Node): node is PrologueDirective {
|
||||
return node.kind === SyntaxKind.ExpressionStatement
|
||||
&& (<ExpressionStatement>node).expression.kind === SyntaxKind.StringLiteral;
|
||||
@@ -1434,31 +1438,17 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getJSDocTags(node: Node, kind: SyntaxKind): JSDocTag[] {
|
||||
const docs = getJSDocs(node);
|
||||
if (docs) {
|
||||
const result: JSDocTag[] = [];
|
||||
for (const doc of docs) {
|
||||
if (doc.kind === SyntaxKind.JSDocParameterTag) {
|
||||
if (doc.kind === kind) {
|
||||
result.push(doc as JSDocTag);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const tags = (doc as JSDoc).tags;
|
||||
if (tags) {
|
||||
result.push(...filter(tags, tag => tag.kind === kind));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return flatMap(getJSDocs(node), doc =>
|
||||
doc.kind === SyntaxKind.JSDocComment
|
||||
? filter((doc as JSDoc).tags, tag => tag.kind === kind)
|
||||
: doc.kind === kind && doc);
|
||||
}
|
||||
|
||||
function getFirstJSDocTag(node: Node, kind: SyntaxKind): JSDocTag {
|
||||
return node && firstOrUndefined(getJSDocTags(node, kind));
|
||||
}
|
||||
|
||||
export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
|
||||
export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
|
||||
if (isJSDocTypedefTag(node)) {
|
||||
return [node.parent];
|
||||
}
|
||||
@@ -1556,6 +1546,12 @@ namespace ts {
|
||||
p.name.kind === SyntaxKind.Identifier && p.name.text === name);
|
||||
}
|
||||
|
||||
export function getTypeParameterFromJsDoc(node: TypeParameterDeclaration & { parent: JSDocTemplateTag }): TypeParameterDeclaration | undefined {
|
||||
const name = node.name.text;
|
||||
const { typeParameters } = (node.parent.parent.parent as ts.SignatureDeclaration | ts.InterfaceDeclaration | ts.ClassDeclaration);
|
||||
return find(typeParameters, p => p.name.text === name);
|
||||
}
|
||||
|
||||
export function getJSDocType(node: Node): JSDocType {
|
||||
let tag: JSDocTypeTag | JSDocParameterTag = getFirstJSDocTag(node, SyntaxKind.JSDocTypeTag) as JSDocTypeTag;
|
||||
if (!tag && node.kind === SyntaxKind.Parameter) {
|
||||
@@ -1572,10 +1568,19 @@ namespace ts {
|
||||
return getFirstJSDocTag(node, SyntaxKind.JSDocAugmentsTag) as JSDocAugmentsTag;
|
||||
}
|
||||
|
||||
export function getJSDocClassTag(node: Node): JSDocClassTag {
|
||||
return getFirstJSDocTag(node, SyntaxKind.JSDocClassTag) as JSDocClassTag;
|
||||
}
|
||||
|
||||
export function getJSDocReturnTag(node: Node): JSDocReturnTag {
|
||||
return getFirstJSDocTag(node, SyntaxKind.JSDocReturnTag) as JSDocReturnTag;
|
||||
}
|
||||
|
||||
export function getJSDocReturnType(node: Node): JSDocType {
|
||||
const returnTag = getJSDocReturnTag(node);
|
||||
return returnTag && returnTag.typeExpression && returnTag.typeExpression.type;
|
||||
}
|
||||
|
||||
export function getJSDocTemplateTag(node: Node): JSDocTemplateTag {
|
||||
return getFirstJSDocTag(node, SyntaxKind.JSDocTemplateTag) as JSDocTemplateTag;
|
||||
}
|
||||
@@ -1622,7 +1627,7 @@ namespace ts {
|
||||
return unaryOperator === SyntaxKind.PlusPlusToken || unaryOperator === SyntaxKind.MinusMinusToken ? AssignmentKind.Compound : AssignmentKind.None;
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
return (<ForInStatement | ForOfStatement>parent).initializer === node ? AssignmentKind.Definite : AssignmentKind.None;
|
||||
return (<ForInOrOfStatement>parent).initializer === node ? AssignmentKind.Definite : AssignmentKind.None;
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
case SyntaxKind.SpreadElement:
|
||||
@@ -2496,7 +2501,7 @@ namespace ts {
|
||||
const path = outputDir
|
||||
? getSourceFilePathInNewDir(sourceFile, host, outputDir)
|
||||
: sourceFile.fileName;
|
||||
return removeFileExtension(path) + ".d.ts";
|
||||
return removeFileExtension(path) + Extension.Dts;
|
||||
}
|
||||
|
||||
export interface EmitFileNames {
|
||||
@@ -2555,7 +2560,7 @@ namespace ts {
|
||||
if (sourceFiles.length) {
|
||||
const jsFilePath = options.outFile || options.out;
|
||||
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
|
||||
const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : "";
|
||||
const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + Extension.Dts : "";
|
||||
action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles);
|
||||
}
|
||||
}
|
||||
@@ -2576,19 +2581,19 @@ namespace ts {
|
||||
// JavaScript files are always LanguageVariant.JSX, as JSX syntax is allowed in .js files also.
|
||||
// So for JavaScript files, '.jsx' is only emitted if the input was '.jsx', and JsxEmit.Preserve.
|
||||
// For TypeScript, the only time to emit with a '.jsx' extension, is on JSX input, and JsxEmit.Preserve
|
||||
function getOutputExtension(sourceFile: SourceFile, options: CompilerOptions): string {
|
||||
function getOutputExtension(sourceFile: SourceFile, options: CompilerOptions): Extension {
|
||||
if (options.jsx === JsxEmit.Preserve) {
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
if (fileExtensionIs(sourceFile.fileName, ".jsx")) {
|
||||
return ".jsx";
|
||||
if (fileExtensionIs(sourceFile.fileName, Extension.Jsx)) {
|
||||
return Extension.Jsx;
|
||||
}
|
||||
}
|
||||
else if (sourceFile.languageVariant === LanguageVariant.JSX) {
|
||||
// TypeScript source file preserving JSX syntax
|
||||
return ".jsx";
|
||||
return Extension.Jsx;
|
||||
}
|
||||
}
|
||||
return ".js";
|
||||
return Extension.Js;
|
||||
}
|
||||
|
||||
export function getSourceFilePathInNewDir(sourceFile: SourceFile, host: EmitHost, newDirPath: string) {
|
||||
@@ -2621,14 +2626,19 @@ namespace ts {
|
||||
});
|
||||
}
|
||||
|
||||
/** Get the type annotaion for the value parameter. */
|
||||
export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode {
|
||||
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].type;
|
||||
return accessor.parameters[hasThis ? 1 : 0];
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the type annotation for the value parameter. */
|
||||
export function getSetAccessorTypeAnnotationNode(accessor: SetAccessorDeclaration): TypeNode {
|
||||
const parameter = getSetAccessorValueParameter(accessor);
|
||||
return parameter && parameter.type;
|
||||
}
|
||||
|
||||
export function getThisParameter(signature: SignatureDeclaration): ParameterDeclaration | undefined {
|
||||
if (signature.parameters.length) {
|
||||
const thisParameter = signature.parameters[0];
|
||||
@@ -2707,6 +2717,55 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the effective type annotation of a variable, parameter, or property. If the node was
|
||||
* parsed in a JavaScript file, gets the type annotation from JSDoc.
|
||||
*/
|
||||
export function getEffectiveTypeAnnotationNode(node: VariableLikeDeclaration): TypeNode {
|
||||
if (node.type) {
|
||||
return node.type;
|
||||
}
|
||||
if (node.flags & NodeFlags.JavaScriptFile) {
|
||||
return getJSDocType(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the effective return type annotation of a signature. If the node was parsed in a
|
||||
* JavaScript file, gets the return type annotation from JSDoc.
|
||||
*/
|
||||
export function getEffectiveReturnTypeNode(node: SignatureDeclaration): TypeNode {
|
||||
if (node.type) {
|
||||
return node.type;
|
||||
}
|
||||
if (node.flags & NodeFlags.JavaScriptFile) {
|
||||
return getJSDocReturnType(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the effective type parameters. If the node was parsed in a
|
||||
* JavaScript file, gets the type parameters from the `@template` tag from JSDoc.
|
||||
*/
|
||||
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): TypeParameterDeclaration[] {
|
||||
if (node.typeParameters) {
|
||||
return node.typeParameters;
|
||||
}
|
||||
if (node.flags & NodeFlags.JavaScriptFile) {
|
||||
const templateTag = getJSDocTemplateTag(node);
|
||||
return templateTag && templateTag.typeParameters;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the effective type annotation of the value parameter of a set accessor. If the node
|
||||
* was parsed in a JavaScript file, gets the type annotation from JSDoc.
|
||||
*/
|
||||
export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode {
|
||||
const parameter = getSetAccessorValueParameter(node);
|
||||
return parameter && getEffectiveTypeAnnotationNode(parameter);
|
||||
}
|
||||
|
||||
export function emitNewLineBeforeLeadingComments(lineMap: number[], writer: EmitTextWriter, node: TextRange, leadingComments: CommentRange[]) {
|
||||
emitNewLineBeforeLeadingCommentsOfPosition(lineMap, writer, node.pos, leadingComments);
|
||||
}
|
||||
@@ -4053,7 +4112,7 @@ namespace ts {
|
||||
|
||||
// Signature elements
|
||||
|
||||
export function isTypeParameter(node: Node): node is TypeParameterDeclaration {
|
||||
export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration {
|
||||
return node.kind === SyntaxKind.TypeParameter;
|
||||
}
|
||||
|
||||
@@ -4676,6 +4735,16 @@ namespace ts {
|
||||
// All node tests in the following list should *not* reference parent pointers so that
|
||||
// they may be used with transformations.
|
||||
namespace ts {
|
||||
/* @internal */
|
||||
export function isNode(node: Node) {
|
||||
return isNodeKind(node.kind);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function isNodeKind(kind: SyntaxKind) {
|
||||
return kind >= SyntaxKind.FirstNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if node is of some token syntax kind.
|
||||
* For example, this is true for an IfKeyword but not for an IfStatement.
|
||||
@@ -5097,6 +5166,11 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function isForInOrOfStatement(node: Node): node is ForInOrOfStatement {
|
||||
return node.kind === SyntaxKind.ForInStatement || node.kind === SyntaxKind.ForOfStatement;
|
||||
}
|
||||
|
||||
// Element
|
||||
|
||||
/* @internal */
|
||||
@@ -5225,6 +5299,10 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export function isDeclaration(node: Node): node is NamedDeclaration {
|
||||
if (node.kind === SyntaxKind.TypeParameter) {
|
||||
return node.parent.kind !== SyntaxKind.JSDocTemplateTag || isInJavaScriptFile(node);
|
||||
}
|
||||
|
||||
return isDeclarationKind(node.kind);
|
||||
}
|
||||
|
||||
@@ -5314,6 +5392,11 @@ namespace ts {
|
||||
return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode;
|
||||
}
|
||||
|
||||
/** True if node is of a kind that may contain comment text. */
|
||||
export function isJSDocCommentContainingNode(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.JSDocComment || isJSDocTag(node);
|
||||
}
|
||||
|
||||
// TODO: determine what this does before making it public.
|
||||
/* @internal */
|
||||
export function isJSDocTag(node: Node): boolean {
|
||||
|
||||
+64
-46
@@ -275,7 +275,7 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.MethodSignature:
|
||||
return updateMethodSignature(<MethodSignature>node,
|
||||
nodesVisitor((<MethodSignature>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<MethodSignature>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<MethodSignature>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<MethodSignature>node).type, visitor, isTypeNode),
|
||||
visitNode((<MethodSignature>node).name, visitor, isPropertyName),
|
||||
@@ -288,7 +288,7 @@ namespace ts {
|
||||
visitNode((<MethodDeclaration>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<MethodDeclaration>node).name, visitor, isPropertyName),
|
||||
visitNode((<MethodDeclaration>node).questionToken, tokenVisitor, isToken),
|
||||
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<MethodDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<MethodDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<MethodDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<MethodDeclaration>node).body, visitor, context));
|
||||
@@ -319,13 +319,13 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.CallSignature:
|
||||
return updateCallSignature(<CallSignatureDeclaration>node,
|
||||
nodesVisitor((<CallSignatureDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<CallSignatureDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<CallSignatureDeclaration>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<CallSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ConstructSignature:
|
||||
return updateConstructSignature(<ConstructSignatureDeclaration>node,
|
||||
nodesVisitor((<ConstructSignatureDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<ConstructSignatureDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ConstructSignatureDeclaration>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<ConstructSignatureDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
@@ -350,13 +350,13 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.FunctionType:
|
||||
return updateFunctionTypeNode(<FunctionTypeNode>node,
|
||||
nodesVisitor((<FunctionTypeNode>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<FunctionTypeNode>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<FunctionTypeNode>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<FunctionTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.ConstructorType:
|
||||
return updateConstructorTypeNode(<ConstructorTypeNode>node,
|
||||
nodesVisitor((<ConstructorTypeNode>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<ConstructorTypeNode>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ConstructorTypeNode>node).parameters, visitor, isParameterDeclaration),
|
||||
visitNode((<ConstructorTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
@@ -400,7 +400,7 @@ namespace ts {
|
||||
case SyntaxKind.MappedType:
|
||||
return updateMappedTypeNode((<MappedTypeNode>node),
|
||||
visitNode((<MappedTypeNode>node).readonlyToken, tokenVisitor, isToken),
|
||||
visitNode((<MappedTypeNode>node).typeParameter, visitor, isTypeParameter),
|
||||
visitNode((<MappedTypeNode>node).typeParameter, visitor, isTypeParameterDeclaration),
|
||||
visitNode((<MappedTypeNode>node).questionToken, tokenVisitor, isToken),
|
||||
visitNode((<MappedTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
@@ -476,7 +476,7 @@ namespace ts {
|
||||
nodesVisitor((<FunctionExpression>node).modifiers, visitor, isModifier),
|
||||
visitNode((<FunctionExpression>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<FunctionExpression>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<FunctionExpression>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<FunctionExpression>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionExpression>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
@@ -484,7 +484,7 @@ namespace ts {
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return updateArrowFunction(<ArrowFunction>node,
|
||||
nodesVisitor((<ArrowFunction>node).modifiers, visitor, isModifier),
|
||||
nodesVisitor((<ArrowFunction>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<ArrowFunction>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<ArrowFunction>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<ArrowFunction>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<ArrowFunction>node).body, visitor, context));
|
||||
@@ -543,7 +543,7 @@ namespace ts {
|
||||
return updateClassExpression(<ClassExpression>node,
|
||||
nodesVisitor((<ClassExpression>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassExpression>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<ClassExpression>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<ClassExpression>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ClassExpression>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassExpression>node).members, visitor, isClassElement));
|
||||
|
||||
@@ -676,7 +676,7 @@ namespace ts {
|
||||
nodesVisitor((<FunctionDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<FunctionDeclaration>node).asteriskToken, tokenVisitor, isToken),
|
||||
visitNode((<FunctionDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<FunctionDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitParameterList((<FunctionDeclaration>node).parameters, visitor, context, nodesVisitor),
|
||||
visitNode((<FunctionDeclaration>node).type, visitor, isTypeNode),
|
||||
visitFunctionBody((<FunctionExpression>node).body, visitor, context));
|
||||
@@ -686,7 +686,7 @@ namespace ts {
|
||||
nodesVisitor((<ClassDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<ClassDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<ClassDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<ClassDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<ClassDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<ClassDeclaration>node).members, visitor, isClassElement));
|
||||
|
||||
@@ -695,7 +695,7 @@ namespace ts {
|
||||
nodesVisitor((<InterfaceDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<InterfaceDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<InterfaceDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<InterfaceDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<InterfaceDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
nodesVisitor((<InterfaceDeclaration>node).heritageClauses, visitor, isHeritageClause),
|
||||
nodesVisitor((<InterfaceDeclaration>node).members, visitor, isTypeElement));
|
||||
|
||||
@@ -704,7 +704,7 @@ namespace ts {
|
||||
nodesVisitor((<TypeAliasDeclaration>node).decorators, visitor, isDecorator),
|
||||
nodesVisitor((<TypeAliasDeclaration>node).modifiers, visitor, isModifier),
|
||||
visitNode((<TypeAliasDeclaration>node).name, visitor, isIdentifier),
|
||||
nodesVisitor((<TypeAliasDeclaration>node).typeParameters, visitor, isTypeParameter),
|
||||
nodesVisitor((<TypeAliasDeclaration>node).typeParameters, visitor, isTypeParameterDeclaration),
|
||||
visitNode((<TypeAliasDeclaration>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
@@ -1198,9 +1198,9 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ForInStatement:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
result = reduceNode((<ForInStatement | ForOfStatement>node).initializer, cbNode, result);
|
||||
result = reduceNode((<ForInStatement | ForOfStatement>node).expression, cbNode, result);
|
||||
result = reduceNode((<ForInStatement | ForOfStatement>node).statement, cbNode, result);
|
||||
result = reduceNode((<ForInOrOfStatement>node).initializer, cbNode, result);
|
||||
result = reduceNode((<ForInOrOfStatement>node).expression, cbNode, result);
|
||||
result = reduceNode((<ForInOrOfStatement>node).statement, cbNode, result);
|
||||
break;
|
||||
|
||||
case SyntaxKind.ReturnStatement:
|
||||
@@ -1517,35 +1517,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
export namespace Debug {
|
||||
if (isDebugging) {
|
||||
// Add additional properties in debug mode to assist with debugging.
|
||||
Object.defineProperties(objectAllocator.getSymbolConstructor().prototype, {
|
||||
"__debugFlags": { get(this: Symbol) { return formatSymbolFlags(this.flags); } }
|
||||
});
|
||||
|
||||
Object.defineProperties(objectAllocator.getTypeConstructor().prototype, {
|
||||
"__debugFlags": { get(this: Type) { return formatTypeFlags(this.flags); } },
|
||||
"__debugObjectFlags": { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((<ObjectType>this).objectFlags) : ""; } },
|
||||
"__debugTypeToString": { value(this: Type) { return this.checker.typeToString(this); } },
|
||||
});
|
||||
|
||||
for (const ctor of [objectAllocator.getNodeConstructor(), objectAllocator.getIdentifierConstructor(), objectAllocator.getTokenConstructor(), objectAllocator.getSourceFileConstructor()]) {
|
||||
if (!ctor.prototype.hasOwnProperty("__debugKind")) {
|
||||
Object.defineProperties(ctor.prototype, {
|
||||
"__debugKind": { get(this: Node) { return formatSyntaxKind(this.kind); } },
|
||||
"__debugModifierFlags": { get(this: Node) { return formatModifierFlags(getModifierFlagsNoCache(this)); } },
|
||||
"__debugTransformFlags": { get(this: Node) { return formatTransformFlags(this.transformFlags); } },
|
||||
"__debugEmitFlags": { get(this: Node) { return formatEmitFlags(getEmitFlags(this)); } },
|
||||
"__debugGetText": { value(this: Node, includeTrivia?: boolean) {
|
||||
if (nodeIsSynthesized(this)) return "";
|
||||
const parseNode = getParseTreeNode(this);
|
||||
const sourceFile = parseNode && getSourceFileOfNode(parseNode);
|
||||
return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : "";
|
||||
} }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
let isDebugInfoEnabled = false;
|
||||
|
||||
export const failBadSyntaxKind = shouldAssert(AssertionLevel.Normal)
|
||||
? (node: Node, message?: string): void => fail(
|
||||
@@ -1592,5 +1564,51 @@ namespace ts {
|
||||
() => `Node ${formatSyntaxKind(node.kind)} was unexpected'.`,
|
||||
assertMissingNode)
|
||||
: noop;
|
||||
|
||||
/**
|
||||
* Injects debug information into frequently used types.
|
||||
*/
|
||||
export function enableDebugInfo() {
|
||||
if (isDebugInfoEnabled) return;
|
||||
|
||||
// Add additional properties in debug mode to assist with debugging.
|
||||
Object.defineProperties(objectAllocator.getSymbolConstructor().prototype, {
|
||||
"__debugFlags": { get(this: Symbol) { return formatSymbolFlags(this.flags); } }
|
||||
});
|
||||
|
||||
Object.defineProperties(objectAllocator.getTypeConstructor().prototype, {
|
||||
"__debugFlags": { get(this: Type) { return formatTypeFlags(this.flags); } },
|
||||
"__debugObjectFlags": { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((<ObjectType>this).objectFlags) : ""; } },
|
||||
"__debugTypeToString": { value(this: Type) { return this.checker.typeToString(this); } },
|
||||
});
|
||||
|
||||
const nodeConstructors = [
|
||||
objectAllocator.getNodeConstructor(),
|
||||
objectAllocator.getIdentifierConstructor(),
|
||||
objectAllocator.getTokenConstructor(),
|
||||
objectAllocator.getSourceFileConstructor()
|
||||
];
|
||||
|
||||
for (const ctor of nodeConstructors) {
|
||||
if (!ctor.prototype.hasOwnProperty("__debugKind")) {
|
||||
Object.defineProperties(ctor.prototype, {
|
||||
"__debugKind": { get(this: Node) { return formatSyntaxKind(this.kind); } },
|
||||
"__debugModifierFlags": { get(this: Node) { return formatModifierFlags(getModifierFlagsNoCache(this)); } },
|
||||
"__debugTransformFlags": { get(this: Node) { return formatTransformFlags(this.transformFlags); } },
|
||||
"__debugEmitFlags": { get(this: Node) { return formatEmitFlags(getEmitFlags(this)); } },
|
||||
"__debugGetText": {
|
||||
value(this: Node, includeTrivia?: boolean) {
|
||||
if (nodeIsSynthesized(this)) return "";
|
||||
const parseNode = getParseTreeNode(this);
|
||||
const sourceFile = parseNode && getSourceFileOfNode(parseNode);
|
||||
return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : "";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
isDebugInfoEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
}
|
||||
|
||||
lastUnit = units[units.length - 1];
|
||||
hasNonDtsFiles = ts.forEach(units, unit => !ts.fileExtensionIs(unit.name, ".d.ts"));
|
||||
hasNonDtsFiles = ts.forEach(units, unit => !ts.fileExtensionIs(unit.name, ts.Extension.Dts));
|
||||
// We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test)
|
||||
// If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references,
|
||||
// otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another.
|
||||
|
||||
+109
-73
@@ -479,24 +479,11 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
private getDiagnostics(fileName: string): ts.Diagnostic[] {
|
||||
const syntacticErrors = this.languageService.getSyntacticDiagnostics(fileName);
|
||||
const semanticErrors = this.languageService.getSemanticDiagnostics(fileName);
|
||||
|
||||
const diagnostics: ts.Diagnostic[] = [];
|
||||
diagnostics.push.apply(diagnostics, syntacticErrors);
|
||||
diagnostics.push.apply(diagnostics, semanticErrors);
|
||||
|
||||
return diagnostics;
|
||||
return this.languageService.getSyntacticDiagnostics(fileName).concat(this.languageService.getSemanticDiagnostics(fileName));
|
||||
}
|
||||
|
||||
private getAllDiagnostics(): ts.Diagnostic[] {
|
||||
const diagnostics: ts.Diagnostic[] = [];
|
||||
|
||||
for (const fileName of this.languageServiceAdapterHost.getFilenames()) {
|
||||
diagnostics.push.apply(this.getDiagnostics(fileName));
|
||||
}
|
||||
|
||||
return diagnostics;
|
||||
return ts.flatMap(this.languageServiceAdapterHost.getFilenames(), fileName => this.getDiagnostics(fileName));
|
||||
}
|
||||
|
||||
public verifyErrorExistsAfterMarker(markerName: string, negative: boolean, after: boolean) {
|
||||
@@ -549,11 +536,16 @@ namespace FourSlash {
|
||||
Harness.IO.log("Unexpected error(s) found. Error list is:");
|
||||
}
|
||||
|
||||
for (const { start, length, messageText } of errors) {
|
||||
Harness.IO.log(" minChar: " + start +
|
||||
", limChar: " + (start + length) +
|
||||
for (const { start, length, messageText, file } of errors) {
|
||||
Harness.IO.log(" from: " + showPosition(file, start) +
|
||||
", to: " + showPosition(file, start + length) +
|
||||
", message: " + ts.flattenDiagnosticMessageText(messageText, Harness.IO.newLine()) + "\n");
|
||||
}
|
||||
|
||||
function showPosition(file: ts.SourceFile, pos: number) {
|
||||
const { line, character } = ts.getLineAndCharacterOfPosition(file, pos);
|
||||
return `${line}:${character}`;
|
||||
}
|
||||
}
|
||||
|
||||
public verifyNoErrors() {
|
||||
@@ -1052,21 +1044,27 @@ namespace FourSlash {
|
||||
fail(`Expected ${expected}, got ${actual}`);
|
||||
}
|
||||
|
||||
for (const key in actual) if (ts.hasProperty(actual as any, key)) {
|
||||
const ak = actual[key], ek = expected[key];
|
||||
if (typeof ak === "object" && typeof ek === "object") {
|
||||
recur(ak, ek, path ? path + "." + key : key);
|
||||
}
|
||||
else if (ak !== ek) {
|
||||
fail(`Expected '${key}' to be '${ek}', got '${ak}'`);
|
||||
for (const key in actual) {
|
||||
if (ts.hasProperty(actual as any, key)) {
|
||||
const ak = actual[key], ek = expected[key];
|
||||
if (typeof ak === "object" && typeof ek === "object") {
|
||||
recur(ak, ek, path ? path + "." + key : key);
|
||||
}
|
||||
else if (ak !== ek) {
|
||||
fail(`Expected '${key}' to be '${ek}', got '${ak}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const key in expected) if (ts.hasProperty(expected as any, key)) {
|
||||
if (!ts.hasProperty(actual as any, key)) {
|
||||
fail(`${msgPrefix}Missing property '${key}'`);
|
||||
|
||||
for (const key in expected) {
|
||||
if (ts.hasProperty(expected as any, key)) {
|
||||
if (!ts.hasProperty(actual as any, key)) {
|
||||
fail(`${msgPrefix}Missing property '${key}'`);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (fullActual === undefined || fullExpected === undefined) {
|
||||
if (fullActual === fullExpected) {
|
||||
return;
|
||||
@@ -1148,15 +1146,17 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
public verifyQuickInfos(namesAndTexts: { [name: string]: string | [string, string] }) {
|
||||
for (const name in namesAndTexts) if (ts.hasProperty(namesAndTexts, name)) {
|
||||
const text = namesAndTexts[name];
|
||||
if (ts.isArray(text)) {
|
||||
assert(text.length === 2);
|
||||
const [expectedText, expectedDocumentation] = text;
|
||||
this.verifyQuickInfoAt(name, expectedText, expectedDocumentation);
|
||||
}
|
||||
else {
|
||||
this.verifyQuickInfoAt(name, text);
|
||||
for (const name in namesAndTexts) {
|
||||
if (ts.hasProperty(namesAndTexts, name)) {
|
||||
const text = namesAndTexts[name];
|
||||
if (ts.isArray(text)) {
|
||||
assert(text.length === 2);
|
||||
const [expectedText, expectedDocumentation] = text;
|
||||
this.verifyQuickInfoAt(name, expectedText, expectedDocumentation);
|
||||
}
|
||||
else {
|
||||
this.verifyQuickInfoAt(name, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1165,7 +1165,6 @@ namespace FourSlash {
|
||||
if (expectedDocumentation === "") {
|
||||
throw new Error("Use 'undefined' instead");
|
||||
}
|
||||
|
||||
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
const actualQuickInfoText = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.displayParts) : "";
|
||||
const actualQuickInfoDocumentation = actualQuickInfo ? ts.displayPartsToString(actualQuickInfo.documentation) : "";
|
||||
@@ -1468,7 +1467,7 @@ namespace FourSlash {
|
||||
let baselineFile = this.testData.globalOptions[metadataOptionNames.baselineFile];
|
||||
if (!baselineFile) {
|
||||
baselineFile = this.activeFile.fileName.replace(this.basePath + "/breakpointValidation", "bpSpan");
|
||||
baselineFile = baselineFile.replace(".ts", ".baseline");
|
||||
baselineFile = baselineFile.replace(ts.Extension.Ts, ".baseline");
|
||||
|
||||
}
|
||||
Harness.Baseline.runBaseline(
|
||||
@@ -1538,7 +1537,7 @@ namespace FourSlash {
|
||||
public baselineQuickInfo() {
|
||||
let baselineFile = this.testData.globalOptions[metadataOptionNames.baselineFile];
|
||||
if (!baselineFile) {
|
||||
baselineFile = ts.getBaseFileName(this.activeFile.fileName).replace(".ts", ".baseline");
|
||||
baselineFile = ts.getBaseFileName(this.activeFile.fileName).replace(ts.Extension.Ts, ".baseline");
|
||||
}
|
||||
|
||||
Harness.Baseline.runBaseline(
|
||||
@@ -1611,16 +1610,19 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
private printMembersOrCompletions(info: ts.CompletionInfo) {
|
||||
if (info === undefined) { return "No completion info."; }
|
||||
const { entries } = info;
|
||||
|
||||
function pad(s: string, length: number) {
|
||||
return s + new Array(length - s.length + 1).join(" ");
|
||||
}
|
||||
function max<T>(arr: T[], selector: (x: T) => number): number {
|
||||
return arr.reduce((prev, x) => Math.max(prev, selector(x)), 0);
|
||||
}
|
||||
const longestNameLength = max(info.entries, m => m.name.length);
|
||||
const longestKindLength = max(info.entries, m => m.kind.length);
|
||||
info.entries.sort((m, n) => m.sortText > n.sortText ? 1 : m.sortText < n.sortText ? -1 : m.name > n.name ? 1 : m.name < n.name ? -1 : 0);
|
||||
const membersString = info.entries.map(m => `${pad(m.name, longestNameLength)} ${pad(m.kind, longestKindLength)} ${m.kindModifiers}`).join("\n");
|
||||
const longestNameLength = max(entries, m => m.name.length);
|
||||
const longestKindLength = max(entries, m => m.kind.length);
|
||||
entries.sort((m, n) => m.sortText > n.sortText ? 1 : m.sortText < n.sortText ? -1 : m.name > n.name ? 1 : m.name < n.name ? -1 : 0);
|
||||
const membersString = entries.map(m => `${pad(m.name, longestNameLength)} ${pad(m.kind, longestKindLength)} ${m.kindModifiers}`).join("\n");
|
||||
Harness.IO.log(membersString);
|
||||
}
|
||||
|
||||
@@ -2172,7 +2174,7 @@ namespace FourSlash {
|
||||
Harness.IO.log(this.spanInfoToString(this.getNameOrDottedNameSpan(pos), "**"));
|
||||
}
|
||||
|
||||
private verifyClassifications(expected: { classificationType: string; text: string; textSpan?: TextSpan }[], actual: ts.ClassifiedSpan[]) {
|
||||
private verifyClassifications(expected: { classificationType: string; text: string; textSpan?: TextSpan }[], actual: ts.ClassifiedSpan[], sourceFileText: string) {
|
||||
if (actual.length !== expected.length) {
|
||||
this.raiseError("verifyClassifications failed - expected total classifications to be " + expected.length +
|
||||
", but was " + actual.length +
|
||||
@@ -2212,9 +2214,11 @@ namespace FourSlash {
|
||||
});
|
||||
|
||||
function jsonMismatchString() {
|
||||
const showActual = actual.map(({ classificationType, textSpan }) =>
|
||||
({ classificationType, text: sourceFileText.slice(textSpan.start, textSpan.start + textSpan.length) }));
|
||||
return Harness.IO.newLine() +
|
||||
"expected: '" + Harness.IO.newLine() + stringify(expected) + "'" + Harness.IO.newLine() +
|
||||
"actual: '" + Harness.IO.newLine() + stringify(actual) + "'";
|
||||
"actual: '" + Harness.IO.newLine() + stringify(showActual) + "'";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2237,14 +2241,14 @@ namespace FourSlash {
|
||||
const actual = this.languageService.getSemanticClassifications(this.activeFile.fileName,
|
||||
ts.createTextSpan(0, this.activeFile.content.length));
|
||||
|
||||
this.verifyClassifications(expected, actual);
|
||||
this.verifyClassifications(expected, actual, this.activeFile.content);
|
||||
}
|
||||
|
||||
public verifySyntacticClassifications(expected: { classificationType: string; text: string }[]) {
|
||||
const actual = this.languageService.getSyntacticClassifications(this.activeFile.fileName,
|
||||
ts.createTextSpan(0, this.activeFile.content.length));
|
||||
|
||||
this.verifyClassifications(expected, actual);
|
||||
this.verifyClassifications(expected, actual, this.activeFile.content);
|
||||
}
|
||||
|
||||
public verifyOutliningSpans(spans: TextSpan[]) {
|
||||
@@ -2279,23 +2283,22 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares expected text to the text that would be in the sole range
|
||||
* (ie: [|...|]) in the file after applying the codefix sole codefix
|
||||
* in the source file.
|
||||
*
|
||||
* Because codefixes are only applied on the working file, it is unsafe
|
||||
* to apply this more than once (consider a refactoring across files).
|
||||
* Finds and applies a code action corresponding to the supplied parameters.
|
||||
* If index is undefined, applies the unique code action available.
|
||||
* @param errorCode The error code that generated the code action.
|
||||
* @param index The nth (0-index-based) codeaction available generated by errorCode.
|
||||
*/
|
||||
public verifyRangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number) {
|
||||
public getAndApplyCodeActions(errorCode?: number, index?: number) {
|
||||
const fileName = this.activeFile.fileName;
|
||||
this.applyCodeActions(this.getCodeFixActions(fileName, errorCode), index);
|
||||
}
|
||||
|
||||
public verifyRangeIs(expectedText: string, includeWhiteSpace?: boolean) {
|
||||
const ranges = this.getRanges();
|
||||
if (ranges.length !== 1) {
|
||||
this.raiseError("Exactly one range should be specified in the testfile.");
|
||||
}
|
||||
|
||||
const fileName = this.activeFile.fileName;
|
||||
|
||||
this.applyCodeAction(fileName, this.getCodeFixActions(fileName, errorCode), index);
|
||||
|
||||
const actualText = this.rangeText(ranges[0]);
|
||||
|
||||
const result = includeWhiteSpace
|
||||
@@ -2307,6 +2310,16 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares expected text to the text that would be in the sole range
|
||||
* (ie: [|...|]) in the file after applying the codefix sole codefix
|
||||
* in the source file.
|
||||
*/
|
||||
public verifyRangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number) {
|
||||
this.getAndApplyCodeActions(errorCode, index);
|
||||
this.verifyRangeIs(expectedText, includeWhiteSpace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies fixes for the errors in fileName and compares the results to
|
||||
* expectedContents after all fixes have been applied.
|
||||
@@ -2319,7 +2332,7 @@ namespace FourSlash {
|
||||
public verifyFileAfterCodeFix(expectedContents: string, fileName?: string) {
|
||||
fileName = fileName ? fileName : this.activeFile.fileName;
|
||||
|
||||
this.applyCodeAction(fileName, this.getCodeFixActions(fileName));
|
||||
this.applyCodeActions(this.getCodeFixActions(fileName));
|
||||
|
||||
const actualContents: string = this.getFileContent(fileName);
|
||||
if (this.removeWhitespace(actualContents) !== this.removeWhitespace(expectedContents)) {
|
||||
@@ -2357,11 +2370,10 @@ namespace FourSlash {
|
||||
return actions;
|
||||
}
|
||||
|
||||
private applyCodeAction(fileName: string, actions: ts.CodeAction[], index?: number): void {
|
||||
private applyCodeActions(actions: ts.CodeAction[], index?: number): void {
|
||||
if (index === undefined) {
|
||||
if (!(actions && actions.length === 1)) {
|
||||
const actionText = (actions && actions.length) ? JSON.stringify(actions) : "none";
|
||||
this.raiseError(`Should find exactly one codefix, but found ${actionText}`);
|
||||
this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found.`);
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
@@ -2371,12 +2383,11 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
const fileChanges = ts.find(actions[index].changes, change => change.fileName === fileName);
|
||||
if (!fileChanges) {
|
||||
this.raiseError("The CodeFix found doesn't provide any changes in this file.");
|
||||
}
|
||||
const changes = actions[index].changes;
|
||||
|
||||
this.applyEdits(fileChanges.fileName, fileChanges.textChanges, /*isFormattingEdit*/ false);
|
||||
for (const change of changes) {
|
||||
this.applyEdits(change.fileName, change.textChanges, /*isFormattingEdit*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
public verifyImportFixAtPosition(expectedTextArray: string[], errorCode?: number) {
|
||||
@@ -2388,7 +2399,10 @@ namespace FourSlash {
|
||||
const codeFixes = this.getCodeFixActions(this.activeFile.fileName, errorCode);
|
||||
|
||||
if (!codeFixes || codeFixes.length === 0) {
|
||||
this.raiseError("No codefixes returned.");
|
||||
if (expectedTextArray.length !== 0) {
|
||||
this.raiseError("No codefixes returned.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const actualTextArray: string[] = [];
|
||||
@@ -2665,6 +2679,13 @@ namespace FourSlash {
|
||||
this.rangesByText().forEach(ranges => this.verifyRangesAreDocumentHighlights(ranges));
|
||||
}
|
||||
|
||||
public verifyDocumentHighlightsOf(startRange: Range, ranges: Range[]) {
|
||||
ts.Debug.assert(ts.contains(ranges, startRange));
|
||||
const fileNames = unique(ranges, range => range.fileName);
|
||||
this.goToRangeStart(startRange);
|
||||
this.verifyDocumentHighlights(ranges, fileNames);
|
||||
}
|
||||
|
||||
public verifyRangesAreDocumentHighlights(ranges?: Range[]) {
|
||||
ranges = ranges || this.getRanges();
|
||||
const fileNames = unique(ranges, range => range.fileName);
|
||||
@@ -2747,6 +2768,7 @@ namespace FourSlash {
|
||||
markerName: string,
|
||||
expectedContent: string,
|
||||
refactorNameToApply: string,
|
||||
actionName: string,
|
||||
formattingOptions?: ts.FormatCodeSettings) {
|
||||
|
||||
formattingOptions = formattingOptions || this.formatCodeSettings;
|
||||
@@ -2759,9 +2781,11 @@ namespace FourSlash {
|
||||
this.raiseError(`The expected refactor: ${refactorNameToApply} is not available at the marker location.`);
|
||||
}
|
||||
|
||||
const codeActions = this.languageService.getRefactorCodeActions(this.activeFile.fileName, formattingOptions, markerPos, refactorNameToApply);
|
||||
const editInfo = this.languageService.getEditsForRefactor(this.activeFile.fileName, formattingOptions, markerPos, refactorNameToApply, actionName);
|
||||
|
||||
this.applyCodeAction(this.activeFile.fileName, codeActions);
|
||||
for (const edit of editInfo.edits) {
|
||||
this.applyEdits(edit.fileName, edit.textChanges);
|
||||
}
|
||||
const actualContent = this.getFileContent(this.activeFile.fileName);
|
||||
|
||||
if (this.normalizeNewlines(actualContent) !== this.normalizeNewlines(expectedContent)) {
|
||||
@@ -3804,8 +3828,16 @@ namespace FourSlashInterface {
|
||||
this.state.verifyRangeAfterCodeFix(expectedText, includeWhiteSpace, errorCode, index);
|
||||
}
|
||||
|
||||
public fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, formattingOptions?: ts.FormatCodeSettings): void {
|
||||
this.state.verifyFileAfterApplyingRefactorAtMarker(markerName, expectedContent, refactorNameToApply, formattingOptions);
|
||||
public fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, actionName: string, formattingOptions?: ts.FormatCodeSettings): void {
|
||||
this.state.verifyFileAfterApplyingRefactorAtMarker(markerName, expectedContent, refactorNameToApply, actionName, formattingOptions);
|
||||
}
|
||||
|
||||
public rangeIs(expectedText: string, includeWhiteSpace?: boolean): void {
|
||||
this.state.verifyRangeIs(expectedText, includeWhiteSpace);
|
||||
}
|
||||
|
||||
public getAndApplyCodeFix(errorCode?: number, index?: number): void {
|
||||
this.state.getAndApplyCodeActions(errorCode, index);
|
||||
}
|
||||
|
||||
public importFixAtPosition(expectedTextArray: string[], errorCode?: number): void {
|
||||
@@ -3868,6 +3900,10 @@ namespace FourSlashInterface {
|
||||
this.state.verifyRangesWithSameTextAreDocumentHighlights();
|
||||
}
|
||||
|
||||
public documentHighlightsOf(startRange: FourSlash.Range, ranges: FourSlash.Range[]) {
|
||||
this.state.verifyDocumentHighlightsOf(startRange, ranges);
|
||||
}
|
||||
|
||||
public completionEntryDetailIs(entryName: string, text: string, documentation?: string, kind?: string, tags?: ts.JSDocTagInfo[]) {
|
||||
this.state.verifyCompletionEntryDetails(entryName, text, documentation, kind, tags);
|
||||
}
|
||||
|
||||
+13
-11
@@ -259,8 +259,9 @@ namespace Utils {
|
||||
return true;
|
||||
}
|
||||
else if ((f & v) > 0) {
|
||||
if (result.length)
|
||||
if (result.length) {
|
||||
result += " | ";
|
||||
}
|
||||
result += flags[v];
|
||||
return false;
|
||||
}
|
||||
@@ -857,6 +858,7 @@ namespace Harness {
|
||||
|
||||
export function getDefaultLibFileName(options: ts.CompilerOptions): string {
|
||||
switch (options.target) {
|
||||
case ts.ScriptTarget.ESNext:
|
||||
case ts.ScriptTarget.ES2017:
|
||||
return "lib.es2017.d.ts";
|
||||
case ts.ScriptTarget.ES2016:
|
||||
@@ -1051,7 +1053,7 @@ namespace Harness {
|
||||
];
|
||||
|
||||
let optionsIndex: ts.Map<ts.CommandLineOption>;
|
||||
function getCommandLineOption(name: string): ts.CommandLineOption {
|
||||
function getCommandLineOption(name: string): ts.CommandLineOption | undefined {
|
||||
if (!optionsIndex) {
|
||||
optionsIndex = ts.createMap<ts.CommandLineOption>();
|
||||
const optionDeclarations = harnessOptionDeclarations.concat(ts.optionDeclarations);
|
||||
@@ -1247,7 +1249,7 @@ namespace Harness {
|
||||
sourceFileName = outFile;
|
||||
}
|
||||
|
||||
const dTsFileName = ts.removeFileExtension(sourceFileName) + ".d.ts";
|
||||
const dTsFileName = ts.removeFileExtension(sourceFileName) + ts.Extension.Dts;
|
||||
|
||||
return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined);
|
||||
}
|
||||
@@ -1463,7 +1465,7 @@ namespace Harness {
|
||||
// When calling this function from rwc-runner, the baselinePath will have no extension.
|
||||
// As rwc test- file is stored in json which ".json" will get stripped off.
|
||||
// When calling this function from compiler-runner, the baselinePath will then has either ".ts" or ".tsx" extension
|
||||
const outputFileName = ts.endsWith(baselinePath, ".ts") || ts.endsWith(baselinePath, ".tsx") ?
|
||||
const outputFileName = ts.endsWith(baselinePath, ts.Extension.Ts) || ts.endsWith(baselinePath, ts.Extension.Tsx) ?
|
||||
baselinePath.replace(/\.tsx?/, fullExtension) : baselinePath.concat(fullExtension);
|
||||
Harness.Baseline.runBaseline(outputFileName, () => fullBaseLine, opts);
|
||||
}
|
||||
@@ -1561,7 +1563,7 @@ namespace Harness {
|
||||
}
|
||||
|
||||
// check js output
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ".js"), () => {
|
||||
Harness.Baseline.runBaseline(baselinePath.replace(/\.tsx?/, ts.Extension.Js), () => {
|
||||
let tsCode = "";
|
||||
const tsSources = otherFiles.concat(toBeCompiled);
|
||||
if (tsSources.length > 1) {
|
||||
@@ -1649,22 +1651,22 @@ namespace Harness {
|
||||
}
|
||||
|
||||
export function isTS(fileName: string) {
|
||||
return ts.endsWith(fileName, ".ts");
|
||||
return ts.endsWith(fileName, ts.Extension.Ts);
|
||||
}
|
||||
|
||||
export function isTSX(fileName: string) {
|
||||
return ts.endsWith(fileName, ".tsx");
|
||||
return ts.endsWith(fileName, ts.Extension.Tsx);
|
||||
}
|
||||
|
||||
export function isDTS(fileName: string) {
|
||||
return ts.endsWith(fileName, ".d.ts");
|
||||
return ts.endsWith(fileName, ts.Extension.Dts);
|
||||
}
|
||||
|
||||
export function isJS(fileName: string) {
|
||||
return ts.endsWith(fileName, ".js");
|
||||
return ts.endsWith(fileName, ts.Extension.Js);
|
||||
}
|
||||
export function isJSX(fileName: string) {
|
||||
return ts.endsWith(fileName, ".jsx");
|
||||
return ts.endsWith(fileName, ts.Extension.Jsx);
|
||||
}
|
||||
|
||||
export function isJSMap(fileName: string) {
|
||||
@@ -1971,7 +1973,7 @@ namespace Harness {
|
||||
export function isDefaultLibraryFile(filePath: string): boolean {
|
||||
// We need to make sure that the filePath is prefixed with "lib." not just containing "lib." and end with ".d.ts"
|
||||
const fileName = ts.getBaseFileName(ts.normalizeSlashes(filePath));
|
||||
return ts.startsWith(fileName, "lib.") && ts.endsWith(fileName, ".d.ts");
|
||||
return ts.startsWith(fileName, "lib.") && ts.endsWith(fileName, ts.Extension.Dts);
|
||||
}
|
||||
|
||||
export function isBuiltFile(filePath: string): boolean {
|
||||
|
||||
@@ -492,7 +492,7 @@ namespace Harness.LanguageService {
|
||||
getCodeFixDiagnostics(): ts.Diagnostic[] {
|
||||
throw new Error("Not supported on the shim.");
|
||||
}
|
||||
getRefactorCodeActions(): ts.CodeAction[] {
|
||||
getEditsForRefactor(): ts.RefactorEditInfo {
|
||||
throw new Error("Not supported on the shim.");
|
||||
}
|
||||
getApplicableRefactors(): ts.ApplicableRefactorInfo[] {
|
||||
@@ -731,7 +731,7 @@ namespace Harness.LanguageService {
|
||||
}
|
||||
|
||||
createHash(s: string) {
|
||||
return s;
|
||||
return mockHash(s);
|
||||
}
|
||||
|
||||
require(_initialDir: string, _moduleName: string): ts.server.RequireResult {
|
||||
@@ -856,4 +856,8 @@ namespace Harness.LanguageService {
|
||||
getClassifier(): ts.Classifier { throw new Error("getClassifier is not available using the server interface."); }
|
||||
getPreProcessedFileInfo(): ts.PreProcessedFileInfo { throw new Error("getPreProcessedFileInfo is not available using the server interface."); }
|
||||
}
|
||||
|
||||
export function mockHash(s: string): string {
|
||||
return `hash-${s}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,14 +232,11 @@ namespace Playback {
|
||||
// different entry).
|
||||
// TODO (yuisu): We can certainly remove these once we recapture the RWC using new API
|
||||
const normalizedPath = ts.normalizePath(path).toLowerCase();
|
||||
const result: string[] = [];
|
||||
for (const directory of replayLog.directoriesRead) {
|
||||
return ts.flatMap(replayLog.directoriesRead, directory => {
|
||||
if (ts.normalizeSlashes(directory.path).toLowerCase() === normalizedPath) {
|
||||
result.push(...directory.result);
|
||||
return directory.result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
});
|
||||
|
||||
wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)(
|
||||
|
||||
@@ -325,8 +325,8 @@ class ProjectRunner extends RunnerBase {
|
||||
// we need to instead create files that can live in the project reference folder
|
||||
// but make sure extension of these files matches with the fileName the compiler asked to write
|
||||
diskRelativeName = "diskFile" + nonSubfolderDiskFiles +
|
||||
(Harness.Compiler.isDTS(fileName) ? ".d.ts" :
|
||||
Harness.Compiler.isJS(fileName) ? ".js" : ".js.map");
|
||||
(Harness.Compiler.isDTS(fileName) ? ts.Extension.Dts :
|
||||
Harness.Compiler.isJS(fileName) ? ts.Extension.Js : ".js.map");
|
||||
nonSubfolderDiskFiles++;
|
||||
}
|
||||
|
||||
@@ -386,14 +386,14 @@ class ProjectRunner extends RunnerBase {
|
||||
emitOutputFilePathWithoutExtension = ts.removeFileExtension(sourceFile.fileName);
|
||||
}
|
||||
|
||||
const outputDtsFileName = emitOutputFilePathWithoutExtension + ".d.ts";
|
||||
const outputDtsFileName = emitOutputFilePathWithoutExtension + ts.Extension.Dts;
|
||||
const file = findOutputDtsFile(outputDtsFileName);
|
||||
if (file) {
|
||||
allInputFiles.unshift(file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out) + ".d.ts";
|
||||
const outputDtsFileName = ts.removeFileExtension(compilerOptions.outFile || compilerOptions.out) + ts.Extension.Dts;
|
||||
const outputDtsFile = findOutputDtsFile(outputDtsFileName);
|
||||
if (!ts.contains(allInputFiles, outputDtsFile)) {
|
||||
allInputFiles.unshift(outputDtsFile);
|
||||
|
||||
@@ -222,6 +222,10 @@ if (taskConfigsFolder) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ts.Debug.isDebugging) {
|
||||
ts.Debug.enableDebugInfo();
|
||||
}
|
||||
|
||||
runTests(runners);
|
||||
}
|
||||
if (!runUnitTests) {
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace ts {
|
||||
clearTimeout,
|
||||
setImmediate: typeof setImmediate !== "undefined" ? setImmediate : action => setTimeout(action, 0),
|
||||
clearImmediate: typeof clearImmediate !== "undefined" ? clearImmediate : clearTimeout,
|
||||
createHash: s => s
|
||||
createHash: Harness.LanguageService.mockHash,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace ts {
|
||||
start: undefined,
|
||||
length: undefined,
|
||||
}, {
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'.",
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'esnext'.",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
|
||||
@@ -513,7 +513,7 @@ namespace ts.projectSystem {
|
||||
const lines = ["var x = 1;", "var y = 2;"];
|
||||
const path = "/a/app";
|
||||
const f = {
|
||||
path: path + ".ts",
|
||||
path: path + ts.Extension.Ts,
|
||||
content: lines.join(newLine)
|
||||
};
|
||||
const host = createServerHost([f], { newLine });
|
||||
@@ -530,7 +530,7 @@ namespace ts.projectSystem {
|
||||
command: "compileOnSaveEmitFile",
|
||||
arguments: { file: f.path }
|
||||
});
|
||||
const emitOutput = host.readFile(path + ".js");
|
||||
const emitOutput = host.readFile(path + ts.Extension.Js);
|
||||
assert.equal(emitOutput, f.content + newLine, "content of emit output should be identical with the input + newline");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace ts {
|
||||
file: undefined,
|
||||
start: 0,
|
||||
length: 0,
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'.",
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015', 'esnext'.",
|
||||
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
|
||||
}]
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace ts {
|
||||
if (!expected === !actual) {
|
||||
if (expected) {
|
||||
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
|
||||
assert.isTrue(expected.extension === actual.extension, `'ext': expected '${Extension[expected.extension]}' to be equal to '${Extension[actual.extension]}'`);
|
||||
assert.isTrue(expected.extension === actual.extension, `'ext': expected '${expected.extension}' to be equal to '${actual.extension}'`);
|
||||
assert.isTrue(expected.isExternalLibraryImport === actual.isExternalLibraryImport, `'isExternalLibraryImport': expected '${expected.isExternalLibraryImport}' to be equal to '${actual.isExternalLibraryImport}'`);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -81,63 +81,136 @@ namespace ts {
|
||||
|
||||
describe("printNode", () => {
|
||||
const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly");
|
||||
let sourceFile: SourceFile;
|
||||
before(() => sourceFile = createSourceFile("source.ts", "", ScriptTarget.ES2015));
|
||||
// tslint:disable boolean-trivia
|
||||
const syntheticNode = createClassDeclaration(
|
||||
undefined,
|
||||
undefined,
|
||||
/*name*/ createIdentifier("C"),
|
||||
undefined,
|
||||
undefined,
|
||||
createNodeArray([
|
||||
createProperty(
|
||||
undefined,
|
||||
printsCorrectly("class", {}, printer => printer.printNode(
|
||||
EmitHint.Unspecified,
|
||||
createClassDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*name*/ createIdentifier("C"),
|
||||
/*typeParameters*/ undefined,
|
||||
/*heritageClauses*/ undefined,
|
||||
[createProperty(
|
||||
/*decorators*/ undefined,
|
||||
createNodeArray([createToken(SyntaxKind.PublicKeyword)]),
|
||||
createIdentifier("prop"),
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
])
|
||||
);
|
||||
/*questionToken*/ undefined,
|
||||
/*type*/ undefined,
|
||||
/*initializer*/ undefined
|
||||
)]
|
||||
),
|
||||
createSourceFile("source.ts", "", ScriptTarget.ES2015)
|
||||
));
|
||||
|
||||
printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode(
|
||||
EmitHint.Unspecified,
|
||||
createNamespaceExportDeclaration("B"),
|
||||
createSourceFile("source.ts", "", ScriptTarget.ES2015)
|
||||
));
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/15971
|
||||
const classWithOptionalMethodAndProperty = createClassDeclaration(
|
||||
undefined,
|
||||
/* modifiers */ createNodeArray([createToken(SyntaxKind.DeclareKeyword)]),
|
||||
/* name */ createIdentifier("X"),
|
||||
undefined,
|
||||
undefined,
|
||||
createNodeArray([
|
||||
createMethod(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
/* name */ createIdentifier("method"),
|
||||
/* questionToken */ createToken(SyntaxKind.QuestionToken),
|
||||
undefined,
|
||||
undefined,
|
||||
/* type */ createKeywordTypeNode(SyntaxKind.VoidKeyword),
|
||||
undefined
|
||||
printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode(
|
||||
EmitHint.Unspecified,
|
||||
createClassDeclaration(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ [createToken(SyntaxKind.DeclareKeyword)],
|
||||
/*name*/ createIdentifier("X"),
|
||||
/*typeParameters*/ undefined,
|
||||
/*heritageClauses*/ undefined,
|
||||
[
|
||||
createMethod(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
/*name*/ createIdentifier("method"),
|
||||
/*questionToken*/ createToken(SyntaxKind.QuestionToken),
|
||||
/*typeParameters*/ undefined,
|
||||
[],
|
||||
/*type*/ createKeywordTypeNode(SyntaxKind.VoidKeyword),
|
||||
/*body*/ undefined
|
||||
),
|
||||
createProperty(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*name*/ createIdentifier("property"),
|
||||
/*questionToken*/ createToken(SyntaxKind.QuestionToken),
|
||||
/*type*/ createKeywordTypeNode(SyntaxKind.StringKeyword),
|
||||
/*initializer*/ undefined
|
||||
),
|
||||
]
|
||||
),
|
||||
createSourceFile("source.ts", "", ScriptTarget.ES2015)
|
||||
));
|
||||
|
||||
// https://github.com/Microsoft/TypeScript/issues/15651
|
||||
printsCorrectly("functionTypes", {}, printer => printer.printNode(
|
||||
EmitHint.Unspecified,
|
||||
createTupleTypeNode([
|
||||
createFunctionTypeNode(
|
||||
/*typeArguments*/ undefined,
|
||||
[createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
createIdentifier("args")
|
||||
)],
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword)
|
||||
),
|
||||
createProperty(
|
||||
undefined,
|
||||
undefined,
|
||||
/* name */ createIdentifier("property"),
|
||||
/* questionToken */ createToken(SyntaxKind.QuestionToken),
|
||||
/* type */ createKeywordTypeNode(SyntaxKind.StringKeyword),
|
||||
undefined
|
||||
createFunctionTypeNode(
|
||||
[createTypeParameterDeclaration("T")],
|
||||
[createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
createIdentifier("args")
|
||||
)],
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword)
|
||||
),
|
||||
])
|
||||
);
|
||||
|
||||
// tslint:enable boolean-trivia
|
||||
printsCorrectly("class", {}, printer => printer.printNode(EmitHint.Unspecified, syntheticNode, sourceFile));
|
||||
|
||||
printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode(EmitHint.Unspecified, createNamespaceExportDeclaration("B"), sourceFile));
|
||||
|
||||
printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode(EmitHint.Unspecified, classWithOptionalMethodAndProperty, sourceFile));
|
||||
createFunctionTypeNode(
|
||||
/*typeArguments*/ undefined,
|
||||
[createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
createToken(SyntaxKind.DotDotDotToken),
|
||||
createIdentifier("args")
|
||||
)],
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword)
|
||||
),
|
||||
createFunctionTypeNode(
|
||||
/*typeArguments*/ undefined,
|
||||
[createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
createIdentifier("args"),
|
||||
createToken(SyntaxKind.QuestionToken)
|
||||
)],
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword)
|
||||
),
|
||||
createFunctionTypeNode(
|
||||
/*typeArguments*/ undefined,
|
||||
[createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
createIdentifier("args"),
|
||||
/*questionToken*/ undefined,
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword)
|
||||
)],
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword)
|
||||
),
|
||||
createFunctionTypeNode(
|
||||
/*typeArguments*/ undefined,
|
||||
[createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
createObjectBindingPattern([])
|
||||
)],
|
||||
createKeywordTypeNode(SyntaxKind.AnyKeyword)
|
||||
),
|
||||
]),
|
||||
createSourceFile("source.ts", "", ScriptTarget.ES2015)
|
||||
));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ts.server {
|
||||
clearTimeout: noop,
|
||||
setImmediate: () => 0,
|
||||
clearImmediate: noop,
|
||||
createHash: s => s
|
||||
createHash: Harness.LanguageService.mockHash,
|
||||
};
|
||||
|
||||
const mockLogger: Logger = {
|
||||
@@ -240,8 +240,8 @@ namespace ts.server {
|
||||
CommandNames.GetCodeFixesFull,
|
||||
CommandNames.GetSupportedCodeFixes,
|
||||
CommandNames.GetApplicableRefactors,
|
||||
CommandNames.GetRefactorCodeActions,
|
||||
CommandNames.GetRefactorCodeActionsFull,
|
||||
CommandNames.GetEditsForRefactor,
|
||||
CommandNames.GetEditsForRefactorFull,
|
||||
];
|
||||
|
||||
it("should not throw when commands are executed with invalid arguments", () => {
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace ts.projectSystem {
|
||||
et.service.openClientFile(file.path);
|
||||
assert.equal(et.getEvents().length, 0);
|
||||
});
|
||||
|
||||
it("only sends an event once", () => {
|
||||
const file = makeFile("/a.ts");
|
||||
const tsconfig = makeFile("/tsconfig.json", {});
|
||||
@@ -46,12 +47,13 @@ namespace ts.projectSystem {
|
||||
const et = new EventTracker([file1]);
|
||||
const compilerOptions: ts.CompilerOptions = { strict: true };
|
||||
|
||||
const projectFileName = "foo.csproj";
|
||||
const projectFileName = "/hunter2/foo.csproj";
|
||||
|
||||
open();
|
||||
|
||||
// TODO: Apparently compilerOptions is mutated, so have to repeat it here!
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
projectId: Harness.LanguageService.mockHash("/hunter2/foo.csproj"),
|
||||
compilerOptions: { strict: true },
|
||||
compileOnSave: true,
|
||||
// These properties can't be present for an external project, so they are undefined instead of false.
|
||||
@@ -195,6 +197,7 @@ namespace ts.projectSystem {
|
||||
const et = new EventTracker([jsconfig, file]);
|
||||
et.service.openClientFile(file.path);
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
projectId: Harness.LanguageService.mockHash("/jsconfig.json"),
|
||||
fileStats: fileStats({ js: 1 }),
|
||||
compilerOptions: autoJsCompilerOptions,
|
||||
typeAcquisition: {
|
||||
@@ -214,6 +217,7 @@ namespace ts.projectSystem {
|
||||
et.service.openClientFile(file.path);
|
||||
et.getEvent<server.ProjectLanguageServiceStateEvent>(server.ProjectLanguageServiceStateEvent, /*mayBeMore*/ true);
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
projectId: Harness.LanguageService.mockHash("/jsconfig.json"),
|
||||
fileStats: fileStats({ js: 1 }),
|
||||
compilerOptions: autoJsCompilerOptions,
|
||||
configFileName: "jsconfig.json",
|
||||
@@ -248,39 +252,37 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
assertProjectInfoTelemetryEvent(partial: Partial<server.ProjectInfoTelemetryEventData>): void {
|
||||
assert.deepEqual(this.getEvent<server.ProjectInfoTelemetryEvent>(ts.server.ProjectInfoTelemetryEvent), makePayload(partial));
|
||||
assert.deepEqual(this.getEvent<server.ProjectInfoTelemetryEvent>(ts.server.ProjectInfoTelemetryEvent), {
|
||||
projectId: Harness.LanguageService.mockHash("/tsconfig.json"),
|
||||
fileStats: fileStats({ ts: 1 }),
|
||||
compilerOptions: {},
|
||||
extends: false,
|
||||
files: false,
|
||||
include: false,
|
||||
exclude: false,
|
||||
compileOnSave: false,
|
||||
typeAcquisition: {
|
||||
enable: false,
|
||||
exclude: false,
|
||||
include: false,
|
||||
},
|
||||
configFileName: "tsconfig.json",
|
||||
projectType: "configured",
|
||||
languageServiceEnabled: true,
|
||||
version: ts.version,
|
||||
...partial,
|
||||
});
|
||||
}
|
||||
|
||||
getEvent<T extends server.ProjectServiceEvent>(eventName: T["eventName"], mayBeMore = false): T["data"] {
|
||||
if (mayBeMore) assert(this.events.length !== 0); else assert.equal(this.events.length, 1);
|
||||
if (mayBeMore) { assert(this.events.length !== 0); }
|
||||
else { assert.equal(this.events.length, 1); }
|
||||
const event = this.events.shift();
|
||||
assert.equal(event.eventName, eventName);
|
||||
return event.data;
|
||||
}
|
||||
}
|
||||
|
||||
function makePayload(partial: Partial<server.ProjectInfoTelemetryEventData>): server.ProjectInfoTelemetryEventData {
|
||||
return {
|
||||
fileStats: fileStats({ ts: 1 }),
|
||||
compilerOptions: {},
|
||||
extends: false,
|
||||
files: false,
|
||||
include: false,
|
||||
exclude: false,
|
||||
compileOnSave: false,
|
||||
typeAcquisition: {
|
||||
enable: false,
|
||||
exclude: false,
|
||||
include: false,
|
||||
},
|
||||
configFileName: "tsconfig.json",
|
||||
projectType: "configured",
|
||||
languageServiceEnabled: true,
|
||||
version: ts.version,
|
||||
...partial
|
||||
};
|
||||
}
|
||||
|
||||
function makeFile(path: string, content: {} = ""): projectSystem.FileOrFolder {
|
||||
return { path, content: typeof content === "string" ? "" : JSON.stringify(content) };
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace ts {
|
||||
|
||||
transpileOptions.reportDiagnostics = true;
|
||||
|
||||
justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? ".tsx" : ".ts");
|
||||
justName = "transpile/" + name.replace(/[^a-z0-9\-. ]/ig, "") + (transpileOptions.compilerOptions.jsx ? Extension.Tsx : Extension.Ts);
|
||||
toBeCompiled = [{
|
||||
unitName: transpileOptions.fileName,
|
||||
content: input
|
||||
@@ -88,7 +88,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
it("Correct output for " + justName, () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ".js"), () => {
|
||||
Harness.Baseline.runBaseline(justName.replace(/\.tsx?$/, ts.Extension.Js), () => {
|
||||
if (transpileResult.outputText) {
|
||||
return transpileResult.outputText;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace ts.projectSystem {
|
||||
express: "express",
|
||||
jquery: "jquery",
|
||||
lodash: "lodash",
|
||||
moment: "moment"
|
||||
moment: "moment",
|
||||
chroma: "chroma-js"
|
||||
})
|
||||
};
|
||||
|
||||
@@ -61,7 +62,6 @@ namespace ts.projectSystem {
|
||||
super(installTypingHost, globalTypingsCacheLocation, safeList.path, throttleLimit, log);
|
||||
}
|
||||
|
||||
safeFileList = safeList.path;
|
||||
protected postExecActions: PostExecAction[] = [];
|
||||
|
||||
executePendingCommands() {
|
||||
@@ -472,7 +472,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
createHash(s: string): string {
|
||||
return s;
|
||||
return Harness.LanguageService.mockHash(s);
|
||||
}
|
||||
|
||||
triggerDirectoryWatcherCallback(directoryName: string, fileName: string): void {
|
||||
|
||||
@@ -1009,6 +1009,26 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("discover typings", () => {
|
||||
it("should use mappings from safe list", () => {
|
||||
const app = {
|
||||
path: "/a/b/app.js",
|
||||
content: ""
|
||||
};
|
||||
const jquery = {
|
||||
path: "/a/b/jquery.js",
|
||||
content: ""
|
||||
};
|
||||
const chroma = {
|
||||
path: "/a/b/chroma.min.js",
|
||||
content: ""
|
||||
};
|
||||
const cache = createMap<string>();
|
||||
|
||||
const host = createServerHost([app, jquery, chroma]);
|
||||
const result = JsTyping.discoverTypings(host, [app.path, jquery.path, chroma.path], getDirectoryPath(<Path>app.path), /*safeListPath*/ undefined, cache, { enable: true }, []);
|
||||
assert.deepEqual(result.newTypingNames, ["jquery", "chroma-js"]);
|
||||
});
|
||||
|
||||
it("should return node for core modules", () => {
|
||||
const f = {
|
||||
path: "/a/b/app.js",
|
||||
@@ -1016,6 +1036,7 @@ namespace ts.projectSystem {
|
||||
};
|
||||
const host = createServerHost([f]);
|
||||
const cache = createMap<string>();
|
||||
|
||||
for (const name of JsTyping.nodeCoreModuleList) {
|
||||
const result = JsTyping.discoverTypings(host, [f.path], getDirectoryPath(<Path>f.path), /*safeListPath*/ undefined, cache, { enable: true }, [name, "somename"]);
|
||||
assert.deepEqual(result.newTypingNames.sort(), ["node", "somename"]);
|
||||
@@ -1040,7 +1061,7 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("telemetry events", () => {
|
||||
it ("should be received", () => {
|
||||
it("should be received", () => {
|
||||
const f1 = {
|
||||
path: "/a/app.js",
|
||||
content: ""
|
||||
@@ -1089,7 +1110,7 @@ namespace ts.projectSystem {
|
||||
});
|
||||
|
||||
describe("progress notifications", () => {
|
||||
it ("should be sent for success", () => {
|
||||
it("should be sent for success", () => {
|
||||
const f1 = {
|
||||
path: "/a/app.js",
|
||||
content: ""
|
||||
@@ -1140,7 +1161,7 @@ namespace ts.projectSystem {
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [f1.path, commander.path]);
|
||||
});
|
||||
|
||||
it ("should be sent for error", () => {
|
||||
it("should be sent for error", () => {
|
||||
const f1 = {
|
||||
path: "/a/app.js",
|
||||
content: ""
|
||||
|
||||
Vendored
+2
-1
@@ -3483,7 +3483,7 @@ interface DragEvent extends MouseEvent {
|
||||
|
||||
declare var DragEvent: {
|
||||
prototype: DragEvent;
|
||||
new(): DragEvent;
|
||||
new(type: "drag" | "dragend" | "dragenter" | "dragexit" | "dragleave" | "dragover" | "dragstart" | "drop", dragEventInit?: { dataTransfer?: DataTransfer }): DragEvent;
|
||||
};
|
||||
|
||||
interface DynamicsCompressorNode extends AudioNode {
|
||||
@@ -8224,6 +8224,7 @@ interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorConte
|
||||
readonly serviceWorker: ServiceWorkerContainer;
|
||||
readonly webdriver: boolean;
|
||||
readonly hardwareConcurrency: number;
|
||||
readonly languages: string[];
|
||||
getGamepads(): Gamepad[];
|
||||
javaEnabled(): boolean;
|
||||
msLaunchUri(uri: string, successCallback?: MSLaunchUriCallback, noHandlerCallback?: MSLaunchUriCallback): void;
|
||||
|
||||
Vendored
+146
-351
File diff suppressed because it is too large
Load Diff
+37
-8
@@ -719,20 +719,49 @@ namespace ts.server {
|
||||
return response.body;
|
||||
}
|
||||
|
||||
getRefactorCodeActions(
|
||||
getEditsForRefactor(
|
||||
fileName: string,
|
||||
_formatOptions: FormatCodeSettings,
|
||||
positionOrRange: number | TextRange,
|
||||
refactorName: string) {
|
||||
refactorName: string,
|
||||
actionName: string): RefactorEditInfo {
|
||||
|
||||
const args = this.createFileLocationOrRangeRequestArgs(positionOrRange, fileName) as protocol.GetRefactorCodeActionsRequestArgs;
|
||||
args.refactorName = refactorName;
|
||||
const args = this.createFileLocationOrRangeRequestArgs(positionOrRange, fileName) as protocol.GetEditsForRefactorRequestArgs;
|
||||
args.refactor = refactorName;
|
||||
args.action = actionName;
|
||||
|
||||
const request = this.processRequest<protocol.GetRefactorCodeActionsRequest>(CommandNames.GetRefactorCodeActions, args);
|
||||
const response = this.processResponse<protocol.GetRefactorCodeActionsResponse>(request);
|
||||
const codeActions = response.body.actions;
|
||||
const request = this.processRequest<protocol.GetEditsForRefactorRequest>(CommandNames.GetEditsForRefactor, args);
|
||||
const response = this.processResponse<protocol.GetEditsForRefactorResponse>(request);
|
||||
|
||||
return map(codeActions, codeAction => this.convertCodeActions(codeAction, fileName));
|
||||
if (!response.body) {
|
||||
return {
|
||||
edits: []
|
||||
};
|
||||
}
|
||||
|
||||
const edits: FileTextChanges[] = this.convertCodeEditsToTextChanges(response.body.edits);
|
||||
|
||||
const renameFilename: string | undefined = response.body.renameFilename;
|
||||
let renameLocation: number | undefined = undefined;
|
||||
if (renameFilename !== undefined) {
|
||||
renameLocation = this.lineOffsetToPosition(renameFilename, response.body.renameLocation);
|
||||
}
|
||||
|
||||
return {
|
||||
edits,
|
||||
renameFilename,
|
||||
renameLocation
|
||||
};
|
||||
}
|
||||
|
||||
private convertCodeEditsToTextChanges(edits: ts.server.protocol.FileCodeEdits[]): FileTextChanges[] {
|
||||
return edits.map(edit => {
|
||||
const fileName = edit.fileName;
|
||||
return {
|
||||
fileName,
|
||||
textChanges: edit.textChanges.map(t => this.convertTextChangeToCodeEdit(t, fileName))
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
convertCodeActions(entry: protocol.CodeAction, fileName: string): CodeAction {
|
||||
|
||||
@@ -37,6 +37,8 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
export interface ProjectInfoTelemetryEventData {
|
||||
/** Cryptographically secure hash of project file location. */
|
||||
readonly projectId: string;
|
||||
/** Count of file extensions seen in the project. */
|
||||
readonly fileStats: FileStats;
|
||||
/**
|
||||
@@ -1049,6 +1051,7 @@ namespace ts.server {
|
||||
if (!this.eventHandler) return;
|
||||
|
||||
const data: ProjectInfoTelemetryEventData = {
|
||||
projectId: this.host.createHash(projectKey),
|
||||
fileStats: countEachFileTypes(project.getScriptInfos()),
|
||||
compilerOptions: convertCompilerOptionsForTelemetry(project.getCompilerOptions()),
|
||||
typeAcquisition: convertTypeAcquisition(project.getTypeAcquisition()),
|
||||
|
||||
+32
-16
@@ -25,7 +25,7 @@ namespace ts.server {
|
||||
result.jsx += 1;
|
||||
break;
|
||||
case ScriptKind.TS:
|
||||
fileExtensionIs(info.fileName, ".d.ts")
|
||||
fileExtensionIs(info.fileName, Extension.Dts)
|
||||
? result.dts += 1
|
||||
: result.ts += 1;
|
||||
break;
|
||||
@@ -106,6 +106,7 @@ namespace ts.server {
|
||||
private rootFiles: ScriptInfo[] = [];
|
||||
private rootFilesMap: FileMap<ScriptInfo> = createFileMap<ScriptInfo>();
|
||||
private program: ts.Program;
|
||||
private externalFiles: SortedReadonlyArray<string>;
|
||||
|
||||
private cachedUnresolvedImportsPerFile = new UnresolvedImportsMap();
|
||||
private lastCachedUnresolvedImportsList: SortedReadonlyArray<string>;
|
||||
@@ -261,8 +262,8 @@ namespace ts.server {
|
||||
abstract getProjectRootPath(): string | undefined;
|
||||
abstract getTypeAcquisition(): TypeAcquisition;
|
||||
|
||||
getExternalFiles(): string[] {
|
||||
return [];
|
||||
getExternalFiles(): SortedReadonlyArray<string> {
|
||||
return emptyArray as SortedReadonlyArray<string>;
|
||||
}
|
||||
|
||||
getSourceFile(path: Path) {
|
||||
@@ -561,6 +562,24 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const oldExternalFiles = this.externalFiles || emptyArray as SortedReadonlyArray<string>;
|
||||
this.externalFiles = this.getExternalFiles();
|
||||
enumerateInsertsAndDeletes(this.externalFiles, oldExternalFiles,
|
||||
// Ensure a ScriptInfo is created for new external files. This is performed indirectly
|
||||
// by the LSHost for files in the program when the program is retrieved above but
|
||||
// the program doesn't contain external files so this must be done explicitly.
|
||||
inserted => {
|
||||
const scriptInfo = this.projectService.getOrCreateScriptInfo(inserted, /*openedByClient*/ false);
|
||||
scriptInfo.attachToProject(this);
|
||||
},
|
||||
removed => {
|
||||
const scriptInfoToDetach = this.projectService.getScriptInfo(removed);
|
||||
if (scriptInfoToDetach) {
|
||||
scriptInfoToDetach.detachFromProject(this);
|
||||
}
|
||||
});
|
||||
|
||||
return hasChanges;
|
||||
}
|
||||
|
||||
@@ -646,7 +665,7 @@ namespace ts.server {
|
||||
|
||||
const added: string[] = [];
|
||||
const removed: string[] = [];
|
||||
const updated: string[] = arrayFrom(updatedFileNames.keys());
|
||||
const updated: string[] = updatedFileNames ? arrayFrom(updatedFileNames.keys()) : [];
|
||||
|
||||
forEachKey(currentFiles, id => {
|
||||
if (!lastReportedFileNames.has(id)) {
|
||||
@@ -956,19 +975,16 @@ namespace ts.server {
|
||||
return this.typeAcquisition;
|
||||
}
|
||||
|
||||
getExternalFiles(): string[] {
|
||||
const items: string[] = [];
|
||||
for (const plugin of this.plugins) {
|
||||
if (typeof plugin.getExternalFiles === "function") {
|
||||
try {
|
||||
items.push(...plugin.getExternalFiles(this));
|
||||
}
|
||||
catch (e) {
|
||||
this.projectService.logger.info(`A plugin threw an exception in getExternalFiles: ${e}`);
|
||||
}
|
||||
getExternalFiles(): SortedReadonlyArray<string> {
|
||||
return toSortedReadonlyArray(flatMap(this.plugins, plugin => {
|
||||
if (typeof plugin.getExternalFiles !== "function") return;
|
||||
try {
|
||||
return plugin.getExternalFiles(this);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
catch (e) {
|
||||
this.projectService.logger.info(`A plugin threw an exception in getExternalFiles: ${e}`);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
watchConfigFile(callback: (project: ConfiguredProject) => void) {
|
||||
|
||||
+79
-30
@@ -98,8 +98,11 @@ namespace ts.server.protocol {
|
||||
GetSupportedCodeFixes = "getSupportedCodeFixes",
|
||||
|
||||
GetApplicableRefactors = "getApplicableRefactors",
|
||||
GetRefactorCodeActions = "getRefactorCodeActions",
|
||||
GetRefactorCodeActionsFull = "getRefactorCodeActions-full",
|
||||
GetEditsForRefactor = "getEditsForRefactor",
|
||||
/* @internal */
|
||||
GetEditsForRefactorFull = "getEditsForRefactor-full",
|
||||
|
||||
// NOTE: If updating this, be sure to also update `allCommandNames` in `harness/unittests/session.ts`.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,52 +404,98 @@ namespace ts.server.protocol {
|
||||
|
||||
export type FileLocationOrRangeRequestArgs = FileLocationRequestArgs | FileRangeRequestArgs;
|
||||
|
||||
/**
|
||||
* Request refactorings at a given position or selection area.
|
||||
*/
|
||||
export interface GetApplicableRefactorsRequest extends Request {
|
||||
command: CommandTypes.GetApplicableRefactors;
|
||||
arguments: GetApplicableRefactorsRequestArgs;
|
||||
}
|
||||
|
||||
export type GetApplicableRefactorsRequestArgs = FileLocationOrRangeRequestArgs;
|
||||
|
||||
export interface ApplicableRefactorInfo {
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response is a list of available refactorings.
|
||||
* Each refactoring exposes one or more "Actions"; a user selects one action to invoke a refactoring
|
||||
*/
|
||||
export interface GetApplicableRefactorsResponse extends Response {
|
||||
body?: ApplicableRefactorInfo[];
|
||||
}
|
||||
|
||||
export interface GetRefactorCodeActionsRequest extends Request {
|
||||
command: CommandTypes.GetRefactorCodeActions;
|
||||
arguments: GetRefactorCodeActionsRequestArgs;
|
||||
/**
|
||||
* A set of one or more available refactoring actions, grouped under a parent refactoring.
|
||||
*/
|
||||
export interface ApplicableRefactorInfo {
|
||||
/**
|
||||
* The programmatic name of the refactoring
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A description of this refactoring category to show to the user.
|
||||
* If the refactoring gets inlined (see below), this text will not be visible.
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* Inlineable refactorings can have their actions hoisted out to the top level
|
||||
* of a context menu. Non-inlineanable refactorings should always be shown inside
|
||||
* their parent grouping.
|
||||
*
|
||||
* If not specified, this value is assumed to be 'true'
|
||||
*/
|
||||
inlineable?: boolean;
|
||||
|
||||
actions: RefactorActionInfo[];
|
||||
}
|
||||
|
||||
export type GetRefactorCodeActionsRequestArgs = FileLocationOrRangeRequestArgs & {
|
||||
/* The kind of the applicable refactor */
|
||||
refactorName: string;
|
||||
/**
|
||||
* Represents a single refactoring action - for example, the "Extract Method..." refactor might
|
||||
* offer several actions, each corresponding to a surround class or closure to extract into.
|
||||
*/
|
||||
export type RefactorActionInfo = {
|
||||
/**
|
||||
* The programmatic name of the refactoring action
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* A description of this refactoring action to show to the user.
|
||||
* If the parent refactoring is inlined away, this will be the only text shown,
|
||||
* so this description should make sense by itself if the parent is inlineable=true
|
||||
*/
|
||||
description: string;
|
||||
};
|
||||
|
||||
export type RefactorCodeActions = {
|
||||
actions: protocol.CodeAction[];
|
||||
renameLocation?: number
|
||||
};
|
||||
|
||||
/* @internal */
|
||||
export type RefactorCodeActionsFull = {
|
||||
actions: ts.CodeAction[];
|
||||
renameLocation?: number
|
||||
};
|
||||
|
||||
export interface GetRefactorCodeActionsResponse extends Response {
|
||||
body: RefactorCodeActions;
|
||||
export interface GetEditsForRefactorRequest extends Request {
|
||||
command: CommandTypes.GetEditsForRefactor;
|
||||
arguments: GetEditsForRefactorRequestArgs;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface GetRefactorCodeActionsFullResponse extends Response {
|
||||
body: RefactorCodeActionsFull;
|
||||
/**
|
||||
* Request the edits that a particular refactoring action produces.
|
||||
* Callers must specify the name of the refactor and the name of the action.
|
||||
*/
|
||||
export type GetEditsForRefactorRequestArgs = FileLocationOrRangeRequestArgs & {
|
||||
/* The 'name' property from the refactoring that offered this action */
|
||||
refactor: string;
|
||||
/* The 'name' property from the refactoring action */
|
||||
action: string;
|
||||
};
|
||||
|
||||
|
||||
export interface GetEditsForRefactorResponse extends Response {
|
||||
body?: RefactorEditInfo;
|
||||
}
|
||||
|
||||
export type RefactorEditInfo = {
|
||||
edits: FileCodeEdits[];
|
||||
|
||||
/**
|
||||
* An optional location where the editor should start a rename operation once
|
||||
* the refactoring edits have been applied
|
||||
*/
|
||||
renameLocation?: Location;
|
||||
renameFilename?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request for the available codefixes at a specific position.
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace ts.server {
|
||||
} = require("os");
|
||||
|
||||
function getGlobalTypingsCacheLocation() {
|
||||
const versionMajorMinor = ts.version.match(/\d+\.\d+/)[0];
|
||||
switch (process.platform) {
|
||||
case "win32": {
|
||||
const basePath = process.env.LOCALAPPDATA ||
|
||||
@@ -43,13 +44,15 @@ namespace ts.server {
|
||||
process.env.USERPROFILE ||
|
||||
(process.env.HOMEDRIVE && process.env.HOMEPATH && normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) ||
|
||||
os.tmpdir();
|
||||
return combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript");
|
||||
return combinePaths(combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript"), versionMajorMinor);
|
||||
}
|
||||
case "openbsd":
|
||||
case "freebsd":
|
||||
case "darwin":
|
||||
case "linux":
|
||||
case "android": {
|
||||
const cacheLocation = getNonWindowsCacheLocation(process.platform === "darwin");
|
||||
return combinePaths(cacheLocation, "typescript");
|
||||
return combinePaths(combinePaths(cacheLocation, "typescript"), versionMajorMinor);
|
||||
}
|
||||
default:
|
||||
Debug.fail(`unsupported platform '${process.platform}'`);
|
||||
@@ -524,7 +527,7 @@ namespace ts.server {
|
||||
watchedFile.callback(watchedFile.fileName);
|
||||
}
|
||||
else if (watchedFile.mtime.getTime() !== stats.mtime.getTime()) {
|
||||
watchedFile.mtime = getModifiedTime(watchedFile.fileName);
|
||||
watchedFile.mtime = stats.mtime;
|
||||
watchedFile.callback(watchedFile.fileName, watchedFile.mtime.getTime() === 0);
|
||||
}
|
||||
});
|
||||
|
||||
+48
-19
@@ -112,7 +112,13 @@ namespace ts.server {
|
||||
return true;
|
||||
}
|
||||
|
||||
export import CommandNames = protocol.CommandTypes;
|
||||
// CommandNames used to be exposed before TS 2.4 as a namespace
|
||||
// In TS 2.4 we switched to an enum, keep this for backward compatibility
|
||||
// The var assignment ensures that even though CommandTypes are a const enum
|
||||
// we want to ensure the value is maintained in the out since the file is
|
||||
// built using --preseveConstEnum.
|
||||
export type CommandNames = protocol.CommandTypes;
|
||||
export const CommandNames = (<any>protocol).CommandTypes;
|
||||
|
||||
export function formatMessage<T extends protocol.Message>(msg: T, logger: server.Logger, byteLength: (s: string, encoding: string) => number, newLine: string): string {
|
||||
const verboseLogging = logger.hasLevel(LogLevel.verbose);
|
||||
@@ -1425,29 +1431,40 @@ namespace ts.server {
|
||||
return project.getLanguageService().getApplicableRefactors(file, position || textRange);
|
||||
}
|
||||
|
||||
private getRefactorCodeActions(args: protocol.GetRefactorCodeActionsRequestArgs, simplifiedResult: boolean): protocol.RefactorCodeActions | protocol.RefactorCodeActionsFull {
|
||||
private getEditsForRefactor(args: protocol.GetEditsForRefactorRequestArgs, simplifiedResult: boolean): ts.RefactorEditInfo | protocol.RefactorEditInfo {
|
||||
const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args);
|
||||
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
|
||||
const { position, textRange } = this.extractPositionAndRange(args, scriptInfo);
|
||||
|
||||
const result: ts.CodeAction[] = project.getLanguageService().getRefactorCodeActions(
|
||||
const result = project.getLanguageService().getEditsForRefactor(
|
||||
file,
|
||||
this.projectService.getFormatCodeOptions(),
|
||||
position || textRange,
|
||||
args.refactorName
|
||||
args.refactor,
|
||||
args.action
|
||||
);
|
||||
|
||||
if (simplifiedResult) {
|
||||
// Not full
|
||||
if (result === undefined) {
|
||||
return {
|
||||
actions: result.map(action => this.mapCodeAction(action, scriptInfo))
|
||||
edits: []
|
||||
};
|
||||
}
|
||||
|
||||
if (simplifiedResult) {
|
||||
const file = result.renameFilename;
|
||||
let location: ILineInfo | undefined = undefined;
|
||||
if (file !== undefined && result.renameLocation !== undefined) {
|
||||
const renameScriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(file));
|
||||
location = renameScriptInfo.positionToLineOffset(result.renameLocation);
|
||||
}
|
||||
return {
|
||||
renameLocation: location,
|
||||
renameFilename: file,
|
||||
edits: result.edits.map(change => this.mapTextChangesToCodeEdits(project, change))
|
||||
};
|
||||
}
|
||||
else {
|
||||
// Full
|
||||
return {
|
||||
actions: result
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1505,6 +1522,14 @@ namespace ts.server {
|
||||
};
|
||||
}
|
||||
|
||||
private mapTextChangesToCodeEdits(project: Project, textChanges: FileTextChanges): protocol.FileCodeEdits {
|
||||
const scriptInfo = project.getScriptInfoForNormalizedPath(toNormalizedPath(textChanges.fileName));
|
||||
return {
|
||||
fileName: textChanges.fileName,
|
||||
textChanges: textChanges.textChanges.map(textChange => this.convertTextChangeToCodeEdit(textChange, scriptInfo))
|
||||
};
|
||||
}
|
||||
|
||||
private convertTextChangeToCodeEdit(change: ts.TextChange, scriptInfo: ScriptInfo): protocol.CodeEdit {
|
||||
return {
|
||||
start: scriptInfo.positionToLineOffset(change.span.start),
|
||||
@@ -1544,18 +1569,22 @@ namespace ts.server {
|
||||
const normalizedFileName = toNormalizedPath(fileName);
|
||||
const project = this.projectService.getDefaultProjectForFile(normalizedFileName, /*refreshInferredProjects*/ true);
|
||||
for (const fileNameInProject of fileNamesInProject) {
|
||||
if (this.getCanonicalFileName(fileNameInProject) === this.getCanonicalFileName(fileName))
|
||||
if (this.getCanonicalFileName(fileNameInProject) === this.getCanonicalFileName(fileName)) {
|
||||
highPriorityFiles.push(fileNameInProject);
|
||||
}
|
||||
else {
|
||||
const info = this.projectService.getScriptInfo(fileNameInProject);
|
||||
if (!info.isScriptOpen()) {
|
||||
if (fileNameInProject.indexOf(".d.ts") > 0)
|
||||
if (fileNameInProject.indexOf(Extension.Dts) > 0) {
|
||||
veryLowPriorityFiles.push(fileNameInProject);
|
||||
else
|
||||
}
|
||||
else {
|
||||
lowPriorityFiles.push(fileNameInProject);
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
mediumPriorityFiles.push(fileNameInProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1833,11 +1862,11 @@ namespace ts.server {
|
||||
[CommandNames.GetApplicableRefactors]: (request: protocol.GetApplicableRefactorsRequest) => {
|
||||
return this.requiredResponse(this.getApplicableRefactors(request.arguments));
|
||||
},
|
||||
[CommandNames.GetRefactorCodeActions]: (request: protocol.GetRefactorCodeActionsRequest) => {
|
||||
return this.requiredResponse(this.getRefactorCodeActions(request.arguments, /*simplifiedResult*/ true));
|
||||
[CommandNames.GetEditsForRefactor]: (request: protocol.GetEditsForRefactorRequest) => {
|
||||
return this.requiredResponse(this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.GetRefactorCodeActionsFull]: (request: protocol.GetRefactorCodeActionsRequest) => {
|
||||
return this.requiredResponse(this.getRefactorCodeActions(request.arguments, /*simplifiedResult*/ false));
|
||||
[CommandNames.GetEditsForRefactorFull]: (request: protocol.GetEditsForRefactorRequest) => {
|
||||
return this.requiredResponse(this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ false));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -195,6 +195,37 @@ namespace ts.server {
|
||||
return <any>arr;
|
||||
}
|
||||
|
||||
export function enumerateInsertsAndDeletes<T>(a: SortedReadonlyArray<T>, b: SortedReadonlyArray<T>, inserted: (item: T) => void, deleted: (item: T) => void, compare?: (a: T, b: T) => Comparison) {
|
||||
compare = compare || ts.compareValues;
|
||||
let aIndex = 0;
|
||||
let bIndex = 0;
|
||||
const aLen = a.length;
|
||||
const bLen = b.length;
|
||||
while (aIndex < aLen && bIndex < bLen) {
|
||||
const aItem = a[aIndex];
|
||||
const bItem = b[bIndex];
|
||||
const compareResult = compare(aItem, bItem);
|
||||
if (compareResult === Comparison.LessThan) {
|
||||
inserted(aItem);
|
||||
aIndex++;
|
||||
}
|
||||
else if (compareResult === Comparison.GreaterThan) {
|
||||
deleted(bItem);
|
||||
bIndex++;
|
||||
}
|
||||
else {
|
||||
aIndex++;
|
||||
bIndex++;
|
||||
}
|
||||
}
|
||||
while (aIndex < aLen) {
|
||||
inserted(a[aIndex++]);
|
||||
}
|
||||
while (bIndex < bLen) {
|
||||
deleted(b[bIndex++]);
|
||||
}
|
||||
}
|
||||
|
||||
export class ThrottledOperations {
|
||||
private pendingTimeouts: Map<any> = createMap<any>();
|
||||
constructor(private readonly host: ServerHost) {
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace ts.BreakpointResolver {
|
||||
|
||||
case SyntaxKind.ForOfStatement:
|
||||
// span in initializer
|
||||
return spanInInitializerOfForLike(<ForOfStatement | ForInStatement>node);
|
||||
return spanInInitializerOfForLike(<ForOfStatement>node);
|
||||
|
||||
case SyntaxKind.SwitchStatement:
|
||||
// span on switch(...)
|
||||
|
||||
@@ -724,8 +724,8 @@ namespace ts {
|
||||
pushCommentRange(pos, tag.pos - pos);
|
||||
}
|
||||
|
||||
pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, ClassificationType.punctuation);
|
||||
pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, ClassificationType.docCommentTagName);
|
||||
pushClassification(tag.atToken.pos, tag.atToken.end - tag.atToken.pos, ClassificationType.punctuation); // "@"
|
||||
pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, ClassificationType.docCommentTagName); // e.g. "param"
|
||||
|
||||
pos = tag.tagName.end;
|
||||
|
||||
@@ -814,7 +814,7 @@ namespace ts {
|
||||
* False will mean that node is not classified and traverse routine should recurse into node contents.
|
||||
*/
|
||||
function tryClassifyNode(node: Node): boolean {
|
||||
if (isJSDocTag(node)) {
|
||||
if (isJSDoc(node)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,107 +8,161 @@ namespace ts.codefix {
|
||||
|
||||
function getActionsForAddMissingMember(context: CodeFixContext): CodeAction[] | undefined {
|
||||
|
||||
const sourceFile = context.sourceFile;
|
||||
const tokenSourceFile = context.sourceFile;
|
||||
const start = context.span.start;
|
||||
// This is the identifier of the missing property. eg:
|
||||
// The identifier of the missing property. eg:
|
||||
// this.missing = 1;
|
||||
// ^^^^^^^
|
||||
const token = getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false);
|
||||
const token = getTokenAtPosition(tokenSourceFile, start, /*includeJsDocComment*/ false);
|
||||
|
||||
if (token.kind !== SyntaxKind.Identifier) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!isPropertyAccessExpression(token.parent) || token.parent.expression.kind !== SyntaxKind.ThisKeyword) {
|
||||
if (!isPropertyAccessExpression(token.parent)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const classMemberDeclaration = getThisContainer(token, /*includeArrowFunctions*/ false);
|
||||
if (!isClassElement(classMemberDeclaration)) {
|
||||
return undefined;
|
||||
const tokenName = token.getText(tokenSourceFile);
|
||||
|
||||
let makeStatic = false;
|
||||
let classDeclaration: ClassLikeDeclaration;
|
||||
|
||||
if (token.parent.expression.kind === SyntaxKind.ThisKeyword) {
|
||||
const containingClassMemberDeclaration = getThisContainer(token, /*includeArrowFunctions*/ false);
|
||||
if (!isClassElement(containingClassMemberDeclaration)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
classDeclaration = <ClassLikeDeclaration>containingClassMemberDeclaration.parent;
|
||||
|
||||
// Property accesses on `this` in a static method are accesses of a static member.
|
||||
makeStatic = classDeclaration && hasModifier(containingClassMemberDeclaration, ModifierFlags.Static);
|
||||
}
|
||||
else {
|
||||
|
||||
const checker = context.program.getTypeChecker();
|
||||
const leftExpression = token.parent.expression;
|
||||
const leftExpressionType = checker.getTypeAtLocation(leftExpression);
|
||||
|
||||
if (leftExpressionType.flags & TypeFlags.Object) {
|
||||
const symbol = leftExpressionType.symbol;
|
||||
if (symbol.flags & SymbolFlags.Class) {
|
||||
classDeclaration = symbol.declarations && <ClassLikeDeclaration>symbol.declarations[0];
|
||||
if (leftExpressionType !== checker.getDeclaredTypeOfSymbol(symbol)) {
|
||||
// The expression is a class symbol but the type is not the instance-side.
|
||||
makeStatic = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const classDeclaration = <ClassLikeDeclaration>classMemberDeclaration.parent;
|
||||
if (!classDeclaration || !isClassLike(classDeclaration)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const isStatic = hasModifier(classMemberDeclaration, ModifierFlags.Static);
|
||||
const classDeclarationSourceFile = getSourceFileOfNode(classDeclaration);
|
||||
const classOpenBrace = getOpenBraceOfClassLike(classDeclaration, classDeclarationSourceFile);
|
||||
|
||||
return isInJavaScriptFile(sourceFile) ? getActionsForAddMissingMemberInJavaScriptFile() : getActionsForAddMissingMemberInTypeScriptFile();
|
||||
return isInJavaScriptFile(classDeclarationSourceFile) ?
|
||||
getActionsForAddMissingMemberInJavaScriptFile(classDeclaration, makeStatic) :
|
||||
getActionsForAddMissingMemberInTypeScriptFile(classDeclaration, makeStatic);
|
||||
|
||||
function getActionsForAddMissingMemberInJavaScriptFile(): CodeAction[] | undefined {
|
||||
const memberName = token.getText();
|
||||
function getActionsForAddMissingMemberInJavaScriptFile(classDeclaration: ClassLikeDeclaration, makeStatic: boolean): CodeAction[] | undefined {
|
||||
let actions: CodeAction[];
|
||||
|
||||
if (isStatic) {
|
||||
const methodCodeAction = getActionForMethodDeclaration(/*includeTypeScriptSyntax*/ false);
|
||||
if (methodCodeAction) {
|
||||
actions = [methodCodeAction];
|
||||
}
|
||||
|
||||
if (makeStatic) {
|
||||
if (classDeclaration.kind === SyntaxKind.ClassExpression) {
|
||||
return undefined;
|
||||
return actions;
|
||||
}
|
||||
|
||||
const className = classDeclaration.name.getText();
|
||||
|
||||
return [{
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_static_property_0), [memberName]),
|
||||
changes: [{
|
||||
fileName: sourceFile.fileName,
|
||||
textChanges: [{
|
||||
span: { start: classDeclaration.getEnd(), length: 0 },
|
||||
newText: `${context.newLineCharacter}${className}.${memberName} = undefined;${context.newLineCharacter}`
|
||||
}]
|
||||
}]
|
||||
}];
|
||||
const staticInitialization = createStatement(createAssignment(
|
||||
createPropertyAccess(createIdentifier(className), tokenName),
|
||||
createIdentifier("undefined")));
|
||||
|
||||
const staticInitializationChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
staticInitializationChangeTracker.insertNodeAfter(
|
||||
classDeclarationSourceFile,
|
||||
classDeclaration,
|
||||
staticInitialization,
|
||||
{ suffix: context.newLineCharacter });
|
||||
const initializeStaticAction = {
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_static_property_0), [tokenName]),
|
||||
changes: staticInitializationChangeTracker.getChanges()
|
||||
};
|
||||
|
||||
(actions || (actions = [])).push(initializeStaticAction);
|
||||
return actions;
|
||||
}
|
||||
else {
|
||||
const classConstructor = getFirstConstructorWithBody(classDeclaration);
|
||||
if (!classConstructor) {
|
||||
return undefined;
|
||||
return actions;
|
||||
}
|
||||
|
||||
return [{
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_property_0_in_the_constructor), [memberName]),
|
||||
changes: [{
|
||||
fileName: sourceFile.fileName,
|
||||
textChanges: [{
|
||||
span: { start: classConstructor.body.getEnd() - 1, length: 0 },
|
||||
newText: `this.${memberName} = undefined;${context.newLineCharacter}`
|
||||
}]
|
||||
}]
|
||||
}];
|
||||
const propertyInitialization = createStatement(createAssignment(
|
||||
createPropertyAccess(createThis(), tokenName),
|
||||
createIdentifier("undefined")));
|
||||
|
||||
const propertyInitializationChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
propertyInitializationChangeTracker.insertNodeAt(
|
||||
classDeclarationSourceFile,
|
||||
classConstructor.body.getEnd() - 1,
|
||||
propertyInitialization,
|
||||
{ prefix: context.newLineCharacter, suffix: context.newLineCharacter });
|
||||
|
||||
const initializeAction = {
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Initialize_property_0_in_the_constructor), [tokenName]),
|
||||
changes: propertyInitializationChangeTracker.getChanges()
|
||||
};
|
||||
|
||||
(actions || (actions = [])).push(initializeAction);
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
||||
function getActionsForAddMissingMemberInTypeScriptFile(): CodeAction[] | undefined {
|
||||
let typeNode: TypeNode;
|
||||
function getActionsForAddMissingMemberInTypeScriptFile(classDeclaration: ClassLikeDeclaration, makeStatic: boolean): CodeAction[] | undefined {
|
||||
let actions: CodeAction[];
|
||||
|
||||
if (token.parent.parent.kind === SyntaxKind.BinaryExpression) {
|
||||
const binaryExpression = token.parent.parent as BinaryExpression;
|
||||
|
||||
const checker = context.program.getTypeChecker();
|
||||
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right)));
|
||||
typeNode = checker.typeToTypeNode(widenedType, classDeclaration);
|
||||
const methodCodeAction = getActionForMethodDeclaration(/*includeTypeScriptSyntax*/ true);
|
||||
if (methodCodeAction) {
|
||||
actions = [methodCodeAction];
|
||||
}
|
||||
|
||||
let typeNode: TypeNode;
|
||||
if (token.parent.parent.kind === SyntaxKind.BinaryExpression) {
|
||||
const binaryExpression = token.parent.parent as BinaryExpression;
|
||||
const otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left;
|
||||
const checker = context.program.getTypeChecker();
|
||||
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)));
|
||||
typeNode = checker.typeToTypeNode(widenedType, classDeclaration);
|
||||
}
|
||||
typeNode = typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
|
||||
const openBrace = getOpenBraceOfClassLike(classDeclaration, sourceFile);
|
||||
|
||||
const property = createProperty(
|
||||
/*decorators*/undefined,
|
||||
/*modifiers*/ isStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined,
|
||||
token.getText(sourceFile),
|
||||
/*modifiers*/ makeStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined,
|
||||
tokenName,
|
||||
/*questionToken*/ undefined,
|
||||
typeNode,
|
||||
/*initializer*/ undefined);
|
||||
const propertyChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
propertyChangeTracker.insertNodeAfter(sourceFile, openBrace, property, { suffix: context.newLineCharacter });
|
||||
propertyChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, property, { suffix: context.newLineCharacter });
|
||||
|
||||
const actions = [{
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]),
|
||||
(actions || (actions = [])).push({
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Declare_property_0), [tokenName]),
|
||||
changes: propertyChangeTracker.getChanges()
|
||||
}];
|
||||
});
|
||||
|
||||
if (!isStatic) {
|
||||
if (!makeStatic) {
|
||||
// Index signatures cannot have the static modifier.
|
||||
const stringTypeNode = createKeywordTypeNode(SyntaxKind.StringKeyword);
|
||||
const indexingParameter = createParameter(
|
||||
/*decorators*/ undefined,
|
||||
@@ -125,15 +179,32 @@ namespace ts.codefix {
|
||||
typeNode);
|
||||
|
||||
const indexSignatureChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
indexSignatureChangeTracker.insertNodeAfter(sourceFile, openBrace, indexSignature, { suffix: context.newLineCharacter });
|
||||
indexSignatureChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, indexSignature, { suffix: context.newLineCharacter });
|
||||
|
||||
actions.push({
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_missing_property_0), [token.getText()]),
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_property_0), [tokenName]),
|
||||
changes: indexSignatureChangeTracker.getChanges()
|
||||
});
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
function getActionForMethodDeclaration(includeTypeScriptSyntax: boolean): CodeAction | undefined {
|
||||
if (token.parent.parent.kind === SyntaxKind.CallExpression) {
|
||||
const callExpression = <CallExpression>token.parent.parent;
|
||||
const methodDeclaration = createMethodFromCallExpression(callExpression, tokenName, includeTypeScriptSyntax, makeStatic);
|
||||
|
||||
const methodDeclarationChangeTracker = textChanges.ChangeTracker.fromCodeFixContext(context);
|
||||
methodDeclarationChangeTracker.insertNodeAfter(classDeclarationSourceFile, classOpenBrace, methodDeclaration, { suffix: context.newLineCharacter });
|
||||
return {
|
||||
description: formatStringFromArgs(getLocaleSpecificMessage(makeStatic ?
|
||||
Diagnostics.Declare_method_0 :
|
||||
Diagnostics.Declare_static_method_0),
|
||||
[tokenName]),
|
||||
changes: methodDeclarationChangeTracker.getChanges()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +142,50 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
export function createMethodFromCallExpression(callExpression: CallExpression, methodName: string, includeTypeScriptSyntax: boolean, makeStatic: boolean): MethodDeclaration {
|
||||
const parameters = createDummyParameters(callExpression.arguments.length, /*names*/ undefined, /*minArgumentCount*/ undefined, includeTypeScriptSyntax);
|
||||
|
||||
let typeParameters: TypeParameterDeclaration[];
|
||||
if (includeTypeScriptSyntax) {
|
||||
const typeArgCount = length(callExpression.typeArguments);
|
||||
for (let i = 0; i < typeArgCount; i++) {
|
||||
const name = typeArgCount < 8 ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`;
|
||||
const typeParameter = createTypeParameterDeclaration(name, /*constraint*/ undefined, /*defaultType*/ undefined);
|
||||
(typeParameters ? typeParameters : typeParameters = []).push(typeParameter);
|
||||
}
|
||||
}
|
||||
|
||||
const newMethod = createMethod(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ makeStatic ? [createToken(SyntaxKind.StaticKeyword)] : undefined,
|
||||
/*asteriskToken*/ undefined,
|
||||
methodName,
|
||||
/*questionToken*/ undefined,
|
||||
typeParameters,
|
||||
parameters,
|
||||
/*type*/ includeTypeScriptSyntax ? createKeywordTypeNode(SyntaxKind.AnyKeyword) : undefined,
|
||||
createStubbedMethodBody()
|
||||
);
|
||||
return newMethod;
|
||||
}
|
||||
|
||||
function createDummyParameters(argCount: number, names: string[] | undefined, minArgumentCount: number | undefined, addAnyType: boolean) {
|
||||
const parameters: ParameterDeclaration[] = [];
|
||||
for (let i = 0; i < argCount; i++) {
|
||||
const newParameter = createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
/*name*/ names && names[i] || `arg${i}`,
|
||||
/*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined,
|
||||
/*type*/ addAnyType ? createKeywordTypeNode(SyntaxKind.AnyKeyword) : undefined,
|
||||
/*initializer*/ undefined);
|
||||
parameters.push(newParameter);
|
||||
}
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
function createMethodImplementingSignatures(signatures: Signature[], name: PropertyName, optional: boolean, modifiers: Modifier[] | undefined): MethodDeclaration {
|
||||
/** This is *a* signature with the maximal number of arguments,
|
||||
* such that if there is a "maximal" signature without rest arguments,
|
||||
@@ -163,19 +207,7 @@ namespace ts.codefix {
|
||||
const maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0);
|
||||
const maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(symbol => symbol.getName());
|
||||
|
||||
const parameters: ParameterDeclaration[] = [];
|
||||
for (let i = 0; i < maxNonRestArgs; i++) {
|
||||
const anyType = createKeywordTypeNode(SyntaxKind.AnyKeyword);
|
||||
const newParameter = createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
/*dotDotDotToken*/ undefined,
|
||||
maxArgsParameterSymbolNames[i],
|
||||
/*questionToken*/ i >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined,
|
||||
anyType,
|
||||
/*initializer*/ undefined);
|
||||
parameters.push(newParameter);
|
||||
}
|
||||
const parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, minArgumentCount, /*addAnyType*/ true);
|
||||
|
||||
if (someSigHasRestParameter) {
|
||||
const anyArrayType = createArrayTypeNode(createKeywordTypeNode(SyntaxKind.AnyKeyword));
|
||||
|
||||
@@ -138,8 +138,23 @@ namespace ts.codefix {
|
||||
|
||||
const currentTokenMeaning = getMeaningFromLocation(token);
|
||||
if (context.errorCode === Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code) {
|
||||
const symbol = checker.getAliasedSymbol(checker.getSymbolAtLocation(token));
|
||||
return getCodeActionForImport(symbol, /*isDefault*/ false, /*isNamespaceImport*/ true);
|
||||
const umdSymbol = checker.getSymbolAtLocation(token);
|
||||
let symbol: ts.Symbol;
|
||||
let symbolName: string;
|
||||
if (umdSymbol.flags & ts.SymbolFlags.Alias) {
|
||||
symbol = checker.getAliasedSymbol(umdSymbol);
|
||||
symbolName = name;
|
||||
}
|
||||
else if (isJsxOpeningLikeElement(token.parent) && token.parent.tagName === token) {
|
||||
// The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`.
|
||||
symbol = checker.getAliasedSymbol(checker.resolveNameAtLocation(token, checker.getJsxNamespace(), SymbolFlags.Value));
|
||||
symbolName = symbol.name;
|
||||
}
|
||||
else {
|
||||
Debug.fail("Either the symbol or the JSX namespace should be a UMD global if we got here");
|
||||
}
|
||||
|
||||
return getCodeActionForImport(symbol, symbolName, /*isDefault*/ false, /*isNamespaceImport*/ true);
|
||||
}
|
||||
|
||||
const candidateModules = checker.getAmbientModules();
|
||||
@@ -159,7 +174,7 @@ namespace ts.codefix {
|
||||
if (localSymbol && localSymbol.name === name && checkSymbolHasMeaning(localSymbol, currentTokenMeaning)) {
|
||||
// check if this symbol is already used
|
||||
const symbolId = getUniqueSymbolId(localSymbol);
|
||||
symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, /*isDefault*/ true));
|
||||
symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, name, /*isDefault*/ true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +182,7 @@ namespace ts.codefix {
|
||||
const exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExports(name, moduleSymbol);
|
||||
if (exportSymbolWithIdenticalName && checkSymbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) {
|
||||
const symbolId = getUniqueSymbolId(exportSymbolWithIdenticalName);
|
||||
symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol));
|
||||
symbolIdActionMap.addActions(symbolId, getCodeActionForImport(moduleSymbol, name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +233,7 @@ namespace ts.codefix {
|
||||
return declarations ? some(symbol.declarations, decl => !!(getMeaningFromDeclaration(decl) & meaning)) : false;
|
||||
}
|
||||
|
||||
function getCodeActionForImport(moduleSymbol: Symbol, isDefault?: boolean, isNamespaceImport?: boolean): ImportCodeAction[] {
|
||||
function getCodeActionForImport(moduleSymbol: Symbol, symbolName: string, isDefault?: boolean, isNamespaceImport?: boolean): ImportCodeAction[] {
|
||||
const existingDeclarations = getImportDeclarations(moduleSymbol);
|
||||
if (existingDeclarations.length > 0) {
|
||||
// With an existing import statement, there are more than one actions the user can do.
|
||||
@@ -375,10 +390,10 @@ namespace ts.codefix {
|
||||
const moduleSpecifierWithoutQuotes = stripQuotes(moduleSpecifier || getModuleSpecifierForNewImport());
|
||||
const changeTracker = createChangeTracker();
|
||||
const importClause = isDefault
|
||||
? createImportClause(createIdentifier(name), /*namedBindings*/ undefined)
|
||||
? createImportClause(createIdentifier(symbolName), /*namedBindings*/ undefined)
|
||||
: isNamespaceImport
|
||||
? createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(name)))
|
||||
: createImportClause(/*name*/ undefined, createNamedImports([createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name))]));
|
||||
? createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(symbolName)))
|
||||
: createImportClause(/*name*/ undefined, createNamedImports([createImportSpecifier(/*propertyName*/ undefined, createIdentifier(symbolName))]));
|
||||
const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, importClause, createLiteral(moduleSpecifierWithoutQuotes));
|
||||
if (!lastImportDeclaration) {
|
||||
changeTracker.insertNodeAt(sourceFile, sourceFile.getStart(), importDecl, { suffix: `${context.newLineCharacter}${context.newLineCharacter}` });
|
||||
@@ -392,7 +407,7 @@ namespace ts.codefix {
|
||||
// are there are already a new line seperating code and import statements.
|
||||
return createCodeAction(
|
||||
Diagnostics.Import_0_from_1,
|
||||
[name, `"${moduleSpecifierWithoutQuotes}"`],
|
||||
[symbolName, `"${moduleSpecifierWithoutQuotes}"`],
|
||||
changeTracker.getChanges(),
|
||||
"NewImport",
|
||||
moduleSpecifierWithoutQuotes
|
||||
@@ -412,8 +427,9 @@ namespace ts.codefix {
|
||||
removeFileExtension(getRelativePath(moduleFileName, sourceDirectory));
|
||||
|
||||
function tryGetModuleNameFromAmbientModule(): string {
|
||||
if (moduleSymbol.valueDeclaration.kind !== SyntaxKind.SourceFile) {
|
||||
return moduleSymbol.name;
|
||||
const decl = moduleSymbol.valueDeclaration;
|
||||
if (isModuleDeclaration(decl) && isStringLiteral(decl.name)) {
|
||||
return decl.name.text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+114
-70
@@ -18,16 +18,33 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords } = completionData;
|
||||
const { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, request, hasFilteredClassMemberKeywords } = completionData;
|
||||
|
||||
if (requestJsDocTagName) {
|
||||
// If the current position is a jsDoc tag name, only tag names should be provided for completion
|
||||
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: JsDoc.getJSDocTagNameCompletions() };
|
||||
if (sourceFile.languageVariant === LanguageVariant.JSX &&
|
||||
location && location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) {
|
||||
// In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
|
||||
// instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element.
|
||||
// For example:
|
||||
// var x = <div> </ /*1*/> completion list at "1" will contain "div" with type any
|
||||
const tagName = (<JsxElement>location.parent.parent).openingElement.tagName;
|
||||
return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false,
|
||||
entries: [{
|
||||
name: (<JsxTagNameExpression>tagName).getFullText(),
|
||||
kind: ScriptElementKind.classElement,
|
||||
kindModifiers: undefined,
|
||||
sortText: "0",
|
||||
}]};
|
||||
}
|
||||
|
||||
if (requestJsDocTag) {
|
||||
// If the current position is a jsDoc tag, only tags should be provided for completion
|
||||
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: JsDoc.getJSDocTagCompletions() };
|
||||
if (request) {
|
||||
const entries = request.kind === "JsDocTagName"
|
||||
// If the current position is a jsDoc tag name, only tag names should be provided for completion
|
||||
? JsDoc.getJSDocTagNameCompletions()
|
||||
: request.kind === "JsDocTag"
|
||||
// If the current position is a jsDoc tag, only tags should be provided for completion
|
||||
? JsDoc.getJSDocTagCompletions()
|
||||
: JsDoc.getJSDocParameterNameCompletions(request.tag);
|
||||
return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries };
|
||||
}
|
||||
|
||||
const entries: CompletionEntry[] = [];
|
||||
@@ -38,21 +55,7 @@ namespace ts.Completions {
|
||||
}
|
||||
else {
|
||||
if (!symbols || symbols.length === 0) {
|
||||
if (sourceFile.languageVariant === LanguageVariant.JSX &&
|
||||
location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) {
|
||||
// In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
|
||||
// instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element.
|
||||
// For example:
|
||||
// var x = <div> </ /*1*/> completion list at "1" will contain "div" with type any
|
||||
const tagName = (<JsxElement>location.parent.parent).openingElement.tagName;
|
||||
entries.push({
|
||||
name: (<Identifier>tagName).text,
|
||||
kind: undefined,
|
||||
kindModifiers: undefined,
|
||||
sortText: "0",
|
||||
});
|
||||
}
|
||||
else if (!hasFilteredClassMemberKeywords) {
|
||||
if (!hasFilteredClassMemberKeywords) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -64,7 +67,7 @@ namespace ts.Completions {
|
||||
addRange(entries, classMemberKeywordCompletions);
|
||||
}
|
||||
// Add keywords if this is not a member completion list
|
||||
else if (!isMemberCompletion && !requestJsDocTag && !requestJsDocTagName) {
|
||||
else if (!isMemberCompletion) {
|
||||
addRange(entries, keywordCompletions);
|
||||
}
|
||||
|
||||
@@ -345,16 +348,27 @@ namespace ts.Completions {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getCompletionData(typeChecker: TypeChecker, log: (message: string) => void, sourceFile: SourceFile, position: number) {
|
||||
interface CompletionData {
|
||||
symbols: Symbol[];
|
||||
isGlobalCompletion: boolean;
|
||||
isMemberCompletion: boolean;
|
||||
isNewIdentifierLocation: boolean;
|
||||
location: Node;
|
||||
isRightOfDot: boolean;
|
||||
request?: Request;
|
||||
hasFilteredClassMemberKeywords: boolean;
|
||||
}
|
||||
type Request = { kind: "JsDocTagName" } | { kind: "JsDocTag" } | { kind: "JsDocParameterName", tag: JSDocParameterTag };
|
||||
|
||||
function getCompletionData(typeChecker: TypeChecker, log: (message: string) => void, sourceFile: SourceFile, position: number): CompletionData {
|
||||
const isJavaScriptFile = isSourceFileJavaScript(sourceFile);
|
||||
|
||||
// JsDoc tag-name is just the name of the JSDoc tagname (exclude "@")
|
||||
let requestJsDocTagName = false;
|
||||
// JsDoc tag includes both "@" and tag-name
|
||||
let requestJsDocTag = false;
|
||||
let request: Request | undefined;
|
||||
|
||||
let start = timestamp();
|
||||
let currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853
|
||||
// We will check for jsdoc comments with insideComment and getJsDocTagAtPosition. (TODO: that seems rather inefficient to check the same thing so many times.)
|
||||
|
||||
log("getCompletionData: Get current token: " + (timestamp() - start));
|
||||
|
||||
start = timestamp();
|
||||
@@ -365,10 +379,10 @@ namespace ts.Completions {
|
||||
let insideJsDocTagTypeExpression = false;
|
||||
if (insideComment) {
|
||||
if (hasDocComment(sourceFile, position)) {
|
||||
// The current position is next to the '@' sign, when no tag name being provided yet.
|
||||
// Provide a full list of tag names
|
||||
if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) {
|
||||
requestJsDocTagName = true;
|
||||
// The current position is next to the '@' sign, when no tag name being provided yet.
|
||||
// Provide a full list of tag names
|
||||
request = { kind: "JsDocTagName" };
|
||||
}
|
||||
else {
|
||||
// When completion is requested without "@", we will have check to make sure that
|
||||
@@ -388,17 +402,19 @@ namespace ts.Completions {
|
||||
// * |c|
|
||||
// */
|
||||
const lineStart = getLineStartPositionForPosition(position, sourceFile);
|
||||
requestJsDocTag = !(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/));
|
||||
if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) {
|
||||
request = { kind: "JsDocTag" };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Completion should work inside certain JsDoc tags. For example:
|
||||
// /** @type {number | string} */
|
||||
// Completion should work in the brackets
|
||||
const tag = getJsDocTagAtPosition(sourceFile, position);
|
||||
const tag = getJsDocTagAtPosition(currentToken, position);
|
||||
if (tag) {
|
||||
if (tag.tagName.pos <= position && position <= tag.tagName.end) {
|
||||
requestJsDocTagName = true;
|
||||
request = { kind: "JsDocTagName" };
|
||||
}
|
||||
if (isTagWithTypeExpression(tag) && tag.typeExpression) {
|
||||
currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
@@ -410,10 +426,13 @@ namespace ts.Completions {
|
||||
insideJsDocTagTypeExpression = isCurrentlyEditingNode(tag.typeExpression);
|
||||
}
|
||||
}
|
||||
if (isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) {
|
||||
request = { kind: "JsDocParameterName", tag };
|
||||
}
|
||||
}
|
||||
|
||||
if (requestJsDocTagName || requestJsDocTag) {
|
||||
return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords: false };
|
||||
if (request) {
|
||||
return { symbols: undefined, isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, location: undefined, isRightOfDot: false, request, hasFilteredClassMemberKeywords: false };
|
||||
}
|
||||
|
||||
if (!insideJsDocTagTypeExpression) {
|
||||
@@ -494,7 +513,7 @@ namespace ts.Completions {
|
||||
// It has a left-hand side, so we're not in an opening JSX tag.
|
||||
break;
|
||||
}
|
||||
// falls through
|
||||
// falls through
|
||||
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.JsxElement:
|
||||
@@ -550,7 +569,7 @@ namespace ts.Completions {
|
||||
|
||||
log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
|
||||
|
||||
return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), requestJsDocTagName, requestJsDocTag, hasFilteredClassMemberKeywords };
|
||||
return { symbols, isGlobalCompletion, isMemberCompletion, isNewIdentifierLocation, location, isRightOfDot: (isRightOfDot || isRightOfOpenTag), request, hasFilteredClassMemberKeywords };
|
||||
|
||||
type JSDocTagWithTypeExpression = JSDocAugmentsTag | JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag;
|
||||
|
||||
@@ -923,7 +942,7 @@ namespace ts.Completions {
|
||||
*
|
||||
* @returns true if 'symbols' was successfully populated; false otherwise.
|
||||
*/
|
||||
function tryGetObjectLikeCompletionSymbols(objectLikeContainer: ObjectLiteralExpression | BindingPattern): boolean {
|
||||
function tryGetObjectLikeCompletionSymbols(objectLikeContainer: ObjectLiteralExpression | ObjectBindingPattern): boolean {
|
||||
// We're looking up possible property names from contextual/inferred/declared type.
|
||||
isMemberCompletion = true;
|
||||
|
||||
@@ -939,41 +958,36 @@ namespace ts.Completions {
|
||||
typeMembers = typeChecker.getAllPossiblePropertiesOfType(typeForObject);
|
||||
existingMembers = (<ObjectLiteralExpression>objectLikeContainer).properties;
|
||||
}
|
||||
else if (objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
else {
|
||||
Debug.assert(objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern);
|
||||
// We are *only* completing on properties from the type being destructured.
|
||||
isNewIdentifierLocation = false;
|
||||
|
||||
const rootDeclaration = getRootDeclaration(objectLikeContainer.parent);
|
||||
if (isVariableLike(rootDeclaration)) {
|
||||
// We don't want to complete using the type acquired by the shape
|
||||
// of the binding pattern; we are only interested in types acquired
|
||||
// through type declaration or inference.
|
||||
// Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
|
||||
// type of parameter will flow in from the contextual type of the function
|
||||
let canGetType = !!(rootDeclaration.initializer || rootDeclaration.type);
|
||||
if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) {
|
||||
if (isExpression(rootDeclaration.parent)) {
|
||||
canGetType = !!typeChecker.getContextualType(<Expression>rootDeclaration.parent);
|
||||
}
|
||||
else if (rootDeclaration.parent.kind === SyntaxKind.MethodDeclaration || rootDeclaration.parent.kind === SyntaxKind.SetAccessor) {
|
||||
canGetType = isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(<Expression>rootDeclaration.parent.parent);
|
||||
}
|
||||
if (!isVariableLike(rootDeclaration)) throw Debug.fail("Root declaration is not variable-like.");
|
||||
|
||||
// We don't want to complete using the type acquired by the shape
|
||||
// of the binding pattern; we are only interested in types acquired
|
||||
// through type declaration or inference.
|
||||
// Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
|
||||
// type of parameter will flow in from the contextual type of the function
|
||||
let canGetType = rootDeclaration.initializer || rootDeclaration.type || rootDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement;
|
||||
if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) {
|
||||
if (isExpression(rootDeclaration.parent)) {
|
||||
canGetType = !!typeChecker.getContextualType(<Expression>rootDeclaration.parent);
|
||||
}
|
||||
if (canGetType) {
|
||||
const typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
|
||||
if (!typeForObject) return false;
|
||||
// In a binding pattern, get only known properties. Everywhere else we will get all possible properties.
|
||||
typeMembers = typeChecker.getPropertiesOfType(typeForObject);
|
||||
existingMembers = (<ObjectBindingPattern>objectLikeContainer).elements;
|
||||
else if (rootDeclaration.parent.kind === SyntaxKind.MethodDeclaration || rootDeclaration.parent.kind === SyntaxKind.SetAccessor) {
|
||||
canGetType = isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(<Expression>rootDeclaration.parent.parent);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.fail("Root declaration is not variable-like.");
|
||||
if (canGetType) {
|
||||
const typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
|
||||
if (!typeForObject) return false;
|
||||
// In a binding pattern, get only known properties. Everywhere else we will get all possible properties.
|
||||
typeMembers = typeChecker.getPropertiesOfType(typeForObject);
|
||||
existingMembers = (<ObjectBindingPattern>objectLikeContainer).elements;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind);
|
||||
}
|
||||
|
||||
if (typeMembers && typeMembers.length > 0) {
|
||||
// Add filtered items to the completion list
|
||||
@@ -1082,14 +1096,14 @@ namespace ts.Completions {
|
||||
* Returns the immediate owning object literal or binding pattern of a context token,
|
||||
* on the condition that one exists and that the context implies completion should be given.
|
||||
*/
|
||||
function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | BindingPattern {
|
||||
function tryGetObjectLikeCompletionContainer(contextToken: Node): ObjectLiteralExpression | ObjectBindingPattern {
|
||||
if (contextToken) {
|
||||
switch (contextToken.kind) {
|
||||
case SyntaxKind.OpenBraceToken: // const x = { |
|
||||
case SyntaxKind.CommaToken: // const x = { a: 0, |
|
||||
const parent = contextToken.parent;
|
||||
if (parent && (parent.kind === SyntaxKind.ObjectLiteralExpression || parent.kind === SyntaxKind.ObjectBindingPattern)) {
|
||||
return <ObjectLiteralExpression | BindingPattern>parent;
|
||||
if (isObjectLiteralExpression(parent) || isObjectBindingPattern(parent)) {
|
||||
return parent;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1148,7 +1162,7 @@ namespace ts.Completions {
|
||||
default:
|
||||
if (isFromClassElementDeclaration(contextToken) &&
|
||||
(isClassMemberCompletionKeyword(contextToken.kind) ||
|
||||
isClassMemberCompletionKeywordText(contextToken.getText()))) {
|
||||
isClassMemberCompletionKeywordText(contextToken.getText()))) {
|
||||
return contextToken.parent.parent as ClassLikeDeclaration;
|
||||
}
|
||||
}
|
||||
@@ -1296,7 +1310,7 @@ namespace ts.Completions {
|
||||
if (isFromClassElementDeclaration(contextToken)) {
|
||||
return false;
|
||||
}
|
||||
// falls through
|
||||
// falls through
|
||||
case SyntaxKind.ClassKeyword:
|
||||
case SyntaxKind.EnumKeyword:
|
||||
case SyntaxKind.InterfaceKeyword:
|
||||
@@ -1603,4 +1617,34 @@ namespace ts.Completions {
|
||||
kind === SyntaxKind.EqualsEqualsEqualsToken ||
|
||||
kind === SyntaxKind.ExclamationEqualsEqualsToken;
|
||||
}
|
||||
|
||||
/** Get the corresponding JSDocTag node if the position is in a jsDoc comment */
|
||||
function getJsDocTagAtPosition(node: Node, position: number): JSDocTag | undefined {
|
||||
const { jsDoc } = getJsDocHavingNode(node);
|
||||
if (!jsDoc) return undefined;
|
||||
|
||||
for (const { pos, end, tags } of jsDoc) {
|
||||
if (!tags || position < pos || position > end) continue;
|
||||
for (let i = tags.length - 1; i >= 0; i--) {
|
||||
const tag = tags[i];
|
||||
if (position >= tag.pos) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getJsDocHavingNode(node: Node): Node {
|
||||
if (!isToken(node)) return node;
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VarKeyword:
|
||||
case SyntaxKind.LetKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
// if the current token is var, let or const, skip the VariableDeclarationList
|
||||
return node.parent.parent;
|
||||
default:
|
||||
return node.parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
/* @internal */
|
||||
namespace ts.DocumentHighlights {
|
||||
export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
|
||||
export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] | undefined {
|
||||
const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
return node && (getSemanticDocumentHighlights(node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile));
|
||||
if (!node) return undefined;
|
||||
|
||||
if (isJsxOpeningElement(node.parent) && node.parent.tagName === node || isJsxClosingElement(node.parent)) {
|
||||
// For a JSX element, just highlight the matching tag, not all references.
|
||||
const { openingElement, closingElement } = node.parent.parent;
|
||||
const highlightSpans = [openingElement, closingElement].map(({ tagName }) => getHighlightSpanForNode(tagName, sourceFile));
|
||||
return [{ fileName: sourceFile.fileName, highlightSpans }];
|
||||
}
|
||||
|
||||
return getSemanticDocumentHighlights(node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile);
|
||||
}
|
||||
|
||||
function getHighlightSpanForNode(node: Node, sourceFile: SourceFile): HighlightSpan {
|
||||
const start = node.getStart(sourceFile);
|
||||
const end = node.getEnd();
|
||||
|
||||
return {
|
||||
fileName: sourceFile.fileName,
|
||||
textSpan: createTextSpanFromBounds(start, end),
|
||||
textSpan: createTextSpanFromNode(node, sourceFile),
|
||||
kind: HighlightSpanKind.none
|
||||
};
|
||||
}
|
||||
|
||||
@@ -185,7 +185,8 @@ namespace ts.FindAllReferences {
|
||||
if (entry.type === "node") {
|
||||
const { node } = entry;
|
||||
return { textSpan: getTextSpan(node), fileName: node.getSourceFile().fileName, ...implementationKindDisplayParts(node, checker) };
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
const { textSpan, fileName } = entry;
|
||||
return { textSpan, fileName, kind: ScriptElementKind.unknown, displayParts: [] };
|
||||
}
|
||||
@@ -495,11 +496,10 @@ namespace ts.FindAllReferences.Core {
|
||||
const { text = stripQuotes(getDeclaredName(this.checker, symbol, location)), allSearchSymbols = undefined } = searchOptions;
|
||||
const escapedText = escapeIdentifier(text);
|
||||
const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker);
|
||||
return { location, symbol, comingFrom, text, escapedText, parents, includes };
|
||||
|
||||
function includes(referenceSymbol: Symbol): boolean {
|
||||
return allSearchSymbols ? contains(allSearchSymbols, referenceSymbol) : referenceSymbol === symbol;
|
||||
}
|
||||
return {
|
||||
location, symbol, comingFrom, text, escapedText, parents,
|
||||
includes: referenceSymbol => allSearchSymbols ? contains(allSearchSymbols, referenceSymbol) : referenceSymbol === symbol,
|
||||
};
|
||||
}
|
||||
|
||||
private readonly symbolIdToReferences: Entry[][] = [];
|
||||
@@ -678,9 +678,7 @@ namespace ts.FindAllReferences.Core {
|
||||
return parent ? scope.getSourceFile() : scope;
|
||||
}
|
||||
|
||||
function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile, fullStart = false): number[] {
|
||||
const start = fullStart ? container.getFullStart() : container.getStart(sourceFile);
|
||||
const end = container.getEnd();
|
||||
function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): number[] {
|
||||
const positions: number[] = [];
|
||||
|
||||
/// TODO: Cache symbol existence for files to save text search
|
||||
@@ -695,10 +693,10 @@ namespace ts.FindAllReferences.Core {
|
||||
const sourceLength = text.length;
|
||||
const symbolNameLength = symbolName.length;
|
||||
|
||||
let position = text.indexOf(symbolName, start);
|
||||
let position = text.indexOf(symbolName, container.pos);
|
||||
while (position >= 0) {
|
||||
// If we are past the end, stop looking
|
||||
if (position > end) break;
|
||||
if (position > container.end) break;
|
||||
|
||||
// We found a match. Make sure it's not part of a larger word (i.e. the char
|
||||
// before and after it have to be a non-identifier char).
|
||||
@@ -759,8 +757,7 @@ namespace ts.FindAllReferences.Core {
|
||||
}
|
||||
|
||||
function addReferencesForKeywordInFile(sourceFile: SourceFile, kind: SyntaxKind, searchText: string, references: Push<NodeEntry>): void {
|
||||
// Want fullStart so we can find the symbol in JSDoc comments
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, sourceFile, /*fullStart*/ true);
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, sourceFile);
|
||||
for (const position of possiblePositions) {
|
||||
const referenceLocation = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
if (referenceLocation.kind === kind) {
|
||||
@@ -784,8 +781,7 @@ namespace ts.FindAllReferences.Core {
|
||||
return;
|
||||
}
|
||||
|
||||
const fullStart = state.options.findInComments || container.jsDoc !== undefined || forEach(search.symbol.declarations, d => d.kind === ts.SyntaxKind.JSDocTypedefTag);
|
||||
for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container, fullStart)) {
|
||||
for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container)) {
|
||||
getReferencesAtLocation(sourceFile, position, search, state);
|
||||
}
|
||||
}
|
||||
|
||||
+127
-91
@@ -73,54 +73,56 @@ namespace ts.FindAllReferences {
|
||||
|
||||
function handleDirectImports(exportingModuleSymbol: Symbol): void {
|
||||
const theseDirectImports = getDirectImports(exportingModuleSymbol);
|
||||
if (theseDirectImports) for (const direct of theseDirectImports) {
|
||||
if (!markSeenDirectImport(direct)) {
|
||||
continue;
|
||||
}
|
||||
if (theseDirectImports) {
|
||||
for (const direct of theseDirectImports) {
|
||||
if (!markSeenDirectImport(direct)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
switch (direct.kind) {
|
||||
case SyntaxKind.CallExpression:
|
||||
if (!isAvailableThroughGlobal) {
|
||||
const parent = direct.parent!;
|
||||
if (exportKind === ExportKind.ExportEquals && parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
const { name } = parent as ts.VariableDeclaration;
|
||||
if (name.kind === SyntaxKind.Identifier) {
|
||||
directImports.push(name);
|
||||
break;
|
||||
switch (direct.kind) {
|
||||
case SyntaxKind.CallExpression:
|
||||
if (!isAvailableThroughGlobal) {
|
||||
const parent = direct.parent!;
|
||||
if (exportKind === ExportKind.ExportEquals && parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
const { name } = parent as ts.VariableDeclaration;
|
||||
if (name.kind === SyntaxKind.Identifier) {
|
||||
directImports.push(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't support re-exporting 'require()' calls, so just add a single indirect user.
|
||||
addIndirectUser(direct.getSourceFile());
|
||||
}
|
||||
break;
|
||||
|
||||
// Don't support re-exporting 'require()' calls, so just add a single indirect user.
|
||||
addIndirectUser(direct.getSourceFile());
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
handleNamespaceImport(direct, direct.name, hasModifier(direct, ModifierFlags.Export));
|
||||
break;
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
handleNamespaceImport(direct, direct.name, hasModifier(direct, ModifierFlags.Export));
|
||||
break;
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
const namedBindings = direct.importClause && direct.importClause.namedBindings;
|
||||
if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) {
|
||||
handleNamespaceImport(direct, namedBindings.name);
|
||||
}
|
||||
else {
|
||||
directImports.push(direct);
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
const namedBindings = direct.importClause && direct.importClause.namedBindings;
|
||||
if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) {
|
||||
handleNamespaceImport(direct, namedBindings.name);
|
||||
}
|
||||
else {
|
||||
directImports.push(direct);
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
if (!direct.exportClause) {
|
||||
// This is `export * from "foo"`, so imports of this module may import the export too.
|
||||
handleDirectImports(getContainingModuleSymbol(direct, checker));
|
||||
}
|
||||
else {
|
||||
// This is `export { foo } from "foo"` and creates an alias symbol, so recursive search will get handle re-exports.
|
||||
directImports.push(direct);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
if (!direct.exportClause) {
|
||||
// This is `export * from "foo"`, so imports of this module may import the export too.
|
||||
handleDirectImports(getContainingModuleSymbol(direct, checker));
|
||||
}
|
||||
else {
|
||||
// This is `export { foo } from "foo"` and creates an alias symbol, so recursive search will get handle re-exports.
|
||||
directImports.push(direct);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,8 +162,10 @@ namespace ts.FindAllReferences {
|
||||
const moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol);
|
||||
Debug.assert(!!(moduleSymbol.flags & SymbolFlags.Module));
|
||||
const directImports = getDirectImports(moduleSymbol);
|
||||
if (directImports) for (const directImport of directImports) {
|
||||
addIndirectUsers(getSourceFileLikeForImportDeclaration(directImport));
|
||||
if (directImports) {
|
||||
for (const directImport of directImports) {
|
||||
addIndirectUsers(getSourceFileLikeForImportDeclaration(directImport));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,8 +187,10 @@ namespace ts.FindAllReferences {
|
||||
importSearches.push([location, symbol]);
|
||||
}
|
||||
|
||||
if (directImports) for (const decl of directImports) {
|
||||
handleImport(decl);
|
||||
if (directImports) {
|
||||
for (const decl of directImports) {
|
||||
handleImport(decl);
|
||||
}
|
||||
}
|
||||
|
||||
return { importSearches, singleReferences };
|
||||
@@ -258,25 +264,27 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
function searchForNamedImport(namedBindings: NamedImportsOrExports | undefined): void {
|
||||
if (namedBindings) for (const element of namedBindings.elements) {
|
||||
const { name, propertyName } = element;
|
||||
if ((propertyName || name).text !== exportName) {
|
||||
continue;
|
||||
}
|
||||
if (namedBindings) {
|
||||
for (const element of namedBindings.elements) {
|
||||
const { name, propertyName } = element;
|
||||
if ((propertyName || name).text !== exportName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (propertyName) {
|
||||
// This is `import { foo as bar } from "./a"` or `export { foo as bar } from "./a"`. `foo` isn't a local in the file, so just add it as a single reference.
|
||||
singleReferences.push(propertyName);
|
||||
if (!isForRename) { // If renaming `foo`, don't touch `bar`, just `foo`.
|
||||
// Search locally for `bar`.
|
||||
addSearch(name, checker.getSymbolAtLocation(name));
|
||||
if (propertyName) {
|
||||
// This is `import { foo as bar } from "./a"` or `export { foo as bar } from "./a"`. `foo` isn't a local in the file, so just add it as a single reference.
|
||||
singleReferences.push(propertyName);
|
||||
if (!isForRename) { // If renaming `foo`, don't touch `bar`, just `foo`.
|
||||
// Search locally for `bar`.
|
||||
addSearch(name, checker.getSymbolAtLocation(name));
|
||||
}
|
||||
}
|
||||
else {
|
||||
const localSymbol = element.kind === SyntaxKind.ExportSpecifier && element.propertyName
|
||||
? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol.
|
||||
: checker.getSymbolAtLocation(name);
|
||||
addSearch(name, localSymbol);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const localSymbol = element.kind === SyntaxKind.ExportSpecifier && element.propertyName
|
||||
? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol.
|
||||
: checker.getSymbolAtLocation(name);
|
||||
addSearch(name, localSymbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -436,8 +444,8 @@ namespace ts.FindAllReferences {
|
||||
if (parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
// When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use.
|
||||
// So check that we are at the declaration.
|
||||
return symbol.declarations.some(d => d === parent) && parent.parent.kind === ts.SyntaxKind.BinaryExpression
|
||||
? getSpecialPropertyExport(parent.parent as ts.BinaryExpression, /*useLhsSymbol*/ false)
|
||||
return symbol.declarations.some(d => d === parent) && isBinaryExpression(parent.parent)
|
||||
? getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ false)
|
||||
: undefined;
|
||||
}
|
||||
else {
|
||||
@@ -449,31 +457,41 @@ namespace ts.FindAllReferences {
|
||||
else {
|
||||
const exportNode = getExportNode(parent);
|
||||
if (exportNode && hasModifier(exportNode, ModifierFlags.Export)) {
|
||||
if (exportNode.kind === SyntaxKind.ImportEqualsDeclaration && (exportNode as ImportEqualsDeclaration).moduleReference === node) {
|
||||
if (isImportEqualsDeclaration(exportNode) && exportNode.moduleReference === node) {
|
||||
// We're at `Y` in `export import X = Y`. This is not the exported symbol, the left-hand-side is. So treat this as an import statement.
|
||||
if (comingFromExport) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const lhsSymbol = checker.getSymbolAtLocation((exportNode as ImportEqualsDeclaration).name);
|
||||
const lhsSymbol = checker.getSymbolAtLocation(exportNode.name);
|
||||
return { kind: ImportExport.Import, symbol: lhsSymbol, isNamedImport: false };
|
||||
}
|
||||
else {
|
||||
return exportInfo(symbol, getExportKindForDeclaration(exportNode));
|
||||
}
|
||||
}
|
||||
else if (parent.kind === SyntaxKind.ExportAssignment) {
|
||||
// Get the symbol for the `export =` node; its parent is the module it's the export of.
|
||||
const exportingModuleSymbol = parent.symbol.parent;
|
||||
Debug.assert(!!exportingModuleSymbol);
|
||||
return { kind: ImportExport.Export, symbol, exportInfo: { exportingModuleSymbol, exportKind: ExportKind.ExportEquals } };
|
||||
// If we are in `export = a;`, `parent` is the export assignment.
|
||||
else if (isExportAssignment(parent)) {
|
||||
return getExportAssignmentExport(parent);
|
||||
}
|
||||
else if (parent.kind === ts.SyntaxKind.BinaryExpression) {
|
||||
return getSpecialPropertyExport(parent as ts.BinaryExpression, /*useLhsSymbol*/ true);
|
||||
// If we are in `export = class A {};` at `A`, `parent.parent` is the export assignment.
|
||||
else if (isExportAssignment(parent.parent)) {
|
||||
return getExportAssignmentExport(parent.parent);
|
||||
}
|
||||
else if (parent.parent.kind === SyntaxKind.BinaryExpression) {
|
||||
return getSpecialPropertyExport(parent.parent as ts.BinaryExpression, /*useLhsSymbol*/ true);
|
||||
// Similar for `module.exports =` and `exports.A =`.
|
||||
else if (isBinaryExpression(parent)) {
|
||||
return getSpecialPropertyExport(parent, /*useLhsSymbol*/ true);
|
||||
}
|
||||
else if (isBinaryExpression(parent.parent)) {
|
||||
return getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
function getExportAssignmentExport(ex: ExportAssignment): ExportedSymbol {
|
||||
// Get the symbol for the `export =` node; its parent is the module it's the export of.
|
||||
const exportingModuleSymbol = ex.symbol.parent;
|
||||
Debug.assert(!!exportingModuleSymbol);
|
||||
return { kind: ImportExport.Export, symbol, exportInfo: { exportingModuleSymbol, exportKind: ExportKind.ExportEquals } };
|
||||
}
|
||||
|
||||
function getSpecialPropertyExport(node: ts.BinaryExpression, useLhsSymbol: boolean): ExportedSymbol | undefined {
|
||||
@@ -496,21 +514,21 @@ namespace ts.FindAllReferences {
|
||||
|
||||
function getImport(): ImportedSymbol | undefined {
|
||||
const isImport = isNodeImport(node);
|
||||
if (!isImport) return;
|
||||
if (!isImport) return undefined;
|
||||
|
||||
// A symbol being imported is always an alias. So get what that aliases to find the local symbol.
|
||||
let importedSymbol = checker.getImmediateAliasedSymbol(symbol);
|
||||
if (importedSymbol) {
|
||||
// Search on the local symbol in the exporting module, not the exported symbol.
|
||||
importedSymbol = skipExportSpecifierSymbol(importedSymbol, checker);
|
||||
// Similarly, skip past the symbol for 'export ='
|
||||
if (importedSymbol.name === "export=") {
|
||||
importedSymbol = checker.getImmediateAliasedSymbol(importedSymbol);
|
||||
}
|
||||
if (!importedSymbol) return undefined;
|
||||
|
||||
if (symbolName(importedSymbol) === symbol.name) { // If this is a rename import, do not continue searching.
|
||||
return { kind: ImportExport.Import, symbol: importedSymbol, ...isImport };
|
||||
}
|
||||
// Search on the local symbol in the exporting module, not the exported symbol.
|
||||
importedSymbol = skipExportSpecifierSymbol(importedSymbol, checker);
|
||||
// Similarly, skip past the symbol for 'export ='
|
||||
if (importedSymbol.name === "export=") {
|
||||
importedSymbol = getExportEqualsLocalSymbol(importedSymbol, checker);
|
||||
}
|
||||
|
||||
if (symbolName(importedSymbol) === symbol.name) { // If this is a rename import, do not continue searching.
|
||||
return { kind: ImportExport.Import, symbol: importedSymbol, ...isImport };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,12 +543,29 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
function getExportEqualsLocalSymbol(importedSymbol: Symbol, checker: TypeChecker): Symbol {
|
||||
if (importedSymbol.flags & SymbolFlags.Alias) {
|
||||
return checker.getImmediateAliasedSymbol(importedSymbol);
|
||||
}
|
||||
|
||||
const decl = importedSymbol.valueDeclaration;
|
||||
if (isExportAssignment(decl)) { // `export = class {}`
|
||||
return decl.expression.symbol;
|
||||
}
|
||||
else if (isBinaryExpression(decl)) { // `module.exports = class {}`
|
||||
return decl.right.symbol;
|
||||
}
|
||||
Debug.fail();
|
||||
}
|
||||
|
||||
// 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 | undefined {
|
||||
if (parent.kind === SyntaxKind.VariableDeclaration) {
|
||||
const p = parent as ts.VariableDeclaration;
|
||||
return p.parent.kind === ts.SyntaxKind.CatchClause ? undefined : p.parent.parent.kind === SyntaxKind.VariableStatement ? p.parent.parent : undefined;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
@@ -577,12 +612,13 @@ namespace ts.FindAllReferences {
|
||||
/** If at an export specifier, go to the symbol it refers to. */
|
||||
function skipExportSpecifierSymbol(symbol: Symbol, checker: TypeChecker): Symbol {
|
||||
// For `export { foo } from './bar", there's nothing to skip, because it does not create a new alias. But `export { foo } does.
|
||||
if (symbol.declarations) for (const declaration of symbol.declarations) {
|
||||
if (isExportSpecifier(declaration) && !(declaration as ExportSpecifier).propertyName && !(declaration as ExportSpecifier).parent.parent.moduleSpecifier) {
|
||||
return checker.getExportSpecifierLocalTargetSymbol(declaration);
|
||||
if (symbol.declarations) {
|
||||
for (const declaration of symbol.declarations) {
|
||||
if (isExportSpecifier(declaration) && !(declaration as ExportSpecifier).propertyName && !(declaration as ExportSpecifier).parent.parent.moduleSpecifier) {
|
||||
return checker.getExportSpecifierLocalTargetSymbol(declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,25 @@ namespace ts.JsDoc {
|
||||
}));
|
||||
}
|
||||
|
||||
export function getJSDocParameterNameCompletions(tag: JSDocParameterTag): CompletionEntry[] {
|
||||
const nameThusFar = tag.name.text;
|
||||
const jsdoc = tag.parent;
|
||||
const fn = jsdoc.parent;
|
||||
if (!ts.isFunctionLike(fn)) return [];
|
||||
|
||||
return mapDefined(fn.parameters, param => {
|
||||
if (!isIdentifier(param.name)) return undefined;
|
||||
|
||||
const name = param.name.text;
|
||||
if (jsdoc.tags.some(t => t !== tag && isJSDocParameterTag(t) && t.name.text === name)
|
||||
|| nameThusFar !== undefined && !startsWith(name, nameThusFar)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return { name, kind: ScriptElementKind.parameterElement, kindModifiers: "", sortText: "0" };
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if position points to a valid position to add JSDoc comments, and if so,
|
||||
* returns the appropriate template. Otherwise returns an empty string.
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace ts.JsTyping {
|
||||
/**
|
||||
* Merge a given list of typingNames to the inferredTypings map
|
||||
*/
|
||||
function mergeTypings(typingNames: string[]) {
|
||||
function mergeTypings(typingNames: ReadonlyArray<string>) {
|
||||
if (!typingNames) {
|
||||
return;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ namespace ts.JsTyping {
|
||||
const cleanedTypingNames = map(inferredTypingNames, f => f.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""));
|
||||
|
||||
if (safeList !== EmptySafeList) {
|
||||
mergeTypings(filter(cleanedTypingNames, f => safeList.has(f)));
|
||||
mergeTypings(ts.mapDefined(cleanedTypingNames, f => safeList.get(f)));
|
||||
}
|
||||
|
||||
const hasJsxFile = forEach(fileNames, f => ensureScriptKind(f, getScriptKindFromFileName(f)) === ScriptKind.JSX);
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace ts.NavigateTo {
|
||||
for (const sourceFile of sourceFiles) {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
if (excludeDtsFiles && fileExtensionIs(sourceFile.fileName, ".d.ts")) {
|
||||
if (excludeDtsFiles && fileExtensionIs(sourceFile.fileName, Extension.Dts)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,9 +95,16 @@ namespace ts {
|
||||
function tryConsumeImport(): boolean {
|
||||
let token = scanner.getToken();
|
||||
if (token === SyntaxKind.ImportKeyword) {
|
||||
|
||||
token = nextToken();
|
||||
if (token === SyntaxKind.StringLiteral) {
|
||||
if (token === SyntaxKind.OpenParenToken) {
|
||||
token = nextToken();
|
||||
if (token === SyntaxKind.StringLiteral) {
|
||||
// import("mod");
|
||||
recordModuleName();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (token === SyntaxKind.StringLiteral) {
|
||||
// import "mod";
|
||||
recordModuleName();
|
||||
return true;
|
||||
@@ -297,7 +304,8 @@ namespace ts {
|
||||
// import * as NS from "mod"
|
||||
// import d, {a, b as B} from "mod"
|
||||
// import i = require("mod");
|
||||
//
|
||||
// import("mod");
|
||||
|
||||
// export * from "mod"
|
||||
// export {a as b} from "mod"
|
||||
// export import i = require("mod")
|
||||
|
||||
@@ -8,10 +8,10 @@ namespace ts {
|
||||
description: string;
|
||||
|
||||
/** Compute the associated code actions */
|
||||
getCodeActions(context: RefactorContext): CodeAction[];
|
||||
getEditsForAction(context: RefactorContext, actionName: string): RefactorEditInfo | undefined;
|
||||
|
||||
/** A fast syntactic check to see if the refactor is applicable at given position. */
|
||||
isApplicable(context: RefactorContext): boolean;
|
||||
/** Compute (quickly) which actions are available here */
|
||||
getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined;
|
||||
}
|
||||
|
||||
export interface RefactorContext {
|
||||
@@ -34,7 +34,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function getApplicableRefactors(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
|
||||
|
||||
let results: ApplicableRefactorInfo[];
|
||||
const refactorList: Refactor[] = [];
|
||||
refactors.forEach(refactor => {
|
||||
@@ -44,26 +43,17 @@ namespace ts {
|
||||
if (context.cancellationToken && context.cancellationToken.isCancellationRequested()) {
|
||||
return results;
|
||||
}
|
||||
if (refactor.isApplicable(context)) {
|
||||
(results || (results = [])).push({ name: refactor.name, description: refactor.description });
|
||||
const infos = refactor.getAvailableActions(context);
|
||||
if (infos && infos.length) {
|
||||
(results || (results = [])).push(...infos);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
export function getRefactorCodeActions(context: RefactorContext, refactorName: string): CodeAction[] | undefined {
|
||||
|
||||
let result: CodeAction[];
|
||||
export function getEditsForRefactor(context: RefactorContext, refactorName: string, actionName: string): RefactorEditInfo | undefined {
|
||||
const refactor = refactors.get(refactorName);
|
||||
if (!refactor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const codeActions = refactor.getCodeActions(context);
|
||||
if (codeActions) {
|
||||
addRange((result || (result = [])), codeActions);
|
||||
}
|
||||
return result;
|
||||
return refactor && refactor.getEditsForAction(context, actionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
/* @internal */
|
||||
|
||||
namespace ts.refactor {
|
||||
const actionName = "convert";
|
||||
|
||||
const convertFunctionToES6Class: Refactor = {
|
||||
name: "Convert to ES2015 class",
|
||||
description: Diagnostics.Convert_function_to_an_ES2015_class.message,
|
||||
getCodeActions,
|
||||
isApplicable
|
||||
getEditsForAction,
|
||||
getAvailableActions
|
||||
};
|
||||
|
||||
registerRefactor(convertFunctionToES6Class);
|
||||
|
||||
function isApplicable(context: RefactorContext): boolean {
|
||||
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] {
|
||||
const start = context.startPosition;
|
||||
const node = getTokenAtPosition(context.file, start, /*includeJsDocComment*/ false);
|
||||
const checker = context.program.getTypeChecker();
|
||||
@@ -20,10 +22,28 @@ namespace ts.refactor {
|
||||
symbol = (symbol.valueDeclaration as VariableDeclaration).initializer.symbol;
|
||||
}
|
||||
|
||||
return symbol && symbol.flags & SymbolFlags.Function && symbol.members && symbol.members.size > 0;
|
||||
if (symbol && (symbol.flags & SymbolFlags.Function) && symbol.members && (symbol.members.size > 0)) {
|
||||
return [
|
||||
{
|
||||
name: convertFunctionToES6Class.name,
|
||||
description: convertFunctionToES6Class.description,
|
||||
actions: [
|
||||
{
|
||||
description: convertFunctionToES6Class.description,
|
||||
name: actionName
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
function getCodeActions(context: RefactorContext): CodeAction[] | undefined {
|
||||
function getEditsForAction(context: RefactorContext, action: string): RefactorEditInfo | undefined {
|
||||
// Somehow wrong action got invoked?
|
||||
if (actionName !== action) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const start = context.startPosition;
|
||||
const sourceFile = context.file;
|
||||
const checker = context.program.getTypeChecker();
|
||||
@@ -35,7 +55,7 @@ namespace ts.refactor {
|
||||
const deletes: (() => any)[] = [];
|
||||
|
||||
if (!(ctorSymbol.flags & (SymbolFlags.Function | SymbolFlags.Variable))) {
|
||||
return [];
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const ctorDeclaration = ctorSymbol.valueDeclaration;
|
||||
@@ -63,7 +83,7 @@ namespace ts.refactor {
|
||||
}
|
||||
|
||||
if (!newClassDeclaration) {
|
||||
return [];
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Because the preceding node could be touched, we need to insert nodes before delete nodes.
|
||||
@@ -72,10 +92,9 @@ namespace ts.refactor {
|
||||
deleteCallback();
|
||||
}
|
||||
|
||||
return [{
|
||||
description: formatStringFromArgs(Diagnostics.Convert_function_0_to_class.message, [ctorSymbol.name]),
|
||||
changes: changeTracker.getChanges()
|
||||
}];
|
||||
return {
|
||||
edits: changeTracker.getChanges()
|
||||
};
|
||||
|
||||
function deleteNode(node: Node, inList = false) {
|
||||
if (deletedNodes.some(n => isNodeDescendantOf(node, n))) {
|
||||
|
||||
+59
-50
@@ -37,7 +37,7 @@ namespace ts {
|
||||
let ruleProvider: formatting.RulesProvider;
|
||||
|
||||
function createNode<TKind extends SyntaxKind>(kind: TKind, pos: number, end: number, parent?: Node): NodeObject | TokenObject<TKind> | IdentifierObject {
|
||||
const node = kind >= SyntaxKind.FirstNode ? new NodeObject(kind, pos, end) :
|
||||
const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) :
|
||||
kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) :
|
||||
new TokenObject(kind, pos, end);
|
||||
node.parent = parent;
|
||||
@@ -103,10 +103,10 @@ namespace ts {
|
||||
return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd());
|
||||
}
|
||||
|
||||
private addSyntheticNodes(nodes: Node[], pos: number, end: number, useJSDocScanner?: boolean): number {
|
||||
private addSyntheticNodes(nodes: Node[], pos: number, end: number): number {
|
||||
scanner.setTextPos(pos);
|
||||
while (pos < end) {
|
||||
const token = useJSDocScanner ? scanner.scanJSDocToken() : scanner.scan();
|
||||
const token = scanner.scan();
|
||||
Debug.assert(token !== SyntaxKind.EndOfFileToken); // Else it would infinitely loop
|
||||
const textPos = scanner.getTextPos();
|
||||
if (textPos <= end) {
|
||||
@@ -136,54 +136,50 @@ namespace ts {
|
||||
}
|
||||
|
||||
private createChildren(sourceFile?: SourceFileLike) {
|
||||
if (isJSDocTag(this)) {
|
||||
if (!isNodeKind(this.kind)) {
|
||||
this._children = emptyArray;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isJSDocCommentContainingNode(this)) {
|
||||
/** Don't add trivia for "tokens" since this is in a comment. */
|
||||
const children: Node[] = [];
|
||||
this.forEachChild(child => { children.push(child); });
|
||||
this._children = children;
|
||||
return;
|
||||
}
|
||||
else if (this.kind >= SyntaxKind.FirstNode) {
|
||||
const children: Node[] = [];
|
||||
scanner.setText((sourceFile || this.getSourceFile()).text);
|
||||
let pos = this.pos;
|
||||
const useJSDocScanner = this.kind >= SyntaxKind.FirstJSDocTagNode && this.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
const processNode = (node: Node) => {
|
||||
const isJSDocTagNode = isJSDocTag(node);
|
||||
if (!isJSDocTagNode && pos < node.pos) {
|
||||
pos = this.addSyntheticNodes(children, pos, node.pos, useJSDocScanner);
|
||||
}
|
||||
children.push(node);
|
||||
if (!isJSDocTagNode) {
|
||||
pos = node.end;
|
||||
}
|
||||
};
|
||||
const processNodes = (nodes: NodeArray<Node>) => {
|
||||
if (pos < nodes.pos) {
|
||||
pos = this.addSyntheticNodes(children, pos, nodes.pos, useJSDocScanner);
|
||||
}
|
||||
children.push(this.createSyntaxList(nodes));
|
||||
pos = nodes.end;
|
||||
};
|
||||
// jsDocComments need to be the first children
|
||||
if (this.jsDoc) {
|
||||
for (const jsDocComment of this.jsDoc) {
|
||||
processNode(jsDocComment);
|
||||
}
|
||||
|
||||
const children: Node[] = [];
|
||||
scanner.setText((sourceFile || this.getSourceFile()).text);
|
||||
let pos = this.pos;
|
||||
const processNode = (node: Node) => {
|
||||
pos = this.addSyntheticNodes(children, pos, node.pos);
|
||||
children.push(node);
|
||||
pos = node.end;
|
||||
};
|
||||
const processNodes = (nodes: NodeArray<Node>) => {
|
||||
if (pos < nodes.pos) {
|
||||
pos = this.addSyntheticNodes(children, pos, nodes.pos);
|
||||
}
|
||||
// For syntactic classifications, all trivia are classcified together, including jsdoc comments.
|
||||
// For that to work, the jsdoc comments should still be the leading trivia of the first child.
|
||||
// Restoring the scanner position ensures that.
|
||||
pos = this.pos;
|
||||
forEachChild(this, processNode, processNodes);
|
||||
if (pos < this.end) {
|
||||
this.addSyntheticNodes(children, pos, this.end);
|
||||
children.push(this.createSyntaxList(nodes));
|
||||
pos = nodes.end;
|
||||
};
|
||||
// jsDocComments need to be the first children
|
||||
if (this.jsDoc) {
|
||||
for (const jsDocComment of this.jsDoc) {
|
||||
processNode(jsDocComment);
|
||||
}
|
||||
scanner.setText(undefined);
|
||||
this._children = children;
|
||||
}
|
||||
else {
|
||||
this._children = emptyArray;
|
||||
// For syntactic classifications, all trivia are classcified together, including jsdoc comments.
|
||||
// For that to work, the jsdoc comments should still be the leading trivia of the first child.
|
||||
// Restoring the scanner position ensures that.
|
||||
pos = this.pos;
|
||||
forEachChild(this, processNode, processNodes);
|
||||
if (pos < this.end) {
|
||||
this.addSyntheticNodes(children, pos, this.end);
|
||||
}
|
||||
scanner.setText(undefined);
|
||||
this._children = children;
|
||||
}
|
||||
|
||||
public getChildCount(sourceFile?: SourceFile): number {
|
||||
@@ -368,7 +364,7 @@ namespace ts {
|
||||
_primaryExpressionBrand: any;
|
||||
_memberExpressionBrand: any;
|
||||
_leftHandSideExpressionBrand: any;
|
||||
_incrementExpressionBrand: any;
|
||||
_updateExpressionBrand: any;
|
||||
_unaryExpressionBrand: any;
|
||||
_expressionBrand: any;
|
||||
/*@internal*/typeArguments: NodeArray<TypeNode>;
|
||||
@@ -521,6 +517,7 @@ namespace ts {
|
||||
private namedDeclarations: Map<Declaration[]>;
|
||||
public ambientModuleNames: string[];
|
||||
public checkJsDirective: CheckJsDirective | undefined;
|
||||
public possiblyContainDynamicImport: boolean;
|
||||
|
||||
constructor(kind: SyntaxKind, pos: number, end: number) {
|
||||
super(kind, pos, end);
|
||||
@@ -683,8 +680,9 @@ namespace ts {
|
||||
forEachChild(decl.name, visit);
|
||||
break;
|
||||
}
|
||||
if (decl.initializer)
|
||||
if (decl.initializer) {
|
||||
visit(decl.initializer);
|
||||
}
|
||||
}
|
||||
// falls through
|
||||
case SyntaxKind.EnumMember:
|
||||
@@ -731,6 +729,15 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
class SourceMapSourceObject implements SourceMapSource {
|
||||
lineMap: number[];
|
||||
constructor (public fileName: string, public text: string, public skipTrivia?: (pos: number) => number) {}
|
||||
|
||||
public getLineAndCharacterOfPosition(pos: number): LineAndCharacter {
|
||||
return ts.getLineAndCharacterOfPosition(this, pos);
|
||||
}
|
||||
}
|
||||
|
||||
function getServicesObjectAllocator(): ObjectAllocator {
|
||||
return {
|
||||
getNodeConstructor: () => NodeObject,
|
||||
@@ -741,6 +748,7 @@ namespace ts {
|
||||
getSymbolConstructor: () => SymbolObject,
|
||||
getTypeConstructor: () => TypeObject,
|
||||
getSignatureConstructor: () => SignatureObject,
|
||||
getSourceMapSourceConstructor: () => SourceMapSourceObject,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1988,15 +1996,16 @@ namespace ts {
|
||||
return refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange));
|
||||
}
|
||||
|
||||
function getRefactorCodeActions(
|
||||
function getEditsForRefactor(
|
||||
fileName: string,
|
||||
formatOptions: FormatCodeSettings,
|
||||
positionOrRange: number | TextRange,
|
||||
refactorName: string): CodeAction[] | undefined {
|
||||
refactorName: string,
|
||||
actionName: string): RefactorEditInfo {
|
||||
|
||||
synchronizeHostData();
|
||||
const file = getValidSourceFile(fileName);
|
||||
return refactor.getRefactorCodeActions(getRefactorContext(file, positionOrRange, formatOptions), refactorName);
|
||||
return refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, formatOptions), refactorName, actionName);
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -2004,8 +2013,6 @@ namespace ts {
|
||||
cleanupSemanticCache,
|
||||
getSyntacticDiagnostics,
|
||||
getSemanticDiagnostics,
|
||||
getApplicableRefactors,
|
||||
getRefactorCodeActions,
|
||||
getCompilerOptionsDiagnostics,
|
||||
getSyntacticClassifications,
|
||||
getSemanticClassifications,
|
||||
@@ -2043,7 +2050,9 @@ namespace ts {
|
||||
getEmitOutput,
|
||||
getNonBoundSourceFile,
|
||||
getSourceFile,
|
||||
getProgram
|
||||
getProgram,
|
||||
getApplicableRefactors,
|
||||
getEditsForRefactor,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ namespace ts.SymbolDisplay {
|
||||
export function getSymbolKind(typeChecker: TypeChecker, symbol: Symbol, location: Node): ScriptElementKind {
|
||||
const { flags } = symbol;
|
||||
|
||||
if (flags & SymbolFlags.Class) return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ?
|
||||
if (flags & SymbolFlags.Class) {
|
||||
return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ?
|
||||
ScriptElementKind.localClassElement : ScriptElementKind.classElement;
|
||||
}
|
||||
if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
|
||||
if (flags & SymbolFlags.TypeAlias) return ScriptElementKind.typeElement;
|
||||
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
|
||||
|
||||
+55
-1
@@ -71,6 +71,10 @@ namespace ts {
|
||||
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
|
||||
}
|
||||
|
||||
export interface SourceMapSource {
|
||||
getLineAndCharacterOfPosition(pos: number): LineAndCharacter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an immutable snapshot of a script at a specified time.Once acquired, the
|
||||
* snapshot is observably immutable. i.e. the same calls with the same parameters will return
|
||||
@@ -261,8 +265,9 @@ namespace ts {
|
||||
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean;
|
||||
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: FormatCodeSettings): CodeAction[];
|
||||
|
||||
getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange): ApplicableRefactorInfo[];
|
||||
getRefactorCodeActions(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string): CodeAction[] | undefined;
|
||||
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string): RefactorEditInfo | undefined;
|
||||
|
||||
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
|
||||
|
||||
@@ -353,11 +358,60 @@ namespace ts {
|
||||
changes: FileTextChanges[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of one or more available refactoring actions, grouped under a parent refactoring.
|
||||
*/
|
||||
export interface ApplicableRefactorInfo {
|
||||
/**
|
||||
* The programmatic name of the refactoring
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A description of this refactoring category to show to the user.
|
||||
* If the refactoring gets inlined (see below), this text will not be visible.
|
||||
*/
|
||||
description: string;
|
||||
/**
|
||||
* Inlineable refactorings can have their actions hoisted out to the top level
|
||||
* of a context menu. Non-inlineanable refactorings should always be shown inside
|
||||
* their parent grouping.
|
||||
*
|
||||
* If not specified, this value is assumed to be 'true'
|
||||
*/
|
||||
inlineable?: boolean;
|
||||
|
||||
actions: RefactorActionInfo[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a single refactoring action - for example, the "Extract Method..." refactor might
|
||||
* offer several actions, each corresponding to a surround class or closure to extract into.
|
||||
*/
|
||||
export type RefactorActionInfo = {
|
||||
/**
|
||||
* The programmatic name of the refactoring action
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* A description of this refactoring action to show to the user.
|
||||
* If the parent refactoring is inlined away, this will be the only text shown,
|
||||
* so this description should make sense by itself if the parent is inlineable=true
|
||||
*/
|
||||
description: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* A set of edits to make in response to a refactor action, plus an optional
|
||||
* location where renaming should be invoked from
|
||||
*/
|
||||
export type RefactorEditInfo = {
|
||||
edits: FileTextChanges[];
|
||||
renameFilename?: string;
|
||||
renameLocation?: number;
|
||||
};
|
||||
|
||||
|
||||
export interface TextInsertion {
|
||||
newText: string;
|
||||
/** The position in newText the caret should point to after the insertion. */
|
||||
|
||||
+20
-49
@@ -94,6 +94,10 @@ namespace ts {
|
||||
else if (isNamespaceReference(node)) {
|
||||
return SemanticMeaning.Namespace;
|
||||
}
|
||||
else if (isTypeParameterDeclaration(node.parent)) {
|
||||
Debug.assert(isJSDocTemplateTag(node.parent.parent)); // Else would be handled by isDeclarationName
|
||||
return SemanticMeaning.Type;
|
||||
}
|
||||
else {
|
||||
return SemanticMeaning.Value;
|
||||
}
|
||||
@@ -615,18 +619,21 @@ namespace ts {
|
||||
return getTouchingToken(sourceFile, position, includeJsDocComment, n => isPropertyName(n.kind));
|
||||
}
|
||||
|
||||
/** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */
|
||||
export function getTouchingToken(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includeItemAtEndPosition?: (n: Node) => boolean): Node {
|
||||
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition, includeJsDocComment);
|
||||
/**
|
||||
* Returns the token if position is in [start, end).
|
||||
* If position === end, returns the preceding token if includeItemAtEndPosition(previousToken) === true
|
||||
*/
|
||||
export function getTouchingToken(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includePrecedingTokenAtEndPosition?: (n: Node) => boolean): Node {
|
||||
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includePrecedingTokenAtEndPosition, /*includeEndPosition*/ false, includeJsDocComment);
|
||||
}
|
||||
|
||||
/** Returns a token if position is in [start-of-leading-trivia, end) */
|
||||
export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment: boolean): Node {
|
||||
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined, includeJsDocComment);
|
||||
export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment: boolean, includeEndPosition?: boolean): Node {
|
||||
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includePrecedingTokenAtEndPosition*/ undefined, includeEndPosition, includeJsDocComment);
|
||||
}
|
||||
|
||||
/** Get the token whose text contains the position */
|
||||
function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includeItemAtEndPosition: (n: Node) => boolean, includeJsDocComment: boolean): Node {
|
||||
function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includePrecedingTokenAtEndPosition: (n: Node) => boolean, includeEndPosition: boolean, includeJsDocComment: boolean): Node {
|
||||
let current: Node = sourceFile;
|
||||
outer: while (true) {
|
||||
if (isToken(current)) {
|
||||
@@ -636,7 +643,7 @@ namespace ts {
|
||||
|
||||
// find the child that contains 'position'
|
||||
for (const child of current.getChildren()) {
|
||||
if (isJSDocNode(child) && !includeJsDocComment) {
|
||||
if (!includeJsDocComment && isJSDocNode(child)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -646,13 +653,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
const end = child.getEnd();
|
||||
if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) {
|
||||
if (position < end || (position === end && (child.kind === SyntaxKind.EndOfFileToken || includeEndPosition))) {
|
||||
current = child;
|
||||
continue outer;
|
||||
}
|
||||
else if (includeItemAtEndPosition && end === position) {
|
||||
else if (includePrecedingTokenAtEndPosition && end === position) {
|
||||
const previousToken = findPrecedingToken(position, sourceFile, child);
|
||||
if (previousToken && includeItemAtEndPosition(previousToken)) {
|
||||
if (previousToken && includePrecedingTokenAtEndPosition(previousToken)) {
|
||||
return previousToken;
|
||||
}
|
||||
}
|
||||
@@ -707,7 +714,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node, includeJsDocComment?: boolean): Node {
|
||||
export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node, includeJsDoc?: boolean): Node {
|
||||
return find(startNode || sourceFile);
|
||||
|
||||
function findRightmostToken(n: Node): Node {
|
||||
@@ -738,7 +745,7 @@ namespace ts {
|
||||
// NOTE: JsxText is a weird kind of node that can contain only whitespaces (since they are not counted as trivia).
|
||||
// if this is the case - then we should assume that token in question is located in previous child.
|
||||
if (position < child.end && (nodeHasTokens(child) || child.kind === SyntaxKind.JsxText)) {
|
||||
const start = child.getStart(sourceFile, includeJsDocComment);
|
||||
const start = child.getStart(sourceFile, includeJsDoc);
|
||||
const lookInPreviousChild =
|
||||
(start >= position) || // cursor in the leading trivia
|
||||
(child.kind === SyntaxKind.JsxText && start === child.end); // whitespace only JsxText
|
||||
@@ -755,7 +762,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
Debug.assert(startNode !== undefined || n.kind === SyntaxKind.SourceFile);
|
||||
Debug.assert(startNode !== undefined || n.kind === SyntaxKind.SourceFile || isJSDocCommentContainingNode(n));
|
||||
|
||||
// Here we know that none of child token nodes embrace the position,
|
||||
// the only known case is when position is at the end of the file.
|
||||
@@ -901,42 +908,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the corresponding JSDocTag node if the position is in a jsDoc comment
|
||||
*/
|
||||
export function getJsDocTagAtPosition(sourceFile: SourceFile, position: number): JSDocTag {
|
||||
let node = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false);
|
||||
if (isToken(node)) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VarKeyword:
|
||||
case SyntaxKind.LetKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
// if the current token is var, let or const, skip the VariableDeclarationList
|
||||
node = node.parent === undefined ? undefined : node.parent.parent;
|
||||
break;
|
||||
default:
|
||||
node = node.parent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (node) {
|
||||
if (node.jsDoc) {
|
||||
for (const jsDoc of node.jsDoc) {
|
||||
if (jsDoc.tags) {
|
||||
for (const tag of jsDoc.tags) {
|
||||
if (tag.pos <= position && position <= tag.end) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function nodeHasTokens(n: Node): boolean {
|
||||
// If we have a token or node that has a non-zero width, it must have tokens.
|
||||
// Note, that getWidth() does not take trivia into account.
|
||||
|
||||
@@ -25,11 +25,11 @@ class Board {
|
||||
>allShipsSunk : Symbol(Board.allShipsSunk, Decl(2dArrays.ts, 9, 18))
|
||||
|
||||
return this.ships.every(function (val) { return val.isSunk; });
|
||||
>this.ships.every : Symbol(Array.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>this.ships.every : Symbol(Array.every, Decl(lib.d.ts, --, --))
|
||||
>this.ships : Symbol(Board.ships, Decl(2dArrays.ts, 7, 13))
|
||||
>this : Symbol(Board, Decl(2dArrays.ts, 5, 1))
|
||||
>ships : Symbol(Board.ships, Decl(2dArrays.ts, 7, 13))
|
||||
>every : Symbol(Array.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>every : Symbol(Array.every, Decl(lib.d.ts, --, --))
|
||||
>val : Symbol(val, Decl(2dArrays.ts, 12, 42))
|
||||
>val.isSunk : Symbol(Ship.isSunk, Decl(2dArrays.ts, 3, 12))
|
||||
>val : Symbol(val, Decl(2dArrays.ts, 12, 42))
|
||||
|
||||
@@ -26,12 +26,12 @@ class Board {
|
||||
|
||||
return this.ships.every(function (val) { return val.isSunk; });
|
||||
>this.ships.every(function (val) { return val.isSunk; }) : boolean
|
||||
>this.ships.every : { (callbackfn: (this: void, value: Ship, index: number, array: Ship[]) => boolean): boolean; (callbackfn: (this: void, value: Ship, index: number, array: Ship[]) => boolean, thisArg: undefined): boolean; <Z>(callbackfn: (this: Z, value: Ship, index: number, array: Ship[]) => boolean, thisArg: Z): boolean; }
|
||||
>this.ships.every : (callbackfn: (value: Ship, index: number, array: Ship[]) => boolean, thisArg?: any) => boolean
|
||||
>this.ships : Ship[]
|
||||
>this : this
|
||||
>ships : Ship[]
|
||||
>every : { (callbackfn: (this: void, value: Ship, index: number, array: Ship[]) => boolean): boolean; (callbackfn: (this: void, value: Ship, index: number, array: Ship[]) => boolean, thisArg: undefined): boolean; <Z>(callbackfn: (this: Z, value: Ship, index: number, array: Ship[]) => boolean, thisArg: Z): boolean; }
|
||||
>function (val) { return val.isSunk; } : (this: void, val: Ship) => boolean
|
||||
>every : (callbackfn: (value: Ship, index: number, array: Ship[]) => boolean, thisArg?: any) => boolean
|
||||
>function (val) { return val.isSunk; } : (val: Ship) => boolean
|
||||
>val : Ship
|
||||
>val.isSunk : boolean
|
||||
>val : Ship
|
||||
|
||||
@@ -11,7 +11,7 @@ declare var fs: {
|
||||
existsSync(path: string): boolean;
|
||||
readdirSync(path: string): string[];
|
||||
readFileSync(filename: string, encoding?: string): string;
|
||||
writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; }): void;
|
||||
writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; } | string): void;
|
||||
watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: { mtime: Date }, prev: { mtime: Date }) => void): void;
|
||||
};
|
||||
declare var path: any;
|
||||
|
||||
+1
@@ -40,6 +40,7 @@
|
||||
"end": 27,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": "Description"
|
||||
},
|
||||
"length": 1,
|
||||
|
||||
+1
@@ -40,6 +40,7 @@
|
||||
"end": 32,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": "Description"
|
||||
},
|
||||
"length": 1,
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": "Description text follows"
|
||||
},
|
||||
"length": 1,
|
||||
|
||||
+1
@@ -40,6 +40,7 @@
|
||||
"end": 20,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
|
||||
+1
@@ -40,6 +40,7 @@
|
||||
"end": 20,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": "Description"
|
||||
},
|
||||
"length": 1,
|
||||
|
||||
+1
@@ -30,6 +30,7 @@
|
||||
"end": 18,
|
||||
"text": "foo"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": ""
|
||||
},
|
||||
"length": 1,
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": ""
|
||||
},
|
||||
"1": {
|
||||
@@ -79,6 +80,7 @@
|
||||
"end": 55,
|
||||
"text": "name2"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": ""
|
||||
},
|
||||
"length": 2,
|
||||
|
||||
+2
@@ -40,6 +40,7 @@
|
||||
"end": 29,
|
||||
"text": "name1"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": ""
|
||||
},
|
||||
"1": {
|
||||
@@ -79,6 +80,7 @@
|
||||
"end": 51,
|
||||
"text": "name2"
|
||||
},
|
||||
"isBracketed": false,
|
||||
"comment": ""
|
||||
},
|
||||
"length": 2,
|
||||
|
||||
+4
-2
@@ -103,7 +103,8 @@
|
||||
"pos": 66,
|
||||
"end": 69,
|
||||
"text": "age"
|
||||
}
|
||||
},
|
||||
"isBracketed": false
|
||||
},
|
||||
{
|
||||
"kind": "JSDocPropertyTag",
|
||||
@@ -141,7 +142,8 @@
|
||||
"pos": 93,
|
||||
"end": 97,
|
||||
"text": "name"
|
||||
}
|
||||
},
|
||||
"isBracketed": false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -35,16 +35,16 @@ paired.reduce((b3, b4) => b3.concat({}), []);
|
||||
>b3 : Symbol(b3, Decl(anyInferenceAnonymousFunctions.ts, 13, 15))
|
||||
|
||||
paired.map((c1) => c1.count);
|
||||
>paired.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>paired.map : Symbol(Array.map, Decl(lib.d.ts, --, --))
|
||||
>paired : Symbol(paired, Decl(anyInferenceAnonymousFunctions.ts, 0, 3))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --))
|
||||
>c1 : Symbol(c1, Decl(anyInferenceAnonymousFunctions.ts, 15, 12))
|
||||
>c1 : Symbol(c1, Decl(anyInferenceAnonymousFunctions.ts, 15, 12))
|
||||
|
||||
paired.map(function (c2) { return c2.count; });
|
||||
>paired.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>paired.map : Symbol(Array.map, Decl(lib.d.ts, --, --))
|
||||
>paired : Symbol(paired, Decl(anyInferenceAnonymousFunctions.ts, 0, 3))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --))
|
||||
>c2 : Symbol(c2, Decl(anyInferenceAnonymousFunctions.ts, 16, 21))
|
||||
>c2 : Symbol(c2, Decl(anyInferenceAnonymousFunctions.ts, 16, 21))
|
||||
|
||||
|
||||
@@ -57,10 +57,10 @@ paired.reduce((b3, b4) => b3.concat({}), []);
|
||||
|
||||
paired.map((c1) => c1.count);
|
||||
>paired.map((c1) => c1.count) : any[]
|
||||
>paired.map : { <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; }
|
||||
>paired.map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
|
||||
>paired : any[]
|
||||
>map : { <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; }
|
||||
>(c1) => c1.count : (this: void, c1: any) => any
|
||||
>map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
|
||||
>(c1) => c1.count : (c1: any) => any
|
||||
>c1 : any
|
||||
>c1.count : any
|
||||
>c1 : any
|
||||
@@ -68,10 +68,10 @@ paired.map((c1) => c1.count);
|
||||
|
||||
paired.map(function (c2) { return c2.count; });
|
||||
>paired.map(function (c2) { return c2.count; }) : any[]
|
||||
>paired.map : { <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; }
|
||||
>paired.map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
|
||||
>paired : any[]
|
||||
>map : { <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; }
|
||||
>function (c2) { return c2.count; } : (this: void, c2: any) => any
|
||||
>map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
|
||||
>function (c2) { return c2.count; } : (c2: any) => any
|
||||
>c2 : any
|
||||
>c2.count : any
|
||||
>c2 : any
|
||||
|
||||
@@ -34,8 +34,8 @@ function myFunction(myType: MyType) {
|
||||
>x : Symbol(x, Decl(argumentsAsPropertyName.ts, 11, 13))
|
||||
|
||||
[1, 2, 3].forEach(function(j) { use(x); })
|
||||
>[1, 2, 3].forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>[1, 2, 3].forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --))
|
||||
>forEach : Symbol(Array.forEach, Decl(lib.d.ts, --, --))
|
||||
>j : Symbol(j, Decl(argumentsAsPropertyName.ts, 12, 35))
|
||||
>use : Symbol(use, Decl(argumentsAsPropertyName.ts, 3, 1))
|
||||
>x : Symbol(x, Decl(argumentsAsPropertyName.ts, 11, 13))
|
||||
|
||||
@@ -42,13 +42,13 @@ function myFunction(myType: MyType) {
|
||||
|
||||
[1, 2, 3].forEach(function(j) { use(x); })
|
||||
>[1, 2, 3].forEach(function(j) { use(x); }) : void
|
||||
>[1, 2, 3].forEach : { (callbackfn: (this: void, value: number, index: number, array: number[]) => void): void; (callbackfn: (this: void, value: number, index: number, array: number[]) => void, thisArg: undefined): void; <Z>(callbackfn: (this: Z, value: number, index: number, array: number[]) => void, thisArg: Z): void; }
|
||||
>[1, 2, 3].forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
|
||||
>[1, 2, 3] : number[]
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
>forEach : { (callbackfn: (this: void, value: number, index: number, array: number[]) => void): void; (callbackfn: (this: void, value: number, index: number, array: number[]) => void, thisArg: undefined): void; <Z>(callbackfn: (this: Z, value: number, index: number, array: number[]) => void, thisArg: Z): void; }
|
||||
>function(j) { use(x); } : (this: void, j: number) => void
|
||||
>forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
|
||||
>function(j) { use(x); } : (j: number) => void
|
||||
>j : number
|
||||
>use(x) : any
|
||||
>use : (s: any) => any
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
=== tests/cases/compiler/main.js ===
|
||||
function allRest() { arguments; }
|
||||
>allRest : Symbol(allRest, Decl(main.js, 0, 0))
|
||||
>arguments : Symbol(arguments)
|
||||
|
||||
allRest();
|
||||
>allRest : Symbol(allRest, Decl(main.js, 0, 0))
|
||||
|
||||
allRest(1, 2, 3);
|
||||
>allRest : Symbol(allRest, Decl(main.js, 0, 0))
|
||||
|
||||
function someRest(x, y) { arguments; }
|
||||
>someRest : Symbol(someRest, Decl(main.js, 2, 17))
|
||||
>x : Symbol(x, Decl(main.js, 3, 18))
|
||||
>y : Symbol(y, Decl(main.js, 3, 20))
|
||||
>arguments : Symbol(arguments)
|
||||
|
||||
someRest(); // x and y are still optional because they are in a JS file
|
||||
>someRest : Symbol(someRest, Decl(main.js, 2, 17))
|
||||
|
||||
someRest(1, 2, 3);
|
||||
>someRest : Symbol(someRest, Decl(main.js, 2, 17))
|
||||
|
||||
/**
|
||||
* @param {number} x - a thing
|
||||
*/
|
||||
function jsdocced(x) { arguments; }
|
||||
>jsdocced : Symbol(jsdocced, Decl(main.js, 5, 18))
|
||||
>x : Symbol(x, Decl(main.js, 10, 18))
|
||||
>arguments : Symbol(arguments)
|
||||
|
||||
jsdocced(1);
|
||||
>jsdocced : Symbol(jsdocced, Decl(main.js, 5, 18))
|
||||
|
||||
function dontDoubleRest(x, ...y) { arguments; }
|
||||
>dontDoubleRest : Symbol(dontDoubleRest, Decl(main.js, 11, 12))
|
||||
>x : Symbol(x, Decl(main.js, 13, 24))
|
||||
>y : Symbol(y, Decl(main.js, 13, 26))
|
||||
>arguments : Symbol(arguments)
|
||||
|
||||
dontDoubleRest(1, 2, 3);
|
||||
>dontDoubleRest : Symbol(dontDoubleRest, Decl(main.js, 11, 12))
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
=== tests/cases/compiler/main.js ===
|
||||
function allRest() { arguments; }
|
||||
>allRest : (...args: any[]) => void
|
||||
>arguments : IArguments
|
||||
|
||||
allRest();
|
||||
>allRest() : void
|
||||
>allRest : (...args: any[]) => void
|
||||
|
||||
allRest(1, 2, 3);
|
||||
>allRest(1, 2, 3) : void
|
||||
>allRest : (...args: any[]) => void
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
function someRest(x, y) { arguments; }
|
||||
>someRest : (x: any, y: any, ...args: any[]) => void
|
||||
>x : any
|
||||
>y : any
|
||||
>arguments : IArguments
|
||||
|
||||
someRest(); // x and y are still optional because they are in a JS file
|
||||
>someRest() : void
|
||||
>someRest : (x: any, y: any, ...args: any[]) => void
|
||||
|
||||
someRest(1, 2, 3);
|
||||
>someRest(1, 2, 3) : void
|
||||
>someRest : (x: any, y: any, ...args: any[]) => void
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
/**
|
||||
* @param {number} x - a thing
|
||||
*/
|
||||
function jsdocced(x) { arguments; }
|
||||
>jsdocced : (x: number) => void
|
||||
>x : number
|
||||
>arguments : IArguments
|
||||
|
||||
jsdocced(1);
|
||||
>jsdocced(1) : void
|
||||
>jsdocced : (x: number) => void
|
||||
>1 : 1
|
||||
|
||||
function dontDoubleRest(x, ...y) { arguments; }
|
||||
>dontDoubleRest : (x: any, ...y: any[]) => void
|
||||
>x : any
|
||||
>y : any[]
|
||||
>arguments : IArguments
|
||||
|
||||
dontDoubleRest(1, 2, 3);
|
||||
>dontDoubleRest(1, 2, 3) : void
|
||||
>dontDoubleRest : (x: any, ...y: any[]) => void
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
=== tests/cases/compiler/arrayConcatMap.ts ===
|
||||
var x = [].concat([{ a: 1 }], [{ a: 2 }])
|
||||
>x : Symbol(x, Decl(arrayConcatMap.ts, 0, 3))
|
||||
>[].concat([{ a: 1 }], [{ a: 2 }]) .map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>[].concat([{ a: 1 }], [{ a: 2 }]) .map : Symbol(Array.map, Decl(lib.d.ts, --, --))
|
||||
>[].concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>concat : Symbol(Array.concat, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>a : Symbol(a, Decl(arrayConcatMap.ts, 0, 20))
|
||||
>a : Symbol(a, Decl(arrayConcatMap.ts, 0, 32))
|
||||
|
||||
.map(b => b.a);
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>map : Symbol(Array.map, Decl(lib.d.ts, --, --))
|
||||
>b : Symbol(b, Decl(arrayConcatMap.ts, 1, 15))
|
||||
>b : Symbol(b, Decl(arrayConcatMap.ts, 1, 15))
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var x = [].concat([{ a: 1 }], [{ a: 2 }])
|
||||
>x : any[]
|
||||
>[].concat([{ a: 1 }], [{ a: 2 }]) .map(b => b.a) : any[]
|
||||
>[].concat([{ a: 1 }], [{ a: 2 }]) .map : { <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; }
|
||||
>[].concat([{ a: 1 }], [{ a: 2 }]) .map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
|
||||
>[].concat([{ a: 1 }], [{ a: 2 }]) : any[]
|
||||
>[].concat : { (...items: any[][]): any[]; (...items: any[]): any[]; }
|
||||
>[] : undefined[]
|
||||
@@ -17,8 +17,8 @@ var x = [].concat([{ a: 1 }], [{ a: 2 }])
|
||||
>2 : 2
|
||||
|
||||
.map(b => b.a);
|
||||
>map : { <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U, U]; <U>(this: [any, any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U, U]; <Z, U>(this: [any, any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U, U]; <U>(this: [any, any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U, U]; <Z, U>(this: [any, any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U, U]; <U>(this: [any, any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U, U]; <Z, U>(this: [any, any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U): [U, U]; <U>(this: [any, any], callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): [U, U]; <Z, U>(this: [any, any], callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): [U, U]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U): U[]; <U>(callbackfn: (this: void, value: any, index: number, array: any[]) => U, thisArg: undefined): U[]; <Z, U>(callbackfn: (this: Z, value: any, index: number, array: any[]) => U, thisArg: Z): U[]; }
|
||||
>b => b.a : (this: void, b: any) => any
|
||||
>map : <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[]
|
||||
>b => b.a : (b: any) => any
|
||||
>b : any
|
||||
>b.a : any
|
||||
>b : any
|
||||
|
||||
@@ -14,9 +14,9 @@ var foo = [
|
||||
]
|
||||
|
||||
foo.filter(x => x.name); //should accepted all possible types not only boolean!
|
||||
>foo.filter : Symbol(Array.filter, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>foo.filter : Symbol(Array.filter, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>foo : Symbol(foo, Decl(arrayFilter.ts, 0, 3))
|
||||
>filter : Symbol(Array.filter, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>filter : Symbol(Array.filter, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(arrayFilter.ts, 6, 11))
|
||||
>x.name : Symbol(name, Decl(arrayFilter.ts, 1, 5))
|
||||
>x : Symbol(x, Decl(arrayFilter.ts, 6, 11))
|
||||
|
||||
@@ -22,10 +22,10 @@ var foo = [
|
||||
|
||||
foo.filter(x => x.name); //should accepted all possible types not only boolean!
|
||||
>foo.filter(x => x.name) : { name: string; }[]
|
||||
>foo.filter : { (callbackfn: (this: void, value: { name: string; }, index: number, array: { name: string; }[]) => any): { name: string; }[]; (callbackfn: (this: void, value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg: undefined): { name: string; }[]; <Z>(callbackfn: (this: Z, value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg: Z): { name: string; }[]; }
|
||||
>foo.filter : { <S extends { name: string; }>(callbackfn: (value: { name: string; }, index: number, array: { name: string; }[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg?: any): { name: string; }[]; }
|
||||
>foo : { name: string; }[]
|
||||
>filter : { (callbackfn: (this: void, value: { name: string; }, index: number, array: { name: string; }[]) => any): { name: string; }[]; (callbackfn: (this: void, value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg: undefined): { name: string; }[]; <Z>(callbackfn: (this: Z, value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg: Z): { name: string; }[]; }
|
||||
>x => x.name : (this: void, x: { name: string; }) => string
|
||||
>filter : { <S extends { name: string; }>(callbackfn: (value: { name: string; }, index: number, array: { name: string; }[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: { name: string; }, index: number, array: { name: string; }[]) => any, thisArg?: any): { name: string; }[]; }
|
||||
>x => x.name : (x: { name: string; }) => string
|
||||
>x : { name: string; }
|
||||
>x.name : string
|
||||
>x : { name: string; }
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(13,1): error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray<B>'.
|
||||
Types of property 'concat' are incompatible.
|
||||
Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
Type 'A[]' is not assignable to type 'B[]'.
|
||||
Type 'A' is not assignable to type 'B'.
|
||||
Property 'b' is missing in type 'A'.
|
||||
tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error TS2322: Type 'C<A>' is not assignable to type 'ReadonlyArray<B>'.
|
||||
Types of property 'concat' are incompatible.
|
||||
Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
Type 'A[]' is not assignable to type 'B[]'.
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error T
|
||||
~~~
|
||||
!!! error TS2322: Type 'A[]' is not assignable to type 'ReadonlyArray<B>'.
|
||||
!!! error TS2322: Types of property 'concat' are incompatible.
|
||||
!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
!!! error TS2322: Type 'A[]' is not assignable to type 'B[]'.
|
||||
!!! error TS2322: Type 'A' is not assignable to type 'B'.
|
||||
!!! error TS2322: Property 'b' is missing in type 'A'.
|
||||
@@ -39,6 +39,6 @@ tests/cases/compiler/arrayOfSubtypeIsAssignableToReadonlyArray.ts(18,1): error T
|
||||
~~~
|
||||
!!! error TS2322: Type 'C<A>' is not assignable to type 'ReadonlyArray<B>'.
|
||||
!!! error TS2322: Types of property 'concat' are incompatible.
|
||||
!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ <U extends ReadonlyArray<B>>(...items: U[]): B[]; (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
!!! error TS2322: Type '{ (...items: A[][]): A[]; (...items: (A | A[])[]): A[]; }' is not assignable to type '{ (...items: B[][]): B[]; (...items: (B | B[])[]): B[]; }'.
|
||||
!!! error TS2322: Type 'A[]' is not assignable to type 'B[]'.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user