Merge branch 'master' into reorderOptions

This commit is contained in:
Mohamed Hegazy
2016-06-08 12:40:26 -07:00
197 changed files with 7222 additions and 1221 deletions
+98 -50
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+3 -3
View File
@@ -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;
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+1
View File
@@ -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) ||
+4 -1
View File
@@ -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) {
+1 -1
View File
@@ -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
View File
@@ -2,7 +2,7 @@
namespace ts {
export type FileWatcherCallback = (fileName: string, removed?: boolean) => void;
export type DirectoryWatcherCallback = (directoryName: string) => void;
export type DirectoryWatcherCallback = (fileName: string) => void;
export interface WatchedFile {
fileName: string;
callback: FileWatcherCallback;
+48 -5
View File
@@ -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
View File
@@ -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;
+11 -3
View File
@@ -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
View File
@@ -746,7 +746,7 @@ namespace FourSlash {
}
const missingItem = { fileName: fileName, start: start, end: end, isWriteAccess: isWriteAccess };
this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${JSON.stringify(missingItem, undefined, 2)} in the returned list: (${JSON.stringify(references, undefined, 2)})`);
this.raiseError(`verifyReferencesAtPositionListContains failed - could not find the item: ${stringify(missingItem)} in the returned list: (${stringify(references)})`);
}
public verifyReferencesCountIs(count: number, localFilesOnly = true) {
@@ -800,7 +800,7 @@ namespace FourSlash {
private testDiagnostics(expected: string, diagnostics: ts.Diagnostic[]) {
const realized = ts.realizeDiagnostics(diagnostics, "\r\n");
const actual = JSON.stringify(realized, undefined, 2);
const actual = stringify(realized);
assert.equal(actual, expected);
}
@@ -875,7 +875,7 @@ namespace FourSlash {
}
if (ranges.length !== references.length) {
this.raiseError("Rename location count does not match result.\n\nExpected: " + JSON.stringify(ranges, undefined, 2) + "\n\nActual:" + JSON.stringify(references, undefined, 2));
this.raiseError("Rename location count does not match result.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + stringify(references));
}
ranges = ranges.sort((r1, r2) => r1.start - r2.start);
@@ -888,7 +888,7 @@ namespace FourSlash {
if (reference.textSpan.start !== range.start ||
ts.textSpanEnd(reference.textSpan) !== range.end) {
this.raiseError("Rename location results do not match.\n\nExpected: " + JSON.stringify(ranges, undefined, 2) + "\n\nActual:" + JSON.stringify(references, undefined, 2));
this.raiseError("Rename location results do not match.\n\nExpected: " + stringify(ranges) + "\n\nActual:" + JSON.stringify(references));
}
}
}
@@ -972,7 +972,7 @@ namespace FourSlash {
}
else {
if (actual) {
this.raiseError(`Expected no signature help, but got "${JSON.stringify(actual, undefined, 2)}"`);
this.raiseError(`Expected no signature help, but got "${stringify(actual)}"`);
}
}
}
@@ -1176,7 +1176,7 @@ namespace FourSlash {
public printCurrentParameterHelp() {
const help = this.languageService.getSignatureHelpItems(this.activeFile.fileName, this.currentCaretPosition);
Harness.IO.log(JSON.stringify(help, undefined, 2));
Harness.IO.log(stringify(help));
}
public printCurrentQuickInfo() {
@@ -1218,7 +1218,7 @@ namespace FourSlash {
public printCurrentSignatureHelp() {
const sigHelp = this.getActiveSignatureHelpItem();
Harness.IO.log(JSON.stringify(sigHelp, undefined, 2));
Harness.IO.log(stringify(sigHelp));
}
public printMemberListMembers() {
@@ -1248,7 +1248,7 @@ namespace FourSlash {
public printReferences() {
const references = this.getReferencesAtCaret();
ts.forEach(references, entry => {
Harness.IO.log(JSON.stringify(entry, undefined, 2));
Harness.IO.log(stringify(entry));
});
}
@@ -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;
+10 -2
View File
@@ -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
View File
@@ -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) => []
};
+1 -7
View File
@@ -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));
+11 -3
View File
@@ -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
View File
@@ -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;
}
+11 -2
View File
@@ -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;
+9 -1
View File
@@ -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]);
}
+10 -2
View File
@@ -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 {
+13 -1
View File
@@ -136,12 +136,24 @@ interface ObjectConstructor {
*/
getOwnPropertyNames(o: any): string[];
/**
* Creates an object that has null prototype.
* @param o Object to use as a prototype. May be null
*/
create(o: null): any;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
*/
create<T>(o: T): T;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
* @param o Object to use as a prototype. May be null
* @param properties JavaScript object that contains one or more property descriptors.
*/
create(o: any, properties?: PropertyDescriptorMap): any;
create(o: any, properties: PropertyDescriptorMap): any;
/**
* Adds a property to an object, or modifies attributes of an existing property.
+1 -1
View File
@@ -459,7 +459,7 @@ namespace ts.server {
kindModifiers: item.kindModifiers || "",
spans: item.spans.map(span => createTextSpanFromBounds(this.lineOffsetToPosition(fileName, span.start), this.lineOffsetToPosition(fileName, span.end))),
childItems: this.decodeNavigationBarItems(item.childItems, fileName),
indent: 0,
indent: item.indent,
bolded: false,
grayed: false
}));
+2 -2
View File
@@ -268,7 +268,7 @@ namespace ts.server {
}
removeRoot(info: ScriptInfo) {
if (!this.filenameToScript.contains(info.path)) {
if (this.filenameToScript.contains(info.path)) {
this.filenameToScript.remove(info.path);
this.roots = copyListRemovingItem(info, this.roots);
this.resolvedModuleNames.remove(info.path);
@@ -1138,7 +1138,7 @@ namespace ts.server {
else {
this.log("No config files found.");
}
return {};
return configFileName ? { configFileName } : {};
}
/**
+5
View File
@@ -1242,6 +1242,11 @@ declare namespace ts.server.protocol {
* Optional children.
*/
childItems?: NavigationBarItem[];
/**
* Number of levels deep this item should appear.
*/
indent: number;
}
export interface NavBarResponse extends Response {
+2 -1
View File
@@ -872,7 +872,8 @@ namespace ts.server {
start: compilerService.host.positionToLineOffset(fileName, span.start),
end: compilerService.host.positionToLineOffset(fileName, ts.textSpanEnd(span))
})),
childItems: this.decorateNavigationBarItem(project, fileName, item.childItems)
childItems: this.decorateNavigationBarItem(project, fileName, item.childItems),
indent: item.indent
}));
}
+9 -9
View File
@@ -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
+6
View File
@@ -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),
+2 -2
View File
@@ -268,9 +268,9 @@ namespace ts.formatting {
return startPos < endPos && current !== SyntaxKind.EndOfFileToken && !isTrivia(current);
}
// when containing node in the tree is token
// when containing node in the tree is token
// but its kind differs from the kind that was returned by the scanner,
// then kind needs to be fixed. This might happen in cases
// then kind needs to be fixed. This might happen in cases
// when parser interprets token differently, i.e keyword treated as identifier
function fixTokenKind(tokenInfo: TokenInfo, container: Node): TokenInfo {
if (isToken(container) && tokenInfo.token.kind !== container.kind) {
+3 -3
View File
@@ -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.
+2 -2
View File
@@ -95,9 +95,9 @@ namespace ts.formatting {
//// 4- Context rules with any token combination
//// 5- Non-context rules with specific token combination
//// 6- Non-context rules with any token combination
////
////
//// The member rulesInsertionIndexBitmap is used to describe the number of rules
//// in each sub-bucket (above) hence can be used to know the index of where to insert
//// in each sub-bucket (above) hence can be used to know the index of where to insert
//// the next rule. It's a bitmap which contains 6 different sections each is given 5 bits.
////
//// Example:
+3 -3
View File
@@ -9,7 +9,7 @@ namespace ts.NavigateTo {
// This means "compare in a case insensitive manner."
const baseSensitivity: Intl.CollatorOptions = { sensitivity: "base" };
// Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
// Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
forEach(program.getSourceFiles(), sourceFile => {
cancellationToken.throwIfCancellationRequested();
@@ -17,7 +17,7 @@ namespace ts.NavigateTo {
for (const name in nameToDeclarations) {
const declarations = getProperty(nameToDeclarations, name);
if (declarations) {
// First do a quick check to see if the name of the declaration matches the
// First do a quick check to see if the name of the declaration matches the
// last portion of the (possibly) dotted name they're searching for.
let matches = patternMatcher.getMatchesForLastSegmentOfPattern(name);
@@ -26,7 +26,7 @@ namespace ts.NavigateTo {
}
for (const declaration of declarations) {
// It was a match! If the pattern has dots in it, then also see if the
// It was a match! If the pattern has dots in it, then also see if the
// declaration container matches as well.
if (patternMatcher.patternContainsDots) {
const containers = getContainers(declaration);
+40 -14
View File
@@ -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
View File
@@ -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);
}
}
}
}
}
+2 -2
View File
@@ -295,7 +295,7 @@ namespace ts {
constructor(private shimHost: LanguageServiceShimHost) {
// if shimHost is a COM object then property check will become method call with no arguments.
// 'in' does not have this effect.
// 'in' does not have this effect.
if ("getModuleResolutionsForFile" in this.shimHost) {
this.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
@@ -966,7 +966,7 @@ namespace ts {
return this.forwardJSONCall(
"getPreProcessedFileInfo('" + fileName + "')",
() => {
// for now treat files as JavaScript
// for now treat files as JavaScript
const result = preProcessFile(sourceTextSnapshot.getText(0, sourceTextSnapshot.getLength()), /* readImportFiles */ true, /* detectJavaScriptImports */ true);
return {
referencedFiles: this.convertFileReferences(result.referencedFiles),
+8 -8
View File
@@ -3,9 +3,9 @@
namespace ts.SignatureHelp {
// A partially written generic type expression is not guaranteed to have the correct syntax tree. the expression could be parsed as less than/greater than expression or a comma expression
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
// or some other combination depending on what the user has typed so far. For the purposes of signature help we need to consider any location after "<" as a possible generic type reference.
// To do this, the method will back parse the expression starting at the position required. it will try to parse the current expression as a generic type expression, if it did succeed it
// will return the generic identifier that started the expression (e.g. "foo" in "foo<any, |"). It is then up to the caller to ensure that this is a valid generic expression through
// looking up the type. The method will also keep track of the parameter index inside the expression.
// public static isInPartiallyWrittenTypeArgumentList(syntaxTree: TypeScript.SyntaxTree, position: number): any {
// let token = Syntax.findTokenOnLeft(syntaxTree.sourceUnit(), position, /*includeSkippedTokens*/ true);
@@ -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
View File
@@ -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