Merge branch 'transforms' into transforms-importHelpers

This commit is contained in:
Ron Buckton
2016-06-14 13:21:24 -07:00
406 changed files with 283336 additions and 272632 deletions
+1 -1
View File
@@ -36,7 +36,6 @@ tests/webhost/*.d.ts
tests/webhost/webtsc.js
tests/cases/**/*.js
tests/cases/**/*.js.map
tests/cases/**/*.d.ts
*.config
scripts/debug.bat
scripts/run.bat
@@ -51,3 +50,4 @@ internal/
**/.vs
**/.vscode
!**/.vscode/tasks.json
!tests/cases/projects/projectOption/**/node_modules
+2 -2
View File
@@ -91,10 +91,10 @@ These two files represent the DOM typings and are auto-generated. To make any mo
## Running the Tests
To run all tests, invoke the `runtests` target using jake:
To run all tests, invoke the `runtests-parallel` target using jake:
```Shell
jake runtests
jake runtests-parallel
```
This run will all tests; to run only a specific subset of tests, use:
+64 -53
View File
@@ -5,6 +5,7 @@ var os = require("os");
var path = require("path");
var child_process = require("child_process");
var Linter = require("tslint");
var runTestsInParallel = require("./scripts/mocha-parallel").runTestsInParallel;
// Variables
var compilerDirectory = "src/compiler/";
@@ -212,7 +213,10 @@ var es2016LibrarySourceMap = es2016LibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});
var es2017LibrarySource = ["es2017.object.d.ts"];
var es2017LibrarySource = [
"es2017.object.d.ts",
"es2017.sharedmemory.d.ts"
];
var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
@@ -296,6 +300,7 @@ var builtLocalCompiler = path.join(builtLocalDirectory, compilerFilename);
* @param {boolean} opts.noResolve: true if compiler should not include non-rooted files in compilation
* @param {boolean} opts.stripInternal: true if compiler should remove declarations marked as @internal
* @param {boolean} opts.noMapRoot: true if compiler omit mapRoot option
* @param {boolean} opts.inlineSourceMap: true if compiler should inline sourceMap
* @param callback: a function to execute after the compilation process ends
*/
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts, callback) {
@@ -337,10 +342,16 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
}
if (useDebugMode) {
options += " -sourcemap";
if (!opts.noMapRoot) {
options += " -mapRoot file:///" + path.resolve(path.dirname(outFile));
if (opts.inlineSourceMap) {
options += " --inlineSourceMap --inlineSources";
} else {
options += " -sourcemap";
if (!opts.noMapRoot) {
options += " -mapRoot file:///" + path.resolve(path.dirname(outFile));
}
}
} else {
options += " --newLine LF";
}
if (opts.stripInternal) {
@@ -517,7 +528,13 @@ var nodeStandaloneDefinitionsFile = path.join(builtLocalDirectory, "typescript_s
compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources),
/*prefixes*/ [copyright],
/*useBuiltCompiler*/ true,
{ noOutFile: false, generateDeclarations: true, preserveConstEnums: true, keepComments: true, noResolve: false, stripInternal: true },
/*opts*/ { noOutFile: false,
generateDeclarations: true,
preserveConstEnums: true,
keepComments: true,
noResolve: false,
stripInternal: true
},
/*callback*/ function () {
jake.cpR(servicesFile, nodePackageFile, {silent: true});
@@ -540,16 +557,21 @@ compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].conca
fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents);
});
compileFile(servicesFileInBrowserTest, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources),
/*prefixes*/ [copyright],
/*useBuiltCompiler*/ true,
{ noOutFile: false, generateDeclarations: true, preserveConstEnums: true, keepComments: true, noResolve: false, stripInternal: true, noMapRoot: true },
/*callback*/ function () {
var content = fs.readFileSync(servicesFileInBrowserTest).toString();
var i = content.lastIndexOf("\n");
fs.writeFileSync(servicesFileInBrowserTest, content.substring(0, i) + "\r\n//# sourceURL=../built/local/typeScriptServices.js" + content.substring(i));
});
compileFile(
servicesFileInBrowserTest,
servicesSources,
[builtLocalDirectory, copyright].concat(servicesSources),
/*prefixes*/ [copyright],
/*useBuiltCompiler*/ true,
{ noOutFile: false,
generateDeclarations: true,
preserveConstEnums: true,
keepComments: true,
noResolve: false,
stripInternal: true,
noMapRoot: true,
inlineSourceMap: true
});
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true);
@@ -650,7 +672,13 @@ directory(builtLocalDirectory);
// Task to build the tests infrastructure using the built compiler
var run = path.join(builtLocalDirectory, "run.js");
compileFile(run, harnessSources, [builtLocalDirectory, tscFile].concat(libraryTargets).concat(harnessSources), [], /*useBuiltCompiler:*/ true);
compileFile(
/*outFile*/ run,
/*source*/ harnessSources,
/*prereqs*/ [builtLocalDirectory, tscFile].concat(libraryTargets).concat(harnessSources),
/*prefixes*/ [],
/*useBuiltCompiler:*/ true,
/*opts*/ { inlineSourceMap: true });
var internalTests = "internal/";
@@ -774,51 +802,34 @@ function runConsoleTests(defaultReporter, runInParallel) {
tests = tests ? ' -g "' + tests + '"' : '';
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + ' -t ' + testTimeout + ' ' + run;
console.log(cmd);
var savedNodeEnv = process.env.NODE_ENV;
process.env.NODE_ENV = "development";
exec(cmd, function () {
process.env.NODE_ENV = savedNodeEnv;
runLinter();
finish();
}, function(e, status) {
process.env.NODE_ENV = savedNodeEnv;
finish(status);
});
}
else {
// run task to load all tests and partition them between workers
var cmd = "mocha " + " -R min " + colors + run;
console.log(cmd);
exec(cmd, function() {
// read all configuration files and spawn a worker for every config
var configFiles = fs.readdirSync(taskConfigsFolder);
var counter = configFiles.length;
var firstErrorStatus;
// schedule work for chunks
configFiles.forEach(function (f) {
var configPath = path.join(taskConfigsFolder, f);
var workerCmd = "mocha" + " -t " + testTimeout + " -R " + reporter + " " + colors + " " + run + " --config='" + configPath + "'";
console.log(workerCmd);
exec(workerCmd, finishWorker, finishWorker)
});
var savedNodeEnv = process.env.NODE_ENV;
process.env.NODE_ENV = "development";
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
process.env.NODE_ENV = savedNodeEnv;
function finishWorker(e, errorStatus) {
counter--;
if (firstErrorStatus === undefined && errorStatus !== undefined) {
firstErrorStatus = errorStatus;
}
if (counter !== 0) {
complete();
}
else {
// last worker clean everything and runs linter in case if there were no errors
deleteTemporaryProjectOutput();
jake.rmRf(taskConfigsFolder);
if (firstErrorStatus === undefined) {
runLinter();
complete();
}
else {
failWithStatus(firstErrorStatus);
}
}
// last worker clean everything and runs linter in case if there were no errors
deleteTemporaryProjectOutput();
jake.rmRf(taskConfigsFolder);
if (err) {
fail(err);
}
else {
runLinter();
complete();
}
});
}
@@ -873,7 +884,7 @@ compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile
desc("Runs browserify on run.js to produce a file suitable for running tests in the browser");
task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() {
var cmd = 'browserify built/local/run.js -t ./scripts/browserify-optional -o built/local/bundle.js';
var cmd = 'browserify built/local/run.js -t ./scripts/browserify-optional -d -o built/local/bundle.js';
exec(cmd);
}, {async: true});
@@ -894,7 +905,7 @@ task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFi
}
tests = tests ? tests : '';
var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + tests;
var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + JSON.stringify(tests);
console.log(cmd);
exec(cmd);
}, {async: true});
+13 -1
View File
@@ -152,12 +152,24 @@ interface ObjectConstructor {
*/
getOwnPropertyNames(o: any): string[];
/**
* Creates an object that has null prototype.
* @param o Object to use as a prototype. May be null
*/
create(o: null): any;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
*/
create<T>(o: T): T;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
* @param properties JavaScript object that contains one or more property descriptors.
*/
create(o: any, properties?: PropertyDescriptorMap): any;
create(o: any, properties: PropertyDescriptorMap): any;
/**
* Adds a property to an object, or modifies attributes of an existing property.
+2 -1
View File
@@ -15,4 +15,5 @@ and limitations under the License.
/// <reference no-default-lib="true"/>
/// <reference path="lib.es2016.d.ts" />
/// <reference path="lib.es2017.object.d.ts" />
/// <reference path="lib.es2017.object.d.ts" />
/// <reference path="lib.es2017.sharedmemory.d.ts" />
+43
View File
@@ -0,0 +1,43 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference path="lib.es2015.symbol.d.ts" />
/// <reference path="lib.es2015.symbol.wellknown.d.ts" />
interface SharedArrayBuffer {
/**
* Read-only. The length of the ArrayBuffer (in bytes).
*/
readonly byteLength: number;
/*
* The SharedArrayBuffer constructor's length property whose value is 1.
*/
length: number;
/**
* Returns a section of an SharedArrayBuffer.
*/
slice(begin:number, end?:number): SharedArrayBuffer;
readonly [Symbol.species]: SharedArrayBuffer;
readonly [Symbol.toStringTag]: "SharedArrayBuffer";
}
interface SharedArrayBufferConstructor {
readonly prototype: SharedArrayBuffer;
new (byteLength: number): SharedArrayBuffer;
}
declare var SharedArrayBuffer: SharedArrayBufferConstructor;
+13 -1
View File
@@ -152,12 +152,24 @@ interface ObjectConstructor {
*/
getOwnPropertyNames(o: any): string[];
/**
* Creates an object that has null prototype.
* @param o Object to use as a prototype. May be null
*/
create(o: null): any;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
*/
create<T>(o: T): T;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
* @param properties JavaScript object that contains one or more property descriptors.
*/
create(o: any, properties?: PropertyDescriptorMap): any;
create(o: any, properties: PropertyDescriptorMap): any;
/**
* Adds a property to an object, or modifies attributes of an existing property.
+13 -1
View File
@@ -152,12 +152,24 @@ interface ObjectConstructor {
*/
getOwnPropertyNames(o: any): string[];
/**
* Creates an object that has null prototype.
* @param o Object to use as a prototype. May be null
*/
create(o: null): any;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
*/
create<T>(o: T): T;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
* @param properties JavaScript object that contains one or more property descriptors.
*/
create(o: any, properties?: PropertyDescriptorMap): any;
create(o: any, properties: PropertyDescriptorMap): any;
/**
* Adds a property to an object, or modifies attributes of an existing property.
+38042 -37654
View File
File diff suppressed because one or more lines are too long
+52451 -51851
View File
File diff suppressed because one or more lines are too long
+8715 -8648
View File
File diff suppressed because it is too large Load Diff
+52217 -51617
View File
File diff suppressed because one or more lines are too long
+2508 -2488
View File
File diff suppressed because it is too large Load Diff
+58975 -58311
View File
File diff suppressed because one or more lines are too long
+2508 -2488
View File
File diff suppressed because it is too large Load Diff
+58975 -58311
View File
File diff suppressed because one or more lines are too long
+26
View File
@@ -0,0 +1,26 @@
/**
* Module dependencies.
*/
var Base = require('mocha').reporters.Base;
/**
* Expose `None`.
*/
exports = module.exports = None;
/**
* Initialize a new `None` test reporter.
*
* @api public
* @param {Runner} runner
*/
function None(runner) {
Base.call(this);
}
/**
* Inherit from `Base.prototype`.
*/
None.prototype.__proto__ = Base.prototype;
+360
View File
@@ -0,0 +1,360 @@
var tty = require("tty")
, readline = require("readline")
, fs = require("fs")
, path = require("path")
, child_process = require("child_process")
, os = require("os")
, mocha = require("mocha")
, Base = mocha.reporters.Base
, color = Base.color
, cursor = Base.cursor
, ms = require("mocha/lib/ms");
var isatty = tty.isatty(1) && tty.isatty(2);
var tapRangePattern = /^(\d+)\.\.(\d+)(?:$|\r\n?|\n)/;
var tapTestPattern = /^(not\sok|ok)\s+(\d+)\s+(?:-\s+)?(.*)$/;
var tapCommentPattern = /^#(?: (tests|pass|fail) (\d+)$)?/;
exports.runTestsInParallel = runTestsInParallel;
exports.ProgressBars = ProgressBars;
function runTestsInParallel(taskConfigsFolder, run, options, cb) {
if (options === undefined) options = { };
return discoverTests(run, options, function (error) {
if (error) {
return cb(error);
}
return runTests(taskConfigsFolder, run, options, cb);
});
}
function discoverTests(run, options, cb) {
console.log("Discovering tests...");
var cmd = "mocha -R " + require.resolve("./mocha-none-reporter.js") + " " + run;
var p = spawnProcess(cmd);
p.on("exit", function (status) {
if (status) {
cb(new Error("Process exited with code " + status));
}
else {
cb();
}
});
}
function runTests(taskConfigsFolder, run, options, cb) {
var configFiles = fs.readdirSync(taskConfigsFolder);
var numPartitions = configFiles.length;
if (numPartitions <= 0) {
cb();
return;
}
console.log("Running tests on " + numPartitions + " threads...");
var partitions = Array(numPartitions);
var progressBars = new ProgressBars();
progressBars.enable();
var counter = numPartitions;
configFiles.forEach(runTestsInPartition);
function runTestsInPartition(file, index) {
var partition = {
file: path.join(taskConfigsFolder, file),
tests: 0,
passed: 0,
failed: 0,
completed: 0,
current: undefined,
start: undefined,
end: undefined,
failures: []
};
partitions[index] = partition;
// Set up the progress bar.
updateProgress(0);
// Start the background process.
var cmd = "mocha -t " + (options.testTimeout || 20000) + " -R tap --no-colors " + run + " --config='" + partition.file + "'";
var p = spawnProcess(cmd);
var rl = readline.createInterface({
input: p.stdout,
terminal: false
});
rl.on("line", onmessage);
p.on("exit", onexit)
function onmessage(line) {
if (partition.start === undefined) {
partition.start = Date.now();
}
var rangeMatch = tapRangePattern.exec(line);
if (rangeMatch) {
partition.tests = parseInt(rangeMatch[2]);
return;
}
var testMatch = tapTestPattern.exec(line);
if (testMatch) {
var test = {
result: testMatch[1],
id: parseInt(testMatch[2]),
name: testMatch[3],
output: []
};
partition.current = test;
partition.completed++;
if (test.result === "ok") {
partition.passed++;
}
else {
partition.failed++;
partition.failures.push(test);
}
var progress = partition.completed / partition.tests;
if (progress < 1) {
updateProgress(progress);
}
return;
}
var commentMatch = tapCommentPattern.exec(line);
if (commentMatch) {
switch (commentMatch[1]) {
case "tests":
partition.current = undefined;
partition.tests = parseInt(commentMatch[2]);
break;
case "pass":
partition.passed = parseInt(commentMatch[2]);
break;
case "fail":
partition.failed = parseInt(commentMatch[2]);
break;
}
return;
}
if (partition.current) {
partition.current.output.push(line);
}
}
function onexit() {
if (partition.end === undefined) {
partition.end = Date.now();
}
partition.duration = partition.end - partition.start;
var summaryColor = partition.failed ? "fail" : "green";
var summarySymbol = partition.failed ? Base.symbols.err : Base.symbols.ok;
var summaryTests = (partition.passed === partition.tests ? partition.passed : partition.passed + "/" + partition.tests) + " passing";
var summaryDuration = "(" + ms(partition.duration) + ")";
var savedUseColors = Base.useColors;
Base.useColors = !options.noColors;
var summary = color(summaryColor, summarySymbol + " " + summaryTests) + " " + color("light", summaryDuration);
Base.useColors = savedUseColors;
updateProgress(1, summary);
signal();
}
function updateProgress(percentComplete, title) {
var progressColor = "pending";
if (partition.failed) {
progressColor = "fail";
}
progressBars.update(
index,
percentComplete,
progressColor,
title
);
}
}
function signal() {
counter--;
if (counter <= 0) {
var failed = 0;
var reporter = new Base(),
stats = reporter.stats,
failures = reporter.failures;
var duration = 0;
for (var i = 0; i < numPartitions; i++) {
var partition = partitions[i];
stats.passes += partition.passed;
stats.failures += partition.failed;
stats.tests += partition.tests;
duration += partition.duration;
for (var j = 0; j < partition.failures.length; j++) {
var failure = partition.failures[j];
failures.push(makeMochaTest(failure));
}
}
stats.duration = duration;
progressBars.disable();
if (options.noColors) {
var savedUseColors = Base.useColors;
Base.useColors = false;
reporter.epilogue();
Base.useColors = savedUseColors;
}
else {
reporter.epilogue();
}
if (failed) {
return cb(new Error("Test failures reported: " + failed));
}
else {
return cb();
}
}
}
function makeMochaTest(test) {
return {
fullTitle: function() {
return test.name;
},
err: {
message: test.output[0],
stack: test.output.join(os.EOL)
}
};
}
}
function spawnProcess(cmd, options) {
var shell = process.platform === "win32" ? "cmd" : "/bin/sh";
var prefix = process.platform === "win32" ? "/c" : "-c";
return child_process.spawn(shell, [prefix, cmd], { windowsVerbatimArguments: true });
}
function ProgressBars(options) {
if (!options) options = {};
var open = options.open || '[';
var close = options.close || ']';
var complete = options.complete || '▬';
var incomplete = options.incomplete || Base.symbols.dot;
var maxWidth = Math.floor(Base.window.width * .30) - open.length - close.length - 2;
var width = minMax(options.width || maxWidth, 10, maxWidth);
this._options = {
open: open,
complete: complete,
incomplete: incomplete,
close: close,
width: width
};
this._progressBars = [];
this._lineCount = 0;
this._enabled = false;
}
ProgressBars.prototype = {
enable: function () {
if (!this._enabled) {
process.stdout.write(os.EOL);
this._enabled = true;
}
},
disable: function () {
if (this._enabled) {
process.stdout.write(os.EOL);
this._enabled = false;
}
},
update: function (index, percentComplete, color, title) {
percentComplete = minMax(percentComplete, 0, 1);
var progressBar = this._progressBars[index] || (this._progressBars[index] = { });
var width = this._options.width;
var n = Math.floor(width * percentComplete);
var i = width - n;
if (n === progressBar.lastN && title === progressBar.title && color === progressBar.progressColor) {
return;
}
progressBar.lastN = n;
progressBar.title = title;
progressBar.progressColor = color;
var progress = " ";
progress += this._color('progress', this._options.open);
progress += this._color(color, fill(this._options.complete, n));
progress += this._color('progress', fill(this._options.incomplete, i));
progress += this._color('progress', this._options.close);
if (title) {
progress += this._color('progress', ' ' + title);
}
if (progressBar.text !== progress) {
progressBar.text = progress;
this._render(index);
}
},
_render: function (index) {
if (!this._enabled || !isatty) {
return;
}
cursor.hide();
readline.moveCursor(process.stdout, -process.stdout.columns, -this._lineCount);
var lineCount = 0;
var numProgressBars = this._progressBars.length;
for (var i = 0; i < numProgressBars; i++) {
if (i === index) {
readline.clearLine(process.stdout, 1);
process.stdout.write(this._progressBars[i].text + os.EOL);
}
else {
readline.moveCursor(process.stdout, -process.stdout.columns, +1);
}
lineCount++;
}
this._lineCount = lineCount;
cursor.show();
},
_color: function (type, text) {
return type && !this._options.noColors ? color(type, text) : text;
}
};
function fill(ch, size) {
var s = "";
while (s.length < size) {
s += ch;
}
return s.length > size ? s.substr(0, size) : s;
}
function minMax(value, min, max) {
if (value < min) return min;
if (value > max) return max;
return value;
}
+40 -9
View File
@@ -51,7 +51,8 @@ namespace ts {
return state;
}
else if (node.kind === SyntaxKind.ModuleDeclaration) {
return getModuleInstanceState((<ModuleDeclaration>node).body);
const body = (<ModuleDeclaration>node).body;
return body ? getModuleInstanceState(body) : ModuleInstanceState.Instantiated;
}
else {
return ModuleInstanceState.Instantiated;
@@ -630,10 +631,11 @@ namespace ts {
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
if (isNarrowingExpression(expr.left) && (expr.right.kind === SyntaxKind.NullKeyword || expr.right.kind === SyntaxKind.Identifier)) {
if ((isNarrowingExpression(expr.left) && (expr.right.kind === SyntaxKind.NullKeyword || expr.right.kind === SyntaxKind.Identifier)) ||
(isNarrowingExpression(expr.right) && (expr.left.kind === SyntaxKind.NullKeyword || expr.left.kind === SyntaxKind.Identifier))) {
return true;
}
if (expr.left.kind === SyntaxKind.TypeOfExpression && isNarrowingExpression((<TypeOfExpression>expr.left).expression) && expr.right.kind === SyntaxKind.StringLiteral) {
if (isTypeOfNarrowingBinaryExpression(expr)) {
return true;
}
return false;
@@ -645,6 +647,20 @@ namespace ts {
return false;
}
function isTypeOfNarrowingBinaryExpression(expr: BinaryExpression) {
let typeOf: Expression;
if (expr.left.kind === SyntaxKind.StringLiteral) {
typeOf = expr.right;
}
else if (expr.right.kind === SyntaxKind.StringLiteral) {
typeOf = expr.left;
}
else {
typeOf = undefined;
}
return typeOf && typeOf.kind === SyntaxKind.TypeOfExpression && isNarrowingExpression((<TypeOfExpression>typeOf).expression);
}
function createBranchLabel(): FlowLabel {
return {
flags: FlowFlags.BranchLabel,
@@ -1204,9 +1220,9 @@ namespace ts {
lastContainer = next;
}
function declareSymbolAndAddToSymbolTable(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): void {
function declareSymbolAndAddToSymbolTable(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol {
// Just call this directly so that the return type of this function stays "void".
declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes);
return declareSymbolAndAddToSymbolTableWorker(node, symbolFlags, symbolExcludes);
}
function declareSymbolAndAddToSymbolTableWorker(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol {
@@ -1279,7 +1295,7 @@ namespace ts {
function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean {
const body = node.kind === SyntaxKind.SourceFile ? node : (<ModuleDeclaration>node).body;
if (body.kind === SyntaxKind.SourceFile || body.kind === SyntaxKind.ModuleBlock) {
if (body && (body.kind === SyntaxKind.SourceFile || body.kind === SyntaxKind.ModuleBlock)) {
for (const stat of (<Block>body).statements) {
if (stat.kind === SyntaxKind.ExportDeclaration || stat.kind === SyntaxKind.ExportAssignment) {
return true;
@@ -1310,7 +1326,22 @@ namespace ts {
declareSymbolAndAddToSymbolTable(node, SymbolFlags.NamespaceModule, SymbolFlags.NamespaceModuleExcludes);
}
else {
declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
let pattern: Pattern | undefined;
if (node.name.kind === SyntaxKind.StringLiteral) {
const text = (<StringLiteral>node.name).text;
if (hasZeroOrOneAsteriskCharacter(text)) {
pattern = tryParsePattern(text);
}
else {
errorOnFirstToken(node.name, Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text);
}
}
const symbol = declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
if (pattern) {
(file.patternAmbientModules || (file.patternAmbientModules = [])).push({ pattern, symbol });
}
}
}
else {
@@ -2091,10 +2122,10 @@ namespace ts {
checkStrictModeFunctionName(<FunctionDeclaration>node);
if (inStrictMode) {
checkStrictModeFunctionDeclaration(node);
return bindBlockScopedDeclaration(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
bindBlockScopedDeclaration(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
}
else {
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
}
}
+164 -99
View File
@@ -138,6 +138,12 @@ namespace ts {
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
const globals: SymbolTable = {};
/**
* List of every ambient module with a "*" wildcard.
* Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches.
* This is only used if there is no exact match.
*/
let patternAmbientModules: PatternAmbientModule[];
let getGlobalESSymbolConstructorSymbol: () => Symbol;
@@ -984,7 +990,9 @@ namespace ts {
const moduleSymbol = resolveExternalModuleName(node, (<ImportDeclaration>node.parent).moduleSpecifier);
if (moduleSymbol) {
const exportDefaultSymbol = moduleSymbol.exports["export="] ?
const exportDefaultSymbol = isShorthandAmbientModule(moduleSymbol.valueDeclaration) ?
moduleSymbol :
moduleSymbol.exports["export="] ?
getPropertyOfType(getTypeOfSymbol(moduleSymbol.exports["export="]), "default") :
resolveSymbol(moduleSymbol.exports["default"]);
@@ -1058,6 +1066,10 @@ namespace ts {
if (targetSymbol) {
const name = specifier.propertyName || specifier.name;
if (name.text) {
if (isShorthandAmbientModule(moduleSymbol.valueDeclaration)) {
return moduleSymbol;
}
let symbolFromVariable: Symbol;
// First check if module was specified with "export=". If so, get the member from the resolved type
if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports["export="]) {
@@ -1283,6 +1295,14 @@ namespace ts {
}
return undefined;
}
if (patternAmbientModules) {
const pattern = findBestPatternMatch(patternAmbientModules, _ => _.pattern, moduleName);
if (pattern) {
return getMergedSymbol(pattern.symbol);
}
}
if (moduleNotFoundError) {
// report errors only if it was requested
error(moduleReferenceLiteral, moduleNotFoundError, moduleName);
@@ -2842,7 +2862,7 @@ namespace ts {
}
// In strict null checking mode, if a default value of a non-undefined type is specified, remove
// undefined from the final type.
if (strictNullChecks && declaration.initializer && !(getNullableKind(checkExpressionCached(declaration.initializer)) & TypeFlags.Undefined)) {
if (strictNullChecks && declaration.initializer && !(getCombinedTypeFlags(checkExpressionCached(declaration.initializer)) & TypeFlags.Undefined)) {
type = getTypeWithFacts(type, TypeFacts.NEUndefined);
}
return type;
@@ -2885,7 +2905,7 @@ namespace ts {
}
function addOptionality(type: Type, optional: boolean): Type {
return strictNullChecks && optional ? addNullableKind(type, TypeFlags.Undefined) : type;
return strictNullChecks && optional ? addTypeKind(type, TypeFlags.Undefined) : type;
}
// Return the inferred type for a variable, parameter, or property declaration
@@ -3218,9 +3238,14 @@ namespace ts {
function getTypeOfFuncClassEnumModule(symbol: Symbol): Type {
const links = getSymbolLinks(symbol);
if (!links.type) {
const type = createObjectType(TypeFlags.Anonymous, symbol);
links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ?
addNullableKind(type, TypeFlags.Undefined) : type;
if (symbol.valueDeclaration.kind === SyntaxKind.ModuleDeclaration && isShorthandAmbientModule(<ModuleDeclaration>symbol.valueDeclaration)) {
links.type = anyType;
}
else {
const type = createObjectType(TypeFlags.Anonymous, symbol);
links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ?
addTypeKind(type, TypeFlags.Undefined) : type;
}
}
return links.type;
}
@@ -6744,7 +6769,7 @@ namespace ts {
return getUnionType(types);
}
const supertype = forEach(primaryTypes, t => isSupertypeOfEach(t, primaryTypes) ? t : undefined);
return supertype && addNullableKind(supertype, getCombinedFlagsOfTypes(types) & TypeFlags.Nullable);
return supertype && addTypeKind(supertype, getCombinedFlagsOfTypes(types) & TypeFlags.Nullable);
}
function reportNoCommonSupertypeError(types: Type[], errorLocation: Node, errorMessageChainHead: DiagnosticMessageChain): void {
@@ -6815,28 +6840,22 @@ namespace ts {
return !!(type.flags & TypeFlags.Tuple);
}
function getNullableKind(type: Type): TypeFlags {
let flags = type.flags;
if (flags & TypeFlags.Union) {
for (const t of (type as UnionType).types) {
flags |= t.flags;
}
}
return flags & TypeFlags.Nullable;
function getCombinedTypeFlags(type: Type): TypeFlags {
return type.flags & TypeFlags.Union ? getCombinedFlagsOfTypes((<UnionType>type).types) : type.flags;
}
function addNullableKind(type: Type, kind: TypeFlags): Type {
if ((getNullableKind(type) & kind) !== kind) {
const types = [type];
if (kind & TypeFlags.Undefined) {
types.push(undefinedType);
}
if (kind & TypeFlags.Null) {
types.push(nullType);
}
type = getUnionType(types);
function addTypeKind(type: Type, kind: TypeFlags) {
if ((getCombinedTypeFlags(type) & kind) === kind) {
return type;
}
return type;
const types = [type];
if (kind & TypeFlags.String) types.push(stringType);
if (kind & TypeFlags.Number) types.push(numberType);
if (kind & TypeFlags.Boolean) types.push(booleanType);
if (kind & TypeFlags.Void) types.push(voidType);
if (kind & TypeFlags.Undefined) types.push(undefinedType);
if (kind & TypeFlags.Null) types.push(nullType);
return getUnionType(types);
}
function getNonNullableType(type: Type): Type {
@@ -7660,12 +7679,27 @@ namespace ts {
getInitialTypeOfBindingElement(<BindingElement>node);
}
function getReferenceFromExpression(node: Expression): Expression {
switch (node.kind) {
case SyntaxKind.ParenthesizedExpression:
return getReferenceFromExpression((<ParenthesizedExpression>node).expression);
case SyntaxKind.BinaryExpression:
switch ((<BinaryExpression>node).operatorToken.kind) {
case SyntaxKind.EqualsToken:
return getReferenceFromExpression((<BinaryExpression>node).left);
case SyntaxKind.CommaToken:
return getReferenceFromExpression((<BinaryExpression>node).right);
}
}
return node;
}
function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean) {
let key: string;
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
return declaredType;
}
const initialType = assumeInitialized ? declaredType : addNullableKind(declaredType, TypeFlags.Undefined);
const initialType = assumeInitialized ? declaredType : addTypeKind(declaredType, TypeFlags.Undefined);
const visitedFlowStart = visitedFlowCount;
const result = getTypeAtFlowNode(reference.flowNode);
visitedFlowCount = visitedFlowStart;
@@ -7859,10 +7893,11 @@ namespace ts {
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
if (isNullOrUndefinedLiteral(expr.right)) {
if (isNullOrUndefinedLiteral(expr.left) || isNullOrUndefinedLiteral(expr.right)) {
return narrowTypeByNullCheck(type, expr, assumeTrue);
}
if (expr.left.kind === SyntaxKind.TypeOfExpression && expr.right.kind === SyntaxKind.StringLiteral) {
if (expr.left.kind === SyntaxKind.TypeOfExpression && expr.right.kind === SyntaxKind.StringLiteral ||
expr.left.kind === SyntaxKind.StringLiteral && expr.right.kind === SyntaxKind.TypeOfExpression) {
return narrowTypeByTypeof(type, expr, assumeTrue);
}
break;
@@ -7875,18 +7910,20 @@ namespace ts {
}
function narrowTypeByNullCheck(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
// We have '==', '!=', '===', or '!==' operator with 'null' or 'undefined' on the right
// We have '==', '!=', '===', or '!==' operator with 'null' or 'undefined' on one side
const operator = expr.operatorToken.kind;
const nullLike = isNullOrUndefinedLiteral(expr.left) ? expr.left : expr.right;
const narrowed = isNullOrUndefinedLiteral(expr.left) ? expr.right : expr.left;
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
assumeTrue = !assumeTrue;
}
if (!strictNullChecks || !isMatchingReference(reference, expr.left)) {
if (!strictNullChecks || !isMatchingReference(reference, getReferenceFromExpression(narrowed))) {
return type;
}
const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken;
const facts = doubleEquals ?
assumeTrue ? TypeFacts.EQUndefinedOrNull : TypeFacts.NEUndefinedOrNull :
expr.right.kind === SyntaxKind.NullKeyword ?
nullLike.kind === SyntaxKind.NullKeyword ?
assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull :
assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined;
return getTypeWithFacts(type, facts);
@@ -7895,12 +7932,12 @@ namespace ts {
function narrowTypeByTypeof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
// We have '==', '!=', '====', or !==' operator with 'typeof xxx' on the left
// and string literal on the right
const left = <TypeOfExpression>expr.left;
const right = <LiteralExpression>expr.right;
if (!isMatchingReference(reference, left.expression)) {
const narrowed = getReferenceFromExpression((<TypeOfExpression>(expr.left.kind === SyntaxKind.TypeOfExpression ? expr.left : expr.right)).expression);
const literal = <LiteralExpression>(expr.right.kind === SyntaxKind.StringLiteral ? expr.right : expr.left);
if (!isMatchingReference(reference, narrowed)) {
// For a reference of the form 'x.y', a 'typeof x === ...' type guard resets the
// narrowed type of 'y' to its declared type.
if (containsMatchingReference(reference, left.expression)) {
if (containsMatchingReference(reference, narrowed)) {
return declaredType;
}
return type;
@@ -7913,22 +7950,23 @@ namespace ts {
// We narrow a non-union type to an exact primitive type if the non-union type
// is a supertype of that primtive type. For example, type 'any' can be narrowed
// to one of the primitive types.
const targetType = getProperty(typeofTypesByName, right.text);
const targetType = getProperty(typeofTypesByName, literal.text);
if (targetType && isTypeSubtypeOf(targetType, type)) {
return targetType;
}
}
const facts = assumeTrue ?
getProperty(typeofEQFacts, right.text) || TypeFacts.TypeofEQHostObject :
getProperty(typeofNEFacts, right.text) || TypeFacts.TypeofNEHostObject;
getProperty(typeofEQFacts, literal.text) || TypeFacts.TypeofEQHostObject :
getProperty(typeofNEFacts, literal.text) || TypeFacts.TypeofNEHostObject;
return getTypeWithFacts(type, facts);
}
function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
if (!isMatchingReference(reference, expr.left)) {
const left = getReferenceFromExpression(expr.left);
if (!isMatchingReference(reference, left)) {
// For a reference of the form 'x.y', an 'x instanceof T' type guard resets the
// narrowed type of 'y' to its declared type.
if (containsMatchingReference(reference, expr.left)) {
if (containsMatchingReference(reference, left)) {
return declaredType;
}
return type;
@@ -7995,7 +8033,7 @@ namespace ts {
const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type;
return isTypeAssignableTo(candidate, targetType) ? candidate :
isTypeAssignableTo(type, candidate) ? type :
neverType;
getIntersectionType([type, candidate]);
}
function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
@@ -8089,13 +8127,22 @@ namespace ts {
return expression;
}
function getControlFlowContainer(node: Node): Node {
while (true) {
node = node.parent;
if (isFunctionLike(node) || node.kind === SyntaxKind.ModuleBlock || node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.PropertyDeclaration) {
return node;
}
}
}
function isDeclarationIncludedInFlow(reference: Node, declaration: Declaration, includeOuterFunctions: boolean) {
const declarationContainer = getContainingFunctionOrModule(declaration);
let container = getContainingFunctionOrModule(reference);
const declarationContainer = getControlFlowContainer(declaration);
let container = getControlFlowContainer(reference);
while (container !== declarationContainer &&
(container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.ArrowFunction) &&
(includeOuterFunctions || getImmediatelyInvokedFunctionExpression(<FunctionExpression>container))) {
container = getContainingFunctionOrModule(container);
container = getControlFlowContainer(container);
}
return container === declarationContainer;
}
@@ -8161,7 +8208,7 @@ namespace ts {
getRootDeclaration(declaration).kind === SyntaxKind.Parameter || isInAmbientContext(declaration) ||
!isDeclarationIncludedInFlow(node, declaration, includeOuterFunctions);
const flowType = getFlowTypeOfReference(node, type, assumeInitialized, includeOuterFunctions);
if (!assumeInitialized && !(getNullableKind(type) & TypeFlags.Undefined) && getNullableKind(flowType) & TypeFlags.Undefined) {
if (!assumeInitialized && !(getCombinedTypeFlags(type) & TypeFlags.Undefined) && getCombinedTypeFlags(flowType) & TypeFlags.Undefined) {
error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
// Return the declared type to reduce follow-on errors
return type;
@@ -8381,7 +8428,10 @@ namespace ts {
if (needToCaptureLexicalThis) {
captureLexicalThis(node, container);
}
if (isFunctionLike(container)) {
if (isFunctionLike(container) &&
(!isInParameterInitializerBeforeContainingFunction(node) || getFunctionLikeThisParameter(container))) {
// Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated.
// If this is a function in a JS file, it might be a class method. Check if it's the RHS
// of a x.prototype.y = function [name]() { .... }
if (container.kind === SyntaxKind.FunctionExpression &&
@@ -8735,6 +8785,16 @@ namespace ts {
function getContextualTypeForReturnExpression(node: Expression): Type {
const func = getContainingFunction(node);
if (isAsyncFunctionLike(func)) {
const contextualReturnType = getContextualReturnType(func);
if (contextualReturnType) {
return getPromisedType(contextualReturnType);
}
return undefined;
}
if (func && !func.asteriskToken) {
return getContextualReturnType(func);
}
@@ -9947,7 +10007,7 @@ namespace ts {
function checkNonNullExpression(node: Expression | QualifiedName) {
const type = checkExpression(node);
if (strictNullChecks) {
const kind = getNullableKind(type);
const kind = getCombinedTypeFlags(type) & TypeFlags.Nullable;
if (kind) {
error(node, kind & TypeFlags.Undefined ? kind & TypeFlags.Null ?
Diagnostics.Object_is_possibly_null_or_undefined :
@@ -9993,24 +10053,14 @@ namespace ts {
}
const propType = getTypeOfSymbol(prop);
// Only compute control flow type if this is a property access expression that isn't an
// assignment target, and the referenced property was declared as a variable, property,
// accessor, or optional method.
if (node.kind !== SyntaxKind.PropertyAccessExpression || isAssignmentTarget(node) ||
!(propType.flags & TypeFlags.Union) && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor))) {
!(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) &&
!(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) {
return propType;
}
const leftmostNode = getLeftmostIdentifierOrThis(node);
if (!leftmostNode) {
return propType;
}
if (leftmostNode.kind === SyntaxKind.Identifier) {
const leftmostSymbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(<Identifier>leftmostNode));
if (!leftmostSymbol) {
return propType;
}
const declaration = leftmostSymbol.valueDeclaration;
if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.Parameter && declaration.kind !== SyntaxKind.BindingElement) {
return propType;
}
}
return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*includeOuterFunctions*/ false);
}
@@ -10325,8 +10375,8 @@ namespace ts {
return -1;
}
function hasCorrectArity(node: CallLikeExpression, args: Expression[], signature: Signature) {
let adjustedArgCount: number; // Apparent number of arguments we will have in this call
function hasCorrectArity(node: CallLikeExpression, args: Expression[], signature: Signature, signatureHelpTrailingComma = false) {
let argCount: number; // Apparent number of arguments we will have in this call
let typeArguments: NodeArray<TypeNode>; // Type arguments (undefined if none)
let callIsIncomplete: boolean; // In incomplete call we want to be lenient when we have too few arguments
let isDecorator: boolean;
@@ -10337,7 +10387,7 @@ namespace ts {
// Even if the call is incomplete, we'll have a missing expression as our last argument,
// so we can say the count is just the arg list length
adjustedArgCount = args.length;
argCount = args.length;
typeArguments = undefined;
if (tagExpression.template.kind === SyntaxKind.TemplateExpression) {
@@ -10360,7 +10410,7 @@ namespace ts {
else if (node.kind === SyntaxKind.Decorator) {
isDecorator = true;
typeArguments = undefined;
adjustedArgCount = getEffectiveArgumentCount(node, /*args*/ undefined, signature);
argCount = getEffectiveArgumentCount(node, /*args*/ undefined, signature);
}
else {
const callExpression = <CallExpression>node;
@@ -10371,8 +10421,7 @@ namespace ts {
return signature.minArgumentCount === 0;
}
// For IDE scenarios we may have an incomplete call, so a trailing comma is tantamount to adding another argument.
adjustedArgCount = callExpression.arguments.hasTrailingComma ? args.length + 1 : args.length;
argCount = signatureHelpTrailingComma ? args.length + 1 : args.length;
// If we are missing the close paren, the call is incomplete.
callIsIncomplete = (<CallExpression>callExpression).arguments.end === callExpression.end;
@@ -10396,12 +10445,12 @@ namespace ts {
}
// Too many arguments implies incorrect arity.
if (!signature.hasRestParameter && adjustedArgCount > signature.parameters.length) {
if (!signature.hasRestParameter && argCount > signature.parameters.length) {
return false;
}
// If the call is incomplete, we should skip the lower bound check.
const hasEnoughArguments = adjustedArgCount >= signature.minArgumentCount;
const hasEnoughArguments = argCount >= signature.minArgumentCount;
return callIsIncomplete || hasEnoughArguments;
}
@@ -10973,6 +11022,11 @@ namespace ts {
let resultOfFailedInference: InferenceContext;
let result: Signature;
// If we are in signature help, a trailing comma indicates that we intend to provide another argument,
// so we will only accept overloads with arity at least 1 higher than the current number of provided arguments.
const signatureHelpTrailingComma =
candidatesOutArray && node.kind === SyntaxKind.CallExpression && (<CallExpression>node).arguments.hasTrailingComma;
// Section 4.12.1:
// if the candidate list contains one or more signatures for which the type of each argument
// expression is a subtype of each corresponding parameter type, the return type of the first
@@ -10984,14 +11038,14 @@ namespace ts {
// is just important for choosing the best signature. So in the case where there is only one
// signature, the subtype pass is useless. So skipping it is an optimization.
if (candidates.length > 1) {
result = chooseOverload(candidates, subtypeRelation);
result = chooseOverload(candidates, subtypeRelation, signatureHelpTrailingComma);
}
if (!result) {
// Reinitialize these pointers for round two
candidateForArgumentError = undefined;
candidateForTypeArgumentError = undefined;
resultOfFailedInference = undefined;
result = chooseOverload(candidates, assignableRelation);
result = chooseOverload(candidates, assignableRelation, signatureHelpTrailingComma);
}
if (result) {
return result;
@@ -11062,9 +11116,9 @@ namespace ts {
diagnostics.add(createDiagnosticForNodeFromMessageChain(node, errorInfo));
}
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>) {
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
for (const originalCandidate of candidates) {
if (!hasCorrectArity(node, args, originalCandidate)) {
if (!hasCorrectArity(node, args, originalCandidate, signatureHelpTrailingComma)) {
continue;
}
@@ -11487,7 +11541,7 @@ namespace ts {
if (strictNullChecks) {
const declaration = symbol.valueDeclaration;
if (declaration && (<VariableLikeDeclaration>declaration).initializer) {
return addNullableKind(type, TypeFlags.Undefined);
return addTypeKind(type, TypeFlags.Undefined);
}
}
return type;
@@ -12413,7 +12467,7 @@ namespace ts {
case SyntaxKind.InKeyword:
return checkInExpression(left, right, leftType, rightType);
case SyntaxKind.AmpersandAmpersandToken:
return strictNullChecks ? addNullableKind(rightType, getNullableKind(leftType)) : rightType;
return strictNullChecks ? addTypeKind(rightType, getCombinedTypeFlags(leftType) & TypeFlags.Falsy) : rightType;
case SyntaxKind.BarBarToken:
return getUnionType([getNonNullableType(leftType), rightType]);
case SyntaxKind.EqualsToken:
@@ -15109,7 +15163,7 @@ namespace ts {
// In a 'switch' statement, each 'case' expression must be of a type that is comparable
// to or from the type of the 'switch' expression.
const caseType = checkExpression(caseClause.expression);
if (!isTypeComparableTo(expressionType, caseType)) {
if (!isTypeEqualityComparableTo(expressionType, caseType)) {
// expressionType is not comparable to caseType, try the reversed check and report errors if it fails
checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);
}
@@ -16014,7 +16068,7 @@ namespace ts {
// - augmentation for a global scope is always applied
// - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module).
const checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & SymbolFlags.Merged);
if (checkBody) {
if (checkBody && node.body) {
// body of ambient external module is always a module block
for (const statement of (<ModuleBlock>node.body).statements) {
checkModuleAugmentationElement(statement, isGlobalAugmentation);
@@ -16041,7 +16095,15 @@ namespace ts {
}
}
}
checkSourceElement(node.body);
if (compilerOptions.noImplicitAny && !node.body) {
// Ambient shorthand module is an implicit any
reportImplicitAnyError(node, anyType);
}
if (node.body) {
checkSourceElement(node.body);
}
}
function checkModuleAugmentationElement(node: Node, isGlobalAugmentation: boolean): void {
@@ -16226,7 +16288,7 @@ namespace ts {
else {
if (modulekind === ModuleKind.ES6 && !isInAmbientContext(node)) {
// Import equals declaration is deprecated in es6 or above
grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead);
grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_2015_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead);
}
}
}
@@ -16312,7 +16374,7 @@ namespace ts {
if (node.isExportEquals && !isInAmbientContext(node)) {
if (modulekind === ModuleKind.ES6) {
// export assignment is not supported in es6 modules
grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_modules_Consider_using_export_default_or_another_module_format_instead);
grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_2015_modules_Consider_using_export_default_or_another_module_format_instead);
}
else if (modulekind === ModuleKind.System) {
// system modules does not support export assignment
@@ -16862,10 +16924,7 @@ namespace ts {
return getIntrinsicTagSymbol(<JsxOpeningLikeElement>entityName.parent);
}
// Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead
// return the alias symbol.
const meaning: SymbolFlags = SymbolFlags.Value | SymbolFlags.Alias;
return resolveEntityName(<Identifier>entityName, meaning);
return resolveEntityName(<Identifier>entityName, SymbolFlags.Value, /*ignoreErrors*/ false, /*dontResolveAlias*/ true);
}
else if (entityName.kind === SyntaxKind.PropertyAccessExpression) {
const symbol = getNodeLinks(entityName).resolvedSymbol;
@@ -16883,11 +16942,8 @@ namespace ts {
}
}
else if (isTypeReferenceIdentifier(<EntityName>entityName)) {
let meaning = (entityName.parent.kind === SyntaxKind.TypeReference || entityName.parent.kind === SyntaxKind.JSDocTypeReference) ? SymbolFlags.Type : SymbolFlags.Namespace;
// Include aliases in the meaning, this ensures that we do not follow aliases to where they point and instead
// return the alias symbol.
meaning |= SymbolFlags.Alias;
return resolveEntityName(<EntityName>entityName, meaning);
const meaning = (entityName.parent.kind === SyntaxKind.TypeReference || entityName.parent.kind === SyntaxKind.JSDocTypeReference) ? SymbolFlags.Type : SymbolFlags.Namespace;
return resolveEntityName(<EntityName>entityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/true);
}
else if (entityName.parent.kind === SyntaxKind.JsxAttribute) {
return getJsxAttributePropertySymbol(<JsxAttribute>entityName.parent);
@@ -17714,6 +17770,10 @@ namespace ts {
if (!isExternalOrCommonJsModule(file)) {
mergeSymbolTable(globals, file.locals);
}
if (file.patternAmbientModules && file.patternAmbientModules.length) {
patternAmbientModules = concatenate(patternAmbientModules, file.patternAmbientModules);
}
if (file.moduleAugmentations.length) {
(augmentations || (augmentations = [])).push(file.moduleAugmentations);
}
@@ -17844,6 +17904,8 @@ namespace ts {
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.ExportAssignment:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.Parameter:
break;
case SyntaxKind.FunctionDeclaration:
@@ -18075,7 +18137,7 @@ namespace ts {
function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean {
if (languageVersion < ScriptTarget.ES6) {
return grammarErrorOnNode(asyncModifier, Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_6_and_higher);
return grammarErrorOnNode(asyncModifier, Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_2015_or_higher);
}
switch (node.kind) {
@@ -18114,10 +18176,6 @@ namespace ts {
}
function checkGrammarParameterList(parameters: NodeArray<ParameterDeclaration>) {
if (checkGrammarForDisallowedTrailingComma(parameters)) {
return true;
}
let seenOptionalParameter = false;
const parameterCount = parameters.length;
@@ -18236,8 +18294,7 @@ namespace ts {
}
function checkGrammarArguments(node: CallExpression, args: NodeArray<Expression>): boolean {
return checkGrammarForDisallowedTrailingComma(args) ||
checkGrammarForOmittedArgument(node, args);
return checkGrammarForOmittedArgument(node, args);
}
function checkGrammarHeritageClause(node: HeritageClause): boolean {
@@ -18338,7 +18395,7 @@ namespace ts {
return grammarErrorOnNode(node.asteriskToken, Diagnostics.An_overload_signature_cannot_be_declared_as_a_generator);
}
if (languageVersion < ScriptTarget.ES6) {
return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_only_available_when_targeting_ECMAScript_6_or_higher);
return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_only_available_when_targeting_ECMAScript_2015_or_higher);
}
}
}
@@ -18562,6 +18619,14 @@ namespace ts {
}
}
function getFunctionLikeThisParameter(func: FunctionLikeDeclaration) {
if (func.parameters.length &&
func.parameters[0].name.kind === SyntaxKind.Identifier &&
(<Identifier>func.parameters[0].name).originalKeywordKind === SyntaxKind.ThisKeyword) {
return func.parameters[0];
}
}
function checkGrammarForNonSymbolComputedProperty(node: DeclarationName, message: DiagnosticMessage) {
if (isDynamicName(node)) {
return grammarErrorOnNode(node, message);
+4 -3
View File
@@ -6,7 +6,7 @@
namespace ts {
/* @internal */
export let optionDeclarations: CommandLineOption[] = [
export const optionDeclarations: CommandLineOption[] = [
{
name: "charset",
type: "string",
@@ -406,7 +406,8 @@ namespace ts {
"es2015.symbol": "lib.es2015.symbol.d.ts",
"es2015.symbol.wellknown": "lib.es2015.symbol.wellknown.d.ts",
"es2016.array.include": "lib.es2016.array.include.d.ts",
"es2017.object": "lib.es2017.object.d.ts"
"es2017.object": "lib.es2017.object.d.ts",
"es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts"
},
},
description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation_Colon
@@ -727,7 +728,7 @@ namespace ts {
if (outDir) {
exclude.push(outDir);
}
exclude = map(exclude, normalizeSlashes);
exclude = map(exclude, e => getNormalizedAbsolutePath(e, basePath));
const supportedExtensions = getSupportedExtensions(options);
Debug.assert(indexOf(supportedExtensions, ".ts") < indexOf(supportedExtensions, ".d.ts"), "Changed priority of extensions to pick");
+11 -2
View File
@@ -1020,13 +1020,22 @@ namespace ts {
const extensionsToRemove = [".d.ts", ".ts", ".js", ".tsx", ".jsx"];
export function removeFileExtension(path: string): string {
for (const ext of extensionsToRemove) {
if (fileExtensionIs(path, ext)) {
return path.substr(0, path.length - ext.length);
const extensionless = tryRemoveExtension(path, ext);
if (extensionless !== undefined) {
return extensionless;
}
}
return path;
}
export function tryRemoveExtension(path: string, extension: string): string {
return fileExtensionIs(path, extension) ? path.substring(0, path.length - extension.length) : undefined;
}
export function isJsxOrTsxExtension(ext: string): boolean {
return ext === ".jsx" || ext === ".tsx";
}
export interface ObjectAllocator {
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
getSourceFileConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => SourceFile;
+15 -10
View File
@@ -854,21 +854,26 @@ namespace ts {
writeTextOfNode(currentText, node.name);
}
}
while (node.body.kind !== SyntaxKind.ModuleBlock) {
while (node.body && node.body.kind !== SyntaxKind.ModuleBlock) {
node = <ModuleDeclaration>node.body;
write(".");
writeTextOfNode(currentText, node.name);
}
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
write(" {");
writeLine();
increaseIndent();
emitLines((<ModuleBlock>node.body).statements);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
if (node.body) {
enclosingDeclaration = node;
write(" {");
writeLine();
increaseIndent();
emitLines((<ModuleBlock>node.body).statements);
decreaseIndent();
write("}");
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
}
else {
write(";");
}
}
function writeTypeAliasDeclaration(node: TypeAliasDeclaration) {
+10 -10
View File
@@ -627,18 +627,14 @@
"category": "Error",
"code": 1200
},
"Import assignment cannot be used when targeting ECMAScript 6 modules. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"', 'import d from \"mod\"', or another module format instead.": {
"Import assignment cannot be used when targeting ECMAScript 2015 modules. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"', 'import d from \"mod\"', or another module format instead.": {
"category": "Error",
"code": 1202
},
"Export assignment cannot be used when targeting ECMAScript 6 modules. Consider using 'export default' or another module format instead.": {
"Export assignment cannot be used when targeting ECMAScript 2015 modules. Consider using 'export default' or another module format instead.": {
"category": "Error",
"code": 1203
},
"Cannot compile modules into 'es2015' when targeting 'ES5' or lower.": {
"category": "Error",
"code": 1204
},
"Decorators are not valid here.": {
"category": "Error",
"code": 1206
@@ -687,7 +683,7 @@
"category": "Error",
"code": 1219
},
"Generators are only available when targeting ECMAScript 6 or higher.": {
"Generators are only available when targeting ECMAScript 2015 or higher.": {
"category": "Error",
"code": 1220
},
@@ -831,7 +827,7 @@
"category": "Error",
"code": 1308
},
"Async functions are only available when targeting ECMAScript 6 and higher.": {
"Async functions are only available when targeting ECMAScript 2015 or higher.": {
"category": "Error",
"code": 1311
},
@@ -2260,7 +2256,7 @@
"category": "Error",
"code": 5047
},
"Option 'inlineSources' can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.": {
"Option '{0} can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.": {
"category": "Error",
"code": 5051
},
@@ -2772,10 +2768,14 @@
"category": "Error",
"code": 6131
},
"Import emit helpers from 'tslib'.": {
"File name '{0}' has a '{1}' extension - stripping it": {
"category": "Message",
"code": 6132
},
"Import emit helpers from 'tslib'.": {
"category": "Message",
"code": 6133
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
+8 -1
View File
@@ -5332,7 +5332,14 @@ namespace ts {
else {
node.name = parseLiteralNode(/*internName*/ true);
}
node.body = parseModuleBlock();
if (token === SyntaxKind.OpenBraceToken) {
node.body = parseModuleBlock();
}
else {
parseSemicolon();
}
return finishNode(node);
}
+112 -56
View File
@@ -90,7 +90,8 @@ namespace ts {
return compilerOptions.traceResolution && host.trace !== undefined;
}
function hasZeroOrOneAsteriskCharacter(str: string): boolean {
/* @internal */
export function hasZeroOrOneAsteriskCharacter(str: string): boolean {
let seenAsterisk = false;
for (let i = 0; i < str.length; i++) {
if (str.charCodeAt(i) === CharacterCodes.asterisk) {
@@ -491,48 +492,23 @@ namespace ts {
trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, state.compilerOptions.baseUrl, moduleName);
}
let longestMatchPrefixLength = -1;
let matchedPattern: string;
let matchedStar: string;
// string is for exact match
let matchedPattern: Pattern | string | undefined = undefined;
if (state.compilerOptions.paths) {
if (state.traceEnabled) {
trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName);
}
for (const key in state.compilerOptions.paths) {
const pattern: string = key;
const indexOfStar = pattern.indexOf("*");
if (indexOfStar !== -1) {
const prefix = pattern.substr(0, indexOfStar);
const suffix = pattern.substr(indexOfStar + 1);
if (moduleName.length >= prefix.length + suffix.length &&
startsWith(moduleName, prefix) &&
endsWith(moduleName, suffix)) {
// use length of prefix as betterness criteria
if (prefix.length > longestMatchPrefixLength) {
longestMatchPrefixLength = prefix.length;
matchedPattern = pattern;
matchedStar = moduleName.substr(prefix.length, moduleName.length - suffix.length);
}
}
}
else if (pattern === moduleName) {
// pattern was matched as is - no need to search further
matchedPattern = pattern;
matchedStar = undefined;
break;
}
}
matchedPattern = matchPatternOrExact(getKeys(state.compilerOptions.paths), moduleName);
}
if (matchedPattern) {
const matchedStar = typeof matchedPattern === "string" ? undefined : matchedText(matchedPattern, moduleName);
const matchedPatternText = typeof matchedPattern === "string" ? matchedPattern : patternText(matchedPattern);
if (state.traceEnabled) {
trace(state.host, Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPattern);
trace(state.host, Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText);
}
for (const subst of state.compilerOptions.paths[matchedPattern]) {
const path = matchedStar ? subst.replace("\*", matchedStar) : subst;
for (const subst of state.compilerOptions.paths[matchedPatternText]) {
const path = matchedStar ? subst.replace("*", matchedStar) : subst;
const candidate = normalizePath(combinePaths(state.compilerOptions.baseUrl, path));
if (state.traceEnabled) {
trace(state.host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path);
@@ -555,6 +531,75 @@ namespace ts {
}
}
/**
* patternStrings contains both pattern strings (containing "*") and regular strings.
* Return an exact match if possible, or a pattern match, or undefined.
* (These are verified by verifyCompilerOptions to have 0 or 1 "*" characters.)
*/
function matchPatternOrExact(patternStrings: string[], candidate: string): string | Pattern | undefined {
const patterns: Pattern[] = [];
for (const patternString of patternStrings) {
const pattern = tryParsePattern(patternString);
if (pattern) {
patterns.push(pattern);
}
else if (patternString === candidate) {
// pattern was matched as is - no need to search further
return patternString;
}
}
return findBestPatternMatch(patterns, _ => _, candidate);
}
function patternText({prefix, suffix}: Pattern): string {
return `${prefix}*${suffix}`;
}
/**
* Given that candidate matches pattern, returns the text matching the '*'.
* E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar"
*/
function matchedText(pattern: Pattern, candidate: string): string {
Debug.assert(isPatternMatch(pattern, candidate));
return candidate.substr(pattern.prefix.length, candidate.length - pattern.suffix.length);
}
/** Return the object corresponding to the best pattern to match `candidate`. */
/* @internal */
export function findBestPatternMatch<T>(values: T[], getPattern: (value: T) => Pattern, candidate: string): T | undefined {
let matchedValue: T | undefined = undefined;
// use length of prefix as betterness criteria
let longestMatchPrefixLength = -1;
for (const v of values) {
const pattern = getPattern(v);
if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) {
longestMatchPrefixLength = pattern.prefix.length;
matchedValue = v;
}
}
return matchedValue;
}
function isPatternMatch({prefix, suffix}: Pattern, candidate: string) {
return candidate.length >= prefix.length + suffix.length &&
startsWith(candidate, prefix) &&
endsWith(candidate, suffix);
}
/* @internal */
export function tryParsePattern(pattern: string): Pattern | undefined {
// This should be verified outside of here and a proper error thrown.
Debug.assert(hasZeroOrOneAsteriskCharacter(pattern));
const indexOfStar = pattern.indexOf("*");
return indexOfStar === -1 ? undefined : {
prefix: pattern.substr(0, indexOfStar),
suffix: pattern.substr(indexOfStar + 1)
};
}
export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
const containingDirectory = getDirectoryPath(containingFile);
const supportedExtensions = getSupportedExtensions(compilerOptions);
@@ -614,8 +659,25 @@ namespace ts {
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
*/
function loadModuleFromFile(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
// First try to keep/add an extension: importing "./foo.ts" can be matched by a file "./foo.ts", and "./foo" by "./foo.d.ts"
const resolvedByAddingOrKeepingExtension = loadModuleFromFileWorker(candidate, extensions, failedLookupLocation, onlyRecordFailures, state);
if (resolvedByAddingOrKeepingExtension) {
return resolvedByAddingOrKeepingExtension;
}
// Then try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one, e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts"
if (hasJavaScriptFileExtension(candidate)) {
const extensionless = removeFileExtension(candidate);
if (state.traceEnabled) {
const extension = candidate.substring(extensionless.length);
trace(state.host, Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension);
}
return loadModuleFromFileWorker(extensionless, extensions, failedLookupLocation, onlyRecordFailures, state);
}
}
function loadModuleFromFileWorker(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
if (!onlyRecordFailures) {
// check if containig folder exists - if it doesn't then just record failures for all supported extensions without disk probing
// check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing
const directory = getDirectoryPath(candidate);
if (directory) {
onlyRecordFailures = !directoryProbablyExists(directory, state.host);
@@ -624,7 +686,7 @@ namespace ts {
return forEach(extensions, tryLoad);
function tryLoad(ext: string): string {
if (ext === ".tsx" && state.skipTsx) {
if (state.skipTsx && isJsxOrTsxExtension(ext)) {
return undefined;
}
const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext;
@@ -1139,6 +1201,7 @@ namespace ts {
// if any of these properties has changed - structure cannot be reused
const oldOptions = oldProgram.getCompilerOptions();
if ((oldOptions.module !== options.module) ||
(oldOptions.moduleResolution !== options.moduleResolution) ||
(oldOptions.noResolve !== options.noResolve) ||
(oldOptions.target !== options.target) ||
(oldOptions.noLib !== options.noLib) ||
@@ -1709,9 +1772,12 @@ namespace ts {
// The StringLiteral must specify a top - level external module name.
// Relative external module names are not permitted
// NOTE: body of ambient module is always a module block
for (const statement of (<ModuleBlock>(<ModuleDeclaration>node).body).statements) {
collectModuleReferences(statement, /*inAmbientModule*/ true);
// NOTE: body of ambient module is always a module block, if it exists
const body = <ModuleBlock>(<ModuleDeclaration>node).body;
if (body) {
for (const statement of body.statements) {
collectModuleReferences(statement, /*inAmbientModule*/ true);
}
}
}
}
@@ -2039,12 +2105,12 @@ namespace ts {
}
}
if (options.inlineSources) {
if (!options.sourceMap && !options.inlineSourceMap) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_inlineSources_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided));
if (!options.sourceMap && !options.inlineSourceMap) {
if (options.inlineSources) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources"));
}
if (options.sourceRoot) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceRoot", "inlineSources"));
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot"));
}
}
@@ -2052,14 +2118,9 @@ namespace ts {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile"));
}
if (!options.sourceMap && (options.mapRoot || options.sourceRoot)) {
// Error to specify --mapRoot or --sourceRoot without mapSourceFiles
if (options.mapRoot) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap"));
}
if (options.sourceRoot && !options.inlineSourceMap) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "sourceRoot", "sourceMap"));
}
if (options.mapRoot && !options.sourceMap) {
// Error to specify --mapRoot without --sourcemap
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "mapRoot", "sourceMap"));
}
if (options.declarationDir) {
@@ -2096,11 +2157,6 @@ namespace ts {
programDiagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none));
}
// Cannot specify module gen target of es6 when below es6
if (options.module === ModuleKind.ES6 && languageVersion < ScriptTarget.ES6) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Cannot_compile_modules_into_es2015_when_targeting_ES5_or_lower));
}
// Cannot specify module gen that isn't amd or system with --out
if (outFile) {
if (options.module && !(options.module === ModuleKind.AMD || options.module === ModuleKind.System)) {
+1 -1
View File
@@ -2,7 +2,7 @@
namespace ts {
export type FileWatcherCallback = (fileName: string, removed?: boolean) => void;
export type DirectoryWatcherCallback = (directoryName: string) => void;
export type DirectoryWatcherCallback = (fileName: string) => void;
export interface WatchedFile {
fileName: string;
callback: FileWatcherCallback;
+86 -3
View File
@@ -26,14 +26,24 @@ namespace ts {
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
const previousOnSubstituteNode = context.onSubstituteNode;
const previousOnEmitNode = context.onEmitNode;
context.onSubstituteNode = onSubstituteNode;
context.onEmitNode = onEmitNode;
context.enableSubstitution(SyntaxKind.Identifier);
context.enableSubstitution(SyntaxKind.BinaryExpression);
context.enableSubstitution(SyntaxKind.PrefixUnaryExpression);
context.enableSubstitution(SyntaxKind.PostfixUnaryExpression);
context.enableSubstitution(SyntaxKind.ShorthandPropertyAssignment);
context.enableEmitNotification(SyntaxKind.SourceFile);
let currentSourceFile: SourceFile;
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
let exportSpecifiers: Map<ExportSpecifier[]>;
let exportEquals: ExportAssignment;
let bindingNameExportSpecifiersMap: Map<ExportSpecifier[]>;
// Subset of exportSpecifiers that is a binding-name.
// This is to reduce amount of memory we have to keep around even after we done with module-transformer
const bindingNameExportSpecifiersForFileMap: Map<Map<ExportSpecifier[]>> = {};
let hasExportStarsToExportValues: boolean;
return transformSourceFile;
@@ -653,7 +663,14 @@ namespace ts {
}
}
else {
addExportMemberAssignments(resultStatements, name);
if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
const sourceFileId = getOriginalNodeId(currentSourceFile);
if (!bindingNameExportSpecifiersForFileMap[sourceFileId]) {
bindingNameExportSpecifiersForFileMap[sourceFileId] = {};
}
bindingNameExportSpecifiersForFileMap[sourceFileId][name.text] = exportSpecifiers[name.text];
addExportMemberAssignments(resultStatements, name);
}
}
}
@@ -799,6 +816,17 @@ namespace ts {
return node.name ? getSynthesizedClone(node.name) : getGeneratedNameForNode(node);
}
function onEmitNode(node: Node, emit: (node: Node) => void): void {
if (node.kind === SyntaxKind.SourceFile) {
bindingNameExportSpecifiersMap = bindingNameExportSpecifiersForFileMap[getOriginalNodeId(node)];
previousOnEmitNode(node, emit);
bindingNameExportSpecifiersMap = undefined;
}
else {
previousOnEmitNode(node, emit);
}
}
/**
* Hooks node substitutions.
*
@@ -833,8 +861,14 @@ namespace ts {
}
function substituteExpression(node: Expression) {
if (isIdentifier(node)) {
return substituteExpressionIdentifier(node);
switch (node.kind) {
case SyntaxKind.Identifier:
return substituteExpressionIdentifier(<Identifier>node);
case SyntaxKind.BinaryExpression:
return substituteBinaryExpression(<BinaryExpression>node);
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.PrefixUnaryExpression:
return substituteUnaryExpression(<PrefixUnaryExpression | PostfixUnaryExpression>node);
}
return node;
@@ -846,6 +880,55 @@ namespace ts {
|| node;
}
function substituteBinaryExpression(node: BinaryExpression): Expression {
const left = node.left;
// If the left-hand-side of the binaryExpression is an identifier and its is export through export Specifier
if (isIdentifier(left) && isAssignmentOperator(node.operatorToken.kind)) {
if (bindingNameExportSpecifiersMap && hasProperty(bindingNameExportSpecifiersMap, left.text)) {
setNodeEmitFlags(node, NodeEmitFlags.NoSubstitution);
let nestedExportAssignment: BinaryExpression;
for (const specifier of bindingNameExportSpecifiersMap[left.text]) {
nestedExportAssignment = nestedExportAssignment ?
createExportAssignment(specifier.name, nestedExportAssignment) :
createExportAssignment(specifier.name, node);
}
return nestedExportAssignment;
}
}
return node;
}
function substituteUnaryExpression(node: PrefixUnaryExpression | PostfixUnaryExpression): Expression {
// Because how the compiler only parse plusplus and minusminus to be either prefixUnaryExpression or postFixUnaryExpression depended on where they are
// We don't need to check that the operator has SyntaxKind.plusplus or SyntaxKind.minusminus
const operator = node.operator;
const operand = node.operand;
if (isIdentifier(operand) && bindingNameExportSpecifiersForFileMap) {
if (bindingNameExportSpecifiersMap && hasProperty(bindingNameExportSpecifiersMap, operand.text)) {
setNodeEmitFlags(node, NodeEmitFlags.NoSubstitution);
let transformedUnaryExpression: BinaryExpression;
if (node.kind === SyntaxKind.PostfixUnaryExpression) {
transformedUnaryExpression = createBinaryWithOperatorToken(
operand,
createNode(operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken),
createLiteral(1),
/*location*/ node
);
// We have to set no substitution flag here to prevent visit the binary expression and substitute it again as we will preform all necessary substitution in here
setNodeEmitFlags(transformedUnaryExpression, NodeEmitFlags.NoSubstitution);
}
let nestedExportAssignment: BinaryExpression;
for (const specifier of bindingNameExportSpecifiersMap[operand.text]) {
nestedExportAssignment = nestedExportAssignment ?
createExportAssignment(specifier.name, nestedExportAssignment) :
createExportAssignment(specifier.name, transformedUnaryExpression || node);
}
return nestedExportAssignment;
}
}
return node;
}
function trySubstituteExportedName(node: Identifier) {
const emitFlags = getNodeEmitFlags(node);
if ((emitFlags & NodeEmitFlags.LocalName) === 0) {
+60 -50
View File
@@ -1363,8 +1363,8 @@ namespace ts {
// @kind(SyntaxKind.ModuleDeclaration)
export interface ModuleDeclaration extends DeclarationStatement {
name: ModuleName;
body: ModuleBlock | ModuleDeclaration;
name: Identifier | LiteralExpression;
body?: ModuleBlock | ModuleDeclaration;
}
// @kind(SyntaxKind.ModuleBlock)
@@ -1725,6 +1725,7 @@ namespace ts {
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
/* @internal */ imports: LiteralExpression[];
/* @internal */ moduleAugmentations: LiteralExpression[];
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
// The synthesized identifier for an imported tslib helpers runtime.
/* @internal */ tslib?: Identifier;
}
@@ -2204,6 +2205,20 @@ namespace ts {
[index: string]: Symbol;
}
/** Represents a "prefix*suffix" pattern. */
/* @internal */
export interface Pattern {
prefix: string;
suffix: string;
}
/** Used to track a `declare module "foo*"`-like declaration. */
/* @internal */
export interface PatternAmbientModule {
pattern: Pattern;
symbol: Symbol;
}
/* @internal */
export const enum NodeCheckFlags {
TypeChecked = 0x00000001, // Node has been type checked
@@ -2278,6 +2293,7 @@ namespace ts {
/* @internal */
Nullable = Undefined | Null,
Falsy = String | Number | Boolean | Void | Undefined | Null,
/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null | Never,
/* @internal */
@@ -2287,7 +2303,10 @@ namespace ts {
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
UnionOrIntersection = Union | Intersection,
StructuredType = ObjectType | Union | Intersection,
Narrowable = Any | ObjectType | Union | TypeParameter,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | StructuredType | TypeParameter | StringLike | NumberLike | Boolean | ESSymbol,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
/* @internal */
@@ -2549,86 +2568,77 @@ namespace ts {
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | TsConfigOnlyOptions;
export interface CompilerOptions {
allowNonTsExtensions?: boolean;
allowJs?: boolean;
/*@internal*/ allowNonTsExtensions?: boolean;
allowSyntheticDefaultImports?: boolean;
allowUnreachableCode?: boolean;
allowUnusedLabels?: boolean;
baseUrl?: string;
charset?: string;
/* @internal */ configFilePath?: string;
declaration?: boolean;
declarationDir?: string;
diagnostics?: boolean;
/* @internal */ diagnostics?: boolean;
/*@internal*/ extendedDiagnostics?: boolean;
emitBOM?: boolean;
help?: boolean;
init?: boolean;
emitDecoratorMetadata?: boolean;
experimentalDecorators?: boolean;
forceConsistentCasingInFileNames?: boolean;
/*@internal*/help?: boolean;
importHelpers?: boolean;
/*@internal*/init?: boolean;
inlineSourceMap?: boolean;
inlineSources?: boolean;
importHelpers?: boolean;
isolatedModules?: boolean;
jsx?: JsxEmit;
reactNamespace?: string;
listFiles?: boolean;
typesSearchPaths?: string[];
lib?: string[];
/*@internal*/listEmittedFiles?: boolean;
/*@internal*/listFiles?: boolean;
locale?: string;
mapRoot?: string;
module?: ModuleKind;
moduleResolution?: ModuleResolutionKind;
newLine?: NewLineKind;
noEmit?: boolean;
noEmitHelpers?: boolean;
noEmitOnError?: boolean;
noErrorTruncation?: boolean;
noFallthroughCasesInSwitch?: boolean;
noImplicitAny?: boolean;
noImplicitReturns?: boolean;
noImplicitThis?: boolean;
noImplicitUseStrict?: boolean;
noLib?: boolean;
noResolve?: boolean;
out?: string;
outFile?: string;
outDir?: string;
outFile?: string;
paths?: PathSubstitutions;
preserveConstEnums?: boolean;
/* @internal */ pretty?: DiagnosticStyle;
project?: string;
/* @internal */ pretty?: DiagnosticStyle;
reactNamespace?: string;
removeComments?: boolean;
rootDir?: string;
rootDirs?: RootPaths;
skipLibCheck?: boolean;
skipDefaultLibCheck?: boolean;
sourceMap?: boolean;
sourceRoot?: string;
strictNullChecks?: boolean;
/* @internal */ stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget;
version?: boolean;
watch?: boolean;
isolatedModules?: boolean;
experimentalDecorators?: boolean;
emitDecoratorMetadata?: boolean;
moduleResolution?: ModuleResolutionKind;
allowUnusedLabels?: boolean;
allowUnreachableCode?: boolean;
noImplicitReturns?: boolean;
noFallthroughCasesInSwitch?: boolean;
forceConsistentCasingInFileNames?: boolean;
baseUrl?: string;
paths?: PathSubstitutions;
rootDirs?: RootPaths;
traceResolution?: boolean;
allowSyntheticDefaultImports?: boolean;
allowJs?: boolean;
noImplicitUseStrict?: boolean;
strictNullChecks?: boolean;
skipLibCheck?: boolean;
listEmittedFiles?: boolean;
lib?: string[];
/* @internal */ stripInternal?: boolean;
/* @internal */ useLegacyEmitter?: boolean;
// Skip checking lib.d.ts to help speed up tests.
/* @internal */ skipDefaultLibCheck?: boolean;
// Do not perform validation of output file name in transpile scenarios
/* @internal */ suppressOutputPathCheck?: boolean;
/* @internal */
// When options come from a config file, its path is recorded here
configFilePath?: string;
/* @internal */
// Path used to used to compute primary search locations
typesRoot?: string;
target?: ScriptTarget;
traceResolution?: boolean;
types?: string[];
/* @internal */ typesRoot?: string;
typesSearchPaths?: string[];
/* @internal */ useLegacyEmitter?: boolean;
/*@internal*/ version?: boolean;
/*@internal*/ watch?: boolean;
list?: string[];
[option: string]: CompilerOptionsValue | undefined;
}
+12 -12
View File
@@ -424,6 +424,11 @@ namespace ts {
((<ModuleDeclaration>node).name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(<ModuleDeclaration>node));
}
export function isShorthandAmbientModule(node: Node): boolean {
// The only kind of module that can be missing a body is a shorthand ambient module.
return node.kind === SyntaxKind.ModuleDeclaration && (!(<ModuleDeclaration>node).body);
}
export function isBlockScopedContainerTopLevel(node: Node): boolean {
return node.kind === SyntaxKind.SourceFile ||
node.kind === SyntaxKind.ModuleDeclaration ||
@@ -685,9 +690,11 @@ namespace ts {
}
export function getJsDocCommentsFromText(node: Node, text: string) {
const commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter) ?
concatenate(getTrailingCommentRanges(text, node.pos),
getLeadingCommentRanges(text, node.pos)) :
const commentRanges = (node.kind === SyntaxKind.Parameter ||
node.kind === SyntaxKind.TypeParameter ||
node.kind === SyntaxKind.FunctionExpression ||
node.kind === SyntaxKind.ArrowFunction) ?
concatenate(getTrailingCommentRanges(text, node.pos), getLeadingCommentRanges(text, node.pos)) :
getLeadingCommentRangesOfNodeFromText(node, text);
return filter(commentRanges, isJsDocComment);
@@ -906,6 +913,8 @@ namespace ts {
case SyntaxKind.ConstructorType:
return true;
}
return false;
}
export function introducesArgumentsExoticObject(node: Node) {
@@ -963,15 +972,6 @@ namespace ts {
}
}
export function getContainingFunctionOrModule(node: Node): Node {
while (true) {
node = node.parent;
if (isFunctionLike(node) || node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.SourceFile) {
return node;
}
}
}
export function getContainingClass(node: Node): ClassLikeDeclaration {
while (true) {
node = node.parent;
+1 -1
View File
@@ -154,7 +154,7 @@ class CompilerBaselineRunner extends RunnerBase {
it (`Correct module resolution tracing for ${fileName}`, () => {
if (options.traceResolution) {
Harness.Baseline.runBaseline("Correct sourcemap content for " + fileName, justName.replace(/\.tsx?$/, ".trace.json"), () => {
Harness.Baseline.runBaseline("Correct module resolution tracing for " + fileName, justName.replace(/\.tsx?$/, ".trace.json"), () => {
return JSON.stringify(result.traceResults || [], undefined, 4);
});
}
+20 -16
View File
@@ -746,7 +746,7 @@ namespace FourSlash {
}
const missingItem = { fileName: fileName, start: start, end: end, isWriteAccess: isWriteAccess };
this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(references, undefined, 2)})`);
this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(references)})`);
}
public verifyReferencesCountIs(count: number, localFilesOnly = true) {
@@ -800,7 +800,7 @@ namespace FourSlash {
private testDiagnostics(expected: string, diagnostics: ts.Diagnostic[]) {
const realized = ts.realizeDiagnostics(diagnostics, "\r\n");
const actual = JSON.stringify(realized, undefined, 2);
const actual = stringify(realized);
assert.equal(actual, expected);
}
@@ -875,7 +875,7 @@ namespace FourSlash {
}
if (ranges.length !== references.length) {
this.raiseError("Rename location count does not match result.\n\nExpected: " + JSON.stringify(ranges, undefined, 2) + "\n\nActual:" + JSON.stringify(references, undefined, 2));
this.raiseError("Rename location count does not match result.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + stringify(references));
}
ranges = ranges.sort((r1, r2) => r1.start - r2.start);
@@ -888,7 +888,7 @@ namespace FourSlash {
if (reference.textSpan.start !== range.start ||
ts.textSpanEnd(reference.textSpan) !== range.end) {
this.raiseError("Rename location results do not match.\n\nExpected: " + JSON.stringify(ranges, undefined, 2) + "\n\nActual:" + JSON.stringify(references, undefined, 2));
this.raiseError("Rename location results do not match.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + JSON.stringify(references));
}
}
}
@@ -972,7 +972,7 @@ namespace FourSlash {
}
else {
if (actual) {
this.raiseError(`Expected no signature help, but got "${JSON.stringify(actual, undefined, 2)}"`);
this.raiseError(`Expected no signature help, but got "${stringify(actual)}"`);
}
}
}
@@ -1176,7 +1176,7 @@ namespace FourSlash {
public printCurrentParameterHelp() {
const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
Harness.IO.log(JSON.stringify(help, undefined, 2));
Harness.IO.log(stringify(help));
}
public printCurrentQuickInfo() {
@@ -1218,7 +1218,7 @@ namespace FourSlash {
public printCurrentSignatureHelp() {
const sigHelp = this.getActiveSignatureHelpItem();
Harness.IO.log(JSON.stringify(sigHelp, undefined, 2));
Harness.IO.log(stringify(sigHelp));
}
public printMemberListMembers() {
@@ -1248,7 +1248,7 @@ namespace FourSlash {
public printReferences() {
const references = this.getReferencesAtCaret();
ts.forEach(references, entry => {
Harness.IO.log(JSON.stringify(entry, undefined, 2));
Harness.IO.log(stringify(entry));
});
}
@@ -1745,8 +1745,8 @@ namespace FourSlash {
function jsonMismatchString() {
return Harness.IO.newLine() +
"expected: '" + Harness.IO.newLine() + JSON.stringify(expected, undefined, 2) + "'" + Harness.IO.newLine() +
"actual: '" + Harness.IO.newLine() + JSON.stringify(actual, undefined, 2) + "'";
"expected: '" + Harness.IO.newLine() + stringify(expected) + "'" + Harness.IO.newLine() +
"actual: '" + Harness.IO.newLine() + stringify(actual) + "'";
}
}
@@ -1961,14 +1961,14 @@ namespace FourSlash {
// if there was an explicit match kind specified, then it should be validated.
if (matchKind !== undefined) {
const missingItem = { name: name, kind: kind, searchValue: searchValue, matchKind: matchKind, fileName: fileName, parentName: parentName };
this.raiseError(`verifyNavigationItemsListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(items, undefined, 2)})`);
this.raiseError(`verifyNavigationItemsListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(items)})`);
}
}
public verifyNavigationBar(json: any) {
const items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
if (JSON.stringify(items, replacer) !== JSON.stringify(json)) {
this.raiseError(`verifyNavigationBar failed - expected: ${JSON.stringify(json, undefined, 2)}, got: ${JSON.stringify(items, replacer, 2)}`);
this.raiseError(`verifyNavigationBar failed - expected: ${stringify(json)}, got: ${stringify(items, replacer)}`);
}
// Make the data easier to read.
@@ -2031,7 +2031,7 @@ namespace FourSlash {
}
const missingItem = { fileName: fileName, start: start, end: end, isWriteAccess: isWriteAccess };
this.raiseError(`verifyOccurrencesAtPositionListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(occurrences, undefined, 2)})`);
this.raiseError(`verifyOccurrencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(occurrences)})`);
}
public verifyOccurrencesAtPositionListCount(expectedCount: number) {
@@ -2070,7 +2070,7 @@ namespace FourSlash {
}
const missingItem = { fileName: fileName, start: start, end: end, kind: kind };
this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(documentHighlights, undefined, 2)})`);
this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(documentHighlights)})`);
}
public verifyDocumentHighlightsAtPositionListCount(expectedCount: number, fileNamesToSearch: string[]) {
@@ -2136,9 +2136,9 @@ namespace FourSlash {
}
}
const itemsString = items.map((item) => JSON.stringify({ name: item.name, kind: item.kind }, undefined, 2)).join(",\n");
const itemsString = items.map(item => stringify({ name: item.name, kind: item.kind })).join(",\n");
this.raiseError(`Expected "${JSON.stringify({ name, text, documentation, kind }, undefined, 2)}" to be in list [${itemsString}]`);
this.raiseError(`Expected "${stringify({ name, text, documentation, kind })}" to be in list [${itemsString}]`);
}
private findFile(indexOrName: any) {
@@ -2701,6 +2701,10 @@ ${code}
}
return result;
}
function stringify(data: any, replacer?: (key: string, value: any) => any): string {
return JSON.stringify(data, replacer, 2);
}
}
namespace FourSlashInterface {
+1 -8
View File
@@ -1770,11 +1770,4 @@ namespace Harness {
}
if (Error) (<any>Error).stackTraceLimit = 1;
}
if (Harness.IO.tryEnableSourceMapsForHost && /^development$/i.test(Harness.IO.getEnvironmentVariable("NODE_ENV"))) {
Harness.IO.tryEnableSourceMapsForHost();
}
// TODO: not sure why Utils.evalFile isn't working with this, eventually will concat it like old compiler instead of eval
eval(Harness.tcServicesFile);
}
+1 -1
View File
@@ -244,7 +244,7 @@ class ProjectRunner extends RunnerBase {
mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? Harness.IO.resolvePath(testCase.mapRoot) : testCase.mapRoot,
sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? Harness.IO.resolvePath(testCase.sourceRoot) : testCase.sourceRoot,
module: moduleKind,
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
};
// Set the values specified using json
const optionNameMap: ts.Map<ts.CommandLineOption> = {};
+1 -1
View File
@@ -24,7 +24,7 @@ abstract class RunnerBase {
abstract enumerateTestFiles(): string[];
/** Setup the runner's tests so that they are ready to be executed by the harness
/** Setup the runner's tests so that they are ready to be executed by the harness
* The first test should be a describe/it block that sets up the harness's compiler instance appropriately
*/
public abstract initializeTests(): void;
+2 -1
View File
@@ -1,2 +1,3 @@
/// <reference path="lib.es2016.d.ts" />
/// <reference path="lib.es2017.object.d.ts" />
/// <reference path="lib.es2017.object.d.ts" />
/// <reference path="lib.es2017.sharedmemory.d.ts" />
+27
View File
@@ -0,0 +1,27 @@
/// <reference path="lib.es2015.symbol.d.ts" />
/// <reference path="lib.es2015.symbol.wellknown.d.ts" />
interface SharedArrayBuffer {
/**
* Read-only. The length of the ArrayBuffer (in bytes).
*/
readonly byteLength: number;
/*
* The SharedArrayBuffer constructor's length property whose value is 1.
*/
length: number;
/**
* Returns a section of an SharedArrayBuffer.
*/
slice(begin:number, end?:number): SharedArrayBuffer;
readonly [Symbol.species]: SharedArrayBuffer;
readonly [Symbol.toStringTag]: "SharedArrayBuffer";
}
interface SharedArrayBufferConstructor {
readonly prototype: SharedArrayBuffer;
new (byteLength: number): SharedArrayBuffer;
}
declare var SharedArrayBuffer: SharedArrayBufferConstructor;
+13 -1
View File
@@ -136,12 +136,24 @@ interface ObjectConstructor {
*/
getOwnPropertyNames(o: any): string[];
/**
* Creates an object that has null prototype.
* @param o Object to use as a prototype. May be null
*/
create(o: null): any;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
*/
create<T>(o: T): T;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
* @param properties JavaScript object that contains one or more property descriptors.
*/
create(o: any, properties?: PropertyDescriptorMap): any;
create(o: any, properties: PropertyDescriptorMap): any;
/**
* Adds a property to an object, or modifies attributes of an existing property.
+1 -1
View File
@@ -459,7 +459,7 @@ namespace ts.server {
kindModifiers: item.kindModifiers || "",
spans: item.spans.map(span => createTextSpanFromBounds(this.lineOffsetToPosition(fileName, span.start), this.lineOffsetToPosition(fileName, span.end))),
childItems: this.decodeNavigationBarItems(item.childItems, fileName),
indent: 0,
indent: item.indent,
bolded: false,
grayed: false
}));
+1 -1
View File
@@ -268,7 +268,7 @@ namespace ts.server {
}
removeRoot(info: ScriptInfo) {
if (!this.filenameToScript.contains(info.path)) {
if (this.filenameToScript.contains(info.path)) {
this.filenameToScript.remove(info.path);
this.roots = copyListRemovingItem(info, this.roots);
this.resolvedModuleNames.remove(info.path);
+5
View File
@@ -1242,6 +1242,11 @@ declare namespace ts.server.protocol {
* Optional children.
*/
childItems?: NavigationBarItem[];
/**
* Number of levels deep this item should appear.
*/
indent: number;
}
export interface NavBarResponse extends Response {
+7 -2
View File
@@ -872,7 +872,8 @@ namespace ts.server {
start: compilerService.host.positionToLineOffset(fileName, span.start),
end: compilerService.host.positionToLineOffset(fileName, ts.textSpanEnd(span))
})),
childItems: this.decorateNavigationBarItem(project, fileName, item.childItems)
childItems: this.decorateNavigationBarItem(project, fileName, item.childItems),
indent: item.indent
}));
}
@@ -1206,7 +1207,11 @@ namespace ts.server {
// Handle cancellation exceptions
}
this.logError(err, message);
this.output(undefined, request ? request.command : CommandNames.Unknown, request ? request.seq : 0, "Error processing request. " + err.message);
this.output(
undefined,
request ? request.command : CommandNames.Unknown,
request ? request.seq : 0,
"Error processing request. " + (<StackTraceError>err).message + "\n" + (<StackTraceError>err).stack);
}
}
}
+2 -2
View File
@@ -722,5 +722,5 @@ namespace ts.BreakpointResolver {
return spanInNode(node.parent);
}
}
}
}
}
}
+2 -2
View File
@@ -268,9 +268,9 @@ namespace ts.formatting {
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
}
// when containing node in the tree is token
// when containing node in the tree is token
// but its kind differs from the kind that was returned by the scanner,
// then kind needs to be fixed. This might happen in cases
// then kind needs to be fixed. This might happen in cases
// when parser interprets token differently, i.e keyword treated as identifier
function fixTokenKind(tokenInfo: TokenInfo, container: Node): TokenInfo {
if (isToken(container) && tokenInfo.token.kind !== container.kind) {
+2 -2
View File
@@ -95,9 +95,9 @@ namespace ts.formatting {
//// 4- Context rules with any token combination
//// 5- Non-context rules with specific token combination
//// 6- Non-context rules with any token combination
////
////
//// The member rulesInsertionIndexBitmap is used to describe the number of rules
//// in each sub-bucket (above) hence can be used to know the index of where to insert
//// in each sub-bucket (above) hence can be used to know the index of where to insert
//// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits.
////
//// Example:
+3 -3
View File
@@ -9,7 +9,7 @@ namespace ts.NavigateTo {
// This means "compare in a case insensitive manner."
const baseSensitivity: Intl.CollatorOptions = { sensitivity: "base" };
// Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
// Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
forEach(program.getSourceFiles(), sourceFile => {
cancellationToken.throwIfCancellationRequested();
@@ -17,7 +17,7 @@ namespace ts.NavigateTo {
for (const name in nameToDeclarations) {
const declarations = getProperty(nameToDeclarations, name);
if (declarations) {
// First do a quick check to see if the name of the declaration matches the
// First do a quick check to see if the name of the declaration matches the
// last portion of the (possibly) dotted name they're searching for.
let matches = patternMatcher.getMatchesForLastSegmentOfPattern(name);
@@ -26,7 +26,7 @@ namespace ts.NavigateTo {
}
for (const declaration of declarations) {
// It was a match! If the pattern has dots in it, then also see if the
// It was a match! If the pattern has dots in it, then also see if the
// declaration container matches as well.
if (patternMatcher.patternContainsDots) {
const containers = getContainers(declaration);
+7 -3
View File
@@ -188,7 +188,10 @@ namespace ts.NavigationBar {
case SyntaxKind.ModuleDeclaration:
let moduleDeclaration = <ModuleDeclaration>node;
topLevelNodes.push(node);
addTopLevelNodes((<Block>getInnermostModule(moduleDeclaration).body).statements, topLevelNodes);
const inner = getInnermostModule(moduleDeclaration);
if (inner.body) {
addTopLevelNodes((<Block>inner.body).statements, topLevelNodes);
}
break;
case SyntaxKind.FunctionDeclaration:
@@ -453,7 +456,8 @@ namespace ts.NavigationBar {
function createModuleItem(node: ModuleDeclaration): NavigationBarItem {
const moduleName = getModuleName(node);
const childItems = getItemsWorker(getChildNodes((<Block>getInnermostModule(node).body).statements), createChildItem);
const body = <Block>getInnermostModule(node).body;
const childItems = body ? getItemsWorker(getChildNodes(body.statements), createChildItem) : [];
return getNavigationBarItem(moduleName,
ts.ScriptElementKind.moduleElement,
@@ -611,7 +615,7 @@ namespace ts.NavigationBar {
}
function getInnermostModule(node: ModuleDeclaration): ModuleDeclaration {
while (node.body.kind === SyntaxKind.ModuleDeclaration) {
while (node.body && node.body.kind === SyntaxKind.ModuleDeclaration) {
node = <ModuleDeclaration>node.body;
}
+192 -37
View File
@@ -412,37 +412,56 @@ namespace ts {
const sourceFileOfDeclaration = getSourceFileOfNode(declaration);
// If it is parameter - try and get the jsDoc comment with @param tag from function declaration's jsDoc comments
if (canUseParsedParamTagComments && declaration.kind === SyntaxKind.Parameter) {
ts.forEach(getJsDocCommentTextRange(declaration.parent, sourceFileOfDeclaration), jsDocCommentTextRange => {
const cleanedParamJsDocComment = getCleanedParamJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
if (cleanedParamJsDocComment) {
addRange(jsDocCommentParts, cleanedParamJsDocComment);
}
});
if ((declaration.parent.kind === SyntaxKind.FunctionExpression || declaration.parent.kind === SyntaxKind.ArrowFunction) &&
declaration.parent.parent.kind === SyntaxKind.VariableDeclaration) {
addCommentParts(declaration.parent.parent.parent, sourceFileOfDeclaration, getCleanedParamJsDocComment);
}
addCommentParts(declaration.parent, sourceFileOfDeclaration, getCleanedParamJsDocComment);
}
// If this is left side of dotted module declaration, there is no doc comments associated with this node
if (declaration.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>declaration).body.kind === SyntaxKind.ModuleDeclaration) {
if (declaration.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>declaration).body && (<ModuleDeclaration>declaration).body.kind === SyntaxKind.ModuleDeclaration) {
return;
}
if ((declaration.kind === SyntaxKind.FunctionExpression || declaration.kind === SyntaxKind.ArrowFunction) &&
declaration.parent.kind === SyntaxKind.VariableDeclaration) {
addCommentParts(declaration.parent.parent, sourceFileOfDeclaration, getCleanedJsDocComment);
}
// If this is dotted module name, get the doc comments from the parent
while (declaration.kind === SyntaxKind.ModuleDeclaration && declaration.parent.kind === SyntaxKind.ModuleDeclaration) {
declaration = <ModuleDeclaration>declaration.parent;
}
addCommentParts(declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent.parent : declaration,
sourceFileOfDeclaration,
getCleanedJsDocComment);
// Get the cleaned js doc comment text from the declaration
ts.forEach(getJsDocCommentTextRange(
declaration.kind === SyntaxKind.VariableDeclaration ? declaration.parent.parent : declaration, sourceFileOfDeclaration), jsDocCommentTextRange => {
const cleanedJsDocComment = getCleanedJsDocComment(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
if (cleanedJsDocComment) {
addRange(jsDocCommentParts, cleanedJsDocComment);
}
});
if (declaration.kind === SyntaxKind.VariableDeclaration) {
const init = (declaration as VariableDeclaration).initializer;
if (init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction)) {
// Get the cleaned js doc comment text from the initializer
addCommentParts(init, sourceFileOfDeclaration, getCleanedJsDocComment);
}
}
}
});
return jsDocCommentParts;
function addCommentParts(commented: Node,
sourceFileOfDeclaration: SourceFile,
getCommentPart: (pos: number, end: number, file: SourceFile) => SymbolDisplayPart[]): void {
const ranges = getJsDocCommentTextRange(commented, sourceFileOfDeclaration);
// Get the cleaned js doc comment text from the declaration
ts.forEach(ranges, jsDocCommentTextRange => {
const cleanedComment = getCommentPart(jsDocCommentTextRange.pos, jsDocCommentTextRange.end, sourceFileOfDeclaration);
if (cleanedComment) {
addRange(jsDocCommentParts, cleanedComment);
}
});
}
function getJsDocCommentTextRange(node: Node, sourceFile: SourceFile): TextRange[] {
return ts.map(getJsDocComments(node, sourceFile),
jsDocComment => {
@@ -1051,10 +1070,10 @@ namespace ts {
getCancellationToken?(): HostCancellationToken;
getCurrentDirectory(): string;
getDefaultLibFileName(options: CompilerOptions): string;
log? (s: string): void;
trace? (s: string): void;
error? (s: string): void;
useCaseSensitiveFileNames? (): boolean;
log?(s: string): void;
trace?(s: string): void;
error?(s: string): void;
useCaseSensitiveFileNames?(): boolean;
/*
* LS host can optionally implement this method if it wants to be completely in charge of module name resolution.
@@ -1926,6 +1945,46 @@ namespace ts {
sourceMapText?: string;
}
let commandLineOptionsStringToEnum: CommandLineOptionOfCustomType[];
/**
* Convert an option's string name of enum-value in compiler-options, "options", into its corresponding enum value if possible.
* This is necessary because JS users may pass in string values for enum compiler options (e.g. ModuleKind).
*
* @param options a compiler-options used in transpilation which can contain string value to specify instead of enum values
* @param diagnostics a list of Diagnostic which occur during conversion (e.g invalid option's value)
*/
function ConvertStringForEnumNameInCompilerOptionsToEnumValue(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions {
// Lazily create this value to fix module loading errors.
commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || <CommandLineOptionOfCustomType[]>filter(optionDeclarations, o =>
typeof o.type === "object" && !forEachValue(<Map<number | string>> o.type, v => typeof v !== "number"));
options = clone(options);
for (const opt of commandLineOptionsStringToEnum) {
if (!hasProperty(options, opt.name)) {
continue;
}
const value = options[opt.name];
// Value should be a key of opt.type
if (typeof value === "string") {
// If value is not a string, this will fail
options[opt.name] = parseCustomTypeOption(opt, value, diagnostics);
}
else {
if (!forEachValue(opt.type, v => v === value)) {
// Supplied value isn't a valid enum value.
diagnostics.push(createCompilerDiagnosticForInvalidCustomType(opt));
}
}
}
return options;
}
/*
* This function will compile source text from 'input' argument using specified compiler options.
* If not options are provided - it will use a set of default compiler options.
@@ -1936,7 +1995,9 @@ namespace ts {
* - noResolve = true
*/
export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput {
const options = transpileOptions.compilerOptions ? clone(transpileOptions.compilerOptions) : getDefaultCompilerOptions();
const diagnostics: Diagnostic[] = [];
const options: CompilerOptions = transpileOptions.compilerOptions ? ConvertStringForEnumNameInCompilerOptionsToEnumValue(transpileOptions.compilerOptions, diagnostics) : getDefaultCompilerOptions();
options.isolatedModules = true;
@@ -1992,13 +2053,16 @@ namespace ts {
directoryExists: directoryExists => true
};
// If there is an error from converting string in compiler-options to its corresponding enum value,
// do not proceed and return and an error;
if (diagnostics.length > 0) {
return { outputText: undefined, diagnostics, sourceMapText };
}
const program = createProgram([inputFileName], options, compilerHost);
let diagnostics: Diagnostic[];
if (transpileOptions.reportDiagnostics) {
diagnostics = [];
addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile));
addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics());
}
// Emit
program.emit();
@@ -2486,7 +2550,7 @@ namespace ts {
}
// should be start of dependency list
if (token !== SyntaxKind.OpenBracketToken) {
if (token !== SyntaxKind.OpenBracketToken) {
return true;
}
@@ -2663,7 +2727,7 @@ namespace ts {
return false;
}
/**
/**
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
*/
function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement {
@@ -2925,6 +2989,7 @@ namespace ts {
const changesInCompilationSettingsAffectSyntax = oldSettings &&
(oldSettings.target !== newSettings.target ||
oldSettings.module !== newSettings.module ||
oldSettings.moduleResolution !== newSettings.moduleResolution ||
oldSettings.noResolve !== newSettings.noResolve ||
oldSettings.jsx !== newSettings.jsx ||
oldSettings.allowJs !== newSettings.allowJs);
@@ -4018,10 +4083,15 @@ namespace ts {
}
}
function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo {
synchronizeHostData();
const sourceFile = getValidSourceFile(fileName);
if (isInString(sourceFile, position)) {
return getStringLiteralCompletionEntries(sourceFile, position);
}
const completionData = getCompletionData(fileName, position);
if (!completionData) {
return undefined;
@@ -4034,12 +4104,10 @@ namespace ts {
return { isMemberCompletion: false, isNewIdentifierLocation: false, entries: getAllJsDocCompletionEntries() };
}
const sourceFile = getValidSourceFile(fileName);
const entries: CompletionEntry[] = [];
if (isSourceFileJavaScript(sourceFile)) {
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries);
const uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ false);
addRange(entries, getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames));
}
else {
@@ -4063,7 +4131,7 @@ namespace ts {
}
}
getCompletionEntriesFromSymbols(symbols, entries);
getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true);
}
// Add keywords if this is not a member completion list
@@ -4113,11 +4181,11 @@ namespace ts {
}));
}
function createCompletionEntry(symbol: Symbol, location: Node): CompletionEntry {
function createCompletionEntry(symbol: Symbol, location: Node, performCharacterChecks: boolean): CompletionEntry {
// Try to get a valid display name for this symbol, if we could not find one, then ignore it.
// We would like to only show things that can be added after a dot, so for instance numeric properties can
// not be accessed with a dot (a.1 <- invalid)
const displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, /*performCharacterChecks*/ true, location);
const displayName = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, performCharacterChecks, location);
if (!displayName) {
return undefined;
}
@@ -4138,12 +4206,12 @@ namespace ts {
};
}
function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[]): Map<string> {
function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[], location: Node, performCharacterChecks: boolean): Map<string> {
const start = new Date().getTime();
const uniqueNames: Map<string> = {};
if (symbols) {
for (const symbol of symbols) {
const entry = createCompletionEntry(symbol, location);
const entry = createCompletionEntry(symbol, location, performCharacterChecks);
if (entry) {
const id = escapeIdentifier(entry.name);
if (!lookUp(uniqueNames, id)) {
@@ -4157,6 +4225,93 @@ namespace ts {
log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (new Date().getTime() - start));
return uniqueNames;
}
function getStringLiteralCompletionEntries(sourceFile: SourceFile, position: number) {
const node = findPrecedingToken(position, sourceFile);
if (!node || node.kind !== SyntaxKind.StringLiteral) {
return undefined;
}
const argumentInfo = SignatureHelp.getContainingArgumentInfo(node, position, sourceFile);
if (argumentInfo) {
// Get string literal completions from specialized signatures of the target
return getStringLiteralCompletionEntriesFromCallExpression(argumentInfo);
}
else if (isElementAccessExpression(node.parent) && node.parent.argumentExpression === node) {
// Get all names of properties on the expression
return getStringLiteralCompletionEntriesFromElementAccess(node.parent);
}
else {
// Otherwise, get the completions from the contextual type if one exists
return getStringLiteralCompletionEntriesFromContextualType(<StringLiteral>node);
}
}
function getStringLiteralCompletionEntriesFromCallExpression(argumentInfo: SignatureHelp.ArgumentListInfo) {
const typeChecker = program.getTypeChecker();
const candidates: Signature[] = [];
const entries: CompletionEntry[] = [];
typeChecker.getResolvedSignature(argumentInfo.invocation, candidates);
for (const candidate of candidates) {
if (candidate.parameters.length > argumentInfo.argumentIndex) {
const parameter = candidate.parameters[argumentInfo.argumentIndex];
addStringLiteralCompletionsFromType(typeChecker.getTypeAtLocation(parameter.valueDeclaration), entries);
}
}
if (entries.length) {
return { isMemberCompletion: false, isNewIdentifierLocation: true, entries };
}
return undefined;
}
function getStringLiteralCompletionEntriesFromElementAccess(node: ElementAccessExpression) {
const typeChecker = program.getTypeChecker();
const type = typeChecker.getTypeAtLocation(node.expression);
const entries: CompletionEntry[] = [];
if (type) {
getCompletionEntriesFromSymbols(type.getApparentProperties(), entries, node, /*performCharacterChecks*/false);
if (entries.length) {
return { isMemberCompletion: true, isNewIdentifierLocation: true, entries };
}
}
return undefined;
}
function getStringLiteralCompletionEntriesFromContextualType(node: StringLiteral) {
const typeChecker = program.getTypeChecker();
const type = typeChecker.getContextualType(node);
if (type) {
const entries: CompletionEntry[] = [];
addStringLiteralCompletionsFromType(type, entries);
if (entries.length) {
return { isMemberCompletion: false, isNewIdentifierLocation: false, entries };
}
}
return undefined;
}
function addStringLiteralCompletionsFromType(type: Type, result: CompletionEntry[]): void {
if (!type) {
return;
}
if (type.flags & TypeFlags.Union) {
forEach((<UnionType>type).types, t => addStringLiteralCompletionsFromType(t, result));
}
else {
if (type.flags & TypeFlags.StringLiteral) {
result.push({
name: (<StringLiteralType>type).text,
kindModifiers: ScriptElementKindModifier.none,
kind: ScriptElementKind.variableElement,
sortText: "0"
});
}
}
}
}
function getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails {
@@ -4321,7 +4476,7 @@ namespace ts {
// try get the call/construct signature from the type if it matches
let callExpression: CallExpression;
if (location.kind === SyntaxKind.CallExpression || location.kind === SyntaxKind.NewExpression) {
callExpression = <CallExpression> location;
callExpression = <CallExpression>location;
}
else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) {
callExpression = <CallExpression>location.parent;
@@ -7610,11 +7765,11 @@ namespace ts {
function isValidBraceCompletionAtPostion(fileName: string, position: number, openingBrace: number): boolean {
// '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too
// '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too
// expensive to do during typing scenarios
// i.e. whether we're dealing with:
// var x = new foo<| ( with class foo<T>{} )
// or
// or
// var y = 3 <|
if (openingBrace === CharacterCodes.lessThan) {
return false;
+2 -2
View File
@@ -295,7 +295,7 @@ namespace ts {
constructor(private shimHost: LanguageServiceShimHost) {
// if shimHost is a COM object then property check will become method call with no arguments.
// 'in' does not have this effect.
// 'in' does not have this effect.
if ("getModuleResolutionsForFile" in this.shimHost) {
this.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
@@ -966,7 +966,7 @@ namespace ts {
return this.forwardJSONCall(
"getPreProcessedFileInfo('" + fileName + "')",
() => {
// for now treat files as JavaScript
// for now treat files as JavaScript
const result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true);
return {
referencedFiles: this.convertFileReferences(result.referencedFiles),
+383 -380
View File
@@ -3,9 +3,9 @@
namespace ts.SignatureHelp {
// A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
// looking up the type. The method will also keep track of the parameter index inside the expression.
// public static isInPartiallyWrittenTypeArgumentList(syntaxTree: TypeScript.SyntaxTree, position: number): any {
// let token = Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, /*includeSkippedTokens*/ true);
@@ -162,15 +162,16 @@ namespace ts.SignatureHelp {
// // Did not find matching token
// return null;
// }
const emptyArray: any[] = [];
const enum ArgumentListKind {
export const enum ArgumentListKind {
TypeArguments,
CallArguments,
TaggedTemplateArguments
}
interface ArgumentListInfo {
export interface ArgumentListInfo {
kind: ArgumentListKind;
invocation: CallLikeExpression;
argumentsSpan: TextSpan;
@@ -188,7 +189,8 @@ namespace ts.SignatureHelp {
return undefined;
}
const argumentInfo = getContainingArgumentInfo(startingToken);
const argumentInfo = getContainingArgumentInfo(startingToken, position, sourceFile);
cancellationToken.throwIfCancellationRequested();
// Semantic filtering of signature help
@@ -202,434 +204,435 @@ namespace ts.SignatureHelp {
cancellationToken.throwIfCancellationRequested();
if (!candidates.length) {
// We didn't have any sig help items produced by the TS compiler. If this is a JS
// We didn't have any sig help items produced by the TS compiler. If this is a JS
// file, then see if we can figure out anything better.
if (isSourceFileJavaScript(sourceFile)) {
return createJavaScriptSignatureHelpItems(argumentInfo);
return createJavaScriptSignatureHelpItems(argumentInfo, program);
}
return undefined;
}
return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo);
return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo, typeChecker);
}
function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo): SignatureHelpItems {
if (argumentInfo.invocation.kind !== SyntaxKind.CallExpression) {
return undefined;
}
function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program): SignatureHelpItems {
if (argumentInfo.invocation.kind !== SyntaxKind.CallExpression) {
return undefined;
}
// See if we can find some symbol with the call expression name that has call signatures.
const callExpression = <CallExpression>argumentInfo.invocation;
const expression = callExpression.expression;
const name = expression.kind === SyntaxKind.Identifier
? <Identifier> expression
: expression.kind === SyntaxKind.PropertyAccessExpression
? (<PropertyAccessExpression>expression).name
: undefined;
// See if we can find some symbol with the call expression name that has call signatures.
const callExpression = <CallExpression>argumentInfo.invocation;
const expression = callExpression.expression;
const name = expression.kind === SyntaxKind.Identifier
? <Identifier>expression
: expression.kind === SyntaxKind.PropertyAccessExpression
? (<PropertyAccessExpression>expression).name
: undefined;
if (!name || !name.text) {
return undefined;
}
if (!name || !name.text) {
return undefined;
}
const typeChecker = program.getTypeChecker();
for (const sourceFile of program.getSourceFiles()) {
const nameToDeclarations = sourceFile.getNamedDeclarations();
const declarations = getProperty(nameToDeclarations, name.text);
const typeChecker = program.getTypeChecker();
for (const sourceFile of program.getSourceFiles()) {
const nameToDeclarations = sourceFile.getNamedDeclarations();
const declarations = getProperty(nameToDeclarations, name.text);
if (declarations) {
for (const declaration of declarations) {
const symbol = declaration.symbol;
if (symbol) {
const type = typeChecker.getTypeOfSymbolAtLocation(symbol, declaration);
if (type) {
const callSignatures = type.getCallSignatures();
if (callSignatures && callSignatures.length) {
return createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo);
}
if (declarations) {
for (const declaration of declarations) {
const symbol = declaration.symbol;
if (symbol) {
const type = typeChecker.getTypeOfSymbolAtLocation(symbol, declaration);
if (type) {
const callSignatures = type.getCallSignatures();
if (callSignatures && callSignatures.length) {
return createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo, typeChecker);
}
}
}
}
}
}
}
/**
* Returns relevant information for the argument list and the current argument if we are
* in the argument of an invocation; returns undefined otherwise.
*/
function getImmediatelyContainingArgumentInfo(node: Node): ArgumentListInfo {
if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) {
const callExpression = <CallExpression>node.parent;
// There are 3 cases to handle:
// 1. The token introduces a list, and should begin a sig help session
// 2. The token is either not associated with a list, or ends a list, so the session should end
// 3. The token is buried inside a list, and should give sig help
//
// The following are examples of each:
//
// Case 1:
// foo<#T, U>(#a, b) -> The token introduces a list, and should begin a sig help session
// Case 2:
// fo#o<T, U>#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end
// Case 3:
// foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give sig help
// Find out if 'node' is an argument, a type argument, or neither
if (node.kind === SyntaxKind.LessThanToken ||
node.kind === SyntaxKind.OpenParenToken) {
// Find the list that starts right *after* the < or ( token.
// If the user has just opened a list, consider this item 0.
const list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
const isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
Debug.assert(list !== undefined);
return {
kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
invocation: callExpression,
argumentsSpan: getApplicableSpanForArguments(list),
argumentIndex: 0,
argumentCount: getArgumentCount(list)
};
}
// findListItemInfo can return undefined if we are not in parent's argument list
// or type argument list. This includes cases where the cursor is:
// - To the right of the closing paren, non-substitution template, or template tail.
// - Between the type arguments and the arguments (greater than token)
// - On the target of the call (parent.func)
// - On the 'new' keyword in a 'new' expression
const listItemInfo = findListItemInfo(node);
if (listItemInfo) {
const list = listItemInfo.list;
const isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
const argumentIndex = getArgumentIndex(list, node);
const argumentCount = getArgumentCount(list);
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount,
`argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
return {
kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
invocation: callExpression,
argumentsSpan: getApplicableSpanForArguments(list),
argumentIndex: argumentIndex,
argumentCount: argumentCount
};
}
}
else if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && node.parent.kind === SyntaxKind.TaggedTemplateExpression) {
// Check if we're actually inside the template;
// otherwise we'll fall out and return undefined.
if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
return getArgumentListInfoForTemplate(<TaggedTemplateExpression>node.parent, /*argumentIndex*/ 0);
}
}
else if (node.kind === SyntaxKind.TemplateHead && node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
const templateExpression = <TemplateExpression>node.parent;
const tagExpression = <TaggedTemplateExpression>templateExpression.parent;
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
const argumentIndex = isInsideTemplateLiteral(<LiteralExpression>node, position) ? 0 : 1;
return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
}
else if (node.parent.kind === SyntaxKind.TemplateSpan && node.parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
const templateSpan = <TemplateSpan>node.parent;
const templateExpression = <TemplateExpression>templateSpan.parent;
const tagExpression = <TaggedTemplateExpression>templateExpression.parent;
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
// If we're just after a template tail, don't show signature help.
if (node.kind === SyntaxKind.TemplateTail && !isInsideTemplateLiteral(<LiteralExpression>node, position)) {
return undefined;
}
const spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
const argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node);
return getArgumentListInfoForTemplate(tagExpression, argumentIndex);
}
return undefined;
}
function getArgumentIndex(argumentsList: Node, node: Node) {
// The list we got back can include commas. In the presence of errors it may
// also just have nodes without commas. For example "Foo(a b c)" will have 3
// args without commas. We want to find what index we're at. So we count
// forward until we hit ourselves, only incrementing the index if it isn't a
// comma.
/**
* Returns relevant information for the argument list and the current argument if we are
* in the argument of an invocation; returns undefined otherwise.
*/
function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo {
if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) {
const callExpression = <CallExpression>node.parent;
// There are 3 cases to handle:
// 1. The token introduces a list, and should begin a sig help session
// 2. The token is either not associated with a list, or ends a list, so the session should end
// 3. The token is buried inside a list, and should give sig help
//
// Note: the subtlety around trailing commas (in getArgumentCount) does not apply
// here. That's because we're only walking forward until we hit the node we're
// on. In that case, even if we're after the trailing comma, we'll still see
// that trailing comma in the list, and we'll have generated the appropriate
// arg index.
let argumentIndex = 0;
const listChildren = argumentsList.getChildren();
for (const child of listChildren) {
if (child === node) {
break;
}
if (child.kind !== SyntaxKind.CommaToken) {
argumentIndex++;
}
// The following are examples of each:
//
// Case 1:
// foo<#T, U>(#a, b) -> The token introduces a list, and should begin a sig help session
// Case 2:
// fo#o<T, U>#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end
// Case 3:
// foo<T#, U#>(a#, #b#) -> The token is buried inside a list, and should give sig help
// Find out if 'node' is an argument, a type argument, or neither
if (node.kind === SyntaxKind.LessThanToken ||
node.kind === SyntaxKind.OpenParenToken) {
// Find the list that starts right *after* the < or ( token.
// If the user has just opened a list, consider this item 0.
const list = getChildListThatStartsWithOpenerToken(callExpression, node, sourceFile);
const isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
Debug.assert(list !== undefined);
return {
kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
invocation: callExpression,
argumentsSpan: getApplicableSpanForArguments(list, sourceFile),
argumentIndex: 0,
argumentCount: getArgumentCount(list)
};
}
return argumentIndex;
}
// findListItemInfo can return undefined if we are not in parent's argument list
// or type argument list. This includes cases where the cursor is:
// - To the right of the closing paren, non-substitution template, or template tail.
// - Between the type arguments and the arguments (greater than token)
// - On the target of the call (parent.func)
// - On the 'new' keyword in a 'new' expression
const listItemInfo = findListItemInfo(node);
if (listItemInfo) {
const list = listItemInfo.list;
const isTypeArgList = callExpression.typeArguments && callExpression.typeArguments.pos === list.pos;
function getArgumentCount(argumentsList: Node) {
// The argument count for a list is normally the number of non-comma children it has.
// For example, if you have "Foo(a,b)" then there will be three children of the arg
// list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
// is a small subtlety. If you have "Foo(a,)", then the child list will just have
// 'a' '<comma>'. So, in the case where the last child is a comma, we increase the
// arg count by one to compensate.
//
// Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
// we'll have: 'a' '<comma>' '<missing>'
// That will give us 2 non-commas. We then add one for the last comma, givin us an
// arg count of 3.
const listChildren = argumentsList.getChildren();
const argumentIndex = getArgumentIndex(list, node);
const argumentCount = getArgumentCount(list);
let argumentCount = countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken);
if (listChildren.length > 0 && lastOrUndefined(listChildren).kind === SyntaxKind.CommaToken) {
argumentCount++;
}
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount,
`argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
return argumentCount;
}
// spanIndex is either the index for a given template span.
// This does not give appropriate results for a NoSubstitutionTemplateLiteral
function getArgumentIndexForTemplatePiece(spanIndex: number, node: Node): number {
// Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1.
// There are three cases we can encounter:
// 1. We are precisely in the template literal (argIndex = 0).
// 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1).
// 3. We are directly to the right of the template literal, but because we look for the token on the left,
// not enough to put us in the substitution expression; we should consider ourselves part of
// the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1).
//
// Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # `
// ^ ^ ^ ^ ^ ^ ^ ^ ^
// Case: 1 1 3 2 1 3 2 2 1
Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
if (isTemplateLiteralKind(node.kind)) {
if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
return 0;
}
return spanIndex + 2;
}
return spanIndex + 1;
}
function getArgumentListInfoForTemplate(tagExpression: TaggedTemplateExpression, argumentIndex: number): ArgumentListInfo {
// argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument.
const argumentCount = tagExpression.template.kind === SyntaxKind.NoSubstitutionTemplateLiteral
? 1
: (<TemplateExpression>tagExpression.template).templateSpans.length + 1;
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
return {
kind: ArgumentListKind.TaggedTemplateArguments,
invocation: tagExpression,
argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression),
argumentIndex: argumentIndex,
argumentCount: argumentCount
};
}
function getApplicableSpanForArguments(argumentsList: Node): TextSpan {
// We use full start and skip trivia on the end because we want to include trivia on
// both sides. For example,
//
// foo( /*comment */ a, b, c /*comment*/ )
// | |
//
// The applicable span is from the first bar to the second bar (inclusive,
// but not including parentheses)
const applicableSpanStart = argumentsList.getFullStart();
const applicableSpanEnd = skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false);
return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
}
function getApplicableSpanForTaggedTemplate(taggedTemplate: TaggedTemplateExpression): TextSpan {
const template = taggedTemplate.template;
const applicableSpanStart = template.getStart();
let applicableSpanEnd = template.getEnd();
// We need to adjust the end position for the case where the template does not have a tail.
// Otherwise, we will not show signature help past the expression.
// For example,
//
// ` ${ 1 + 1 foo(10)
// | |
//
// This is because a Missing node has no width. However, what we actually want is to include trivia
// leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
if (template.kind === SyntaxKind.TemplateExpression) {
const lastSpan = lastOrUndefined((<TemplateExpression>template).templateSpans);
if (lastSpan.literal.getFullWidth() === 0) {
applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
}
}
return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
}
function getContainingArgumentInfo(node: Node): ArgumentListInfo {
for (let n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) {
if (isFunctionBlock(n)) {
return undefined;
}
// If the node is not a subspan of its parent, this is a big problem.
// There have been crashes that might be caused by this violation.
if (n.pos < n.parent.pos || n.end > n.parent.end) {
Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind);
}
const argumentInfo = getImmediatelyContainingArgumentInfo(n);
if (argumentInfo) {
return argumentInfo;
}
// TODO: Handle generic call with incomplete syntax
return {
kind: isTypeArgList ? ArgumentListKind.TypeArguments : ArgumentListKind.CallArguments,
invocation: callExpression,
argumentsSpan: getApplicableSpanForArguments(list, sourceFile),
argumentIndex: argumentIndex,
argumentCount: argumentCount
};
}
return undefined;
}
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
const children = parent.getChildren(sourceFile);
const indexOfOpenerToken = children.indexOf(openerToken);
Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
return children[indexOfOpenerToken + 1];
else if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && node.parent.kind === SyntaxKind.TaggedTemplateExpression) {
// Check if we're actually inside the template;
// otherwise we'll fall out and return undefined.
if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
return getArgumentListInfoForTemplate(<TaggedTemplateExpression>node.parent, /*argumentIndex*/ 0, sourceFile);
}
}
else if (node.kind === SyntaxKind.TemplateHead && node.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
const templateExpression = <TemplateExpression>node.parent;
const tagExpression = <TaggedTemplateExpression>templateExpression.parent;
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
/**
* The selectedItemIndex could be negative for several reasons.
* 1. There are too many arguments for all of the overloads
* 2. None of the overloads were type compatible
* The solution here is to try to pick the best overload by picking
* either the first one that has an appropriate number of parameters,
* or the one with the most parameters.
*/
function selectBestInvalidOverloadIndex(candidates: Signature[], argumentCount: number): number {
let maxParamsSignatureIndex = -1;
let maxParams = -1;
for (let i = 0; i < candidates.length; i++) {
const candidate = candidates[i];
const argumentIndex = isInsideTemplateLiteral(<LiteralExpression>node, position) ? 0 : 1;
if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) {
return i;
}
return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile);
}
else if (node.parent.kind === SyntaxKind.TemplateSpan && node.parent.parent.parent.kind === SyntaxKind.TaggedTemplateExpression) {
const templateSpan = <TemplateSpan>node.parent;
const templateExpression = <TemplateExpression>templateSpan.parent;
const tagExpression = <TaggedTemplateExpression>templateExpression.parent;
Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression);
if (candidate.parameters.length > maxParams) {
maxParams = candidate.parameters.length;
maxParamsSignatureIndex = i;
}
// If we're just after a template tail, don't show signature help.
if (node.kind === SyntaxKind.TemplateTail && !isInsideTemplateLiteral(<LiteralExpression>node, position)) {
return undefined;
}
return maxParamsSignatureIndex;
const spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
const argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node, position);
return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile);
}
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentListInfo: ArgumentListInfo): SignatureHelpItems {
const applicableSpan = argumentListInfo.argumentsSpan;
const isTypeParameterList = argumentListInfo.kind === ArgumentListKind.TypeArguments;
return undefined;
}
const invocation = argumentListInfo.invocation;
const callTarget = getInvokedExpression(invocation);
const callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget);
const callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined);
const items: SignatureHelpItem[] = map(candidates, candidateSignature => {
let signatureHelpParameters: SignatureHelpParameter[];
const prefixDisplayParts: SymbolDisplayPart[] = [];
const suffixDisplayParts: SymbolDisplayPart[] = [];
function getArgumentIndex(argumentsList: Node, node: Node) {
// The list we got back can include commas. In the presence of errors it may
// also just have nodes without commas. For example "Foo(a b c)" will have 3
// args without commas. We want to find what index we're at. So we count
// forward until we hit ourselves, only incrementing the index if it isn't a
// comma.
//
// Note: the subtlety around trailing commas (in getArgumentCount) does not apply
// here. That's because we're only walking forward until we hit the node we're
// on. In that case, even if we're after the trailing comma, we'll still see
// that trailing comma in the list, and we'll have generated the appropriate
// arg index.
let argumentIndex = 0;
const listChildren = argumentsList.getChildren();
for (const child of listChildren) {
if (child === node) {
break;
}
if (child.kind !== SyntaxKind.CommaToken) {
argumentIndex++;
}
}
if (callTargetDisplayParts) {
addRange(prefixDisplayParts, callTargetDisplayParts);
}
return argumentIndex;
}
if (isTypeParameterList) {
prefixDisplayParts.push(punctuationPart(SyntaxKind.LessThanToken));
const typeParameters = candidateSignature.typeParameters;
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
const parameterParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.thisType, candidateSignature.parameters, writer, invocation));
addRange(suffixDisplayParts, parameterParts);
}
else {
const typeParameterParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation));
addRange(prefixDisplayParts, typeParameterParts);
prefixDisplayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
function getArgumentCount(argumentsList: Node) {
// The argument count for a list is normally the number of non-comma children it has.
// For example, if you have "Foo(a,b)" then there will be three children of the arg
// list 'a' '<comma>' 'b'. So, in this case the arg count will be 2. However, there
// is a small subtlety. If you have "Foo(a,)", then the child list will just have
// 'a' '<comma>'. So, in the case where the last child is a comma, we increase the
// arg count by one to compensate.
//
// Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
// we'll have: 'a' '<comma>' '<missing>'
// That will give us 2 non-commas. We then add one for the last comma, givin us an
// arg count of 3.
const listChildren = argumentsList.getChildren();
const parameters = candidateSignature.parameters;
signatureHelpParameters = parameters.length > 0 ? map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
suffixDisplayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
}
let argumentCount = countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken);
if (listChildren.length > 0 && lastOrUndefined(listChildren).kind === SyntaxKind.CommaToken) {
argumentCount++;
}
const returnTypeParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation));
addRange(suffixDisplayParts, returnTypeParts);
return argumentCount;
}
return {
isVariadic: candidateSignature.hasRestParameter,
prefixDisplayParts,
suffixDisplayParts,
separatorDisplayParts: [punctuationPart(SyntaxKind.CommaToken), spacePart()],
parameters: signatureHelpParameters,
documentation: candidateSignature.getDocumentationComment()
};
});
// spanIndex is either the index for a given template span.
// This does not give appropriate results for a NoSubstitutionTemplateLiteral
function getArgumentIndexForTemplatePiece(spanIndex: number, node: Node, position: number): number {
// Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1.
// There are three cases we can encounter:
// 1. We are precisely in the template literal (argIndex = 0).
// 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1).
// 3. We are directly to the right of the template literal, but because we look for the token on the left,
// not enough to put us in the substitution expression; we should consider ourselves part of
// the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1).
//
// Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # `
// ^ ^ ^ ^ ^ ^ ^ ^ ^
// Case: 1 1 3 2 1 3 2 2 1
Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
if (isTemplateLiteralKind(node.kind)) {
if (isInsideTemplateLiteral(<LiteralExpression>node, position)) {
return 0;
}
return spanIndex + 2;
}
return spanIndex + 1;
}
const argumentIndex = argumentListInfo.argumentIndex;
function getArgumentListInfoForTemplate(tagExpression: TaggedTemplateExpression, argumentIndex: number, sourceFile: SourceFile): ArgumentListInfo {
// argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument.
const argumentCount = tagExpression.template.kind === SyntaxKind.NoSubstitutionTemplateLiteral
? 1
: (<TemplateExpression>tagExpression.template).templateSpans.length + 1;
// argumentCount is the *apparent* number of arguments.
const argumentCount = argumentListInfo.argumentCount;
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
let selectedItemIndex = candidates.indexOf(bestSignature);
if (selectedItemIndex < 0) {
selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount);
return {
kind: ArgumentListKind.TaggedTemplateArguments,
invocation: tagExpression,
argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression, sourceFile),
argumentIndex: argumentIndex,
argumentCount: argumentCount
};
}
function getApplicableSpanForArguments(argumentsList: Node, sourceFile: SourceFile): TextSpan {
// We use full start and skip trivia on the end because we want to include trivia on
// both sides. For example,
//
// foo( /*comment */ a, b, c /*comment*/ )
// | |
//
// The applicable span is from the first bar to the second bar (inclusive,
// but not including parentheses)
const applicableSpanStart = argumentsList.getFullStart();
const applicableSpanEnd = skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false);
return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
}
function getApplicableSpanForTaggedTemplate(taggedTemplate: TaggedTemplateExpression, sourceFile: SourceFile): TextSpan {
const template = taggedTemplate.template;
const applicableSpanStart = template.getStart();
let applicableSpanEnd = template.getEnd();
// We need to adjust the end position for the case where the template does not have a tail.
// Otherwise, we will not show signature help past the expression.
// For example,
//
// ` ${ 1 + 1 foo(10)
// | |
//
// This is because a Missing node has no width. However, what we actually want is to include trivia
// leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
if (template.kind === SyntaxKind.TemplateExpression) {
const lastSpan = lastOrUndefined((<TemplateExpression>template).templateSpans);
if (lastSpan.literal.getFullWidth() === 0) {
applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
}
}
return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
}
export function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo {
for (let n = node; n.kind !== SyntaxKind.SourceFile; n = n.parent) {
if (isFunctionBlock(n)) {
return undefined;
}
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
// If the node is not a subspan of its parent, this is a big problem.
// There have been crashes that might be caused by this violation.
if (n.pos < n.parent.pos || n.end > n.parent.end) {
Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind);
}
const argumentInfo = getImmediatelyContainingArgumentInfo(n, position, sourceFile);
if (argumentInfo) {
return argumentInfo;
}
// TODO: Handle generic call with incomplete syntax
}
return undefined;
}
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
const children = parent.getChildren(sourceFile);
const indexOfOpenerToken = children.indexOf(openerToken);
Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
return children[indexOfOpenerToken + 1];
}
/**
* The selectedItemIndex could be negative for several reasons.
* 1. There are too many arguments for all of the overloads
* 2. None of the overloads were type compatible
* The solution here is to try to pick the best overload by picking
* either the first one that has an appropriate number of parameters,
* or the one with the most parameters.
*/
function selectBestInvalidOverloadIndex(candidates: Signature[], argumentCount: number): number {
let maxParamsSignatureIndex = -1;
let maxParams = -1;
for (let i = 0; i < candidates.length; i++) {
const candidate = candidates[i];
if (candidate.hasRestParameter || candidate.parameters.length >= argumentCount) {
return i;
}
if (candidate.parameters.length > maxParams) {
maxParams = candidate.parameters.length;
maxParamsSignatureIndex = i;
}
}
return maxParamsSignatureIndex;
}
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentListInfo: ArgumentListInfo, typeChecker: TypeChecker): SignatureHelpItems {
const applicableSpan = argumentListInfo.argumentsSpan;
const isTypeParameterList = argumentListInfo.kind === ArgumentListKind.TypeArguments;
const invocation = argumentListInfo.invocation;
const callTarget = getInvokedExpression(invocation);
const callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget);
const callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined);
const items: SignatureHelpItem[] = map(candidates, candidateSignature => {
let signatureHelpParameters: SignatureHelpParameter[];
const prefixDisplayParts: SymbolDisplayPart[] = [];
const suffixDisplayParts: SymbolDisplayPart[] = [];
if (callTargetDisplayParts) {
addRange(prefixDisplayParts, callTargetDisplayParts);
}
if (isTypeParameterList) {
prefixDisplayParts.push(punctuationPart(SyntaxKind.LessThanToken));
const typeParameters = candidateSignature.typeParameters;
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
suffixDisplayParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
const parameterParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.thisType, candidateSignature.parameters, writer, invocation));
addRange(suffixDisplayParts, parameterParts);
}
else {
const typeParameterParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, invocation));
addRange(prefixDisplayParts, typeParameterParts);
prefixDisplayParts.push(punctuationPart(SyntaxKind.OpenParenToken));
const parameters = candidateSignature.parameters;
signatureHelpParameters = parameters.length > 0 ? map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
suffixDisplayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
}
const returnTypeParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, invocation));
addRange(suffixDisplayParts, returnTypeParts);
return {
items,
applicableSpan,
selectedItemIndex,
argumentIndex,
argumentCount
isVariadic: candidateSignature.hasRestParameter,
prefixDisplayParts,
suffixDisplayParts,
separatorDisplayParts: [punctuationPart(SyntaxKind.CommaToken), spacePart()],
parameters: signatureHelpParameters,
documentation: candidateSignature.getDocumentationComment()
};
});
function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter {
const displayParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation));
const argumentIndex = argumentListInfo.argumentIndex;
return {
name: parameter.name,
documentation: parameter.getDocumentationComment(),
displayParts,
isOptional: typeChecker.isOptionalParameter(<ParameterDeclaration>parameter.valueDeclaration)
};
}
// argumentCount is the *apparent* number of arguments.
const argumentCount = argumentListInfo.argumentCount;
function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter {
const displayParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation));
let selectedItemIndex = candidates.indexOf(bestSignature);
if (selectedItemIndex < 0) {
selectedItemIndex = selectBestInvalidOverloadIndex(candidates, argumentCount);
}
return {
name: typeParameter.symbol.name,
documentation: emptyArray,
displayParts,
isOptional: false
};
}
Debug.assert(argumentIndex === 0 || argumentIndex < argumentCount, `argumentCount < argumentIndex, ${argumentCount} < ${argumentIndex}`);
return {
items,
applicableSpan,
selectedItemIndex,
argumentIndex,
argumentCount
};
function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter {
const displayParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, invocation));
return {
name: parameter.name,
documentation: parameter.getDocumentationComment(),
displayParts,
isOptional: typeChecker.isOptionalParameter(<ParameterDeclaration>parameter.valueDeclaration)
};
}
function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter {
const displayParts = mapToDisplayParts(writer =>
typeChecker.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, invocation));
return {
name: typeParameter.symbol.name,
documentation: emptyArray,
displayParts,
isOptional: false
};
}
}
}
+21 -3
View File
@@ -426,9 +426,27 @@ namespace ts {
}
}
export function isInString(sourceFile: SourceFile, position: number) {
const token = getTokenAtPosition(sourceFile, position);
return token && (token.kind === SyntaxKind.StringLiteral || token.kind === SyntaxKind.StringLiteralType) && position > token.getStart(sourceFile);
export function isInString(sourceFile: SourceFile, position: number): boolean {
const previousToken = findPrecedingToken(position, sourceFile);
if (previousToken &&
(previousToken.kind === SyntaxKind.StringLiteral || previousToken.kind === SyntaxKind.StringLiteralType)) {
const start = previousToken.getStart();
const end = previousToken.getEnd();
// To be "in" one of these literals, the position has to be:
// 1. entirely within the token text.
// 2. at the end position of an unterminated token.
// 3. at the end of a regular expression (due to trailing flags like '/foo/g').
if (start < position && position < end) {
return true;
}
if (position === end) {
return !!(<LiteralExpression>previousToken).isUnterminated;
}
}
return false;
}
export function isInComment(sourceFile: SourceFile, position: number) {
@@ -1,12 +0,0 @@
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction2.ts(1,13): error TS2304: Cannot find name 'b'.
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction2.ts(1,14): error TS1009: Trailing comma not allowed.
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction2.ts (2 errors) ====
var v = (a: b,) => {
~
!!! error TS2304: Cannot find name 'b'.
~
!!! error TS1009: Trailing comma not allowed.
};
@@ -1,8 +0,0 @@
//// [ArrowFunction2.ts]
var v = (a: b,) => {
};
//// [ArrowFunction2.js]
var v = function (a) {
};
@@ -1,8 +1,8 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts (1 errors) ====
function * yield() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
}
@@ -1,11 +1,11 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts(3,11): error TS2304: Cannot find name 'yield'.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts (2 errors) ====
function * foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
// Legal to use 'yield' in a type context.
var v: yield;
~~~~~
@@ -1,8 +1,8 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts (1 errors) ====
function * foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
}
@@ -1,11 +1,11 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts(1,18): error TS2523: 'yield' expressions cannot be used in a parameter initializer.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts (2 errors) ====
function*foo(a = yield) {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
~~~~~
!!! error TS2523: 'yield' expressions cannot be used in a parameter initializer.
}
@@ -1,16 +1,16 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(3,11): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(3,11): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(3,20): error TS2523: 'yield' expressions cannot be used in a parameter initializer.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts (3 errors) ====
function*bar() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
// 'yield' here is an identifier, and not a yield expression.
function*foo(a = yield) {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
~~~~~
!!! error TS2523: 'yield' expressions cannot be used in a parameter initializer.
}
@@ -1,9 +1,9 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts (1 errors) ====
function * foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
var v = { [yield]: foo }
}
@@ -1,7 +1,7 @@
tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts(1,18): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts(1,18): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts (1 errors) ====
var v = function * () { }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
@@ -1,7 +1,7 @@
tests/cases/conformance/es6/functionExpressions/FunctionExpression2_es6.ts(1,18): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionExpressions/FunctionExpression2_es6.ts(1,18): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionExpressions/FunctionExpression2_es6.ts (1 errors) ====
var v = function * foo() { }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
@@ -1,7 +1,7 @@
tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments1_es6.ts(1,11): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments1_es6.ts(1,11): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments1_es6.ts (1 errors) ====
var v = { *foo() { } }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
@@ -1,10 +1,10 @@
tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments5_es6.ts(1,11): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments5_es6.ts(1,11): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments5_es6.ts(1,13): error TS2304: Cannot find name 'foo'.
==== tests/cases/conformance/es6/functionPropertyAssignments/FunctionPropertyAssignments5_es6.ts (2 errors) ====
var v = { *[foo()]() { } }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
~~~
!!! error TS2304: Cannot find name 'foo'.
@@ -1,9 +1,9 @@
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration1_es6.ts(2,4): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration1_es6.ts(2,4): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration1_es6.ts (1 errors) ====
class C {
*foo() { }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
}
@@ -1,9 +1,9 @@
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration2_es6.ts(2,11): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration2_es6.ts(2,11): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration2_es6.ts (1 errors) ====
class C {
public * foo() { }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
}
@@ -1,4 +1,4 @@
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts(2,4): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts(2,4): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration3_es6.ts(2,6): error TS2304: Cannot find name 'foo'.
@@ -6,7 +6,7 @@ tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration
class C {
*[foo]() { }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
~~~
!!! error TS2304: Cannot find name 'foo'.
}
@@ -1,9 +1,9 @@
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration7_es6.ts(2,4): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration7_es6.ts(2,4): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/memberFunctionDeclarations/MemberFunctionDeclaration7_es6.ts (1 errors) ====
class C {
*foo<T>() { }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
}
@@ -1,11 +1,11 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts(1,11): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts(1,11): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts(2,11): error TS2304: Cannot find name 'foo'.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression10_es6.ts (2 errors) ====
var v = { * foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield(foo);
~~~
!!! error TS2304: Cannot find name 'foo'.
@@ -1,4 +1,4 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(2,3): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(2,3): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(3,11): error TS2663: Cannot find name 'foo'. Did you mean the instance member 'this.foo'?
@@ -6,7 +6,7 @@ tests/cases/conformance/es6/yieldExpressions/YieldExpression11_es6.ts(3,11): err
class C {
*foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield(foo);
~~~
!!! error TS2663: Cannot find name 'foo'. Did you mean the instance member 'this.foo'?
@@ -1,7 +1,7 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression13_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression13_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression13_es6.ts (1 errors) ====
function* foo() { yield }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
@@ -1,11 +1,11 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression16_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression16_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression16_es6.ts(3,5): error TS1163: A 'yield' expression is only allowed in a generator body.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression16_es6.ts (2 errors) ====
function* foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
function bar() {
yield foo;
~~~~~
@@ -1,15 +1,15 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression19_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression19_es6.ts(3,13): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression19_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression19_es6.ts(3,13): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression19_es6.ts (2 errors) ====
function*foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
function bar() {
function* quux() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield(foo);
}
}
@@ -1,10 +1,10 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression3_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression3_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression3_es6.ts (1 errors) ====
function* foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield
yield
}
@@ -1,10 +1,10 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression4_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression4_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression4_es6.ts (1 errors) ====
function* foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield;
yield;
}
@@ -1,11 +1,11 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts(2,9): error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression6_es6.ts (2 errors) ====
function* foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield*foo
~~~
!!! error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
@@ -1,9 +1,9 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression7_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression7_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression7_es6.ts (1 errors) ====
function* foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield foo
}
@@ -1,5 +1,5 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression8_es6.ts(1,1): error TS2304: Cannot find name 'yield'.
tests/cases/conformance/es6/yieldExpressions/YieldExpression8_es6.ts(2,9): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression8_es6.ts(2,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression8_es6.ts (2 errors) ====
@@ -8,6 +8,6 @@ tests/cases/conformance/es6/yieldExpressions/YieldExpression8_es6.ts(2,9): error
!!! error TS2304: Cannot find name 'yield'.
function* foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield(foo);
}
@@ -1,11 +1,11 @@
tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts(1,17): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts(1,17): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts(2,9): error TS2304: Cannot find name 'foo'.
==== tests/cases/conformance/es6/yieldExpressions/YieldExpression9_es6.ts (2 errors) ====
var v = function*() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield(foo);
~~~
!!! error TS2304: Cannot find name 'foo'.
@@ -1,11 +1,11 @@
tests/cases/conformance/es6/yieldExpressions/YieldStarExpression4_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldStarExpression4_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/yieldExpressions/YieldStarExpression4_es6.ts(2,13): error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
==== tests/cases/conformance/es6/yieldExpressions/YieldStarExpression4_es6.ts (2 errors) ====
function *g() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 6 or higher.
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
yield * [];
~~
!!! error TS2488: Type must have a '[Symbol.iterator]()' method that returns an iterator.
@@ -0,0 +1,44 @@
//// [tests/cases/conformance/ambient/ambientDeclarationsPatterns.ts] ////
//// [declarations.d.ts]
declare module "foo*baz" {
export function foo(s: string): void;
}
// Augmentations still work
declare module "foo*baz" {
export const baz: string;
}
// Longest prefix wins
declare module "foos*" {
export const foos: string;
}
declare module "*!text" {
const x: string;
export default x;
}
//// [user.ts]
///<reference path="declarations.d.ts" />
import {foo, baz} from "foobarbaz";
foo(baz);
import {foos} from "foosball";
foo(foos);
// Works with relative file name
import fileText from "./file!text";
foo(fileText);
//// [user.js]
"use strict";
///<reference path="declarations.d.ts" />
var foobarbaz_1 = require("foobarbaz");
foobarbaz_1.foo(foobarbaz_1.baz);
var foosball_1 = require("foosball");
foobarbaz_1.foo(foosball_1.foos);
// Works with relative file name
var file_text_1 = require("./file!text");
foobarbaz_1.foo(file_text_1["default"]);
@@ -0,0 +1,51 @@
=== tests/cases/conformance/ambient/user.ts ===
///<reference path="declarations.d.ts" />
import {foo, baz} from "foobarbaz";
>foo : Symbol(foo, Decl(user.ts, 1, 8))
>baz : Symbol(baz, Decl(user.ts, 1, 12))
foo(baz);
>foo : Symbol(foo, Decl(user.ts, 1, 8))
>baz : Symbol(baz, Decl(user.ts, 1, 12))
import {foos} from "foosball";
>foos : Symbol(foos, Decl(user.ts, 4, 8))
foo(foos);
>foo : Symbol(foo, Decl(user.ts, 1, 8))
>foos : Symbol(foos, Decl(user.ts, 4, 8))
// Works with relative file name
import fileText from "./file!text";
>fileText : Symbol(fileText, Decl(user.ts, 8, 6))
foo(fileText);
>foo : Symbol(foo, Decl(user.ts, 1, 8))
>fileText : Symbol(fileText, Decl(user.ts, 8, 6))
=== tests/cases/conformance/ambient/declarations.d.ts ===
declare module "foo*baz" {
export function foo(s: string): void;
>foo : Symbol(foo, Decl(declarations.d.ts, 0, 26))
>s : Symbol(s, Decl(declarations.d.ts, 1, 24))
}
// Augmentations still work
declare module "foo*baz" {
export const baz: string;
>baz : Symbol(baz, Decl(declarations.d.ts, 5, 16))
}
// Longest prefix wins
declare module "foos*" {
export const foos: string;
>foos : Symbol(foos, Decl(declarations.d.ts, 10, 16))
}
declare module "*!text" {
const x: string;
>x : Symbol(x, Decl(declarations.d.ts, 14, 9))
export default x;
>x : Symbol(x, Decl(declarations.d.ts, 14, 9))
}
@@ -0,0 +1,54 @@
=== tests/cases/conformance/ambient/user.ts ===
///<reference path="declarations.d.ts" />
import {foo, baz} from "foobarbaz";
>foo : (s: string) => void
>baz : string
foo(baz);
>foo(baz) : void
>foo : (s: string) => void
>baz : string
import {foos} from "foosball";
>foos : string
foo(foos);
>foo(foos) : void
>foo : (s: string) => void
>foos : string
// Works with relative file name
import fileText from "./file!text";
>fileText : string
foo(fileText);
>foo(fileText) : void
>foo : (s: string) => void
>fileText : string
=== tests/cases/conformance/ambient/declarations.d.ts ===
declare module "foo*baz" {
export function foo(s: string): void;
>foo : (s: string) => void
>s : string
}
// Augmentations still work
declare module "foo*baz" {
export const baz: string;
>baz : string
}
// Longest prefix wins
declare module "foos*" {
export const foos: string;
>foos : string
}
declare module "*!text" {
const x: string;
>x : string
export default x;
>x : string
}
@@ -0,0 +1,8 @@
tests/cases/conformance/ambient/ambientDeclarationsPatterns_tooManyAsterisks.ts(1,16): error TS5061: Pattern 'too*many*asterisks' can have at most one '*' character
==== tests/cases/conformance/ambient/ambientDeclarationsPatterns_tooManyAsterisks.ts (1 errors) ====
declare module "too*many*asterisks" { }
~~~~~~~~~~~~~~~~~~~~
!!! error TS5061: Pattern 'too*many*asterisks' can have at most one '*' character
@@ -0,0 +1,5 @@
//// [ambientDeclarationsPatterns_tooManyAsterisks.ts]
declare module "too*many*asterisks" { }
//// [ambientDeclarationsPatterns_tooManyAsterisks.js]
@@ -0,0 +1,22 @@
//// [tests/cases/conformance/ambient/ambientShorthand.ts] ////
//// [declarations.d.ts]
declare module "jquery"
// Semicolon is optional
declare module "fs";
//// [user.ts]
///<reference path="declarations.d.ts"/>
import foo, {bar} from "jquery";
import * as baz from "fs";
import boom = require("jquery");
foo(bar, baz, boom);
//// [user.js]
"use strict";
///<reference path="declarations.d.ts"/>
var jquery_1 = require("jquery");
var baz = require("fs");
var boom = require("jquery");
jquery_1["default"](jquery_1.bar, baz, boom);
@@ -0,0 +1,24 @@
=== tests/cases/conformance/ambient/user.ts ===
///<reference path="declarations.d.ts"/>
import foo, {bar} from "jquery";
>foo : Symbol(foo, Decl(user.ts, 1, 6))
>bar : Symbol(bar, Decl(user.ts, 1, 13))
import * as baz from "fs";
>baz : Symbol(baz, Decl(user.ts, 2, 6))
import boom = require("jquery");
>boom : Symbol(boom, Decl(user.ts, 2, 26))
foo(bar, baz, boom);
>foo : Symbol(foo, Decl(user.ts, 1, 6))
>bar : Symbol(bar, Decl(user.ts, 1, 13))
>baz : Symbol(baz, Decl(user.ts, 2, 6))
>boom : Symbol(boom, Decl(user.ts, 2, 26))
=== tests/cases/conformance/ambient/declarations.d.ts ===
declare module "jquery"
No type information for this code.// Semicolon is optional
No type information for this code.declare module "fs";
No type information for this code.
No type information for this code.
@@ -0,0 +1,25 @@
=== tests/cases/conformance/ambient/user.ts ===
///<reference path="declarations.d.ts"/>
import foo, {bar} from "jquery";
>foo : any
>bar : any
import * as baz from "fs";
>baz : any
import boom = require("jquery");
>boom : any
foo(bar, baz, boom);
>foo(bar, baz, boom) : any
>foo : any
>bar : any
>baz : any
>boom : any
=== tests/cases/conformance/ambient/declarations.d.ts ===
declare module "jquery"
No type information for this code.// Semicolon is optional
No type information for this code.declare module "fs";
No type information for this code.
No type information for this code.
@@ -0,0 +1,9 @@
//// [ambientShorthand_declarationEmit.ts]
declare module "foo";
//// [ambientShorthand_declarationEmit.js]
//// [ambientShorthand_declarationEmit.d.ts]
declare module "foo";
@@ -0,0 +1,4 @@
=== tests/cases/conformance/ambient/ambientShorthand_declarationEmit.ts ===
declare module "foo";
No type information for this code.
No type information for this code.
@@ -0,0 +1,4 @@
=== tests/cases/conformance/ambient/ambientShorthand_declarationEmit.ts ===
declare module "foo";
No type information for this code.
No type information for this code.
@@ -0,0 +1,16 @@
//// [tests/cases/conformance/ambient/ambientShorthand_duplicate.ts] ////
//// [declarations1.d.ts]
declare module "foo";
//// [declarations2.d.ts]
declare module "foo";
//// [user.ts]
///<reference path="declarations1.d.ts" />
///<reference path="declarations1.d.ts" />
import foo from "foo";
//// [user.js]
"use strict";
@@ -0,0 +1,10 @@
=== tests/cases/conformance/ambient/user.ts ===
///<reference path="declarations1.d.ts" />
///<reference path="declarations1.d.ts" />
import foo from "foo";
>foo : Symbol(foo, Decl(user.ts, 2, 6))
=== tests/cases/conformance/ambient/declarations1.d.ts ===
declare module "foo";
No type information for this code.
No type information for this code.
@@ -0,0 +1,10 @@
=== tests/cases/conformance/ambient/user.ts ===
///<reference path="declarations1.d.ts" />
///<reference path="declarations1.d.ts" />
import foo from "foo";
>foo : any
=== tests/cases/conformance/ambient/declarations1.d.ts ===
declare module "foo";
No type information for this code.
No type information for this code.
@@ -0,0 +1,8 @@
tests/cases/conformance/ambient/ambientShorthand_isImplicitAny.ts(1,16): error TS7005: Variable '"jquery"' implicitly has an 'any' type.
==== tests/cases/conformance/ambient/ambientShorthand_isImplicitAny.ts (1 errors) ====
declare module "jquery";
~~~~~~~~
!!! error TS7005: Variable '"jquery"' implicitly has an 'any' type.
@@ -0,0 +1,5 @@
//// [ambientShorthand_isImplicitAny.ts]
declare module "jquery";
//// [ambientShorthand_isImplicitAny.js]
@@ -0,0 +1,18 @@
//// [tests/cases/conformance/ambient/ambientShorthand_merging.ts] ////
//// [declarations1.d.ts]
declare module "foo";
//// [declarations2.d.ts]
declare module "foo" {
export const bar: number;
}
//// [user.ts]
///<reference path="declarations1.d.ts" />
///<reference path="declarations1.d.ts" />
import foo, {bar} from "foo";
//// [user.js]
"use strict";
@@ -0,0 +1,11 @@
=== tests/cases/conformance/ambient/user.ts ===
///<reference path="declarations1.d.ts" />
///<reference path="declarations1.d.ts" />
import foo, {bar} from "foo";
>foo : Symbol(foo, Decl(user.ts, 2, 6))
>bar : Symbol(bar, Decl(user.ts, 2, 13))
=== tests/cases/conformance/ambient/declarations1.d.ts ===
declare module "foo";
No type information for this code.
No type information for this code.
@@ -0,0 +1,11 @@
=== tests/cases/conformance/ambient/user.ts ===
///<reference path="declarations1.d.ts" />
///<reference path="declarations1.d.ts" />
import foo, {bar} from "foo";
>foo : any
>bar : any
=== tests/cases/conformance/ambient/declarations1.d.ts ===
declare module "foo";
No type information for this code.
No type information for this code.
@@ -0,0 +1,30 @@
//// [tests/cases/conformance/ambient/ambientShorthand_reExport.ts] ////
//// [declarations.d.ts]
declare module "jquery";
//// [reExportX.ts]
export {x} from "jquery";
//// [reExportAll.ts]
export * from "jquery";
//// [reExportUser.ts]
import {x} from "./reExportX";
import * as $ from "./reExportAll";
// '$' is not callable, it is an object.
x($);
//// [reExportX.js]
"use strict";
var jquery_1 = require("jquery");
exports.x = jquery_1.x;
//// [reExportAll.js]
"use strict";
//// [reExportUser.js]
"use strict";
var reExportX_1 = require("./reExportX");
var $ = require("./reExportAll");
// '$' is not callable, it is an object.
reExportX_1.x($);
@@ -0,0 +1,22 @@
=== tests/cases/conformance/ambient/declarations.d.ts ===
declare module "jquery";
No type information for this code.
No type information for this code.=== tests/cases/conformance/ambient/reExportX.ts ===
export {x} from "jquery";
>x : Symbol(x, Decl(reExportX.ts, 0, 8))
=== tests/cases/conformance/ambient/reExportAll.ts ===
export * from "jquery";
No type information for this code.
No type information for this code.=== tests/cases/conformance/ambient/reExportUser.ts ===
import {x} from "./reExportX";
>x : Symbol(x, Decl(reExportUser.ts, 0, 8))
import * as $ from "./reExportAll";
>$ : Symbol($, Decl(reExportUser.ts, 1, 6))
// '$' is not callable, it is an object.
x($);
>x : Symbol(x, Decl(reExportUser.ts, 0, 8))
>$ : Symbol($, Decl(reExportUser.ts, 1, 6))

Some files were not shown because too many files have changed in this diff Show More