Added stack behavior verification and ensured proper stack behavior for all emit functions

This commit is contained in:
Ron Buckton
2015-07-23 18:07:31 -07:00
parent 87e146c189
commit 3e6214939c
2 changed files with 985 additions and 376 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -215,8 +215,10 @@ namespace ts {
// Gets the nearest enclosing block scope container that has the provided node
// as a descendant, that is not the provided node.
export function getEnclosingBlockScopeContainer(node: Node): Node {
let current = node.parent;
export function getEnclosingBlockScopeContainer(node: Node): Node;
export function getEnclosingBlockScopeContainer(node: Node, getAncestorOrSelf: (offset: number) => Node, offset: number): Node;
export function getEnclosingBlockScopeContainer(node: Node, getAncestorOrSelf?: (offset: number) => Node, offset?: number): Node {
let current = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent;
while (current) {
if (isFunctionLike(current)) {
return current;
@@ -233,12 +235,12 @@ namespace ts {
case SyntaxKind.Block:
// function block is not considered block-scope container
// see comment in binder.ts: bind(...), case for SyntaxKind.Block
if (!isFunctionLike(current.parent)) {
if (!isFunctionLike(getAncestorOrSelf ? getAncestorOrSelf(offset + 1) : current.parent)) {
return current;
}
}
current = current.parent;
current = getAncestorOrSelf ? getAncestorOrSelf(++offset) : current.parent;
}
}
@@ -333,14 +335,6 @@ namespace ts {
return node.kind === SyntaxKind.EnumDeclaration && isConst(node);
}
function walkUpBindingElementsAndPatterns(node: Node): Node {
while (node && (node.kind === SyntaxKind.BindingElement || isBindingPattern(node))) {
node = node.parent;
}
return node;
}
// Returns the node flags for this node and all relevant parent nodes. This is done so that
// nodes like variable declarations and binding elements can returned a view of their flags
// that includes the modifiers from their container. i.e. flags like export/declare aren't
@@ -348,41 +342,21 @@ namespace ts {
// (if it has one). Similarly, flags for let/const are store on the variable declaration
// list. By calling this function, all those flags are combined so that the client can treat
// the node as if it actually had those flags.
export function getCombinedNodeFlags(node: Node): NodeFlags {
node = walkUpBindingElementsAndPatterns(node);
export function getCombinedNodeFlags(node: Node): NodeFlags;
export function getCombinedNodeFlags(node: Node, getAncestorOrSelf: (offset: number) => Node, offset: number): NodeFlags;
export function getCombinedNodeFlags(node: Node, getAncestorOrSelf?: (offset: number) => Node, offset?: number): NodeFlags {
while (node && (node.kind === SyntaxKind.BindingElement || isBindingPattern(node))) {
node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent;
}
let flags = node.flags;
if (node.kind === SyntaxKind.VariableDeclaration) {
node = node.parent;
node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent;
}
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
flags |= node.flags;
node = node.parent;
}
if (node && node.kind === SyntaxKind.VariableStatement) {
flags |= node.flags;
}
return flags;
}
export function getCombinedNodeFlagsForNodeStack(nodeStack: Node[]): NodeFlags {
let i = nodeStack.length - 1;
let node = nodeStack[i--];
while (node && (node.kind === SyntaxKind.BindingElement || isBindingPattern(node))) {
node = nodeStack[i--];
}
let flags = node.flags;
if (node && node.kind === SyntaxKind.VariableDeclaration) {
node = nodeStack[i--];
}
if (node && node.kind === SyntaxKind.VariableDeclarationList) {
flags |= node.flags;
node = nodeStack[i--];
node = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent;
}
if (node && node.kind === SyntaxKind.VariableStatement) {
@@ -875,7 +849,10 @@ namespace ts {
return nodeIsDecorated(node) || childIsDecorated(node);
}
export function isExpression(node: Node): boolean {
export function isExpression(node: Node): boolean;
export function isExpression(node: Node, getAncestorOrSelf: (offset: number) => Node, offset: number): boolean;
export function isExpression(node: Node, getAncestorOrSelf?: (offset: number) => Node, offset?: number): boolean {
let parent: Node;
switch (node.kind) {
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
@@ -912,18 +889,22 @@ namespace ts {
case SyntaxKind.YieldExpression:
return true;
case SyntaxKind.QualifiedName:
while (node.parent.kind === SyntaxKind.QualifiedName) {
node = node.parent;
parent = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent;
while (parent.kind === SyntaxKind.QualifiedName) {
node = parent;
parent = getAncestorOrSelf ? getAncestorOrSelf(++offset) : node.parent;
}
return node.parent.kind === SyntaxKind.TypeQuery;
return parent.kind === SyntaxKind.TypeQuery;
case SyntaxKind.Identifier:
if (node.parent.kind === SyntaxKind.TypeQuery) {
parent = getAncestorOrSelf ? getAncestorOrSelf(offset + 1) : node.parent;
if (parent.kind === SyntaxKind.TypeQuery) {
return true;
}
// fall through
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
let parent = node.parent;
parent = getAncestorOrSelf ? getAncestorOrSelf(offset + 1) : node.parent;
switch (parent.kind) {
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Parameter:
@@ -964,9 +945,9 @@ namespace ts {
case SyntaxKind.Decorator:
return true;
case SyntaxKind.ExpressionWithTypeArguments:
return (<ExpressionWithTypeArguments>parent).expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent);
return (<ExpressionWithTypeArguments>parent).expression === node && isExpressionWithTypeArgumentsInClassExtendsClause(parent, getAncestorOrSelf, offset + 1);
default:
if (isExpression(parent)) {
if (isExpression(parent, getAncestorOrSelf, offset)) {
return true;
}
}
@@ -1451,7 +1432,7 @@ namespace ts {
export function nodeStartsNewLexicalEnvironment(n: Node): boolean {
return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile;
}
export function nodeIsSynthesized(node: Node): boolean {
return node.pos === -1;
}
@@ -1980,10 +1961,15 @@ namespace ts {
return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment;
}
export function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): boolean {
return node.kind === SyntaxKind.ExpressionWithTypeArguments &&
(<HeritageClause>node.parent).token === SyntaxKind.ExtendsKeyword &&
isClassLike(node.parent.parent);
export function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node, getAncestorOrSelf?: (offset: number) => Node, offset?: number): boolean {
if (node.kind === SyntaxKind.ExpressionWithTypeArguments) {
let parent = getAncestorOrSelf ? getAncestorOrSelf(offset + 1) : node.parent;
if ((<HeritageClause>parent).token === SyntaxKind.ExtendsKeyword) {
let grandparent = getAncestorOrSelf ? getAncestorOrSelf(offset + 2) : parent.parent;
return isClassLike(grandparent);
}
}
return false;
}
// Returns false if this heritage clause element's expression contains something unsupported