Merge pull request #6986 from Microsoft/transforms-transformer

Adds the transformFiles API for tree transformations
This commit is contained in:
Ron Buckton
2016-03-18 16:39:30 -07:00
243 changed files with 15078 additions and 2082 deletions
+31
View File
@@ -42,7 +42,18 @@ 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",
"printer.ts",
"declarationEmitter.ts",
"emitter.ts",
"program.ts",
@@ -64,7 +75,18 @@ 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",
"printer.ts",
"declarationEmitter.ts",
"emitter.ts",
"program.ts",
@@ -216,6 +238,7 @@ function concatenateFiles(destinationFile, sourceFiles) {
}
var useDebugMode = true;
var useTransforms = process.env.USE_TRANSFORMS || false;
var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node");
var compilerFilename = "tsc.js";
var LKGCompiler = path.join(LKGDirectory, compilerFilename);
@@ -275,6 +298,10 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOu
options += " --stripInternal"
}
if (useBuiltCompiler && useTransforms) {
options += " --experimentalTransforms"
}
var cmd = host + " " + compilerPath + " " + options + " ";
cmd = cmd + sources.join(" ");
console.log(cmd + "\n");
@@ -398,6 +425,10 @@ task("setDebugMode", function() {
useDebugMode = true;
});
task("setTransforms", function() {
useTransforms = true;
});
task("configure-nightly", [configureNightlyJs], function() {
var cmd = host + " " + configureNightlyJs + " " + packageJson + " " + programTs;
console.log(cmd);
+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;
}
+7
View File
@@ -320,6 +320,13 @@ namespace ts {
name: "allowSyntheticDefaultImports",
type: "boolean",
description: Diagnostics.Allow_default_imports_from_modules_with_no_default_export_This_does_not_affect_code_emit_just_typechecking
},
{
// this option will be removed when this is merged with master and exists solely
// to enable the tree transforming emitter side-by-side with the existing emitter.
name: "experimentalTransforms",
type: "boolean",
experimental: true
}
];
+248
View File
@@ -0,0 +1,248 @@
/// <reference path="sourcemap.ts" />
/* @internal */
namespace ts {
export interface CommentWriter {
reset(): void;
setSourceFile(sourceFile: SourceFile): void;
getLeadingComments(range: Node, getAdditionalRange?: (range: Node) => Node): CommentRange[];
getLeadingComments(range: TextRange): CommentRange[];
getLeadingCommentsOfPosition(pos: number): CommentRange[];
getTrailingComments(range: Node, getAdditionalRange?: (range: Node) => Node): CommentRange[];
getTrailingComments(range: TextRange): CommentRange[];
getTrailingCommentsOfPosition(pos: number): CommentRange[];
emitLeadingComments(range: TextRange, comments?: CommentRange[]): void;
emitTrailingComments(range: TextRange, comments?: CommentRange[]): void;
emitDetachedComments(range: TextRange): void;
}
export function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter {
const compilerOptions = host.getCompilerOptions();
const newLine = host.getNewLine();
const { emitPos } = sourceMap;
let currentSourceFile: SourceFile;
let currentText: string;
let currentLineMap: number[];
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[];
// This maps start->end for a comment range. See `hasConsumedCommentRange` and
// `consumeCommentRange` for usage.
let consumedCommentRanges: number[];
let leadingCommentRangePositions: boolean[];
let trailingCommentRangePositions: boolean[];
return compilerOptions.removeComments
? createCommentRemovingWriter()
: createCommentPreservingWriter();
function createCommentRemovingWriter(): CommentWriter {
return {
reset,
setSourceFile,
getLeadingComments(range: TextRange, getAdditionalRange?: (range: TextRange) => TextRange): CommentRange[] { return undefined; },
getLeadingCommentsOfPosition(pos: number): CommentRange[] { return undefined; },
getTrailingComments(range: TextRange, getAdditionalRange?: (range: TextRange) => TextRange): CommentRange[] { return undefined; },
getTrailingCommentsOfPosition(pos: number): CommentRange[] { return undefined; },
emitLeadingComments(range: TextRange, comments?: CommentRange[]): void { },
emitTrailingComments(range: TextRange, comments?: CommentRange[]): void { },
emitDetachedComments,
};
function emitDetachedComments(node: TextRange): void {
emitDetachedCommentsAndUpdateCommentsInfo(node, /*removeComments*/ true);
}
}
function createCommentPreservingWriter(): CommentWriter {
const noComments: CommentRange[] = [];
return {
reset,
setSourceFile,
getLeadingComments,
getLeadingCommentsOfPosition,
getTrailingComments,
getTrailingCommentsOfPosition,
emitLeadingComments,
emitTrailingComments,
emitDetachedComments,
};
function getLeadingComments(range: TextRange | Node, getAdditionalRange?: (range: Node) => Node) {
let comments = getLeadingCommentsOfPosition(range.pos);
if (getAdditionalRange) {
let additionalRange = getAdditionalRange(<Node>range);
while (additionalRange) {
comments = concatenate(
getLeadingCommentsOfPosition(additionalRange.pos),
comments
);
additionalRange = getAdditionalRange(additionalRange);
}
}
return comments;
}
function getTrailingComments(range: TextRange | Node, getAdditionalRange?: (range: Node) => Node) {
let comments = getTrailingCommentsOfPosition(range.end);
if (getAdditionalRange) {
let additionalRange = getAdditionalRange(<Node>range);
while (additionalRange) {
comments = concatenate(
comments,
getTrailingCommentsOfPosition(additionalRange.end)
);
additionalRange = getAdditionalRange(additionalRange);
}
}
return comments;
}
function getLeadingCommentsOfPosition(pos: number) {
if (positionIsSynthesized(pos) || leadingCommentRangePositions[pos]) {
return undefined;
}
leadingCommentRangePositions[pos] = true;
const comments = hasDetachedComments(pos)
? getLeadingCommentsWithoutDetachedComments()
: getLeadingCommentRanges(currentText, pos);
return consumeCommentRanges(comments);
}
function getTrailingCommentsOfPosition(pos: number) {
if (positionIsSynthesized(pos) || trailingCommentRangePositions[pos]) {
return undefined;
}
trailingCommentRangePositions[pos] = true;
const comments = getTrailingCommentRanges(currentText, pos);
return consumeCommentRanges(comments);
}
function emitLeadingComments(range: TextRange, comments = getLeadingComments(range)) {
emitNewLineBeforeLeadingComments(currentLineMap, writer, range, comments);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitTrailingComments(range: TextRange, comments = getTrailingComments(range)) {
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
emitComments(currentText, currentLineMap, writer, comments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment);
}
function emitDetachedComments(range: TextRange) {
emitDetachedCommentsAndUpdateCommentsInfo(range, /*removeComments*/ false);
}
function hasConsumedCommentRange(comment: CommentRange) {
return comment.end === consumedCommentRanges[comment.pos];
}
function consumeCommentRange(comment: CommentRange) {
if (!hasConsumedCommentRange(comment)) {
consumedCommentRanges[comment.pos] = comment.end;
return true;
}
return false;
}
function consumeCommentRanges(comments: CommentRange[]) {
let consumed: CommentRange[];
if (comments) {
let commentsSkipped = 0;
let commentsConsumed = 0;
for (let i = 0; i < comments.length; i++) {
const comment = comments[i];
if (consumeCommentRange(comment)) {
commentsConsumed++;
if (commentsSkipped !== 0) {
if (consumed === undefined) {
consumed = [comment];
}
else {
consumed.push(comment);
}
}
}
else {
commentsSkipped++;
if (commentsConsumed !== 0 && consumed === undefined) {
consumed = comments.slice(0, i);
}
}
}
if (commentsConsumed) {
return consumed || comments;
}
}
return noComments;
}
}
function reset() {
currentSourceFile = undefined;
currentText = undefined;
currentLineMap = undefined;
detachedCommentsInfo = undefined;
consumedCommentRanges = undefined;
trailingCommentRangePositions = undefined;
leadingCommentRangePositions = undefined;
}
function setSourceFile(sourceFile: SourceFile) {
currentSourceFile = sourceFile;
currentText = sourceFile.text;
currentLineMap = getLineStarts(sourceFile);
detachedCommentsInfo = undefined;
consumedCommentRanges = [];
leadingCommentRangePositions = [];
trailingCommentRangePositions = [];
}
function hasDetachedComments(pos: number) {
return detachedCommentsInfo !== undefined && lastOrUndefined(detachedCommentsInfo).nodePos === pos;
}
function getLeadingCommentsWithoutDetachedComments() {
// get the leading comments from detachedPos
const pos = lastOrUndefined(detachedCommentsInfo).detachedCommentEndPos;
const leadingComments = getLeadingCommentRanges(currentText, pos);
if (detachedCommentsInfo.length - 1) {
detachedCommentsInfo.pop();
}
else {
detachedCommentsInfo = undefined;
}
return leadingComments;
}
function emitDetachedCommentsAndUpdateCommentsInfo(node: TextRange, removeComments: boolean) {
const currentDetachedCommentInfo = emitDetachedComments(currentText, currentLineMap, writer, writeComment, node, newLine, removeComments);
if (currentDetachedCommentInfo) {
if (detachedCommentsInfo) {
detachedCommentsInfo.push(currentDetachedCommentInfo);
}
else {
detachedCommentsInfo = [currentDetachedCommentInfo];
}
}
}
function writeComment(text: string, lineMap: number[], writer: EmitTextWriter, comment: CommentRange, newLine: string) {
emitPos(comment.pos);
writeCommentRange(text, lineMap, writer, comment, newLine);
emitPos(comment.end);
}
}
}
+121 -12
View File
@@ -172,29 +172,121 @@ 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;
return [...array1, ...array2];
}
@@ -921,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;
}
@@ -943,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;
@@ -963,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[]) {
+33 -32
View File
@@ -91,7 +91,7 @@ namespace ts {
// Emit reference in dts, if the file reference was not already emitted
if (referencedFile && !contains(emittedReferencedFiles, referencedFile)) {
// Add a reference to generated dts file,
// global file reference is added only
// global file reference is added only
// - if it is not bundled emit (because otherwise it would be self reference)
// - and it is not already added
if (writeReferencePath(referencedFile, !isBundledEmit && !addedGlobalFileReference)) {
@@ -144,7 +144,7 @@ namespace ts {
if (!isBundledEmit && isExternalModule(sourceFile) && sourceFile.moduleAugmentations.length && !resultHasExternalModuleIndicator) {
// if file was external module with augmentations - this fact should be preserved in .d.ts as well.
// in case if we didn't write any external module specifiers in .d.ts we need to emit something
// in case if we didn't write any external module specifiers in .d.ts we need to emit something
// that will force compiler to think that this file is an external module - 'export {}' is a reasonable choice here.
write("export {};");
writeLine();
@@ -349,7 +349,7 @@ namespace ts {
const jsDocComments = getJsDocCommentsFromText(declaration, currentText);
emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments);
// jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentText, currentLineMap, writer, jsDocComments, /*trailingSeparator*/ true, newLine, writeCommentRange);
emitComments(currentText, currentLineMap, writer, jsDocComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeCommentRange);
}
}
@@ -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 ");
@@ -736,7 +737,7 @@ namespace ts {
function emitExternalModuleSpecifier(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration) {
// emitExternalModuleSpecifier is usually called when we emit something in the.d.ts file that will make it an external module (i.e. import/export declarations).
// the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered
// the only case when it is not true is when we call it to emit correct name for module augmentation - d.ts files with just module augmentations are not considered
// external modules since they are indistingushable from script files with ambient modules. To fix this in such d.ts files we'll emit top level 'export {}'
// so compiler will treat them as external modules.
resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || parent.kind !== SyntaxKind.ModuleDeclaration;
@@ -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 :
+91 -96
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)) {
@@ -895,7 +895,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
function emitLiteral(node: LiteralExpression | TemplateLiteralFragment) {
const text = getLiteralText(node);
const text = getLiteralText(node, currentSourceFile, languageVersion);
if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) {
writer.writeLiteral(text);
@@ -909,43 +909,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
}
function getLiteralText(node: LiteralExpression | TemplateLiteralFragment) {
// Any template literal or string literal with an extended escape
// (e.g. "\u{0067}") will need to be downleveled as a escaped string literal.
if (languageVersion < ScriptTarget.ES6 && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) {
return getQuotedEscapedLiteralText("\"", node.text, "\"");
}
// If we don't need to downlevel and we can reach the original source text using
// the node's parent reference, then simply get the text as it was originally written.
if (node.parent) {
return getTextOfNodeFromSourceText(currentText, node);
}
// If we can't reach the original source text, use the canonical form if it's a number,
// or an escaped quoted form of the original text if it's string-like.
switch (node.kind) {
case SyntaxKind.StringLiteral:
return getQuotedEscapedLiteralText("\"", node.text, "\"");
case SyntaxKind.NoSubstitutionTemplateLiteral:
return getQuotedEscapedLiteralText("`", node.text, "`");
case SyntaxKind.TemplateHead:
return getQuotedEscapedLiteralText("`", node.text, "${");
case SyntaxKind.TemplateMiddle:
return getQuotedEscapedLiteralText("}", node.text, "${");
case SyntaxKind.TemplateTail:
return getQuotedEscapedLiteralText("}", node.text, "`");
case SyntaxKind.NumericLiteral:
return node.text;
}
Debug.fail(`Literal kind '${node.kind}' not accounted for.`);
}
function getQuotedEscapedLiteralText(leftQuote: string, text: string, rightQuote: string) {
return leftQuote + escapeNonAsciiCharacters(escapeString(text)) + rightQuote;
}
function emitDownlevelRawTemplateLiteral(node: LiteralExpression) {
// Find original source text, since we need to emit the raw strings of the tagged template.
// The raw strings contain the (escaped) strings of what the user wrote.
@@ -1566,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.
@@ -1952,7 +1915,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
if (multiLine) {
decreaseIndent();
writeLine();
}
write(")");
@@ -2272,13 +2234,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return forEach(elements, e => e.kind === SyntaxKind.SpreadElementExpression);
}
function skipParentheses(node: Expression): Expression {
function skipParenthesesAndAssertions(node: Expression): Expression {
while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) {
node = (<ParenthesizedExpression | AssertionExpression>node).expression;
}
return node;
}
function skipAssertions(node: Expression): Expression {
while (node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) {
node = (<ParenthesizedExpression | AssertionExpression>node).expression;
}
return node;
}
function emitCallTarget(node: Expression): Expression {
if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || node.kind === SyntaxKind.SuperKeyword) {
emit(node);
@@ -2296,7 +2265,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function emitCallWithSpread(node: CallExpression) {
let target: Expression;
const expr = skipParentheses(node.expression);
const expr = skipParenthesesAndAssertions(node.expression);
if (expr.kind === SyntaxKind.PropertyAccessExpression) {
// Target will be emitted as "this" argument
target = emitCallTarget((<PropertyAccessExpression>expr).expression);
@@ -2370,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);
}
@@ -2610,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;
@@ -3345,8 +3314,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
// we can't reuse 'arr' because it might be modified within the body of the loop.
const counter = createTempVariable(TempFlags._i);
const rhsReference = createSynthesizedNode(SyntaxKind.Identifier) as Identifier;
rhsReference.text = node.expression.kind === SyntaxKind.Identifier ?
makeUniqueName((<Identifier>node.expression).text) :
const expressionWithoutAssertions = skipAssertions(node.expression);
rhsReference.text = expressionWithoutAssertions.kind === SyntaxKind.Identifier ?
makeUniqueName((<Identifier>expressionWithoutAssertions).text) :
makeTempVariableName(TempFlags.Auto);
// This is the let keyword for the counter and rhsReference. The let keyword for
@@ -3657,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));
@@ -3681,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) {
@@ -3700,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);
@@ -3709,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 {
@@ -3720,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\"]");
@@ -3851,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;
}
@@ -4193,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;
}
@@ -4201,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 ");
@@ -4230,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;
}
@@ -4361,7 +4331,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
writeLine();
emitStart(restParam);
emitNodeWithCommentsAndWithoutSourcemap(restParam.name);
write("[" + tempName + " - " + restIndex + "] = arguments[" + tempName + "];");
write(`[${tempName} - ${restIndex}] = arguments[${tempName}];`);
emitEnd(restParam);
decreaseIndent();
writeLine();
@@ -4438,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 ");
}
}
@@ -4691,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;
}
@@ -4807,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);
@@ -4843,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);
}
}
@@ -4866,7 +4836,7 @@ const _super = (function (geti, seti) {
emit(receiver);
}
else {
if (property.flags & NodeFlags.Static) {
if (hasModifier(property, ModifierFlags.Static)) {
emitDeclarationName(node);
}
else {
@@ -4968,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 ");
}
@@ -5026,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;
}
});
@@ -5233,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 ");
}
@@ -5254,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 ");
}
}
@@ -5288,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);
}
@@ -5337,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) {
@@ -5346,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();
@@ -5377,6 +5347,18 @@ const _super = (function (geti, seti) {
write(" = ");
}
const staticProperties = getInitializedProperties(node, /*isStatic*/ true);
const isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression;
let tempVariable: Identifier;
if (isClassExpressionWithStaticProperties) {
tempVariable = createAndRecordTempVariable(TempFlags.Auto);
write("(");
increaseIndent();
emit(tempVariable);
write(" = ");
}
write("(function (");
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
if (baseTypeNode) {
@@ -5406,9 +5388,6 @@ const _super = (function (geti, seti) {
writeLine();
emitConstructor(node, baseTypeNode);
emitMemberFunctionsForES5AndLower(node);
emitPropertyDeclarations(node, getInitializedProperties(node, /*isStatic*/ true));
writeLine();
emitDecoratorsOfClass(node, /*decoratedClassAlias*/ undefined);
writeLine();
emitToken(SyntaxKind.CloseBraceToken, node.members.end, () => {
write("return ");
@@ -5435,7 +5414,22 @@ const _super = (function (geti, seti) {
write("))");
if (node.kind === SyntaxKind.ClassDeclaration) {
write(";");
emitPropertyDeclarations(node, staticProperties);
emitDecoratorsOfClass(node, /*decoratedClassAlias*/ undefined);
}
else if (isClassExpressionWithStaticProperties) {
for (const property of staticProperties) {
write(",");
writeLine();
emitPropertyDeclaration(node, property, /*receiver*/ tempVariable, /*isExpression*/ true);
}
write(",");
writeLine();
emit(tempVariable);
decreaseIndent();
write(")");
}
emitEnd(node);
if (node.kind === SyntaxKind.ClassDeclaration) {
@@ -5445,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);
}
@@ -5506,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;
}
@@ -5970,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 ");
@@ -5999,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);
@@ -6011,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}("`);
@@ -6133,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(" = ");
}
@@ -6143,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);
@@ -6255,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 ";
@@ -6345,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 ");
}
}
@@ -6590,7 +6584,8 @@ const _super = (function (geti, seti) {
}
const moduleName = getExternalModuleName(importNode);
if (moduleName.kind === SyntaxKind.StringLiteral) {
return tryRenameExternalModule(<LiteralExpression>moduleName) || getLiteralText(<LiteralExpression>moduleName);
return tryRenameExternalModule(<LiteralExpression>moduleName)
|| getLiteralText(<LiteralExpression>moduleName, currentSourceFile, languageVersion);
}
return undefined;
@@ -6737,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;
}
@@ -6809,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 = [];
}
@@ -6825,7 +6820,7 @@ const _super = (function (geti, seti) {
writeLine();
emit(f);
if (f.flags & NodeFlags.Export) {
if (hasModifier(f, ModifierFlags.Export)) {
if (!exportedDeclarations) {
exportedDeclarations = [];
}
@@ -6837,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;
}
@@ -7601,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);
}
@@ -7973,7 +7968,7 @@ const _super = (function (geti, seti) {
emitNewLineBeforeLeadingComments(currentLineMap, writer, node, leadingComments);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, leadingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitTrailingComments(node: Node) {
@@ -7985,7 +7980,7 @@ const _super = (function (geti, seti) {
const trailingComments = getTrailingCommentsToEmit(node);
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ false, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, trailingComments, /*leadingSeparator*/ true, /*trailingSeparator*/ false, newLine, writeComment);
}
/**
@@ -8000,8 +7995,8 @@ const _super = (function (geti, seti) {
const trailingComments = getTrailingCommentRanges(currentText, pos);
// trailing comments are emitted at space/*trailing comment1 */space/*trailing comment*/
emitComments(currentText, currentLineMap, writer, trailingComments, /*trailingSeparator*/ true, newLine, writeComment);
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
emitComments(currentText, currentLineMap, writer, trailingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitLeadingCommentsOfPositionWorker(pos: number) {
@@ -8022,7 +8017,7 @@ const _super = (function (geti, seti) {
emitNewLineBeforeLeadingComments(currentLineMap, writer, { pos: pos, end: pos }, leadingComments);
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentText, currentLineMap, writer, leadingComments, /*trailingSeparator*/ true, newLine, writeComment);
emitComments(currentText, currentLineMap, writer, leadingComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeComment);
}
function emitDetachedCommentsAndUpdateCommentsInfo(node: TextRange) {
+1283 -92
View File
File diff suppressed because it is too large Load Diff
+64 -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) :
@@ -4069,6 +4049,10 @@ namespace ts {
function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
const node = <Block>createNode(SyntaxKind.Block);
if (parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage) || ignoreMissingOpenBrace) {
if (scanner.hasPrecedingLineBreak()) {
node.multiLine = true;
}
node.statements = parseList(ParsingContext.BlockStatements, parseStatement);
parseExpected(SyntaxKind.CloseBraceToken);
}
@@ -4611,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);
}
}
@@ -4746,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();
@@ -4810,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);
@@ -4818,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();
@@ -4837,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);
@@ -4959,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;
@@ -4979,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();
}
@@ -5063,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();
@@ -5145,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();
@@ -5157,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();
@@ -5181,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)) {
@@ -5209,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();
@@ -5240,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);
@@ -5271,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();
@@ -5284,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();
@@ -5296,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 ;
@@ -5432,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();
@@ -5455,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;
}
@@ -5537,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
File diff suppressed because it is too large Load Diff
+5 -3
View File
@@ -1,6 +1,7 @@
/// <reference path="sys.ts" />
/// <reference path="emitter.ts" />
/// <reference path="core.ts" />
/// <reference path="printer.ts" />
namespace ts {
/* @internal */ export let programTime = 0;
@@ -968,7 +969,8 @@ namespace ts {
const start = new Date().getTime();
const emitResult = emitFiles(
const fileEmitter = options.experimentalTransforms ? printFiles : emitFiles;
const emitResult = fileEmitter(
emitResolver,
getEmitHost(writeFileCallback),
sourceFile);
@@ -1194,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) {
@@ -1309,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 = [];
+44 -4
View File
@@ -7,12 +7,15 @@ namespace ts {
setSourceFile(sourceFile: SourceFile): void;
emitPos(pos: number): void;
emitStart(range: TextRange): void;
emitEnd(range: TextRange, stopOverridingSpan?: boolean): void;
changeEmitSourcePos(): void;
emitEnd(range: TextRange): void;
/*@deprecated*/ emitEnd(range: TextRange, stopOverridingSpan: boolean): void;
/*@deprecated*/ changeEmitSourcePos(): void;
getText(): string;
getSourceMappingURL(): string;
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
reset(): void;
enable(): void;
disable(): void;
}
let nullSourceMapWriter: SourceMapWriter;
@@ -38,6 +41,8 @@ namespace ts {
getSourceMappingURL(): string { return undefined; },
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void { },
reset(): void { },
enable(): void { },
disable(): void { }
};
}
@@ -62,6 +67,13 @@ 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 {
getSourceMapData: () => sourceMapData,
setSourceFile,
@@ -73,6 +85,8 @@ namespace ts {
getSourceMappingURL,
initialize,
reset,
enable,
disable,
};
function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
@@ -81,6 +95,7 @@ namespace ts {
}
currentSourceFile = undefined;
disableDepth = 0;
// Current source map file and its index in the sources list
sourceMapSourceIndex = -1;
@@ -147,6 +162,23 @@ namespace ts {
lastEncodedSourceMapSpan = undefined;
lastEncodedNameIndex = undefined;
sourceMapData = undefined;
disableDepth = 0;
}
/**
* Re-enables the recording of mappings.
*/
function enable() {
if (disableDepth > 0) {
disableDepth--;
}
}
/**
* Disables the recording of mappings.
*/
function disable() {
disableDepth++;
}
function updateLastEncodedAndRecordedSpans() {
@@ -168,7 +200,7 @@ namespace ts {
sourceMapData.sourceMapDecodedMappings[sourceMapData.sourceMapDecodedMappings.length - 1] :
defaultLastEncodedSourceMapSpan;
// TODO: Update lastEncodedNameIndex
// TODO: Update lastEncodedNameIndex
// Since we dont support this any more, lets not worry about it right now.
// When we start supporting nameIndex, we will get back to this
@@ -236,7 +268,7 @@ namespace ts {
}
function emitPos(pos: number) {
if (pos === -1) {
if (positionIsSynthesized(pos) || disableDepth > 0) {
return;
}
@@ -288,9 +320,17 @@ namespace ts {
function emitStart(range: TextRange) {
emitPos(getStartPos(range));
if (range.disableSourceMap) {
disable();
}
}
function emitEnd(range: TextRange, stopOverridingEnd?: boolean) {
if (range.disableSourceMap) {
enable();
}
emitPos(range.end);
stopOverridingSpan = stopOverridingEnd;
}
+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.
}
}
};
}
+291
View File
@@ -0,0 +1,291 @@
/// <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[] = [];
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;
}
/**
* Transforms an array of SourceFiles by passing them through each transformer.
*
* @param resolver The emit resolver provided by the checker.
* @param host The emit host.
* @param sourceFiles An array of source files
* @param transforms An array of Transformers.
*/
export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]) {
const nodeEmitFlags: NodeEmitFlags[] = [];
const lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
const lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
let lexicalEnvironmentStackOffset = 0;
let hoistedVariableDeclarations: VariableDeclaration[];
let hoistedFunctionDeclarations: FunctionDeclaration[];
let currentSourceFile: SourceFile;
// The transformation context is provided to each transformer as part of transformer
// initialization.
const context: TransformationContext = {
getCompilerOptions: () => host.getCompilerOptions(),
getEmitResolver: () => resolver,
getNodeEmitFlags,
setNodeEmitFlags,
hoistVariableDeclaration,
hoistFunctionDeclaration,
startLexicalEnvironment,
endLexicalEnvironment,
identifierSubstitution: node => node,
expressionSubstitution: node => node,
enableExpressionSubstitution,
isExpressionSubstitutionEnabled,
onEmitNode: (node, emit) => emit(node),
enableEmitNotification,
isEmitNotificationEnabled,
};
// Chain together and initialize each transformer.
const transformation = chain(...transformers)(context);
// Transform each source file.
return map(sourceFiles, transformSourceFile);
/**
* Transforms a source file.
*
* @param sourceFile The source file to transform.
*/
function transformSourceFile(sourceFile: SourceFile) {
if (isDeclarationFile(sourceFile)) {
return sourceFile;
}
currentSourceFile = sourceFile;
return transformation(sourceFile);
}
function enableExpressionSubstitution(kind: SyntaxKind) {
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.ExpressionSubstitution;
}
function isExpressionSubstitutionEnabled(node: Node) {
return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.ExpressionSubstitution) !== 0;
}
function enableEmitNotification(kind: SyntaxKind) {
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.EmitNotifications;
}
function isEmitNotificationEnabled(node: Node) {
return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.EmitNotifications) !== 0
|| (getNodeEmitFlags(node) & NodeEmitFlags.AdviseOnEmitNode) !== 0;
}
/**
* Gets flags that control emit behavior of a node.
*/
function getNodeEmitFlags(node: Node) {
while (node) {
const nodeId = getNodeId(node);
if (nodeEmitFlags[nodeId] !== undefined) {
return nodeEmitFlags[nodeId];
}
node = node.original;
}
return undefined;
}
/**
* Sets flags that control emit behavior of a node.
*/
function setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags) {
nodeEmitFlags[getNodeId(node)] = flags;
return node;
}
/**
* Records a hoisted variable declaration for the provided name within a lexical environment.
*/
function hoistVariableDeclaration(name: Identifier): void {
const decl = createVariableDeclaration(name);
if (!hoistedVariableDeclarations) {
hoistedVariableDeclarations = [decl];
}
else {
hoistedVariableDeclarations.push(decl);
}
}
/**
* Records a hoisted function declaration within a lexical environment.
*/
function hoistFunctionDeclaration(func: FunctionDeclaration): void {
if (!hoistedFunctionDeclarations) {
hoistedFunctionDeclarations = [func];
}
else {
hoistedFunctionDeclarations.push(func);
}
}
/**
* Starts a new lexical environment. Any existing hoisted variable or function declarations
* are pushed onto a stack, and the related storage variables are reset.
*/
function startLexicalEnvironment(): void {
// Save the current lexical environment. Rather than resizing the array we adjust the
// stack size variable. This allows us to reuse existing array slots we've
// already allocated between transformations to avoid allocation and GC overhead during
// transformation.
lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedVariableDeclarations;
lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset] = hoistedFunctionDeclarations;
lexicalEnvironmentStackOffset++;
hoistedVariableDeclarations = undefined;
hoistedFunctionDeclarations = undefined;
}
/**
* Ends a lexical environment. The previous set of hoisted declarations are restored and
* any hoisted declarations added in this environment are returned.
*/
function endLexicalEnvironment(): Statement[] {
let statements: Statement[];
if (hoistedVariableDeclarations || hoistedFunctionDeclarations) {
if (hoistedFunctionDeclarations) {
statements = [...hoistedFunctionDeclarations];
}
if (hoistedVariableDeclarations) {
const statement = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(hoistedVariableDeclarations)
);
if (!statements) {
statements = [statement];
}
else {
statements.push(statement);
}
}
}
// Restore the previous lexical environment.
lexicalEnvironmentStackOffset--;
hoistedVariableDeclarations = lexicalEnvironmentVariableDeclarationsStack[lexicalEnvironmentStackOffset];
hoistedFunctionDeclarations = lexicalEnvironmentFunctionDeclarationsStack[lexicalEnvironmentStackOffset];
return statements;
}
}
/**
* High-order function, creates a function that executes a function composition.
* For example, `chain(a, b)` is the equivalent of `x => ((a', b') => y => b'(a'(y)))(a(x), b(x))`
*
* @param args The functions to chain.
*/
function chain<T, U>(...args: ((t: T) => (u: U) => U)[]): (t: T) => (u: U) => U;
function chain<T, U>(a: (t: T) => (u: U) => U, b: (t: T) => (u: U) => U, c: (t: T) => (u: U) => U, d: (t: T) => (u: U) => U, e: (t: T) => (u: U) => U): (t: T) => (u: U) => U {
if (e) {
const args = arrayOf<(t: T) => (u: U) => U>(arguments);
return t => compose(...map(args, f => f(t)));
}
else if (d) {
return t => compose(a(t), b(t), c(t), d(t));
}
else if (c) {
return t => compose(a(t), b(t), c(t));
}
else if (b) {
return t => compose(a(t), b(t));
}
else if (a) {
return t => compose(a(t));
}
else {
return t => u => u;
}
}
/**
* High-order function, composes functions. Note that functions are composed inside-out;
* for example, `compose(a, b)` is the equivalent of `x => b(a(x))`.
*
* @param args The functions to compose.
*/
function compose<T>(...args: ((t: T) => T)[]): (t: T) => T;
function compose<T>(a: (t: T) => T, b: (t: T) => T, c: (t: T) => T, d: (t: T) => T, e: (t: T) => T): (t: T) => T {
if (e) {
const args = arrayOf(arguments);
return t => reduceLeft<(t: T) => T, T>(args, (u, f) => f(u), t);
}
else if (d) {
return t => d(c(b(a(t))));
}
else if (c) {
return t => c(b(a(t)));
}
else if (b) {
return t => b(a(t));
}
else if (a) {
return t => a(t);
}
else {
return t => t;
}
}
/**
* Makes an array from an ArrayLike.
*/
function arrayOf<T>(arrayLike: ArrayLike<T>) {
const length = arrayLike.length;
const array: T[] = new Array<T>(length);
for (let i = 0; i < length; i++) {
array[i] = arrayLike[i];
}
return array;
}
}
+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);
+4
View File
@@ -19,6 +19,10 @@
"checker.ts",
"factory.ts",
"visitor.ts",
"transformer.ts",
"comments.ts",
"printer.ts",
"declarationEmitter.ts",
"emitter.ts",
"program.ts",
"commandLineParser.ts",
+127 -52
View File
@@ -20,6 +20,7 @@ namespace ts {
export interface TextRange {
pos: number;
end: number;
/* @internal */ disableSourceMap?: boolean; // Whether a synthesized text range disables source maps for its contents (used by transforms).
}
// token > SyntaxKind.Identifer => token is a keyword
@@ -341,7 +342,7 @@ namespace ts {
// Synthesized list
SyntaxList,
NodeArrayNode,
// Enum value count
Count,
// Markers
@@ -372,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"
@@ -403,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,
@@ -417,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 */
@@ -442,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.
@@ -457,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)
@@ -496,10 +484,19 @@ namespace ts {
// @kind(SyntaxKind.StaticKeyword)
export interface Modifier extends Node { }
export const enum GeneratedIdentifierKind {
None, // Not automatically generated.
Auto, // Automatically generated identifier.
Loop, // Automatically generated identifier with a preference for '_i'.
Unique, // Unique name based on the 'text' property.
Node, // Unique name based on the node in the 'original' property.
}
// @kind(SyntaxKind.Identifier)
export interface Identifier extends PrimaryExpression {
text: string; // Text of identifier (with escapes converted to characters)
originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later
autoGenerateKind?: GeneratedIdentifierKind; // Specifies whether to auto-generate the text for an identifier.
}
// @kind(SyntaxKind.QualifiedName)
@@ -1119,6 +1116,7 @@ namespace ts {
// @kind(SyntaxKind.Block)
export interface Block extends Statement {
statements: NodeArray<Statement>;
/*@internal*/ multiLine?: boolean;
}
// @kind(SyntaxKind.VariableStatement)
@@ -1296,7 +1294,7 @@ namespace ts {
export interface EnumMember extends Declaration {
// This does include ComputedPropertyName, but the parser will give an error
// if it parses a ComputedPropertyName in an EnumMember
name: DeclarationName;
name: PropertyName;
initializer?: Expression;
}
@@ -2080,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 */
@@ -2461,6 +2459,7 @@ namespace ts {
allowSyntheticDefaultImports?: boolean;
allowJs?: boolean;
/* @internal */ stripInternal?: boolean;
/* @internal */ experimentalTransforms?: boolean;
// Skip checking lib.d.ts to help speed up tests.
/* @internal */ skipDefaultLibCheck?: boolean;
@@ -2739,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,
@@ -2749,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.
@@ -2772,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,
@@ -2784,6 +2788,22 @@ namespace ts {
ArrayLiteralOrCallOrNewExcludes = ContainsSpreadElementExpression,
}
/* @internal */
export const enum NodeEmitFlags {
EmitEmitHelpers = 1 << 0, // Any emit helpers should be written to this node.
EmitExportStar = 1 << 1, // The export * helper should be written to this node.
EmitSuperHelper = 1 << 2, // Emit the basic _super helper for async methods.
EmitAdvancedSuperHelper = 1 << 3, // Emit the advanced _super helper for async methods.
UMDDefine = 1 << 4, // This node should be replaced with the UMD define helper.
NoLexicalEnvironment = 1 << 5, // A new LexicalEnvironment should *not* be introduced when emitting this node, this is primarily used when printing a SystemJS module.
SingleLine = 1 << 6, // The contents of this node should be emit on a single line.
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` */
export interface LexicalEnvironment {
/** Starts a new lexical environment. */
@@ -2793,6 +2813,61 @@ namespace ts {
endLexicalEnvironment(): Statement[];
}
/* @internal */
export interface TransformationContext extends LexicalEnvironment {
getCompilerOptions(): CompilerOptions;
getEmitResolver(): EmitResolver;
getNodeEmitFlags(node: Node): NodeEmitFlags;
setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags): T;
hoistFunctionDeclaration(node: FunctionDeclaration): void;
hoistVariableDeclaration(node: Identifier): void;
/**
* Hook used by transformers to substitute non-expression identifiers
* just before theyare emitted by the pretty printer.
*/
identifierSubstitution?: (node: Identifier) => Identifier;
/**
* Enables expression substitutions in the pretty printer for
* the provided SyntaxKind.
*/
enableExpressionSubstitution(kind: SyntaxKind): void;
/**
* Determines whether expression substitutions are enabled for the
* provided node.
*/
isExpressionSubstitutionEnabled(node: Node): boolean;
/**
* Hook used by transformers to substitute expressions just before they
* are emitted by the pretty printer.
*/
expressionSubstitution?: (node: Expression) => Expression;
/**
* Enables before/after emit notifications in the pretty printer for
* the provided SyntaxKind.
*/
enableEmitNotification(kind: SyntaxKind): void;
/**
* Determines whether before/after emit notifications should be raised
* in the pretty printer when it emits a node.
*/
isEmitNotificationEnabled(node: Node): boolean;
/**
* Hook used to allow transformers to capture state before or after
* the printer emits a node.
*/
onEmitNode?: (node: Node, emit: (node: Node) => void) => void;
}
/* @internal */
export type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile;
export interface TextSpan {
start: number;
length: number;
+651 -102
View File
File diff suppressed because it is too large Load Diff
+182 -141
View File
@@ -1,8 +1,9 @@
/// <reference path="checker.ts" />
/// <reference path="factory.ts" />
/* @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.
@@ -19,6 +20,9 @@ namespace ts {
/** A callback used to lift a NodeArrayNode into a valid node. */
lift?: (nodes: NodeArray<Node>) => Node;
/** A callback used to parenthesize a node to preserve the intended order of operations. */
parenthesize?: (value: Node, parentNode: Node) => Node;
};
/**
@@ -52,7 +56,7 @@ namespace ts {
{ name: "modifiers", test: isModifier },
{ name: "name", test: isBindingName },
{ name: "type", test: isTypeNode, optional: true },
{ name: "initializer", test: isExpression, optional: true },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.Decorator]: [
{ name: "expression", test: isLeftHandSideExpression },
@@ -108,34 +112,34 @@ namespace ts {
[SyntaxKind.BindingElement]: [
{ name: "propertyName", test: isPropertyName, optional: true },
{ name: "name", test: isBindingName },
{ name: "initializer", test: isExpression, optional: true },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.ArrayLiteralExpression]: [
{ name: "elements", test: isExpression },
{ name: "elements", test: isExpression, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.ObjectLiteralExpression]: [
{ name: "properties", test: isObjectLiteralElement },
],
[SyntaxKind.PropertyAccessExpression]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "name", test: isIdentifier },
],
[SyntaxKind.ElementAccessExpression]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "argumentExpression", test: isExpression },
],
[SyntaxKind.CallExpression]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "typeArguments", test: isTypeNode },
{ name: "arguments", test: isExpression },
],
[SyntaxKind.NewExpression]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForNew },
{ name: "typeArguments", test: isTypeNode },
{ name: "arguments", test: isExpression },
],
[SyntaxKind.TaggedTemplateExpression]: [
{ name: "tag", test: isLeftHandSideExpression },
{ name: "tag", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "template", test: isTemplate },
],
[SyntaxKind.TypeAssertionExpression]: [
@@ -160,29 +164,29 @@ namespace ts {
{ name: "typeParameters", test: isTypeParameter },
{ name: "parameters", test: isParameter },
{ name: "type", test: isTypeNode, optional: true },
{ name: "body", test: isConciseBody, lift: liftToBlock },
{ name: "body", test: isConciseBody, lift: liftToBlock, parenthesize: parenthesizeConciseBody },
],
[SyntaxKind.DeleteExpression]: [
{ name: "expression", test: isUnaryExpression },
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.TypeOfExpression]: [
{ name: "expression", test: isUnaryExpression },
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.VoidExpression]: [
{ name: "expression", test: isUnaryExpression },
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.AwaitExpression]: [
{ name: "expression", test: isUnaryExpression },
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.PrefixUnaryExpression]: [
{ name: "operand", test: isUnaryExpression },
{ name: "operand", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.PostfixUnaryExpression]: [
{ name: "operand", test: isLeftHandSideExpression },
{ name: "operand", test: isLeftHandSideExpression, parenthesize: parenthesizePostfixOperand },
],
[SyntaxKind.BinaryExpression]: [
{ name: "left", test: isExpression },
{ name: "right", test: isExpression },
{ name: "left", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, true) },
{ name: "right", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, false) },
],
[SyntaxKind.ConditionalExpression]: [
{ name: "condition", test: isExpression },
@@ -197,7 +201,7 @@ namespace ts {
{ name: "expression", test: isExpression, optional: true },
],
[SyntaxKind.SpreadElementExpression]: [
{ name: "expression", test: isExpression },
{ name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.ClassExpression]: [
{ name: "decorators", test: isDecorator },
@@ -208,7 +212,7 @@ namespace ts {
{ name: "members", test: isClassElement },
],
[SyntaxKind.ExpressionWithTypeArguments]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "typeArguments", test: isTypeNode },
],
[SyntaxKind.AsExpression]: [
@@ -228,7 +232,7 @@ namespace ts {
{ name: "declarationList", test: isVariableDeclarationList },
],
[SyntaxKind.ExpressionStatement]: [
{ name: "expression", test: isExpression },
{ name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForExpressionStatement },
],
[SyntaxKind.IfStatement]: [
{ name: "expression", test: isExpression },
@@ -291,7 +295,7 @@ namespace ts {
[SyntaxKind.VariableDeclaration]: [
{ name: "name", test: isBindingName },
{ name: "type", test: isTypeNode, optional: true },
{ name: "initializer", test: isExpression, optional: true },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.VariableDeclarationList]: [
{ name: "declarations", test: isVariableDeclaration },
@@ -405,7 +409,7 @@ namespace ts {
{ name: "expression", test: isExpression, optional: true },
],
[SyntaxKind.CaseClause]: [
{ name: "expression", test: isExpression },
{ name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList },
{ name: "statements", test: isStatement },
],
[SyntaxKind.DefaultClause]: [
@@ -420,7 +424,7 @@ namespace ts {
],
[SyntaxKind.PropertyAssignment]: [
{ name: "name", test: isPropertyName },
{ name: "initializer", test: isExpression },
{ name: "initializer", test: isExpression, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.ShorthandPropertyAssignment]: [
{ name: "name", test: isIdentifier },
@@ -428,7 +432,7 @@ namespace ts {
],
[SyntaxKind.EnumMember]: [
{ name: "name", test: isPropertyName },
{ name: "initializer", test: isExpression, optional: true },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.SourceFile]: [
{ name: "statements", test: isStatement },
@@ -444,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;
}
@@ -474,7 +478,22 @@ 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);
}
/**
* Visits a Node using the supplied visitor, possibly returning a new Node in its place.
*
* @param node The Node to visit.
* @param visitor The callback used to visit the Node.
* @param test A callback to execute to verify the Node is valid.
* @param optional A value indicating whether the Node is itself optional.
* @param lift A callback to execute to lift a NodeArrayNode into a valid Node.
* @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) => 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;
}
@@ -484,15 +503,28 @@ namespace ts {
return node;
}
const lifted = liftNode(visited, lift);
if (lifted === undefined) {
Debug.assert(optional, "Node not optional.");
let visitedNode: Node;
if (visited === undefined) {
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 <T>visited;
if (parenthesize !== undefined) {
visitedNode = parenthesize(visitedNode, parentNode);
}
Debug.assertNode(visitedNode, test);
aggregateTransformFlags(visitedNode);
return visitedNode;
}
/**
@@ -504,12 +536,25 @@ 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);
}
/**
* Visits a NodeArray using the supplied visitor, possibly returning a new NodeArray in its place.
*
* @param nodes The NodeArray to visit.
* @param visitor The callback used to visit a Node.
* @param test A node test to execute for each node.
* @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) => 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: T[];
let updated: NodeArray<Node>;
// Ensure start and count have valid values
const length = nodes.length;
@@ -521,36 +566,29 @@ 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.
for (let i = 0; i < count; i++) {
const node = nodes[i + start];
const visited = node && <OneOrMany<T>>visitor(node);
const visited = node !== undefined ? visitor(node) : undefined;
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);
}
if (visited !== node) {
aggregateTransformFlags(visited);
}
addNodeWorker(updated, visited, /*addOnNewLine*/ undefined, test);
addNodeWorker(updated, visited, /*addOnNewLine*/ undefined, test, parenthesize, parentNode, /*isVisiting*/ visited !== node);
}
}
if (updated !== undefined) {
return <TArray>(isModifiersArray(nodes)
? createModifiersArray(updated, nodes)
: createNodeArray(updated, nodes, nodes.hasTrailingComma));
}
return nodes;
return updated || nodes;
}
/**
@@ -560,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;
}
@@ -576,28 +614,25 @@ 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) {
const visited = visitEdge(edge, value, visitor);
if (visited && isArray(visited) && isModifiersArray(visited)) {
modifiers = visited.flags;
let visited: Node | NodeArray<Node>;
if (isArray(value)) {
const visitedArray = visitNodesWorker(value, visitor, edge.test, edge.parenthesize, node, 0, value.length);
visited = visitedArray;
}
else {
visited = visitNodeWorker(<Node>value, visitor, edge.test, edge.optional, edge.lift, edge.parenthesize, node);
}
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) {
setEdgeValue(updated, edge, visited);
updated[edge.name] = visited;
}
}
}
@@ -623,35 +658,14 @@ namespace ts {
return updated;
}
/**
* Sets the value of an edge, adjusting the value as necessary for cases such as expression precedence.
*/
function setEdgeValue(parentNode: Node & Map<any>, edge: NodeEdge, value: Node | NodeArray<Node>) {
parentNode[edge.name] = value;
}
/**
* Visits a node edge.
*
* @param edge The edge of the Node.
* @param value The Node or NodeArray value for the edge.
* @param visitor A callback used to visit the node.
*/
function visitEdge(edge: NodeEdge, value: Node | NodeArray<Node>, visitor: (node: Node) => Node) {
return isArray(value)
? visitNodes(<NodeArray<Node>>value, visitor, edge.test, /*start*/ undefined, /*count*/ undefined)
: visitNode(<Node>value, visitor, edge.test, edge.optional, edge.lift);
}
/**
* Appends a node to an array.
*
* @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) {
addNodeWorker(to, from, startOnNewLine, /*test*/ undefined);
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);
}
/**
@@ -659,32 +673,40 @@ 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) {
addNodesWorker(to, from, startOnNewLine, /*test*/ undefined);
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<T extends Node>(to: T[], from: OneOrMany<T>, startOnNewLine: boolean, test: (node: Node) => 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);
if (isArray(from)) {
addNodesWorker(to, from, startOnNewLine, test, parenthesize, parentNode, isVisiting);
}
else {
Debug.assert(test === undefined || test(from), "Wrong node type after visit.");
const node = parenthesize !== undefined
? parenthesize(from, parentNode)
: from;
Debug.assertNode(node, test);
if (startOnNewLine) {
from.startsOnNewLine = true;
node.startsOnNewLine = true;
}
to.push(from);
if (isVisiting) {
aggregateTransformFlags(node);
}
to.push(node);
}
}
}
function addNodesWorker<T extends Node>(to: T[], from: OneOrMany<T>[], startOnNewLine: boolean, test: (node: Node) => 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);
addNodeWorker(to, node, startOnNewLine, test, parenthesize, parentNode, isVisiting);
}
}
}
@@ -722,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;
}
@@ -738,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;
}
@@ -755,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;
}
@@ -772,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);
}
@@ -786,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);
@@ -808,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;
}
@@ -820,36 +842,16 @@ 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);
}
/**
* Tries to lift a NodeArrayNode to a Node. This is primarily used to
* lift multiple statements into a single Block.
*
* @param node The visited Node.
* @param options Options used to control lift behavior.
*/
function liftNode(node: Node, lifter: (nodes: NodeArray<Node>) => Node): Node {
if (node === undefined) {
return undefined;
}
else if (isNodeArrayNode(node)) {
const lift = lifter || extractSingleNode;
return lift(node.nodes);
}
else {
return node;
}
}
/**
* Lifts a NodeArray containing only Statement nodes to a block.
*
* @param nodes The NodeArray.
*/
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);
}
@@ -859,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);
}
/**
@@ -880,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;
}
/**
@@ -897,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);
}
/**
@@ -912,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);
}
+1 -1
View File
@@ -204,7 +204,7 @@ namespace ts.formatting {
// - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually
// - parent and child are not on the same line
let useActualIndentation =
(isDeclaration(current) || isStatement(current)) &&
(isDeclaration(current) || isStatementButNotDeclaration(current)) &&
(parent.kind === SyntaxKind.SourceFile || !parentAndChildShareLine);
if (!useActualIndentation) {
+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;
@@ -28,9 +28,9 @@ var Point = (function () {
this.x = x;
this.y = y;
}
Point.Origin = { x: 0, y: 0 };
return Point;
}());
Point.Origin = { x: 0, y: 0 };
var Point;
(function (Point) {
Point.Origin = ""; //expected duplicate identifier error
@@ -42,9 +42,9 @@ var A;
this.x = x;
this.y = y;
}
Point.Origin = { x: 0, y: 0 };
return Point;
}());
Point.Origin = { x: 0, y: 0 };
A.Point = Point;
var Point;
(function (Point) {
@@ -28,9 +28,9 @@ var Point = (function () {
this.x = x;
this.y = y;
}
Point.Origin = { x: 0, y: 0 };
return Point;
}());
Point.Origin = { x: 0, y: 0 };
var Point;
(function (Point) {
var Origin = ""; // not an error, since not exported
@@ -42,9 +42,9 @@ var A;
this.x = x;
this.y = y;
}
Point.Origin = { x: 0, y: 0 };
return Point;
}());
Point.Origin = { x: 0, y: 0 };
A.Point = Point;
var Point;
(function (Point) {
@@ -7,6 +7,6 @@ class AtomicNumbers {
var AtomicNumbers = (function () {
function AtomicNumbers() {
}
AtomicNumbers.H = 1;
return AtomicNumbers;
}());
AtomicNumbers.H = 1;
@@ -14,7 +14,6 @@ obj[Symbol.foo];
var Symbol;
var obj = (_a = {},
_a[Symbol.foo] = 0,
_a
);
_a);
obj[Symbol.foo];
var _a;
@@ -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
}
}
@@ -38,9 +38,9 @@ define(["require", "exports"], function (require, exports) {
function C1() {
this.m1 = 42;
}
C1.s1 = true;
return C1;
}());
C1.s1 = true;
exports.C1 = C1;
(function (E1) {
E1[E1["A"] = 0] = "A";
+1 -1
View File
@@ -37,9 +37,9 @@ var Point = (function () {
Point.prototype.getDist = function () {
return Math.sqrt(this.x * this.x + this.y * this.y);
};
Point.origin = new Point(0, 0);
return Point;
}());
Point.origin = new Point(0, 0);
var Point3D = (function (_super) {
__extends(Point3D, _super);
function Point3D(x, y, z, m) {
@@ -163,31 +163,35 @@ function foo8() {
var x;
}
function foo9() {
var y = (function () {
function class_3() {
}
class_3.a = x;
return class_3;
}());
var y = (_a = (function () {
function class_3() {
}
return class_3;
}()),
_a.a = x,
_a);
var x;
var _a;
}
function foo10() {
var A = (function () {
function A() {
}
A.a = x;
return A;
}());
A.a = x;
var x;
}
function foo11() {
function f() {
var y = (function () {
function class_4() {
}
class_4.a = x;
return class_4;
}());
var y = (_a = (function () {
function class_4() {
}
return class_4;
}()),
_a.a = x,
_a);
var _a;
}
var x;
}
+1 -1
View File
@@ -5,6 +5,6 @@ class foo { constructor() { static f = 3; } }
var foo = (function () {
function foo() {
}
foo.f = 3;
return foo;
}());
foo.f = 3;
@@ -12,10 +12,10 @@ var v = ;
var C = (function () {
function C() {
}
C.p = 1;
C = __decorate([
decorate
], C);
return C;
}());
C.p = 1;
C = __decorate([
decorate
], C);
;
@@ -2,10 +2,12 @@
var v = class C { static a = 1; static b = 2 };
//// [classExpressionWithStaticProperties1.js]
var v = (function () {
function C() {
}
C.a = 1;
C.b = 2;
return C;
}());
var v = (_a = (function () {
function C() {
}
return C;
}()),
_a.a = 1,
_a.b = 2,
_a);
var _a;
@@ -2,9 +2,11 @@
var v = class C { static a = 1; static b };
//// [classExpressionWithStaticProperties2.js]
var v = (function () {
function C() {
}
C.a = 1;
return C;
}());
var v = (_a = (function () {
function C() {
}
return C;
}()),
_a.a = 1,
_a);
var _a;
@@ -27,9 +27,9 @@ var CCC = (function () {
this.y = aaa;
this.y = ''; // was: error, cannot assign string to number
}
CCC.staticY = aaa; // This shouldnt be error
return CCC;
}());
CCC.staticY = aaa; // This shouldnt be error
// above is equivalent to this:
var aaaa = 1;
var CCCC = (function () {
@@ -40,12 +40,12 @@ var Test = (function () {
console.log(field); // Using field here shouldnt be error
};
}
Test.staticMessageHandler = function () {
var field = Test.field;
console.log(field); // Using field here shouldnt be error
};
return Test;
}());
Test.staticMessageHandler = function () {
var field = Test.field;
console.log(field); // Using field here shouldnt be error
};
var field1;
var Test1 = (function () {
function Test1(field1) {
@@ -56,8 +56,8 @@ var Test1 = (function () {
// it would resolve to private field1 and thats not what user intended here.
};
}
Test1.staticMessageHandler = function () {
console.log(field1); // This shouldnt be error as its a static property
};
return Test1;
}());
Test1.staticMessageHandler = function () {
console.log(field1); // This shouldnt be error as its a static property
};
@@ -32,9 +32,9 @@ var C = (function () {
}
C.prototype.c = function () { return ''; };
C.f = function () { return ''; };
C.g = function () { return ''; };
return C;
}());
C.g = function () { return ''; };
var c = new C();
var r1 = c.x;
var r2 = c.a;
@@ -42,9 +42,9 @@ var C = (function () {
}
C.prototype.c = function () { return ''; };
C.f = function () { return ''; };
C.g = function () { return ''; };
return C;
}());
C.g = function () { return ''; };
var D = (function (_super) {
__extends(D, _super);
function D() {
@@ -30,9 +30,9 @@ var C = (function () {
}
C.prototype.c = function () { return ''; };
C.f = function () { return ''; };
C.g = function () { return ''; };
return C;
}());
C.g = function () { return ''; };
// all of these are valid
var c = new C();
var r1 = c.x;
@@ -16,10 +16,10 @@ module Clod {
var Clod = (function () {
function Clod() {
}
Clod.x = 10;
Clod.y = 10;
return Clod;
}());
Clod.x = 10;
Clod.y = 10;
var Clod;
(function (Clod) {
var p = Clod.x;
@@ -24,13 +24,13 @@ class test {
var test = (function () {
function test() {
}
/**
* p1 comment appears in output
*/
test.p1 = "";
/**
* p3 comment appears in output
*/
test.p3 = "";
return test;
}());
/**
* p1 comment appears in output
*/
test.p1 = "";
/**
* p3 comment appears in output
*/
test.p3 = "";
@@ -19,9 +19,9 @@ var C1 = (function () {
function C1() {
this.m1 = 42;
}
C1.s1 = true;
return C1;
}());
C1.s1 = true;
exports.C1 = C1;
//// [foo_1.js]
"use strict";
@@ -37,9 +37,9 @@ var C1 = (function () {
function C1() {
this.m1 = 42;
}
C1.s1 = true;
return C1;
}());
C1.s1 = true;
exports.C1 = C1;
(function (E1) {
E1[E1["A"] = 0] = "A";
@@ -32,6 +32,5 @@ var v = (_a = {},
_a[true] = function () { },
_a["hello bye"] = function () { },
_a["hello " + a + " bye"] = function () { },
_a
);
_a);
var _a;
@@ -68,6 +68,5 @@ var v = (_a = {},
enumerable: true,
configurable: true
}),
_a
);
_a);
var _a;
@@ -26,6 +26,6 @@ var C = (function () {
this[s + n] = 2;
this["hello bye"] = 0;
}
C["hello " + a + " bye"] = 0;
return C;
}());
C["hello " + a + " bye"] = 0;
@@ -9,7 +9,6 @@ function foo() {
function foo() {
var obj = (_a = {},
_a[this.bar] = 0,
_a
);
_a);
var _a;
}

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