diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0a472e5e5df..ac38c26d62e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1347,6 +1347,7 @@ namespace ts { function isBlockScopedNameDeclaredBeforeUse(declaration: Declaration, usage: Node): boolean { const declarationFile = getSourceFileOfNode(declaration); const useFile = getSourceFileOfNode(usage); + const declContainer = getEnclosingBlockScopeContainer(declaration); if (declarationFile !== useFile) { if ((moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || (!compilerOptions.outFile && !compilerOptions.out) || @@ -1389,11 +1390,10 @@ namespace ts { return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ false); } else if (isParameterPropertyDeclaration(declaration, declaration.parent)) { - const container = getEnclosingBlockScopeContainer(declaration.parent); // foo = this.bar is illegal in esnext+useDefineForClassFields when bar is a parameter property return !(compilerOptions.target === ScriptTarget.ESNext && !!compilerOptions.useDefineForClassFields && getContainingClass(declaration) === getContainingClass(usage) - && isUsedInFunctionOrInstanceProperty(usage, declaration, container)); + && isUsedInFunctionOrInstanceProperty(usage, declaration)); } return true; } @@ -1418,11 +1418,10 @@ namespace ts { return true; } - const container = getEnclosingBlockScopeContainer(declaration); if (!!(usage.flags & NodeFlags.JSDoc) || isInTypeQuery(usage)) { return true; } - if (isUsedInFunctionOrInstanceProperty(usage, declaration, container)) { + if (isUsedInFunctionOrInstanceProperty(usage, declaration)) { if (compilerOptions.target === ScriptTarget.ESNext && !!compilerOptions.useDefineForClassFields && getContainingClass(declaration)) { return (isPropertyDeclaration(declaration) || isParameterPropertyDeclaration(declaration, declaration.parent)) && !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ true); @@ -1434,15 +1433,13 @@ namespace ts { return false; function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean { - const container = getEnclosingBlockScopeContainer(declaration); - switch (declaration.parent.parent.kind) { case SyntaxKind.VariableStatement: case SyntaxKind.ForStatement: case SyntaxKind.ForOfStatement: // variable statement/for/for-of statement case, // use site should not be inside variable declaration (initializer of declaration or binding element) - if (isSameScopeDescendentOf(usage, declaration, container)) { + if (isSameScopeDescendentOf(usage, declaration, declContainer)) { return true; } break; @@ -1450,12 +1447,12 @@ namespace ts { // ForIn/ForOf case - use site should not be used in expression part const grandparent = declaration.parent.parent; - return isForInOrOfStatement(grandparent) && isSameScopeDescendentOf(usage, grandparent.expression, container); + return isForInOrOfStatement(grandparent) && isSameScopeDescendentOf(usage, grandparent.expression, declContainer); } - function isUsedInFunctionOrInstanceProperty(usage: Node, declaration: Node, container?: Node): boolean { + function isUsedInFunctionOrInstanceProperty(usage: Node, declaration: Node): boolean { return !!findAncestor(usage, current => { - if (current === container) { + if (current === declContainer) { return "quit"; } if (isFunctionLike(current)) {