From 50390bb586985232854c258e87f53ec24c62b651 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 2 May 2016 13:31:35 -0700 Subject: [PATCH] check usage before declaration for computed properties in destructuring inside for-of variable declaration --- src/compiler/checker.ts | 30 ++++++++++++------- ...blockScopedBindingUsedBeforeDef.errors.txt | 23 ++++++++++++++ .../blockScopedBindingUsedBeforeDef.js | 21 +++++++++++++ .../blockScopedBindingUsedBeforeDef.ts | 8 +++++ 4 files changed, 72 insertions(+), 10 deletions(-) create mode 100644 tests/baselines/reference/blockScopedBindingUsedBeforeDef.errors.txt create mode 100644 tests/baselines/reference/blockScopedBindingUsedBeforeDef.js create mode 100644 tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8b53ecbf191..cf374acd97a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -574,18 +574,28 @@ namespace ts { function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean { const container = getEnclosingBlockScopeContainer(declaration); - if (declaration.parent.parent.kind === SyntaxKind.VariableStatement || - declaration.parent.parent.kind === SyntaxKind.ForStatement) { - // variable statement/for statement case, - // use site should not be inside variable declaration (initializer of declaration or binding element) - return isSameScopeDescendentOf(usage, declaration, container); + 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)) { + return true; + } + break; } - else if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement || - declaration.parent.parent.kind === SyntaxKind.ForInStatement) { - // ForIn/ForOf case - use site should not be used in expression part - const expression = (declaration.parent.parent).expression; - return isSameScopeDescendentOf(usage, expression, container); + + switch (declaration.parent.parent.kind) { + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + // ForIn/ForOf case - use site should not be used in expression part + if (isSameScopeDescendentOf(usage, (declaration.parent.parent).expression, container)) { + return true; + } } + + return false; } function isUsedInFunctionOrNonStaticProperty(declaration: Declaration, usage: Node): boolean { diff --git a/tests/baselines/reference/blockScopedBindingUsedBeforeDef.errors.txt b/tests/baselines/reference/blockScopedBindingUsedBeforeDef.errors.txt new file mode 100644 index 00000000000..55b5c9dab2d --- /dev/null +++ b/tests/baselines/reference/blockScopedBindingUsedBeforeDef.errors.txt @@ -0,0 +1,23 @@ +tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts(2,12): error TS2448: Block-scoped variable 'a' used before its declaration. +tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts(5,12): error TS2448: Block-scoped variable 'a' used before its declaration. +tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts(5,35): error TS7027: Unreachable code detected. +tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts(8,7): error TS2448: Block-scoped variable 'b' used before its declaration. + + +==== tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts (4 errors) ==== + // 1: + for (let {[a]: a} of [{ }]) continue; + ~ +!!! error TS2448: Block-scoped variable 'a' used before its declaration. + + // 2: + for (let {[a]: a} = { }; false; ) continue; + ~ +!!! error TS2448: Block-scoped variable 'a' used before its declaration. + ~~~~~~~~ +!!! error TS7027: Unreachable code detected. + + // 3: + let {[b]: b} = { }; + ~ +!!! error TS2448: Block-scoped variable 'b' used before its declaration. \ No newline at end of file diff --git a/tests/baselines/reference/blockScopedBindingUsedBeforeDef.js b/tests/baselines/reference/blockScopedBindingUsedBeforeDef.js new file mode 100644 index 00000000000..cc9ad56be88 --- /dev/null +++ b/tests/baselines/reference/blockScopedBindingUsedBeforeDef.js @@ -0,0 +1,21 @@ +//// [blockScopedBindingUsedBeforeDef.ts] +// 1: +for (let {[a]: a} of [{ }]) continue; + +// 2: +for (let {[a]: a} = { }; false; ) continue; + +// 3: +let {[b]: b} = { }; + +//// [blockScopedBindingUsedBeforeDef.js] +// 1: +for (var _i = 0, _a = [{}]; _i < _a.length; _i++) { + var _b = a, a = _a[_i][_b]; + continue; +} +// 2: +for (var _c = a, a = {}[_c]; false;) + continue; +// 3: +var _d = b, b = {}[_d]; diff --git a/tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts b/tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts new file mode 100644 index 00000000000..c0b803df6e8 --- /dev/null +++ b/tests/cases/compiler/blockScopedBindingUsedBeforeDef.ts @@ -0,0 +1,8 @@ +// 1: +for (let {[a]: a} of [{ }]) continue; + +// 2: +for (let {[a]: a} = { }; false; ) continue; + +// 3: +let {[b]: b} = { }; \ No newline at end of file