mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into primitive-type-guards-are-order-independent
This commit is contained in:
+14
-54
@@ -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/";
|
||||
@@ -312,10 +313,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
}
|
||||
|
||||
if (useDebugMode) {
|
||||
options += " -sourcemap";
|
||||
if (!opts.noMapRoot) {
|
||||
options += " -mapRoot file:///" + path.resolve(path.dirname(outFile));
|
||||
}
|
||||
options += " --inlineSourceMap --inlineSources";
|
||||
} else {
|
||||
options += " --newLine LF";
|
||||
}
|
||||
@@ -485,7 +483,6 @@ var tscFile = path.join(builtLocalDirectory, compilerFilename);
|
||||
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false);
|
||||
|
||||
var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js");
|
||||
var servicesFileInBrowserTest = path.join(builtLocalDirectory, "typescriptServicesInBrowserTest.js");
|
||||
var standaloneDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts");
|
||||
var nodePackageFile = path.join(builtLocalDirectory, "typescript.js");
|
||||
var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts");
|
||||
@@ -517,16 +514,6 @@ 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));
|
||||
});
|
||||
|
||||
|
||||
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true);
|
||||
@@ -688,7 +675,6 @@ function cleanTestDirs() {
|
||||
// used to pass data from jake command line directly to run.js
|
||||
function writeTestConfigFile(tests, light, taskConfigsFolder, workerCount) {
|
||||
var testConfigContents = JSON.stringify({ test: tests ? [tests] : undefined, light: light, workerCount: workerCount, taskConfigsFolder: taskConfigsFolder });
|
||||
console.log('Running tests with config: ' + testConfigContents);
|
||||
fs.writeFileSync('test.config', testConfigContents);
|
||||
}
|
||||
|
||||
@@ -749,42 +735,16 @@ function runConsoleTests(defaultReporter, runInParallel) {
|
||||
|
||||
}
|
||||
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)
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
|
||||
// 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -839,12 +799,12 @@ 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 -o built/local/bundle.js';
|
||||
var cmd = 'browserify built/local/run.js -d -o built/local/bundle.js';
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
desc("Runs the tests using the built run.js file like 'jake runtests'. Syntax is jake runtests-browser. Additional optional parameters tests=[regex], port=, browser=[chrome|IE]");
|
||||
task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFileInBrowserTest], function() {
|
||||
task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFile], function() {
|
||||
cleanTestDirs();
|
||||
host = "node";
|
||||
port = process.env.port || process.env.p || '8888';
|
||||
|
||||
@@ -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;
|
||||
@@ -0,0 +1,367 @@
|
||||
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 = child_process.spawn(
|
||||
process.platform === "win32" ? "cmd" : "/bin/sh",
|
||||
process.platform === "win32" ? ["/c", cmd] : ["-c", cmd], {
|
||||
windowsVerbatimArguments: true,
|
||||
env: { NODE_ENV: "development" }
|
||||
});
|
||||
|
||||
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 = child_process.spawn(
|
||||
process.platform === "win32" ? "cmd" : "/bin/sh",
|
||||
process.platform === "win32" ? ["/c", cmd] : ["-c", cmd], {
|
||||
windowsVerbatimArguments: true,
|
||||
env: { NODE_ENV: "development" }
|
||||
});
|
||||
|
||||
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 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;
|
||||
}
|
||||
+20
-5
@@ -1198,9 +1198,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 {
|
||||
@@ -1304,7 +1304,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 {
|
||||
@@ -2082,10 +2097,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+78
-44
@@ -140,6 +140,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;
|
||||
|
||||
@@ -1285,6 +1291,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);
|
||||
@@ -2844,7 +2858,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;
|
||||
@@ -2887,7 +2901,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
|
||||
@@ -3222,7 +3236,7 @@ namespace ts {
|
||||
if (!links.type) {
|
||||
const type = createObjectType(TypeFlags.Anonymous, symbol);
|
||||
links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ?
|
||||
addNullableKind(type, TypeFlags.Undefined) : type;
|
||||
addTypeKind(type, TypeFlags.Undefined) : type;
|
||||
}
|
||||
return links.type;
|
||||
}
|
||||
@@ -6746,7 +6760,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 {
|
||||
@@ -6817,28 +6831,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 {
|
||||
@@ -7662,12 +7670,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;
|
||||
@@ -7885,7 +7908,7 @@ namespace ts {
|
||||
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
|
||||
assumeTrue = !assumeTrue;
|
||||
}
|
||||
if (!strictNullChecks || !isMatchingReference(reference, narrowed)) {
|
||||
if (!strictNullChecks || !isMatchingReference(reference, getReferenceFromExpression(narrowed))) {
|
||||
return type;
|
||||
}
|
||||
const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken;
|
||||
@@ -7900,12 +7923,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 typeOf = <TypeOfExpression>(expr.left.kind === SyntaxKind.TypeOfExpression ? expr.left : expr.right);
|
||||
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, typeOf.expression)) {
|
||||
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, typeOf.expression)) {
|
||||
if (containsMatchingReference(reference, narrowed)) {
|
||||
return declaredType;
|
||||
}
|
||||
return type;
|
||||
@@ -7930,10 +7953,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -8000,7 +8024,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 {
|
||||
@@ -8175,7 +8199,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;
|
||||
@@ -8749,6 +8773,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);
|
||||
}
|
||||
@@ -9957,7 +9991,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 :
|
||||
@@ -11491,7 +11525,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;
|
||||
@@ -12417,7 +12451,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:
|
||||
@@ -16866,10 +16900,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;
|
||||
@@ -16887,11 +16918,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);
|
||||
@@ -17635,6 +17663,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);
|
||||
}
|
||||
@@ -17765,6 +17797,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:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
namespace ts {
|
||||
/* @internal */
|
||||
export let optionDeclarations: CommandLineOption[] = [
|
||||
export const optionDeclarations: CommandLineOption[] = [
|
||||
{
|
||||
name: "charset",
|
||||
type: "string",
|
||||
|
||||
+11
-2
@@ -849,13 +849,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;
|
||||
|
||||
@@ -2260,7 +2260,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,6 +2772,10 @@
|
||||
"category": "Error",
|
||||
"code": 6131
|
||||
},
|
||||
"File name '{0}' has a '{1}' extension - stripping it": {
|
||||
"category": "Message",
|
||||
"code": 6132
|
||||
},
|
||||
|
||||
"Variable '{0}' implicitly has an '{1}' type.": {
|
||||
"category": "Error",
|
||||
|
||||
+105
-48
@@ -95,7 +95,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) {
|
||||
@@ -496,48 +497,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);
|
||||
@@ -560,6 +536,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);
|
||||
@@ -619,8 +664,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);
|
||||
@@ -629,7 +691,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;
|
||||
@@ -2043,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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2056,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) {
|
||||
|
||||
@@ -1658,6 +1658,7 @@ namespace ts {
|
||||
/* @internal */ resolvedTypeReferenceDirectiveNames: Map<ResolvedTypeReferenceDirective>;
|
||||
/* @internal */ imports: LiteralExpression[];
|
||||
/* @internal */ moduleAugmentations: LiteralExpression[];
|
||||
/* @internal */ patternAmbientModules?: PatternAmbientModule[];
|
||||
}
|
||||
|
||||
export interface ScriptReferenceHost {
|
||||
@@ -2135,6 +2136,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
|
||||
@@ -2209,6 +2224,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 */
|
||||
|
||||
@@ -1692,6 +1692,3 @@ namespace Harness {
|
||||
|
||||
if (Error) (<any>Error).stackTraceLimit = 1;
|
||||
}
|
||||
|
||||
// TODO: not sure why Utils.evalFile isn't working with this, eventually will concat it like old compiler instead of eval
|
||||
eval(Harness.tcServicesFile);
|
||||
|
||||
@@ -1207,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,5 +722,5 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+142
-18
@@ -1064,10 +1064,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.
|
||||
@@ -1939,6 +1939,40 @@ namespace ts {
|
||||
sourceMapText?: string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
let commandLineOptions_stringToEnum: CommandLineOptionOfCustomType[];
|
||||
|
||||
/** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */
|
||||
function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions {
|
||||
// Lazily create this value to fix module loading errors.
|
||||
commandLineOptions_stringToEnum = commandLineOptions_stringToEnum || <CommandLineOptionOfCustomType[]>filter(optionDeclarations, o =>
|
||||
typeof o.type === "object" && !forEachValue(<Map<any>> o.type, v => typeof v !== "number"));
|
||||
|
||||
options = clone(options);
|
||||
|
||||
for (const opt of commandLineOptions_stringToEnum) {
|
||||
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.
|
||||
@@ -1949,7 +1983,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 ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : getDefaultCompilerOptions();
|
||||
|
||||
options.isolatedModules = true;
|
||||
|
||||
@@ -2007,9 +2043,7 @@ namespace ts {
|
||||
|
||||
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());
|
||||
}
|
||||
@@ -2499,7 +2533,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// should be start of dependency list
|
||||
if (token !== SyntaxKind.OpenBracketToken) {
|
||||
if (token !== SyntaxKind.OpenBracketToken) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4032,10 +4066,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;
|
||||
@@ -4048,12 +4087,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 {
|
||||
@@ -4077,7 +4114,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
getCompletionEntriesFromSymbols(symbols, entries);
|
||||
getCompletionEntriesFromSymbols(symbols, entries, location, /*performCharacterChecks*/ true);
|
||||
}
|
||||
|
||||
// Add keywords if this is not a member completion list
|
||||
@@ -4127,11 +4164,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;
|
||||
}
|
||||
@@ -4152,12 +4189,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)) {
|
||||
@@ -4171,6 +4208,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 {
|
||||
@@ -4335,7 +4459,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;
|
||||
|
||||
+379
-376
@@ -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
|
||||
@@ -205,431 +207,432 @@ namespace ts.SignatureHelp {
|
||||
// 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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,33 @@
|
||||
//// [asyncFunctionReturnType.ts]
|
||||
async function fAsync() {
|
||||
// Without explicit type annotation, this is just an array.
|
||||
return [1, true];
|
||||
}
|
||||
|
||||
async function fAsyncExplicit(): Promise<[number, boolean]> {
|
||||
// This is contextually typed as a tuple.
|
||||
return [1, true];
|
||||
}
|
||||
|
||||
|
||||
//// [asyncFunctionReturnType.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function fAsync() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// Without explicit type annotation, this is just an array.
|
||||
return [1, true];
|
||||
});
|
||||
}
|
||||
function fAsyncExplicit() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// This is contextually typed as a tuple.
|
||||
return [1, true];
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
=== tests/cases/compiler/asyncFunctionReturnType.ts ===
|
||||
async function fAsync() {
|
||||
>fAsync : Symbol(fAsync, Decl(asyncFunctionReturnType.ts, 0, 0))
|
||||
|
||||
// Without explicit type annotation, this is just an array.
|
||||
return [1, true];
|
||||
}
|
||||
|
||||
async function fAsyncExplicit(): Promise<[number, boolean]> {
|
||||
>fAsyncExplicit : Symbol(fAsyncExplicit, Decl(asyncFunctionReturnType.ts, 3, 1))
|
||||
>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
|
||||
// This is contextually typed as a tuple.
|
||||
return [1, true];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
=== tests/cases/compiler/asyncFunctionReturnType.ts ===
|
||||
async function fAsync() {
|
||||
>fAsync : () => Promise<(number | boolean)[]>
|
||||
|
||||
// Without explicit type annotation, this is just an array.
|
||||
return [1, true];
|
||||
>[1, true] : (number | boolean)[]
|
||||
>1 : number
|
||||
>true : boolean
|
||||
}
|
||||
|
||||
async function fAsyncExplicit(): Promise<[number, boolean]> {
|
||||
>fAsyncExplicit : () => Promise<[number, boolean]>
|
||||
>Promise : Promise<T>
|
||||
|
||||
// This is contextually typed as a tuple.
|
||||
return [1, true];
|
||||
>[1, true] : [number, boolean]
|
||||
>1 : number
|
||||
>true : boolean
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
error TS2318: Cannot find global type 'Promise'.
|
||||
tests/cases/compiler/disallowAsyncModifierInES5.ts(2,1): error TS1311: Async functions are only available when targeting ECMAScript 6 and higher.
|
||||
tests/cases/compiler/disallowAsyncModifierInES5.ts(2,16): error TS1057: An async function or method must have a valid awaitable return type.
|
||||
tests/cases/compiler/disallowAsyncModifierInES5.ts(3,11): error TS1057: An async function or method must have a valid awaitable return type.
|
||||
tests/cases/compiler/disallowAsyncModifierInES5.ts(3,11): error TS1311: Async functions are only available when targeting ECMAScript 6 and higher.
|
||||
tests/cases/compiler/disallowAsyncModifierInES5.ts(4,11): error TS1311: Async functions are only available when targeting ECMAScript 6 and higher.
|
||||
tests/cases/compiler/disallowAsyncModifierInES5.ts(4,11): error TS1057: An async function or method must have a valid awaitable return type.
|
||||
|
||||
|
||||
!!! error TS2318: Cannot find global type 'Promise'.
|
||||
==== tests/cases/compiler/disallowAsyncModifierInES5.ts (6 errors) ====
|
||||
|
||||
async function foo() { return 42; } // ERROR: Async functions are only available in ES6+
|
||||
~~~~~
|
||||
!!! error TS1311: Async functions are only available when targeting ECMAScript 6 and higher.
|
||||
~~~
|
||||
!!! error TS1057: An async function or method must have a valid awaitable return type.
|
||||
let bar = async function () { return 42; } // OK, but should be an error
|
||||
~~~~~
|
||||
!!! error TS1057: An async function or method must have a valid awaitable return type.
|
||||
~~~~~
|
||||
!!! error TS1311: Async functions are only available when targeting ECMAScript 6 and higher.
|
||||
let baz = async () => 42; // OK, but should be an error
|
||||
~~~~~
|
||||
!!! error TS1311: Async functions are only available when targeting ECMAScript 6 and higher.
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS1057: An async function or method must have a valid awaitable return type.
|
||||
@@ -0,0 +1,22 @@
|
||||
//// [disallowAsyncModifierInES5.ts]
|
||||
|
||||
async function foo() { return 42; } // ERROR: Async functions are only available in ES6+
|
||||
let bar = async function () { return 42; } // OK, but should be an error
|
||||
let baz = async () => 42; // OK, but should be an error
|
||||
|
||||
//// [disallowAsyncModifierInES5.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function foo() {
|
||||
return __awaiter(this, void 0, void 0, function* () { return 42; });
|
||||
} // ERROR: Async functions are only available in ES6+
|
||||
var bar = function () {
|
||||
return __awaiter(this, void 0, void 0, function* () { return 42; });
|
||||
}; // OK, but should be an error
|
||||
var baz = function () __awaiter(this, void 0, void 0, function* () { return 42; }); // OK, but should be an error
|
||||
@@ -133,8 +133,8 @@ function fn5(x: Derived1) {
|
||||
// 1.5: y: Derived1
|
||||
// Want: ???
|
||||
let y = x;
|
||||
>y : never
|
||||
>x : never
|
||||
>y : Derived1 & Derived2
|
||||
>x : Derived1 & Derived2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
//// [logicalAndOperatorStrictMode.ts]
|
||||
|
||||
const a = [0];
|
||||
const s = "";
|
||||
const x = 0;
|
||||
const b = false;
|
||||
const v: void = undefined;
|
||||
const u = undefined;
|
||||
const n = null;
|
||||
const z = s || x || u;
|
||||
|
||||
const a1 = a && a;
|
||||
const a2 = a && s;
|
||||
const a3 = a && x;
|
||||
const a4 = a && b;
|
||||
const a5 = a && v;
|
||||
const a6 = a && u;
|
||||
const a7 = a && n;
|
||||
const a8 = a && z;
|
||||
|
||||
const s1 = s && a;
|
||||
const s2 = s && s;
|
||||
const s3 = s && x;
|
||||
const s4 = s && b;
|
||||
const s5 = s && v;
|
||||
const s6 = s && u;
|
||||
const s7 = s && n;
|
||||
const s8 = s && z;
|
||||
|
||||
const x1 = x && a;
|
||||
const x2 = x && s;
|
||||
const x3 = x && x;
|
||||
const x4 = x && b;
|
||||
const x5 = x && v;
|
||||
const x6 = x && u;
|
||||
const x7 = x && n;
|
||||
const x8 = x && z;
|
||||
|
||||
const b1 = b && a;
|
||||
const b2 = b && s;
|
||||
const b3 = b && x;
|
||||
const b4 = b && b;
|
||||
const b5 = b && v;
|
||||
const b6 = b && u;
|
||||
const b7 = b && n;
|
||||
const b8 = b && z;
|
||||
|
||||
const v1 = v && a;
|
||||
const v2 = v && s;
|
||||
const v3 = v && x;
|
||||
const v4 = v && b;
|
||||
const v5 = v && v;
|
||||
const v6 = v && u;
|
||||
const v7 = v && n;
|
||||
const v8 = v && z;
|
||||
|
||||
const u1 = u && a;
|
||||
const u2 = u && s;
|
||||
const u3 = u && x;
|
||||
const u4 = u && b;
|
||||
const u5 = u && v;
|
||||
const u6 = u && u;
|
||||
const u7 = u && n;
|
||||
const u8 = u && z;
|
||||
|
||||
const n1 = n && a;
|
||||
const n2 = n && s;
|
||||
const n3 = n && x;
|
||||
const n4 = n && b;
|
||||
const n5 = n && v;
|
||||
const n6 = n && u;
|
||||
const n7 = n && n;
|
||||
const n8 = n && z;
|
||||
|
||||
const z1 = z && a;
|
||||
const z2 = z && s;
|
||||
const z3 = z && x;
|
||||
const z4 = z && b;
|
||||
const z5 = z && v;
|
||||
const z6 = z && u;
|
||||
const z7 = z && n;
|
||||
const z8 = z && z;
|
||||
|
||||
//// [logicalAndOperatorStrictMode.js]
|
||||
var a = [0];
|
||||
var s = "";
|
||||
var x = 0;
|
||||
var b = false;
|
||||
var v = undefined;
|
||||
var u = undefined;
|
||||
var n = null;
|
||||
var z = s || x || u;
|
||||
var a1 = a && a;
|
||||
var a2 = a && s;
|
||||
var a3 = a && x;
|
||||
var a4 = a && b;
|
||||
var a5 = a && v;
|
||||
var a6 = a && u;
|
||||
var a7 = a && n;
|
||||
var a8 = a && z;
|
||||
var s1 = s && a;
|
||||
var s2 = s && s;
|
||||
var s3 = s && x;
|
||||
var s4 = s && b;
|
||||
var s5 = s && v;
|
||||
var s6 = s && u;
|
||||
var s7 = s && n;
|
||||
var s8 = s && z;
|
||||
var x1 = x && a;
|
||||
var x2 = x && s;
|
||||
var x3 = x && x;
|
||||
var x4 = x && b;
|
||||
var x5 = x && v;
|
||||
var x6 = x && u;
|
||||
var x7 = x && n;
|
||||
var x8 = x && z;
|
||||
var b1 = b && a;
|
||||
var b2 = b && s;
|
||||
var b3 = b && x;
|
||||
var b4 = b && b;
|
||||
var b5 = b && v;
|
||||
var b6 = b && u;
|
||||
var b7 = b && n;
|
||||
var b8 = b && z;
|
||||
var v1 = v && a;
|
||||
var v2 = v && s;
|
||||
var v3 = v && x;
|
||||
var v4 = v && b;
|
||||
var v5 = v && v;
|
||||
var v6 = v && u;
|
||||
var v7 = v && n;
|
||||
var v8 = v && z;
|
||||
var u1 = u && a;
|
||||
var u2 = u && s;
|
||||
var u3 = u && x;
|
||||
var u4 = u && b;
|
||||
var u5 = u && v;
|
||||
var u6 = u && u;
|
||||
var u7 = u && n;
|
||||
var u8 = u && z;
|
||||
var n1 = n && a;
|
||||
var n2 = n && s;
|
||||
var n3 = n && x;
|
||||
var n4 = n && b;
|
||||
var n5 = n && v;
|
||||
var n6 = n && u;
|
||||
var n7 = n && n;
|
||||
var n8 = n && z;
|
||||
var z1 = z && a;
|
||||
var z2 = z && s;
|
||||
var z3 = z && x;
|
||||
var z4 = z && b;
|
||||
var z5 = z && v;
|
||||
var z6 = z && u;
|
||||
var z7 = z && n;
|
||||
var z8 = z && z;
|
||||
@@ -0,0 +1,351 @@
|
||||
=== tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts ===
|
||||
|
||||
const a = [0];
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
|
||||
const s = "";
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
|
||||
const x = 0;
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
|
||||
const b = false;
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
|
||||
const v: void = undefined;
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
const u = undefined;
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
const n = null;
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
|
||||
const z = s || x || u;
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
|
||||
const a1 = a && a;
|
||||
>a1 : Symbol(a1, Decl(logicalAndOperatorStrictMode.ts, 10, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
|
||||
const a2 = a && s;
|
||||
>a2 : Symbol(a2, Decl(logicalAndOperatorStrictMode.ts, 11, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
|
||||
const a3 = a && x;
|
||||
>a3 : Symbol(a3, Decl(logicalAndOperatorStrictMode.ts, 12, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
|
||||
const a4 = a && b;
|
||||
>a4 : Symbol(a4, Decl(logicalAndOperatorStrictMode.ts, 13, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
|
||||
const a5 = a && v;
|
||||
>a5 : Symbol(a5, Decl(logicalAndOperatorStrictMode.ts, 14, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
|
||||
const a6 = a && u;
|
||||
>a6 : Symbol(a6, Decl(logicalAndOperatorStrictMode.ts, 15, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
|
||||
const a7 = a && n;
|
||||
>a7 : Symbol(a7, Decl(logicalAndOperatorStrictMode.ts, 16, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
|
||||
const a8 = a && z;
|
||||
>a8 : Symbol(a8, Decl(logicalAndOperatorStrictMode.ts, 17, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
|
||||
const s1 = s && a;
|
||||
>s1 : Symbol(s1, Decl(logicalAndOperatorStrictMode.ts, 19, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
|
||||
const s2 = s && s;
|
||||
>s2 : Symbol(s2, Decl(logicalAndOperatorStrictMode.ts, 20, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
|
||||
const s3 = s && x;
|
||||
>s3 : Symbol(s3, Decl(logicalAndOperatorStrictMode.ts, 21, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
|
||||
const s4 = s && b;
|
||||
>s4 : Symbol(s4, Decl(logicalAndOperatorStrictMode.ts, 22, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
|
||||
const s5 = s && v;
|
||||
>s5 : Symbol(s5, Decl(logicalAndOperatorStrictMode.ts, 23, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
|
||||
const s6 = s && u;
|
||||
>s6 : Symbol(s6, Decl(logicalAndOperatorStrictMode.ts, 24, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
|
||||
const s7 = s && n;
|
||||
>s7 : Symbol(s7, Decl(logicalAndOperatorStrictMode.ts, 25, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
|
||||
const s8 = s && z;
|
||||
>s8 : Symbol(s8, Decl(logicalAndOperatorStrictMode.ts, 26, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
|
||||
const x1 = x && a;
|
||||
>x1 : Symbol(x1, Decl(logicalAndOperatorStrictMode.ts, 28, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
|
||||
const x2 = x && s;
|
||||
>x2 : Symbol(x2, Decl(logicalAndOperatorStrictMode.ts, 29, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
|
||||
const x3 = x && x;
|
||||
>x3 : Symbol(x3, Decl(logicalAndOperatorStrictMode.ts, 30, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
|
||||
const x4 = x && b;
|
||||
>x4 : Symbol(x4, Decl(logicalAndOperatorStrictMode.ts, 31, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
|
||||
const x5 = x && v;
|
||||
>x5 : Symbol(x5, Decl(logicalAndOperatorStrictMode.ts, 32, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
|
||||
const x6 = x && u;
|
||||
>x6 : Symbol(x6, Decl(logicalAndOperatorStrictMode.ts, 33, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
|
||||
const x7 = x && n;
|
||||
>x7 : Symbol(x7, Decl(logicalAndOperatorStrictMode.ts, 34, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
|
||||
const x8 = x && z;
|
||||
>x8 : Symbol(x8, Decl(logicalAndOperatorStrictMode.ts, 35, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
|
||||
const b1 = b && a;
|
||||
>b1 : Symbol(b1, Decl(logicalAndOperatorStrictMode.ts, 37, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
|
||||
const b2 = b && s;
|
||||
>b2 : Symbol(b2, Decl(logicalAndOperatorStrictMode.ts, 38, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
|
||||
const b3 = b && x;
|
||||
>b3 : Symbol(b3, Decl(logicalAndOperatorStrictMode.ts, 39, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
|
||||
const b4 = b && b;
|
||||
>b4 : Symbol(b4, Decl(logicalAndOperatorStrictMode.ts, 40, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
|
||||
const b5 = b && v;
|
||||
>b5 : Symbol(b5, Decl(logicalAndOperatorStrictMode.ts, 41, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
|
||||
const b6 = b && u;
|
||||
>b6 : Symbol(b6, Decl(logicalAndOperatorStrictMode.ts, 42, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
|
||||
const b7 = b && n;
|
||||
>b7 : Symbol(b7, Decl(logicalAndOperatorStrictMode.ts, 43, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
|
||||
const b8 = b && z;
|
||||
>b8 : Symbol(b8, Decl(logicalAndOperatorStrictMode.ts, 44, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
|
||||
const v1 = v && a;
|
||||
>v1 : Symbol(v1, Decl(logicalAndOperatorStrictMode.ts, 46, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
|
||||
const v2 = v && s;
|
||||
>v2 : Symbol(v2, Decl(logicalAndOperatorStrictMode.ts, 47, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
|
||||
const v3 = v && x;
|
||||
>v3 : Symbol(v3, Decl(logicalAndOperatorStrictMode.ts, 48, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
|
||||
const v4 = v && b;
|
||||
>v4 : Symbol(v4, Decl(logicalAndOperatorStrictMode.ts, 49, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
|
||||
const v5 = v && v;
|
||||
>v5 : Symbol(v5, Decl(logicalAndOperatorStrictMode.ts, 50, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
|
||||
const v6 = v && u;
|
||||
>v6 : Symbol(v6, Decl(logicalAndOperatorStrictMode.ts, 51, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
|
||||
const v7 = v && n;
|
||||
>v7 : Symbol(v7, Decl(logicalAndOperatorStrictMode.ts, 52, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
|
||||
const v8 = v && z;
|
||||
>v8 : Symbol(v8, Decl(logicalAndOperatorStrictMode.ts, 53, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
|
||||
const u1 = u && a;
|
||||
>u1 : Symbol(u1, Decl(logicalAndOperatorStrictMode.ts, 55, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
|
||||
const u2 = u && s;
|
||||
>u2 : Symbol(u2, Decl(logicalAndOperatorStrictMode.ts, 56, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
|
||||
const u3 = u && x;
|
||||
>u3 : Symbol(u3, Decl(logicalAndOperatorStrictMode.ts, 57, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
|
||||
const u4 = u && b;
|
||||
>u4 : Symbol(u4, Decl(logicalAndOperatorStrictMode.ts, 58, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
|
||||
const u5 = u && v;
|
||||
>u5 : Symbol(u5, Decl(logicalAndOperatorStrictMode.ts, 59, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
|
||||
const u6 = u && u;
|
||||
>u6 : Symbol(u6, Decl(logicalAndOperatorStrictMode.ts, 60, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
|
||||
const u7 = u && n;
|
||||
>u7 : Symbol(u7, Decl(logicalAndOperatorStrictMode.ts, 61, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
|
||||
const u8 = u && z;
|
||||
>u8 : Symbol(u8, Decl(logicalAndOperatorStrictMode.ts, 62, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
|
||||
const n1 = n && a;
|
||||
>n1 : Symbol(n1, Decl(logicalAndOperatorStrictMode.ts, 64, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
|
||||
const n2 = n && s;
|
||||
>n2 : Symbol(n2, Decl(logicalAndOperatorStrictMode.ts, 65, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
|
||||
const n3 = n && x;
|
||||
>n3 : Symbol(n3, Decl(logicalAndOperatorStrictMode.ts, 66, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
|
||||
const n4 = n && b;
|
||||
>n4 : Symbol(n4, Decl(logicalAndOperatorStrictMode.ts, 67, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
|
||||
const n5 = n && v;
|
||||
>n5 : Symbol(n5, Decl(logicalAndOperatorStrictMode.ts, 68, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
|
||||
const n6 = n && u;
|
||||
>n6 : Symbol(n6, Decl(logicalAndOperatorStrictMode.ts, 69, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
|
||||
const n7 = n && n;
|
||||
>n7 : Symbol(n7, Decl(logicalAndOperatorStrictMode.ts, 70, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
|
||||
const n8 = n && z;
|
||||
>n8 : Symbol(n8, Decl(logicalAndOperatorStrictMode.ts, 71, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
|
||||
const z1 = z && a;
|
||||
>z1 : Symbol(z1, Decl(logicalAndOperatorStrictMode.ts, 73, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
>a : Symbol(a, Decl(logicalAndOperatorStrictMode.ts, 1, 5))
|
||||
|
||||
const z2 = z && s;
|
||||
>z2 : Symbol(z2, Decl(logicalAndOperatorStrictMode.ts, 74, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
>s : Symbol(s, Decl(logicalAndOperatorStrictMode.ts, 2, 5))
|
||||
|
||||
const z3 = z && x;
|
||||
>z3 : Symbol(z3, Decl(logicalAndOperatorStrictMode.ts, 75, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
>x : Symbol(x, Decl(logicalAndOperatorStrictMode.ts, 3, 5))
|
||||
|
||||
const z4 = z && b;
|
||||
>z4 : Symbol(z4, Decl(logicalAndOperatorStrictMode.ts, 76, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
>b : Symbol(b, Decl(logicalAndOperatorStrictMode.ts, 4, 5))
|
||||
|
||||
const z5 = z && v;
|
||||
>z5 : Symbol(z5, Decl(logicalAndOperatorStrictMode.ts, 77, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
>v : Symbol(v, Decl(logicalAndOperatorStrictMode.ts, 5, 5))
|
||||
|
||||
const z6 = z && u;
|
||||
>z6 : Symbol(z6, Decl(logicalAndOperatorStrictMode.ts, 78, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
>u : Symbol(u, Decl(logicalAndOperatorStrictMode.ts, 6, 5))
|
||||
|
||||
const z7 = z && n;
|
||||
>z7 : Symbol(z7, Decl(logicalAndOperatorStrictMode.ts, 79, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
>n : Symbol(n, Decl(logicalAndOperatorStrictMode.ts, 7, 5))
|
||||
|
||||
const z8 = z && z;
|
||||
>z8 : Symbol(z8, Decl(logicalAndOperatorStrictMode.ts, 80, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
>z : Symbol(z, Decl(logicalAndOperatorStrictMode.ts, 8, 5))
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
=== tests/cases/conformance/expressions/binaryOperators/logicalAndOperator/logicalAndOperatorStrictMode.ts ===
|
||||
|
||||
const a = [0];
|
||||
>a : number[]
|
||||
>[0] : number[]
|
||||
>0 : number
|
||||
|
||||
const s = "";
|
||||
>s : string
|
||||
>"" : string
|
||||
|
||||
const x = 0;
|
||||
>x : number
|
||||
>0 : number
|
||||
|
||||
const b = false;
|
||||
>b : boolean
|
||||
>false : boolean
|
||||
|
||||
const v: void = undefined;
|
||||
>v : void
|
||||
>undefined : undefined
|
||||
|
||||
const u = undefined;
|
||||
>u : undefined
|
||||
>undefined : undefined
|
||||
|
||||
const n = null;
|
||||
>n : null
|
||||
>null : null
|
||||
|
||||
const z = s || x || u;
|
||||
>z : string | number | undefined
|
||||
>s || x || u : string | number | undefined
|
||||
>s || x : string | number
|
||||
>s : string
|
||||
>x : number
|
||||
>u : undefined
|
||||
|
||||
const a1 = a && a;
|
||||
>a1 : number[]
|
||||
>a && a : number[]
|
||||
>a : number[]
|
||||
>a : number[]
|
||||
|
||||
const a2 = a && s;
|
||||
>a2 : string
|
||||
>a && s : string
|
||||
>a : number[]
|
||||
>s : string
|
||||
|
||||
const a3 = a && x;
|
||||
>a3 : number
|
||||
>a && x : number
|
||||
>a : number[]
|
||||
>x : number
|
||||
|
||||
const a4 = a && b;
|
||||
>a4 : boolean
|
||||
>a && b : boolean
|
||||
>a : number[]
|
||||
>b : boolean
|
||||
|
||||
const a5 = a && v;
|
||||
>a5 : void
|
||||
>a && v : void
|
||||
>a : number[]
|
||||
>v : void
|
||||
|
||||
const a6 = a && u;
|
||||
>a6 : undefined
|
||||
>a && u : undefined
|
||||
>a : number[]
|
||||
>u : undefined
|
||||
|
||||
const a7 = a && n;
|
||||
>a7 : null
|
||||
>a && n : null
|
||||
>a : number[]
|
||||
>n : null
|
||||
|
||||
const a8 = a && z;
|
||||
>a8 : string | number | undefined
|
||||
>a && z : string | number | undefined
|
||||
>a : number[]
|
||||
>z : string | number | undefined
|
||||
|
||||
const s1 = s && a;
|
||||
>s1 : number[] | string
|
||||
>s && a : number[] | string
|
||||
>s : string
|
||||
>a : number[]
|
||||
|
||||
const s2 = s && s;
|
||||
>s2 : string
|
||||
>s && s : string
|
||||
>s : string
|
||||
>s : string
|
||||
|
||||
const s3 = s && x;
|
||||
>s3 : number | string
|
||||
>s && x : number | string
|
||||
>s : string
|
||||
>x : number
|
||||
|
||||
const s4 = s && b;
|
||||
>s4 : boolean | string
|
||||
>s && b : boolean | string
|
||||
>s : string
|
||||
>b : boolean
|
||||
|
||||
const s5 = s && v;
|
||||
>s5 : void | string
|
||||
>s && v : void | string
|
||||
>s : string
|
||||
>v : void
|
||||
|
||||
const s6 = s && u;
|
||||
>s6 : string | undefined
|
||||
>s && u : string | undefined
|
||||
>s : string
|
||||
>u : undefined
|
||||
|
||||
const s7 = s && n;
|
||||
>s7 : string | null
|
||||
>s && n : string | null
|
||||
>s : string
|
||||
>n : null
|
||||
|
||||
const s8 = s && z;
|
||||
>s8 : string | number | undefined
|
||||
>s && z : string | number | undefined
|
||||
>s : string
|
||||
>z : string | number | undefined
|
||||
|
||||
const x1 = x && a;
|
||||
>x1 : number[] | number
|
||||
>x && a : number[] | number
|
||||
>x : number
|
||||
>a : number[]
|
||||
|
||||
const x2 = x && s;
|
||||
>x2 : string | number
|
||||
>x && s : string | number
|
||||
>x : number
|
||||
>s : string
|
||||
|
||||
const x3 = x && x;
|
||||
>x3 : number
|
||||
>x && x : number
|
||||
>x : number
|
||||
>x : number
|
||||
|
||||
const x4 = x && b;
|
||||
>x4 : boolean | number
|
||||
>x && b : boolean | number
|
||||
>x : number
|
||||
>b : boolean
|
||||
|
||||
const x5 = x && v;
|
||||
>x5 : void | number
|
||||
>x && v : void | number
|
||||
>x : number
|
||||
>v : void
|
||||
|
||||
const x6 = x && u;
|
||||
>x6 : number | undefined
|
||||
>x && u : number | undefined
|
||||
>x : number
|
||||
>u : undefined
|
||||
|
||||
const x7 = x && n;
|
||||
>x7 : number | null
|
||||
>x && n : number | null
|
||||
>x : number
|
||||
>n : null
|
||||
|
||||
const x8 = x && z;
|
||||
>x8 : string | number | undefined
|
||||
>x && z : string | number | undefined
|
||||
>x : number
|
||||
>z : string | number | undefined
|
||||
|
||||
const b1 = b && a;
|
||||
>b1 : number[] | boolean
|
||||
>b && a : number[] | boolean
|
||||
>b : boolean
|
||||
>a : number[]
|
||||
|
||||
const b2 = b && s;
|
||||
>b2 : string | boolean
|
||||
>b && s : string | boolean
|
||||
>b : boolean
|
||||
>s : string
|
||||
|
||||
const b3 = b && x;
|
||||
>b3 : number | boolean
|
||||
>b && x : number | boolean
|
||||
>b : boolean
|
||||
>x : number
|
||||
|
||||
const b4 = b && b;
|
||||
>b4 : boolean
|
||||
>b && b : boolean
|
||||
>b : boolean
|
||||
>b : boolean
|
||||
|
||||
const b5 = b && v;
|
||||
>b5 : void | boolean
|
||||
>b && v : void | boolean
|
||||
>b : boolean
|
||||
>v : void
|
||||
|
||||
const b6 = b && u;
|
||||
>b6 : boolean | undefined
|
||||
>b && u : boolean | undefined
|
||||
>b : boolean
|
||||
>u : undefined
|
||||
|
||||
const b7 = b && n;
|
||||
>b7 : boolean | null
|
||||
>b && n : boolean | null
|
||||
>b : boolean
|
||||
>n : null
|
||||
|
||||
const b8 = b && z;
|
||||
>b8 : string | number | boolean | undefined
|
||||
>b && z : string | number | boolean | undefined
|
||||
>b : boolean
|
||||
>z : string | number | undefined
|
||||
|
||||
const v1 = v && a;
|
||||
>v1 : number[] | void
|
||||
>v && a : number[] | void
|
||||
>v : void
|
||||
>a : number[]
|
||||
|
||||
const v2 = v && s;
|
||||
>v2 : string | void
|
||||
>v && s : string | void
|
||||
>v : void
|
||||
>s : string
|
||||
|
||||
const v3 = v && x;
|
||||
>v3 : number | void
|
||||
>v && x : number | void
|
||||
>v : void
|
||||
>x : number
|
||||
|
||||
const v4 = v && b;
|
||||
>v4 : boolean | void
|
||||
>v && b : boolean | void
|
||||
>v : void
|
||||
>b : boolean
|
||||
|
||||
const v5 = v && v;
|
||||
>v5 : void
|
||||
>v && v : void
|
||||
>v : void
|
||||
>v : never
|
||||
|
||||
const v6 = v && u;
|
||||
>v6 : void
|
||||
>v && u : void
|
||||
>v : void
|
||||
>u : undefined
|
||||
|
||||
const v7 = v && n;
|
||||
>v7 : void | null
|
||||
>v && n : void | null
|
||||
>v : void
|
||||
>n : null
|
||||
|
||||
const v8 = v && z;
|
||||
>v8 : string | number | void
|
||||
>v && z : string | number | void
|
||||
>v : void
|
||||
>z : string | number | undefined
|
||||
|
||||
const u1 = u && a;
|
||||
>u1 : number[] | undefined
|
||||
>u && a : number[] | undefined
|
||||
>u : undefined
|
||||
>a : number[]
|
||||
|
||||
const u2 = u && s;
|
||||
>u2 : string | undefined
|
||||
>u && s : string | undefined
|
||||
>u : undefined
|
||||
>s : string
|
||||
|
||||
const u3 = u && x;
|
||||
>u3 : number | undefined
|
||||
>u && x : number | undefined
|
||||
>u : undefined
|
||||
>x : number
|
||||
|
||||
const u4 = u && b;
|
||||
>u4 : boolean | undefined
|
||||
>u && b : boolean | undefined
|
||||
>u : undefined
|
||||
>b : boolean
|
||||
|
||||
const u5 = u && v;
|
||||
>u5 : void
|
||||
>u && v : void
|
||||
>u : undefined
|
||||
>v : void
|
||||
|
||||
const u6 = u && u;
|
||||
>u6 : undefined
|
||||
>u && u : undefined
|
||||
>u : undefined
|
||||
>u : never
|
||||
|
||||
const u7 = u && n;
|
||||
>u7 : null | undefined
|
||||
>u && n : null | undefined
|
||||
>u : undefined
|
||||
>n : null
|
||||
|
||||
const u8 = u && z;
|
||||
>u8 : string | number | undefined
|
||||
>u && z : string | number | undefined
|
||||
>u : undefined
|
||||
>z : string | number | undefined
|
||||
|
||||
const n1 = n && a;
|
||||
>n1 : number[] | null
|
||||
>n && a : number[] | null
|
||||
>n : null
|
||||
>a : number[]
|
||||
|
||||
const n2 = n && s;
|
||||
>n2 : string | null
|
||||
>n && s : string | null
|
||||
>n : null
|
||||
>s : string
|
||||
|
||||
const n3 = n && x;
|
||||
>n3 : number | null
|
||||
>n && x : number | null
|
||||
>n : null
|
||||
>x : number
|
||||
|
||||
const n4 = n && b;
|
||||
>n4 : boolean | null
|
||||
>n && b : boolean | null
|
||||
>n : null
|
||||
>b : boolean
|
||||
|
||||
const n5 = n && v;
|
||||
>n5 : void | null
|
||||
>n && v : void | null
|
||||
>n : null
|
||||
>v : void
|
||||
|
||||
const n6 = n && u;
|
||||
>n6 : null | undefined
|
||||
>n && u : null | undefined
|
||||
>n : null
|
||||
>u : undefined
|
||||
|
||||
const n7 = n && n;
|
||||
>n7 : null
|
||||
>n && n : null
|
||||
>n : null
|
||||
>n : never
|
||||
|
||||
const n8 = n && z;
|
||||
>n8 : string | number | null | undefined
|
||||
>n && z : string | number | null | undefined
|
||||
>n : null
|
||||
>z : string | number | undefined
|
||||
|
||||
const z1 = z && a;
|
||||
>z1 : number[] | string | number | undefined
|
||||
>z && a : number[] | string | number | undefined
|
||||
>z : string | number | undefined
|
||||
>a : number[]
|
||||
|
||||
const z2 = z && s;
|
||||
>z2 : string | number | undefined
|
||||
>z && s : string | number | undefined
|
||||
>z : string | number | undefined
|
||||
>s : string
|
||||
|
||||
const z3 = z && x;
|
||||
>z3 : number | string | undefined
|
||||
>z && x : number | string | undefined
|
||||
>z : string | number | undefined
|
||||
>x : number
|
||||
|
||||
const z4 = z && b;
|
||||
>z4 : boolean | string | number | undefined
|
||||
>z && b : boolean | string | number | undefined
|
||||
>z : string | number | undefined
|
||||
>b : boolean
|
||||
|
||||
const z5 = z && v;
|
||||
>z5 : void | string | number
|
||||
>z && v : void | string | number
|
||||
>z : string | number | undefined
|
||||
>v : void
|
||||
|
||||
const z6 = z && u;
|
||||
>z6 : string | number | undefined
|
||||
>z && u : string | number | undefined
|
||||
>z : string | number | undefined
|
||||
>u : undefined
|
||||
|
||||
const z7 = z && n;
|
||||
>z7 : string | number | null | undefined
|
||||
>z && n : string | number | null | undefined
|
||||
>z : string | number | undefined
|
||||
>n : null
|
||||
|
||||
const z8 = z && z;
|
||||
>z8 : string | number | undefined
|
||||
>z && z : string | number | undefined
|
||||
>z : string | number | undefined
|
||||
>z : string | number
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
//// [tests/cases/conformance/externalModules/moduleResolutionWithExtensions.ts] ////
|
||||
|
||||
//// [a.ts]
|
||||
|
||||
export default 0;
|
||||
|
||||
// No extension: '.ts' added
|
||||
//// [b.ts]
|
||||
import a from './a';
|
||||
|
||||
// Matching extension
|
||||
//// [c.ts]
|
||||
import a from './a.ts';
|
||||
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
//// [d.ts]
|
||||
import a from './a.js';
|
||||
|
||||
//// [jquery.d.ts]
|
||||
declare var x: number;
|
||||
export default x;
|
||||
|
||||
// No extension: '.d.ts' added
|
||||
//// [jquery_user_1.ts]
|
||||
import j from "./jquery";
|
||||
|
||||
// '.js' extension: stripped and replaced with '.d.ts'
|
||||
//// [jquery_user_1.ts]
|
||||
import j from "./jquery.js"
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports["default"] = 0;
|
||||
// No extension: '.ts' added
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
// Matching extension
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
//// [d.js]
|
||||
"use strict";
|
||||
//// [jquery_user_1.js]
|
||||
"use strict";
|
||||
@@ -0,0 +1,37 @@
|
||||
=== /src/a.ts ===
|
||||
|
||||
No type information for this code.export default 0;
|
||||
No type information for this code.
|
||||
No type information for this code.// No extension: '.ts' added
|
||||
No type information for this code.=== /src/b.ts ===
|
||||
import a from './a';
|
||||
>a : Symbol(a, Decl(b.ts, 0, 6))
|
||||
|
||||
// Matching extension
|
||||
=== /src/c.ts ===
|
||||
import a from './a.ts';
|
||||
>a : Symbol(a, Decl(c.ts, 0, 6))
|
||||
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
=== /src/d.ts ===
|
||||
import a from './a.js';
|
||||
>a : Symbol(a, Decl(d.ts, 0, 6))
|
||||
|
||||
=== /src/jquery.d.ts ===
|
||||
declare var x: number;
|
||||
>x : Symbol(x, Decl(jquery.d.ts, 0, 11))
|
||||
|
||||
export default x;
|
||||
>x : Symbol(x, Decl(jquery.d.ts, 0, 11))
|
||||
|
||||
// No extension: '.d.ts' added
|
||||
=== /src/jquery_user_1.ts ===
|
||||
import j from "./jquery";
|
||||
>j : Symbol(j, Decl(jquery_user_1.ts, 0, 6))
|
||||
|
||||
// '.js' extension: stripped and replaced with '.d.ts'
|
||||
=== /src/jquery_user_1.ts ===
|
||||
import j from "./jquery.js"
|
||||
>j : Symbol(j, Decl(jquery_user_1.ts, 0, 6))
|
||||
>j : Symbol(j, Decl(jquery_user_1.ts, 0, 6))
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
[
|
||||
"======== Resolving module './a' from '/src/b.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'NodeJs'.",
|
||||
"Loading module as file / folder, candidate module location '/src/a'.",
|
||||
"File '/src/a.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name './a' was successfully resolved to '/src/a.ts'. ========",
|
||||
"======== Resolving module './a.ts' from '/src/c.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'NodeJs'.",
|
||||
"Loading module as file / folder, candidate module location '/src/a.ts'.",
|
||||
"File '/src/a.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name './a.ts' was successfully resolved to '/src/a.ts'. ========",
|
||||
"======== Resolving module './a.js' from '/src/d.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'NodeJs'.",
|
||||
"Loading module as file / folder, candidate module location '/src/a.js'.",
|
||||
"File '/src/a.js.ts' does not exist.",
|
||||
"File '/src/a.js.tsx' does not exist.",
|
||||
"File '/src/a.js.d.ts' does not exist.",
|
||||
"File name '/src/a.js' has a '.js' extension - stripping it",
|
||||
"File '/src/a.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name './a.js' was successfully resolved to '/src/a.ts'. ========",
|
||||
"======== Resolving module './jquery.js' from '/src/jquery_user_1.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'NodeJs'.",
|
||||
"Loading module as file / folder, candidate module location '/src/jquery.js'.",
|
||||
"File '/src/jquery.js.ts' does not exist.",
|
||||
"File '/src/jquery.js.tsx' does not exist.",
|
||||
"File '/src/jquery.js.d.ts' does not exist.",
|
||||
"File name '/src/jquery.js' has a '.js' extension - stripping it",
|
||||
"File '/src/jquery.ts' does not exist.",
|
||||
"File '/src/jquery.tsx' does not exist.",
|
||||
"File '/src/jquery.d.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name './jquery.js' was successfully resolved to '/src/jquery.d.ts'. ========"
|
||||
]
|
||||
@@ -0,0 +1,37 @@
|
||||
=== /src/a.ts ===
|
||||
|
||||
No type information for this code.export default 0;
|
||||
No type information for this code.
|
||||
No type information for this code.// No extension: '.ts' added
|
||||
No type information for this code.=== /src/b.ts ===
|
||||
import a from './a';
|
||||
>a : number
|
||||
|
||||
// Matching extension
|
||||
=== /src/c.ts ===
|
||||
import a from './a.ts';
|
||||
>a : number
|
||||
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
=== /src/d.ts ===
|
||||
import a from './a.js';
|
||||
>a : number
|
||||
|
||||
=== /src/jquery.d.ts ===
|
||||
declare var x: number;
|
||||
>x : number
|
||||
|
||||
export default x;
|
||||
>x : number
|
||||
|
||||
// No extension: '.d.ts' added
|
||||
=== /src/jquery_user_1.ts ===
|
||||
import j from "./jquery";
|
||||
>j : number
|
||||
|
||||
// '.js' extension: stripped and replaced with '.d.ts'
|
||||
=== /src/jquery_user_1.ts ===
|
||||
import j from "./jquery.js"
|
||||
>j : number
|
||||
>j : number
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
tests/cases/conformance/externalModules/foo_1.ts(1,22): error TS2307: Cannot find module './foo_0.js'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/externalModules/foo_1.ts (1 errors) ====
|
||||
import foo = require('./foo_0.js');
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2307: Cannot find module './foo_0.js'.
|
||||
var x = foo.foo + 42;
|
||||
|
||||
==== tests/cases/conformance/externalModules/foo_0.ts (0 errors) ====
|
||||
export var foo = 42;
|
||||
|
||||
@@ -8,6 +8,9 @@ import foo = require('./foo_0.js');
|
||||
var x = foo.foo + 42;
|
||||
|
||||
|
||||
//// [foo_0.js]
|
||||
"use strict";
|
||||
exports.foo = 42;
|
||||
//// [foo_1.js]
|
||||
"use strict";
|
||||
var foo = require('./foo_0.js');
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
=== tests/cases/conformance/externalModules/foo_1.ts ===
|
||||
import foo = require('./foo_0.js');
|
||||
>foo : Symbol(foo, Decl(foo_1.ts, 0, 0))
|
||||
|
||||
var x = foo.foo + 42;
|
||||
>x : Symbol(x, Decl(foo_1.ts, 1, 3))
|
||||
>foo.foo : Symbol(foo.foo, Decl(foo_0.ts, 0, 10))
|
||||
>foo : Symbol(foo, Decl(foo_1.ts, 0, 0))
|
||||
>foo : Symbol(foo.foo, Decl(foo_0.ts, 0, 10))
|
||||
|
||||
=== tests/cases/conformance/externalModules/foo_0.ts ===
|
||||
export var foo = 42;
|
||||
>foo : Symbol(foo, Decl(foo_0.ts, 0, 10))
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
=== tests/cases/conformance/externalModules/foo_1.ts ===
|
||||
import foo = require('./foo_0.js');
|
||||
>foo : typeof foo
|
||||
|
||||
var x = foo.foo + 42;
|
||||
>x : number
|
||||
>foo.foo + 42 : number
|
||||
>foo.foo : number
|
||||
>foo : typeof foo
|
||||
>foo : number
|
||||
>42 : number
|
||||
|
||||
=== tests/cases/conformance/externalModules/foo_0.ts ===
|
||||
export var foo = 42;
|
||||
>foo : number
|
||||
>42 : number
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
error TS5053: Option 'sourceRoot' cannot be specified with option 'inlineSources'.
|
||||
|
||||
|
||||
!!! error TS5053: Option 'sourceRoot' cannot be specified with option 'inlineSources'.
|
||||
==== tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts (0 errors) ====
|
||||
|
||||
var a = 10;
|
||||
@@ -0,0 +1,5 @@
|
||||
=== tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts ===
|
||||
|
||||
var a = 10;
|
||||
>a : Symbol(a, Decl(optionsSourcemapInlineSourcesSourceRoot.ts, 1, 3))
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
=== tests/cases/compiler/optionsSourcemapInlineSourcesSourceRoot.ts ===
|
||||
|
||||
var a = 10;
|
||||
>a : number
|
||||
>10 : number
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
decl.ts(1,26): error TS2307: Cannot find module './foo/bar.js'.
|
||||
decl.ts(1,26): error TS2307: Cannot find module './foo/bar.tx'.
|
||||
decl.ts(2,26): error TS2307: Cannot find module 'baz'.
|
||||
decl.ts(3,26): error TS2307: Cannot find module './baz'.
|
||||
|
||||
|
||||
==== decl.ts (3 errors) ====
|
||||
import modErr = require("./foo/bar.js");
|
||||
import modErr = require("./foo/bar.tx");
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2307: Cannot find module './foo/bar.js'.
|
||||
!!! error TS2307: Cannot find module './foo/bar.tx'.
|
||||
import modErr1 = require("baz");
|
||||
~~~~~
|
||||
!!! error TS2307: Cannot find module 'baz'.
|
||||
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
decl.ts(1,26): error TS2307: Cannot find module './foo/bar.js'.
|
||||
decl.ts(1,26): error TS2307: Cannot find module './foo/bar.tx'.
|
||||
decl.ts(2,26): error TS2307: Cannot find module 'baz'.
|
||||
decl.ts(3,26): error TS2307: Cannot find module './baz'.
|
||||
|
||||
|
||||
==== decl.ts (3 errors) ====
|
||||
import modErr = require("./foo/bar.js");
|
||||
import modErr = require("./foo/bar.tx");
|
||||
~~~~~~~~~~~~~~
|
||||
!!! error TS2307: Cannot find module './foo/bar.js'.
|
||||
!!! error TS2307: Cannot find module './foo/bar.tx'.
|
||||
import modErr1 = require("baz");
|
||||
~~~~~
|
||||
!!! error TS2307: Cannot find module 'baz'.
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
error TS5051: Option 'sourceRoot can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.
|
||||
error TS5052: Option 'mapRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
error TS5052: Option 'sourceRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
|
||||
|
||||
!!! error TS5051: Option 'sourceRoot can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.
|
||||
!!! error TS5052: Option 'mapRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
!!! error TS5052: Option 'sourceRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
==== m1.ts (0 errors) ====
|
||||
var m1_a1 = 10;
|
||||
class m1_c1 {
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
error TS5051: Option 'sourceRoot can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.
|
||||
error TS5052: Option 'mapRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
error TS5052: Option 'sourceRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
|
||||
|
||||
!!! error TS5051: Option 'sourceRoot can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.
|
||||
!!! error TS5052: Option 'mapRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
!!! error TS5052: Option 'sourceRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
==== m1.ts (0 errors) ====
|
||||
var m1_a1 = 10;
|
||||
class m1_c1 {
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
error TS5052: Option 'sourceRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
error TS5051: Option 'sourceRoot can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.
|
||||
|
||||
|
||||
!!! error TS5052: Option 'sourceRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
!!! error TS5051: Option 'sourceRoot can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.
|
||||
==== m1.ts (0 errors) ====
|
||||
var m1_a1 = 10;
|
||||
class m1_c1 {
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
error TS5052: Option 'sourceRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
error TS5051: Option 'sourceRoot can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.
|
||||
|
||||
|
||||
!!! error TS5052: Option 'sourceRoot' cannot be specified without specifying option 'sourceMap'.
|
||||
!!! error TS5051: Option 'sourceRoot can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided.
|
||||
==== m1.ts (0 errors) ====
|
||||
var m1_a1 = 10;
|
||||
class m1_c1 {
|
||||
|
||||
@@ -116,6 +116,6 @@ if (!hasKind(x, "B")) {
|
||||
}
|
||||
else {
|
||||
let d = x;
|
||||
>d : never
|
||||
>x : never
|
||||
>d : A & B
|
||||
>x : A & B
|
||||
}
|
||||
|
||||
@@ -110,6 +110,6 @@ if (!hasKind(x, "B")) {
|
||||
}
|
||||
else {
|
||||
let d = x;
|
||||
>d : never
|
||||
>x : never
|
||||
>d : A & B
|
||||
>x : A & B
|
||||
}
|
||||
|
||||
@@ -113,6 +113,6 @@ if (!hasKind(x, "B")) {
|
||||
}
|
||||
else {
|
||||
let d = x;
|
||||
>d : never
|
||||
>x : never
|
||||
>d : A & B
|
||||
>x : A & B
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
//// [typeGuardIntersectionTypes.ts]
|
||||
|
||||
interface X {
|
||||
x: string;
|
||||
}
|
||||
|
||||
interface Y {
|
||||
y: string;
|
||||
}
|
||||
|
||||
interface Z {
|
||||
z: string;
|
||||
}
|
||||
|
||||
declare function isX(obj: any): obj is X;
|
||||
declare function isY(obj: any): obj is Y;
|
||||
declare function isZ(obj: any): obj is Z;
|
||||
|
||||
function f1(obj: Object) {
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8911
|
||||
|
||||
// two interfaces
|
||||
interface A {
|
||||
a: string;
|
||||
}
|
||||
|
||||
interface B {
|
||||
b: string;
|
||||
}
|
||||
|
||||
// a type guard for B
|
||||
function isB(toTest: any): toTest is B {
|
||||
return toTest && toTest.b;
|
||||
}
|
||||
|
||||
// a function that turns an A into an A & B
|
||||
function union(a: A): A & B | null {
|
||||
if (isB(a)) {
|
||||
return a;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #9016
|
||||
|
||||
declare function log(s: string): void;
|
||||
|
||||
// Supported beast features
|
||||
interface Beast { wings?: boolean; legs?: number }
|
||||
interface Legged { legs: number; }
|
||||
interface Winged { wings: boolean; }
|
||||
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x: Beast): x is Legged { return x && typeof x.legs === 'number'; }
|
||||
function hasWings(x: Beast): x is Winged { return x && !!x.wings; }
|
||||
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast: Beast) {
|
||||
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
if (beast.legs === 4) {
|
||||
log(`pegasus - 4 legs, wings`);
|
||||
}
|
||||
else if (beast.legs === 2) {
|
||||
log(`bird - 2 legs, wings`);
|
||||
}
|
||||
else {
|
||||
log(`unknown - ${beast.legs} legs, wings`);
|
||||
}
|
||||
}
|
||||
|
||||
// All non-winged beasts with legs
|
||||
else {
|
||||
log(`manbearpig - ${beast.legs} legs, no wings`);
|
||||
}
|
||||
}
|
||||
|
||||
// All beasts without legs
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
log(`quetzalcoatl - no legs, wings`)
|
||||
}
|
||||
else {
|
||||
log(`snake - no legs, no wings`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function beastFoo(beast: Object) {
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
beast; // Winged & Legged
|
||||
}
|
||||
else {
|
||||
beast;
|
||||
}
|
||||
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
beast; // Legged & Winged
|
||||
}
|
||||
}
|
||||
|
||||
//// [typeGuardIntersectionTypes.js]
|
||||
function f1(obj) {
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
}
|
||||
// a type guard for B
|
||||
function isB(toTest) {
|
||||
return toTest && toTest.b;
|
||||
}
|
||||
// a function that turns an A into an A & B
|
||||
function union(a) {
|
||||
if (isB(a)) {
|
||||
return a;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x) { return x && typeof x.legs === 'number'; }
|
||||
function hasWings(x) { return x && !!x.wings; }
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast) {
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
if (beast.legs === 4) {
|
||||
log("pegasus - 4 legs, wings");
|
||||
}
|
||||
else if (beast.legs === 2) {
|
||||
log("bird - 2 legs, wings");
|
||||
}
|
||||
else {
|
||||
log("unknown - " + beast.legs + " legs, wings");
|
||||
}
|
||||
}
|
||||
else {
|
||||
log("manbearpig - " + beast.legs + " legs, no wings");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
log("quetzalcoatl - no legs, wings");
|
||||
}
|
||||
else {
|
||||
log("snake - no legs, no wings");
|
||||
}
|
||||
}
|
||||
}
|
||||
function beastFoo(beast) {
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
beast; // Winged & Legged
|
||||
}
|
||||
else {
|
||||
beast;
|
||||
}
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
beast; // Legged & Winged
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardIntersectionTypes.ts ===
|
||||
|
||||
interface X {
|
||||
>X : Symbol(X, Decl(typeGuardIntersectionTypes.ts, 0, 0))
|
||||
|
||||
x: string;
|
||||
>x : Symbol(X.x, Decl(typeGuardIntersectionTypes.ts, 1, 13))
|
||||
}
|
||||
|
||||
interface Y {
|
||||
>Y : Symbol(Y, Decl(typeGuardIntersectionTypes.ts, 3, 1))
|
||||
|
||||
y: string;
|
||||
>y : Symbol(Y.y, Decl(typeGuardIntersectionTypes.ts, 5, 13))
|
||||
}
|
||||
|
||||
interface Z {
|
||||
>Z : Symbol(Z, Decl(typeGuardIntersectionTypes.ts, 7, 1))
|
||||
|
||||
z: string;
|
||||
>z : Symbol(Z.z, Decl(typeGuardIntersectionTypes.ts, 9, 13))
|
||||
}
|
||||
|
||||
declare function isX(obj: any): obj is X;
|
||||
>isX : Symbol(isX, Decl(typeGuardIntersectionTypes.ts, 11, 1))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 13, 21))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 13, 21))
|
||||
>X : Symbol(X, Decl(typeGuardIntersectionTypes.ts, 0, 0))
|
||||
|
||||
declare function isY(obj: any): obj is Y;
|
||||
>isY : Symbol(isY, Decl(typeGuardIntersectionTypes.ts, 13, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 14, 21))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 14, 21))
|
||||
>Y : Symbol(Y, Decl(typeGuardIntersectionTypes.ts, 3, 1))
|
||||
|
||||
declare function isZ(obj: any): obj is Z;
|
||||
>isZ : Symbol(isZ, Decl(typeGuardIntersectionTypes.ts, 14, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 15, 21))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 15, 21))
|
||||
>Z : Symbol(Z, Decl(typeGuardIntersectionTypes.ts, 7, 1))
|
||||
|
||||
function f1(obj: Object) {
|
||||
>f1 : Symbol(f1, Decl(typeGuardIntersectionTypes.ts, 15, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
>isX : Symbol(isX, Decl(typeGuardIntersectionTypes.ts, 11, 1))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>isY : Symbol(isY, Decl(typeGuardIntersectionTypes.ts, 13, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>isZ : Symbol(isZ, Decl(typeGuardIntersectionTypes.ts, 14, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
|
||||
obj;
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
>isX : Symbol(isX, Decl(typeGuardIntersectionTypes.ts, 11, 1))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>isY : Symbol(isY, Decl(typeGuardIntersectionTypes.ts, 13, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
>isZ : Symbol(isZ, Decl(typeGuardIntersectionTypes.ts, 14, 41))
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
|
||||
obj;
|
||||
>obj : Symbol(obj, Decl(typeGuardIntersectionTypes.ts, 17, 12))
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8911
|
||||
|
||||
// two interfaces
|
||||
interface A {
|
||||
>A : Symbol(A, Decl(typeGuardIntersectionTypes.ts, 24, 1))
|
||||
|
||||
a: string;
|
||||
>a : Symbol(A.a, Decl(typeGuardIntersectionTypes.ts, 29, 13))
|
||||
}
|
||||
|
||||
interface B {
|
||||
>B : Symbol(B, Decl(typeGuardIntersectionTypes.ts, 31, 1))
|
||||
|
||||
b: string;
|
||||
>b : Symbol(B.b, Decl(typeGuardIntersectionTypes.ts, 33, 13))
|
||||
}
|
||||
|
||||
// a type guard for B
|
||||
function isB(toTest: any): toTest is B {
|
||||
>isB : Symbol(isB, Decl(typeGuardIntersectionTypes.ts, 35, 1))
|
||||
>toTest : Symbol(toTest, Decl(typeGuardIntersectionTypes.ts, 38, 13))
|
||||
>toTest : Symbol(toTest, Decl(typeGuardIntersectionTypes.ts, 38, 13))
|
||||
>B : Symbol(B, Decl(typeGuardIntersectionTypes.ts, 31, 1))
|
||||
|
||||
return toTest && toTest.b;
|
||||
>toTest : Symbol(toTest, Decl(typeGuardIntersectionTypes.ts, 38, 13))
|
||||
>toTest : Symbol(toTest, Decl(typeGuardIntersectionTypes.ts, 38, 13))
|
||||
}
|
||||
|
||||
// a function that turns an A into an A & B
|
||||
function union(a: A): A & B | null {
|
||||
>union : Symbol(union, Decl(typeGuardIntersectionTypes.ts, 40, 1))
|
||||
>a : Symbol(a, Decl(typeGuardIntersectionTypes.ts, 43, 15))
|
||||
>A : Symbol(A, Decl(typeGuardIntersectionTypes.ts, 24, 1))
|
||||
>A : Symbol(A, Decl(typeGuardIntersectionTypes.ts, 24, 1))
|
||||
>B : Symbol(B, Decl(typeGuardIntersectionTypes.ts, 31, 1))
|
||||
|
||||
if (isB(a)) {
|
||||
>isB : Symbol(isB, Decl(typeGuardIntersectionTypes.ts, 35, 1))
|
||||
>a : Symbol(a, Decl(typeGuardIntersectionTypes.ts, 43, 15))
|
||||
|
||||
return a;
|
||||
>a : Symbol(a, Decl(typeGuardIntersectionTypes.ts, 43, 15))
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #9016
|
||||
|
||||
declare function log(s: string): void;
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
>s : Symbol(s, Decl(typeGuardIntersectionTypes.ts, 53, 21))
|
||||
|
||||
// Supported beast features
|
||||
interface Beast { wings?: boolean; legs?: number }
|
||||
>Beast : Symbol(Beast, Decl(typeGuardIntersectionTypes.ts, 53, 38))
|
||||
>wings : Symbol(Beast.wings, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>legs : Symbol(Beast.legs, Decl(typeGuardIntersectionTypes.ts, 56, 38))
|
||||
|
||||
interface Legged { legs: number; }
|
||||
>Legged : Symbol(Legged, Decl(typeGuardIntersectionTypes.ts, 56, 54))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
|
||||
interface Winged { wings: boolean; }
|
||||
>Winged : Symbol(Winged, Decl(typeGuardIntersectionTypes.ts, 57, 37))
|
||||
>wings : Symbol(Winged.wings, Decl(typeGuardIntersectionTypes.ts, 58, 21))
|
||||
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x: Beast): x is Legged { return x && typeof x.legs === 'number'; }
|
||||
>hasLegs : Symbol(hasLegs, Decl(typeGuardIntersectionTypes.ts, 58, 39))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 61, 17))
|
||||
>Beast : Symbol(Beast, Decl(typeGuardIntersectionTypes.ts, 53, 38))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 61, 17))
|
||||
>Legged : Symbol(Legged, Decl(typeGuardIntersectionTypes.ts, 56, 54))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 61, 17))
|
||||
>x.legs : Symbol(Beast.legs, Decl(typeGuardIntersectionTypes.ts, 56, 38))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 61, 17))
|
||||
>legs : Symbol(Beast.legs, Decl(typeGuardIntersectionTypes.ts, 56, 38))
|
||||
|
||||
function hasWings(x: Beast): x is Winged { return x && !!x.wings; }
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 62, 18))
|
||||
>Beast : Symbol(Beast, Decl(typeGuardIntersectionTypes.ts, 53, 38))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 62, 18))
|
||||
>Winged : Symbol(Winged, Decl(typeGuardIntersectionTypes.ts, 57, 37))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 62, 18))
|
||||
>x.wings : Symbol(Beast.wings, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
>x : Symbol(x, Decl(typeGuardIntersectionTypes.ts, 62, 18))
|
||||
>wings : Symbol(Beast.wings, Decl(typeGuardIntersectionTypes.ts, 56, 21))
|
||||
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast: Beast) {
|
||||
>identifyBeast : Symbol(identifyBeast, Decl(typeGuardIntersectionTypes.ts, 62, 67))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>Beast : Symbol(Beast, Decl(typeGuardIntersectionTypes.ts, 53, 38))
|
||||
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
>hasLegs : Symbol(hasLegs, Decl(typeGuardIntersectionTypes.ts, 58, 39))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
|
||||
if (beast.legs === 4) {
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
|
||||
log(`pegasus - 4 legs, wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
}
|
||||
else if (beast.legs === 2) {
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
|
||||
log(`bird - 2 legs, wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
}
|
||||
else {
|
||||
log(`unknown - ${beast.legs} legs, wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
}
|
||||
}
|
||||
|
||||
// All non-winged beasts with legs
|
||||
else {
|
||||
log(`manbearpig - ${beast.legs} legs, no wings`);
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
>beast.legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
>legs : Symbol(Legged.legs, Decl(typeGuardIntersectionTypes.ts, 57, 21))
|
||||
}
|
||||
}
|
||||
|
||||
// All beasts without legs
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 65, 23))
|
||||
|
||||
log(`quetzalcoatl - no legs, wings`)
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
}
|
||||
else {
|
||||
log(`snake - no legs, no wings`)
|
||||
>log : Symbol(log, Decl(typeGuardIntersectionTypes.ts, 49, 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function beastFoo(beast: Object) {
|
||||
>beastFoo : Symbol(beastFoo, Decl(typeGuardIntersectionTypes.ts, 98, 1))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
>hasLegs : Symbol(hasLegs, Decl(typeGuardIntersectionTypes.ts, 58, 39))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
|
||||
beast; // Winged & Legged
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
}
|
||||
else {
|
||||
beast;
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
}
|
||||
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
>hasLegs : Symbol(hasLegs, Decl(typeGuardIntersectionTypes.ts, 58, 39))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
>hasWings : Symbol(hasWings, Decl(typeGuardIntersectionTypes.ts, 61, 83))
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
|
||||
beast; // Legged & Winged
|
||||
>beast : Symbol(beast, Decl(typeGuardIntersectionTypes.ts, 100, 18))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardIntersectionTypes.ts ===
|
||||
|
||||
interface X {
|
||||
>X : X
|
||||
|
||||
x: string;
|
||||
>x : string
|
||||
}
|
||||
|
||||
interface Y {
|
||||
>Y : Y
|
||||
|
||||
y: string;
|
||||
>y : string
|
||||
}
|
||||
|
||||
interface Z {
|
||||
>Z : Z
|
||||
|
||||
z: string;
|
||||
>z : string
|
||||
}
|
||||
|
||||
declare function isX(obj: any): obj is X;
|
||||
>isX : (obj: any) => obj is X
|
||||
>obj : any
|
||||
>obj : any
|
||||
>X : X
|
||||
|
||||
declare function isY(obj: any): obj is Y;
|
||||
>isY : (obj: any) => obj is Y
|
||||
>obj : any
|
||||
>obj : any
|
||||
>Y : Y
|
||||
|
||||
declare function isZ(obj: any): obj is Z;
|
||||
>isZ : (obj: any) => obj is Z
|
||||
>obj : any
|
||||
>obj : any
|
||||
>Z : Z
|
||||
|
||||
function f1(obj: Object) {
|
||||
>f1 : (obj: Object) => void
|
||||
>obj : Object
|
||||
>Object : Object
|
||||
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
>isX(obj) || isY(obj) || isZ(obj) : boolean
|
||||
>isX(obj) || isY(obj) : boolean
|
||||
>isX(obj) : boolean
|
||||
>isX : (obj: any) => obj is X
|
||||
>obj : Object
|
||||
>isY(obj) : boolean
|
||||
>isY : (obj: any) => obj is Y
|
||||
>obj : Object
|
||||
>isZ(obj) : boolean
|
||||
>isZ : (obj: any) => obj is Z
|
||||
>obj : Object
|
||||
|
||||
obj;
|
||||
>obj : X | Y | Z
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
>isX(obj) && isY(obj) && isZ(obj) : boolean
|
||||
>isX(obj) && isY(obj) : boolean
|
||||
>isX(obj) : boolean
|
||||
>isX : (obj: any) => obj is X
|
||||
>obj : Object
|
||||
>isY(obj) : boolean
|
||||
>isY : (obj: any) => obj is Y
|
||||
>obj : X
|
||||
>isZ(obj) : boolean
|
||||
>isZ : (obj: any) => obj is Z
|
||||
>obj : X & Y
|
||||
|
||||
obj;
|
||||
>obj : X & Y & Z
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8911
|
||||
|
||||
// two interfaces
|
||||
interface A {
|
||||
>A : A
|
||||
|
||||
a: string;
|
||||
>a : string
|
||||
}
|
||||
|
||||
interface B {
|
||||
>B : B
|
||||
|
||||
b: string;
|
||||
>b : string
|
||||
}
|
||||
|
||||
// a type guard for B
|
||||
function isB(toTest: any): toTest is B {
|
||||
>isB : (toTest: any) => toTest is B
|
||||
>toTest : any
|
||||
>toTest : any
|
||||
>B : B
|
||||
|
||||
return toTest && toTest.b;
|
||||
>toTest && toTest.b : any
|
||||
>toTest : any
|
||||
>toTest.b : any
|
||||
>toTest : any
|
||||
>b : any
|
||||
}
|
||||
|
||||
// a function that turns an A into an A & B
|
||||
function union(a: A): A & B | null {
|
||||
>union : (a: A) => (A & B) | null
|
||||
>a : A
|
||||
>A : A
|
||||
>A : A
|
||||
>B : B
|
||||
>null : null
|
||||
|
||||
if (isB(a)) {
|
||||
>isB(a) : boolean
|
||||
>isB : (toTest: any) => toTest is B
|
||||
>a : A
|
||||
|
||||
return a;
|
||||
>a : A & B
|
||||
|
||||
} else {
|
||||
return null;
|
||||
>null : null
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #9016
|
||||
|
||||
declare function log(s: string): void;
|
||||
>log : (s: string) => void
|
||||
>s : string
|
||||
|
||||
// Supported beast features
|
||||
interface Beast { wings?: boolean; legs?: number }
|
||||
>Beast : Beast
|
||||
>wings : boolean | undefined
|
||||
>legs : number | undefined
|
||||
|
||||
interface Legged { legs: number; }
|
||||
>Legged : Legged
|
||||
>legs : number
|
||||
|
||||
interface Winged { wings: boolean; }
|
||||
>Winged : Winged
|
||||
>wings : boolean
|
||||
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x: Beast): x is Legged { return x && typeof x.legs === 'number'; }
|
||||
>hasLegs : (x: Beast) => x is Legged
|
||||
>x : Beast
|
||||
>Beast : Beast
|
||||
>x : any
|
||||
>Legged : Legged
|
||||
>x && typeof x.legs === 'number' : boolean
|
||||
>x : Beast
|
||||
>typeof x.legs === 'number' : boolean
|
||||
>typeof x.legs : string
|
||||
>x.legs : number | undefined
|
||||
>x : Beast
|
||||
>legs : number | undefined
|
||||
>'number' : string
|
||||
|
||||
function hasWings(x: Beast): x is Winged { return x && !!x.wings; }
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>x : Beast
|
||||
>Beast : Beast
|
||||
>x : any
|
||||
>Winged : Winged
|
||||
>x && !!x.wings : boolean
|
||||
>x : Beast
|
||||
>!!x.wings : boolean
|
||||
>!x.wings : boolean
|
||||
>x.wings : boolean | undefined
|
||||
>x : Beast
|
||||
>wings : boolean | undefined
|
||||
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast: Beast) {
|
||||
>identifyBeast : (beast: Beast) => void
|
||||
>beast : Beast
|
||||
>Beast : Beast
|
||||
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
>hasLegs(beast) : boolean
|
||||
>hasLegs : (x: Beast) => x is Legged
|
||||
>beast : Beast
|
||||
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
>hasWings(beast) : boolean
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>beast : Legged
|
||||
|
||||
if (beast.legs === 4) {
|
||||
>beast.legs === 4 : boolean
|
||||
>beast.legs : number
|
||||
>beast : Legged & Winged
|
||||
>legs : number
|
||||
>4 : number
|
||||
|
||||
log(`pegasus - 4 legs, wings`);
|
||||
>log(`pegasus - 4 legs, wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`pegasus - 4 legs, wings` : string
|
||||
}
|
||||
else if (beast.legs === 2) {
|
||||
>beast.legs === 2 : boolean
|
||||
>beast.legs : number
|
||||
>beast : Legged & Winged
|
||||
>legs : number
|
||||
>2 : number
|
||||
|
||||
log(`bird - 2 legs, wings`);
|
||||
>log(`bird - 2 legs, wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`bird - 2 legs, wings` : string
|
||||
}
|
||||
else {
|
||||
log(`unknown - ${beast.legs} legs, wings`);
|
||||
>log(`unknown - ${beast.legs} legs, wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`unknown - ${beast.legs} legs, wings` : string
|
||||
>beast.legs : number
|
||||
>beast : Legged & Winged
|
||||
>legs : number
|
||||
}
|
||||
}
|
||||
|
||||
// All non-winged beasts with legs
|
||||
else {
|
||||
log(`manbearpig - ${beast.legs} legs, no wings`);
|
||||
>log(`manbearpig - ${beast.legs} legs, no wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`manbearpig - ${beast.legs} legs, no wings` : string
|
||||
>beast.legs : number
|
||||
>beast : Legged
|
||||
>legs : number
|
||||
}
|
||||
}
|
||||
|
||||
// All beasts without legs
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
>hasWings(beast) : boolean
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>beast : Beast
|
||||
|
||||
log(`quetzalcoatl - no legs, wings`)
|
||||
>log(`quetzalcoatl - no legs, wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`quetzalcoatl - no legs, wings` : string
|
||||
}
|
||||
else {
|
||||
log(`snake - no legs, no wings`)
|
||||
>log(`snake - no legs, no wings`) : void
|
||||
>log : (s: string) => void
|
||||
>`snake - no legs, no wings` : string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function beastFoo(beast: Object) {
|
||||
>beastFoo : (beast: Object) => void
|
||||
>beast : Object
|
||||
>Object : Object
|
||||
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
>hasWings(beast) && hasLegs(beast) : boolean
|
||||
>hasWings(beast) : boolean
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>beast : Object
|
||||
>hasLegs(beast) : boolean
|
||||
>hasLegs : (x: Beast) => x is Legged
|
||||
>beast : Winged
|
||||
|
||||
beast; // Winged & Legged
|
||||
>beast : Winged & Legged
|
||||
}
|
||||
else {
|
||||
beast;
|
||||
>beast : Object
|
||||
}
|
||||
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
>hasLegs(beast) && hasWings(beast) : boolean
|
||||
>hasLegs(beast) : boolean
|
||||
>hasLegs : (x: Beast) => x is Legged
|
||||
>beast : Object
|
||||
>hasWings(beast) : boolean
|
||||
>hasWings : (x: Beast) => x is Winged
|
||||
>beast : Legged
|
||||
|
||||
beast; // Legged & Winged
|
||||
>beast : Legged & Winged
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//// [typeGuardsNestedAssignments.ts]
|
||||
|
||||
class Foo {
|
||||
x: string;
|
||||
}
|
||||
|
||||
declare function getFooOrNull(): Foo | null;
|
||||
declare function getStringOrNumberOrNull(): string | number | null;
|
||||
|
||||
function f1() {
|
||||
let foo: Foo | null;
|
||||
if ((foo = getFooOrNull()) !== null) {
|
||||
foo; // Foo
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
let foo1: Foo | null;
|
||||
let foo2: Foo | null;
|
||||
if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) {
|
||||
foo1; // Foo | null
|
||||
foo2; // Foo
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
let obj: Object | null;
|
||||
if ((obj = getFooOrNull()) instanceof Foo) {
|
||||
obj;
|
||||
}
|
||||
}
|
||||
|
||||
function f4() {
|
||||
let x: string | number | null;
|
||||
if (typeof (x = getStringOrNumberOrNull()) === "number") {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8851
|
||||
|
||||
const re = /./g
|
||||
let match: RegExpExecArray | null
|
||||
|
||||
while ((match = re.exec("xxx")) != null) {
|
||||
const length = match[1].length + match[2].length
|
||||
}
|
||||
|
||||
//// [typeGuardsNestedAssignments.js]
|
||||
var Foo = (function () {
|
||||
function Foo() {
|
||||
}
|
||||
return Foo;
|
||||
}());
|
||||
function f1() {
|
||||
var foo;
|
||||
if ((foo = getFooOrNull()) !== null) {
|
||||
foo; // Foo
|
||||
}
|
||||
}
|
||||
function f2() {
|
||||
var foo1;
|
||||
var foo2;
|
||||
if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) {
|
||||
foo1; // Foo | null
|
||||
foo2; // Foo
|
||||
}
|
||||
}
|
||||
function f3() {
|
||||
var obj;
|
||||
if ((obj = getFooOrNull()) instanceof Foo) {
|
||||
obj;
|
||||
}
|
||||
}
|
||||
function f4() {
|
||||
var x;
|
||||
if (typeof (x = getStringOrNumberOrNull()) === "number") {
|
||||
x;
|
||||
}
|
||||
}
|
||||
// Repro from #8851
|
||||
var re = /./g;
|
||||
var match;
|
||||
while ((match = re.exec("xxx")) != null) {
|
||||
var length = match[1].length + match[2].length;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
=== tests/cases/conformance/controlFlow/typeGuardsNestedAssignments.ts ===
|
||||
|
||||
class Foo {
|
||||
>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0))
|
||||
|
||||
x: string;
|
||||
>x : Symbol(Foo.x, Decl(typeGuardsNestedAssignments.ts, 1, 11))
|
||||
}
|
||||
|
||||
declare function getFooOrNull(): Foo | null;
|
||||
>getFooOrNull : Symbol(getFooOrNull, Decl(typeGuardsNestedAssignments.ts, 3, 1))
|
||||
>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0))
|
||||
|
||||
declare function getStringOrNumberOrNull(): string | number | null;
|
||||
>getStringOrNumberOrNull : Symbol(getStringOrNumberOrNull, Decl(typeGuardsNestedAssignments.ts, 5, 44))
|
||||
|
||||
function f1() {
|
||||
>f1 : Symbol(f1, Decl(typeGuardsNestedAssignments.ts, 6, 67))
|
||||
|
||||
let foo: Foo | null;
|
||||
>foo : Symbol(foo, Decl(typeGuardsNestedAssignments.ts, 9, 7))
|
||||
>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0))
|
||||
|
||||
if ((foo = getFooOrNull()) !== null) {
|
||||
>foo : Symbol(foo, Decl(typeGuardsNestedAssignments.ts, 9, 7))
|
||||
>getFooOrNull : Symbol(getFooOrNull, Decl(typeGuardsNestedAssignments.ts, 3, 1))
|
||||
|
||||
foo; // Foo
|
||||
>foo : Symbol(foo, Decl(typeGuardsNestedAssignments.ts, 9, 7))
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
>f2 : Symbol(f2, Decl(typeGuardsNestedAssignments.ts, 13, 1))
|
||||
|
||||
let foo1: Foo | null;
|
||||
>foo1 : Symbol(foo1, Decl(typeGuardsNestedAssignments.ts, 16, 7))
|
||||
>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0))
|
||||
|
||||
let foo2: Foo | null;
|
||||
>foo2 : Symbol(foo2, Decl(typeGuardsNestedAssignments.ts, 17, 7))
|
||||
>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0))
|
||||
|
||||
if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) {
|
||||
>foo1 : Symbol(foo1, Decl(typeGuardsNestedAssignments.ts, 16, 7))
|
||||
>getFooOrNull : Symbol(getFooOrNull, Decl(typeGuardsNestedAssignments.ts, 3, 1))
|
||||
>foo2 : Symbol(foo2, Decl(typeGuardsNestedAssignments.ts, 17, 7))
|
||||
>foo1 : Symbol(foo1, Decl(typeGuardsNestedAssignments.ts, 16, 7))
|
||||
|
||||
foo1; // Foo | null
|
||||
>foo1 : Symbol(foo1, Decl(typeGuardsNestedAssignments.ts, 16, 7))
|
||||
|
||||
foo2; // Foo
|
||||
>foo2 : Symbol(foo2, Decl(typeGuardsNestedAssignments.ts, 17, 7))
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
>f3 : Symbol(f3, Decl(typeGuardsNestedAssignments.ts, 22, 1))
|
||||
|
||||
let obj: Object | null;
|
||||
>obj : Symbol(obj, Decl(typeGuardsNestedAssignments.ts, 25, 7))
|
||||
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
if ((obj = getFooOrNull()) instanceof Foo) {
|
||||
>obj : Symbol(obj, Decl(typeGuardsNestedAssignments.ts, 25, 7))
|
||||
>getFooOrNull : Symbol(getFooOrNull, Decl(typeGuardsNestedAssignments.ts, 3, 1))
|
||||
>Foo : Symbol(Foo, Decl(typeGuardsNestedAssignments.ts, 0, 0))
|
||||
|
||||
obj;
|
||||
>obj : Symbol(obj, Decl(typeGuardsNestedAssignments.ts, 25, 7))
|
||||
}
|
||||
}
|
||||
|
||||
function f4() {
|
||||
>f4 : Symbol(f4, Decl(typeGuardsNestedAssignments.ts, 29, 1))
|
||||
|
||||
let x: string | number | null;
|
||||
>x : Symbol(x, Decl(typeGuardsNestedAssignments.ts, 32, 7))
|
||||
|
||||
if (typeof (x = getStringOrNumberOrNull()) === "number") {
|
||||
>x : Symbol(x, Decl(typeGuardsNestedAssignments.ts, 32, 7))
|
||||
>getStringOrNumberOrNull : Symbol(getStringOrNumberOrNull, Decl(typeGuardsNestedAssignments.ts, 5, 44))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(typeGuardsNestedAssignments.ts, 32, 7))
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8851
|
||||
|
||||
const re = /./g
|
||||
>re : Symbol(re, Decl(typeGuardsNestedAssignments.ts, 40, 5))
|
||||
|
||||
let match: RegExpExecArray | null
|
||||
>match : Symbol(match, Decl(typeGuardsNestedAssignments.ts, 41, 3))
|
||||
>RegExpExecArray : Symbol(RegExpExecArray, Decl(lib.d.ts, --, --))
|
||||
|
||||
while ((match = re.exec("xxx")) != null) {
|
||||
>match : Symbol(match, Decl(typeGuardsNestedAssignments.ts, 41, 3))
|
||||
>re.exec : Symbol(RegExp.exec, Decl(lib.d.ts, --, --))
|
||||
>re : Symbol(re, Decl(typeGuardsNestedAssignments.ts, 40, 5))
|
||||
>exec : Symbol(RegExp.exec, Decl(lib.d.ts, --, --))
|
||||
|
||||
const length = match[1].length + match[2].length
|
||||
>length : Symbol(length, Decl(typeGuardsNestedAssignments.ts, 44, 9))
|
||||
>match[1].length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>match : Symbol(match, Decl(typeGuardsNestedAssignments.ts, 41, 3))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>match[2].length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>match : Symbol(match, Decl(typeGuardsNestedAssignments.ts, 41, 3))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
=== tests/cases/conformance/controlFlow/typeGuardsNestedAssignments.ts ===
|
||||
|
||||
class Foo {
|
||||
>Foo : Foo
|
||||
|
||||
x: string;
|
||||
>x : string
|
||||
}
|
||||
|
||||
declare function getFooOrNull(): Foo | null;
|
||||
>getFooOrNull : () => Foo | null
|
||||
>Foo : Foo
|
||||
>null : null
|
||||
|
||||
declare function getStringOrNumberOrNull(): string | number | null;
|
||||
>getStringOrNumberOrNull : () => string | number | null
|
||||
>null : null
|
||||
|
||||
function f1() {
|
||||
>f1 : () => void
|
||||
|
||||
let foo: Foo | null;
|
||||
>foo : Foo | null
|
||||
>Foo : Foo
|
||||
>null : null
|
||||
|
||||
if ((foo = getFooOrNull()) !== null) {
|
||||
>(foo = getFooOrNull()) !== null : boolean
|
||||
>(foo = getFooOrNull()) : Foo | null
|
||||
>foo = getFooOrNull() : Foo | null
|
||||
>foo : Foo | null
|
||||
>getFooOrNull() : Foo | null
|
||||
>getFooOrNull : () => Foo | null
|
||||
>null : null
|
||||
|
||||
foo; // Foo
|
||||
>foo : Foo
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
>f2 : () => void
|
||||
|
||||
let foo1: Foo | null;
|
||||
>foo1 : Foo | null
|
||||
>Foo : Foo
|
||||
>null : null
|
||||
|
||||
let foo2: Foo | null;
|
||||
>foo2 : Foo | null
|
||||
>Foo : Foo
|
||||
>null : null
|
||||
|
||||
if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) {
|
||||
>(foo1 = getFooOrNull(), foo2 = foo1) !== null : boolean
|
||||
>(foo1 = getFooOrNull(), foo2 = foo1) : Foo | null
|
||||
>foo1 = getFooOrNull(), foo2 = foo1 : Foo | null
|
||||
>foo1 = getFooOrNull() : Foo | null
|
||||
>foo1 : Foo | null
|
||||
>getFooOrNull() : Foo | null
|
||||
>getFooOrNull : () => Foo | null
|
||||
>foo2 = foo1 : Foo | null
|
||||
>foo2 : Foo | null
|
||||
>foo1 : Foo | null
|
||||
>null : null
|
||||
|
||||
foo1; // Foo | null
|
||||
>foo1 : Foo | null
|
||||
|
||||
foo2; // Foo
|
||||
>foo2 : Foo
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
>f3 : () => void
|
||||
|
||||
let obj: Object | null;
|
||||
>obj : Object | null
|
||||
>Object : Object
|
||||
>null : null
|
||||
|
||||
if ((obj = getFooOrNull()) instanceof Foo) {
|
||||
>(obj = getFooOrNull()) instanceof Foo : boolean
|
||||
>(obj = getFooOrNull()) : Foo | null
|
||||
>obj = getFooOrNull() : Foo | null
|
||||
>obj : Object | null
|
||||
>getFooOrNull() : Foo | null
|
||||
>getFooOrNull : () => Foo | null
|
||||
>Foo : typeof Foo
|
||||
|
||||
obj;
|
||||
>obj : Foo
|
||||
}
|
||||
}
|
||||
|
||||
function f4() {
|
||||
>f4 : () => void
|
||||
|
||||
let x: string | number | null;
|
||||
>x : string | number | null
|
||||
>null : null
|
||||
|
||||
if (typeof (x = getStringOrNumberOrNull()) === "number") {
|
||||
>typeof (x = getStringOrNumberOrNull()) === "number" : boolean
|
||||
>typeof (x = getStringOrNumberOrNull()) : string
|
||||
>(x = getStringOrNumberOrNull()) : string | number | null
|
||||
>x = getStringOrNumberOrNull() : string | number | null
|
||||
>x : string | number | null
|
||||
>getStringOrNumberOrNull() : string | number | null
|
||||
>getStringOrNumberOrNull : () => string | number | null
|
||||
>"number" : string
|
||||
|
||||
x;
|
||||
>x : number
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8851
|
||||
|
||||
const re = /./g
|
||||
>re : RegExp
|
||||
>/./g : RegExp
|
||||
|
||||
let match: RegExpExecArray | null
|
||||
>match : RegExpExecArray | null
|
||||
>RegExpExecArray : RegExpExecArray
|
||||
>null : null
|
||||
|
||||
while ((match = re.exec("xxx")) != null) {
|
||||
>(match = re.exec("xxx")) != null : boolean
|
||||
>(match = re.exec("xxx")) : RegExpExecArray | null
|
||||
>match = re.exec("xxx") : RegExpExecArray | null
|
||||
>match : RegExpExecArray | null
|
||||
>re.exec("xxx") : RegExpExecArray | null
|
||||
>re.exec : (string: string) => RegExpExecArray | null
|
||||
>re : RegExp
|
||||
>exec : (string: string) => RegExpExecArray | null
|
||||
>"xxx" : string
|
||||
>null : null
|
||||
|
||||
const length = match[1].length + match[2].length
|
||||
>length : number
|
||||
>match[1].length + match[2].length : number
|
||||
>match[1].length : number
|
||||
>match[1] : string
|
||||
>match : RegExpExecArray
|
||||
>1 : number
|
||||
>length : number
|
||||
>match[2].length : number
|
||||
>match[2] : string
|
||||
>match : RegExpExecArray
|
||||
>2 : number
|
||||
>length : number
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts(7,20): error TS2339: Property 'global' does not exist on type 'never'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts (1 errors) ====
|
||||
interface I { global: string; }
|
||||
var result: I;
|
||||
var result2: I;
|
||||
|
||||
if (!(result instanceof RegExp)) {
|
||||
result = result2;
|
||||
} else if (!result.global) {
|
||||
~~~~~~
|
||||
!!! error TS2339: Property 'global' does not exist on type 'never'.
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts ===
|
||||
interface I { global: string; }
|
||||
>I : Symbol(I, Decl(typeGuardsWithInstanceOf.ts, 0, 0))
|
||||
>global : Symbol(I.global, Decl(typeGuardsWithInstanceOf.ts, 0, 13))
|
||||
|
||||
var result: I;
|
||||
>result : Symbol(result, Decl(typeGuardsWithInstanceOf.ts, 1, 3))
|
||||
>I : Symbol(I, Decl(typeGuardsWithInstanceOf.ts, 0, 0))
|
||||
|
||||
var result2: I;
|
||||
>result2 : Symbol(result2, Decl(typeGuardsWithInstanceOf.ts, 2, 3))
|
||||
>I : Symbol(I, Decl(typeGuardsWithInstanceOf.ts, 0, 0))
|
||||
|
||||
if (!(result instanceof RegExp)) {
|
||||
>result : Symbol(result, Decl(typeGuardsWithInstanceOf.ts, 1, 3))
|
||||
>RegExp : Symbol(RegExp, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
result = result2;
|
||||
>result : Symbol(result, Decl(typeGuardsWithInstanceOf.ts, 1, 3))
|
||||
>result2 : Symbol(result2, Decl(typeGuardsWithInstanceOf.ts, 2, 3))
|
||||
|
||||
} else if (!result.global) {
|
||||
>result.global : Symbol(global, Decl(typeGuardsWithInstanceOf.ts, 0, 13), Decl(lib.d.ts, --, --))
|
||||
>result : Symbol(result, Decl(typeGuardsWithInstanceOf.ts, 1, 3))
|
||||
>global : Symbol(global, Decl(typeGuardsWithInstanceOf.ts, 0, 13), Decl(lib.d.ts, --, --))
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOf.ts ===
|
||||
interface I { global: string; }
|
||||
>I : I
|
||||
>global : string
|
||||
|
||||
var result: I;
|
||||
>result : I
|
||||
>I : I
|
||||
|
||||
var result2: I;
|
||||
>result2 : I
|
||||
>I : I
|
||||
|
||||
if (!(result instanceof RegExp)) {
|
||||
>!(result instanceof RegExp) : boolean
|
||||
>(result instanceof RegExp) : boolean
|
||||
>result instanceof RegExp : boolean
|
||||
>result : I
|
||||
>RegExp : RegExpConstructor
|
||||
|
||||
result = result2;
|
||||
>result = result2 : I
|
||||
>result : I
|
||||
>result2 : I
|
||||
|
||||
} else if (!result.global) {
|
||||
>!result.global : boolean
|
||||
>result.global : string & boolean
|
||||
>result : I & RegExp
|
||||
>global : string & boolean
|
||||
}
|
||||
@@ -8,7 +8,7 @@ export interface A {
|
||||
|
||||
x: () => typeof $
|
||||
>x : Symbol(A.x, Decl(app.ts, 2, 20))
|
||||
>$ : Symbol($, Decl(app.ts, 1, 8))
|
||||
>$ : Symbol($, Decl(index.d.ts, 0, 11))
|
||||
}
|
||||
|
||||
=== /ref.d.ts ===
|
||||
|
||||
@@ -8,7 +8,7 @@ export interface A {
|
||||
|
||||
x: typeof $;
|
||||
>x : Symbol(A.x, Decl(app.ts, 2, 20))
|
||||
>$ : Symbol($, Decl(app.ts, 1, 8))
|
||||
>$ : Symbol($, Decl(index.d.ts, 0, 11))
|
||||
}
|
||||
=== /ref.d.ts ===
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// @target: ES6
|
||||
async function fAsync() {
|
||||
// Without explicit type annotation, this is just an array.
|
||||
return [1, true];
|
||||
}
|
||||
|
||||
async function fAsyncExplicit(): Promise<[number, boolean]> {
|
||||
// This is contextually typed as a tuple.
|
||||
return [1, true];
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// @target: es5
|
||||
|
||||
async function foo() { return 42; } // ERROR: Async functions are only available in ES6+
|
||||
let bar = async function () { return 42; } // OK, but should be an error
|
||||
let baz = async () => 42; // OK, but should be an error
|
||||
@@ -0,0 +1,30 @@
|
||||
// @Filename: 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;
|
||||
}
|
||||
|
||||
// @Filename: 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);
|
||||
@@ -0,0 +1 @@
|
||||
declare module "too*many*asterisks" { }
|
||||
@@ -0,0 +1,47 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
class Foo {
|
||||
x: string;
|
||||
}
|
||||
|
||||
declare function getFooOrNull(): Foo | null;
|
||||
declare function getStringOrNumberOrNull(): string | number | null;
|
||||
|
||||
function f1() {
|
||||
let foo: Foo | null;
|
||||
if ((foo = getFooOrNull()) !== null) {
|
||||
foo; // Foo
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
let foo1: Foo | null;
|
||||
let foo2: Foo | null;
|
||||
if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) {
|
||||
foo1; // Foo | null
|
||||
foo2; // Foo
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
let obj: Object | null;
|
||||
if ((obj = getFooOrNull()) instanceof Foo) {
|
||||
obj;
|
||||
}
|
||||
}
|
||||
|
||||
function f4() {
|
||||
let x: string | number | null;
|
||||
if (typeof (x = getStringOrNumberOrNull()) === "number") {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8851
|
||||
|
||||
const re = /./g
|
||||
let match: RegExpExecArray | null
|
||||
|
||||
while ((match = re.exec("xxx")) != null) {
|
||||
const length = match[1].length + match[2].length
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
const a = [0];
|
||||
const s = "";
|
||||
const x = 0;
|
||||
const b = false;
|
||||
const v: void = undefined;
|
||||
const u = undefined;
|
||||
const n = null;
|
||||
const z = s || x || u;
|
||||
|
||||
const a1 = a && a;
|
||||
const a2 = a && s;
|
||||
const a3 = a && x;
|
||||
const a4 = a && b;
|
||||
const a5 = a && v;
|
||||
const a6 = a && u;
|
||||
const a7 = a && n;
|
||||
const a8 = a && z;
|
||||
|
||||
const s1 = s && a;
|
||||
const s2 = s && s;
|
||||
const s3 = s && x;
|
||||
const s4 = s && b;
|
||||
const s5 = s && v;
|
||||
const s6 = s && u;
|
||||
const s7 = s && n;
|
||||
const s8 = s && z;
|
||||
|
||||
const x1 = x && a;
|
||||
const x2 = x && s;
|
||||
const x3 = x && x;
|
||||
const x4 = x && b;
|
||||
const x5 = x && v;
|
||||
const x6 = x && u;
|
||||
const x7 = x && n;
|
||||
const x8 = x && z;
|
||||
|
||||
const b1 = b && a;
|
||||
const b2 = b && s;
|
||||
const b3 = b && x;
|
||||
const b4 = b && b;
|
||||
const b5 = b && v;
|
||||
const b6 = b && u;
|
||||
const b7 = b && n;
|
||||
const b8 = b && z;
|
||||
|
||||
const v1 = v && a;
|
||||
const v2 = v && s;
|
||||
const v3 = v && x;
|
||||
const v4 = v && b;
|
||||
const v5 = v && v;
|
||||
const v6 = v && u;
|
||||
const v7 = v && n;
|
||||
const v8 = v && z;
|
||||
|
||||
const u1 = u && a;
|
||||
const u2 = u && s;
|
||||
const u3 = u && x;
|
||||
const u4 = u && b;
|
||||
const u5 = u && v;
|
||||
const u6 = u && u;
|
||||
const u7 = u && n;
|
||||
const u8 = u && z;
|
||||
|
||||
const n1 = n && a;
|
||||
const n2 = n && s;
|
||||
const n3 = n && x;
|
||||
const n4 = n && b;
|
||||
const n5 = n && v;
|
||||
const n6 = n && u;
|
||||
const n7 = n && n;
|
||||
const n8 = n && z;
|
||||
|
||||
const z1 = z && a;
|
||||
const z2 = z && s;
|
||||
const z3 = z && x;
|
||||
const z4 = z && b;
|
||||
const z5 = z && v;
|
||||
const z6 = z && u;
|
||||
const z7 = z && n;
|
||||
const z8 = z && z;
|
||||
@@ -0,0 +1,113 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
interface X {
|
||||
x: string;
|
||||
}
|
||||
|
||||
interface Y {
|
||||
y: string;
|
||||
}
|
||||
|
||||
interface Z {
|
||||
z: string;
|
||||
}
|
||||
|
||||
declare function isX(obj: any): obj is X;
|
||||
declare function isY(obj: any): obj is Y;
|
||||
declare function isZ(obj: any): obj is Z;
|
||||
|
||||
function f1(obj: Object) {
|
||||
if (isX(obj) || isY(obj) || isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
if (isX(obj) && isY(obj) && isZ(obj)) {
|
||||
obj;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #8911
|
||||
|
||||
// two interfaces
|
||||
interface A {
|
||||
a: string;
|
||||
}
|
||||
|
||||
interface B {
|
||||
b: string;
|
||||
}
|
||||
|
||||
// a type guard for B
|
||||
function isB(toTest: any): toTest is B {
|
||||
return toTest && toTest.b;
|
||||
}
|
||||
|
||||
// a function that turns an A into an A & B
|
||||
function union(a: A): A & B | null {
|
||||
if (isB(a)) {
|
||||
return a;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Repro from #9016
|
||||
|
||||
declare function log(s: string): void;
|
||||
|
||||
// Supported beast features
|
||||
interface Beast { wings?: boolean; legs?: number }
|
||||
interface Legged { legs: number; }
|
||||
interface Winged { wings: boolean; }
|
||||
|
||||
// Beast feature detection via user-defined type guards
|
||||
function hasLegs(x: Beast): x is Legged { return x && typeof x.legs === 'number'; }
|
||||
function hasWings(x: Beast): x is Winged { return x && !!x.wings; }
|
||||
|
||||
// Function to identify a given beast by detecting its features
|
||||
function identifyBeast(beast: Beast) {
|
||||
|
||||
// All beasts with legs
|
||||
if (hasLegs(beast)) {
|
||||
|
||||
// All winged beasts with legs
|
||||
if (hasWings(beast)) {
|
||||
if (beast.legs === 4) {
|
||||
log(`pegasus - 4 legs, wings`);
|
||||
}
|
||||
else if (beast.legs === 2) {
|
||||
log(`bird - 2 legs, wings`);
|
||||
}
|
||||
else {
|
||||
log(`unknown - ${beast.legs} legs, wings`);
|
||||
}
|
||||
}
|
||||
|
||||
// All non-winged beasts with legs
|
||||
else {
|
||||
log(`manbearpig - ${beast.legs} legs, no wings`);
|
||||
}
|
||||
}
|
||||
|
||||
// All beasts without legs
|
||||
else {
|
||||
if (hasWings(beast)) {
|
||||
log(`quetzalcoatl - no legs, wings`)
|
||||
}
|
||||
else {
|
||||
log(`snake - no legs, no wings`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function beastFoo(beast: Object) {
|
||||
if (hasWings(beast) && hasLegs(beast)) {
|
||||
beast; // Winged & Legged
|
||||
}
|
||||
else {
|
||||
beast;
|
||||
}
|
||||
|
||||
if (hasLegs(beast) && hasWings(beast)) {
|
||||
beast; // Legged & Winged
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// @traceResolution: true
|
||||
|
||||
// @Filename: /src/a.ts
|
||||
export default 0;
|
||||
|
||||
// No extension: '.ts' added
|
||||
// @Filename: /src/b.ts
|
||||
import a from './a';
|
||||
|
||||
// Matching extension
|
||||
// @Filename: /src/c.ts
|
||||
import a from './a.ts';
|
||||
|
||||
// '.js' extension: stripped and replaced with '.ts'
|
||||
// @Filename: /src/d.ts
|
||||
import a from './a.js';
|
||||
|
||||
// @Filename: /src/jquery.d.ts
|
||||
declare var x: number;
|
||||
export default x;
|
||||
|
||||
// No extension: '.d.ts' added
|
||||
// @Filename: /src/jquery_user_1.ts
|
||||
import j from "./jquery";
|
||||
|
||||
// '.js' extension: stripped and replaced with '.d.ts'
|
||||
// @Filename: /src/jquery_user_1.ts
|
||||
import j from "./jquery.js"
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////type Options = "Option 1" | "Option 2" | "Option 3";
|
||||
////var x: Options = "/*1*/Option 3";
|
||||
////
|
||||
////function f(a: Options) { };
|
||||
////f("/*2*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.completionListContains("Option 1");
|
||||
verify.memberListCount(3);
|
||||
|
||||
goTo.marker('2');
|
||||
verify.completionListContains("Option 2");
|
||||
verify.memberListCount(3);
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////var o = {
|
||||
//// foo() { },
|
||||
//// bar: 0,
|
||||
//// "some other name": 1
|
||||
////};
|
||||
////
|
||||
////o["/*1*/bar"];
|
||||
////o["/*2*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.completionListContains("foo");
|
||||
verify.completionListAllowsNewIdentifier();
|
||||
verify.memberListCount(3);
|
||||
|
||||
goTo.marker('2');
|
||||
verify.completionListContains("some other name");
|
||||
verify.completionListAllowsNewIdentifier();
|
||||
verify.memberListCount(3);
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////declare function f(a: "A", b: number): void;
|
||||
////declare function f(a: "B", b: number): void;
|
||||
////declare function f(a: "C", b: number): void;
|
||||
////declare function f(a: string, b: number): void;
|
||||
////
|
||||
////f("/*1*/C", 2);
|
||||
////
|
||||
////f("/*2*/
|
||||
|
||||
goTo.marker('1');
|
||||
verify.completionListContains("A");
|
||||
verify.completionListAllowsNewIdentifier();
|
||||
verify.memberListCount(3);
|
||||
|
||||
goTo.marker('2');
|
||||
verify.completionListContains("A");
|
||||
verify.completionListAllowsNewIdentifier();
|
||||
verify.memberListCount(3);
|
||||
@@ -52,13 +52,13 @@ declare module ts {
|
||||
None = 0,
|
||||
Block = 1,
|
||||
Smart = 2,
|
||||
}
|
||||
}
|
||||
|
||||
interface OutputFile {
|
||||
name: string;
|
||||
writeByteOrderMark: boolean;
|
||||
text: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare namespace FourSlashInterface {
|
||||
@@ -139,7 +139,7 @@ declare namespace FourSlashInterface {
|
||||
isValidBraceCompletionAtPostion(openingBrace?: string): void;
|
||||
}
|
||||
class verify extends verifyNegatable {
|
||||
assertHasRanges(ranges: FourSlash.Range[]): void;
|
||||
assertHasRanges(ranges: Range[]): void;
|
||||
caretAtMarker(markerName?: string): void;
|
||||
indentationIs(numberOfSpaces: number): void;
|
||||
indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle?: ts.IndentStyle): void;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
///<reference path="fourslash.ts" />
|
||||
|
||||
// Testing that quickInfo gets information with a corresponding meaning: values to values, types to types.
|
||||
// For quick info purposes, we don't resolve past aliases.
|
||||
// However, when we have an alias for a type, the quickInfo for a value with the same should skip the alias, and vice versa.
|
||||
// goToDefinition should work the same way.
|
||||
|
||||
// @Filename: foo.d.ts
|
||||
////declare const /*foo_value_declaration*/foo: number;
|
||||
////declare module "foo_module" {
|
||||
//// interface I { x: number; y: number }
|
||||
//// export = I;
|
||||
////}
|
||||
|
||||
// @Filename: foo_user.ts
|
||||
///////<reference path="foo.d.ts" />
|
||||
/////*foo_type_declaration*/import foo = require("foo_module");
|
||||
////const x = foo/*foo_value*/;
|
||||
////const i: foo/*foo_type*/ = { x: 1, y: 2 };
|
||||
|
||||
verify.numberOfErrorsInCurrentFile(0);
|
||||
|
||||
verify.navigationItemsListCount(2, "foo", "exact");
|
||||
verify.navigationItemsListContains("foo", "alias", "foo", "exact");
|
||||
verify.navigationItemsListContains("foo", "const", "foo", "exact");
|
||||
|
||||
goTo.marker("foo_value");
|
||||
verify.quickInfoIs("const foo: number");
|
||||
goTo.definition();
|
||||
verify.caretAtMarker("foo_value_declaration");
|
||||
|
||||
goTo.marker("foo_type");
|
||||
verify.quickInfoIs("import foo = require(\"foo_module\")");
|
||||
goTo.definition();
|
||||
verify.caretAtMarker("foo_type_declaration");
|
||||
|
||||
|
||||
// Above tested for global const and imported interface. Now test with global interface and imported const.
|
||||
|
||||
|
||||
// @Filename: bar.d.ts
|
||||
/////*bar_type_declaration*/declare interface bar { x: number; y: number }
|
||||
////declare module "bar_module" {
|
||||
//// const x: number;
|
||||
//// export = x;
|
||||
////}
|
||||
|
||||
// @Filename: bar_user.ts
|
||||
///////<reference path="bar.d.ts" />
|
||||
/////*bar_value_declaration*/import bar = require("bar_module");
|
||||
////const x = bar/*bar_value*/;
|
||||
////const i: bar/*bar_type*/ = { x: 1, y: 2 };
|
||||
|
||||
verify.numberOfErrorsInCurrentFile(0);
|
||||
verify.navigationItemsListCount(2, "bar", "exact");
|
||||
verify.navigationItemsListContains("bar", "alias", "bar", "exact");
|
||||
verify.navigationItemsListContains("bar", "interface", "bar", "exact");
|
||||
|
||||
goTo.marker("bar_value");
|
||||
verify.quickInfoIs("import bar = require(\"bar_module\")");
|
||||
goTo.definition();
|
||||
verify.caretAtMarker("bar_value_declaration");
|
||||
|
||||
goTo.marker("bar_type");
|
||||
verify.quickInfoIs("interface bar");
|
||||
goTo.definition();
|
||||
verify.caretAtMarker("bar_type_declaration");
|
||||
@@ -1,4 +1,4 @@
|
||||
import modErr = require("./foo/bar.js");
|
||||
import modErr = require("./foo/bar.tx");
|
||||
import modErr1 = require("baz");
|
||||
import modErr2 = require("./baz");
|
||||
|
||||
|
||||
@@ -7,17 +7,21 @@ namespace ts {
|
||||
options?: TranspileOptions;
|
||||
expectedOutput?: string;
|
||||
expectedDiagnosticCodes?: number[];
|
||||
expectedDiagnosticTexts?: string[];
|
||||
}
|
||||
|
||||
function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes?: number[]) {
|
||||
if (!expectedDiagnosticCodes) {
|
||||
return;
|
||||
function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes: number[] = [], expectedDiagnosticTexts?: string[]) {
|
||||
const n = expectedDiagnosticCodes.length;
|
||||
if (expectedDiagnosticTexts) {
|
||||
assert.equal(n, expectedDiagnosticTexts.length);
|
||||
}
|
||||
|
||||
for (let i = 0; i < expectedDiagnosticCodes.length; i++) {
|
||||
assert.equal(expectedDiagnosticCodes[i], diagnostics[i] && diagnostics[i].code, `Could not find expeced diagnostic.`);
|
||||
}
|
||||
assert.equal(diagnostics.length, expectedDiagnosticCodes.length, "Resuting diagnostics count does not match expected");
|
||||
for (let i = 0; i < n; i++) {
|
||||
assert.equal(expectedDiagnosticCodes[i], diagnostics[i] && diagnostics[i].code, `Could not find expected diagnostic.`);
|
||||
if (expectedDiagnosticTexts) {
|
||||
assert.equal(expectedDiagnosticTexts[i], diagnostics[i] && diagnostics[i].messageText);
|
||||
}
|
||||
};
|
||||
assert.equal(diagnostics.length, n, "Resuting diagnostics count does not match expected");
|
||||
}
|
||||
|
||||
function test(input: string, testSettings: TranspileTestSettings): void {
|
||||
@@ -26,7 +30,7 @@ namespace ts {
|
||||
if (!transpileOptions.compilerOptions) {
|
||||
transpileOptions.compilerOptions = {};
|
||||
}
|
||||
if (transpileOptions.compilerOptions.newLine === undefined) { //
|
||||
if (transpileOptions.compilerOptions.newLine === undefined) {
|
||||
// use \r\n as default new line
|
||||
transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed;
|
||||
}
|
||||
@@ -36,7 +40,7 @@ namespace ts {
|
||||
transpileOptions.reportDiagnostics = true;
|
||||
const transpileModuleResult = transpileModule(input, transpileOptions);
|
||||
|
||||
checkDiagnostics(transpileModuleResult.diagnostics, testSettings.expectedDiagnosticCodes);
|
||||
checkDiagnostics(transpileModuleResult.diagnostics, testSettings.expectedDiagnosticCodes, testSettings.expectedDiagnosticTexts);
|
||||
|
||||
if (testSettings.expectedOutput !== undefined) {
|
||||
assert.equal(transpileModuleResult.outputText, testSettings.expectedOutput);
|
||||
@@ -45,7 +49,7 @@ namespace ts {
|
||||
if (canUseOldTranspile) {
|
||||
const diagnostics: Diagnostic[] = [];
|
||||
const transpileResult = transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, diagnostics, transpileOptions.moduleName);
|
||||
checkDiagnostics(diagnostics, testSettings.expectedDiagnosticCodes);
|
||||
checkDiagnostics(diagnostics, testSettings.expectedDiagnosticCodes, testSettings.expectedDiagnosticTexts);
|
||||
if (testSettings.expectedOutput) {
|
||||
assert.equal(transpileResult, testSettings.expectedOutput);
|
||||
}
|
||||
@@ -292,13 +296,37 @@ var x = 0;`,
|
||||
const output = `"use strict";\nvar a = 10;\n`;
|
||||
test(input, {
|
||||
expectedOutput: output,
|
||||
options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true },
|
||||
expectedDiagnosticCodes: []
|
||||
options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true }
|
||||
});
|
||||
});
|
||||
|
||||
it("Supports urls in file name", () => {
|
||||
test("var x", { expectedOutput: `"use strict";\r\nvar x;\r\n`, options: { fileName: "http://somewhere/directory//directory2/file.ts" } });
|
||||
});
|
||||
|
||||
describe("String values for enums", () => {
|
||||
it("Accepts strings instead of enum values", () => {
|
||||
test(`export const x = 0`, {
|
||||
options: {
|
||||
compilerOptions: {
|
||||
module: <ModuleKind><any>"es6",
|
||||
// Capitalization and spaces ignored
|
||||
target: <ScriptTarget><any>" Es6 "
|
||||
}
|
||||
},
|
||||
expectedOutput: "export const x = 0;\r\n"
|
||||
});
|
||||
});
|
||||
|
||||
it("Fails on bad value", () => {
|
||||
for (const value in [123, {}, ""]) {
|
||||
test(``, {
|
||||
options: { compilerOptions: { module: <ModuleKind><any>value } },
|
||||
expectedDiagnosticCodes: [6046],
|
||||
expectedDiagnosticTexts: ["Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'"]
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user