Merge branch 'master' into object-spread

This commit is contained in:
Nathan Shively-Sanders 2016-10-19 09:03:51 -07:00
commit f9fe01a6e3
361 changed files with 10155 additions and 1321 deletions

1
.gitignore vendored
View file

@ -41,6 +41,7 @@ tests/cases/**/*.js.map
scripts/debug.bat
scripts/run.bat
scripts/word2md.js
scripts/buildProtocol.js
scripts/ior.js
scripts/buildProtocol.js
scripts/*.js.map

View file

@ -183,5 +183,3 @@ jake baseline-accept
```
to establish the new baselines as the desired behavior. This will change the files in `tests\baselines\reference`, which should be included as part of your commit. It's important to carefully validate changes in the baselines.
**Note** that `baseline-accept` should only be run after a full test run! Accepting baselines after running a subset of tests will delete baseline files for the tests that didn't run.

View file

@ -70,14 +70,16 @@ var compilerSources = [
"visitor.ts",
"transformers/destructuring.ts",
"transformers/ts.ts",
"transformers/module/es6.ts",
"transformers/module/es2015.ts",
"transformers/module/system.ts",
"transformers/module/module.ts",
"transformers/jsx.ts",
"transformers/experimental.ts",
"transformers/es7.ts",
"transformers/es2017.ts",
"transformers/es2016.ts",
"transformers/es2015.ts",
"transformers/generators.ts",
"transformers/es6.ts",
"transformers/es5.ts",
"transformer.ts",
"sourcemap.ts",
"comments.ts",
@ -105,14 +107,16 @@ var servicesSources = [
"visitor.ts",
"transformers/destructuring.ts",
"transformers/ts.ts",
"transformers/module/es6.ts",
"transformers/module/es2015.ts",
"transformers/module/system.ts",
"transformers/module/module.ts",
"transformers/jsx.ts",
"transformers/experimental.ts",
"transformers/es7.ts",
"transformers/es2017.ts",
"transformers/es2016.ts",
"transformers/es2015.ts",
"transformers/generators.ts",
"transformers/es6.ts",
"transformers/es5.ts",
"transformer.ts",
"sourcemap.ts",
"comments.ts",
@ -355,6 +359,7 @@ function concatenateFiles(destinationFile, sourceFiles) {
if (!fs.existsSync(sourceFiles[i])) {
fail(sourceFiles[i] + " does not exist!");
}
fs.appendFileSync(temp, "\n\n");
fs.appendFileSync(temp, fs.readFileSync(sourceFiles[i]));
}
// Move the file to the final destination
@ -445,6 +450,8 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts
options += " --stripInternal";
}
options += " --target es5";
var cmd = host + " " + compilerPath + " " + options + " ";
cmd = cmd + sources.join(" ");
console.log(cmd + "\n");

View file

@ -2,7 +2,7 @@
<!-- QUESTIONS: This is not a general support forum! Ask Qs at http://stackoverflow.com/questions/tagged/typescript -->
<!-- SUGGESTIONS: See https://github.com/Microsoft/TypeScript-wiki/blob/master/Writing-Good-Design-Proposals.md -->
**TypeScript Version:** 1.8.0 / nightly (2.0.0-dev.201xxxxx)
**TypeScript Version:** 2.0.3 / nightly (2.1.0-dev.201xxxxx)
**Code**

View file

@ -10,6 +10,8 @@ function endsWith(s: string, suffix: string) {
class DeclarationsWalker {
private visitedTypes: ts.Type[] = [];
private text = "";
private removedTypes: ts.Type[] = [];
private constructor(private typeChecker: ts.TypeChecker, private protocolFile: ts.SourceFile) {
}
@ -17,9 +19,18 @@ class DeclarationsWalker {
let text = "declare namespace ts.server.protocol {\n";
var walker = new DeclarationsWalker(typeChecker, protocolFile);
walker.visitTypeNodes(protocolFile);
return walker.text
text = walker.text
? `declare namespace ts.server.protocol {\n${walker.text}}`
: "";
if (walker.removedTypes) {
text += "\ndeclare namespace ts {\n";
text += " // these types are empty stubs for types from services and should not be used directly\n"
for (const type of walker.removedTypes) {
text += ` export type ${type.symbol.name} = never;\n`;
}
text += "}"
}
return text;
}
private processType(type: ts.Type): void {
@ -41,12 +52,18 @@ class DeclarationsWalker {
if (sourceFile === this.protocolFile || path.basename(sourceFile.fileName) === "lib.d.ts") {
return;
}
// splice declaration in final d.ts file
const text = decl.getFullText();
this.text += `${text}\n`;
if (decl.kind === ts.SyntaxKind.EnumDeclaration) {
this.removedTypes.push(type);
return;
}
else {
// splice declaration in final d.ts file
let text = decl.getFullText();
this.text += `${text}\n`;
// recursively pull all dependencies into result dts file
// recursively pull all dependencies into result dts file
this.visitTypeNodes(decl);
this.visitTypeNodes(decl);
}
}
}
}
@ -62,15 +79,37 @@ class DeclarationsWalker {
case ts.SyntaxKind.Parameter:
case ts.SyntaxKind.IndexSignature:
if (((<ts.VariableDeclaration | ts.MethodDeclaration | ts.PropertyDeclaration | ts.ParameterDeclaration | ts.PropertySignature | ts.MethodSignature | ts.IndexSignatureDeclaration>node.parent).type) === node) {
const type = this.typeChecker.getTypeAtLocation(node);
if (type && !(type.flags & ts.TypeFlags.TypeParameter)) {
this.processType(type);
}
this.processTypeOfNode(node);
}
break;
case ts.SyntaxKind.InterfaceDeclaration:
const heritageClauses = (<ts.InterfaceDeclaration>node.parent).heritageClauses;
if (heritageClauses) {
if (heritageClauses[0].token !== ts.SyntaxKind.ExtendsKeyword) {
throw new Error(`Unexpected kind of heritage clause: ${ts.SyntaxKind[heritageClauses[0].kind]}`);
}
for (const type of heritageClauses[0].types) {
this.processTypeOfNode(type);
}
}
break;
}
}
ts.forEachChild(node, n => this.visitTypeNodes(n));
}
private processTypeOfNode(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.UnionType) {
for (const t of (<ts.UnionTypeNode>node).types) {
this.processTypeOfNode(t);
}
}
else {
const type = this.typeChecker.getTypeAtLocation(node);
if (type && !(type.flags & (ts.TypeFlags.TypeParameter))) {
this.processType(type);
}
}
}
}
@ -121,9 +160,12 @@ function generateProtocolFile(protocolTs: string, typeScriptServicesDts: string)
if (extraDeclarations) {
protocolDts += extraDeclarations;
}
protocolDts += "\nimport protocol = ts.server.protocol;";
protocolDts += "\nexport = protocol;";
protocolDts += "\nexport as namespace protocol;";
// do sanity check and try to compile generated text as standalone program
const sanityCheckProgram = getProgramWithProtocolText(protocolDts, /*includeTypeScriptServices*/ false);
const diagnostics = [...program.getSyntacticDiagnostics(), ...program.getSemanticDiagnostics(), ...program.getGlobalDiagnostics()];
const diagnostics = [...sanityCheckProgram.getSyntacticDiagnostics(), ...sanityCheckProgram.getSemanticDiagnostics(), ...sanityCheckProgram.getGlobalDiagnostics()];
if (diagnostics.length) {
const flattenedDiagnostics = diagnostics.map(d => ts.flattenDiagnosticMessageText(d.messageText, "\n")).join("\n");
throw new Error(`Unexpected errors during sanity check: ${flattenedDiagnostics}`);

View file

@ -785,6 +785,15 @@ namespace ts {
};
}
function createFlowArrayMutation(antecedent: FlowNode, node: CallExpression | BinaryExpression): FlowNode {
setFlowNodeReferenced(antecedent);
return <FlowArrayMutation>{
flags: FlowFlags.ArrayMutation,
antecedent,
node
};
}
function finishFlowLabel(flow: FlowLabel): FlowNode {
const antecedents = flow.antecedents;
if (!antecedents) {
@ -975,24 +984,44 @@ namespace ts {
}
function bindTryStatement(node: TryStatement): void {
const postFinallyLabel = createBranchLabel();
const preFinallyLabel = createBranchLabel();
const preTryFlow = currentFlow;
// TODO: Every statement in try block is potentially an exit point!
bind(node.tryBlock);
addAntecedent(postFinallyLabel, currentFlow);
addAntecedent(preFinallyLabel, currentFlow);
const flowAfterTry = currentFlow;
let flowAfterCatch = unreachableFlow;
if (node.catchClause) {
currentFlow = preTryFlow;
bind(node.catchClause);
addAntecedent(postFinallyLabel, currentFlow);
addAntecedent(preFinallyLabel, currentFlow);
flowAfterCatch = currentFlow;
}
if (node.finallyBlock) {
currentFlow = preTryFlow;
// in finally flow is combined from pre-try/flow from try/flow from catch
// pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable
addAntecedent(preFinallyLabel, preTryFlow);
currentFlow = finishFlowLabel(preFinallyLabel);
bind(node.finallyBlock);
// if flow after finally is unreachable - keep it
// otherwise check if flows after try and after catch are unreachable
// if yes - convert current flow to unreachable
// i.e.
// try { return "1" } finally { console.log(1); }
// console.log(2); // this line should be unreachable even if flow falls out of finally block
if (!(currentFlow.flags & FlowFlags.Unreachable)) {
if ((flowAfterTry.flags & FlowFlags.Unreachable) && (flowAfterCatch.flags & FlowFlags.Unreachable)) {
currentFlow = flowAfterTry === reportedUnreachableFlow || flowAfterCatch === reportedUnreachableFlow
? reportedUnreachableFlow
: unreachableFlow;
}
}
}
// if try statement has finally block and flow after finally block is unreachable - keep it
// otherwise use whatever flow was accumulated at postFinallyLabel
if (!node.finallyBlock || !(currentFlow.flags & FlowFlags.Unreachable)) {
currentFlow = finishFlowLabel(postFinallyLabel);
else {
currentFlow = finishFlowLabel(preFinallyLabel);
}
}
@ -1168,6 +1197,12 @@ namespace ts {
forEachChild(node, bind);
if (operator === SyntaxKind.EqualsToken && !isAssignmentTarget(node)) {
bindAssignmentTargetFlow(node.left);
if (node.left.kind === SyntaxKind.ElementAccessExpression) {
const elementAccess = <ElementAccessExpression>node.left;
if (isNarrowableOperand(elementAccess.expression)) {
currentFlow = createFlowArrayMutation(currentFlow, node);
}
}
}
}
}
@ -1228,6 +1263,12 @@ namespace ts {
else {
forEachChild(node, bind);
}
if (node.expression.kind === SyntaxKind.PropertyAccessExpression) {
const propertyAccess = <PropertyAccessExpression>node.expression;
if (isNarrowableOperand(propertyAccess.expression) && isPushOrUnshiftIdentifier(propertyAccess.name)) {
currentFlow = createFlowArrayMutation(currentFlow, node);
}
}
}
function getContainerFlags(node: Node): ContainerFlags {
@ -1667,7 +1708,7 @@ namespace ts {
}
function checkStrictModeFunctionDeclaration(node: FunctionDeclaration) {
if (languageVersion < ScriptTarget.ES6) {
if (languageVersion < ScriptTarget.ES2015) {
// Report error if function is not top level function declaration
if (blockScopeContainer.kind !== SyntaxKind.SourceFile &&
blockScopeContainer.kind !== SyntaxKind.ModuleDeclaration &&
@ -2035,7 +2076,9 @@ namespace ts {
function setCommonJsModuleIndicator(node: Node) {
if (!file.commonJsModuleIndicator) {
file.commonJsModuleIndicator = node;
bindSourceFileAsExternalModule();
if (!file.externalModuleIndicator) {
bindSourceFileAsExternalModule();
}
}
}
@ -2334,6 +2377,9 @@ namespace ts {
case SyntaxKind.CallExpression:
return computeCallExpression(<CallExpression>node, subtreeFlags);
case SyntaxKind.NewExpression:
return computeNewExpression(<NewExpression>node, subtreeFlags);
case SyntaxKind.ModuleDeclaration:
return computeModuleDeclaration(<ModuleDeclaration>node, subtreeFlags);
@ -2411,11 +2457,15 @@ namespace ts {
const expression = node.expression;
const expressionKind = expression.kind;
if (node.typeArguments) {
transformFlags |= TransformFlags.AssertTypeScript;
}
if (subtreeFlags & TransformFlags.ContainsSpreadExpression
|| isSuperOrSuperProperty(expression, expressionKind)) {
// If the this node contains a SpreadExpression, or is a super call, then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@ -2437,6 +2487,21 @@ namespace ts {
return false;
}
function computeNewExpression(node: NewExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
if (node.typeArguments) {
transformFlags |= TransformFlags.AssertTypeScript;
}
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
// If the this node contains a SpreadElementExpression then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES2015;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
}
function computeBinaryExpression(node: BinaryExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const operatorTokenKind = node.operatorToken.kind;
@ -2446,12 +2511,12 @@ namespace ts {
&& (leftKind === SyntaxKind.ObjectLiteralExpression
|| leftKind === SyntaxKind.ArrayLiteralExpression)) {
// Destructuring assignments are ES6 syntax.
transformFlags |= TransformFlags.AssertES6 | TransformFlags.DestructuringAssignment;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.DestructuringAssignment;
}
else if (operatorTokenKind === SyntaxKind.AsteriskAsteriskToken
|| operatorTokenKind === SyntaxKind.AsteriskAsteriskEqualsToken) {
// Exponentiation is ES7 syntax.
transformFlags |= TransformFlags.AssertES7;
// Exponentiation is ES2016 syntax.
transformFlags |= TransformFlags.AssertES2016;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@ -2465,13 +2530,12 @@ namespace ts {
const initializer = node.initializer;
const dotDotDotToken = node.dotDotDotToken;
// If the parameter has a question token, then it is TypeScript syntax.
if (node.questionToken) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// If the parameter's name is 'this', then it is TypeScript syntax.
if (subtreeFlags & TransformFlags.ContainsDecorators || isThisIdentifier(name)) {
// The '?' token, type annotations, decorators, and 'this' parameters are TypeSCript
// syntax.
if (node.questionToken
|| node.type
|| subtreeFlags & TransformFlags.ContainsDecorators
|| isThisIdentifier(name)) {
transformFlags |= TransformFlags.AssertTypeScript;
}
@ -2483,7 +2547,7 @@ namespace ts {
// If a parameter has an initializer, a binding pattern or a dotDotDot token, then
// it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel.
if (subtreeFlags & TransformFlags.ContainsBindingPattern || initializer || dotDotDotToken) {
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsDefaultValueAssignments;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsDefaultValueAssignments;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@ -2524,13 +2588,14 @@ namespace ts {
}
else {
// A ClassDeclaration is ES6 syntax.
transformFlags = subtreeFlags | TransformFlags.AssertES6;
transformFlags = subtreeFlags | TransformFlags.AssertES2015;
// A class with a parameter property assignment, property initializer, or decorator is
// TypeScript syntax.
// An exported declaration may be TypeScript syntax.
if ((subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask)
|| (modifierFlags & ModifierFlags.Export)) {
|| (modifierFlags & ModifierFlags.Export)
|| node.typeParameters) {
transformFlags |= TransformFlags.AssertTypeScript;
}
@ -2547,11 +2612,12 @@ namespace ts {
function computeClassExpression(node: ClassExpression, subtreeFlags: TransformFlags) {
// A ClassExpression is ES6 syntax.
let transformFlags = subtreeFlags | TransformFlags.AssertES6;
let transformFlags = subtreeFlags | TransformFlags.AssertES2015;
// A class with a parameter property assignment, property initializer, or decorator is
// TypeScript syntax.
if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask) {
if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxMask
|| node.typeParameters) {
transformFlags |= TransformFlags.AssertTypeScript;
}
@ -2571,7 +2637,7 @@ namespace ts {
switch (node.token) {
case SyntaxKind.ExtendsKeyword:
// An `extends` HeritageClause is ES6 syntax.
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
break;
case SyntaxKind.ImplementsKeyword:
@ -2591,7 +2657,7 @@ namespace ts {
function computeExpressionWithTypeArguments(node: ExpressionWithTypeArguments, subtreeFlags: TransformFlags) {
// An ExpressionWithTypeArguments is ES6 syntax, as it is used in the
// extends clause of a class.
let transformFlags = subtreeFlags | TransformFlags.AssertES6;
let transformFlags = subtreeFlags | TransformFlags.AssertES2015;
// If an ExpressionWithTypeArguments contains type arguments, then it
// is TypeScript syntax.
@ -2605,10 +2671,10 @@ namespace ts {
function computeConstructor(node: ConstructorDeclaration, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const body = node.body;
if (body === undefined) {
// An overload constructor is TypeScript syntax.
// TypeScript-specific modifiers and overloads are TypeScript syntax
if (hasModifier(node, ModifierFlags.TypeScriptModifier)
|| !node.body) {
transformFlags |= TransformFlags.AssertTypeScript;
}
@ -2618,23 +2684,25 @@ namespace ts {
function computeMethod(node: MethodDeclaration, subtreeFlags: TransformFlags) {
// A MethodDeclaration is ES6 syntax.
let transformFlags = subtreeFlags | TransformFlags.AssertES6;
const modifierFlags = getModifierFlags(node);
const body = node.body;
const typeParameters = node.typeParameters;
const asteriskToken = node.asteriskToken;
let transformFlags = subtreeFlags | TransformFlags.AssertES2015;
// A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
// generic, or has a decorator.
if (!body
|| typeParameters
|| (modifierFlags & (ModifierFlags.Async | ModifierFlags.Abstract))
|| (subtreeFlags & TransformFlags.ContainsDecorators)) {
// Decorators, TypeScript-specific modifiers, type parameters, type annotations, and
// overloads are TypeScript syntax.
if (node.decorators
|| hasModifier(node, ModifierFlags.TypeScriptModifier)
|| node.typeParameters
|| node.type
|| !node.body) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// An async method declaration is ES2017 syntax.
if (hasModifier(node, ModifierFlags.Async)) {
transformFlags |= TransformFlags.AssertES2017;
}
// Currently, we only support generators that were originally async function bodies.
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
transformFlags |= TransformFlags.AssertGenerator;
}
@ -2644,14 +2712,13 @@ namespace ts {
function computeAccessor(node: AccessorDeclaration, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const modifierFlags = getModifierFlags(node);
const body = node.body;
// A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
// generic, or has a decorator.
if (!body
|| (modifierFlags & (ModifierFlags.Async | ModifierFlags.Abstract))
|| (subtreeFlags & TransformFlags.ContainsDecorators)) {
// Decorators, TypeScript-specific modifiers, type annotations, and overloads are
// TypeScript syntax.
if (node.decorators
|| hasModifier(node, ModifierFlags.TypeScriptModifier)
|| node.type
|| !node.body) {
transformFlags |= TransformFlags.AssertTypeScript;
}
@ -2677,7 +2744,6 @@ namespace ts {
let transformFlags: TransformFlags;
const modifierFlags = getModifierFlags(node);
const body = node.body;
const asteriskToken = node.asteriskToken;
if (!body || (modifierFlags & ModifierFlags.Ambient)) {
// An ambient declaration is TypeScript syntax.
@ -2689,19 +2755,27 @@ namespace ts {
// If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax.
if (modifierFlags & ModifierFlags.Export) {
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.AssertES2015;
}
// If a FunctionDeclaration is async, then it is TypeScript syntax.
if (modifierFlags & ModifierFlags.Async) {
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
// syntax.
if (modifierFlags & ModifierFlags.TypeScriptModifier
|| node.typeParameters
|| node.type) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// An async function declaration is ES2017 syntax.
if (modifierFlags & ModifierFlags.Async) {
transformFlags |= TransformFlags.AssertES2017;
}
// If a FunctionDeclaration's subtree has marked the container as needing to capture the
// lexical this, or the function contains parameters with initializers, then this node is
// ES6 syntax.
if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) {
transformFlags |= TransformFlags.AssertES6;
if (subtreeFlags & TransformFlags.ES2015FunctionSyntaxMask) {
transformFlags |= TransformFlags.AssertES2015;
}
// If a FunctionDeclaration is generator function and is the body of a
@ -2709,7 +2783,7 @@ namespace ts {
// down-level generator.
// Currently we do not support transforming any other generator fucntions
// down level.
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
transformFlags |= TransformFlags.AssertGenerator;
}
}
@ -2720,19 +2794,25 @@ namespace ts {
function computeFunctionExpression(node: FunctionExpression, subtreeFlags: TransformFlags) {
let transformFlags = subtreeFlags;
const modifierFlags = getModifierFlags(node);
const asteriskToken = node.asteriskToken;
// An async function expression is TypeScript syntax.
if (modifierFlags & ModifierFlags.Async) {
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
// syntax.
if (hasModifier(node, ModifierFlags.TypeScriptModifier)
|| node.typeParameters
|| node.type) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// An async function expression is ES2017 syntax.
if (hasModifier(node, ModifierFlags.Async)) {
transformFlags |= TransformFlags.AssertES2017;
}
// If a FunctionExpression's subtree has marked the container as needing to capture the
// lexical this, or the function contains parameters with initializers, then this node is
// ES6 syntax.
if (subtreeFlags & TransformFlags.ES6FunctionSyntaxMask) {
transformFlags |= TransformFlags.AssertES6;
if (subtreeFlags & TransformFlags.ES2015FunctionSyntaxMask) {
transformFlags |= TransformFlags.AssertES2015;
}
// If a FunctionExpression is generator function and is the body of a
@ -2740,7 +2820,7 @@ namespace ts {
// down-level generator.
// Currently we do not support transforming any other generator fucntions
// down level.
if (asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
transformFlags |= TransformFlags.AssertGenerator;
}
@ -2750,14 +2830,21 @@ namespace ts {
function computeArrowFunction(node: ArrowFunction, subtreeFlags: TransformFlags) {
// An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction.
let transformFlags = subtreeFlags | TransformFlags.AssertES6;
const modifierFlags = getModifierFlags(node);
let transformFlags = subtreeFlags | TransformFlags.AssertES2015;
// An async arrow function is TypeScript syntax.
if (modifierFlags & ModifierFlags.Async) {
// TypeScript-specific modifiers, type parameters, and type annotations are TypeScript
// syntax.
if (hasModifier(node, ModifierFlags.TypeScriptModifier)
|| node.typeParameters
|| node.type) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// An async arrow function is ES2017 syntax.
if (hasModifier(node, ModifierFlags.Async)) {
transformFlags |= TransformFlags.AssertES2017;
}
// If an ArrowFunction contains a lexical this, its container must capture the lexical this.
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
@ -2788,7 +2875,12 @@ namespace ts {
// A VariableDeclaration with a binding pattern is ES6 syntax.
if (nameKind === SyntaxKind.ObjectBindingPattern || nameKind === SyntaxKind.ArrayBindingPattern) {
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsBindingPattern;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
}
// Type annotations are TypeScript syntax.
if (node.type) {
transformFlags |= TransformFlags.AssertTypeScript;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@ -2809,11 +2901,11 @@ namespace ts {
// If a VariableStatement is exported, then it is either ES6 or TypeScript syntax.
if (modifierFlags & ModifierFlags.Export) {
transformFlags |= TransformFlags.AssertES6 | TransformFlags.AssertTypeScript;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.AssertTypeScript;
}
if (declarationListTransformFlags & TransformFlags.ContainsBindingPattern) {
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
}
}
@ -2827,7 +2919,7 @@ namespace ts {
// A labeled statement containing a block scoped binding *may* need to be transformed from ES6.
if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding
&& isIterationStatement(node, /*lookInLabeledStatements*/ true)) {
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@ -2853,7 +2945,7 @@ namespace ts {
// then we treat the statement as ES6 so that we can indicate that we do not
// need to hold on to the right-hand side.
if (node.expression.transformFlags & TransformFlags.DestructuringAssignment) {
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@ -2876,12 +2968,12 @@ namespace ts {
let transformFlags = subtreeFlags | TransformFlags.ContainsHoistedDeclarationOrCompletion;
if (subtreeFlags & TransformFlags.ContainsBindingPattern) {
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
}
// If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax.
if (node.flags & NodeFlags.BlockScoped) {
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsBlockScopedBinding;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBlockScopedBinding;
}
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@ -2894,14 +2986,18 @@ namespace ts {
let excludeFlags = TransformFlags.NodeExcludes;
switch (kind) {
case SyntaxKind.AsyncKeyword:
case SyntaxKind.AwaitExpression:
// async/await is ES2017 syntax
transformFlags |= TransformFlags.AssertES2017;
break;
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.AbstractKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.AsyncKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.AwaitExpression:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumMember:
case SyntaxKind.TypeAssertionExpression:
@ -2926,7 +3022,7 @@ namespace ts {
case SyntaxKind.ExportKeyword:
// This node is both ES6 and TypeScript syntax.
transformFlags |= TransformFlags.AssertES6 | TransformFlags.AssertTypeScript;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.AssertTypeScript;
break;
case SyntaxKind.DefaultKeyword:
@ -2939,12 +3035,12 @@ namespace ts {
case SyntaxKind.ShorthandPropertyAssignment:
case SyntaxKind.ForOfStatement:
// These nodes are ES6 syntax.
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
break;
case SyntaxKind.YieldExpression:
// This node is ES6 syntax.
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsYield;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsYield;
break;
case SyntaxKind.AnyKeyword:
@ -3006,7 +3102,7 @@ namespace ts {
case SyntaxKind.SuperKeyword:
// This node is ES6 syntax.
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
break;
case SyntaxKind.ThisKeyword:
@ -3017,7 +3113,7 @@ namespace ts {
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
// These nodes are ES6 syntax.
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsBindingPattern;
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsBindingPattern;
break;
case SyntaxKind.Decorator:
@ -3030,7 +3126,7 @@ namespace ts {
if (subtreeFlags & TransformFlags.ContainsComputedPropertyName) {
// If an ObjectLiteralExpression contains a ComputedPropertyName, then it
// is an ES6 node.
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
}
if (subtreeFlags & TransformFlags.ContainsLexicalThisInComputedPropertyName) {
@ -3053,7 +3149,7 @@ namespace ts {
if (subtreeFlags & TransformFlags.ContainsSpreadExpression) {
// If the this node contains a SpreadExpression, then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
}
break;
@ -3064,14 +3160,14 @@ namespace ts {
case SyntaxKind.ForInStatement:
// A loop containing a block scoped binding *may* need to be transformed from ES6.
if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding) {
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
}
break;
case SyntaxKind.SourceFile:
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) {
transformFlags |= TransformFlags.AssertES6;
transformFlags |= TransformFlags.AssertES2015;
}
break;

View file

@ -116,6 +116,7 @@ namespace ts {
const spreadTypes = createMap<SpreadType>();
const stringLiteralTypes = createMap<LiteralType>();
const numericLiteralTypes = createMap<LiteralType>();
const evolvingArrayTypes: AnonymousType[] = [];
const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown");
const resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__");
@ -177,6 +178,7 @@ namespace ts {
let globalBooleanType: ObjectType;
let globalRegExpType: ObjectType;
let anyArrayType: Type;
let autoArrayType: Type;
let anyReadonlyArrayType: Type;
// The library files are only loaded when the feature is used.
@ -367,7 +369,7 @@ namespace ts {
return emitResolver;
}
function error(location: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): void {
function error(location: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): void {
const diagnostic = location
? createDiagnosticForNode(location, message, arg0, arg1, arg2)
: createCompilerDiagnostic(message, arg0, arg1, arg2);
@ -1053,7 +1055,7 @@ namespace ts {
if (node.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
return resolveExternalModuleSymbol(resolveExternalModuleName(node, getExternalModuleImportEqualsDeclarationExpression(node)));
}
return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>node.moduleReference, node);
return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>node.moduleReference);
}
function getTargetOfImportClause(node: ImportClause): Symbol {
@ -1266,7 +1268,7 @@ namespace ts {
}
// This function is only for imports with entity names
function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, importDeclaration: ImportEqualsDeclaration, dontResolveAlias?: boolean): Symbol {
function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, dontResolveAlias?: boolean): Symbol {
// There are three things we might try to look for. In the following examples,
// the search term is enclosed in |...|:
//
@ -2204,7 +2206,7 @@ namespace ts {
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
}
else if (type.flags & TypeFlags.Spread) {
writeSpreadType(<SpreadType>type, nextFlags);
writeSpreadType(<SpreadType>type);
}
else if (type.flags & TypeFlags.Anonymous) {
writeAnonymousType(<ObjectType>type, nextFlags);
@ -2310,7 +2312,7 @@ namespace ts {
}
}
function writeSpreadType(type: SpreadType, flags: TypeFormatFlags) {
function writeSpreadType(type: SpreadType) {
writePunctuation(writer, SyntaxKind.OpenBraceToken);
writer.writeLine();
writer.increaseIndent();
@ -2629,7 +2631,7 @@ namespace ts {
}
}
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node) {
if (typeParameters && typeParameters.length) {
writePunctuation(writer, SyntaxKind.LessThanToken);
let flags = TypeFormatFlags.InFirstTypeArgument;
@ -3109,9 +3111,14 @@ namespace ts {
return undefined;
}
function isAutoVariableInitializer(initializer: Expression) {
const expr = initializer && skipParentheses(initializer);
return !expr || expr.kind === SyntaxKind.NullKeyword || expr.kind === SyntaxKind.Identifier && getResolvedSymbol(<Identifier>expr) === undefinedSymbol;
function isNullOrUndefined(node: Expression) {
const expr = skipParentheses(node);
return expr.kind === SyntaxKind.NullKeyword || expr.kind === SyntaxKind.Identifier && getResolvedSymbol(<Identifier>expr) === undefinedSymbol;
}
function isEmptyArrayLiteral(node: Expression) {
const expr = skipParentheses(node);
return expr.kind === SyntaxKind.ArrayLiteralExpression && (<ArrayLiteralExpression>expr).elements.length === 0;
}
function addOptionality(type: Type, optional: boolean): Type {
@ -3152,12 +3159,18 @@ namespace ts {
return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ declaration.questionToken && includeOptionality);
}
// Use control flow type inference for non-ambient, non-exported var or let variables with no initializer
// or a 'null' or 'undefined' initializer.
if (declaration.kind === SyntaxKind.VariableDeclaration && !isBindingPattern(declaration.name) &&
!(getCombinedNodeFlags(declaration) & NodeFlags.Const) && !(getCombinedModifierFlags(declaration) & ModifierFlags.Export) &&
!isInAmbientContext(declaration) && isAutoVariableInitializer(declaration.initializer)) {
return autoType;
!(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !isInAmbientContext(declaration)) {
// Use control flow tracked 'any' type for non-ambient, non-exported var or let variables with no
// initializer or a 'null' or 'undefined' initializer.
if (!(getCombinedNodeFlags(declaration) & NodeFlags.Const) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) {
return autoType;
}
// Use control flow tracked 'any[]' type for non-ambient, non-exported variables with an empty array
// literal initializer.
if (declaration.initializer && isEmptyArrayLiteral(declaration.initializer)) {
return autoArrayType;
}
}
if (declaration.kind === SyntaxKind.Parameter) {
@ -3179,8 +3192,7 @@ namespace ts {
// Use contextual parameter type if one is available
let type: Type;
if (declaration.symbol.name === "this") {
const thisParameter = getContextualThisParameter(func);
type = thisParameter ? getTypeOfSymbol(thisParameter) : undefined;
type = getContextualThisParameterType(func);
}
else {
type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
@ -3260,7 +3272,7 @@ namespace ts {
const elements = pattern.elements;
const lastElement = lastOrUndefined(elements);
if (elements.length === 0 || (!isOmittedExpression(lastElement) && lastElement.dotDotDotToken)) {
return languageVersion >= ScriptTarget.ES6 ? createIterableType(anyType) : anyArrayType;
return languageVersion >= ScriptTarget.ES2015 ? createIterableType(anyType) : anyArrayType;
}
// If the pattern has at least one element, and no rest element, then it should imply a tuple type.
const elementTypes = map(elements, e => isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors));
@ -4856,9 +4868,6 @@ namespace ts {
if (isJSConstructSignature) {
minArgumentCount--;
}
if (!thisParameter && isObjectLiteralMethod(declaration)) {
thisParameter = getContextualThisParameter(declaration);
}
const classType = declaration.kind === SyntaxKind.Constructor ?
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
@ -4866,7 +4875,7 @@ namespace ts {
const typeParameters = classType ? classType.localTypeParameters :
declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) :
getTypeParametersFromJSDocTemplate(declaration);
const returnType = getSignatureReturnTypeFromDeclaration(declaration, minArgumentCount, isJSConstructSignature, classType);
const returnType = getSignatureReturnTypeFromDeclaration(declaration, isJSConstructSignature, classType);
const typePredicate = declaration.type && declaration.type.kind === SyntaxKind.TypePredicate ?
createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode) :
undefined;
@ -4876,7 +4885,7 @@ namespace ts {
return links.resolvedSignature;
}
function getSignatureReturnTypeFromDeclaration(declaration: SignatureDeclaration, minArgumentCount: number, isJSConstructSignature: boolean, classType: Type) {
function getSignatureReturnTypeFromDeclaration(declaration: SignatureDeclaration, isJSConstructSignature: boolean, classType: Type) {
if (isJSConstructSignature) {
return getTypeFromTypeNode(declaration.parameters[0].type);
}
@ -5241,10 +5250,7 @@ namespace ts {
return undefined;
}
function resolveTypeReferenceName(
node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference,
typeReferenceName: EntityNameExpression | EntityName) {
function resolveTypeReferenceName(typeReferenceName: EntityNameExpression | EntityName) {
if (!typeReferenceName) {
return unknownSymbol;
}
@ -5282,7 +5288,7 @@ namespace ts {
let type: Type;
if (node.kind === SyntaxKind.JSDocTypeReference) {
const typeReferenceName = getTypeReferenceName(node);
symbol = resolveTypeReferenceName(node, typeReferenceName);
symbol = resolveTypeReferenceName(typeReferenceName);
type = getTypeReferenceType(node, symbol);
}
else {
@ -6353,9 +6359,24 @@ namespace ts {
}
function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) {
const areAllParametersUntyped = !forEach(node.parameters, p => p.type);
const isNullaryArrow = node.kind === SyntaxKind.ArrowFunction && !node.parameters.length;
return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow;
// Functions with type parameters are not context sensitive.
if (node.typeParameters) {
return false;
}
// Functions with any parameters that lack type annotations are context sensitive.
if (forEach(node.parameters, p => !p.type)) {
return true;
}
// For arrow functions we now know we're not context sensitive.
if (node.kind === SyntaxKind.ArrowFunction) {
return false;
}
// If the first parameter is not an explicit 'this' parameter, then the function has
// an implicit 'this' parameter which is subject to contextual typing. Otherwise we
// know that all parameters (including 'this') have type annotations and nothing is
// subject to contextual typing.
const parameter = firstOrUndefined(node.parameters);
return !(parameter && parameterIsThisKeyword(parameter));
}
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration {
@ -6961,8 +6982,8 @@ namespace ts {
}
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target, /*reportErrors*/ false)) {
if (result &= eachTypeRelatedToSomeType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source, /*reportErrors*/ false)) {
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target)) {
if (result &= eachTypeRelatedToSomeType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source)) {
return result;
}
}
@ -7023,7 +7044,7 @@ namespace ts {
return false;
}
function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary {
let result = Ternary.True;
const sourceTypes = source.types;
for (const sourceType of sourceTypes) {
@ -7735,7 +7756,7 @@ namespace ts {
type.flags & TypeFlags.NumberLiteral ? numberType :
type.flags & TypeFlags.BooleanLiteral ? booleanType :
type.flags & TypeFlags.EnumLiteral ? (<EnumLiteralType>type).baseType :
type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(map((<UnionType>type).types, getBaseTypeOfLiteralType)) :
type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(sameMap((<UnionType>type).types, getBaseTypeOfLiteralType)) :
type;
}
@ -7744,7 +7765,7 @@ namespace ts {
type.flags & TypeFlags.NumberLiteral && type.flags & TypeFlags.FreshLiteral ? numberType :
type.flags & TypeFlags.BooleanLiteral ? booleanType :
type.flags & TypeFlags.EnumLiteral ? (<EnumLiteralType>type).baseType :
type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(map((<UnionType>type).types, getWidenedLiteralType)) :
type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Enum) ? getUnionType(sameMap((<UnionType>type).types, getWidenedLiteralType)) :
type;
}
@ -7883,10 +7904,10 @@ namespace ts {
return getWidenedTypeOfObjectLiteral(type);
}
if (type.flags & TypeFlags.Union) {
return getUnionType(map((<UnionType>type).types, getWidenedConstituentType));
return getUnionType(sameMap((<UnionType>type).types, getWidenedConstituentType));
}
if (isArrayType(type) || isTupleType(type)) {
return createTypeReference((<TypeReference>type).target, map((<TypeReference>type).typeArguments, getWidenedType));
return createTypeReference((<TypeReference>type).target, sameMap((<TypeReference>type).typeArguments, getWidenedType));
}
}
return type;
@ -8346,7 +8367,7 @@ namespace ts {
const widenLiteralTypes = context.inferences[index].topLevel &&
!hasPrimitiveConstraint(signature.typeParameters[index]) &&
(context.inferences[index].isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), signature.typeParameters[index]));
const baseInferences = widenLiteralTypes ? map(inferences, getWidenedLiteralType) : inferences;
const baseInferences = widenLiteralTypes ? sameMap(inferences, getWidenedLiteralType) : inferences;
// Infer widened union or supertype, or the unknown type for no common supertype
const unionOrSuperType = context.inferUnionTypes ? getUnionType(baseInferences, /*subtypeReduction*/ true) : getCommonSupertype(baseInferences);
inferredType = unionOrSuperType ? getWidenedType(unionOrSuperType) : unknownType;
@ -8749,6 +8770,13 @@ namespace ts {
getAssignedType(<Expression>node);
}
function isEmptyArrayAssignment(node: VariableDeclaration | BindingElement | Expression) {
return node.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>node).initializer &&
isEmptyArrayLiteral((<VariableDeclaration>node).initializer) ||
node.kind !== SyntaxKind.BindingElement && node.parent.kind === SyntaxKind.BinaryExpression &&
isEmptyArrayLiteral((<BinaryExpression>node.parent).right);
}
function getReferenceCandidate(node: Expression): Expression {
switch (node.kind) {
case SyntaxKind.ParenthesizedExpression:
@ -8764,6 +8792,14 @@ namespace ts {
return node;
}
function getReferenceRoot(node: Node): Node {
const parent = node.parent;
return parent.kind === SyntaxKind.ParenthesizedExpression ||
parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).operatorToken.kind === SyntaxKind.EqualsToken && (<BinaryExpression>parent).left === node ||
parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).operatorToken.kind === SyntaxKind.CommaToken && (<BinaryExpression>parent).right === node ?
getReferenceRoot(parent) : node;
}
function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) {
if (clause.kind === SyntaxKind.CaseClause) {
const caseType = getRegularTypeOfLiteralType(checkExpression((<CaseClause>clause).expression));
@ -8849,21 +8885,113 @@ namespace ts {
return incomplete ? { flags: 0, type } : type;
}
// An evolving array type tracks the element types that have so far been seen in an
// 'x.push(value)' or 'x[n] = value' operation along the control flow graph. Evolving
// array types are ultimately converted into manifest array types (using getFinalArrayType)
// and never escape the getFlowTypeOfReference function.
function createEvolvingArrayType(elementType: Type): AnonymousType {
const result = <AnonymousType>createObjectType(TypeFlags.Anonymous);
result.elementType = elementType;
return result;
}
function getEvolvingArrayType(elementType: Type): AnonymousType {
return evolvingArrayTypes[elementType.id] || (evolvingArrayTypes[elementType.id] = createEvolvingArrayType(elementType));
}
// When adding evolving array element types we do not perform subtype reduction. Instead,
// we defer subtype reduction until the evolving array type is finalized into a manifest
// array type.
function addEvolvingArrayElementType(evolvingArrayType: AnonymousType, node: Expression): AnonymousType {
const elementType = getBaseTypeOfLiteralType(checkExpression(node));
return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType]));
}
function isEvolvingArrayType(type: Type) {
return !!(type.flags & TypeFlags.Anonymous && (<AnonymousType>type).elementType);
}
function createFinalArrayType(elementType: Type) {
return elementType.flags & TypeFlags.Never ?
autoArrayType :
createArrayType(elementType.flags & TypeFlags.Union ?
getUnionType((<UnionType>elementType).types, /*subtypeReduction*/ true) :
elementType);
}
// We perform subtype reduction upon obtaining the final array type from an evolving array type.
function getFinalArrayType(evolvingArrayType: AnonymousType): Type {
return evolvingArrayType.finalArrayType || (evolvingArrayType.finalArrayType = createFinalArrayType(evolvingArrayType.elementType));
}
function finalizeEvolvingArrayType(type: Type): Type {
return isEvolvingArrayType(type) ? getFinalArrayType(<AnonymousType>type) : type;
}
function getElementTypeOfEvolvingArrayType(type: Type) {
return isEvolvingArrayType(type) ? (<AnonymousType>type).elementType : neverType;
}
function isEvolvingArrayTypeList(types: Type[]) {
let hasEvolvingArrayType = false;
for (const t of types) {
if (!(t.flags & TypeFlags.Never)) {
if (!isEvolvingArrayType(t)) {
return false;
}
hasEvolvingArrayType = true;
}
}
return hasEvolvingArrayType;
}
// At flow control branch or loop junctions, if the type along every antecedent code path
// is an evolving array type, we construct a combined evolving array type. Otherwise we
// finalize all evolving array types.
function getUnionOrEvolvingArrayType(types: Type[], subtypeReduction: boolean) {
return isEvolvingArrayTypeList(types) ?
getEvolvingArrayType(getUnionType(map(types, getElementTypeOfEvolvingArrayType))) :
getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction);
}
// Return true if the given node is 'x' in an 'x.length', x.push(value)', 'x.unshift(value)' or
// 'x[n] = value' operation, where 'n' is an expression of type any, undefined, or a number-like type.
function isEvolvingArrayOperationTarget(node: Node) {
const root = getReferenceRoot(node);
const parent = root.parent;
const isLengthPushOrUnshift = parent.kind === SyntaxKind.PropertyAccessExpression && (
(<PropertyAccessExpression>parent).name.text === "length" ||
parent.parent.kind === SyntaxKind.CallExpression && isPushOrUnshiftIdentifier((<PropertyAccessExpression>parent).name));
const isElementAssignment = parent.kind === SyntaxKind.ElementAccessExpression &&
(<ElementAccessExpression>parent).expression === root &&
parent.parent.kind === SyntaxKind.BinaryExpression &&
(<BinaryExpression>parent.parent).operatorToken.kind === SyntaxKind.EqualsToken &&
(<BinaryExpression>parent.parent).left === parent &&
!isAssignmentTarget(parent.parent) &&
isTypeAnyOrAllConstituentTypesHaveKind(checkExpression((<ElementAccessExpression>parent).argumentExpression), TypeFlags.NumberLike | TypeFlags.Undefined);
return isLengthPushOrUnshift || isElementAssignment;
}
function getFlowTypeOfReference(reference: Node, declaredType: Type, assumeInitialized: boolean, flowContainer: Node) {
let key: string;
if (!reference.flowNode || assumeInitialized && !(declaredType.flags & TypeFlags.Narrowable)) {
return declaredType;
}
const initialType = assumeInitialized ? declaredType :
declaredType === autoType ? undefinedType :
declaredType === autoType || declaredType === autoArrayType ? undefinedType :
includeFalsyTypes(declaredType, TypeFlags.Undefined);
const visitedFlowStart = visitedFlowCount;
const result = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode));
const evolvedType = getTypeFromFlowType(getTypeAtFlowNode(reference.flowNode));
visitedFlowCount = visitedFlowStart;
if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
// When the reference is 'x' in an 'x.length', 'x.push(value)', 'x.unshift(value)' or x[n] = value' operation,
// we give type 'any[]' to 'x' instead of using the type determined by control flow analysis such that operations
// on empty arrays are possible without implicit any errors and new element types can be inferred without
// type mismatch errors.
const resultType = isEvolvingArrayType(evolvedType) && isEvolvingArrayOperationTarget(reference) ? anyArrayType : finalizeEvolvingArrayType(evolvedType);
if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
return declaredType;
}
return result;
return resultType;
function getTypeAtFlowNode(flow: FlowNode): FlowType {
while (true) {
@ -8900,6 +9028,13 @@ namespace ts {
getTypeAtFlowBranchLabel(<FlowLabel>flow) :
getTypeAtFlowLoopLabel(<FlowLabel>flow);
}
else if (flow.flags & FlowFlags.ArrayMutation) {
type = getTypeAtFlowArrayMutation(<FlowArrayMutation>flow);
if (!type) {
flow = (<FlowArrayMutation>flow).antecedent;
continue;
}
}
else if (flow.flags & FlowFlags.Start) {
// Check if we should continue with the control flow of the containing function.
const container = (<FlowStart>flow).container;
@ -8912,8 +9047,8 @@ namespace ts {
}
else {
// Unreachable code errors are reported in the binding phase. Here we
// simply return the declared type to reduce follow-on errors.
type = declaredType;
// simply return the non-auto declared type to reduce follow-on errors.
type = convertAutoToAny(declaredType);
}
if (flow.flags & FlowFlags.Shared) {
// Record visited node and the associated type in the cache.
@ -8934,9 +9069,17 @@ namespace ts {
const flowType = getTypeAtFlowNode(flow.antecedent);
return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType));
}
return declaredType === autoType ? getBaseTypeOfLiteralType(getInitialOrAssignedType(node)) :
declaredType.flags & TypeFlags.Union ? getAssignmentReducedType(<UnionType>declaredType, getInitialOrAssignedType(node)) :
declaredType;
if (declaredType === autoType || declaredType === autoArrayType) {
if (isEmptyArrayAssignment(node)) {
return getEvolvingArrayType(neverType);
}
const assignedType = getBaseTypeOfLiteralType(getInitialOrAssignedType(node));
return isTypeAssignableTo(assignedType, declaredType) ? assignedType : anyArrayType;
}
if (declaredType.flags & TypeFlags.Union) {
return getAssignmentReducedType(<UnionType>declaredType, getInitialOrAssignedType(node));
}
return declaredType;
}
// We didn't have a direct match. However, if the reference is a dotted name, this
// may be an assignment to a left hand part of the reference. For example, for a
@ -8949,24 +9092,56 @@ namespace ts {
return undefined;
}
function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType {
const node = flow.node;
const expr = node.kind === SyntaxKind.CallExpression ?
(<PropertyAccessExpression>(<CallExpression>node).expression).expression :
(<ElementAccessExpression>(<BinaryExpression>node).left).expression;
if (isMatchingReference(reference, getReferenceCandidate(expr))) {
const flowType = getTypeAtFlowNode(flow.antecedent);
const type = getTypeFromFlowType(flowType);
if (isEvolvingArrayType(type)) {
let evolvedType = <AnonymousType>type;
if (node.kind === SyntaxKind.CallExpression) {
for (const arg of (<CallExpression>node).arguments) {
evolvedType = addEvolvingArrayElementType(evolvedType, arg);
}
}
else {
const indexType = checkExpression((<ElementAccessExpression>(<BinaryExpression>node).left).argumentExpression);
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike | TypeFlags.Undefined)) {
evolvedType = addEvolvingArrayElementType(evolvedType, (<BinaryExpression>node).right);
}
}
return evolvedType === type ? flowType : createFlowType(evolvedType, isIncomplete(flowType));
}
return flowType;
}
return undefined;
}
function getTypeAtFlowCondition(flow: FlowCondition): FlowType {
const flowType = getTypeAtFlowNode(flow.antecedent);
let type = getTypeFromFlowType(flowType);
if (!(type.flags & TypeFlags.Never)) {
// If we have an antecedent type (meaning we're reachable in some way), we first
// attempt to narrow the antecedent type. If that produces the never type, and if
// the antecedent type is incomplete (i.e. a transient type in a loop), then we
// take the type guard as an indication that control *could* reach here once we
// have the complete type. We proceed by switching to the silent never type which
// doesn't report errors when operators are applied to it. Note that this is the
// *only* place a silent never type is ever generated.
const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
type = narrowType(type, flow.expression, assumeTrue);
if (type.flags & TypeFlags.Never && isIncomplete(flowType)) {
type = silentNeverType;
}
const type = getTypeFromFlowType(flowType);
if (type.flags & TypeFlags.Never) {
return flowType;
}
return createFlowType(type, isIncomplete(flowType));
// If we have an antecedent type (meaning we're reachable in some way), we first
// attempt to narrow the antecedent type. If that produces the never type, and if
// the antecedent type is incomplete (i.e. a transient type in a loop), then we
// take the type guard as an indication that control *could* reach here once we
// have the complete type. We proceed by switching to the silent never type which
// doesn't report errors when operators are applied to it. Note that this is the
// *only* place a silent never type is ever generated.
const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
const nonEvolvingType = finalizeEvolvingArrayType(type);
const narrowedType = narrowType(nonEvolvingType, flow.expression, assumeTrue);
if (narrowedType === nonEvolvingType) {
return flowType;
}
const incomplete = isIncomplete(flowType);
const resultType = incomplete && narrowedType.flags & TypeFlags.Never ? silentNeverType : narrowedType;
return createFlowType(resultType, incomplete);
}
function getTypeAtSwitchClause(flow: FlowSwitchClause): FlowType {
@ -9009,7 +9184,7 @@ namespace ts {
seenIncomplete = true;
}
}
return createFlowType(getUnionType(antecedentTypes, subtypeReduction), seenIncomplete);
return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction), seenIncomplete);
}
function getTypeAtFlowLoopLabel(flow: FlowLabel): FlowType {
@ -9025,11 +9200,15 @@ namespace ts {
}
// If this flow loop junction and reference are already being processed, return
// the union of the types computed for each branch so far, marked as incomplete.
// We should never see an empty array here because the first antecedent of a loop
// junction is always the non-looping control flow path that leads to the top.
// It is possible to see an empty array in cases where loops are nested and the
// back edge of the outer loop reaches an inner loop that is already being analyzed.
// In such cases we restart the analysis of the inner loop, which will then see
// a non-empty in-process array for the outer loop and eventually terminate because
// the first antecedent of a loop junction is always the non-looping control flow
// path that leads to the top.
for (let i = flowLoopStart; i < flowLoopCount; i++) {
if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key) {
return createFlowType(getUnionType(flowLoopTypes[i]), /*incomplete*/ true);
if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key && flowLoopTypes[i].length) {
return createFlowType(getUnionOrEvolvingArrayType(flowLoopTypes[i], /*subtypeReduction*/ false), /*incomplete*/ true);
}
}
// Add the flow loop junction and reference to the in-process stack and analyze
@ -9072,7 +9251,7 @@ namespace ts {
}
// The result is incomplete if the first antecedent (the non-looping control flow path)
// is incomplete.
const result = getUnionType(antecedentTypes, subtypeReduction);
const result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction);
if (isIncomplete(firstAntecedentType)) {
return createFlowType(result, /*incomplete*/ true);
}
@ -9454,6 +9633,10 @@ namespace ts {
}
}
function isConstVariable(symbol: Symbol) {
return symbol.flags & SymbolFlags.Variable && (getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0 && getTypeOfSymbol(symbol) !== autoArrayType;
}
function checkIdentifier(node: Identifier): Type {
const symbol = getResolvedSymbol(node);
@ -9465,7 +9648,7 @@ namespace ts {
// can explicitly bound arguments objects
if (symbol === argumentsSymbol) {
const container = getContainingFunction(node);
if (languageVersion < ScriptTarget.ES6) {
if (languageVersion < ScriptTarget.ES2015) {
if (container.kind === SyntaxKind.ArrowFunction) {
error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
}
@ -9490,7 +9673,7 @@ namespace ts {
// Due to the emit for class decorators, any reference to the class from inside of the class body
// must instead be rewritten to point to a temporary variable to avoid issues with the double-bind
// behavior of class names in ES6.
if (languageVersion === ScriptTarget.ES6
if (languageVersion === ScriptTarget.ES2015
&& declaration.kind === SyntaxKind.ClassDeclaration
&& nodeIsDecorated(declaration)) {
let container = getContainingClass(node);
@ -9544,30 +9727,28 @@ namespace ts {
// When the control flow originates in a function expression or arrow function and we are referencing
// a const variable or parameter from an outer function, we extend the origin of the control flow
// analysis to include the immediately enclosing function.
while (flowContainer !== declarationContainer &&
(flowContainer.kind === SyntaxKind.FunctionExpression ||
flowContainer.kind === SyntaxKind.ArrowFunction ||
isObjectLiteralOrClassExpressionMethod(flowContainer)) &&
(isReadonlySymbol(localOrExportSymbol) || isParameter && !isParameterAssigned(localOrExportSymbol))) {
while (flowContainer !== declarationContainer && (flowContainer.kind === SyntaxKind.FunctionExpression ||
flowContainer.kind === SyntaxKind.ArrowFunction || isObjectLiteralOrClassExpressionMethod(flowContainer)) &&
(isConstVariable(localOrExportSymbol) || isParameter && !isParameterAssigned(localOrExportSymbol))) {
flowContainer = getControlFlowContainer(flowContainer);
}
// We only look for uninitialized variables in strict null checking mode, and only when we can analyze
// the entire control flow graph from the variable's declaration (i.e. when the flow container and
// declaration container are the same).
const assumeInitialized = isParameter || isOuterVariable ||
type !== autoType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0) ||
type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & TypeFlags.Any) !== 0) ||
isInAmbientContext(declaration);
const flowType = getFlowTypeOfReference(node, type, assumeInitialized, flowContainer);
// A variable is considered uninitialized when it is possible to analyze the entire control flow graph
// from declaration to use, and when the variable's declared type doesn't include undefined but the
// control flow based type does include undefined.
if (type === autoType) {
if (flowType === autoType) {
if (type === autoType || type === autoArrayType) {
if (flowType === autoType || flowType === autoArrayType) {
if (compilerOptions.noImplicitAny) {
error(declaration.name, Diagnostics.Variable_0_implicitly_has_type_any_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol));
error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(anyType));
error(declaration.name, Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType));
error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType));
}
return anyType;
return convertAutoToAny(flowType);
}
}
else if (!assumeInitialized && !(getFalsyFlags(type) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
@ -9591,7 +9772,7 @@ namespace ts {
}
function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void {
if (languageVersion >= ScriptTarget.ES6 ||
if (languageVersion >= ScriptTarget.ES2015 ||
(symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 ||
symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause) {
return;
@ -9757,7 +9938,7 @@ namespace ts {
container = getThisContainer(container, /* includeArrowFunctions */ false);
// When targeting es6, arrow function lexically bind "this" so we do not need to do the work of binding "this" in emitted code
needToCaptureLexicalThis = (languageVersion < ScriptTarget.ES6);
needToCaptureLexicalThis = (languageVersion < ScriptTarget.ES2015);
}
switch (container.kind) {
@ -9810,7 +9991,7 @@ namespace ts {
}
}
const thisType = getThisTypeOfDeclaration(container);
const thisType = getThisTypeOfDeclaration(container) || getContextualThisParameterType(container);
if (thisType) {
return thisType;
}
@ -9865,7 +10046,7 @@ namespace ts {
if (!isCallExpression) {
while (container && container.kind === SyntaxKind.ArrowFunction) {
container = getSuperContainer(container, /*stopOnFunctions*/ true);
needToCaptureLexicalThis = languageVersion < ScriptTarget.ES6;
needToCaptureLexicalThis = languageVersion < ScriptTarget.ES2015;
}
}
@ -9979,7 +10160,7 @@ namespace ts {
}
if (container.parent.kind === SyntaxKind.ObjectLiteralExpression) {
if (languageVersion < ScriptTarget.ES6) {
if (languageVersion < ScriptTarget.ES2015) {
error(node, Diagnostics.super_is_only_allowed_in_members_of_object_literal_expressions_when_option_target_is_ES2015_or_higher);
return unknownType;
}
@ -10050,14 +10231,16 @@ namespace ts {
}
}
function getContextualThisParameter(func: FunctionLikeDeclaration): Symbol {
function getContextualThisParameterType(func: FunctionLikeDeclaration): Type {
if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
const contextualSignature = getContextualSignature(func);
if (contextualSignature) {
return contextualSignature.thisParameter;
const thisParameter = contextualSignature.thisParameter;
if (thisParameter) {
return getTypeOfSymbol(thisParameter);
}
}
}
return undefined;
}
@ -10347,7 +10530,7 @@ namespace ts {
const index = indexOf(arrayLiteral.elements, node);
return getTypeOfPropertyOfContextualType(type, "" + index)
|| getIndexTypeOfContextualType(type, IndexKind.Number)
|| (languageVersion >= ScriptTarget.ES6 ? getElementTypeOfIterable(type, /*errorNode*/ undefined) : undefined);
|| (languageVersion >= ScriptTarget.ES2015 ? getElementTypeOfIterable(type, /*errorNode*/ undefined) : undefined);
}
return undefined;
}
@ -10580,7 +10763,7 @@ namespace ts {
// if there is no index type / iterated type.
const restArrayType = checkExpression((<SpreadExpression>e).expression, contextualMapper);
const restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) ||
(languageVersion >= ScriptTarget.ES6 ? getElementTypeOfIterable(restArrayType, /*errorNode*/ undefined) : undefined);
(languageVersion >= ScriptTarget.ES2015 ? getElementTypeOfIterable(restArrayType, /*errorNode*/ undefined) : undefined);
if (restElementType) {
elementTypes.push(restElementType);
}
@ -11038,7 +11221,7 @@ namespace ts {
}
}
return getUnionType(signatures.map(getReturnTypeOfSignature), /*subtypeReduction*/ true);
return getUnionType(map(signatures, getReturnTypeOfSignature), /*subtypeReduction*/ true);
}
/// e.g. "props" for React.d.ts,
@ -11088,7 +11271,7 @@ namespace ts {
}
if (elemType.flags & TypeFlags.Union) {
const types = (<UnionOrIntersectionType>elemType).types;
return getUnionType(types.map(type => {
return getUnionType(map(types, type => {
return getResolvedJsxType(node, type, elemClassType);
}), /*subtypeReduction*/ true);
}
@ -11354,7 +11537,7 @@ namespace ts {
// - In a static member function or static member accessor
// where this references the constructor function object of a derived class,
// a super property access is permitted and must specify a public static member function of the base class.
if (languageVersion < ScriptTarget.ES6 && getDeclarationKindFromSymbol(prop) !== SyntaxKind.MethodDeclaration) {
if (languageVersion < ScriptTarget.ES2015 && getDeclarationKindFromSymbol(prop) !== SyntaxKind.MethodDeclaration) {
// `prop` refers to a *property* declared in the super class
// rather than a *method*, so it does not satisfy the above criteria.
@ -11967,7 +12150,7 @@ namespace ts {
// If the effective argument is 'undefined', then it is an argument that is present but is synthetic.
if (arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) {
const paramType = getTypeAtPosition(signature, i);
let argType = getEffectiveArgumentType(node, i, arg);
let argType = getEffectiveArgumentType(node, i);
// If the effective argument type is 'undefined', there is no synthetic type
// for the argument. In that case, we should check the argument.
@ -12053,7 +12236,7 @@ namespace ts {
if (arg === undefined || arg.kind !== SyntaxKind.OmittedExpression) {
// Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter)
const paramType = getTypeAtPosition(signature, i);
let argType = getEffectiveArgumentType(node, i, arg);
let argType = getEffectiveArgumentType(node, i);
// If the effective argument type is 'undefined', there is no synthetic type
// for the argument. In that case, we should check the argument.
@ -12346,7 +12529,7 @@ namespace ts {
/**
* Gets the effective argument type for an argument in a call expression.
*/
function getEffectiveArgumentType(node: CallLikeExpression, argIndex: number, arg: Expression): Type {
function getEffectiveArgumentType(node: CallLikeExpression, argIndex: number): Type {
// Decorators provide special arguments, a tagged template expression provides
// a special first argument, and string literals get string literal types
// unless we're reporting errors
@ -12999,7 +13182,10 @@ namespace ts {
}
// In JavaScript files, calls to any identifier 'require' are treated as external module imports
if (isInJavaScriptFile(node) && isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) {
if (isInJavaScriptFile(node) &&
isRequireCall(node, /*checkArgumentIsStringLiteral*/true) &&
// Make sure require is not a local function
!resolveName(node.expression, (<Identifier>node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)) {
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
}
@ -13048,21 +13234,36 @@ namespace ts {
function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) {
const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
if (context.thisParameter) {
if (!signature.thisParameter) {
signature.thisParameter = createTransientSymbol(context.thisParameter, undefined);
if (isInferentialContext(mapper)) {
for (let i = 0; i < len; i++) {
const declaration = <ParameterDeclaration>signature.parameters[i].valueDeclaration;
if (declaration.type) {
inferTypes(mapper.context, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i));
}
}
}
if (context.thisParameter) {
const parameter = signature.thisParameter;
if (!parameter || parameter.valueDeclaration && !(<ParameterDeclaration>parameter.valueDeclaration).type) {
if (!parameter) {
signature.thisParameter = createTransientSymbol(context.thisParameter, undefined);
}
assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper);
}
assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper);
}
for (let i = 0; i < len; i++) {
const parameter = signature.parameters[i];
const contextualParameterType = getTypeAtPosition(context, i);
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
const contextualParameterType = getTypeAtPosition(context, i);
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
}
}
if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) {
const parameter = lastOrUndefined(signature.parameters);
const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
if (!(<ParameterDeclaration>parameter.valueDeclaration).type) {
const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
}
}
}
@ -13733,15 +13934,15 @@ namespace ts {
return booleanType;
}
function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type {
function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type): Type {
const properties = node.properties;
for (const p of properties) {
checkObjectLiteralDestructuringPropertyAssignment(sourceType, p, contextualMapper);
checkObjectLiteralDestructuringPropertyAssignment(sourceType, p);
}
return sourceType;
}
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike, contextualMapper?: TypeMapper) {
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElementLike) {
if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
const name = <PropertyName>(<PropertyAssignment>property).name;
if (name.kind === SyntaxKind.ComputedPropertyName) {
@ -13856,7 +14057,7 @@ namespace ts {
target = (<BinaryExpression>target).left;
}
if (target.kind === SyntaxKind.ObjectLiteralExpression) {
return checkObjectLiteralAssignment(<ObjectLiteralExpression>target, sourceType, contextualMapper);
return checkObjectLiteralAssignment(<ObjectLiteralExpression>target, sourceType);
}
if (target.kind === SyntaxKind.ArrayLiteralExpression) {
return checkArrayLiteralAssignment(<ArrayLiteralExpression>target, sourceType, contextualMapper);
@ -14676,7 +14877,7 @@ namespace ts {
}
if (node.type) {
if (languageVersion >= ScriptTarget.ES6 && isSyntacticallyValidGenerator(node)) {
if (languageVersion >= ScriptTarget.ES2015 && isSyntacticallyValidGenerator(node)) {
const returnType = getTypeFromTypeNode(node.type);
if (returnType === voidType) {
error(node.type, Diagnostics.A_generator_cannot_have_a_void_type_annotation);
@ -15639,7 +15840,7 @@ namespace ts {
* callable `then` signature.
*/
function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
if (languageVersion >= ScriptTarget.ES6) {
if (languageVersion >= ScriptTarget.ES2015) {
const returnType = getTypeFromTypeNode(node.type);
return checkCorrectPromiseType(returnType, node.type, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type);
}
@ -16168,7 +16369,7 @@ namespace ts {
function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) {
// No need to check for require or exports for ES6 modules and later
if (modulekind >= ModuleKind.ES6) {
if (modulekind >= ModuleKind.ES2015) {
return;
}
@ -16349,7 +16550,7 @@ namespace ts {
}
function convertAutoToAny(type: Type) {
return type === autoType ? anyType : type;
return type === autoType ? anyType : type === autoArrayType ? anyArrayType : type;
}
// Check variable, parameter, or property declaration
@ -16664,7 +16865,7 @@ namespace ts {
if (isTypeAny(inputType)) {
return inputType;
}
if (languageVersion >= ScriptTarget.ES6) {
if (languageVersion >= ScriptTarget.ES2015) {
return checkElementTypeOfIterable(inputType, errorNode);
}
if (allowStringInput) {
@ -16842,7 +17043,7 @@ namespace ts {
* 2. Some constituent is a string and target is less than ES5 (because in ES3 string is not indexable).
*/
function checkElementTypeOfArrayOrString(arrayOrStringType: Type, errorNode: Node): Type {
Debug.assert(languageVersion < ScriptTarget.ES6);
Debug.assert(languageVersion < ScriptTarget.ES2015);
// After we remove all types that are StringLike, we will know if there was a string constituent
// based on whether the remaining type is the same as the initial type.
@ -18155,7 +18356,7 @@ namespace ts {
}
}
else {
if (modulekind === ModuleKind.ES6 && !isInAmbientContext(node)) {
if (modulekind === ModuleKind.ES2015 && !isInAmbientContext(node)) {
// Import equals declaration is deprecated in es6 or above
grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_2015_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead);
}
@ -18243,7 +18444,7 @@ namespace ts {
checkExternalModuleExports(container);
if (node.isExportEquals && !isInAmbientContext(node)) {
if (modulekind === ModuleKind.ES6) {
if (modulekind === ModuleKind.ES2015) {
// export assignment is not supported in es6 modules
grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_2015_modules_Consider_using_export_default_or_another_module_format_instead);
}
@ -18769,7 +18970,7 @@ namespace ts {
// Since we already checked for ExportAssignment, this really could only be an Import
const importEqualsDeclaration = <ImportEqualsDeclaration>getAncestor(entityName, SyntaxKind.ImportEqualsDeclaration);
Debug.assert(importEqualsDeclaration !== undefined);
return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>entityName, importEqualsDeclaration, /*dontResolveAlias*/ true);
return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>entityName, /*dontResolveAlias*/ true);
}
if (isRightSideOfQualifiedNameOrPropertyAccess(entityName)) {
@ -19761,7 +19962,7 @@ namespace ts {
getGlobalTemplateStringsArrayType = memoize(() => getGlobalType("TemplateStringsArray"));
if (languageVersion >= ScriptTarget.ES6) {
if (languageVersion >= ScriptTarget.ES2015) {
getGlobalESSymbolType = memoize(() => getGlobalType("Symbol"));
getGlobalIterableType = memoize(() => <GenericType>getGlobalType("Iterable", /*arity*/ 1));
getGlobalIteratorType = memoize(() => <GenericType>getGlobalType("Iterator", /*arity*/ 1));
@ -19775,6 +19976,7 @@ namespace ts {
}
anyArrayType = createArrayType(anyType);
autoArrayType = createArrayType(autoType);
const symbol = getGlobalSymbol("ReadonlyArray", SymbolFlags.Type, /*diagnostic*/ undefined);
globalReadonlyArrayType = symbol && <GenericType>getTypeOfGlobalSymbol(symbol, /*arity*/ 1);
@ -19794,7 +19996,7 @@ namespace ts {
// If we found the module, report errors if it does not have the necessary exports.
if (helpersModule) {
const exports = helpersModule.exports;
if (requestedExternalEmitHelpers & NodeFlags.HasClassExtends && languageVersion < ScriptTarget.ES6) {
if (requestedExternalEmitHelpers & NodeFlags.HasClassExtends && languageVersion < ScriptTarget.ES2015) {
verifyHelperSymbol(exports, "__extends", SymbolFlags.Value);
}
if (requestedExternalEmitHelpers & NodeFlags.HasSpreadAttribute && compilerOptions.jsx !== JsxEmit.Preserve) {
@ -19811,7 +20013,7 @@ namespace ts {
}
if (requestedExternalEmitHelpers & NodeFlags.HasAsyncFunctions) {
verifyHelperSymbol(exports, "__awaiter", SymbolFlags.Value);
if (languageVersion < ScriptTarget.ES6) {
if (languageVersion < ScriptTarget.ES2015) {
verifyHelperSymbol(exports, "__generator", SymbolFlags.Value);
}
}
@ -20157,7 +20359,7 @@ namespace ts {
}
}
function checkGrammarTypeParameterList(node: FunctionLikeDeclaration, typeParameters: NodeArray<TypeParameterDeclaration>, file: SourceFile): boolean {
function checkGrammarTypeParameterList(typeParameters: NodeArray<TypeParameterDeclaration>, file: SourceFile): boolean {
if (checkGrammarForDisallowedTrailingComma(typeParameters)) {
return true;
}
@ -20208,7 +20410,7 @@ namespace ts {
function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean {
// Prevent cascading error by short-circuit
const file = getSourceFileOfNode(node);
return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarTypeParameterList(node, node.typeParameters, file) ||
return checkGrammarDecorators(node) || checkGrammarModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) ||
checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file);
}
@ -20393,13 +20595,13 @@ namespace ts {
if (!node.body) {
return grammarErrorOnNode(node.asteriskToken, Diagnostics.An_overload_signature_cannot_be_declared_as_a_generator);
}
if (languageVersion < ScriptTarget.ES6) {
if (languageVersion < ScriptTarget.ES2015) {
return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_only_available_when_targeting_ECMAScript_2015_or_higher);
}
}
}
function checkGrammarForInvalidQuestionMark(node: Declaration, questionToken: Node, message: DiagnosticMessage): boolean {
function checkGrammarForInvalidQuestionMark(questionToken: Node, message: DiagnosticMessage): boolean {
if (questionToken) {
return grammarErrorOnNode(questionToken, message);
}
@ -20448,7 +20650,7 @@ namespace ts {
let currentKind: number;
if (prop.kind === SyntaxKind.PropertyAssignment || prop.kind === SyntaxKind.ShorthandPropertyAssignment) {
// Grammar checking for computedPropertyName and shorthandPropertyAssignment
checkGrammarForInvalidQuestionMark(prop, (<PropertyAssignment>prop).questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
checkGrammarForInvalidQuestionMark((<PropertyAssignment>prop).questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
if (name.kind === SyntaxKind.NumericLiteral) {
checkGrammarNumericLiteral(<NumericLiteral>name);
}
@ -20632,7 +20834,7 @@ namespace ts {
}
if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) {
if (checkGrammarForInvalidQuestionMark(node, node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional)) {
if (checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional)) {
return true;
}
else if (node.body === undefined) {

View file

@ -101,7 +101,7 @@ namespace ts {
"amd": ModuleKind.AMD,
"system": ModuleKind.System,
"umd": ModuleKind.UMD,
"es6": ModuleKind.ES6,
"es6": ModuleKind.ES2015,
"es2015": ModuleKind.ES2015,
}),
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
@ -261,8 +261,10 @@ namespace ts {
type: createMap({
"es3": ScriptTarget.ES3,
"es5": ScriptTarget.ES5,
"es6": ScriptTarget.ES6,
"es6": ScriptTarget.ES2015,
"es2015": ScriptTarget.ES2015,
"es2016": ScriptTarget.ES2016,
"es2017": ScriptTarget.ES2017,
}),
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015,
paramType: Diagnostics.VERSION,
@ -513,10 +515,7 @@ namespace ts {
/* @internal */
export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic {
const namesOfType: string[] = [];
for (const key in opt.type) {
namesOfType.push(` '${key}'`);
}
const namesOfType = Object.keys(opt.type).map(key => `'${key}'`).join(", ");
return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
}

View file

@ -188,7 +188,7 @@ namespace ts {
}
}
function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) {
function emitLeadingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) {
if (!hasWrittenComment) {
emitNewLineBeforeLeadingCommentOfPosition(currentLineMap, writer, rangePos, commentPos);
hasWrittenComment = true;
@ -211,7 +211,7 @@ namespace ts {
forEachTrailingCommentToEmit(pos, emitTrailingComment);
}
function emitTrailingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) {
function emitTrailingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/
if (!writer.isAtStartOfLine()) {
writer.write(" ");
@ -242,7 +242,7 @@ namespace ts {
}
}
function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) {
function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
emitPos(commentPos);

View file

@ -20,6 +20,9 @@ namespace ts {
const createObject = Object.create;
// More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times.
export const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator() : undefined;
export function createMap<T>(template?: MapLike<T>): Map<T> {
const map: Map<T> = createObject(null); // tslint:disable-line:no-null-keyword
@ -265,13 +268,33 @@ namespace ts {
if (array) {
result = [];
for (let i = 0; i < array.length; i++) {
const v = array[i];
result.push(f(v, i));
result.push(f(array[i], i));
}
}
return result;
}
// Maps from T to T and avoids allocation if all elements map to themselves
export function sameMap<T>(array: T[], f: (x: T, i: number) => T): T[] {
let result: T[];
if (array) {
for (let i = 0; i < array.length; i++) {
if (result) {
result.push(f(array[i], i));
}
else {
const item = array[i];
const mapped = f(item, i);
if (item !== mapped) {
result = array.slice(0, i);
result.push(mapped);
}
}
}
}
return result || array;
}
/**
* Flattens an array containing a mix of array or non-array elements.
*
@ -399,6 +422,17 @@ namespace ts {
return result;
}
export function some<T>(array: T[], predicate?: (value: T) => boolean): boolean {
if (array) {
for (const v of array) {
if (!predicate || predicate(v)) {
return true;
}
}
}
return false;
}
export function concatenate<T>(array1: T[], array2: T[]): T[] {
if (!array2 || !array2.length) return array1;
if (!array1 || !array1.length) return array2;
@ -869,7 +903,7 @@ namespace ts {
return t => compose(a(t));
}
else {
return t => u => u;
return _ => u => u;
}
}
@ -906,10 +940,10 @@ namespace ts {
}
}
function formatStringFromArgs(text: string, args: { [index: number]: any; }, baseIndex?: number): string {
function formatStringFromArgs(text: string, args: { [index: number]: string; }, baseIndex?: number): string {
baseIndex = baseIndex || 0;
return text.replace(/{(\d+)}/g, (match, index?) => args[+index + baseIndex]);
return text.replace(/{(\d+)}/g, (_match, index?) => args[+index + baseIndex]);
}
export let localizedDiagnosticMessages: Map<string> = undefined;
@ -918,7 +952,7 @@ namespace ts {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
}
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number)[]): Diagnostic;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic {
const end = start + length;
@ -948,7 +982,7 @@ namespace ts {
}
/* internal */
export function formatMessage(dummy: any, message: DiagnosticMessage): string {
export function formatMessage(_dummy: any, message: DiagnosticMessage): string {
let text = getLocaleSpecificMessage(message);
if (arguments.length > 2) {
@ -958,7 +992,7 @@ namespace ts {
return text;
}
export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: any[]): Diagnostic;
export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: (string | number)[]): Diagnostic;
export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic {
let text = getLocaleSpecificMessage(message);
@ -1016,7 +1050,8 @@ namespace ts {
if (a === undefined) return Comparison.LessThan;
if (b === undefined) return Comparison.GreaterThan;
if (ignoreCase) {
if (String.prototype.localeCompare) {
if (collator && String.prototype.localeCompare) {
// accent means a ≠ b, a ≠ á, a = A
const result = a.localeCompare(b, /*locales*/ undefined, { usage: "sort", sensitivity: "accent" });
return result < 0 ? Comparison.LessThan : result > 0 ? Comparison.GreaterThan : Comparison.EqualTo;
}
@ -1177,7 +1212,7 @@ namespace ts {
/**
* Returns the path except for its basename. Eg:
*
*
* /path/to/file.ext -> /path/to
*/
export function getDirectoryPath(path: Path): Path;
@ -1203,7 +1238,7 @@ namespace ts {
export function getEmitModuleKind(compilerOptions: CompilerOptions) {
return typeof compilerOptions.module === "number" ?
compilerOptions.module :
getEmitScriptTarget(compilerOptions) === ScriptTarget.ES6 ? ModuleKind.ES6 : ModuleKind.CommonJS;
getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 ? ModuleKind.ES2015 : ModuleKind.CommonJS;
}
/* @internal */
@ -1588,7 +1623,7 @@ namespace ts {
basePaths: string[];
}
export function getFileMatcherPatterns(path: string, extensions: string[], excludes: string[], includes: string[], useCaseSensitiveFileNames: boolean, currentDirectory: string): FileMatcherPatterns {
export function getFileMatcherPatterns(path: string, excludes: string[], includes: string[], useCaseSensitiveFileNames: boolean, currentDirectory: string): FileMatcherPatterns {
path = normalizePath(path);
currentDirectory = normalizePath(currentDirectory);
const absolutePath = combinePaths(currentDirectory, path);
@ -1605,7 +1640,7 @@ namespace ts {
path = normalizePath(path);
currentDirectory = normalizePath(currentDirectory);
const patterns = getFileMatcherPatterns(path, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
const patterns = getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
const regexFlag = useCaseSensitiveFileNames ? "" : "i";
const includeFileRegex = patterns.includeFilePattern && new RegExp(patterns.includeFilePattern, regexFlag);
@ -1839,11 +1874,11 @@ namespace ts {
this.declarations = undefined;
}
function Type(this: Type, checker: TypeChecker, flags: TypeFlags) {
function Type(this: Type, _checker: TypeChecker, flags: TypeFlags) {
this.flags = flags;
}
function Signature(checker: TypeChecker) {
function Signature() {
}
function Node(this: Node, kind: SyntaxKind, pos: number, end: number) {
@ -1876,9 +1911,6 @@ namespace ts {
}
export namespace Debug {
declare var process: any;
declare var require: any;
export let currentAssertionLevel = AssertionLevel.None;
export function shouldAssert(level: AssertionLevel): boolean {

View file

@ -63,7 +63,7 @@ namespace ts {
let isCurrentFileExternalModule: boolean;
let reportedDeclarationError = false;
let errorNameNode: DeclarationName;
const emitJsDocComments = compilerOptions.removeComments ? function (declaration: Node) { } : writeJsDocComments;
const emitJsDocComments = compilerOptions.removeComments ? () => {} : writeJsDocComments;
const emit = compilerOptions.stripInternal ? stripInternal : emitNode;
let noDeclare: boolean;
@ -580,7 +580,7 @@ namespace ts {
writeAsynchronousModuleElements(nodes);
}
function getDefaultExportAccessibilityDiagnostic(diagnostic: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
function getDefaultExportAccessibilityDiagnostic(): SymbolAccessibilityDiagnostic {
return {
diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
errorNode: node
@ -710,7 +710,7 @@ namespace ts {
}
writer.writeLine();
function getImportEntityNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
function getImportEntityNameVisibilityError(): SymbolAccessibilityDiagnostic {
return {
diagnosticMessage: Diagnostics.Import_declaration_0_is_using_private_name_1,
errorNode: node,
@ -888,7 +888,7 @@ namespace ts {
writeLine();
enclosingDeclaration = prevEnclosingDeclaration;
function getTypeAliasDeclarationVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
function getTypeAliasDeclarationVisibilityError(): SymbolAccessibilityDiagnostic {
return {
diagnosticMessage: Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1,
errorNode: node.type,
@ -955,7 +955,7 @@ namespace ts {
}
}
function getTypeParameterConstraintVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
function getTypeParameterConstraintVisibilityError(): SymbolAccessibilityDiagnostic {
// Type parameter constraints are named by user so we should always be able to name it
let diagnosticMessage: DiagnosticMessage;
switch (node.parent.kind) {
@ -1029,7 +1029,7 @@ namespace ts {
resolver.writeBaseConstructorTypeOfClass(<ClassLikeDeclaration>enclosingDeclaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
}
function getHeritageClauseVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
function getHeritageClauseVisibilityError(): SymbolAccessibilityDiagnostic {
let diagnosticMessage: DiagnosticMessage;
// Heritage clause is written by user so it can always be named
if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
@ -1752,7 +1752,7 @@ namespace ts {
}
return addedBundledEmitReference;
function getDeclFileName(emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) {
function getDeclFileName(emitFileNames: EmitFileNames, _sourceFiles: SourceFile[], isBundledEmit: boolean) {
// Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path
if (isBundledEmit && !addBundledFileReference) {
return;

View file

@ -2965,7 +2965,7 @@
"category": "Error",
"code": 7033
},
"Variable '{0}' implicitly has type 'any' in some locations where its type cannot be determined.": {
"Variable '{0}' implicitly has type '{1}' in some locations where its type cannot be determined.": {
"category": "Error",
"code": 7034
},

View file

@ -14,7 +14,7 @@ namespace ts {
}
const id = (s: SourceFile) => s;
const nullTransformers: Transformer[] = [ctx => id];
const nullTransformers: Transformer[] = [_ => id];
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult {
@ -504,15 +504,29 @@ const _super = (function (geti, seti) {
// Contextual keywords
case SyntaxKind.AbstractKeyword:
case SyntaxKind.AsKeyword:
case SyntaxKind.AnyKeyword:
case SyntaxKind.AsyncKeyword:
case SyntaxKind.AwaitKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.ConstructorKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.GetKeyword:
case SyntaxKind.IsKeyword:
case SyntaxKind.ModuleKeyword:
case SyntaxKind.NamespaceKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.ReadonlyKeyword:
case SyntaxKind.RequireKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.SetKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.TypeKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.FromKeyword:
case SyntaxKind.GlobalKeyword:
case SyntaxKind.OfKeyword:
writeTokenText(kind);
return;
@ -579,7 +593,7 @@ const _super = (function (geti, seti) {
case SyntaxKind.ExpressionWithTypeArguments:
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>node);
case SyntaxKind.ThisType:
return emitThisType(<ThisTypeNode>node);
return emitThisType();
case SyntaxKind.LiteralType:
return emitLiteralType(<LiteralTypeNode>node);
@ -595,7 +609,7 @@ const _super = (function (geti, seti) {
case SyntaxKind.TemplateSpan:
return emitTemplateSpan(<TemplateSpan>node);
case SyntaxKind.SemicolonClassElement:
return emitSemicolonClassElement(<SemicolonClassElement>node);
return emitSemicolonClassElement();
// Statements
case SyntaxKind.Block:
@ -603,7 +617,7 @@ const _super = (function (geti, seti) {
case SyntaxKind.VariableStatement:
return emitVariableStatement(<VariableStatement>node);
case SyntaxKind.EmptyStatement:
return emitEmptyStatement(<EmptyStatement>node);
return emitEmptyStatement();
case SyntaxKind.ExpressionStatement:
return emitExpressionStatement(<ExpressionStatement>node);
case SyntaxKind.IfStatement:
@ -1000,7 +1014,7 @@ const _super = (function (geti, seti) {
write(";");
}
function emitSemicolonClassElement(node: SemicolonClassElement) {
function emitSemicolonClassElement() {
write(";");
}
@ -1070,7 +1084,7 @@ const _super = (function (geti, seti) {
write(")");
}
function emitThisType(node: ThisTypeNode) {
function emitThisType() {
write("this");
}
@ -1198,12 +1212,14 @@ const _super = (function (geti, seti) {
function emitCallExpression(node: CallExpression) {
emitExpression(node.expression);
emitTypeArguments(node, node.typeArguments);
emitExpressionList(node, node.arguments, ListFormat.CallExpressionArguments);
}
function emitNewExpression(node: NewExpression) {
write("new ");
emitExpression(node.expression);
emitTypeArguments(node, node.typeArguments);
emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments);
}
@ -1381,7 +1397,7 @@ const _super = (function (geti, seti) {
// Statements
//
function emitBlock(node: Block, format?: ListFormat) {
function emitBlock(node: Block) {
if (isSingleLineEmptyBlock(node)) {
writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node);
write(" ");
@ -1409,7 +1425,7 @@ const _super = (function (geti, seti) {
write(";");
}
function emitEmptyStatement(node: EmptyStatement) {
function emitEmptyStatement() {
write(";");
}
@ -1575,6 +1591,7 @@ const _super = (function (geti, seti) {
function emitVariableDeclaration(node: VariableDeclaration) {
emit(node.name);
emitWithPrefix(": ", node.type);
emitExpressionWithPrefix(" = ", node.initializer);
}
@ -1606,13 +1623,13 @@ const _super = (function (geti, seti) {
if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) {
emitSignatureHead(node);
emitBlockFunctionBody(node, body);
emitBlockFunctionBody(body);
}
else {
const savedTempFlags = tempFlags;
tempFlags = 0;
emitSignatureHead(node);
emitBlockFunctionBody(node, body);
emitBlockFunctionBody(body);
tempFlags = savedTempFlags;
}
@ -1639,7 +1656,7 @@ const _super = (function (geti, seti) {
emitWithPrefix(": ", node.type);
}
function shouldEmitBlockFunctionBodyOnSingleLine(parentNode: Node, body: Block) {
function shouldEmitBlockFunctionBodyOnSingleLine(body: Block) {
// We must emit a function body as a single-line body in the following case:
// * The body has NodeEmitFlags.SingleLine specified.
@ -1677,12 +1694,12 @@ const _super = (function (geti, seti) {
return true;
}
function emitBlockFunctionBody(parentNode: Node, body: Block) {
function emitBlockFunctionBody(body: Block) {
write(" {");
increaseIndent();
emitBodyWithDetachedComments(body, body.statements,
shouldEmitBlockFunctionBodyOnSingleLine(parentNode, body)
shouldEmitBlockFunctionBodyOnSingleLine(body)
? emitBlockFunctionBodyOnSingleLine
: emitBlockFunctionBodyWorker);
@ -2165,7 +2182,7 @@ const _super = (function (geti, seti) {
// Only Emit __extends function when target ES5.
// For target ES6 and above, we can emit classDeclaration as is.
if ((languageVersion < ScriptTarget.ES6) && (!extendsEmitted && node.flags & NodeFlags.HasClassExtends)) {
if ((languageVersion < ScriptTarget.ES2015) && (!extendsEmitted && node.flags & NodeFlags.HasClassExtends)) {
writeLines(extendsHelper);
extendsEmitted = true;
helpersEmitted = true;
@ -2192,9 +2209,12 @@ const _super = (function (geti, seti) {
helpersEmitted = true;
}
if (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions) {
// Only emit __awaiter function when target ES5/ES6.
// Only emit __generator function when target ES5.
// For target ES2017 and above, we can emit async/await as is.
if ((languageVersion < ScriptTarget.ES2017) && (!awaiterEmitted && node.flags & NodeFlags.HasAsyncFunctions)) {
writeLines(awaiterHelper);
if (languageVersion < ScriptTarget.ES6) {
if (languageVersion < ScriptTarget.ES2015) {
writeLines(generatorHelper);
}

View file

@ -525,9 +525,9 @@ namespace ts {
return node;
}
export function createFunctionExpression(asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags) {
export function createFunctionExpression(modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags) {
const node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression, location, flags);
node.modifiers = undefined;
node.modifiers = modifiers ? createNodeArray(modifiers) : undefined;
node.asteriskToken = asteriskToken;
node.name = typeof name === "string" ? createIdentifier(name) : name;
node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined;
@ -537,9 +537,9 @@ namespace ts {
return node;
}
export function updateFunctionExpression(node: FunctionExpression, name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
if (node.name !== name || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) {
return updateNode(createFunctionExpression(node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node);
export function updateFunctionExpression(node: FunctionExpression, modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
if (node.name !== name || node.modifiers !== modifiers || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) {
return updateNode(createFunctionExpression(modifiers, node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node);
}
return node;
}
@ -1736,6 +1736,7 @@ namespace ts {
export function createAwaiterHelper(externalHelpersModuleName: Identifier | undefined, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
const generatorFunc = createFunctionExpression(
/*modifiers*/ undefined,
createToken(SyntaxKind.AsteriskToken),
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -1909,6 +1910,7 @@ namespace ts {
createCall(
createParen(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -1984,7 +1986,7 @@ namespace ts {
}
else if (callee.kind === SyntaxKind.SuperKeyword) {
thisArg = createThis();
target = languageVersion < ScriptTarget.ES6 ? createIdentifier("_super", /*location*/ callee) : <PrimaryExpression>callee;
target = languageVersion < ScriptTarget.ES2015 ? createIdentifier("_super", /*location*/ callee) : <PrimaryExpression>callee;
}
else {
switch (callee.kind) {
@ -2090,6 +2092,7 @@ namespace ts {
const properties: ObjectLiteralElementLike[] = [];
if (getAccessor) {
const getterFunction = createFunctionExpression(
getAccessor.modifiers,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -2105,6 +2108,7 @@ namespace ts {
if (setAccessor) {
const setterFunction = createFunctionExpression(
setAccessor.modifiers,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -2171,6 +2175,7 @@ namespace ts {
createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name),
setOriginalNode(
createFunctionExpression(
method.modifiers,
method.asteriskToken,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -2206,7 +2211,7 @@ namespace ts {
* @param visitor: Optional callback used to visit any custom prologue directives.
*/
export function addPrologueDirectives(target: Statement[], source: Statement[], ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult<Node>): number {
Debug.assert(target.length === 0, "PrologueDirectives should be at the first statement in the target statements array");
Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array");
let foundUseStrict = false;
let statementOffset = 0;
const numStatements = source.length;
@ -2219,16 +2224,20 @@ namespace ts {
target.push(statement);
}
else {
if (ensureUseStrict && !foundUseStrict) {
target.push(startOnNewLine(createStatement(createLiteral("use strict"))));
foundUseStrict = true;
}
if (getEmitFlags(statement) & EmitFlags.CustomPrologue) {
target.push(visitor ? visitNode(statement, visitor, isStatement) : statement);
}
else {
break;
}
break;
}
statementOffset++;
}
if (ensureUseStrict && !foundUseStrict) {
target.push(startOnNewLine(createStatement(createLiteral("use strict"))));
}
while (statementOffset < numStatements) {
const statement = source[statementOffset];
if (getEmitFlags(statement) & EmitFlags.CustomPrologue) {
target.push(visitor ? visitNode(statement, visitor, isStatement) : statement);
}
else {
break;
}
statementOffset++;
}

View file

@ -5,7 +5,7 @@ namespace ts {
/* @internal */
export function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void;
export function trace(host: ModuleResolutionHost, message: DiagnosticMessage): void {
export function trace(host: ModuleResolutionHost): void {
host.trace(formatMessage.apply(undefined, arguments));
}

View file

@ -576,10 +576,10 @@ namespace ts {
// attached to the EOF token.
let parseErrorBeforeNextFinishedNode = false;
export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile {
export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, scriptKind?: ScriptKind): SourceFile {
scriptKind = ensureScriptKind(fileName, scriptKind);
initializeState(fileName, _sourceText, languageVersion, _syntaxCursor, scriptKind);
initializeState(sourceText, languageVersion, syntaxCursor, scriptKind);
const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, scriptKind);
@ -593,7 +593,7 @@ namespace ts {
return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS ? LanguageVariant.JSX : LanguageVariant.Standard;
}
function initializeState(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) {
function initializeState(_sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, scriptKind: ScriptKind) {
NodeConstructor = objectAllocator.getNodeConstructor();
TokenConstructor = objectAllocator.getTokenConstructor();
IdentifierConstructor = objectAllocator.getIdentifierConstructor();
@ -5284,7 +5284,7 @@ namespace ts {
parseExpected(SyntaxKind.ClassKeyword);
node.name = parseNameOfClassDeclarationOrExpression();
node.typeParameters = parseTypeParameters();
node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause*/ true);
node.heritageClauses = parseHeritageClauses();
if (parseExpected(SyntaxKind.OpenBraceToken)) {
// ClassTail[Yield,Await] : (Modified) See 14.5
@ -5314,7 +5314,7 @@ namespace ts {
return token() === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword);
}
function parseHeritageClauses(isClassHeritageClause: boolean): NodeArray<HeritageClause> {
function parseHeritageClauses(): NodeArray<HeritageClause> {
// ClassTail[Yield,Await] : (Modified) See 14.5
// ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
@ -5362,7 +5362,7 @@ namespace ts {
parseExpected(SyntaxKind.InterfaceKeyword);
node.name = parseIdentifier();
node.typeParameters = parseTypeParameters();
node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause*/ false);
node.heritageClauses = parseHeritageClauses();
node.members = parseObjectTypeMembers();
return addJSDocComment(finishNode(node));
}
@ -5842,7 +5842,7 @@ namespace ts {
}
export function parseJSDocTypeExpressionForTests(content: string, start: number, length: number) {
initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS);
scanner.setText(content, start, length);
currentToken = scanner.scan();
@ -6159,7 +6159,7 @@ namespace ts {
}
export function parseIsolatedJSDocComment(content: string, start: number, length: number) {
initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
initializeState(content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
sourceFile = <SourceFile>{ languageVariant: LanguageVariant.Standard, text: content };
const jsDoc = parseJSDocCommentWorker(start, length);
const diagnostics = parseDiagnostics;

View file

@ -12,7 +12,7 @@ namespace ts.performance {
const profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true
? onProfilerEvent
: (markName: string) => { };
: (_markName: string) => { };
let enabled = false;
let profilerStart = 0;

View file

@ -724,7 +724,7 @@ namespace ts {
}
}
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
return sourceFile.parseDiagnostics;
}
@ -761,16 +761,16 @@ namespace ts {
// Instead, we just report errors for using TypeScript-only constructs from within a
// JavaScript file.
const checkDiagnostics = isSourceFileJavaScript(sourceFile) ?
getJavaScriptSemanticDiagnosticsForFile(sourceFile, cancellationToken) :
getJavaScriptSemanticDiagnosticsForFile(sourceFile) :
typeChecker.getDiagnostics(sourceFile, cancellationToken);
const fileProcessingDiagnosticsInFile = fileProcessingDiagnostics.getDiagnostics(sourceFile.fileName);
const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName);
return bindDiagnostics.concat(checkDiagnostics).concat(fileProcessingDiagnosticsInFile).concat(programDiagnosticsInFile);
return bindDiagnostics.concat(checkDiagnostics, fileProcessingDiagnosticsInFile, programDiagnosticsInFile);
});
}
function getJavaScriptSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): Diagnostic[] {
function getJavaScriptSemanticDiagnosticsForFile(sourceFile: SourceFile): Diagnostic[] {
return runWithCancellationToken(() => {
const diagnostics: Diagnostic[] = [];
walk(sourceFile);
@ -977,7 +977,7 @@ namespace ts {
}
function processRootFile(fileName: string, isDefaultLib: boolean) {
processSourceFile(normalizePath(fileName), isDefaultLib, /*isReference*/ true);
processSourceFile(normalizePath(fileName), isDefaultLib);
}
function fileReferenceIsEqualTo(a: FileReference, b: FileReference): boolean {
@ -1088,7 +1088,7 @@ namespace ts {
/**
* 'isReference' indicates whether the file was brought in via a reference directive (rather than an import declaration)
*/
function processSourceFile(fileName: string, isDefaultLib: boolean, isReference: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
function processSourceFile(fileName: string, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number) {
let diagnosticArgument: string[];
let diagnostic: DiagnosticMessage;
if (hasExtension(fileName)) {
@ -1096,7 +1096,7 @@ namespace ts {
diagnostic = Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1;
diagnosticArgument = [fileName, "'" + supportedExtensions.join("', '") + "'"];
}
else if (!findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd)) {
else if (!findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd)) {
diagnostic = Diagnostics.File_0_not_found;
diagnosticArgument = [fileName];
}
@ -1106,13 +1106,13 @@ namespace ts {
}
}
else {
const nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd);
const nonTsFile: SourceFile = options.allowNonTsExtensions && findSourceFile(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd);
if (!nonTsFile) {
if (options.allowNonTsExtensions) {
diagnostic = Diagnostics.File_0_not_found;
diagnosticArgument = [fileName];
}
else if (!forEach(supportedExtensions, extension => findSourceFile(fileName + extension, toPath(fileName + extension, currentDirectory, getCanonicalFileName), isDefaultLib, isReference, refFile, refPos, refEnd))) {
else if (!forEach(supportedExtensions, extension => findSourceFile(fileName + extension, toPath(fileName + extension, currentDirectory, getCanonicalFileName), isDefaultLib, refFile, refPos, refEnd))) {
diagnostic = Diagnostics.File_0_not_found;
fileName += ".ts";
diagnosticArgument = [fileName];
@ -1141,7 +1141,7 @@ namespace ts {
}
// Get source file from normalized fileName
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, isReference: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, refFile?: SourceFile, refPos?: number, refEnd?: number): SourceFile {
if (filesByName.contains(path)) {
const file = filesByName.get(path);
// try to check if we've already seen this file but with a different casing in path
@ -1155,18 +1155,18 @@ namespace ts {
if (file && sourceFilesFoundSearchingNodeModules[file.path] && currentNodeModulesDepth == 0) {
sourceFilesFoundSearchingNodeModules[file.path] = false;
if (!options.noResolve) {
processReferencedFiles(file, getDirectoryPath(fileName), isDefaultLib);
processReferencedFiles(file, isDefaultLib);
processTypeReferenceDirectives(file);
}
modulesWithElidedImports[file.path] = false;
processImportedModules(file, getDirectoryPath(fileName));
processImportedModules(file);
}
// See if we need to reprocess the imports due to prior skipped imports
else if (file && modulesWithElidedImports[file.path]) {
if (currentNodeModulesDepth < maxNodeModulesJsDepth) {
modulesWithElidedImports[file.path] = false;
processImportedModules(file, getDirectoryPath(fileName));
processImportedModules(file);
}
}
@ -1202,14 +1202,13 @@ namespace ts {
skipDefaultLib = skipDefaultLib || file.hasNoDefaultLib;
const basePath = getDirectoryPath(fileName);
if (!options.noResolve) {
processReferencedFiles(file, basePath, isDefaultLib);
processReferencedFiles(file, isDefaultLib);
processTypeReferenceDirectives(file);
}
// always process imported modules to record module name resolutions
processImportedModules(file, basePath);
processImportedModules(file);
if (isDefaultLib) {
files.unshift(file);
@ -1222,10 +1221,10 @@ namespace ts {
return file;
}
function processReferencedFiles(file: SourceFile, basePath: string, isDefaultLib: boolean) {
function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) {
forEach(file.referencedFiles, ref => {
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
processSourceFile(referencedFileName, isDefaultLib, /*isReference*/ true, file, ref.pos, ref.end);
processSourceFile(referencedFileName, isDefaultLib, file, ref.pos, ref.end);
});
}
@ -1256,7 +1255,7 @@ namespace ts {
if (resolvedTypeReferenceDirective) {
if (resolvedTypeReferenceDirective.primary) {
// resolved from the primary path
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd);
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, refFile, refPos, refEnd);
}
else {
// If we already resolved to this file, it must have been a secondary reference. Check file contents
@ -1276,7 +1275,7 @@ namespace ts {
}
else {
// First resolution of this library
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, /*isReference*/ true, refFile, refPos, refEnd);
processSourceFile(resolvedTypeReferenceDirective.resolvedFileName, /*isDefaultLib*/ false, refFile, refPos, refEnd);
}
}
}
@ -1302,7 +1301,7 @@ namespace ts {
return host.getCanonicalFileName(fileName);
}
function processImportedModules(file: SourceFile, basePath: string) {
function processImportedModules(file: SourceFile) {
collectExternalModuleReferences(file);
if (file.imports.length || file.moduleAugmentations.length) {
file.resolvedModules = createMap<ResolvedModule>();
@ -1333,7 +1332,7 @@ namespace ts {
else if (shouldAddFile) {
findSourceFile(resolution.resolvedFileName,
toPath(resolution.resolvedFileName, currentDirectory, getCanonicalFileName),
/*isDefaultLib*/ false, /*isReference*/ false,
/*isDefaultLib*/ false,
file,
skipTrivia(file.text, file.imports[i].pos),
file.imports[i].end);
@ -1482,7 +1481,7 @@ namespace ts {
const firstNonAmbientExternalModuleSourceFile = forEach(files, f => isExternalModule(f) && !isDeclarationFile(f) ? f : undefined);
if (options.isolatedModules) {
if (options.module === ModuleKind.None && languageVersion < ScriptTarget.ES6) {
if (options.module === ModuleKind.None && languageVersion < ScriptTarget.ES2015) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher));
}
@ -1492,7 +1491,7 @@ namespace ts {
programDiagnostics.add(createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided));
}
}
else if (firstNonAmbientExternalModuleSourceFile && languageVersion < ScriptTarget.ES6 && options.module === ModuleKind.None) {
else if (firstNonAmbientExternalModuleSourceFile && languageVersion < ScriptTarget.ES2015 && options.module === ModuleKind.None) {
// We cannot use createDiagnosticFromNode because nodes do not have parents yet
const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator);
programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none));
@ -1541,7 +1540,7 @@ namespace ts {
if (!options.noEmit && !options.suppressOutputPathCheck) {
const emitHost = getEmitHost();
const emitFilesSeen = createFileMap<boolean>(!host.useCaseSensitiveFileNames() ? key => key.toLocaleLowerCase() : undefined);
forEachExpectedEmitFile(emitHost, (emitFileNames, sourceFiles, isBundledEmit) => {
forEachExpectedEmitFile(emitHost, (emitFileNames) => {
verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen);
verifyEmitFilePath(emitFileNames.declarationFilePath, emitFilesSeen);
});
@ -1553,13 +1552,13 @@ namespace ts {
const emitFilePath = toPath(emitFileName, currentDirectory, getCanonicalFileName);
// Report error if the output overwrites input file
if (filesByName.contains(emitFilePath)) {
createEmitBlockingDiagnostics(emitFileName, emitFilePath, Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file);
createEmitBlockingDiagnostics(emitFileName, Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file);
}
// Report error if multiple files write into same file
if (emitFilesSeen.contains(emitFilePath)) {
// Already seen the same emit file - report error
createEmitBlockingDiagnostics(emitFileName, emitFilePath, Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files);
createEmitBlockingDiagnostics(emitFileName, Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files);
}
else {
emitFilesSeen.set(emitFilePath, true);
@ -1568,7 +1567,7 @@ namespace ts {
}
}
function createEmitBlockingDiagnostics(emitFileName: string, emitFilePath: Path, message: DiagnosticMessage) {
function createEmitBlockingDiagnostics(emitFileName: string, message: DiagnosticMessage) {
hasEmitBlockingDiagnostics.set(toPath(emitFileName, currentDirectory, getCanonicalFileName), true);
programDiagnostics.add(createCompilerDiagnostic(message, emitFileName));
}

View file

@ -723,7 +723,7 @@ namespace ts {
return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial);
}
function appendCommentRange(pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: any, comments: CommentRange[]) {
function appendCommentRange(pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, _state: any, comments: CommentRange[]) {
if (!comments) {
comments = [];
}

View file

@ -46,13 +46,9 @@ namespace ts {
}
declare var require: any;
declare var module: any;
declare var process: any;
declare var global: any;
declare var __filename: string;
declare var Buffer: {
new (str: string, encoding?: string): any;
};
declare class Enumerator {
public atEnd(): boolean;
@ -324,7 +320,7 @@ namespace ts {
const platform: string = _os.platform();
const useCaseSensitiveFileNames = isFileSystemCaseSensitive();
function readFile(fileName: string, encoding?: string): string {
function readFile(fileName: string, _encoding?: string): string {
if (!fileExists(fileName)) {
return undefined;
}
@ -576,7 +572,7 @@ namespace ts {
args: ChakraHost.args,
useCaseSensitiveFileNames: !!ChakraHost.useCaseSensitiveFileNames,
write: ChakraHost.echo,
readFile(path: string, encoding?: string) {
readFile(path: string, _encoding?: string) {
// encoding is automatically handled by the implementation in ChakraHost
return ChakraHost.readFile(path);
},
@ -595,9 +591,9 @@ namespace ts {
getExecutingFilePath: () => ChakraHost.executingFile,
getCurrentDirectory: () => ChakraHost.currentDirectory,
getDirectories: ChakraHost.getDirectories,
getEnvironmentVariable: ChakraHost.getEnvironmentVariable || ((name: string) => ""),
getEnvironmentVariable: ChakraHost.getEnvironmentVariable || (() => ""),
readDirectory: (path: string, extensions?: string[], excludes?: string[], includes?: string[]) => {
const pattern = getFileMatcherPatterns(path, extensions, excludes, includes, !!ChakraHost.useCaseSensitiveFileNames, ChakraHost.currentDirectory);
const pattern = getFileMatcherPatterns(path, excludes, includes, !!ChakraHost.useCaseSensitiveFileNames, ChakraHost.currentDirectory);
return ChakraHost.readDirectory(path, extensions, pattern.basePaths, pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern);
},
exit: ChakraHost.quit,

View file

@ -2,17 +2,19 @@
/// <reference path="transformers/ts.ts" />
/// <reference path="transformers/jsx.ts" />
/// <reference path="transformers/experimental.ts" />
/// <reference path="transformers/es7.ts" />
/// <reference path="transformers/es6.ts" />
/// <reference path="transformers/es2017.ts" />
/// <reference path="transformers/es2016.ts" />
/// <reference path="transformers/es2015.ts" />
/// <reference path="transformers/generators.ts" />
/// <reference path="transformers/es5.ts" />
/// <reference path="transformers/module/module.ts" />
/// <reference path="transformers/module/system.ts" />
/// <reference path="transformers/module/es6.ts" />
/// <reference path="transformers/module/es2015.ts" />
/* @internal */
namespace ts {
const moduleTransformerMap = createMap<Transformer>({
[ModuleKind.ES6]: transformES6Module,
[ModuleKind.ES2015]: transformES2015Module,
[ModuleKind.System]: transformSystemModule,
[ModuleKind.AMD]: transformModule,
[ModuleKind.CommonJS]: transformModule,
@ -117,13 +119,23 @@ namespace ts {
}
transformers.push(transformExperimental);
transformers.push(transformES7);
if (languageVersion < ScriptTarget.ES2017) {
transformers.push(transformES2017);
}
if (languageVersion < ScriptTarget.ES6) {
transformers.push(transformES6);
if (languageVersion < ScriptTarget.ES2016) {
transformers.push(transformES2016);
}
if (languageVersion < ScriptTarget.ES2015) {
transformers.push(transformES2015);
transformers.push(transformGenerators);
}
if (languageVersion < ScriptTarget.ES5) {
transformers.push(transformES5);
}
return transformers;
}
@ -155,7 +167,7 @@ namespace ts {
hoistFunctionDeclaration,
startLexicalEnvironment,
endLexicalEnvironment,
onSubstituteNode: (emitContext, node) => node,
onSubstituteNode: (_emitContext, node) => node,
enableSubstitution,
isSubstitutionEnabled,
onEmitNode: (node, emitContext, emitCallback) => emitCallback(node, emitContext),

View file

@ -51,7 +51,7 @@ namespace ts {
location = value;
}
flattenDestructuring(context, node, value, location, emitAssignment, emitTempVariableAssignment, visitor);
flattenDestructuring(node, value, location, emitAssignment, emitTempVariableAssignment, visitor);
if (needsValue) {
expressions.push(value);
@ -87,13 +87,12 @@ namespace ts {
* @param visitor An optional visitor to use to visit expressions.
*/
export function flattenParameterDestructuring(
context: TransformationContext,
node: ParameterDeclaration,
value: Expression,
visitor?: (node: Node) => VisitResult<Node>) {
const declarations: VariableDeclaration[] = [];
flattenDestructuring(context, node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
return declarations;
@ -123,7 +122,6 @@ namespace ts {
* @param visitor An optional visitor to use to visit expressions.
*/
export function flattenVariableDestructuring(
context: TransformationContext,
node: VariableDeclaration,
value?: Expression,
visitor?: (node: Node) => VisitResult<Node>,
@ -131,7 +129,7 @@ namespace ts {
const declarations: VariableDeclaration[] = [];
let pendingAssignments: Expression[];
flattenDestructuring(context, node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
return declarations;
@ -180,7 +178,6 @@ namespace ts {
* @param visitor An optional visitor to use to visit expressions.
*/
export function flattenVariableDestructuringToExpression(
context: TransformationContext,
node: VariableDeclaration,
recordTempVariable: (name: Identifier) => void,
nameSubstitution?: (name: Identifier) => Expression,
@ -188,7 +185,7 @@ namespace ts {
const pendingAssignments: Expression[] = [];
flattenDestructuring(context, node, /*value*/ undefined, node, emitAssignment, emitTempVariableAssignment, visitor);
flattenDestructuring(node, /*value*/ undefined, node, emitAssignment, emitTempVariableAssignment, visitor);
const expression = inlineExpressions(pendingAssignments);
aggregateTransformFlags(expression);
@ -219,7 +216,6 @@ namespace ts {
}
function flattenDestructuring(
context: TransformationContext,
root: VariableDeclaration | ParameterDeclaration | BindingElement | BinaryExpression,
value: Expression,
location: TextRange,

View file

@ -4,7 +4,7 @@
/*@internal*/
namespace ts {
const enum ES6SubstitutionFlags {
const enum ES2015SubstitutionFlags {
/** Enables substitutions for captured `this` */
CapturedThis = 1 << 0,
/** Enables substitutions for block-scoped bindings. */
@ -163,7 +163,7 @@ namespace ts {
ReplaceWithReturn,
}
export function transformES6(context: TransformationContext) {
export function transformES2015(context: TransformationContext) {
const {
startLexicalEnvironment,
endLexicalEnvironment,
@ -197,7 +197,7 @@ namespace ts {
* They are persisted between each SourceFile transformation and should not
* be reset.
*/
let enabledSubstitutions: ES6SubstitutionFlags;
let enabledSubstitutions: ES2015SubstitutionFlags;
return transformSourceFile;
@ -252,7 +252,7 @@ namespace ts {
}
function shouldCheckNode(node: Node): boolean {
return (node.transformFlags & TransformFlags.ES6) !== 0 ||
return (node.transformFlags & TransformFlags.ES2015) !== 0 ||
node.kind === SyntaxKind.LabeledStatement ||
(isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node));
}
@ -261,7 +261,7 @@ namespace ts {
if (shouldCheckNode(node)) {
return visitJavaScript(node);
}
else if (node.transformFlags & TransformFlags.ContainsES6) {
else if (node.transformFlags & TransformFlags.ContainsES2015) {
return visitEachChild(node, visitor, context);
}
else {
@ -396,7 +396,7 @@ namespace ts {
return visitYieldExpression(<YieldExpression>node);
case SyntaxKind.SuperKeyword:
return visitSuperKeyword(<PrimaryExpression>node);
return visitSuperKeyword();
case SyntaxKind.YieldExpression:
// `yield` will be handled by a generators transform.
@ -681,6 +681,7 @@ namespace ts {
const extendsClauseElement = getClassExtendsHeritageClauseElement(node);
const classFunction = createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -1117,7 +1118,7 @@ namespace ts {
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(
flattenParameterDestructuring(context, parameter, temp, visitor)
flattenParameterDestructuring(parameter, temp, visitor)
)
),
EmitFlags.CustomPrologue
@ -1416,6 +1417,7 @@ namespace ts {
if (getAccessor) {
const getterFunction = transformFunctionLikeToExpression(getAccessor, /*location*/ undefined, /*name*/ undefined);
setSourceMapRange(getterFunction, getSourceMapRange(getAccessor));
setEmitFlags(getterFunction, EmitFlags.NoLeadingComments);
const getter = createPropertyAssignment("get", getterFunction);
setCommentRange(getter, getCommentRange(getAccessor));
properties.push(getter);
@ -1424,6 +1426,7 @@ namespace ts {
if (setAccessor) {
const setterFunction = transformFunctionLikeToExpression(setAccessor, /*location*/ undefined, /*name*/ undefined);
setSourceMapRange(setterFunction, getSourceMapRange(setAccessor));
setEmitFlags(setterFunction, EmitFlags.NoLeadingComments);
const setter = createPropertyAssignment("set", setterFunction);
setCommentRange(setter, getCommentRange(setAccessor));
properties.push(setter);
@ -1509,6 +1512,7 @@ namespace ts {
const expression = setOriginalNode(
createFunctionExpression(
/*modifiers*/ undefined,
node.asteriskToken,
name,
/*typeParameters*/ undefined,
@ -1686,7 +1690,7 @@ namespace ts {
if (decl.initializer) {
let assignment: Expression;
if (isBindingPattern(decl.name)) {
assignment = flattenVariableDestructuringToExpression(context, decl, hoistVariableDeclaration, /*nameSubstitution*/ undefined, visitor);
assignment = flattenVariableDestructuringToExpression(decl, hoistVariableDeclaration, /*nameSubstitution*/ undefined, visitor);
}
else {
assignment = createBinary(<Identifier>decl.name, SyntaxKind.EqualsToken, visitNode(decl.initializer, visitor, isExpression));
@ -1839,7 +1843,7 @@ namespace ts {
if (isBindingPattern(node.name)) {
const recordTempVariablesInLine = !enclosingVariableStatement
|| !hasModifier(enclosingVariableStatement, ModifierFlags.Export);
return flattenVariableDestructuring(context, node, /*value*/ undefined, visitor,
return flattenVariableDestructuring(node, /*value*/ undefined, visitor,
recordTempVariablesInLine ? undefined : hoistVariableDeclaration);
}
@ -1942,7 +1946,6 @@ namespace ts {
// This works whether the declaration is a var, let, or const.
// It will use rhsIterationValue _a[_i] as the initializer.
const declarations = flattenVariableDestructuring(
context,
firstOriginalDeclaration,
createElementAccess(rhsReference, counter),
visitor
@ -2240,6 +2243,7 @@ namespace ts {
/*type*/ undefined,
setEmitFlags(
createFunctionExpression(
/*modifiers*/ undefined,
isAsyncBlockContainingAwait ? createToken(SyntaxKind.AsteriskToken) : undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -2534,15 +2538,15 @@ namespace ts {
break;
case SyntaxKind.PropertyAssignment:
expressions.push(transformPropertyAssignmentToExpression(node, <PropertyAssignment>property, receiver, node.multiLine));
expressions.push(transformPropertyAssignmentToExpression(<PropertyAssignment>property, receiver, node.multiLine));
break;
case SyntaxKind.ShorthandPropertyAssignment:
expressions.push(transformShorthandPropertyAssignmentToExpression(node, <ShorthandPropertyAssignment>property, receiver, node.multiLine));
expressions.push(transformShorthandPropertyAssignmentToExpression(<ShorthandPropertyAssignment>property, receiver, node.multiLine));
break;
case SyntaxKind.MethodDeclaration:
expressions.push(transformObjectLiteralMethodDeclarationToExpression(node, <MethodDeclaration>property, receiver, node.multiLine));
expressions.push(transformObjectLiteralMethodDeclarationToExpression(<MethodDeclaration>property, receiver, node.multiLine));
break;
default:
@ -2559,7 +2563,7 @@ namespace ts {
* @param property The PropertyAssignment node.
* @param receiver The receiver for the assignment.
*/
function transformPropertyAssignmentToExpression(node: ObjectLiteralExpression, property: PropertyAssignment, receiver: Expression, startsOnNewLine: boolean) {
function transformPropertyAssignmentToExpression(property: PropertyAssignment, receiver: Expression, startsOnNewLine: boolean) {
const expression = createAssignment(
createMemberAccessForPropertyName(
receiver,
@ -2581,7 +2585,7 @@ namespace ts {
* @param property The ShorthandPropertyAssignment node.
* @param receiver The receiver for the assignment.
*/
function transformShorthandPropertyAssignmentToExpression(node: ObjectLiteralExpression, property: ShorthandPropertyAssignment, receiver: Expression, startsOnNewLine: boolean) {
function transformShorthandPropertyAssignmentToExpression(property: ShorthandPropertyAssignment, receiver: Expression, startsOnNewLine: boolean) {
const expression = createAssignment(
createMemberAccessForPropertyName(
receiver,
@ -2603,7 +2607,7 @@ namespace ts {
* @param method The MethodDeclaration node.
* @param receiver The receiver for the assignment.
*/
function transformObjectLiteralMethodDeclarationToExpression(node: ObjectLiteralExpression, method: MethodDeclaration, receiver: Expression, startsOnNewLine: boolean) {
function transformObjectLiteralMethodDeclarationToExpression(method: MethodDeclaration, receiver: Expression, startsOnNewLine: boolean) {
const expression = createAssignment(
createMemberAccessForPropertyName(
receiver,
@ -2793,7 +2797,7 @@ namespace ts {
// expressions into an array literal.
const numElements = elements.length;
const segments = flatten(
spanMap(elements, partitionSpread, (partition, visitPartition, start, end) =>
spanMap(elements, partitionSpread, (partition, visitPartition, _start, end) =>
visitPartition(partition, multiLine, hasTrailingComma && end === numElements)
)
);
@ -2815,7 +2819,7 @@ namespace ts {
: visitSpanOfNonSpreads;
}
function visitSpanOfSpreads(chunk: Expression[], multiLine: boolean, hasTrailingComma: boolean): VisitResult<Expression> {
function visitSpanOfSpreads(chunk: Expression[]): VisitResult<Expression> {
return map(chunk, visitExpressionOfSpread);
}
@ -3004,7 +3008,7 @@ namespace ts {
/**
* Visits the `super` keyword
*/
function visitSuperKeyword(node: PrimaryExpression): LeftHandSideExpression {
function visitSuperKeyword(): LeftHandSideExpression {
return enclosingNonAsyncFunctionBody
&& isClassElement(enclosingNonAsyncFunctionBody)
&& !hasModifier(enclosingNonAsyncFunctionBody, ModifierFlags.Static)
@ -3034,7 +3038,7 @@ namespace ts {
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
const savedEnclosingFunction = enclosingFunction;
if (enabledSubstitutions & ES6SubstitutionFlags.CapturedThis && isFunctionLike(node)) {
if (enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis && isFunctionLike(node)) {
// If we are tracking a captured `this`, keep track of the enclosing function.
enclosingFunction = node;
}
@ -3049,8 +3053,8 @@ namespace ts {
* contains block-scoped bindings (e.g. `let` or `const`).
*/
function enableSubstitutionsForBlockScopedBindings() {
if ((enabledSubstitutions & ES6SubstitutionFlags.BlockScopedBindings) === 0) {
enabledSubstitutions |= ES6SubstitutionFlags.BlockScopedBindings;
if ((enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings) === 0) {
enabledSubstitutions |= ES2015SubstitutionFlags.BlockScopedBindings;
context.enableSubstitution(SyntaxKind.Identifier);
}
}
@ -3060,8 +3064,8 @@ namespace ts {
* contains a captured `this`.
*/
function enableSubstitutionsForCapturedThis() {
if ((enabledSubstitutions & ES6SubstitutionFlags.CapturedThis) === 0) {
enabledSubstitutions |= ES6SubstitutionFlags.CapturedThis;
if ((enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis) === 0) {
enabledSubstitutions |= ES2015SubstitutionFlags.CapturedThis;
context.enableSubstitution(SyntaxKind.ThisKeyword);
context.enableEmitNotification(SyntaxKind.Constructor);
context.enableEmitNotification(SyntaxKind.MethodDeclaration);
@ -3100,7 +3104,7 @@ namespace ts {
function substituteIdentifier(node: Identifier) {
// Only substitute the identifier if we have enabled substitutions for block-scoped
// bindings.
if (enabledSubstitutions & ES6SubstitutionFlags.BlockScopedBindings) {
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings) {
const original = getParseTreeNode(node, isIdentifier);
if (original && isNameOfDeclarationWithCollidingName(original)) {
return getGeneratedNameForNode(original);
@ -3153,7 +3157,7 @@ namespace ts {
* @param node An Identifier node.
*/
function substituteExpressionIdentifier(node: Identifier): Identifier {
if (enabledSubstitutions & ES6SubstitutionFlags.BlockScopedBindings) {
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings) {
const declaration = resolver.getReferencedDeclarationWithCollidingName(node);
if (declaration) {
return getGeneratedNameForNode(declaration.name);
@ -3169,7 +3173,7 @@ namespace ts {
* @param node The ThisKeyword node.
*/
function substituteThisKeyword(node: PrimaryExpression): PrimaryExpression {
if (enabledSubstitutions & ES6SubstitutionFlags.CapturedThis
if (enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis
&& enclosingFunction
&& getEmitFlags(enclosingFunction) & EmitFlags.CapturesThis) {
return createIdentifier("_this", /*location*/ node);

View file

@ -3,7 +3,7 @@
/*@internal*/
namespace ts {
export function transformES7(context: TransformationContext) {
export function transformES2016(context: TransformationContext) {
const { hoistVariableDeclaration } = context;
return transformSourceFile;
@ -17,10 +17,10 @@ namespace ts {
}
function visitor(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.ES7) {
if (node.transformFlags & TransformFlags.ES2016) {
return visitorWorker(node);
}
else if (node.transformFlags & TransformFlags.ContainsES7) {
else if (node.transformFlags & TransformFlags.ContainsES2016) {
return visitEachChild(node, visitor, context);
}
else {
@ -39,7 +39,7 @@ namespace ts {
}
function visitBinaryExpression(node: BinaryExpression): Expression {
// We are here because ES7 adds support for the exponentiation operator.
// We are here because ES2016 adds support for the exponentiation operator.
const left = visitNode(node.left, visitor, isExpression);
const right = visitNode(node.right, visitor, isExpression);
if (node.operatorToken.kind === SyntaxKind.AsteriskAsteriskEqualsToken) {

View file

@ -0,0 +1,510 @@
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/*@internal*/
namespace ts {
type SuperContainer = ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration;
export function transformES2017(context: TransformationContext) {
const enum ES2017SubstitutionFlags {
/** Enables substitutions for async methods with `super` calls. */
AsyncMethodsWithSuper = 1 << 0
}
const {
startLexicalEnvironment,
endLexicalEnvironment,
} = context;
const resolver = context.getEmitResolver();
const compilerOptions = context.getCompilerOptions();
const languageVersion = getEmitScriptTarget(compilerOptions);
// These variables contain state that changes as we descend into the tree.
let currentSourceFileExternalHelpersModuleName: Identifier;
/**
* Keeps track of whether expression substitution has been enabled for specific edge cases.
* They are persisted between each SourceFile transformation and should not be reset.
*/
let enabledSubstitutions: ES2017SubstitutionFlags;
/**
* Keeps track of whether we are within any containing namespaces when performing
* just-in-time substitution while printing an expression identifier.
*/
let applicableSubstitutions: ES2017SubstitutionFlags;
/**
* This keeps track of containers where `super` is valid, for use with
* just-in-time substitution for `super` expressions inside of async methods.
*/
let currentSuperContainer: SuperContainer;
// Save the previous transformation hooks.
const previousOnEmitNode = context.onEmitNode;
const previousOnSubstituteNode = context.onSubstituteNode;
// Set new transformation hooks.
context.onEmitNode = onEmitNode;
context.onSubstituteNode = onSubstituteNode;
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
if (isDeclarationFile(node)) {
return node;
}
currentSourceFileExternalHelpersModuleName = node.externalHelpersModuleName;
return visitEachChild(node, visitor, context);
}
function visitor(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.ES2017) {
return visitorWorker(node);
}
else if (node.transformFlags & TransformFlags.ContainsES2017) {
return visitEachChild(node, visitor, context);
}
return node;
}
function visitorWorker(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.AsyncKeyword:
// ES2017 async modifier should be elided for targets < ES2017
return undefined;
case SyntaxKind.AwaitExpression:
// ES2017 'await' expressions must be transformed for targets < ES2017.
return visitAwaitExpression(<AwaitExpression>node);
case SyntaxKind.MethodDeclaration:
// ES2017 method declarations may be 'async'
return visitMethodDeclaration(<MethodDeclaration>node);
case SyntaxKind.FunctionDeclaration:
// ES2017 function declarations may be 'async'
return visitFunctionDeclaration(<FunctionDeclaration>node);
case SyntaxKind.FunctionExpression:
// ES2017 function expressions may be 'async'
return visitFunctionExpression(<FunctionExpression>node);
case SyntaxKind.ArrowFunction:
// ES2017 arrow functions may be 'async'
return visitArrowFunction(<ArrowFunction>node);
default:
Debug.failBadSyntaxKind(node);
return node;
}
}
/**
* Visits an await expression.
*
* This function will be called any time a ES2017 await expression is encountered.
*
* @param node The await expression node.
*/
function visitAwaitExpression(node: AwaitExpression): Expression {
return setOriginalNode(
createYield(
/*asteriskToken*/ undefined,
visitNode(node.expression, visitor, isExpression),
/*location*/ node
),
node
);
}
/**
* Visits a method declaration of a class.
*
* This function will be called when one of the following conditions are met:
* - The node is marked as async
*
* @param node The method node.
*/
function visitMethodDeclaration(node: MethodDeclaration) {
if (!isAsyncFunctionLike(node)) {
return node;
}
const method = createMethod(
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
/*type*/ undefined,
transformFunctionBody(node),
/*location*/ node
);
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setCommentRange(method, node);
setSourceMapRange(method, moveRangePastDecorators(node));
setOriginalNode(method, node);
return method;
}
/**
* Visits a function declaration.
*
* This function will be called when one of the following conditions are met:
* - The node is marked async
*
* @param node The function node.
*/
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
if (!isAsyncFunctionLike(node)) {
return node;
}
const func = createFunctionDeclaration(
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
/*type*/ undefined,
transformFunctionBody(node),
/*location*/ node
);
setOriginalNode(func, node);
return func;
}
/**
* Visits a function expression node.
*
* This function will be called when one of the following conditions are met:
* - The node is marked async
*
* @param node The function expression node.
*/
function visitFunctionExpression(node: FunctionExpression): Expression {
if (!isAsyncFunctionLike(node)) {
return node;
}
if (nodeIsMissing(node.body)) {
return createOmittedExpression();
}
const func = createFunctionExpression(
/*modifiers*/ undefined,
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
/*type*/ undefined,
transformFunctionBody(node),
/*location*/ node
);
setOriginalNode(func, node);
return func;
}
/**
* @remarks
* This function will be called when one of the following conditions are met:
* - The node is marked async
*/
function visitArrowFunction(node: ArrowFunction) {
if (!isAsyncFunctionLike(node)) {
return node;
}
const func = createArrowFunction(
visitNodes(node.modifiers, visitor, isModifier),
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
/*type*/ undefined,
node.equalsGreaterThanToken,
transformConciseBody(node),
/*location*/ node
);
setOriginalNode(func, node);
return func;
}
function transformFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody {
return <FunctionBody>transformAsyncFunctionBody(node);
}
function transformConciseBody(node: ArrowFunction): ConciseBody {
return transformAsyncFunctionBody(node);
}
function transformFunctionBodyWorker(body: Block, start = 0) {
const savedCurrentScope = currentScope;
currentScope = body;
startLexicalEnvironment();
const statements = visitNodes(body.statements, visitor, isStatement, start);
const visited = updateBlock(body, statements);
const declarations = endLexicalEnvironment();
currentScope = savedCurrentScope;
return mergeFunctionBodyLexicalEnvironment(visited, declarations);
}
function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody {
const nodeType = node.original ? (<FunctionLikeDeclaration>node.original).type : node.type;
const promiseConstructor = languageVersion < ScriptTarget.ES2015 ? getPromiseConstructor(nodeType) : undefined;
const isArrowFunction = node.kind === SyntaxKind.ArrowFunction;
const hasLexicalArguments = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0;
// An async function is emit as an outer function that calls an inner
// generator function. To preserve lexical bindings, we pass the current
// `this` and `arguments` objects to `__awaiter`. The generator function
// passed to `__awaiter` is executed inside of the callback to the
// promise constructor.
if (!isArrowFunction) {
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, (<Block>node.body).statements, /*ensureUseStrict*/ false, visitor);
statements.push(
createReturn(
createAwaiterHelper(
currentSourceFileExternalHelpersModuleName,
hasLexicalArguments,
promiseConstructor,
transformFunctionBodyWorker(<Block>node.body, statementOffset)
)
)
);
const block = createBlock(statements, /*location*/ node.body, /*multiLine*/ true);
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
if (languageVersion >= ScriptTarget.ES2015) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
enableSubstitutionForAsyncMethodsWithSuper();
setEmitFlags(block, EmitFlags.EmitAdvancedSuperHelper);
}
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) {
enableSubstitutionForAsyncMethodsWithSuper();
setEmitFlags(block, EmitFlags.EmitSuperHelper);
}
}
return block;
}
else {
return createAwaiterHelper(
currentSourceFileExternalHelpersModuleName,
hasLexicalArguments,
promiseConstructor,
<Block>transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ true)
);
}
}
function transformConciseBodyWorker(body: Block | Expression, forceBlockFunctionBody: boolean) {
if (isBlock(body)) {
return transformFunctionBodyWorker(body);
}
else {
startLexicalEnvironment();
const visited: Expression | Block = visitNode(body, visitor, isConciseBody);
const declarations = endLexicalEnvironment();
const merged = mergeFunctionBodyLexicalEnvironment(visited, declarations);
if (forceBlockFunctionBody && !isBlock(merged)) {
return createBlock([
createReturn(<Expression>merged)
]);
}
else {
return merged;
}
}
}
function getPromiseConstructor(type: TypeNode) {
const typeName = getEntityNameFromTypeNode(type);
if (typeName && isEntityName(typeName)) {
const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue
|| serializationKind === TypeReferenceSerializationKind.Unknown) {
return typeName;
}
}
return undefined;
}
function enableSubstitutionForAsyncMethodsWithSuper() {
if ((enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper) === 0) {
enabledSubstitutions |= ES2017SubstitutionFlags.AsyncMethodsWithSuper;
// We need to enable substitutions for call, property access, and element access
// if we need to rewrite super calls.
context.enableSubstitution(SyntaxKind.CallExpression);
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
context.enableSubstitution(SyntaxKind.ElementAccessExpression);
// We need to be notified when entering and exiting declarations that bind super.
context.enableEmitNotification(SyntaxKind.ClassDeclaration);
context.enableEmitNotification(SyntaxKind.MethodDeclaration);
context.enableEmitNotification(SyntaxKind.GetAccessor);
context.enableEmitNotification(SyntaxKind.SetAccessor);
context.enableEmitNotification(SyntaxKind.Constructor);
}
}
function substituteExpression(node: Expression) {
switch (node.kind) {
case SyntaxKind.PropertyAccessExpression:
return substitutePropertyAccessExpression(<PropertyAccessExpression>node);
case SyntaxKind.ElementAccessExpression:
return substituteElementAccessExpression(<ElementAccessExpression>node);
case SyntaxKind.CallExpression:
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper) {
return substituteCallExpression(<CallExpression>node);
}
break;
}
return node;
}
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
const flags = getSuperContainerAsyncMethodFlags();
if (flags) {
return createSuperAccessInAsyncMethod(
createLiteral(node.name.text),
flags,
node
);
}
}
return node;
}
function substituteElementAccessExpression(node: ElementAccessExpression) {
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
const flags = getSuperContainerAsyncMethodFlags();
if (flags) {
return createSuperAccessInAsyncMethod(
node.argumentExpression,
flags,
node
);
}
}
return node;
}
function substituteCallExpression(node: CallExpression): Expression {
const expression = node.expression;
if (isSuperProperty(expression)) {
const flags = getSuperContainerAsyncMethodFlags();
if (flags) {
const argumentExpression = isPropertyAccessExpression(expression)
? substitutePropertyAccessExpression(expression)
: substituteElementAccessExpression(expression);
return createCall(
createPropertyAccess(argumentExpression, "call"),
/*typeArguments*/ undefined,
[
createThis(),
...node.arguments
]
);
}
}
return node;
}
function isSuperContainer(node: Node): node is SuperContainer {
const kind = node.kind;
return kind === SyntaxKind.ClassDeclaration
|| kind === SyntaxKind.Constructor
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.GetAccessor
|| kind === SyntaxKind.SetAccessor;
}
/**
* Hook for node emit.
*
* @param node The node to emit.
* @param emit A callback used to emit the node in the printer.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
const savedApplicableSubstitutions = applicableSubstitutions;
const savedCurrentSuperContainer = currentSuperContainer;
// If we need to support substitutions for `super` in an async method,
// we should track it here.
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
currentSuperContainer = node;
}
previousOnEmitNode(emitContext, node, emitCallback);
applicableSubstitutions = savedApplicableSubstitutions;
currentSuperContainer = savedCurrentSuperContainer;
}
/**
* Hooks node substitutions.
*
* @param node The node to substitute.
* @param isExpression A value indicating whether the node is to be used in an expression
* position.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
node = previousOnSubstituteNode(emitContext, node);
if (emitContext === EmitContext.Expression) {
return substituteExpression(<Expression>node);
}
return node;
}
function createSuperAccessInAsyncMethod(argumentExpression: Expression, flags: NodeCheckFlags, location: TextRange): LeftHandSideExpression {
if (flags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
return createPropertyAccess(
createCall(
createIdentifier("_super"),
/*typeArguments*/ undefined,
[argumentExpression]
),
"value",
location
);
}
else {
return createCall(
createIdentifier("_super"),
/*typeArguments*/ undefined,
[argumentExpression],
location
);
}
}
function getSuperContainerAsyncMethodFlags() {
return currentSuperContainer !== undefined
&& resolver.getNodeCheckFlags(currentSuperContainer) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
}
}
}

View file

@ -0,0 +1,83 @@
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/*@internal*/
namespace ts {
/**
* Transforms ES5 syntax into ES3 syntax.
*
* @param context Context and state information for the transformation.
*/
export function transformES5(context: TransformationContext) {
const previousOnSubstituteNode = context.onSubstituteNode;
context.onSubstituteNode = onSubstituteNode;
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
context.enableSubstitution(SyntaxKind.PropertyAssignment);
return transformSourceFile;
/**
* Transforms an ES5 source file to ES3.
*
* @param node A SourceFile
*/
function transformSourceFile(node: SourceFile) {
return node;
}
/**
* Hooks node substitutions.
*
* @param emitContext The context for the emitter.
* @param node The node to substitute.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
node = previousOnSubstituteNode(emitContext, node);
if (isPropertyAccessExpression(node)) {
return substitutePropertyAccessExpression(node);
}
else if (isPropertyAssignment(node)) {
return substitutePropertyAssignment(node);
}
return node;
}
/**
* Substitutes a PropertyAccessExpression whose name is a reserved word.
*
* @param node A PropertyAccessExpression
*/
function substitutePropertyAccessExpression(node: PropertyAccessExpression): Expression {
const literalName = trySubstituteReservedName(node.name);
if (literalName) {
return createElementAccess(node.expression, literalName, /*location*/ node);
}
return node;
}
/**
* Substitutes a PropertyAssignment whose name is a reserved word.
*
* @param node A PropertyAssignment
*/
function substitutePropertyAssignment(node: PropertyAssignment): PropertyAssignment {
const literalName = isIdentifier(node.name) && trySubstituteReservedName(node.name);
if (literalName) {
return updatePropertyAssignment(node, literalName, node.initializer);
}
return node;
}
/**
* If an identifier name is a reserved word, returns a string literal for the name.
*
* @param name An Identifier
*/
function trySubstituteReservedName(name: Identifier) {
const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(name.text) : undefined);
if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) {
return createLiteral(name, /*location*/ name);
}
return undefined;
}
}
}

View file

@ -496,6 +496,7 @@ namespace ts {
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
node = setOriginalNode(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
node.name,
/*typeParameters*/ undefined,
@ -955,7 +956,7 @@ namespace ts {
* @param elements The elements to visit.
* @param multiLine Whether array literals created should be emitted on multiple lines.
*/
function visitElements(elements: NodeArray<Expression>, multiLine: boolean) {
function visitElements(elements: NodeArray<Expression>, _multiLine?: boolean) {
// [source]
// ar = [1, yield, 2];
//
@ -1101,7 +1102,7 @@ namespace ts {
createFunctionApply(
cacheExpression(visitNode(target, visitor, isLeftHandSideExpression)),
thisArg,
visitElements(node.arguments, /*multiLine*/ false),
visitElements(node.arguments),
/*location*/ node
),
node
@ -1130,7 +1131,7 @@ namespace ts {
createFunctionApply(
cacheExpression(visitNode(target, visitor, isExpression)),
thisArg,
visitElements(node.arguments, /*multiLine*/ false)
visitElements(node.arguments)
),
/*typeArguments*/ undefined,
[],
@ -2591,6 +2592,7 @@ namespace ts {
createThis(),
setEmitFlags(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -3080,4 +3082,4 @@ namespace ts {
);
}
}
}
}

View file

@ -0,0 +1,39 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/*@internal*/
namespace ts {
export function transformES2015Module(context: TransformationContext) {
const compilerOptions = context.getCompilerOptions();
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
if (isDeclarationFile(node)) {
return node;
}
if (isExternalModule(node) || compilerOptions.isolatedModules) {
return visitEachChild(node, visitor, context);
}
return node;
}
function visitor(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.ImportEqualsDeclaration:
// Elide `import=` as it is not legal with --module ES6
return undefined;
case SyntaxKind.ExportAssignment:
return visitExportAssignment(<ExportAssignment>node);
}
return node;
}
function visitExportAssignment(node: ExportAssignment): VisitResult<ExportAssignment> {
// Elide `export=` as it is not legal with --module ES6
return node.isExportEquals ? undefined : node;
}
}
}

View file

@ -1,144 +0,0 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/*@internal*/
namespace ts {
export function transformES6Module(context: TransformationContext) {
const compilerOptions = context.getCompilerOptions();
const resolver = context.getEmitResolver();
let currentSourceFile: SourceFile;
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
if (isDeclarationFile(node)) {
return node;
}
if (isExternalModule(node) || compilerOptions.isolatedModules) {
currentSourceFile = node;
return visitEachChild(node, visitor, context);
}
return node;
}
function visitor(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
return visitImportDeclaration(<ImportDeclaration>node);
case SyntaxKind.ImportEqualsDeclaration:
return visitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
case SyntaxKind.ImportClause:
return visitImportClause(<ImportClause>node);
case SyntaxKind.NamedImports:
case SyntaxKind.NamespaceImport:
return visitNamedBindings(<NamedImportBindings>node);
case SyntaxKind.ImportSpecifier:
return visitImportSpecifier(<ImportSpecifier>node);
case SyntaxKind.ExportAssignment:
return visitExportAssignment(<ExportAssignment>node);
case SyntaxKind.ExportDeclaration:
return visitExportDeclaration(<ExportDeclaration>node);
case SyntaxKind.NamedExports:
return visitNamedExports(<NamedExports>node);
case SyntaxKind.ExportSpecifier:
return visitExportSpecifier(<ExportSpecifier>node);
}
return node;
}
function visitExportAssignment(node: ExportAssignment): ExportAssignment {
if (node.isExportEquals) {
return undefined; // do not emit export equals for ES6
}
const original = getOriginalNode(node);
return nodeIsSynthesized(original) || resolver.isValueAliasDeclaration(original) ? node : undefined;
}
function visitExportDeclaration(node: ExportDeclaration): ExportDeclaration {
if (!node.exportClause) {
return resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined;
}
if (!resolver.isValueAliasDeclaration(node)) {
return undefined;
}
const newExportClause = visitNode(node.exportClause, visitor, isNamedExports, /*optional*/ true);
if (node.exportClause === newExportClause) {
return node;
}
return newExportClause
? createExportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
newExportClause,
node.moduleSpecifier)
: undefined;
}
function visitNamedExports(node: NamedExports): NamedExports {
const newExports = visitNodes(node.elements, visitor, isExportSpecifier);
if (node.elements === newExports) {
return node;
}
return newExports.length ? createNamedExports(newExports) : undefined;
}
function visitExportSpecifier(node: ExportSpecifier): ExportSpecifier {
return resolver.isValueAliasDeclaration(node) ? node : undefined;
}
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): ImportEqualsDeclaration {
return !isExternalModuleImportEqualsDeclaration(node) || resolver.isReferencedAliasDeclaration(node) ? node : undefined;
}
function visitImportDeclaration(node: ImportDeclaration) {
if (node.importClause) {
const newImportClause = visitNode(node.importClause, visitor, isImportClause);
if (!newImportClause.name && !newImportClause.namedBindings) {
return undefined;
}
else if (newImportClause !== node.importClause) {
return createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
newImportClause,
node.moduleSpecifier);
}
}
return node;
}
function visitImportClause(node: ImportClause): ImportClause {
let newDefaultImport = node.name;
if (!resolver.isReferencedAliasDeclaration(node)) {
newDefaultImport = undefined;
}
const newNamedBindings = visitNode(node.namedBindings, visitor, isNamedImportBindings, /*optional*/ true);
return newDefaultImport !== node.name || newNamedBindings !== node.namedBindings
? createImportClause(newDefaultImport, newNamedBindings)
: node;
}
function visitNamedBindings(node: NamedImportBindings): VisitResult<NamedImportBindings> {
if (node.kind === SyntaxKind.NamespaceImport) {
return resolver.isReferencedAliasDeclaration(node) ? node : undefined;
}
else {
const newNamedImportElements = visitNodes((<NamedImports>node).elements, visitor, isImportSpecifier);
if (!newNamedImportElements || newNamedImportElements.length == 0) {
return undefined;
}
if (newNamedImportElements === (<NamedImports>node).elements) {
return node;
}
return createNamedImports(newNamedImportElements);
}
}
function visitImportSpecifier(node: ImportSpecifier) {
return resolver.isReferencedAliasDeclaration(node) ? node : undefined;
}
}
}

View file

@ -59,7 +59,7 @@ namespace ts {
currentSourceFile = node;
// Collect information about the external module.
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node, resolver));
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node));
// Perform the transformation.
const transformModule = transformModuleDelegates[moduleKind] || transformModuleDelegates[ModuleKind.None];
@ -179,6 +179,7 @@ namespace ts {
//
// function (require, exports, module1, module2) ...
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -228,7 +229,7 @@ namespace ts {
}
function addExportEqualsIfNeeded(statements: Statement[], emitAsReturn: boolean) {
if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) {
if (exportEquals) {
if (emitAsReturn) {
const statement = createReturn(
exportEquals.expression,
@ -415,7 +416,7 @@ namespace ts {
)
],
/*location*/ undefined,
/*flags*/ languageVersion >= ScriptTarget.ES6 ? NodeFlags.Const : NodeFlags.None),
/*flags*/ languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None),
/*location*/ node
)
);
@ -461,23 +462,21 @@ namespace ts {
);
}
for (const specifier of node.exportClause.elements) {
if (resolver.isValueAliasDeclaration(specifier)) {
const exportedValue = createPropertyAccess(
generatedName,
specifier.propertyName || specifier.name
);
statements.push(
createStatement(
createExportAssignment(specifier.name, exportedValue),
/*location*/ specifier
)
);
}
const exportedValue = createPropertyAccess(
generatedName,
specifier.propertyName || specifier.name
);
statements.push(
createStatement(
createExportAssignment(specifier.name, exportedValue),
/*location*/ specifier
)
);
}
return singleOrMany(statements);
}
else if (resolver.moduleExportsSomeValue(node.moduleSpecifier)) {
else {
// export * from "mod";
return createStatement(
createCall(
@ -495,15 +494,14 @@ namespace ts {
}
function visitExportAssignment(node: ExportAssignment): VisitResult<Statement> {
if (!node.isExportEquals) {
if (nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) {
const statements: Statement[] = [];
addExportDefault(statements, node.expression, /*location*/ node);
return statements;
}
if (node.isExportEquals) {
// Elide as `export=` is handled in addExportEqualsIfNeeded
return undefined;
}
return undefined;
const statements: Statement[] = [];
addExportDefault(statements, node.expression, /*location*/ node);
return statements;
}
function addExportDefault(statements: Statement[], expression: Expression, location: TextRange): void {
@ -568,7 +566,7 @@ namespace ts {
}
function collectExportMembers(names: Identifier[], node: Node): Identifier[] {
if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node) && isDeclaration(node)) {
if (isAliasSymbolDeclaration(node) && isDeclaration(node)) {
const name = node.name;
if (isIdentifier(name)) {
names.push(name);
@ -682,7 +680,6 @@ namespace ts {
const name = node.name;
if (isBindingPattern(name)) {
return flattenVariableDestructuringToExpression(
context,
node,
hoistVariableDeclaration,
getModuleMemberName,
@ -701,11 +698,13 @@ namespace ts {
const statements: Statement[] = [];
const name = node.name || getGeneratedNameForNode(node);
if (hasModifier(node, ModifierFlags.Export)) {
// Keep async modifier for ES2017 transformer
const isAsync = hasModifier(node, ModifierFlags.Async);
statements.push(
setOriginalNode(
createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
isAsync ? [<Modifier>createNode(SyntaxKind.AsyncKeyword)] : undefined,
node.asteriskToken,
name,
/*typeParameters*/ undefined,
@ -958,39 +957,19 @@ namespace ts {
const declaration = resolver.getReferencedImportDeclaration(node);
if (declaration) {
if (isImportClause(declaration)) {
if (languageVersion >= ScriptTarget.ES5) {
return createPropertyAccess(
getGeneratedNameForNode(declaration.parent),
createIdentifier("default"),
/*location*/ node
);
}
else {
// TODO: ES3 transform to handle x.default -> x["default"]
return createElementAccess(
getGeneratedNameForNode(declaration.parent),
createLiteral("default"),
/*location*/ node
);
}
return createPropertyAccess(
getGeneratedNameForNode(declaration.parent),
createIdentifier("default"),
/*location*/ node
);
}
else if (isImportSpecifier(declaration)) {
const name = declaration.propertyName || declaration.name;
if (name.originalKeywordKind === SyntaxKind.DefaultKeyword && languageVersion <= ScriptTarget.ES3) {
// TODO: ES3 transform to handle x.default -> x["default"]
return createElementAccess(
getGeneratedNameForNode(declaration.parent.parent.parent),
createLiteral(name.text),
/*location*/ node
);
}
else {
return createPropertyAccess(
getGeneratedNameForNode(declaration.parent.parent.parent),
getSynthesizedClone(name),
/*location*/ node
);
}
return createPropertyAccess(
getGeneratedNameForNode(declaration.parent.parent.parent),
getSynthesizedClone(name),
/*location*/ node
);
}
}
}
@ -1027,15 +1006,10 @@ namespace ts {
function createExportAssignment(name: Identifier, value: Expression) {
return createAssignment(
name.originalKeywordKind === SyntaxKind.DefaultKeyword && languageVersion === ScriptTarget.ES3
? createElementAccess(
createIdentifier("exports"),
createLiteral(name.text)
)
: createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(name)
),
createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(name)
),
value
);
}

View file

@ -19,7 +19,6 @@ namespace ts {
const compilerOptions = context.getCompilerOptions();
const resolver = context.getEmitResolver();
const host = context.getEmitHost();
const languageVersion = getEmitScriptTarget(compilerOptions);
const previousOnSubstituteNode = context.onSubstituteNode;
const previousOnEmitNode = context.onEmitNode;
context.onSubstituteNode = onSubstituteNode;
@ -91,7 +90,7 @@ namespace ts {
Debug.assert(!exportFunctionForFile);
// Collect information about the external module and dependency groups.
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node, resolver));
({ externalImports, exportSpecifiers, exportEquals, hasExportStarsToExportValues } = collectExternalModuleInfo(node));
// Make sure that the name of the 'exports' function does not conflict with
// existing identifiers.
@ -110,6 +109,7 @@ namespace ts {
const moduleName = tryGetModuleNameFromFile(node, host, compilerOptions);
const dependencies = createArrayLiteral(map(dependencyGroups, getNameOfDependencyGroup));
const body = createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -244,6 +244,7 @@ namespace ts {
),
createPropertyAssignment("execute",
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -430,6 +431,7 @@ namespace ts {
setters.push(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -573,28 +575,23 @@ namespace ts {
}
function visitExportSpecifier(specifier: ExportSpecifier): Statement {
if (resolver.getReferencedValueDeclaration(specifier.propertyName || specifier.name)
|| resolver.isValueAliasDeclaration(specifier)) {
recordExportName(specifier.name);
return createExportStatement(
specifier.name,
specifier.propertyName || specifier.name
);
}
return undefined;
recordExportName(specifier.name);
return createExportStatement(
specifier.name,
specifier.propertyName || specifier.name
);
}
function visitExportAssignment(node: ExportAssignment): Statement {
if (!node.isExportEquals) {
if (nodeIsSynthesized(node) || resolver.isValueAliasDeclaration(node)) {
return createExportStatement(
createLiteral("default"),
node.expression
);
}
if (node.isExportEquals) {
// Elide `export=` as it is illegal in a SystemJS module.
return undefined;
}
return undefined;
return createExportStatement(
createLiteral("default"),
node.expression
);
}
/**
@ -649,7 +646,7 @@ namespace ts {
}
else {
// If the variable has a BindingPattern, flatten the variable into multiple assignment expressions.
return flattenVariableDestructuringToExpression(context, node, hoistVariableDeclaration);
return flattenVariableDestructuringToExpression(node, hoistVariableDeclaration);
}
}
@ -662,9 +659,11 @@ namespace ts {
if (hasModifier(node, ModifierFlags.Export)) {
// If the function is exported, ensure it has a name and rewrite the function without any export flags.
const name = node.name || getGeneratedNameForNode(node);
// Keep async modifier for ES2017 transformer
const isAsync = hasModifier(node, ModifierFlags.Async);
const newNode = createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
isAsync ? [<Modifier>createNode(SyntaxKind.AsyncKeyword)] : undefined,
node.asteriskToken,
name,
/*typeParameters*/ undefined,
@ -796,7 +795,7 @@ namespace ts {
const name = firstDeclaration.name;
return isIdentifier(name)
? name
: flattenVariableDestructuringToExpression(context, firstDeclaration, hoistVariableDeclaration);
: flattenVariableDestructuringToExpression(firstDeclaration, hoistVariableDeclaration);
}
/**
@ -1317,12 +1316,7 @@ namespace ts {
return undefined;
}
if (name.originalKeywordKind && languageVersion === ScriptTarget.ES3) {
return createElementAccess(importAlias, createLiteral(name.text));
}
else {
return createPropertyAccess(importAlias, getSynthesizedClone(name));
}
return createPropertyAccess(importAlias, getSynthesizedClone(name));
}
function collectDependencyGroups(externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]) {

View file

@ -4,8 +4,6 @@
/*@internal*/
namespace ts {
type SuperContainer = ClassDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration;
/**
* Indicates whether to emit type metadata in the new format.
*/
@ -16,8 +14,6 @@ namespace ts {
ClassAliases = 1 << 0,
/** Enables substitutions for namespace exports. */
NamespaceExports = 1 << 1,
/** Enables substitutions for async methods with `super` calls. */
AsyncMethodsWithSuper = 1 << 2,
/* Enables substitutions for unqualified enum members */
NonQualifiedEnumMembers = 1 << 3
}
@ -72,12 +68,6 @@ namespace ts {
*/
let applicableSubstitutions: TypeScriptSubstitutionFlags;
/**
* This keeps track of containers where `super` is valid, for use with
* just-in-time substitution for `super` expressions inside of async methods.
*/
let currentSuperContainer: SuperContainer;
return transformSourceFile;
/**
@ -147,6 +137,35 @@ namespace ts {
return node;
}
/**
* Specialized visitor that visits the immediate children of a SourceFile.
*
* @param node The node to visit.
*/
function sourceElementVisitor(node: Node): VisitResult<Node> {
return saveStateAndInvoke(node, sourceElementVisitorWorker);
}
/**
* Specialized visitor that visits the immediate children of a SourceFile.
*
* @param node The node to visit.
*/
function sourceElementVisitorWorker(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
return visitImportDeclaration(<ImportDeclaration>node);
case SyntaxKind.ImportEqualsDeclaration:
return visitImportEqualsDeclaration(<ImportEqualsDeclaration>node);
case SyntaxKind.ExportAssignment:
return visitExportAssignment(<ExportAssignment>node);
case SyntaxKind.ExportDeclaration:
return visitExportDeclaration(<ExportDeclaration>node);
default:
return visitorWorker(node);
}
}
/**
* Specialized visitor that visits the immediate children of a namespace.
*
@ -244,7 +263,6 @@ namespace ts {
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.AbstractKeyword:
case SyntaxKind.AsyncKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.DeclareKeyword:
case SyntaxKind.ReadonlyKeyword:
@ -286,8 +304,7 @@ namespace ts {
// TypeScript property declarations are elided.
case SyntaxKind.Constructor:
// TypeScript constructors are transformed in `visitClassDeclaration`.
return undefined;
return visitConstructor(<ConstructorDeclaration>node);
case SyntaxKind.InterfaceDeclaration:
// TypeScript interfaces are elided, but some comments may be preserved.
@ -304,7 +321,6 @@ namespace ts {
// - property declarations
// - index signatures
// - method overload signatures
// - async methods
return visitClassDeclaration(<ClassDeclaration>node);
case SyntaxKind.ClassExpression:
@ -317,7 +333,6 @@ namespace ts {
// - property declarations
// - index signatures
// - method overload signatures
// - async methods
return visitClassExpression(<ClassExpression>node);
case SyntaxKind.HeritageClause:
@ -332,7 +347,7 @@ namespace ts {
return visitExpressionWithTypeArguments(<ExpressionWithTypeArguments>node);
case SyntaxKind.MethodDeclaration:
// TypeScript method declarations may be 'async', and may have decorators, modifiers
// TypeScript method declarations may have decorators, modifiers
// or type annotations.
return visitMethodDeclaration(<MethodDeclaration>node);
@ -341,19 +356,19 @@ namespace ts {
return visitGetAccessor(<GetAccessorDeclaration>node);
case SyntaxKind.SetAccessor:
// Set Accessors can have TypeScript modifiers, decorators, and type annotations.
// Set Accessors can have TypeScript modifiers and type annotations.
return visitSetAccessor(<SetAccessorDeclaration>node);
case SyntaxKind.FunctionDeclaration:
// TypeScript function declarations may be 'async'
// Typescript function declarations can have modifiers, decorators, and type annotations.
return visitFunctionDeclaration(<FunctionDeclaration>node);
case SyntaxKind.FunctionExpression:
// TypeScript function expressions may be 'async'
// TypeScript function expressions can have modifiers and type annotations.
return visitFunctionExpression(<FunctionExpression>node);
case SyntaxKind.ArrowFunction:
// TypeScript arrow functions may be 'async'
// TypeScript arrow functions can have modifiers and type annotations.
return visitArrowFunction(<ArrowFunction>node);
case SyntaxKind.Parameter:
@ -377,6 +392,12 @@ namespace ts {
// TypeScript type assertions are removed, but their subtrees are preserved.
return visitAssertionExpression(<AssertionExpression>node);
case SyntaxKind.CallExpression:
return visitCallExpression(<CallExpression>node);
case SyntaxKind.NewExpression:
return visitNewExpression(<NewExpression>node);
case SyntaxKind.NonNullExpression:
// TypeScript non-null expressions are removed, but their subtrees are preserved.
return visitNonNullExpression(<NonNullExpression>node);
@ -385,14 +406,13 @@ namespace ts {
// TypeScript enum declarations do not exist in ES6 and must be rewritten.
return visitEnumDeclaration(<EnumDeclaration>node);
case SyntaxKind.AwaitExpression:
// TypeScript 'await' expressions must be transformed.
return visitAwaitExpression(<AwaitExpression>node);
case SyntaxKind.VariableStatement:
// TypeScript namespace exports for variable statements must be transformed.
return visitVariableStatement(<VariableStatement>node);
case SyntaxKind.VariableDeclaration:
return visitVariableDeclaration(<VariableDeclaration>node);
case SyntaxKind.ModuleDeclaration:
// TypeScript namespace declarations must be transformed.
return visitModuleDeclaration(<ModuleDeclaration>node);
@ -462,7 +482,7 @@ namespace ts {
statements.push(externalHelpersModuleImport);
currentSourceFileExternalHelpersModuleName = externalHelpersModuleName;
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
addRange(statements, endLexicalEnvironment());
currentSourceFileExternalHelpersModuleName = undefined;
@ -470,7 +490,7 @@ namespace ts {
node.externalHelpersModuleName = externalHelpersModuleName;
}
else {
node = visitEachChild(node, visitor, context);
node = visitEachChild(node, sourceElementVisitor, context);
}
setEmitFlags(node, EmitFlags.EmitEmitHelpers | getEmitFlags(node));
@ -560,7 +580,7 @@ namespace ts {
// HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
if (staticProperties.length) {
addInitializedPropertyStatements(statements, node, staticProperties, getLocalName(node, /*noSourceMaps*/ true));
addInitializedPropertyStatements(statements, staticProperties, getLocalName(node, /*noSourceMaps*/ true));
}
// Write any decorators of the node.
@ -775,7 +795,7 @@ namespace ts {
function visitClassExpression(node: ClassExpression): Expression {
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
const members = transformClassMembers(node, heritageClauses !== undefined);
const members = transformClassMembers(node, some(heritageClauses, c => c.token === SyntaxKind.ExtendsKeyword));
const classExpression = setOriginalNode(
createClassExpression(
@ -802,7 +822,7 @@ namespace ts {
// the body of a class with static initializers.
setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression));
expressions.push(startOnNewLine(createAssignment(temp, classExpression)));
addRange(expressions, generateInitializedPropertyExpressions(node, staticProperties, temp));
addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp));
expressions.push(startOnNewLine(temp));
return inlineExpressions(expressions);
}
@ -848,7 +868,7 @@ namespace ts {
}
const parameters = transformConstructorParameters(constructor);
const body = transformConstructorBody(node, constructor, hasExtendsClause, parameters);
const body = transformConstructorBody(node, constructor, hasExtendsClause);
// constructor(${parameters}) {
// ${body}
@ -902,9 +922,8 @@ namespace ts {
* @param node The current class.
* @param constructor The current class constructor.
* @param hasExtendsClause A value indicating whether the class has an extends clause.
* @param parameters The transformed parameters for the constructor.
*/
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, hasExtendsClause: boolean, parameters: ParameterDeclaration[]) {
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, hasExtendsClause: boolean) {
const statements: Statement[] = [];
let indexOfFirstStatement = 0;
@ -956,7 +975,7 @@ namespace ts {
// }
//
const properties = getInitializedProperties(node, /*isStatic*/ false);
addInitializedPropertyStatements(statements, node, properties, createThis());
addInitializedPropertyStatements(statements, properties, createThis());
if (constructor) {
// The class already had a constructor, so we should add the existing statements, skipping the initial super call.
@ -1096,13 +1115,12 @@ namespace ts {
/**
* Generates assignment statements for property initializers.
*
* @param node The class node.
* @param properties An array of property declarations to transform.
* @param receiver The receiver on which each property should be assigned.
*/
function addInitializedPropertyStatements(statements: Statement[], node: ClassExpression | ClassDeclaration, properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
function addInitializedPropertyStatements(statements: Statement[], properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
for (const property of properties) {
const statement = createStatement(transformInitializedProperty(node, property, receiver));
const statement = createStatement(transformInitializedProperty(property, receiver));
setSourceMapRange(statement, moveRangePastModifiers(property));
setCommentRange(statement, property);
statements.push(statement);
@ -1112,14 +1130,13 @@ namespace ts {
/**
* Generates assignment expressions for property initializers.
*
* @param node The class node.
* @param properties An array of property declarations to transform.
* @param receiver The receiver on which each property should be assigned.
*/
function generateInitializedPropertyExpressions(node: ClassExpression | ClassDeclaration, properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
function generateInitializedPropertyExpressions(properties: PropertyDeclaration[], receiver: LeftHandSideExpression) {
const expressions: Expression[] = [];
for (const property of properties) {
const expression = transformInitializedProperty(node, property, receiver);
const expression = transformInitializedProperty(property, receiver);
expression.startsOnNewLine = true;
setSourceMapRange(expression, moveRangePastModifiers(property));
setCommentRange(expression, property);
@ -1132,11 +1149,10 @@ namespace ts {
/**
* Transforms a property initializer into an assignment statement.
*
* @param node The class containing the property.
* @param property The property declaration.
* @param receiver The object receiving the property assignment.
*/
function transformInitializedProperty(node: ClassExpression | ClassDeclaration, property: PropertyDeclaration, receiver: LeftHandSideExpression) {
function transformInitializedProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) {
const propertyName = visitPropertyNameOfClassElement(property);
const initializer = visitNode(property.initializer, visitor, isExpression);
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);
@ -1799,7 +1815,7 @@ namespace ts {
return createIdentifier("Number");
case SyntaxKind.SymbolKeyword:
return languageVersion < ScriptTarget.ES6
return languageVersion < ScriptTarget.ES2015
? getGlobalSymbolNameWithFallback()
: createIdentifier("Symbol");
@ -1896,7 +1912,7 @@ namespace ts {
return createIdentifier("Array");
case TypeReferenceSerializationKind.ESSymbolType:
return languageVersion < ScriptTarget.ES6
return languageVersion < ScriptTarget.ES2015
? getGlobalSymbolNameWithFallback()
: createIdentifier("Symbol");
@ -2088,12 +2104,20 @@ namespace ts {
return !nodeIsMissing(node.body);
}
function visitConstructor(node: ConstructorDeclaration) {
if (!shouldEmitFunctionLikeDeclaration(node)) {
return undefined;
}
return visitEachChild(node, visitor, context);
}
/**
* Visits a method declaration of a class.
*
* This function will be called when one of the following conditions are met:
* - The node is an overload
* - The node is marked as abstract, async, public, private, protected, or readonly
* - The node is marked as abstract, public, private, protected, or readonly
* - The node has both a decorator and a computed property name
*
* @param node The method node.
@ -2204,8 +2228,8 @@ namespace ts {
*
* This function will be called when one of the following conditions are met:
* - The node is an overload
* - The node is marked async
* - The node is exported from a TypeScript namespace
* - The node has decorators
*
* @param node The function node.
*/
@ -2240,7 +2264,7 @@ namespace ts {
* Visits a function expression node.
*
* This function will be called when one of the following conditions are met:
* - The node is marked async
* - The node has type annotations
*
* @param node The function expression node.
*/
@ -2250,6 +2274,7 @@ namespace ts {
}
const func = createFunctionExpression(
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
@ -2267,11 +2292,11 @@ namespace ts {
/**
* @remarks
* This function will be called when one of the following conditions are met:
* - The node is marked async
* - The node has type annotations
*/
function visitArrowFunction(node: ArrowFunction) {
const func = createArrowFunction(
/*modifiers*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
/*typeParameters*/ undefined,
visitNodes(node.parameters, visitor, isParameter),
/*type*/ undefined,
@ -2286,30 +2311,25 @@ namespace ts {
}
function transformFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody {
if (isAsyncFunctionLike(node)) {
return <FunctionBody>transformAsyncFunctionBody(node);
}
return transformFunctionBodyWorker(node.body);
}
function transformFunctionBodyWorker(body: Block, start = 0) {
const savedCurrentScope = currentScope;
const savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName;
currentScope = body;
currentScopeFirstDeclarationsOfName = createMap<Node>();
startLexicalEnvironment();
const statements = visitNodes(body.statements, visitor, isStatement, start);
const visited = updateBlock(body, statements);
const declarations = endLexicalEnvironment();
currentScope = savedCurrentScope;
currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName;
return mergeFunctionBodyLexicalEnvironment(visited, declarations);
}
function transformConciseBody(node: ArrowFunction): ConciseBody {
if (isAsyncFunctionLike(node)) {
return transformAsyncFunctionBody(node);
}
return transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ false);
}
@ -2333,72 +2353,6 @@ namespace ts {
}
}
function getPromiseConstructor(type: TypeNode) {
const typeName = getEntityNameFromTypeNode(type);
if (typeName && isEntityName(typeName)) {
const serializationKind = resolver.getTypeReferenceSerializationKind(typeName);
if (serializationKind === TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue
|| serializationKind === TypeReferenceSerializationKind.Unknown) {
return typeName;
}
}
return undefined;
}
function transformAsyncFunctionBody(node: FunctionLikeDeclaration): ConciseBody | FunctionBody {
const promiseConstructor = languageVersion < ScriptTarget.ES6 ? getPromiseConstructor(node.type) : undefined;
const isArrowFunction = node.kind === SyntaxKind.ArrowFunction;
const hasLexicalArguments = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.CaptureArguments) !== 0;
// An async function is emit as an outer function that calls an inner
// generator function. To preserve lexical bindings, we pass the current
// `this` and `arguments` objects to `__awaiter`. The generator function
// passed to `__awaiter` is executed inside of the callback to the
// promise constructor.
if (!isArrowFunction) {
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, (<Block>node.body).statements, /*ensureUseStrict*/ false, visitor);
statements.push(
createReturn(
createAwaiterHelper(
currentSourceFileExternalHelpersModuleName,
hasLexicalArguments,
promiseConstructor,
transformFunctionBodyWorker(<Block>node.body, statementOffset)
)
)
);
const block = createBlock(statements, /*location*/ node.body, /*multiLine*/ true);
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
if (languageVersion >= ScriptTarget.ES6) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
enableSubstitutionForAsyncMethodsWithSuper();
setEmitFlags(block, EmitFlags.EmitAdvancedSuperHelper);
}
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) {
enableSubstitutionForAsyncMethodsWithSuper();
setEmitFlags(block, EmitFlags.EmitSuperHelper);
}
}
return block;
}
else {
return createAwaiterHelper(
currentSourceFileExternalHelpersModuleName,
hasLexicalArguments,
promiseConstructor,
<Block>transformConciseBodyWorker(node.body, /*forceBlockFunctionBody*/ true)
);
}
}
/**
* Visits a parameter declaration node.
*
@ -2465,7 +2419,6 @@ namespace ts {
const name = node.name;
if (isBindingPattern(name)) {
return flattenVariableDestructuringToExpression(
context,
node,
hoistVariableDeclaration,
getNamespaceMemberNameWithSourceMapsAndWithoutComments,
@ -2481,22 +2434,12 @@ namespace ts {
}
}
/**
* Visits an await expression.
*
* This function will be called any time a TypeScript await expression is encountered.
*
* @param node The await expression node.
*/
function visitAwaitExpression(node: AwaitExpression): Expression {
return setOriginalNode(
createYield(
/*asteriskToken*/ undefined,
visitNode(node.expression, visitor, isExpression),
/*location*/ node
),
node
);
function visitVariableDeclaration(node: VariableDeclaration) {
return updateVariableDeclaration(
node,
visitNode(node.name, visitor, isBindingName),
/*type*/ undefined,
visitNode(node.initializer, visitor, isExpression));
}
/**
@ -2541,6 +2484,22 @@ namespace ts {
return createPartiallyEmittedExpression(expression, node);
}
function visitCallExpression(node: CallExpression) {
return updateCall(
node,
visitNode(node.expression, visitor, isExpression),
/*typeArguments*/ undefined,
visitNodes(node.arguments, visitor, isExpression));
}
function visitNewExpression(node: NewExpression) {
return updateNew(
node,
visitNode(node.expression, visitor, isExpression),
/*typeArguments*/ undefined,
visitNodes(node.arguments, visitor, isExpression));
}
/**
* Determines whether to emit an enum declaration.
*
@ -2622,6 +2581,7 @@ namespace ts {
const enumStatement = createStatement(
createCall(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -2735,7 +2695,7 @@ namespace ts {
function isES6ExportedDeclaration(node: Node) {
return isExternalModuleExport(node)
&& moduleKind === ModuleKind.ES6;
&& moduleKind === ModuleKind.ES2015;
}
/**
@ -2893,6 +2853,7 @@ namespace ts {
const moduleStatement = createStatement(
createCall(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
@ -2998,6 +2959,133 @@ namespace ts {
}
}
/**
* Visits an import declaration, eliding it if it is not referenced.
*
* @param node The import declaration node.
*/
function visitImportDeclaration(node: ImportDeclaration): VisitResult<Statement> {
if (!node.importClause) {
// Do not elide a side-effect only import declaration.
// import "foo";
return node;
}
// Elide the declaration if the import clause was elided.
const importClause = visitNode(node.importClause, visitImportClause, isImportClause, /*optional*/ true);
return importClause
? updateImportDeclaration(
node,
/*decorators*/ undefined,
/*modifiers*/ undefined,
importClause,
node.moduleSpecifier)
: undefined;
}
/**
* Visits an import clause, eliding it if it is not referenced.
*
* @param node The import clause node.
*/
function visitImportClause(node: ImportClause): VisitResult<ImportClause> {
// Elide the import clause if we elide both its name and its named bindings.
const name = resolver.isReferencedAliasDeclaration(node) ? node.name : undefined;
const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings, /*optional*/ true);
return (name || namedBindings) ? updateImportClause(node, name, namedBindings) : undefined;
}
/**
* Visits named import bindings, eliding it if it is not referenced.
*
* @param node The named import bindings node.
*/
function visitNamedImportBindings(node: NamedImportBindings): VisitResult<NamedImportBindings> {
if (node.kind === SyntaxKind.NamespaceImport) {
// Elide a namespace import if it is not referenced.
return resolver.isReferencedAliasDeclaration(node) ? node : undefined;
}
else {
// Elide named imports if all of its import specifiers are elided.
const elements = visitNodes(node.elements, visitImportSpecifier, isImportSpecifier);
return some(elements) ? updateNamedImports(node, elements) : undefined;
}
}
/**
* Visits an import specifier, eliding it if it is not referenced.
*
* @param node The import specifier node.
*/
function visitImportSpecifier(node: ImportSpecifier): VisitResult<ImportSpecifier> {
// Elide an import specifier if it is not referenced.
return resolver.isReferencedAliasDeclaration(node) ? node : undefined;
}
/**
* Visits an export assignment, eliding it if it does not contain a clause that resolves
* to a value.
*
* @param node The export assignment node.
*/
function visitExportAssignment(node: ExportAssignment): VisitResult<Statement> {
// Elide the export assignment if it does not reference a value.
return resolver.isValueAliasDeclaration(node)
? visitEachChild(node, visitor, context)
: undefined;
}
/**
* Visits an export declaration, eliding it if it does not contain a clause that resolves
* to a value.
*
* @param node The export declaration node.
*/
function visitExportDeclaration(node: ExportDeclaration): VisitResult<Statement> {
if (!node.exportClause) {
// Elide a star export if the module it references does not export a value.
return resolver.moduleExportsSomeValue(node.moduleSpecifier) ? node : undefined;
}
if (!resolver.isValueAliasDeclaration(node)) {
// Elide the export declaration if it does not export a value.
return undefined;
}
// Elide the export declaration if all of its named exports are elided.
const exportClause = visitNode(node.exportClause, visitNamedExports, isNamedExports, /*optional*/ true);
return exportClause
? updateExportDeclaration(
node,
/*decorators*/ undefined,
/*modifiers*/ undefined,
exportClause,
node.moduleSpecifier)
: undefined;
}
/**
* Visits named exports, eliding it if it does not contain an export specifier that
* resolves to a value.
*
* @param node The named exports node.
*/
function visitNamedExports(node: NamedExports): VisitResult<NamedExports> {
// Elide the named exports if all of its export specifiers were elided.
const elements = visitNodes(node.elements, visitExportSpecifier, isExportSpecifier);
return some(elements) ? updateNamedExports(node, elements) : undefined;
}
/**
* Visits an export specifier, eliding it if it does not resolve to a value.
*
* @param node The export specifier node.
*/
function visitExportSpecifier(node: ExportSpecifier): VisitResult<ExportSpecifier> {
// Elide an export specifier if it does not reference a value.
return resolver.isValueAliasDeclaration(node) ? node : undefined;
}
/**
* Determines whether to emit an import equals declaration.
*
@ -3019,7 +3107,10 @@ namespace ts {
*/
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult<Statement> {
if (isExternalModuleImportEqualsDeclaration(node)) {
return visitEachChild(node, visitor, context);
// Elide external module `import=` if it is not referenced.
return resolver.isReferencedAliasDeclaration(node)
? visitEachChild(node, visitor, context)
: undefined;
}
if (!shouldEmitImportEqualsDeclaration(node)) {
@ -3253,25 +3344,6 @@ namespace ts {
}
}
function enableSubstitutionForAsyncMethodsWithSuper() {
if ((enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper) === 0) {
enabledSubstitutions |= TypeScriptSubstitutionFlags.AsyncMethodsWithSuper;
// We need to enable substitutions for call, property access, and element access
// if we need to rewrite super calls.
context.enableSubstitution(SyntaxKind.CallExpression);
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
context.enableSubstitution(SyntaxKind.ElementAccessExpression);
// We need to be notified when entering and exiting declarations that bind super.
context.enableEmitNotification(SyntaxKind.ClassDeclaration);
context.enableEmitNotification(SyntaxKind.MethodDeclaration);
context.enableEmitNotification(SyntaxKind.GetAccessor);
context.enableEmitNotification(SyntaxKind.SetAccessor);
context.enableEmitNotification(SyntaxKind.Constructor);
}
}
function enableSubstitutionForClassAliases() {
if ((enabledSubstitutions & TypeScriptSubstitutionFlags.ClassAliases) === 0) {
enabledSubstitutions |= TypeScriptSubstitutionFlags.ClassAliases;
@ -3299,15 +3371,6 @@ namespace ts {
}
}
function isSuperContainer(node: Node): node is SuperContainer {
const kind = node.kind;
return kind === SyntaxKind.ClassDeclaration
|| kind === SyntaxKind.Constructor
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.GetAccessor
|| kind === SyntaxKind.SetAccessor;
}
function isTransformedModuleDeclaration(node: Node): boolean {
return getOriginalNode(node).kind === SyntaxKind.ModuleDeclaration;
}
@ -3324,12 +3387,6 @@ namespace ts {
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
const savedApplicableSubstitutions = applicableSubstitutions;
const savedCurrentSuperContainer = currentSuperContainer;
// If we need to support substitutions for `super` in an async method,
// we should track it here.
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
currentSuperContainer = node;
}
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isTransformedModuleDeclaration(node)) {
applicableSubstitutions |= TypeScriptSubstitutionFlags.NamespaceExports;
@ -3342,7 +3399,6 @@ namespace ts {
previousOnEmitNode(emitContext, node, emitCallback);
applicableSubstitutions = savedApplicableSubstitutions;
currentSuperContainer = savedCurrentSuperContainer;
}
/**
@ -3389,11 +3445,6 @@ namespace ts {
return substitutePropertyAccessExpression(<PropertyAccessExpression>node);
case SyntaxKind.ElementAccessExpression:
return substituteElementAccessExpression(<ElementAccessExpression>node);
case SyntaxKind.CallExpression:
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper) {
return substituteCallExpression(<CallExpression>node);
}
break;
}
return node;
@ -3448,54 +3499,11 @@ namespace ts {
return undefined;
}
function substituteCallExpression(node: CallExpression): Expression {
const expression = node.expression;
if (isSuperProperty(expression)) {
const flags = getSuperContainerAsyncMethodFlags();
if (flags) {
const argumentExpression = isPropertyAccessExpression(expression)
? substitutePropertyAccessExpression(expression)
: substituteElementAccessExpression(expression);
return createCall(
createPropertyAccess(argumentExpression, "call"),
/*typeArguments*/ undefined,
[
createThis(),
...node.arguments
]
);
}
}
return node;
}
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
const flags = getSuperContainerAsyncMethodFlags();
if (flags) {
return createSuperAccessInAsyncMethod(
createLiteral(node.name.text),
flags,
node
);
}
}
return substituteConstantValue(node);
}
function substituteElementAccessExpression(node: ElementAccessExpression) {
if (enabledSubstitutions & TypeScriptSubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
const flags = getSuperContainerAsyncMethodFlags();
if (flags) {
return createSuperAccessInAsyncMethod(
node.argumentExpression,
flags,
node
);
}
}
return substituteConstantValue(node);
}
@ -3528,32 +3536,5 @@ namespace ts {
? resolver.getConstantValue(<PropertyAccessExpression | ElementAccessExpression>node)
: undefined;
}
function createSuperAccessInAsyncMethod(argumentExpression: Expression, flags: NodeCheckFlags, location: TextRange): LeftHandSideExpression {
if (flags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
return createPropertyAccess(
createCall(
createIdentifier("_super"),
/*typeArguments*/ undefined,
[argumentExpression]
),
"value",
location
);
}
else {
return createCall(
createIdentifier("_super"),
/*typeArguments*/ undefined,
[argumentExpression],
location
);
}
}
function getSuperContainerAsyncMethodFlags() {
return currentSuperContainer !== undefined
&& resolver.getNodeCheckFlags(currentSuperContainer) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
}
}
}

View file

@ -29,7 +29,7 @@ namespace ts {
}
}
function reportEmittedFiles(files: string[], host: CompilerHost): void {
function reportEmittedFiles(files: string[]): void {
if (!files || files.length == 0) {
return;
}
@ -111,7 +111,7 @@ namespace ts {
return count;
}
function getDiagnosticText(message: DiagnosticMessage, ...args: any[]): string {
function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string {
const diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
return <string>diagnostic.messageText;
}
@ -456,7 +456,7 @@ namespace ts {
const sourceFile = hostGetSourceFile(fileName, languageVersion, onError);
if (sourceFile && isWatchSet(compilerOptions) && sys.watchFile) {
// Attach a file watcher
sourceFile.fileWatcher = sys.watchFile(sourceFile.fileName, (fileName: string, removed?: boolean) => sourceFileChanged(sourceFile, removed));
sourceFile.fileWatcher = sys.watchFile(sourceFile.fileName, (_fileName: string, removed?: boolean) => sourceFileChanged(sourceFile, removed));
}
return sourceFile;
}
@ -617,7 +617,7 @@ namespace ts {
reportDiagnostics(sortAndDeduplicateDiagnostics(diagnostics), compilerHost);
reportEmittedFiles(emitOutput.emittedFiles, compilerHost);
reportEmittedFiles(emitOutput.emittedFiles);
if (emitOutput.emitSkipped && diagnostics.length > 0) {
// If the emitter didn't emit anything, then pass that value along.

View file

@ -8,7 +8,10 @@
"outFile": "../../built/local/tsc.js",
"sourceMap": true,
"declaration": true,
"stripInternal": true
"stripInternal": true,
"target": "es5",
"noUnusedLocals": true,
"noUnusedParameters": true
},
"files": [
"core.ts",
@ -25,13 +28,15 @@
"transformers/ts.ts",
"transformers/jsx.ts",
"transformers/experimental.ts",
"transformers/es7.ts",
"transformers/es6.ts",
"transformers/es2017.ts",
"transformers/es2016.ts",
"transformers/es2015.ts",
"transformers/generators.ts",
"transformers/es5.ts",
"transformers/destructuring.ts",
"transformers/module/module.ts",
"transformers/module/system.ts",
"transformers/module/es6.ts",
"transformers/module/es2015.ts",
"transformer.ts",
"comments.ts",
"sourcemap.ts",

View file

@ -45,6 +45,7 @@ namespace ts {
// Literals
NumericLiteral,
StringLiteral,
JsxText,
RegularExpressionLiteral,
NoSubstitutionTemplateLiteral,
// Pseudo-literals
@ -302,7 +303,6 @@ namespace ts {
JsxElement,
JsxSelfClosingElement,
JsxOpeningElement,
JsxText,
JsxClosingElement,
JsxAttribute,
JsxSpreadAttribute,
@ -458,6 +458,8 @@ namespace ts {
// Accessibility modifiers and 'readonly' can be attached to a parameter in a constructor to make it a property.
ParameterPropertyModifier = AccessibilityModifier | Readonly,
NonPublicAccessibilityModifier = Private | Protected,
TypeScriptModifier = Ambient | Public | Private | Protected | Readonly | Abstract | Const
}
export const enum JsxFlags {
@ -1921,8 +1923,9 @@ namespace ts {
TrueCondition = 1 << 5, // Condition known to be true
FalseCondition = 1 << 6, // Condition known to be false
SwitchClause = 1 << 7, // Switch statement clause
Referenced = 1 << 8, // Referenced as antecedent once
Shared = 1 << 9, // Referenced as antecedent more than once
ArrayMutation = 1 << 8, // Potential array mutation
Referenced = 1 << 9, // Referenced as antecedent once
Shared = 1 << 10, // Referenced as antecedent more than once
Label = BranchLabel | LoopLabel,
Condition = TrueCondition | FalseCondition
}
@ -1965,6 +1968,13 @@ namespace ts {
antecedent: FlowNode;
}
// FlowArrayMutation represents a node potentially mutates an array, i.e. an
// operation of the form 'x.push(value)', 'x.unshift(value)' or 'x[n] = value'.
export interface FlowArrayMutation extends FlowNode {
node: CallExpression | BinaryExpression;
antecedent: FlowNode;
}
export type FlowType = Type | IncompleteType;
// Incomplete types occur during control flow analysis of loops. An IncompleteType
@ -2778,6 +2788,8 @@ namespace ts {
export interface AnonymousType extends ObjectType {
target?: AnonymousType; // Instantiation target
mapper?: TypeMapper; // Instantiation mapper
elementType?: Type; // Element expressions of evolving array type
finalArrayType?: Type; // Final array type of evolving array type
}
/* @internal */
@ -3050,8 +3062,7 @@ namespace ts {
AMD = 2,
UMD = 3,
System = 4,
ES6 = 5,
ES2015 = ES6,
ES2015 = 5,
}
export const enum JsxEmit {
@ -3084,9 +3095,10 @@ namespace ts {
export const enum ScriptTarget {
ES3 = 0,
ES5 = 1,
ES6 = 2,
ES2015 = ES6,
Latest = ES6,
ES2015 = 2,
ES2016 = 3,
ES2017 = 4,
Latest = ES2017,
}
export const enum LanguageVariant {
@ -3373,29 +3385,31 @@ namespace ts {
ContainsJsx = 1 << 3,
Experimental = 1 << 4,
ContainsExperimental = 1 << 5,
ES7 = 1 << 6,
ContainsES7 = 1 << 7,
ES6 = 1 << 8,
ContainsES6 = 1 << 9,
DestructuringAssignment = 1 << 10,
Generator = 1 << 11,
ContainsGenerator = 1 << 12,
ES2017 = 1 << 6,
ContainsES2017 = 1 << 7,
ES2016 = 1 << 8,
ContainsES2016 = 1 << 9,
ES2015 = 1 << 10,
ContainsES2015 = 1 << 11,
DestructuringAssignment = 1 << 12,
Generator = 1 << 13,
ContainsGenerator = 1 << 14,
// Markers
// - Flags used to indicate that a subtree contains a specific transformation.
ContainsDecorators = 1 << 13,
ContainsPropertyInitializer = 1 << 14,
ContainsLexicalThis = 1 << 15,
ContainsCapturedLexicalThis = 1 << 16,
ContainsLexicalThisInComputedPropertyName = 1 << 17,
ContainsDefaultValueAssignments = 1 << 18,
ContainsParameterPropertyAssignments = 1 << 19,
ContainsSpreadExpression = 1 << 20,
ContainsComputedPropertyName = 1 << 21,
ContainsBlockScopedBinding = 1 << 22,
ContainsBindingPattern = 1 << 23,
ContainsYield = 1 << 24,
ContainsHoistedDeclarationOrCompletion = 1 << 25,
ContainsDecorators = 1 << 15,
ContainsPropertyInitializer = 1 << 16,
ContainsLexicalThis = 1 << 17,
ContainsCapturedLexicalThis = 1 << 18,
ContainsLexicalThisInComputedPropertyName = 1 << 19,
ContainsDefaultValueAssignments = 1 << 20,
ContainsParameterPropertyAssignments = 1 << 21,
ContainsSpreadExpression = 1 << 22,
ContainsComputedPropertyName = 1 << 23,
ContainsBlockScopedBinding = 1 << 24,
ContainsBindingPattern = 1 << 25,
ContainsYield = 1 << 26,
ContainsHoistedDeclarationOrCompletion = 1 << 27,
HasComputedFlags = 1 << 29, // Transform flags have been computed.
@ -3404,14 +3418,15 @@ namespace ts {
AssertTypeScript = TypeScript | ContainsTypeScript,
AssertJsx = Jsx | ContainsJsx,
AssertExperimental = Experimental | ContainsExperimental,
AssertES7 = ES7 | ContainsES7,
AssertES6 = ES6 | ContainsES6,
AssertES2017 = ES2017 | ContainsES2017,
AssertES2016 = ES2016 | ContainsES2016,
AssertES2015 = ES2015 | ContainsES2015,
AssertGenerator = Generator | ContainsGenerator,
// Scope Exclusions
// - Bitmasks that exclude flags from propagating out of a specific context
// into the subtree flags of their container.
NodeExcludes = TypeScript | Jsx | Experimental | ES7 | ES6 | DestructuringAssignment | Generator | HasComputedFlags,
NodeExcludes = TypeScript | Jsx | Experimental | ES2017 | ES2016 | ES2015 | DestructuringAssignment | Generator | HasComputedFlags,
ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
@ -3427,7 +3442,7 @@ namespace ts {
// Masks
// - Additional bitmasks
TypeScriptClassSyntaxMask = ContainsParameterPropertyAssignments | ContainsPropertyInitializer | ContainsDecorators,
ES6FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments,
ES2015FunctionSyntaxMask = ContainsCapturedLexicalThis | ContainsDefaultValueAssignments,
}
/* @internal */

View file

@ -337,7 +337,7 @@ namespace ts {
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, languageVersion: ScriptTarget) {
// Any template literal or string literal with an extended escape
// (e.g. "\u{0067}") will need to be downleveled as a escaped string literal.
if (languageVersion < ScriptTarget.ES6 && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) {
if (languageVersion < ScriptTarget.ES2015 && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) {
return getQuotedEscapedLiteralText('"', node.text, '"');
}
@ -345,7 +345,7 @@ namespace ts {
// the node's parent reference, then simply get the text as it was originally written.
if (!nodeIsSynthesized(node) && node.parent) {
const text = getSourceTextOfNodeFromSourceFile(sourceFile, node);
if (languageVersion < ScriptTarget.ES6 && isBinaryOrOctalIntegerLiteral(node, text)) {
if (languageVersion < ScriptTarget.ES2015 && isBinaryOrOctalIntegerLiteral(node, text)) {
return node.text;
}
return text;
@ -503,7 +503,7 @@ namespace ts {
return getFullWidth(name) === 0 ? "(Missing)" : getTextOfNode(name);
}
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): Diagnostic {
export function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic {
const sourceFile = getSourceFileOfNode(node);
const span = getErrorSpanForNode(sourceFile, node);
return createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2);
@ -1901,6 +1901,10 @@ namespace ts {
return node.kind === SyntaxKind.Identifier && (<Identifier>node).text === "Symbol";
}
export function isPushOrUnshiftIdentifier(node: Identifier) {
return node.text === "push" || node.text === "unshift";
}
export function isModifierKind(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.AbstractKeyword:
@ -2562,7 +2566,7 @@ namespace ts {
const options = host.getCompilerOptions();
// Emit on each source file
if (options.outFile || options.out) {
onBundledEmit(host, sourceFiles);
onBundledEmit(sourceFiles);
}
else {
for (const sourceFile of sourceFiles) {
@ -2595,7 +2599,7 @@ namespace ts {
action(jsFilePath, sourceMapFilePath, declarationFilePath, [sourceFile], /*isBundledEmit*/ false);
}
function onBundledEmit(host: EmitHost, sourceFiles: SourceFile[]) {
function onBundledEmit(sourceFiles: SourceFile[]) {
if (sourceFiles.length) {
const jsFilePath = options.outFile || options.out;
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
@ -3502,7 +3506,7 @@ namespace ts {
return positionIsSynthesized(range.pos) ? -1 : skipTrivia(sourceFile.text, range.pos);
}
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver) {
export function collectExternalModuleInfo(sourceFile: SourceFile) {
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
const exportSpecifiers = createMap<ExportSpecifier[]>();
let exportEquals: ExportAssignment = undefined;
@ -3510,19 +3514,16 @@ namespace ts {
for (const node of sourceFile.statements) {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
if (!(<ImportDeclaration>node).importClause ||
resolver.isReferencedAliasDeclaration((<ImportDeclaration>node).importClause, /*checkChildren*/ true)) {
// import "mod"
// import x from "mod" where x is referenced
// import * as x from "mod" where x is referenced
// import { x, y } from "mod" where at least one import is referenced
externalImports.push(<ImportDeclaration>node);
}
// import "mod"
// import x from "mod"
// import * as x from "mod"
// import { x, y } from "mod"
externalImports.push(<ImportDeclaration>node);
break;
case SyntaxKind.ImportEqualsDeclaration:
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(node)) {
// import x = require("mod") where x is referenced
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference) {
// import x = require("mod")
externalImports.push(<ImportEqualsDeclaration>node);
}
break;
@ -3531,13 +3532,11 @@ namespace ts {
if ((<ExportDeclaration>node).moduleSpecifier) {
if (!(<ExportDeclaration>node).exportClause) {
// export * from "mod"
if (resolver.moduleExportsSomeValue((<ExportDeclaration>node).moduleSpecifier)) {
externalImports.push(<ExportDeclaration>node);
hasExportStarsToExportValues = true;
}
externalImports.push(<ExportDeclaration>node);
hasExportStarsToExportValues = true;
}
else if (resolver.isValueAliasDeclaration(node)) {
// export { x, y } from "mod" where at least one export is a value symbol
else {
// export { x, y } from "mod"
externalImports.push(<ExportDeclaration>node);
}
}
@ -4168,7 +4167,17 @@ namespace ts {
namespace ts {
export function getDefaultLibFileName(options: CompilerOptions): string {
return options.target === ScriptTarget.ES6 ? "lib.es6.d.ts" : "lib.d.ts";
switch (options.target) {
case ScriptTarget.ES2017:
return "lib.es2017.d.ts";
case ScriptTarget.ES2016:
return "lib.es2016.d.ts";
case ScriptTarget.ES2015:
return "lib.es6.d.ts";
default:
return "lib.d.ts";
}
}
export function textSpanEnd(span: TextSpan) {

View file

@ -807,6 +807,7 @@ namespace ts {
case SyntaxKind.FunctionExpression:
return updateFunctionExpression(<FunctionExpression>node,
visitNodes((<FunctionExpression>node).modifiers, visitor, isModifier),
visitNode((<FunctionExpression>node).name, visitor, isPropertyName),
visitNodes((<FunctionExpression>node).typeParameters, visitor, isTypeParameter),
(context.startLexicalEnvironment(), visitNodes((<FunctionExpression>node).parameters, visitor, isParameter)),
@ -1330,18 +1331,18 @@ namespace ts {
export namespace Debug {
export const failNotOptional = shouldAssert(AssertionLevel.Normal)
? (message?: string) => assert(false, message || "Node not optional.")
: (message?: string) => {};
: () => {};
export const failBadSyntaxKind = shouldAssert(AssertionLevel.Normal)
? (node: Node, message?: string) => assert(false, message || "Unexpected node.", () => `Node ${formatSyntaxKind(node.kind)} was unexpected.`)
: (node: Node, message?: string) => {};
: () => {};
export const assertNode = shouldAssert(AssertionLevel.Normal)
? (node: Node, test: (node: Node) => boolean, message?: string) => assert(
test === undefined || test(node),
message || "Unexpected node.",
() => `Node ${formatSyntaxKind(node.kind)} did not pass test '${getFunctionName(test)}'.`)
: (node: Node, test: (node: Node) => boolean, message?: string) => {};
: () => {};
function getFunctionName(func: Function) {
if (typeof func !== "function") {

View file

@ -941,7 +941,17 @@ namespace Harness {
}
export function getDefaultLibFileName(options: ts.CompilerOptions): string {
return options.target === ts.ScriptTarget.ES6 ? es2015DefaultLibFileName : defaultLibFileName;
switch (options.target) {
case ts.ScriptTarget.ES2017:
return "lib.es2017.d.ts";
case ts.ScriptTarget.ES2016:
return "lib.es2016.d.ts";
case ts.ScriptTarget.ES2015:
return es2015DefaultLibFileName;
default:
return defaultLibFileName;
}
}
// Cache these between executions so we don't have to re-parse them for every test
@ -1634,7 +1644,7 @@ namespace Harness {
export function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): string {
// Collect, test, and sort the fileNames
outputFiles.sort((a, b) => cleanName(a.fileName).localeCompare(cleanName(b.fileName)));
outputFiles.sort((a, b) => ts.compareStrings(cleanName(a.fileName), cleanName(b.fileName)));
// Emit them
let result = "";

View file

@ -10,7 +10,8 @@
"stripInternal": true,
"types": [
"node", "mocha", "chai"
]
],
"target": "es5"
},
"files": [
"../compiler/core.ts",
@ -27,13 +28,15 @@
"../compiler/transformers/ts.ts",
"../compiler/transformers/jsx.ts",
"../compiler/transformers/experimental.ts",
"../compiler/transformers/es7.ts",
"../compiler/transformers/es6.ts",
"../compiler/transformers/es2017.ts",
"../compiler/transformers/es2016.ts",
"../compiler/transformers/es2015.ts",
"../compiler/transformers/generators.ts",
"../compiler/transformers/es5.ts",
"../compiler/transformers/destructuring.ts",
"../compiler/transformers/module/module.ts",
"../compiler/transformers/module/system.ts",
"../compiler/transformers/module/es6.ts",
"../compiler/transformers/module/es2015.ts",
"../compiler/transformer.ts",
"../compiler/comments.ts",
"../compiler/sourcemap.ts",

View file

@ -60,7 +60,7 @@ namespace ts {
assertParseResult(["--lib", "es5,invalidOption", "0.ts"],
{
errors: [{
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@ -87,7 +87,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--jsx' option must be: 'preserve', 'react'",
messageText: "Argument for '--jsx' option must be: 'preserve', 'react'",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@ -113,7 +113,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@ -139,7 +139,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'",
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@ -165,7 +165,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015'",
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017'",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@ -191,7 +191,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'",
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@ -263,7 +263,7 @@ namespace ts {
assertParseResult(["--lib", "es5,", "es7", "0.ts"],
{
errors: [{
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@ -283,7 +283,7 @@ namespace ts {
assertParseResult(["--lib", "es5, ", "es7", "0.ts"],
{
errors: [{
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,

View file

@ -94,7 +94,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--jsx' option must be: 'preserve', 'react'",
messageText: "Argument for '--jsx' option must be: 'preserve', 'react'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@ -122,7 +122,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@ -150,7 +150,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'",
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@ -176,7 +176,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015'",
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@ -202,7 +202,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'",
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@ -233,7 +233,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@ -264,7 +264,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@ -295,7 +295,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@ -326,7 +326,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory'",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]

View file

@ -1017,7 +1017,7 @@ import b = require("./moduleB");
const files = [f1, f2, f3, f4];
const names = map(files, f => f.name);
const sourceFiles = arrayToMap(map(files, f => createSourceFile(f.name, f.content, ScriptTarget.ES6)), f => f.fileName);
const sourceFiles = arrayToMap(map(files, f => createSourceFile(f.name, f.content, ScriptTarget.ES2015)), f => f.fileName);
const compilerHost: CompilerHost = {
fileExists : fileName => fileName in sourceFiles,
getSourceFile: fileName => sourceFiles[fileName],

View file

@ -39,12 +39,18 @@ namespace ts.server {
getLogFileName: (): string => undefined
};
class TestSession extends Session {
getProjectService() {
return this.projectService;
}
}
describe("the Session class", () => {
let session: Session;
let session: TestSession;
let lastSent: protocol.Message;
beforeEach(() => {
session = new Session(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger, /*canUseEvents*/ true);
session = new TestSession(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger, /*canUseEvents*/ true);
session.send = (msg: protocol.Message) => {
lastSent = msg;
};
@ -55,7 +61,7 @@ namespace ts.server {
const req: protocol.FileRequest = {
command: CommandNames.Open,
seq: 0,
type: "command",
type: "request",
arguments: {
file: undefined
}
@ -67,7 +73,7 @@ namespace ts.server {
const req: protocol.Request = {
command: "foobar",
seq: 0,
type: "command"
type: "request"
};
session.executeCommand(req);
@ -85,7 +91,7 @@ namespace ts.server {
const req: protocol.ConfigureRequest = {
command: CommandNames.Configure,
seq: 0,
type: "command",
type: "request",
arguments: {
hostInfo: "unit test",
formatOptions: {
@ -106,6 +112,47 @@ namespace ts.server {
body: undefined
});
});
it ("should handle literal types in request", () => {
const configureRequest: protocol.ConfigureRequest = {
command: CommandNames.Configure,
seq: 0,
type: "request",
arguments: {
formatOptions: {
indentStyle: "Block"
}
}
};
session.onMessage(JSON.stringify(configureRequest));
assert.equal(session.getProjectService().getFormatCodeOptions().indentStyle, IndentStyle.Block);
const setOptionsRequest: protocol.SetCompilerOptionsForInferredProjectsRequest = {
command: CommandNames.CompilerOptionsForInferredProjects,
seq: 1,
type: "request",
arguments: {
options: {
module: "System",
target: "ES5",
jsx: "React",
newLine: "Lf",
moduleResolution: "Node"
}
}
};
session.onMessage(JSON.stringify(setOptionsRequest));
assert.deepEqual(
session.getProjectService().getCompilerOptionsForInferredProjects(),
<CompilerOptions>{
module: ModuleKind.System,
target: ScriptTarget.ES5,
jsx: JsxEmit.React,
newLine: NewLineKind.LineFeed,
moduleResolution: ModuleResolutionKind.NodeJs
});
});
});
describe("onMessage", () => {
@ -118,7 +165,7 @@ namespace ts.server {
const req: protocol.Request = {
command: name,
seq: i,
type: "command"
type: "request"
};
i++;
session.onMessage(JSON.stringify(req));
@ -151,7 +198,7 @@ namespace ts.server {
const req: protocol.ConfigureRequest = {
command: CommandNames.Configure,
seq: 0,
type: "command",
type: "request",
arguments: {
hostInfo: "unit test",
formatOptions: {
@ -175,7 +222,7 @@ namespace ts.server {
describe("send", () => {
it("is an overrideable handle which sends protocol messages over the wire", () => {
const msg = { seq: 0, type: "none" };
const msg: server.protocol.Request = { seq: 0, type: "request", command: "" };
const strmsg = JSON.stringify(msg);
const len = 1 + Utils.byteLength(strmsg, "utf8");
const resultMsg = `Content-Length: ${len}\r\n\r\n${strmsg}\n`;
@ -203,7 +250,7 @@ namespace ts.server {
expect(session.executeCommand({
command,
seq: 0,
type: "command"
type: "request"
})).to.deep.equal(result);
});
it("throws when a duplicate handler is passed", () => {
@ -304,7 +351,7 @@ namespace ts.server {
expect(session.executeCommand({
seq: 0,
type: "command",
type: "request",
command: session.customHandler
})).to.deep.equal({
response: undefined,
@ -405,7 +452,7 @@ namespace ts.server {
this.seq++;
this.server.enqueue({
seq: this.seq,
type: "command",
type: "request",
command,
arguments: args
});

View file

@ -135,7 +135,7 @@ namespace ts.projectSystem {
}
export class TestServerEventManager {
private events: server.ProjectServiceEvent[] = [];
public events: server.ProjectServiceEvent[] = [];
handler: server.ProjectServiceEventHandler = (event: server.ProjectServiceEvent) => {
this.events.push(event);
@ -170,11 +170,18 @@ namespace ts.projectSystem {
return host;
}
class TestSession extends server.Session {
getProjectService() {
return this.projectService;
}
};
export function createSession(host: server.ServerHost, typingsInstaller?: server.ITypingsInstaller, projectServiceEventHandler?: server.ProjectServiceEventHandler) {
if (typingsInstaller === undefined) {
typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
}
return new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ projectServiceEventHandler !== undefined, projectServiceEventHandler);
return new TestSession(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ projectServiceEventHandler !== undefined, projectServiceEventHandler);
}
export interface CreateProjectServiceParameters {
@ -515,11 +522,13 @@ namespace ts.projectSystem {
this.reloadFS(filesOrFolders);
}
write(s: string) {
}
readonly readFile = (s: string) => (<File>this.fs.get(this.toPath(s))).content;
readonly resolvePath = (s: string) => s;
readonly getExecutingFilePath = () => this.executingFilePath;
readonly getCurrentDirectory = () => this.currentDirectory;
readonly write = (s: string) => notImplemented();
readonly exit = () => notImplemented();
readonly getEnvironmentVariable = (v: string) => notImplemented();
}
@ -2286,6 +2295,14 @@ namespace ts.projectSystem {
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
openFilesForSession([file], session);
serverEventManager.checkEventCountOfType("configFileDiag", 1);
for (const event of serverEventManager.events) {
if (event.eventName === "configFileDiag") {
assert.equal(event.data.configFileName, configFile.path);
assert.equal(event.data.triggerFile, file.path);
return;
}
}
});
it("are generated when the config file doesn't have errors", () => {
@ -2412,4 +2429,53 @@ namespace ts.projectSystem {
assert.isTrue(inferredProject.containsFile(<server.NormalizedPath>file1.path));
});
});
describe("reload", () => {
it("should work with temp file", () => {
const f1 = {
path: "/a/b/app.ts",
content: "let x = 1"
};
const tmp = {
path: "/a/b/app.tmp",
content: "const y = 42"
};
const host = createServerHost([f1, tmp]);
const session = createSession(host);
// send open request
session.executeCommand(<server.protocol.OpenRequest>{
type: "request",
command: "open",
seq: 1,
arguments: { file: f1.path }
});
// reload from tmp file
session.executeCommand(<server.protocol.ReloadRequest>{
type: "request",
command: "reload",
seq: 2,
arguments: { file: f1.path, tmpfile: tmp.path }
});
// verify content
const projectServiice = session.getProjectService();
const snap1 = projectServiice.getScriptInfo(f1.path).snap();
assert.equal(snap1.getText(0, snap1.getLength()), tmp.content, "content should be equal to the content of temp file");
// reload from original file file
session.executeCommand(<server.protocol.ReloadRequest>{
type: "request",
command: "reload",
seq: 2,
arguments: { file: f1.path }
});
// verify content
const snap2 = projectServiice.getScriptInfo(f1.path).snap();
assert.equal(snap2.getText(0, snap2.getLength()), f1.content, "content should be equal to the content of original file");
});
});
}

View file

@ -10,7 +10,8 @@
"stripInternal": true,
"types": [
"node"
]
],
"target": "es5"
},
"files": [
"cancellationToken.ts"

View file

@ -424,33 +424,39 @@ namespace ts.server {
}
getSyntacticDiagnostics(fileName: string): Diagnostic[] {
const args: protocol.SyntacticDiagnosticsSyncRequestArgs = { file: fileName };
const args: protocol.SyntacticDiagnosticsSyncRequestArgs = { file: fileName, includeLinePosition: true };
const request = this.processRequest<protocol.SyntacticDiagnosticsSyncRequest>(CommandNames.SyntacticDiagnosticsSync, args);
const response = this.processResponse<protocol.SyntacticDiagnosticsSyncResponse>(request);
return (<protocol.Diagnostic[]>response.body).map(entry => this.convertDiagnostic(entry, fileName));
return (<protocol.DiagnosticWithLinePosition[]>response.body).map(entry => this.convertDiagnostic(entry, fileName));
}
getSemanticDiagnostics(fileName: string): Diagnostic[] {
const args: protocol.SemanticDiagnosticsSyncRequestArgs = { file: fileName };
const args: protocol.SemanticDiagnosticsSyncRequestArgs = { file: fileName, includeLinePosition: true };
const request = this.processRequest<protocol.SemanticDiagnosticsSyncRequest>(CommandNames.SemanticDiagnosticsSync, args);
const response = this.processResponse<protocol.SemanticDiagnosticsSyncResponse>(request);
return (<protocol.Diagnostic[]>response.body).map(entry => this.convertDiagnostic(entry, fileName));
return (<protocol.DiagnosticWithLinePosition[]>response.body).map(entry => this.convertDiagnostic(entry, fileName));
}
convertDiagnostic(entry: protocol.Diagnostic, fileName: string): Diagnostic {
const start = this.lineOffsetToPosition(fileName, entry.start);
const end = this.lineOffsetToPosition(fileName, entry.end);
convertDiagnostic(entry: protocol.DiagnosticWithLinePosition, fileName: string): Diagnostic {
let category: DiagnosticCategory;
for (const id in DiagnosticCategory) {
if (typeof id === "string" && entry.category === id.toLowerCase()) {
category = (<any>DiagnosticCategory)[id];
}
}
Debug.assert(category !== undefined, "convertDiagnostic: category should not be undefined");
return {
file: undefined,
start: start,
length: end - start,
messageText: entry.text,
category: undefined,
start: entry.start,
length: entry.length,
messageText: entry.message,
category: category,
code: entry.code
};
}

View file

@ -11,12 +11,74 @@ namespace ts.server {
export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
export type ProjectServiceEvent =
{ eventName: "context", data: { project: Project, fileName: NormalizedPath } } | { eventName: "configFileDiag", data: { triggerFile?: string, configFileName: string, diagnostics: Diagnostic[] } };
{ eventName: "context", data: { project: Project, fileName: NormalizedPath } } | { eventName: "configFileDiag", data: { triggerFile: string, configFileName: string, diagnostics: Diagnostic[] } };
export interface ProjectServiceEventHandler {
(event: ProjectServiceEvent): void;
}
function prepareConvertersForEnumLikeCompilerOptions(commandLineOptions: CommandLineOption[]): Map<Map<number>> {
const map: Map<Map<number>> = createMap<Map<number>>();
for (const option of commandLineOptions) {
if (typeof option.type === "object") {
const optionMap = <Map<number>>option.type;
// verify that map contains only numbers
for (const id in optionMap) {
Debug.assert(typeof optionMap[id] === "number");
}
map[option.name] = optionMap;
}
}
return map;
}
const compilerOptionConverters = prepareConvertersForEnumLikeCompilerOptions(optionDeclarations);
const indentStyle = createMap({
"none": IndentStyle.None,
"block": IndentStyle.Block,
"smart": IndentStyle.Smart
});
export function convertFormatOptions(protocolOptions: protocol.FormatCodeSettings): FormatCodeSettings {
if (typeof protocolOptions.indentStyle === "string") {
protocolOptions.indentStyle = indentStyle[protocolOptions.indentStyle.toLowerCase()];
Debug.assert(protocolOptions.indentStyle !== undefined);
}
return <any>protocolOptions;
}
export function convertCompilerOptions(protocolOptions: protocol.ExternalProjectCompilerOptions): CompilerOptions & protocol.CompileOnSaveMixin {
for (const id in compilerOptionConverters) {
const propertyValue = protocolOptions[id];
if (typeof propertyValue === "string") {
const mappedValues = compilerOptionConverters[id];
protocolOptions[id] = mappedValues[propertyValue.toLowerCase()];
}
}
return <any>protocolOptions;
}
export function tryConvertScriptKindName(scriptKindName: protocol.ScriptKindName | ScriptKind): ScriptKind {
return typeof scriptKindName === "string"
? convertScriptKindName(scriptKindName)
: scriptKindName;
}
export function convertScriptKindName(scriptKindName: protocol.ScriptKindName) {
switch (scriptKindName) {
case "JS":
return ScriptKind.JS;
case "JSX":
return ScriptKind.JSX;
case "TS":
return ScriptKind.TS;
case "TSX":
return ScriptKind.TSX;
default:
return ScriptKind.Unknown;
}
}
/**
* This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project.
*/
@ -63,7 +125,7 @@ namespace ts.server {
const externalFilePropertyReader: FilePropertyReader<protocol.ExternalFile> = {
getFileName: x => x.fileName,
getScriptKind: x => x.scriptKind,
getScriptKind: x => tryConvertScriptKindName(x.scriptKind),
hasMixedContent: x => x.hasMixedContent
};
@ -214,6 +276,10 @@ namespace ts.server {
this.ensureInferredProjectsUpToDate();
}
getCompilerOptionsForInferredProjects() {
return this.compilerOptionsForInferredProjects;
}
updateTypingsForProject(response: SetTypings | InvalidateCachedTypings): void {
const project = this.findProject(response.projectName);
if (!project) {
@ -231,10 +297,10 @@ namespace ts.server {
}
setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions): void {
this.compilerOptionsForInferredProjects = projectCompilerOptions;
this.compilerOptionsForInferredProjects = convertCompilerOptions(projectCompilerOptions);
this.compileOnSaveForInferredProjects = projectCompilerOptions.compileOnSave;
for (const proj of this.inferredProjects) {
proj.setCompilerOptions(projectCompilerOptions);
proj.setCompilerOptions(this.compilerOptionsForInferredProjects);
proj.compileOnSaveEnabled = projectCompilerOptions.compileOnSave;
}
this.updateProjectGraphs(this.inferredProjects);
@ -392,12 +458,12 @@ namespace ts.server {
this.throttledOperations.schedule(
project.configFileName,
/*delay*/250,
() => this.handleChangeInSourceFileForConfiguredProject(project));
() => this.handleChangeInSourceFileForConfiguredProject(project, fileName));
}
private handleChangeInSourceFileForConfiguredProject(project: ConfiguredProject) {
private handleChangeInSourceFileForConfiguredProject(project: ConfiguredProject, triggerFile: string) {
const { projectOptions, configFileErrors } = this.convertConfigFileContentToProjectOptions(project.configFileName);
this.reportConfigFileDiagnostics(project.getProjectName(), configFileErrors);
this.reportConfigFileDiagnostics(project.getProjectName(), configFileErrors, triggerFile);
const newRootFiles = projectOptions.files.map((f => this.getCanonicalFileName(f)));
const currentRootFiles = project.getRootFiles().map((f => this.getCanonicalFileName(f)));
@ -434,7 +500,7 @@ namespace ts.server {
}
const { configFileErrors } = this.convertConfigFileContentToProjectOptions(fileName);
this.reportConfigFileDiagnostics(fileName, configFileErrors);
this.reportConfigFileDiagnostics(fileName, configFileErrors, fileName);
this.logger.info(`Detected newly added tsconfig file: ${fileName}`);
this.reloadProjects();
@ -744,12 +810,13 @@ namespace ts.server {
}
private createAndAddExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typingOptions: TypingOptions) {
const compilerOptions = convertCompilerOptions(options);
const project = new ExternalProject(
projectFileName,
this,
this.documentRegistry,
options,
/*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(options, files, externalFilePropertyReader),
compilerOptions,
/*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(compilerOptions, files, externalFilePropertyReader),
options.compileOnSave === undefined ? true : options.compileOnSave);
this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typingOptions, /*configFileErrors*/ undefined);
@ -757,7 +824,7 @@ namespace ts.server {
return project;
}
private reportConfigFileDiagnostics(configFileName: string, diagnostics: Diagnostic[], triggerFile?: string) {
private reportConfigFileDiagnostics(configFileName: string, diagnostics: Diagnostic[], triggerFile: string) {
if (!this.eventHandler) {
return;
}
@ -1018,7 +1085,7 @@ namespace ts.server {
if (args.file) {
const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file));
if (info) {
info.setFormatOptions(args.formatOptions);
info.setFormatOptions(convertFormatOptions(args.formatOptions));
this.logger.info(`Host configuration update for file ${args.file}`);
}
}
@ -1028,7 +1095,7 @@ namespace ts.server {
this.logger.info(`Host information ${args.hostInfo}`);
}
if (args.formatOptions) {
mergeMaps(this.hostConfiguration.formatCodeOptions, args.formatOptions);
mergeMaps(this.hostConfiguration.formatCodeOptions, convertFormatOptions(args.formatOptions));
this.logger.info("Format host information updated");
}
}
@ -1142,7 +1209,7 @@ namespace ts.server {
const scriptInfo = this.getScriptInfo(file.fileName);
Debug.assert(!scriptInfo || !scriptInfo.isOpen);
const normalizedPath = scriptInfo ? scriptInfo.fileName : toNormalizedPath(file.fileName);
this.openClientFileWithNormalizedPath(normalizedPath, file.content, file.scriptKind, file.hasMixedContent);
this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent);
}
}
@ -1235,7 +1302,7 @@ namespace ts.server {
if (externalProject) {
if (!tsConfigFiles) {
// external project already exists and not config files were added - update the project and return;
this.updateNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, proj.options, proj.typingOptions, proj.options.compileOnSave, /*configFileErrors*/ undefined);
this.updateNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, convertCompilerOptions(proj.options), proj.typingOptions, proj.options.compileOnSave, /*configFileErrors*/ undefined);
return;
}
// some config files were added to external project (that previously were not there)

View file

@ -437,11 +437,11 @@ namespace ts.server {
}
}
reloadScript(filename: NormalizedPath): boolean {
reloadScript(filename: NormalizedPath, tempFileName?: NormalizedPath): boolean {
const script = this.projectService.getScriptInfoForNormalizedPath(filename);
if (script) {
Debug.assert(script.isAttached(this));
script.reloadFromFile();
script.reloadFromFile(tempFileName);
return true;
}
return false;

View file

@ -109,7 +109,7 @@ namespace ts.server.protocol {
/**
* One of "request", "response", or "event"
*/
type: string;
type: "request" | "response" | "event";
}
/**
@ -833,7 +833,7 @@ namespace ts.server.protocol {
/**
* Script kind of the file
*/
scriptKind?: ScriptKind;
scriptKind?: ScriptKindName | ts.ScriptKind;
/**
* Whether file has mixed content (i.e. .cshtml file that combines html markup with C#/JavaScript)
*/
@ -866,20 +866,23 @@ namespace ts.server.protocol {
typingOptions?: TypingOptions;
}
/**
* For external projects, some of the project settings are sent together with
* compiler settings.
*/
export interface ExternalProjectCompilerOptions extends CompilerOptions {
export interface CompileOnSaveMixin {
/**
* If compile on save is enabled for the project
*/
compileOnSave?: boolean;
}
/**
* For external projects, some of the project settings are sent together with
* compiler settings.
*/
export type ExternalProjectCompilerOptions = CompilerOptions & CompileOnSaveMixin;
/**
* Contains information about current project version
*/
/* @internal */
export interface ProjectVersionInfo {
/**
* Project name
@ -896,7 +899,7 @@ namespace ts.server.protocol {
/**
* Current set of compiler options for project
*/
options: CompilerOptions;
options: ts.CompilerOptions;
}
/**
@ -920,6 +923,7 @@ namespace ts.server.protocol {
* if changes is set - then this is the set of changes that should be applied to existing project
* otherwise - assume that nothing is changed
*/
/* @internal */
export interface ProjectFiles {
/**
* Information abount project verison
@ -938,6 +942,7 @@ namespace ts.server.protocol {
/**
* Combines project information with project level errors.
*/
/* @internal */
export interface ProjectFilesWithDiagnostics extends ProjectFiles {
/**
* List of errors in project
@ -1012,9 +1017,11 @@ namespace ts.server.protocol {
* Used to specify the script kind of the file explicitly. It could be one of the following:
* "TS", "JS", "TSX", "JSX"
*/
scriptKindName?: "TS" | "JS" | "TSX" | "JSX";
scriptKindName?: ScriptKindName;
}
export type ScriptKindName = "TS" | "JS" | "TSX" | "JSX";
/**
* Open request; value of command field is "open". Notify the
* server that the client has file open. The server will not
@ -1109,6 +1116,7 @@ namespace ts.server.protocol {
/**
* Arguments to SynchronizeProjectListRequest
*/
/* @internal */
export interface SynchronizeProjectListRequestArgs {
/**
* List of last known projects
@ -2056,4 +2064,141 @@ namespace ts.server.protocol {
export interface NavTreeResponse extends Response {
body?: NavigationTree;
}
export namespace IndentStyle {
export type None = "None";
export type Block = "Block";
export type Smart = "Smart";
}
export type IndentStyle = IndentStyle.None | IndentStyle.Block | IndentStyle.Smart;
export interface EditorSettings {
baseIndentSize?: number;
indentSize?: number;
tabSize?: number;
newLineCharacter?: string;
convertTabsToSpaces?: boolean;
indentStyle?: IndentStyle | ts.IndentStyle;
}
export interface FormatCodeSettings extends EditorSettings {
insertSpaceAfterCommaDelimiter?: boolean;
insertSpaceAfterSemicolonInForStatements?: boolean;
insertSpaceBeforeAndAfterBinaryOperators?: boolean;
insertSpaceAfterKeywordsInControlFlowStatements?: boolean;
insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean;
insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean;
insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean;
insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean;
placeOpenBraceOnNewLineForFunctions?: boolean;
placeOpenBraceOnNewLineForControlBlocks?: boolean;
}
export interface CompilerOptions {
allowJs?: boolean;
allowSyntheticDefaultImports?: boolean;
allowUnreachableCode?: boolean;
allowUnusedLabels?: boolean;
baseUrl?: string;
charset?: string;
declaration?: boolean;
declarationDir?: string;
disableSizeLimit?: boolean;
emitBOM?: boolean;
emitDecoratorMetadata?: boolean;
experimentalDecorators?: boolean;
forceConsistentCasingInFileNames?: boolean;
inlineSourceMap?: boolean;
inlineSources?: boolean;
isolatedModules?: boolean;
jsx?: JsxEmit | ts.JsxEmit;
lib?: string[];
locale?: string;
mapRoot?: string;
maxNodeModuleJsDepth?: number;
module?: ModuleKind | ts.ModuleKind;
moduleResolution?: ModuleResolutionKind | ts.ModuleResolutionKind;
newLine?: NewLineKind | ts.NewLineKind;
noEmit?: boolean;
noEmitHelpers?: boolean;
noEmitOnError?: boolean;
noErrorTruncation?: boolean;
noFallthroughCasesInSwitch?: boolean;
noImplicitAny?: boolean;
noImplicitReturns?: boolean;
noImplicitThis?: boolean;
noUnusedLocals?: boolean;
noUnusedParameters?: boolean;
noImplicitUseStrict?: boolean;
noLib?: boolean;
noResolve?: boolean;
out?: string;
outDir?: string;
outFile?: string;
paths?: MapLike<string[]>;
preserveConstEnums?: boolean;
project?: string;
reactNamespace?: string;
removeComments?: boolean;
rootDir?: string;
rootDirs?: string[];
skipLibCheck?: boolean;
skipDefaultLibCheck?: boolean;
sourceMap?: boolean;
sourceRoot?: string;
strictNullChecks?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
target?: ScriptTarget | ts.ScriptTarget;
traceResolution?: boolean;
types?: string[];
/** Paths used to used to compute primary types search locations */
typeRoots?: string[];
[option: string]: CompilerOptionsValue | undefined;
}
export namespace JsxEmit {
export type None = "None";
export type Preserve = "Preserve";
export type React = "React";
}
export type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React;
export namespace ModuleKind {
export type None = "None";
export type CommonJS = "CommonJS";
export type AMD = "AMD";
export type UMD = "UMD";
export type System = "System";
export type ES6 = "ES6";
export type ES2015 = "ES2015";
}
export type ModuleKind = ModuleKind.None | ModuleKind.CommonJS | ModuleKind.AMD | ModuleKind.UMD | ModuleKind.System | ModuleKind.ES6 | ModuleKind.ES2015;
export namespace ModuleResolutionKind {
export type Classic = "Classic";
export type Node = "Node";
}
export type ModuleResolutionKind = ModuleResolutionKind.Classic | ModuleResolutionKind.Node;
export namespace NewLineKind {
export type Crlf = "Crlf";
export type Lf = "Lf";
}
export type NewLineKind = NewLineKind.Crlf | NewLineKind.Lf;
export namespace ScriptTarget {
export type ES3 = "ES3";
export type ES5 = "ES5";
export type ES6 = "ES6";
export type ES2015 = "ES2015";
}
export type ScriptTarget = ScriptTarget.ES3 | ScriptTarget.ES5 | ScriptTarget.ES6 | ScriptTarget.ES2015;
}

View file

@ -87,7 +87,6 @@ namespace ts.server {
if (this.containingProjects.length === 0) {
return Errors.ThrowNoProject();
}
Debug.assert(this.containingProjects.length !== 0);
return this.containingProjects[0];
}
@ -126,12 +125,12 @@ namespace ts.server {
this.host.writeFile(fileName, snap.getText(0, snap.getLength()));
}
reloadFromFile() {
reloadFromFile(tempFileName?: NormalizedPath) {
if (this.hasMixedContent) {
this.reload("");
}
else {
this.svc.reloadFromFile(this.fileName);
this.svc.reloadFromFile(tempFileName || this.fileName);
this.markContainingProjectsAsDirty();
}
}

View file

@ -389,9 +389,9 @@ namespace ts.server {
});
}
private getDiagnosticsWorker(args: protocol.FileRequestArgs, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) {
private getDiagnosticsWorker(args: protocol.FileRequestArgs, isSemantic: boolean, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) {
const { project, file } = this.getFileAndProject(args);
if (shouldSkipSematicCheck(project)) {
if (isSemantic && shouldSkipSematicCheck(project)) {
return [];
}
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
@ -492,11 +492,11 @@ namespace ts.server {
}
private getSyntacticDiagnosticsSync(args: protocol.SyntacticDiagnosticsSyncRequestArgs): protocol.Diagnostic[] | protocol.DiagnosticWithLinePosition[] {
return this.getDiagnosticsWorker(args, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), args.includeLinePosition);
return this.getDiagnosticsWorker(args, /*isSemantic*/ false, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), args.includeLinePosition);
}
private getSemanticDiagnosticsSync(args: protocol.SemanticDiagnosticsSyncRequestArgs): protocol.Diagnostic[] | protocol.DiagnosticWithLinePosition[] {
return this.getDiagnosticsWorker(args, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition);
return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition);
}
private getDocumentHighlights(args: protocol.DocumentHighlightsRequestArgs, simplifiedResult: boolean): protocol.DocumentHighlightsItem[] | DocumentHighlights[] {
@ -761,7 +761,7 @@ namespace ts.server {
if (this.eventHander) {
this.eventHander({
eventName: "configFileDiag",
data: { fileName, configFileName, diagnostics: configFileErrors || [] }
data: { triggerFile: fileName, configFileName, diagnostics: configFileErrors || [] }
});
}
}
@ -807,7 +807,7 @@ namespace ts.server {
private getIndentation(args: protocol.IndentationRequestArgs) {
const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args);
const position = this.getPosition(args, project.getScriptInfoForNormalizedPath(file));
const options = args.options || this.projectService.getFormatCodeOptions(file);
const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(file);
const indentation = project.getLanguageService(/*ensureSynchronized*/ false).getIndentationAtPosition(file, position, options);
return { position, indentation };
}
@ -874,19 +874,19 @@ namespace ts.server {
private getFormattingEditsForRangeFull(args: protocol.FormatRequestArgs) {
const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args);
const options = args.options || this.projectService.getFormatCodeOptions(file);
const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(file);
return project.getLanguageService(/*ensureSynchronized*/ false).getFormattingEditsForRange(file, args.position, args.endPosition, options);
}
private getFormattingEditsForDocumentFull(args: protocol.FormatRequestArgs) {
const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args);
const options = args.options || this.projectService.getFormatCodeOptions(file);
const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(file);
return project.getLanguageService(/*ensureSynchronized*/ false).getFormattingEditsForDocument(file, options);
}
private getFormattingEditsAfterKeystrokeFull(args: protocol.FormatOnKeyRequestArgs) {
const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args);
const options = args.options || this.projectService.getFormatCodeOptions(file);
const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(file);
return project.getLanguageService(/*ensureSynchronized*/ false).getFormattingEditsAfterKeystroke(file, args.position, args.key, options);
}
@ -967,7 +967,7 @@ namespace ts.server {
result.push({ name, kind, kindModifiers, sortText, replacementSpan: convertedSpan });
}
return result;
}, []).sort((a, b) => a.name.localeCompare(b.name));
}, []).sort((a, b) => ts.compareStrings(a.name, b.name));
}
else {
return completions;
@ -1076,11 +1076,12 @@ namespace ts.server {
private reload(args: protocol.ReloadRequestArgs, reqSeq: number) {
const file = toNormalizedPath(args.file);
const tempFileName = args.tmpfile && toNormalizedPath(args.tmpfile);
const project = this.projectService.getDefaultProjectForFile(file, /*refreshInferredProjects*/ true);
if (project) {
this.changeSeq++;
// make sure no changes happen before this one is finished
if (project.reloadScript(file)) {
if (project.reloadScript(file, tempFileName)) {
this.output(undefined, CommandNames.Reload, reqSeq);
}
}
@ -1426,24 +1427,8 @@ namespace ts.server {
[CommandNames.RenameInfoFull]: (request: protocol.FileLocationRequest) => {
return this.requiredResponse(this.getRenameInfo(request.arguments));
},
[CommandNames.Open]: (request: protocol.Request) => {
const openArgs = <protocol.OpenRequestArgs>request.arguments;
let scriptKind: ScriptKind;
switch (openArgs.scriptKindName) {
case "TS":
scriptKind = ScriptKind.TS;
break;
case "JS":
scriptKind = ScriptKind.JS;
break;
case "TSX":
scriptKind = ScriptKind.TSX;
break;
case "JSX":
scriptKind = ScriptKind.JSX;
break;
}
this.openClientFile(toNormalizedPath(openArgs.file), openArgs.fileContent, scriptKind);
[CommandNames.Open]: (request: protocol.OpenRequest) => {
this.openClientFile(toNormalizedPath(request.arguments.file), request.arguments.fileContent, convertScriptKindName(request.arguments.scriptKindName));
return this.notRequired();
},
[CommandNames.Quickinfo]: (request: protocol.QuickInfoRequest) => {

View file

@ -10,7 +10,8 @@
"stripInternal": true,
"types": [
"node"
]
],
"target": "es5"
},
"files": [
"../services/shims.ts",

View file

@ -7,7 +7,8 @@
"sourceMap": true,
"stripInternal": true,
"declaration": true,
"types": []
"types": [],
"target": "es5"
},
"files": [
"../services/shims.ts",

View file

@ -10,7 +10,8 @@
"stripInternal": true,
"types": [
"node"
]
],
"target": "es5"
},
"files": [
"../types.d.ts",

View file

@ -1,3 +1,5 @@
/// <reference path='../compiler/utilities.ts' />
/* @internal */
namespace ts.Completions {
export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: (message: string) => void, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo {
@ -951,7 +953,6 @@ namespace ts.Completions {
if (!tryGetGlobalSymbols()) {
return undefined;
}
isGlobalCompletion = true;
}
log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
@ -1030,7 +1031,6 @@ namespace ts.Completions {
if ((jsxContainer.kind === SyntaxKind.JsxSelfClosingElement) || (jsxContainer.kind === SyntaxKind.JsxOpeningElement)) {
// Cursor is inside a JSX self-closing element or opening element
attrsType = typeChecker.getJsxElementAttributesType(<JsxOpeningLikeElement>jsxContainer);
isGlobalCompletion = false;
if (attrsType) {
symbols = filterJsxAttributes(typeChecker.getPropertiesOfType(attrsType), (<JsxOpeningLikeElement>jsxContainer).attributes);
@ -1038,7 +1038,6 @@ namespace ts.Completions {
isNewIdentifierLocation = false;
return true;
}
}
}
@ -1079,6 +1078,13 @@ namespace ts.Completions {
position;
const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
if (scopeNode) {
isGlobalCompletion =
scopeNode.kind === SyntaxKind.SourceFile ||
scopeNode.kind === SyntaxKind.TemplateExpression ||
scopeNode.kind === SyntaxKind.JsxExpression ||
isStatement(scopeNode);
}
/// TODO filter meaning based on the current context
const symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;

View file

@ -624,10 +624,11 @@ namespace ts.formatting {
return inheritedIndentation;
}
if (isToken(child)) {
// JSX text shouldn't affect indenting
if (isToken(child) && child.kind !== SyntaxKind.JsxText) {
// if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
const tokenInfo = formattingScanner.readTokenInfo(child);
Debug.assert(tokenInfo.token.end === child.end);
Debug.assert(tokenInfo.token.end === child.end, "Token end is child end");
consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child);
return inheritedIndentation;
}

View file

@ -31,7 +31,7 @@ namespace ts.formatting {
}
export function getFormattingScanner(sourceFile: SourceFile, startPos: number, endPos: number): FormattingScanner {
Debug.assert(scanner === undefined);
Debug.assert(scanner === undefined, "Scanner should be undefined");
scanner = sourceFile.languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner;
scanner.setText(sourceFile.text);
@ -62,7 +62,7 @@ namespace ts.formatting {
};
function advance(): void {
Debug.assert(scanner !== undefined);
Debug.assert(scanner !== undefined, "Scanner should be present");
lastTokenInfo = undefined;
const isStarted = scanner.getStartPos() !== startPos;

View file

@ -35,8 +35,8 @@ namespace ts.formatting {
}
private GetRuleBucketIndex(row: number, column: number): number {
Debug.assert(row <= SyntaxKind.LastKeyword && column <= SyntaxKind.LastKeyword, "Must compute formatting context from tokens");
const rulesBucketIndex = (row * this.mapRowLength) + column;
// Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array.");
return rulesBucketIndex;
}

View file

@ -6,9 +6,6 @@ namespace ts.NavigateTo {
const patternMatcher = createPatternMatcher(searchValue);
let rawItems: RawNavigateToItem[] = [];
// 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[]
forEach(sourceFiles, sourceFile => {
cancellationToken.throwIfCancellationRequested();
@ -188,8 +185,8 @@ namespace ts.NavigateTo {
// We first sort case insensitively. So "Aaa" will come before "bar".
// Then we sort case sensitively, so "aaa" will come before "Aaa".
return i1.matchKind - i2.matchKind ||
i1.name.localeCompare(i2.name, undefined, baseSensitivity) ||
i1.name.localeCompare(i2.name);
ts.compareStringsCaseInsensitive(i1.name, i2.name) ||
ts.compareStrings(i1.name, i2.name);
}
function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem {

View file

@ -330,10 +330,8 @@ namespace ts.NavigationBar {
}
}
// More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times.
const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator() : undefined;
// Intl is missing in Safari, and node 0.10 treats "a" as greater than "B".
const localeCompareIsCorrect = collator && collator.compare("a", "B") < 0;
const localeCompareIsCorrect = ts.collator && ts.collator.compare("a", "B") < 0;
const localeCompareFix: (a: string, b: string) => number = localeCompareIsCorrect ? collator.compare : function(a, b) {
// This isn't perfect, but it passes all of our tests.
for (let i = 0; i < Math.min(a.length, b.length); i++) {
@ -344,7 +342,7 @@ namespace ts.NavigationBar {
if (chA === "'" && chB === "\"") {
return -1;
}
const cmp = chA.toLocaleLowerCase().localeCompare(chB.toLocaleLowerCase());
const cmp = ts.compareStrings(chA.toLocaleLowerCase(), chB.toLocaleLowerCase());
if (cmp !== 0) {
return cmp;
}

View file

@ -444,7 +444,7 @@ namespace ts {
}
public readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[], depth?: number): string[] {
const pattern = getFileMatcherPatterns(path, extensions, exclude, include,
const pattern = getFileMatcherPatterns(path, exclude, include,
this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory());
return JSON.parse(this.shimHost.readDirectory(
path,
@ -509,7 +509,7 @@ namespace ts {
// Wrap the API changes for 2.0 release. This try/catch
// should be removed once TypeScript 2.0 has shipped.
try {
const pattern = getFileMatcherPatterns(rootDir, extensions, exclude, include,
const pattern = getFileMatcherPatterns(rootDir, exclude, include,
this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory());
return JSON.parse(this.shimHost.readDirectory(
rootDir,

View file

@ -9,7 +9,8 @@
"sourceMap": true,
"stripInternal": true,
"noResolve": false,
"declaration": true
"declaration": true,
"target": "es5"
},
"files": [
"../compiler/core.ts",
@ -26,13 +27,15 @@
"../compiler/transformers/ts.ts",
"../compiler/transformers/jsx.ts",
"../compiler/transformers/experimental.ts",
"../compiler/transformers/es7.ts",
"../compiler/transformers/es6.ts",
"../compiler/transformers/es2017.ts",
"../compiler/transformers/es2016.ts",
"../compiler/transformers/es2015.ts",
"../compiler/transformers/generators.ts",
"../compiler/transformers/generators.ts",
"../compiler/transformers/destructuring.ts",
"../compiler/transformers/module/module.ts",
"../compiler/transformers/module/system.ts",
"../compiler/transformers/module/es6.ts",
"../compiler/transformers/module/es2015.ts",
"../compiler/transformer.ts",
"../compiler/comments.ts",
"../compiler/sourcemap.ts",

View file

@ -750,7 +750,7 @@ namespace ts {
return find(startNode || sourceFile);
function findRightmostToken(n: Node): Node {
if (isToken(n) || n.kind === SyntaxKind.JsxText) {
if (isToken(n)) {
return n;
}
@ -761,7 +761,7 @@ namespace ts {
}
function find(n: Node): Node {
if (isToken(n) || n.kind === SyntaxKind.JsxText) {
if (isToken(n)) {
return n;
}
@ -1339,7 +1339,7 @@ namespace ts {
const options: TranspileOptions = {
fileName: "config.js",
compilerOptions: {
target: ScriptTarget.ES6,
target: ScriptTarget.ES2015,
removeComments: true
},
reportDiagnostics: true

View file

@ -58,7 +58,7 @@ export function delint(sourceFile: ts.SourceFile) {
const fileNames: string[] = process.argv.slice(2);
fileNames.forEach(fileName => {
// Parse a file
let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true);
let sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES2015, /*setParentNodes */ true);
// delint it
delint(sourceFile);
@ -113,7 +113,7 @@ exports.delint = delint;
var fileNames = process.argv.slice(2);
fileNames.forEach(function (fileName) {
// Parse a file
var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true);
var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES2015, /*setParentNodes */ true);
// delint it
delint(sourceFile);
});

View file

@ -13,5 +13,5 @@ Foo.default.default.foo();
//// [a.js]
"use strict";
var Foo = require("./b");
Foo.default.bar();
Foo.default.default.foo();
Foo["default"].bar();
Foo["default"]["default"].foo();

View file

@ -0,0 +1,6 @@
//// [arrowFunctionWithParameterNameAsync_es2017.ts]
const x = async => async;
//// [arrowFunctionWithParameterNameAsync_es2017.js]
var x = function (async) { return async; };

View file

@ -0,0 +1,7 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es2017.ts ===
const x = async => async;
>x : Symbol(x, Decl(arrowFunctionWithParameterNameAsync_es2017.ts, 1, 5))
>async : Symbol(async, Decl(arrowFunctionWithParameterNameAsync_es2017.ts, 1, 9))
>async : Symbol(async, Decl(arrowFunctionWithParameterNameAsync_es2017.ts, 1, 9))

View file

@ -0,0 +1,8 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/arrowFunctionWithParameterNameAsync_es2017.ts ===
const x = async => async;
>x : (async: any) => any
>async => async : (async: any) => any
>async : any
>async : any

View file

@ -0,0 +1,12 @@
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction10_es2017.ts(4,11): error TS2304: Cannot find name 'await'.
==== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction10_es2017.ts (1 errors) ====
var foo = async (): Promise<void> => {
// Legal to use 'await' in a type context.
var v: await;
~~~~~
!!! error TS2304: Cannot find name 'await'.
}

View file

@ -0,0 +1,13 @@
//// [asyncArrowFunction10_es2017.ts]
var foo = async (): Promise<void> => {
// Legal to use 'await' in a type context.
var v: await;
}
//// [asyncArrowFunction10_es2017.js]
var foo = async () => {
// Legal to use 'await' in a type context.
var v;
};

View file

@ -0,0 +1,8 @@
//// [asyncArrowFunction1_es2017.ts]
var foo = async (): Promise<void> => {
};
//// [asyncArrowFunction1_es2017.js]
var foo = async () => {
};

View file

@ -0,0 +1,7 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction1_es2017.ts ===
var foo = async (): Promise<void> => {
>foo : Symbol(foo, Decl(asyncArrowFunction1_es2017.ts, 1, 3))
>Promise : Symbol(Promise, Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --))
};

View file

@ -0,0 +1,8 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction1_es2017.ts ===
var foo = async (): Promise<void> => {
>foo : () => Promise<void>
>async (): Promise<void> => {} : () => Promise<void>
>Promise : Promise<T>
};

View file

@ -0,0 +1,7 @@
//// [asyncArrowFunction2_es2017.ts]
var f = (await) => {
}
//// [asyncArrowFunction2_es2017.js]
var f = (await) => {
};

View file

@ -0,0 +1,5 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction2_es2017.ts ===
var f = (await) => {
>f : Symbol(f, Decl(asyncArrowFunction2_es2017.ts, 0, 3))
>await : Symbol(await, Decl(asyncArrowFunction2_es2017.ts, 0, 9))
}

View file

@ -0,0 +1,6 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction2_es2017.ts ===
var f = (await) => {
>f : (await: any) => void
>(await) => {} : (await: any) => void
>await : any
}

View file

@ -0,0 +1,8 @@
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction3_es2017.ts(1,20): error TS2372: Parameter 'await' cannot be referenced in its initializer.
==== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction3_es2017.ts (1 errors) ====
function f(await = await) {
~~~~~
!!! error TS2372: Parameter 'await' cannot be referenced in its initializer.
}

View file

@ -0,0 +1,7 @@
//// [asyncArrowFunction3_es2017.ts]
function f(await = await) {
}
//// [asyncArrowFunction3_es2017.js]
function f(await = await) {
}

View file

@ -0,0 +1,7 @@
//// [asyncArrowFunction4_es2017.ts]
var await = () => {
}
//// [asyncArrowFunction4_es2017.js]
var await = () => {
};

View file

@ -0,0 +1,4 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction4_es2017.ts ===
var await = () => {
>await : Symbol(await, Decl(asyncArrowFunction4_es2017.ts, 0, 3))
}

View file

@ -0,0 +1,5 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction4_es2017.ts ===
var await = () => {
>await : () => void
>() => {} : () => void
}

View file

@ -0,0 +1,24 @@
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction5_es2017.ts(2,11): error TS2304: Cannot find name 'async'.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction5_es2017.ts(2,18): error TS2304: Cannot find name 'await'.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction5_es2017.ts(2,24): error TS1005: ',' expected.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction5_es2017.ts(2,26): error TS2403: Subsequent variable declarations must have the same type. Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'void'.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction5_es2017.ts(2,33): error TS1005: '=' expected.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction5_es2017.ts(2,40): error TS1109: Expression expected.
==== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction5_es2017.ts (6 errors) ====
var foo = async (await): Promise<void> => {
~~~~~
!!! error TS2304: Cannot find name 'async'.
~~~~~
!!! error TS2304: Cannot find name 'await'.
~
!!! error TS1005: ',' expected.
~~~~~~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'void'.
~
!!! error TS1005: '=' expected.
~~
!!! error TS1109: Expression expected.
}

View file

@ -0,0 +1,9 @@
//// [asyncArrowFunction5_es2017.ts]
var foo = async (await): Promise<void> => {
}
//// [asyncArrowFunction5_es2017.js]
var foo = async(await), Promise = ;
{
}

View file

@ -0,0 +1,12 @@
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction6_es2017.ts(2,22): error TS2524: 'await' expressions cannot be used in a parameter initializer.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction6_es2017.ts(2,27): error TS1109: Expression expected.
==== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction6_es2017.ts (2 errors) ====
var foo = async (a = await): Promise<void> => {
~~~~~
!!! error TS2524: 'await' expressions cannot be used in a parameter initializer.
~
!!! error TS1109: Expression expected.
}

View file

@ -0,0 +1,8 @@
//// [asyncArrowFunction6_es2017.ts]
var foo = async (a = await): Promise<void> => {
}
//// [asyncArrowFunction6_es2017.js]
var foo = async (a = await ) => {
};

View file

@ -0,0 +1,15 @@
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction7_es2017.ts(4,24): error TS2524: 'await' expressions cannot be used in a parameter initializer.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction7_es2017.ts(4,29): error TS1109: Expression expected.
==== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction7_es2017.ts (2 errors) ====
var bar = async (): Promise<void> => {
// 'await' here is an identifier, and not an await expression.
var foo = async (a = await): Promise<void> => {
~~~~~
!!! error TS2524: 'await' expressions cannot be used in a parameter initializer.
~
!!! error TS1109: Expression expected.
}
}

View file

@ -0,0 +1,14 @@
//// [asyncArrowFunction7_es2017.ts]
var bar = async (): Promise<void> => {
// 'await' here is an identifier, and not an await expression.
var foo = async (a = await): Promise<void> => {
}
}
//// [asyncArrowFunction7_es2017.js]
var bar = async () => {
// 'await' here is an identifier, and not an await expression.
var foo = async (a = await ) => {
};
};

View file

@ -0,0 +1,10 @@
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction8_es2017.ts(3,19): error TS1109: Expression expected.
==== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction8_es2017.ts (1 errors) ====
var foo = async (): Promise<void> => {
var v = { [await]: foo }
~
!!! error TS1109: Expression expected.
}

View file

@ -0,0 +1,10 @@
//// [asyncArrowFunction8_es2017.ts]
var foo = async (): Promise<void> => {
var v = { [await]: foo }
}
//// [asyncArrowFunction8_es2017.js]
var foo = async () => {
var v = { [await ]: foo };
};

View file

@ -0,0 +1,23 @@
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction9_es2017.ts(1,11): error TS2304: Cannot find name 'async'.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction9_es2017.ts(1,18): error TS2304: Cannot find name 'a'.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction9_es2017.ts(1,37): error TS1005: ',' expected.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction9_es2017.ts(1,39): error TS2403: Subsequent variable declarations must have the same type. Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'void'.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction9_es2017.ts(1,46): error TS1005: '=' expected.
tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction9_es2017.ts(1,53): error TS1109: Expression expected.
==== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction9_es2017.ts (6 errors) ====
var foo = async (a = await => await): Promise<void> => {
~~~~~
!!! error TS2304: Cannot find name 'async'.
~
!!! error TS2304: Cannot find name 'a'.
~
!!! error TS1005: ',' expected.
~~~~~~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'Promise' must be of type 'PromiseConstructor', but here has type 'void'.
~
!!! error TS1005: '=' expected.
~~
!!! error TS1109: Expression expected.
}

View file

@ -0,0 +1,8 @@
//// [asyncArrowFunction9_es2017.ts]
var foo = async (a = await => await): Promise<void> => {
}
//// [asyncArrowFunction9_es2017.js]
var foo = async(a = await => await), Promise = ;
{
}

View file

@ -0,0 +1,16 @@
//// [asyncArrowFunctionCapturesArguments_es2017.ts]
class C {
method() {
function other() {}
var fn = async () => await other.apply(this, arguments);
}
}
//// [asyncArrowFunctionCapturesArguments_es2017.js]
class C {
method() {
function other() { }
var fn = async () => await other.apply(this, arguments);
}
}

View file

@ -0,0 +1,20 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunctionCapturesArguments_es2017.ts ===
class C {
>C : Symbol(C, Decl(asyncArrowFunctionCapturesArguments_es2017.ts, 0, 0))
method() {
>method : Symbol(C.method, Decl(asyncArrowFunctionCapturesArguments_es2017.ts, 0, 9))
function other() {}
>other : Symbol(other, Decl(asyncArrowFunctionCapturesArguments_es2017.ts, 1, 13))
var fn = async () => await other.apply(this, arguments);
>fn : Symbol(fn, Decl(asyncArrowFunctionCapturesArguments_es2017.ts, 3, 9))
>other.apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --))
>other : Symbol(other, Decl(asyncArrowFunctionCapturesArguments_es2017.ts, 1, 13))
>apply : Symbol(Function.apply, Decl(lib.es5.d.ts, --, --))
>this : Symbol(C, Decl(asyncArrowFunctionCapturesArguments_es2017.ts, 0, 0))
>arguments : Symbol(arguments)
}
}

View file

@ -0,0 +1,23 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunctionCapturesArguments_es2017.ts ===
class C {
>C : C
method() {
>method : () => void
function other() {}
>other : () => void
var fn = async () => await other.apply(this, arguments);
>fn : () => Promise<any>
>async () => await other.apply(this, arguments) : () => Promise<any>
>await other.apply(this, arguments) : any
>other.apply(this, arguments) : any
>other.apply : (this: Function, thisArg: any, argArray?: any) => any
>other : () => void
>apply : (this: Function, thisArg: any, argArray?: any) => any
>this : this
>arguments : IArguments
}
}

View file

@ -0,0 +1,14 @@
//// [asyncArrowFunctionCapturesThis_es2017.ts]
class C {
method() {
var fn = async () => await this;
}
}
//// [asyncArrowFunctionCapturesThis_es2017.js]
class C {
method() {
var fn = async () => await this;
}
}

View file

@ -0,0 +1,13 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunctionCapturesThis_es2017.ts ===
class C {
>C : Symbol(C, Decl(asyncArrowFunctionCapturesThis_es2017.ts, 0, 0))
method() {
>method : Symbol(C.method, Decl(asyncArrowFunctionCapturesThis_es2017.ts, 0, 9))
var fn = async () => await this;
>fn : Symbol(fn, Decl(asyncArrowFunctionCapturesThis_es2017.ts, 2, 9))
>this : Symbol(C, Decl(asyncArrowFunctionCapturesThis_es2017.ts, 0, 0))
}
}

View file

@ -0,0 +1,15 @@
=== tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunctionCapturesThis_es2017.ts ===
class C {
>C : C
method() {
>method : () => void
var fn = async () => await this;
>fn : () => Promise<this>
>async () => await this : () => Promise<this>
>await this : this
>this : this
}
}

View file

@ -0,0 +1,45 @@
tests/cases/conformance/async/es2017/asyncAwaitIsolatedModules_es2017.ts(1,27): error TS2307: Cannot find module 'missing'.
==== tests/cases/conformance/async/es2017/asyncAwaitIsolatedModules_es2017.ts (1 errors) ====
import { MyPromise } from "missing";
~~~~~~~~~
!!! error TS2307: Cannot find module 'missing'.
declare var p: Promise<number>;
declare var mp: MyPromise<number>;
async function f0() { }
async function f1(): Promise<void> { }
async function f3(): MyPromise<void> { }
let f4 = async function() { }
let f5 = async function(): Promise<void> { }
let f6 = async function(): MyPromise<void> { }
let f7 = async () => { };
let f8 = async (): Promise<void> => { };
let f9 = async (): MyPromise<void> => { };
let f10 = async () => p;
let f11 = async () => mp;
let f12 = async (): Promise<number> => mp;
let f13 = async (): MyPromise<number> => p;
let o = {
async m1() { },
async m2(): Promise<void> { },
async m3(): MyPromise<void> { }
};
class C {
async m1() { }
async m2(): Promise<void> { }
async m3(): MyPromise<void> { }
static async m4() { }
static async m5(): Promise<void> { }
static async m6(): MyPromise<void> { }
}
module M {
export async function f1() { }
}

View file

@ -0,0 +1,73 @@
//// [asyncAwaitIsolatedModules_es2017.ts]
import { MyPromise } from "missing";
declare var p: Promise<number>;
declare var mp: MyPromise<number>;
async function f0() { }
async function f1(): Promise<void> { }
async function f3(): MyPromise<void> { }
let f4 = async function() { }
let f5 = async function(): Promise<void> { }
let f6 = async function(): MyPromise<void> { }
let f7 = async () => { };
let f8 = async (): Promise<void> => { };
let f9 = async (): MyPromise<void> => { };
let f10 = async () => p;
let f11 = async () => mp;
let f12 = async (): Promise<number> => mp;
let f13 = async (): MyPromise<number> => p;
let o = {
async m1() { },
async m2(): Promise<void> { },
async m3(): MyPromise<void> { }
};
class C {
async m1() { }
async m2(): Promise<void> { }
async m3(): MyPromise<void> { }
static async m4() { }
static async m5(): Promise<void> { }
static async m6(): MyPromise<void> { }
}
module M {
export async function f1() { }
}
//// [asyncAwaitIsolatedModules_es2017.js]
async function f0() { }
async function f1() { }
async function f3() { }
let f4 = async function () { };
let f5 = async function () { };
let f6 = async function () { };
let f7 = async () => { };
let f8 = async () => { };
let f9 = async () => { };
let f10 = async () => p;
let f11 = async () => mp;
let f12 = async () => mp;
let f13 = async () => p;
let o = {
async m1() { },
async m2() { },
async m3() { }
};
class C {
async m1() { }
async m2() { }
async m3() { }
static async m4() { }
static async m5() { }
static async m6() { }
}
var M;
(function (M) {
async function f1() { }
M.f1 = f1;
})(M || (M = {}));

View file

@ -0,0 +1,73 @@
//// [asyncAwait_es2017.ts]
type MyPromise<T> = Promise<T>;
declare var MyPromise: typeof Promise;
declare var p: Promise<number>;
declare var mp: MyPromise<number>;
async function f0() { }
async function f1(): Promise<void> { }
async function f3(): MyPromise<void> { }
let f4 = async function() { }
let f5 = async function(): Promise<void> { }
let f6 = async function(): MyPromise<void> { }
let f7 = async () => { };
let f8 = async (): Promise<void> => { };
let f9 = async (): MyPromise<void> => { };
let f10 = async () => p;
let f11 = async () => mp;
let f12 = async (): Promise<number> => mp;
let f13 = async (): MyPromise<number> => p;
let o = {
async m1() { },
async m2(): Promise<void> { },
async m3(): MyPromise<void> { }
};
class C {
async m1() { }
async m2(): Promise<void> { }
async m3(): MyPromise<void> { }
static async m4() { }
static async m5(): Promise<void> { }
static async m6(): MyPromise<void> { }
}
module M {
export async function f1() { }
}
//// [asyncAwait_es2017.js]
async function f0() { }
async function f1() { }
async function f3() { }
let f4 = async function () { };
let f5 = async function () { };
let f6 = async function () { };
let f7 = async () => { };
let f8 = async () => { };
let f9 = async () => { };
let f10 = async () => p;
let f11 = async () => mp;
let f12 = async () => mp;
let f13 = async () => p;
let o = {
async m1() { },
async m2() { },
async m3() { }
};
class C {
async m1() { }
async m2() { }
async m3() { }
static async m4() { }
static async m5() { }
static async m6() { }
}
var M;
(function (M) {
async function f1() { }
M.f1 = f1;
})(M || (M = {}));

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