Cleanup and organization

This commit is contained in:
Ron Buckton
2015-09-12 15:32:05 -07:00
parent 380452becb
commit f15d20b9f2
15 changed files with 413 additions and 582 deletions
+37 -3
View File
@@ -532,7 +532,7 @@ function generateFactory(outputFile: string) {
return;
}
// Skip the is function for this node if it is already defined
// Skip the is function for this node if it is already defined
if (resolveQualifiedName(factorySourceFile, `ts.is${syntaxNode.kindName}`, SymbolFlags.Function)) {
return;
}
@@ -552,8 +552,24 @@ function generateFactory(outputFile: string) {
return;
}
let typeNames = splitTypeName(typeName);
let nodeTestFunction: string;
if (typeNames.length === 1) {
let typeSymbol = resolveExportedQualifiedName(tsModuleSymbol, typeName, SymbolFlags.Type);
if (typeSymbol) {
let nodeTestAnnotation = findFirstAnnotation(typeSymbol, NodeTestAnnotation.match);
if (nodeTestAnnotation) {
nodeTestFunction = nodeTestAnnotation.functionName;
}
}
}
if (!nodeTestFunction) {
nodeTestFunction = `is${typeNameToMethodNameSuffix(typeName)}`;
}
// Skip the is function for this type if it is already defined in factory.ts
if (resolveQualifiedName(factorySourceFile, `ts.is${typeNameToMethodNameSuffix(typeName)}`, SymbolFlags.Function)) {
if (resolveQualifiedName(factorySourceFile, `ts.${nodeTestFunction}`, SymbolFlags.Function)) {
return;
}
@@ -562,7 +578,7 @@ function generateFactory(outputFile: string) {
return;
}
writer.write(`export function is${typeNameToMethodNameSuffix(typeName)}(node: Node): node is ${typeName} {`);
writer.write(`export function ${nodeTestFunction}(node: Node): node is ${typeName} {`);
writer.writeLine();
writer.increaseIndent();
@@ -1307,6 +1323,8 @@ function createLineWrappingTextWriter(newLine: string, maxWidth: number): EmitTe
// Annotations
//
function findFirstAnnotation<TAnnotation extends Annotation>(symbol: Symbol, match: (annotation: Annotation) => annotation is TAnnotation): TAnnotation;
function findFirstAnnotation<TAnnotation extends Annotation>(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation;
function findFirstAnnotation<TAnnotation extends Annotation>(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation {
for (let annotation of getAnnotations(symbol)) {
if (match(annotation)) {
@@ -1317,6 +1335,8 @@ function findFirstAnnotation<TAnnotation extends Annotation>(symbol: Symbol, mat
return undefined;
}
function findAllAnnotations<TAnnotation extends Annotation>(symbol: Symbol, match: (annotation: Annotation) => annotation is TAnnotation): TAnnotation[];
function findAllAnnotations<TAnnotation extends Annotation>(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation[];
function findAllAnnotations<TAnnotation extends Annotation>(symbol: Symbol, match: (annotation: Annotation) => boolean): TAnnotation[] {
let annotations: TAnnotation[];
for (let annotation of getAnnotations(symbol)) {
@@ -1570,6 +1590,20 @@ class NewLexicalEnvironmentAnnotation extends Annotation {
}
}
@annotation("nodetest")
class NodeTestAnnotation extends Annotation {
public name = "nodetest";
public functionName: string;
constructor([functionName, ..._arguments]: [string, any]) {
super(_arguments);
this.functionName = functionName
}
public static match(annotation: Annotation): annotation is NodeTestAnnotation {
return annotation instanceof NodeTestAnnotation;
}
}
function createAnnotation(name: string, _arguments: any[]): Annotation {
let ctor = getProperty(annotationConstructors, name);
if (ctor) {
+3 -3
View File
@@ -1400,7 +1400,7 @@ namespace ts {
}
function isEntityNameOrExpression(node: Node): node is EntityName | Expression {
return isEntityName(node) || isExpression(node);
return isEntityName(node) || isExpressionNode(node);
}
function isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult {
@@ -13951,7 +13951,7 @@ namespace ts {
(entityName.parent.kind === SyntaxKind.JsxClosingElement)) {
return getJsxElementTagSymbol(<JsxOpeningLikeElement>entityName.parent);
}
else if (isPartOfExpression(entityName)) {
else if (isExpression(entityName)) {
if (nodeIsMissing(entityName)) {
// Missing entity name.
return undefined;
@@ -14089,7 +14089,7 @@ namespace ts {
return getTypeFromTypeNode(<TypeNode>node);
}
if (isPartOfExpression(node)) {
if (isExpression(node)) {
return getTypeOfExpression(<Expression>node);
}
+41 -33
View File
@@ -189,6 +189,34 @@ namespace ts {
}
}
}
export function trimArray<T>(array: T[]): T[] {
let result: T[];
if (array) {
result = [];
for (let v of array) {
if (v !== undefined) {
result.push(v);
}
}
}
return result;
}
export function append<T>(to: T[], ...values: T[]): T[] {
let result: T[];
if (to) {
for (let v of values) {
if (v !== undefined) {
if (!result) {
result = to.slice(0);
}
result.push(v);
}
}
}
return result || to;
}
export function rangeEquals<T>(array1: T[], array2: T[], pos: number, end: number) {
while (pos < end) {
@@ -835,16 +863,6 @@ namespace ts {
* @param currentNode The current node for the navigator.
*/
export function createParentNavigator(currentNode: Node): ParentNavigator {
/** Traverses the parent pointers for the current node to find the root node. */
function getRoot() {
let rootNode = currentNode;
while (rootNode && rootNode.parent) {
rootNode = rootNode.parent;
}
return rootNode;
}
/** Gets the grandparent of the current node, without moving the navigator. */
function getGrandparent() {
let parent = getParent();
@@ -877,30 +895,17 @@ namespace ts {
return false;
}
/** Navigates to the root node for the current node. */
function moveToRoot(): boolean {
let rootNode = getRoot();
if (rootNode) {
currentNode = rootNode;
return true;
}
return false;
}
/** Creates a new ParentNavigator from the current node. */
function createParentNavigator() {
return ts.createParentNavigator(currentNode);
}
return {
getRoot,
getGrandparent,
getParent,
getNode,
getKind,
moveToParent,
moveToRoot,
createParentNavigator,
};
}
@@ -915,11 +920,6 @@ namespace ts {
let parentNode: Node;
let currentNode: Node;
/** Gets the node at the bottom of the stack. */
function getRoot() {
return rootNode;
}
/** Gets the node two steps back from the top of the stack. */
function getGrandparent() {
return peekNode(2);
@@ -953,6 +953,16 @@ namespace ts {
currentNode = node;
}
/** Pushes a node onto the stack if it is not already at the top of the stack. */
function tryPushNode(node: Node): boolean {
if (currentNode !== node) {
return false;
}
pushNode(node);
return true;
}
/** Pops the top node from the stack. */
function popNode(): void {
currentNode = parentNode;
@@ -985,7 +995,7 @@ namespace ts {
if (parentNode && match(parentNode)) {
return parentNode;
}
for (let i = stack.length; i >= 0; i--) {
for (let i = stack.length - 1; i >= 0; i--) {
let node = stack[i];
if (match(node)) {
return node;
@@ -1048,26 +1058,24 @@ namespace ts {
}
return {
getRoot,
getGrandparent,
getParent,
getNode,
getKind,
moveToRoot,
moveToParent,
createParentNavigator,
};
}
return {
getRoot,
getGrandparent,
getParent,
getNode,
getKind,
pushNode,
popNode,
tryPushNode,
setNode,
popNode,
findAncestorNode,
createParentNavigator,
};
+13 -7
View File
@@ -504,11 +504,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
function writeTextWithSpanRecord(tokenKind: SyntaxKind, startPos: number, emitFn?: () => void) {
let tokenStartPos = ts.skipTrivia(currentSourceFile.text, startPos);
recordSourceMapSpan(tokenStartPos);
let tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
recordSourceMapSpan(tokenEndPos);
return tokenEndPos;
if (!positionIsSynthesized(startPos)) {
let tokenStartPos = skipTrivia(currentSourceFile.text, startPos);
recordSourceMapSpan(tokenStartPos);
let tokenEndPos = emitTokenText(tokenKind, tokenStartPos, emitFn);
recordSourceMapSpan(tokenEndPos);
return tokenEndPos;
}
else {
emitTokenText(tokenKind, startPos, emitFn);
}
}
function recordNewSourceFileStart(node: SourceFile) {
@@ -1112,7 +1117,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
let nav = nodeStack.createParentNavigator();
nav.moveToParent();
let emitOuterParens = isPartOfExpression(nav) && templateNeedsParens(node);
let emitOuterParens = isExpression(nav) && templateNeedsParens(node);
if (emitOuterParens) {
write("(");
}
@@ -4389,7 +4394,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
pushNode(body);
let preambleEmitted = writer.getTextPos() !== initialTextPos;
if (!preambleEmitted && nodeEndIsOnSameLineAsNodeStart(body, body)
if (!preambleEmitted && !nodeIsSynthesized(body)
&& nodeEndIsOnSameLineAsNodeStart(body, body)
&& !isBlockWithSynthesizedStatementsOnNewLine(body)
&& (!nodeIsSynthesized(body) || isSingleLineSynthesizedBlock(body))) {
for (let statement of body.statements) {
+40 -1
View File
@@ -2967,7 +2967,7 @@ namespace ts {
}
return false;
}
export function isExpression(node: Node): node is Expression {
export function isExpressionNode(node: Node): node is Expression {
if (node) {
switch (node.kind) {
case SyntaxKind.OmittedExpression:
@@ -3386,6 +3386,45 @@ namespace ts {
}
return false;
}
export function isStatementNode(node: Node): node is Statement {
if (node) {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.Block:
case SyntaxKind.EmptyStatement:
case SyntaxKind.DebuggerStatement:
case SyntaxKind.MissingDeclaration:
case SyntaxKind.VariableStatement:
case SyntaxKind.ExpressionStatement:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.BreakStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.ReturnStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.LabeledStatement:
case SyntaxKind.ThrowStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ModuleBlock:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.ExportAssignment:
return true;
}
}
return false;
}
export function isExpressionOrVariableDeclarationList(node: Node): node is Expression | VariableDeclarationList {
if (node) {
switch (node.kind) {
+82 -327
View File
@@ -140,23 +140,20 @@ namespace ts {
}
export function createNumericLiteral2(value: number, location?: TextRange, flags?: NodeFlags): LiteralExpression {
let node = factory.createNumericLiteral(String(value), location, flags);
let node = createNumericLiteral(String(value), location, flags);
return node;
}
export function createPropertyAccessExpression2(expression: Expression, name: Identifier, location?: TextRange, flags?: NodeFlags) {
return factory.createPropertyAccessExpression(
factory.parenthesizeForAccess(expression),
factory.createNode(SyntaxKind.DotToken),
name,
location,
flags
);
return createPropertyAccessExpression(parenthesizeForAccess(expression), createNode(SyntaxKind.DotToken), name, location, flags);
}
export function createPropertyAccessExpression3(expression: Expression, name: string, location?: TextRange, flags?: NodeFlags) {
return createPropertyAccessExpression(parenthesizeForAccess(expression), createNode(SyntaxKind.DotToken), createIdentifier(name), location, flags);
}
export const enum BinaryOperand {
Left,
Right
export function makeSynthesized<TNode extends Node>(node: TNode): TNode {
return nodeIsSynthesized(node) ? node : cloneNode(node);
}
export function parenthesizeForBinary(expr: Expression, operator: SyntaxKind) {
@@ -175,7 +172,7 @@ namespace ts {
let operatorPrecedence = getBinaryOperatorPrecedence(operator);
if (exprPrecedence < operatorPrecedence) {
// lower precedence, the expression needs parenthesis
return factory.createParenthesizedExpression(expr);
return createParenthesizedExpression(expr);
}
else {
// higher precedence.
@@ -205,25 +202,15 @@ namespace ts {
return <LeftHandSideExpression>expr;
}
return factory.createParenthesizedExpression(expr);
return createParenthesizedExpression(expr);
}
export function createCallExpression2(expression: Expression, _arguments?: Expression[], location?: TextRange, flags?: NodeFlags) {
return factory.createCallExpression(
parenthesizeForAccess(expression),
/*typeArguments*/ undefined,
_arguments,
location,
flags
);
return createCallExpression(parenthesizeForAccess(expression), undefined, _arguments, location, flags);
}
export function createObjectLiteralExpression2(properties?: ObjectLiteralElement[]) {
return createObjectLiteralExpression(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createNodeArray(properties)
);
return createObjectLiteralExpression(undefined, undefined, createNodeArray(properties));
}
export function createAssignmentExpression(left: Expression, right: Expression) {
@@ -251,353 +238,150 @@ namespace ts {
}
export function createBinaryExpression2(left: Expression, operator: SyntaxKind, right: Expression) {
return factory.createBinaryExpression(
parenthesizeForBinary(left, operator),
factory.createNode(operator),
parenthesizeForBinary(right, operator)
);
return createBinaryExpression(parenthesizeForBinary(left, operator), createNode(operator), parenthesizeForBinary(right, operator));
}
export function createConditionalExpression2(condition: Expression, whenTrue: Expression, whenFalse: Expression, location?: TextRange, flags?: NodeFlags) {
return factory.createConditionalExpression(
condition,
factory.createNode(SyntaxKind.QuestionToken),
whenTrue,
factory.createNode(SyntaxKind.ColonToken),
whenFalse,
location,
flags
);
return createConditionalExpression(condition, createNode(SyntaxKind.QuestionToken), whenTrue, createNode(SyntaxKind.ColonToken), whenFalse, location, flags);
}
export function createParameter2(name: BindingPattern | Identifier, initializer?: Expression, location?: TextRange, flags?: NodeFlags) {
return factory.createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
name,
/*questionToken*/ undefined,
/*type*/ undefined,
initializer,
location,
flags
);
return createParameter(undefined, undefined, undefined, name, undefined, undefined, initializer, location, flags);
}
export function createRestParameter(name: Identifier, location?: TextRange, flags?: NodeFlags) {
return factory.createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
factory.createNode(SyntaxKind.DotDotDotToken),
name,
/*questionToken*/ undefined,
/*type*/ undefined,
/*initializer*/ undefined,
location,
flags
);
}
export function createVariableStatement2(declarationList: VariableDeclarationList, location?: TextRange, flags?: NodeFlags) {
return factory.createVariableStatement(
/*decorators*/ undefined,
/*modifiers*/ undefined,
declarationList,
location,
flags
);
return createParameter(undefined, undefined, createNode(SyntaxKind.DotDotDotToken), name, undefined, undefined, undefined, location, flags);
}
export function createVariableDeclaration2(name: Identifier | BindingPattern, initializer?: Expression, location?: TextRange, flags?: NodeFlags) {
return factory.createVariableDeclaration(
name,
/*type*/ undefined,
initializer,
location,
flags
);
return createVariableDeclaration(name, undefined, initializer, location, flags);
}
export function createClassDeclaration2(name: Identifier, heritageClause: HeritageClause, members: ClassElement[], location?: TextRange, flags?: NodeFlags): ClassDeclaration {
return factory.createClassDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
name,
/*typeParameters*/ undefined,
heritageClause ? [heritageClause] : undefined,
members,
location,
flags
);
export function createVariableStatement2(declarationList: VariableDeclarationList, location?: TextRange, flags?: NodeFlags) {
return createVariableStatement(undefined, undefined, declarationList, location, flags);
}
export function createSimpleLetStatement(name: Identifier, initializer: Expression, location?: TextRange, exported?: boolean) {
let varDecl = createVariableDeclaration2(name, initializer);
let varDeclList = createVariableDeclarationList([varDecl], undefined, NodeFlags.Let);
let varStmt = createVariableStatement2(varDeclList, location, exported ? NodeFlags.Export : 0);
return varStmt;
}
export function createExportDefaultStatement(expression: Expression): ExportAssignment {
return createExportAssignment(undefined, undefined, expression);
}
function createClassHeritageClauses(baseTypeNode: ExpressionWithTypeArguments) {
return baseTypeNode ? [createHeritageClause(SyntaxKind.ExtendsKeyword, [baseTypeNode])] : undefined;
}
export function createClassExpression2(name: Identifier, heritageClause: HeritageClause, members: ClassElement[]): ClassExpression {
return factory.createClassExpression(
/*decorators*/ undefined,
/*modifiers*/ undefined,
name,
/*typeParameters*/ undefined,
heritageClause ? [heritageClause] : undefined,
members
);
export function createClassDeclaration2(name: Identifier, baseTypeNode: ExpressionWithTypeArguments, members: ClassElement[], location?: TextRange, flags?: NodeFlags): ClassDeclaration {
return createClassDeclaration(undefined, undefined, name, undefined, createClassHeritageClauses(baseTypeNode), members, location, flags);
}
export function createClassExpression2(name: Identifier, baseTypeNode: ExpressionWithTypeArguments, members: ClassElement[]): ClassExpression {
return createClassExpression(undefined, undefined, name, undefined, createClassHeritageClauses(baseTypeNode), members);
}
export function createClassExpression3(baseTypeNode: ExpressionWithTypeArguments, members: ClassElement[]): ClassExpression {
return createClassExpression2(undefined, baseTypeNode, members);
}
export function createConstructor2(parameters: Array<ParameterDeclaration>, body: Block, location?: TextRange, flags?: NodeFlags): ConstructorDeclaration {
return factory.createConstructor(
/*decorators*/ undefined,
/*modifiers*/ undefined,
parameters,
/*type*/ undefined,
body,
location,
flags
);
return createConstructor(undefined, undefined, parameters, undefined, body, location, flags);
}
export function createMethodDeclaration2(name: PropertyName, parameters: Array<ParameterDeclaration>, body: Block, location?: TextRange, flags?: NodeFlags): MethodDeclaration {
return factory.createMethodDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
name,
/*typeParameters*/ undefined,
parameters,
/*type*/ undefined,
body,
location,
flags
);
return createMethodDeclaration(undefined, undefined, undefined, name, undefined, parameters, undefined, body, location, flags);
}
export function createGetAccessor2(name: PropertyName, parameters: Array<ParameterDeclaration>, body: Block, location?: TextRange, flags?: NodeFlags): GetAccessorDeclaration {
return factory.createGetAccessor(
/*decorators*/ undefined,
/*modifiers*/ undefined,
name,
parameters,
/*type*/ undefined,
body,
location,
flags
);
return createGetAccessor(undefined, undefined, name, parameters, undefined, body, location, flags);
}
export function createSetAccessor2(name: PropertyName, parameters: Array<ParameterDeclaration>, body: Block, location?: TextRange, flags?: NodeFlags): SetAccessorDeclaration {
return factory.createSetAccessor(
/*decorators*/ undefined,
/*modifiers*/ undefined,
name,
parameters,
/*type*/ undefined,
body,
location,
flags
);
return createSetAccessor(undefined, undefined, name, parameters, undefined, body, location, flags);
}
export function createFunctionDeclaration2(name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
return factory.createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
name,
/*typeParameters*/ undefined,
parameters,
/*type*/ undefined,
body,
location,
flags
);
return createFunctionDeclaration(undefined, undefined, undefined, name, undefined, parameters, undefined, body, location, flags);
}
export function createFunctionDeclaration3(asteriskToken: Node, name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
return factory.createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
asteriskToken,
name,
/*typeParameters*/ undefined,
parameters,
/*type*/ undefined,
body,
location,
flags
);
}
return createFunctionDeclaration(undefined, undefined, asteriskToken, name, undefined, parameters, undefined, body, location, flags);
}
export function createFunctionExpression2(name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
return factory.createFunctionExpression(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
name,
/*typeParameters*/ undefined,
parameters,
/*type*/ undefined,
body,
location,
flags
);
return createFunctionExpression(undefined, undefined, undefined, name, undefined, parameters, undefined, body, location, flags);
}
export function createFunctionExpression3(asteriskToken: Node, name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
return factory.createFunctionExpression(
/*decorators*/ undefined,
/*modifiers*/ undefined,
asteriskToken,
name,
/*typeParameters*/ undefined,
parameters,
/*type*/ undefined,
body,
location,
flags
);
return createFunctionExpression(undefined, undefined, asteriskToken, name, undefined, parameters, undefined, body, location, flags);
}
export function createGeneratorFunctionExpression(name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
return factory.createFunctionExpression(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createNode(SyntaxKind.AsteriskToken),
name,
/*typeParameters*/ undefined,
parameters,
/*type*/ undefined,
body,
location,
flags
);
export function createGeneratorFunctionExpression(parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
return createFunctionExpression(undefined, undefined, createNode(SyntaxKind.AsteriskToken), undefined, undefined, parameters, undefined, body, location, flags);
}
export function createVoidZeroExpression(location?: TextRange, flags?: NodeFlags): VoidExpression {
return factory.createVoidExpression(
factory.createNumericLiteral2(0),
location,
flags);
return createVoidExpression(createNumericLiteral2(0), location, flags);
}
export function createPropertyOrElementAccessExpression(expression: Expression, propName: Identifier | LiteralExpression, location?: TextRange, flags?: NodeFlags): LeftHandSideExpression {
if (!nodeIsSynthesized(propName)) {
propName = cloneNode(propName);
}
if (propName.kind !== SyntaxKind.Identifier) {
return createElementAccessExpression2(expression, propName, location, flags);
}
return createPropertyAccessExpression2(expression, <Identifier>propName, location, flags);
return isIdentifier(propName)
? createPropertyAccessExpression2(expression, makeSynthesized(propName), location, flags)
: createElementAccessExpression2(expression, makeSynthesized(propName), location, flags);
}
export function createElementAccessExpression2(expression: Expression, argumentExpression: Expression, location?: TextRange, flags?: NodeFlags): ElementAccessExpression {
return factory.createElementAccessExpression(
factory.parenthesizeForAccess(expression),
argumentExpression,
location,
flags
);
return createElementAccessExpression(parenthesizeForAccess(expression), argumentExpression, location, flags);
}
export function createElementAccessExpression3(expression: Expression, index: number, location?: TextRange, flags?: NodeFlags): ElementAccessExpression {
return factory.createElementAccessExpression2(
expression,
factory.createNumericLiteral2(index),
location,
flags
);
return createElementAccessExpression2(expression, createNumericLiteral2(index), location, flags);
}
export function createSliceCall(value: Expression, sliceIndex: number, location?: TextRange, flags?: NodeFlags): CallExpression {
return factory.createCallExpression2(
factory.createPropertyAccessExpression2(
factory.parenthesizeForAccess(value),
factory.createIdentifier("slice")
),
[factory.createNumericLiteral2(sliceIndex)],
location,
flags
);
return createCallExpression2(createPropertyAccessExpression3(value, "slice"), [createNumericLiteral2(sliceIndex)], location, flags);
}
export function createApplyCall(target: Expression, thisArg: Expression, _arguments: Expression, location?: TextRange, flags?: NodeFlags) {
let applyName = createIdentifier("apply");
let propExpr = createPropertyAccessExpression2(target, applyName);
return factory.createCallExpression2(propExpr, [thisArg, _arguments], location, flags);
return factory.createCallExpression2(createPropertyAccessExpression3(target, "apply"), [thisArg, _arguments], location, flags);
}
export function createExtendsHelperCall(name: Identifier) {
let extendsName = factory.createIdentifier("__extends");
let superName = factory.createIdentifier("_super");
let callExpr = factory.createCallExpression2(extendsName, [name, superName]);
return callExpr;
return factory.createCallExpression2(createIdentifier("__extends"), [name, createIdentifier("_super")]);
}
export function createAwaiterHelperCall(hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
let thisExpr = factory.createThisKeyword();
let awaiterName = factory.createIdentifier("__awaiter");
let argumentsExpr = hasLexicalArguments ? factory.createIdentifier("arguments") : factory.createVoidZeroExpression();
let promiseExpr = promiseConstructor ? convertEntityNameToExpression(promiseConstructor) : factory.createIdentifier("Promise");
let generatorFunc = factory.createGeneratorFunctionExpression(/*name*/ undefined, [], body);
let callExpr = factory.createCallExpression2(awaiterName, [thisExpr, argumentsExpr, promiseExpr, generatorFunc]);
return callExpr;
let argumentsExpr = hasLexicalArguments ? createIdentifier("arguments") : createVoidZeroExpression();
let promiseExpr = promiseConstructor ? convertEntityNameToExpression(promiseConstructor) : createIdentifier("Promise");
return createCallExpression2(createIdentifier("__awaiter"), [createThisKeyword(), argumentsExpr, promiseExpr, createGeneratorFunctionExpression([], body)]);
}
function convertEntityNameToExpression(node: EntityName | Expression): Expression {
if (isQualifiedName(node)) {
let left = convertEntityNameToExpression(node.left);
let right = factory.cloneNode(node.right);
return factory.createPropertyAccessExpression2(left, right);
}
else {
return factory.cloneNode(node);
}
return isQualifiedName(node) ? createPropertyAccessExpression2(convertEntityNameToExpression(node.left), cloneNode(node.right)) : cloneNode(node);
}
export function createDecorateHelperCall(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression) {
let _arguments: Expression[] = [
factory.createArrayLiteralExpression(decoratorExpressions),
target
];
if (memberName) {
_arguments.push(memberName);
if (descriptor) {
_arguments.push(descriptor);
}
}
let decorateHelperName = factory.createIdentifier("__decorate");
let decoratorsExpr = factory.createArrayLiteralExpression(decoratorExpressions);
let callExpr = factory.createCallExpression2(decorateHelperName, _arguments);
return callExpr;
return createCallExpression2(createIdentifier("__decorate"), append([createArrayLiteralExpression(decoratorExpressions), target], memberName, descriptor));
}
export function createParamHelperCall(parameterIndex: number, decoratorExpression: Expression) {
let paramHelperName = factory.createIdentifier("__param");
let parameterIndexExpr = factory.createNumericLiteral(String(parameterIndex));
let callExpr = factory.createCallExpression2(paramHelperName, [parameterIndexExpr, decoratorExpression]);
return callExpr;
return createCallExpression2(createIdentifier("__param"), [createNumericLiteral2(parameterIndex), decoratorExpression]);
}
export function createMetadataHelperCall(metadataKey: string, metadataValue: Expression) {
let metadataHelperName = factory.createIdentifier("__metadata");
let metadataKeyExpr = factory.createStringLiteral(metadataKey);
let callExpr = factory.createCallExpression2(metadataHelperName, [metadataKeyExpr, metadataValue]);
return callExpr;
return createCallExpression2(createIdentifier("__metadata"), [createStringLiteral(metadataKey), metadataValue]);
}
export function createDefinePropertyCall(target: Expression, memberName: Expression, descriptor: Expression) {
let globalObjectName = factory.createIdentifier("Object");
let definePropertyName = factory.createIdentifier("defineProperty");
let propExpr = factory.createPropertyAccessExpression(globalObjectName, factory.createNode(SyntaxKind.DotToken), definePropertyName);
let callExpr = factory.createCallExpression2(propExpr, [target, memberName, descriptor]);
return callExpr;
return createCallExpression2(createPropertyAccessExpression3(createIdentifier("Object"), "defineProperty"), [target, memberName, descriptor]);
}
export function createGetOwnPropertyDescriptorCall(target: Expression, memberName: Expression) {
let globalObjectName = factory.createIdentifier("Object");
let getOwnPropertyDescriptorName = factory.createIdentifier("getOwnPropertyDescriptor");
let propExpr = factory.createPropertyAccessExpression(globalObjectName, factory.createNode(SyntaxKind.DotToken), getOwnPropertyDescriptorName);
let callExpr = factory.createCallExpression2(propExpr, [target, memberName]);
return callExpr;
return createCallExpression2(createPropertyAccessExpression3(createIdentifier("Object"), "getOwnPropertyDescriptor"), [target, memberName]);
}
export function createDefaultValueCheck(value: Expression, defaultValue: Expression, ensureIdentifier: (value: Expression) => Expression, location?: TextRange, flags?: NodeFlags): Expression {
@@ -609,45 +393,16 @@ namespace ts {
return factory.createConditionalExpression2(factory.createStrictEqualityExpression(value, factory.createVoidZeroExpression()), defaultValue, value, location, flags);
}
export function createMemberAccessForPropertyName(target: Expression, memberName: DeclarationName, location?: TextRange, flags?: NodeFlags): MemberExpression {
if (isStringLiteral(memberName) || isNumericLiteral(memberName)) {
return factory.createElementAccessExpression2(
target,
cloneNode(memberName),
location,
flags
);
}
else if (isComputedPropertyName(memberName)) {
// TODO(rbuckton): Decorators? Will be handled higher in the stack I think.
return factory.createElementAccessExpression2(
target,
cloneNode(memberName.expression),
location,
flags
);
}
else {
return factory.createPropertyAccessExpression2(
target,
cloneNode(<Identifier>memberName),
location,
flags
)
}
export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange, flags?: NodeFlags): MemberExpression {
return isIdentifier(memberName)
? createPropertyAccessExpression2(target, cloneNode(memberName), location, flags)
: isComputedPropertyName(memberName)
? createElementAccessExpression2(target, cloneNode(memberName.expression), location, flags)
: createElementAccessExpression2(target, cloneNode(memberName), location, flags);
}
export function inlineExpressions(expressions: Expression[]) {
let expression = expressions[0];
for (let i = 1; i < expressions.length; i++) {
expression = createBinaryExpression2(
expression,
SyntaxKind.CommaToken,
expressions[i]
);
}
return expression;
return reduceLeft(expressions, createCommaExpression);
}
}
+4
View File
@@ -418,6 +418,10 @@ namespace ts {
/* @internal */
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
if (pos < 0) {
return pos;
}
// Keep in sync with couldStartTrivia
while (true) {
let ch = text.charCodeAt(pos);
+114 -91
View File
@@ -1,6 +1,6 @@
/// <reference path="factory.ts" />
/// <reference path="transform.generated.ts" />
const FORCE_TRANSFORMS = false;
const FORCE_TRANSFORMS = true;
/* @internal */
namespace ts {
@@ -255,10 +255,13 @@ namespace ts {
}
export type Visitor = (input: Node, output: (node: Node) => void) => void;
export type PipelineOutput<TOut extends Node> = (node: TOut) => void;
export type Pipeline<TIn extends Node, TOut extends Node> = (input: TIn, output: PipelineOutput<TOut>) => void;
export type NodeTest<T extends Node> = (node: Node) => node is T;
export const enum VisitorFlags {
NewLexicalEnvironment = 1 << 1,
PreserveStack = 1 << 2,
ReturnUndefinedIfEmpty = 1 << 3,
}
@@ -591,6 +594,24 @@ namespace ts {
transformFlags |= aggregateTransformFlagsForThisNodeAndSubtree(child);
}
function verifyNode<TOut extends Node>(node: Node, nodeTestCallback: (node: Node) => node is TOut): node is TOut {
if (!nodeTestCallback(node)) {
Debug.fail("Incorrect node kind after visit");
return false;
}
return true;
}
function writeNodeToPipeline<TOut extends Node>(node: Node, output: (node: TOut) => void, nodeTest: (node: Node) => node is TOut): void {
if (!node) {
return;
}
if (verifyNode(node, nodeTest)) {
output(node);
}
}
/**
* A function passed to a visitor callback that can be used to write a single node.
* @param node The node to write
@@ -689,43 +710,20 @@ namespace ts {
}
}
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);
}
function addNodeTestToPipeline<TOut extends Node>(output: (node: TOut) => void, nodeTest: (node: Node) => node is TOut): (node: TOut) => void {
return (node: Node) => writeNodeToPipeline<TOut>(node, output, nodeTest);
}
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) {
/**
* Pipes an input node (or nodes) into an output callback by passing it through a visitor callback.
* @remarks
* The primary responsibility of `pipeOneOrMany` is to execute the `visitor` callback for each
* input node, passing the input node and the output callback.
* This function also manages when new lexical environments are introduced, and tracks temporary
* variables and hoisted variable and function declarations.
*/
function pipeOneOrMany<TIn extends Node, TOut extends Node>(inputNode: TIn, inputNodes: TIn[], pipeline: Visitor, output: (node: TOut) => void, flags: VisitorFlags, nodeTest: (node: Node) => node is TOut): void {
if (!inputNode && !inputNodes) {
return;
}
@@ -746,21 +744,44 @@ namespace ts {
hoistedFunctionDeclarations = undefined;
}
pipe(input, output, visitor, flags & ~VisitorFlags.NewLexicalEnvironment);
// If a node test was supplied, we need to wrap the output with an assertion
if (nodeTest) {
output = addNodeTestToPipeline(output, nodeTest);
}
if (inputNode) {
let nodeWasPushed = nodeStack.tryPushNode(inputNode);
pipeline(inputNode, output);
if (nodeWasPushed) {
nodeStack.popNode();
}
}
else {
// 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 `nodeStack`.
nodeStack.pushNode(/*node*/ undefined);
// Visit each input node
for (let node of inputNodes) {
nodeStack.setNode(node);
pipeline(node, output);
}
// For the perf reasons mentioned above, we pop the current node at the end of the loop.
nodeStack.popNode();
}
// If we established a new lexical environment, we need to write any hoisted variables or
// function declarations to the end of the output.
if (flags & VisitorFlags.NewLexicalEnvironment) {
if (hoistedVariableDeclarations) {
output(factory.createVariableStatement2(
factory.createVariableDeclarationList(
hoistedVariableDeclarations
)
));
var stmt = factory.createVariableStatement2(factory.createVariableDeclarationList(hoistedVariableDeclarations));
output(<TOut><Node>stmt);
}
else if (hoistedFunctionDeclarations) {
for (let decl of hoistedFunctionDeclarations) {
output(decl);
output(<TOut><Node>decl);
}
}
@@ -770,33 +791,11 @@ namespace ts {
hoistedFunctionDeclarations = savedHoistedFunctionDeclarations;
}
}
/**
* Writes the result from visiting a single input node to an output node array.
* @param input The source node to visit.
* @param output The destination node array to which to write the results from visiting each node.
* @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, flags?: VisitorFlags): void {
pipeOneOrMany(input, output, visitor, flags, pipeOne);
}
/**
* Pipelines the results of visiting each node from an input source to an output callback function.
* @param input The source nodes to visit.
* @param output The callback passed to `visitor` (below) to write each visited node.
* @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, flags?: VisitorFlags): void {
pipeOneOrMany(input, output, visitor, flags, pipeMany);
}
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 {
function emitOneOrMany<TIn extends Node, TOut extends Node>(inputNode: TIn, inputNodes: TIn[], pipeline: Pipeline<TIn, TOut>, output: TOut[], flags: VisitorFlags, nodeTest: (node: Node) => node is TOut): TOut[] {
// Exit early if we have nothing to do
if (!input) {
return;
if (!inputNode && !inputNodes) {
return undefined;
}
// Preserve the current environment on the call stack as we descend into the tree
@@ -811,40 +810,64 @@ namespace ts {
offsetWritten = 0;
writeNodeToNodeArrayFastOrSlow = writeNodeToNodeArrayFast;
pipe(input, writeNodeToNodeArray, visitor, flags | VisitorFlags.PreserveStack);
pipeOneOrMany<TIn, TOut>(inputNode, inputNodes, pipeline, writeNodeToNodeArray, flags, nodeTest);
// Restore previous environment
originalNodes = savedOriginalNodes;
updatedNodes = savedUpdatedNodes;
offsetWritten = savedOffsetWritten;
writeNodeToNodeArrayFastOrSlow = savedWriteNodeToNodeArrayFastOrSlow;
writeNodeToNodeArrayFastOrSlow = savedWriteNodeToNodeArrayFastOrSlow;
return output;
}
/**
* Pipelines the results of visiting a single input node to an output callback function.
* @param input The source node to visit.
* @param pipeline The callback to execute as we visit each node in the source.
* @param output The callback passed to `visitor` to write each visited node.
* @param flags Flags that affect the pipeline.
*/
export function pipeNode<TIn extends Node, TOut extends Node>(input: TIn, pipeline: Pipeline<TIn, TOut>, output: PipelineOutput<TOut>, flags?: VisitorFlags, nodeTest?: NodeTest<TOut>): void {
pipeOneOrMany(input, undefined, pipeline, output, flags, nodeTest);
}
/**
* Pipelines the results of visiting each node from an input source to an output callback function.
* @param input The source nodes to visit.
* @param pipeline The callback to execute as we visit each node in the source.
* @param output The callback passed to `visitor` to write each visited node.
* @param flags Flags that affect the pipeline.
*/
export function pipeNodes<TIn extends Node, TOut extends Node>(input: TIn[], pipeline: Pipeline<TIn, TOut>, output: PipelineOutput<TOut>, flags?: VisitorFlags, nodeTest?: NodeTest<TOut>): void {
pipeOneOrMany(undefined, input, pipeline, output, flags, nodeTest);
}
/**
* Writes the result from visiting a single input node to an output node array.
* @param input The source node to visit.
* @param pipeline The callback to execute as we visit each node in the source.
* @param output The destination node array to which to write the results from visiting each node.
* @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.
* @param flags Flags that affect the pipeline.
*/
export function emitNode(input: Node, output: Node[], visitor: (input: Node, write: (output: Node) => void) => void, flags?: VisitorFlags): void {
emitOneOrMany(input, output, visitor, flags, pipeOne);
export function emitNode<TIn extends Node, TOut extends Node>(input: TIn, pipeline: Pipeline<TIn, TOut>, output: TOut[], flags?: VisitorFlags, nodeTest?: NodeTest<TOut>): void {
emitOneOrMany(input, undefined, pipeline, output, flags, nodeTest);
}
/**
* Writes the result from visiting each node from an input source to an output node array.
* @param input The source nodes to visit.
* @param pipeline The callback to execute as we visit each node in the source.
* @param output The destination node array to which to write the results from visiting each node.
* @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.
* @param flags Flags that affect the pipeline.
*/
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 emitNodes<TIn extends Node, TOut extends Node>(input: TIn[], pipeline: Pipeline<TIn, TOut>, output: TOut[], flags?: VisitorFlags, nodeTest?: NodeTest<TOut>): void {
emitOneOrMany(undefined, input, pipeline, output, flags, nodeTest);
}
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 {
export function visitNode<T extends Node>(node: T, visitor: Visitor, flags?: VisitorFlags): T;
export function visitNode<TIn extends Node, TOut extends Node>(node: TIn, visitor: Visitor, flags?: VisitorFlags, nodeTest?: (node: Node) => node is TOut): TOut;
export function visitNode<TIn extends Node, TOut extends Node>(node: TIn, visitor: Visitor, flags?: VisitorFlags, nodeTest?: (node: Node) => node is TOut): TOut {
if (!node) {
return undefined;
}
@@ -854,7 +877,7 @@ namespace ts {
updatedNode = undefined;
writeNodeFastOrSlow = writeNodeSlow;
pipeNode(node, writeNode, visitor, flags);
pipeNode<TIn, TOut>(node, visitor, writeNode, flags, nodeTest);
let visited = <TOut>readNode();
updatedNode = savedUpdatedNode;
@@ -863,7 +886,7 @@ namespace ts {
return visited;
}
export function visitStatement(node: Statement, visitor: (input: Node, write: (node: Node) => void) => void, flags?: VisitorFlags) {
export function visitStatement(node: Statement, visitor: Visitor, flags?: VisitorFlags) {
if (!node) {
return node;
}
@@ -876,7 +899,7 @@ namespace ts {
updatedBlock = undefined;
writeStatementFastOrSlow = writeStatementSlow;
pipeNode(node, writeStatement, visitor, flags);
pipeNode<Statement, Statement>(node, visitor, writeStatement, flags, isStatementNode);
let visited = readStatement();
updatedStatement = savedUpdatedStatement;
@@ -886,9 +909,9 @@ namespace ts {
return visited;
}
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> {
export function visitNodes<T extends Node>(nodes: T[], visitor: Visitor, flags?: VisitorFlags): NodeArray<T>;
export function visitNodes<TIn extends Node, TOut extends Node>(nodes: TIn[], visitor: Visitor, flags?: VisitorFlags): NodeArray<TOut>;
export function visitNodes<TIn extends Node, TOut extends Node>(nodes: TIn[], visitor: Visitor, flags?: VisitorFlags, nodeTest?: (node: Node) => node is TOut): NodeArray<TOut> {
// Exit early if we have nothing to do
if (!nodes) {
return undefined;
@@ -907,7 +930,7 @@ namespace ts {
writeNodeToNodeArrayFastOrSlow = writeNodeToNodeArraySlow;
// Pipe each node from input into output
pipeNodes(originalNodes, writeNodeToNodeArray, visitor, flags);
pipeNodes<TIn, TOut>(nodes, visitor, writeNodeToNodeArray, flags, nodeTest);
let visited = readNodeArray(flags);
@@ -969,7 +992,7 @@ namespace ts {
);
default:
if (isExpression(node)) {
if (isExpressionNode(node)) {
return visitExpressionFunctionBodyInNewLexicalEnvironment(node, visitor);
}
else {
+8 -8
View File
@@ -115,7 +115,7 @@ namespace ts.transform {
function transformClassLikeDeclaration(node: ClassLikeDeclaration, name: Identifier): LeftHandSideExpression {
let baseTypeNode = getClassExtendsHeritageClauseElement(node);
let classBody = factory.createBlock([]);
emitNode(node, classBody.statements, transformClassBody);
emitNode(node, transformClassBody, classBody.statements);
let superExpr = baseTypeNode ? visitNode(baseTypeNode.expression, transformNode) : undefined;
let superName = baseTypeNode ? factory.createIdentifier("_super") : undefined;
@@ -153,7 +153,7 @@ namespace ts.transform {
let body = factory.createBlock([]);
if (constructor) {
emitNode(constructor, body.statements, transformConstructor, VisitorFlags.NewLexicalEnvironment);
emitNode(constructor, transformConstructor, body.statements, VisitorFlags.NewLexicalEnvironment);
}
else if (baseTypeNode) {
let superCall = createDefaultSuperCall();
@@ -168,7 +168,7 @@ namespace ts.transform {
emitCaptureThisForNode(constructor, write);
emitDefaultValueAssignments(constructor, write);
emitRestParameter(constructor, write);
pipeNodes(constructor.body.statements, write, transformNode);
pipeNodes(constructor.body.statements, transformNode, write);
}
function transformParameter(node: ParameterDeclaration, write: (node: ParameterDeclaration) => void) {
@@ -194,7 +194,7 @@ namespace ts.transform {
function emitDefaultValueAssignments(node: FunctionLikeDeclaration, write: (node: Statement) => void) {
if (!(node.transformFlags & (TransformFlags.SubtreeContainsParameterInitializer | TransformFlags.SubtreeContainsParameterBindingPattern))) {
return
return;
}
for (let parameter of node.parameters) {
@@ -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, VisitorFlags.NewLexicalEnvironment);
emitNode(node, transformFunctionBody, body.statements, 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, VisitorFlags.NewLexicalEnvironment);
emitNode(node, transformFunctionBody, body.statements, 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, VisitorFlags.NewLexicalEnvironment);
emitNode(node, transformFunctionBody, newBody.statements, VisitorFlags.NewLexicalEnvironment);
let func = createfn(name, parameters, newBody, location);
return func;
@@ -482,7 +482,7 @@ namespace ts.transform {
let body = node.body;
if (isBlock(body)) {
pipeNodes(body.statements, write, transformNode);
pipeNodes(body.statements, transformNode, write);
}
else {
let expr = visitNode(body, transformNode);
+52 -92
View File
@@ -67,7 +67,7 @@ namespace ts.transform {
* @param context Context information for the transform.
* @param node The node to transform.
*/
function transformNodeWorker(node: Node, write?: (node: Node) => void): void {
function transformNodeWorker(node: Node, write: (node: Node) => void): void {
// TypeScript ambient declarations are elided.
if (node.flags & NodeFlags.Ambient) {
return;
@@ -120,10 +120,6 @@ namespace ts.transform {
// 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`.
@@ -240,36 +236,33 @@ namespace ts.transform {
return accept(node, transformNode, write);
}
}
/**
* Transforms a TypeScript class declaration with syntax extensions into compatible ES6.
* @param context Context information for the transform.
* @param node The node to transform.
*/
function transformClassDeclaration(node: ClassDeclaration, write: (node: Statement) => void) {
let thisNodeIsNamespaceExport = isNamespaceLevelExport(node);
let name = getDeclarationName(node);
let heritageClauses = visitNodes(node.heritageClauses, transformNode);
let extendsClause = heritageClauses && firstOrUndefined(heritageClauses);
let baseTypeNode = extendsClause && firstOrUndefined(extendsClause.types);
let baseTypeNode = visitAndGetClassExtendsHeritageClauseElement(node);
let classMembers: ClassElement[] = [];
let constructor = transformConstructor(node, baseTypeNode);
let members = visitNodes(node.members, transformNode);
let classMembers: ClassElement[] = constructor ? [constructor, ...members] : members;
if (constructor) {
classMembers.push(constructor);
}
emitNodes(node.members, transformNode, classMembers);
if (nodeIsDecorated(node)) {
let classExpr = factory.createClassExpression2(/*name*/ undefined, extendsClause, classMembers);
let varDecl = factory.createVariableDeclaration2(name, classExpr);
let varDeclList = factory.createVariableDeclarationList([varDecl], /*location*/ undefined, NodeFlags.Let);
let exportFlags = isTopLevelNonDefaultExport(node) ? NodeFlags.Export : undefined;
let varStmt = factory.createVariableStatement2(varDeclList, /*location*/ node, exportFlags);
// If the class has been decorated, we need to emit the class as part of a `let` declaration
// to avoid the pitfalls of the doubly-bound class name.
let classExpr = factory.createClassExpression3(baseTypeNode, classMembers);
let varStmt = factory.createSimpleLetStatement(getDeclarationName(node), classExpr, /*location*/ node, isTopLevelNonDefaultExport(node));
varStmt.original = node;
write(varStmt);
}
else {
let exportFlags = thisNodeIsNamespaceExport
? undefined
: node.flags & (NodeFlags.Export | NodeFlags.Default);
let classDecl = factory.createClassDeclaration2(name, extendsClause, classMembers, /*location*/ node, exportFlags);
let exportFlags = isNamespaceLevelExport(node) ? undefined : node.flags & (NodeFlags.Export | NodeFlags.Default);
let classDecl = factory.createClassDeclaration2(getDeclarationName(node), baseTypeNode, classMembers, /*location*/ node, exportFlags);
classDecl.original = node;
write(classDecl);
}
@@ -279,50 +272,49 @@ namespace ts.transform {
transformDecoratorsOfMembers(node, /*isStatic*/ true, write);
transformDecoratorsOfConstructor(node, write);
if (thisNodeIsNamespaceExport) {
let namespaceExportExpr = factory.createAssignmentExpression(getModuleMemberName(node), name);
let exprStmt = factory.createExpressionStatement(namespaceExportExpr);
write(exprStmt);
if (isNamespaceLevelExport(node)) {
write(factory.createExpressionStatement(factory.createAssignmentExpression(getModuleMemberName(node), getDeclarationName(node))));
}
else if (isTopLevelDefaultExport(node) && nodeIsDecorated(node)) {
let exportDefaultStmt = factory.createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, name);
write(exportDefaultStmt);
write(factory.createExportDefaultStatement(getDeclarationName(node)));
}
}
function transformClassExpression(node: ClassExpression, write: (node: LeftHandSideExpression) => void) {
let name = getDeclarationName(node);
let heritageClauses = visitNodes(node.heritageClauses, transformNode);
let extendsClause = heritageClauses ? firstOrUndefined(heritageClauses) : undefined;
let baseTypeNode = extendsClause ? firstOrUndefined(extendsClause.types) : undefined;
let baseTypeNode = visitAndGetClassExtendsHeritageClauseElement(node);
let classMembers: ClassElement[] = [];
let constructor = transformConstructor(node, baseTypeNode);
let members = visitNodes(node.members, transformNodeWorker);
let classMembers = constructor ? [constructor, ...members] : members;
let newNode = factory.createClassExpression2(
name,
extendsClause,
classMembers
);
if (constructor) {
classMembers.push(constructor);
}
emitNodes(node.members, transformNode, classMembers);
let classExpr = factory.createClassExpression2(getDeclarationName(node), baseTypeNode, classMembers);
let staticPropertyAssignments = getInitializedProperties(node, /*isStatic*/ true);
if (staticPropertyAssignments) {
let expressions: Expression[] = [];
let tempVar = declareLocal();
let cacheExpr = factory.createAssignmentExpression(tempVar, newNode);
let cacheExpr = factory.createAssignmentExpression(tempVar, classExpr);
expressions.push(cacheExpr);
transformPropertyDeclarationsToExpressions(node, staticPropertyAssignments, expressions);
expressions.push(tempVar);
write(factory.createParenthesizedExpression(factory.inlineExpressions(expressions)));
}
else {
write(newNode);
write(classExpr);
}
}
function visitAndGetClassExtendsHeritageClauseElement(node: ClassLikeDeclaration) {
let heritageClauses = visitNodes(node.heritageClauses, transformNode);
let extendsClause = heritageClauses && firstOrUndefined(heritageClauses);
let baseTypeNode = extendsClause && firstOrUndefined(extendsClause.types);
return baseTypeNode;
}
function isTopLevelExport(node: Node) {
return !!(node.flags & NodeFlags.Export) &&
getParentNode().kind === SyntaxKind.SourceFile;
return !!(node.flags & NodeFlags.Export) && isSourceFile(getParentNode());
}
function isTopLevelDefaultExport(node: Node) {
@@ -334,8 +326,7 @@ namespace ts.transform {
}
function isNamespaceLevelExport(node: Node) {
return !!(node.flags & NodeFlags.Export) &&
getParentNode().kind !== SyntaxKind.SourceFile;
return !!(node.flags & NodeFlags.Export) && !isSourceFile(getParentNode());
}
function getContainingModule(): ModuleDeclaration {
@@ -366,53 +357,29 @@ namespace ts.transform {
let constructor = getFirstConstructorWithBody(node);
let parameterPropertyAssignments = constructor ? getParametersWithPropertyAssignments(constructor) : undefined;
let instancePropertyAssignments = getInitializedProperties(node, /*isStatic*/ false);
// let leadingCommentRanges: CommentRange[];
// let trailingCommentRanges: CommentRange[];
// for (let member of node.members) {
// if (isConstructor(member) && !member.body) {
// let leadingCommentRangesOfMember = context.getLeadingCommentRanges(member, /*onlyPinnedOrTripleSlashComments*/ true);
// leadingCommentRanges = concatenate(leadingCommentRanges, leadingCommentRangesOfMember);
// }
// }
// For target ES6 and above, if there is no property assignment
// do not emit constructor in class declaration.
if (!parameterPropertyAssignments && !instancePropertyAssignments) {
// if (leadingCommentRanges) {
// leadingCommentRanges = concatenate(leadingCommentRanges, context.getLeadingCommentRanges(ctor));
// ctor = factory.cloneNode(ctor);
// factory.attachCommentRanges(ctor, leadingCommentRanges, trailingCommentRanges);
// }
return constructor;
}
let parameters =
constructor ? visitNodes(constructor.parameters, transformNode) :
baseTypeNode ? [factory.createRestParameter(factory.createIdentifier("args"), /*location*/ undefined, NodeFlags.GeneratedRest)] :
[];
// let parameters =
// constructor ? transformSignatureParameters(constructor.parameters) :
// hasBaseType ? [factory.createRestParameter(tag_id`args`, /*location*/ undefined, NodeFlags.GeneratedRest)] :
// [];
let parameters = constructor
? visitNodes(constructor.parameters, transformNode)
: baseTypeNode
? [factory.createRestParameter(factory.createIdentifier("args"), /*location*/ undefined, NodeFlags.GeneratedRest)]
: [];
let statements: Statement[] = [];
let superCall: ExpressionStatement;
if (constructor) {
// leadingCommentRanges = concatenate(
// leadingCommentRanges,
// context.getLeadingCommentRanges(ctor)
// );
// trailingCommentRanges = context.getTrailingCommentRanges(ctor);
if (baseTypeNode) {
superCall = findInitialSuperCall(constructor);
if (superCall) {
statements.push(superCall);
}
}
if (parameterPropertyAssignments) {
for (let parameter of parameterPropertyAssignments) {
let name = <Identifier>factory.cloneNode(parameter.name);
@@ -438,19 +405,11 @@ namespace ts.transform {
transformPropertyDeclarationsToStatements(node, instancePropertyAssignments, n => { statements.push(n); });
if (constructor) {
let bodyStatements = superCall
? constructor.body.statements.slice(1)
: constructor.body.statements;
statements.push(...visitNodes(bodyStatements, transformNode));
let bodyStatements = constructor.body.statements;
emitNodes(superCall ? bodyStatements.slice(1) : bodyStatements, transformNode, statements, VisitorFlags.NewLexicalEnvironment);
}
let body = constructor
? factory.updateBlock(constructor.body, statements)
: factory.createBlock(statements);
let newConstructor = factory.createConstructor2(parameters, body, /*location*/ constructor);
// factory.attachCommentRanges(newConstructor, leadingCommentRanges, trailingCommentRanges);
return newConstructor;
return factory.createConstructor2(parameters, factory.createBlock(statements), /*location*/ constructor);
}
function transformHeritageClause(node: HeritageClause, write: (node: HeritageClause) => void) {
@@ -772,13 +731,14 @@ namespace ts.transform {
function transformVariableStatement(node: VariableStatement, write: (node: Statement) => void) {
// TODO(rbuckton): transform namespace exports for a variable declaration list
Debug.assert(isNamespaceLevelExport(node), "Should only reach here for exported variables.");
pipeNode(node.declarationList, write, transformVariableDeclarationList);
// Debug.assert(isNamespaceLevelExport(node), "Should only reach here for exported variables." + node.declarationList.declarations[0].name);
// pipeNode(node.declarationList, write, transformVariableDeclarationList);
return accept(node, transformNode, write);
}
function transformVariableDeclarationList(node: VariableDeclarationList, write: (node: Statement) => void) {
let expressions: Expression[] = [];
emitNodes(node.declarations, expressions, transformVariableDeclaration);
emitNodes(node.declarations, transformVariableDeclaration, expressions);
if (expressions.length) {
let exprStmt = factory.createExpressionStatement(factory.inlineExpressions(expressions));
+7 -7
View File
@@ -561,13 +561,13 @@ namespace ts {
}
}
declare var global: any, require: any;
if (typeof global !== "undefined" && Object.prototype.toString.call(global.process) === '[object process]') {
try {
require("source-map-support").install();
}
catch (e) { }
}
// declare var global: any, require: any;
// if (typeof global !== "undefined" && Object.prototype.toString.call(global.process) === '[object process]') {
// try {
// require("source-map-support").install();
// }
// catch (e) { }
// }
}
ts.executeCommandLine(ts.sys.args);
+4 -6
View File
@@ -638,8 +638,6 @@ namespace ts {
// @internal
export interface ParentNavigator extends ParentNavigable {
/** Gets the root node for the current node. */
getRoot(): Node;
/** Gets the grandparent node for the current node. */
getGrandparent(): Node;
/** Gets the parent node for the current node. */
@@ -650,14 +648,10 @@ namespace ts {
getKind(): SyntaxKind;
/** Moves the navigator to the parent node of the current node. */
moveToParent(): boolean;
/** Moves the navigator to the root node of the current node. */
moveToRoot(): boolean;
}
// @internal
export interface NodeStack extends ParentNavigable {
/** Gets the node at the bottom of the stack. */
getRoot(): Node;
/** Gets the node two steps down from the top of the stack. */
getGrandparent(): Node;
/** Gets the node one step down from the top of the stack. */
@@ -672,6 +666,8 @@ namespace ts {
findAncestorNode(match: (node: Node) => boolean): Node;
/** Pushes a node onto the stack. */
pushNode(node: Node): void;
/** Pushes a node onto the stack if it is not already at the top of the stack. */
tryPushNode(node: Node): boolean;
/** Replaces the node at the top of the stack. */
setNode(node: Node): void;
/** Pops the top node from the stack. */
@@ -1102,6 +1098,7 @@ namespace ts {
// checker actually thinks you have something of the right type. Note: the brands are
// never actually given values. At runtime they have zero cost.
// @kind(SyntaxKind.OmittedExpression)
// @nodetest("isExpressionNode")
export interface Expression extends Node {
_expressionBrand: any;
contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
@@ -1372,6 +1369,7 @@ namespace ts {
export type JsxChild = JsxText | JsxExpression | JsxElement | JsxSelfClosingElement;
// @nodetest("isStatementNode")
export interface Statement extends Node {
_statementBrand: any;
}
+6 -2
View File
@@ -918,7 +918,7 @@ namespace ts {
}
/** Returns whether the node is part of an expression. */
export function isPartOfExpression(navigable: ParentNavigable): boolean {
export function isExpression(navigable: ParentNavigable): boolean {
let nav = navigable.createParentNavigator();
while (true) {
let node = nav.getNode();
@@ -1702,6 +1702,10 @@ namespace ts {
export function nodeIsSynthesized(node: Node): boolean {
return node && node.pos === -1;
}
export function positionIsSynthesized(pos: number): boolean {
return pos === -1;
}
export function createDiagnosticCollection(): DiagnosticCollection {
let nonFileDiagnostics: Diagnostic[] = [];
@@ -1957,7 +1961,7 @@ namespace ts {
}
export function getLineOfLocalPosition(currentSourceFile: SourceFile, pos: number) {
return getLineAndCharacterOfPosition(currentSourceFile, pos).line;
return !positionIsSynthesized(pos) ? getLineAndCharacterOfPosition(currentSourceFile, pos).line : NaN;
}
export function getFirstConstructorWithBody(node: ClassLikeDeclaration): ConstructorDeclaration {
+1 -1
View File
@@ -59,7 +59,7 @@ namespace ts.BreakpointResolver {
function spanInNode(node: Node): TextSpan {
if (node) {
if (isPartOfExpression(node)) {
if (isExpression(node)) {
if (node.parent.kind === SyntaxKind.DoStatement) {
// Set span as if on while keyword
return spanInPreviousNode(node);
+1 -1
View File
@@ -744,7 +744,7 @@ namespace ts.formatting {
}
static NodeIsInDecoratorContext(node: Node): boolean {
while (isPartOfExpression(node)) {
while (isExpression(node)) {
node = node.parent;
}
return node.kind === SyntaxKind.Decorator;