Merge pull request #7191 from Microsoft/transforms-transformer-ts

Adds the TypeScript transformer
This commit is contained in:
Ron Buckton
2016-03-18 16:31:05 -07:00
72 changed files with 9323 additions and 994 deletions
+16
View File
@@ -42,6 +42,14 @@ var compilerSources = [
"checker.ts",
"factory.ts",
"visitor.ts",
"transformers/destructuring.ts",
"transformers/ts.ts",
"transformers/module/es6.ts",
"transformers/module/system.ts",
"transformers/module/module.ts",
"transformers/jsx.ts",
"transformers/es7.ts",
"transformers/es6.ts",
"transformer.ts",
"sourcemap.ts",
"comments.ts",
@@ -67,6 +75,14 @@ var servicesSources = [
"checker.ts",
"factory.ts",
"visitor.ts",
"transformers/destructuring.ts",
"transformers/ts.ts",
"transformers/module/es6.ts",
"transformers/module/system.ts",
"transformers/module/module.ts",
"transformers/jsx.ts",
"transformers/es7.ts",
"transformers/es6.ts",
"transformer.ts",
"sourcemap.ts",
"comments.ts",
+316 -213
View File
@@ -37,7 +37,7 @@ namespace ts {
return ModuleInstanceState.ConstEnumOnly;
}
// 3. non-exported import declarations
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && !(node.flags & NodeFlags.Export)) {
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && !(hasModifier(node, ModifierFlags.Export))) {
return ModuleInstanceState.NonInstantiated;
}
// 4. other uninstantiated module declarations.
@@ -133,7 +133,7 @@ namespace ts {
let classifiableNames: Map<string>;
// state used to aggregate transform flags during bind.
let subtreeTransformFlags: TransformFlags;
let subtreeTransformFlags: TransformFlags = TransformFlags.None;
let skipTransformFlagAggregation: boolean;
function bindSourceFile(f: SourceFile, opts: CompilerOptions) {
@@ -141,7 +141,6 @@ namespace ts {
options = opts;
inStrictMode = !!file.externalModuleIndicator;
classifiableNames = {};
subtreeTransformFlags = undefined;
skipTransformFlagAggregation = isDeclarationFile(file);
Symbol = objectAllocator.getSymbolConstructor();
@@ -167,6 +166,7 @@ namespace ts {
hasAsyncFunctions = false;
hasDecorators = false;
hasParameterDecorators = false;
subtreeTransformFlags = TransformFlags.None;
}
return bindSourceFile;
@@ -256,7 +256,7 @@ namespace ts {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ClassDeclaration:
return node.flags & NodeFlags.Default ? "default" : undefined;
return hasModifier(node, ModifierFlags.Default) ? "default" : undefined;
case SyntaxKind.JSDocFunctionType:
return isJSDocConstructSignature(node) ? "__new" : "__call";
case SyntaxKind.Parameter:
@@ -284,7 +284,7 @@ namespace ts {
function declareSymbol(symbolTable: SymbolTable, parent: Symbol, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags): Symbol {
Debug.assert(!hasDynamicName(node));
const isDefaultExport = node.flags & NodeFlags.Default;
const isDefaultExport = hasModifier(node, ModifierFlags.Default);
// The exported symbol for an export default function/class node is always named "default"
const name = isDefaultExport && parent ? "default" : getDeclarationName(node);
@@ -329,7 +329,7 @@ namespace ts {
: Diagnostics.Duplicate_identifier_0;
forEach(symbol.declarations, declaration => {
if (declaration.flags & NodeFlags.Default) {
if (hasModifier(declaration, ModifierFlags.Default)) {
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
}
});
@@ -353,7 +353,7 @@ namespace ts {
}
function declareModuleMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol {
const hasExportModifier = getCombinedNodeFlags(node) & NodeFlags.Export;
const hasExportModifier = getCombinedModifierFlags(node) & ModifierFlags.Export;
if (symbolFlags & SymbolFlags.Alias) {
if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) {
return declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes);
@@ -862,7 +862,7 @@ namespace ts {
}
function declareClassMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
return node.flags & NodeFlags.Static
return hasModifier(node, ModifierFlags.Static)
? declareSymbol(container.symbol.exports, container.symbol, node, symbolFlags, symbolExcludes)
: declareSymbol(container.symbol.members, container.symbol, node, symbolFlags, symbolExcludes);
}
@@ -899,7 +899,7 @@ namespace ts {
function bindModuleDeclaration(node: ModuleDeclaration) {
setExportContextFlag(node);
if (isAmbientModule(node)) {
if (node.flags & NodeFlags.Export) {
if (hasModifier(node, ModifierFlags.Export)) {
errorOnFirstToken(node, Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible);
}
declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
@@ -1184,41 +1184,22 @@ namespace ts {
// symbols we do specialized work when we recurse. For example, we'll keep track of
// the current 'container' node when it changes. This helps us know which symbol table
// a local should go into for example.
aggregateTransformFlagsIfNeededAndBindChildren(node);
inStrictMode = savedInStrictMode;
}
function aggregateTransformFlagsIfNeededAndBindChildren(node: Node) {
if (node.transformFlags !== undefined) {
skipTransformFlagAggregationAndBindChildren(node);
if (skipTransformFlagAggregation) {
bindChildren(node);
}
else {
aggregateTransformFlagsAndBindChildren(node);
}
}
function skipTransformFlagAggregationAndBindChildren(node: Node) {
if (!skipTransformFlagAggregation) {
else if (node.transformFlags & TransformFlags.HasComputedFlags) {
skipTransformFlagAggregation = true;
bindChildren(node);
skipTransformFlagAggregation = false;
}
else {
bindChildren(node);
}
}
function aggregateTransformFlagsAndBindChildren(node: Node) {
if (!skipTransformFlagAggregation) {
const savedSubtreeTransformFlags = subtreeTransformFlags;
subtreeTransformFlags = 0;
bindChildren(node);
subtreeTransformFlags = savedSubtreeTransformFlags | computeTransformFlagsForNode(node, subtreeTransformFlags);
}
else {
bindChildren(node);
}
inStrictMode = savedInStrictMode;
}
function updateStrictMode(node: Node) {
@@ -1799,15 +1780,9 @@ namespace ts {
* @param subtreeFlags Transform flags computed for this node's subtree
*/
export function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags): TransformFlags {
// Ambient nodes are TypeScript syntax and the flags of their subtree are ignored.
if (node.flags & NodeFlags.Ambient) {
return (node.transformFlags = TransformFlags.AssertTypeScript)
& ~(node.excludeTransformFlags = TransformFlags.NodeExcludes);
}
// Mark transformations needed for each node
let transformFlags: TransformFlags;
let excludeFlags: TransformFlags;
let transformFlags = TransformFlags.None;
let excludeFlags = TransformFlags.None;
switch (node.kind) {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
@@ -1823,7 +1798,7 @@ namespace ts {
case SyntaxKind.AsExpression:
case SyntaxKind.ReadonlyKeyword:
// These nodes are TypeScript syntax.
transformFlags |= TransformFlags.AssertTypeScript;
transformFlags = TransformFlags.AssertTypeScript;
break;
case SyntaxKind.JsxElement:
@@ -1835,12 +1810,12 @@ namespace ts {
case SyntaxKind.JsxSpreadAttribute:
case SyntaxKind.JsxExpression:
// These nodes are Jsx syntax.
transformFlags |= TransformFlags.AssertJsx;
transformFlags = TransformFlags.AssertJsx;
break;
case SyntaxKind.ExportKeyword:
// This node is both ES6 and TypeScript syntax.
transformFlags |= TransformFlags.AssertES6 | TransformFlags.TypeScript;
transformFlags = TransformFlags.AssertES6 | TransformFlags.TypeScript;
break;
case SyntaxKind.DefaultKeyword:
@@ -1854,10 +1829,9 @@ namespace ts {
case SyntaxKind.ForOfStatement:
case SyntaxKind.YieldExpression:
// These nodes are ES6 syntax.
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
break;
case SyntaxKind.AnyKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.StringKeyword:
@@ -1886,36 +1860,42 @@ namespace ts {
case SyntaxKind.ThisType:
case SyntaxKind.StringLiteralType:
// Types and signatures are TypeScript syntax, and exclude all other facts.
subtreeFlags = TransformFlags.None;
excludeFlags = TransformFlags.TypeExcludes;
transformFlags |= TransformFlags.AssertTypeScript;
transformFlags = TransformFlags.AssertTypeScript;
break;
case SyntaxKind.ComputedPropertyName:
// Even though computed property names are ES6, we don't treat them as such.
// This is so that they can flow through PropertyName transforms unaffected.
// Instead, we mark the container as ES6, so that it can properly handle the transform.
transformFlags |= TransformFlags.ContainsComputedPropertyName;
transformFlags = TransformFlags.ContainsComputedPropertyName;
break;
case SyntaxKind.SpreadElementExpression:
// This node is ES6 syntax, but is handled by a containing node.
transformFlags |= TransformFlags.ContainsSpreadElementExpression;
transformFlags = TransformFlags.ContainsSpreadElementExpression;
break;
case SyntaxKind.SuperKeyword:
// This node is ES6 syntax.
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
break;
case SyntaxKind.ThisKeyword:
// Mark this node and its ancestors as containing a lexical `this` keyword.
transformFlags |= TransformFlags.ContainsLexicalThis;
transformFlags = TransformFlags.ContainsLexicalThis;
break;
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
// These nodes are ES6 syntax.
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
break;
case SyntaxKind.Decorator:
// This node is TypeScript syntax, and marks its container as also being TypeScript syntax.
transformFlags = TransformFlags.AssertTypeScript | TransformFlags.ContainsDecorators;
break;
case SyntaxKind.ObjectLiteralExpression:
@@ -1923,19 +1903,12 @@ namespace ts {
if (subtreeFlags & TransformFlags.ContainsComputedPropertyName) {
// If an ObjectLiteralExpression contains a ComputedPropertyName, then it
// is an ES6 node.
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
}
break;
case SyntaxKind.CallExpression:
excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExcludes;
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression
|| isSuperCall(node)) {
// If the this node contains a SpreadElementExpression, or is a super call, then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES6;
}
break;
return computeCallExpression(<CallExpression>node, subtreeFlags);
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.NewExpression:
@@ -1943,163 +1916,66 @@ namespace ts {
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression) {
// If the this node contains a SpreadElementExpression, then it is an ES6
// node.
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
}
break;
case SyntaxKind.Decorator:
// This node is TypeScript syntax, and marks its container as also being TypeScript syntax.
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsDecorators;
break;
case SyntaxKind.ModuleDeclaration:
// An ambient declaration is TypeScript syntax.
if (hasModifier(node, ModifierFlags.Ambient)) {
subtreeFlags = TransformFlags.None;
}
// This node is TypeScript syntax, and excludes markers that should not escape the module scope.
excludeFlags = TransformFlags.ModuleExcludes;
transformFlags |= TransformFlags.AssertTypeScript;
transformFlags = TransformFlags.AssertTypeScript;
break;
case SyntaxKind.ParenthesizedExpression:
// If the node is synthesized, it means the emitter put the parentheses there,
// not the user. If we didn't want them, the emitter would not have put them
// there.
if (!nodeIsSynthesized(node)) {
if ((<ParenthesizedExpression>node).expression.kind === SyntaxKind.AsExpression
|| (<ParenthesizedExpression>node).expression.kind === SyntaxKind.TypeAssertionExpression) {
transformFlags = TransformFlags.AssertTypeScript;
}
}
break;
return computeParenthesizedExpression(<ParenthesizedExpression>node, subtreeFlags);
case SyntaxKind.BinaryExpression:
if (isDestructuringAssignment(node)) {
// Destructuring assignments are ES6 syntax.
transformFlags |= TransformFlags.AssertES6;
}
else if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AsteriskAsteriskToken
|| (<BinaryExpression>node).operatorToken.kind === SyntaxKind.AsteriskAsteriskEqualsToken) {
// Exponentiation is ES7 syntax.
transformFlags |= TransformFlags.AssertES7;
return computeBinaryExpression(<BinaryExpression>node, subtreeFlags);
case SyntaxKind.ExpressionStatement:
// If the expression of an expression statement is a destructuring assignment,
// 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 ((<ExpressionStatement>node).expression.transformFlags & TransformFlags.DestructuringAssignment) {
transformFlags = TransformFlags.AssertES6;
}
break;
case SyntaxKind.Parameter:
// If the parameter has a question token, then it is TypeScript syntax.
if ((<ParameterDeclaration>node).questionToken) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// If a parameter has an accessibility modifier, then it is TypeScript syntax.
if ((<ParameterDeclaration>node).flags & NodeFlags.AccessibilityModifier) {
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsParameterPropertyAssignments;
}
// 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 ((<ParameterDeclaration>node).initializer
|| (<ParameterDeclaration>node).dotDotDotToken
|| isBindingPattern((<ParameterDeclaration>node).name)) {
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsDefaultValueAssignments;
}
break;
return computeParameter(<ParameterDeclaration>node, subtreeFlags);
case SyntaxKind.ArrowFunction:
// An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction.
excludeFlags = TransformFlags.ArrowFunctionExcludes;
transformFlags = TransformFlags.AssertES6;
// If an ArrowFunction contains a lexical this, its container must capture the lexical this.
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
}
// An async arrow function is TypeScript syntax.
if (node.flags & NodeFlags.Async) {
transformFlags |= TransformFlags.AssertTypeScript;
}
break;
return computeArrowFunction(<ArrowFunction>node, subtreeFlags);
case SyntaxKind.FunctionExpression:
// A FunctionExpression excludes markers that should not escape the scope of a FunctionExpression.
excludeFlags = TransformFlags.FunctionExcludes;
// If a FunctionExpression contains an asterisk token, or its subtree has marked the container
// as needing to capture the lexical this, then this node is ES6 syntax.
if ((<FunctionLikeDeclaration>node).asteriskToken
|| subtreeFlags & TransformFlags.ContainsCapturedLexicalThis
|| subtreeFlags & TransformFlags.ContainsDefaultValueAssignments) {
transformFlags |= TransformFlags.AssertES6;
}
// An async function expression is TypeScript syntax.
if (node.flags & NodeFlags.Async) {
transformFlags |= TransformFlags.AssertTypeScript;
}
break;
return computeFunctionExpression(<FunctionExpression>node, subtreeFlags);
case SyntaxKind.FunctionDeclaration:
// A FunctionDeclaration excludes markers that should not escape the scope of a FunctionDeclaration.
excludeFlags = TransformFlags.FunctionExcludes;
// A FunctionDeclaration without a body is an overload and is TypeScript syntax.
if (!(<FunctionDeclaration>node).body) {
transformFlags = TransformFlags.AssertTypeScript;
break;
}
// If a FunctionDeclaration has an asterisk token, is exported, or its
// subtree has marked the container as needing to capture the lexical `this`,
// then this node is ES6 syntax.
if ((<FunctionDeclaration>node).asteriskToken
|| node.flags & NodeFlags.Export
|| subtreeFlags & TransformFlags.ContainsCapturedLexicalThis
|| subtreeFlags & TransformFlags.ContainsDefaultValueAssignments) {
transformFlags |= TransformFlags.AssertES6;
}
// An async function declaration is TypeScript syntax.
if (node.flags & NodeFlags.Async) {
transformFlags |= TransformFlags.AssertTypeScript;
}
break;
return computeFunctionDeclaration(<FunctionDeclaration>node, subtreeFlags);
case SyntaxKind.VariableDeclaration:
// A VariableDeclaration with a binding pattern is ES6 syntax.
if (isBindingPattern((<VariableDeclaration>node).name)) {
transformFlags |= TransformFlags.AssertES6;
}
break;
return computeVariableDeclaration(<VariableDeclaration>node, subtreeFlags);
case SyntaxKind.VariableDeclarationList:
// If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax.
if (node.flags & NodeFlags.BlockScoped) {
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsBlockScopedBinding;
transformFlags = TransformFlags.AssertES6 | TransformFlags.ContainsBlockScopedBinding;
}
break;
case SyntaxKind.VariableStatement:
// If a VariableStatement is exported, then it is either ES6 or TypeScript syntax.
if (node.flags & NodeFlags.Export) {
transformFlags |= TransformFlags.AssertES6 | TransformFlags.AssertTypeScript;
}
break;
return computeVariableStatement(<VariableStatement>node, subtreeFlags);
case SyntaxKind.LabeledStatement:
// A labeled statement containing a block scoped binding *may* need to be transformed from ES6.
if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding
&& isIterationStatement(this, /*lookInLabeledStatements*/ true)) {
transformFlags |= TransformFlags.AssertES6;
}
break;
return computeLabeledStatement(<LabeledStatement>node, subtreeFlags);
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
@@ -2107,36 +1983,26 @@ 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.AssertES6;
}
break;
case SyntaxKind.ClassDeclaration:
return computeClassDeclaration(<ClassDeclaration>node, subtreeFlags);
case SyntaxKind.ClassExpression:
// A ClassDeclarations or ClassExpression is ES6 syntax.
excludeFlags = TransformFlags.ClassExcludes;
transformFlags = TransformFlags.AssertES6;
// A class with a parameter property assignment, property initializer, or decorator is
// TypeScript syntax.
if (subtreeFlags & TransformFlags.ContainsParameterPropertyAssignments
|| subtreeFlags & TransformFlags.ContainsPropertyInitializer
|| subtreeFlags & TransformFlags.ContainsDecorators) {
transformFlags |= TransformFlags.AssertTypeScript;
}
break;
return computeClassExpression(<ClassExpression>node, subtreeFlags);
case SyntaxKind.HeritageClause:
if ((<HeritageClause>node).token === SyntaxKind.ExtendsKeyword) {
// An `extends` HeritageClause is ES6 syntax.
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
}
else {
// An `implements` HeritageClause is TypeScript syntax.
Debug.assert((<HeritageClause>node).token === SyntaxKind.ImplementsKeyword);
transformFlags |= TransformFlags.AssertTypeScript;
transformFlags = TransformFlags.AssertTypeScript;
}
break;
@@ -2144,7 +2010,7 @@ namespace ts {
case SyntaxKind.ExpressionWithTypeArguments:
// An ExpressionWithTypeArguments is ES6 syntax, as it is used in the
// extends clause of a class.
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
// If an ExpressionWithTypeArguments contains type arguments, then it
// is TypeScript syntax.
@@ -2157,7 +2023,7 @@ namespace ts {
case SyntaxKind.Constructor:
// A Constructor is ES6 syntax.
excludeFlags = TransformFlags.ConstructorExcludes;
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
// An overload constructor is TypeScript syntax.
if (!(<ConstructorDeclaration>node).body) {
@@ -2168,7 +2034,7 @@ namespace ts {
case SyntaxKind.PropertyDeclaration:
// A PropertyDeclaration is TypeScript syntax.
transformFlags |= TransformFlags.AssertTypeScript;
transformFlags = TransformFlags.AssertTypeScript;
// If the PropertyDeclaration has an initializer, we need to inform its ancestor
// so that it handle the transformation.
@@ -2181,14 +2047,13 @@ namespace ts {
case SyntaxKind.MethodDeclaration:
// A MethodDeclaration is ES6 syntax.
excludeFlags = TransformFlags.MethodOrAccessorExcludes;
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
// A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
// generic, or has both a computed property name and a decorator.
if ((<MethodDeclaration>node).body === undefined
|| (<MethodDeclaration>node).typeParameters !== undefined
|| node.flags & NodeFlags.Async
|| node.flags & NodeFlags.Abstract
|| hasModifier(node, ModifierFlags.Async | ModifierFlags.Abstract)
|| (subtreeFlags & TransformFlags.ContainsDecorators
&& subtreeFlags & TransformFlags.ContainsComputedPropertyName)) {
transformFlags |= TransformFlags.AssertTypeScript;
@@ -2203,10 +2068,10 @@ namespace ts {
// A GetAccessor or SetAccessor is TypeScript syntax if it is either abstract,
// or has both a computed property name and a decorator.
if (node.flags & NodeFlags.Abstract ||
subtreeFlags & TransformFlags.ContainsDecorators &&
subtreeFlags & TransformFlags.ContainsComputedPropertyName) {
transformFlags |= TransformFlags.AssertTypeScript;
if (hasModifier(node, ModifierFlags.Abstract)
|| (subtreeFlags & TransformFlags.ContainsDecorators
&& subtreeFlags & TransformFlags.ContainsComputedPropertyName)) {
transformFlags = TransformFlags.AssertTypeScript;
}
break;
@@ -2214,7 +2079,7 @@ namespace ts {
case SyntaxKind.ImportEqualsDeclaration:
// An ImportEqualsDeclaration with a namespace reference is TypeScript.
if (!isExternalModuleImportEqualsDeclaration(node)) {
transformFlags |= TransformFlags.AssertTypeScript;
transformFlags = TransformFlags.AssertTypeScript;
}
break;
@@ -2223,20 +2088,258 @@ namespace ts {
// If a PropertyAccessExpression starts with a super keyword, then it is
// ES6 syntax, and requires a lexical `this` binding.
if ((<PropertyAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword) {
transformFlags |= TransformFlags.ContainsLexicalThis;
transformFlags = TransformFlags.ContainsLexicalThis;
}
break;
case SyntaxKind.SourceFile:
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) {
transformFlags |= TransformFlags.AssertES6;
transformFlags = TransformFlags.AssertES6;
}
break;
}
return (node.transformFlags = subtreeFlags | transformFlags)
& ~(node.excludeTransformFlags = excludeFlags | TransformFlags.NodeExcludes);
return updateTransformFlags(node, subtreeFlags, transformFlags, excludeFlags);
}
function computeCallExpression(node: CallExpression, subtreeFlags: TransformFlags) {
let transformFlags = TransformFlags.None;
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression
|| isSuperCall(node)
|| isSuperPropertyCall(node)) {
// If the this node contains a SpreadElementExpression, or is a super call, then it is an ES6
// node.
transformFlags = TransformFlags.AssertES6;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.ArrayLiteralOrCallOrNewExcludes);
}
function computeBinaryExpression(node: BinaryExpression, subtreeFlags: TransformFlags) {
let transformFlags = TransformFlags.None;
if (isDestructuringAssignment(node)) {
// Destructuring assignments are ES6 syntax.
transformFlags = TransformFlags.AssertES6 | TransformFlags.DestructuringAssignment;
}
else if (isExponentiation(node)) {
// Exponentiation is ES7 syntax.
transformFlags = TransformFlags.AssertES7;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.None);
}
function isDestructuringAssignment(node: BinaryExpression) {
return node.operatorToken.kind === SyntaxKind.EqualsToken
&& isObjectOrArrayLiteral(node.left);
}
function isObjectOrArrayLiteral(node: Node) {
switch (node.kind) {
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.ArrayLiteralExpression:
return true;
}
return false;
}
function isExponentiation(operatorToken: Node) {
switch (operatorToken.kind) {
case SyntaxKind.AsteriskAsteriskToken:
case SyntaxKind.AsteriskAsteriskEqualsToken:
return true;
}
return false;
}
function computeParameter(node: ParameterDeclaration, subtreeFlags: TransformFlags) {
let transformFlags = TransformFlags.None;
// If the parameter has a question token, then it is TypeScript syntax.
if (isDefined(node.questionToken)) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// If a parameter has an accessibility modifier, then it is TypeScript syntax.
if (hasModifier(node, ModifierFlags.AccessibilityModifier)) {
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.ContainsParameterPropertyAssignments;
}
// 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 (isDefined(node.initializer) || isDefined(node.dotDotDotToken) || isBindingPattern(node.name)) {
transformFlags |= TransformFlags.AssertES6 | TransformFlags.ContainsDefaultValueAssignments;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.None);
}
function computeParenthesizedExpression(node: ParenthesizedExpression, subtreeFlags: TransformFlags) {
let transformFlags = TransformFlags.None;
// If the node is synthesized, it means the emitter put the parentheses there,
// not the user. If we didn't want them, the emitter would not have put them
// there.
if (node.expression.kind === SyntaxKind.AsExpression
|| node.expression.kind === SyntaxKind.TypeAssertionExpression) {
transformFlags = TransformFlags.AssertTypeScript;
}
// If the expression of a ParenthesizedExpression is a destructuring assignment,
// then the ParenthesizedExpression is a destructuring assignment.
if (node.expression.transformFlags & TransformFlags.DestructuringAssignment) {
transformFlags |= TransformFlags.DestructuringAssignment;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.None);
}
function computeClassDeclaration(node: ClassDeclaration, subtreeFlags: TransformFlags) {
// An ambient declaration is TypeScript syntax.
if (hasModifier(node, ModifierFlags.Ambient)) {
return updateTransformFlags(node, TransformFlags.None, TransformFlags.TypeScript, TransformFlags.ClassExcludes);
}
// A ClassDeclaration is ES6 syntax.
let transformFlags = TransformFlags.AssertES6;
// A class with a parameter property assignment, property initializer, or decorator is
// TypeScript syntax.
// An exported declaration may be TypeScript syntax.
if (subtreeFlags
& (TransformFlags.ContainsParameterPropertyAssignments
| TransformFlags.ContainsPropertyInitializer
| TransformFlags.ContainsDecorators)
|| hasModifier(node, ModifierFlags.Export)) {
transformFlags |= TransformFlags.AssertTypeScript;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.ClassExcludes);
}
function computeClassExpression(node: ClassExpression, subtreeFlags: TransformFlags) {
// A ClassExpression is ES6 syntax.
let transformFlags = TransformFlags.AssertES6;
// A class with a parameter property assignment, property initializer, or decorator is
// TypeScript syntax.
if (subtreeFlags
& (TransformFlags.ContainsParameterPropertyAssignments
| TransformFlags.ContainsPropertyInitializer
| TransformFlags.ContainsDecorators)) {
transformFlags |= TransformFlags.AssertTypeScript;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.ClassExcludes);
}
function computeFunctionDeclaration(node: FunctionDeclaration, subtreeFlags: TransformFlags) {
const modifiers = getModifierFlags(node);
// An ambient declaration is TypeScript syntax.
// A FunctionDeclaration without a body is an overload and is TypeScript syntax.
if (!node.body || modifiers & ModifierFlags.Ambient) {
return updateTransformFlags(node, TransformFlags.None, TransformFlags.AssertTypeScript, TransformFlags.FunctionExcludes);
}
let transformFlags = TransformFlags.None;
// If a FunctionDeclaration is exported, then it is either ES6 or TypeScript syntax.
if (modifiers & ModifierFlags.Export) {
transformFlags |= TransformFlags.AssertTypeScript | TransformFlags.AssertES6;
}
// If a FunctionDeclaration has an asterisk token, is exported, or its
// subtree has marked the container as needing to capture the lexical `this`,
// then this node is ES6 syntax.
if (subtreeFlags & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsDefaultValueAssignments)
|| node.asteriskToken) {
transformFlags |= TransformFlags.AssertES6;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.FunctionExcludes);
}
function computeFunctionExpression(node: FunctionExpression, subtreeFlags: TransformFlags) {
let transformFlags = TransformFlags.None;
// An async function expression is TypeScript syntax.
if (hasModifier(node, ModifierFlags.Async)) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// If a FunctionExpression contains an asterisk token, or its subtree has marked the container
// as needing to capture the lexical this, then this node is ES6 syntax.
if (subtreeFlags & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsDefaultValueAssignments)
|| node.asteriskToken) {
transformFlags |= TransformFlags.AssertES6;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.FunctionExcludes);
}
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 = TransformFlags.AssertES6;
// An async arrow function is TypeScript syntax.
if (hasModifier(node, ModifierFlags.Async)) {
transformFlags |= TransformFlags.AssertTypeScript;
}
// If an ArrowFunction contains a lexical this, its container must capture the lexical this.
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.ArrowFunctionExcludes);
}
function computeVariableDeclaration(node: VariableDeclaration, subtreeFlags: TransformFlags) {
let transformFlags = TransformFlags.None;
// A VariableDeclaration with a binding pattern is ES6 syntax.
if (isBindingPattern((<VariableDeclaration>node).name)) {
transformFlags = TransformFlags.AssertES6;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.None);
}
function computeVariableStatement(node: VariableStatement, subtreeFlags: TransformFlags) {
const modifiers = getModifierFlags(node);
// An ambient declaration is TypeScript syntax.
if (modifiers & ModifierFlags.Ambient) {
return updateTransformFlags(node, TransformFlags.None, TransformFlags.AssertTypeScript, TransformFlags.None);
}
let transformFlags = TransformFlags.None;
// If a VariableStatement is exported, then it is either ES6 or TypeScript syntax.
if (modifiers & ModifierFlags.Export) {
transformFlags = TransformFlags.AssertES6 | TransformFlags.AssertTypeScript;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.None);
}
function computeLabeledStatement(node: LabeledStatement, subtreeFlags: TransformFlags) {
let transformFlags = TransformFlags.None;
// A labeled statement containing a block scoped binding *may* need to be transformed from ES6.
if (subtreeFlags & TransformFlags.ContainsBlockScopedBinding
&& isIterationStatement(this, /*lookInLabeledStatements*/ true)) {
transformFlags = TransformFlags.AssertES6;
}
return updateTransformFlags(node, subtreeFlags, transformFlags, TransformFlags.None);
}
function updateTransformFlags(node: Node, subtreeFlags: TransformFlags, transformFlags: TransformFlags, excludeFlags: TransformFlags) {
node.transformFlags = transformFlags | subtreeFlags | TransformFlags.HasComputedFlags;
node.excludeTransformFlags = excludeFlags | TransformFlags.NodeExcludes;
return node.transformFlags & ~node.excludeTransformFlags;
}
}
+133 -128
View File
@@ -535,7 +535,7 @@ namespace ts {
const initializerOfNonStaticProperty = current.parent &&
current.parent.kind === SyntaxKind.PropertyDeclaration &&
(current.parent.flags & NodeFlags.Static) === 0 &&
(getModifierFlags(current.parent) & ModifierFlags.Static) === 0 &&
(<PropertyDeclaration>current.parent).initializer === current;
if (initializerOfNonStaticProperty) {
@@ -653,7 +653,7 @@ namespace ts {
// local variables of the constructor. This effectively means that entities from outer scopes
// by the same name as a constructor parameter or local variable are inaccessible
// in initializer expressions for instance member variables.
if (isClassLike(location.parent) && !(location.flags & NodeFlags.Static)) {
if (isClassLike(location.parent) && !(getModifierFlags(location) & ModifierFlags.Static)) {
const ctor = findConstructorDeclaration(<ClassLikeDeclaration>location.parent);
if (ctor && ctor.locals) {
if (getSymbol(ctor.locals, name, meaning & SymbolFlags.Value)) {
@@ -667,7 +667,7 @@ namespace ts {
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
if (result = getSymbol(getSymbolOfNode(location).members, name, meaning & SymbolFlags.Type)) {
if (lastLocation && lastLocation.flags & NodeFlags.Static) {
if (lastLocation && getModifierFlags(lastLocation) & ModifierFlags.Static) {
// TypeScript 1.0 spec (April 2014): 3.4.1
// The scope of a type parameter extends over the entire declaration with which the type
// parameter list is associated, with the exception of static member declarations in classes.
@@ -824,7 +824,7 @@ namespace ts {
// No static member is present.
// Check if we're in an instance method and look for a relevant instance member.
if (location === container && !(location.flags & NodeFlags.Static)) {
if (location === container && !(getModifierFlags(location) & ModifierFlags.Static)) {
const instanceType = (<InterfaceType>getDeclaredTypeOfSymbol(classSymbol)).thisType;
if (getPropertyOfType(instanceType, name)) {
error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, typeof nameArg === "string" ? nameArg : declarationNameToString(nameArg));
@@ -1617,7 +1617,7 @@ namespace ts {
const anyImportSyntax = getAnyImportSyntax(declaration);
if (anyImportSyntax &&
!(anyImportSyntax.flags & NodeFlags.Export) && // import clause without export
!(getModifierFlags(anyImportSyntax) & ModifierFlags.Export) && // import clause without export
isDeclarationVisible(<Declaration>anyImportSyntax.parent)) {
getNodeLinks(declaration).isVisible = true;
if (aliasesToMakeVisible) {
@@ -2014,7 +2014,7 @@ namespace ts {
function shouldWriteTypeOfFunctionSymbol() {
const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method && // typeof static method
forEach(symbol.declarations, declaration => declaration.flags & NodeFlags.Static));
forEach(symbol.declarations, declaration => getModifierFlags(declaration) & ModifierFlags.Static));
const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) &&
(symbol.parent || // is exported function symbol
forEach(symbol.declarations, declaration =>
@@ -2306,7 +2306,7 @@ namespace ts {
}
const parent = getDeclarationContainer(node);
// If the node is not exported or it is not ambient module element (except import declaration)
if (!(getCombinedNodeFlags(node) & NodeFlags.Export) &&
if (!(getCombinedModifierFlags(node) & ModifierFlags.Export) &&
!(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && isInAmbientContext(parent))) {
return isGlobalSourceFile(parent);
}
@@ -2319,7 +2319,7 @@ namespace ts {
case SyntaxKind.SetAccessor:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
if (node.flags & (NodeFlags.Private | NodeFlags.Protected)) {
if (getModifierFlags(node) & (ModifierFlags.Private | ModifierFlags.Protected)) {
// Private/protected properties/methods are not visible
return false;
}
@@ -3867,7 +3867,7 @@ namespace ts {
const type = getApparentType(current);
if (type !== unknownType) {
const prop = getPropertyOfType(type, name);
if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) {
if (prop && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected))) {
commonFlags &= prop.flags;
if (!props) {
props = [prop];
@@ -4309,7 +4309,7 @@ namespace ts {
const declaration = getIndexDeclarationOfSymbol(symbol, kind);
if (declaration) {
return createIndexInfo(declaration.type ? getTypeFromTypeNode(declaration.type) : anyType,
(declaration.flags & NodeFlags.Readonly) !== 0, declaration);
(getModifierFlags(declaration) & ModifierFlags.Readonly) !== 0, declaration);
}
return undefined;
}
@@ -4845,8 +4845,8 @@ namespace ts {
const container = getThisContainer(node, /*includeArrowFunctions*/ false);
const parent = container && container.parent;
if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) {
if (!(container.flags & NodeFlags.Static) &&
(container.kind !== SyntaxKind.Constructor || isNodeDescendentOf(node, (<ConstructorDeclaration>container).body))) {
if (!(getModifierFlags(container) & ModifierFlags.Static) &&
(container.kind !== SyntaxKind.Constructor || isNodeDescendantOf(node, (<ConstructorDeclaration>container).body))) {
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent)).thisType;
}
}
@@ -5791,24 +5791,24 @@ namespace ts {
}
}
else if (!(targetProp.flags & SymbolFlags.Prototype)) {
const sourcePropFlags = getDeclarationFlagsFromSymbol(sourceProp);
const targetPropFlags = getDeclarationFlagsFromSymbol(targetProp);
if (sourcePropFlags & NodeFlags.Private || targetPropFlags & NodeFlags.Private) {
const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp);
const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp);
if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) {
if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) {
if (reportErrors) {
if (sourcePropFlags & NodeFlags.Private && targetPropFlags & NodeFlags.Private) {
if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) {
reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp));
}
else {
reportError(Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp),
typeToString(sourcePropFlags & NodeFlags.Private ? source : target),
typeToString(sourcePropFlags & NodeFlags.Private ? target : source));
typeToString(sourcePropFlags & ModifierFlags.Private ? source : target),
typeToString(sourcePropFlags & ModifierFlags.Private ? target : source));
}
}
return Ternary.False;
}
}
else if (targetPropFlags & NodeFlags.Protected) {
else if (targetPropFlags & ModifierFlags.Protected) {
const sourceDeclaredInClass = sourceProp.parent && sourceProp.parent.flags & SymbolFlags.Class;
const sourceClass = sourceDeclaredInClass ? <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(sourceProp)) : undefined;
const targetClass = <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(targetProp));
@@ -5820,7 +5820,7 @@ namespace ts {
return Ternary.False;
}
}
else if (sourcePropFlags & NodeFlags.Protected) {
else if (sourcePropFlags & ModifierFlags.Protected) {
if (reportErrors) {
reportError(Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2,
symbolToString(targetProp), typeToString(source), typeToString(target));
@@ -6060,7 +6060,7 @@ namespace ts {
const symbol = type.symbol;
if (symbol && symbol.flags & SymbolFlags.Class) {
const declaration = getClassLikeDeclarationOfSymbol(symbol);
if (declaration && declaration.flags & NodeFlags.Abstract) {
if (declaration && getModifierFlags(declaration) & ModifierFlags.Abstract) {
return true;
}
}
@@ -6100,8 +6100,8 @@ namespace ts {
if (sourceProp === targetProp) {
return Ternary.True;
}
const sourcePropAccessibility = getDeclarationFlagsFromSymbol(sourceProp) & (NodeFlags.Private | NodeFlags.Protected);
const targetPropAccessibility = getDeclarationFlagsFromSymbol(targetProp) & (NodeFlags.Private | NodeFlags.Protected);
const sourcePropAccessibility = getDeclarationModifierFlagsFromSymbol(sourceProp) & ModifierFlags.NonPublicAccessibilityModifier;
const targetPropAccessibility = getDeclarationModifierFlagsFromSymbol(targetProp) & ModifierFlags.NonPublicAccessibilityModifier;
if (sourcePropAccessibility !== targetPropAccessibility) {
return Ternary.False;
}
@@ -7206,8 +7206,8 @@ namespace ts {
let container = getContainingClass(node);
while (container !== undefined) {
if (container === localOrExportSymbol.valueDeclaration && container.name !== node) {
getNodeLinks(container).flags |= NodeCheckFlags.ClassWithBodyScopedClassBinding;
getNodeLinks(node).flags |= NodeCheckFlags.BodyScopedClassBinding;
getNodeLinks(container).flags |= NodeCheckFlags.DecoratedClassWithSelfReference;
getNodeLinks(node).flags |= NodeCheckFlags.SelfReferenceInDecoratedClass;
break;
}
@@ -7323,7 +7323,7 @@ namespace ts {
break;
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
if (container.flags & NodeFlags.Static) {
if (getModifierFlags(container) & ModifierFlags.Static) {
error(node, Diagnostics.this_cannot_be_referenced_in_a_static_property_initializer);
// do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks
}
@@ -7339,7 +7339,7 @@ namespace ts {
if (isClassLike(container.parent)) {
const symbol = getSymbolOfNode(container.parent);
return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType;
return getModifierFlags(container) & ModifierFlags.Static ? getTypeOfSymbol(symbol) : (<InterfaceType>getDeclaredTypeOfSymbol(symbol)).thisType;
}
if (isInJavaScriptFile(node)) {
@@ -7429,7 +7429,7 @@ namespace ts {
return unknownType;
}
if ((container.flags & NodeFlags.Static) || isCallExpression) {
if ((getModifierFlags(container) & ModifierFlags.Static) || isCallExpression) {
nodeCheckFlag = NodeCheckFlags.SuperStatic;
}
else {
@@ -7494,8 +7494,8 @@ namespace ts {
// This helper creates an object with a "value" property that wraps the `super` property or indexed access for both get and set.
// This is required for destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment
// while a property access can.
if (container.kind === SyntaxKind.MethodDeclaration && container.flags & NodeFlags.Async) {
if (isSuperPropertyOrElementAccess(node.parent) && isAssignmentTarget(node.parent)) {
if (container.kind === SyntaxKind.MethodDeclaration && getModifierFlags(container) & ModifierFlags.Async) {
if (isSuperProperty(node.parent) && isAssignmentTarget(node.parent)) {
getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuperBinding;
}
else {
@@ -7560,7 +7560,7 @@ namespace ts {
// topmost container must be something that is directly nested in the class declaration\object literal expression
if (isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression) {
if (container.flags & NodeFlags.Static) {
if (getModifierFlags(container) & ModifierFlags.Static) {
return container.kind === SyntaxKind.MethodDeclaration ||
container.kind === SyntaxKind.MethodSignature ||
container.kind === SyntaxKind.GetAccessor ||
@@ -8785,8 +8785,12 @@ namespace ts {
return s.valueDeclaration ? s.valueDeclaration.kind : SyntaxKind.PropertyDeclaration;
}
function getDeclarationFlagsFromSymbol(s: Symbol): NodeFlags {
return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : s.flags & SymbolFlags.Prototype ? NodeFlags.Public | NodeFlags.Static : 0;
function getDeclarationModifierFlagsFromSymbol(s: Symbol): ModifierFlags {
return s.valueDeclaration ? getCombinedModifierFlags(s.valueDeclaration) : s.flags & SymbolFlags.Prototype ? ModifierFlags.Public | ModifierFlags.Static : 0;
}
function getDeclarationNodeFlagsFromSymbol(s: Symbol): NodeFlags {
return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : 0;
}
/**
@@ -8798,7 +8802,7 @@ namespace ts {
* @param prop The symbol for the right hand side of the property access.
*/
function checkClassPropertyAccess(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, type: Type, prop: Symbol): boolean {
const flags = getDeclarationFlagsFromSymbol(prop);
const flags = getDeclarationModifierFlagsFromSymbol(prop);
const declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(prop));
if (left.kind === SyntaxKind.SuperKeyword) {
@@ -8821,7 +8825,7 @@ namespace ts {
return false;
}
if (flags & NodeFlags.Abstract) {
if (flags & ModifierFlags.Abstract) {
// A method cannot be accessed in a super property access if the method is abstract.
// This error could mask a private property access error. But, a member
// cannot simultaneously be private and abstract, so this will trigger an
@@ -8833,7 +8837,7 @@ namespace ts {
}
// Public properties are otherwise accessible.
if (!(flags & (NodeFlags.Private | NodeFlags.Protected))) {
if (!(flags & ModifierFlags.NonPublicAccessibilityModifier)) {
return true;
}
@@ -8844,7 +8848,7 @@ namespace ts {
const enclosingClass = enclosingClassDeclaration ? <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClassDeclaration)) : undefined;
// Private property is accessible if declaring and enclosing class are the same
if (flags & NodeFlags.Private) {
if (flags & ModifierFlags.Private) {
if (declaringClass !== enclosingClass) {
error(node, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(declaringClass));
return false;
@@ -8864,7 +8868,7 @@ namespace ts {
return false;
}
// No further restrictions for static properties
if (flags & NodeFlags.Static) {
if (flags & ModifierFlags.Static) {
return true;
}
// An instance property must be accessed through an instance of the enclosing class
@@ -10082,7 +10086,7 @@ namespace ts {
// In the case of a merged class-module or class-interface declaration,
// only the class declaration node will have the Abstract flag set.
const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol);
if (valueDecl && valueDecl.flags & NodeFlags.Abstract) {
if (valueDecl && getModifierFlags(valueDecl) & ModifierFlags.Abstract) {
error(node, Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, declarationNameToString(valueDecl.name));
return resolveErrorCall(node);
}
@@ -10700,8 +10704,8 @@ namespace ts {
// Variables declared with 'const'
// Get accessors without matching set accessors
// Enum members
return symbol.flags & SymbolFlags.Property && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Readonly) !== 0 ||
symbol.flags & SymbolFlags.Variable && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0 ||
return symbol.flags & SymbolFlags.Property && (getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.Readonly) !== 0 ||
symbol.flags & SymbolFlags.Variable && (getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0 ||
symbol.flags & SymbolFlags.Accessor && !(symbol.flags & SymbolFlags.SetAccessor) ||
(symbol.flags & SymbolFlags.EnumMember) !== 0;
}
@@ -11516,7 +11520,7 @@ namespace ts {
checkVariableLikeDeclaration(node);
let func = getContainingFunction(node);
if (node.flags & NodeFlags.AccessibilityModifier) {
if (getModifierFlags(node) & ModifierFlags.AccessibilityModifier) {
func = getContainingFunction(node);
if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) {
error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
@@ -11760,7 +11764,7 @@ namespace ts {
// Abstract methods cannot have an implementation.
// Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node.
if (node.flags & NodeFlags.Abstract && node.body) {
if (getModifierFlags(node) & ModifierFlags.Abstract && node.body) {
error(node, Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, declarationNameToString(node.name));
}
}
@@ -11822,7 +11826,7 @@ namespace ts {
function isInstancePropertyWithInitializer(n: Node): boolean {
return n.kind === SyntaxKind.PropertyDeclaration &&
!(n.flags & NodeFlags.Static) &&
!(getModifierFlags(n) & ModifierFlags.Static) &&
!!(<PropertyDeclaration>n).initializer;
}
@@ -11847,7 +11851,7 @@ namespace ts {
// or the containing class declares instance member variables with initializers.
const superCallShouldBeFirst =
forEach((<ClassDeclaration>node.parent).members, isInstancePropertyWithInitializer) ||
forEach(node.parameters, p => p.flags & (NodeFlags.Public | NodeFlags.Private | NodeFlags.Protected));
forEach(node.parameters, p => getModifierFlags(p) & ModifierFlags.AccessibilityModifier);
// Skip past any prologue directives to find the first statement
// to ensure that it was a super call.
@@ -11905,7 +11909,7 @@ namespace ts {
const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor;
const otherAccessor = <AccessorDeclaration>getDeclarationOfKind(node.symbol, otherKind);
if (otherAccessor) {
if (((node.flags & NodeFlags.AccessibilityModifier) !== (otherAccessor.flags & NodeFlags.AccessibilityModifier))) {
if ((getModifierFlags(node) & ModifierFlags.AccessibilityModifier) !== (getModifierFlags(otherAccessor) & ModifierFlags.AccessibilityModifier)) {
error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility);
}
@@ -12006,11 +12010,11 @@ namespace ts {
}
function isPrivateWithinAmbient(node: Node): boolean {
return (node.flags & NodeFlags.Private) && isInAmbientContext(node);
return (getModifierFlags(node) & ModifierFlags.Private) && isInAmbientContext(node);
}
function getEffectiveDeclarationFlags(n: Node, flagsToCheck: NodeFlags): NodeFlags {
let flags = getCombinedNodeFlags(n);
function getEffectiveDeclarationFlags(n: Node, flagsToCheck: ModifierFlags): ModifierFlags {
let flags = getCombinedModifierFlags(n);
// children of classes (even ambient classes) should not be marked as ambient or export
// because those flags have no useful semantics there.
@@ -12018,11 +12022,11 @@ namespace ts {
n.parent.kind !== SyntaxKind.ClassDeclaration &&
n.parent.kind !== SyntaxKind.ClassExpression &&
isInAmbientContext(n)) {
if (!(flags & NodeFlags.Ambient)) {
if (!(flags & ModifierFlags.Ambient)) {
// It is nested in an ambient context, which means it is automatically exported
flags |= NodeFlags.Export;
flags |= ModifierFlags.Export;
}
flags |= NodeFlags.Ambient;
flags |= ModifierFlags.Ambient;
}
return flags & flagsToCheck;
@@ -12043,7 +12047,7 @@ namespace ts {
return implementationSharesContainerWithFirstOverload ? implementation : overloads[0];
}
function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void {
function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void {
// Error if some overloads have a flag that is not shared by all overloads. To find the
// deviations, we XOR someOverloadFlags with allOverloadFlags
const someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags;
@@ -12052,16 +12056,16 @@ namespace ts {
forEach(overloads, o => {
const deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags;
if (deviation & NodeFlags.Export) {
if (deviation & ModifierFlags.Export) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_exported_or_not_exported);
}
else if (deviation & NodeFlags.Ambient) {
else if (deviation & ModifierFlags.Ambient) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient);
}
else if (deviation & (NodeFlags.Private | NodeFlags.Protected)) {
else if (deviation & (ModifierFlags.Private | ModifierFlags.Protected)) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected);
}
else if (deviation & NodeFlags.Abstract) {
else if (deviation & ModifierFlags.Abstract) {
error(o.name, Diagnostics.Overload_signatures_must_all_be_abstract_or_not_abstract);
}
});
@@ -12080,8 +12084,8 @@ namespace ts {
}
}
const flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.Protected | NodeFlags.Abstract;
let someNodeFlags: NodeFlags = 0;
const flagsToCheck: ModifierFlags = ModifierFlags.Export | ModifierFlags.Ambient | ModifierFlags.Private | ModifierFlags.Protected | ModifierFlags.Abstract;
let someNodeFlags: ModifierFlags = ModifierFlags.None;
let allNodeFlags = flagsToCheck;
let someHaveQuestionToken = false;
let allHaveQuestionToken = true;
@@ -12116,13 +12120,13 @@ namespace ts {
if (node.name && (<FunctionLikeDeclaration>subsequentNode).name && (<Identifier>node.name).text === (<Identifier>(<FunctionLikeDeclaration>subsequentNode).name).text) {
const reportError =
(node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) &&
(node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static);
(getModifierFlags(node) & ModifierFlags.Static) !== (getModifierFlags(subsequentNode) & ModifierFlags.Static);
// we can get here in two cases
// 1. mixed static and instance class members
// 2. something with the same name was defined before the set of overloads that prevents them from merging
// here we'll report error only for the first case since for second we should already report error in binder
if (reportError) {
const diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static;
const diagnostic = getModifierFlags(node) & ModifierFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static;
error(errorNode, diagnostic);
}
return;
@@ -12140,7 +12144,7 @@ namespace ts {
else {
// Report different errors regarding non-consecutive blocks of declarations depending on whether
// the node in question is abstract.
if (node.flags & NodeFlags.Abstract) {
if (getModifierFlags(node) & ModifierFlags.Abstract) {
error(errorNode, Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive);
}
else {
@@ -12219,7 +12223,7 @@ namespace ts {
// Abstract methods can't have an implementation -- in particular, they don't need one.
if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
!(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract)) {
!(getModifierFlags(lastSeenNonAmbientDeclaration) & ModifierFlags.Abstract)) {
reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
}
@@ -12269,10 +12273,10 @@ namespace ts {
let defaultExportedDeclarationSpaces = SymbolFlags.None;
for (const d of symbol.declarations) {
const declarationSpaces = getDeclarationSpaces(d);
const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, NodeFlags.Export | NodeFlags.Default);
const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, ModifierFlags.Export | ModifierFlags.Default);
if (effectiveDeclarationFlags & NodeFlags.Export) {
if (effectiveDeclarationFlags & NodeFlags.Default) {
if (effectiveDeclarationFlags & ModifierFlags.Export) {
if (effectiveDeclarationFlags & ModifierFlags.Default) {
defaultExportedDeclarationSpaces |= declarationSpaces;
}
else {
@@ -13012,7 +13016,7 @@ namespace ts {
if (localDeclarationSymbol &&
localDeclarationSymbol !== symbol &&
localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) {
if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) {
if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) {
const varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList);
const container =
varDeclList.parent.kind === SyntaxKind.VariableStatement && varDeclList.parent.parent
@@ -13788,7 +13792,7 @@ namespace ts {
// Only process instance properties with computed names here.
// Static properties cannot be in conflict with indexers,
// and properties with literal names were already checked.
if (!(member.flags & NodeFlags.Static) && hasDynamicName(member)) {
if (!(getModifierFlags(member) & ModifierFlags.Static) && hasDynamicName(member)) {
const propType = getTypeOfSymbol(member.symbol);
checkIndexConstraintForProperty(member.symbol, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String);
checkIndexConstraintForProperty(member.symbol, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number);
@@ -13899,7 +13903,7 @@ namespace ts {
}
function checkClassDeclaration(node: ClassDeclaration) {
if (!node.name && !(node.flags & NodeFlags.Default)) {
if (!node.name && !(getModifierFlags(node) & ModifierFlags.Default)) {
grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
}
checkClassLikeDeclaration(node);
@@ -14019,7 +14023,7 @@ namespace ts {
}
const derived = getTargetSymbol(getPropertyOfObjectType(type, base.name));
const baseDeclarationFlags = getDeclarationFlagsFromSymbol(base);
const baseDeclarationFlags = getDeclarationModifierFlagsFromSymbol(base);
Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration.");
@@ -14035,7 +14039,7 @@ namespace ts {
// It is an error to inherit an abstract member without implementing it or being declared abstract.
// If there is no declaration for the derived class (as in the case of class expressions),
// then the class cannot be declared abstract.
if (baseDeclarationFlags & NodeFlags.Abstract && (!derivedClassDecl || !(derivedClassDecl.flags & NodeFlags.Abstract))) {
if (baseDeclarationFlags & ModifierFlags.Abstract && (!derivedClassDecl || !(getModifierFlags(derivedClassDecl) & ModifierFlags.Abstract))) {
if (derivedClassDecl.kind === SyntaxKind.ClassExpression) {
error(derivedClassDecl, Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1,
symbolToString(baseProperty), typeToString(baseType));
@@ -14048,13 +14052,13 @@ namespace ts {
}
else {
// derived overrides base.
const derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived);
if ((baseDeclarationFlags & NodeFlags.Private) || (derivedDeclarationFlags & NodeFlags.Private)) {
const derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived);
if ((baseDeclarationFlags & ModifierFlags.Private) || (derivedDeclarationFlags & ModifierFlags.Private)) {
// either base or derived property is private - not override, skip it
continue;
}
if ((baseDeclarationFlags & NodeFlags.Static) !== (derivedDeclarationFlags & NodeFlags.Static)) {
if ((baseDeclarationFlags & ModifierFlags.Static) !== (derivedDeclarationFlags & ModifierFlags.Static)) {
// value of 'static' is not the same for properties - not override, skip it
continue;
}
@@ -14727,7 +14731,7 @@ namespace ts {
// If we hit an import declaration in an illegal context, just bail out to avoid cascading errors.
return;
}
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && getModifierFlags(node) !== 0) {
grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers);
}
if (checkExternalImportOrExportDeclaration(node)) {
@@ -14757,7 +14761,7 @@ namespace ts {
checkGrammarDecorators(node) || checkGrammarModifiers(node);
if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) {
checkImportBinding(node);
if (node.flags & NodeFlags.Export) {
if (getModifierFlags(node) & ModifierFlags.Export) {
markExportAsReferenced(node);
}
if (isInternalModuleImportEqualsDeclaration(node)) {
@@ -14790,7 +14794,7 @@ namespace ts {
return;
}
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && getModifierFlags(node) !== 0) {
grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers);
}
@@ -14849,7 +14853,7 @@ namespace ts {
return;
}
// Grammar checking
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) {
if (!checkGrammarDecorators(node) && !checkGrammarModifiers(node) && getModifierFlags(node) !== 0) {
grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers);
}
if (node.expression.kind === SyntaxKind.Identifier) {
@@ -15177,7 +15181,7 @@ namespace ts {
function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[] {
const symbols: SymbolTable = {};
let memberFlags: NodeFlags = 0;
let memberFlags: ModifierFlags = ModifierFlags.None;
if (isInsideWithStatementBody(location)) {
// We cannot answer semantic questions within a with block, do not proceed any further
@@ -15218,7 +15222,7 @@ namespace ts {
// add the type parameters into the symbol table
// (type parameters of classDeclaration/classExpression and interface are in member property of the symbol.
// Note: that the memberFlags come from previous iteration.
if (!(memberFlags & NodeFlags.Static)) {
if (!(memberFlags & ModifierFlags.Static)) {
copySymbols(getSymbolOfNode(location).members, meaning & SymbolFlags.Type);
}
break;
@@ -15234,7 +15238,7 @@ namespace ts {
copySymbol(argumentsSymbol, meaning);
}
memberFlags = location.flags;
memberFlags = getModifierFlags(location);
location = location.parent;
}
@@ -15592,7 +15596,7 @@ namespace ts {
*/
function getParentTypeOfClassElement(node: ClassElement) {
const classSymbol = getSymbolOfNode(node.parent);
return node.flags & NodeFlags.Static
return getModifierFlags(node) & ModifierFlags.Static
? getTypeOfSymbol(classSymbol)
: getDeclaredTypeOfSymbol(classSymbol);
}
@@ -16169,7 +16173,7 @@ namespace ts {
}
let lastStatic: Node, lastPrivate: Node, lastProtected: Node, lastDeclare: Node, lastAsync: Node, lastReadonly: Node;
let flags = 0;
let flags = ModifierFlags.None;
for (const modifier of node.modifiers) {
if (modifier.kind !== SyntaxKind.ReadonlyKeyword) {
if (node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.MethodSignature) {
@@ -16201,22 +16205,22 @@ namespace ts {
lastPrivate = modifier;
}
if (flags & NodeFlags.AccessibilityModifier) {
if (flags & ModifierFlags.AccessibilityModifier) {
return grammarErrorOnNode(modifier, Diagnostics.Accessibility_modifier_already_seen);
}
else if (flags & NodeFlags.Static) {
else if (flags & ModifierFlags.Static) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "static");
}
else if (flags & NodeFlags.Readonly) {
else if (flags & ModifierFlags.Readonly) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "readonly");
}
else if (flags & NodeFlags.Async) {
else if (flags & ModifierFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "async");
}
else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, text);
}
else if (flags & NodeFlags.Abstract) {
else if (flags & ModifierFlags.Abstract) {
if (modifier.kind === SyntaxKind.PrivateKeyword) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, text, "abstract");
}
@@ -16228,13 +16232,13 @@ namespace ts {
break;
case SyntaxKind.StaticKeyword:
if (flags & NodeFlags.Static) {
if (flags & ModifierFlags.Static) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "static");
}
else if (flags & NodeFlags.Readonly) {
else if (flags & ModifierFlags.Readonly) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "readonly");
}
else if (flags & NodeFlags.Async) {
else if (flags & ModifierFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "async");
}
else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
@@ -16243,35 +16247,35 @@ namespace ts {
else if (node.kind === SyntaxKind.Parameter) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static");
}
else if (flags & NodeFlags.Abstract) {
else if (flags & ModifierFlags.Abstract) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract");
}
flags |= NodeFlags.Static;
flags |= ModifierFlags.Static;
lastStatic = modifier;
break;
case SyntaxKind.ReadonlyKeyword:
if (flags & NodeFlags.Readonly) {
if (flags & ModifierFlags.Readonly) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly");
}
else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature) {
return grammarErrorOnNode(modifier, Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature);
}
flags |= NodeFlags.Readonly;
flags |= ModifierFlags.Readonly;
lastReadonly = modifier;
break;
case SyntaxKind.ExportKeyword:
if (flags & NodeFlags.Export) {
if (flags & ModifierFlags.Export) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "export");
}
else if (flags & NodeFlags.Ambient) {
else if (flags & ModifierFlags.Ambient) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare");
}
else if (flags & NodeFlags.Abstract) {
else if (flags & ModifierFlags.Abstract) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "abstract");
}
else if (flags & NodeFlags.Async) {
else if (flags & ModifierFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "async");
}
else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
@@ -16280,14 +16284,14 @@ namespace ts {
else if (node.kind === SyntaxKind.Parameter) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export");
}
flags |= NodeFlags.Export;
flags |= ModifierFlags.Export;
break;
case SyntaxKind.DeclareKeyword:
if (flags & NodeFlags.Ambient) {
if (flags & ModifierFlags.Ambient) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare");
}
else if (flags & NodeFlags.Async) {
else if (flags & ModifierFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async");
}
else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
@@ -16299,76 +16303,76 @@ namespace ts {
else if (isInAmbientContext(node.parent) && node.parent.kind === SyntaxKind.ModuleBlock) {
return grammarErrorOnNode(modifier, Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context);
}
flags |= NodeFlags.Ambient;
flags |= ModifierFlags.Ambient;
lastDeclare = modifier;
break;
case SyntaxKind.AbstractKeyword:
if (flags & NodeFlags.Abstract) {
if (flags & ModifierFlags.Abstract) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "abstract");
}
if (node.kind !== SyntaxKind.ClassDeclaration) {
if (node.kind !== SyntaxKind.MethodDeclaration) {
return grammarErrorOnNode(modifier, Diagnostics.abstract_modifier_can_only_appear_on_a_class_or_method_declaration);
}
if (!(node.parent.kind === SyntaxKind.ClassDeclaration && node.parent.flags & NodeFlags.Abstract)) {
if (!(node.parent.kind === SyntaxKind.ClassDeclaration && getModifierFlags(node.parent) & ModifierFlags.Abstract)) {
return grammarErrorOnNode(modifier, Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class);
}
if (flags & NodeFlags.Static) {
if (flags & ModifierFlags.Static) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract");
}
if (flags & NodeFlags.Private) {
if (flags & ModifierFlags.Private) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "abstract");
}
}
flags |= NodeFlags.Abstract;
flags |= ModifierFlags.Abstract;
break;
case SyntaxKind.AsyncKeyword:
if (flags & NodeFlags.Async) {
if (flags & ModifierFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "async");
}
else if (flags & NodeFlags.Ambient || isInAmbientContext(node.parent)) {
else if (flags & ModifierFlags.Ambient || isInAmbientContext(node.parent)) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async");
}
else if (node.kind === SyntaxKind.Parameter) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async");
}
flags |= NodeFlags.Async;
flags |= ModifierFlags.Async;
lastAsync = modifier;
break;
}
}
if (node.kind === SyntaxKind.Constructor) {
if (flags & NodeFlags.Static) {
if (flags & ModifierFlags.Static) {
return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static");
}
if (flags & NodeFlags.Abstract) {
if (flags & ModifierFlags.Abstract) {
return grammarErrorOnNode(lastStatic, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "abstract");
}
else if (flags & NodeFlags.Protected) {
else if (flags & ModifierFlags.Protected) {
return grammarErrorOnNode(lastProtected, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "protected");
}
else if (flags & NodeFlags.Private) {
else if (flags & ModifierFlags.Private) {
return grammarErrorOnNode(lastPrivate, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
}
else if (flags & NodeFlags.Async) {
else if (flags & ModifierFlags.Async) {
return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async");
}
else if (flags & NodeFlags.Readonly) {
else if (flags & ModifierFlags.Readonly) {
return grammarErrorOnNode(lastReadonly, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "readonly");
}
return;
}
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & NodeFlags.Ambient) {
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) {
return grammarErrorOnNode(lastDeclare, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare");
}
else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.AccessibilityModifier) && isBindingPattern((<ParameterDeclaration>node).name)) {
else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.AccessibilityModifier) && isBindingPattern((<ParameterDeclaration>node).name)) {
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_a_binding_pattern);
}
if (flags & NodeFlags.Async) {
if (flags & ModifierFlags.Async) {
return checkGrammarAsyncModifier(node, lastAsync);
}
}
@@ -16485,7 +16489,7 @@ namespace ts {
if (parameter.dotDotDotToken) {
return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.An_index_signature_cannot_have_a_rest_parameter);
}
if (parameter.flags & NodeFlags.Modifier) {
if (getModifierFlags(parameter) !== 0) {
return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier);
}
if (parameter.questionToken) {
@@ -16672,11 +16676,13 @@ namespace ts {
}
// Modifiers are never allowed on properties except for 'async' on a method declaration
forEach(prop.modifiers, mod => {
if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) {
grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod));
if (prop.modifiers) {
for (const mod of prop.modifiers) {
if (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration) {
grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod));
}
}
});
}
// ECMA-262 11.1.5 Object Initialiser
// If previous is not undefined then throw a SyntaxError exception if any of the following conditions are true
@@ -16830,7 +16836,7 @@ namespace ts {
if (parameter.dotDotDotToken) {
return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter);
}
else if (parameter.flags & NodeFlags.Modifier) {
else if (getModifierFlags(parameter) !== 0) {
return grammarErrorOnNode(accessor.name, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
}
else if (parameter.questionToken) {
@@ -17136,8 +17142,7 @@ namespace ts {
node.kind === SyntaxKind.ImportEqualsDeclaration ||
node.kind === SyntaxKind.ExportDeclaration ||
node.kind === SyntaxKind.ExportAssignment ||
(node.flags & NodeFlags.Ambient) ||
(node.flags & (NodeFlags.Export | NodeFlags.Default))) {
getModifierFlags(node) & (ModifierFlags.Ambient | ModifierFlags.Export | ModifierFlags.Default)) {
return false;
}
+121 -11
View File
@@ -172,25 +172,118 @@ namespace ts {
}
/**
* Maps an array. If the mapped value is an array, it is spread into the result.
* Flattens an array containing a mix of array or non-array elements.
*
* @param array The array to flatten.
*/
export function flatMap<T, U>(array: T[], f: (x: T, i: number) => U | U[]): U[] {
export function flatten<T>(array: (T | T[])[]): T[] {
let result: T[];
if (array) {
result = [];
for (const v of array) {
if (v) {
if (isArray(v)) {
addRange(result, v);
}
else {
result.push(v);
}
}
}
}
return result;
}
/**
* Maps an array. If the mapped value is an array, it is spread into the result.
*
* @param array The array to map.
* @param mapfn The callback used to map the result into one or more values.
*/
export function flatMap<T, U>(array: T[], mapfn: (x: T, i: number) => U | U[]): U[] {
let result: U[];
if (array) {
result = [];
for (let i = 0; i < array.length; i++) {
const v = array[i];
const ar = f(v, i);
if (ar) {
// We cast to <U> here to leverage the behavior of Array#concat
// which will append a single value here.
result = result.concat(<U[]>ar);
const v = mapfn(array[i], i);
if (v) {
if (isArray(v)) {
addRange(result, v);
}
else {
result.push(v);
}
}
}
}
return result;
}
/**
* Computes the first matching span of elements and returns a tuple of the first span
* and the remaining elements.
*/
export function span<T>(array: T[], f: (x: T, i: number) => boolean): [T[], T[]] {
if (array) {
for (let i = 0; i < array.length; i++) {
if (!f(array[i], i)) {
return [array.slice(0, i), array.slice(i)];
}
}
return [array.slice(0), []];
}
return undefined;
}
/**
* Maps contiguous spans of values with the same key.
*
* @param array The array to map.
* @param keyfn A callback used to select the key for an element.
* @param mapfn A callback used to map a contiguous chunk of values to a single value.
*/
export function spanMap<T, K, U>(array: T[], keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K) => U): U[] {
let result: U[];
if (array) {
result = [];
const len = array.length;
let previousKey: K;
let key: K;
let start = 0;
let pos = 0;
while (start < len) {
while (pos < len) {
const value = array[pos];
key = keyfn(value, pos);
if (pos === 0) {
previousKey = key;
}
else if (key !== previousKey) {
break;
}
pos++;
}
if (start < pos) {
const v = mapfn(array.slice(start, pos), previousKey);
if (v) {
result.push(v);
}
start = pos;
}
previousKey = key;
pos++;
}
}
return result;
}
export function concatenate<T>(array1: T[], array2: T[]): T[] {
if (!array2 || !array2.length) return array1;
if (!array1 || !array1.length) return array2;
@@ -920,8 +1013,9 @@ namespace ts {
this.pos = pos;
this.end = end;
this.flags = NodeFlags.None;
this.transformFlags = undefined;
this.excludeTransformFlags = undefined;
this.modifierFlagsCache = ModifierFlags.None;
this.transformFlags = TransformFlags.None;
this.excludeTransformFlags = TransformFlags.None;
this.parent = undefined;
this.original = undefined;
}
@@ -942,7 +1036,12 @@ namespace ts {
}
export namespace Debug {
const currentAssertionLevel = AssertionLevel.None;
declare var process: any;
declare var require: any;
const currentAssertionLevel = getDevelopmentMode() === "development"
? AssertionLevel.Normal
: AssertionLevel.None;
export function shouldAssert(level: AssertionLevel): boolean {
return currentAssertionLevel >= level;
@@ -962,6 +1061,17 @@ namespace ts {
export function fail(message?: string): void {
Debug.assert(/*expression*/ false, message);
}
function getDevelopmentMode() {
return typeof require !== "undefined"
&& typeof process !== "undefined"
&& !process.browser
&& process.nextTick
&& process.env
&& process.env.NODE_ENV
? String(process.env.NODE_ENV).toLowerCase()
: undefined;
}
}
export function copyListRemovingItem<T>(item: T, list: T[]) {
+29 -28
View File
@@ -623,12 +623,13 @@ namespace ts {
function emitModuleElementDeclarationFlags(node: Node) {
// If the node is parented in the current source file we need to emit export declare or just export
if (node.parent.kind === SyntaxKind.SourceFile) {
const modifiers = getModifierFlags(node);
// If the node is exported
if (node.flags & NodeFlags.Export) {
if (modifiers & ModifierFlags.Export) {
write("export ");
}
if (node.flags & NodeFlags.Default) {
if (modifiers & ModifierFlags.Default) {
write("default ");
}
else if (node.kind !== SyntaxKind.InterfaceDeclaration && !noDeclare) {
@@ -637,21 +638,21 @@ namespace ts {
}
}
function emitClassMemberDeclarationFlags(flags: NodeFlags) {
if (flags & NodeFlags.Private) {
function emitClassMemberDeclarationFlags(flags: ModifierFlags) {
if (flags & ModifierFlags.Private) {
write("private ");
}
else if (flags & NodeFlags.Protected) {
else if (flags & ModifierFlags.Protected) {
write("protected ");
}
if (flags & NodeFlags.Static) {
if (flags & ModifierFlags.Static) {
write("static ");
}
if (flags & NodeFlags.Readonly) {
if (flags & ModifierFlags.Readonly) {
write("readonly ");
}
if (flags & NodeFlags.Abstract) {
if (flags & ModifierFlags.Abstract) {
write("abstract ");
}
}
@@ -660,7 +661,7 @@ namespace ts {
// note usage of writer. methods instead of aliases created, just to make sure we are using
// correct writer especially to handle asynchronous alias writing
emitJsDocComments(node);
if (node.flags & NodeFlags.Export) {
if (hasModifier(node, ModifierFlags.Export)) {
write("export ");
}
write("import ");
@@ -698,12 +699,12 @@ namespace ts {
}
function writeImportDeclaration(node: ImportDeclaration) {
if (!node.importClause && !(node.flags & NodeFlags.Export)) {
if (!node.importClause && !hasModifier(node, ModifierFlags.Export)) {
// do not write non-exported import declarations that don't have import clauses
return;
}
emitJsDocComments(node);
if (node.flags & NodeFlags.Export) {
if (hasModifier(node, ModifierFlags.Export)) {
write("export ");
}
write("import ");
@@ -893,7 +894,7 @@ namespace ts {
}
function isPrivateMethodTypeParameter(node: TypeParameterDeclaration) {
return node.parent.kind === SyntaxKind.MethodDeclaration && (node.parent.flags & NodeFlags.Private);
return node.parent.kind === SyntaxKind.MethodDeclaration && hasModifier(node.parent, ModifierFlags.Private);
}
function emitTypeParameters(typeParameters: TypeParameterDeclaration[]) {
@@ -943,7 +944,7 @@ namespace ts {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
if (node.parent.flags & NodeFlags.Static) {
if (hasModifier(node.parent, ModifierFlags.Static)) {
diagnosticMessage = Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1;
}
else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) {
@@ -1018,7 +1019,7 @@ namespace ts {
function emitParameterProperties(constructorDeclaration: ConstructorDeclaration) {
if (constructorDeclaration) {
forEach(constructorDeclaration.parameters, param => {
if (param.flags & NodeFlags.AccessibilityModifier) {
if (hasModifier(param, ModifierFlags.AccessibilityModifier)) {
emitPropertyDeclaration(param);
}
});
@@ -1027,7 +1028,7 @@ namespace ts {
emitJsDocComments(node);
emitModuleElementDeclarationFlags(node);
if (node.flags & NodeFlags.Abstract) {
if (hasModifier(node, ModifierFlags.Abstract)) {
write("abstract ");
}
@@ -1077,7 +1078,7 @@ namespace ts {
}
emitJsDocComments(node);
emitClassMemberDeclarationFlags(node.flags);
emitClassMemberDeclarationFlags(getModifierFlags(node));
emitVariableDeclaration(<VariableDeclaration>node);
write(";");
writeLine();
@@ -1102,7 +1103,7 @@ namespace ts {
if ((node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) && node.parent.kind === SyntaxKind.TypeLiteral) {
emitTypeOfVariableDeclarationFromTypeLiteral(node);
}
else if (!(node.flags & NodeFlags.Private)) {
else if (!hasModifier(node, ModifierFlags.Private)) {
writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError);
}
}
@@ -1119,7 +1120,7 @@ namespace ts {
// This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit
else if (node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertySignature) {
// TODO(jfreeman): Deal with computed properties in error reporting.
if (node.flags & NodeFlags.Static) {
if (hasModifier(node, ModifierFlags.Static)) {
return symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
@@ -1230,9 +1231,9 @@ namespace ts {
if (node === accessors.firstAccessor) {
emitJsDocComments(accessors.getAccessor);
emitJsDocComments(accessors.setAccessor);
emitClassMemberDeclarationFlags(node.flags | (accessors.setAccessor ? 0 : NodeFlags.Readonly));
emitClassMemberDeclarationFlags(getModifierFlags(node) | (accessors.setAccessor ? 0 : ModifierFlags.Readonly));
writeTextOfNode(currentText, node.name);
if (!(node.flags & NodeFlags.Private)) {
if (!hasModifier(node, ModifierFlags.Private)) {
accessorWithTypeAnnotation = node;
let type = getTypeAnnotationFromAccessor(node);
if (!type) {
@@ -1263,7 +1264,7 @@ namespace ts {
let diagnosticMessage: DiagnosticMessage;
if (accessorWithTypeAnnotation.kind === SyntaxKind.SetAccessor) {
// Setters have to have type named and cannot infer it so, the type should always be named
if (accessorWithTypeAnnotation.parent.flags & NodeFlags.Static) {
if (hasModifier(accessorWithTypeAnnotation.parent, ModifierFlags.Static)) {
diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_name_1_from_private_module_2 :
Diagnostics.Parameter_0_of_public_static_property_setter_from_exported_class_has_or_is_using_private_name_1;
@@ -1281,7 +1282,7 @@ namespace ts {
};
}
else {
if (accessorWithTypeAnnotation.flags & NodeFlags.Static) {
if (hasModifier(accessorWithTypeAnnotation, ModifierFlags.Static)) {
diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Return_type_of_public_static_property_getter_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
@@ -1317,7 +1318,7 @@ namespace ts {
emitModuleElementDeclarationFlags(node);
}
else if (node.kind === SyntaxKind.MethodDeclaration) {
emitClassMemberDeclarationFlags(node.flags);
emitClassMemberDeclarationFlags(getModifierFlags(node));
}
if (node.kind === SyntaxKind.FunctionDeclaration) {
write("function ");
@@ -1347,7 +1348,7 @@ namespace ts {
if (node.kind === SyntaxKind.IndexSignature) {
// Index signature can have readonly modifier
emitClassMemberDeclarationFlags(node.flags);
emitClassMemberDeclarationFlags(getModifierFlags(node));
write("[");
}
else {
@@ -1378,7 +1379,7 @@ namespace ts {
emitType(node.type);
}
}
else if (node.kind !== SyntaxKind.Constructor && !(node.flags & NodeFlags.Private)) {
else if (node.kind !== SyntaxKind.Constructor && !hasModifier(node, ModifierFlags.Private)) {
writeReturnTypeAtSignature(node, getReturnTypeVisibilityError);
}
@@ -1415,7 +1416,7 @@ namespace ts {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
if (node.flags & NodeFlags.Static) {
if (hasModifier(node, ModifierFlags.Static)) {
diagnosticMessage = symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named :
@@ -1481,7 +1482,7 @@ namespace ts {
node.parent.parent.kind === SyntaxKind.TypeLiteral) {
emitTypeOfVariableDeclarationFromTypeLiteral(node);
}
else if (!(node.parent.flags & NodeFlags.Private)) {
else if (!hasModifier(node.parent, ModifierFlags.Private)) {
writeTypeOfDeclaration(node, node.type, getParameterDeclarationTypeVisibilityError);
}
@@ -1517,7 +1518,7 @@ namespace ts {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
if (node.parent.flags & NodeFlags.Static) {
if (hasModifier(node.parent, ModifierFlags.Static)) {
return symbolAccesibilityResult.errorModuleName ?
symbolAccesibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ?
Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named :
+43 -43
View File
@@ -346,7 +346,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
function isUniqueLocalName(name: string, container: Node): boolean {
for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) {
if (node.locals && hasProperty(node.locals, name)) {
// We conservatively include alias symbols to cover cases where they're emitted as locals
if (node.locals[name].flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) {
@@ -1529,7 +1529,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return;
}
}
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.BodyScopedClassBinding) {
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.SelfReferenceInDecoratedClass) {
// 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.
@@ -2339,7 +2339,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
superCall = true;
}
else {
superCall = isSuperPropertyOrElementAccess(expression);
superCall = isSuperProperty(expression);
isAsyncMethodWithSuper = superCall && isInAsyncMethodWithSuperInES6(node);
emit(expression);
}
@@ -2579,7 +2579,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
let current = getRootDeclaration(node).parent;
while (current) {
if (current.kind === SyntaxKind.SourceFile) {
return !isExported || ((getCombinedNodeFlags(node) & NodeFlags.Export) !== 0);
return !isExported || ((getCombinedModifierFlags(node) & ModifierFlags.Export) !== 0);
}
else if (isDeclaration(current)) {
return false;
@@ -3627,7 +3627,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function emitModuleMemberName(node: Declaration) {
emitStart(node.name);
if (getCombinedNodeFlags(node) & NodeFlags.Export) {
if (getCombinedModifierFlags(node) & ModifierFlags.Export) {
const container = getContainingModule(node);
if (container) {
write(getGeneratedNameForNode(container));
@@ -3651,7 +3651,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function emitEs6ExportDefaultCompat(node: Node) {
if (node.parent.kind === SyntaxKind.SourceFile) {
Debug.assert(!!(node.flags & NodeFlags.Default) || node.kind === SyntaxKind.ExportAssignment);
Debug.assert(hasModifier(node, ModifierFlags.Default) || node.kind === SyntaxKind.ExportAssignment);
// only allow export default at a source file level
if (modulekind === ModuleKind.CommonJS || modulekind === ModuleKind.AMD || modulekind === ModuleKind.UMD) {
if (!isEs6Module) {
@@ -3670,7 +3670,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
function emitExportMemberAssignment(node: FunctionLikeDeclaration | ClassDeclaration) {
if (node.flags & NodeFlags.Export) {
if (hasModifier(node, ModifierFlags.Export)) {
writeLine();
emitStart(node);
@@ -3679,7 +3679,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
// emit export default <smth> as
// export("default", <smth>)
write(`${exportFunctionForFile}("`);
if (node.flags & NodeFlags.Default) {
if (hasModifier(node, ModifierFlags.Default)) {
write("default");
}
else {
@@ -3690,7 +3690,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
write(")");
}
else {
if (node.flags & NodeFlags.Default) {
if (hasModifier(node, ModifierFlags.Default)) {
emitEs6ExportDefaultCompat(node);
if (languageVersion === ScriptTarget.ES3) {
write("exports[\"default\"]");
@@ -3821,7 +3821,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
// because actual variable declarations are hoisted
let canDefineTempVariablesInPlace = false;
if (root.kind === SyntaxKind.VariableDeclaration) {
const isExported = getCombinedNodeFlags(root) & NodeFlags.Export;
const isExported = getCombinedModifierFlags(root) & ModifierFlags.Export;
const isSourceLevelForSystemModuleKind = shouldHoistDeclarationInSystemJsModule(root);
canDefineTempVariablesInPlace = !isExported && !isSourceLevelForSystemModuleKind;
}
@@ -4163,7 +4163,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
function isES6ExportedDeclaration(node: Node) {
return !!(node.flags & NodeFlags.Export) &&
return hasModifier(node, ModifierFlags.Export) &&
modulekind === ModuleKind.ES6 &&
node.parent.kind === SyntaxKind.SourceFile;
}
@@ -4171,7 +4171,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function emitVariableStatement(node: VariableStatement) {
let startIsEmitted = false;
if (node.flags & NodeFlags.Export) {
if (hasModifier(node, ModifierFlags.Export)) {
if (isES6ExportedDeclaration(node)) {
// Exported ES6 module member
write("export ");
@@ -4200,7 +4200,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function shouldEmitLeadingAndTrailingCommentsForVariableStatement(node: VariableStatement) {
// If we're not exporting the variables, there's nothing special here.
// Always emit comments for these nodes.
if (!(node.flags & NodeFlags.Export)) {
if (!hasModifier(node, ModifierFlags.Export)) {
return true;
}
@@ -4408,7 +4408,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
if (!shouldEmitAsArrowFunction(node)) {
if (isES6ExportedDeclaration(node)) {
write("export ");
if (node.flags & NodeFlags.Default) {
if (hasModifier(node, ModifierFlags.Default)) {
write("default ");
}
}
@@ -4661,7 +4661,7 @@ const _super = (function (geti, seti) {
}
function emitExpressionFunctionBody(node: FunctionLikeDeclaration, body: Expression) {
if (languageVersion < ScriptTarget.ES6 || node.flags & NodeFlags.Async) {
if (languageVersion < ScriptTarget.ES6 || hasModifier(node, ModifierFlags.Async)) {
emitDownLevelExpressionFunctionBody(node, body);
return;
}
@@ -4777,7 +4777,7 @@ const _super = (function (geti, seti) {
function emitParameterPropertyAssignments(node: ConstructorDeclaration) {
forEach(node.parameters, param => {
if (param.flags & NodeFlags.AccessibilityModifier) {
if (hasModifier(param, ModifierFlags.AccessibilityModifier)) {
writeLine();
emitStart(param);
emitStart(param.name);
@@ -4813,7 +4813,7 @@ const _super = (function (geti, seti) {
function getInitializedProperties(node: ClassLikeDeclaration, isStatic: boolean) {
const properties: PropertyDeclaration[] = [];
for (const member of node.members) {
if (member.kind === SyntaxKind.PropertyDeclaration && isStatic === ((member.flags & NodeFlags.Static) !== 0) && (<PropertyDeclaration>member).initializer) {
if (member.kind === SyntaxKind.PropertyDeclaration && isStatic === hasModifier(member, ModifierFlags.Static) && (<PropertyDeclaration>member).initializer) {
properties.push(<PropertyDeclaration>member);
}
}
@@ -4836,7 +4836,7 @@ const _super = (function (geti, seti) {
emit(receiver);
}
else {
if (property.flags & NodeFlags.Static) {
if (hasModifier(property, ModifierFlags.Static)) {
emitDeclarationName(node);
}
else {
@@ -4938,7 +4938,7 @@ const _super = (function (geti, seti) {
writeLine();
emitLeadingComments(member);
emitStart(member);
if (member.flags & NodeFlags.Static) {
if (hasModifier(member, ModifierFlags.Static)) {
write("static ");
}
@@ -4996,7 +4996,7 @@ const _super = (function (geti, seti) {
emitCommentsOnNotEmittedNode(member);
}
// Check if there is any non-static property assignment
if (member.kind === SyntaxKind.PropertyDeclaration && (<PropertyDeclaration>member).initializer && (member.flags & NodeFlags.Static) === 0) {
if (member.kind === SyntaxKind.PropertyDeclaration && (<PropertyDeclaration>member).initializer && !hasModifier(member, ModifierFlags.Static)) {
hasInstancePropertyWithInitializer = true;
}
});
@@ -5203,14 +5203,14 @@ const _super = (function (geti, seti) {
// [Example 4]
//
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithBodyScopedClassBinding) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.DecoratedClassWithSelfReference) {
decoratedClassAlias = unescapeIdentifier(makeUniqueName(node.name ? node.name.text : "default"));
decoratedClassAliases[getNodeId(node)] = decoratedClassAlias;
write(`let ${decoratedClassAlias};`);
writeLine();
}
if (isES6ExportedDeclaration(node) && !(node.flags & NodeFlags.Default)) {
if (isES6ExportedDeclaration(node) && !hasModifier(node, ModifierFlags.Default)) {
write("export ");
}
@@ -5224,7 +5224,7 @@ const _super = (function (geti, seti) {
}
else if (isES6ExportedDeclaration(node)) {
write("export ");
if (node.flags & NodeFlags.Default) {
if (hasModifier(node, ModifierFlags.Default)) {
write("default ");
}
}
@@ -5258,7 +5258,7 @@ const _super = (function (geti, seti) {
// emit name if
// - node has a name
// - this is default export with static initializers
if (node.name || (node.flags & NodeFlags.Default && (staticProperties.length > 0 || modulekind !== ModuleKind.ES6) && !thisNodeIsDecorated)) {
if (node.name || (hasModifier(node, ModifierFlags.Default) && (staticProperties.length > 0 || modulekind !== ModuleKind.ES6) && !thisNodeIsDecorated)) {
write(" ");
emitDeclarationName(node);
}
@@ -5307,7 +5307,7 @@ const _super = (function (geti, seti) {
emitDecoratorsOfClass(node, decoratedClassAlias);
}
if (!(node.flags & NodeFlags.Export)) {
if (!hasModifier(node, ModifierFlags.Export)) {
return;
}
if (modulekind !== ModuleKind.ES6) {
@@ -5316,7 +5316,7 @@ const _super = (function (geti, seti) {
else {
// If this is an exported class, but not on the top level (i.e. on an internal
// module), export it
if (node.flags & NodeFlags.Default) {
if (hasModifier(node, ModifierFlags.Default)) {
// if this is a top level default export of decorated class, write the export after the declaration.
if (thisNodeIsDecorated) {
writeLine();
@@ -5439,14 +5439,14 @@ const _super = (function (geti, seti) {
function emitClassMemberPrefix(node: ClassLikeDeclaration, member: Node) {
emitDeclarationName(node);
if (!(member.flags & NodeFlags.Static)) {
if (!hasModifier(member, ModifierFlags.Static)) {
write(".prototype");
}
}
function emitDecoratorsOfClass(node: ClassLikeDeclaration, decoratedClassAlias: string) {
emitDecoratorsOfMembers(node, /*staticFlag*/ 0);
emitDecoratorsOfMembers(node, NodeFlags.Static);
emitDecoratorsOfMembers(node, ModifierFlags.Static);
emitDecoratorsOfConstructor(node, decoratedClassAlias);
}
@@ -5500,10 +5500,10 @@ const _super = (function (geti, seti) {
writeLine();
}
function emitDecoratorsOfMembers(node: ClassLikeDeclaration, staticFlag: NodeFlags) {
function emitDecoratorsOfMembers(node: ClassLikeDeclaration, staticFlag: ModifierFlags) {
for (const member of node.members) {
// only emit members in the correct group
if ((member.flags & NodeFlags.Static) !== staticFlag) {
if ((getModifierFlags(member) & ModifierFlags.Static) !== staticFlag) {
continue;
}
@@ -5964,7 +5964,7 @@ const _super = (function (geti, seti) {
// do not emit var if variable was already hoisted
const isES6ExportedEnum = isES6ExportedDeclaration(node);
if (!(node.flags & NodeFlags.Export) || (isES6ExportedEnum && isFirstDeclarationOfKind(node, node.symbol && node.symbol.declarations, SyntaxKind.EnumDeclaration))) {
if (!hasModifier(node, ModifierFlags.Export) || (isES6ExportedEnum && isFirstDeclarationOfKind(node, node.symbol && node.symbol.declarations, SyntaxKind.EnumDeclaration))) {
emitStart(node);
if (isES6ExportedEnum) {
write("export ");
@@ -5993,7 +5993,7 @@ const _super = (function (geti, seti) {
emitModuleMemberName(node);
write(" = {}));");
emitEnd(node);
if (!isES6ExportedDeclaration(node) && node.flags & NodeFlags.Export && !shouldHoistDeclarationInSystemJsModule(node)) {
if (!isES6ExportedDeclaration(node) && hasModifier(node, ModifierFlags.Export) && !shouldHoistDeclarationInSystemJsModule(node)) {
// do not emit var if variable was already hoisted
writeLine();
emitStart(node);
@@ -6005,7 +6005,7 @@ const _super = (function (geti, seti) {
write(";");
}
if (modulekind !== ModuleKind.ES6 && node.parent === currentSourceFile) {
if (modulekind === ModuleKind.System && (node.flags & NodeFlags.Export)) {
if (modulekind === ModuleKind.System && hasModifier(node, ModifierFlags.Export)) {
// write the call to exporter for enum
writeLine();
write(`${exportFunctionForFile}("`);
@@ -6127,7 +6127,7 @@ const _super = (function (geti, seti) {
}
write(")(");
// write moduleDecl = containingModule.m only if it is not exported es6 module member
if ((node.flags & NodeFlags.Export) && !isES6ExportedDeclaration(node)) {
if (hasModifier(node, ModifierFlags.Export) && !isES6ExportedDeclaration(node)) {
emit(node.name);
write(" = ");
}
@@ -6137,7 +6137,7 @@ const _super = (function (geti, seti) {
write(" = {}));");
emitEnd(node);
if (!isES6ExportedDeclaration(node) && node.name.kind === SyntaxKind.Identifier && node.parent === currentSourceFile) {
if (modulekind === ModuleKind.System && (node.flags & NodeFlags.Export)) {
if (modulekind === ModuleKind.System && hasModifier(node, ModifierFlags.Export)) {
writeLine();
write(`${exportFunctionForFile}("`);
emitDeclarationName(node);
@@ -6249,7 +6249,7 @@ const _super = (function (geti, seti) {
function emitExternalImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration) {
if (contains(externalImports, node)) {
const isExportedImport = node.kind === SyntaxKind.ImportEqualsDeclaration && (node.flags & NodeFlags.Export) !== 0;
const isExportedImport = node.kind === SyntaxKind.ImportEqualsDeclaration && hasModifier(node, ModifierFlags.Export);
const namespaceDeclaration = getNamespaceDeclarationNode(node);
const varOrConst = (languageVersion <= ScriptTarget.ES5) ? "var " : "const ";
@@ -6339,7 +6339,7 @@ const _super = (function (geti, seti) {
write("export ");
write("var ");
}
else if (!(node.flags & NodeFlags.Export)) {
else if (!hasModifier(node, ModifierFlags.Export)) {
write("var ");
}
}
@@ -6732,7 +6732,7 @@ const _super = (function (geti, seti) {
function writeExportedName(node: Identifier | Declaration): void {
// do not record default exports
// they are local to module and never overwritten (explicitly skipped) by star export
if (node.kind !== SyntaxKind.Identifier && node.flags & NodeFlags.Default) {
if (node.kind !== SyntaxKind.Identifier && hasModifier(node, ModifierFlags.Default)) {
return;
}
@@ -6804,8 +6804,8 @@ const _super = (function (geti, seti) {
emit(local);
}
const flags = getCombinedNodeFlags(local.kind === SyntaxKind.Identifier ? local.parent : local);
if (flags & NodeFlags.Export) {
const flags = getCombinedModifierFlags(local.kind === SyntaxKind.Identifier ? local.parent : local);
if (flags & ModifierFlags.Export) {
if (!exportedDeclarations) {
exportedDeclarations = [];
}
@@ -6820,7 +6820,7 @@ const _super = (function (geti, seti) {
writeLine();
emit(f);
if (f.flags & NodeFlags.Export) {
if (hasModifier(f, ModifierFlags.Export)) {
if (!exportedDeclarations) {
exportedDeclarations = [];
}
@@ -6832,7 +6832,7 @@ const _super = (function (geti, seti) {
return exportedDeclarations;
function visit(node: Node): void {
if (node.flags & NodeFlags.Ambient) {
if (hasModifier(node, ModifierFlags.Ambient)) {
return;
}
@@ -7596,7 +7596,7 @@ const _super = (function (geti, seti) {
function emitNodeConsideringCommentsOption(node: Node, emitNodeConsideringSourcemap: (node: Node) => void): void {
if (node) {
if (node.flags & NodeFlags.Ambient) {
if (hasModifier(node, ModifierFlags.Ambient)) {
return emitCommentsOnNotEmittedNode(node);
}
+144 -104
View File
@@ -46,55 +46,9 @@ namespace ts {
array.hasTrailingComma = true;
}
array.arrayKind = ArrayKind.NodeArray;
return array;
}
export function createModifiersArray(elements?: Modifier[], location?: TextRange): ModifiersArray {
let flags: NodeFlags;
if (elements) {
if (isModifiersArray(elements)) {
return elements;
}
flags = 0;
for (const modifier of elements) {
flags |= modifierToFlag(modifier.kind);
}
}
else {
elements = [];
flags = 0;
}
const array = <ModifiersArray>elements;
if (location) {
array.pos = location.pos;
array.end = location.end;
}
else {
array.pos = -1;
array.end = -1;
}
array.arrayKind = ArrayKind.ModifiersArray;
array.flags = flags;
return array;
}
export function setModifiers<T extends Node>(node: T, modifiers: Modifier[]) {
if (modifiers) {
const array = createModifiersArray(modifiers);
node.modifiers = array;
node.flags |= array.flags;
}
else {
node.modifiers = undefined;
}
return node;
}
export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node {
const node = createNode(kind, /*location*/ undefined);
node.startsOnNewLine = startsOnNewLine;
@@ -105,26 +59,16 @@ namespace ts {
return createNodeArray(elements, /*location*/ undefined);
}
export function createSynthesizedModifiersArray(elements?: Modifier[]): ModifiersArray {
return createModifiersArray(elements, /*location*/ undefined);
}
/**
* Creates a shallow, memberwise clone of a node. The "kind", "pos", "end", "flags", and "parent"
* properties are excluded by default, and can be provided via the "location", "flags", and
* "parent" parameters.
*
* @param node The node to clone.
* @param location An optional TextRange to use to supply the new position.
* @param flags The NodeFlags to use for the cloned node.
* @param parent The parent for the new node.
* @param original An optional pointer to the original source tree node.
* Creates a shallow, memberwise clone of a node with no source map location.
*/
export function cloneNode<T extends Node>(node: T, location?: TextRange, flags?: NodeFlags, parent?: Node, original?: Node): T {
export function getSynthesizedClone<T extends Node>(node: T): T {
// We don't use "clone" from core.ts here, as we need to preserve the prototype chain of
// the original node. We also need to exclude specific properties and only include own-
// properties (to skip members already defined on the shared prototype).
const clone = <T>createNode(node.kind, location);
const clone = <T>createSynthesizedNode(node.kind);
clone.flags = node.flags;
clone.original = node;
for (const key in node) {
if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) {
@@ -134,32 +78,28 @@ namespace ts {
(<any>clone)[key] = (<any>node)[key];
}
if (flags !== undefined) {
clone.flags = flags;
}
if (parent !== undefined) {
clone.parent = parent;
}
if (original !== undefined) {
clone.original = original;
}
return clone;
}
/**
* Creates a shallow, memberwise clone of a node for mutation.
*/
export function getMutableNode<T extends Node>(node: T): T {
return cloneNode<T>(node, node, node.flags, node.parent, node);
export function getMutableClone<T extends Node>(node: T): T {
const clone = getSynthesizedClone(node);
clone.pos = node.pos;
clone.end = node.end;
clone.parent = node.parent;
return clone;
}
export function createNodeArrayNode<T extends Node>(elements: T[]): NodeArrayNode<T> {
const node = <NodeArrayNode<T>>createSynthesizedNode(SyntaxKind.NodeArrayNode);
node.nodes = createNodeArray(elements);
return node;
/**
* Creates a shallow, memberwise clone of a node at the specified source map location.
*/
export function getRelocatedClone<T extends Node>(node: T, location: TextRange): T {
const clone = getSynthesizedClone(node);
clone.pos = location.pos;
clone.end = location.end;
return clone;
}
// Literals
@@ -213,7 +153,7 @@ namespace ts {
return name;
}
export function createGeneratedNameForNode(node: Node, location?: TextRange): Identifier {
export function getGeneratedNameForNode(node: Node, location?: TextRange): Identifier {
const name = <Identifier>createNode(SyntaxKind.Identifier, location);
name.autoGenerateKind = GeneratedIdentifierKind.Node;
name.original = node;
@@ -251,7 +191,7 @@ namespace ts {
export function createMethod(modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
const node = <MethodDeclaration>createNode(SyntaxKind.MethodDeclaration, location);
node.decorators = undefined;
setModifiers(node, modifiers);
node.modifiers = modifiers ? createNodeArray(modifiers) : undefined;
node.name = typeof name === "string" ? createIdentifier(name) : name;
node.typeParameters = undefined;
node.parameters = createNodeArray(parameters);
@@ -273,7 +213,7 @@ namespace ts {
export function createGetAccessor(modifiers: Modifier[], name: string | PropertyName, body: Block, location?: TextRange) {
const node = <GetAccessorDeclaration>createNode(SyntaxKind.GetAccessor, location);
node.decorators = undefined;
setModifiers(node, modifiers);
node.modifiers = modifiers ? createNodeArray(modifiers) : undefined;
node.name = typeof name === "string" ? createIdentifier(name) : name;
node.typeParameters = undefined;
node.parameters = createNodeArray<ParameterDeclaration>();
@@ -284,7 +224,7 @@ namespace ts {
export function createSetAccessor(modifiers: Modifier[], name: string | PropertyName, parameter: ParameterDeclaration, body: Block, location?: TextRange) {
const node = <SetAccessorDeclaration>createNode(SyntaxKind.SetAccessor, location);
node.decorators = undefined;
setModifiers(node, modifiers);
node.modifiers = modifiers ? createNodeArray(modifiers) : undefined;
node.name = typeof name === "string" ? createIdentifier(name) : name;
node.typeParameters = undefined;
node.parameters = createNodeArray([parameter]);
@@ -306,15 +246,21 @@ namespace ts {
// Expression
export function createArrayLiteral(elements?: Expression[]) {
const node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression);
export function createArrayLiteral(elements?: Expression[], location?: TextRange, multiLine?: boolean) {
const node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression, location);
node.elements = parenthesizeListElements(createNodeArray(elements));
if (multiLine) {
node.multiLine = multiLine;
}
return node;
}
export function createObjectLiteral(properties?: ObjectLiteralElement[], location?: TextRange) {
export function createObjectLiteral(properties?: ObjectLiteralElement[], location?: TextRange, multiLine?: boolean) {
const node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression, location);
node.properties = createNodeArray(properties);
if (multiLine) {
node.multiLine = multiLine;
}
return node;
}
@@ -342,7 +288,7 @@ namespace ts {
export function createNew(expression: Expression, argumentsArray: Expression[], location?: TextRange) {
const node = <NewExpression>createNode(SyntaxKind.NewExpression, location);
node.expression = parenthesizeForAccess(expression);
node.expression = parenthesizeForNew(expression);
node.arguments = argumentsArray
? parenthesizeListElements(createNodeArray(argumentsArray))
: undefined;
@@ -355,7 +301,7 @@ namespace ts {
return node;
}
export function createFunctionExpression(asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
export function createFunctionExpression(asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, original?: Node) {
const node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression, location);
node.modifiers = undefined;
node.asteriskToken = asteriskToken;
@@ -364,6 +310,10 @@ namespace ts {
node.parameters = createNodeArray(parameters);
node.type = undefined;
node.body = body;
if (original) {
node.original = original;
}
return node;
}
@@ -454,16 +404,19 @@ namespace ts {
// Element
export function createBlock(statements: Statement[], location?: TextRange): Block {
export function createBlock(statements: Statement[], location?: TextRange, multiLine?: boolean): Block {
const block = <Block>createNode(SyntaxKind.Block, location);
block.statements = createNodeArray(statements);
if (multiLine) {
block.multiLine = true;
}
return block;
}
export function createVariableStatement(modifiers: Modifier[], declarationList: VariableDeclarationList, location?: TextRange): VariableStatement {
const node = <VariableStatement>createNode(SyntaxKind.VariableStatement, location);
node.decorators = undefined;
setModifiers(node, modifiers);
node.modifiers = modifiers ? createNodeArray(modifiers) : undefined;
node.declarationList = declarationList;
return node;
}
@@ -559,23 +512,26 @@ namespace ts {
return node;
}
export function createFunctionDeclaration(modifiers: Modifier[], asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange) {
export function createFunctionDeclaration(modifiers: Modifier[], asteriskToken: Node, name: string | Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, original?: Node) {
const node = <FunctionDeclaration>createNode(SyntaxKind.FunctionDeclaration, location);
node.decorators = undefined;
setModifiers(node, modifiers);
node.modifiers = modifiers ? createNodeArray(modifiers) : undefined;
node.asteriskToken = asteriskToken;
node.name = typeof name === "string" ? createIdentifier(name) : name;
node.typeParameters = undefined;
node.parameters = createNodeArray(parameters);
node.type = undefined;
node.body = body;
if (original) {
node.original = original;
}
return node;
}
export function createClassDeclaration(modifiers: Modifier[], name: Identifier, heritageClauses: HeritageClause[], members: ClassElement[], location?: TextRange) {
const node = <ClassDeclaration>createNode(SyntaxKind.ClassDeclaration, location);
node.decorators = undefined;
setModifiers(node, modifiers);
node.modifiers = modifiers ? createNodeArray(modifiers) : undefined;
node.name = name;
node.typeParameters = undefined;
node.heritageClauses = createNodeArray(heritageClauses);
@@ -688,8 +644,8 @@ namespace ts {
export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression {
return isIdentifier(memberName)
? createPropertyAccess(target, cloneNode(memberName), location)
: createElementAccess(target, cloneNode(isComputedPropertyName(memberName) ? memberName.expression : memberName), location);
? createPropertyAccess(target, getSynthesizedClone(memberName), location)
: createElementAccess(target, getSynthesizedClone(isComputedPropertyName(memberName) ? memberName.expression : memberName), location);
}
export function createRestParameter(name: string | Identifier) {
@@ -868,7 +824,7 @@ namespace ts {
);
if (preferNewLine) {
property.startsOnNewLine = true;
startOnNewLine(property);
}
properties.push(property);
@@ -1054,6 +1010,68 @@ namespace ts {
);
}
export interface CallBinding {
target: LeftHandSideExpression;
thisArg: Expression;
}
export function createCallBinding(expression: Expression, languageVersion?: ScriptTarget): CallBinding {
const callee = skipParentheses(expression);
let thisArg: Expression;
let target: LeftHandSideExpression;
if (isSuperProperty(callee)) {
thisArg = createThis(/*location*/ callee.expression);
target = callee;
}
else if (callee.kind === SyntaxKind.SuperKeyword) {
thisArg = createThis(/*location*/ callee);
target = languageVersion < ScriptTarget.ES6 ? createIdentifier("_super", /*location*/ callee) : <PrimaryExpression>callee;
}
else {
switch (callee.kind) {
case SyntaxKind.PropertyAccessExpression: {
// for `a.b()` target is `(_a = a).b` and thisArg is `_a`
thisArg = createTempVariable();
target = createPropertyAccess(
createAssignment(
thisArg,
(<PropertyAccessExpression>callee).expression,
/*location*/ (<PropertyAccessExpression>callee).expression
),
(<PropertyAccessExpression>callee).name,
/*location*/ callee
);
break;
}
case SyntaxKind.ElementAccessExpression: {
// for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a`
thisArg = createTempVariable();
target = createElementAccess(
createAssignment(
thisArg,
(<ElementAccessExpression>callee).expression,
/*location*/ (<ElementAccessExpression>callee).expression
),
(<ElementAccessExpression>callee).argumentExpression,
/*location*/ callee
);
break;
}
default: {
// for `a()` target is `a` and thisArg is `void 0`
thisArg = createVoidZero();
target = parenthesizeForAccess(expression);
break;
}
}
}
return { target, thisArg };
}
export function inlineExpressions(expressions: Expression[]) {
return reduceLeft(expressions, createComma);
}
@@ -1062,18 +1080,17 @@ namespace ts {
return isQualifiedName(node)
? createPropertyAccess(
createExpressionFromEntityName(node.left),
cloneNode(node.right)
getSynthesizedClone(node.right)
)
: cloneNode(node);
: getSynthesizedClone(node);
}
export function createExpressionForPropertyName(memberName: PropertyName, location?: TextRange): Expression {
return isIdentifier(memberName) ? createLiteral(memberName.text, location)
: isComputedPropertyName(memberName) ? cloneNode(memberName.expression, location)
: cloneNode(memberName, location);
: isComputedPropertyName(memberName) ? getRelocatedClone(memberName.expression, location)
: getRelocatedClone(memberName, location);
}
// Utilities
/**
@@ -1193,6 +1210,23 @@ namespace ts {
|| binaryOperator === SyntaxKind.CaretToken;
}
/**
* Wraps an expression in parentheses if it is needed in order to use the expression
* as the expression of a NewExpression node.
*
* @param expression The Expression node.
*/
export function parenthesizeForNew(expression: Expression): LeftHandSideExpression {
const lhs = parenthesizeForAccess(expression);
switch (lhs.kind) {
case SyntaxKind.CallExpression:
case SyntaxKind.NewExpression:
return createParen(lhs);
}
return lhs;
}
/**
* Wraps an expression in parentheses if it is needed in order to use the expression for
* property or element access.
@@ -1262,7 +1296,7 @@ namespace ts {
const callee = expression.expression;
if (callee.kind === SyntaxKind.FunctionExpression
|| callee.kind === SyntaxKind.ArrowFunction) {
const clone = cloneNode(expression, expression, expression.flags, expression.parent, expression);
const clone = getMutableClone(expression);
clone.expression = createParen(callee, /*location*/ callee);
return clone;
}
@@ -1341,7 +1375,13 @@ namespace ts {
return node;
}
export function getSynthesizedNode<T extends Node>(node: T): T {
return nodeIsSynthesized(node) ? node : cloneNode(node, /*location*/ undefined, node.flags, /*parent*/ undefined, /*original*/ node);
export function setMultiLine<T extends ObjectLiteralExpression | ArrayLiteralExpression | Block>(node: T, multiLine: boolean): T {
node.multiLine = multiLine;
return node;
}
export function setHasTrailingComma<T extends Node>(nodes: NodeArray<T>, hasTrailingComma: boolean): NodeArray<T> {
nodes.hasTrailingComma = hasTrailingComma;
return nodes;
}
}
+60 -84
View File
@@ -997,19 +997,6 @@ namespace ts {
}
array.pos = pos;
array.end = pos;
array.arrayKind = ArrayKind.NodeArray;
return array;
}
function createModifiersArray(elements?: Modifier[], pos?: number): ModifiersArray {
const array = <ModifiersArray>(elements || []);
if (!(pos >= 0)) {
pos = getNodePos();
}
array.pos = pos;
array.end = pos;
array.arrayKind = ArrayKind.ModifiersArray;
array.flags = 0;
return array;
}
@@ -2019,17 +2006,10 @@ namespace ts {
return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token) || token === SyntaxKind.AtToken;
}
function setModifiers(node: Node, modifiers: ModifiersArray) {
if (modifiers) {
node.flags |= modifiers.flags;
node.modifiers = modifiers;
}
}
function parseParameter(): ParameterDeclaration {
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter);
node.decorators = parseDecorators();
setModifiers(node, parseModifiers());
node.modifiers = parseModifiers();
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
// FormalParameter [Yield,Await]:
@@ -2218,23 +2198,23 @@ namespace ts {
return token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken || token === SyntaxKind.CloseBracketToken;
}
function parseIndexSignatureDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): IndexSignatureDeclaration {
function parseIndexSignatureDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): IndexSignatureDeclaration {
const node = <IndexSignatureDeclaration>createNode(SyntaxKind.IndexSignature, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
node.parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
node.type = parseTypeAnnotation();
parseTypeMemberSemicolon();
return finishNode(node);
}
function parsePropertyOrMethodSignature(fullStart: number, modifiers: ModifiersArray): PropertySignature | MethodSignature {
function parsePropertyOrMethodSignature(fullStart: number, modifiers: NodeArray<Modifier>): PropertySignature | MethodSignature {
const name = parsePropertyName();
const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
const method = <MethodSignature>createNode(SyntaxKind.MethodSignature, fullStart);
setModifiers(method, modifiers);
method.modifiers = modifiers;
method.name = name;
method.questionToken = questionToken;
@@ -2246,7 +2226,7 @@ namespace ts {
}
else {
const property = <PropertySignature>createNode(SyntaxKind.PropertySignature, fullStart);
setModifiers(property, modifiers);
property.modifiers = modifiers;
property.name = name;
property.questionToken = questionToken;
property.type = parseTypeAnnotation();
@@ -2826,7 +2806,7 @@ namespace ts {
return undefined;
}
const isAsync = !!(arrowFunction.flags & NodeFlags.Async);
const isAsync = !!(getModifierFlags(arrowFunction) & ModifierFlags.Async);
// If we have an arrow, then try to parse the body. Even if not, try to parse if we
// have an opening brace, just in case we're in an error state.
@@ -2971,8 +2951,8 @@ namespace ts {
function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction {
const node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction);
setModifiers(node, parseModifiersForArrowFunction());
const isAsync = !!(node.flags & NodeFlags.Async);
node.modifiers = parseModifiersForArrowFunction();
const isAsync = !!(getModifierFlags(node) & ModifierFlags.Async);
// Arrow functions are never generators.
//
@@ -3942,7 +3922,7 @@ namespace ts {
return finishNode(node);
}
function tryParseAccessorDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): AccessorDeclaration {
function tryParseAccessorDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): AccessorDeclaration {
if (parseContextualModifier(SyntaxKind.GetKeyword)) {
return parseAccessorDeclaration(SyntaxKind.GetAccessor, fullStart, decorators, modifiers);
}
@@ -4027,12 +4007,12 @@ namespace ts {
}
const node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression);
setModifiers(node, parseModifiers());
node.modifiers = parseModifiers();
parseExpected(SyntaxKind.FunctionKeyword);
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
const isGenerator = !!node.asteriskToken;
const isAsync = !!(node.flags & NodeFlags.Async);
const isAsync = !!(getModifierFlags(node) & ModifierFlags.Async);
node.name =
isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) :
isGenerator ? doInYieldContext(parseOptionalIdentifier) :
@@ -4615,7 +4595,7 @@ namespace ts {
const node = <Statement>createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
node.pos = fullStart;
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
return finishNode(node);
}
}
@@ -4750,57 +4730,57 @@ namespace ts {
return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken;
}
function parseVariableStatement(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): VariableStatement {
function parseVariableStatement(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): VariableStatement {
const node = <VariableStatement>createNode(SyntaxKind.VariableStatement, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
node.declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false);
parseSemicolon();
return addJSDocComment(finishNode(node));
}
function parseFunctionDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): FunctionDeclaration {
function parseFunctionDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): FunctionDeclaration {
const node = <FunctionDeclaration>createNode(SyntaxKind.FunctionDeclaration, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
parseExpected(SyntaxKind.FunctionKeyword);
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
node.name = node.flags & NodeFlags.Default ? parseOptionalIdentifier() : parseIdentifier();
node.name = hasModifier(node, ModifierFlags.Default) ? parseOptionalIdentifier() : parseIdentifier();
const isGenerator = !!node.asteriskToken;
const isAsync = !!(node.flags & NodeFlags.Async);
const isAsync = hasModifier(node, ModifierFlags.Async);
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, node);
node.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, Diagnostics.or_expected);
return addJSDocComment(finishNode(node));
}
function parseConstructorDeclaration(pos: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ConstructorDeclaration {
function parseConstructorDeclaration(pos: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ConstructorDeclaration {
const node = <ConstructorDeclaration>createNode(SyntaxKind.Constructor, pos);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
parseExpected(SyntaxKind.ConstructorKeyword);
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node);
node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false, Diagnostics.or_expected);
return addJSDocComment(finishNode(node));
}
function parseMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, asteriskToken: Node, name: PropertyName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
function parseMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>, asteriskToken: Node, name: PropertyName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
const method = <MethodDeclaration>createNode(SyntaxKind.MethodDeclaration, fullStart);
method.decorators = decorators;
setModifiers(method, modifiers);
method.modifiers = modifiers;
method.asteriskToken = asteriskToken;
method.name = name;
method.questionToken = questionToken;
const isGenerator = !!asteriskToken;
const isAsync = !!(method.flags & NodeFlags.Async);
const isAsync = hasModifier(method, ModifierFlags.Async);
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ isGenerator, /*awaitContext*/ isAsync, /*requireCompleteParameterList*/ false, method);
method.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, diagnosticMessage);
return addJSDocComment(finishNode(method));
}
function parsePropertyDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, name: PropertyName, questionToken: Node): ClassElement {
function parsePropertyDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>, name: PropertyName, questionToken: Node): ClassElement {
const property = <PropertyDeclaration>createNode(SyntaxKind.PropertyDeclaration, fullStart);
property.decorators = decorators;
setModifiers(property, modifiers);
property.modifiers = modifiers;
property.name = name;
property.questionToken = questionToken;
property.type = parseTypeAnnotation();
@@ -4814,7 +4794,7 @@ namespace ts {
// AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initialiser_opt[In, ?Yield];
//
// The checker may still error in the static case to explicitly disallow the yield expression.
property.initializer = modifiers && modifiers.flags & NodeFlags.Static
property.initializer = hasModifier(property, ModifierFlags.Static)
? allowInAnd(parseNonParameterInitializer)
: doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.DisallowInContext, parseNonParameterInitializer);
@@ -4822,7 +4802,7 @@ namespace ts {
return finishNode(property);
}
function parsePropertyOrMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ClassElement {
function parsePropertyOrMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ClassElement {
const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
const name = parsePropertyName();
@@ -4841,10 +4821,10 @@ namespace ts {
return parseInitializer(/*inParameter*/ false);
}
function parseAccessorDeclaration(kind: SyntaxKind, fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): AccessorDeclaration {
function parseAccessorDeclaration(kind: SyntaxKind, fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): AccessorDeclaration {
const node = <AccessorDeclaration>createNode(kind, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
node.name = parsePropertyName();
fillSignature(SyntaxKind.ColonToken, /*yieldContext*/ false, /*awaitContext*/ false, /*requireCompleteParameterList*/ false, node);
node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false);
@@ -4963,9 +4943,8 @@ namespace ts {
*
* In such situations, 'permitInvalidConstAsModifier' should be set to true.
*/
function parseModifiers(permitInvalidConstAsModifier?: boolean): ModifiersArray {
let flags = 0;
let modifiers: ModifiersArray;
function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray<Modifier> {
let modifiers: NodeArray<Modifier>;
while (true) {
const modifierStart = scanner.getStartPos();
const modifierKind = token;
@@ -4983,31 +4962,28 @@ namespace ts {
}
}
flags |= modifierToFlag(modifierKind);
const modifier = finishNode(createNode(modifierKind, modifierStart));
if (!modifiers) {
modifiers = createModifiersArray([modifier], modifierStart);
modifiers = createNodeArray<Modifier>([modifier], modifierStart);
}
else {
modifiers.push(modifier);
}
}
if (modifiers) {
modifiers.flags = flags;
modifiers.end = scanner.getStartPos();
}
return modifiers;
}
function parseModifiersForArrowFunction(): ModifiersArray {
let modifiers: ModifiersArray;
function parseModifiersForArrowFunction(): NodeArray<Modifier> {
let modifiers: NodeArray<Modifier>;
if (token === SyntaxKind.AsyncKeyword) {
const modifierStart = scanner.getStartPos();
const modifierKind = token;
nextToken();
const modifier = finishNode(createNode(modifierKind, modifierStart));
modifiers = createModifiersArray([modifier], modifierStart);
modifiers.flags = modifierToFlag(modifierKind);
modifiers = createNodeArray<Modifier>([modifier], modifierStart);
modifiers.end = scanner.getStartPos();
}
@@ -5067,14 +5043,14 @@ namespace ts {
SyntaxKind.ClassExpression);
}
function parseClassDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ClassDeclaration {
function parseClassDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ClassDeclaration {
return <ClassDeclaration>parseClassDeclarationOrExpression(fullStart, decorators, modifiers, SyntaxKind.ClassDeclaration);
}
function parseClassDeclarationOrExpression(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, kind: SyntaxKind): ClassLikeDeclaration {
function parseClassDeclarationOrExpression(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>, kind: SyntaxKind): ClassLikeDeclaration {
const node = <ClassLikeDeclaration>createNode(kind, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
parseExpected(SyntaxKind.ClassKeyword);
node.name = parseNameOfClassDeclarationOrExpression();
node.typeParameters = parseTypeParameters();
@@ -5149,10 +5125,10 @@ namespace ts {
return parseList(ParsingContext.ClassMembers, parseClassElement);
}
function parseInterfaceDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): InterfaceDeclaration {
function parseInterfaceDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): InterfaceDeclaration {
const node = <InterfaceDeclaration>createNode(SyntaxKind.InterfaceDeclaration, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
parseExpected(SyntaxKind.InterfaceKeyword);
node.name = parseIdentifier();
node.typeParameters = parseTypeParameters();
@@ -5161,10 +5137,10 @@ namespace ts {
return finishNode(node);
}
function parseTypeAliasDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): TypeAliasDeclaration {
function parseTypeAliasDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): TypeAliasDeclaration {
const node = <TypeAliasDeclaration>createNode(SyntaxKind.TypeAliasDeclaration, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
parseExpected(SyntaxKind.TypeKeyword);
node.name = parseIdentifier();
node.typeParameters = parseTypeParameters();
@@ -5185,10 +5161,10 @@ namespace ts {
return finishNode(node);
}
function parseEnumDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): EnumDeclaration {
function parseEnumDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): EnumDeclaration {
const node = <EnumDeclaration>createNode(SyntaxKind.EnumDeclaration, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
parseExpected(SyntaxKind.EnumKeyword);
node.name = parseIdentifier();
if (parseExpected(SyntaxKind.OpenBraceToken)) {
@@ -5213,25 +5189,25 @@ namespace ts {
return finishNode(node);
}
function parseModuleOrNamespaceDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, flags: NodeFlags): ModuleDeclaration {
function parseModuleOrNamespaceDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>, flags: NodeFlags): ModuleDeclaration {
const node = <ModuleDeclaration>createNode(SyntaxKind.ModuleDeclaration, fullStart);
// If we are parsing a dotted namespace name, we want to
// propagate the 'Namespace' flag across the names if set.
const namespaceFlag = flags & NodeFlags.Namespace;
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
node.flags |= flags;
node.name = parseIdentifier();
node.body = parseOptional(SyntaxKind.DotToken)
? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.Export | namespaceFlag)
? parseModuleOrNamespaceDeclaration(getNodePos(), /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.NestedNamespace | namespaceFlag)
: parseModuleBlock();
return finishNode(node);
}
function parseAmbientExternalModuleDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ModuleDeclaration {
function parseAmbientExternalModuleDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ModuleDeclaration {
const node = <ModuleDeclaration>createNode(SyntaxKind.ModuleDeclaration, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
if (token === SyntaxKind.GlobalKeyword) {
// parse 'global' as name of global scope augmentation
node.name = parseIdentifier();
@@ -5244,8 +5220,8 @@ namespace ts {
return finishNode(node);
}
function parseModuleDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ModuleDeclaration {
let flags = modifiers ? modifiers.flags : 0;
function parseModuleDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ModuleDeclaration {
let flags: NodeFlags = 0;
if (token === SyntaxKind.GlobalKeyword) {
// global augmentation
return parseAmbientExternalModuleDeclaration(fullStart, decorators, modifiers);
@@ -5275,7 +5251,7 @@ namespace ts {
return nextToken() === SyntaxKind.SlashToken;
}
function parseImportDeclarationOrImportEqualsDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ImportEqualsDeclaration | ImportDeclaration {
function parseImportDeclarationOrImportEqualsDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ImportEqualsDeclaration | ImportDeclaration {
parseExpected(SyntaxKind.ImportKeyword);
const afterImportPos = scanner.getStartPos();
@@ -5288,7 +5264,7 @@ namespace ts {
// import x = M.x;
const importEqualsDeclaration = <ImportEqualsDeclaration>createNode(SyntaxKind.ImportEqualsDeclaration, fullStart);
importEqualsDeclaration.decorators = decorators;
setModifiers(importEqualsDeclaration, modifiers);
importEqualsDeclaration.modifiers = modifiers;
importEqualsDeclaration.name = identifier;
parseExpected(SyntaxKind.EqualsToken);
importEqualsDeclaration.moduleReference = parseModuleReference();
@@ -5300,7 +5276,7 @@ namespace ts {
// Import statement
const importDeclaration = <ImportDeclaration>createNode(SyntaxKind.ImportDeclaration, fullStart);
importDeclaration.decorators = decorators;
setModifiers(importDeclaration, modifiers);
importDeclaration.modifiers = modifiers;
// ImportDeclaration:
// import ImportClause from ModuleSpecifier ;
@@ -5436,10 +5412,10 @@ namespace ts {
return finishNode(node);
}
function parseExportDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ExportDeclaration {
function parseExportDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ExportDeclaration {
const node = <ExportDeclaration>createNode(SyntaxKind.ExportDeclaration, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
if (parseOptional(SyntaxKind.AsteriskToken)) {
parseExpected(SyntaxKind.FromKeyword);
node.moduleSpecifier = parseModuleSpecifier();
@@ -5459,10 +5435,10 @@ namespace ts {
return finishNode(node);
}
function parseExportAssignment(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ExportAssignment {
function parseExportAssignment(fullStart: number, decorators: NodeArray<Decorator>, modifiers: NodeArray<Modifier>): ExportAssignment {
const node = <ExportAssignment>createNode(SyntaxKind.ExportAssignment, fullStart);
node.decorators = decorators;
setModifiers(node, modifiers);
node.modifiers = modifiers;
if (parseOptional(SyntaxKind.EqualsToken)) {
node.isExportEquals = true;
}
@@ -5541,7 +5517,7 @@ namespace ts {
function setExternalModuleIndicator(sourceFile: SourceFile) {
sourceFile.externalModuleIndicator = forEach(sourceFile.statements, node =>
node.flags & NodeFlags.Export
hasModifier(node, ModifierFlags.Export)
|| node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference
|| node.kind === SyntaxKind.ImportDeclaration
|| node.kind === SyntaxKind.ExportAssignment
+45 -35
View File
@@ -6,9 +6,6 @@
/* @internal */
namespace ts {
const delimiters = createDelimiterMap();
const brackets = createBracketsMap();
// Flags enum to track count of temp variables and a few dedicated names
const enum TempFlags {
Auto = 0x00000000, // No preferred name
@@ -18,6 +15,9 @@ namespace ts {
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
export function printFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
const delimiters = createDelimiterMap();
const brackets = createBracketsMap();
// emit output for the __extends helper function
const extendsHelper = `
var __extends = (this && this.__extends) || function (d, b) {
@@ -147,6 +147,7 @@ const _super = (function (geti, seti) {
let startLexicalEnvironment: () => void;
let endLexicalEnvironment: () => Statement[];
let getNodeEmitFlags: (node: Node) => NodeEmitFlags;
let setNodeEmitFlags: (node: Node, flags: NodeEmitFlags) => void;
let isExpressionSubstitutionEnabled: (node: Node) => boolean;
let isEmitNotificationEnabled: (node: Node) => boolean;
let expressionSubstitution: (node: Expression) => Expression;
@@ -208,6 +209,7 @@ const _super = (function (geti, seti) {
startLexicalEnvironment = undefined;
endLexicalEnvironment = undefined;
getNodeEmitFlags = undefined;
setNodeEmitFlags = undefined;
isExpressionSubstitutionEnabled = undefined;
isEmitNotificationEnabled = undefined;
expressionSubstitution = undefined;
@@ -228,6 +230,7 @@ const _super = (function (geti, seti) {
startLexicalEnvironment = context.startLexicalEnvironment;
endLexicalEnvironment = context.endLexicalEnvironment;
getNodeEmitFlags = context.getNodeEmitFlags;
setNodeEmitFlags = context.setNodeEmitFlags;
isExpressionSubstitutionEnabled = context.isExpressionSubstitutionEnabled;
isEmitNotificationEnabled = context.isEmitNotificationEnabled;
expressionSubstitution = context.expressionSubstitution;
@@ -672,7 +675,7 @@ const _super = (function (geti, seti) {
//
function emitIdentifier(node: Identifier) {
if (getNodeEmitFlags(node) && NodeEmitFlags.UMDDefine) {
if (getNodeEmitFlags(node) & NodeEmitFlags.UMDDefine) {
writeLines(umdHelper);
}
else {
@@ -1408,6 +1411,10 @@ const _super = (function (geti, seti) {
}
function shouldEmitBlockFunctionBodyOnSingleLine(parentNode: Node, body: Block) {
if (body.multiLine) {
return false;
}
const originalNode = getOriginalNode(parentNode);
if (isFunctionLike(originalNode) && !nodeIsSynthesized(originalNode)) {
const body = originalNode.body;
@@ -1951,7 +1958,7 @@ const _super = (function (geti, seti) {
}
}
function emitModifiers(node: Node, modifiers: ModifiersArray) {
function emitModifiers(node: Node, modifiers: NodeArray<Modifier>) {
if (modifiers && modifiers.length) {
emitList(node, modifiers, ListFormat.SingleLine);
write(" ");
@@ -1981,10 +1988,13 @@ const _super = (function (geti, seti) {
}
function tryEmitSubstitute(node: Node, substitution: (node: Node) => Node) {
const substitute = substitution ? substitution(node) : node;
if (substitute && substitute !== node) {
emitWorker(substitute);
return true;
if (substitution && (getNodeEmitFlags(node) & NodeEmitFlags.NoSubstitution) === 0) {
const substitute = substitution(node);
if (substitute !== node) {
setNodeEmitFlags(substitute, NodeEmitFlags.NoSubstitution | getNodeEmitFlags(substitute));
emitWorker(substitute);
return true;
}
}
return false;
@@ -2392,7 +2402,7 @@ const _super = (function (geti, seti) {
}
function isUniqueLocalName(name: string, container: Node): boolean {
for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) {
if (node.locals && hasProperty(node.locals, name)) {
// We conservatively include alias symbols to cover cases where they're emitted as locals
if (node.locals[name].flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) {
@@ -2510,36 +2520,36 @@ const _super = (function (geti, seti) {
return nodeToGeneratedName[id] || (nodeToGeneratedName[id] = unescapeIdentifier(generateIdentifier(node)));
}
}
}
function createDelimiterMap() {
const delimiters: string[] = [];
delimiters[ListFormat.None] = "";
delimiters[ListFormat.CommaDelimited] = ",";
delimiters[ListFormat.BarDelimited] = " |";
delimiters[ListFormat.AmpersandDelimited] = " &";
return delimiters;
}
function createDelimiterMap() {
const delimiters: string[] = [];
delimiters[ListFormat.None] = "";
delimiters[ListFormat.CommaDelimited] = ",";
delimiters[ListFormat.BarDelimited] = " |";
delimiters[ListFormat.AmpersandDelimited] = " &";
return delimiters;
}
function getDelimiter(format: ListFormat) {
return delimiters[format & ListFormat.DelimitersMask];
}
function getDelimiter(format: ListFormat) {
return delimiters[format & ListFormat.DelimitersMask];
}
function createBracketsMap() {
const brackets: string[][] = [];
brackets[ListFormat.Braces] = ["{", "}"];
brackets[ListFormat.Parenthesis] = ["(", ")"];
brackets[ListFormat.AngleBrackets] = ["<", ">"];
brackets[ListFormat.SquareBrackets] = ["[", "]"];
return brackets;
}
function createBracketsMap() {
const brackets: string[][] = [];
brackets[ListFormat.Braces] = ["{", "}"];
brackets[ListFormat.Parenthesis] = ["(", ")"];
brackets[ListFormat.AngleBrackets] = ["<", ">"];
brackets[ListFormat.SquareBrackets] = ["[", "]"];
return brackets;
}
function getOpeningBracket(format: ListFormat) {
return brackets[format & ListFormat.BracketsMask][0];
}
function getOpeningBracket(format: ListFormat) {
return brackets[format & ListFormat.BracketsMask][0];
}
function getClosingBracket(format: ListFormat) {
return brackets[format & ListFormat.BracketsMask][1];
function getClosingBracket(format: ListFormat) {
return brackets[format & ListFormat.BracketsMask][1];
}
}
const enum ListFormat {
+2 -2
View File
@@ -1196,7 +1196,7 @@ namespace ts {
return false;
}
function checkModifiers(modifiers: ModifiersArray): boolean {
function checkModifiers(modifiers: NodeArray<Modifier>): boolean {
if (modifiers) {
for (const modifier of modifiers) {
switch (modifier.kind) {
@@ -1311,7 +1311,7 @@ namespace ts {
}
break;
case SyntaxKind.ModuleDeclaration:
if (isAmbientModule(<ModuleDeclaration>node) && (inAmbientModule || node.flags & NodeFlags.Ambient || isDeclarationFile(file))) {
if (isAmbientModule(<ModuleDeclaration>node) && (inAmbientModule || hasModifier(node, ModifierFlags.Ambient) || isDeclarationFile(file))) {
const moduleName = <LiteralExpression>(<ModuleDeclaration>node).name;
// Ambient module declarations can be interpreted as augmentations for some existing external modules.
// This will happen in two cases:
+2 -3
View File
@@ -433,9 +433,7 @@ namespace ts {
/* @internal */
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
// Using ! with a greater than test is a fast way of testing the following conditions:
// pos === undefined || pos === null || isNaN(pos) || pos < 0;
if (!(pos >= 0)) {
if (positionIsSynthesized(pos)) {
return pos;
}
@@ -642,6 +640,7 @@ namespace ts {
pos++;
}
}
if (collecting) {
if (!result) {
result = [];
+11
View File
@@ -67,6 +67,11 @@ namespace ts {
// Source map data
let sourceMapData: SourceMapData;
// This keeps track of the number of times `disable` has been called without a
// corresponding call to `enable`. As long as this value is non-zero, mappings will not
// be recorded.
// This is primarily used to provide a better experience when debugging binding
// patterns and destructuring assignments for simple expressions.
let disableDepth: number;
return {
@@ -160,12 +165,18 @@ namespace ts {
disableDepth = 0;
}
/**
* Re-enables the recording of mappings.
*/
function enable() {
if (disableDepth > 0) {
disableDepth--;
}
}
/**
* Disables the recording of mappings.
*/
function disable() {
disableDepth++;
}
+11
View File
@@ -8,6 +8,7 @@ namespace ts {
args: string[];
newLine: string;
useCaseSensitiveFileNames: boolean;
/*@internal*/ developmentMode?: boolean;
write(s: string): void;
readFile(path: string, encoding?: string): string;
writeFile(path: string, data: string, writeByteOrderMark?: boolean): void;
@@ -22,6 +23,7 @@ namespace ts {
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
getMemoryUsage?(): number;
exit(exitCode?: number): void;
/*@internal*/ tryEnableSourceMapsForHost?(): void;
}
interface WatchedFile {
@@ -494,6 +496,7 @@ namespace ts {
args: process.argv.slice(2),
newLine: _os.EOL,
useCaseSensitiveFileNames: useCaseSensitiveFileNames,
developmentMode: /^development$/i.test(String(process.env.NODE_ENV)),
write(s: string): void {
process.stdout.write(s);
},
@@ -564,6 +567,14 @@ namespace ts {
},
exit(exitCode?: number): void {
process.exit(exitCode);
},
tryEnableSourceMapsForHost() {
try {
require("source-map-support").install();
}
catch (e) {
// Could not enable source maps.
}
}
};
}
+33 -1
View File
@@ -1,15 +1,47 @@
/// <reference path="visitor.ts" />
/// <reference path="transformers/ts.ts" />
/// <reference path="transformers/jsx.ts" />
/// <reference path="transformers/es7.ts" />
/// <reference path="transformers/es6.ts" />
/// <reference path="transformers/module/module.ts" />
/// <reference path="transformers/module/system.ts" />
/// <reference path="transformers/module/es6.ts" />
/* @internal */
namespace ts {
const moduleTransformerMap: Map<Transformer> = {
[ModuleKind.ES6]: transformES6Module,
[ModuleKind.System]: transformSystemModule,
[ModuleKind.AMD]: transformModule,
[ModuleKind.CommonJS]: transformModule,
[ModuleKind.UMD]: transformModule,
[ModuleKind.None]: transformModule,
};
const enum SyntaxKindFeatureFlags {
ExpressionSubstitution = 1 << 0,
EmitNotifications = 1 << 1,
}
export function getTransformers(compilerOptions: CompilerOptions) {
const jsx = compilerOptions.jsx;
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
const transformers: Transformer[] = [];
// TODO(rbuckton): Add transformers
transformers.push(transformTypeScript);
transformers.push(moduleTransformerMap[moduleKind]);
if (jsx === JsxEmit.React) {
transformers.push(transformJsx);
}
transformers.push(transformES7);
if (languageVersion < ScriptTarget.ES6) {
transformers.push(transformES6);
}
return transformers;
}
+397
View File
@@ -0,0 +1,397 @@
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/*@internal*/
namespace ts {
/**
* Flattens a destructuring assignment expression.
*
* @param root The destructuring assignment expression.
* @param needsValue Indicates whether the value from the right-hand-side of the
* destructuring assignment is needed as part of a larger expression.
* @param recordTempVariable A callback used to record new temporary variables.
* @param visitor An optional visitor to use to visit expressions.
*/
export function flattenDestructuringAssignment(
node: BinaryExpression,
needsValue: boolean,
recordTempVariable: (node: Identifier) => void,
visitor?: (node: Node) => VisitResult<Node>) {
if (isEmptyObjectLiteralOrArrayLiteral(node.left)) {
return node.right;
}
let location: TextRange = node;
let value = node.right;
const expressions: Expression[] = [];
if (needsValue) {
// If the right-hand value of the destructuring assignment needs to be preserved (as
// is the case when the destructuring assignmen) is part of a larger expression),
// then we need to cache the right-hand value.
//
// The source map location for the assignment should point to the entire binary
// expression.
value = ensureIdentifier(node.right, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
}
else if (nodeIsSynthesized(node)) {
// Generally, the source map location for a destructuring assignment is the root
// expression.
//
// However, if the root expression is synthesized (as in the case
// of the initializer when transforming a ForOfStatement), then the source map
// location should point to the right-hand value of the expression.
location = node.right;
}
flattenDestructuring(node, value, location, emitAssignment, emitTempVariableAssignment, visitor);
if (needsValue) {
expressions.push(value);
}
const expression = inlineExpressions(expressions);
aggregateTransformFlags(expression);
return expression;
function emitAssignment(name: Identifier, value: Expression, location: TextRange) {
const expression = createAssignment(name, value, location);
if (isSimpleExpression(value)) {
expression.disableSourceMap = true;
}
aggregateTransformFlags(expression);
expressions.push(expression);
}
function emitTempVariableAssignment(value: Expression, location: TextRange) {
const name = createTempVariable();
recordTempVariable(name);
emitAssignment(name, value, location);
return name;
}
}
/**
* Flattens binding patterns in a parameter declaration.
*
* @param node The ParameterDeclaration to flatten.
* @param value The rhs value for the binding pattern.
* @param visitor An optional visitor to use to visit expressions.
*/
export function flattenParameterDestructuring(node: ParameterDeclaration, value: Expression, visitor?: (node: Node) => VisitResult<Node>) {
const declarations: VariableDeclaration[] = [];
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
return declarations;
function emitAssignment(name: Identifier, value: Expression, location: TextRange) {
const declaration = createVariableDeclaration(name, value, location);
if (isSimpleExpression(value)) {
declaration.disableSourceMap = true;
}
aggregateTransformFlags(declaration);
declarations.push(declaration);
}
function emitTempVariableAssignment(value: Expression, location: TextRange) {
const name = createTempVariable();
emitAssignment(name, value, location);
return name;
}
}
/**
* Flattens binding patterns in a variable declaration.
*
* @param node The VariableDeclaration to flatten.
* @param value An optional rhs value for the binding pattern.
* @param visitor An optional visitor to use to visit expressions.
*/
export function flattenVariableDestructuring(node: VariableDeclaration, value?: Expression, visitor?: (node: Node) => VisitResult<Node>) {
const declarations: VariableDeclaration[] = [];
flattenDestructuring(node, value, node, emitAssignment, emitTempVariableAssignment, visitor);
return declarations;
function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
const declaration = createVariableDeclaration(name, value, location);
if (declarations.length === 0) {
declaration.pos = -1;
}
if (isSimpleExpression(value)) {
declaration.disableSourceMap = true;
}
declaration.original = original;
declarations.push(declaration);
aggregateTransformFlags(declaration);
}
function emitTempVariableAssignment(value: Expression, location: TextRange) {
const name = createTempVariable();
emitAssignment(name, value, location, /*original*/ undefined);
return name;
}
}
/**
* Flattens binding patterns in a variable declaration and transforms them into an expression.
*
* @param node The VariableDeclaration to flatten.
* @param recordTempVariable A callback used to record new temporary variables.
* @param nameSubstitution An optional callback used to substitute binding names.
* @param visitor An optional visitor to use to visit expressions.
*/
export function flattenVariableDestructuringToExpression(
node: VariableDeclaration,
recordTempVariable: (name: Identifier) => void,
nameSubstitution?: (name: Identifier) => Expression,
visitor?: (node: Node) => VisitResult<Node>) {
const pendingAssignments: Expression[] = [];
flattenDestructuring(node, /*value*/ undefined, node, emitAssignment, emitTempVariableAssignment);
const expression = inlineExpressions(pendingAssignments);
aggregateTransformFlags(expression);
return expression;
function emitAssignment(name: Identifier, value: Expression, location: TextRange, original: Node) {
const left = nameSubstitution && nameSubstitution(name) || name;
emitPendingAssignment(left, value, location, original);
}
function emitTempVariableAssignment(value: Expression, location: TextRange) {
const name = createTempVariable();
recordTempVariable(name);
emitPendingAssignment(name, value, location, /*original*/ undefined);
return name;
}
function emitPendingAssignment(name: Expression, value: Expression, location: TextRange, original: Node) {
const expression = createAssignment(name, value, location);
if (isSimpleExpression(value)) {
expression.disableSourceMap = true;
}
expression.original = original;
pendingAssignments.push(expression);
return expression;
}
}
function flattenDestructuring(
root: BindingElement | BinaryExpression,
value: Expression,
location: TextRange,
emitAssignment: (name: Identifier, value: Expression, location: TextRange, original: Node) => void,
emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier,
visitor?: (node: Node) => VisitResult<Node>) {
if (value && visitor) {
value = visitNode(value, visitor, isExpression);
}
if (isBinaryExpression(root)) {
emitDestructuringAssignment(root.left, value, location);
}
else {
emitBindingElement(root, value);
}
function emitDestructuringAssignment(bindingTarget: Expression | ShorthandPropertyAssignment, value: Expression, location: TextRange) {
// When emitting target = value use source map node to highlight, including any temporary assignments needed for this
let target: Expression;
if (isShorthandPropertyAssignment(bindingTarget)) {
const initializer = visitor
? visitNode(bindingTarget.objectAssignmentInitializer, visitor, isExpression)
: bindingTarget.objectAssignmentInitializer;
if (initializer) {
value = createDefaultValueCheck(value, initializer, location);
}
target = bindingTarget.name;
}
else if (isBinaryExpression(bindingTarget) && bindingTarget.operatorToken.kind === SyntaxKind.EqualsToken) {
const initializer = visitor
? visitNode(bindingTarget.right, visitor, isExpression)
: bindingTarget.right;
value = createDefaultValueCheck(value, initializer, location);
target = bindingTarget.left;
}
else {
target = bindingTarget;
}
if (target.kind === SyntaxKind.ObjectLiteralExpression) {
emitObjectLiteralAssignment(<ObjectLiteralExpression>target, value, location);
}
else if (target.kind === SyntaxKind.ArrayLiteralExpression) {
emitArrayLiteralAssignment(<ArrayLiteralExpression>target, value, location);
}
else {
const name = getRelocatedClone(<Identifier>target, /*location*/ target);
emitAssignment(name, value, location, /*original*/ undefined);
}
}
function emitObjectLiteralAssignment(target: ObjectLiteralExpression, value: Expression, location: TextRange) {
const properties = target.properties;
if (properties.length !== 1) {
// For anything but a single element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once.
// When doing so we want to hightlight the passed in source map node since thats the one needing this temp assignment
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
}
for (const p of properties) {
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
const propName = <Identifier | LiteralExpression>(<PropertyAssignment>p).name;
const target = p.kind === SyntaxKind.ShorthandPropertyAssignment ? <ShorthandPropertyAssignment>p : (<PropertyAssignment>p).initializer || propName;
// Assignment for target = value.propName should highligh whole property, hence use p as source map node
emitDestructuringAssignment(target, createDestructuringPropertyAccess(value, propName), p);
}
}
}
function emitArrayLiteralAssignment(target: ArrayLiteralExpression, value: Expression, location: TextRange) {
const elements = target.elements;
const numElements = elements.length;
if (numElements !== 1) {
// For anything but a single element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once.
// When doing so we want to hightlight the passed in source map node since thats the one needing this temp assignment
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
}
for (let i = 0; i < numElements; i++) {
const e = elements[i];
if (e.kind !== SyntaxKind.OmittedExpression) {
// Assignment for target = value.propName should highligh whole property, hence use e as source map node
if (e.kind !== SyntaxKind.SpreadElementExpression) {
emitDestructuringAssignment(e, createElementAccess(value, createLiteral(i)), e);
}
else if (i === numElements - 1) {
emitDestructuringAssignment((<SpreadElementExpression>e).expression, createArraySlice(value, i), e);
}
}
}
}
function emitBindingElement(target: BindingElement, value: Expression) {
// Any temporary assignments needed to emit target = value should point to target
const initializer = visitor ? visitNode(target.initializer, visitor, isExpression) : target.initializer;
if (initializer) {
// Combine value and initializer
value = value ? createDefaultValueCheck(value, initializer, target) : initializer;
}
else if (!value) {
// Use 'void 0' in absence of value and initializer
value = createVoidZero();
}
const name = target.name;
if (isBindingPattern(name)) {
const elements = name.elements;
const numElements = elements.length;
if (numElements !== 1) {
// For anything other than a single-element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once. Additionally, if we have zero elements
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
// so in that case, we'll intentionally create that temporary.
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ numElements !== 0, target, emitTempVariableAssignment);
}
for (let i = 0; i < numElements; i++) {
const element = elements[i];
if (name.kind === SyntaxKind.ObjectBindingPattern) {
// Rewrite element to a declaration with an initializer that fetches property
const propName = element.propertyName || <Identifier>element.name;
emitBindingElement(element, createDestructuringPropertyAccess(value, propName));
}
else if (element.kind !== SyntaxKind.OmittedExpression) {
if (!element.dotDotDotToken) {
// Rewrite element to a declaration that accesses array element at index i
emitBindingElement(element, createElementAccess(value, i));
}
else if (i === numElements - 1) {
emitBindingElement(element, createArraySlice(value, i));
}
}
}
}
else {
const clonedName = getSynthesizedClone(name);
emitAssignment(clonedName, value, target, target);
}
}
function createDefaultValueCheck(value: Expression, defaultValue: Expression, location: TextRange): Expression {
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, location, emitTempVariableAssignment);
return createConditional(
createStrictEquality(value, createVoidZero()),
defaultValue,
value
);
}
/**
* Creates either a PropertyAccessExpression or an ElementAccessExpression for the
* right-hand side of a transformed destructuring assignment.
*
* @param expression The right-hand expression that is the source of the property.
* @param propertyName The destructuring property name.
*/
function createDestructuringPropertyAccess(expression: Expression, propertyName: PropertyName): LeftHandSideExpression {
if (isComputedPropertyName(propertyName)) {
return createElementAccess(
expression,
ensureIdentifier(propertyName.expression, /*reuseIdentifierExpressions*/ false, /*location*/ propertyName, emitTempVariableAssignment)
);
}
else if (isIdentifier(propertyName)) {
return createPropertyAccess(
expression,
propertyName.text
);
}
else {
// We create a synthetic copy of the identifier in order to avoid the rewriting that might
// otherwise occur when the identifier is emitted.
return createElementAccess(
expression,
getSynthesizedClone(propertyName)
);
}
}
}
/**
* Ensures that there exists a declared identifier whose value holds the given expression.
* This function is useful to ensure that the expression's value can be read from in subsequent expressions.
* Unless 'reuseIdentifierExpressions' is false, 'value' will be returned if it is just an identifier.
*
* @param value the expression whose value needs to be bound.
* @param reuseIdentifierExpressions true if identifier expressions can simply be returned;
* false if it is necessary to always emit an identifier.
* @param location The location to use for source maps and comments.
* @param emitTempVariableAssignment A callback used to emit a temporary variable.
*/
function ensureIdentifier(
value: Expression,
reuseIdentifierExpressions: boolean,
location: TextRange,
emitTempVariableAssignment: (value: Expression, location: TextRange) => Identifier) {
if (isIdentifier(value) && reuseIdentifierExpressions) {
return value;
}
else {
return emitTempVariableAssignment(value, location);
}
}
}
File diff suppressed because it is too large Load Diff
+100
View File
@@ -0,0 +1,100 @@
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/*@internal*/
namespace ts {
export function transformES7(context: TransformationContext) {
const { hoistVariableDeclaration } = context;
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
return visitEachChild(node, visitor, context);
}
function visitor(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.ES7) {
return visitorWorker(node);
}
else if (node.transformFlags & TransformFlags.ContainsES7) {
return visitEachChild(node, visitor, context);
}
else {
return node;
}
}
function visitorWorker(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.BinaryExpression:
return visitBinaryExpression(<BinaryExpression>node);
default:
Debug.failBadSyntaxKind(node);
return visitEachChild(node, visitor, context);
}
}
function visitBinaryExpression(node: BinaryExpression): Expression {
// We are here because ES7 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) {
let target: Expression;
let value: Expression;
if (isElementAccessExpression(left)) {
// Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)`
const expressionTemp = createTempVariable();
hoistVariableDeclaration(expressionTemp);
const argumentExpressionTemp = createTempVariable();
hoistVariableDeclaration(argumentExpressionTemp);
target = createElementAccess(
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
createAssignment(argumentExpressionTemp, left.argumentExpression, /*location*/ left.argumentExpression),
/*location*/ left
);
value = createElementAccess(
expressionTemp,
argumentExpressionTemp,
/*location*/ left
);
}
else if (isPropertyAccessExpression(left)) {
// Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)`
const expressionTemp = createTempVariable();
hoistVariableDeclaration(expressionTemp);
target = createPropertyAccess(
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
left.name,
/*location*/ left
);
value = createPropertyAccess(
expressionTemp,
left.name,
/*location*/ left
);
}
else {
// Transforms `a **= b` into `a = Math.pow(a, b)`
target = left;
value = left;
}
return createAssignment(target, createMathPow(value, right, /*location*/ node), /*location*/ node);
}
else if (node.operatorToken.kind === SyntaxKind.AsteriskAsteriskToken) {
// Transforms `a ** b` into `Math.pow(a, b)`
return createMathPow(left, right, /*location*/ node);
}
else {
Debug.failBadSyntaxKind(node);
return visitEachChild(node, visitor, context);
}
}
}
}
+490
View File
@@ -0,0 +1,490 @@
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/*@internal*/
namespace ts {
const entities: Map<number> = createEntitiesMap();
export function transformJsx(context: TransformationContext) {
const compilerOptions = context.getCompilerOptions();
return transformSourceFile;
/**
* Transform JSX-specific syntax in a SourceFile.
*
* @param node A SourceFile node.
*/
function transformSourceFile(node: SourceFile) {
return visitEachChild(node, visitor, context);
}
function visitor(node: Node): VisitResult<Node> {
if (node.transformFlags & TransformFlags.Jsx) {
return visitorWorker(node);
}
else if (node.transformFlags & TransformFlags.ContainsJsx) {
return visitEachChild(node, visitor, context);
}
else {
return node;
}
}
function visitorWorker(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.JsxElement:
return visitJsxElement(<JsxElement>node);
case SyntaxKind.JsxSelfClosingElement:
return visitJsxSelfClosingElement(<JsxSelfClosingElement>node);
default:
Debug.failBadSyntaxKind(node);
return undefined;
}
}
function transformJsxChildToExpression(node: JsxChild): Expression {
switch (node.kind) {
case SyntaxKind.JsxText:
return visitJsxText(<JsxText>node);
case SyntaxKind.JsxExpression:
return visitJsxExpression(<JsxExpression>node);
case SyntaxKind.JsxElement:
return visitJsxElement(<JsxElement>node);
case SyntaxKind.JsxSelfClosingElement:
return visitJsxSelfClosingElement(<JsxSelfClosingElement>node);
default:
Debug.failBadSyntaxKind(node);
return undefined;
}
}
function visitJsxElement(node: JsxElement) {
return visitJsxOpeningLikeElement(node.openingElement, node.children);
}
function visitJsxSelfClosingElement(node: JsxSelfClosingElement) {
return visitJsxOpeningLikeElement(node, /*children*/ undefined);
}
function visitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[]) {
const tagName = getTagName(node);
let objectProperties: Expression;
const attrs = node.attributes;
if (attrs.length === 0) {
// When there are no attributes, React wants "null"
objectProperties = createNull();
}
else {
// Map spans of JsxAttribute nodes into object literals and spans
// of JsxSpreadAttribute nodes into expressions.
const segments = flatten(
spanMap(attrs, isJsxSpreadAttribute, (attrs, isSpread) => isSpread
? map(attrs, transformJsxSpreadAttributeToExpression)
: createObjectLiteral(map(attrs, transformJsxAttributeToObjectLiteralElement))
)
);
if (isJsxSpreadAttribute(attrs[0])) {
// We must always emit at least one object literal before a spread
// argument.
segments.unshift(createObjectLiteral());
}
// Either emit one big object literal (no spread attribs), or
// a call to React.__spread
objectProperties = singleOrUndefined(segments)
|| createJsxSpread(compilerOptions.reactNamespace, segments);
}
return createJsxCreateElement(
compilerOptions.reactNamespace,
tagName,
objectProperties,
filter(map(children, transformJsxChildToExpression), isDefined)
);
}
function transformJsxSpreadAttributeToExpression(node: JsxSpreadAttribute) {
return visitNode(node.expression, visitor, isExpression);
}
function transformJsxAttributeToObjectLiteralElement(node: JsxAttribute) {
const name = getAttributeName(node);
const expression = node.initializer
? visitNode(node.initializer, visitor, isExpression)
: createLiteral(true);
return createPropertyAssignment(name, expression);
}
function visitJsxText(node: JsxText) {
const text = getTextOfNode(node, /*includeTrivia*/ true);
let parts: Expression[];
let firstNonWhitespace = 0;
let lastNonWhitespace = -1;
// JSX trims whitespace at the end and beginning of lines, except that the
// start/end of a tag is considered a start/end of a line only if that line is
// on the same line as the closing tag. See examples in
// tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx
for (let i = 0; i < text.length; i++) {
const c = text.charCodeAt(i);
if (isLineBreak(c)) {
if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) {
const part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1);
if (!parts) {
parts = [];
}
// We do not escape the string here as that is handled by the printer
// when it emits the literal. We do, however, need to decode JSX entities.
parts.push(createLiteral(decodeEntities(part)));
}
firstNonWhitespace = -1;
}
else if (!isWhiteSpace(c)) {
lastNonWhitespace = i;
if (firstNonWhitespace === -1) {
firstNonWhitespace = i;
}
}
}
if (firstNonWhitespace !== -1) {
const part = text.substr(firstNonWhitespace);
if (!parts) {
parts = [];
}
// We do not escape the string here as that is handled by the printer
// when it emits the literal. We do, however, need to decode JSX entities.
parts.push(createLiteral(decodeEntities(part)));
}
if (parts) {
return reduceLeft(parts, aggregateJsxTextParts);
}
return undefined;
}
/**
* Aggregates two expressions by interpolating them with a whitespace literal.
*/
function aggregateJsxTextParts(left: Expression, right: Expression) {
return createAdd(createAdd(left, createLiteral(" ")), right);
}
/**
* Decodes JSX entities.
*/
function decodeEntities(text: string) {
return text.replace(/&(\w+);/g, function(s: any, m: string) {
if (entities[m] !== undefined) {
return String.fromCharCode(entities[m]);
}
else {
return s;
}
});
}
function getTagName(node: JsxElement | JsxOpeningLikeElement): Expression {
if (node.kind === SyntaxKind.JsxElement) {
return getTagName((<JsxElement>node).openingElement);
}
else {
const name = (<JsxOpeningLikeElement>node).tagName;
if (isIdentifier(name) && isIntrinsicJsxName(name.text)) {
return createLiteral(name.text);
}
else {
return createExpressionFromEntityName(name);
}
}
}
/**
* Emit an attribute name, which is quoted if it needs to be quoted. Because
* these emit into an object literal property name, we don't need to be worried
* about keywords, just non-identifier characters
*/
function getAttributeName(node: JsxAttribute): StringLiteral | Identifier {
const name = node.name;
if (/^[A-Za-z_]\w*$/.test(name.text)) {
return createLiteral(name.text);
}
else {
return name;
}
}
function visitJsxExpression(node: JsxExpression) {
return visitNode(node.expression, visitor, isExpression);
}
}
function createEntitiesMap(): Map<number> {
return {
"quot": 0x0022,
"amp": 0x0026,
"apos": 0x0027,
"lt": 0x003C,
"gt": 0x003E,
"nbsp": 0x00A0,
"iexcl": 0x00A1,
"cent": 0x00A2,
"pound": 0x00A3,
"curren": 0x00A4,
"yen": 0x00A5,
"brvbar": 0x00A6,
"sect": 0x00A7,
"uml": 0x00A8,
"copy": 0x00A9,
"ordf": 0x00AA,
"laquo": 0x00AB,
"not": 0x00AC,
"shy": 0x00AD,
"reg": 0x00AE,
"macr": 0x00AF,
"deg": 0x00B0,
"plusmn": 0x00B1,
"sup2": 0x00B2,
"sup3": 0x00B3,
"acute": 0x00B4,
"micro": 0x00B5,
"para": 0x00B6,
"middot": 0x00B7,
"cedil": 0x00B8,
"sup1": 0x00B9,
"ordm": 0x00BA,
"raquo": 0x00BB,
"frac14": 0x00BC,
"frac12": 0x00BD,
"frac34": 0x00BE,
"iquest": 0x00BF,
"Agrave": 0x00C0,
"Aacute": 0x00C1,
"Acirc": 0x00C2,
"Atilde": 0x00C3,
"Auml": 0x00C4,
"Aring": 0x00C5,
"AElig": 0x00C6,
"Ccedil": 0x00C7,
"Egrave": 0x00C8,
"Eacute": 0x00C9,
"Ecirc": 0x00CA,
"Euml": 0x00CB,
"Igrave": 0x00CC,
"Iacute": 0x00CD,
"Icirc": 0x00CE,
"Iuml": 0x00CF,
"ETH": 0x00D0,
"Ntilde": 0x00D1,
"Ograve": 0x00D2,
"Oacute": 0x00D3,
"Ocirc": 0x00D4,
"Otilde": 0x00D5,
"Ouml": 0x00D6,
"times": 0x00D7,
"Oslash": 0x00D8,
"Ugrave": 0x00D9,
"Uacute": 0x00DA,
"Ucirc": 0x00DB,
"Uuml": 0x00DC,
"Yacute": 0x00DD,
"THORN": 0x00DE,
"szlig": 0x00DF,
"agrave": 0x00E0,
"aacute": 0x00E1,
"acirc": 0x00E2,
"atilde": 0x00E3,
"auml": 0x00E4,
"aring": 0x00E5,
"aelig": 0x00E6,
"ccedil": 0x00E7,
"egrave": 0x00E8,
"eacute": 0x00E9,
"ecirc": 0x00EA,
"euml": 0x00EB,
"igrave": 0x00EC,
"iacute": 0x00ED,
"icirc": 0x00EE,
"iuml": 0x00EF,
"eth": 0x00F0,
"ntilde": 0x00F1,
"ograve": 0x00F2,
"oacute": 0x00F3,
"ocirc": 0x00F4,
"otilde": 0x00F5,
"ouml": 0x00F6,
"divide": 0x00F7,
"oslash": 0x00F8,
"ugrave": 0x00F9,
"uacute": 0x00FA,
"ucirc": 0x00FB,
"uuml": 0x00FC,
"yacute": 0x00FD,
"thorn": 0x00FE,
"yuml": 0x00FF,
"OElig": 0x0152,
"oelig": 0x0153,
"Scaron": 0x0160,
"scaron": 0x0161,
"Yuml": 0x0178,
"fnof": 0x0192,
"circ": 0x02C6,
"tilde": 0x02DC,
"Alpha": 0x0391,
"Beta": 0x0392,
"Gamma": 0x0393,
"Delta": 0x0394,
"Epsilon": 0x0395,
"Zeta": 0x0396,
"Eta": 0x0397,
"Theta": 0x0398,
"Iota": 0x0399,
"Kappa": 0x039A,
"Lambda": 0x039B,
"Mu": 0x039C,
"Nu": 0x039D,
"Xi": 0x039E,
"Omicron": 0x039F,
"Pi": 0x03A0,
"Rho": 0x03A1,
"Sigma": 0x03A3,
"Tau": 0x03A4,
"Upsilon": 0x03A5,
"Phi": 0x03A6,
"Chi": 0x03A7,
"Psi": 0x03A8,
"Omega": 0x03A9,
"alpha": 0x03B1,
"beta": 0x03B2,
"gamma": 0x03B3,
"delta": 0x03B4,
"epsilon": 0x03B5,
"zeta": 0x03B6,
"eta": 0x03B7,
"theta": 0x03B8,
"iota": 0x03B9,
"kappa": 0x03BA,
"lambda": 0x03BB,
"mu": 0x03BC,
"nu": 0x03BD,
"xi": 0x03BE,
"omicron": 0x03BF,
"pi": 0x03C0,
"rho": 0x03C1,
"sigmaf": 0x03C2,
"sigma": 0x03C3,
"tau": 0x03C4,
"upsilon": 0x03C5,
"phi": 0x03C6,
"chi": 0x03C7,
"psi": 0x03C8,
"omega": 0x03C9,
"thetasym": 0x03D1,
"upsih": 0x03D2,
"piv": 0x03D6,
"ensp": 0x2002,
"emsp": 0x2003,
"thinsp": 0x2009,
"zwnj": 0x200C,
"zwj": 0x200D,
"lrm": 0x200E,
"rlm": 0x200F,
"ndash": 0x2013,
"mdash": 0x2014,
"lsquo": 0x2018,
"rsquo": 0x2019,
"sbquo": 0x201A,
"ldquo": 0x201C,
"rdquo": 0x201D,
"bdquo": 0x201E,
"dagger": 0x2020,
"Dagger": 0x2021,
"bull": 0x2022,
"hellip": 0x2026,
"permil": 0x2030,
"prime": 0x2032,
"Prime": 0x2033,
"lsaquo": 0x2039,
"rsaquo": 0x203A,
"oline": 0x203E,
"frasl": 0x2044,
"euro": 0x20AC,
"image": 0x2111,
"weierp": 0x2118,
"real": 0x211C,
"trade": 0x2122,
"alefsym": 0x2135,
"larr": 0x2190,
"uarr": 0x2191,
"rarr": 0x2192,
"darr": 0x2193,
"harr": 0x2194,
"crarr": 0x21B5,
"lArr": 0x21D0,
"uArr": 0x21D1,
"rArr": 0x21D2,
"dArr": 0x21D3,
"hArr": 0x21D4,
"forall": 0x2200,
"part": 0x2202,
"exist": 0x2203,
"empty": 0x2205,
"nabla": 0x2207,
"isin": 0x2208,
"notin": 0x2209,
"ni": 0x220B,
"prod": 0x220F,
"sum": 0x2211,
"minus": 0x2212,
"lowast": 0x2217,
"radic": 0x221A,
"prop": 0x221D,
"infin": 0x221E,
"ang": 0x2220,
"and": 0x2227,
"or": 0x2228,
"cap": 0x2229,
"cup": 0x222A,
"int": 0x222B,
"there4": 0x2234,
"sim": 0x223C,
"cong": 0x2245,
"asymp": 0x2248,
"ne": 0x2260,
"equiv": 0x2261,
"le": 0x2264,
"ge": 0x2265,
"sub": 0x2282,
"sup": 0x2283,
"nsub": 0x2284,
"sube": 0x2286,
"supe": 0x2287,
"oplus": 0x2295,
"otimes": 0x2297,
"perp": 0x22A5,
"sdot": 0x22C5,
"lceil": 0x2308,
"rceil": 0x2309,
"lfloor": 0x230A,
"rfloor": 0x230B,
"lang": 0x2329,
"rang": 0x232A,
"loz": 0x25CA,
"spades": 0x2660,
"clubs": 0x2663,
"hearts": 0x2665,
"diams": 0x2666
};
}
}
+13
View File
@@ -0,0 +1,13 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/*@internal*/
namespace ts {
export function transformES6Module(context: TransformationContext) {
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
return node;
}
}
}
+759
View File
@@ -0,0 +1,759 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/*@internal*/
namespace ts {
export function transformModule(context: TransformationContext) {
const transformModuleDelegates: Map<(node: SourceFile) => SourceFile> = {
[ModuleKind.None]: transformCommonJSModule,
[ModuleKind.CommonJS]: transformCommonJSModule,
[ModuleKind.AMD]: transformAMDModule,
[ModuleKind.UMD]: transformUMDModule,
};
const {
startLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration,
setNodeEmitFlags
} = context;
const compilerOptions = context.getCompilerOptions();
const resolver = context.getEmitResolver();
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
const previousExpressionSubstitution = context.expressionSubstitution;
context.enableExpressionSubstitution(SyntaxKind.Identifier);
context.expressionSubstitution = substituteExpression;
let currentSourceFile: SourceFile;
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
let exportSpecifiers: Map<ExportSpecifier[]>;
let exportEquals: ExportAssignment;
let hasExportStars: boolean;
return transformSourceFile;
/**
* Transforms the module aspects of a SourceFile.
*
* @param node The SourceFile node.
*/
function transformSourceFile(node: SourceFile) {
if (isExternalModule(node) || compilerOptions.isolatedModules) {
currentSourceFile = node;
// Collect information about the external module.
({ externalImports, exportSpecifiers, exportEquals, hasExportStars } = collectExternalModuleInfo(node, resolver));
// Perform the transformation.
const updated = transformModuleDelegates[moduleKind](node);
currentSourceFile = undefined;
externalImports = undefined;
exportSpecifiers = undefined;
exportEquals = undefined;
hasExportStars = false;
return updated;
}
return node;
}
/**
* Transforms a SourceFile into a CommonJS module.
*
* @param node The SourceFile node.
*/
function transformCommonJSModule(node: SourceFile) {
startLexicalEnvironment();
return setNodeEmitFlags(
updateSourceFile(
node,
[
...visitNodes(node.statements, visitor, isStatement),
...(endLexicalEnvironment() || []),
tryCreateExportEquals(/*emitAsReturn*/ false)
]
),
hasExportStars ? NodeEmitFlags.EmitExportStar : 0
);
}
/**
* Transforms a SourceFile into an AMD module.
*
* @param node The SourceFile node.
*/
function transformAMDModule(node: SourceFile) {
const define = createIdentifier("define");
const moduleName = node.moduleName ? createLiteral(node.moduleName) : undefined;
return transformAsynchronousModule(node, define, moduleName, /*includeNonAmdDependencies*/ true);
}
/**
* Transforms a SourceFile into a UMD module.
*
* @param node The SourceFile node.
*/
function transformUMDModule(node: SourceFile) {
const define = createIdentifier("define");
setNodeEmitFlags(define, NodeEmitFlags.UMDDefine);
return transformAsynchronousModule(node, define, /*moduleName*/ undefined, /*includeNonAmdDependencies*/ false);
}
/**
* Transforms a SourceFile into an AMD or UMD module.
*
* @param node The SourceFile node.
* @param define The expression used to define the module.
* @param moduleName An expression for the module name, if available.
* @param includeNonAmdDependencies A value indicating whether to incldue any non-AMD dependencies.
*/
function transformAsynchronousModule(node: SourceFile, define: Expression, moduleName: Expression, includeNonAmdDependencies: boolean) {
// Start the lexical environment for the module body.
startLexicalEnvironment();
const { importModuleNames, importAliasNames } = collectAsynchronousDependencies(node, includeNonAmdDependencies);
// Create an updated SourceFile:
//
// define(moduleName?, ["module1", "module2"], function ...
return updateSourceFile(node, [
createStatement(
createCall(
define,
flatten([
// Add the module name (if provided).
moduleName,
// Add the dependency array argument:
//
// ["module1", "module2", ...]
createArrayLiteral(importModuleNames),
// Add the module body function argument:
//
// function (module1, module2) ...
createFunctionExpression(
/*asteriskToken*/ undefined,
/*name*/ undefined,
importAliasNames,
setNodeEmitFlags(
setMultiLine(
createBlock(
flatten([
// Visit each statement of the module body.
...visitNodes(node.statements, visitor, isStatement),
// End the lexical environment for the module body
// and merge any new lexical declarations.
...(endLexicalEnvironment() || []),
// Append the 'export =' statement if provided.
tryCreateExportEquals(/*emitAsReturn*/ true)
])
),
/*multiLine*/ true
),
// If we have any `export * from ...` declarations
// we need to inform the emitter to add the __export helper.
hasExportStars ? NodeEmitFlags.EmitExportStar : 0
)
)
])
)
)
]);
}
function tryCreateExportEquals(emitAsReturn: boolean) {
if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) {
if (emitAsReturn) {
return createReturn(exportEquals.expression);
}
else {
return createStatement(
createAssignment(
createPropertyAccess(
createIdentifier("module"),
"exports"
),
exportEquals.expression
)
);
}
}
return undefined;
}
/**
* Visits a node at the top level of the source file.
*
* @param node The 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.ExportDeclaration:
return visitExportDeclaration(<ExportDeclaration>node);
case SyntaxKind.ExportAssignment:
return visitExportAssignment(<ExportAssignment>node);
case SyntaxKind.VariableStatement:
return visitVariableStatement(<VariableStatement>node);
case SyntaxKind.FunctionDeclaration:
return visitFunctionDeclaration(<FunctionDeclaration>node);
case SyntaxKind.ClassDeclaration:
return visitClassDeclaration(<ClassDeclaration>node);
default:
// This visitor does not descend into the tree, as export/import statements
// are only transformed at the top level of a file.
return node;
}
}
/**
* Visits an ImportDeclaration node.
*
* @param node The ImportDeclaration node.
*/
function visitImportDeclaration(node: ImportDeclaration): VisitResult<Statement> {
if (!contains(externalImports, node)) {
return undefined;
}
const statements: Statement[] = [];
const namespaceDeclaration = getNamespaceDeclarationNode(node);
if (moduleKind !== ModuleKind.AMD) {
if (!node.importClause) {
// import "mod";
addNode(statements,
createStatement(
createRequireCall(node),
/*location*/ node
)
);
}
else {
const variables: VariableDeclaration[] = [];
if (namespaceDeclaration && !isDefaultImport(node)) {
// import * as n from "mod";
addNode(variables,
createVariableDeclaration(
getSynthesizedClone(namespaceDeclaration.name),
createRequireCall(node)
)
);
}
else {
// import d from "mod";
// import { x, y } from "mod";
// import d, { x, y } from "mod";
// import d, * as n from "mod";
addNode(variables,
createVariableDeclaration(
getGeneratedNameForNode(node),
createRequireCall(node)
)
);
if (namespaceDeclaration && isDefaultImport(node)) {
addNode(variables,
createVariableDeclaration(
getSynthesizedClone(namespaceDeclaration.name),
getGeneratedNameForNode(node)
)
);
}
}
addNode(statements,
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(variables),
/*location*/ node
)
);
}
}
else if (namespaceDeclaration && isDefaultImport(node)) {
// import d, * as n from "mod";
addNode(statements,
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
getSynthesizedClone(namespaceDeclaration.name),
getGeneratedNameForNode(node),
/*location*/ node
)
])
)
);
}
addExportImportAssignments(statements, node);
return statements;
}
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration): VisitResult<Statement> {
if (!contains(externalImports, node)) {
return undefined;
}
const statements: Statement[] = [];
if (moduleKind !== ModuleKind.AMD) {
if (hasModifier(node, ModifierFlags.Export)) {
addNode(statements,
createStatement(
createExportAssignment(
node.name,
createRequireCall(node)
),
/*location*/ node
)
);
}
else {
addNode(statements,
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
getSynthesizedClone(node.name),
createRequireCall(node),
/*location*/ node
)
])
)
);
}
}
else {
if (hasModifier(node, ModifierFlags.Export)) {
addNode(statements,
createStatement(
createExportAssignment(node.name, node.name),
/*location*/ node
)
);
}
}
addExportImportAssignments(statements, node);
return statements;
}
function visitExportDeclaration(node: ExportDeclaration): VisitResult<Statement> {
if (!contains(externalImports, node)) {
return undefined;
}
const generatedName = getGeneratedNameForNode(node);
if (node.exportClause) {
const statements: Statement[] = [];
// export { x, y } from "mod";
if (moduleKind !== ModuleKind.AMD) {
addNode(statements,
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
generatedName,
createRequireCall(node),
/*location*/ node
)
])
)
);
}
for (const specifier of node.exportClause.elements) {
if (resolver.isValueAliasDeclaration(specifier)) {
const exportedValue = createPropertyAccess(
generatedName,
specifier.propertyName || specifier.name
);
addNode(statements,
createStatement(
createExportAssignment(specifier.name, exportedValue),
/*location*/ specifier
)
);
}
}
return statements;
}
else {
// export * from "mod";
return createStatement(
createCall(
createIdentifier("__export"),
[
moduleKind !== ModuleKind.AMD
? createRequireCall(node)
: generatedName
]
),
/*location*/ node
);
}
}
function visitExportAssignment(node: ExportAssignment): VisitResult<Statement> {
if (!node.isExportEquals && resolver.isValueAliasDeclaration(node)) {
const statements: Statement[] = [];
addExportDefault(statements, node.expression, /*location*/ node);
return statements;
}
return undefined;
}
function addExportDefault(statements: Statement[], expression: Expression, location: TextRange): void {
addNode(statements, tryCreateExportDefaultCompat());
addNode(statements,
createStatement(
createExportAssignment(
createIdentifier("default"),
expression
),
location
)
);
}
function tryCreateExportDefaultCompat(): Statement {
const original = getOriginalNode(currentSourceFile);
Debug.assert(original.kind === SyntaxKind.SourceFile);
if (!(<SourceFile>original).symbol.exports["___esModule"]) {
if (languageVersion === ScriptTarget.ES3) {
return createStatement(
createExportAssignment(
createIdentifier("__esModule"),
createLiteral(true)
)
);
}
else {
return createStatement(
createObjectDefineProperty(
createIdentifier("exports"),
createLiteral("_esModule"),
{ value: createLiteral(true) }
)
);
}
}
}
function addExportImportAssignments(statements: Statement[], node: Node) {
const names = reduceEachChild(node, collectExportMembers, []);
for (const name of names) {
addExportMemberAssignments(statements, name);
}
}
function collectExportMembers(names: Identifier[], node: Node): Identifier[] {
if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node) && isDeclaration(node)) {
const name = node.name;
if (isIdentifier(name)) {
names.push(name);
}
}
return reduceEachChild(node, collectExportMembers, names);
}
function addExportMemberAssignments(statements: Statement[], name: Identifier): void {
if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
for (const specifier of exportSpecifiers[name.text]) {
addNode(statements,
createStatement(
createExportAssignment(specifier.name, name),
/*location*/ specifier.name
)
);
}
}
}
function visitVariableStatement(node: VariableStatement): VisitResult<Statement> {
const variables = getInitializedVariables(node.declarationList);
if (variables.length === 0) {
// elide statement if there are no initialized variables
return undefined;
}
return createStatement(
inlineExpressions(
map(variables, transformInitializedVariable)
)
);
}
function transformInitializedVariable(node: VariableDeclaration): Expression {
const name = node.name;
if (isBindingPattern(name)) {
return flattenVariableDestructuringToExpression(
node,
hoistVariableDeclaration,
getModuleMemberName,
visitor
);
}
else {
return createAssignment(
getModuleMemberName(name),
visitNode(node.initializer, visitor, isExpression)
);
}
}
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
const statements: Statement[] = [];
if (node.name) {
if (hasModifier(node, ModifierFlags.Export)) {
addNode(statements,
createFunctionDeclaration(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
node.name,
node.parameters,
node.body,
/*location*/ node
)
);
if (hasModifier(node, ModifierFlags.Default)) {
addExportDefault(statements, getSynthesizedClone(node.name), /*location*/ node);
}
}
else {
addNode(statements, node);
}
addExportMemberAssignments(statements, node.name);
}
else {
Debug.assert(hasModifier(node, ModifierFlags.Default));
addExportDefault(statements,
createFunctionExpression(
/*asteriskToken*/ undefined,
/*name*/ undefined,
node.parameters,
node.body,
/*location*/ node
),
/*location*/ node
);
}
return statements;
}
function visitClassDeclaration(node: ClassDeclaration): VisitResult<Statement> {
const statements: Statement[] = [];
if (node.name) {
if (hasModifier(node, ModifierFlags.Export)) {
addNode(statements,
createClassDeclaration(
/*modifiers*/ undefined,
node.name,
node.heritageClauses,
node.members,
/*location*/ node
)
);
if (hasModifier(node, ModifierFlags.Default)) {
addExportDefault(statements, getSynthesizedClone(node.name), /*location*/ node);
}
}
else {
addNode(statements, node);
}
addExportMemberAssignments(statements, node.name);
}
else {
Debug.assert(hasModifier(node, ModifierFlags.Default));
addExportDefault(statements,
createClassExpression(
/*name*/ undefined,
node.heritageClauses,
node.members,
/*location*/ node
),
/*location*/ node
);
}
return statements;
}
function substituteExpression(node: Expression) {
node = previousExpressionSubstitution(node);
if (isIdentifier(node)) {
return substituteExpressionIdentifier(node);
}
return node;
}
function substituteExpressionIdentifier(node: Identifier): Expression {
const container = resolver.getReferencedExportContainer(node);
if (container && container.kind === SyntaxKind.SourceFile) {
return createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(node),
/*location*/ node
);
}
return node;
}
function getModuleMemberName(name: Identifier) {
return createPropertyAccess(
createIdentifier("exports"),
name,
/*location*/ name
);
}
function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration) {
const moduleName = getExternalModuleName(importNode);
if (moduleName.kind === SyntaxKind.StringLiteral) {
return tryRenameExternalModule(<StringLiteral>moduleName)
|| getSynthesizedClone(<StringLiteral>moduleName);
}
return undefined;
}
/**
* Some bundlers (SystemJS builder) sometimes want to rename dependencies.
* Here we check if alternative name was provided for a given moduleName and return it if possible.
*/
function tryRenameExternalModule(moduleName: LiteralExpression) {
if (currentSourceFile.renamedDependencies && hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) {
return createLiteral(currentSourceFile.renamedDependencies[moduleName.text]);
}
return undefined;
}
function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): Identifier {
const namespaceDeclaration = getNamespaceDeclarationNode(node);
if (namespaceDeclaration && !isDefaultImport(node)) {
return createIdentifier(getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name));
}
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
return getGeneratedNameForNode(node);
}
if (node.kind === SyntaxKind.ExportDeclaration && (<ExportDeclaration>node).moduleSpecifier) {
return getGeneratedNameForNode(node);
}
}
function createRequireCall(importNode: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
const moduleName = getExternalModuleNameLiteral(importNode);
Debug.assert(isDefined(moduleName));
return createCall(
createIdentifier("require"),
[moduleName]
);
}
function createExportAssignment(name: Identifier, value: Expression) {
return createAssignment(
name.originalKeywordKind && languageVersion === ScriptTarget.ES3
? createElementAccess(
createIdentifier("exports"),
createLiteral(name.text)
)
: createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(name)
),
value
);
}
function collectAsynchronousDependencies(node: SourceFile, includeNonAmdDependencies: boolean) {
// An AMD define function has the following shape:
//
// define(id?, dependencies?, factory);
//
// This has the shape of the following:
//
// define(name, ["module1", "module2"], function (module1Alias) { ... }
//
// The location of the alias in the parameter list in the factory function needs to
// match the position of the module name in the dependency list.
//
// To ensure this is true in cases of modules with no aliases, e.g.:
//
// import "module"
//
// or
//
// /// <amd-dependency path= "a.css" />
//
// we need to add modules without alias names to the end of the dependencies list
const unaliasedModuleNames: Expression[] = [];
const aliasedModuleNames: Expression[] = [createLiteral("require"), createLiteral("exports") ];
const importAliasNames = [createParameter("require"), createParameter("exports")];
for (const amdDependency of node.amdDependencies) {
if (amdDependency.name) {
aliasedModuleNames.push(createLiteral(amdDependency.name));
importAliasNames.push(createParameter(createIdentifier(amdDependency.name)));
}
else {
unaliasedModuleNames.push(createLiteral(amdDependency.path));
}
}
for (const importNode of externalImports) {
// Find the name of the external module
const externalModuleName = getExternalModuleNameLiteral(importNode);
// Find the name of the module alias, if there is one
const importAliasName = getLocalNameForExternalImport(importNode);
if (includeNonAmdDependencies && importAliasName) {
aliasedModuleNames.push(externalModuleName);
importAliasNames.push(createParameter(importAliasName));
}
else {
unaliasedModuleNames.push(externalModuleName);
}
}
return {
importModuleNames: [
...unaliasedModuleNames,
...aliasedModuleNames
],
importAliasNames
};
}
function updateSourceFile(node: SourceFile, statements: Statement[]) {
const updated = getMutableClone(node);
updated.statements = createNodeArray(statements, node.statements);
return updated;
}
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+4
View File
@@ -777,4 +777,8 @@ namespace ts {
}
}
if (ts.sys.developmentMode && ts.sys.tryEnableSourceMapsForHost) {
ts.sys.tryEnableSourceMapsForHost();
}
ts.executeCommandLine(ts.sys.args);
+45 -51
View File
@@ -342,7 +342,7 @@ namespace ts {
// Synthesized list
SyntaxList,
NodeArrayNode,
// Enum value count
Count,
// Markers
@@ -373,18 +373,9 @@ namespace ts {
export const enum NodeFlags {
None = 0,
Export = 1 << 0, // Declarations
Ambient = 1 << 1, // Declarations
Public = 1 << 2, // Property/Method
Private = 1 << 3, // Property/Method
Protected = 1 << 4, // Property/Method
Static = 1 << 5, // Property/Method
Readonly = 1 << 6, // Property/Method
Abstract = 1 << 7, // Class/Method/ConstructSignature
Async = 1 << 8, // Property/Method/Function
Default = 1 << 9, // Function/Class (export default declaration)
Let = 1 << 10, // Variable declaration
Const = 1 << 11, // Variable declaration
Let = 1 << 0, // Variable declaration
Const = 1 << 1, // Variable declaration
NestedNamespace = 1 << 2, // Namespace declaration
Namespace = 1 << 12, // Namespace declaration
ExportContext = 1 << 13, // Export context (initialized by binding)
ContainsThis = 1 << 14, // Interface contains references to "this"
@@ -404,8 +395,6 @@ namespace ts {
ThisNodeOrAnySubNodesHasError = 1 << 28, // If this node or any of its children had an error
HasAggregatedChildData = 1 << 29, // If we've computed data from children and cached it in this node
Modifier = Export | Ambient | Public | Private | Protected | Static | Abstract | Default | Async,
AccessibilityModifier = Public | Private | Protected,
BlockScoped = Let | Const,
ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn,
@@ -418,6 +407,26 @@ namespace ts {
TypeExcludesFlags = YieldContext | AwaitContext,
}
export const enum ModifierFlags {
None = 0,
Export = 1 << 0, // Declarations
Ambient = 1 << 1, // Declarations
Public = 1 << 2, // Property/Method
Private = 1 << 3, // Property/Method
Protected = 1 << 4, // Property/Method
Static = 1 << 5, // Property/Method
Readonly = 1 << 6, // Property/Method
Abstract = 1 << 7, // Class/Method/ConstructSignature
Async = 1 << 8, // Property/Method/Function
Default = 1 << 9, // Function/Class (export default declaration)
Const = 1 << 11, // Variable declaration
HasComputedFlags = 1 << 31, // Modifier flags have been computed
AccessibilityModifier = Public | Private | Protected,
NonPublicAccessibilityModifier = Private | Protected,
}
export const enum JsxFlags {
None = 0,
/** An element from a named property of the JSX.IntrinsicElements interface */
@@ -443,10 +452,11 @@ namespace ts {
export interface Node extends TextRange {
kind: SyntaxKind;
flags: NodeFlags;
/* @internal */ modifierFlagsCache?: ModifierFlags;
/* @internal */ transformFlags?: TransformFlags;
/* @internal */ excludeTransformFlags?: TransformFlags;
decorators?: NodeArray<Decorator>; // Array of decorators (in document order)
modifiers?: ModifiersArray; // Array of modifiers
modifiers?: NodeArray<Modifier>; // Array of modifiers
/* @internal */ id?: number; // Unique id (used to look up NodeLinks)
parent?: Node; // Parent node (initialized by binding)
/* @internal */ original?: Node; // The original node if this is an updated node.
@@ -458,33 +468,10 @@ namespace ts {
/* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
}
export const enum ArrayKind {
NodeArray = 1,
ModifiersArray = 2,
}
export interface NodeArray<T extends Node> extends Array<T>, TextRange {
arrayKind: ArrayKind;
hasTrailingComma?: boolean;
}
/**
* A NodeArrayNode is a transient node used during transformations to indicate that more than
* one node will substitute a single node in the source. When the source is a NodeArray (as
* part of a call to `visitNodes`), the nodes of a NodeArrayNode will be spread into the
* result array. When the source is a Node (as part of a call to `visitNode`), the NodeArrayNode
* must be converted into a compatible node via the `lift` callback.
*/
/* @internal */
// @kind(SyntaxKind.NodeArrayNode)
export interface NodeArrayNode<T extends Node> extends Node {
nodes: NodeArray<T>;
}
export interface ModifiersArray extends NodeArray<Modifier> {
flags: number;
}
// @kind(SyntaxKind.AbstractKeyword)
// @kind(SyntaxKind.AsyncKeyword)
// @kind(SyntaxKind.ConstKeyword)
@@ -2091,8 +2078,8 @@ namespace ts {
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
HasSeenSuperCall = 0x00080000, // Set during the binding when encounter 'super'
ClassWithBodyScopedClassBinding = 0x00100000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00200000, // Binding to a decorated class inside of the class's body.
DecoratedClassWithSelfReference = 0x00100000, // Decorated class that contains a binding to itself inside of the class body.
SelfReferenceInDecoratedClass = 0x00200000, // Binding to a decorated class inside of the class's body.
}
/* @internal */
@@ -2751,6 +2738,8 @@ namespace ts {
/* @internal */
export const enum TransformFlags {
None = 0,
// Facts
// - Flags used to indicate that a node or subtree contains syntax that requires transformation.
TypeScript = 1 << 0,
@@ -2761,18 +2750,21 @@ namespace ts {
ContainsES7 = 1 << 5,
ES6 = 1 << 6,
ContainsES6 = 1 << 7,
DestructuringAssignment = 1 << 8,
// Markers
// - Flags used to indicate that a subtree contains a specific transformation.
ContainsDecorators = 1 << 8,
ContainsPropertyInitializer = 1 << 9,
ContainsLexicalThis = 1 << 10,
ContainsCapturedLexicalThis = 1 << 11,
ContainsDefaultValueAssignments = 1 << 12,
ContainsParameterPropertyAssignments = 1 << 13,
ContainsSpreadElementExpression = 1 << 14,
ContainsComputedPropertyName = 1 << 15,
ContainsBlockScopedBinding = 1 << 16,
ContainsDecorators = 1 << 9,
ContainsPropertyInitializer = 1 << 10,
ContainsLexicalThis = 1 << 11,
ContainsCapturedLexicalThis = 1 << 12,
ContainsDefaultValueAssignments = 1 << 13,
ContainsParameterPropertyAssignments = 1 << 14,
ContainsSpreadElementExpression = 1 << 15,
ContainsComputedPropertyName = 1 << 16,
ContainsBlockScopedBinding = 1 << 17,
HasComputedFlags = 1 << 31, // Transform flags have been computed.
// Assertions
// - Bitmasks that are used to assert facts about the syntax of a node and its subtree.
@@ -2784,7 +2776,7 @@ namespace ts {
// Scope Exclusions
// - Bitmasks that exclude flags from propagating out of a specific context
// into the subtree flags of their container.
NodeExcludes = TypeScript | Jsx | ES7 | ES6,
NodeExcludes = TypeScript | Jsx | ES7 | ES6 | DestructuringAssignment | HasComputedFlags,
ArrowFunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
FunctionExcludes = ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding,
ConstructorExcludes = ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding,
@@ -2808,6 +2800,8 @@ namespace ts {
AdviseOnEmitNode = 1 << 7, // The node printer should invoke the onBeforeEmitNode and onAfterEmitNode callbacks when printing this node.
IsNotEmittedNode = 1 << 8, // Is a node that is not emitted but whose comments should be preserved if possible.
EmitCommentsOfNotEmittedParent = 1 << 9, // Emits comments of missing parent nodes.
NoSubstitution = 1 << 10, // Disables further substitution of an expression.
CapturesThis = 1 << 11, // The function captures a lexical `this`
}
/** Additional context provided to `visitEachChild` */
+322 -63
View File
@@ -190,7 +190,7 @@ namespace ts {
// However, this node will be 'missing' in the sense that no actual source-code/tokens are
// contained within it.
export function nodeIsMissing(node: Node) {
if (!node) {
if (node === undefined) {
return true;
}
@@ -323,8 +323,7 @@ namespace ts {
export function isBlockScopedContainerTopLevel(node: Node): boolean {
return node.kind === SyntaxKind.SourceFile ||
node.kind === SyntaxKind.ModuleDeclaration ||
isFunctionLike(node) ||
isFunctionBlock(node);
isFunctionLike(node);
}
export function isGlobalScopeAugmentation(module: ModuleDeclaration): boolean {
@@ -347,30 +346,41 @@ namespace ts {
return false;
}
export function isBlockScope(node: Node, parentNode: Node) {
switch (node.kind) {
case SyntaxKind.SourceFile:
case SyntaxKind.CaseBlock:
case SyntaxKind.CatchClause:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.Constructor:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
return true;
case SyntaxKind.Block:
// function block is not considered block-scope container
// see comment in binder.ts: bind(...), case for SyntaxKind.Block
return parentNode && !isFunctionLike(parentNode);
}
return false;
}
// Gets the nearest enclosing block scope container that has the provided node
// as a descendant, that is not the provided node.
export function getEnclosingBlockScopeContainer(node: Node): Node {
let current = node.parent;
while (current) {
if (isFunctionLike(current)) {
if (isBlockScope(current, current.parent)) {
return current;
}
switch (current.kind) {
case SyntaxKind.SourceFile:
case SyntaxKind.CaseBlock:
case SyntaxKind.CatchClause:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
return current;
case SyntaxKind.Block:
// function block is not considered block-scope container
// see comment in binder.ts: bind(...), case for SyntaxKind.Block
if (!isFunctionLike(current.parent)) {
return current;
}
}
current = current.parent;
}
@@ -481,6 +491,25 @@ namespace ts {
return node;
}
export function getCombinedModifierFlags(node: Node): ModifierFlags {
node = walkUpBindingElementsAndPatterns(node);
let flags = getModifierFlags(node);
if (node.kind === SyntaxKind.VariableDeclaration) {
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
flags |= getModifierFlags(node);
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableStatement) {
flags |= getModifierFlags(node);
}
return flags;
}
// Returns the node flags for this node and all relevant parent nodes. This is done so that
// nodes like variable declarations and binding elements can returned a view of their flags
// that includes the modifiers from their container. i.e. flags like export/declare aren't
@@ -509,7 +538,8 @@ namespace ts {
}
export function isConst(node: Node): boolean {
return !!(getCombinedNodeFlags(node) & NodeFlags.Const);
return !!(getCombinedNodeFlags(node) & NodeFlags.Const)
|| !!(getCombinedModifierFlags(node) & ModifierFlags.Const);
}
export function isLet(node: Node): boolean {
@@ -925,19 +955,20 @@ namespace ts {
/**
* Determines whether a node is a property or element access expression for super.
*/
export function isSuperPropertyOrElementAccess(node: Node): node is (PropertyAccessExpression | ElementAccessExpression) {
export function isSuperProperty(node: Node): node is (PropertyAccessExpression | ElementAccessExpression) {
return (node.kind === SyntaxKind.PropertyAccessExpression
|| node.kind === SyntaxKind.ElementAccessExpression)
&& (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
}
/**
* Determines whether a node is a call to either `super`, or a super property or element access.
*/
export function isSuperPropertyCall(node: Node): node is CallExpression {
return node.kind === SyntaxKind.CallExpression
&& <boolean>isSuperProperty((<CallExpression>node).expression);
}
export function isSuperCall(node: Node): node is CallExpression {
return node.kind === SyntaxKind.CallExpression
&& ((<CallExpression>node).expression.kind === SyntaxKind.SuperKeyword
|| isSuperPropertyOrElementAccess((<CallExpression>node).expression));
&& (<CallExpression>node).expression.kind === SyntaxKind.SuperKeyword;
}
export function getEntityNameFromTypeNode(node: TypeNode): EntityName | Expression {
@@ -999,6 +1030,20 @@ namespace ts {
&& nodeCanBeDecorated(node);
}
export function nodeOrChildIsDecorated(node: Node): boolean {
return nodeIsDecorated(node) || childIsDecorated(node);
}
export function childIsDecorated(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
return forEach((<ClassDeclaration>node).members, nodeOrChildIsDecorated);
case SyntaxKind.MethodDeclaration:
case SyntaxKind.SetAccessor:
return forEach((<FunctionLikeDeclaration>node).parameters, nodeIsDecorated);
}
}
export function isPartOfExpression(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.SuperKeyword:
@@ -1203,6 +1248,23 @@ namespace ts {
}
}
export function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
return <ImportEqualsDeclaration>node;
}
const importClause = (<ImportDeclaration>node).importClause;
if (importClause && importClause.namedBindings && importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
return <NamespaceImport>importClause.namedBindings;
}
}
export function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
return node.kind === SyntaxKind.ImportDeclaration
&& (<ImportDeclaration>node).importClause
&& !!(<ImportDeclaration>node).importClause.name;
}
export function hasQuestionToken(node: Node) {
if (node) {
switch (node.kind) {
@@ -1338,7 +1400,7 @@ namespace ts {
export function isNodeDescendentOf(node: Node, ancestor: Node): boolean {
export function isNodeDescendantOf(node: Node, ancestor: Node): boolean {
while (node) {
if (node === ancestor) return true;
node = node.parent;
@@ -1348,7 +1410,7 @@ namespace ts {
export function isInAmbientContext(node: Node): boolean {
while (node) {
if (node.flags & NodeFlags.Ambient || (node.kind === SyntaxKind.SourceFile && (node as SourceFile).isDeclarationFile)) {
if (hasModifier(node, ModifierFlags.Ambient) || (node.kind === SyntaxKind.SourceFile && (node as SourceFile).isDeclarationFile)) {
return true;
}
node = node.parent;
@@ -1516,7 +1578,7 @@ namespace ts {
}
export function isAsyncFunctionLike(node: Node): boolean {
return isFunctionLike(node) && (node.flags & NodeFlags.Async) !== 0 && !isAccessor(node);
return isFunctionLike(node) && hasModifier(node, ModifierFlags.Async) && !isAccessor(node);
}
export function isStringOrNumericLiteral(kind: SyntaxKind): boolean {
@@ -1624,11 +1686,13 @@ namespace ts {
* @param parent The parent for the cloned node.
*/
export function cloneEntityName(node: EntityName, parent?: Node): EntityName {
const clone = cloneNode(node, node, node.flags, parent);
const clone = getMutableClone(node);
clone.parent = parent;
if (isQualifiedName(clone)) {
const { left, right } = clone;
clone.left = cloneEntityName(left, clone);
clone.right = cloneNode(right, right, right.flags, parent);
clone.right = getMutableClone(right);
clone.right.parent = clone;
}
return clone;
@@ -2232,7 +2296,14 @@ namespace ts {
return accessor && accessor.parameters.length > 0 && accessor.parameters[0].type;
}
export function getAllAccessorDeclarations(declarations: NodeArray<Declaration>, accessor: AccessorDeclaration) {
export interface AllAccessorDeclarations {
firstAccessor: AccessorDeclaration;
secondAccessor: AccessorDeclaration;
getAccessor: AccessorDeclaration;
setAccessor: AccessorDeclaration;
}
export function getAllAccessorDeclarations(declarations: NodeArray<Declaration>, accessor: AccessorDeclaration): AllAccessorDeclarations {
let firstAccessor: AccessorDeclaration;
let secondAccessor: AccessorDeclaration;
let getAccessor: AccessorDeclaration;
@@ -2252,7 +2323,7 @@ namespace ts {
else {
forEach(declarations, (member: Declaration) => {
if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor)
&& (member.flags & NodeFlags.Static) === (accessor.flags & NodeFlags.Static)) {
&& hasModifier(member, ModifierFlags.Static) === hasModifier(accessor, ModifierFlags.Static)) {
const memberName = getPropertyNameForPropertyNameNode(member.name);
const accessorName = getPropertyNameForPropertyNameNode(accessor.name);
if (memberName === accessorName) {
@@ -2485,21 +2556,49 @@ namespace ts {
return currentLineIndent;
}
export function modifierToFlag(token: SyntaxKind): NodeFlags {
switch (token) {
case SyntaxKind.StaticKeyword: return NodeFlags.Static;
case SyntaxKind.PublicKeyword: return NodeFlags.Public;
case SyntaxKind.ProtectedKeyword: return NodeFlags.Protected;
case SyntaxKind.PrivateKeyword: return NodeFlags.Private;
case SyntaxKind.AbstractKeyword: return NodeFlags.Abstract;
case SyntaxKind.ExportKeyword: return NodeFlags.Export;
case SyntaxKind.DeclareKeyword: return NodeFlags.Ambient;
case SyntaxKind.ConstKeyword: return NodeFlags.Const;
case SyntaxKind.DefaultKeyword: return NodeFlags.Default;
case SyntaxKind.AsyncKeyword: return NodeFlags.Async;
case SyntaxKind.ReadonlyKeyword: return NodeFlags.Readonly;
export function hasModifiers(node: Node) {
return getModifierFlags(node) !== ModifierFlags.None;
}
export function hasModifier(node: Node, flags: ModifierFlags) {
return (getModifierFlags(node) & flags) !== 0;
}
export function getModifierFlags(node: Node): ModifierFlags {
if (node.modifierFlagsCache & ModifierFlags.HasComputedFlags) {
return node.modifierFlagsCache & ~ModifierFlags.HasComputedFlags;
}
return 0;
let flags = ModifierFlags.None;
if (node.modifiers) {
for (const modifier of node.modifiers) {
flags |= modifierToFlag(modifier.kind);
}
}
if (node.flags & NodeFlags.NestedNamespace) {
flags |= ModifierFlags.Export;
}
node.modifierFlagsCache = flags | ModifierFlags.HasComputedFlags;
return flags;
}
export function modifierToFlag(token: SyntaxKind): ModifierFlags {
switch (token) {
case SyntaxKind.StaticKeyword: return ModifierFlags.Static;
case SyntaxKind.PublicKeyword: return ModifierFlags.Public;
case SyntaxKind.ProtectedKeyword: return ModifierFlags.Protected;
case SyntaxKind.PrivateKeyword: return ModifierFlags.Private;
case SyntaxKind.AbstractKeyword: return ModifierFlags.Abstract;
case SyntaxKind.ExportKeyword: return ModifierFlags.Export;
case SyntaxKind.DeclareKeyword: return ModifierFlags.Ambient;
case SyntaxKind.ConstKeyword: return ModifierFlags.Const;
case SyntaxKind.DefaultKeyword: return ModifierFlags.Default;
case SyntaxKind.AsyncKeyword: return ModifierFlags.Async;
case SyntaxKind.ReadonlyKeyword: return ModifierFlags.Readonly;
}
return ModifierFlags.None;
}
export function isAssignmentOperator(token: SyntaxKind): boolean {
@@ -2559,7 +2658,7 @@ namespace ts {
}
export function getLocalSymbolForExportDefault(symbol: Symbol) {
return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined;
return symbol && symbol.valueDeclaration && hasModifier(symbol.valueDeclaration, ModifierFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined;
}
export function hasJavaScriptFileExtension(fileName: string) {
@@ -2712,6 +2811,82 @@ namespace ts {
return carriageReturnLineFeed;
}
/**
* Tests whether a node and its subtree is simple enough to have its position
* information ignored when emitting source maps in a destructuring assignment.
*
* @param node The expression to test.
*/
export function isSimpleExpression(node: Expression): boolean {
return isSimpleExpressionWorker(node, 0);
}
function isSimpleExpressionWorker(node: Expression, depth: number): boolean {
if (depth <= 5) {
const kind = node.kind;
if (kind === SyntaxKind.StringLiteral
|| kind === SyntaxKind.NumericLiteral
|| kind === SyntaxKind.RegularExpressionLiteral
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral
|| kind === SyntaxKind.Identifier
|| kind === SyntaxKind.ThisKeyword
|| kind === SyntaxKind.SuperKeyword
|| kind === SyntaxKind.TrueKeyword
|| kind === SyntaxKind.FalseKeyword
|| kind === SyntaxKind.NullKeyword) {
return true;
}
else if (kind === SyntaxKind.PropertyAccessExpression) {
return isSimpleExpressionWorker((<PropertyAccessExpression>node).expression, depth + 1);
}
else if (kind === SyntaxKind.ElementAccessExpression) {
return isSimpleExpressionWorker((<ElementAccessExpression>node).expression, depth + 1)
&& isSimpleExpressionWorker((<ElementAccessExpression>node).argumentExpression, depth + 1);
}
else if (kind === SyntaxKind.PrefixUnaryExpression
|| kind === SyntaxKind.PostfixUnaryExpression) {
return isSimpleExpressionWorker((<PrefixUnaryExpression | PostfixUnaryExpression>node).operand, depth + 1);
}
else if (kind === SyntaxKind.BinaryExpression) {
return (<BinaryExpression>node).operatorToken.kind !== SyntaxKind.AsteriskAsteriskToken
&& isSimpleExpressionWorker((<BinaryExpression>node).left, depth + 1)
&& isSimpleExpressionWorker((<BinaryExpression>node).right, depth + 1);
}
else if (kind === SyntaxKind.ConditionalExpression) {
return isSimpleExpressionWorker((<ConditionalExpression>node).condition, depth + 1)
&& isSimpleExpressionWorker((<ConditionalExpression>node).whenTrue, depth + 1)
&& isSimpleExpressionWorker((<ConditionalExpression>node).whenFalse, depth + 1);
}
else if (kind === SyntaxKind.VoidExpression
|| kind === SyntaxKind.TypeOfExpression
|| kind === SyntaxKind.DeleteExpression) {
return isSimpleExpressionWorker((<VoidExpression | TypeOfExpression | DeleteExpression>node).expression, depth + 1);
}
else if (kind === SyntaxKind.ArrayLiteralExpression) {
return (<ArrayLiteralExpression>node).elements.length === 0;
}
else if (kind === SyntaxKind.ObjectLiteralExpression) {
return (<ObjectLiteralExpression>node).properties.length === 0;
}
}
return false;
}
export function formatSyntaxKind(kind: SyntaxKind): string {
const syntaxKindEnum = (<any>ts).SyntaxKind;
if (syntaxKindEnum) {
for (const name in syntaxKindEnum) {
if (syntaxKindEnum[name] === kind) {
return kind.toString() + " (" + name + ")";
}
}
}
else {
return kind.toString();
}
}
export const enum TextRangeCollapse {
CollapseToStart,
CollapseToEnd,
@@ -2727,6 +2902,90 @@ namespace ts {
: { pos: range.end, end: range.end };
}
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver) {
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
const exportSpecifiers: Map<ExportSpecifier[]> = {};
let exportEquals: ExportAssignment = undefined;
let hasExportStars = false;
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);
}
break;
case SyntaxKind.ImportEqualsDeclaration:
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(node)) {
// import x = require("mod") where x is referenced
externalImports.push(<ImportEqualsDeclaration>node);
}
break;
case SyntaxKind.ExportDeclaration:
if ((<ExportDeclaration>node).moduleSpecifier) {
if (!(<ExportDeclaration>node).exportClause) {
// export * from "mod"
externalImports.push(<ExportDeclaration>node);
hasExportStars = true;
}
else if (resolver.isValueAliasDeclaration(node)) {
// export { x, y } from "mod" where at least one export is a value symbol
externalImports.push(<ExportDeclaration>node);
}
}
else {
// export { x, y }
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
const name = (specifier.propertyName || specifier.name).text;
if (!exportSpecifiers[name]) {
exportSpecifiers[name] = [specifier];
}
else {
exportSpecifiers[name].push(specifier);
}
}
}
break;
case SyntaxKind.ExportAssignment:
if ((<ExportAssignment>node).isExportEquals && !exportEquals) {
// export = x
exportEquals = <ExportAssignment>node;
}
break;
}
}
return { externalImports, exportSpecifiers, exportEquals, hasExportStars };
}
export function copyPrologueDirectives(from: Statement[], to: Statement[]): number {
for (let i = 0; i < from.length; i++) {
if (isPrologueDirective(from[i])) {
addNode(to, from[i]);
}
else {
return i;
}
}
return from.length;
}
export function getInitializedVariables(node: VariableDeclarationList) {
return filter(node.declarations, isInitializedVariable);
}
function isInitializedVariable(node: VariableDeclaration) {
return node.initializer !== undefined;
}
// Node tests
//
// All node tests in the following list should *not* reference parent pointers so that
@@ -2735,11 +2994,8 @@ namespace ts {
// Node Arrays
export function isNodeArray<T extends Node>(array: T[]): array is NodeArray<T> {
return (<NodeArray<T>>array).arrayKind === ArrayKind.NodeArray;
}
export function isModifiersArray(array: Modifier[]): array is ModifiersArray {
return (<ModifiersArray>array).arrayKind === ArrayKind.ModifiersArray;
return array.hasOwnProperty("pos")
&& array.hasOwnProperty("end");
}
// Literals
@@ -2782,6 +3038,11 @@ namespace ts {
return node.kind === SyntaxKind.Identifier;
}
export function isGeneratedIdentifier(node: Node): node is Identifier {
// Using `>` here catches both `GeneratedIdentifierKind.None` and `undefined`.
return isIdentifier(node) && node.autoGenerateKind > GeneratedIdentifierKind.None;
}
// Keywords
export function isModifier(node: Node): node is Modifier {
@@ -2852,7 +3113,8 @@ namespace ts {
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.GetAccessor
|| kind === SyntaxKind.SetAccessor
|| kind === SyntaxKind.IndexSignature;
|| kind === SyntaxKind.IndexSignature
|| kind === SyntaxKind.SemicolonClassElement;
}
export function isObjectLiteralElement(node: Node): node is ObjectLiteralElement {
@@ -3180,6 +3442,10 @@ namespace ts {
return node.kind === SyntaxKind.JsxSpreadAttribute;
}
export function isJsxAttribute(node: Node): node is JsxAttribute {
return node.kind === SyntaxKind.JsxAttribute;
}
// Clauses
export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause {
@@ -3212,13 +3478,6 @@ namespace ts {
export function isEnumMember(node: Node): node is EnumMember {
return node.kind === SyntaxKind.EnumMember;
}
// Synthesized
export function isNodeArrayNode<T extends Node>(node: Node): node is NodeArrayNode<T> {
return node.kind === SyntaxKind.NodeArrayNode;
}
}
namespace ts {
@@ -3454,6 +3713,6 @@ namespace ts {
}
export function isParameterPropertyDeclaration(node: ParameterDeclaration): boolean {
return node.flags & NodeFlags.AccessibilityModifier && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent);
return hasModifier(node, ModifierFlags.AccessibilityModifier) && node.parent.kind === SyntaxKind.Constructor && isClassLike(node.parent.parent);
}
}
+120 -90
View File
@@ -3,7 +3,8 @@
/* @internal */
namespace ts {
export type OneOrMany<T extends Node> = T | NodeArrayNode<T>;
export type VisitResult<T extends Node> = T | T[];
/**
* Describes an edge of a Node, used when traversing a syntax tree.
*/
@@ -133,7 +134,7 @@ namespace ts {
{ name: "arguments", test: isExpression },
],
[SyntaxKind.NewExpression]: [
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForNew },
{ name: "typeArguments", test: isTypeNode },
{ name: "arguments", test: isExpression },
],
@@ -447,7 +448,7 @@ namespace ts {
* @param f The callback function
* @param initial The initial value to supply to the reduction.
*/
export function reduceEachChild<T>(node: Node, f: (memo: T, node: Node) => T, initial: T) {
export function reduceEachChild<T>(node: Node, f: (memo: T, node: Node) => T, initial: T): T {
if (node === undefined) {
return undefined;
}
@@ -477,7 +478,7 @@ namespace ts {
* @param optional An optional value indicating whether the Node is itself optional.
* @param lift An optional callback to execute to lift a NodeArrayNode into a valid Node.
*/
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => Node, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T {
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T {
return <T>visitNodeWorker(node, visitor, test, optional, lift, /*parenthesize*/ undefined, /*parentNode*/ undefined);
}
@@ -492,32 +493,38 @@ namespace ts {
* @param parenthesize A callback used to parenthesize the node if needed.
* @param parentNode A parentNode for the node.
*/
function visitNodeWorker(node: Node, visitor: (node: Node) => Node, test: (node: Node) => boolean, optional: boolean, lift: (node: NodeArray<Node>) => Node, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): Node {
function visitNodeWorker(node: Node, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional: boolean, lift: (node: Node[]) => Node, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): Node {
if (node === undefined) {
return undefined;
}
let visited = visitor(node);
const visited = visitor(node);
if (visited === node) {
return node;
}
if (visited !== undefined && isNodeArrayNode(visited)) {
visited = (lift || extractSingleNode)((<NodeArrayNode<Node>>visited).nodes);
}
if (parenthesize !== undefined && visited !== undefined) {
visited = parenthesize(visited, parentNode);
}
let visitedNode: Node;
if (visited === undefined) {
Debug.assert(optional, "Node not optional.");
if (!optional) {
Debug.failNotOptional();
}
return undefined;
}
else if (isArray(visited)) {
visitedNode = (lift || extractSingleNode)(visited);
}
else {
visitedNode = visited;
}
Debug.assert(test === undefined || test(visited), "Wrong node type after visit.");
aggregateTransformFlags(visited);
return visited;
if (parenthesize !== undefined) {
visitedNode = parenthesize(visitedNode, parentNode);
}
Debug.assertNode(visitedNode, test);
aggregateTransformFlags(visitedNode);
return visitedNode;
}
/**
@@ -529,7 +536,7 @@ namespace ts {
* @param start An optional value indicating the starting offset at which to start visiting.
* @param count An optional value indicating the maximum number of nodes to visit.
*/
export function visitNodes<T extends Node, TArray extends NodeArray<T>>(nodes: TArray, visitor: (node: Node) => Node, test: (node: Node) => boolean, start?: number, count?: number): TArray {
export function visitNodes<T extends Node, TArray extends NodeArray<T>>(nodes: TArray, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, start?: number, count?: number): TArray {
return <TArray>visitNodesWorker(nodes, visitor, test, /*parenthesize*/ undefined, /*parentNode*/ undefined, start, count);
}
@@ -542,12 +549,12 @@ namespace ts {
* @param start An optional value indicating the starting offset at which to start visiting.
* @param count An optional value indicating the maximum number of nodes to visit.
*/
function visitNodesWorker(nodes: NodeArray<Node>, visitor: (node: Node) => Node, test: (node: Node) => boolean, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node, start: number, count: number): NodeArray<Node> {
function visitNodesWorker(nodes: NodeArray<Node>, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node, start: number, count: number): NodeArray<Node> {
if (nodes === undefined) {
return undefined;
}
let updated: Node[];
let updated: NodeArray<Node>;
// Ensure start and count have valid values
const length = nodes.length;
@@ -559,9 +566,12 @@ namespace ts {
count = length - start;
}
// If we are not visiting all of the original nodes, we must always create a new array.
if (start > 0 || count < length) {
updated = [];
// If we are not visiting all of the original nodes, we must always create a new array.
// Since this is a fragment of a node array, we do not copy over the previous location
// and will only copy over `hasTrailingComma` if we are including the last element.
updated = createNodeArray<Node>([], /*location*/ undefined,
/*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length);
}
// Visit each original node.
@@ -571,20 +581,14 @@ namespace ts {
if (updated !== undefined || visited === undefined || visited !== node) {
if (updated === undefined) {
// Ensure we have a copy of `nodes`, up to the current index.
updated = nodes.slice(0, i);
updated = createNodeArray(nodes.slice(0, i), /*location*/ nodes, nodes.hasTrailingComma);
}
addNodeWorker(updated, visited, /*addOnNewLine*/ undefined, test, parenthesize, parentNode, /*isVisiting*/ visited !== node);
}
}
if (updated !== undefined) {
return isModifiersArray(nodes)
? createModifiersArray(updated, nodes)
: createNodeArray(updated, nodes, nodes.hasTrailingComma);
}
return nodes;
return updated || nodes;
}
/**
@@ -594,8 +598,8 @@ namespace ts {
* @param visitor The callback used to visit each child.
* @param context A lexical environment context for the visitor.
*/
export function visitEachChild<T extends Node>(node: T, visitor: (node: Node) => Node, context: LexicalEnvironment): T;
export function visitEachChild<T extends Node>(node: T & Map<any>, visitor: (node: Node) => Node, context: LexicalEnvironment): T {
export function visitEachChild<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, context: LexicalEnvironment): T;
export function visitEachChild<T extends Node>(node: T & Map<any>, visitor: (node: Node) => VisitResult<Node>, context: LexicalEnvironment): T {
if (node === undefined) {
return undefined;
}
@@ -610,17 +614,12 @@ namespace ts {
const edgeTraversalPath = nodeEdgeTraversalMap[node.kind];
if (edgeTraversalPath) {
let modifiers: NodeFlags;
for (const edge of edgeTraversalPath) {
const value = <Node | NodeArray<Node>>node[edge.name];
if (value !== undefined) {
let visited: Node | NodeArray<Node>;
if (isArray(value)) {
const visitedArray = visitNodesWorker(value, visitor, edge.test, edge.parenthesize, node, 0, value.length);
if (isModifiersArray(visitedArray)) {
modifiers = visitedArray.flags;
}
visited = visitedArray;
}
else {
@@ -629,13 +628,7 @@ namespace ts {
if (updated !== undefined || visited !== value) {
if (updated === undefined) {
updated = getMutableNode(node);
updated.flags &= ~NodeFlags.Modifier;
}
if (modifiers) {
updated.flags |= modifiers;
modifiers = undefined;
updated = getMutableClone(node);
}
if (visited !== value) {
@@ -670,9 +663,8 @@ namespace ts {
*
* @param to The destination array.
* @param from The source Node or NodeArrayNode.
* @param test The node test used to validate each node.
*/
export function addNode<T extends Node>(to: T[], from: OneOrMany<T>, startOnNewLine?: boolean) {
export function addNode<T extends Node>(to: T[], from: VisitResult<T>, startOnNewLine?: boolean): void {
addNodeWorker(to, from, startOnNewLine, /*test*/ undefined, /*parenthesize*/ undefined, /*parentNode*/ undefined, /*isVisiting*/ false);
}
@@ -681,38 +673,37 @@ namespace ts {
*
* @param to The destination NodeArray.
* @param from The source array of Node or NodeArrayNode.
* @param test The node test used to validate each node.
*/
export function addNodes<T extends Node>(to: T[], from: OneOrMany<T>[], startOnNewLine?: boolean) {
export function addNodes<T extends Node>(to: T[], from: VisitResult<T>[], startOnNewLine?: boolean): void {
addNodesWorker(to, from, startOnNewLine, /*test*/ undefined, /*parenthesize*/ undefined, /*parentNode*/ undefined, /*isVisiting*/ false);
}
function addNodeWorker(to: Node[], from: OneOrMany<Node>, startOnNewLine: boolean, test: (node: Node) => boolean, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node, isVisiting: boolean) {
function addNodeWorker(to: Node[], from: VisitResult<Node>, startOnNewLine: boolean, test: (node: Node) => boolean, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node, isVisiting: boolean): void {
if (to && from) {
if (isNodeArrayNode(from)) {
addNodesWorker(to, from.nodes, startOnNewLine, test, parenthesize, parentNode, isVisiting);
return;
if (isArray(from)) {
addNodesWorker(to, from, startOnNewLine, test, parenthesize, parentNode, isVisiting);
}
else {
const node = parenthesize !== undefined
? parenthesize(from, parentNode)
: from;
if (parenthesize !== undefined) {
from = parenthesize(from, parentNode);
Debug.assertNode(node, test);
if (startOnNewLine) {
node.startsOnNewLine = true;
}
if (isVisiting) {
aggregateTransformFlags(node);
}
to.push(node);
}
Debug.assert(test === undefined || test(from), "Wrong node type after visit.");
if (startOnNewLine) {
from.startsOnNewLine = true;
}
if (isVisiting) {
aggregateTransformFlags(from);
}
to.push(from);
}
}
function addNodesWorker(to: Node[], from: OneOrMany<Node>[], startOnNewLine: boolean, test: (node: Node) => boolean, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node, isVisiting: boolean) {
function addNodesWorker(to: Node[], from: VisitResult<Node>[], startOnNewLine: boolean, test: (node: Node) => boolean, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node, isVisiting: boolean): void {
if (to && from) {
for (const node of from) {
addNodeWorker(to, node, startOnNewLine, test, parenthesize, parentNode, isVisiting);
@@ -753,9 +744,9 @@ namespace ts {
* @param node The SourceFile node.
* @param declarations The generated lexical declarations.
*/
export function mergeSourceFileLexicalEnvironment(node: SourceFile, declarations: Statement[]) {
export function mergeSourceFileLexicalEnvironment(node: SourceFile, declarations: Statement[]): SourceFile {
if (declarations !== undefined && declarations.length) {
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
const mutableNode = getMutableClone(node);
mutableNode.statements = mergeStatements(mutableNode.statements, declarations);
return mutableNode;
}
@@ -769,10 +760,10 @@ namespace ts {
* @param node The ModuleDeclaration node.
* @param declarations The generated lexical declarations.
*/
export function mergeModuleDeclarationLexicalEnvironment(node: ModuleDeclaration, declarations: Statement[]) {
export function mergeModuleDeclarationLexicalEnvironment(node: ModuleDeclaration, declarations: Statement[]): ModuleDeclaration {
Debug.assert(node.body.kind === SyntaxKind.ModuleBlock);
if (declarations !== undefined && declarations.length) {
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
const mutableNode = getMutableClone(node);
mutableNode.body = mergeBlockLexicalEnvironment(<ModuleBlock>node.body, declarations);
return mutableNode;
}
@@ -786,10 +777,10 @@ namespace ts {
* @param node The function-like node.
* @param declarations The generated lexical declarations.
*/
function mergeFunctionLikeLexicalEnvironment(node: FunctionLikeDeclaration, declarations: Statement[]) {
function mergeFunctionLikeLexicalEnvironment(node: FunctionLikeDeclaration, declarations: Statement[]): FunctionLikeDeclaration {
Debug.assert(node.body !== undefined);
if (declarations !== undefined && declarations.length) {
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
const mutableNode = getMutableClone(node);
mutableNode.body = mergeConciseBodyLexicalEnvironment(mutableNode.body, declarations);
return mutableNode;
}
@@ -803,7 +794,7 @@ namespace ts {
* @param node The ConciseBody of an arrow function.
* @param declarations The lexical declarations to merge.
*/
export function mergeFunctionBodyLexicalEnvironment(body: FunctionBody, declarations: Statement[]) {
export function mergeFunctionBodyLexicalEnvironment(body: FunctionBody, declarations: Statement[]): FunctionBody {
if (declarations !== undefined && declarations.length > 0) {
return mergeBlockLexicalEnvironment(body, declarations);
}
@@ -817,7 +808,7 @@ namespace ts {
* @param node The ConciseBody of an arrow function.
* @param declarations The lexical declarations to merge.
*/
export function mergeConciseBodyLexicalEnvironment(body: ConciseBody, declarations: Statement[]) {
export function mergeConciseBodyLexicalEnvironment(body: ConciseBody, declarations: Statement[]): ConciseBody {
if (declarations !== undefined && declarations.length > 0) {
if (isBlock(body)) {
return mergeBlockLexicalEnvironment(body, declarations);
@@ -839,8 +830,8 @@ namespace ts {
* @param node The block into which to merge lexical declarations.
* @param declarations The lexical declarations to merge.
*/
function mergeBlockLexicalEnvironment<T extends Block>(node: T, declarations: Statement[]) {
const mutableNode = cloneNode(node, /*location*/ node, node.flags, /*parent*/ undefined, /*original*/ node);
function mergeBlockLexicalEnvironment<T extends Block>(node: T, declarations: Statement[]): T {
const mutableNode = getMutableClone(node);
mutableNode.statements = mergeStatements(node.statements, declarations);
return mutableNode;
}
@@ -851,7 +842,7 @@ namespace ts {
* @param statements The node array to concatentate with the supplied lexical declarations.
* @param declarations The lexical declarations to merge.
*/
function mergeStatements(statements: NodeArray<Statement>, declarations: Statement[]) {
function mergeStatements(statements: NodeArray<Statement>, declarations: Statement[]): NodeArray<Statement> {
return createNodeArray(concatenate(statements, declarations), /*location*/ statements);
}
@@ -860,7 +851,7 @@ namespace ts {
*
* @param nodes The NodeArray.
*/
export function liftToBlock(nodes: NodeArray<Node>) {
export function liftToBlock(nodes: Node[]): Block {
Debug.assert(every(nodes, isStatement), "Cannot lift nodes to a Block.");
return createBlock(<NodeArray<Statement>>nodes);
}
@@ -870,9 +861,9 @@ namespace ts {
*
* @param nodes The NodeArray.
*/
function extractSingleNode(nodes: NodeArray<Node>) {
function extractSingleNode(nodes: Node[]): Node {
Debug.assert(nodes.length <= 1, "Too many nodes written to output.");
return nodes.length > 0 ? nodes[0] : undefined;
return singleOrUndefined(nodes);
}
/**
@@ -891,15 +882,15 @@ namespace ts {
*/
function aggregateTransformFlagsForNode(node: Node): TransformFlags {
if (node === undefined) {
return <TransformFlags>0;
return TransformFlags.None;
}
if (node.transformFlags === undefined) {
else if (node.transformFlags & TransformFlags.HasComputedFlags) {
return node.transformFlags & ~node.excludeTransformFlags;
}
else {
const subtreeFlags = aggregateTransformFlagsForSubtree(node);
return computeTransformFlagsForNode(node, subtreeFlags);
}
return node.transformFlags & ~node.excludeTransformFlags;
}
/**
@@ -908,12 +899,12 @@ namespace ts {
function aggregateTransformFlagsForSubtree(node: Node): TransformFlags {
// We do not transform ambient declarations or types, so there is no need to
// recursively aggregate transform flags.
if (node.flags & NodeFlags.Ambient || isTypeNode(node)) {
return <TransformFlags>0;
if (hasModifier(node, ModifierFlags.Ambient) || isTypeNode(node)) {
return TransformFlags.None;
}
// Aggregate the transform flags of each child.
return reduceEachChild<TransformFlags>(node, aggregateTransformFlagsForChildNode, 0);
return reduceEachChild(node, aggregateTransformFlagsForChildNode, TransformFlags.None);
}
/**
@@ -923,4 +914,43 @@ namespace ts {
function aggregateTransformFlagsForChildNode(transformFlags: TransformFlags, child: Node): TransformFlags {
return transformFlags | aggregateTransformFlagsForNode(child);
}
export namespace Debug {
export function failNotOptional(message?: string) {
if (shouldAssert(AssertionLevel.Normal)) {
Debug.assert(false, message || "Node not optional.");
}
}
export function failBadSyntaxKind(node: Node, message?: string) {
if (shouldAssert(AssertionLevel.Normal)) {
Debug.assert(false,
message || "Unexpected node.",
() => `Node ${formatSyntaxKind(node.kind)} was unexpected.`);
}
}
export function assertNode<T extends Node>(node: Node, test: (node: Node) => boolean, message?: string): void {
if (shouldAssert(AssertionLevel.Normal)) {
Debug.assert(
test === undefined || test(node),
message || "Unexpected node.",
() => `Node ${formatSyntaxKind(node.kind)} did not pass test '${getFunctionName(test)}'.`);
};
}
function getFunctionName(func: Function) {
if (typeof func !== "function") {
return "";
}
else if (func.hasOwnProperty("name")) {
return (<any>func).name;
}
else {
const text = Function.prototype.toString.call(func);
const match = /^function\s+([\w\$]+)\s*\(/.exec(text);
return match ? match[1] : "";
}
}
}
}
+3 -3
View File
@@ -395,7 +395,7 @@ namespace ts.BreakpointResolver {
// Breakpoint is possible in variableDeclaration only if there is initialization
// or its declaration from 'for of'
if (variableDeclaration.initializer ||
(variableDeclaration.flags & NodeFlags.Export) ||
hasModifier(variableDeclaration, ModifierFlags.Export) ||
variableDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
return textSpanFromVariableDeclaration(variableDeclaration);
}
@@ -413,7 +413,7 @@ namespace ts.BreakpointResolver {
function canHaveSpanInParameterDeclaration(parameter: ParameterDeclaration): boolean {
// Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier
return !!parameter.initializer || parameter.dotDotDotToken !== undefined ||
!!(parameter.flags & NodeFlags.Public) || !!(parameter.flags & NodeFlags.Private);
hasModifier(parameter, ModifierFlags.Public | ModifierFlags.Private);
}
function spanInParameterDeclaration(parameter: ParameterDeclaration): TextSpan {
@@ -439,7 +439,7 @@ namespace ts.BreakpointResolver {
}
function canFunctionHaveSpanInWholeDeclaration(functionDeclaration: FunctionLikeDeclaration) {
return !!(functionDeclaration.flags & NodeFlags.Export) ||
return hasModifier(functionDeclaration, ModifierFlags.Export) ||
(functionDeclaration.parent.kind === SyntaxKind.ClassDeclaration && functionDeclaration.kind !== SyntaxKind.Constructor);
}
+9 -9
View File
@@ -130,7 +130,7 @@ namespace ts.NavigationBar {
return topLevelNodes;
}
function sortNodes(nodes: Node[]): Node[] {
return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => {
if (n1.name && n2.name) {
@@ -147,7 +147,7 @@ namespace ts.NavigationBar {
}
});
}
function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void {
nodes = sortNodes(nodes);
@@ -178,8 +178,8 @@ namespace ts.NavigationBar {
function isTopLevelFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration) {
if (functionDeclaration.kind === SyntaxKind.FunctionDeclaration) {
// A function declaration is 'top level' if it contains any function declarations
// within it.
// A function declaration is 'top level' if it contains any function declarations
// within it.
if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.Block) {
// Proper function declarations can only have identifier names
if (forEach((<Block>functionDeclaration.body).statements,
@@ -198,7 +198,7 @@ namespace ts.NavigationBar {
return false;
}
function getItemsWorker(nodes: Node[], createItem: (n: Node) => ts.NavigationBarItem): ts.NavigationBarItem[] {
let items: ts.NavigationBarItem[] = [];
@@ -258,7 +258,7 @@ namespace ts.NavigationBar {
if (isBindingPattern((<ParameterDeclaration>node).name)) {
break;
}
if ((node.flags & NodeFlags.Modifier) === 0) {
if (!hasModifiers(node)) {
return undefined;
}
return createItem(node, getTextOfNode((<ParameterDeclaration>node).name), ts.ScriptElementKind.memberVariableElement);
@@ -395,19 +395,19 @@ namespace ts.NavigationBar {
let result: string[] = [];
result.push(moduleDeclaration.name.text);
while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) {
moduleDeclaration = <ModuleDeclaration>moduleDeclaration.body;
result.push(moduleDeclaration.name.text);
}
}
return result.join(".");
}
function createModuleItem(node: ModuleDeclaration): NavigationBarItem {
let moduleName = getModuleName(node);
let childItems = getItemsWorker(getChildNodes((<Block>getInnermostModule(node).body).statements), createChildItem);
return getNavigationBarItem(moduleName,
+21 -21
View File
@@ -962,7 +962,7 @@ namespace ts {
case SyntaxKind.Parameter:
// Only consider properties defined as constructor parameters
if (!(node.flags & NodeFlags.AccessibilityModifier)) {
if (!(getModifierFlags(node) & ModifierFlags.AccessibilityModifier)) {
break;
}
// fall through
@@ -2655,7 +2655,7 @@ namespace ts {
case SyntaxKind.Constructor: return ScriptElementKind.constructorImplementationElement;
case SyntaxKind.TypeParameter: return ScriptElementKind.typeParameterElement;
case SyntaxKind.EnumMember: return ScriptElementKind.variableElement;
case SyntaxKind.Parameter: return (node.flags & NodeFlags.AccessibilityModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement;
case SyntaxKind.Parameter: return (getModifierFlags(node) & ModifierFlags.AccessibilityModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement;
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ImportClause:
@@ -5046,14 +5046,14 @@ namespace ts {
}
const keywords: Node[] = [];
const modifierFlag: NodeFlags = getFlagFromModifier(modifier);
const modifierFlag: ModifierFlags = getFlagFromModifier(modifier);
let nodes: Node[];
switch (container.kind) {
case SyntaxKind.ModuleBlock:
case SyntaxKind.SourceFile:
// Container is either a class declaration or the declaration is a classDeclaration
if (modifierFlag & NodeFlags.Abstract) {
if (modifierFlag & ModifierFlags.Abstract) {
nodes = (<Node[]>(<ClassDeclaration>declaration).members).concat(declaration);
}
else {
@@ -5070,7 +5070,7 @@ namespace ts {
// If we're an accessibility modifier, we're in an instance member and should search
// the constructor's parameter list for instance members as well.
if (modifierFlag & NodeFlags.AccessibilityModifier) {
if (modifierFlag & ModifierFlags.AccessibilityModifier) {
const constructor = forEach((<ClassLikeDeclaration>container).members, member => {
return member.kind === SyntaxKind.Constructor && <ConstructorDeclaration>member;
});
@@ -5079,7 +5079,7 @@ namespace ts {
nodes = nodes.concat(constructor.parameters);
}
}
else if (modifierFlag & NodeFlags.Abstract) {
else if (modifierFlag & ModifierFlags.Abstract) {
nodes = nodes.concat(container);
}
break;
@@ -5088,7 +5088,7 @@ namespace ts {
}
forEach(nodes, node => {
if (node.modifiers && node.flags & modifierFlag) {
if (getModifierFlags(node) & modifierFlag) {
forEach(node.modifiers, child => pushKeywordIf(keywords, child, modifier));
}
});
@@ -5098,19 +5098,19 @@ namespace ts {
function getFlagFromModifier(modifier: SyntaxKind) {
switch (modifier) {
case SyntaxKind.PublicKeyword:
return NodeFlags.Public;
return ModifierFlags.Public;
case SyntaxKind.PrivateKeyword:
return NodeFlags.Private;
return ModifierFlags.Private;
case SyntaxKind.ProtectedKeyword:
return NodeFlags.Protected;
return ModifierFlags.Protected;
case SyntaxKind.StaticKeyword:
return NodeFlags.Static;
return ModifierFlags.Static;
case SyntaxKind.ExportKeyword:
return NodeFlags.Export;
return ModifierFlags.Export;
case SyntaxKind.DeclareKeyword:
return NodeFlags.Ambient;
return ModifierFlags.Ambient;
case SyntaxKind.AbstractKeyword:
return NodeFlags.Abstract;
return ModifierFlags.Abstract;
default:
Debug.fail();
}
@@ -5564,7 +5564,7 @@ namespace ts {
// If this is private property or method, the scope is the containing class
if (symbol.flags & (SymbolFlags.Property | SymbolFlags.Method)) {
const privateDeclaration = forEach(symbol.getDeclarations(), d => (d.flags & NodeFlags.Private) ? d : undefined);
const privateDeclaration = forEach(symbol.getDeclarations(), d => (getModifierFlags(d) & ModifierFlags.Private) ? d : undefined);
if (privateDeclaration) {
return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration);
}
@@ -5819,7 +5819,7 @@ namespace ts {
return undefined;
}
// Whether 'super' occurs in a static context within a class.
let staticFlag = NodeFlags.Static;
let staticFlag = ModifierFlags.Static;
switch (searchSpaceNode.kind) {
case SyntaxKind.PropertyDeclaration:
@@ -5829,7 +5829,7 @@ namespace ts {
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
staticFlag &= searchSpaceNode.flags;
staticFlag &= getModifierFlags(searchSpaceNode);
searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
break;
default:
@@ -5854,7 +5854,7 @@ namespace ts {
// If we have a 'super' container, we must have an enclosing class.
// Now make sure the owning class is the same as the search-space
// and has the same static qualifier as the original 'super's owner.
if (container && (NodeFlags.Static & container.flags) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) {
if (container && (ModifierFlags.Static & getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) {
references.push(getReferenceEntryFromNode(node));
}
});
@@ -5867,7 +5867,7 @@ namespace ts {
let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
// Whether 'this' occurs in a static context within a class.
let staticFlag = NodeFlags.Static;
let staticFlag = ModifierFlags.Static;
switch (searchSpaceNode.kind) {
case SyntaxKind.MethodDeclaration:
@@ -5881,7 +5881,7 @@ namespace ts {
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
staticFlag &= searchSpaceNode.flags;
staticFlag &= getModifierFlags(searchSpaceNode);
searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
break;
case SyntaxKind.SourceFile:
@@ -5953,7 +5953,7 @@ namespace ts {
case SyntaxKind.ClassDeclaration:
// Make sure the container belongs to the same class
// and has the appropriate static modifier from the original container.
if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (container.flags & NodeFlags.Static) === staticFlag) {
if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (getModifierFlags(container) & ModifierFlags.Static) === staticFlag) {
result.push(getReferenceEntryFromNode(node));
}
break;
+9 -9
View File
@@ -521,15 +521,15 @@ namespace ts {
}
export function getNodeModifiers(node: Node): string {
let flags = getCombinedNodeFlags(node);
let flags = getCombinedModifierFlags(node);
let result: string[] = [];
if (flags & NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
if (flags & NodeFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier);
if (flags & NodeFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier);
if (flags & NodeFlags.Static) result.push(ScriptElementKindModifier.staticModifier);
if (flags & NodeFlags.Abstract) result.push(ScriptElementKindModifier.abstractModifier);
if (flags & NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier);
if (flags & ModifierFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
if (flags & ModifierFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier);
if (flags & ModifierFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier);
if (flags & ModifierFlags.Static) result.push(ScriptElementKindModifier.staticModifier);
if (flags & ModifierFlags.Abstract) result.push(ScriptElementKindModifier.abstractModifier);
if (flags & ModifierFlags.Export) result.push(ScriptElementKindModifier.exportedModifier);
if (isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier);
return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none;
@@ -615,7 +615,7 @@ namespace ts {
// [a,b,c] from:
// [a, b, c] = someExpression;
if (node.parent.kind === SyntaxKind.BinaryExpression &&
(<BinaryExpression>node.parent).left === node &&
(<BinaryExpression>node.parent).left === node &&
(<BinaryExpression>node.parent).operatorToken.kind === SyntaxKind.EqualsToken) {
return true;
}
@@ -629,7 +629,7 @@ namespace ts {
// [a, b, c] of
// [x, [a, b, c] ] = someExpression
// or
// or
// {x, a: {a, b, c} } = someExpression
if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === SyntaxKind.PropertyAssignment ? node.parent.parent : node.parent)) {
return true;
@@ -31,7 +31,6 @@
},
"length": 1,
"pos": 8,
"end": 22,
"arrayKind": 1
"end": 22
}
}
@@ -31,7 +31,6 @@
},
"length": 1,
"pos": 8,
"end": 22,
"arrayKind": 1
"end": 22
}
}
@@ -21,7 +21,6 @@
},
"length": 1,
"pos": 8,
"end": 15,
"arrayKind": 1
"end": 15
}
}
@@ -21,7 +21,6 @@
},
"length": 1,
"pos": 8,
"end": 13,
"arrayKind": 1
"end": 13
}
}
@@ -37,7 +37,6 @@
},
"length": 1,
"pos": 8,
"end": 29,
"arrayKind": 1
"end": 29
}
}
@@ -37,7 +37,6 @@
},
"length": 1,
"pos": 8,
"end": 29,
"arrayKind": 1
"end": 29
}
}
@@ -38,7 +38,6 @@
},
"length": 1,
"pos": 8,
"end": 31,
"arrayKind": 1
"end": 31
}
}
@@ -38,7 +38,6 @@
},
"length": 1,
"pos": 8,
"end": 36,
"arrayKind": 1
"end": 36
}
}
@@ -37,7 +37,6 @@
},
"length": 1,
"pos": 8,
"end": 29,
"arrayKind": 1
"end": 29
}
}
@@ -37,7 +37,6 @@
},
"length": 1,
"pos": 8,
"end": 29,
"arrayKind": 1
"end": 29
}
}
@@ -27,7 +27,6 @@
},
"length": 1,
"pos": 8,
"end": 18,
"arrayKind": 1
"end": 18
}
}
@@ -31,7 +31,6 @@
},
"length": 1,
"pos": 8,
"end": 24,
"arrayKind": 1
"end": 24
}
}
@@ -31,7 +31,6 @@
},
"length": 1,
"pos": 8,
"end": 24,
"arrayKind": 1
"end": 24
}
}
@@ -31,7 +31,6 @@
},
"length": 1,
"pos": 8,
"end": 25,
"arrayKind": 1
"end": 25
}
}
@@ -32,13 +32,11 @@
},
"length": 1,
"pos": 17,
"end": 19,
"arrayKind": 1
"end": 19
}
},
"length": 1,
"pos": 8,
"end": 19,
"arrayKind": 1
"end": 19
}
}
@@ -43,13 +43,11 @@
},
"length": 2,
"pos": 17,
"end": 21,
"arrayKind": 1
"end": 21
}
},
"length": 1,
"pos": 8,
"end": 21,
"arrayKind": 1
"end": 21
}
}
@@ -43,13 +43,11 @@
},
"length": 2,
"pos": 17,
"end": 22,
"arrayKind": 1
"end": 22
}
},
"length": 1,
"pos": 8,
"end": 22,
"arrayKind": 1
"end": 22
}
}
@@ -43,13 +43,11 @@
},
"length": 2,
"pos": 17,
"end": 22,
"arrayKind": 1
"end": 22
}
},
"length": 1,
"pos": 8,
"end": 22,
"arrayKind": 1
"end": 22
}
}
@@ -43,13 +43,11 @@
},
"length": 2,
"pos": 17,
"end": 23,
"arrayKind": 1
"end": 23
}
},
"length": 1,
"pos": 8,
"end": 23,
"arrayKind": 1
"end": 23
}
}
@@ -43,13 +43,11 @@
},
"length": 2,
"pos": 17,
"end": 23,
"arrayKind": 1
"end": 23
}
},
"length": 1,
"pos": 8,
"end": 23,
"arrayKind": 1
"end": 23
}
}
@@ -69,7 +69,6 @@
},
"length": 2,
"pos": 8,
"end": 55,
"arrayKind": 1
"end": 55
}
}
@@ -37,7 +37,6 @@
},
"length": 1,
"pos": 8,
"end": 29,
"arrayKind": 1
"end": 29
}
}
@@ -31,7 +31,6 @@
},
"length": 1,
"pos": 8,
"end": 22,
"arrayKind": 1
"end": 22
}
}
@@ -25,7 +25,6 @@
},
"length": 2,
"pos": 10,
"end": 25,
"arrayKind": 1
"end": 25
}
}
@@ -5,7 +5,6 @@
"parameters": {
"length": 0,
"pos": 10,
"end": 10,
"arrayKind": 1
"end": 10
}
}
@@ -25,7 +25,6 @@
},
"length": 2,
"pos": 10,
"end": 25,
"arrayKind": 1
"end": 25
}
}
@@ -5,7 +5,6 @@
"members": {
"length": 0,
"pos": 2,
"end": 2,
"arrayKind": 1
"end": 2
}
}
@@ -16,7 +16,6 @@
},
"length": 1,
"pos": 2,
"end": 5,
"arrayKind": 1
"end": 5
}
}
@@ -21,7 +21,6 @@
},
"length": 1,
"pos": 2,
"end": 13,
"arrayKind": 1
"end": 13
}
}
@@ -27,7 +27,6 @@
},
"length": 2,
"pos": 2,
"end": 10,
"arrayKind": 1
"end": 10
}
}
@@ -32,7 +32,6 @@
},
"length": 2,
"pos": 2,
"end": 18,
"arrayKind": 1
"end": 18
}
}
@@ -32,7 +32,6 @@
},
"length": 2,
"pos": 2,
"end": 18,
"arrayKind": 1
"end": 18
}
}
@@ -37,7 +37,6 @@
},
"length": 2,
"pos": 2,
"end": 26,
"arrayKind": 1
"end": 26
}
}
@@ -17,7 +17,6 @@
},
"length": 1,
"pos": 2,
"end": 10,
"arrayKind": 1
"end": 10
}
}
@@ -15,7 +15,6 @@
},
"length": 2,
"pos": 1,
"end": 14,
"arrayKind": 1
"end": 14
}
}
@@ -5,7 +5,6 @@
"types": {
"length": 0,
"pos": 2,
"end": 2,
"arrayKind": 1
"end": 2
}
}
@@ -10,7 +10,6 @@
},
"length": 1,
"pos": 2,
"end": 8,
"arrayKind": 1
"end": 8
}
}
@@ -15,7 +15,6 @@
},
"length": 2,
"pos": 2,
"end": 15,
"arrayKind": 1
"end": 15
}
}
@@ -20,7 +20,6 @@
},
"length": 3,
"pos": 2,
"end": 23,
"arrayKind": 1
"end": 23
}
}
@@ -16,7 +16,6 @@
},
"length": 1,
"pos": 4,
"end": 10,
"arrayKind": 1
"end": 10
}
}
@@ -21,7 +21,6 @@
},
"length": 2,
"pos": 4,
"end": 17,
"arrayKind": 1
"end": 17
}
}
@@ -15,7 +15,6 @@
},
"length": 2,
"pos": 2,
"end": 15,
"arrayKind": 1
"end": 15
}
}