mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
consider binding elements as always initialized with doing shadow check
This commit is contained in:
parent
82a940df06
commit
0675a92acc
@ -8609,36 +8609,47 @@ module ts {
|
||||
// const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration
|
||||
// var x = 0; // symbol for this declaration will be 'symbol'
|
||||
// }
|
||||
if (node.initializer && (getCombinedNodeFlags(node) & NodeFlags.BlockScoped) === 0) {
|
||||
var symbol = getSymbolOfNode(node);
|
||||
if (symbol.flags & SymbolFlags.FunctionScopedVariable) {
|
||||
var localDeclarationSymbol = resolveName(node, (<Identifier>node.name).text, SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined);
|
||||
if (localDeclarationSymbol &&
|
||||
localDeclarationSymbol !== symbol &&
|
||||
localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) {
|
||||
if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) {
|
||||
|
||||
var varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList);
|
||||
var container =
|
||||
varDeclList.parent.kind === SyntaxKind.VariableStatement &&
|
||||
varDeclList.parent.parent;
|
||||
// skip block-scoped variables and parameters
|
||||
if ((getCombinedNodeFlags(node) & NodeFlags.BlockScoped) !== 0 || isParameterDeclaration(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// names of block-scoped and function scoped variables can collide only
|
||||
// if block scoped variable is defined in the function\module\source file scope (because of variable hoisting)
|
||||
var namesShareScope =
|
||||
container &&
|
||||
(container.kind === SyntaxKind.Block && isFunctionLike(container.parent) ||
|
||||
(container.kind === SyntaxKind.ModuleBlock && container.kind === SyntaxKind.ModuleDeclaration) ||
|
||||
container.kind === SyntaxKind.SourceFile);
|
||||
// skip variable declarations that don't have initializers
|
||||
// NOTE: in ES6 spec initializer is required in variable declarations where name is binding pattern
|
||||
// so we'll always treat binding elements as initialized
|
||||
if (node.kind === SyntaxKind.VariableDeclaration && !node.initializer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// here we know that function scoped variable is shadowed by block scoped one
|
||||
// if they are defined in the same scope - binder has already reported redeclaration error
|
||||
// otherwise if variable has an initializer - show error that initialization will fail
|
||||
// since LHS will be block scoped name instead of function scoped
|
||||
if (!namesShareScope) {
|
||||
var name = symbolToString(localDeclarationSymbol);
|
||||
error(node, Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name);
|
||||
}
|
||||
var symbol = getSymbolOfNode(node);
|
||||
if (symbol.flags & SymbolFlags.FunctionScopedVariable) {
|
||||
var localDeclarationSymbol = resolveName(node, (<Identifier>node.name).text, SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined);
|
||||
if (localDeclarationSymbol &&
|
||||
localDeclarationSymbol !== symbol &&
|
||||
localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) {
|
||||
if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) {
|
||||
|
||||
var varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList);
|
||||
var container =
|
||||
varDeclList.parent.kind === SyntaxKind.VariableStatement &&
|
||||
varDeclList.parent.parent;
|
||||
|
||||
// names of block-scoped and function scoped variables can collide only
|
||||
// if block scoped variable is defined in the function\module\source file scope (because of variable hoisting)
|
||||
var namesShareScope =
|
||||
container &&
|
||||
(container.kind === SyntaxKind.Block && isFunctionLike(container.parent) ||
|
||||
(container.kind === SyntaxKind.ModuleBlock && container.kind === SyntaxKind.ModuleDeclaration) ||
|
||||
container.kind === SyntaxKind.SourceFile);
|
||||
|
||||
// here we know that function scoped variable is shadowed by block scoped one
|
||||
// if they are defined in the same scope - binder has already reported redeclaration error
|
||||
// otherwise if variable has an initializer - show error that initialization will fail
|
||||
// since LHS will be block scoped name instead of function scoped
|
||||
if (!namesShareScope) {
|
||||
var name = symbolToString(localDeclarationSymbol);
|
||||
error(node, Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
tests/cases/compiler/shadowingViaLocalValueOrBindingElement.ts(4,13): error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
tests/cases/compiler/shadowingViaLocalValueOrBindingElement.ts(5,15): error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
tests/cases/compiler/shadowingViaLocalValueOrBindingElement.ts(6,18): error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
tests/cases/compiler/shadowingViaLocalValueOrBindingElement.ts(7,15): error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
tests/cases/compiler/shadowingViaLocalValueOrBindingElement.ts(8,18): error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/shadowingViaLocalValueOrBindingElement.ts (5 errors) ====
|
||||
if (true) {
|
||||
let x;
|
||||
if (true) {
|
||||
var x = 0; // Error
|
||||
~
|
||||
!!! error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
var { x = 0 } = { x: 0 }; // Error
|
||||
~
|
||||
!!! error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
var { x: x = 0 } = { x: 0 }; // Error
|
||||
~
|
||||
!!! error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
var { x } = { x: 0 }; // No error, even though the let x is being initialized
|
||||
~
|
||||
!!! error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
var { x: x } = { x: 0 }; // No error, even though the let x is being initialized
|
||||
~
|
||||
!!! error TS2481: Cannot initialize outer scoped variable 'x' in the same scope as block scoped declaration 'x'.
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
//// [shadowingViaLocalValueOrBindingElement.ts]
|
||||
if (true) {
|
||||
let x;
|
||||
if (true) {
|
||||
var x = 0; // Error
|
||||
var { x = 0 } = { x: 0 }; // Error
|
||||
var { x: x = 0 } = { x: 0 }; // Error
|
||||
var { x } = { x: 0 }; // No error, even though the let x is being initialized
|
||||
var { x: x } = { x: 0 }; // No error, even though the let x is being initialized
|
||||
}
|
||||
}
|
||||
|
||||
//// [shadowingViaLocalValueOrBindingElement.js]
|
||||
if (true) {
|
||||
var _x;
|
||||
if (true) {
|
||||
var x = 0; // Error
|
||||
var _a = ({
|
||||
_x: 0
|
||||
}).x, x = _a === void 0 ? 0 : _a; // Error
|
||||
var _b = ({
|
||||
_x: 0
|
||||
}).x, x = _b === void 0 ? 0 : _b; // Error
|
||||
var x = ({
|
||||
_x: 0
|
||||
}).x; // No error, even though the let x is being initialized
|
||||
var x = ({
|
||||
_x: 0
|
||||
}).x; // No error, even though the let x is being initialized
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
if (true) {
|
||||
let x;
|
||||
if (true) {
|
||||
var x = 0; // Error
|
||||
var { x = 0 } = { x: 0 }; // Error
|
||||
var { x: x = 0 } = { x: 0 }; // Error
|
||||
var { x } = { x: 0 }; // No error, even though the let x is being initialized
|
||||
var { x: x } = { x: 0 }; // No error, even though the let x is being initialized
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user