From 433ea84c524fbb6aaf9f38970ac03a1d90e831eb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 30 Nov 2018 16:28:10 -0800 Subject: [PATCH] Handle destructuring in control flow reference matching --- src/compiler/checker.ts | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 61b9f563c48..0b4853acac7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14613,15 +14613,15 @@ namespace ts { getAccessedPropertyName(source as PropertyAccessExpression | ElementAccessExpression) === getAccessedPropertyName(target) && isMatchingReference((source as PropertyAccessExpression | ElementAccessExpression).expression, target.expression); case SyntaxKind.BindingElement: - if (target.kind !== SyntaxKind.PropertyAccessExpression) return false; - const t = target as PropertyAccessExpression; - if (t.name.escapedText !== getBindingElementNameText(source as BindingElement)) return false; - if (source.parent.parent.kind === SyntaxKind.BindingElement && isMatchingReference(source.parent.parent, t.expression)) { - return true; - } - if (source.parent.parent.kind === SyntaxKind.VariableDeclaration) { - const maybeId = (source.parent.parent as VariableDeclaration).initializer; - return !!maybeId && isMatchingReference(maybeId, t.expression); + if (target.kind === SyntaxKind.PropertyAccessExpression && (target).name.escapedText === getBindingElementNameText(source)) { + const ancestor = source.parent.parent; + if (ancestor.kind === SyntaxKind.BindingElement) { + return isMatchingReference(ancestor, (target).expression); + } + if (ancestor.kind === SyntaxKind.VariableDeclaration) { + const initializer = (ancestor).initializer; + return !!initializer && isMatchingReference(initializer, (target).expression); + } } } return false; @@ -14633,14 +14633,25 @@ namespace ts { undefined; } + function getReferenceParent(source: Node) { + if (source.kind === SyntaxKind.PropertyAccessExpression) { + return (source).expression; + } + if (source.kind === SyntaxKind.BindingElement) { + const ancestor = source.parent.parent; + return ancestor.kind === SyntaxKind.VariableDeclaration ? (ancestor).initializer : ancestor; + } + return undefined; + } + function containsMatchingReference(source: Node, target: Node) { - while (source.kind === SyntaxKind.PropertyAccessExpression) { - source = (source).expression; - if (isMatchingReference(source, target)) { + let parent = getReferenceParent(source); + while (parent) { + if (isMatchingReference(parent, target)) { return true; } + parent = getReferenceParent(parent); } - return false; } // Return true if target is a property access xxx.yyy, source is a property access xxx.zzz, the declared