Merged some changes from other branches.

This commit is contained in:
Ron Buckton 2016-02-22 15:52:16 -08:00
parent 024eff1334
commit 11d54ba322
6 changed files with 1023 additions and 161 deletions

File diff suppressed because it is too large Load diff

View file

@ -4069,6 +4069,10 @@ namespace ts {
function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
const node = <Block>createNode(SyntaxKind.Block);
if (parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage) || ignoreMissingOpenBrace) {
if (scanner.hasPrecedingLineBreak()) {
node.multiLine = true;
}
node.statements = parseList(ParsingContext.BlockStatements, parseStatement);
parseExpected(SyntaxKind.CloseBraceToken);
}

View file

@ -42,8 +42,12 @@ namespace ts {
hoistFunctionDeclaration,
startLexicalEnvironment,
endLexicalEnvironment,
identifierSubstitution: node => node,
expressionSubstitution: node => node,
enableExpressionSubstitution,
isExpressionSubstitutionEnabled,
onBeforeEmitNode: node => { },
onAfterEmitNode: node => { },
enableEmitNotification,
isEmitNotificationEnabled,
};
@ -106,8 +110,9 @@ namespace ts {
/**
* Sets flags that control emit behavior of a node.
*/
function setNodeEmitFlags(node: Node, flags: NodeEmitFlags) {
function setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags) {
nodeEmitFlags[getNodeId(node)] = flags;
return node;
}
/**
@ -196,7 +201,7 @@ namespace ts {
case SyntaxKind.ClassExpression:
return generateNameForClassExpression();
default:
return createTempVariable(TempVariableKind.Auto);
return createTempVariable();
}
}
@ -276,6 +281,7 @@ namespace ts {
if (hoistedVariableDeclarations) {
const statement = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(hoistedVariableDeclarations)
);

View file

@ -1125,6 +1125,7 @@ namespace ts {
// @kind(SyntaxKind.Block)
export interface Block extends Statement {
statements: NodeArray<Statement>;
/*@internal*/ multiLine?: boolean;
}
// @kind(SyntaxKind.VariableStatement)
@ -1302,7 +1303,7 @@ namespace ts {
export interface EnumMember extends Declaration {
// This does include ComputedPropertyName, but the parser will give an error
// if it parses a ComputedPropertyName in an EnumMember
name: DeclarationName;
name: PropertyName;
initializer?: Expression;
}
@ -2799,8 +2800,7 @@ namespace ts {
UMDDefine = 1 << 4, // This node should be replaced with the UMD define helper.
NoLexicalEnvironment = 1 << 5, // A new LexicalEnvironment should *not* be introduced when emitting this node, this is primarily used when printing a SystemJS module.
SingleLine = 1 << 6, // The contents of this node should be emit on a single line.
MultiLine = 1 << 7, // The contents of this node should be emit on multiple lines.
AdviseOnEmitNode = 1 << 8, // The node printer should invoke the onBeforeEmitNode and onAfterEmitNode callbacks when printing this node.
AdviseOnEmitNode = 1 << 7, // The node printer should invoke the onBeforeEmitNode and onAfterEmitNode callbacks when printing this node.
}
/** Additional context provided to `visitEachChild` */
@ -2817,7 +2817,7 @@ namespace ts {
getCompilerOptions(): CompilerOptions;
getEmitResolver(): EmitResolver;
getNodeEmitFlags(node: Node): NodeEmitFlags;
setNodeEmitFlags(node: Node, flags: NodeEmitFlags): void;
setNodeEmitFlags<T extends Node>(node: T, flags: NodeEmitFlags): T;
hoistFunctionDeclaration(node: FunctionDeclaration): void;
hoistVariableDeclaration(node: Identifier): void;
isUniqueName(name: string): boolean;

View file

@ -173,6 +173,10 @@ namespace ts {
return node.pos;
}
export function isDefined(value: any): boolean {
return value !== undefined;
}
// Returns true if this node is missing from the actual source code. A 'missing' node is different
// from 'undefined/defined'. When a node is undefined (which can happen for optional nodes
// in the tree), it is definitely missing. However, a node may be defined, but still be
@ -1654,7 +1658,7 @@ namespace ts {
return getOperatorPrecedence(expression.kind, operator, hasArguments);
}
function getOperator(expression: Expression) {
export function getOperator(expression: Expression) {
if (expression.kind === SyntaxKind.BinaryExpression) {
return (<BinaryExpression>expression).operatorToken.kind;
}
@ -2664,6 +2668,10 @@ namespace ts {
// Literals
export function isNoSubstitutionTemplateLiteral(node: Node): node is LiteralExpression {
return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
export function isLiteralKind(kind: SyntaxKind): boolean {
return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
}
@ -2757,6 +2765,10 @@ namespace ts {
// Type members
export function isMethodDeclaration(node: Node): node is MethodDeclaration {
return node.kind === SyntaxKind.MethodDeclaration;
}
export function isClassElement(node: Node): node is ClassElement {
const kind = node.kind;
return kind === SyntaxKind.Constructor
@ -2764,7 +2776,6 @@ namespace ts {
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.GetAccessor
|| kind === SyntaxKind.SetAccessor
|| kind === SyntaxKind.MethodSignature
|| kind === SyntaxKind.IndexSignature;
}
@ -2830,6 +2841,10 @@ namespace ts {
return node.kind === SyntaxKind.BinaryExpression;
}
export function isConditionalExpression(node: Node): node is ConditionalExpression {
return node.kind === SyntaxKind.ConditionalExpression;
}
export function isCallExpression(node: Node): node is CallExpression {
return node.kind === SyntaxKind.CallExpression;
}
@ -2840,11 +2855,16 @@ namespace ts {
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
export function isSpreadElementExpression(node: Node): node is SpreadElementExpression {
return node.kind === SyntaxKind.SpreadElementExpression;
}
export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments {
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
}
function isLeftHandSideExpressionKind(kind: SyntaxKind) {
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
const kind = node.kind;
return kind === SyntaxKind.PropertyAccessExpression
|| kind === SyntaxKind.ElementAccessExpression
|| kind === SyntaxKind.NewExpression
@ -2870,11 +2890,8 @@ namespace ts {
|| kind === SyntaxKind.SuperKeyword;
}
export function isLeftHandSideExpression(node: Node): node is LeftHandSideExpression {
return isLeftHandSideExpressionKind(node.kind);
}
function isUnaryExpressionKind(kind: SyntaxKind): boolean {
export function isUnaryExpression(node: Node): node is UnaryExpression {
const kind = node.kind;
return kind === SyntaxKind.PrefixUnaryExpression
|| kind === SyntaxKind.PostfixUnaryExpression
|| kind === SyntaxKind.DeleteExpression
@ -2882,14 +2899,11 @@ namespace ts {
|| kind === SyntaxKind.VoidExpression
|| kind === SyntaxKind.AwaitExpression
|| kind === SyntaxKind.TypeAssertionExpression
|| isLeftHandSideExpressionKind(kind);
|| isLeftHandSideExpression(node);
}
export function isUnaryExpression(node: Node): node is UnaryExpression {
return isUnaryExpressionKind(node.kind);
}
function isExpressionKind(kind: SyntaxKind): boolean {
export function isExpression(node: Node): node is Expression {
const kind = node.kind;
return kind === SyntaxKind.ConditionalExpression
|| kind === SyntaxKind.YieldExpression
|| kind === SyntaxKind.ArrowFunction
@ -2897,11 +2911,7 @@ namespace ts {
|| kind === SyntaxKind.SpreadElementExpression
|| kind === SyntaxKind.AsExpression
|| kind === SyntaxKind.OmittedExpression
|| isUnaryExpressionKind(kind);
}
export function isExpression(node: Node): node is Expression {
return isExpressionKind(node.kind);
|| isUnaryExpression(node);
}
// Misc
@ -3053,7 +3063,8 @@ namespace ts {
export function isStatement(node: Node): node is Statement {
const kind = node.kind;
return isStatementKindButNotDeclarationKind(kind)
|| isDeclarationStatementKind(kind);
|| isDeclarationStatementKind(kind)
|| kind === SyntaxKind.Block;
}
// Module references
@ -3089,6 +3100,10 @@ namespace ts {
|| kind === SyntaxKind.JsxSpreadAttribute;
}
export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute {
return node.kind === SyntaxKind.JsxSpreadAttribute;
}
// Clauses
export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause {
@ -3108,9 +3123,12 @@ namespace ts {
// Property assignments
export function isShortHandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
const kind = node.kind;
return kind === SyntaxKind.ShorthandPropertyAssignment;
export function isPropertyAssignment(node: Node): node is PropertyAssignment {
return node.kind === SyntaxKind.PropertyAssignment;
}
export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
return node.kind === SyntaxKind.ShorthandPropertyAssignment;
}
// Enum

View file

@ -18,6 +18,9 @@ namespace ts {
/** A callback used to lift a NodeArrayNode into a valid node. */
lift?: (nodes: NodeArray<Node>) => Node;
/** A callback used to parenthesize a node to preserve the intended order of operations. */
parenthesize?: (value: Node, parentNode: Node) => Node;
};
/**
@ -51,7 +54,7 @@ namespace ts {
{ name: "modifiers", test: isModifier },
{ name: "name", test: isBindingName },
{ name: "type", test: isTypeNode, optional: true },
{ name: "initializer", test: isExpression, optional: true },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.Decorator]: [
{ name: "expression", test: isLeftHandSideExpression },
@ -107,34 +110,34 @@ namespace ts {
[SyntaxKind.BindingElement]: [
{ name: "propertyName", test: isPropertyName, optional: true },
{ name: "name", test: isBindingName },
{ name: "initializer", test: isExpression, optional: true },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.ArrayLiteralExpression]: [
{ name: "elements", test: isExpression },
{ name: "elements", test: isExpression, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.ObjectLiteralExpression]: [
{ name: "properties", test: isObjectLiteralElement },
],
[SyntaxKind.PropertyAccessExpression]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "name", test: isIdentifier },
],
[SyntaxKind.ElementAccessExpression]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "argumentExpression", test: isExpression },
],
[SyntaxKind.CallExpression]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "typeArguments", test: isTypeNode },
{ name: "arguments", test: isExpression },
],
[SyntaxKind.NewExpression]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "typeArguments", test: isTypeNode },
{ name: "arguments", test: isExpression },
],
[SyntaxKind.TaggedTemplateExpression]: [
{ name: "tag", test: isLeftHandSideExpression },
{ name: "tag", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "template", test: isTemplate },
],
[SyntaxKind.TypeAssertionExpression]: [
@ -162,26 +165,26 @@ namespace ts {
{ name: "body", test: isConciseBody, lift: liftToBlock },
],
[SyntaxKind.DeleteExpression]: [
{ name: "expression", test: isUnaryExpression },
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.TypeOfExpression]: [
{ name: "expression", test: isUnaryExpression },
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.VoidExpression]: [
{ name: "expression", test: isUnaryExpression },
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.AwaitExpression]: [
{ name: "expression", test: isUnaryExpression },
{ name: "expression", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.PrefixUnaryExpression]: [
{ name: "operand", test: isUnaryExpression },
{ name: "operand", test: isUnaryExpression, parenthesize: parenthesizePrefixOperand },
],
[SyntaxKind.PostfixUnaryExpression]: [
{ name: "operand", test: isLeftHandSideExpression },
{ name: "operand", test: isLeftHandSideExpression, parenthesize: parenthesizePostfixOperand },
],
[SyntaxKind.BinaryExpression]: [
{ name: "left", test: isExpression },
{ name: "right", test: isExpression },
{ name: "left", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, true) },
{ name: "right", test: isExpression, parenthesize: (node: Expression, parent: BinaryExpression) => parenthesizeBinaryOperand(getOperator(parent), node, false) },
],
[SyntaxKind.ConditionalExpression]: [
{ name: "condition", test: isExpression },
@ -196,7 +199,7 @@ namespace ts {
{ name: "expression", test: isExpression, optional: true },
],
[SyntaxKind.SpreadElementExpression]: [
{ name: "expression", test: isExpression },
{ name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.ClassExpression]: [
{ name: "decorators", test: isDecorator },
@ -207,7 +210,7 @@ namespace ts {
{ name: "members", test: isClassElement },
],
[SyntaxKind.ExpressionWithTypeArguments]: [
{ name: "expression", test: isLeftHandSideExpression },
{ name: "expression", test: isLeftHandSideExpression, parenthesize: parenthesizeForAccess },
{ name: "typeArguments", test: isTypeNode },
],
[SyntaxKind.AsExpression]: [
@ -227,7 +230,7 @@ namespace ts {
{ name: "declarationList", test: isVariableDeclarationList },
],
[SyntaxKind.ExpressionStatement]: [
{ name: "expression", test: isExpression },
{ name: "expression", test: isExpression, parenthesize: parenthesizeExpressionForExpressionStatement },
],
[SyntaxKind.IfStatement]: [
{ name: "expression", test: isExpression },
@ -290,7 +293,7 @@ namespace ts {
[SyntaxKind.VariableDeclaration]: [
{ name: "name", test: isBindingName },
{ name: "type", test: isTypeNode, optional: true },
{ name: "initializer", test: isExpression, optional: true },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.VariableDeclarationList]: [
{ name: "declarations", test: isVariableDeclaration },
@ -419,7 +422,7 @@ namespace ts {
],
[SyntaxKind.PropertyAssignment]: [
{ name: "name", test: isPropertyName },
{ name: "initializer", test: isExpression },
{ name: "initializer", test: isExpression, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.ShorthandPropertyAssignment]: [
{ name: "name", test: isIdentifier },
@ -427,7 +430,7 @@ namespace ts {
],
[SyntaxKind.EnumMember]: [
{ name: "name", test: isPropertyName },
{ name: "initializer", test: isExpression, optional: true },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList },
],
[SyntaxKind.SourceFile]: [
{ name: "statements", test: isStatement },
@ -622,13 +625,6 @@ namespace ts {
return updated;
}
/**
* Sets the value of an edge, adjusting the value as necessary for cases such as expression precedence.
*/
function setEdgeValue(parentNode: Node & Map<any>, edge: NodeEdge, value: Node | NodeArray<Node>) {
parentNode[edge.name] = value;
}
/**
* Visits a node edge.
*
@ -642,6 +638,26 @@ namespace ts {
: visitNode(<Node>value, visitor, edge.test, edge.optional, edge.lift);
}
/**
* Sets the value of an edge, adjusting the value as necessary for cases such as expression precedence.
*/
function setEdgeValue(parentNode: Node & Map<any>, edge: NodeEdge, value: Node | NodeArray<Node>) {
if (value && edge.parenthesize && !isArray(value)) {
value = parenthesizeEdge(<Node>value, parentNode, edge.parenthesize, edge.test);
}
parentNode[edge.name] = value;
}
/**
* Applies parentheses to a node to ensure the correct precedence.
*/
function parenthesizeEdge(node: Node, parentNode: Node, parenthesize: (node: Node, parentNode: Node) => Node, test: (node: Node) => boolean) {
node = parenthesize(node, parentNode);
Debug.assert(test === undefined || test(node), "Unexpected node kind after visit.");
return node;
}
/**
* Appends a node to an array.
*
@ -848,7 +864,7 @@ namespace ts {
*
* @param nodes The NodeArray.
*/
function liftToBlock(nodes: NodeArray<Node>) {
export function liftToBlock(nodes: NodeArray<Node>) {
Debug.assert(every(nodes, isStatement), "Cannot lift nodes to a Block.");
return createBlock(<NodeArray<Statement>>nodes);
}