Migrated to NodeStack for transforms

This commit is contained in:
Ron Buckton
2015-09-08 17:03:30 -07:00
parent b73bef89fc
commit 380452becb
12 changed files with 181 additions and 151 deletions

View File

@@ -31,9 +31,9 @@ if (process.env.path !== undefined) {
}
var compilerSources = [
"types.ts",
"core.ts",
"sys.ts",
"types.ts",
"scanner.ts",
"factory.ts",
"factory.generated.ts",
@@ -60,6 +60,8 @@ var servicesSources = [
"sys.ts",
"types.ts",
"scanner.ts",
"factory.ts",
"factory.generated.ts",
"parser.ts",
"utilities.ts",
"binder.ts",

View File

@@ -404,8 +404,6 @@ function generateFactory(outputFile: string) {
let writer = createLineWrappingTextWriter(host.getNewLine(), columnWrap);
writer.write(`// <auto-generated />`);
writer.writeLine();
writer.write(`/// <reference path="parser.ts" />`);
writer.writeLine();
writer.write(`/// <reference path="factory.ts" />`);
writer.writeLine();
writer.write(`namespace ts {`);

View File

@@ -2814,9 +2814,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
return;
}
let parentNode = nodeStack.getParent();
emitToken(SyntaxKind.OpenBraceToken, node.pos);
increaseIndent();
let parentNode = nodeStack.getParent();
scopeEmitStart(parentNode);
if (node.kind === SyntaxKind.ModuleBlock) {
Debug.assert(parentNode.kind === SyntaxKind.ModuleDeclaration);

View File

@@ -1,5 +1,4 @@
// <auto-generated />
/// <reference path="parser.ts" />
/// <reference path="factory.ts" />
namespace ts {
export namespace factory {
@@ -2889,6 +2888,9 @@ namespace ts {
export function isEnumMember(node: Node): node is EnumMember {
return node && node.kind === SyntaxKind.EnumMember;
}
export function isSourceFile(node: Node): node is SourceFile {
return node && node.kind === SyntaxKind.SourceFile;
}
export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression {
return node && node.kind === SyntaxKind.JSDocTypeExpression;
}
@@ -3187,6 +3189,7 @@ namespace ts {
case SyntaxKind.JSDocReturnTag:
case SyntaxKind.JSDocTypeTag:
case SyntaxKind.JSDocParameterTag:
case SyntaxKind.SourceFile:
return true;
}
}

View File

@@ -10,7 +10,7 @@ namespace ts {
export function createNode<T extends Node>(kind: SyntaxKind): T {
return factory.createNode<T>(kind);
}
// @internal
export namespace factory {
export function setNodeFlags<T extends Node>(node: T, flags: NodeFlags): T {
@@ -129,6 +129,16 @@ namespace ts {
return node;
}
export function updateSourceFile(node: SourceFile, statements: NodeArray<Statement>, endOfFileToken: Node): SourceFile {
if (statements !== node.statements || endOfFileToken !== node.endOfFileToken) {
let newNode = createSourceFile();
newNode.statements = statements;
newNode.endOfFileToken = endOfFileToken;
return updateFrom(node, newNode);
}
return node;
}
export function createNumericLiteral2(value: number, location?: TextRange, flags?: NodeFlags): LiteralExpression {
let node = factory.createNumericLiteral(String(value), location, flags);
return node;

View File

@@ -600,6 +600,11 @@ namespace ts.transform {
<EnumMember>node,
<DeclarationName>visitNode((<EnumMember>node).name, visitor),
<Expression>visitNode((<EnumMember>node).initializer, visitor)));
case SyntaxKind.SourceFile:
return write(factory.updateSourceFile(
<SourceFile>node,
<NodeArray<Statement>>visitNodes((<SourceFile>node).statements, visitor),
(<SourceFile>node).endOfFileToken));
case SyntaxKind.JSDocTypeExpression:
return write(factory.updateJSDocTypeExpression(
<JSDocTypeExpression>node,

View File

@@ -4,14 +4,6 @@ const FORCE_TRANSFORMS = false;
/* @internal */
namespace ts {
// Flags enum to track count of temp variables and a few dedicated names
const enum TempFlags {
Auto = 0x00000000, // No preferred name
CountMask = 0x0FFFFFFF, // Temp variable counter
_i = 0x10000000, // Use/preference flag for '_i'
}
/**
* Computes the transform flags for a node, given the transform flags of its subtree
* @param node The node to analyze
@@ -261,8 +253,23 @@ namespace ts {
_compilerOptions: CompilerOptions, _currentSourceFile: SourceFile, _resolver: EmitResolver, _generatedNameSet: Map<string>, _nodeToGeneratedName: string[]) {
return transform.runTransformationChain(statements, chain, _compilerOptions, _currentSourceFile, _resolver, _generatedNameSet, _nodeToGeneratedName);
}
export type Visitor = (input: Node, output: (node: Node) => void) => void;
export const enum VisitorFlags {
NewLexicalEnvironment = 1 << 1,
PreserveStack = 1 << 2,
ReturnUndefinedIfEmpty = 1 << 3,
}
export namespace transform {
// Flags enum to track count of temp variables and a few dedicated names
const enum TempFlags {
Auto = 0x00000000, // No preferred name
CountMask = 0x0FFFFFFF, // Temp variable counter
_i = 0x10000000, // Use/preference flag for '_i'
}
let transformationRunning: boolean;
let transformFlags: TransformFlags;
let generatedNameSet: Map<string>;
@@ -277,10 +284,7 @@ namespace ts {
let resolver: EmitResolver;
// node stack
let nodeStackSize: number;
let ancestorStack: Node[];
let parentNode: Node;
let currentNode: Node;
let nodeStack: NodeStack;
// single node transform
let updatedNode: Node;
@@ -315,9 +319,8 @@ namespace ts {
generatedNameSet = _generatedNameSet;
nodeToGeneratedName = _nodeToGeneratedName;
nodeToGeneratedIdentifier = [];
ancestorStack = [];
nodeStackSize = 1;
currentNode = _currentSourceFile;
nodeStack = createNodeStack();
nodeStack.pushNode(_currentSourceFile);
transformationRunning = true;
}
@@ -329,18 +332,14 @@ namespace ts {
generatedNameSet = undefined;
nodeToGeneratedName = undefined;
nodeToGeneratedIdentifier = undefined;
ancestorStack = undefined;
nodeStackSize = undefined;
currentNode = undefined;
nodeStack = undefined;
transformationRunning = false;
}
// Return the next available name in the pattern _a ... _z, _0, _1, ...
// TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name.
// Note that names generated by makeTempVariableName and makeUniqueName will never conflict.
export function makeTempVariableName(flags: TempFlags): string {
function makeTempVariableName(flags: TempFlags): string {
if (flags && !(tempFlags & flags)) {
let name = flags === TempFlags._i ? "_i" : "_n";
if (isUniqueName(name)) {
@@ -458,21 +457,6 @@ namespace ts {
return makeUniqueName("class");
}
function pushNode(node: Node): void {
nodeStackSize++;
if (nodeStackSize > 2) {
ancestorStack.push(parentNode);
}
parentNode = currentNode;
currentNode = node;
}
function popNode(): void {
currentNode = parentNode;
parentNode = nodeStackSize > 2 ? ancestorStack.pop() : undefined;
nodeStackSize--;
}
export function getEmitResolver(): EmitResolver {
return resolver;
}
@@ -481,32 +465,22 @@ namespace ts {
return compilerOptions;
}
export function createParentNavigator(): ParentNavigator {
return nodeStack.createParentNavigator();
}
export function getCurrentNode(): Node {
return currentNode;
return nodeStack.getNode();
}
export function getParentNode(): Node {
return parentNode;
return nodeStack.getParent();
}
export function peekNode(offset: number): Node {
switch (offset) {
case 0: return currentNode;
case 1: return parentNode;
default: return nodeStackSize > 2 ? ancestorStack[nodeStackSize - 1 - offset] : undefined;
}
}
export function findAncestorNode<T extends Node>(match: (node: Node) => node is T): T;
export function findAncestorNode(match: (node: Node) => boolean): Node;
export function findAncestorNode(match: (node: Node) => boolean) {
for (let i = 1; i < nodeStackSize; i++) {
let node = peekNode(i);
if (match(node)) {
return node;
}
}
return undefined;
return nodeStack.findAncestorNode(match);
}
export function getDeclarationName(node: DeclarationStatement): Identifier;
@@ -698,12 +672,12 @@ namespace ts {
updatedNodes.push(node);
}
function readNodeArray(returnUndefinedIfEmpty?: boolean): NodeArray<Node> {
function readNodeArray(flags: VisitorFlags): NodeArray<Node> {
if (updatedNodes) {
return factory.createNodeArray(updatedNodes, /*location*/ <NodeArray<Node>>originalNodes);
}
else if (offsetWritten !== originalNodes.length) {
if (offsetWritten === 0 && returnUndefinedIfEmpty) {
if (offsetWritten === 0 && (flags & VisitorFlags.ReturnUndefinedIfEmpty)) {
return undefined;
}
else {
@@ -715,31 +689,42 @@ namespace ts {
}
}
type Visitor = (input: Node, output: (node: Node) => void) => void;
function pipeOne(input: Node, output: (node: Node) => void, visitor: Visitor): void {
pushNode(input);
visitor(input, output);
popNode();
}
function pipeMany(input: Node[], output: (node: Node) => void, visitor: Visitor): void {
// For perf reasons, we push `undefined` as the current node and set it to the correct
// value for each iteration of the loop below. This avoids excessive push and pop
// operations on `ancestorStack`.
pushNode(/*node*/ undefined);
// Visit each input node
for (let i = 0, l = input.length; i < l; ++i) {
currentNode = input[i];
visitor(currentNode, output);
function pipeOne(input: Node, output: (node: Node) => void, visitor: Visitor, flags: VisitorFlags): void {
if (!(flags & VisitorFlags.PreserveStack)) {
nodeStack.pushNode(input);
visitor(input, output);
nodeStack.popNode();
}
else {
visitor(input, output);
}
// For the perf reasons mentioned above, we pop the current node at the end of the loop.
popNode();
}
function pipeOneOrMany<T extends Node | Node[]>(input: T, output: (node: Node) => void, visitor: Visitor, newLexicalEnvironment: boolean, pipe: (input: T, output: (node: Node) => void, visitor: Visitor) => void): void {
function pipeMany(input: Node[], output: (node: Node) => void, visitor: Visitor, flags: VisitorFlags): void {
if (!(flags & VisitorFlags.PreserveStack)) {
// For perf reasons, we push `undefined` as the current node and set it to the correct
// value for each iteration of the loop below. This avoids excessive push and pop
// operations on `ancestorStack`.
nodeStack.pushNode(/*node*/ undefined);
// Visit each input node
for (let i = 0, l = input.length; i < l; ++i) {
let currentNode = input[i];
nodeStack.setNode(currentNode);
visitor(currentNode, output);
}
// For the perf reasons mentioned above, we pop the current node at the end of the loop.
nodeStack.popNode();
}
else {
for (let node of input) {
visitor(node, output);
}
}
}
function pipeOneOrMany<T extends Node | Node[]>(input: T, output: (node: Node) => void, visitor: Visitor, flags: VisitorFlags, pipe: (input: T, output: (node: Node) => void, visitor: Visitor, flags: VisitorFlags) => void): void {
if (!input) {
return;
}
@@ -751,7 +736,7 @@ namespace ts {
// If we are starting a new lexical environment, we need to reinitialize the lexical
// environment state as well
if (newLexicalEnvironment) {
if (flags & VisitorFlags.NewLexicalEnvironment) {
savedTempFlags = tempFlags;
savedHoistedVariableDeclarations = hoistedVariableDeclarations;
savedHoistedFunctionDeclarations = hoistedFunctionDeclarations;
@@ -761,11 +746,11 @@ namespace ts {
hoistedFunctionDeclarations = undefined;
}
pipe(input, output, visitor);
pipe(input, output, visitor, flags & ~VisitorFlags.NewLexicalEnvironment);
// If we established a new lexical environment, we need to write any hoisted variables or
// function declarations to the end of the output.
if (newLexicalEnvironment) {
if (flags & VisitorFlags.NewLexicalEnvironment) {
if (hoistedVariableDeclarations) {
output(factory.createVariableStatement2(
factory.createVariableDeclarationList(
@@ -793,8 +778,8 @@ namespace ts {
* @param visitor The callback to execute as we visit each node in the source.
* @param newLexicalEnvironment A value that indicates whether this pipeline starts a new lexical environment.
*/
export function pipeNode(input: Node, output: (node: Node) => void, visitor: Visitor, newLexicalEnvironment?: boolean): void {
pipeOneOrMany(input, output, visitor, newLexicalEnvironment, pipeOne);
export function pipeNode(input: Node, output: (node: Node) => void, visitor: Visitor, flags?: VisitorFlags): void {
pipeOneOrMany(input, output, visitor, flags, pipeOne);
}
/**
@@ -804,11 +789,11 @@ namespace ts {
* @param visitor The callback to execute as we visit each node in the source.
* @param newLexicalEnvironment A value that indicates whether this pipeline starts a new lexical environment.
*/
export function pipeNodes(input: Node[], output: (node: Node) => void, visitor: Visitor, newLexicalEnvironment?: boolean): void {
pipeOneOrMany(input, output, visitor, newLexicalEnvironment, pipeMany);
export function pipeNodes(input: Node[], output: (node: Node) => void, visitor: Visitor, flags?: VisitorFlags): void {
pipeOneOrMany(input, output, visitor, flags, pipeMany);
}
function emitOneOrMany<T extends Node | Node[]>(input: T, output: Node[], visitor: Visitor, newLexicalEnvironment: boolean, pipe: (input: T, output: (node: Node) => void, visitor: Visitor, newLexicalEnvironment: boolean) => void): void {
function emitOneOrMany<T extends Node | Node[]>(input: T, output: Node[], visitor: Visitor, flags: VisitorFlags, pipe: (input: T, output: (node: Node) => void, visitor: Visitor, flags: VisitorFlags) => void): void {
// Exit early if we have nothing to do
if (!input) {
return;
@@ -826,7 +811,7 @@ namespace ts {
offsetWritten = 0;
writeNodeToNodeArrayFastOrSlow = writeNodeToNodeArrayFast;
pipe(input, writeNodeToNodeArray, visitor, newLexicalEnvironment);
pipe(input, writeNodeToNodeArray, visitor, flags | VisitorFlags.PreserveStack);
// Restore previous environment
originalNodes = savedOriginalNodes;
@@ -842,8 +827,8 @@ namespace ts {
* @param visitor The callback to execute as we visit each node in the source.
* @param newLexicalEnvironment A value that indicates whether this pipeline starts a new lexical environment.
*/
export function emitNode(input: Node, output: Node[], visitor: (input: Node, write: (output: Node) => void) => void, newLexicalEnvironment?: boolean): void {
emitOneOrMany(input, output, visitor, newLexicalEnvironment, pipeOne);
export function emitNode(input: Node, output: Node[], visitor: (input: Node, write: (output: Node) => void) => void, flags?: VisitorFlags): void {
emitOneOrMany(input, output, visitor, flags, pipeOne);
}
/**
@@ -853,13 +838,15 @@ namespace ts {
* @param visitor The callback to execute as we visit each node in the source.
* @param newLexicalEnvironment A value that indicates whether this pipeline starts a new lexical environment.
*/
export function emitNodes(input: Node[], output: Node[], visitor: (input: Node, write: (output: Node) => void) => void, newLexicalEnvironment?: boolean): void {
emitOneOrMany(input, output, visitor, newLexicalEnvironment, pipeMany);
export function emitNodes(input: Node[], output: Node[], visitor: (input: Node, write: (output: Node) => void) => void, flags?: VisitorFlags): void {
emitOneOrMany(input, output, visitor, flags, pipeMany);
}
export function visitNode<T extends Node>(node: T, visitor: (input: Node, write: (node: Node) => void) => void): T {
export function visitNode<T extends Node>(node: T, visitor: (input: Node, write: (node: Node) => void) => void, flags?: VisitorFlags): T;
export function visitNode<TIn extends Node, TOut extends Node>(node: TIn, visitor: (input: TIn, write: (node: TOut) => void) => void, flags?: VisitorFlags): TOut;
export function visitNode<TIn extends Node, TOut extends Node>(node: TIn, visitor: (input: TIn, write: (node: TOut) => void) => void, flags?: VisitorFlags): TOut {
if (!node) {
return node;
return undefined;
}
let savedUpdatedNode = updatedNode;
@@ -867,16 +854,16 @@ namespace ts {
updatedNode = undefined;
writeNodeFastOrSlow = writeNodeSlow;
pipeNode(node, writeNode, visitor);
pipeNode(node, writeNode, visitor, flags);
let visited = <T>readNode();
let visited = <TOut>readNode();
updatedNode = savedUpdatedNode;
writeNodeFastOrSlow = savedWriteOneNode;
return visited;
}
export function visitStatement(node: Statement, visitor: (input: Node, write: (node: Node) => void) => void) {
export function visitStatement(node: Statement, visitor: (input: Node, write: (node: Node) => void) => void, flags?: VisitorFlags) {
if (!node) {
return node;
}
@@ -889,7 +876,7 @@ namespace ts {
updatedBlock = undefined;
writeStatementFastOrSlow = writeStatementSlow;
pipeNode(node, writeStatement, visitor);
pipeNode(node, writeStatement, visitor, flags);
let visited = readStatement();
updatedStatement = savedUpdatedStatement;
@@ -899,10 +886,9 @@ namespace ts {
return visited;
}
export function visitNodes(nodes: Statement[], visitor: (input: Node, output: (node: Node) => void) => void, newLexicalEnvironment: boolean): NodeArray<Statement>;
export function visitNodes<T extends Node>(nodes: T[], visitor: (input: Node, output: (node: Node) => void) => void): NodeArray<T>;
export function visitNodes<TIn extends Node, TOut extends Node>(nodes: TIn[], visitor: (input: TIn, output: (node: TOut) => void) => void, newLexicalEnvironment?: boolean, returnUndefinedIfEmpty?: boolean): NodeArray<TOut>;
export function visitNodes<TIn extends Node, TOut extends Node>(nodes: TIn[], visitor: (input: TIn, output: (node: TOut) => void) => void, newLexicalEnvironment?: boolean, returnUndefinedIfEmpty?: boolean): NodeArray<TOut> {
export function visitNodes<T extends Node>(nodes: T[], visitor: (input: Node, output: (node: Node) => void) => void, flags?: VisitorFlags): NodeArray<T>;
export function visitNodes<TIn extends Node, TOut extends Node>(nodes: TIn[], visitor: (input: TIn, output: (node: TOut) => void) => void, flags?: VisitorFlags): NodeArray<TOut>;
export function visitNodes<TIn extends Node, TOut extends Node>(nodes: TIn[], visitor: (input: TIn, output: (node: TOut) => void) => void, flags?: VisitorFlags): NodeArray<TOut> {
// Exit early if we have nothing to do
if (!nodes) {
return undefined;
@@ -921,9 +907,9 @@ namespace ts {
writeNodeToNodeArrayFastOrSlow = writeNodeToNodeArraySlow;
// Pipe each node from input into output
pipeNodes(originalNodes, writeNodeToNodeArray, visitor, newLexicalEnvironment);
pipeNodes(originalNodes, writeNodeToNodeArray, visitor, flags);
let visited = readNodeArray(returnUndefinedIfEmpty);
let visited = readNodeArray(flags);
// Restore previous environment
originalNodes = savedOriginalNodes;
@@ -973,13 +959,13 @@ namespace ts {
case SyntaxKind.Block:
return factory.updateBlock(
<Block>node,
visitNodes((<Block>node).statements, visitor, /*newLexicalEnvironment*/ true)
visitNodes((<Block>node).statements, visitor, VisitorFlags.NewLexicalEnvironment)
);
case SyntaxKind.ModuleBlock:
return factory.updateModuleBlock(
<ModuleBlock>node,
visitNodes((<ModuleBlock>node).statements, visitor, /*newLexicalEnvironment*/ true)
visitNodes((<ModuleBlock>node).statements, visitor, VisitorFlags.NewLexicalEnvironment)
);
default:

View File

@@ -2,7 +2,7 @@
/*@internal*/
namespace ts.transform {
export function toES5(statements: NodeArray<Statement>) {
return visitNodes(statements, transformNode, /*newLexicalEnvironment*/ true);
return visitNodes(statements, transformNode, VisitorFlags.NewLexicalEnvironment);
}
/**
@@ -153,7 +153,7 @@ namespace ts.transform {
let body = factory.createBlock([]);
if (constructor) {
emitNode(constructor, body.statements, transformConstructor, /*newLexicalEnvironment*/ true);
emitNode(constructor, body.statements, transformConstructor, VisitorFlags.NewLexicalEnvironment);
}
else if (baseTypeNode) {
let superCall = createDefaultSuperCall();
@@ -453,14 +453,14 @@ namespace ts.transform {
function rewriteFunctionExpression(node: FunctionLikeDeclaration, name: Identifier, location: TextRange): FunctionExpression {
let parameters = visitNodes(node.parameters, transformNode);
let body = factory.createBlock([], node.body);
emitNode(node, body.statements, transformFunctionBody, /*newLexicalEnvironment*/ true);
emitNode(node, body.statements, transformFunctionBody, VisitorFlags.NewLexicalEnvironment);
return factory.createFunctionExpression2(name, parameters, body, location);
}
function transformFunctionDeclaration(node: FunctionDeclaration, write: (node: Statement) => void): void {
let parameters = visitNodes(node.parameters, transformNode);
let body = factory.createBlock([], node.body);
emitNode(node, body.statements, transformFunctionBody, /*newLexicalEnvironment*/ true);
emitNode(node, body.statements, transformFunctionBody, VisitorFlags.NewLexicalEnvironment);
write(factory.createFunctionDeclaration2(node.name, parameters, body, /*location*/ node));
}
@@ -469,7 +469,7 @@ namespace ts.transform {
let parameters = visitNodes(node.parameters, transformNode);
let newBody = factory.createBlock([], /*location*/ isBlock(node.body) ? node.body : undefined);
emitNode(node, newBody.statements, transformFunctionBody, /*newLexicalEnvironment*/ true);
emitNode(node, newBody.statements, transformFunctionBody, VisitorFlags.NewLexicalEnvironment);
let func = createfn(name, parameters, newBody, location);
return func;
@@ -526,7 +526,7 @@ namespace ts.transform {
}
function transformThisKeyword(node: LeftHandSideExpression): LeftHandSideExpression {
let container = getThisContainer(node, /*includeArrowFunctions*/ true);
let container = getThisContainer(transform, /*includeArrowFunctions*/ true);
if (isArrowFunction(container)) {
let thisName = factory.createIdentifier("_this");
return thisName;

View File

@@ -9,7 +9,7 @@ namespace ts.transform {
resolver = getEmitResolver();
compilerOptions = getCompilerOptions();
languageVersion = compilerOptions.target || ScriptTarget.ES3;
return visitNodes(statements, transformNode, /*newLexicalEnvironment*/ true);
return visitNodes(statements, transformNode, VisitorFlags.NewLexicalEnvironment);
}
/**
@@ -74,24 +74,6 @@ namespace ts.transform {
}
switch (node.kind) {
// case SyntaxKind.Block:
// case SyntaxKind.ModuleBlock:
// case SyntaxKind.CaseClause:
// case SyntaxKind.DefaultClause:
// // These nodes contain statement lists which may need to be expanded to include multiple statements...
// // See NodeArraywrite in transform.ts for approach
// case SyntaxKind.DoStatement:
// case SyntaxKind.WhileStatement:
// case SyntaxKind.ForStatement:
// case SyntaxKind.ForInStatement:
// case SyntaxKind.ForOfStatement:
// case SyntaxKind.IfStatement:
// case SyntaxKind.LabeledStatement:
// case SyntaxKind.WithStatement:
// // These nodes contain single statement nodes that may need to be switched to a block if a child node needs multiple statements...
// // See Statementwrite in transform.ts for approach
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
@@ -100,6 +82,7 @@ namespace ts.transform {
case SyntaxKind.ConstKeyword:
case SyntaxKind.DeclareKeyword:
// TypeScript accessibility modifiers are elided.
return;
case SyntaxKind.ArrayType:
case SyntaxKind.TupleType:
@@ -118,31 +101,37 @@ namespace ts.transform {
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
// TypeScript type nodes are elided.
return;
case SyntaxKind.IndexSignature:
// TypeScript index signatures are elided.
return;
case SyntaxKind.Decorator:
// TypeScript decorators are elided. They will be emitted as part of transformClassDeclaration.
return;
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
// TypeScript type-only declarations are elided
return;
case SyntaxKind.PropertyDeclaration:
// TypeScript property declarations are elided.
return;
case SyntaxKind.IndexSignature:
// TypeScript index signatures are elided.
return;
case SyntaxKind.Constructor:
// TypeScript constructors are elided. The constructor of a class will be
// reordered to the start of the member list in `transformClassDeclaration`.
return;
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
// TypeScript interfaces and type aliases are elided.
return;
case SyntaxKind.ClassDeclaration:
@@ -233,9 +222,9 @@ namespace ts.transform {
// TypeScript 'await' expressions must be transformed.
return transformAwaitExpression(<AwaitExpression>node, write);
// case SyntaxKind.VariableStatement:
// // TypeScript namespace exports for variable statements must be transformed.
// return transformVariableStatement(<VariableStatement>node, write);
case SyntaxKind.VariableStatement:
// TypeScript namespace exports for variable statements must be transformed.
return transformVariableStatement(<VariableStatement>node, write);
case SyntaxKind.ModuleDeclaration:
// TypeScript namespace declarations must be transformed.
@@ -362,7 +351,7 @@ namespace ts.transform {
let name = <Identifier>getDeclarationName(node);
Debug.assert(isIdentifier(name));
if (getCombinedNodeFlags(node) & NodeFlags.Export) {
if (getCombinedNodeFlags(transform) & NodeFlags.Export) {
let container = getContainingModuleName();
let propExpr = factory.createPropertyAccessExpression2(container, name);
return propExpr;
@@ -788,16 +777,27 @@ namespace ts.transform {
}
function transformVariableDeclarationList(node: VariableDeclarationList, write: (node: Statement) => void) {
let expressions = visitNodes<VariableDeclaration, Expression>(node.declarations, transformVariableDeclaration, /*newLexicalEnvironment*/ false, /*returnUndefinedIfEmpty*/ true);
if (expressions) {
let expressions: Expression[] = [];
emitNodes(node.declarations, expressions, transformVariableDeclaration);
if (expressions.length) {
let exprStmt = factory.createExpressionStatement(factory.inlineExpressions(expressions));
write(exprStmt);
}
}
function transformVariableDeclaration(node: VariableDeclaration, write: (node: Expression) => void) {
if (isBindingPattern(node.name)) {
Debug.fail("Transform not yet supported.");
if (!node.initializer) {
return;
}
let name = node.name;
if (isBindingPattern(name)) {
let expr = visitNode<BindingPattern, Expression>(name, transformBindingPatternToExpression);
let initializer = visitNode(node.initializer, transformNode);
let assignExpr = factory.createAssignmentExpression(expr, initializer);
let parenExpr = factory.createParenthesizedExpression(assignExpr);
write(parenExpr);
}
else {
let name = getModuleMemberName(node);
@@ -806,6 +806,27 @@ namespace ts.transform {
write(assignExpr);
}
}
function transformBindingPatternToExpression(node: BindingPattern, write: (node: Expression) => void) {
switch (node.kind) {
case SyntaxKind.ObjectBindingPattern:
return transformObjectBindingPatternToExpression(<ObjectBindingPattern>node, write);
case SyntaxKind.ArrayBindingPattern:
return transformArrayBindingPatternToExpression(<ObjectBindingPattern>node, write);
}
}
function transformObjectBindingPatternToExpression(node: ObjectBindingPattern, write: (node: Expression) => void) {
let properties: ObjectLiteralElement[] = [];
write(factory.createObjectLiteralExpression2(properties));
}
function transformArrayBindingPatternToExpression(node: ArrayBindingPattern, write: (node: Expression) => void) {
let elements: Expression[] = [];
write(factory.createArrayLiteralExpression(elements));
}
function transformModuleDeclaration(node: ModuleDeclaration, write: (node: Statement) => void) {
if (!shouldEmitModuleDeclaration(node)) {

View File

@@ -1830,8 +1830,10 @@ namespace ts {
}
// Source files are declarations when they are external modules.
// @kind(SyntaxKind.SourceFile)
// @factoryhidden
// @kind(SyntaxKind.SourceFile, { create: false, update: false })
// @factoryhidden("decorators")
// @factoryhidden("modifiers")
// @factoryhidden("name")
export interface SourceFile extends Declaration {
statements: NodeArray<Statement>;
endOfFileToken: Node;
@@ -1861,6 +1863,7 @@ namespace ts {
languageVersion: ScriptTarget;
// The first node that causes this file to be an external module
// @factoryhidden
/* @internal */ externalModuleIndicator: Node;
/* @internal */ isDefaultLib: boolean;

View File

@@ -391,7 +391,7 @@ namespace ts {
return flags;
}
export function isConst(navigable: ParentNavigable): boolean {
return !!(getCombinedNodeFlags(navigable) & NodeFlags.Const);
}
@@ -717,7 +717,7 @@ namespace ts {
break;
case SyntaxKind.Decorator:
// Decorators are always applied outside of the body of a class or method.
if (nav.getParent().kind === SyntaxKind.Parameter && isClassElement(nav.getGrandparent())) {
if (isParameter(nav.getParent()) && isClassElement(nav.getGrandparent())) {
// If the decorator's parent is a Parameter, we resolve the this container from
// the grandparent class declaration.
nav.moveToParent();
@@ -773,7 +773,8 @@ namespace ts {
break;
case SyntaxKind.Decorator:
// Decorators are always applied outside of the body of a class or method.
if (nav.getParent().kind === SyntaxKind.Parameter && isClassElement(nav.getGrandparent())) {
if (isParameter(nav.getParent())
&& isClassElement(nav.getGrandparent())) {
// If the decorator's parent is a Parameter, we resolve the this container from
// the grandparent class declaration.
nav.moveToParent();

View File

@@ -225,7 +225,7 @@ namespace ts {
public getText(sourceFile?: SourceFile): string {
return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
}
private addSyntheticNodes(nodes: Node[], pos: number, end: number): number {
scanner.setTextPos(pos);
while (pos < end) {