Skip to content

Commit 120569a

Browse files
committed
Support for-in both with and without variable declaration
1 parent 9ce5e64 commit 120569a

1 file changed

Lines changed: 32 additions & 6 deletions

File tree

src/compiler/checker.ts

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8563,18 +8563,44 @@ namespace ts {
85638563
return true;
85648564
}
85658565

8566+
/**
8567+
* Return the symbol of the for-in variable declared or referenced by the given for-in statement.
8568+
*/
8569+
function getForInVariableSymbol(node: ForInStatement): Symbol {
8570+
const initializer = node.initializer;
8571+
if (initializer.kind === SyntaxKind.VariableDeclarationList) {
8572+
const variable = (<VariableDeclarationList>initializer).declarations[0];
8573+
if (variable && !isBindingPattern(variable.name)) {
8574+
return getSymbolOfNode(variable);
8575+
}
8576+
}
8577+
else if (initializer.kind === SyntaxKind.Identifier) {
8578+
return getResolvedSymbol(<Identifier>initializer);
8579+
}
8580+
return undefined;
8581+
}
8582+
85668583
/**
85678584
* Return true if given node is an expression consisting of an identifier (possibly parenthesized)
8568-
* that references a variable declared in a for-in statement for an array-like object.
8585+
* that references a variable declared in a containing for-in statement for an array-like object.
85698586
*/
8570-
function isForInVariableForArrayLikeObject(node: Expression) {
8571-
const e = skipParenthesizedNodes(node);
8587+
function isForInVariableForArrayLikeObject(expr: Expression) {
8588+
const e = skipParenthesizedNodes(expr);
85728589
if (e.kind === SyntaxKind.Identifier) {
85738590
const symbol = getResolvedSymbol(<Identifier>e);
85748591
if (symbol.flags & SymbolFlags.Variable) {
8575-
const parent = symbol.valueDeclaration.parent.parent;
8576-
return parent.kind === SyntaxKind.ForInStatement &&
8577-
isArrayLikeType(checkExpression((<ForInStatement>parent).expression));
8592+
let child: Node = expr;
8593+
let node = expr.parent;
8594+
while (node) {
8595+
if (node.kind === SyntaxKind.ForInStatement &&
8596+
child === (<ForInStatement>node).statement &&
8597+
getForInVariableSymbol(<ForInStatement>node) === symbol &&
8598+
isArrayLikeType(checkExpression((<ForInStatement>node).expression))) {
8599+
return true;
8600+
}
8601+
child = node;
8602+
node = node.parent;
8603+
}
85788604
}
85798605
}
85808606
return false;

0 commit comments

Comments
 (0)