mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into dynamicNames
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);
|
||||
});
|
||||
|
||||
|
||||
+20
-11
@@ -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"));
|
||||
@@ -551,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
|
||||
@@ -611,6 +617,7 @@ compileFile(
|
||||
fs.readFileSync(tsserverLibraryDefinitionFile).toString() +
|
||||
"\r\nexport = ts;" +
|
||||
"\r\nexport as namespace ts;";
|
||||
tsserverLibraryDefinitionFileContents = removeConstModifierFromEnumDeclarations(tsserverLibraryDefinitionFileContents);
|
||||
|
||||
fs.writeFileSync(tsserverLibraryDefinitionFile, tsserverLibraryDefinitionFileContents);
|
||||
});
|
||||
@@ -800,8 +807,8 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
cleanTestDirs();
|
||||
}
|
||||
|
||||
var debug = process.env.debug || process.env.d;
|
||||
var inspect = process.env.inspect;
|
||||
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;
|
||||
@@ -842,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}"`);
|
||||
@@ -861,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(" ");
|
||||
@@ -926,7 +935,6 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
}
|
||||
}
|
||||
|
||||
var defaultTestTimeout = 22000;
|
||||
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);
|
||||
@@ -939,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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
+181
-139
@@ -2842,6 +2842,17 @@ namespace ts {
|
||||
|
||||
function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext): ParameterDeclaration {
|
||||
const parameterDeclaration = getDeclarationOfKind<ParameterDeclaration>(parameterSymbol, SyntaxKind.Parameter);
|
||||
if (isTransientSymbol(parameterSymbol) && parameterSymbol.isRestParameter) {
|
||||
// special-case synthetic rest parameters in JS files
|
||||
return createParameter(
|
||||
/*decorators*/ undefined,
|
||||
/*modifiers*/ undefined,
|
||||
parameterSymbol.isRestParameter ? createToken(SyntaxKind.DotDotDotToken) : undefined,
|
||||
"args",
|
||||
/*questionToken*/ undefined,
|
||||
typeToTypeNodeHelper(anyArrayType, context),
|
||||
/*initializer*/ undefined);
|
||||
}
|
||||
const modifiers = parameterDeclaration.modifiers && parameterDeclaration.modifiers.map(getSynthesizedClone);
|
||||
const dotDotDotToken = isRestParameter(parameterDeclaration) ? createToken(SyntaxKind.DotDotDotToken) : undefined;
|
||||
const name = parameterDeclaration.name ?
|
||||
@@ -4220,16 +4231,6 @@ namespace ts {
|
||||
|
||||
// Return the inferred type for a variable, parameter, or property declaration
|
||||
function getTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, includeOptionality: boolean): Type {
|
||||
if (declaration.flags & NodeFlags.JavaScriptFile) {
|
||||
// If this is a variable in a JavaScript file, then use the JSDoc type (if it has
|
||||
// one as its type), otherwise fallback to the below standard TS codepaths to
|
||||
// try to figure it out.
|
||||
const type = getTypeForDeclarationFromJSDocComment(declaration);
|
||||
if (type && type !== unknownType) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
// A variable declared in a for..in statement is of type string, or of type keyof T when the
|
||||
// right hand expression is of a type parameter type.
|
||||
if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
|
||||
@@ -4251,8 +4252,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Use type from type annotation if one is present
|
||||
if (declaration.type) {
|
||||
const declaredType = getTypeFromTypeNode(declaration.type);
|
||||
const typeNode = getEffectiveTypeAnnotationNode(declaration);
|
||||
if (typeNode) {
|
||||
const declaredType = getTypeFromTypeNode(typeNode);
|
||||
return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality);
|
||||
}
|
||||
|
||||
@@ -4553,10 +4555,11 @@ namespace ts {
|
||||
function getAnnotatedAccessorType(accessor: AccessorDeclaration): Type {
|
||||
if (accessor) {
|
||||
if (accessor.kind === SyntaxKind.GetAccessor) {
|
||||
return accessor.type && getTypeFromTypeNode(accessor.type);
|
||||
const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor);
|
||||
return getterTypeAnnotation && getTypeFromTypeNode(getterTypeAnnotation);
|
||||
}
|
||||
else {
|
||||
const setterTypeAnnotation = getSetAccessorTypeAnnotationNode(accessor);
|
||||
const setterTypeAnnotation = getEffectiveSetAccessorTypeAnnotationNode(accessor);
|
||||
return setterTypeAnnotation && getTypeFromTypeNode(setterTypeAnnotation);
|
||||
}
|
||||
}
|
||||
@@ -4709,7 +4712,7 @@ namespace ts {
|
||||
|
||||
function reportCircularityError(symbol: Symbol) {
|
||||
// Check if variable has type annotation that circularly references the variable itself
|
||||
if ((<VariableLikeDeclaration>symbol.valueDeclaration).type) {
|
||||
if (getEffectiveTypeAnnotationNode(<VariableLikeDeclaration>symbol.valueDeclaration)) {
|
||||
error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation,
|
||||
symbolToString(symbol));
|
||||
return unknownType;
|
||||
@@ -5295,14 +5298,18 @@ namespace ts {
|
||||
// A variable-like declaration is considered independent (free of this references) if it has a type annotation
|
||||
// that specifies an independent type, or if it has no type annotation and no initializer (and thus of type any).
|
||||
function isIndependentVariableLikeDeclaration(node: VariableLikeDeclaration): boolean {
|
||||
return node.type && isIndependentType(node.type) || !node.type && !node.initializer;
|
||||
const typeNode = getEffectiveTypeAnnotationNode(node);
|
||||
return typeNode ? isIndependentType(typeNode) : !node.initializer;
|
||||
}
|
||||
|
||||
// A function-like declaration is considered independent (free of this references) if it has a return type
|
||||
// annotation that is considered independent and if each parameter is considered independent.
|
||||
function isIndependentFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
|
||||
if (node.kind !== SyntaxKind.Constructor && (!node.type || !isIndependentType(node.type))) {
|
||||
return false;
|
||||
if (node.kind !== SyntaxKind.Constructor) {
|
||||
const typeNode = getEffectiveReturnTypeNode(node);
|
||||
if (!typeNode || !isIndependentType(typeNode)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const parameter of node.parameters) {
|
||||
if (!isIndependentVariableLikeDeclaration(parameter)) {
|
||||
@@ -6600,8 +6607,17 @@ namespace ts {
|
||||
const typePredicate = declaration.type && declaration.type.kind === SyntaxKind.TypePredicate ?
|
||||
createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode) :
|
||||
undefined;
|
||||
// JS functions get a free rest parameter if they reference `arguments`
|
||||
let hasRestLikeParameter = hasRestParameter(declaration);
|
||||
if (!hasRestLikeParameter && isInJavaScriptFile(declaration) && !hasJSDocParameterTags(declaration) && containsArgumentsReference(declaration)) {
|
||||
hasRestLikeParameter = true;
|
||||
const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args");
|
||||
syntheticArgsSymbol.type = anyArrayType;
|
||||
syntheticArgsSymbol.isRestParameter = true;
|
||||
parameters.push(syntheticArgsSymbol);
|
||||
}
|
||||
|
||||
links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasLiteralTypes);
|
||||
links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, returnType, typePredicate, minArgumentCount, hasRestLikeParameter, hasLiteralTypes);
|
||||
}
|
||||
return links.resolvedSignature;
|
||||
}
|
||||
@@ -6613,15 +6629,10 @@ namespace ts {
|
||||
else if (classType) {
|
||||
return classType;
|
||||
}
|
||||
else if (declaration.type) {
|
||||
return getTypeFromTypeNode(declaration.type);
|
||||
}
|
||||
|
||||
if (declaration.flags & NodeFlags.JavaScriptFile) {
|
||||
const type = getReturnTypeFromJSDocComment(declaration);
|
||||
if (type && type !== unknownType) {
|
||||
return type;
|
||||
}
|
||||
const typeNode = getEffectiveReturnTypeNode(declaration);
|
||||
if (typeNode) {
|
||||
return getTypeFromTypeNode(typeNode);
|
||||
}
|
||||
|
||||
// TypeScript 1.0 spec (April 2014):
|
||||
@@ -6636,14 +6647,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function containsArgumentsReference(declaration: FunctionLikeDeclaration): boolean {
|
||||
function containsArgumentsReference(declaration: SignatureDeclaration): boolean {
|
||||
const links = getNodeLinks(declaration);
|
||||
if (links.containsArgumentsReference === undefined) {
|
||||
if (links.flags & NodeCheckFlags.CaptureArguments) {
|
||||
links.containsArgumentsReference = true;
|
||||
}
|
||||
else {
|
||||
links.containsArgumentsReference = traverse(declaration.body);
|
||||
links.containsArgumentsReference = traverse((declaration as FunctionLikeDeclaration).body);
|
||||
}
|
||||
}
|
||||
return links.containsArgumentsReference;
|
||||
@@ -7030,21 +7041,46 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName) {
|
||||
function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName, meaning: SymbolFlags) {
|
||||
if (!typeReferenceName) {
|
||||
return unknownSymbol;
|
||||
}
|
||||
|
||||
return resolveEntityName(typeReferenceName, SymbolFlags.Type) || unknownSymbol;
|
||||
return resolveEntityName(typeReferenceName, meaning) || unknownSymbol;
|
||||
}
|
||||
|
||||
function getTypeReferenceType(node: TypeReferenceType, symbol: Symbol) {
|
||||
const typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced.
|
||||
|
||||
if (symbol === unknownSymbol) {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
const type = getTypeReferenceTypeWorker(node, symbol, typeArguments);
|
||||
if (type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) {
|
||||
// A JSDocTypeReference may have resolved to a value (as opposed to a type). If
|
||||
// the symbol is a constructor function, return the inferred class type; otherwise,
|
||||
// the type of this reference is just the type of the value we resolved to.
|
||||
const valueType = getTypeOfSymbol(symbol);
|
||||
if (valueType.symbol && !isInferredClassType(valueType)) {
|
||||
const referenceType = getTypeReferenceTypeWorker(node, valueType.symbol, typeArguments);
|
||||
if (referenceType) {
|
||||
return referenceType;
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve the type reference as a Type for the purpose of reporting errors.
|
||||
resolveTypeReferenceName(getTypeReferenceName(node), SymbolFlags.Type);
|
||||
return valueType;
|
||||
}
|
||||
|
||||
return getTypeFromNonGenericTypeReference(node, symbol);
|
||||
}
|
||||
|
||||
function getTypeReferenceTypeWorker(node: TypeReferenceType, symbol: Symbol, typeArguments: Type[]): Type | undefined {
|
||||
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
return getTypeFromClassOrInterfaceReference(node, symbol, typeArguments);
|
||||
}
|
||||
@@ -7053,14 +7089,9 @@ namespace ts {
|
||||
return getTypeFromTypeAliasReference(node, symbol, typeArguments);
|
||||
}
|
||||
|
||||
if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) {
|
||||
// A JSDocTypeReference may have resolved to a value (as opposed to a type). In
|
||||
// that case, the type of this reference is just the type of the value we resolved
|
||||
// to.
|
||||
return getTypeOfSymbol(symbol);
|
||||
if (symbol.flags & SymbolFlags.Function && node.kind === SyntaxKind.JSDocTypeReference && (symbol.members || getJSDocClassTag(symbol.valueDeclaration))) {
|
||||
return getInferredClassType(symbol);
|
||||
}
|
||||
|
||||
return getTypeFromNonGenericTypeReference(node, symbol);
|
||||
}
|
||||
|
||||
function getPrimitiveTypeFromJSDocTypeReference(node: JSDocTypeReference): Type {
|
||||
@@ -7103,22 +7134,13 @@ namespace ts {
|
||||
if (!links.resolvedType) {
|
||||
let symbol: Symbol;
|
||||
let type: Type;
|
||||
let meaning = SymbolFlags.Type;
|
||||
if (node.kind === SyntaxKind.JSDocTypeReference) {
|
||||
type = getPrimitiveTypeFromJSDocTypeReference(<JSDocTypeReference>node);
|
||||
if (!type) {
|
||||
const typeReferenceName = getTypeReferenceName(node);
|
||||
symbol = resolveTypeReferenceName(typeReferenceName);
|
||||
type = getTypeReferenceType(node, symbol);
|
||||
}
|
||||
type = getPrimitiveTypeFromJSDocTypeReference(node);
|
||||
meaning |= SymbolFlags.Value;
|
||||
}
|
||||
else {
|
||||
// We only support expressions that are simple qualified names. For other expressions this produces undefined.
|
||||
const typeNameOrExpression: EntityNameOrEntityNameExpression = node.kind === SyntaxKind.TypeReference
|
||||
? (<TypeReferenceNode>node).typeName
|
||||
: isEntityNameExpression((<ExpressionWithTypeArguments>node).expression)
|
||||
? <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression
|
||||
: undefined;
|
||||
symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
|
||||
if (!type) {
|
||||
symbol = resolveTypeReferenceName(getTypeReferenceName(node), meaning);
|
||||
type = getTypeReferenceType(node, symbol);
|
||||
}
|
||||
// Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the
|
||||
@@ -8281,7 +8303,7 @@ namespace ts {
|
||||
const result = createSignature(signature.declaration, freshTypeParameters,
|
||||
signature.thisParameter && instantiateSymbol(signature.thisParameter, mapper),
|
||||
instantiateList(signature.parameters, mapper, instantiateSymbol),
|
||||
instantiateType(signature.resolvedReturnType, mapper),
|
||||
/*resolvedReturnType*/ undefined,
|
||||
freshTypePredicate,
|
||||
signature.minArgumentCount, signature.hasRestParameter, signature.hasLiteralTypes);
|
||||
result.target = signature;
|
||||
@@ -8545,7 +8567,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
// Functions with any parameters that lack type annotations are context sensitive.
|
||||
if (forEach(node.parameters, p => !p.type)) {
|
||||
if (forEach(node.parameters, p => !getEffectiveTypeAnnotationNode(p))) {
|
||||
return true;
|
||||
}
|
||||
// For arrow functions we now know we're not context sensitive.
|
||||
@@ -9183,7 +9205,9 @@ namespace ts {
|
||||
reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(prop), typeToString(target));
|
||||
}
|
||||
else {
|
||||
errorNode = prop.valueDeclaration;
|
||||
if (prop.valueDeclaration) {
|
||||
errorNode = prop.valueDeclaration;
|
||||
}
|
||||
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1,
|
||||
symbolToString(prop), typeToString(target));
|
||||
}
|
||||
@@ -12959,8 +12983,15 @@ namespace ts {
|
||||
function getContextualTypeForInitializerExpression(node: Expression): Type {
|
||||
const declaration = <VariableLikeDeclaration>node.parent;
|
||||
if (node === declaration.initializer) {
|
||||
if (declaration.type) {
|
||||
return getTypeFromTypeNode(declaration.type);
|
||||
const typeNode = getEffectiveTypeAnnotationNode(declaration);
|
||||
if (typeNode) {
|
||||
return getTypeFromTypeNode(typeNode);
|
||||
}
|
||||
if (isInJavaScriptFile(declaration)) {
|
||||
const jsDocType = getTypeForDeclarationFromJSDocComment(declaration);
|
||||
if (jsDocType) {
|
||||
return jsDocType;
|
||||
}
|
||||
}
|
||||
if (declaration.kind === SyntaxKind.Parameter) {
|
||||
const type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
|
||||
@@ -12974,12 +13005,13 @@ namespace ts {
|
||||
if (isBindingPattern(declaration.parent)) {
|
||||
const parentDeclaration = declaration.parent.parent;
|
||||
const name = declaration.propertyName || declaration.name;
|
||||
if (parentDeclaration.kind !== SyntaxKind.BindingElement &&
|
||||
parentDeclaration.type &&
|
||||
!isBindingPattern(name)) {
|
||||
const text = getTextOfPropertyName(name);
|
||||
if (text) {
|
||||
return getTypeOfPropertyOfType(getTypeFromTypeNode(parentDeclaration.type), text);
|
||||
if (parentDeclaration.kind !== SyntaxKind.BindingElement) {
|
||||
const parentTypeNode = getEffectiveTypeAnnotationNode(parentDeclaration);
|
||||
if (parentTypeNode && !isBindingPattern(name)) {
|
||||
const text = getTextOfPropertyName(name);
|
||||
if (text) {
|
||||
return getTypeOfPropertyOfType(getTypeFromTypeNode(parentTypeNode), text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13033,9 +13065,9 @@ namespace ts {
|
||||
function getContextualReturnType(functionDecl: FunctionLikeDeclaration): Type {
|
||||
// If the containing function has a return type annotation, is a constructor, or is a get accessor whose
|
||||
// corresponding set accessor has a type annotation, return statements in the function are contextually typed
|
||||
if (functionDecl.type ||
|
||||
functionDecl.kind === SyntaxKind.Constructor ||
|
||||
functionDecl.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind<SetAccessorDeclaration>(functionDecl.symbol, SyntaxKind.SetAccessor))) {
|
||||
if (functionDecl.kind === SyntaxKind.Constructor ||
|
||||
getEffectiveReturnTypeNode(functionDecl) ||
|
||||
isGetAccessorWithAnnotatedSetAccessor(functionDecl)) {
|
||||
return getReturnTypeOfSignature(getSignatureFromDeclaration(functionDecl));
|
||||
}
|
||||
|
||||
@@ -14444,9 +14476,13 @@ namespace ts {
|
||||
|
||||
/**
|
||||
* Check if a property with the given name is known anywhere in the given type. In an object type, a property
|
||||
* is considered known if the object type is empty and the check is for assignability, if the object type has
|
||||
* index signatures, or if the property is actually declared in the object type. In a union or intersection
|
||||
* type, a property is considered known if it is known in any constituent type.
|
||||
* is considered known if
|
||||
* 1. the object type is empty and the check is for assignability, or
|
||||
* 2. if the object type has index signatures, or
|
||||
* 3. if the property is actually declared in the object type
|
||||
* (this means that 'toString', for example, is not usually a known property).
|
||||
* 4. In a union or intersection type,
|
||||
* a property is considered known if it is known in any constituent type.
|
||||
* @param targetType a type to search a given name in
|
||||
* @param name a property name to search
|
||||
* @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType
|
||||
@@ -14456,7 +14492,7 @@ namespace ts {
|
||||
const resolved = resolveStructuredTypeMembers(<ObjectType>targetType);
|
||||
if (resolved.stringIndexInfo ||
|
||||
resolved.numberIndexInfo && isNumericLiteralName(name) ||
|
||||
getPropertyOfType(targetType, name) ||
|
||||
getPropertyOfObjectType(targetType, name) ||
|
||||
isComparingJsxAttributes && !isUnhyphenatedJsxName(name)) {
|
||||
// For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known.
|
||||
return true;
|
||||
@@ -15751,21 +15787,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (signatures.length === 1) {
|
||||
const declaration = signatures[0].declaration;
|
||||
if (declaration && isInJavaScriptFile(declaration) && !hasJSDocParameterTags(declaration)) {
|
||||
if (containsArgumentsReference(<FunctionLikeDeclaration>declaration)) {
|
||||
const signatureWithRest = cloneSignature(signatures[0]);
|
||||
const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args");
|
||||
syntheticArgsSymbol.type = anyArrayType;
|
||||
syntheticArgsSymbol.isRestParameter = true;
|
||||
signatureWithRest.parameters = concatenate(signatureWithRest.parameters, [syntheticArgsSymbol]);
|
||||
signatureWithRest.hasRestParameter = true;
|
||||
signatures = [signatureWithRest];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const candidates = candidatesOutArray || [];
|
||||
// reorderCandidates fills up the candidates array directly
|
||||
reorderCandidates(signatures, candidates);
|
||||
@@ -16414,6 +16435,12 @@ namespace ts {
|
||||
return links.inferredClassType;
|
||||
}
|
||||
|
||||
function isInferredClassType(type: Type) {
|
||||
return type.symbol
|
||||
&& getObjectFlags(type) & ObjectFlags.Anonymous
|
||||
&& getSymbolLinks(type.symbol).inferredClassType === type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntactically and semantically checks a call or new expression.
|
||||
* @param node The call/new expression to be checked.
|
||||
@@ -16621,8 +16648,9 @@ namespace ts {
|
||||
if (checkMode === CheckMode.Inferential) {
|
||||
for (let i = 0; i < len; i++) {
|
||||
const declaration = <ParameterDeclaration>signature.parameters[i].valueDeclaration;
|
||||
if (declaration.type) {
|
||||
inferTypes((<InferenceContext>mapper).inferences, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
|
||||
const typeNode = getEffectiveTypeAnnotationNode(declaration);
|
||||
if (typeNode) {
|
||||
inferTypes((<InferenceContext>mapper).inferences, getTypeFromTypeNode(typeNode), getTypeAtPosition(context, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16637,14 +16665,14 @@ namespace ts {
|
||||
}
|
||||
for (let i = 0; i < len; i++) {
|
||||
const parameter = signature.parameters[i];
|
||||
if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
|
||||
if (!getEffectiveTypeAnnotationNode(<ParameterDeclaration>parameter.valueDeclaration)) {
|
||||
const contextualParameterType = getTypeAtPosition(context, i);
|
||||
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper, checkMode);
|
||||
}
|
||||
}
|
||||
if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) {
|
||||
const parameter = lastOrUndefined(signature.parameters);
|
||||
if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
|
||||
if (!getEffectiveTypeAnnotationNode(<ParameterDeclaration>parameter.valueDeclaration)) {
|
||||
const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
|
||||
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper, checkMode);
|
||||
}
|
||||
@@ -16712,15 +16740,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getReturnTypeFromJSDocComment(func: SignatureDeclaration | FunctionDeclaration): Type {
|
||||
const returnTag = getJSDocReturnTag(func);
|
||||
if (returnTag && returnTag.typeExpression) {
|
||||
return getTypeFromTypeNode(returnTag.typeExpression.type);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function createPromiseType(promisedType: Type): Type {
|
||||
// creates a `Promise<T>` type where `T` is the promisedType argument
|
||||
const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true);
|
||||
@@ -16947,16 +16966,16 @@ namespace ts {
|
||||
const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn;
|
||||
|
||||
if (returnType && returnType.flags & TypeFlags.Never) {
|
||||
error(func.type, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point);
|
||||
error(getEffectiveReturnTypeNode(func), Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point);
|
||||
}
|
||||
else if (returnType && !hasExplicitReturn) {
|
||||
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
|
||||
// this function does not conform to the specification.
|
||||
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
|
||||
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
|
||||
error(getEffectiveReturnTypeNode(func), Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
|
||||
}
|
||||
else if (returnType && strictNullChecks && !isTypeAssignableTo(undefinedType, returnType)) {
|
||||
error(func.type, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined);
|
||||
error(getEffectiveReturnTypeNode(func), Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined);
|
||||
}
|
||||
else if (compilerOptions.noImplicitReturns) {
|
||||
if (!returnType) {
|
||||
@@ -16971,7 +16990,7 @@ namespace ts {
|
||||
return;
|
||||
}
|
||||
}
|
||||
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
|
||||
error(getEffectiveReturnTypeNode(func) || func, Diagnostics.Not_all_code_paths_return_a_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17011,7 +17030,7 @@ namespace ts {
|
||||
if (contextSensitive) {
|
||||
assignContextualParameterTypes(signature, contextualSignature, getContextualMapper(node), checkMode);
|
||||
}
|
||||
if (mightFixTypeParameters || !node.type && !signature.resolvedReturnType) {
|
||||
if (mightFixTypeParameters || !getEffectiveReturnTypeNode(node) && !signature.resolvedReturnType) {
|
||||
const returnType = getReturnTypeFromBody(node, checkMode);
|
||||
if (!signature.resolvedReturnType) {
|
||||
signature.resolvedReturnType = returnType;
|
||||
@@ -17039,10 +17058,11 @@ namespace ts {
|
||||
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
|
||||
|
||||
const functionFlags = getFunctionFlags(node);
|
||||
const returnOrPromisedType = node.type &&
|
||||
const returnTypeNode = getEffectiveReturnTypeNode(node);
|
||||
const returnOrPromisedType = returnTypeNode &&
|
||||
((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async ?
|
||||
checkAsyncFunctionReturnType(node) : // Async function
|
||||
getTypeFromTypeNode(node.type)); // AsyncGenerator function, Generator function, or normal function
|
||||
getTypeFromTypeNode(returnTypeNode)); // AsyncGenerator function, Generator function, or normal function
|
||||
|
||||
if ((functionFlags & FunctionFlags.Generator) === 0) { // Async function or normal function
|
||||
// return is not necessary in the body of generators
|
||||
@@ -17050,7 +17070,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (node.body) {
|
||||
if (!node.type) {
|
||||
if (!returnTypeNode) {
|
||||
// There are some checks that are only performed in getReturnTypeFromBody, that may produce errors
|
||||
// we need. An example is the noImplicitAny errors resulting from widening the return expression
|
||||
// of a function. Because checking of function expression bodies is deferred, there was never an
|
||||
@@ -17113,8 +17133,9 @@ namespace ts {
|
||||
(expr as PropertyAccessExpression | ElementAccessExpression).expression.kind === SyntaxKind.ThisKeyword) {
|
||||
// Look for if this is the constructor for the class that `symbol` is a property of.
|
||||
const func = getContainingFunction(expr);
|
||||
if (!(func && func.kind === SyntaxKind.Constructor))
|
||||
if (!(func && func.kind === SyntaxKind.Constructor)) {
|
||||
return true;
|
||||
}
|
||||
// If func.parent is a class and symbol is a (readonly) property of that class, or
|
||||
// if func is a constructor and symbol is a (readonly) parameter property declared in it,
|
||||
// then symbol is writeable here.
|
||||
@@ -17835,8 +17856,9 @@ namespace ts {
|
||||
// There is no point in doing an assignability check if the function
|
||||
// has no explicit return type because the return type is directly computed
|
||||
// from the yield expressions.
|
||||
if (func.type) {
|
||||
const signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(func.type), (functionFlags & FunctionFlags.Async) !== 0) || anyType;
|
||||
const returnType = getEffectiveReturnTypeNode(func);
|
||||
if (returnType) {
|
||||
const signatureElementType = getIteratedTypeOfGenerator(getTypeFromTypeNode(returnType), (functionFlags & FunctionFlags.Async) !== 0) || anyType;
|
||||
if (nodeIsYieldStar) {
|
||||
checkTypeAssignableTo(
|
||||
functionFlags & FunctionFlags.Async
|
||||
@@ -18364,13 +18386,15 @@ namespace ts {
|
||||
|
||||
forEach(node.parameters, checkParameter);
|
||||
|
||||
// TODO(rbuckton): Should we start checking JSDoc types?
|
||||
if (node.type) {
|
||||
checkSourceElement(node.type);
|
||||
}
|
||||
|
||||
if (produceDiagnostics) {
|
||||
checkCollisionWithArgumentsInGeneratedCode(node);
|
||||
if (noImplicitAny && !node.type) {
|
||||
const returnTypeNode = getEffectiveReturnTypeNode(node);
|
||||
if (noImplicitAny && !returnTypeNode) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ConstructSignature:
|
||||
error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
|
||||
@@ -18381,12 +18405,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type) {
|
||||
if (returnTypeNode) {
|
||||
const functionFlags = getFunctionFlags(<FunctionDeclaration>node);
|
||||
if ((functionFlags & (FunctionFlags.Invalid | FunctionFlags.Generator)) === FunctionFlags.Generator) {
|
||||
const returnType = getTypeFromTypeNode(node.type);
|
||||
const returnType = getTypeFromTypeNode(returnTypeNode);
|
||||
if (returnType === voidType) {
|
||||
error(node.type, Diagnostics.A_generator_cannot_have_a_void_type_annotation);
|
||||
error(returnTypeNode, Diagnostics.A_generator_cannot_have_a_void_type_annotation);
|
||||
}
|
||||
else {
|
||||
const generatorElementType = getIteratedTypeOfGenerator(returnType, (functionFlags & FunctionFlags.Async) !== 0) || anyType;
|
||||
@@ -18400,7 +18424,7 @@ namespace ts {
|
||||
// interface BadGenerator extends Iterable<number>, Iterator<string> { }
|
||||
// function* g(): BadGenerator { } // Iterable and Iterator have different types!
|
||||
//
|
||||
checkTypeAssignableTo(iterableIteratorInstantiation, returnType, node.type);
|
||||
checkTypeAssignableTo(iterableIteratorInstantiation, returnType, returnTypeNode);
|
||||
}
|
||||
}
|
||||
else if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) {
|
||||
@@ -19416,7 +19440,8 @@ namespace ts {
|
||||
// then<U>(...): Promise<U>;
|
||||
// }
|
||||
//
|
||||
const returnType = getTypeFromTypeNode(node.type);
|
||||
const returnTypeNode = getEffectiveReturnTypeNode(node);
|
||||
const returnType = getTypeFromTypeNode(returnTypeNode);
|
||||
|
||||
if (languageVersion >= ScriptTarget.ES2015) {
|
||||
if (returnType === unknownType) {
|
||||
@@ -19426,21 +19451,21 @@ namespace ts {
|
||||
if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) {
|
||||
// The promise type was not a valid type reference to the global promise type, so we
|
||||
// report an error and return the unknown type.
|
||||
error(node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
|
||||
error(returnTypeNode, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
|
||||
return unknownType;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Always mark the type node as referenced if it points to a value
|
||||
markTypeNodeAsReferenced(node.type);
|
||||
markTypeNodeAsReferenced(returnTypeNode);
|
||||
|
||||
if (returnType === unknownType) {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
const promiseConstructorName = getEntityNameFromTypeNode(node.type);
|
||||
const promiseConstructorName = getEntityNameFromTypeNode(returnTypeNode);
|
||||
if (promiseConstructorName === undefined) {
|
||||
error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(returnType));
|
||||
error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(returnType));
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
@@ -19448,10 +19473,10 @@ namespace ts {
|
||||
const promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : unknownType;
|
||||
if (promiseConstructorType === unknownType) {
|
||||
if (promiseConstructorName.kind === SyntaxKind.Identifier && promiseConstructorName.text === "Promise" && getTargetType(returnType) === getGlobalPromiseType(/*reportErrors*/ false)) {
|
||||
error(node.type, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
|
||||
error(returnTypeNode, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
|
||||
}
|
||||
else {
|
||||
error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
|
||||
error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
@@ -19460,11 +19485,11 @@ namespace ts {
|
||||
if (globalPromiseConstructorLikeType === emptyObjectType) {
|
||||
// If we couldn't resolve the global PromiseConstructorLike type we cannot verify
|
||||
// compatibility with __awaiter.
|
||||
error(node.type, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
|
||||
error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName));
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node.type,
|
||||
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, returnTypeNode,
|
||||
Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) {
|
||||
return unknownType;
|
||||
}
|
||||
@@ -19609,7 +19634,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode {
|
||||
return node.dotDotDotToken ? getRestParameterElementType(node.type) : node.type;
|
||||
const typeNode = getEffectiveTypeAnnotationNode(node);
|
||||
return isRestParameter(node) ? getRestParameterElementType(typeNode) : typeNode;
|
||||
}
|
||||
|
||||
/** Check the decorators of a node */
|
||||
@@ -19655,14 +19681,15 @@ namespace ts {
|
||||
markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter));
|
||||
}
|
||||
|
||||
markDecoratorMedataDataTypeNodeAsReferenced((<FunctionLikeDeclaration>node).type);
|
||||
markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveReturnTypeNode(<FunctionLikeDeclaration>node));
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(<ParameterDeclaration>node));
|
||||
markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveTypeAnnotationNode(<ParameterDeclaration>node));
|
||||
break;
|
||||
|
||||
case SyntaxKind.Parameter:
|
||||
markDecoratorMedataDataTypeNodeAsReferenced((<PropertyDeclaration>node).type);
|
||||
markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(<ParameterDeclaration>node));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -19672,8 +19699,8 @@ namespace ts {
|
||||
|
||||
function checkFunctionDeclaration(node: FunctionDeclaration): void {
|
||||
if (produceDiagnostics) {
|
||||
checkFunctionOrMethodDeclaration(node) || checkGrammarForGenerator(node);
|
||||
|
||||
checkFunctionOrMethodDeclaration(node);
|
||||
checkGrammarForGenerator(node);
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithCapturedNewTargetVariable(node, node.name);
|
||||
@@ -19727,14 +19754,15 @@ namespace ts {
|
||||
|
||||
checkSourceElement(node.body);
|
||||
|
||||
const returnTypeNode = getEffectiveReturnTypeNode(node);
|
||||
if ((functionFlags & FunctionFlags.Generator) === 0) { // Async function or normal function
|
||||
const returnOrPromisedType = node.type && (functionFlags & FunctionFlags.Async
|
||||
const returnOrPromisedType = returnTypeNode && (functionFlags & FunctionFlags.Async
|
||||
? checkAsyncFunctionReturnType(node) // Async function
|
||||
: getTypeFromTypeNode(node.type)); // normal function
|
||||
: getTypeFromTypeNode(returnTypeNode)); // normal function
|
||||
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
|
||||
}
|
||||
|
||||
if (produceDiagnostics && !node.type) {
|
||||
if (produceDiagnostics && !returnTypeNode) {
|
||||
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
|
||||
// in an ambient context
|
||||
if (noImplicitAny && nodeIsMissing(node.body) && !isPrivateWithinAmbient(node)) {
|
||||
@@ -20867,7 +20895,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLikeDeclaration) {
|
||||
return !!(node.kind === SyntaxKind.GetAccessor && getSetAccessorTypeAnnotationNode(getDeclarationOfKind<SetAccessorDeclaration>(node.symbol, SyntaxKind.SetAccessor)));
|
||||
return node.kind === SyntaxKind.GetAccessor
|
||||
&& getEffectiveSetAccessorTypeAnnotationNode(getDeclarationOfKind<SetAccessorDeclaration>(node.symbol, SyntaxKind.SetAccessor)) !== undefined;
|
||||
}
|
||||
|
||||
function isUnwrappedReturnTypeVoidOrAny(func: FunctionLikeDeclaration, returnType: Type): boolean {
|
||||
@@ -20911,7 +20940,7 @@ namespace ts {
|
||||
error(node, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
|
||||
}
|
||||
}
|
||||
else if (func.type || isGetAccessorWithAnnotatedSetAccessor(func)) {
|
||||
else if (getEffectiveReturnTypeNode(func) || isGetAccessorWithAnnotatedSetAccessor(func)) {
|
||||
if (functionFlags & FunctionFlags.Async) { // Async function
|
||||
const promisedType = getPromisedTypeOfPromise(returnType);
|
||||
const awaitedType = checkAwaitedType(exprType, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
|
||||
@@ -22050,7 +22079,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Don't allow to re-export something with no value side when `--isolatedModules` is set.
|
||||
if (node.kind === SyntaxKind.ExportSpecifier && compilerOptions.isolatedModules && !(target.flags & SymbolFlags.Value)) {
|
||||
if (compilerOptions.isolatedModules
|
||||
&& node.kind === SyntaxKind.ExportSpecifier
|
||||
&& !(target.flags & SymbolFlags.Value)
|
||||
&& !isInAmbientContext(node)) {
|
||||
error(node, Diagnostics.Cannot_re_export_a_type_when_the_isolatedModules_flag_is_provided);
|
||||
}
|
||||
}
|
||||
@@ -22154,6 +22186,10 @@ namespace ts {
|
||||
if (moduleSymbol && hasExportAssignmentSymbol(moduleSymbol)) {
|
||||
error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol));
|
||||
}
|
||||
|
||||
if (modulekind !== ModuleKind.System && modulekind !== ModuleKind.ES2015) {
|
||||
checkExternalEmitHelpers(node, ExternalEmitHelpers.ExportStar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22810,10 +22846,16 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (entityName.parent!.kind === SyntaxKind.JSDocParameterTag) {
|
||||
const parameter = ts.getParameterFromJSDoc(entityName.parent as JSDocParameterTag);
|
||||
const parameter = getParameterFromJSDoc(entityName.parent as JSDocParameterTag);
|
||||
return parameter && parameter.symbol;
|
||||
}
|
||||
|
||||
if (entityName.parent.kind === SyntaxKind.TypeParameter && entityName.parent.parent.kind === SyntaxKind.JSDocTemplateTag) {
|
||||
Debug.assert(!isInJavaScriptFile(entityName)); // Otherwise `isDeclarationName` would have been true.
|
||||
const typeParameter = getTypeParameterFromJsDoc(entityName.parent as TypeParameterDeclaration & { parent: JSDocTemplateTag });
|
||||
return typeParameter && typeParameter.symbol;
|
||||
}
|
||||
|
||||
if (isPartOfExpression(entityName)) {
|
||||
if (nodeIsMissing(entityName)) {
|
||||
// Missing entity name.
|
||||
@@ -23849,7 +23891,8 @@ namespace ts {
|
||||
case ExternalEmitHelpers.AsyncGenerator: return "__asyncGenerator";
|
||||
case ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator";
|
||||
case ExternalEmitHelpers.AsyncValues: return "__asyncValues";
|
||||
default: Debug.fail("Unrecognized helper.");
|
||||
case ExternalEmitHelpers.ExportStar: return "__exportStar";
|
||||
default: Debug.fail("Unrecognized helper");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25112,7 +25155,6 @@ namespace ts {
|
||||
// falls through
|
||||
default:
|
||||
return isDeclarationName(name);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1626,10 +1626,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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1717,10 +1719,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;
|
||||
|
||||
+36
-17
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -598,7 +598,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);
|
||||
}
|
||||
|
||||
|
||||
+20
-6
@@ -961,7 +961,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);
|
||||
}
|
||||
@@ -2285,11 +2285,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 {
|
||||
|
||||
+32
-21
@@ -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;
|
||||
@@ -3850,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4249,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:
|
||||
@@ -4370,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 };
|
||||
}
|
||||
|
||||
|
||||
+23
-23
@@ -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 {
|
||||
@@ -481,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 */
|
||||
@@ -1099,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);
|
||||
}
|
||||
@@ -3716,7 +3720,7 @@ namespace ts {
|
||||
// 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.PossiblyContainDynamicImport;
|
||||
sourceFile.flags |= NodeFlags.PossiblyContainsDynamicImport;
|
||||
expression = parseTokenNode<PrimaryExpression>();
|
||||
}
|
||||
else {
|
||||
@@ -6678,14 +6682,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)) {
|
||||
@@ -6694,9 +6696,7 @@ namespace ts {
|
||||
|
||||
parseExpected(SyntaxKind.CloseBracketToken);
|
||||
}
|
||||
else if (tokenIsIdentifierOrKeyword(token())) {
|
||||
name = parseJSDocIdentifierName();
|
||||
}
|
||||
|
||||
return { name, isBracketed };
|
||||
}
|
||||
|
||||
@@ -6707,11 +6707,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;
|
||||
@@ -6962,14 +6957,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();
|
||||
|
||||
@@ -1379,7 +1379,7 @@ namespace ts {
|
||||
|
||||
for (const node of file.statements) {
|
||||
collectModuleReferences(node, /*inAmbientModule*/ false);
|
||||
if ((file.flags & NodeFlags.PossiblyContainDynamicImport) || isJavaScriptFile) {
|
||||
if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) {
|
||||
collectDynamicImportOrRequireCalls(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -239,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];
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ 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);
|
||||
@@ -408,7 +408,7 @@ 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);
|
||||
@@ -514,14 +514,14 @@ namespace ts {
|
||||
|
||||
function visitImportCallExpression(node: ImportCall): Expression {
|
||||
switch (compilerOptions.module) {
|
||||
case ModuleKind.CommonJS:
|
||||
return transformImportCallExpressionCommonJS(node);
|
||||
case ModuleKind.AMD:
|
||||
return transformImportCallExpressionAMD(node);
|
||||
case ModuleKind.UMD:
|
||||
return transformImportCallExpressionUMD(node);
|
||||
case ModuleKind.CommonJS:
|
||||
default:
|
||||
return transformImportCallExpressionCommonJS(node);
|
||||
}
|
||||
Debug.fail("All supported module kind in this transformation step should have been handled");
|
||||
}
|
||||
|
||||
function transformImportCallExpressionUMD(node: ImportCall): Expression {
|
||||
@@ -833,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
|
||||
);
|
||||
@@ -1598,9 +1590,17 @@ 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",
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
+14
-10
@@ -426,7 +426,7 @@ namespace ts {
|
||||
FirstNode = QualifiedName,
|
||||
FirstJSDocNode = JSDocTypeExpression,
|
||||
LastJSDocNode = JSDocLiteralType,
|
||||
FirstJSDocTagNode = JSDocComment,
|
||||
FirstJSDocTagNode = JSDocTag,
|
||||
LastJSDocTagNode = JSDocLiteralType
|
||||
}
|
||||
|
||||
@@ -452,13 +452,16 @@ 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 to true when the parse encounter dynamic import so that post-parsing process of module resolution
|
||||
// will not walk the tree if the flag is not set. However, this flag is just a approximation because once it is set, the flag never get reset.
|
||||
// (hence it is named "possiblyContainDynamicImport").
|
||||
// During editing, if dynamic import is remove, incremental parsing will *NOT* update this flag. This will then causes walking of the tree 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 back the import anyway.
|
||||
// The advantage of this approach is its simplicity. For the case of batch compilation, we garuntee that users won't have to pay the price of walking the tree if dynamic import isn't used.
|
||||
PossiblyContainDynamicImport = 1 << 19,
|
||||
// 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,
|
||||
|
||||
@@ -1799,7 +1802,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;
|
||||
@@ -4118,6 +4121,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,
|
||||
@@ -4135,7 +4139,7 @@ namespace ts {
|
||||
SpreadIncludes = Read | Spread,
|
||||
|
||||
FirstEmitHelper = Extends,
|
||||
LastEmitHelper = AsyncValues
|
||||
LastEmitHelper = ExportStar
|
||||
}
|
||||
|
||||
export const enum EmitHint {
|
||||
|
||||
@@ -1558,6 +1558,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) {
|
||||
@@ -1582,6 +1588,11 @@ namespace ts {
|
||||
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;
|
||||
}
|
||||
@@ -2627,14 +2638,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];
|
||||
@@ -2713,6 +2729,41 @@ 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 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);
|
||||
}
|
||||
@@ -4682,6 +4733,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.
|
||||
@@ -5231,6 +5292,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);
|
||||
}
|
||||
|
||||
@@ -5320,6 +5385,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 {
|
||||
|
||||
+47
-29
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+47
-32
@@ -1036,21 +1036,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;
|
||||
@@ -1132,15 +1138,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1149,7 +1157,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) : "";
|
||||
@@ -1595,16 +1602,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);
|
||||
}
|
||||
|
||||
@@ -2156,7 +2166,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 +
|
||||
@@ -2196,9 +2206,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) + "'";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2221,14 +2233,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[]) {
|
||||
@@ -2741,6 +2753,7 @@ namespace FourSlash {
|
||||
markerName: string,
|
||||
expectedContent: string,
|
||||
refactorNameToApply: string,
|
||||
actionName: string,
|
||||
formattingOptions?: ts.FormatCodeSettings) {
|
||||
|
||||
formattingOptions = formattingOptions || this.formatCodeSettings;
|
||||
@@ -2753,9 +2766,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.applyCodeActions(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)) {
|
||||
@@ -3798,8 +3813,8 @@ 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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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,7 +252,26 @@ 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"] {
|
||||
@@ -260,28 +283,6 @@ namespace ts.projectSystem {
|
||||
}
|
||||
}
|
||||
|
||||
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) };
|
||||
}
|
||||
|
||||
@@ -472,7 +472,7 @@ namespace ts.projectSystem {
|
||||
}
|
||||
|
||||
createHash(s: string): string {
|
||||
return s;
|
||||
return Harness.LanguageService.mockHash(s);
|
||||
}
|
||||
|
||||
triggerDirectoryWatcherCallback(directoryName: string, fileName: string): void {
|
||||
|
||||
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;
|
||||
|
||||
+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()),
|
||||
|
||||
+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,7 +44,7 @@ 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":
|
||||
@@ -51,7 +52,7 @@ namespace ts.server {
|
||||
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}'`);
|
||||
@@ -526,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);
|
||||
}
|
||||
});
|
||||
|
||||
+41
-18
@@ -1425,29 +1425,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 +1516,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 +1563,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(".d.ts") > 0) {
|
||||
veryLowPriorityFiles.push(fileNameInProject);
|
||||
else
|
||||
}
|
||||
else {
|
||||
lowPriorityFiles.push(fileNameInProject);
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
mediumPriorityFiles.push(fileNameInProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1833,11 +1856,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));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+76
-29
@@ -18,7 +18,7 @@ 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 (sourceFile.languageVariant === LanguageVariant.JSX &&
|
||||
location && location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) {
|
||||
@@ -36,14 +36,15 @@ namespace ts.Completions {
|
||||
}]};
|
||||
}
|
||||
|
||||
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 (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[] = [];
|
||||
@@ -66,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);
|
||||
}
|
||||
|
||||
@@ -347,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();
|
||||
const currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853
|
||||
const currentToken = getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false);
|
||||
// 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();
|
||||
@@ -366,10 +378,10 @@ namespace ts.Completions {
|
||||
|
||||
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
|
||||
@@ -389,7 +401,9 @@ 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" };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,10 +411,10 @@ namespace ts.Completions {
|
||||
// /** @type {number | string} */
|
||||
// Completion should work in the brackets
|
||||
let insideJsDocTagExpression = false;
|
||||
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" };
|
||||
}
|
||||
|
||||
switch (tag.kind) {
|
||||
@@ -408,15 +422,18 @@ namespace ts.Completions {
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
case SyntaxKind.JSDocReturnTag:
|
||||
const tagWithExpression = <JSDocTypeTag | JSDocParameterTag | JSDocReturnTag>tag;
|
||||
if (tagWithExpression.typeExpression) {
|
||||
insideJsDocTagExpression = tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end;
|
||||
if (tagWithExpression.typeExpression && tagWithExpression.typeExpression.pos < position && position < tagWithExpression.typeExpression.end) {
|
||||
insideJsDocTagExpression = true;
|
||||
}
|
||||
else if (isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) {
|
||||
request = { kind: "JsDocParameterName", tag };
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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 (!insideJsDocTagExpression) {
|
||||
@@ -428,7 +445,7 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
start = timestamp();
|
||||
const previousToken = findPrecedingToken(position, sourceFile);
|
||||
const previousToken = findPrecedingToken(position, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true);
|
||||
log("getCompletionData: Get previous token 1: " + (timestamp() - start));
|
||||
|
||||
// The decision to provide completion depends on the contextToken, which is determined through the previousToken.
|
||||
@@ -439,7 +456,7 @@ namespace ts.Completions {
|
||||
// Skip this partial identifier and adjust the contextToken to the token that precedes it.
|
||||
if (contextToken && position <= contextToken.end && isWord(contextToken.kind)) {
|
||||
const start = timestamp();
|
||||
contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile);
|
||||
contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true);
|
||||
log("getCompletionData: Get previous token 2: " + (timestamp() - start));
|
||||
}
|
||||
|
||||
@@ -553,7 +570,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 };
|
||||
|
||||
function getTypeScriptMemberSymbols(): void {
|
||||
// Right of dot member completion list
|
||||
@@ -1518,4 +1535,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,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[][] = [];
|
||||
@@ -785,8 +784,8 @@ 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)) {
|
||||
// Need to search in the full start of the node in case there is a reference inside JSDoc.
|
||||
for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container, /*fullStart*/ true)) {
|
||||
getReferencesAtLocation(sourceFile, position, search, state);
|
||||
}
|
||||
}
|
||||
|
||||
+125
-90
@@ -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,6 +543,22 @@ 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) {
|
||||
@@ -578,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.
|
||||
|
||||
@@ -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,16 +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 {
|
||||
export function getEditsForRefactor(context: RefactorContext, refactorName: string, actionName: string): RefactorEditInfo | undefined {
|
||||
const refactor = refactors.get(refactorName);
|
||||
return refactor && refactor.getCodeActions(context);
|
||||
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))) {
|
||||
|
||||
+47
-49
@@ -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 {
|
||||
@@ -684,8 +680,9 @@ namespace ts {
|
||||
forEachChild(decl.name, visit);
|
||||
break;
|
||||
}
|
||||
if (decl.initializer)
|
||||
if (decl.initializer) {
|
||||
visit(decl.initializer);
|
||||
}
|
||||
}
|
||||
// falls through
|
||||
case SyntaxKind.EnumMember:
|
||||
@@ -1999,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 {
|
||||
@@ -2015,8 +2013,6 @@ namespace ts {
|
||||
cleanupSemanticCache,
|
||||
getSyntacticDiagnostics,
|
||||
getSemanticDiagnostics,
|
||||
getApplicableRefactors,
|
||||
getRefactorCodeActions,
|
||||
getCompilerOptionsDiagnostics,
|
||||
getSyntacticClassifications,
|
||||
getSemanticClassifications,
|
||||
@@ -2054,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;
|
||||
|
||||
+51
-1
@@ -265,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;
|
||||
|
||||
@@ -357,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 (isTypeParameter(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): 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);
|
||||
const start = (includeJsDoc && child.jsDoc ? child.jsDoc[0] : child).getStart(sourceFile);
|
||||
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.
|
||||
|
||||
+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
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
tests/cases/conformance/jsdoc/returns.js(6,5): error TS2322: Type '5' is not assignable to type 'string'.
|
||||
tests/cases/conformance/jsdoc/returns.js(13,5): error TS2322: Type 'true | 5' is not assignable to type 'string | number'.
|
||||
Type 'true' is not assignable to type 'string | number'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/returns.js (2 errors) ====
|
||||
// @ts-check
|
||||
/**
|
||||
* @returns {string} This comment is not currently exposed
|
||||
*/
|
||||
function f() {
|
||||
return 5;
|
||||
~~~~~~~~~
|
||||
!!! error TS2322: Type '5' is not assignable to type 'string'.
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string | number} This comment is not currently exposed
|
||||
*/
|
||||
function f1() {
|
||||
return 5 || true;
|
||||
~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type 'true | 5' is not assignable to type 'string | number'.
|
||||
!!! error TS2322: Type 'true' is not assignable to type 'string | number'.
|
||||
}
|
||||
@@ -61,10 +61,10 @@ x(1);
|
||||
/** @type {function (number)} */
|
||||
const x1 = (a) => a + 1;
|
||||
>x1 : (arg0: number) => any
|
||||
>(a) => a + 1 : (a: any) => any
|
||||
>a : any
|
||||
>a + 1 : any
|
||||
>a : any
|
||||
>(a) => a + 1 : (a: number) => number
|
||||
>a : number
|
||||
>a + 1 : number
|
||||
>a : number
|
||||
>1 : 1
|
||||
|
||||
x1(0);
|
||||
@@ -75,10 +75,10 @@ x1(0);
|
||||
/** @type {function (number): number} */
|
||||
const x2 = (a) => a + 1;
|
||||
>x2 : (arg0: number) => number
|
||||
>(a) => a + 1 : (a: any) => any
|
||||
>a : any
|
||||
>a + 1 : any
|
||||
>a : any
|
||||
>(a) => a + 1 : (a: number) => number
|
||||
>a : number
|
||||
>a + 1 : number
|
||||
>a : number
|
||||
>1 : 1
|
||||
|
||||
x2(0);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
tests/cases/conformance/jsdoc/0.js(3,5): error TS2322: Type 'true' is not assignable to type 'string'.
|
||||
tests/cases/conformance/jsdoc/0.js(6,5): error TS2322: Type '"hello"' is not assignable to type 'number'.
|
||||
tests/cases/conformance/jsdoc/0.js(10,4): error TS2345: Argument of type '"string"' is not assignable to parameter of type 'number'.
|
||||
tests/cases/conformance/jsdoc/0.js(13,7): error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
tests/cases/conformance/jsdoc/0.js(17,1): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/jsdoc/0.js(20,7): error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
tests/cases/conformance/jsdoc/0.js(20,21): error TS2339: Property 'concat' does not exist on type 'number'.
|
||||
tests/cases/conformance/jsdoc/0.js(24,7): error TS2322: Type '(a: number) => number' is not assignable to type '(arg0: number) => string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsdoc/0.js (6 errors) ====
|
||||
@@ -26,8 +27,6 @@ tests/cases/conformance/jsdoc/0.js(20,7): error TS2451: Cannot redeclare block-s
|
||||
|
||||
/** @type {function (number): number} */
|
||||
const x2 = (a) => a + 1;
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
|
||||
/** @type {string} */
|
||||
var a;
|
||||
@@ -36,7 +35,14 @@ tests/cases/conformance/jsdoc/0.js(20,7): error TS2451: Cannot redeclare block-s
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
/** @type {function (number): number} */
|
||||
const x2 = (a) => a.concat("hi");
|
||||
const x3 = (a) => a.concat("hi");
|
||||
~~~~~~
|
||||
!!! error TS2339: Property 'concat' does not exist on type 'number'.
|
||||
x3(0);
|
||||
|
||||
/** @type {function (number): string} */
|
||||
const x4 = (a) => a + 1;
|
||||
~~
|
||||
!!! error TS2451: Cannot redeclare block-scoped variable 'x2'.
|
||||
x2(0);
|
||||
!!! error TS2322: Type '(a: number) => number' is not assignable to type '(arg0: number) => string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
x4(0);
|
||||
@@ -18,8 +18,12 @@ var a;
|
||||
a = x2(0);
|
||||
|
||||
/** @type {function (number): number} */
|
||||
const x2 = (a) => a.concat("hi");
|
||||
x2(0);
|
||||
const x3 = (a) => a.concat("hi");
|
||||
x3(0);
|
||||
|
||||
/** @type {function (number): string} */
|
||||
const x4 = (a) => a + 1;
|
||||
x4(0);
|
||||
|
||||
//// [0.js]
|
||||
// @ts-check
|
||||
@@ -36,5 +40,8 @@ var x2 = function (a) { return a + 1; };
|
||||
var a;
|
||||
a = x2(0);
|
||||
/** @type {function (number): number} */
|
||||
var x2 = function (a) { return a.concat("hi"); };
|
||||
x2(0);
|
||||
var x3 = function (a) { return a.concat("hi"); };
|
||||
x3(0);
|
||||
/** @type {function (number): string} */
|
||||
var x4 = function (a) { return a + 1; };
|
||||
x4(0);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
=== tests/cases/conformance/types/contextualTypes/jsdoc/index.js ===
|
||||
/** @type {Array<[string, {x?:number, y?:number}]>} */
|
||||
const arr = [
|
||||
>arr : Symbol(arr, Decl(index.js, 1, 5))
|
||||
|
||||
['a', { x: 1 }],
|
||||
>x : Symbol(x, Decl(index.js, 2, 11))
|
||||
|
||||
['b', { y: 2 }]
|
||||
>y : Symbol(y, Decl(index.js, 3, 11))
|
||||
|
||||
];
|
||||
|
||||
/** @return {Array<[string, {x?:number, y?:number}]>} */
|
||||
function f() {
|
||||
>f : Symbol(f, Decl(index.js, 4, 2))
|
||||
|
||||
return [
|
||||
['a', { x: 1 }],
|
||||
>x : Symbol(x, Decl(index.js, 9, 15))
|
||||
|
||||
['b', { y: 2 }]
|
||||
>y : Symbol(y, Decl(index.js, 10, 15))
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
class C {
|
||||
>C : Symbol(C, Decl(index.js, 12, 1))
|
||||
|
||||
/** @param {Array<[string, {x?:number, y?:number}]>} value */
|
||||
set x(value) { }
|
||||
>x : Symbol(C.x, Decl(index.js, 14, 9), Decl(index.js, 16, 20))
|
||||
>value : Symbol(value, Decl(index.js, 16, 10))
|
||||
|
||||
get x() {
|
||||
>x : Symbol(C.x, Decl(index.js, 14, 9), Decl(index.js, 16, 20))
|
||||
|
||||
return [
|
||||
['a', { x: 1 }],
|
||||
>x : Symbol(x, Decl(index.js, 19, 19))
|
||||
|
||||
['b', { y: 2 }]
|
||||
>y : Symbol(y, Decl(index.js, 20, 19))
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
=== tests/cases/conformance/types/contextualTypes/jsdoc/index.js ===
|
||||
/** @type {Array<[string, {x?:number, y?:number}]>} */
|
||||
const arr = [
|
||||
>arr : [string, { x?: number; y?: number; }][]
|
||||
>[ ['a', { x: 1 }], ['b', { y: 2 }]] : ([string, { x: number; }] | [string, { y: number; }])[]
|
||||
|
||||
['a', { x: 1 }],
|
||||
>['a', { x: 1 }] : [string, { x: number; }]
|
||||
>'a' : "a"
|
||||
>{ x: 1 } : { x: number; }
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
['b', { y: 2 }]
|
||||
>['b', { y: 2 }] : [string, { y: number; }]
|
||||
>'b' : "b"
|
||||
>{ y: 2 } : { y: number; }
|
||||
>y : number
|
||||
>2 : 2
|
||||
|
||||
];
|
||||
|
||||
/** @return {Array<[string, {x?:number, y?:number}]>} */
|
||||
function f() {
|
||||
>f : () => [string, { x?: number; y?: number; }][]
|
||||
|
||||
return [
|
||||
>[ ['a', { x: 1 }], ['b', { y: 2 }] ] : ([string, { x: number; }] | [string, { y: number; }])[]
|
||||
|
||||
['a', { x: 1 }],
|
||||
>['a', { x: 1 }] : [string, { x: number; }]
|
||||
>'a' : "a"
|
||||
>{ x: 1 } : { x: number; }
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
['b', { y: 2 }]
|
||||
>['b', { y: 2 }] : [string, { y: number; }]
|
||||
>'b' : "b"
|
||||
>{ y: 2 } : { y: number; }
|
||||
>y : number
|
||||
>2 : 2
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
class C {
|
||||
>C : C
|
||||
|
||||
/** @param {Array<[string, {x?:number, y?:number}]>} value */
|
||||
set x(value) { }
|
||||
>x : [string, { x?: number; y?: number; }][]
|
||||
>value : [string, { x?: number; y?: number; }][]
|
||||
|
||||
get x() {
|
||||
>x : [string, { x?: number; y?: number; }][]
|
||||
|
||||
return [
|
||||
>[ ['a', { x: 1 }], ['b', { y: 2 }] ] : ([string, { x: number; }] | [string, { y: number; }])[]
|
||||
|
||||
['a', { x: 1 }],
|
||||
>['a', { x: 1 }] : [string, { x: number; }]
|
||||
>'a' : "a"
|
||||
>{ x: 1 } : { x: number; }
|
||||
>x : number
|
||||
>1 : 1
|
||||
|
||||
['b', { y: 2 }]
|
||||
>['b', { y: 2 }] : [string, { y: number; }]
|
||||
>'b' : "b"
|
||||
>{ y: 2 } : { y: number; }
|
||||
>y : number
|
||||
>2 : 2
|
||||
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
tests/cases/compiler/excessPropertyCheckWithSpread.ts(6,3): error TS2345: Argument of type '{ n: number; a: number; }' is not assignable to parameter of type '{ a: any; }'.
|
||||
Object literal may only specify known properties, and 'n' does not exist in type '{ a: any; }'.
|
||||
tests/cases/compiler/excessPropertyCheckWithSpread.ts(16,3): error TS2345: Argument of type '{ opt: string | number; a: number; }' is not assignable to parameter of type '{ a: any; }'.
|
||||
Object literal may only specify known properties, and 'opt' does not exist in type '{ a: any; }'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/excessPropertyCheckWithSpread.ts (2 errors) ====
|
||||
declare function f({ a: number }): void
|
||||
interface I {
|
||||
readonly n: number;
|
||||
}
|
||||
declare let i: I;
|
||||
f({ a: 1, ...i });
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '{ n: number; a: number; }' is not assignable to parameter of type '{ a: any; }'.
|
||||
!!! error TS2345: Object literal may only specify known properties, and 'n' does not exist in type '{ a: any; }'.
|
||||
|
||||
interface R {
|
||||
opt?: number
|
||||
}
|
||||
interface L {
|
||||
opt: string
|
||||
}
|
||||
declare let l: L;
|
||||
declare let r: R;
|
||||
f({ a: 1, ...l, ...r });
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '{ opt: string | number; a: number; }' is not assignable to parameter of type '{ a: any; }'.
|
||||
!!! error TS2345: Object literal may only specify known properties, and 'opt' does not exist in type '{ a: any; }'.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//// [excessPropertyCheckWithSpread.ts]
|
||||
declare function f({ a: number }): void
|
||||
interface I {
|
||||
readonly n: number;
|
||||
}
|
||||
declare let i: I;
|
||||
f({ a: 1, ...i });
|
||||
|
||||
interface R {
|
||||
opt?: number
|
||||
}
|
||||
interface L {
|
||||
opt: string
|
||||
}
|
||||
declare let l: L;
|
||||
declare let r: R;
|
||||
f({ a: 1, ...l, ...r });
|
||||
|
||||
|
||||
//// [excessPropertyCheckWithSpread.js]
|
||||
var __assign = (this && this.__assign) || Object.assign || function(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
f(__assign({ a: 1 }, i));
|
||||
f(__assign({ a: 1 }, l, r));
|
||||
@@ -1,11 +1,12 @@
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(24,14): error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
|
||||
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<State>'.
|
||||
Type 'State | 1' is not assignable to type 'State'.
|
||||
Type '1' is not assignable to type 'State'.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(24,61): error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
|
||||
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
|
||||
Type 'State | 1' is not assignable to type 'StrategicState'.
|
||||
Type '1' has no properties in common with type 'StrategicState'.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(29,70): error TS7025: Generator implicitly has type 'IterableIterator<any>' because it does not yield any values. Consider supplying a return type.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(32,42): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
|
||||
Type argument candidate 'State' is not a valid type argument because it is not a supertype of candidate '1'.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,14): error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,62): error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
|
||||
Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts (4 errors) ====
|
||||
@@ -33,11 +34,11 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,14): err
|
||||
}
|
||||
|
||||
export const Nothing: Strategy<State> = strategy("Nothing", function* (state: State) {
|
||||
~~~~~~~
|
||||
!!! error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
|
||||
!!! error TS2322: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<State>'.
|
||||
!!! error TS2322: Type 'State | 1' is not assignable to type 'State'.
|
||||
!!! error TS2322: Type '1' is not assignable to type 'State'.
|
||||
~~~~~~~~
|
||||
!!! error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
|
||||
!!! error TS2345: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
|
||||
!!! error TS2345: Type 'State | 1' is not assignable to type 'StrategicState'.
|
||||
!!! error TS2345: Type '1' has no properties in common with type 'StrategicState'.
|
||||
yield 1;
|
||||
return state;
|
||||
});
|
||||
@@ -55,8 +56,9 @@ tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck63.ts(36,14): err
|
||||
});
|
||||
|
||||
export const Nothing3: Strategy<State> = strategy("Nothing", function* (state: State) {
|
||||
~~~~~~~~
|
||||
!!! error TS2322: Type '(a: State | 1) => IterableIterator<State | 1>' is not assignable to type 'Strategy<State>'.
|
||||
~~~~~~~~
|
||||
!!! error TS2345: Argument of type '(state: State) => IterableIterator<State | 1>' is not assignable to parameter of type '(a: StrategicState) => IterableIterator<StrategicState>'.
|
||||
!!! error TS2345: Type 'IterableIterator<State | 1>' is not assignable to type 'IterableIterator<StrategicState>'.
|
||||
yield state;
|
||||
return 1;
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
error TS2468: Cannot find global value 'Promise'.
|
||||
tests/cases/conformance/dynamicImport/2.ts(3,24): error TS2712: 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.
|
||||
tests/cases/conformance/dynamicImport/2.ts(7,12): error TS2705: An async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option.
|
||||
tests/cases/conformance/dynamicImport/2.ts(9,29): error TS2712: 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.
|
||||
|
||||
|
||||
!!! error TS2468: Cannot find global value 'Promise'.
|
||||
==== tests/cases/conformance/dynamicImport/0.ts (0 errors) ====
|
||||
export class B {
|
||||
print() { return "I am B"}
|
||||
}
|
||||
|
||||
export function foo() { return "foo" }
|
||||
|
||||
==== tests/cases/conformance/dynamicImport/1.ts (0 errors) ====
|
||||
export function backup() { return "backup"; }
|
||||
|
||||
==== tests/cases/conformance/dynamicImport/2.ts (3 errors) ====
|
||||
declare var console: any;
|
||||
class C {
|
||||
private myModule = import("./0");
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2712: 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.
|
||||
method() {
|
||||
this.myModule.then(Zero => {
|
||||
console.log(Zero.foo());
|
||||
}, async err => {
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2705: An async function or method in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option.
|
||||
console.log(err);
|
||||
let one = await import("./1");
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2712: 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.
|
||||
console.log(one.backup());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
//// [tests/cases/conformance/dynamicImport/importCallExpressionNoModuleKindSpecified.ts] ////
|
||||
|
||||
//// [0.ts]
|
||||
export class B {
|
||||
print() { return "I am B"}
|
||||
}
|
||||
|
||||
export function foo() { return "foo" }
|
||||
|
||||
//// [1.ts]
|
||||
export function backup() { return "backup"; }
|
||||
|
||||
//// [2.ts]
|
||||
declare var console: any;
|
||||
class C {
|
||||
private myModule = import("./0");
|
||||
method() {
|
||||
this.myModule.then(Zero => {
|
||||
console.log(Zero.foo());
|
||||
}, async err => {
|
||||
console.log(err);
|
||||
let one = await import("./1");
|
||||
console.log(one.backup());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//// [0.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var B = (function () {
|
||||
function B() {
|
||||
}
|
||||
B.prototype.print = function () { return "I am B"; };
|
||||
return B;
|
||||
}());
|
||||
exports.B = B;
|
||||
function foo() { return "foo"; }
|
||||
exports.foo = foo;
|
||||
//// [1.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
function backup() { return "backup"; }
|
||||
exports.backup = backup;
|
||||
//// [2.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __generator = (this && this.__generator) || function (thisArg, body) {
|
||||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (_) try {
|
||||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [0, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
};
|
||||
var C = (function () {
|
||||
function C() {
|
||||
this.myModule = Promise.resolve().then(function () { return require("./0"); });
|
||||
}
|
||||
C.prototype.method = function () {
|
||||
var _this = this;
|
||||
this.myModule.then(function (Zero) {
|
||||
console.log(Zero.foo());
|
||||
}, function (err) { return __awaiter(_this, void 0, void 0, function () {
|
||||
var one;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
console.log(err);
|
||||
return [4 /*yield*/, Promise.resolve().then(function () { return require("./1"); })];
|
||||
case 1:
|
||||
one = _a.sent();
|
||||
console.log(one.backup());
|
||||
return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
}); });
|
||||
};
|
||||
return C;
|
||||
}());
|
||||
@@ -5,16 +5,19 @@ export class A { }
|
||||
|
||||
//// [b.ts]
|
||||
import { A } from "./a";
|
||||
export * from "./a";
|
||||
export class B extends A { }
|
||||
|
||||
//// [tslib.d.ts]
|
||||
export declare function __extends(d: Function, b: Function): void;
|
||||
export declare function __assign(t: any, ...sources: any[]): any;
|
||||
export declare function __rest(t: any, propertyNames: string[]): any;
|
||||
export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
|
||||
export declare function __param(paramIndex: number, decorator: Function): Function;
|
||||
export declare function __metadata(metadataKey: any, metadataValue: any): Function;
|
||||
export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;
|
||||
|
||||
export declare function __generator(thisArg: any, body: Function): any;
|
||||
export declare function __exportStar(m: any, exports: any): void;
|
||||
|
||||
//// [a.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
@@ -28,9 +31,10 @@ define(["require", "exports"], function (require, exports) {
|
||||
exports.A = A;
|
||||
});
|
||||
//// [b.js]
|
||||
define(["require", "exports", "tslib", "./a"], function (require, exports, tslib_1, a_1) {
|
||||
define(["require", "exports", "tslib", "./a", "./a"], function (require, exports, tslib_1, a_1, a_2) {
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
tslib_1.__exportStar(a_2, exports);
|
||||
var B = (function (_super) {
|
||||
tslib_1.__extends(B, _super);
|
||||
function B() {
|
||||
|
||||
@@ -6,8 +6,9 @@ export class A { }
|
||||
import { A } from "./a";
|
||||
>A : Symbol(A, Decl(b.ts, 0, 8))
|
||||
|
||||
export * from "./a";
|
||||
export class B extends A { }
|
||||
>B : Symbol(B, Decl(b.ts, 0, 24))
|
||||
>B : Symbol(B, Decl(b.ts, 1, 20))
|
||||
>A : Symbol(A, Decl(b.ts, 0, 8))
|
||||
|
||||
=== tests/cases/compiler/tslib.d.ts ===
|
||||
@@ -23,6 +24,11 @@ export declare function __assign(t: any, ...sources: any[]): any;
|
||||
>t : Symbol(t, Decl(tslib.d.ts, --, --))
|
||||
>sources : Symbol(sources, Decl(tslib.d.ts, --, --))
|
||||
|
||||
export declare function __rest(t: any, propertyNames: string[]): any;
|
||||
>__rest : Symbol(__rest, Decl(tslib.d.ts, --, --))
|
||||
>t : Symbol(t, Decl(tslib.d.ts, --, --))
|
||||
>propertyNames : Symbol(propertyNames, Decl(tslib.d.ts, --, --))
|
||||
|
||||
export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
|
||||
>__decorate : Symbol(__decorate, Decl(tslib.d.ts, --, --))
|
||||
>decorators : Symbol(decorators, Decl(tslib.d.ts, --, --))
|
||||
@@ -53,3 +59,14 @@ export declare function __awaiter(thisArg: any, _arguments: any, P: Function, ge
|
||||
>generator : Symbol(generator, Decl(tslib.d.ts, --, --))
|
||||
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
export declare function __generator(thisArg: any, body: Function): any;
|
||||
>__generator : Symbol(__generator, Decl(tslib.d.ts, --, --))
|
||||
>thisArg : Symbol(thisArg, Decl(tslib.d.ts, --, --))
|
||||
>body : Symbol(body, Decl(tslib.d.ts, --, --))
|
||||
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
export declare function __exportStar(m: any, exports: any): void;
|
||||
>__exportStar : Symbol(__exportStar, Decl(tslib.d.ts, --, --))
|
||||
>m : Symbol(m, Decl(tslib.d.ts, --, --))
|
||||
>exports : Symbol(exports, Decl(tslib.d.ts, --, --))
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ export class A { }
|
||||
import { A } from "./a";
|
||||
>A : typeof A
|
||||
|
||||
export * from "./a";
|
||||
export class B extends A { }
|
||||
>B : B
|
||||
>A : A
|
||||
@@ -23,6 +24,11 @@ export declare function __assign(t: any, ...sources: any[]): any;
|
||||
>t : any
|
||||
>sources : any[]
|
||||
|
||||
export declare function __rest(t: any, propertyNames: string[]): any;
|
||||
>__rest : (t: any, propertyNames: string[]) => any
|
||||
>t : any
|
||||
>propertyNames : string[]
|
||||
|
||||
export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
|
||||
>__decorate : (decorators: Function[], target: any, key?: string | symbol, desc?: any) => any
|
||||
>decorators : Function[]
|
||||
@@ -53,3 +59,14 @@ export declare function __awaiter(thisArg: any, _arguments: any, P: Function, ge
|
||||
>generator : Function
|
||||
>Function : Function
|
||||
|
||||
export declare function __generator(thisArg: any, body: Function): any;
|
||||
>__generator : (thisArg: any, body: Function) => any
|
||||
>thisArg : any
|
||||
>body : Function
|
||||
>Function : Function
|
||||
|
||||
export declare function __exportStar(m: any, exports: any): void;
|
||||
>__exportStar : (m: any, exports: any) => void
|
||||
>m : any
|
||||
>exports : any
|
||||
|
||||
|
||||
@@ -48,11 +48,13 @@ declare namespace N {
|
||||
//// [tslib.d.ts]
|
||||
export declare function __extends(d: Function, b: Function): void;
|
||||
export declare function __assign(t: any, ...sources: any[]): any;
|
||||
export declare function __rest(t: any, propertyNames: string[]): any;
|
||||
export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
|
||||
export declare function __param(paramIndex: number, decorator: Function): Function;
|
||||
export declare function __metadata(metadataKey: any, metadataValue: any): Function;
|
||||
export declare function __awaiter(thisArg: any, _arguments: any, P: Function, generator: Function): any;
|
||||
|
||||
export declare function __generator(thisArg: any, body: Function): any;
|
||||
export declare function __exportStar(m: any, exports: any): void;
|
||||
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
|
||||
@@ -98,6 +98,11 @@ export declare function __assign(t: any, ...sources: any[]): any;
|
||||
>t : Symbol(t, Decl(tslib.d.ts, --, --))
|
||||
>sources : Symbol(sources, Decl(tslib.d.ts, --, --))
|
||||
|
||||
export declare function __rest(t: any, propertyNames: string[]): any;
|
||||
>__rest : Symbol(__rest, Decl(tslib.d.ts, --, --))
|
||||
>t : Symbol(t, Decl(tslib.d.ts, --, --))
|
||||
>propertyNames : Symbol(propertyNames, Decl(tslib.d.ts, --, --))
|
||||
|
||||
export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
|
||||
>__decorate : Symbol(__decorate, Decl(tslib.d.ts, --, --))
|
||||
>decorators : Symbol(decorators, Decl(tslib.d.ts, --, --))
|
||||
@@ -128,3 +133,14 @@ export declare function __awaiter(thisArg: any, _arguments: any, P: Function, ge
|
||||
>generator : Symbol(generator, Decl(tslib.d.ts, --, --))
|
||||
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
export declare function __generator(thisArg: any, body: Function): any;
|
||||
>__generator : Symbol(__generator, Decl(tslib.d.ts, --, --))
|
||||
>thisArg : Symbol(thisArg, Decl(tslib.d.ts, --, --))
|
||||
>body : Symbol(body, Decl(tslib.d.ts, --, --))
|
||||
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
export declare function __exportStar(m: any, exports: any): void;
|
||||
>__exportStar : Symbol(__exportStar, Decl(tslib.d.ts, --, --))
|
||||
>m : Symbol(m, Decl(tslib.d.ts, --, --))
|
||||
>exports : Symbol(exports, Decl(tslib.d.ts, --, --))
|
||||
|
||||
|
||||
@@ -98,6 +98,11 @@ export declare function __assign(t: any, ...sources: any[]): any;
|
||||
>t : any
|
||||
>sources : any[]
|
||||
|
||||
export declare function __rest(t: any, propertyNames: string[]): any;
|
||||
>__rest : (t: any, propertyNames: string[]) => any
|
||||
>t : any
|
||||
>propertyNames : string[]
|
||||
|
||||
export declare function __decorate(decorators: Function[], target: any, key?: string | symbol, desc?: any): any;
|
||||
>__decorate : (decorators: Function[], target: any, key?: string | symbol, desc?: any) => any
|
||||
>decorators : Function[]
|
||||
@@ -128,3 +133,14 @@ export declare function __awaiter(thisArg: any, _arguments: any, P: Function, ge
|
||||
>generator : Function
|
||||
>Function : Function
|
||||
|
||||
export declare function __generator(thisArg: any, body: Function): any;
|
||||
>__generator : (thisArg: any, body: Function) => any
|
||||
>thisArg : any
|
||||
>body : Function
|
||||
>Function : Function
|
||||
|
||||
export declare function __exportStar(m: any, exports: any): void;
|
||||
>__exportStar : (m: any, exports: any) => void
|
||||
>m : any
|
||||
>exports : any
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
tests/cases/compiler/external.ts(2,16): error TS2343: This syntax requires an imported helper named '__extends', but module 'tslib' has no exported member '__extends'.
|
||||
tests/cases/compiler/external.ts(6,1): error TS2343: This syntax requires an imported helper named '__decorate', but module 'tslib' has no exported member '__decorate'.
|
||||
tests/cases/compiler/external.ts(6,1): error TS2343: This syntax requires an imported helper named '__metadata', but module 'tslib' has no exported member '__metadata'.
|
||||
tests/cases/compiler/external.ts(8,12): error TS2343: This syntax requires an imported helper named '__param', but module 'tslib' has no exported member '__param'.
|
||||
tests/cases/compiler/external.ts(13,13): error TS2343: This syntax requires an imported helper named '__assign', but module 'tslib' has no exported member '__assign'.
|
||||
tests/cases/compiler/external.ts(14,12): error TS2343: This syntax requires an imported helper named '__rest', but module 'tslib' has no exported member '__rest'.
|
||||
tests/cases/compiler/external.ts(1,1): error TS2343: This syntax requires an imported helper named '__exportStar', but module 'tslib' has no exported member '__exportStar'.
|
||||
tests/cases/compiler/external.ts(3,16): error TS2343: This syntax requires an imported helper named '__extends', but module 'tslib' has no exported member '__extends'.
|
||||
tests/cases/compiler/external.ts(7,1): error TS2343: This syntax requires an imported helper named '__decorate', but module 'tslib' has no exported member '__decorate'.
|
||||
tests/cases/compiler/external.ts(7,1): error TS2343: This syntax requires an imported helper named '__metadata', but module 'tslib' has no exported member '__metadata'.
|
||||
tests/cases/compiler/external.ts(9,12): error TS2343: This syntax requires an imported helper named '__param', but module 'tslib' has no exported member '__param'.
|
||||
tests/cases/compiler/external.ts(14,13): error TS2343: This syntax requires an imported helper named '__assign', but module 'tslib' has no exported member '__assign'.
|
||||
tests/cases/compiler/external.ts(15,12): error TS2343: This syntax requires an imported helper named '__rest', but module 'tslib' has no exported member '__rest'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/external.ts (6 errors) ====
|
||||
==== tests/cases/compiler/external.ts (7 errors) ====
|
||||
export * from "./other";
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2343: This syntax requires an imported helper named '__exportStar', but module 'tslib' has no exported member '__exportStar'.
|
||||
export class A { }
|
||||
export class B extends A { }
|
||||
~~~~~~~~~
|
||||
@@ -34,6 +38,9 @@ tests/cases/compiler/external.ts(14,12): error TS2343: This syntax requires an i
|
||||
~
|
||||
!!! error TS2343: This syntax requires an imported helper named '__rest', but module 'tslib' has no exported member '__rest'.
|
||||
|
||||
==== tests/cases/compiler/other.ts (0 errors) ====
|
||||
export const x = 1;
|
||||
|
||||
==== tests/cases/compiler/script.ts (0 errors) ====
|
||||
class A { }
|
||||
class B extends A { }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//// [tests/cases/compiler/importHelpersNoHelpers.ts] ////
|
||||
|
||||
//// [external.ts]
|
||||
export * from "./other";
|
||||
export class A { }
|
||||
export class B extends A { }
|
||||
|
||||
@@ -16,6 +17,9 @@ const o = { a: 1 };
|
||||
const y = { ...o };
|
||||
const { ...x } = y;
|
||||
|
||||
//// [other.ts]
|
||||
export const x = 1;
|
||||
|
||||
//// [script.ts]
|
||||
class A { }
|
||||
class B extends A { }
|
||||
@@ -32,10 +36,15 @@ class C {
|
||||
export {}
|
||||
|
||||
|
||||
//// [other.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.x = 1;
|
||||
//// [external.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var tslib_1 = require("tslib");
|
||||
tslib_1.__exportStar(require("./other"), exports);
|
||||
var A = (function () {
|
||||
function A() {
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ export class A { }
|
||||
|
||||
//// [b.ts]
|
||||
import { A } from "./a";
|
||||
export * from "./a";
|
||||
export class B extends A { }
|
||||
|
||||
//// [tslib.d.ts]
|
||||
@@ -38,6 +39,16 @@ System.register(["tslib", "./a"], function (exports_1, context_1) {
|
||||
"use strict";
|
||||
var __moduleName = context_1 && context_1.id;
|
||||
var tslib_1, a_1, B;
|
||||
var exportedNames_1 = {
|
||||
"B": true
|
||||
};
|
||||
function exportStar_1(m) {
|
||||
var exports = {};
|
||||
for (var n in m) {
|
||||
if (n !== "default" && !exportedNames_1.hasOwnProperty(n)) exports[n] = m[n];
|
||||
}
|
||||
exports_1(exports);
|
||||
}
|
||||
return {
|
||||
setters: [
|
||||
function (tslib_1_1) {
|
||||
@@ -45,6 +56,7 @@ System.register(["tslib", "./a"], function (exports_1, context_1) {
|
||||
},
|
||||
function (a_1_1) {
|
||||
a_1 = a_1_1;
|
||||
exportStar_1(a_1_1);
|
||||
}
|
||||
],
|
||||
execute: function () {
|
||||
|
||||
@@ -6,8 +6,9 @@ export class A { }
|
||||
import { A } from "./a";
|
||||
>A : Symbol(A, Decl(b.ts, 0, 8))
|
||||
|
||||
export * from "./a";
|
||||
export class B extends A { }
|
||||
>B : Symbol(B, Decl(b.ts, 0, 24))
|
||||
>B : Symbol(B, Decl(b.ts, 1, 20))
|
||||
>A : Symbol(A, Decl(b.ts, 0, 8))
|
||||
|
||||
=== tests/cases/compiler/tslib.d.ts ===
|
||||
|
||||
@@ -6,6 +6,7 @@ export class A { }
|
||||
import { A } from "./a";
|
||||
>A : typeof A
|
||||
|
||||
export * from "./a";
|
||||
export class B extends A { }
|
||||
>B : B
|
||||
>A : A
|
||||
|
||||
@@ -35,4 +35,14 @@
|
||||
declare type T = number;
|
||||
export = T;
|
||||
|
||||
==== /node_modules/foo/bar.d.ts (0 errors) ====
|
||||
export type T = number;
|
||||
|
||||
==== /node_modules/foo/index.d.ts (0 errors) ====
|
||||
export { T } from "./bar"; // In a declaration file, so not an error.
|
||||
|
||||
==== /node_modules/baz/index.d.ts (0 errors) ====
|
||||
declare module "baz" {
|
||||
export { T } from "foo"; // Also allowed.
|
||||
}
|
||||
|
||||
@@ -9,7 +9,17 @@ export class C {}
|
||||
//// [exportEqualsT.ts]
|
||||
declare type T = number;
|
||||
export = T;
|
||||
|
||||
|
||||
//// [bar.d.ts]
|
||||
export type T = number;
|
||||
|
||||
//// [index.d.ts]
|
||||
export { T } from "./bar"; // In a declaration file, so not an error.
|
||||
|
||||
//// [index.d.ts]
|
||||
declare module "baz" {
|
||||
export { T } from "foo"; // Also allowed.
|
||||
}
|
||||
|
||||
//// [user.ts]
|
||||
// Error, can't re-export something that's only a type.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
=== tests/cases/compiler/foo.js ===
|
||||
// Test #16139
|
||||
function Foo() {
|
||||
>Foo : Symbol(Foo, Decl(foo.js, 0, 0))
|
||||
|
||||
arguments;
|
||||
>arguments : Symbol(arguments)
|
||||
|
||||
return new Foo();
|
||||
>Foo : Symbol(Foo, Decl(foo.js, 0, 0))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
=== tests/cases/compiler/foo.js ===
|
||||
// Test #16139
|
||||
function Foo() {
|
||||
>Foo : (...args: any[]) => any
|
||||
|
||||
arguments;
|
||||
>arguments : IArguments
|
||||
|
||||
return new Foo();
|
||||
>new Foo() : any
|
||||
>Foo : (...args: any[]) => any
|
||||
}
|
||||
|
||||
@@ -43,7 +43,16 @@ tests/cases/compiler/jsdocInTypeScript.ts(30,3): error TS2339: Property 'x' does
|
||||
// @type has no effect either.
|
||||
/** @type {{ x?: number }} */
|
||||
const z = {};
|
||||
z.x = 1;
|
||||
z.x = 1; // Error
|
||||
~
|
||||
!!! error TS2339: Property 'x' does not exist on type '{}'.
|
||||
|
||||
// @template tag should not interfere with constraint or default.
|
||||
/** @template T */
|
||||
interface I<T extends number = 0> {}
|
||||
|
||||
/** @template T */
|
||||
function tem<T extends number>(t: T): I<T> { return {}; }
|
||||
|
||||
let i: I; // Should succeed thanks to type parameter default
|
||||
|
||||
@@ -28,7 +28,16 @@ f(1); f(true).length;
|
||||
// @type has no effect either.
|
||||
/** @type {{ x?: number }} */
|
||||
const z = {};
|
||||
z.x = 1;
|
||||
z.x = 1; // Error
|
||||
|
||||
// @template tag should not interfere with constraint or default.
|
||||
/** @template T */
|
||||
interface I<T extends number = 0> {}
|
||||
|
||||
/** @template T */
|
||||
function tem<T extends number>(t: T): I<T> { return {}; }
|
||||
|
||||
let i: I; // Should succeed thanks to type parameter default
|
||||
|
||||
|
||||
//// [jsdocInTypeScript.js]
|
||||
@@ -50,4 +59,7 @@ f(true).length;
|
||||
// @type has no effect either.
|
||||
/** @type {{ x?: number }} */
|
||||
var z = {};
|
||||
z.x = 1;
|
||||
z.x = 1; // Error
|
||||
/** @template T */
|
||||
function tem(t) { return {}; }
|
||||
var i; // Should succeed thanks to type parameter default
|
||||
|
||||
@@ -4,12 +4,12 @@ tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(9,4): error TS
|
||||
Property 'doStuff' is missing in type '{ value: string; }'.
|
||||
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(10,17): error TS2345: Argument of type '{ value: string; what: number; }' is not assignable to parameter of type 'I2'.
|
||||
Object literal may only specify known properties, and 'what' does not exist in type 'I2'.
|
||||
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(11,4): error TS2345: Argument of type '{ toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
|
||||
Property 'value' is missing in type '{ toString: (s: any) => any; }'.
|
||||
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(12,4): error TS2345: Argument of type '{ toString: (s: string) => string; }' is not assignable to parameter of type 'I2'.
|
||||
Property 'value' is missing in type '{ toString: (s: string) => string; }'.
|
||||
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(13,4): error TS2345: Argument of type '{ value: string; toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
|
||||
Property 'doStuff' is missing in type '{ value: string; toString: (s: any) => any; }'.
|
||||
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(11,6): error TS2345: Argument of type '{ toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
|
||||
Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
|
||||
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(12,6): error TS2345: Argument of type '{ toString: (s: string) => string; }' is not assignable to parameter of type 'I2'.
|
||||
Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
|
||||
tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(13,17): error TS2345: Argument of type '{ value: string; toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
|
||||
Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts (6 errors) ====
|
||||
@@ -33,14 +33,14 @@ tests/cases/compiler/objectLiteralFunctionArgContextualTyping2.ts(13,4): error T
|
||||
!!! error TS2345: Argument of type '{ value: string; what: number; }' is not assignable to parameter of type 'I2'.
|
||||
!!! error TS2345: Object literal may only specify known properties, and 'what' does not exist in type 'I2'.
|
||||
f2({ toString: (s) => s })
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '{ toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
|
||||
!!! error TS2345: Property 'value' is missing in type '{ toString: (s: any) => any; }'.
|
||||
!!! error TS2345: Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
|
||||
f2({ toString: (s: string) => s })
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '{ toString: (s: string) => string; }' is not assignable to parameter of type 'I2'.
|
||||
!!! error TS2345: Property 'value' is missing in type '{ toString: (s: string) => string; }'.
|
||||
!!! error TS2345: Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
|
||||
f2({ value: '', toString: (s) => s.uhhh })
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2345: Argument of type '{ value: string; toString: (s: any) => any; }' is not assignable to parameter of type 'I2'.
|
||||
!!! error TS2345: Property 'doStuff' is missing in type '{ value: string; toString: (s: any) => any; }'.
|
||||
!!! error TS2345: Object literal may only specify known properties, and 'toString' does not exist in type 'I2'.
|
||||
@@ -0,0 +1 @@
|
||||
[args => any, <T>(args) => any, (...args) => any, (args?) => any, (args: any) => any, ({}) => any]
|
||||
@@ -0,0 +1,15 @@
|
||||
//// [returnInfiniteIntersection.ts]
|
||||
function recursive() {
|
||||
let x = <T>(subkey: T) => recursive();
|
||||
return x as typeof x & { p };
|
||||
}
|
||||
|
||||
let result = recursive()(1)
|
||||
|
||||
|
||||
//// [returnInfiniteIntersection.js]
|
||||
function recursive() {
|
||||
var x = function (subkey) { return recursive(); };
|
||||
return x;
|
||||
}
|
||||
var result = recursive()(1);
|
||||
@@ -0,0 +1,21 @@
|
||||
=== tests/cases/compiler/returnInfiniteIntersection.ts ===
|
||||
function recursive() {
|
||||
>recursive : Symbol(recursive, Decl(returnInfiniteIntersection.ts, 0, 0))
|
||||
|
||||
let x = <T>(subkey: T) => recursive();
|
||||
>x : Symbol(x, Decl(returnInfiniteIntersection.ts, 1, 7))
|
||||
>T : Symbol(T, Decl(returnInfiniteIntersection.ts, 1, 13))
|
||||
>subkey : Symbol(subkey, Decl(returnInfiniteIntersection.ts, 1, 16))
|
||||
>T : Symbol(T, Decl(returnInfiniteIntersection.ts, 1, 13))
|
||||
>recursive : Symbol(recursive, Decl(returnInfiniteIntersection.ts, 0, 0))
|
||||
|
||||
return x as typeof x & { p };
|
||||
>x : Symbol(x, Decl(returnInfiniteIntersection.ts, 1, 7))
|
||||
>x : Symbol(x, Decl(returnInfiniteIntersection.ts, 1, 7))
|
||||
>p : Symbol(p, Decl(returnInfiniteIntersection.ts, 2, 28))
|
||||
}
|
||||
|
||||
let result = recursive()(1)
|
||||
>result : Symbol(result, Decl(returnInfiniteIntersection.ts, 5, 3))
|
||||
>recursive : Symbol(recursive, Decl(returnInfiniteIntersection.ts, 0, 0))
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
=== tests/cases/compiler/returnInfiniteIntersection.ts ===
|
||||
function recursive() {
|
||||
>recursive : () => (<T>(subkey: T) => any & { p: any; }) & { p: any; }
|
||||
|
||||
let x = <T>(subkey: T) => recursive();
|
||||
>x : <T>(subkey: T) => any & { p: any; }
|
||||
><T>(subkey: T) => recursive() : <T>(subkey: T) => any & { p: any; }
|
||||
>T : T
|
||||
>subkey : T
|
||||
>T : T
|
||||
>recursive() : (<T>(subkey: T) => any & { p: any; }) & { p: any; }
|
||||
>recursive : () => (<T>(subkey: T) => any & { p: any; }) & { p: any; }
|
||||
|
||||
return x as typeof x & { p };
|
||||
>x as typeof x & { p } : (<T>(subkey: T) => any & { p: any; }) & { p: any; }
|
||||
>x : <T>(subkey: T) => any & { p: any; }
|
||||
>x : <T>(subkey: T) => any & { p: any; }
|
||||
>p : any
|
||||
}
|
||||
|
||||
let result = recursive()(1)
|
||||
>result : (<T>(subkey: T) => any & { p: any; }) & { p: any; }
|
||||
>recursive()(1) : (<T>(subkey: T) => any & { p: any; }) & { p: any; }
|
||||
>recursive() : (<T>(subkey: T) => any & { p: any; }) & { p: any; }
|
||||
>recursive : () => (<T>(subkey: T) => any & { p: any; }) & { p: any; }
|
||||
>1 : 1
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
//// [sourceMapValidationVarInDownLevelGenerator.ts]
|
||||
function * f() {
|
||||
var x = 1, y;
|
||||
}
|
||||
|
||||
//// [sourceMapValidationVarInDownLevelGenerator.js]
|
||||
function f() {
|
||||
var x, y;
|
||||
return __generator(this, function (_a) {
|
||||
x = 1;
|
||||
return [2 /*return*/];
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=sourceMapValidationVarInDownLevelGenerator.js.map
|
||||
@@ -0,0 +1,2 @@
|
||||
//// [sourceMapValidationVarInDownLevelGenerator.js.map]
|
||||
{"version":3,"file":"sourceMapValidationVarInDownLevelGenerator.js","sourceRoot":"","sources":["sourceMapValidationVarInDownLevelGenerator.ts"],"names":[],"mappings":"AAAA;;;QACQ,CAAC,GAAG,CAAC,CAAI;;;CAChB"}
|
||||
@@ -0,0 +1,47 @@
|
||||
===================================================================
|
||||
JsFile: sourceMapValidationVarInDownLevelGenerator.js
|
||||
mapUrl: sourceMapValidationVarInDownLevelGenerator.js.map
|
||||
sourceRoot:
|
||||
sources: sourceMapValidationVarInDownLevelGenerator.ts
|
||||
===================================================================
|
||||
-------------------------------------------------------------------
|
||||
emittedFile:tests/cases/compiler/sourceMapValidationVarInDownLevelGenerator.js
|
||||
sourceFile:sourceMapValidationVarInDownLevelGenerator.ts
|
||||
-------------------------------------------------------------------
|
||||
>>>function f() {
|
||||
1 >
|
||||
2 >^^^^^^^^^^^^^^->
|
||||
1 >
|
||||
1 >Emitted(1, 1) Source(1, 1) + SourceIndex(0)
|
||||
---
|
||||
>>> var x, y;
|
||||
>>> return __generator(this, function (_a) {
|
||||
>>> x = 1;
|
||||
1->^^^^^^^^
|
||||
2 > ^
|
||||
3 > ^^^
|
||||
4 > ^
|
||||
5 > ^
|
||||
6 > ^^^^^^^^^^^^^^^^^->
|
||||
1->function * f() {
|
||||
> var
|
||||
2 > x
|
||||
3 > =
|
||||
4 > 1
|
||||
5 > , y;
|
||||
1->Emitted(4, 9) Source(2, 9) + SourceIndex(0)
|
||||
2 >Emitted(4, 10) Source(2, 10) + SourceIndex(0)
|
||||
3 >Emitted(4, 13) Source(2, 13) + SourceIndex(0)
|
||||
4 >Emitted(4, 14) Source(2, 14) + SourceIndex(0)
|
||||
5 >Emitted(4, 15) Source(2, 18) + SourceIndex(0)
|
||||
---
|
||||
>>> return [2 /*return*/];
|
||||
>>> });
|
||||
>>>}
|
||||
1->^
|
||||
2 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
|
||||
1->
|
||||
>}
|
||||
1->Emitted(7, 2) Source(3, 2) + SourceIndex(0)
|
||||
---
|
||||
>>>//# sourceMappingURL=sourceMapValidationVarInDownLevelGenerator.js.map
|
||||
@@ -0,0 +1,8 @@
|
||||
=== tests/cases/compiler/sourceMapValidationVarInDownLevelGenerator.ts ===
|
||||
function * f() {
|
||||
>f : Symbol(f, Decl(sourceMapValidationVarInDownLevelGenerator.ts, 0, 0))
|
||||
|
||||
var x = 1, y;
|
||||
>x : Symbol(x, Decl(sourceMapValidationVarInDownLevelGenerator.ts, 1, 7))
|
||||
>y : Symbol(y, Decl(sourceMapValidationVarInDownLevelGenerator.ts, 1, 14))
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
=== tests/cases/compiler/sourceMapValidationVarInDownLevelGenerator.ts ===
|
||||
function * f() {
|
||||
>f : () => IterableIterator<any>
|
||||
|
||||
var x = 1, y;
|
||||
>x : number
|
||||
>1 : 1
|
||||
>y : any
|
||||
}
|
||||
@@ -7,11 +7,12 @@ class Poisoned extends React.Component<{}, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
const obj: Object = {};
|
||||
const obj = {};
|
||||
|
||||
// OK
|
||||
let p = <Poisoned {...obj} />;
|
||||
let y = <Poisoned />;
|
||||
let y = <Poisoned />;
|
||||
|
||||
|
||||
//// [file.jsx]
|
||||
"use strict";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user