mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into reorderOptions
This commit is contained in:
+98
-50
@@ -153,7 +153,8 @@ var harnessSources = harnessCoreSources.concat([
|
||||
"tsconfigParsing.ts",
|
||||
"commandLineParsing.ts",
|
||||
"convertCompilerOptionsFromJson.ts",
|
||||
"convertTypingOptionsFromJson.ts"
|
||||
"convertTypingOptionsFromJson.ts",
|
||||
"tsserverProjectSystem.ts"
|
||||
].map(function (f) {
|
||||
return path.join(unittestsDirectory, f);
|
||||
})).concat([
|
||||
@@ -207,7 +208,7 @@ var librarySourceMap = [
|
||||
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
|
||||
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
|
||||
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
|
||||
|
||||
|
||||
// JavaScript + all host library
|
||||
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
|
||||
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
|
||||
@@ -312,6 +313,8 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
|
||||
if (!opts.noMapRoot) {
|
||||
options += " -mapRoot file:///" + path.resolve(path.dirname(outFile));
|
||||
}
|
||||
} else {
|
||||
options += " --newLine LF";
|
||||
}
|
||||
|
||||
if (opts.stripInternal) {
|
||||
@@ -520,7 +523,7 @@ compileFile(servicesFileInBrowserTest, servicesSources,[builtLocalDirectory, cop
|
||||
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);
|
||||
@@ -680,9 +683,9 @@ function cleanTestDirs() {
|
||||
}
|
||||
|
||||
// used to pass data from jake command line directly to run.js
|
||||
function writeTestConfigFile(tests, light, testConfigFile) {
|
||||
console.log('Running test(s): ' + tests);
|
||||
var testConfigContents = JSON.stringify({ test: [tests], light: light });
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -692,7 +695,7 @@ function deleteTemporaryProjectOutput() {
|
||||
}
|
||||
}
|
||||
|
||||
function runConsoleTests(defaultReporter, defaultSubsets) {
|
||||
function runConsoleTests(defaultReporter, runInParallel) {
|
||||
cleanTestDirs();
|
||||
var debug = process.env.debug || process.env.d;
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
@@ -701,9 +704,22 @@ function runConsoleTests(defaultReporter, defaultSubsets) {
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
var workerCount, taskConfigsFolder;
|
||||
if (runInParallel) {
|
||||
// generate name to store task configuration files
|
||||
var prefix = os.tmpdir() + "/ts-tests";
|
||||
var i = 1;
|
||||
do {
|
||||
taskConfigsFolder = prefix + i;
|
||||
i++;
|
||||
} while (fs.existsSync(taskConfigsFolder));
|
||||
fs.mkdirSync(taskConfigsFolder);
|
||||
|
||||
if (tests || light) {
|
||||
writeTestConfigFile(tests, light, testConfigFile);
|
||||
workerCount = process.env.workerCount || os.cpus().length;
|
||||
}
|
||||
|
||||
if (tests || light || taskConfigsFolder) {
|
||||
writeTestConfigFile(tests, light, taskConfigsFolder, workerCount);
|
||||
}
|
||||
|
||||
if (tests && tests.toLocaleLowerCase() === "rwc") {
|
||||
@@ -717,61 +733,93 @@ function runConsoleTests(defaultReporter, defaultSubsets) {
|
||||
|
||||
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
|
||||
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
|
||||
var subsetRegexes;
|
||||
if(defaultSubsets.length === 0) {
|
||||
subsetRegexes = [tests];
|
||||
}
|
||||
else {
|
||||
var subsets = tests ? tests.split("|") : defaultSubsets;
|
||||
subsetRegexes = subsets.map(function (sub) { return "^" + sub + ".*$"; });
|
||||
subsetRegexes.push("^(?!" + subsets.join("|") + ").*$");
|
||||
}
|
||||
var counter = subsetRegexes.length;
|
||||
var errorStatus;
|
||||
subsetRegexes.forEach(function (subsetRegex, i) {
|
||||
tests = subsetRegex ? ' -g "' + subsetRegex + '"' : '';
|
||||
if(!runInParallel) {
|
||||
tests = tests ? ' -g "' + tests + '"' : '';
|
||||
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + ' -t ' + testTimeout + ' ' + run;
|
||||
console.log(cmd);
|
||||
function finish(status) {
|
||||
counter--;
|
||||
// save first error status
|
||||
if (status !== undefined && errorStatus === undefined) {
|
||||
errorStatus = status;
|
||||
}
|
||||
|
||||
deleteTemporaryProjectOutput();
|
||||
if (counter !== 0 || errorStatus === undefined) {
|
||||
// run linter when last worker is finished
|
||||
if (lintFlag && counter === 0) {
|
||||
var lint = jake.Task['lint'];
|
||||
lint.addListener('complete', function () {
|
||||
complete();
|
||||
});
|
||||
lint.invoke();
|
||||
}
|
||||
complete();
|
||||
}
|
||||
else {
|
||||
fail("Process exited with code " + status);
|
||||
}
|
||||
}
|
||||
exec(cmd, function () {
|
||||
runLinter();
|
||||
finish();
|
||||
}, function(e, status) {
|
||||
finish(status);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
// run task to load all tests and partition them between workers
|
||||
var cmd = "mocha " + " -R min " + colors + run;
|
||||
console.log(cmd);
|
||||
exec(cmd, function() {
|
||||
// read all configuration files and spawn a worker for every config
|
||||
var configFiles = fs.readdirSync(taskConfigsFolder);
|
||||
var counter = configFiles.length;
|
||||
var firstErrorStatus;
|
||||
// schedule work for chunks
|
||||
configFiles.forEach(function (f) {
|
||||
var configPath = path.join(taskConfigsFolder, f);
|
||||
var workerCmd = "mocha" + " -t " + testTimeout + " -R " + reporter + " " + colors + " " + run + " --config='" + configPath + "'";
|
||||
console.log(workerCmd);
|
||||
exec(workerCmd, finishWorker, finishWorker)
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function failWithStatus(status) {
|
||||
fail("Process exited with code " + status);
|
||||
}
|
||||
|
||||
function finish(errorStatus) {
|
||||
deleteTemporaryProjectOutput();
|
||||
if (errorStatus !== undefined) {
|
||||
failWithStatus(errorStatus);
|
||||
}
|
||||
else {
|
||||
complete();
|
||||
}
|
||||
}
|
||||
function runLinter() {
|
||||
if (!lintFlag) {
|
||||
return;
|
||||
}
|
||||
var lint = jake.Task['lint'];
|
||||
lint.addListener('complete', function () {
|
||||
complete();
|
||||
});
|
||||
lint.invoke();
|
||||
}
|
||||
}
|
||||
|
||||
var testTimeout = 20000;
|
||||
desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true.");
|
||||
task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function() {
|
||||
runConsoleTests('min', ['compiler', 'conformance', 'Projects', 'fourslash']);
|
||||
runConsoleTests('min', /*runInParallel*/ true);
|
||||
}, {async: true});
|
||||
|
||||
desc("Runs the tests using the built run.js file. Optional arguments are: t[ests]=regex r[eporter]=[list|spec|json|<more>] d[ebug]=true color[s]=false lint=true.");
|
||||
task("runtests", ["build-rules", "tests", builtLocalDirectory], function() {
|
||||
runConsoleTests('mocha-fivemat-progress-reporter', []);
|
||||
runConsoleTests('mocha-fivemat-progress-reporter', /*runInParallel*/ false);
|
||||
}, {async: true});
|
||||
|
||||
desc("Generates code coverage data via instanbul");
|
||||
@@ -805,11 +853,11 @@ task("runtests-browser", ["tests", "browserify", builtLocalDirectory, servicesFi
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
if(tests || light) {
|
||||
writeTestConfigFile(tests, light, testConfigFile);
|
||||
writeTestConfigFile(tests, light);
|
||||
}
|
||||
|
||||
tests = tests ? tests : '';
|
||||
var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + tests;
|
||||
var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + JSON.stringify(tests);
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
+197
-173
@@ -77,12 +77,14 @@ namespace ts {
|
||||
// Blocks (when not parented by functions), Catch clauses, For/For-in/For-of statements...
|
||||
IsBlockScopedContainer = 1 << 1,
|
||||
|
||||
HasLocals = 1 << 2,
|
||||
// The current node is the container of a control flow path. The current control flow should
|
||||
// be saved and restored, and a new control flow initialized within the container.
|
||||
IsControlFlowContainer = 1 << 2,
|
||||
|
||||
// If the current node is a container that also container that also contains locals. Examples:
|
||||
//
|
||||
// Functions, Methods, Modules, Source-files.
|
||||
IsContainerWithLocals = IsContainer | HasLocals
|
||||
IsFunctionLike = 1 << 3,
|
||||
IsFunctionExpression = 1 << 4,
|
||||
HasLocals = 1 << 5,
|
||||
IsInterface = 1 << 6,
|
||||
}
|
||||
|
||||
const binder = createBinder();
|
||||
@@ -103,22 +105,19 @@ namespace ts {
|
||||
let lastContainer: Node;
|
||||
let seenThisKeyword: boolean;
|
||||
|
||||
// state used by reachability checks
|
||||
let hasExplicitReturn: boolean;
|
||||
// state used by control flow analysis
|
||||
let currentFlow: FlowNode;
|
||||
let currentBreakTarget: FlowLabel;
|
||||
let currentContinueTarget: FlowLabel;
|
||||
let currentReturnTarget: FlowLabel;
|
||||
let currentTrueTarget: FlowLabel;
|
||||
let currentFalseTarget: FlowLabel;
|
||||
let preSwitchCaseFlow: FlowNode;
|
||||
let activeLabels: ActiveLabel[];
|
||||
let hasExplicitReturn: boolean;
|
||||
|
||||
// state used for emit helpers
|
||||
let hasClassExtends: boolean;
|
||||
let hasAsyncFunctions: boolean;
|
||||
let hasDecorators: boolean;
|
||||
let hasParameterDecorators: boolean;
|
||||
let hasJsxSpreadAttribute: boolean;
|
||||
let emitFlags: NodeFlags;
|
||||
|
||||
// If this file is an external module, then it is automatically in strict-mode according to
|
||||
// ES6. If it is not an external module, then we'll determine if it is in strict mode or
|
||||
@@ -156,18 +155,15 @@ namespace ts {
|
||||
blockScopeContainer = undefined;
|
||||
lastContainer = undefined;
|
||||
seenThisKeyword = false;
|
||||
hasExplicitReturn = false;
|
||||
currentFlow = undefined;
|
||||
currentBreakTarget = undefined;
|
||||
currentContinueTarget = undefined;
|
||||
currentReturnTarget = undefined;
|
||||
currentTrueTarget = undefined;
|
||||
currentFalseTarget = undefined;
|
||||
activeLabels = undefined;
|
||||
hasClassExtends = false;
|
||||
hasAsyncFunctions = false;
|
||||
hasDecorators = false;
|
||||
hasParameterDecorators = false;
|
||||
hasJsxSpreadAttribute = false;
|
||||
hasExplicitReturn = false;
|
||||
emitFlags = NodeFlags.None;
|
||||
}
|
||||
|
||||
return bindSourceFile;
|
||||
@@ -267,6 +263,18 @@ namespace ts {
|
||||
let functionType = <JSDocFunctionType>node.parent;
|
||||
let index = indexOf(functionType.parameters, node);
|
||||
return "p" + index;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
const parentNode = node.parent && node.parent.parent;
|
||||
let nameFromParentNode: string;
|
||||
if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) {
|
||||
if ((<VariableStatement>parentNode).declarationList.declarations.length > 0) {
|
||||
const nameIdentifier = (<VariableStatement>parentNode).declarationList.declarations[0].name;
|
||||
if (nameIdentifier.kind === SyntaxKind.Identifier) {
|
||||
nameFromParentNode = (<Identifier>nameIdentifier).text;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nameFromParentNode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,17 +408,13 @@ namespace ts {
|
||||
// All container nodes are kept on a linked list in declaration order. This list is used by
|
||||
// the getLocalNameOfContainer function in the type checker to validate that the local name
|
||||
// used for a container is unique.
|
||||
function bindChildren(node: Node) {
|
||||
function bindContainer(node: Node, containerFlags: ContainerFlags) {
|
||||
// Before we recurse into a node's children, we first save the existing parent, container
|
||||
// and block-container. Then after we pop out of processing the children, we restore
|
||||
// these saved values.
|
||||
const saveParent = parent;
|
||||
const saveContainer = container;
|
||||
const savedBlockScopeContainer = blockScopeContainer;
|
||||
|
||||
// This node will now be set as the parent of all of its children as we recurse into them.
|
||||
parent = node;
|
||||
|
||||
// Depending on what kind of node this is, we may have to adjust the current container
|
||||
// and block-container. If the current node is a container, then it is automatically
|
||||
// considered the current block-container as well. Also, for containers that we know
|
||||
@@ -428,115 +432,90 @@ namespace ts {
|
||||
// reusing a node from a previous compilation, that node may have had 'locals' created
|
||||
// for it. We must clear this so we don't accidentally move any stale data forward from
|
||||
// a previous compilation.
|
||||
const containerFlags = getContainerFlags(node);
|
||||
if (containerFlags & ContainerFlags.IsContainer) {
|
||||
container = blockScopeContainer = node;
|
||||
|
||||
if (containerFlags & ContainerFlags.HasLocals) {
|
||||
container.locals = {};
|
||||
}
|
||||
|
||||
addToContainerChain(container);
|
||||
}
|
||||
else if (containerFlags & ContainerFlags.IsBlockScopedContainer) {
|
||||
blockScopeContainer = node;
|
||||
blockScopeContainer.locals = undefined;
|
||||
}
|
||||
|
||||
let savedHasExplicitReturn: boolean;
|
||||
let savedCurrentFlow: FlowNode;
|
||||
let savedBreakTarget: FlowLabel;
|
||||
let savedContinueTarget: FlowLabel;
|
||||
let savedActiveLabels: ActiveLabel[];
|
||||
|
||||
const kind = node.kind;
|
||||
let flags = node.flags;
|
||||
|
||||
// reset all reachability check related flags on node (for incremental scenarios)
|
||||
flags &= ~NodeFlags.ReachabilityCheckFlags;
|
||||
|
||||
// reset all emit helper flags on node (for incremental scenarios)
|
||||
flags &= ~NodeFlags.EmitHelperFlags;
|
||||
|
||||
if (kind === SyntaxKind.InterfaceDeclaration) {
|
||||
seenThisKeyword = false;
|
||||
}
|
||||
|
||||
const saveState = kind === SyntaxKind.SourceFile || kind === SyntaxKind.ModuleBlock || isFunctionLikeKind(kind);
|
||||
if (saveState) {
|
||||
savedHasExplicitReturn = hasExplicitReturn;
|
||||
savedCurrentFlow = currentFlow;
|
||||
savedBreakTarget = currentBreakTarget;
|
||||
savedContinueTarget = currentContinueTarget;
|
||||
savedActiveLabels = activeLabels;
|
||||
|
||||
hasExplicitReturn = false;
|
||||
currentFlow = { flags: FlowFlags.Start };
|
||||
if (containerFlags & ContainerFlags.IsControlFlowContainer) {
|
||||
const saveCurrentFlow = currentFlow;
|
||||
const saveBreakTarget = currentBreakTarget;
|
||||
const saveContinueTarget = currentContinueTarget;
|
||||
const saveReturnTarget = currentReturnTarget;
|
||||
const saveActiveLabels = activeLabels;
|
||||
const saveHasExplicitReturn = hasExplicitReturn;
|
||||
const isIIFE = containerFlags & ContainerFlags.IsFunctionExpression && !!getImmediatelyInvokedFunctionExpression(node);
|
||||
// An IIFE is considered part of the containing control flow. Return statements behave
|
||||
// similarly to break statements that exit to a label just past the statement body.
|
||||
if (isIIFE) {
|
||||
currentReturnTarget = createBranchLabel();
|
||||
}
|
||||
else {
|
||||
currentFlow = { flags: FlowFlags.Start };
|
||||
if (containerFlags & ContainerFlags.IsFunctionExpression) {
|
||||
(<FlowStart>currentFlow).container = <FunctionExpression | ArrowFunction>node;
|
||||
}
|
||||
currentReturnTarget = undefined;
|
||||
}
|
||||
currentBreakTarget = undefined;
|
||||
currentContinueTarget = undefined;
|
||||
activeLabels = undefined;
|
||||
}
|
||||
|
||||
if (isInJavaScriptFile(node) && node.jsDocComment) {
|
||||
bind(node.jsDocComment);
|
||||
}
|
||||
|
||||
bindReachableStatement(node);
|
||||
|
||||
if (!(currentFlow.flags & FlowFlags.Unreachable) && isFunctionLikeKind(kind) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
|
||||
flags |= NodeFlags.HasImplicitReturn;
|
||||
if (hasExplicitReturn) {
|
||||
flags |= NodeFlags.HasExplicitReturn;
|
||||
hasExplicitReturn = false;
|
||||
bindChildren(node);
|
||||
// Reset all reachability check related flags on node (for incremental scenarios)
|
||||
// Reset all emit helper flags on node (for incremental scenarios)
|
||||
node.flags &= ~NodeFlags.ReachabilityAndEmitFlags;
|
||||
if (!(currentFlow.flags & FlowFlags.Unreachable) && containerFlags & ContainerFlags.IsFunctionLike && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
|
||||
node.flags |= NodeFlags.HasImplicitReturn;
|
||||
if (hasExplicitReturn) node.flags |= NodeFlags.HasExplicitReturn;
|
||||
}
|
||||
if (node.kind === SyntaxKind.SourceFile) {
|
||||
node.flags |= emitFlags;
|
||||
}
|
||||
if (isIIFE) {
|
||||
addAntecedent(currentReturnTarget, currentFlow);
|
||||
currentFlow = finishFlowLabel(currentReturnTarget);
|
||||
}
|
||||
else {
|
||||
currentFlow = saveCurrentFlow;
|
||||
}
|
||||
currentBreakTarget = saveBreakTarget;
|
||||
currentContinueTarget = saveContinueTarget;
|
||||
currentReturnTarget = saveReturnTarget;
|
||||
activeLabels = saveActiveLabels;
|
||||
hasExplicitReturn = saveHasExplicitReturn;
|
||||
}
|
||||
|
||||
if (kind === SyntaxKind.InterfaceDeclaration) {
|
||||
flags = seenThisKeyword ? flags | NodeFlags.ContainsThis : flags & ~NodeFlags.ContainsThis;
|
||||
else if (containerFlags & ContainerFlags.IsInterface) {
|
||||
seenThisKeyword = false;
|
||||
bindChildren(node);
|
||||
node.flags = seenThisKeyword ? node.flags | NodeFlags.ContainsThis : node.flags & ~NodeFlags.ContainsThis;
|
||||
}
|
||||
|
||||
if (kind === SyntaxKind.SourceFile) {
|
||||
if (hasClassExtends) {
|
||||
flags |= NodeFlags.HasClassExtends;
|
||||
}
|
||||
if (hasDecorators) {
|
||||
flags |= NodeFlags.HasDecorators;
|
||||
}
|
||||
if (hasParameterDecorators) {
|
||||
flags |= NodeFlags.HasParamDecorators;
|
||||
}
|
||||
if (hasAsyncFunctions) {
|
||||
flags |= NodeFlags.HasAsyncFunctions;
|
||||
}
|
||||
if (hasJsxSpreadAttribute) {
|
||||
flags |= NodeFlags.HasJsxSpreadAttribute;
|
||||
}
|
||||
else {
|
||||
bindChildren(node);
|
||||
}
|
||||
|
||||
node.flags = flags;
|
||||
|
||||
if (saveState) {
|
||||
hasExplicitReturn = savedHasExplicitReturn;
|
||||
currentFlow = savedCurrentFlow;
|
||||
currentBreakTarget = savedBreakTarget;
|
||||
currentContinueTarget = savedContinueTarget;
|
||||
activeLabels = savedActiveLabels;
|
||||
}
|
||||
|
||||
container = saveContainer;
|
||||
parent = saveParent;
|
||||
blockScopeContainer = savedBlockScopeContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if node and its subnodes were successfully traversed.
|
||||
* Returning false means that node was not examined and caller needs to dive into the node himself.
|
||||
*/
|
||||
function bindReachableStatement(node: Node): void {
|
||||
function bindChildren(node: Node): void {
|
||||
// Binding of JsDocComment should be done before the current block scope container changes.
|
||||
// because the scope of JsDocComment should not be affected by whether the current node is a
|
||||
// container or not.
|
||||
if (isInJavaScriptFile(node) && node.jsDocComments) {
|
||||
for (const jsDocComment of node.jsDocComments) {
|
||||
bind(jsDocComment);
|
||||
}
|
||||
}
|
||||
if (checkUnreachable(node)) {
|
||||
forEachChild(node, bind);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.WhileStatement:
|
||||
bindWhileStatement(<WhileStatement>node);
|
||||
@@ -589,6 +568,9 @@ namespace ts {
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
bindVariableDeclarationFlow(<VariableDeclaration>node);
|
||||
break;
|
||||
case SyntaxKind.CallExpression:
|
||||
bindCallExpressionFlow(<CallExpression>node);
|
||||
break;
|
||||
default:
|
||||
forEachChild(node, bind);
|
||||
break;
|
||||
@@ -848,6 +830,9 @@ namespace ts {
|
||||
bind(node.expression);
|
||||
if (node.kind === SyntaxKind.ReturnStatement) {
|
||||
hasExplicitReturn = true;
|
||||
if (currentReturnTarget) {
|
||||
addAntecedent(currentReturnTarget, currentFlow);
|
||||
}
|
||||
}
|
||||
currentFlow = unreachableFlow;
|
||||
}
|
||||
@@ -912,8 +897,8 @@ namespace ts {
|
||||
preSwitchCaseFlow = currentFlow;
|
||||
bind(node.caseBlock);
|
||||
addAntecedent(postSwitchLabel, currentFlow);
|
||||
const hasDefault = forEach(node.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause);
|
||||
if (!hasDefault) {
|
||||
const hasNonEmptyDefault = forEach(node.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause && c.statements.length);
|
||||
if (!hasNonEmptyDefault) {
|
||||
addAntecedent(postSwitchLabel, preSwitchCaseFlow);
|
||||
}
|
||||
currentBreakTarget = saveBreakTarget;
|
||||
@@ -1098,35 +1083,67 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindCallExpressionFlow(node: CallExpression) {
|
||||
// If the target of the call expression is a function expression or arrow function we have
|
||||
// an immediately invoked function expression (IIFE). Initialize the flowNode property to
|
||||
// the current control flow (which includes evaluation of the IIFE arguments).
|
||||
let expr: Expression = node.expression;
|
||||
while (expr.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
expr = (<ParenthesizedExpression>expr).expression;
|
||||
}
|
||||
if (expr.kind === SyntaxKind.FunctionExpression || expr.kind === SyntaxKind.ArrowFunction) {
|
||||
forEach(node.typeArguments, bind);
|
||||
forEach(node.arguments, bind);
|
||||
bind(node.expression);
|
||||
}
|
||||
else {
|
||||
forEachChild(node, bind);
|
||||
}
|
||||
}
|
||||
|
||||
function getContainerFlags(node: Node): ContainerFlags {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
return ContainerFlags.IsContainer;
|
||||
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return ContainerFlags.IsContainer | ContainerFlags.IsInterface;
|
||||
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
return ContainerFlags.IsContainer | ContainerFlags.HasLocals;
|
||||
|
||||
case SyntaxKind.SourceFile:
|
||||
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals;
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike;
|
||||
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
return ContainerFlags.IsContainerWithLocals;
|
||||
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsFunctionExpression;
|
||||
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return ContainerFlags.IsControlFlowContainer;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return (<PropertyDeclaration>node).initializer ? ContainerFlags.IsControlFlowContainer : 0;
|
||||
|
||||
case SyntaxKind.CatchClause:
|
||||
case SyntaxKind.ForStatement:
|
||||
@@ -1194,6 +1211,7 @@ namespace ts {
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
// Interface/Object-types always have their children added to the 'members' of
|
||||
// their container. They are only accessible through an instance of their
|
||||
// container, and are never in scope otherwise (even inside the body of the
|
||||
@@ -1222,7 +1240,7 @@ namespace ts {
|
||||
// their container in the tree. To accomplish this, we simply add their declared
|
||||
// symbol to the 'locals' of the container. These symbols can then be found as
|
||||
// the type checker walks up the containers, checking them for matching names.
|
||||
return declareSymbol(container.locals, undefined, node, symbolFlags, symbolExcludes);
|
||||
return declareSymbol(container.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1560,15 +1578,9 @@ namespace ts {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.parent = parent;
|
||||
|
||||
const savedInStrictMode = inStrictMode;
|
||||
if (!savedInStrictMode) {
|
||||
updateStrictMode(node);
|
||||
}
|
||||
|
||||
// First we bind declaration nodes to a symbol if possible. We'll both create a symbol
|
||||
const saveInStrictMode = inStrictMode;
|
||||
// First we bind declaration nodes to a symbol if possible. We'll both create a symbol
|
||||
// and then potentially add the symbol to an appropriate symbol table. Possible
|
||||
// destination symbol tables are:
|
||||
//
|
||||
@@ -1576,47 +1588,40 @@ namespace ts {
|
||||
// 2) The 'members' table of the current container's symbol.
|
||||
// 3) The 'locals' table of the current container.
|
||||
//
|
||||
// However, not all symbols will end up in any of these tables. 'Anonymous' symbols
|
||||
// However, not all symbols will end up in any of these tables. 'Anonymous' symbols
|
||||
// (like TypeLiterals for example) will not be put in any table.
|
||||
bindWorker(node);
|
||||
|
||||
// Then we recurse into the children of the node to bind them as well. For certain
|
||||
// symbols we do specialized work when we recurse. For example, we'll keep track of
|
||||
// the current 'container' node when it changes. This helps us know which symbol table
|
||||
// a local should go into for example.
|
||||
bindChildren(node);
|
||||
|
||||
inStrictMode = savedInStrictMode;
|
||||
}
|
||||
|
||||
function updateStrictMode(node: Node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
case SyntaxKind.ModuleBlock:
|
||||
updateStrictModeStatementList((<SourceFile | ModuleBlock>node).statements);
|
||||
return;
|
||||
case SyntaxKind.Block:
|
||||
if (isFunctionLike(node.parent)) {
|
||||
updateStrictModeStatementList((<Block>node).statements);
|
||||
}
|
||||
return;
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
// All classes are automatically in strict mode in ES6.
|
||||
inStrictMode = true;
|
||||
return;
|
||||
// Then we recurse into the children of the node to bind them as well. For certain
|
||||
// symbols we do specialized work when we recurse. For example, we'll keep track of
|
||||
// the current 'container' node when it changes. This helps us know which symbol table
|
||||
// a local should go into for example. Since terminal nodes are known not to have
|
||||
// children, as an optimization we don't process those.
|
||||
if (node.kind > SyntaxKind.LastToken) {
|
||||
const saveParent = parent;
|
||||
parent = node;
|
||||
const containerFlags = getContainerFlags(node);
|
||||
if (containerFlags === ContainerFlags.None) {
|
||||
bindChildren(node);
|
||||
}
|
||||
else {
|
||||
bindContainer(node, containerFlags);
|
||||
}
|
||||
parent = saveParent;
|
||||
}
|
||||
inStrictMode = saveInStrictMode;
|
||||
}
|
||||
|
||||
function updateStrictModeStatementList(statements: NodeArray<Statement>) {
|
||||
for (const statement of statements) {
|
||||
if (!isPrologueDirective(statement)) {
|
||||
return;
|
||||
}
|
||||
if (!inStrictMode) {
|
||||
for (const statement of statements) {
|
||||
if (!isPrologueDirective(statement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isUseStrictPrologueDirective(<ExpressionStatement>statement)) {
|
||||
inStrictMode = true;
|
||||
return;
|
||||
if (isUseStrictPrologueDirective(<ExpressionStatement>statement)) {
|
||||
inStrictMode = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1696,6 +1701,8 @@ namespace ts {
|
||||
case SyntaxKind.PropertySignature:
|
||||
case SyntaxKind.JSDocRecordMember:
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property | ((<PropertyDeclaration>node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
|
||||
case SyntaxKind.JSDocPropertyTag:
|
||||
return bindJSDocProperty(<JSDocPropertyTag>node);
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
@@ -1703,7 +1710,7 @@ namespace ts {
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes);
|
||||
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
hasJsxSpreadAttribute = true;
|
||||
emitFlags |= NodeFlags.HasJsxSpreadAttribute;
|
||||
return;
|
||||
|
||||
case SyntaxKind.CallSignature:
|
||||
@@ -1731,6 +1738,7 @@ namespace ts {
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
return bindFunctionOrConstructorType(<SignatureDeclaration>node);
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
return bindAnonymousDeclaration(<TypeLiteralNode>node, SymbolFlags.TypeLiteral, "__type");
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
@@ -1748,9 +1756,12 @@ namespace ts {
|
||||
// Members of classes, interfaces, and modules
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
// All classes are automatically in strict mode in ES6.
|
||||
inStrictMode = true;
|
||||
return bindClassLikeDeclaration(<ClassLikeDeclaration>node);
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
return bindBlockScopedDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
@@ -1773,7 +1784,15 @@ namespace ts {
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return bindExportAssignment(<ExportAssignment>node);
|
||||
case SyntaxKind.SourceFile:
|
||||
updateStrictModeStatementList((<SourceFile>node).statements);
|
||||
return bindSourceFileIfExternalModule();
|
||||
case SyntaxKind.Block:
|
||||
if (!isFunctionLike(node.parent)) {
|
||||
return;
|
||||
}
|
||||
// Fall through
|
||||
case SyntaxKind.ModuleBlock:
|
||||
return updateStrictModeStatementList((<Block | ModuleBlock>node).statements);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1935,10 +1954,10 @@ namespace ts {
|
||||
function bindClassLikeDeclaration(node: ClassLikeDeclaration) {
|
||||
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
|
||||
if (getClassExtendsHeritageClauseElement(node) !== undefined) {
|
||||
hasClassExtends = true;
|
||||
emitFlags |= NodeFlags.HasClassExtends;
|
||||
}
|
||||
if (nodeIsDecorated(node)) {
|
||||
hasDecorators = true;
|
||||
emitFlags |= NodeFlags.HasDecorators;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2014,8 +2033,7 @@ namespace ts {
|
||||
if (!isDeclarationFile(file) &&
|
||||
!isInAmbientContext(node) &&
|
||||
nodeIsDecorated(node)) {
|
||||
hasDecorators = true;
|
||||
hasParameterDecorators = true;
|
||||
emitFlags |= (NodeFlags.HasDecorators | NodeFlags.HasParamDecorators);
|
||||
}
|
||||
|
||||
if (inStrictMode) {
|
||||
@@ -2042,7 +2060,7 @@ namespace ts {
|
||||
function bindFunctionDeclaration(node: FunctionDeclaration) {
|
||||
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
hasAsyncFunctions = true;
|
||||
emitFlags |= NodeFlags.HasAsyncFunctions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2059,10 +2077,12 @@ namespace ts {
|
||||
function bindFunctionExpression(node: FunctionExpression) {
|
||||
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
hasAsyncFunctions = true;
|
||||
emitFlags |= NodeFlags.HasAsyncFunctions;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFlow) {
|
||||
node.flowNode = currentFlow;
|
||||
}
|
||||
checkStrictModeFunctionName(<FunctionExpression>node);
|
||||
const bindingName = (<FunctionExpression>node).name ? (<FunctionExpression>node).name.text : "__function";
|
||||
return bindAnonymousDeclaration(<FunctionExpression>node, SymbolFlags.Function, bindingName);
|
||||
@@ -2071,10 +2091,10 @@ namespace ts {
|
||||
function bindPropertyOrMethodOrAccessor(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
|
||||
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
hasAsyncFunctions = true;
|
||||
emitFlags |= NodeFlags.HasAsyncFunctions;
|
||||
}
|
||||
if (nodeIsDecorated(node)) {
|
||||
hasDecorators = true;
|
||||
emitFlags |= NodeFlags.HasDecorators;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2083,6 +2103,10 @@ namespace ts {
|
||||
: declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
|
||||
}
|
||||
|
||||
function bindJSDocProperty(node: JSDocPropertyTag) {
|
||||
return declareSymbolAndAddToSymbolTable(node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
}
|
||||
|
||||
// reachability checks
|
||||
|
||||
function shouldReportErrorOnModuleDeclaration(node: ModuleDeclaration): boolean {
|
||||
|
||||
+116
-101
@@ -110,16 +110,16 @@ namespace ts {
|
||||
const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown");
|
||||
const resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__");
|
||||
|
||||
const nullableWideningFlags = strictNullChecks ? 0 : TypeFlags.ContainsUndefinedOrNull;
|
||||
const anyType = createIntrinsicType(TypeFlags.Any, "any");
|
||||
const stringType = createIntrinsicType(TypeFlags.String, "string");
|
||||
const numberType = createIntrinsicType(TypeFlags.Number, "number");
|
||||
const booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean");
|
||||
const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
|
||||
const voidType = createIntrinsicType(TypeFlags.Void, "void");
|
||||
const undefinedType = createIntrinsicType(TypeFlags.Undefined | nullableWideningFlags, "undefined");
|
||||
const nullType = createIntrinsicType(TypeFlags.Null | nullableWideningFlags, "null");
|
||||
const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined");
|
||||
const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
|
||||
const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsWideningType, "undefined");
|
||||
const nullType = createIntrinsicType(TypeFlags.Null, "null");
|
||||
const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsWideningType, "null");
|
||||
const unknownType = createIntrinsicType(TypeFlags.Any, "unknown");
|
||||
const neverType = createIntrinsicType(TypeFlags.Never, "never");
|
||||
|
||||
@@ -1180,11 +1180,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// This function is only for imports with entity names
|
||||
function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, importDeclaration?: ImportEqualsDeclaration): Symbol {
|
||||
if (!importDeclaration) {
|
||||
importDeclaration = <ImportEqualsDeclaration>getAncestor(entityName, SyntaxKind.ImportEqualsDeclaration);
|
||||
Debug.assert(importDeclaration !== undefined);
|
||||
}
|
||||
function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, importDeclaration: ImportEqualsDeclaration, dontResolveAlias?: boolean): Symbol {
|
||||
// There are three things we might try to look for. In the following examples,
|
||||
// the search term is enclosed in |...|:
|
||||
//
|
||||
@@ -1196,13 +1192,13 @@ namespace ts {
|
||||
}
|
||||
// Check for case 1 and 3 in the above example
|
||||
if (entityName.kind === SyntaxKind.Identifier || entityName.parent.kind === SyntaxKind.QualifiedName) {
|
||||
return resolveEntityName(entityName, SymbolFlags.Namespace);
|
||||
return resolveEntityName(entityName, SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias);
|
||||
}
|
||||
else {
|
||||
// Case 2 in above example
|
||||
// entityName.kind could be a QualifiedName or a Missing identifier
|
||||
Debug.assert(entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration);
|
||||
return resolveEntityName(entityName, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace);
|
||||
return resolveEntityName(entityName, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1211,7 +1207,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Resolves a qualified name and any involved aliases
|
||||
function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors?: boolean): Symbol {
|
||||
function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean): Symbol {
|
||||
if (nodeIsMissing(name)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1245,7 +1241,7 @@ namespace ts {
|
||||
Debug.fail("Unknown entity name kind.");
|
||||
}
|
||||
Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
|
||||
return symbol.flags & meaning ? symbol : resolveAlias(symbol);
|
||||
return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol);
|
||||
}
|
||||
|
||||
function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression): Symbol {
|
||||
@@ -3409,7 +3405,7 @@ namespace ts {
|
||||
error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
|
||||
return type.resolvedBaseConstructorType = unknownType;
|
||||
}
|
||||
if (baseConstructorType !== unknownType && baseConstructorType !== nullType && !isConstructorType(baseConstructorType)) {
|
||||
if (baseConstructorType !== unknownType && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) {
|
||||
error(baseTypeNode.expression, Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType));
|
||||
return type.resolvedBaseConstructorType = unknownType;
|
||||
}
|
||||
@@ -3585,8 +3581,22 @@ namespace ts {
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.DeclaredType)) {
|
||||
return unknownType;
|
||||
}
|
||||
const declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
|
||||
let type = getTypeFromTypeNode(declaration.type);
|
||||
|
||||
let type: Type;
|
||||
let declaration: JSDocTypedefTag | TypeAliasDeclaration = <JSDocTypedefTag>getDeclarationOfKind(symbol, SyntaxKind.JSDocTypedefTag);
|
||||
if (declaration) {
|
||||
if (declaration.jsDocTypeLiteral) {
|
||||
type = getTypeFromTypeNode(declaration.jsDocTypeLiteral);
|
||||
}
|
||||
else {
|
||||
type = getTypeFromTypeNode(declaration.typeExpression.type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
|
||||
type = getTypeFromTypeNode(declaration.type);
|
||||
}
|
||||
|
||||
if (popTypeResolution()) {
|
||||
links.typeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
|
||||
if (links.typeParameters) {
|
||||
@@ -5001,6 +5011,7 @@ namespace ts {
|
||||
containsAny?: boolean;
|
||||
containsUndefined?: boolean;
|
||||
containsNull?: boolean;
|
||||
containsNonWideningType?: boolean;
|
||||
}
|
||||
|
||||
function addTypeToSet(typeSet: TypeSet, type: Type, typeSetKind: TypeFlags) {
|
||||
@@ -5011,6 +5022,7 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.Any) typeSet.containsAny = true;
|
||||
if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true;
|
||||
if (type.flags & TypeFlags.Null) typeSet.containsNull = true;
|
||||
if (!(type.flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true;
|
||||
}
|
||||
else if (type !== neverType && !contains(typeSet, type)) {
|
||||
typeSet.push(type);
|
||||
@@ -5071,8 +5083,8 @@ namespace ts {
|
||||
removeSubtypes(typeSet);
|
||||
}
|
||||
if (typeSet.length === 0) {
|
||||
return typeSet.containsNull ? nullType :
|
||||
typeSet.containsUndefined ? undefinedType :
|
||||
return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType :
|
||||
typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType :
|
||||
neverType;
|
||||
}
|
||||
else if (typeSet.length === 1) {
|
||||
@@ -5257,6 +5269,7 @@ namespace ts {
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.JSDocRecordType:
|
||||
return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node);
|
||||
@@ -5871,7 +5884,7 @@ namespace ts {
|
||||
if (!(target.flags & TypeFlags.Never)) {
|
||||
if (target.flags & TypeFlags.Any || source.flags & TypeFlags.Never) return Ternary.True;
|
||||
if (source.flags & TypeFlags.Undefined) {
|
||||
if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void) || source === emptyArrayElementType) return Ternary.True;
|
||||
if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void)) return Ternary.True;
|
||||
}
|
||||
if (source.flags & TypeFlags.Null) {
|
||||
if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True;
|
||||
@@ -6961,7 +6974,7 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.ObjectLiteral) {
|
||||
for (const p of getPropertiesOfObjectType(type)) {
|
||||
const t = getTypeOfSymbol(p);
|
||||
if (t.flags & TypeFlags.ContainsUndefinedOrNull) {
|
||||
if (t.flags & TypeFlags.ContainsWideningType) {
|
||||
if (!reportWideningErrorsInType(t)) {
|
||||
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t)));
|
||||
}
|
||||
@@ -7008,7 +7021,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
|
||||
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsUndefinedOrNull) {
|
||||
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsWideningType) {
|
||||
// Report implicit any error within type if possible, otherwise report error on declaration
|
||||
if (!reportWideningErrorsInType(type)) {
|
||||
reportImplicitAnyError(declaration, type);
|
||||
@@ -7649,7 +7662,7 @@ namespace ts {
|
||||
getInitialTypeOfBindingElement(<BindingElement>node);
|
||||
}
|
||||
|
||||
function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean) {
|
||||
function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, includeOuterFunctions: boolean) {
|
||||
let key: string;
|
||||
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
|
||||
return declaredType;
|
||||
@@ -7695,15 +7708,21 @@ namespace ts {
|
||||
getTypeAtFlowBranchLabel(<FlowLabel>flow) :
|
||||
getTypeAtFlowLoopLabel(<FlowLabel>flow);
|
||||
}
|
||||
else if (flow.flags & FlowFlags.Unreachable) {
|
||||
else if (flow.flags & FlowFlags.Start) {
|
||||
// Check if we should continue with the control flow of the containing function.
|
||||
const container = (<FlowStart>flow).container;
|
||||
if (container && includeOuterFunctions) {
|
||||
flow = container.flowNode;
|
||||
continue;
|
||||
}
|
||||
// At the top of the flow we have the initial type.
|
||||
type = initialType;
|
||||
}
|
||||
else {
|
||||
// Unreachable code errors are reported in the binding phase. Here we
|
||||
// simply return the declared type to reduce follow-on errors.
|
||||
type = declaredType;
|
||||
}
|
||||
else {
|
||||
// At the top of the flow we have the initial type.
|
||||
type = initialType;
|
||||
}
|
||||
if (flow.flags & FlowFlags.Shared) {
|
||||
// Record visited node and the associated type in the cache.
|
||||
visitedFlowNodes[visitedFlowCount] = flow;
|
||||
@@ -8072,6 +8091,26 @@ namespace ts {
|
||||
return expression;
|
||||
}
|
||||
|
||||
function getControlFlowContainer(node: Node): Node {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
if (isFunctionLike(node) || node.kind === SyntaxKind.ModuleBlock || node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.PropertyDeclaration) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isDeclarationIncludedInFlow(reference: Node, declaration: Declaration, includeOuterFunctions: boolean) {
|
||||
const declarationContainer = getControlFlowContainer(declaration);
|
||||
let container = getControlFlowContainer(reference);
|
||||
while (container !== declarationContainer &&
|
||||
(container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.ArrowFunction) &&
|
||||
(includeOuterFunctions || getImmediatelyInvokedFunctionExpression(<FunctionExpression>container))) {
|
||||
container = getControlFlowContainer(container);
|
||||
}
|
||||
return container === declarationContainer;
|
||||
}
|
||||
|
||||
function checkIdentifier(node: Identifier): Type {
|
||||
const symbol = getResolvedSymbol(node);
|
||||
|
||||
@@ -8128,10 +8167,11 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
const declaration = localOrExportSymbol.valueDeclaration;
|
||||
const includeOuterFunctions = isReadonlySymbol(localOrExportSymbol);
|
||||
const assumeInitialized = !strictNullChecks || (type.flags & TypeFlags.Any) !== 0 || !declaration ||
|
||||
getRootDeclaration(declaration).kind === SyntaxKind.Parameter || isInAmbientContext(declaration) ||
|
||||
getContainingFunctionOrModule(declaration) !== getContainingFunctionOrModule(node);
|
||||
const flowType = getFlowTypeOfReference(node, type, assumeInitialized);
|
||||
!isDeclarationIncludedInFlow(node, declaration, includeOuterFunctions);
|
||||
const flowType = getFlowTypeOfReference(node, type, assumeInitialized, includeOuterFunctions);
|
||||
if (!assumeInitialized && !(getNullableKind(type) & TypeFlags.Undefined) && getNullableKind(flowType) & TypeFlags.Undefined) {
|
||||
error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
|
||||
// Return the declared type to reduce follow-on errors
|
||||
@@ -8282,7 +8322,7 @@ namespace ts {
|
||||
const classInstanceType = <InterfaceType>getDeclaredTypeOfSymbol(classSymbol);
|
||||
const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType);
|
||||
|
||||
return baseConstructorType === nullType;
|
||||
return baseConstructorType === nullWideningType;
|
||||
}
|
||||
|
||||
function checkThisExpression(node: Node): Type {
|
||||
@@ -8380,7 +8420,7 @@ namespace ts {
|
||||
if (isClassLike(container.parent)) {
|
||||
const symbol = getSymbolOfNode(container.parent);
|
||||
const type = container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType;
|
||||
return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true);
|
||||
return getFlowTypeOfReference(node, type, /*assumeInitialized*/ true, /*includeOuterFunctions*/ true);
|
||||
}
|
||||
|
||||
if (isInJavaScriptFile(node)) {
|
||||
@@ -8665,20 +8705,6 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getImmediatelyInvokedFunctionExpression(func: FunctionExpression | MethodDeclaration) {
|
||||
if (isFunctionExpressionOrArrowFunction(func)) {
|
||||
let prev: Node = func;
|
||||
let parent: Node = func.parent;
|
||||
while (parent.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
prev = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
if (parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === prev) {
|
||||
return parent as CallExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In a variable, parameter or property declaration with a type annotation,
|
||||
// the contextual type of an initializer expression is the type of the variable, parameter or property.
|
||||
// Otherwise, in a parameter declaration of a contextually typed function expression,
|
||||
@@ -9187,7 +9213,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
return createArrayType(elementTypes.length ? getUnionType(elementTypes) : emptyArrayElementType);
|
||||
return createArrayType(elementTypes.length ? getUnionType(elementTypes) : strictNullChecks ? neverType : undefinedWideningType);
|
||||
}
|
||||
|
||||
function isNumericName(name: DeclarationName): boolean {
|
||||
@@ -9974,25 +10000,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
const propType = getTypeOfSymbol(prop);
|
||||
// Only compute control flow type if this is a property access expression that isn't an
|
||||
// assignment target, and the referenced property was declared as a variable, property,
|
||||
// accessor, or optional method.
|
||||
if (node.kind !== SyntaxKind.PropertyAccessExpression || isAssignmentTarget(node) ||
|
||||
!(propType.flags & TypeFlags.Union) && !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor))) {
|
||||
!(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) &&
|
||||
!(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) {
|
||||
return propType;
|
||||
}
|
||||
const leftmostNode = getLeftmostIdentifierOrThis(node);
|
||||
if (!leftmostNode) {
|
||||
return propType;
|
||||
}
|
||||
if (leftmostNode.kind === SyntaxKind.Identifier) {
|
||||
const leftmostSymbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(<Identifier>leftmostNode));
|
||||
if (!leftmostSymbol) {
|
||||
return propType;
|
||||
}
|
||||
const declaration = leftmostSymbol.valueDeclaration;
|
||||
if (!declaration || declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.Parameter && declaration.kind !== SyntaxKind.BindingElement) {
|
||||
return propType;
|
||||
}
|
||||
}
|
||||
return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true);
|
||||
return getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*includeOuterFunctions*/ false);
|
||||
}
|
||||
|
||||
function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
|
||||
@@ -10306,8 +10322,8 @@ namespace ts {
|
||||
return -1;
|
||||
}
|
||||
|
||||
function hasCorrectArity(node: CallLikeExpression, args: Expression[], signature: Signature) {
|
||||
let adjustedArgCount: number; // Apparent number of arguments we will have in this call
|
||||
function hasCorrectArity(node: CallLikeExpression, args: Expression[], signature: Signature, signatureHelpTrailingComma = false) {
|
||||
let argCount: number; // Apparent number of arguments we will have in this call
|
||||
let typeArguments: NodeArray<TypeNode>; // Type arguments (undefined if none)
|
||||
let callIsIncomplete: boolean; // In incomplete call we want to be lenient when we have too few arguments
|
||||
let isDecorator: boolean;
|
||||
@@ -10318,7 +10334,7 @@ namespace ts {
|
||||
|
||||
// Even if the call is incomplete, we'll have a missing expression as our last argument,
|
||||
// so we can say the count is just the arg list length
|
||||
adjustedArgCount = args.length;
|
||||
argCount = args.length;
|
||||
typeArguments = undefined;
|
||||
|
||||
if (tagExpression.template.kind === SyntaxKind.TemplateExpression) {
|
||||
@@ -10341,7 +10357,7 @@ namespace ts {
|
||||
else if (node.kind === SyntaxKind.Decorator) {
|
||||
isDecorator = true;
|
||||
typeArguments = undefined;
|
||||
adjustedArgCount = getEffectiveArgumentCount(node, /*args*/ undefined, signature);
|
||||
argCount = getEffectiveArgumentCount(node, /*args*/ undefined, signature);
|
||||
}
|
||||
else {
|
||||
const callExpression = <CallExpression>node;
|
||||
@@ -10352,8 +10368,7 @@ namespace ts {
|
||||
return signature.minArgumentCount === 0;
|
||||
}
|
||||
|
||||
// For IDE scenarios we may have an incomplete call, so a trailing comma is tantamount to adding another argument.
|
||||
adjustedArgCount = callExpression.arguments.hasTrailingComma ? args.length + 1 : args.length;
|
||||
argCount = signatureHelpTrailingComma ? args.length + 1 : args.length;
|
||||
|
||||
// If we are missing the close paren, the call is incomplete.
|
||||
callIsIncomplete = (<CallExpression>callExpression).arguments.end === callExpression.end;
|
||||
@@ -10377,12 +10392,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Too many arguments implies incorrect arity.
|
||||
if (!signature.hasRestParameter && adjustedArgCount > signature.parameters.length) {
|
||||
if (!signature.hasRestParameter && argCount > signature.parameters.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the call is incomplete, we should skip the lower bound check.
|
||||
const hasEnoughArguments = adjustedArgCount >= signature.minArgumentCount;
|
||||
const hasEnoughArguments = argCount >= signature.minArgumentCount;
|
||||
return callIsIncomplete || hasEnoughArguments;
|
||||
}
|
||||
|
||||
@@ -10954,6 +10969,11 @@ namespace ts {
|
||||
let resultOfFailedInference: InferenceContext;
|
||||
let result: Signature;
|
||||
|
||||
// If we are in signature help, a trailing comma indicates that we intend to provide another argument,
|
||||
// so we will only accept overloads with arity at least 1 higher than the current number of provided arguments.
|
||||
const signatureHelpTrailingComma =
|
||||
candidatesOutArray && node.kind === SyntaxKind.CallExpression && (<CallExpression>node).arguments.hasTrailingComma;
|
||||
|
||||
// Section 4.12.1:
|
||||
// if the candidate list contains one or more signatures for which the type of each argument
|
||||
// expression is a subtype of each corresponding parameter type, the return type of the first
|
||||
@@ -10965,14 +10985,14 @@ namespace ts {
|
||||
// is just important for choosing the best signature. So in the case where there is only one
|
||||
// signature, the subtype pass is useless. So skipping it is an optimization.
|
||||
if (candidates.length > 1) {
|
||||
result = chooseOverload(candidates, subtypeRelation);
|
||||
result = chooseOverload(candidates, subtypeRelation, signatureHelpTrailingComma);
|
||||
}
|
||||
if (!result) {
|
||||
// Reinitialize these pointers for round two
|
||||
candidateForArgumentError = undefined;
|
||||
candidateForTypeArgumentError = undefined;
|
||||
resultOfFailedInference = undefined;
|
||||
result = chooseOverload(candidates, assignableRelation);
|
||||
result = chooseOverload(candidates, assignableRelation, signatureHelpTrailingComma);
|
||||
}
|
||||
if (result) {
|
||||
return result;
|
||||
@@ -11043,9 +11063,9 @@ namespace ts {
|
||||
diagnostics.add(createDiagnosticForNodeFromMessageChain(node, errorInfo));
|
||||
}
|
||||
|
||||
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>) {
|
||||
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
|
||||
for (const originalCandidate of candidates) {
|
||||
if (!hasCorrectArity(node, args, originalCandidate)) {
|
||||
if (!hasCorrectArity(node, args, originalCandidate, signatureHelpTrailingComma)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -11262,7 +11282,7 @@ namespace ts {
|
||||
const declaringClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(declaration.parent.symbol);
|
||||
const declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(declaration.parent.symbol);
|
||||
|
||||
// A private or protected constructor can only be instantiated within it's own class
|
||||
// A private or protected constructor can only be instantiated within it's own class
|
||||
if (!isNodeWithinClass(node, declaringClassDeclaration)) {
|
||||
if (flags & NodeFlags.Private) {
|
||||
error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass));
|
||||
@@ -11987,7 +12007,7 @@ namespace ts {
|
||||
|
||||
function checkVoidExpression(node: VoidExpression): Type {
|
||||
checkExpression(node.expression);
|
||||
return undefinedType;
|
||||
return undefinedWideningType;
|
||||
}
|
||||
|
||||
function checkAwaitExpression(node: AwaitExpression): Type {
|
||||
@@ -12394,7 +12414,7 @@ namespace ts {
|
||||
case SyntaxKind.InKeyword:
|
||||
return checkInExpression(left, right, leftType, rightType);
|
||||
case SyntaxKind.AmpersandAmpersandToken:
|
||||
return addNullableKind(rightType, getNullableKind(leftType));
|
||||
return strictNullChecks ? addNullableKind(rightType, getNullableKind(leftType)) : rightType;
|
||||
case SyntaxKind.BarBarToken:
|
||||
return getUnionType([getNonNullableType(leftType), rightType]);
|
||||
case SyntaxKind.EqualsToken:
|
||||
@@ -12661,7 +12681,7 @@ namespace ts {
|
||||
case SyntaxKind.SuperKeyword:
|
||||
return checkSuperExpression(node);
|
||||
case SyntaxKind.NullKeyword:
|
||||
return nullType;
|
||||
return nullWideningType;
|
||||
case SyntaxKind.TrueKeyword:
|
||||
case SyntaxKind.FalseKeyword:
|
||||
return booleanType;
|
||||
@@ -12719,7 +12739,7 @@ namespace ts {
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
return checkSpreadElementExpression(<SpreadElementExpression>node, contextualMapper);
|
||||
case SyntaxKind.OmittedExpression:
|
||||
return undefinedType;
|
||||
return undefinedWideningType;
|
||||
case SyntaxKind.YieldExpression:
|
||||
return checkYieldExpression(<YieldExpression>node);
|
||||
case SyntaxKind.JsxExpression:
|
||||
@@ -15090,7 +15110,7 @@ namespace ts {
|
||||
// In a 'switch' statement, each 'case' expression must be of a type that is comparable
|
||||
// to or from the type of the 'switch' expression.
|
||||
const caseType = checkExpression(caseClause.expression);
|
||||
if (!isTypeComparableTo(expressionType, caseType)) {
|
||||
if (!isTypeEqualityComparableTo(expressionType, caseType)) {
|
||||
// expressionType is not comparable to caseType, try the reversed check and report errors if it fails
|
||||
checkTypeComparableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);
|
||||
}
|
||||
@@ -16125,12 +16145,12 @@ namespace ts {
|
||||
const symbol = getSymbolOfNode(node);
|
||||
const target = resolveAlias(symbol);
|
||||
if (target !== unknownSymbol) {
|
||||
// For external modules symbol represent local symbol for an alias.
|
||||
// For external modules symbol represent local symbol for an alias.
|
||||
// This local symbol will merge any other local declarations (excluding other aliases)
|
||||
// and symbol.flags will contains combined representation for all merged declaration.
|
||||
// Based on symbol.flags we can compute a set of excluded meanings (meaning that resolved alias should not have,
|
||||
// otherwise it will conflict with some local declaration). Note that in addition to normal flags we include matching SymbolFlags.Export*
|
||||
// in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names).
|
||||
// otherwise it will conflict with some local declaration). Note that in addition to normal flags we include matching SymbolFlags.Export*
|
||||
// in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names).
|
||||
const excludedMeanings =
|
||||
(symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) |
|
||||
(symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) |
|
||||
@@ -16329,7 +16349,7 @@ namespace ts {
|
||||
continue;
|
||||
}
|
||||
const { declarations, flags } = exports[id];
|
||||
// ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.
|
||||
// ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries.
|
||||
// (TS Exceptions: namespaces, function overloads, enums, and interfaces)
|
||||
if (flags & (SymbolFlags.Namespace | SymbolFlags.Interface | SymbolFlags.Enum)) {
|
||||
continue;
|
||||
@@ -16728,7 +16748,7 @@ namespace ts {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return node.parent && node.parent.kind === SyntaxKind.TypeReference;
|
||||
return node.parent && (node.parent.kind === SyntaxKind.TypeReference || node.parent.kind === SyntaxKind.JSDocTypeReference) ;
|
||||
}
|
||||
|
||||
function isHeritageClauseElementIdentifier(entityName: Node): boolean {
|
||||
@@ -16803,7 +16823,9 @@ namespace ts {
|
||||
if (entityName.kind !== SyntaxKind.PropertyAccessExpression) {
|
||||
if (isInRightSideOfImportOrExportAssignment(<EntityName>entityName)) {
|
||||
// Since we already checked for ExportAssignment, this really could only be an Import
|
||||
return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>entityName);
|
||||
const importEqualsDeclaration = <ImportEqualsDeclaration>getAncestor(entityName, SyntaxKind.ImportEqualsDeclaration);
|
||||
Debug.assert(importEqualsDeclaration !== undefined);
|
||||
return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>entityName, importEqualsDeclaration, /*dontResolveAlias*/ true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16862,7 +16884,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (isTypeReferenceIdentifier(<EntityName>entityName)) {
|
||||
let meaning = entityName.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
|
||||
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;
|
||||
@@ -16899,9 +16921,7 @@ namespace ts {
|
||||
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
if (isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
|
||||
return node.parent.kind === SyntaxKind.ExportAssignment
|
||||
? getSymbolOfEntityNameOrPropertyAccessExpression(<Identifier>node)
|
||||
: getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node);
|
||||
return getSymbolOfEntityNameOrPropertyAccessExpression(<Identifier>node);
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.BindingElement &&
|
||||
node.parent.parent.kind === SyntaxKind.ObjectBindingPattern &&
|
||||
@@ -17034,10 +17054,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Gets the type of object literal or array literal of destructuring assignment.
|
||||
// { a } from
|
||||
// { a } from
|
||||
// for ( { a } of elems) {
|
||||
// }
|
||||
// [ a ] from
|
||||
// [ a ] from
|
||||
// [a] = [ some array ...]
|
||||
function getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr: Expression): Type {
|
||||
Debug.assert(expr.kind === SyntaxKind.ObjectLiteralExpression || expr.kind === SyntaxKind.ArrayLiteralExpression);
|
||||
@@ -17070,10 +17090,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Gets the property symbol corresponding to the property in destructuring assignment
|
||||
// 'property1' from
|
||||
// 'property1' from
|
||||
// for ( { property1: a } of elems) {
|
||||
// }
|
||||
// 'property1' at location 'a' from:
|
||||
// 'property1' at location 'a' from:
|
||||
// [a] = [ property1, property2 ]
|
||||
function getPropertySymbolOfDestructuringAssignment(location: Identifier) {
|
||||
// Get the type of the object or array literal and then look for property of given name in the type
|
||||
@@ -17633,7 +17653,7 @@ namespace ts {
|
||||
// Setup global builtins
|
||||
addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0);
|
||||
|
||||
getSymbolLinks(undefinedSymbol).type = undefinedType;
|
||||
getSymbolLinks(undefinedSymbol).type = undefinedWideningType;
|
||||
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
|
||||
getSymbolLinks(unknownSymbol).type = unknownType;
|
||||
|
||||
@@ -18012,10 +18032,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkGrammarParameterList(parameters: NodeArray<ParameterDeclaration>) {
|
||||
if (checkGrammarForDisallowedTrailingComma(parameters)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let seenOptionalParameter = false;
|
||||
const parameterCount = parameters.length;
|
||||
|
||||
@@ -18134,8 +18150,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkGrammarArguments(node: CallExpression, args: NodeArray<Expression>): boolean {
|
||||
return checkGrammarForDisallowedTrailingComma(args) ||
|
||||
checkGrammarForOmittedArgument(node, args);
|
||||
return checkGrammarForOmittedArgument(node, args);
|
||||
}
|
||||
|
||||
function checkGrammarHeritageClause(node: HeritageClause): boolean {
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace ts {
|
||||
// Emit reference in dts, if the file reference was not already emitted
|
||||
if (referencedFile && !contains(emittedReferencedFiles, referencedFile)) {
|
||||
// Add a reference to generated dts file,
|
||||
// global file reference is added only
|
||||
// global file reference is added only
|
||||
// - if it is not bundled emit (because otherwise it would be self reference)
|
||||
// - and it is not already added
|
||||
if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) {
|
||||
@@ -148,7 +148,7 @@ namespace ts {
|
||||
|
||||
if (!isBundledEmit && isExternalModule(sourceFile) && sourceFile.moduleAugmentations.length && !resultHasExternalModuleIndicator) {
|
||||
// if file was external module with augmentations - this fact should be preserved in .d.ts as well.
|
||||
// in case if we didn't write any external module specifiers in .d.ts we need to emit something
|
||||
// in case if we didn't write any external module specifiers in .d.ts we need to emit something
|
||||
// that will force compiler to think that this file is an external module - 'export {}' is a reasonable choice here.
|
||||
write("export {};");
|
||||
writeLine();
|
||||
@@ -766,7 +766,7 @@ namespace ts {
|
||||
|
||||
function emitExternalModuleSpecifier(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration) {
|
||||
// emitExternalModuleSpecifier is usually called when we emit something in the.d.ts file that will make it an external module (i.e. import/export declarations).
|
||||
// the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered
|
||||
// the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered
|
||||
// external modules since they are indistinguishable from script files with ambient modules. To fix this in such d.ts files we'll emit top level 'export {}'
|
||||
// so compiler will treat them as external modules.
|
||||
resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== SyntaxKind.ModuleDeclaration;
|
||||
|
||||
@@ -819,6 +819,10 @@
|
||||
"category": "Error",
|
||||
"code": 1252
|
||||
},
|
||||
"'{0}' tag cannot be used independently as a top level JSDoc tag.": {
|
||||
"category": "Error",
|
||||
"code": 1253
|
||||
},
|
||||
"'with' statements are not allowed in an async function block.": {
|
||||
"category": "Error",
|
||||
"code": 1300
|
||||
|
||||
+64
-10
@@ -2613,11 +2613,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
return isSourceFileLevelDeclarationInSystemJsModule(targetDeclaration, /*isExported*/ true);
|
||||
}
|
||||
|
||||
function isNameOfExportedDeclarationInNonES6Module(node: Node): boolean {
|
||||
if (modulekind === ModuleKind.System || node.kind !== SyntaxKind.Identifier || nodeIsSynthesized(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, (<Identifier>node).text);
|
||||
}
|
||||
|
||||
function emitPrefixUnaryExpression(node: PrefixUnaryExpression) {
|
||||
const exportChanged = (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) &&
|
||||
const isPlusPlusOrMinusMinus = (node.operator === SyntaxKind.PlusPlusToken
|
||||
|| node.operator === SyntaxKind.MinusMinusToken);
|
||||
const externalExportChanged = isPlusPlusOrMinusMinus &&
|
||||
isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand);
|
||||
|
||||
if (exportChanged) {
|
||||
if (externalExportChanged) {
|
||||
// emit
|
||||
// ++x
|
||||
// as
|
||||
@@ -2626,6 +2636,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
emitNodeWithoutSourceMap(node.operand);
|
||||
write(`", `);
|
||||
}
|
||||
const internalExportChanged = isPlusPlusOrMinusMinus &&
|
||||
isNameOfExportedDeclarationInNonES6Module(node.operand);
|
||||
|
||||
if (internalExportChanged) {
|
||||
emitAliasEqual(<Identifier> node.operand);
|
||||
}
|
||||
|
||||
write(tokenToString(node.operator));
|
||||
// In some cases, we need to emit a space between the operator and the operand. One obvious case
|
||||
@@ -2651,14 +2667,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
}
|
||||
emit(node.operand);
|
||||
|
||||
if (exportChanged) {
|
||||
if (externalExportChanged) {
|
||||
write(")");
|
||||
}
|
||||
}
|
||||
|
||||
function emitPostfixUnaryExpression(node: PostfixUnaryExpression) {
|
||||
const exportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand);
|
||||
if (exportChanged) {
|
||||
const externalExportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand);
|
||||
const internalExportChanged = isNameOfExportedDeclarationInNonES6Module(node.operand);
|
||||
|
||||
if (externalExportChanged) {
|
||||
// export function returns the value that was passes as the second argument
|
||||
// however for postfix unary expressions result value should be the value before modification.
|
||||
// emit 'x++' as '(export('x', ++x) - 1)' and 'x--' as '(export('x', --x) + 1)'
|
||||
@@ -2676,6 +2694,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
write(") + 1)");
|
||||
}
|
||||
}
|
||||
else if (internalExportChanged) {
|
||||
emitAliasEqual(<Identifier> node.operand);
|
||||
emit(node.operand);
|
||||
if (node.operator === SyntaxKind.PlusPlusToken) {
|
||||
write(" += 1");
|
||||
}
|
||||
else {
|
||||
write(" -= 1");
|
||||
}
|
||||
}
|
||||
else {
|
||||
emit(node.operand);
|
||||
write(tokenToString(node.operator));
|
||||
@@ -2777,24 +2805,50 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
}
|
||||
}
|
||||
|
||||
function emitAliasEqual(name: Identifier): boolean {
|
||||
for (const specifier of exportSpecifiers[name.text]) {
|
||||
emitStart(specifier.name);
|
||||
emitContainingModuleName(specifier);
|
||||
if (languageVersion === ScriptTarget.ES3 && name.text === "default") {
|
||||
write('["default"]');
|
||||
}
|
||||
else {
|
||||
write(".");
|
||||
emitNodeWithCommentsAndWithoutSourcemap(specifier.name);
|
||||
}
|
||||
emitEnd(specifier.name);
|
||||
write(" = ");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function emitBinaryExpression(node: BinaryExpression) {
|
||||
if (languageVersion < ScriptTarget.ES6 && node.operatorToken.kind === SyntaxKind.EqualsToken &&
|
||||
(node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) {
|
||||
emitDestructuring(node, node.parent.kind === SyntaxKind.ExpressionStatement);
|
||||
}
|
||||
else {
|
||||
const exportChanged =
|
||||
node.operatorToken.kind >= SyntaxKind.FirstAssignment &&
|
||||
node.operatorToken.kind <= SyntaxKind.LastAssignment &&
|
||||
const isAssignment = isAssignmentOperator(node.operatorToken.kind);
|
||||
|
||||
const externalExportChanged = isAssignment &&
|
||||
isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.left);
|
||||
|
||||
if (exportChanged) {
|
||||
if (externalExportChanged) {
|
||||
// emit assignment 'x <op> y' as 'exports("x", x <op> y)'
|
||||
write(`${exportFunctionForFile}("`);
|
||||
emitNodeWithoutSourceMap(node.left);
|
||||
write(`", `);
|
||||
}
|
||||
|
||||
const internalExportChanged = isAssignment &&
|
||||
isNameOfExportedDeclarationInNonES6Module(node.left);
|
||||
|
||||
if (internalExportChanged) {
|
||||
// export { foo }
|
||||
// emit foo = 2 as exports.foo = foo = 2
|
||||
emitAliasEqual(<Identifier>node.left);
|
||||
}
|
||||
|
||||
if (node.operatorToken.kind === SyntaxKind.AsteriskAsteriskToken || node.operatorToken.kind === SyntaxKind.AsteriskAsteriskEqualsToken) {
|
||||
// Downleveled emit exponentiation operator using Math.pow
|
||||
emitExponentiationOperator(node);
|
||||
@@ -2815,7 +2869,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
decreaseIndentIf(indentedBeforeOperator, indentedAfterOperator);
|
||||
}
|
||||
|
||||
if (exportChanged) {
|
||||
if (externalExportChanged) {
|
||||
write(")");
|
||||
}
|
||||
}
|
||||
|
||||
+164
-18
@@ -401,6 +401,15 @@ namespace ts {
|
||||
return visitNode(cbNode, (<JSDocTypeTag>node).typeExpression);
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
return visitNodes(cbNodes, (<JSDocTemplateTag>node).typeParameters);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression) ||
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).name) ||
|
||||
visitNode(cbNode, (<JSDocTypedefTag>node).jsDocTypeLiteral);
|
||||
case SyntaxKind.JSDocTypeLiteral:
|
||||
return visitNodes(cbNodes, (<JSDocTypeLiteral>node).jsDocPropertyTags);
|
||||
case SyntaxKind.JSDocPropertyTag:
|
||||
return visitNode(cbNode, (<JSDocPropertyTag>node).typeExpression) ||
|
||||
visitNode(cbNode, (<JSDocPropertyTag>node).name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,7 +440,14 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
export function parseIsolatedJSDocComment(content: string, start?: number, length?: number) {
|
||||
return Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
|
||||
const result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
|
||||
if (result && result.jsDocComment) {
|
||||
// because the jsDocComment was parsed out of the source file, it might
|
||||
// not be covered by the fixupParentReferences.
|
||||
Parser.fixupParentReferences(result.jsDocComment);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -628,9 +644,14 @@ namespace ts {
|
||||
if (comments) {
|
||||
for (const comment of comments) {
|
||||
const jsDocComment = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos);
|
||||
if (jsDocComment) {
|
||||
node.jsDocComment = jsDocComment;
|
||||
if (!jsDocComment) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.jsDocComments) {
|
||||
node.jsDocComments = [];
|
||||
}
|
||||
node.jsDocComments.push(jsDocComment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -638,14 +659,14 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function fixupParentReferences(sourceFile: Node) {
|
||||
export function fixupParentReferences(rootNode: Node) {
|
||||
// normally parent references are set during binding. However, for clients that only need
|
||||
// a syntax tree, and no semantic features, then the binding process is an unnecessary
|
||||
// overhead. This functions allows us to set all the parents, without all the expense of
|
||||
// binding.
|
||||
|
||||
let parent: Node = sourceFile;
|
||||
forEachChild(sourceFile, visitNode);
|
||||
let parent: Node = rootNode;
|
||||
forEachChild(rootNode, visitNode);
|
||||
return;
|
||||
|
||||
function visitNode(n: Node): void {
|
||||
@@ -658,6 +679,13 @@ namespace ts {
|
||||
const saveParent = parent;
|
||||
parent = n;
|
||||
forEachChild(n, visitNode);
|
||||
if (n.jsDocComments) {
|
||||
for (const jsDocComment of n.jsDocComments) {
|
||||
jsDocComment.parent = n;
|
||||
parent = jsDocComment;
|
||||
forEachChild(jsDocComment, visitNode);
|
||||
}
|
||||
}
|
||||
parent = saveParent;
|
||||
}
|
||||
}
|
||||
@@ -2704,7 +2732,7 @@ namespace ts {
|
||||
// 1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In]
|
||||
// 2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In]
|
||||
// Production (1) of AsyncArrowFunctionExpression is parsed in "tryParseAsyncSimpleArrowFunctionExpression".
|
||||
// And production (2) is parsed in "tryParseParenthesizedArrowFunctionExpression".
|
||||
// And production (2) is parsed in "tryParseParenthesizedArrowFunctionExpression".
|
||||
//
|
||||
// If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
|
||||
// not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done
|
||||
@@ -3396,8 +3424,8 @@ namespace ts {
|
||||
if (sourceFile.languageVariant !== LanguageVariant.JSX) {
|
||||
return false;
|
||||
}
|
||||
// We are in JSX context and the token is part of JSXElement.
|
||||
// Fall through
|
||||
// We are in JSX context and the token is part of JSXElement.
|
||||
// Fall through
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
@@ -4099,9 +4127,9 @@ namespace ts {
|
||||
const isAsync = !!(node.flags & NodeFlags.Async);
|
||||
node.name =
|
||||
isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) :
|
||||
isGenerator ? doInYieldContext(parseOptionalIdentifier) :
|
||||
isAsync ? doInAwaitContext(parseOptionalIdentifier) :
|
||||
parseOptionalIdentifier();
|
||||
isGenerator ? doInYieldContext(parseOptionalIdentifier) :
|
||||
isAsync ? doInAwaitContext(parseOptionalIdentifier) :
|
||||
parseOptionalIdentifier();
|
||||
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, node);
|
||||
node.body = parseFunctionBlock(/*allowYield*/ isGenerator, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false);
|
||||
@@ -5891,7 +5919,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkForEmptyTypeArgumentList(typeArguments: NodeArray<Node>) {
|
||||
if (parseDiagnostics.length === 0 && typeArguments && typeArguments.length === 0) {
|
||||
if (parseDiagnostics.length === 0 && typeArguments && typeArguments.length === 0) {
|
||||
const start = typeArguments.pos - "<".length;
|
||||
const end = skipTrivia(sourceText, typeArguments.end) + ">".length;
|
||||
return parseErrorAtPosition(start, end - start, Diagnostics.Type_argument_list_cannot_be_empty);
|
||||
@@ -6052,7 +6080,6 @@ namespace ts {
|
||||
Debug.assert(end <= content.length);
|
||||
|
||||
let tags: NodeArray<JSDocTag>;
|
||||
|
||||
let result: JSDocComment;
|
||||
|
||||
// Check for /** (JSDoc opening part)
|
||||
@@ -6159,6 +6186,8 @@ namespace ts {
|
||||
return handleTemplateTag(atToken, tagName);
|
||||
case "type":
|
||||
return handleTypeTag(atToken, tagName);
|
||||
case "typedef":
|
||||
return handleTypedefTag(atToken, tagName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6266,6 +6295,122 @@ namespace ts {
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function handlePropertyTag(atToken: Node, tagName: Identifier): JSDocPropertyTag {
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
const name = parseJSDocIdentifierName();
|
||||
if (!name) {
|
||||
parseErrorAtPosition(scanner.getStartPos(), /*length*/ 0, Diagnostics.Identifier_expected);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result = <JSDocPropertyTag>createNode(SyntaxKind.JSDocPropertyTag, atToken.pos);
|
||||
result.atToken = atToken;
|
||||
result.tagName = tagName;
|
||||
result.name = name;
|
||||
result.typeExpression = typeExpression;
|
||||
return finishNode(result);
|
||||
}
|
||||
|
||||
function handleTypedefTag(atToken: Node, tagName: Identifier): JSDocTypedefTag {
|
||||
const typeExpression = tryParseTypeExpression();
|
||||
skipWhitespace();
|
||||
|
||||
const typedefTag = <JSDocTypedefTag>createNode(SyntaxKind.JSDocTypedefTag, atToken.pos);
|
||||
typedefTag.atToken = atToken;
|
||||
typedefTag.tagName = tagName;
|
||||
typedefTag.name = parseJSDocIdentifierName();
|
||||
typedefTag.typeExpression = typeExpression;
|
||||
|
||||
if (typeExpression) {
|
||||
if (typeExpression.type.kind === SyntaxKind.JSDocTypeReference) {
|
||||
const jsDocTypeReference = <JSDocTypeReference>typeExpression.type;
|
||||
if (jsDocTypeReference.name.kind === SyntaxKind.Identifier) {
|
||||
const name = <Identifier>jsDocTypeReference.name;
|
||||
if (name.text === "Object") {
|
||||
typedefTag.jsDocTypeLiteral = scanChildTags();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!typedefTag.jsDocTypeLiteral) {
|
||||
typedefTag.jsDocTypeLiteral = typeExpression.type;
|
||||
}
|
||||
}
|
||||
else {
|
||||
typedefTag.jsDocTypeLiteral = scanChildTags();
|
||||
}
|
||||
|
||||
return finishNode(typedefTag);
|
||||
|
||||
function scanChildTags(): JSDocTypeLiteral {
|
||||
const jsDocTypeLiteral = <JSDocTypeLiteral>createNode(SyntaxKind.JSDocTypeLiteral, scanner.getStartPos());
|
||||
let resumePos = scanner.getStartPos();
|
||||
let canParseTag = true;
|
||||
let seenAsterisk = false;
|
||||
let parentTagTerminated = false;
|
||||
|
||||
while (token !== SyntaxKind.EndOfFileToken && !parentTagTerminated) {
|
||||
nextJSDocToken();
|
||||
switch (token) {
|
||||
case SyntaxKind.AtToken:
|
||||
if (canParseTag) {
|
||||
parentTagTerminated = !tryParseChildTag(jsDocTypeLiteral);
|
||||
}
|
||||
seenAsterisk = false;
|
||||
break;
|
||||
case SyntaxKind.NewLineTrivia:
|
||||
resumePos = scanner.getStartPos() - 1;
|
||||
canParseTag = true;
|
||||
seenAsterisk = false;
|
||||
break;
|
||||
case SyntaxKind.AsteriskToken:
|
||||
if (seenAsterisk) {
|
||||
canParseTag = false;
|
||||
}
|
||||
seenAsterisk = true;
|
||||
break;
|
||||
case SyntaxKind.Identifier:
|
||||
canParseTag = false;
|
||||
case SyntaxKind.EndOfFileToken:
|
||||
break;
|
||||
}
|
||||
}
|
||||
scanner.setTextPos(resumePos);
|
||||
return finishNode(jsDocTypeLiteral);
|
||||
}
|
||||
}
|
||||
|
||||
function tryParseChildTag(parentTag: JSDocTypeLiteral): boolean {
|
||||
Debug.assert(token === SyntaxKind.AtToken);
|
||||
const atToken = createNode(SyntaxKind.AtToken, scanner.getStartPos());
|
||||
atToken.end = scanner.getTextPos();
|
||||
nextJSDocToken();
|
||||
|
||||
const tagName = parseJSDocIdentifierName();
|
||||
if (!tagName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (tagName.text) {
|
||||
case "type":
|
||||
if (parentTag.jsDocTypeTag) {
|
||||
// already has a @type tag, terminate the parent tag now.
|
||||
return false;
|
||||
}
|
||||
parentTag.jsDocTypeTag = handleTypeTag(atToken, tagName);
|
||||
return true;
|
||||
case "prop":
|
||||
case "property":
|
||||
if (!parentTag.jsDocPropertyTags) {
|
||||
parentTag.jsDocPropertyTags = <NodeArray<JSDocPropertyTag>>[];
|
||||
}
|
||||
const propertyTag = handlePropertyTag(atToken, tagName);
|
||||
parentTag.jsDocPropertyTags.push(propertyTag);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleTemplateTag(atToken: Node, tagName: Identifier): JSDocTemplateTag {
|
||||
if (forEach(tags, t => t.kind === SyntaxKind.JSDocTemplateTag)) {
|
||||
parseErrorAtPosition(tagName.pos, scanner.getTokenPos() - tagName.pos, Diagnostics._0_tag_already_specified, tagName.text);
|
||||
@@ -6435,10 +6580,6 @@ namespace ts {
|
||||
node._children = undefined;
|
||||
}
|
||||
|
||||
if (node.jsDocComment) {
|
||||
node.jsDocComment = undefined;
|
||||
}
|
||||
|
||||
node.pos += delta;
|
||||
node.end += delta;
|
||||
|
||||
@@ -6447,6 +6588,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
forEachChild(node, visitNode, visitArray);
|
||||
if (node.jsDocComments) {
|
||||
for (const jsDocComment of node.jsDocComments) {
|
||||
forEachChild(jsDocComment, visitNode, visitArray);
|
||||
}
|
||||
}
|
||||
checkNodePositions(node, aggressiveChecks);
|
||||
}
|
||||
|
||||
|
||||
@@ -1143,6 +1143,7 @@ namespace ts {
|
||||
// if any of these properties has changed - structure cannot be reused
|
||||
const oldOptions = oldProgram.getCompilerOptions();
|
||||
if ((oldOptions.module !== options.module) ||
|
||||
(oldOptions.moduleResolution !== options.moduleResolution) ||
|
||||
(oldOptions.noResolve !== options.noResolve) ||
|
||||
(oldOptions.target !== options.target) ||
|
||||
(oldOptions.noLib !== options.noLib) ||
|
||||
|
||||
@@ -434,7 +434,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
|
||||
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean, stopAtComments = false): number {
|
||||
// Using ! with a greater than test is a fast way of testing the following conditions:
|
||||
// pos === undefined || pos === null || isNaN(pos) || pos < 0;
|
||||
if (!(pos >= 0)) {
|
||||
@@ -462,6 +462,9 @@ namespace ts {
|
||||
pos++;
|
||||
continue;
|
||||
case CharacterCodes.slash:
|
||||
if (stopAtComments) {
|
||||
break;
|
||||
}
|
||||
if (text.charCodeAt(pos + 1) === CharacterCodes.slash) {
|
||||
pos += 2;
|
||||
while (pos < text.length) {
|
||||
|
||||
@@ -168,7 +168,7 @@ namespace ts {
|
||||
sourceMapData.sourceMapDecodedMappings[sourceMapData.sourceMapDecodedMappings.length - 1] :
|
||||
defaultLastEncodedSourceMapSpan;
|
||||
|
||||
// TODO: Update lastEncodedNameIndex
|
||||
// TODO: Update lastEncodedNameIndex
|
||||
// Since we dont support this any more, lets not worry about it right now.
|
||||
// When we start supporting nameIndex, we will get back to this
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace ts {
|
||||
export type FileWatcherCallback = (fileName: string, removed?: boolean) => void;
|
||||
export type DirectoryWatcherCallback = (directoryName: string) => void;
|
||||
export type DirectoryWatcherCallback = (fileName: string) => void;
|
||||
export interface WatchedFile {
|
||||
fileName: string;
|
||||
callback: FileWatcherCallback;
|
||||
|
||||
+48
-5
@@ -343,6 +343,9 @@ namespace ts {
|
||||
JSDocReturnTag,
|
||||
JSDocTypeTag,
|
||||
JSDocTemplateTag,
|
||||
JSDocTypedefTag,
|
||||
JSDocPropertyTag,
|
||||
JSDocTypeLiteral,
|
||||
|
||||
// Synthesized list
|
||||
SyntaxList,
|
||||
@@ -372,6 +375,10 @@ namespace ts {
|
||||
FirstBinaryOperator = LessThanToken,
|
||||
LastBinaryOperator = CaretEqualsToken,
|
||||
FirstNode = QualifiedName,
|
||||
FirstJSDocNode = JSDocTypeExpression,
|
||||
LastJSDocNode = JSDocTypeLiteral,
|
||||
FirstJSDocTagNode = JSDocComment,
|
||||
LastJSDocTagNode = JSDocTypeLiteral
|
||||
}
|
||||
|
||||
export const enum NodeFlags {
|
||||
@@ -416,6 +423,7 @@ namespace ts {
|
||||
|
||||
ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn,
|
||||
EmitHelperFlags = HasClassExtends | HasDecorators | HasParamDecorators | HasAsyncFunctions,
|
||||
ReachabilityAndEmitFlags = ReachabilityCheckFlags | EmitHelperFlags,
|
||||
|
||||
// Parsing context flags
|
||||
ContextFlags = DisallowInContext | YieldContext | DecoratorContext | AwaitContext | JavaScriptFile,
|
||||
@@ -448,7 +456,7 @@ namespace ts {
|
||||
modifiers?: ModifiersArray; // Array of modifiers
|
||||
/* @internal */ id?: number; // Unique id (used to look up NodeLinks)
|
||||
parent?: Node; // Parent node (initialized by binding
|
||||
/* @internal */ jsDocComment?: JSDocComment; // JSDoc for the node, if it has any. Only for .js files.
|
||||
/* @internal */ jsDocComments?: JSDocComment[]; // JSDoc for the node, if it has any. Only for .js files.
|
||||
/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
|
||||
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
|
||||
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
|
||||
@@ -612,6 +620,7 @@ namespace ts {
|
||||
// SyntaxKind.PropertyAssignment
|
||||
// SyntaxKind.ShorthandPropertyAssignment
|
||||
// SyntaxKind.EnumMember
|
||||
// SyntaxKind.JSDocPropertyTag
|
||||
export interface VariableLikeDeclaration extends Declaration {
|
||||
propertyName?: PropertyName;
|
||||
dotDotDotToken?: Node;
|
||||
@@ -1510,6 +1519,25 @@ namespace ts {
|
||||
typeExpression: JSDocTypeExpression;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocTypedefTag)
|
||||
export interface JSDocTypedefTag extends JSDocTag, Declaration {
|
||||
name?: Identifier;
|
||||
typeExpression?: JSDocTypeExpression;
|
||||
jsDocTypeLiteral?: JSDocTypeLiteral;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocPropertyTag)
|
||||
export interface JSDocPropertyTag extends JSDocTag, TypeElement {
|
||||
name: Identifier;
|
||||
typeExpression: JSDocTypeExpression;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocTypeLiteral)
|
||||
export interface JSDocTypeLiteral extends JSDocType {
|
||||
jsDocPropertyTags?: NodeArray<JSDocPropertyTag>;
|
||||
jsDocTypeTag?: JSDocTypeTag;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.JSDocParameterTag)
|
||||
export interface JSDocParameterTag extends JSDocTag {
|
||||
preParameterName?: Identifier;
|
||||
@@ -1537,6 +1565,13 @@ namespace ts {
|
||||
id?: number; // Node id used by flow type cache in checker
|
||||
}
|
||||
|
||||
// FlowStart represents the start of a control flow. For a function expression or arrow
|
||||
// function, the container property references the function (which in turn has a flowNode
|
||||
// property for the containing control flow).
|
||||
export interface FlowStart extends FlowNode {
|
||||
container?: FunctionExpression | ArrowFunction;
|
||||
}
|
||||
|
||||
// FlowLabel represents a junction with multiple possible preceding control flows.
|
||||
export interface FlowLabel extends FlowNode {
|
||||
antecedents: FlowNode[];
|
||||
@@ -2162,7 +2197,7 @@ namespace ts {
|
||||
/* @internal */
|
||||
FreshObjectLiteral = 0x00100000, // Fresh object literal type
|
||||
/* @internal */
|
||||
ContainsUndefinedOrNull = 0x00200000, // Type is or contains undefined or null type
|
||||
ContainsWideningType = 0x00200000, // Type is or contains undefined or null widening type
|
||||
/* @internal */
|
||||
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
|
||||
/* @internal */
|
||||
@@ -2183,11 +2218,14 @@ namespace ts {
|
||||
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
|
||||
UnionOrIntersection = Union | Intersection,
|
||||
StructuredType = ObjectType | Union | Intersection,
|
||||
Narrowable = Any | ObjectType | Union | TypeParameter,
|
||||
|
||||
// 'Narrowable' types are types where narrowing actually narrows.
|
||||
// This *should* be every type other than null, undefined, void, and never
|
||||
Narrowable = Any | StructuredType | TypeParameter | StringLike | NumberLike | Boolean | ESSymbol,
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral,
|
||||
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
|
||||
/* @internal */
|
||||
PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType
|
||||
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType
|
||||
}
|
||||
|
||||
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
|
||||
@@ -2866,4 +2904,9 @@ namespace ts {
|
||||
|
||||
/* @internal */ reattachFileDiagnostics(newFile: SourceFile): void;
|
||||
}
|
||||
|
||||
// SyntaxKind.SyntaxList
|
||||
export interface SyntaxList extends Node {
|
||||
_children: Node[];
|
||||
}
|
||||
}
|
||||
|
||||
+59
-29
@@ -287,16 +287,36 @@ namespace ts {
|
||||
return !nodeIsMissing(node);
|
||||
}
|
||||
|
||||
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
|
||||
export function getTokenPosOfNode(node: Node, sourceFile?: SourceFile, includeJsDocComment?: boolean): number {
|
||||
// With nodes that have no width (i.e. 'Missing' nodes), we actually *don't*
|
||||
// want to skip trivia because this will launch us forward to the next token.
|
||||
if (nodeIsMissing(node)) {
|
||||
return node.pos;
|
||||
}
|
||||
|
||||
if (isJSDocNode(node)) {
|
||||
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
|
||||
}
|
||||
|
||||
if (includeJsDocComment && node.jsDocComments && node.jsDocComments.length > 0) {
|
||||
return getTokenPosOfNode(node.jsDocComments[0]);
|
||||
}
|
||||
|
||||
// For a syntax list, it is possible that one of its children has JSDocComment nodes, while
|
||||
// the syntax list itself considers them as normal trivia. Therefore if we simply skip
|
||||
// trivia for the list, we may have skipped the JSDocComment as well. So we should process its
|
||||
// first child to determine the actual position of its first token.
|
||||
if (node.kind === SyntaxKind.SyntaxList && (<SyntaxList>node)._children.length > 0) {
|
||||
return getTokenPosOfNode((<SyntaxList>node)._children[0], sourceFile, includeJsDocComment);
|
||||
}
|
||||
|
||||
return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, node.pos);
|
||||
}
|
||||
|
||||
export function isJSDocNode(node: Node) {
|
||||
return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode;
|
||||
}
|
||||
|
||||
export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFile): number {
|
||||
if (nodeIsMissing(node) || !node.decorators) {
|
||||
return getTokenPosOfNode(node, sourceFile);
|
||||
@@ -860,15 +880,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function getContainingFunctionOrModule(node: Node): Node {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
if (isFunctionLike(node) || node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.SourceFile) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getContainingClass(node: Node): ClassLikeDeclaration {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
@@ -987,6 +998,20 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function getImmediatelyInvokedFunctionExpression(func: Node): CallExpression {
|
||||
if (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) {
|
||||
let prev = func;
|
||||
let parent = func.parent;
|
||||
while (parent.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
prev = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
if (parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === prev) {
|
||||
return parent as CallExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is a property or element access expression for super.
|
||||
*/
|
||||
@@ -1322,21 +1347,23 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const jsDocComment = getJSDocComment(node, checkParentVariableStatement);
|
||||
if (!jsDocComment) {
|
||||
const jsDocComments = getJSDocComments(node, checkParentVariableStatement);
|
||||
if (!jsDocComments) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.kind === kind) {
|
||||
return tag;
|
||||
for (const jsDocComment of jsDocComments) {
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.kind === kind) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getJSDocComment(node: Node, checkParentVariableStatement: boolean): JSDocComment {
|
||||
if (node.jsDocComment) {
|
||||
return node.jsDocComment;
|
||||
function getJSDocComments(node: Node, checkParentVariableStatement: boolean): JSDocComment[] {
|
||||
if (node.jsDocComments) {
|
||||
return node.jsDocComments;
|
||||
}
|
||||
// Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement.
|
||||
// /**
|
||||
@@ -1352,7 +1379,7 @@ namespace ts {
|
||||
|
||||
const variableStatementNode = isInitializerOfVariableDeclarationInStatement ? node.parent.parent.parent : undefined;
|
||||
if (variableStatementNode) {
|
||||
return variableStatementNode.jsDocComment;
|
||||
return variableStatementNode.jsDocComments;
|
||||
}
|
||||
|
||||
// Also recognize when the node is the RHS of an assignment expression
|
||||
@@ -1363,12 +1390,12 @@ namespace ts {
|
||||
(parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken &&
|
||||
parent.parent.kind === SyntaxKind.ExpressionStatement;
|
||||
if (isSourceOfAssignmentExpressionStatement) {
|
||||
return parent.parent.jsDocComment;
|
||||
return parent.parent.jsDocComments;
|
||||
}
|
||||
|
||||
const isPropertyAssignmentExpression = parent && parent.kind === SyntaxKind.PropertyAssignment;
|
||||
if (isPropertyAssignmentExpression) {
|
||||
return parent.jsDocComment;
|
||||
return parent.jsDocComments;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1393,14 +1420,16 @@ namespace ts {
|
||||
// annotation.
|
||||
const parameterName = (<Identifier>parameter.name).text;
|
||||
|
||||
const jsDocComment = getJSDocComment(parameter.parent, /*checkParentVariableStatement*/ true);
|
||||
if (jsDocComment) {
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.kind === SyntaxKind.JSDocParameterTag) {
|
||||
const parameterTag = <JSDocParameterTag>tag;
|
||||
const name = parameterTag.preParameterName || parameterTag.postParameterName;
|
||||
if (name.text === parameterName) {
|
||||
return parameterTag;
|
||||
const jsDocComments = getJSDocComments(parameter.parent, /*checkParentVariableStatement*/ true);
|
||||
if (jsDocComments) {
|
||||
for (const jsDocComment of jsDocComments) {
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.kind === SyntaxKind.JSDocParameterTag) {
|
||||
const parameterTag = <JSDocParameterTag>tag;
|
||||
const name = parameterTag.preParameterName || parameterTag.postParameterName;
|
||||
if (name.text === parameterName) {
|
||||
return parameterTag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1525,6 +1554,7 @@ namespace ts {
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.TypeParameter:
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -12,7 +12,7 @@ const enum CompilerTestType {
|
||||
|
||||
class CompilerBaselineRunner extends RunnerBase {
|
||||
private basePath = "tests/cases";
|
||||
private testSuiteName: string;
|
||||
private testSuiteName: TestRunnerKind;
|
||||
private errors: boolean;
|
||||
private emit: boolean;
|
||||
private decl: boolean;
|
||||
@@ -41,6 +41,14 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
this.basePath += "/" + this.testSuiteName;
|
||||
}
|
||||
|
||||
public kind() {
|
||||
return this.testSuiteName;
|
||||
}
|
||||
|
||||
public enumerateTestFiles() {
|
||||
return this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true });
|
||||
}
|
||||
|
||||
private makeUnitName(name: string, root: string) {
|
||||
return ts.isRootedDiskPath(name) ? name : ts.combinePaths(root, name);
|
||||
};
|
||||
@@ -146,7 +154,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
|
||||
it (`Correct module resolution tracing for ${fileName}`, () => {
|
||||
if (options.traceResolution) {
|
||||
Harness.Baseline.runBaseline("Correct sourcemap content for " + fileName, justName.replace(/\.tsx?$/, ".trace.json"), () => {
|
||||
Harness.Baseline.runBaseline("Correct module resolution tracing for " + fileName, justName.replace(/\.tsx?$/, ".trace.json"), () => {
|
||||
return JSON.stringify(result.traceResults || [], undefined, 4);
|
||||
});
|
||||
}
|
||||
@@ -391,7 +399,7 @@ class CompilerBaselineRunner extends RunnerBase {
|
||||
|
||||
// this will set up a series of describe/it blocks to run between the setup and cleanup phases
|
||||
if (this.tests.length === 0) {
|
||||
const testFiles = this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true });
|
||||
const testFiles = this.enumerateTestFiles();
|
||||
testFiles.forEach(fn => {
|
||||
fn = fn.replace(/\\/g, "/");
|
||||
this.checkTestCodeOutput(fn);
|
||||
|
||||
+45
-92
@@ -746,7 +746,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
const missingItem = { fileName: fileName, start: start, end: end, isWriteAccess: isWriteAccess };
|
||||
this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(references, undefined, 2)})`);
|
||||
this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(references)})`);
|
||||
}
|
||||
|
||||
public verifyReferencesCountIs(count: number, localFilesOnly = true) {
|
||||
@@ -800,7 +800,7 @@ namespace FourSlash {
|
||||
|
||||
private testDiagnostics(expected: string, diagnostics: ts.Diagnostic[]) {
|
||||
const realized = ts.realizeDiagnostics(diagnostics, "\r\n");
|
||||
const actual = JSON.stringify(realized, undefined, 2);
|
||||
const actual = stringify(realized);
|
||||
assert.equal(actual, expected);
|
||||
}
|
||||
|
||||
@@ -875,7 +875,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
if (ranges.length !== references.length) {
|
||||
this.raiseError("Rename location count does not match result.\n\nExpected: " + JSON.stringify(ranges, undefined, 2) + "\n\nActual:" + JSON.stringify(references, undefined, 2));
|
||||
this.raiseError("Rename location count does not match result.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + stringify(references));
|
||||
}
|
||||
|
||||
ranges = ranges.sort((r1, r2) => r1.start - r2.start);
|
||||
@@ -888,7 +888,7 @@ namespace FourSlash {
|
||||
if (reference.textSpan.start !== range.start ||
|
||||
ts.textSpanEnd(reference.textSpan) !== range.end) {
|
||||
|
||||
this.raiseError("Rename location results do not match.\n\nExpected: " + JSON.stringify(ranges, undefined, 2) + "\n\nActual:" + JSON.stringify(references, undefined, 2));
|
||||
this.raiseError("Rename location results do not match.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + JSON.stringify(references));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -972,7 +972,7 @@ namespace FourSlash {
|
||||
}
|
||||
else {
|
||||
if (actual) {
|
||||
this.raiseError(`Expected no signature help, but got "${JSON.stringify(actual, undefined, 2)}"`);
|
||||
this.raiseError(`Expected no signature help, but got "${stringify(actual)}"`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1176,7 +1176,7 @@ namespace FourSlash {
|
||||
|
||||
public printCurrentParameterHelp() {
|
||||
const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
|
||||
Harness.IO.log(JSON.stringify(help, undefined, 2));
|
||||
Harness.IO.log(stringify(help));
|
||||
}
|
||||
|
||||
public printCurrentQuickInfo() {
|
||||
@@ -1218,7 +1218,7 @@ namespace FourSlash {
|
||||
|
||||
public printCurrentSignatureHelp() {
|
||||
const sigHelp = this.getActiveSignatureHelpItem();
|
||||
Harness.IO.log(JSON.stringify(sigHelp, undefined, 2));
|
||||
Harness.IO.log(stringify(sigHelp));
|
||||
}
|
||||
|
||||
public printMemberListMembers() {
|
||||
@@ -1248,7 +1248,7 @@ namespace FourSlash {
|
||||
public printReferences() {
|
||||
const references = this.getReferencesAtCaret();
|
||||
ts.forEach(references, entry => {
|
||||
Harness.IO.log(JSON.stringify(entry, undefined, 2));
|
||||
Harness.IO.log(stringify(entry));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1486,6 +1486,12 @@ namespace FourSlash {
|
||||
this.fixCaretPosition();
|
||||
}
|
||||
|
||||
public formatOnType(pos: number, key: string) {
|
||||
const edits = this.languageService.getFormattingEditsAfterKeystroke(this.activeFile.fileName, pos, key, this.formatCodeOptions);
|
||||
this.currentCaretPosition += this.applyEdits(this.activeFile.fileName, edits, /*isFormattingEdit*/ true);
|
||||
this.fixCaretPosition();
|
||||
}
|
||||
|
||||
private updateMarkersForEdit(fileName: string, minChar: number, limChar: number, text: string) {
|
||||
for (let i = 0; i < this.testData.markers.length; i++) {
|
||||
const marker = this.testData.markers[i];
|
||||
@@ -1739,8 +1745,8 @@ namespace FourSlash {
|
||||
|
||||
function jsonMismatchString() {
|
||||
return Harness.IO.newLine() +
|
||||
"expected: '" + Harness.IO.newLine() + JSON.stringify(expected, undefined, 2) + "'" + Harness.IO.newLine() +
|
||||
"actual: '" + Harness.IO.newLine() + JSON.stringify(actual, undefined, 2) + "'";
|
||||
"expected: '" + Harness.IO.newLine() + stringify(expected) + "'" + Harness.IO.newLine() +
|
||||
"actual: '" + Harness.IO.newLine() + stringify(actual) + "'";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1955,73 +1961,27 @@ namespace FourSlash {
|
||||
// if there was an explicit match kind specified, then it should be validated.
|
||||
if (matchKind !== undefined) {
|
||||
const missingItem = { name: name, kind: kind, searchValue: searchValue, matchKind: matchKind, fileName: fileName, parentName: parentName };
|
||||
this.raiseError(`verifyNavigationItemsListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(items, undefined, 2)})`);
|
||||
this.raiseError(`verifyNavigationItemsListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(items)})`);
|
||||
}
|
||||
}
|
||||
|
||||
public verifyNavigationBarCount(expected: number) {
|
||||
public verifyNavigationBar(json: any) {
|
||||
const items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
|
||||
const actual = this.getNavigationBarItemsCount(items);
|
||||
|
||||
if (expected !== actual) {
|
||||
this.raiseError(`verifyNavigationBarCount failed - found: ${actual} navigation items, expected: ${expected}.`);
|
||||
}
|
||||
}
|
||||
|
||||
private getNavigationBarItemsCount(items: ts.NavigationBarItem[]) {
|
||||
let result = 0;
|
||||
if (items) {
|
||||
for (let i = 0, n = items.length; i < n; i++) {
|
||||
result++;
|
||||
result += this.getNavigationBarItemsCount(items[i].childItems);
|
||||
}
|
||||
if (JSON.stringify(items, replacer) !== JSON.stringify(json)) {
|
||||
this.raiseError(`verifyNavigationBar failed - expected: ${stringify(json)}, got: ${stringify(items, replacer)}`);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public verifyNavigationBarContains(name: string, kind: string, fileName?: string, parentName?: string, isAdditionalSpan?: boolean, markerPosition?: number) {
|
||||
fileName = fileName || this.activeFile.fileName;
|
||||
const items = this.languageService.getNavigationBarItems(fileName);
|
||||
|
||||
if (!items || items.length === 0) {
|
||||
this.raiseError("verifyNavigationBarContains failed - found 0 navigation items, expected at least one.");
|
||||
}
|
||||
|
||||
if (this.navigationBarItemsContains(items, name, kind, parentName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const missingItem = { name, kind, parentName };
|
||||
this.raiseError(`verifyNavigationBarContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(items, undefined, 2)})`);
|
||||
}
|
||||
|
||||
private navigationBarItemsContains(items: ts.NavigationBarItem[], name: string, kind: string, parentName?: string) {
|
||||
function recur(items: ts.NavigationBarItem[], curParentName: string) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
if (item && item.text === name && item.kind === kind && (!parentName || curParentName === parentName)) {
|
||||
return true;
|
||||
}
|
||||
if (recur(item.childItems, item.text)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return recur(items, "");
|
||||
}
|
||||
|
||||
public verifyNavigationBarChildItem(parent: string, name: string, kind: string) {
|
||||
const items = this.languageService.getNavigationBarItems(this.activeFile.fileName);
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
if (item.text === parent) {
|
||||
if (this.navigationBarItemsContains(item.childItems, name, kind))
|
||||
return;
|
||||
const missingItem = { name, kind };
|
||||
this.raiseError(`verifyNavigationBarChildItem failed - could not find the item: ${JSON.stringify(missingItem)} in the children list: (${JSON.stringify(item.childItems, undefined, 2)})`);
|
||||
// Make the data easier to read.
|
||||
function replacer(key: string, value: any) {
|
||||
switch (key) {
|
||||
case "spans":
|
||||
// We won't ever check this.
|
||||
return undefined;
|
||||
case "childItems":
|
||||
return value.length === 0 ? undefined : value;
|
||||
default:
|
||||
// Omit falsy values, those are presumed to be the default.
|
||||
return value || undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2071,7 +2031,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
const missingItem = { fileName: fileName, start: start, end: end, isWriteAccess: isWriteAccess };
|
||||
this.raiseError(`verifyOccurrencesAtPositionListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(occurrences, undefined, 2)})`);
|
||||
this.raiseError(`verifyOccurrencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(occurrences)})`);
|
||||
}
|
||||
|
||||
public verifyOccurrencesAtPositionListCount(expectedCount: number) {
|
||||
@@ -2110,7 +2070,7 @@ namespace FourSlash {
|
||||
}
|
||||
|
||||
const missingItem = { fileName: fileName, start: start, end: end, kind: kind };
|
||||
this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(documentHighlights, undefined, 2)})`);
|
||||
this.raiseError(`verifyDocumentHighlightsAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(documentHighlights)})`);
|
||||
}
|
||||
|
||||
public verifyDocumentHighlightsAtPositionListCount(expectedCount: number, fileNamesToSearch: string[]) {
|
||||
@@ -2176,9 +2136,9 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
const itemsString = items.map((item) => JSON.stringify({ name: item.name, kind: item.kind }, undefined, 2)).join(",\n");
|
||||
const itemsString = items.map(item => stringify({ name: item.name, kind: item.kind })).join(",\n");
|
||||
|
||||
this.raiseError(`Expected "${JSON.stringify({ name, text, documentation, kind }, undefined, 2)}" to be in list [${itemsString}]`);
|
||||
this.raiseError(`Expected "${stringify({ name, text, documentation, kind })}" to be in list [${itemsString}]`);
|
||||
}
|
||||
|
||||
private findFile(indexOrName: any) {
|
||||
@@ -2741,6 +2701,10 @@ ${code}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function stringify(data: any, replacer?: (key: string, value: any) => any): string {
|
||||
return JSON.stringify(data, replacer, 2);
|
||||
}
|
||||
}
|
||||
|
||||
namespace FourSlashInterface {
|
||||
@@ -3042,23 +3006,8 @@ namespace FourSlashInterface {
|
||||
this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true);
|
||||
}
|
||||
|
||||
public navigationBarCount(count: number) {
|
||||
this.state.verifyNavigationBarCount(count);
|
||||
}
|
||||
|
||||
// TODO: figure out what to do with the unused arguments.
|
||||
public navigationBarContains(
|
||||
name: string,
|
||||
kind: string,
|
||||
fileName?: string,
|
||||
parentName?: string,
|
||||
isAdditionalSpan?: boolean,
|
||||
markerPosition?: number) {
|
||||
this.state.verifyNavigationBarContains(name, kind, fileName, parentName, isAdditionalSpan, markerPosition);
|
||||
}
|
||||
|
||||
public navigationBarChildItem(parent: string, name: string, kind: string) {
|
||||
this.state.verifyNavigationBarChildItem(parent, name, kind);
|
||||
public navigationBar(json: any) {
|
||||
this.state.verifyNavigationBar(json);
|
||||
}
|
||||
|
||||
public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) {
|
||||
@@ -3284,6 +3233,10 @@ namespace FourSlashInterface {
|
||||
this.state.formatSelection(this.state.getMarkerByName(startMarker).position, this.state.getMarkerByName(endMarker).position);
|
||||
}
|
||||
|
||||
public onType(posMarker: string, key: string) {
|
||||
this.state.formatOnType(this.state.getMarkerByName(posMarker).position, key);
|
||||
}
|
||||
|
||||
public setOption(name: string, value: number): void;
|
||||
public setOption(name: string, value: string): void;
|
||||
public setOption(name: string, value: boolean): void;
|
||||
|
||||
@@ -11,7 +11,7 @@ const enum FourSlashTestType {
|
||||
|
||||
class FourSlashRunner extends RunnerBase {
|
||||
protected basePath: string;
|
||||
protected testSuiteName: string;
|
||||
protected testSuiteName: TestRunnerKind;
|
||||
|
||||
constructor(private testType: FourSlashTestType) {
|
||||
super();
|
||||
@@ -35,9 +35,17 @@ class FourSlashRunner extends RunnerBase {
|
||||
}
|
||||
}
|
||||
|
||||
public enumerateTestFiles() {
|
||||
return this.enumerateFiles(this.basePath, /\.ts/i, { recursive: false });
|
||||
}
|
||||
|
||||
public kind() {
|
||||
return this.testSuiteName;
|
||||
}
|
||||
|
||||
public initializeTests() {
|
||||
if (this.tests.length === 0) {
|
||||
this.tests = this.enumerateFiles(this.basePath, /\.ts/i, { recursive: false });
|
||||
this.tests = this.enumerateTestFiles();
|
||||
}
|
||||
|
||||
describe(this.testSuiteName + " tests", () => {
|
||||
|
||||
+20
-7
@@ -1,7 +1,7 @@
|
||||
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -221,6 +221,19 @@ namespace Utils {
|
||||
return k;
|
||||
}
|
||||
|
||||
// For some markers in SyntaxKind, we should print its original syntax name instead of
|
||||
// the marker name in tests.
|
||||
if (k === (<any>ts).SyntaxKind.FirstJSDocNode ||
|
||||
k === (<any>ts).SyntaxKind.LastJSDocNode ||
|
||||
k === (<any>ts).SyntaxKind.FirstJSDocTagNode ||
|
||||
k === (<any>ts).SyntaxKind.LastJSDocTagNode) {
|
||||
for (const kindName in (<any>ts).SyntaxKind) {
|
||||
if ((<any>ts).SyntaxKind[kindName] === k) {
|
||||
return kindName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (<any>ts).SyntaxKind[k];
|
||||
}
|
||||
|
||||
@@ -350,7 +363,7 @@ namespace Utils {
|
||||
assert.equal(node1.end, node2.end, "node1.end !== node2.end");
|
||||
assert.equal(node1.kind, node2.kind, "node1.kind !== node2.kind");
|
||||
|
||||
// call this on both nodes to ensure all propagated flags have been set (and thus can be
|
||||
// call this on both nodes to ensure all propagated flags have been set (and thus can be
|
||||
// compared).
|
||||
assert.equal(ts.containsParseError(node1), ts.containsParseError(node2));
|
||||
assert.equal(node1.flags, node2.flags, "node1.flags !== node2.flags");
|
||||
@@ -751,7 +764,7 @@ namespace Harness {
|
||||
(emittedFile: string, emittedLine: number, emittedColumn: number, sourceFile: string, sourceLine: number, sourceColumn: number, sourceName: string): void;
|
||||
}
|
||||
|
||||
// Settings
|
||||
// Settings
|
||||
export let userSpecifiedRoot = "";
|
||||
export let lightMode = false;
|
||||
|
||||
@@ -790,7 +803,7 @@ namespace Harness {
|
||||
fileName: string,
|
||||
sourceText: string,
|
||||
languageVersion: ts.ScriptTarget) {
|
||||
// We'll only assert invariants outside of light mode.
|
||||
// We'll only assert invariants outside of light mode.
|
||||
const shouldAssertInvariants = !Harness.lightMode;
|
||||
|
||||
// Only set the parent nodes if we're asserting invariants. We don't need them otherwise.
|
||||
@@ -935,7 +948,7 @@ namespace Harness {
|
||||
libFiles?: string;
|
||||
}
|
||||
|
||||
// Additional options not already in ts.optionDeclarations
|
||||
// Additional options not already in ts.optionDeclarations
|
||||
const harnessOptionDeclarations: ts.CommandLineOption[] = [
|
||||
{ name: "allowNonTsExtensions", type: "boolean" },
|
||||
{ name: "useCaseSensitiveFileNames", type: "boolean" },
|
||||
@@ -1187,7 +1200,7 @@ namespace Harness {
|
||||
errLines.forEach(e => outputLines.push(e));
|
||||
|
||||
// do not count errors from lib.d.ts here, they are computed separately as numLibraryDiagnostics
|
||||
// if lib.d.ts is explicitly included in input files and there are some errors in it (i.e. because of duplicate identifiers)
|
||||
// if lib.d.ts is explicitly included in input files and there are some errors in it (i.e. because of duplicate identifiers)
|
||||
// then they will be added twice thus triggering 'total errors' assertion with condition
|
||||
// 'totalErrorsReportedInNonLibraryFiles + numLibraryDiagnostics + numTest262HarnessDiagnostics, diagnostics.length
|
||||
|
||||
@@ -1497,7 +1510,7 @@ namespace Harness {
|
||||
};
|
||||
testUnitData.push(newTestFile2);
|
||||
|
||||
// unit tests always list files explicitly
|
||||
// unit tests always list files explicitly
|
||||
const parseConfigHost: ts.ParseConfigHost = {
|
||||
readDirectory: (name) => []
|
||||
};
|
||||
|
||||
@@ -226,13 +226,7 @@ namespace Playback {
|
||||
(path, extension, exclude) => findResultByPath(wrapper,
|
||||
replayLog.directoriesRead.filter(
|
||||
d => {
|
||||
if (d.extension === extension) {
|
||||
if (d.exclude) {
|
||||
return ts.arrayIsEqualTo(d.exclude, exclude);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return d.extension === extension;
|
||||
}
|
||||
), path));
|
||||
|
||||
|
||||
@@ -36,11 +36,19 @@ interface BatchCompileProjectTestCaseResult extends CompileProjectFilesResult {
|
||||
}
|
||||
|
||||
class ProjectRunner extends RunnerBase {
|
||||
|
||||
public enumerateTestFiles() {
|
||||
return this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true });
|
||||
}
|
||||
|
||||
public kind(): TestRunnerKind {
|
||||
return "project";
|
||||
}
|
||||
|
||||
public initializeTests() {
|
||||
if (this.tests.length === 0) {
|
||||
const testFiles = this.enumerateFiles("tests/cases/project", /\.json$/, { recursive: true });
|
||||
const testFiles = this.enumerateTestFiles();
|
||||
testFiles.forEach(fn => {
|
||||
fn = fn.replace(/\\/g, "/");
|
||||
this.runProjectTestCase(fn);
|
||||
});
|
||||
}
|
||||
@@ -236,7 +244,7 @@ class ProjectRunner extends RunnerBase {
|
||||
mapRoot: testCase.resolveMapRoot && testCase.mapRoot ? Harness.IO.resolvePath(testCase.mapRoot) : testCase.mapRoot,
|
||||
sourceRoot: testCase.resolveSourceRoot && testCase.sourceRoot ? Harness.IO.resolvePath(testCase.sourceRoot) : testCase.sourceRoot,
|
||||
module: moduleKind,
|
||||
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
|
||||
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
|
||||
};
|
||||
// Set the values specified using json
|
||||
const optionNameMap: ts.Map<ts.CommandLineOption> = {};
|
||||
|
||||
+118
-9
@@ -31,18 +31,90 @@ function runTests(runners: RunnerBase[]) {
|
||||
}
|
||||
}
|
||||
|
||||
// users can define tests to run in mytest.config that will override cmd line args, otherwise use cmd line args (test.config), otherwise no options
|
||||
let mytestconfig = "mytest.config";
|
||||
let testconfig = "test.config";
|
||||
let testConfigFile =
|
||||
Harness.IO.fileExists(mytestconfig) ? Harness.IO.readFile(mytestconfig) :
|
||||
(Harness.IO.fileExists(testconfig) ? Harness.IO.readFile(testconfig) : "");
|
||||
function tryGetConfig(args: string[]) {
|
||||
const prefix = "--config=";
|
||||
const configPath = ts.forEach(args, arg => arg.lastIndexOf(prefix, 0) === 0 && arg.substr(prefix.length));
|
||||
// strip leading and trailing quotes from the path (necessary on Windows since shell does not do it automatically)
|
||||
return configPath && configPath.replace(/(^[\"'])|([\"']$)/g, "");
|
||||
}
|
||||
|
||||
if (testConfigFile !== "") {
|
||||
const testConfig = JSON.parse(testConfigFile);
|
||||
function createRunner(kind: TestRunnerKind): RunnerBase {
|
||||
switch (kind) {
|
||||
case "conformance":
|
||||
return new CompilerBaselineRunner(CompilerTestType.Conformance);
|
||||
case "compiler":
|
||||
return new CompilerBaselineRunner(CompilerTestType.Regressions);
|
||||
case "fourslash":
|
||||
return new FourSlashRunner(FourSlashTestType.Native);
|
||||
case "fourslash-shims":
|
||||
return new FourSlashRunner(FourSlashTestType.Shims);
|
||||
case "fourslash-shims-pp":
|
||||
return new FourSlashRunner(FourSlashTestType.ShimsWithPreprocess);
|
||||
case "fourslash-server":
|
||||
return new FourSlashRunner(FourSlashTestType.Server);
|
||||
case "project":
|
||||
return new ProjectRunner();
|
||||
case "rwc":
|
||||
return new RWCRunner();
|
||||
case "test262":
|
||||
return new Test262BaselineRunner();
|
||||
}
|
||||
}
|
||||
|
||||
// users can define tests to run in mytest.config that will override cmd line args, otherwise use cmd line args (test.config), otherwise no options
|
||||
|
||||
const mytestconfigFileName = "mytest.config";
|
||||
const testconfigFileName = "test.config";
|
||||
|
||||
const customConfig = tryGetConfig(Harness.IO.args());
|
||||
let testConfigContent =
|
||||
customConfig && Harness.IO.fileExists(customConfig)
|
||||
? Harness.IO.readFile(customConfig)
|
||||
: Harness.IO.fileExists(mytestconfigFileName)
|
||||
? Harness.IO.readFile(mytestconfigFileName)
|
||||
: Harness.IO.fileExists(testconfigFileName) ? Harness.IO.readFile(testconfigFileName) : "";
|
||||
|
||||
let taskConfigsFolder: string;
|
||||
let workerCount: number;
|
||||
let runUnitTests = true;
|
||||
|
||||
interface TestConfig {
|
||||
light?: boolean;
|
||||
taskConfigsFolder?: string;
|
||||
workerCount?: number;
|
||||
tasks?: TaskSet[];
|
||||
test?: string[];
|
||||
runUnitTests?: boolean;
|
||||
}
|
||||
|
||||
interface TaskSet {
|
||||
runner: TestRunnerKind;
|
||||
files: string[];
|
||||
}
|
||||
|
||||
if (testConfigContent !== "") {
|
||||
const testConfig = <TestConfig>JSON.parse(testConfigContent);
|
||||
if (testConfig.light) {
|
||||
Harness.lightMode = true;
|
||||
}
|
||||
if (testConfig.taskConfigsFolder) {
|
||||
taskConfigsFolder = testConfig.taskConfigsFolder;
|
||||
}
|
||||
if (testConfig.runUnitTests !== undefined) {
|
||||
runUnitTests = testConfig.runUnitTests;
|
||||
}
|
||||
if (testConfig.workerCount) {
|
||||
workerCount = testConfig.workerCount;
|
||||
}
|
||||
if (testConfig.tasks) {
|
||||
for (const taskSet of testConfig.tasks) {
|
||||
const runner = createRunner(taskSet.runner);
|
||||
for (const file of taskSet.files) {
|
||||
runner.addTest(file);
|
||||
}
|
||||
runners.push(runner);
|
||||
}
|
||||
}
|
||||
|
||||
if (testConfig.test && testConfig.test.length > 0) {
|
||||
for (const option of testConfig.test) {
|
||||
@@ -106,4 +178,41 @@ if (runners.length === 0) {
|
||||
// runners.push(new GeneratedFourslashRunner());
|
||||
}
|
||||
|
||||
runTests(runners);
|
||||
if (taskConfigsFolder) {
|
||||
// this instance of mocha should only partition work but not run actual tests
|
||||
runUnitTests = false;
|
||||
const workerConfigs: TestConfig[] = [];
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
// pass light mode settings to workers
|
||||
workerConfigs.push({ light: Harness.lightMode, tasks: [] });
|
||||
}
|
||||
|
||||
for (const runner of runners) {
|
||||
const files = runner.enumerateTestFiles();
|
||||
const chunkSize = Math.floor(files.length / workerCount) + 1; // add extra 1 to prevent missing tests due to rounding
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
const startPos = i * chunkSize;
|
||||
const len = Math.min(chunkSize, files.length - startPos);
|
||||
if (len !== 0) {
|
||||
workerConfigs[i].tasks.push({
|
||||
runner: runner.kind(),
|
||||
files: files.slice(startPos, startPos + len)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < workerCount; i++) {
|
||||
const config = workerConfigs[i];
|
||||
// use last worker to run unit tests
|
||||
config.runUnitTests = i === workerCount - 1;
|
||||
Harness.IO.writeFile(ts.combinePaths(taskConfigsFolder, `task-config${i}.json`), JSON.stringify(workerConfigs[i]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
runTests(runners);
|
||||
}
|
||||
if (!runUnitTests) {
|
||||
// patch `describe` to skip unit tests
|
||||
describe = <any>describe.skip;
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
/// <reference path="harness.ts" />
|
||||
|
||||
|
||||
type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project" | "rwc" | "test262";
|
||||
type CompilerTestKind = "conformance" | "compiler";
|
||||
type FourslashTestKind = "fourslash" | "fourslash-shims" | "fourslash-shims-pp" | "fourslash-server";
|
||||
|
||||
abstract class RunnerBase {
|
||||
constructor() { }
|
||||
|
||||
@@ -12,10 +17,14 @@ abstract class RunnerBase {
|
||||
}
|
||||
|
||||
public enumerateFiles(folder: string, regex?: RegExp, options?: { recursive: boolean }): string[] {
|
||||
return Harness.IO.listFiles(Harness.userSpecifiedRoot + folder, regex, { recursive: (options ? options.recursive : false) });
|
||||
return ts.map(Harness.IO.listFiles(Harness.userSpecifiedRoot + folder, regex, { recursive: (options ? options.recursive : false) }), ts.normalizeSlashes);
|
||||
}
|
||||
|
||||
/** Setup the runner's tests so that they are ready to be executed by the harness
|
||||
abstract kind(): TestRunnerKind;
|
||||
|
||||
abstract enumerateTestFiles(): string[];
|
||||
|
||||
/** Setup the runner's tests so that they are ready to be executed by the harness
|
||||
* The first test should be a describe/it block that sets up the harness's compiler instance appropriately
|
||||
*/
|
||||
public abstract initializeTests(): void;
|
||||
|
||||
@@ -224,12 +224,20 @@ namespace RWC {
|
||||
class RWCRunner extends RunnerBase {
|
||||
private static sourcePath = "internal/cases/rwc/";
|
||||
|
||||
public enumerateTestFiles() {
|
||||
return Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/);
|
||||
}
|
||||
|
||||
public kind(): TestRunnerKind {
|
||||
return "rwc";
|
||||
}
|
||||
|
||||
/** Setup the runner's tests so that they are ready to be executed by the harness
|
||||
* The first test should be a describe/it block that sets up the harness's compiler instance appropriately
|
||||
*/
|
||||
public initializeTests(): void {
|
||||
// Read in and evaluate the test list
|
||||
const testList = Harness.IO.listFiles(RWCRunner.sourcePath, /.+\.json$/);
|
||||
const testList = this.enumerateTestFiles();
|
||||
for (let i = 0; i < testList.length; i++) {
|
||||
this.runTest(testList[i]);
|
||||
}
|
||||
|
||||
@@ -98,12 +98,20 @@ class Test262BaselineRunner extends RunnerBase {
|
||||
});
|
||||
}
|
||||
|
||||
public kind(): TestRunnerKind {
|
||||
return "test262";
|
||||
}
|
||||
|
||||
public enumerateTestFiles() {
|
||||
return ts.map(this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true }), ts.normalizePath);
|
||||
}
|
||||
|
||||
public initializeTests() {
|
||||
// this will set up a series of describe/it blocks to run between the setup and cleanup phases
|
||||
if (this.tests.length === 0) {
|
||||
const testFiles = this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true });
|
||||
const testFiles = this.enumerateTestFiles();
|
||||
testFiles.forEach(fn => {
|
||||
this.runTest(ts.normalizePath(fn));
|
||||
this.runTest(fn);
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
||||
Vendored
+13
-1
@@ -136,12 +136,24 @@ interface ObjectConstructor {
|
||||
*/
|
||||
getOwnPropertyNames(o: any): string[];
|
||||
|
||||
/**
|
||||
* Creates an object that has null prototype.
|
||||
* @param o Object to use as a prototype. May be null
|
||||
*/
|
||||
create(o: null): any;
|
||||
|
||||
/**
|
||||
* Creates an object that has the specified prototype, and that optionally contains specified properties.
|
||||
* @param o Object to use as a prototype. May be null
|
||||
*/
|
||||
create<T>(o: T): T;
|
||||
|
||||
/**
|
||||
* Creates an object that has the specified prototype, and that optionally contains specified properties.
|
||||
* @param o Object to use as a prototype. May be null
|
||||
* @param properties JavaScript object that contains one or more property descriptors.
|
||||
*/
|
||||
create(o: any, properties?: PropertyDescriptorMap): any;
|
||||
create(o: any, properties: PropertyDescriptorMap): any;
|
||||
|
||||
/**
|
||||
* Adds a property to an object, or modifies attributes of an existing property.
|
||||
|
||||
@@ -459,7 +459,7 @@ namespace ts.server {
|
||||
kindModifiers: item.kindModifiers || "",
|
||||
spans: item.spans.map(span => createTextSpanFromBounds(this.lineOffsetToPosition(fileName, span.start), this.lineOffsetToPosition(fileName, span.end))),
|
||||
childItems: this.decodeNavigationBarItems(item.childItems, fileName),
|
||||
indent: 0,
|
||||
indent: item.indent,
|
||||
bolded: false,
|
||||
grayed: false
|
||||
}));
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
removeRoot(info: ScriptInfo) {
|
||||
if (!this.filenameToScript.contains(info.path)) {
|
||||
if (this.filenameToScript.contains(info.path)) {
|
||||
this.filenameToScript.remove(info.path);
|
||||
this.roots = copyListRemovingItem(info, this.roots);
|
||||
this.resolvedModuleNames.remove(info.path);
|
||||
@@ -1138,7 +1138,7 @@ namespace ts.server {
|
||||
else {
|
||||
this.log("No config files found.");
|
||||
}
|
||||
return {};
|
||||
return configFileName ? { configFileName } : {};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+5
@@ -1242,6 +1242,11 @@ declare namespace ts.server.protocol {
|
||||
* Optional children.
|
||||
*/
|
||||
childItems?: NavigationBarItem[];
|
||||
|
||||
/**
|
||||
* Number of levels deep this item should appear.
|
||||
*/
|
||||
indent: number;
|
||||
}
|
||||
|
||||
export interface NavBarResponse extends Response {
|
||||
|
||||
@@ -872,7 +872,8 @@ namespace ts.server {
|
||||
start: compilerService.host.positionToLineOffset(fileName, span.start),
|
||||
end: compilerService.host.positionToLineOffset(fileName, ts.textSpanEnd(span))
|
||||
})),
|
||||
childItems: this.decorateNavigationBarItem(project, fileName, item.childItems)
|
||||
childItems: this.decorateNavigationBarItem(project, fileName, item.childItems),
|
||||
indent: item.indent
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
|
||||
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
|
||||
// See LICENSE.txt in the project root for complete license information.
|
||||
|
||||
/// <reference path='services.ts' />
|
||||
@@ -19,8 +19,8 @@ namespace ts.BreakpointResolver {
|
||||
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) {
|
||||
// Get previous token if the token is returned starts on new line
|
||||
// eg: let x =10; |--- cursor is here
|
||||
// let y = 10;
|
||||
// token at position will return let keyword on second line as the token but we would like to use
|
||||
// let y = 10;
|
||||
// token at position will return let keyword on second line as the token but we would like to use
|
||||
// token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line
|
||||
tokenAtLocation = findPrecedingToken(tokenAtLocation.pos, sourceFile);
|
||||
|
||||
@@ -261,7 +261,7 @@ namespace ts.BreakpointResolver {
|
||||
}
|
||||
|
||||
// Set breakpoint on identifier element of destructuring pattern
|
||||
// a or ...c or d: x from
|
||||
// a or ...c or d: x from
|
||||
// [a, b, ...c] or { a, b } or { d: x } from destructuring pattern
|
||||
if ((node.kind === SyntaxKind.Identifier ||
|
||||
node.kind == SyntaxKind.SpreadElementExpression ||
|
||||
@@ -275,7 +275,7 @@ namespace ts.BreakpointResolver {
|
||||
const binaryExpression = <BinaryExpression>node;
|
||||
// Set breakpoint in destructuring pattern if its destructuring assignment
|
||||
// [a, b, c] or {a, b, c} of
|
||||
// [a, b, c] = expression or
|
||||
// [a, b, c] = expression or
|
||||
// {a, b, c} = expression
|
||||
if (isArrayLiteralOrObjectLiteralDestructuringPattern(binaryExpression.left)) {
|
||||
return spanInArrayLiteralOrObjectLiteralDestructuringPattern(
|
||||
@@ -285,8 +285,8 @@ namespace ts.BreakpointResolver {
|
||||
if (binaryExpression.operatorToken.kind === SyntaxKind.EqualsToken &&
|
||||
isArrayLiteralOrObjectLiteralDestructuringPattern(binaryExpression.parent)) {
|
||||
// Set breakpoint on assignment expression element of destructuring pattern
|
||||
// a = expression of
|
||||
// [a = expression, b, c] = someExpression or
|
||||
// a = expression of
|
||||
// [a = expression, b, c] = someExpression or
|
||||
// { a = expression, b, c } = someExpression
|
||||
return textSpan(node);
|
||||
}
|
||||
@@ -403,7 +403,7 @@ namespace ts.BreakpointResolver {
|
||||
const declarations = variableDeclaration.parent.declarations;
|
||||
if (declarations && declarations[0] !== variableDeclaration) {
|
||||
// If we cannot set breakpoint on this declaration, set it on previous one
|
||||
// Because the variable declaration may be binding pattern and
|
||||
// Because the variable declaration may be binding pattern and
|
||||
// we would like to set breakpoint in last binding element if that's the case,
|
||||
// use preceding token instead
|
||||
return spanInNode(findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent));
|
||||
@@ -549,7 +549,7 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(firstBindingElement);
|
||||
}
|
||||
|
||||
// Could be ArrayLiteral from destructuring assignment or
|
||||
// Could be ArrayLiteral from destructuring assignment or
|
||||
// just nested element in another destructuring assignment
|
||||
// set breakpoint on assignment when parent is destructuring assignment
|
||||
// Otherwise set breakpoint for this element
|
||||
|
||||
@@ -81,6 +81,12 @@ namespace ts.formatting {
|
||||
while (isWhiteSpace(sourceFile.text.charCodeAt(endOfFormatSpan)) && !isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) {
|
||||
endOfFormatSpan--;
|
||||
}
|
||||
// if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to
|
||||
// touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the
|
||||
// previous character before the end of format span is line break character as well.
|
||||
if (isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) {
|
||||
endOfFormatSpan--;
|
||||
}
|
||||
const span = {
|
||||
// get start position for the previous line
|
||||
pos: getStartPositionOfLine(line - 1, sourceFile),
|
||||
|
||||
@@ -268,9 +268,9 @@ namespace ts.formatting {
|
||||
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
|
||||
}
|
||||
|
||||
// when containing node in the tree is token
|
||||
// when containing node in the tree is token
|
||||
// but its kind differs from the kind that was returned by the scanner,
|
||||
// then kind needs to be fixed. This might happen in cases
|
||||
// then kind needs to be fixed. This might happen in cases
|
||||
// when parser interprets token differently, i.e keyword treated as identifier
|
||||
function fixTokenKind(tokenInfo: TokenInfo, container: Node): TokenInfo {
|
||||
if (isToken(container) && tokenInfo.token.kind !== container.kind) {
|
||||
|
||||
@@ -554,17 +554,17 @@ namespace ts.formatting {
|
||||
static IsSameLineTokenOrBeforeMultilineBlockContext(context: FormattingContext): boolean {
|
||||
//// This check is mainly used inside SpaceBeforeOpenBraceInControl and SpaceBeforeOpenBraceInFunction.
|
||||
////
|
||||
//// Ex:
|
||||
//// Ex:
|
||||
//// if (1) { ....
|
||||
//// * ) and { are on the same line so apply the rule. Here we don't care whether it's same or multi block context
|
||||
////
|
||||
//// Ex:
|
||||
//// Ex:
|
||||
//// if (1)
|
||||
//// { ... }
|
||||
//// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we don't format.
|
||||
////
|
||||
//// Ex:
|
||||
//// if (1)
|
||||
//// if (1)
|
||||
//// { ...
|
||||
//// }
|
||||
//// * ) and { are on different lines. We only need to format if the block is multiline context. So in this case we format.
|
||||
|
||||
@@ -95,9 +95,9 @@ namespace ts.formatting {
|
||||
//// 4- Context rules with any token combination
|
||||
//// 5- Non-context rules with specific token combination
|
||||
//// 6- Non-context rules with any token combination
|
||||
////
|
||||
////
|
||||
//// The member rulesInsertionIndexBitmap is used to describe the number of rules
|
||||
//// in each sub-bucket (above) hence can be used to know the index of where to insert
|
||||
//// in each sub-bucket (above) hence can be used to know the index of where to insert
|
||||
//// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits.
|
||||
////
|
||||
//// Example:
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace ts.NavigateTo {
|
||||
// This means "compare in a case insensitive manner."
|
||||
const baseSensitivity: Intl.CollatorOptions = { sensitivity: "base" };
|
||||
|
||||
// Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
|
||||
// Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
|
||||
forEach(program.getSourceFiles(), sourceFile => {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace ts.NavigateTo {
|
||||
for (const name in nameToDeclarations) {
|
||||
const declarations = getProperty(nameToDeclarations, name);
|
||||
if (declarations) {
|
||||
// First do a quick check to see if the name of the declaration matches the
|
||||
// First do a quick check to see if the name of the declaration matches the
|
||||
// last portion of the (possibly) dotted name they're searching for.
|
||||
let matches = patternMatcher.getMatchesForLastSegmentOfPattern(name);
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace ts.NavigateTo {
|
||||
}
|
||||
|
||||
for (const declaration of declarations) {
|
||||
// It was a match! If the pattern has dots in it, then also see if the
|
||||
// It was a match! If the pattern has dots in it, then also see if the
|
||||
// declaration container matches as well.
|
||||
if (patternMatcher.patternContainsDots) {
|
||||
const containers = getContainers(declaration);
|
||||
|
||||
@@ -9,16 +9,10 @@ namespace ts.NavigationBar {
|
||||
return getJsNavigationBarItems(sourceFile, compilerOptions);
|
||||
}
|
||||
|
||||
// If the source file has any child items, then it included in the tree
|
||||
// and takes lexical ownership of all other top-level items.
|
||||
let hasGlobalNode = false;
|
||||
|
||||
return getItemsWorker(getTopLevelNodes(sourceFile), createTopLevelItem);
|
||||
|
||||
function getIndent(node: Node): number {
|
||||
// If we have a global node in the tree,
|
||||
// then it adds an extra layer of depth to all subnodes.
|
||||
let indent = hasGlobalNode ? 1 : 0;
|
||||
let indent = 1; // Global node is the only one with indent 0.
|
||||
|
||||
let current = node.parent;
|
||||
while (current) {
|
||||
@@ -141,7 +135,7 @@ namespace ts.NavigationBar {
|
||||
function sortNodes(nodes: Node[]): Node[] {
|
||||
return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => {
|
||||
if (n1.name && n2.name) {
|
||||
return getPropertyNameForPropertyNameNode(n1.name).localeCompare(getPropertyNameForPropertyNameNode(n2.name));
|
||||
return localeCompareFix(getPropertyNameForPropertyNameNode(n1.name), getPropertyNameForPropertyNameNode(n2.name));
|
||||
}
|
||||
else if (n1.name) {
|
||||
return 1;
|
||||
@@ -153,6 +147,16 @@ namespace ts.NavigationBar {
|
||||
return n1.kind - n2.kind;
|
||||
}
|
||||
});
|
||||
|
||||
// node 0.10 treats "a" as greater than "B".
|
||||
// For consistency, sort alphabetically, falling back to which is lower-case.
|
||||
function localeCompareFix(a: string, b: string) {
|
||||
const cmp = a.toLowerCase().localeCompare(b.toLowerCase());
|
||||
if (cmp !== 0)
|
||||
return cmp;
|
||||
// Return the *opposite* of the `<` operator, which works the same in node 0.10 and 6.0.
|
||||
return a < b ? 1 : a > b ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void {
|
||||
@@ -511,11 +515,6 @@ namespace ts.NavigationBar {
|
||||
function createSourceFileItem(node: SourceFile): ts.NavigationBarItem {
|
||||
const childItems = getItemsWorker(getChildNodes(node.statements), createChildItem);
|
||||
|
||||
if (childItems === undefined || childItems.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
hasGlobalNode = true;
|
||||
const rootName = isExternalModule(node)
|
||||
? "\"" + escapeString(getBaseFileName(removeFileExtension(normalizePath(node.fileName)))) + "\""
|
||||
: "<global>";
|
||||
@@ -653,6 +652,12 @@ namespace ts.NavigationBar {
|
||||
topItem.childItems.push(newItem);
|
||||
}
|
||||
|
||||
if (node.jsDocComments && node.jsDocComments.length > 0) {
|
||||
for (const jsDocComment of node.jsDocComments) {
|
||||
visitNode(jsDocComment);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a level if traversing into a container
|
||||
if (newItem && (isFunctionLike(node) || isClassLike(node))) {
|
||||
const lastTop = topItem;
|
||||
@@ -732,6 +737,27 @@ namespace ts.NavigationBar {
|
||||
}
|
||||
const declName = declarationNameToString(decl.name);
|
||||
return getNavBarItem(declName, ScriptElementKind.constElement, [getNodeSpan(node)]);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
if ((<JSDocTypedefTag>node).name) {
|
||||
return getNavBarItem(
|
||||
(<JSDocTypedefTag>node).name.text,
|
||||
ScriptElementKind.typeElement,
|
||||
[getNodeSpan(node)]);
|
||||
}
|
||||
else {
|
||||
const parentNode = node.parent && node.parent.parent;
|
||||
if (parentNode && parentNode.kind === SyntaxKind.VariableStatement) {
|
||||
if ((<VariableStatement>parentNode).declarationList.declarations.length > 0) {
|
||||
const nameIdentifier = (<VariableStatement>parentNode).declarationList.declarations[0].name;
|
||||
if (nameIdentifier.kind === SyntaxKind.Identifier) {
|
||||
return getNavBarItem(
|
||||
(<Identifier>nameIdentifier).text,
|
||||
ScriptElementKind.typeElement,
|
||||
[getNodeSpan(node)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
@@ -802,7 +828,7 @@ namespace ts.NavigationBar {
|
||||
}
|
||||
|
||||
function getNodeSpan(node: Node) {
|
||||
return node.kind === SyntaxKind.SourceFile
|
||||
return node.kind === SyntaxKind.SourceFile
|
||||
? createTextSpanFromBounds(node.getFullStart(), node.getEnd())
|
||||
: createTextSpanFromBounds(node.getStart(), node.getEnd());
|
||||
}
|
||||
|
||||
+34
-14
@@ -20,7 +20,7 @@ namespace ts {
|
||||
getChildCount(sourceFile?: SourceFile): number;
|
||||
getChildAt(index: number, sourceFile?: SourceFile): Node;
|
||||
getChildren(sourceFile?: SourceFile): Node[];
|
||||
getStart(sourceFile?: SourceFile): number;
|
||||
getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number;
|
||||
getFullStart(): number;
|
||||
getEnd(): number;
|
||||
getWidth(sourceFile?: SourceFile): number;
|
||||
@@ -172,6 +172,9 @@ namespace ts {
|
||||
"static",
|
||||
"throws",
|
||||
"type",
|
||||
"typedef",
|
||||
"property",
|
||||
"prop",
|
||||
"version"
|
||||
];
|
||||
let jsDocCompletionEntries: CompletionEntry[];
|
||||
@@ -189,6 +192,7 @@ namespace ts {
|
||||
public end: number;
|
||||
public flags: NodeFlags;
|
||||
public parent: Node;
|
||||
public jsDocComments: JSDocComment[];
|
||||
private _children: Node[];
|
||||
|
||||
constructor(kind: SyntaxKind, pos: number, end: number) {
|
||||
@@ -203,8 +207,8 @@ namespace ts {
|
||||
return getSourceFileOfNode(this);
|
||||
}
|
||||
|
||||
public getStart(sourceFile?: SourceFile): number {
|
||||
return getTokenPosOfNode(this, sourceFile);
|
||||
public getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number {
|
||||
return getTokenPosOfNode(this, sourceFile, includeJsDocComment);
|
||||
}
|
||||
|
||||
public getFullStart(): number {
|
||||
@@ -235,12 +239,14 @@ namespace ts {
|
||||
return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
|
||||
}
|
||||
|
||||
private addSyntheticNodes(nodes: Node[], pos: number, end: number): number {
|
||||
private addSyntheticNodes(nodes: Node[], pos: number, end: number, useJSDocScanner?: boolean): number {
|
||||
scanner.setTextPos(pos);
|
||||
while (pos < end) {
|
||||
const token = scanner.scan();
|
||||
const token = useJSDocScanner ? scanner.scanJSDocToken() : scanner.scan();
|
||||
const textPos = scanner.getTextPos();
|
||||
nodes.push(createNode(token, pos, textPos, 0, this));
|
||||
if (textPos <= end) {
|
||||
nodes.push(createNode(token, pos, textPos, 0, this));
|
||||
}
|
||||
pos = textPos;
|
||||
}
|
||||
return pos;
|
||||
@@ -270,20 +276,27 @@ namespace ts {
|
||||
scanner.setText((sourceFile || this.getSourceFile()).text);
|
||||
children = [];
|
||||
let pos = this.pos;
|
||||
const useJSDocScanner = this.kind >= SyntaxKind.FirstJSDocTagNode && this.kind <= SyntaxKind.LastJSDocTagNode;
|
||||
const processNode = (node: Node) => {
|
||||
if (pos < node.pos) {
|
||||
pos = this.addSyntheticNodes(children, pos, node.pos);
|
||||
pos = this.addSyntheticNodes(children, pos, node.pos, useJSDocScanner);
|
||||
}
|
||||
children.push(node);
|
||||
pos = node.end;
|
||||
};
|
||||
const processNodes = (nodes: NodeArray<Node>) => {
|
||||
if (pos < nodes.pos) {
|
||||
pos = this.addSyntheticNodes(children, pos, nodes.pos);
|
||||
pos = this.addSyntheticNodes(children, pos, nodes.pos, useJSDocScanner);
|
||||
}
|
||||
children.push(this.createSyntaxList(<NodeArray<Node>>nodes));
|
||||
pos = nodes.end;
|
||||
};
|
||||
// jsDocComments need to be the first children
|
||||
if (this.jsDocComments) {
|
||||
for (const jsDocComment of this.jsDocComments) {
|
||||
processNode(jsDocComment);
|
||||
}
|
||||
}
|
||||
forEachChild(this, processNode, processNodes);
|
||||
if (pos < this.end) {
|
||||
this.addSyntheticNodes(children, pos, this.end);
|
||||
@@ -2644,7 +2657,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
|
||||
*/
|
||||
function getContainingObjectLiteralElement(node: Node): ObjectLiteralElement {
|
||||
@@ -2906,6 +2919,7 @@ namespace ts {
|
||||
const changesInCompilationSettingsAffectSyntax = oldSettings &&
|
||||
(oldSettings.target !== newSettings.target ||
|
||||
oldSettings.module !== newSettings.module ||
|
||||
oldSettings.moduleResolution !== newSettings.moduleResolution ||
|
||||
oldSettings.noResolve !== newSettings.noResolve ||
|
||||
oldSettings.jsx !== newSettings.jsx ||
|
||||
oldSettings.allowJs !== newSettings.allowJs);
|
||||
@@ -5637,7 +5651,7 @@ namespace ts {
|
||||
|
||||
const sourceFile = getValidSourceFile(fileName);
|
||||
|
||||
const node = getTouchingPropertyName(sourceFile, position);
|
||||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
if (node === sourceFile) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -5999,7 +6013,8 @@ namespace ts {
|
||||
const sourceFile = container.getSourceFile();
|
||||
const tripleSlashDirectivePrefixRegex = /^\/\/\/\s*</;
|
||||
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, container.getStart(), container.getEnd());
|
||||
const start = findInComments ? container.getFullStart() : container.getStart();
|
||||
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, start, container.getEnd());
|
||||
|
||||
if (possiblePositions.length) {
|
||||
// Build the set of symbols to search for, initially it has only the current symbol
|
||||
@@ -7590,11 +7605,11 @@ namespace ts {
|
||||
|
||||
function isValidBraceCompletionAtPostion(fileName: string, position: number, openingBrace: number): boolean {
|
||||
|
||||
// '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too
|
||||
// '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too
|
||||
// expensive to do during typing scenarios
|
||||
// i.e. whether we're dealing with:
|
||||
// var x = new foo<| ( with class foo<T>{} )
|
||||
// or
|
||||
// or
|
||||
// var y = 3 <|
|
||||
if (openingBrace === CharacterCodes.lessThan) {
|
||||
return false;
|
||||
@@ -7829,7 +7844,7 @@ namespace ts {
|
||||
const defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings());
|
||||
const canonicalDefaultLibName = getCanonicalFileName(ts.normalizePath(defaultLibFileName));
|
||||
|
||||
const node = getTouchingWord(sourceFile, position);
|
||||
const node = getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true);
|
||||
|
||||
// Can only rename an identifier.
|
||||
if (node) {
|
||||
@@ -7999,6 +8014,11 @@ namespace ts {
|
||||
break;
|
||||
default:
|
||||
forEachChild(node, walk);
|
||||
if (node.jsDocComments) {
|
||||
for (const jsDocComment of node.jsDocComments) {
|
||||
forEachChild(jsDocComment, walk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ namespace ts {
|
||||
|
||||
constructor(private shimHost: LanguageServiceShimHost) {
|
||||
// if shimHost is a COM object then property check will become method call with no arguments.
|
||||
// 'in' does not have this effect.
|
||||
// 'in' does not have this effect.
|
||||
if ("getModuleResolutionsForFile" in this.shimHost) {
|
||||
this.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
|
||||
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
|
||||
@@ -966,7 +966,7 @@ namespace ts {
|
||||
return this.forwardJSONCall(
|
||||
"getPreProcessedFileInfo('" + fileName + "')",
|
||||
() => {
|
||||
// for now treat files as JavaScript
|
||||
// for now treat files as JavaScript
|
||||
const result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true);
|
||||
return {
|
||||
referencedFiles: this.convertFileReferences(result.referencedFiles),
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
namespace ts.SignatureHelp {
|
||||
|
||||
// A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
|
||||
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
|
||||
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
|
||||
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
|
||||
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
|
||||
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
|
||||
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
|
||||
// looking up the type. The method will also keep track of the parameter index inside the expression.
|
||||
// public static isInPartiallyWrittenTypeArgumentList(syntaxTree: TypeScript.SyntaxTree, position: number): any {
|
||||
// let token = Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, /*includeSkippedTokens*/ true);
|
||||
@@ -202,7 +202,7 @@ namespace ts.SignatureHelp {
|
||||
cancellationToken.throwIfCancellationRequested();
|
||||
|
||||
if (!candidates.length) {
|
||||
// We didn't have any sig help items produced by the TS compiler. If this is a JS
|
||||
// We didn't have any sig help items produced by the TS compiler. If this is a JS
|
||||
// file, then see if we can figure out anything better.
|
||||
if (isSourceFileJavaScript(sourceFile)) {
|
||||
return createJavaScriptSignatureHelpItems(argumentInfo);
|
||||
@@ -353,8 +353,8 @@ namespace ts.SignatureHelp {
|
||||
}
|
||||
|
||||
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
|
||||
// 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.
|
||||
@@ -386,8 +386,8 @@ namespace ts.SignatureHelp {
|
||||
// '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>'
|
||||
// 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();
|
||||
|
||||
+45
-18
@@ -234,29 +234,29 @@ namespace ts {
|
||||
/* Gets the token whose text has range [start, end) and
|
||||
* position >= start and (position < end or (position === end && token is keyword or identifier))
|
||||
*/
|
||||
export function getTouchingWord(sourceFile: SourceFile, position: number): Node {
|
||||
return getTouchingToken(sourceFile, position, n => isWord(n.kind));
|
||||
export function getTouchingWord(sourceFile: SourceFile, position: number, includeJsDocComment = false): Node {
|
||||
return getTouchingToken(sourceFile, position, n => isWord(n.kind), includeJsDocComment);
|
||||
}
|
||||
|
||||
/* Gets the token whose text has range [start, end) and position >= start
|
||||
* and (position < end or (position === end && token is keyword or identifier or numeric/string literal))
|
||||
*/
|
||||
export function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node {
|
||||
return getTouchingToken(sourceFile, position, n => isPropertyName(n.kind));
|
||||
export function getTouchingPropertyName(sourceFile: SourceFile, position: number, includeJsDocComment = false): Node {
|
||||
return getTouchingToken(sourceFile, position, n => isPropertyName(n.kind), includeJsDocComment);
|
||||
}
|
||||
|
||||
/** Returns the token if position is in [start, end) or if position === end and includeItemAtEndPosition(token) === true */
|
||||
export function getTouchingToken(sourceFile: SourceFile, position: number, includeItemAtEndPosition?: (n: Node) => boolean): Node {
|
||||
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition);
|
||||
export function getTouchingToken(sourceFile: SourceFile, position: number, includeItemAtEndPosition?: (n: Node) => boolean, includeJsDocComment = false): Node {
|
||||
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includeItemAtEndPosition, includeJsDocComment);
|
||||
}
|
||||
|
||||
/** Returns a token if position is in [start-of-leading-trivia, end) */
|
||||
export function getTokenAtPosition(sourceFile: SourceFile, position: number): Node {
|
||||
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined);
|
||||
export function getTokenAtPosition(sourceFile: SourceFile, position: number, includeJsDocComment = false): Node {
|
||||
return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includeItemAtEndPosition*/ undefined, includeJsDocComment);
|
||||
}
|
||||
|
||||
/** Get the token whose text contains the position */
|
||||
function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includeItemAtEndPosition: (n: Node) => boolean): Node {
|
||||
function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includeItemAtEndPosition: (n: Node) => boolean, includeJsDocComment = false): Node {
|
||||
let current: Node = sourceFile;
|
||||
outer: while (true) {
|
||||
if (isToken(current)) {
|
||||
@@ -264,13 +264,34 @@ namespace ts {
|
||||
return current;
|
||||
}
|
||||
|
||||
if (includeJsDocComment) {
|
||||
const jsDocChildren = ts.filter(current.getChildren(), isJSDocNode);
|
||||
for (const jsDocChild of jsDocChildren) {
|
||||
const start = allowPositionInLeadingTrivia ? jsDocChild.getFullStart() : jsDocChild.getStart(sourceFile, includeJsDocComment);
|
||||
if (start <= position) {
|
||||
const end = jsDocChild.getEnd();
|
||||
if (position < end || (position === end && jsDocChild.kind === SyntaxKind.EndOfFileToken)) {
|
||||
current = jsDocChild;
|
||||
continue outer;
|
||||
}
|
||||
else if (includeItemAtEndPosition && end === position) {
|
||||
const previousToken = findPrecedingToken(position, sourceFile, jsDocChild);
|
||||
if (previousToken && includeItemAtEndPosition(previousToken)) {
|
||||
return previousToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find the child that contains 'position'
|
||||
for (let i = 0, n = current.getChildCount(sourceFile); i < n; i++) {
|
||||
const child = current.getChildAt(i);
|
||||
if (position < child.getFullStart() || position > child.getEnd()) {
|
||||
// all jsDocComment nodes were already visited
|
||||
if (isJSDocNode(child)) {
|
||||
continue;
|
||||
}
|
||||
const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile);
|
||||
const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, includeJsDocComment);
|
||||
if (start <= position) {
|
||||
const end = child.getEnd();
|
||||
if (position < end || (position === end && child.kind === SyntaxKind.EndOfFileToken)) {
|
||||
@@ -285,6 +306,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
}
|
||||
@@ -423,6 +445,10 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (token.kind === SyntaxKind.JsxText) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// <div>Hello |</div>
|
||||
if (token.kind === SyntaxKind.LessThanToken && token.parent.kind === SyntaxKind.JsxText) {
|
||||
return true;
|
||||
@@ -433,7 +459,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
// <div> {
|
||||
// <div> {
|
||||
// |
|
||||
// } < /div>
|
||||
if (token && token.kind === SyntaxKind.CloseBraceToken && token.parent.kind === SyntaxKind.JsxExpression) {
|
||||
@@ -518,11 +544,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (node) {
|
||||
const jsDocComment = node.jsDocComment;
|
||||
if (jsDocComment) {
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.pos <= position && position <= tag.end) {
|
||||
return tag;
|
||||
if (node.jsDocComments) {
|
||||
for (const jsDocComment of node.jsDocComments) {
|
||||
for (const tag of jsDocComment.tags) {
|
||||
if (tag.pos <= position && position <= tag.end) {
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -646,7 +673,7 @@ namespace ts {
|
||||
|
||||
// [a, b, c] of
|
||||
// [x, [a, b, c] ] = someExpression
|
||||
// or
|
||||
// or
|
||||
// {x, a: {a, b, c} } = someExpression
|
||||
if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === SyntaxKind.PropertyAssignment ? node.parent.parent : node.parent)) {
|
||||
return true;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction2.ts(1,13): error TS2304: Cannot find name 'b'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction2.ts(1,14): error TS1009: Trailing comma not allowed.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/ArrowFunction2.ts (2 errors) ====
|
||||
var v = (a: b,) => {
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'b'.
|
||||
~
|
||||
!!! error TS1009: Trailing comma not allowed.
|
||||
|
||||
};
|
||||
@@ -1,8 +0,0 @@
|
||||
//// [ArrowFunction2.ts]
|
||||
var v = (a: b,) => {
|
||||
|
||||
};
|
||||
|
||||
//// [ArrowFunction2.js]
|
||||
var v = function (a) {
|
||||
};
|
||||
@@ -13,5 +13,5 @@ module M {
|
||||
import r = M.X;
|
||||
>r : Symbol(r, Decl(acceptableAlias1.ts, 4, 1))
|
||||
>M : Symbol(M, Decl(acceptableAlias1.ts, 0, 0))
|
||||
>X : Symbol(r, Decl(acceptableAlias1.ts, 0, 10))
|
||||
>X : Symbol(M.X, Decl(acceptableAlias1.ts, 2, 5))
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import foo = require("./foo_0");
|
||||
// None of the below should cause a runtime dependency on foo_0
|
||||
import f = foo.M1;
|
||||
>f : Symbol(f, Decl(foo_1.ts, 0, 32))
|
||||
>foo : Symbol(foo, Decl(foo_0.ts, 0, 0))
|
||||
>foo : Symbol(foo, Decl(foo_1.ts, 0, 0))
|
||||
>M1 : Symbol(foo.M1, Decl(foo_0.ts, 8, 1))
|
||||
|
||||
var i: f.I2;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// array literals are widened upon assignment according to their element type
|
||||
|
||||
var a = []; // any[]
|
||||
var a = [,,];
|
||||
|
||||
var a = [null, null];
|
||||
var a = [undefined, undefined];
|
||||
@@ -12,11 +13,20 @@ var b = [[undefined, undefined]];
|
||||
|
||||
var c = [[[]]]; // any[][][]
|
||||
var c = [[[null]],[undefined]]
|
||||
|
||||
// no widening when one or more elements are non-widening
|
||||
|
||||
var x: undefined = undefined;
|
||||
|
||||
var d = [x];
|
||||
var d = [, x];
|
||||
var d = [undefined, x];
|
||||
|
||||
|
||||
//// [arrayLiteralWidened.js]
|
||||
// array literals are widened upon assignment according to their element type
|
||||
var a = []; // any[]
|
||||
var a = [, ,];
|
||||
var a = [null, null];
|
||||
var a = [undefined, undefined];
|
||||
var b = [[], [null, null]]; // any[][]
|
||||
@@ -24,3 +34,8 @@ var b = [[], []];
|
||||
var b = [[undefined, undefined]];
|
||||
var c = [[[]]]; // any[][][]
|
||||
var c = [[[null]], [undefined]];
|
||||
// no widening when one or more elements are non-widening
|
||||
var x = undefined;
|
||||
var d = [x];
|
||||
var d = [, x];
|
||||
var d = [undefined, x];
|
||||
|
||||
@@ -2,31 +2,53 @@
|
||||
// array literals are widened upon assignment according to their element type
|
||||
|
||||
var a = []; // any[]
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 4, 3), Decl(arrayLiteralWidened.ts, 5, 3))
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
|
||||
|
||||
var a = [,,];
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
|
||||
|
||||
var a = [null, null];
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 4, 3), Decl(arrayLiteralWidened.ts, 5, 3))
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
|
||||
|
||||
var a = [undefined, undefined];
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 4, 3), Decl(arrayLiteralWidened.ts, 5, 3))
|
||||
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var b = [[], [null, null]]; // any[][]
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 7, 3), Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3))
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3), Decl(arrayLiteralWidened.ts, 10, 3))
|
||||
|
||||
var b = [[], []];
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 7, 3), Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3))
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3), Decl(arrayLiteralWidened.ts, 10, 3))
|
||||
|
||||
var b = [[undefined, undefined]];
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 7, 3), Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3))
|
||||
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3), Decl(arrayLiteralWidened.ts, 10, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var c = [[[]]]; // any[][][]
|
||||
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 11, 3), Decl(arrayLiteralWidened.ts, 12, 3))
|
||||
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 12, 3), Decl(arrayLiteralWidened.ts, 13, 3))
|
||||
|
||||
var c = [[[null]],[undefined]]
|
||||
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 11, 3), Decl(arrayLiteralWidened.ts, 12, 3))
|
||||
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 12, 3), Decl(arrayLiteralWidened.ts, 13, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
// no widening when one or more elements are non-widening
|
||||
|
||||
var x: undefined = undefined;
|
||||
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var d = [x];
|
||||
>d : Symbol(d, Decl(arrayLiteralWidened.ts, 19, 3), Decl(arrayLiteralWidened.ts, 20, 3), Decl(arrayLiteralWidened.ts, 21, 3))
|
||||
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
|
||||
|
||||
var d = [, x];
|
||||
>d : Symbol(d, Decl(arrayLiteralWidened.ts, 19, 3), Decl(arrayLiteralWidened.ts, 20, 3), Decl(arrayLiteralWidened.ts, 21, 3))
|
||||
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
|
||||
|
||||
var d = [undefined, x];
|
||||
>d : Symbol(d, Decl(arrayLiteralWidened.ts, 19, 3), Decl(arrayLiteralWidened.ts, 20, 3), Decl(arrayLiteralWidened.ts, 21, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
|
||||
|
||||
|
||||
@@ -5,6 +5,12 @@ var a = []; // any[]
|
||||
>a : any[]
|
||||
>[] : undefined[]
|
||||
|
||||
var a = [,,];
|
||||
>a : any[]
|
||||
>[,,] : undefined[]
|
||||
> : undefined
|
||||
> : undefined
|
||||
|
||||
var a = [null, null];
|
||||
>a : any[]
|
||||
>[null, null] : null[]
|
||||
@@ -53,3 +59,26 @@ var c = [[[null]],[undefined]]
|
||||
>[undefined] : undefined[]
|
||||
>undefined : undefined
|
||||
|
||||
// no widening when one or more elements are non-widening
|
||||
|
||||
var x: undefined = undefined;
|
||||
>x : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var d = [x];
|
||||
>d : undefined[]
|
||||
>[x] : undefined[]
|
||||
>x : undefined
|
||||
|
||||
var d = [, x];
|
||||
>d : undefined[]
|
||||
>[, x] : undefined[]
|
||||
> : undefined
|
||||
>x : undefined
|
||||
|
||||
var d = [undefined, x];
|
||||
>d : undefined[]
|
||||
>[undefined, x] : undefined[]
|
||||
>undefined : undefined
|
||||
>x : undefined
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import x = require('./chainedImportAlias_file0');
|
||||
|
||||
import y = x;
|
||||
>y : Symbol(y, Decl(chainedImportAlias_file1.ts, 0, 49))
|
||||
>x : Symbol(x, Decl(chainedImportAlias_file0.ts, 0, 0))
|
||||
>x : Symbol(x, Decl(chainedImportAlias_file1.ts, 0, 0))
|
||||
|
||||
y.m.foo();
|
||||
>y.m.foo : Symbol(x.m.foo, Decl(chainedImportAlias_file0.ts, 0, 17))
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
//// [classStaticPropertyTypeGuard.ts]
|
||||
|
||||
// Repro from #8923
|
||||
|
||||
class A {
|
||||
private static _a: string | undefined;
|
||||
|
||||
public get a(): string {
|
||||
if (A._a) {
|
||||
return A._a; // is possibly null or undefined.
|
||||
}
|
||||
return A._a = 'helloworld';
|
||||
}
|
||||
}
|
||||
|
||||
//// [classStaticPropertyTypeGuard.js]
|
||||
// Repro from #8923
|
||||
var A = (function () {
|
||||
function A() {
|
||||
}
|
||||
Object.defineProperty(A.prototype, "a", {
|
||||
get: function () {
|
||||
if (A._a) {
|
||||
return A._a; // is possibly null or undefined.
|
||||
}
|
||||
return A._a = 'helloworld';
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return A;
|
||||
}());
|
||||
@@ -0,0 +1,29 @@
|
||||
=== tests/cases/compiler/classStaticPropertyTypeGuard.ts ===
|
||||
|
||||
// Repro from #8923
|
||||
|
||||
class A {
|
||||
>A : Symbol(A, Decl(classStaticPropertyTypeGuard.ts, 0, 0))
|
||||
|
||||
private static _a: string | undefined;
|
||||
>_a : Symbol(A._a, Decl(classStaticPropertyTypeGuard.ts, 3, 9))
|
||||
|
||||
public get a(): string {
|
||||
>a : Symbol(A.a, Decl(classStaticPropertyTypeGuard.ts, 4, 42))
|
||||
|
||||
if (A._a) {
|
||||
>A._a : Symbol(A._a, Decl(classStaticPropertyTypeGuard.ts, 3, 9))
|
||||
>A : Symbol(A, Decl(classStaticPropertyTypeGuard.ts, 0, 0))
|
||||
>_a : Symbol(A._a, Decl(classStaticPropertyTypeGuard.ts, 3, 9))
|
||||
|
||||
return A._a; // is possibly null or undefined.
|
||||
>A._a : Symbol(A._a, Decl(classStaticPropertyTypeGuard.ts, 3, 9))
|
||||
>A : Symbol(A, Decl(classStaticPropertyTypeGuard.ts, 0, 0))
|
||||
>_a : Symbol(A._a, Decl(classStaticPropertyTypeGuard.ts, 3, 9))
|
||||
}
|
||||
return A._a = 'helloworld';
|
||||
>A._a : Symbol(A._a, Decl(classStaticPropertyTypeGuard.ts, 3, 9))
|
||||
>A : Symbol(A, Decl(classStaticPropertyTypeGuard.ts, 0, 0))
|
||||
>_a : Symbol(A._a, Decl(classStaticPropertyTypeGuard.ts, 3, 9))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
=== tests/cases/compiler/classStaticPropertyTypeGuard.ts ===
|
||||
|
||||
// Repro from #8923
|
||||
|
||||
class A {
|
||||
>A : A
|
||||
|
||||
private static _a: string | undefined;
|
||||
>_a : string | undefined
|
||||
|
||||
public get a(): string {
|
||||
>a : string
|
||||
|
||||
if (A._a) {
|
||||
>A._a : string | undefined
|
||||
>A : typeof A
|
||||
>_a : string | undefined
|
||||
|
||||
return A._a; // is possibly null or undefined.
|
||||
>A._a : string
|
||||
>A : typeof A
|
||||
>_a : string
|
||||
}
|
||||
return A._a = 'helloworld';
|
||||
>A._a = 'helloworld' : string
|
||||
>A._a : string | undefined
|
||||
>A : typeof A
|
||||
>_a : string | undefined
|
||||
>'helloworld' : string
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import foo = require("./foo_0");
|
||||
// None of the below should cause a runtime dependency on foo_0
|
||||
import f = foo.M1;
|
||||
>f : Symbol(f, Decl(foo_1.ts, 0, 32))
|
||||
>foo : Symbol(foo, Decl(foo_0.ts, 0, 0))
|
||||
>foo : Symbol(foo, Decl(foo_1.ts, 0, 0))
|
||||
>M1 : Symbol(foo.M1, Decl(foo_0.ts, 8, 1))
|
||||
|
||||
var i: f.I2;
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
//// [constLocalsInFunctionExpressions.ts]
|
||||
declare function getStringOrNumber(): string | number;
|
||||
|
||||
function f1() {
|
||||
const x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
const f = () => x.length;
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
const x = getStringOrNumber();
|
||||
if (typeof x !== "string") {
|
||||
return;
|
||||
}
|
||||
const f = () => x.length;
|
||||
}
|
||||
|
||||
function f3() {
|
||||
const x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
const f = function() { return x.length; };
|
||||
}
|
||||
}
|
||||
|
||||
function f4() {
|
||||
const x = getStringOrNumber();
|
||||
if (typeof x !== "string") {
|
||||
return;
|
||||
}
|
||||
const f = function() { return x.length; };
|
||||
}
|
||||
|
||||
function f5() {
|
||||
const x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
const f = () => () => x.length;
|
||||
}
|
||||
}
|
||||
|
||||
//// [constLocalsInFunctionExpressions.js]
|
||||
function f1() {
|
||||
var x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
var f = function () { return x.length; };
|
||||
}
|
||||
}
|
||||
function f2() {
|
||||
var x = getStringOrNumber();
|
||||
if (typeof x !== "string") {
|
||||
return;
|
||||
}
|
||||
var f = function () { return x.length; };
|
||||
}
|
||||
function f3() {
|
||||
var x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
var f = function () { return x.length; };
|
||||
}
|
||||
}
|
||||
function f4() {
|
||||
var x = getStringOrNumber();
|
||||
if (typeof x !== "string") {
|
||||
return;
|
||||
}
|
||||
var f = function () { return x.length; };
|
||||
}
|
||||
function f5() {
|
||||
var x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
var f = function () { return function () { return x.length; }; };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
=== tests/cases/conformance/controlFlow/constLocalsInFunctionExpressions.ts ===
|
||||
declare function getStringOrNumber(): string | number;
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(constLocalsInFunctionExpressions.ts, 0, 0))
|
||||
|
||||
function f1() {
|
||||
>f1 : Symbol(f1, Decl(constLocalsInFunctionExpressions.ts, 0, 54))
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 3, 9))
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(constLocalsInFunctionExpressions.ts, 0, 0))
|
||||
|
||||
if (typeof x === "string") {
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 3, 9))
|
||||
|
||||
const f = () => x.length;
|
||||
>f : Symbol(f, Decl(constLocalsInFunctionExpressions.ts, 5, 13))
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 3, 9))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
>f2 : Symbol(f2, Decl(constLocalsInFunctionExpressions.ts, 7, 1))
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 10, 9))
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(constLocalsInFunctionExpressions.ts, 0, 0))
|
||||
|
||||
if (typeof x !== "string") {
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 10, 9))
|
||||
|
||||
return;
|
||||
}
|
||||
const f = () => x.length;
|
||||
>f : Symbol(f, Decl(constLocalsInFunctionExpressions.ts, 14, 9))
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 10, 9))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
function f3() {
|
||||
>f3 : Symbol(f3, Decl(constLocalsInFunctionExpressions.ts, 15, 1))
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 18, 9))
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(constLocalsInFunctionExpressions.ts, 0, 0))
|
||||
|
||||
if (typeof x === "string") {
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 18, 9))
|
||||
|
||||
const f = function() { return x.length; };
|
||||
>f : Symbol(f, Decl(constLocalsInFunctionExpressions.ts, 20, 13))
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 18, 9))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
|
||||
function f4() {
|
||||
>f4 : Symbol(f4, Decl(constLocalsInFunctionExpressions.ts, 22, 1))
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 25, 9))
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(constLocalsInFunctionExpressions.ts, 0, 0))
|
||||
|
||||
if (typeof x !== "string") {
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 25, 9))
|
||||
|
||||
return;
|
||||
}
|
||||
const f = function() { return x.length; };
|
||||
>f : Symbol(f, Decl(constLocalsInFunctionExpressions.ts, 29, 9))
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 25, 9))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
function f5() {
|
||||
>f5 : Symbol(f5, Decl(constLocalsInFunctionExpressions.ts, 30, 1))
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 33, 9))
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(constLocalsInFunctionExpressions.ts, 0, 0))
|
||||
|
||||
if (typeof x === "string") {
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 33, 9))
|
||||
|
||||
const f = () => () => x.length;
|
||||
>f : Symbol(f, Decl(constLocalsInFunctionExpressions.ts, 35, 13))
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(constLocalsInFunctionExpressions.ts, 33, 9))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
=== tests/cases/conformance/controlFlow/constLocalsInFunctionExpressions.ts ===
|
||||
declare function getStringOrNumber(): string | number;
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
function f1() {
|
||||
>f1 : () => void
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : string | number
|
||||
>getStringOrNumber() : string | number
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
if (typeof x === "string") {
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
|
||||
const f = () => x.length;
|
||||
>f : () => number
|
||||
>() => x.length : () => number
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
>f2 : () => void
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : string | number
|
||||
>getStringOrNumber() : string | number
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
if (typeof x !== "string") {
|
||||
>typeof x !== "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
|
||||
return;
|
||||
}
|
||||
const f = () => x.length;
|
||||
>f : () => number
|
||||
>() => x.length : () => number
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
}
|
||||
|
||||
function f3() {
|
||||
>f3 : () => void
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : string | number
|
||||
>getStringOrNumber() : string | number
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
if (typeof x === "string") {
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
|
||||
const f = function() { return x.length; };
|
||||
>f : () => number
|
||||
>function() { return x.length; } : () => number
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
}
|
||||
}
|
||||
|
||||
function f4() {
|
||||
>f4 : () => void
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : string | number
|
||||
>getStringOrNumber() : string | number
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
if (typeof x !== "string") {
|
||||
>typeof x !== "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
|
||||
return;
|
||||
}
|
||||
const f = function() { return x.length; };
|
||||
>f : () => number
|
||||
>function() { return x.length; } : () => number
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
}
|
||||
|
||||
function f5() {
|
||||
>f5 : () => void
|
||||
|
||||
const x = getStringOrNumber();
|
||||
>x : string | number
|
||||
>getStringOrNumber() : string | number
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
if (typeof x === "string") {
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
|
||||
const f = () => () => x.length;
|
||||
>f : () => () => number
|
||||
>() => () => x.length : () => () => number
|
||||
>() => x.length : () => number
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
//// [controlFlowIIFE.ts]
|
||||
|
||||
declare function getStringOrNumber(): string | number;
|
||||
|
||||
function f1() {
|
||||
let x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
let n = function() {
|
||||
return x.length;
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
let x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
let n = (function() {
|
||||
return x.length;
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
let x = getStringOrNumber();
|
||||
let y: number;
|
||||
if (typeof x === "string") {
|
||||
let n = (z => x.length + y + z)(y = 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Repros from #8381
|
||||
|
||||
let maybeNumber: number | undefined;
|
||||
(function () {
|
||||
maybeNumber = 1;
|
||||
})();
|
||||
maybeNumber++;
|
||||
if (maybeNumber !== undefined) {
|
||||
maybeNumber++;
|
||||
}
|
||||
|
||||
let test: string | undefined;
|
||||
if (!test) {
|
||||
throw new Error('Test is not defined');
|
||||
}
|
||||
(() => {
|
||||
test.slice(1); // No error
|
||||
})();
|
||||
|
||||
//// [controlFlowIIFE.js]
|
||||
function f1() {
|
||||
var x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
var n = function () {
|
||||
return x.length;
|
||||
}();
|
||||
}
|
||||
}
|
||||
function f2() {
|
||||
var x = getStringOrNumber();
|
||||
if (typeof x === "string") {
|
||||
var n = (function () {
|
||||
return x.length;
|
||||
})();
|
||||
}
|
||||
}
|
||||
function f3() {
|
||||
var x = getStringOrNumber();
|
||||
var y;
|
||||
if (typeof x === "string") {
|
||||
var n = (function (z) { return x.length + y + z; })(y = 1);
|
||||
}
|
||||
}
|
||||
// Repros from #8381
|
||||
var maybeNumber;
|
||||
(function () {
|
||||
maybeNumber = 1;
|
||||
})();
|
||||
maybeNumber++;
|
||||
if (maybeNumber !== undefined) {
|
||||
maybeNumber++;
|
||||
}
|
||||
var test;
|
||||
if (!test) {
|
||||
throw new Error('Test is not defined');
|
||||
}
|
||||
(function () {
|
||||
test.slice(1); // No error
|
||||
})();
|
||||
@@ -0,0 +1,111 @@
|
||||
=== tests/cases/conformance/controlFlow/controlFlowIIFE.ts ===
|
||||
|
||||
declare function getStringOrNumber(): string | number;
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(controlFlowIIFE.ts, 0, 0))
|
||||
|
||||
function f1() {
|
||||
>f1 : Symbol(f1, Decl(controlFlowIIFE.ts, 1, 54))
|
||||
|
||||
let x = getStringOrNumber();
|
||||
>x : Symbol(x, Decl(controlFlowIIFE.ts, 4, 7))
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(controlFlowIIFE.ts, 0, 0))
|
||||
|
||||
if (typeof x === "string") {
|
||||
>x : Symbol(x, Decl(controlFlowIIFE.ts, 4, 7))
|
||||
|
||||
let n = function() {
|
||||
>n : Symbol(n, Decl(controlFlowIIFE.ts, 6, 11))
|
||||
|
||||
return x.length;
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(controlFlowIIFE.ts, 4, 7))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
>f2 : Symbol(f2, Decl(controlFlowIIFE.ts, 10, 1))
|
||||
|
||||
let x = getStringOrNumber();
|
||||
>x : Symbol(x, Decl(controlFlowIIFE.ts, 13, 7))
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(controlFlowIIFE.ts, 0, 0))
|
||||
|
||||
if (typeof x === "string") {
|
||||
>x : Symbol(x, Decl(controlFlowIIFE.ts, 13, 7))
|
||||
|
||||
let n = (function() {
|
||||
>n : Symbol(n, Decl(controlFlowIIFE.ts, 15, 11))
|
||||
|
||||
return x.length;
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(controlFlowIIFE.ts, 13, 7))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
>f3 : Symbol(f3, Decl(controlFlowIIFE.ts, 19, 1))
|
||||
|
||||
let x = getStringOrNumber();
|
||||
>x : Symbol(x, Decl(controlFlowIIFE.ts, 22, 7))
|
||||
>getStringOrNumber : Symbol(getStringOrNumber, Decl(controlFlowIIFE.ts, 0, 0))
|
||||
|
||||
let y: number;
|
||||
>y : Symbol(y, Decl(controlFlowIIFE.ts, 23, 7))
|
||||
|
||||
if (typeof x === "string") {
|
||||
>x : Symbol(x, Decl(controlFlowIIFE.ts, 22, 7))
|
||||
|
||||
let n = (z => x.length + y + z)(y = 1);
|
||||
>n : Symbol(n, Decl(controlFlowIIFE.ts, 25, 11))
|
||||
>z : Symbol(z, Decl(controlFlowIIFE.ts, 25, 17))
|
||||
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>x : Symbol(x, Decl(controlFlowIIFE.ts, 22, 7))
|
||||
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
|
||||
>y : Symbol(y, Decl(controlFlowIIFE.ts, 23, 7))
|
||||
>z : Symbol(z, Decl(controlFlowIIFE.ts, 25, 17))
|
||||
>y : Symbol(y, Decl(controlFlowIIFE.ts, 23, 7))
|
||||
}
|
||||
}
|
||||
|
||||
// Repros from #8381
|
||||
|
||||
let maybeNumber: number | undefined;
|
||||
>maybeNumber : Symbol(maybeNumber, Decl(controlFlowIIFE.ts, 31, 3))
|
||||
|
||||
(function () {
|
||||
maybeNumber = 1;
|
||||
>maybeNumber : Symbol(maybeNumber, Decl(controlFlowIIFE.ts, 31, 3))
|
||||
|
||||
})();
|
||||
maybeNumber++;
|
||||
>maybeNumber : Symbol(maybeNumber, Decl(controlFlowIIFE.ts, 31, 3))
|
||||
|
||||
if (maybeNumber !== undefined) {
|
||||
>maybeNumber : Symbol(maybeNumber, Decl(controlFlowIIFE.ts, 31, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
maybeNumber++;
|
||||
>maybeNumber : Symbol(maybeNumber, Decl(controlFlowIIFE.ts, 31, 3))
|
||||
}
|
||||
|
||||
let test: string | undefined;
|
||||
>test : Symbol(test, Decl(controlFlowIIFE.ts, 40, 3))
|
||||
|
||||
if (!test) {
|
||||
>test : Symbol(test, Decl(controlFlowIIFE.ts, 40, 3))
|
||||
|
||||
throw new Error('Test is not defined');
|
||||
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
}
|
||||
(() => {
|
||||
test.slice(1); // No error
|
||||
>test.slice : Symbol(String.slice, Decl(lib.d.ts, --, --))
|
||||
>test : Symbol(test, Decl(controlFlowIIFE.ts, 40, 3))
|
||||
>slice : Symbol(String.slice, Decl(lib.d.ts, --, --))
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,153 @@
|
||||
=== tests/cases/conformance/controlFlow/controlFlowIIFE.ts ===
|
||||
|
||||
declare function getStringOrNumber(): string | number;
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
function f1() {
|
||||
>f1 : () => void
|
||||
|
||||
let x = getStringOrNumber();
|
||||
>x : string | number
|
||||
>getStringOrNumber() : string | number
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
if (typeof x === "string") {
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
|
||||
let n = function() {
|
||||
>n : number
|
||||
>function() { return x.length; }() : number
|
||||
>function() { return x.length; } : () => number
|
||||
|
||||
return x.length;
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
function f2() {
|
||||
>f2 : () => void
|
||||
|
||||
let x = getStringOrNumber();
|
||||
>x : string | number
|
||||
>getStringOrNumber() : string | number
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
if (typeof x === "string") {
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
|
||||
let n = (function() {
|
||||
>n : number
|
||||
>(function() { return x.length; })() : number
|
||||
>(function() { return x.length; }) : () => number
|
||||
>function() { return x.length; } : () => number
|
||||
|
||||
return x.length;
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
function f3() {
|
||||
>f3 : () => void
|
||||
|
||||
let x = getStringOrNumber();
|
||||
>x : string | number
|
||||
>getStringOrNumber() : string | number
|
||||
>getStringOrNumber : () => string | number
|
||||
|
||||
let y: number;
|
||||
>y : number
|
||||
|
||||
if (typeof x === "string") {
|
||||
>typeof x === "string" : boolean
|
||||
>typeof x : string
|
||||
>x : string | number
|
||||
>"string" : string
|
||||
|
||||
let n = (z => x.length + y + z)(y = 1);
|
||||
>n : number
|
||||
>(z => x.length + y + z)(y = 1) : number
|
||||
>(z => x.length + y + z) : (z: number) => number
|
||||
>z => x.length + y + z : (z: number) => number
|
||||
>z : number
|
||||
>x.length + y + z : number
|
||||
>x.length + y : number
|
||||
>x.length : number
|
||||
>x : string
|
||||
>length : number
|
||||
>y : number
|
||||
>z : number
|
||||
>y = 1 : number
|
||||
>y : number
|
||||
>1 : number
|
||||
}
|
||||
}
|
||||
|
||||
// Repros from #8381
|
||||
|
||||
let maybeNumber: number | undefined;
|
||||
>maybeNumber : number | undefined
|
||||
|
||||
(function () {
|
||||
>(function () { maybeNumber = 1;})() : void
|
||||
>(function () { maybeNumber = 1;}) : () => void
|
||||
>function () { maybeNumber = 1;} : () => void
|
||||
|
||||
maybeNumber = 1;
|
||||
>maybeNumber = 1 : number
|
||||
>maybeNumber : number | undefined
|
||||
>1 : number
|
||||
|
||||
})();
|
||||
maybeNumber++;
|
||||
>maybeNumber++ : number
|
||||
>maybeNumber : number
|
||||
|
||||
if (maybeNumber !== undefined) {
|
||||
>maybeNumber !== undefined : boolean
|
||||
>maybeNumber : number
|
||||
>undefined : undefined
|
||||
|
||||
maybeNumber++;
|
||||
>maybeNumber++ : number
|
||||
>maybeNumber : number
|
||||
}
|
||||
|
||||
let test: string | undefined;
|
||||
>test : string | undefined
|
||||
|
||||
if (!test) {
|
||||
>!test : boolean
|
||||
>test : string | undefined
|
||||
|
||||
throw new Error('Test is not defined');
|
||||
>new Error('Test is not defined') : Error
|
||||
>Error : ErrorConstructor
|
||||
>'Test is not defined' : string
|
||||
}
|
||||
(() => {
|
||||
>(() => { test.slice(1); // No error})() : void
|
||||
>(() => { test.slice(1); // No error}) : () => void
|
||||
>() => { test.slice(1); // No error} : () => void
|
||||
|
||||
test.slice(1); // No error
|
||||
>test.slice(1) : string
|
||||
>test.slice : (start?: number | undefined, end?: number | undefined) => string
|
||||
>test : string
|
||||
>slice : (start?: number | undefined, end?: number | undefined) => string
|
||||
>1 : number
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,291 @@
|
||||
//// [controlFlowPropertyDeclarations.ts]
|
||||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
if (times === 1) {
|
||||
return string;
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
var repeated = '';
|
||||
while (times) {
|
||||
if (times & 1) {
|
||||
repeated += string;
|
||||
}
|
||||
if (times >>= 1) {
|
||||
string += string;
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
return endsWith(haystack, needle)
|
||||
? haystack.slice(0, -needle.length)
|
||||
: haystack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
return chr.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
return !/[^\s]/.test(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
return /^\d+px$/.test(value);
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
private output: string;
|
||||
private level: number;
|
||||
private _inPreTag: boolean;
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
|
||||
if (this._inPreTag) {
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
.replace(/\r/g, '')
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
styles = {};
|
||||
toJSXString = () => {
|
||||
for (var key in this.styles) {
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [controlFlowPropertyDeclarations.js]
|
||||
// Repro from ##8913
|
||||
"use strict";
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
continue;
|
||||
}
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
}
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
if (times === 1) {
|
||||
return string;
|
||||
}
|
||||
if (times < 0) {
|
||||
throw new Error();
|
||||
}
|
||||
var repeated = '';
|
||||
while (times) {
|
||||
if (times & 1) {
|
||||
repeated += string;
|
||||
}
|
||||
if (times >>= 1) {
|
||||
string += string;
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
}
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
}
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
return endsWith(haystack, needle)
|
||||
? haystack.slice(0, -needle.length)
|
||||
: haystack;
|
||||
}
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
return string.replace(/-(.)/g, function (match, chr) {
|
||||
return chr.toUpperCase();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
return !/[^\s]/.test(string);
|
||||
}
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
return /^\d+px$/.test(value);
|
||||
}
|
||||
var HTMLtoJSX = (function () {
|
||||
function HTMLtoJSX() {
|
||||
var _this = this;
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
this._visitText = function (node) {
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
var text = '';
|
||||
if (_this._inPreTag) {
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
.replace(/\r/g, '')
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function (whitespace) {
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
});
|
||||
}
|
||||
else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
}
|
||||
}
|
||||
_this.output += text;
|
||||
};
|
||||
}
|
||||
return HTMLtoJSX;
|
||||
}());
|
||||
exports.HTMLtoJSX = HTMLtoJSX;
|
||||
;
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
var StyleParser = (function () {
|
||||
function StyleParser() {
|
||||
var _this = this;
|
||||
this.styles = {};
|
||||
this.toJSXString = function () {
|
||||
for (var key in _this.styles) {
|
||||
if (!_this.styles.hasOwnProperty(key)) {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return StyleParser;
|
||||
}());
|
||||
exports.StyleParser = StyleParser;
|
||||
@@ -0,0 +1,288 @@
|
||||
=== tests/cases/compiler/controlFlowPropertyDeclarations.ts ===
|
||||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
>require : Symbol(require, Decl(controlFlowPropertyDeclarations.ts, 2, 11))
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
>require : Symbol(require, Decl(controlFlowPropertyDeclarations.ts, 2, 11))
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
>mapFrom : Symbol(mapFrom, Decl(controlFlowPropertyDeclarations.ts, 13, 5))
|
||||
>HTMLDOMPropertyConfig : Symbol(HTMLDOMPropertyConfig, Decl(controlFlowPropertyDeclarations.ts, 4, 3))
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
>propname.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
|
||||
>propname : Symbol(propname, Decl(controlFlowPropertyDeclarations.ts, 8, 8))
|
||||
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
>repeatString : Symbol(repeatString, Decl(controlFlowPropertyDeclarations.ts, 14, 1))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
if (times === 1) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
return string;
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
>Error : Symbol(Error, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
var repeated = '';
|
||||
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
|
||||
|
||||
while (times) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
if (times & 1) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
repeated += string;
|
||||
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
}
|
||||
if (times >>= 1) {
|
||||
>times : Symbol(times, Decl(controlFlowPropertyDeclarations.ts, 25, 29))
|
||||
|
||||
string += string;
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 25, 22))
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
>repeated : Symbol(repeated, Decl(controlFlowPropertyDeclarations.ts, 30, 5))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
>endsWith : Symbol(endsWith, Decl(controlFlowPropertyDeclarations.ts, 40, 1))
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 49, 18))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
|
||||
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 49, 18))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 49, 27))
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
>trimEnd : Symbol(trimEnd, Decl(controlFlowPropertyDeclarations.ts, 51, 1))
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
|
||||
|
||||
return endsWith(haystack, needle)
|
||||
>endsWith : Symbol(endsWith, Decl(controlFlowPropertyDeclarations.ts, 40, 1))
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
|
||||
|
||||
? haystack.slice(0, -needle.length)
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
>needle : Symbol(needle, Decl(controlFlowPropertyDeclarations.ts, 61, 26))
|
||||
|
||||
: haystack;
|
||||
>haystack : Symbol(haystack, Decl(controlFlowPropertyDeclarations.ts, 61, 17))
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
>hyphenToCamelCase : Symbol(hyphenToCamelCase, Decl(controlFlowPropertyDeclarations.ts, 65, 1))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 70, 27))
|
||||
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 70, 27))
|
||||
>match : Symbol(match, Decl(controlFlowPropertyDeclarations.ts, 71, 42))
|
||||
>chr : Symbol(chr, Decl(controlFlowPropertyDeclarations.ts, 71, 48))
|
||||
|
||||
return chr.toUpperCase();
|
||||
>chr : Symbol(chr, Decl(controlFlowPropertyDeclarations.ts, 71, 48))
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
>isEmpty : Symbol(isEmpty, Decl(controlFlowPropertyDeclarations.ts, 74, 1))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 79, 17))
|
||||
|
||||
return !/[^\s]/.test(string);
|
||||
>/[^\s]/.test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>string : Symbol(string, Decl(controlFlowPropertyDeclarations.ts, 79, 17))
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
>isConvertiblePixelValue : Symbol(isConvertiblePixelValue, Decl(controlFlowPropertyDeclarations.ts, 81, 1))
|
||||
>value : Symbol(value, Decl(controlFlowPropertyDeclarations.ts, 90, 33))
|
||||
|
||||
return /^\d+px$/.test(value);
|
||||
>/^\d+px$/.test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>test : Symbol(RegExp.test, Decl(lib.d.ts, --, --))
|
||||
>value : Symbol(value, Decl(controlFlowPropertyDeclarations.ts, 90, 33))
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
>HTMLtoJSX : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
|
||||
|
||||
private output: string;
|
||||
>output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
|
||||
|
||||
private level: number;
|
||||
>level : Symbol(HTMLtoJSX.level, Decl(controlFlowPropertyDeclarations.ts, 95, 27))
|
||||
|
||||
private _inPreTag: boolean;
|
||||
>_inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
>_visitText : Symbol(HTMLtoJSX._visitText, Decl(controlFlowPropertyDeclarations.ts, 97, 31))
|
||||
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
|
||||
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
|
||||
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
|
||||
>node : Symbol(node, Decl(controlFlowPropertyDeclarations.ts, 105, 16))
|
||||
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
|
||||
>parentTag : Symbol(parentTag, Decl(controlFlowPropertyDeclarations.ts, 106, 7))
|
||||
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
|
||||
if (this._inPreTag) {
|
||||
>this._inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
|
||||
>this : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
|
||||
>_inPreTag : Symbol(HTMLtoJSX._inPreTag, Decl(controlFlowPropertyDeclarations.ts, 96, 26))
|
||||
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
>text .replace(/\r/g, '') .replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>text .replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
|
||||
.replace(/\r/g, '')
|
||||
>replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
>replace : Symbol(String.replace, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>whitespace : Symbol(whitespace, Decl(controlFlowPropertyDeclarations.ts, 121, 50))
|
||||
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
>JSON.stringify : Symbol(JSON.stringify, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>JSON : Symbol(JSON, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>stringify : Symbol(JSON.stringify, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
|
||||
>whitespace : Symbol(whitespace, Decl(controlFlowPropertyDeclarations.ts, 121, 50))
|
||||
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
>text.indexOf : Symbol(String.indexOf, Decl(lib.d.ts, --, --))
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
>indexOf : Symbol(String.indexOf, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
>this.output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
|
||||
>this : Symbol(HTMLtoJSX, Decl(controlFlowPropertyDeclarations.ts, 92, 1))
|
||||
>output : Symbol(HTMLtoJSX.output, Decl(controlFlowPropertyDeclarations.ts, 94, 24))
|
||||
>text : Symbol(text, Decl(controlFlowPropertyDeclarations.ts, 113, 7))
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
>StyleParser : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
|
||||
|
||||
styles = {};
|
||||
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
|
||||
toJSXString = () => {
|
||||
>toJSXString : Symbol(StyleParser.toJSXString, Decl(controlFlowPropertyDeclarations.ts, 140, 14))
|
||||
|
||||
for (var key in this.styles) {
|
||||
>key : Symbol(key, Decl(controlFlowPropertyDeclarations.ts, 142, 12))
|
||||
>this.styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
>this : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
|
||||
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
>this.styles.hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.d.ts, --, --))
|
||||
>this.styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
>this : Symbol(StyleParser, Decl(controlFlowPropertyDeclarations.ts, 134, 2))
|
||||
>styles : Symbol(StyleParser.styles, Decl(controlFlowPropertyDeclarations.ts, 139, 26))
|
||||
>hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.d.ts, --, --))
|
||||
>key : Symbol(key, Decl(controlFlowPropertyDeclarations.ts, 142, 12))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,383 @@
|
||||
=== tests/cases/compiler/controlFlowPropertyDeclarations.ts ===
|
||||
// Repro from ##8913
|
||||
|
||||
declare var require:any;
|
||||
>require : any
|
||||
|
||||
var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>require('react/lib/HTMLDOMPropertyConfig') : any
|
||||
>require : any
|
||||
>'react/lib/HTMLDOMPropertyConfig' : string
|
||||
|
||||
// Populate property map with ReactJS's attribute and property mappings
|
||||
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
|
||||
for (var propname in HTMLDOMPropertyConfig.Properties) {
|
||||
>propname : string
|
||||
>HTMLDOMPropertyConfig.Properties : any
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>Properties : any
|
||||
|
||||
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
|
||||
>!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname) : boolean
|
||||
>HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname) : any
|
||||
>HTMLDOMPropertyConfig.Properties.hasOwnProperty : any
|
||||
>HTMLDOMPropertyConfig.Properties : any
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>Properties : any
|
||||
>hasOwnProperty : any
|
||||
>propname : string
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();
|
||||
>mapFrom : any
|
||||
>HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase() : any
|
||||
>HTMLDOMPropertyConfig.DOMAttributeNames[propname] : any
|
||||
>HTMLDOMPropertyConfig.DOMAttributeNames : any
|
||||
>HTMLDOMPropertyConfig : any
|
||||
>DOMAttributeNames : any
|
||||
>propname : string
|
||||
>propname.toLowerCase() : string
|
||||
>propname.toLowerCase : () => string
|
||||
>propname : string
|
||||
>toLowerCase : () => string
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeats a string a certain number of times.
|
||||
* Also: the future is bright and consists of native string repetition:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
|
||||
*
|
||||
* @param {string} string String to repeat
|
||||
* @param {number} times Number of times to repeat string. Integer.
|
||||
* @see http://jsperf.com/string-repeater/2
|
||||
*/
|
||||
function repeatString(string, times) {
|
||||
>repeatString : (string: any, times: any) => any
|
||||
>string : any
|
||||
>times : any
|
||||
|
||||
if (times === 1) {
|
||||
>times === 1 : boolean
|
||||
>times : any
|
||||
>1 : number
|
||||
|
||||
return string;
|
||||
>string : any
|
||||
}
|
||||
if (times < 0) { throw new Error(); }
|
||||
>times < 0 : boolean
|
||||
>times : any
|
||||
>0 : number
|
||||
>new Error() : Error
|
||||
>Error : ErrorConstructor
|
||||
|
||||
var repeated = '';
|
||||
>repeated : string
|
||||
>'' : string
|
||||
|
||||
while (times) {
|
||||
>times : any
|
||||
|
||||
if (times & 1) {
|
||||
>times & 1 : number
|
||||
>times : any
|
||||
>1 : number
|
||||
|
||||
repeated += string;
|
||||
>repeated += string : string
|
||||
>repeated : string
|
||||
>string : any
|
||||
}
|
||||
if (times >>= 1) {
|
||||
>times >>= 1 : number
|
||||
>times : any
|
||||
>1 : number
|
||||
|
||||
string += string;
|
||||
>string += string : any
|
||||
>string : any
|
||||
>string : any
|
||||
}
|
||||
}
|
||||
return repeated;
|
||||
>repeated : string
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the string ends with the specified substring.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {boolean}
|
||||
*/
|
||||
function endsWith(haystack, needle) {
|
||||
>endsWith : (haystack: any, needle: any) => boolean
|
||||
>haystack : any
|
||||
>needle : any
|
||||
|
||||
return haystack.slice(-needle.length) === needle;
|
||||
>haystack.slice(-needle.length) === needle : boolean
|
||||
>haystack.slice(-needle.length) : any
|
||||
>haystack.slice : any
|
||||
>haystack : any
|
||||
>slice : any
|
||||
>-needle.length : number
|
||||
>needle.length : any
|
||||
>needle : any
|
||||
>length : any
|
||||
>needle : any
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the specified substring off the string. If the string does not end
|
||||
* with the specified substring, this is a no-op.
|
||||
*
|
||||
* @param {string} haystack String to search in
|
||||
* @param {string} needle String to search for
|
||||
* @return {string}
|
||||
*/
|
||||
function trimEnd(haystack, needle) {
|
||||
>trimEnd : (haystack: any, needle: any) => any
|
||||
>haystack : any
|
||||
>needle : any
|
||||
|
||||
return endsWith(haystack, needle)
|
||||
>endsWith(haystack, needle) ? haystack.slice(0, -needle.length) : haystack : any
|
||||
>endsWith(haystack, needle) : boolean
|
||||
>endsWith : (haystack: any, needle: any) => boolean
|
||||
>haystack : any
|
||||
>needle : any
|
||||
|
||||
? haystack.slice(0, -needle.length)
|
||||
>haystack.slice(0, -needle.length) : any
|
||||
>haystack.slice : any
|
||||
>haystack : any
|
||||
>slice : any
|
||||
>0 : number
|
||||
>-needle.length : number
|
||||
>needle.length : any
|
||||
>needle : any
|
||||
>length : any
|
||||
|
||||
: haystack;
|
||||
>haystack : any
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hyphenated string to camelCase.
|
||||
*/
|
||||
function hyphenToCamelCase(string) {
|
||||
>hyphenToCamelCase : (string: any) => any
|
||||
>string : any
|
||||
|
||||
return string.replace(/-(.)/g, function(match, chr) {
|
||||
>string.replace(/-(.)/g, function(match, chr) { return chr.toUpperCase(); }) : any
|
||||
>string.replace : any
|
||||
>string : any
|
||||
>replace : any
|
||||
>/-(.)/g : RegExp
|
||||
>function(match, chr) { return chr.toUpperCase(); } : (match: any, chr: any) => any
|
||||
>match : any
|
||||
>chr : any
|
||||
|
||||
return chr.toUpperCase();
|
||||
>chr.toUpperCase() : any
|
||||
>chr.toUpperCase : any
|
||||
>chr : any
|
||||
>toUpperCase : any
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified string consists entirely of whitespace.
|
||||
*/
|
||||
function isEmpty(string) {
|
||||
>isEmpty : (string: any) => boolean
|
||||
>string : any
|
||||
|
||||
return !/[^\s]/.test(string);
|
||||
>!/[^\s]/.test(string) : boolean
|
||||
>/[^\s]/.test(string) : boolean
|
||||
>/[^\s]/.test : (string: string) => boolean
|
||||
>/[^\s]/ : RegExp
|
||||
>test : (string: string) => boolean
|
||||
>string : any
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the CSS value can be converted from a
|
||||
* 'px' suffixed string to a numeric value
|
||||
*
|
||||
* @param {string} value CSS property value
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isConvertiblePixelValue(value) {
|
||||
>isConvertiblePixelValue : (value: any) => boolean
|
||||
>value : any
|
||||
|
||||
return /^\d+px$/.test(value);
|
||||
>/^\d+px$/.test(value) : boolean
|
||||
>/^\d+px$/.test : (string: string) => boolean
|
||||
>/^\d+px$/ : RegExp
|
||||
>test : (string: string) => boolean
|
||||
>value : any
|
||||
}
|
||||
|
||||
export class HTMLtoJSX {
|
||||
>HTMLtoJSX : HTMLtoJSX
|
||||
|
||||
private output: string;
|
||||
>output : string
|
||||
|
||||
private level: number;
|
||||
>level : number
|
||||
|
||||
private _inPreTag: boolean;
|
||||
>_inPreTag : boolean
|
||||
|
||||
|
||||
/**
|
||||
* Handles processing of the specified text node
|
||||
*
|
||||
* @param {TextNode} node
|
||||
*/
|
||||
_visitText = (node) => {
|
||||
>_visitText : (node: any) => void
|
||||
>(node) => { var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase(); if (parentTag === 'textarea' || parentTag === 'style') { // Ignore text content of textareas and styles, as it will have already been moved // to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively. return; } var text = '' if (this._inPreTag) { // If this text is contained within a <pre>, we need to ensure the JSX // whitespace coalescing rules don't eat the whitespace. This means // wrapping newlines and sequences of two or more spaces in variables. text = text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }); } else { // If there's a newline in the text, adjust the indent level if (text.indexOf('\n') > -1) { } } this.output += text; } : (node: any) => void
|
||||
>node : any
|
||||
|
||||
var parentTag = node.parentNode && node.parentNode.tagName.toLowerCase();
|
||||
>parentTag : any
|
||||
>node.parentNode && node.parentNode.tagName.toLowerCase() : any
|
||||
>node.parentNode : any
|
||||
>node : any
|
||||
>parentNode : any
|
||||
>node.parentNode.tagName.toLowerCase() : any
|
||||
>node.parentNode.tagName.toLowerCase : any
|
||||
>node.parentNode.tagName : any
|
||||
>node.parentNode : any
|
||||
>node : any
|
||||
>parentNode : any
|
||||
>tagName : any
|
||||
>toLowerCase : any
|
||||
|
||||
if (parentTag === 'textarea' || parentTag === 'style') {
|
||||
>parentTag === 'textarea' || parentTag === 'style' : boolean
|
||||
>parentTag === 'textarea' : boolean
|
||||
>parentTag : any
|
||||
>'textarea' : string
|
||||
>parentTag === 'style' : boolean
|
||||
>parentTag : any
|
||||
>'style' : string
|
||||
|
||||
// Ignore text content of textareas and styles, as it will have already been moved
|
||||
// to a "defaultValue" attribute and "dangerouslySetInnerHTML" attribute respectively.
|
||||
return;
|
||||
}
|
||||
|
||||
var text = ''
|
||||
>text : string
|
||||
>'' : string
|
||||
|
||||
if (this._inPreTag) {
|
||||
>this._inPreTag : boolean
|
||||
>this : this
|
||||
>_inPreTag : boolean
|
||||
|
||||
// If this text is contained within a <pre>, we need to ensure the JSX
|
||||
// whitespace coalescing rules don't eat the whitespace. This means
|
||||
// wrapping newlines and sequences of two or more spaces in variables.
|
||||
text = text
|
||||
>text = text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }) : string
|
||||
>text : string
|
||||
>text .replace(/\r/g, '') .replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; }) : string
|
||||
>text .replace(/\r/g, '') .replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>text .replace(/\r/g, '') : string
|
||||
>text .replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>text : string
|
||||
|
||||
.replace(/\r/g, '')
|
||||
>replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>/\r/g : RegExp
|
||||
>'' : string
|
||||
|
||||
.replace(/( {2,}|\n|\t|\{|\})/g, function(whitespace) {
|
||||
>replace : { (searchValue: string, replaceValue: string): string; (searchValue: string, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: RegExp, replaceValue: string): string; (searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
|
||||
>/( {2,}|\n|\t|\{|\})/g : RegExp
|
||||
>function(whitespace) { return '{' + JSON.stringify(whitespace) + '}'; } : (whitespace: string) => string
|
||||
>whitespace : string
|
||||
|
||||
return '{' + JSON.stringify(whitespace) + '}';
|
||||
>'{' + JSON.stringify(whitespace) + '}' : string
|
||||
>'{' + JSON.stringify(whitespace) : string
|
||||
>'{' : string
|
||||
>JSON.stringify(whitespace) : string
|
||||
>JSON.stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (number | string)[], space?: string | number): string; }
|
||||
>JSON : JSON
|
||||
>stringify : { (value: any, replacer?: (key: string, value: any) => any, space?: string | number): string; (value: any, replacer?: (number | string)[], space?: string | number): string; }
|
||||
>whitespace : string
|
||||
>'}' : string
|
||||
|
||||
});
|
||||
} else {
|
||||
// If there's a newline in the text, adjust the indent level
|
||||
if (text.indexOf('\n') > -1) {
|
||||
>text.indexOf('\n') > -1 : boolean
|
||||
>text.indexOf('\n') : number
|
||||
>text.indexOf : (searchString: string, position?: number) => number
|
||||
>text : string
|
||||
>indexOf : (searchString: string, position?: number) => number
|
||||
>'\n' : string
|
||||
>-1 : number
|
||||
>1 : number
|
||||
}
|
||||
}
|
||||
this.output += text;
|
||||
>this.output += text : string
|
||||
>this.output : string
|
||||
>this : this
|
||||
>output : string
|
||||
>text : string
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles parsing of inline styles
|
||||
*/
|
||||
export class StyleParser {
|
||||
>StyleParser : StyleParser
|
||||
|
||||
styles = {};
|
||||
>styles : {}
|
||||
>{} : {}
|
||||
|
||||
toJSXString = () => {
|
||||
>toJSXString : () => void
|
||||
>() => { for (var key in this.styles) { if (!this.styles.hasOwnProperty(key)) { } } } : () => void
|
||||
|
||||
for (var key in this.styles) {
|
||||
>key : string
|
||||
>this.styles : {}
|
||||
>this : this
|
||||
>styles : {}
|
||||
|
||||
if (!this.styles.hasOwnProperty(key)) {
|
||||
>!this.styles.hasOwnProperty(key) : boolean
|
||||
>this.styles.hasOwnProperty(key) : boolean
|
||||
>this.styles.hasOwnProperty : (v: string) => boolean
|
||||
>this.styles : {}
|
||||
>this : this
|
||||
>styles : {}
|
||||
>hasOwnProperty : (v: string) => boolean
|
||||
>key : string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
//// [controlFlowPropertyInitializer.ts]
|
||||
|
||||
// Repro from #8967
|
||||
|
||||
const LANG = "Turbo Pascal"
|
||||
|
||||
class BestLanguage {
|
||||
name = LANG;
|
||||
}
|
||||
|
||||
//// [controlFlowPropertyInitializer.js]
|
||||
// Repro from #8967
|
||||
var LANG = "Turbo Pascal";
|
||||
var BestLanguage = (function () {
|
||||
function BestLanguage() {
|
||||
this.name = LANG;
|
||||
}
|
||||
return BestLanguage;
|
||||
}());
|
||||
@@ -0,0 +1,14 @@
|
||||
=== tests/cases/compiler/controlFlowPropertyInitializer.ts ===
|
||||
|
||||
// Repro from #8967
|
||||
|
||||
const LANG = "Turbo Pascal"
|
||||
>LANG : Symbol(LANG, Decl(controlFlowPropertyInitializer.ts, 3, 5))
|
||||
|
||||
class BestLanguage {
|
||||
>BestLanguage : Symbol(BestLanguage, Decl(controlFlowPropertyInitializer.ts, 3, 27))
|
||||
|
||||
name = LANG;
|
||||
>name : Symbol(BestLanguage.name, Decl(controlFlowPropertyInitializer.ts, 5, 20))
|
||||
>LANG : Symbol(LANG, Decl(controlFlowPropertyInitializer.ts, 3, 5))
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
=== tests/cases/compiler/controlFlowPropertyInitializer.ts ===
|
||||
|
||||
// Repro from #8967
|
||||
|
||||
const LANG = "Turbo Pascal"
|
||||
>LANG : string
|
||||
>"Turbo Pascal" : string
|
||||
|
||||
class BestLanguage {
|
||||
>BestLanguage : BestLanguage
|
||||
|
||||
name = LANG;
|
||||
>name : string
|
||||
>LANG : string
|
||||
}
|
||||
@@ -11,7 +11,7 @@ var y = a.x;
|
||||
|
||||
export import b = a;
|
||||
>b : Symbol(b, Decl(declFileForExportedImport_1.ts, 2, 12))
|
||||
>a : Symbol(a, Decl(declFileForExportedImport_0.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(declFileForExportedImport_1.ts, 0, 0))
|
||||
|
||||
var z = b.x;
|
||||
>z : Symbol(z, Decl(declFileForExportedImport_1.ts, 5, 3))
|
||||
|
||||
@@ -17,7 +17,7 @@ import a = m.c;
|
||||
|
||||
import b = a;
|
||||
>b : Symbol(b, Decl(declFileImportChainInExportAssignment.ts, 6, 15))
|
||||
>a : Symbol(a, Decl(declFileImportChainInExportAssignment.ts, 0, 10))
|
||||
>a : Symbol(a, Decl(declFileImportChainInExportAssignment.ts, 5, 1))
|
||||
|
||||
export = b;
|
||||
>b : Symbol(b, Decl(declFileImportChainInExportAssignment.ts, 6, 15))
|
||||
|
||||
@@ -37,7 +37,7 @@ export module M {
|
||||
|
||||
export import d = im;
|
||||
>d : Symbol(d, Decl(declarationEmit_nameConflicts_0.ts, 11, 24))
|
||||
>im : Symbol(d, Decl(declarationEmit_nameConflicts_1.ts, 0, 0))
|
||||
>im : Symbol(im, Decl(declarationEmit_nameConflicts_0.ts, 0, 0))
|
||||
}
|
||||
|
||||
export module M.P {
|
||||
|
||||
@@ -4,7 +4,7 @@ import a = require('A');
|
||||
|
||||
import A = a.A;
|
||||
>A : Symbol(A, Decl(B.ts, 0, 24))
|
||||
>a : Symbol(a, Decl(A.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(B.ts, 0, 0))
|
||||
>A : Symbol(a.A, Decl(A.ts, 0, 0))
|
||||
|
||||
export = A;
|
||||
|
||||
@@ -81,4 +81,14 @@ tests/cases/conformance/types/typeRelationships/comparable/equalityStrictNulls.t
|
||||
!!! error TS2365: Operator '<=' cannot be applied to types 'number' and 'undefined'.
|
||||
}
|
||||
}
|
||||
function f5(x: string) {
|
||||
switch(x) {
|
||||
case null:
|
||||
break;
|
||||
case undefined:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,16 @@ function f4(x: number) {
|
||||
if (x <= undefined) {
|
||||
}
|
||||
}
|
||||
function f5(x: string) {
|
||||
switch(x) {
|
||||
case null:
|
||||
break;
|
||||
case undefined:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [equalityStrictNulls.js]
|
||||
@@ -134,3 +144,13 @@ function f4(x) {
|
||||
if (x <= undefined) {
|
||||
}
|
||||
}
|
||||
function f5(x) {
|
||||
switch (x) {
|
||||
case null:
|
||||
break;
|
||||
case undefined:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//// [server.ts]
|
||||
|
||||
var foo = 2;
|
||||
foo = 3;
|
||||
|
||||
var baz = 3;
|
||||
baz = 4;
|
||||
|
||||
var buzz = 10;
|
||||
buzz += 3;
|
||||
|
||||
var bizz = 8;
|
||||
bizz++; // compiles to exports.bizz = bizz += 1
|
||||
bizz--; // similarly
|
||||
++bizz; // compiles to exports.bizz = ++bizz
|
||||
|
||||
export { foo, baz, baz as quux, buzz, bizz };
|
||||
|
||||
|
||||
//// [server.js]
|
||||
"use strict";
|
||||
var foo = 2;
|
||||
exports.foo = foo;
|
||||
exports.foo = foo = 3;
|
||||
var baz = 3;
|
||||
exports.baz = baz;
|
||||
exports.quux = baz;
|
||||
exports.baz = exports.quux = baz = 4;
|
||||
var buzz = 10;
|
||||
exports.buzz = buzz;
|
||||
exports.buzz = buzz += 3;
|
||||
var bizz = 8;
|
||||
exports.bizz = bizz;
|
||||
exports.bizz = bizz += 1; // compiles to exports.bizz = bizz += 1
|
||||
exports.bizz = bizz -= 1; // similarly
|
||||
exports.bizz = ++bizz; // compiles to exports.bizz = ++bizz
|
||||
@@ -0,0 +1,40 @@
|
||||
=== tests/cases/compiler/server.ts ===
|
||||
|
||||
var foo = 2;
|
||||
>foo : Symbol(foo, Decl(server.ts, 1, 3))
|
||||
|
||||
foo = 3;
|
||||
>foo : Symbol(foo, Decl(server.ts, 1, 3))
|
||||
|
||||
var baz = 3;
|
||||
>baz : Symbol(baz, Decl(server.ts, 4, 3))
|
||||
|
||||
baz = 4;
|
||||
>baz : Symbol(baz, Decl(server.ts, 4, 3))
|
||||
|
||||
var buzz = 10;
|
||||
>buzz : Symbol(buzz, Decl(server.ts, 7, 3))
|
||||
|
||||
buzz += 3;
|
||||
>buzz : Symbol(buzz, Decl(server.ts, 7, 3))
|
||||
|
||||
var bizz = 8;
|
||||
>bizz : Symbol(bizz, Decl(server.ts, 10, 3))
|
||||
|
||||
bizz++; // compiles to exports.bizz = bizz += 1
|
||||
>bizz : Symbol(bizz, Decl(server.ts, 10, 3))
|
||||
|
||||
bizz--; // similarly
|
||||
>bizz : Symbol(bizz, Decl(server.ts, 10, 3))
|
||||
|
||||
++bizz; // compiles to exports.bizz = ++bizz
|
||||
>bizz : Symbol(bizz, Decl(server.ts, 10, 3))
|
||||
|
||||
export { foo, baz, baz as quux, buzz, bizz };
|
||||
>foo : Symbol(foo, Decl(server.ts, 15, 8))
|
||||
>baz : Symbol(baz, Decl(server.ts, 15, 13))
|
||||
>baz : Symbol(quux, Decl(server.ts, 15, 18))
|
||||
>quux : Symbol(quux, Decl(server.ts, 15, 18))
|
||||
>buzz : Symbol(buzz, Decl(server.ts, 15, 31))
|
||||
>bizz : Symbol(bizz, Decl(server.ts, 15, 37))
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
=== tests/cases/compiler/server.ts ===
|
||||
|
||||
var foo = 2;
|
||||
>foo : number
|
||||
>2 : number
|
||||
|
||||
foo = 3;
|
||||
>foo = 3 : number
|
||||
>foo : number
|
||||
>3 : number
|
||||
|
||||
var baz = 3;
|
||||
>baz : number
|
||||
>3 : number
|
||||
|
||||
baz = 4;
|
||||
>baz = 4 : number
|
||||
>baz : number
|
||||
>4 : number
|
||||
|
||||
var buzz = 10;
|
||||
>buzz : number
|
||||
>10 : number
|
||||
|
||||
buzz += 3;
|
||||
>buzz += 3 : number
|
||||
>buzz : number
|
||||
>3 : number
|
||||
|
||||
var bizz = 8;
|
||||
>bizz : number
|
||||
>8 : number
|
||||
|
||||
bizz++; // compiles to exports.bizz = bizz += 1
|
||||
>bizz++ : number
|
||||
>bizz : number
|
||||
|
||||
bizz--; // similarly
|
||||
>bizz-- : number
|
||||
>bizz : number
|
||||
|
||||
++bizz; // compiles to exports.bizz = ++bizz
|
||||
>++bizz : number
|
||||
>bizz : number
|
||||
|
||||
export { foo, baz, baz as quux, buzz, bizz };
|
||||
>foo : number
|
||||
>baz : number
|
||||
>baz : number
|
||||
>quux : number
|
||||
>buzz : number
|
||||
>bizz : number
|
||||
|
||||
@@ -14,7 +14,7 @@ import { a } from "./es6ImportNamedImportInIndirectExportAssignment_0";
|
||||
|
||||
import x = a;
|
||||
>x : Symbol(x, Decl(es6ImportNamedImportInIndirectExportAssignment_1.ts, 0, 71))
|
||||
>a : Symbol(a, Decl(es6ImportNamedImportInIndirectExportAssignment_0.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(es6ImportNamedImportInIndirectExportAssignment_1.ts, 0, 8))
|
||||
|
||||
export = x;
|
||||
>x : Symbol(x, Decl(es6ImportNamedImportInIndirectExportAssignment_1.ts, 0, 71))
|
||||
|
||||
@@ -5,7 +5,7 @@ declare module 'timezonecomplete' {
|
||||
|
||||
export import TimeUnit = basics.TimeUnit;
|
||||
>TimeUnit : Symbol(TimeUnit, Decl(externalModuleReferenceDoubleUnderscore1.ts, 1, 57))
|
||||
>basics : Symbol(basics, Decl(externalModuleReferenceDoubleUnderscore1.ts, 3, 1))
|
||||
>basics : Symbol(basics, Decl(externalModuleReferenceDoubleUnderscore1.ts, 0, 35))
|
||||
>TimeUnit : Symbol(basics.TimeUnit, Decl(externalModuleReferenceDoubleUnderscore1.ts, 5, 44))
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ module m_private {
|
||||
//import r2 = require('m'); // would be error
|
||||
export import C = r; // no error
|
||||
>C : Symbol(C, Decl(importAliasAnExternalModuleInsideAnInternalModule_file1.ts, 1, 18))
|
||||
>r : Symbol(C, Decl(importAliasAnExternalModuleInsideAnInternalModule_file0.ts, 0, 0))
|
||||
>r : Symbol(r, Decl(importAliasAnExternalModuleInsideAnInternalModule_file1.ts, 0, 0))
|
||||
|
||||
C.m.foo();
|
||||
>C.m.foo : Symbol(C.m.foo, Decl(importAliasAnExternalModuleInsideAnInternalModule_file0.ts, 0, 17))
|
||||
|
||||
@@ -4,12 +4,12 @@ import appJs = require("file1");
|
||||
|
||||
import Services = appJs.Services;
|
||||
>Services : Symbol(Services, Decl(file2.ts, 0, 32))
|
||||
>appJs : Symbol(appJs, Decl(file1.ts, 0, 0))
|
||||
>appJs : Symbol(appJs, Decl(file2.ts, 0, 0))
|
||||
>Services : Symbol(appJs.Services, Decl(file1.ts, 0, 12))
|
||||
|
||||
import UserServices = Services.UserServices;
|
||||
>UserServices : Symbol(UserServices, Decl(file2.ts, 1, 33))
|
||||
>Services : Symbol(appJs.Services, Decl(file1.ts, 0, 12))
|
||||
>Services : Symbol(Services, Decl(file2.ts, 0, 32))
|
||||
>UserServices : Symbol(Services.UserServices, Decl(file1.ts, 1, 28))
|
||||
|
||||
var x = new UserServices().getUserName();
|
||||
|
||||
@@ -4,7 +4,7 @@ import appJs = require("file1");
|
||||
|
||||
import Services = appJs.App.Services;
|
||||
>Services : Symbol(Services, Decl(file2.ts, 0, 32))
|
||||
>appJs : Symbol(appJs, Decl(file1.ts, 0, 0))
|
||||
>appJs : Symbol(appJs, Decl(file2.ts, 0, 0))
|
||||
>App : Symbol(appJs.App, Decl(file1.ts, 0, 0))
|
||||
>Services : Symbol(Services, Decl(file1.ts, 0, 19))
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import RT_ALIAS = require("file1");
|
||||
|
||||
import ReferredTo = RT_ALIAS.elaborate.nested.mod.name.ReferredTo;
|
||||
>ReferredTo : Symbol(ReferredTo, Decl(file2.ts, 0, 35))
|
||||
>RT_ALIAS : Symbol(RT_ALIAS, Decl(file1.ts, 0, 0))
|
||||
>RT_ALIAS : Symbol(RT_ALIAS, Decl(file2.ts, 0, 0))
|
||||
>elaborate : Symbol(RT_ALIAS.elaborate, Decl(file1.ts, 0, 0))
|
||||
>nested : Symbol(RT_ALIAS.elaborate.nested, Decl(file1.ts, 0, 24))
|
||||
>mod : Symbol(RT_ALIAS.elaborate.nested.mod, Decl(file1.ts, 0, 31))
|
||||
|
||||
@@ -1,10 +1,44 @@
|
||||
//// [initializersWidened.ts]
|
||||
// these are widened to any at the point of assignment
|
||||
|
||||
var x = null;
|
||||
var y = undefined;
|
||||
var x1 = null;
|
||||
var y1 = undefined;
|
||||
var z1 = void 0;
|
||||
|
||||
// these are not widened
|
||||
|
||||
var x2: null;
|
||||
var y2: undefined;
|
||||
|
||||
var x3: null = null;
|
||||
var y3: undefined = undefined;
|
||||
var z3: undefined = void 0;
|
||||
|
||||
// widen only when all constituents of union are widening
|
||||
|
||||
var x4 = null || null;
|
||||
var y4 = undefined || undefined;
|
||||
var z4 = void 0 || void 0;
|
||||
|
||||
var x5 = null || x2;
|
||||
var y5 = undefined || y2;
|
||||
var z5 = void 0 || y2;
|
||||
|
||||
//// [initializersWidened.js]
|
||||
// these are widened to any at the point of assignment
|
||||
var x = null;
|
||||
var y = undefined;
|
||||
var x1 = null;
|
||||
var y1 = undefined;
|
||||
var z1 = void 0;
|
||||
// these are not widened
|
||||
var x2;
|
||||
var y2;
|
||||
var x3 = null;
|
||||
var y3 = undefined;
|
||||
var z3 = void 0;
|
||||
// widen only when all constituents of union are widening
|
||||
var x4 = null || null;
|
||||
var y4 = undefined || undefined;
|
||||
var z4 = void 0 || void 0;
|
||||
var x5 = null || x2;
|
||||
var y5 = undefined || y2;
|
||||
var z5 = void 0 || y2;
|
||||
|
||||
@@ -1,10 +1,57 @@
|
||||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/initializersWidened.ts ===
|
||||
// these are widened to any at the point of assignment
|
||||
|
||||
var x = null;
|
||||
>x : Symbol(x, Decl(initializersWidened.ts, 2, 3))
|
||||
var x1 = null;
|
||||
>x1 : Symbol(x1, Decl(initializersWidened.ts, 2, 3))
|
||||
|
||||
var y = undefined;
|
||||
>y : Symbol(y, Decl(initializersWidened.ts, 3, 3))
|
||||
var y1 = undefined;
|
||||
>y1 : Symbol(y1, Decl(initializersWidened.ts, 3, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var z1 = void 0;
|
||||
>z1 : Symbol(z1, Decl(initializersWidened.ts, 4, 3))
|
||||
|
||||
// these are not widened
|
||||
|
||||
var x2: null;
|
||||
>x2 : Symbol(x2, Decl(initializersWidened.ts, 8, 3))
|
||||
|
||||
var y2: undefined;
|
||||
>y2 : Symbol(y2, Decl(initializersWidened.ts, 9, 3))
|
||||
|
||||
var x3: null = null;
|
||||
>x3 : Symbol(x3, Decl(initializersWidened.ts, 11, 3))
|
||||
|
||||
var y3: undefined = undefined;
|
||||
>y3 : Symbol(y3, Decl(initializersWidened.ts, 12, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var z3: undefined = void 0;
|
||||
>z3 : Symbol(z3, Decl(initializersWidened.ts, 13, 3))
|
||||
|
||||
// widen only when all constituents of union are widening
|
||||
|
||||
var x4 = null || null;
|
||||
>x4 : Symbol(x4, Decl(initializersWidened.ts, 17, 3))
|
||||
|
||||
var y4 = undefined || undefined;
|
||||
>y4 : Symbol(y4, Decl(initializersWidened.ts, 18, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var z4 = void 0 || void 0;
|
||||
>z4 : Symbol(z4, Decl(initializersWidened.ts, 19, 3))
|
||||
|
||||
var x5 = null || x2;
|
||||
>x5 : Symbol(x5, Decl(initializersWidened.ts, 21, 3))
|
||||
>x2 : Symbol(x2, Decl(initializersWidened.ts, 8, 3))
|
||||
|
||||
var y5 = undefined || y2;
|
||||
>y5 : Symbol(y5, Decl(initializersWidened.ts, 22, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
>y2 : Symbol(y2, Decl(initializersWidened.ts, 9, 3))
|
||||
|
||||
var z5 = void 0 || y2;
|
||||
>z5 : Symbol(z5, Decl(initializersWidened.ts, 23, 3))
|
||||
>y2 : Symbol(y2, Decl(initializersWidened.ts, 9, 3))
|
||||
|
||||
|
||||
@@ -1,11 +1,80 @@
|
||||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/initializersWidened.ts ===
|
||||
// these are widened to any at the point of assignment
|
||||
|
||||
var x = null;
|
||||
>x : any
|
||||
var x1 = null;
|
||||
>x1 : any
|
||||
>null : null
|
||||
|
||||
var y = undefined;
|
||||
>y : any
|
||||
var y1 = undefined;
|
||||
>y1 : any
|
||||
>undefined : undefined
|
||||
|
||||
var z1 = void 0;
|
||||
>z1 : any
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
|
||||
// these are not widened
|
||||
|
||||
var x2: null;
|
||||
>x2 : null
|
||||
>null : null
|
||||
|
||||
var y2: undefined;
|
||||
>y2 : undefined
|
||||
|
||||
var x3: null = null;
|
||||
>x3 : null
|
||||
>null : null
|
||||
>null : null
|
||||
|
||||
var y3: undefined = undefined;
|
||||
>y3 : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var z3: undefined = void 0;
|
||||
>z3 : undefined
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
|
||||
// widen only when all constituents of union are widening
|
||||
|
||||
var x4 = null || null;
|
||||
>x4 : any
|
||||
>null || null : null
|
||||
>null : null
|
||||
>null : null
|
||||
|
||||
var y4 = undefined || undefined;
|
||||
>y4 : any
|
||||
>undefined || undefined : undefined
|
||||
>undefined : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var z4 = void 0 || void 0;
|
||||
>z4 : any
|
||||
>void 0 || void 0 : undefined
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
|
||||
var x5 = null || x2;
|
||||
>x5 : null
|
||||
>null || x2 : null
|
||||
>null : null
|
||||
>x2 : null
|
||||
|
||||
var y5 = undefined || y2;
|
||||
>y5 : undefined
|
||||
>undefined || y2 : undefined
|
||||
>undefined : undefined
|
||||
>y2 : undefined
|
||||
|
||||
var z5 = void 0 || y2;
|
||||
>z5 : undefined
|
||||
>void 0 || y2 : undefined
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
>y2 : undefined
|
||||
|
||||
|
||||
@@ -623,7 +623,7 @@ var rj8 = a8 && undefined;
|
||||
|
||||
var rj9 = null && undefined;
|
||||
>rj9 : any
|
||||
>null && undefined : null
|
||||
>null && undefined : undefined
|
||||
>null : null
|
||||
>undefined : undefined
|
||||
|
||||
|
||||
@@ -1,29 +1,61 @@
|
||||
//// [objectLiteralWidened.ts]
|
||||
// object literal properties are widened to any
|
||||
|
||||
var x = {
|
||||
var x1 = {
|
||||
foo: null,
|
||||
bar: undefined
|
||||
}
|
||||
|
||||
var y = {
|
||||
var y1 = {
|
||||
foo: null,
|
||||
bar: {
|
||||
baz: null,
|
||||
boo: undefined
|
||||
}
|
||||
}
|
||||
|
||||
// these are not widened
|
||||
|
||||
var u: undefined = undefined;
|
||||
var n: null = null;
|
||||
|
||||
var x2 = {
|
||||
foo: n,
|
||||
bar: u
|
||||
}
|
||||
|
||||
var y2 = {
|
||||
foo: n,
|
||||
bar: {
|
||||
baz: n,
|
||||
boo: u
|
||||
}
|
||||
}
|
||||
|
||||
//// [objectLiteralWidened.js]
|
||||
// object literal properties are widened to any
|
||||
var x = {
|
||||
var x1 = {
|
||||
foo: null,
|
||||
bar: undefined
|
||||
};
|
||||
var y = {
|
||||
var y1 = {
|
||||
foo: null,
|
||||
bar: {
|
||||
baz: null,
|
||||
boo: undefined
|
||||
}
|
||||
};
|
||||
// these are not widened
|
||||
var u = undefined;
|
||||
var n = null;
|
||||
var x2 = {
|
||||
foo: n,
|
||||
bar: u
|
||||
};
|
||||
var y2 = {
|
||||
foo: n,
|
||||
bar: {
|
||||
baz: n,
|
||||
boo: u
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/objectLiteralWidened.ts ===
|
||||
// object literal properties are widened to any
|
||||
|
||||
var x = {
|
||||
>x : Symbol(x, Decl(objectLiteralWidened.ts, 2, 3))
|
||||
var x1 = {
|
||||
>x1 : Symbol(x1, Decl(objectLiteralWidened.ts, 2, 3))
|
||||
|
||||
foo: null,
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 2, 9))
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 2, 10))
|
||||
|
||||
bar: undefined
|
||||
>bar : Symbol(bar, Decl(objectLiteralWidened.ts, 3, 14))
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
|
||||
var y = {
|
||||
>y : Symbol(y, Decl(objectLiteralWidened.ts, 7, 3))
|
||||
var y1 = {
|
||||
>y1 : Symbol(y1, Decl(objectLiteralWidened.ts, 7, 3))
|
||||
|
||||
foo: null,
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 7, 9))
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 7, 10))
|
||||
|
||||
bar: {
|
||||
>bar : Symbol(bar, Decl(objectLiteralWidened.ts, 8, 14))
|
||||
@@ -29,3 +29,44 @@ var y = {
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
}
|
||||
|
||||
// these are not widened
|
||||
|
||||
var u: undefined = undefined;
|
||||
>u : Symbol(u, Decl(objectLiteralWidened.ts, 17, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var n: null = null;
|
||||
>n : Symbol(n, Decl(objectLiteralWidened.ts, 18, 3))
|
||||
|
||||
var x2 = {
|
||||
>x2 : Symbol(x2, Decl(objectLiteralWidened.ts, 20, 3))
|
||||
|
||||
foo: n,
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 20, 10))
|
||||
>n : Symbol(n, Decl(objectLiteralWidened.ts, 18, 3))
|
||||
|
||||
bar: u
|
||||
>bar : Symbol(bar, Decl(objectLiteralWidened.ts, 21, 11))
|
||||
>u : Symbol(u, Decl(objectLiteralWidened.ts, 17, 3))
|
||||
}
|
||||
|
||||
var y2 = {
|
||||
>y2 : Symbol(y2, Decl(objectLiteralWidened.ts, 25, 3))
|
||||
|
||||
foo: n,
|
||||
>foo : Symbol(foo, Decl(objectLiteralWidened.ts, 25, 10))
|
||||
>n : Symbol(n, Decl(objectLiteralWidened.ts, 18, 3))
|
||||
|
||||
bar: {
|
||||
>bar : Symbol(bar, Decl(objectLiteralWidened.ts, 26, 11))
|
||||
|
||||
baz: n,
|
||||
>baz : Symbol(baz, Decl(objectLiteralWidened.ts, 27, 10))
|
||||
>n : Symbol(n, Decl(objectLiteralWidened.ts, 18, 3))
|
||||
|
||||
boo: u
|
||||
>boo : Symbol(boo, Decl(objectLiteralWidened.ts, 28, 15))
|
||||
>u : Symbol(u, Decl(objectLiteralWidened.ts, 17, 3))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/objectLiteralWidened.ts ===
|
||||
// object literal properties are widened to any
|
||||
|
||||
var x = {
|
||||
>x : { foo: any; bar: any; }
|
||||
var x1 = {
|
||||
>x1 : { foo: any; bar: any; }
|
||||
>{ foo: null, bar: undefined} : { foo: null; bar: undefined; }
|
||||
|
||||
foo: null,
|
||||
@@ -14,8 +14,8 @@ var x = {
|
||||
>undefined : undefined
|
||||
}
|
||||
|
||||
var y = {
|
||||
>y : { foo: any; bar: { baz: any; boo: any; }; }
|
||||
var y1 = {
|
||||
>y1 : { foo: any; bar: { baz: any; boo: any; }; }
|
||||
>{ foo: null, bar: { baz: null, boo: undefined }} : { foo: null; bar: { baz: null; boo: undefined; }; }
|
||||
|
||||
foo: null,
|
||||
@@ -35,3 +35,49 @@ var y = {
|
||||
>undefined : undefined
|
||||
}
|
||||
}
|
||||
|
||||
// these are not widened
|
||||
|
||||
var u: undefined = undefined;
|
||||
>u : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var n: null = null;
|
||||
>n : null
|
||||
>null : null
|
||||
>null : null
|
||||
|
||||
var x2 = {
|
||||
>x2 : { foo: null; bar: undefined; }
|
||||
>{ foo: n, bar: u} : { foo: null; bar: undefined; }
|
||||
|
||||
foo: n,
|
||||
>foo : null
|
||||
>n : null
|
||||
|
||||
bar: u
|
||||
>bar : undefined
|
||||
>u : undefined
|
||||
}
|
||||
|
||||
var y2 = {
|
||||
>y2 : { foo: null; bar: { baz: null; boo: undefined; }; }
|
||||
>{ foo: n, bar: { baz: n, boo: u }} : { foo: null; bar: { baz: null; boo: undefined; }; }
|
||||
|
||||
foo: n,
|
||||
>foo : null
|
||||
>n : null
|
||||
|
||||
bar: {
|
||||
>bar : { baz: null; boo: undefined; }
|
||||
>{ baz: n, boo: u } : { baz: null; boo: undefined; }
|
||||
|
||||
baz: n,
|
||||
>baz : null
|
||||
>n : null
|
||||
|
||||
boo: u
|
||||
>boo : undefined
|
||||
>u : undefined
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArgumentLists/parserErrorRecovery_ArgumentList5.ts(2,4): error TS2304: Cannot find name 'bar'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArgumentLists/parserErrorRecovery_ArgumentList5.ts(2,8): error TS2304: Cannot find name 'a'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArgumentLists/parserErrorRecovery_ArgumentList5.ts(2,9): error TS1009: Trailing comma not allowed.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArgumentLists/parserErrorRecovery_ArgumentList5.ts (3 errors) ====
|
||||
function foo() {
|
||||
bar(a,)
|
||||
~~~
|
||||
!!! error TS2304: Cannot find name 'bar'.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'a'.
|
||||
~
|
||||
!!! error TS1009: Trailing comma not allowed.
|
||||
return;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
//// [parserErrorRecovery_ArgumentList5.ts]
|
||||
function foo() {
|
||||
bar(a,)
|
||||
return;
|
||||
}
|
||||
|
||||
//// [parserErrorRecovery_ArgumentList5.js]
|
||||
function foo() {
|
||||
bar(a);
|
||||
return;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList3.ts(1,13): error TS1009: Trailing comma not allowed.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ParameterLists/parserErrorRecovery_ParameterList3.ts (1 errors) ====
|
||||
function f(a,) {
|
||||
~
|
||||
!!! error TS1009: Trailing comma not allowed.
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
//// [parserErrorRecovery_ParameterList3.ts]
|
||||
function f(a,) {
|
||||
}
|
||||
|
||||
//// [parserErrorRecovery_ParameterList3.js]
|
||||
function f(a) {
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList12.ts(1,13): error TS1009: Trailing comma not allowed.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList12.ts (1 errors) ====
|
||||
function F(a,) {
|
||||
~
|
||||
!!! error TS1009: Trailing comma not allowed.
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
=== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList12.ts ===
|
||||
function F(a,) {
|
||||
>F : Symbol(F, Decl(parserParameterList12.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(parserParameterList12.ts, 0, 11))
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
=== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList12.ts ===
|
||||
function F(a,) {
|
||||
>F : (a: any) => void
|
||||
>a : any
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction2.ts(1,13): error TS2304: Cannot find name 'b'.
|
||||
tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction2.ts(1,14): error TS1009: Trailing comma not allowed.
|
||||
|
||||
|
||||
==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ArrowFunctions/parserX_ArrowFunction2.ts (2 errors) ====
|
||||
var v = (a: b,) => {
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'b'.
|
||||
~
|
||||
!!! error TS1009: Trailing comma not allowed.
|
||||
|
||||
};
|
||||
@@ -1,8 +0,0 @@
|
||||
//// [parserX_ArrowFunction2.ts]
|
||||
var v = (a: b,) => {
|
||||
|
||||
};
|
||||
|
||||
//// [parserX_ArrowFunction2.js]
|
||||
var v = function (a) {
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
//// [reachabilityCheckWithEmptyDefault.ts]
|
||||
declare function print(s: string): void;
|
||||
function foo(x: any) {
|
||||
switch(x) {
|
||||
case 1: return;
|
||||
default:
|
||||
}
|
||||
print('1');
|
||||
}
|
||||
|
||||
//// [reachabilityCheckWithEmptyDefault.js]
|
||||
function foo(x) {
|
||||
switch (x) {
|
||||
case 1: return;
|
||||
default:
|
||||
}
|
||||
print('1');
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
=== tests/cases/compiler/reachabilityCheckWithEmptyDefault.ts ===
|
||||
declare function print(s: string): void;
|
||||
>print : Symbol(print, Decl(reachabilityCheckWithEmptyDefault.ts, 0, 0))
|
||||
>s : Symbol(s, Decl(reachabilityCheckWithEmptyDefault.ts, 0, 23))
|
||||
|
||||
function foo(x: any) {
|
||||
>foo : Symbol(foo, Decl(reachabilityCheckWithEmptyDefault.ts, 0, 40))
|
||||
>x : Symbol(x, Decl(reachabilityCheckWithEmptyDefault.ts, 1, 13))
|
||||
|
||||
switch(x) {
|
||||
>x : Symbol(x, Decl(reachabilityCheckWithEmptyDefault.ts, 1, 13))
|
||||
|
||||
case 1: return;
|
||||
default:
|
||||
}
|
||||
print('1');
|
||||
>print : Symbol(print, Decl(reachabilityCheckWithEmptyDefault.ts, 0, 0))
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
=== tests/cases/compiler/reachabilityCheckWithEmptyDefault.ts ===
|
||||
declare function print(s: string): void;
|
||||
>print : (s: string) => void
|
||||
>s : string
|
||||
|
||||
function foo(x: any) {
|
||||
>foo : (x: any) => void
|
||||
>x : any
|
||||
|
||||
switch(x) {
|
||||
>x : any
|
||||
|
||||
case 1: return;
|
||||
>1 : number
|
||||
|
||||
default:
|
||||
}
|
||||
print('1');
|
||||
>print('1') : void
|
||||
>print : (s: string) => void
|
||||
>'1' : string
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//// [strictNullChecksNoWidening.ts]
|
||||
|
||||
var a1 = null;
|
||||
var a2 = undefined;
|
||||
var a3 = void 0;
|
||||
|
||||
var b1 = [];
|
||||
var b2 = [,];
|
||||
var b3 = [undefined];
|
||||
var b4 = [[], []];
|
||||
var b5 = [[], [,]];
|
||||
|
||||
declare function f<T>(x: T): T;
|
||||
|
||||
var c1 = f(null);
|
||||
var c2 = f(undefined);
|
||||
var c3 = f([]);
|
||||
|
||||
|
||||
//// [strictNullChecksNoWidening.js]
|
||||
var a1 = null;
|
||||
var a2 = undefined;
|
||||
var a3 = void 0;
|
||||
var b1 = [];
|
||||
var b2 = [,];
|
||||
var b3 = [undefined];
|
||||
var b4 = [[], []];
|
||||
var b5 = [[], [,]];
|
||||
var c1 = f(null);
|
||||
var c2 = f(undefined);
|
||||
var c3 = f([]);
|
||||
@@ -0,0 +1,48 @@
|
||||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/strictNullChecksNoWidening.ts ===
|
||||
|
||||
var a1 = null;
|
||||
>a1 : Symbol(a1, Decl(strictNullChecksNoWidening.ts, 1, 3))
|
||||
|
||||
var a2 = undefined;
|
||||
>a2 : Symbol(a2, Decl(strictNullChecksNoWidening.ts, 2, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var a3 = void 0;
|
||||
>a3 : Symbol(a3, Decl(strictNullChecksNoWidening.ts, 3, 3))
|
||||
|
||||
var b1 = [];
|
||||
>b1 : Symbol(b1, Decl(strictNullChecksNoWidening.ts, 5, 3))
|
||||
|
||||
var b2 = [,];
|
||||
>b2 : Symbol(b2, Decl(strictNullChecksNoWidening.ts, 6, 3))
|
||||
|
||||
var b3 = [undefined];
|
||||
>b3 : Symbol(b3, Decl(strictNullChecksNoWidening.ts, 7, 3))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var b4 = [[], []];
|
||||
>b4 : Symbol(b4, Decl(strictNullChecksNoWidening.ts, 8, 3))
|
||||
|
||||
var b5 = [[], [,]];
|
||||
>b5 : Symbol(b5, Decl(strictNullChecksNoWidening.ts, 9, 3))
|
||||
|
||||
declare function f<T>(x: T): T;
|
||||
>f : Symbol(f, Decl(strictNullChecksNoWidening.ts, 9, 19))
|
||||
>T : Symbol(T, Decl(strictNullChecksNoWidening.ts, 11, 19))
|
||||
>x : Symbol(x, Decl(strictNullChecksNoWidening.ts, 11, 22))
|
||||
>T : Symbol(T, Decl(strictNullChecksNoWidening.ts, 11, 19))
|
||||
>T : Symbol(T, Decl(strictNullChecksNoWidening.ts, 11, 19))
|
||||
|
||||
var c1 = f(null);
|
||||
>c1 : Symbol(c1, Decl(strictNullChecksNoWidening.ts, 13, 3))
|
||||
>f : Symbol(f, Decl(strictNullChecksNoWidening.ts, 9, 19))
|
||||
|
||||
var c2 = f(undefined);
|
||||
>c2 : Symbol(c2, Decl(strictNullChecksNoWidening.ts, 14, 3))
|
||||
>f : Symbol(f, Decl(strictNullChecksNoWidening.ts, 9, 19))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
var c3 = f([]);
|
||||
>c3 : Symbol(c3, Decl(strictNullChecksNoWidening.ts, 15, 3))
|
||||
>f : Symbol(f, Decl(strictNullChecksNoWidening.ts, 9, 19))
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
=== tests/cases/conformance/types/typeRelationships/widenedTypes/strictNullChecksNoWidening.ts ===
|
||||
|
||||
var a1 = null;
|
||||
>a1 : null
|
||||
>null : null
|
||||
|
||||
var a2 = undefined;
|
||||
>a2 : undefined
|
||||
>undefined : undefined
|
||||
|
||||
var a3 = void 0;
|
||||
>a3 : undefined
|
||||
>void 0 : undefined
|
||||
>0 : number
|
||||
|
||||
var b1 = [];
|
||||
>b1 : never[]
|
||||
>[] : never[]
|
||||
|
||||
var b2 = [,];
|
||||
>b2 : undefined[]
|
||||
>[,] : undefined[]
|
||||
> : undefined
|
||||
|
||||
var b3 = [undefined];
|
||||
>b3 : undefined[]
|
||||
>[undefined] : undefined[]
|
||||
>undefined : undefined
|
||||
|
||||
var b4 = [[], []];
|
||||
>b4 : never[][]
|
||||
>[[], []] : never[][]
|
||||
>[] : never[]
|
||||
>[] : never[]
|
||||
|
||||
var b5 = [[], [,]];
|
||||
>b5 : undefined[][]
|
||||
>[[], [,]] : undefined[][]
|
||||
>[] : never[]
|
||||
>[,] : undefined[]
|
||||
> : undefined
|
||||
|
||||
declare function f<T>(x: T): T;
|
||||
>f : <T>(x: T) => T
|
||||
>T : T
|
||||
>x : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
var c1 = f(null);
|
||||
>c1 : null
|
||||
>f(null) : null
|
||||
>f : <T>(x: T) => T
|
||||
>null : null
|
||||
|
||||
var c2 = f(undefined);
|
||||
>c2 : undefined
|
||||
>f(undefined) : undefined
|
||||
>f : <T>(x: T) => T
|
||||
>undefined : undefined
|
||||
|
||||
var c3 = f([]);
|
||||
>c3 : never[]
|
||||
>f([]) : never[]
|
||||
>f : <T>(x: T) => T
|
||||
>[] : never[]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user