Flag const declarations shodowed by var redeclarations
This commit is contained in:
parent
f5c2740093
commit
82f5fb4055
|
@ -6174,6 +6174,36 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
function checkCollisionsWithConstDeclarations(node: VariableDeclaration) {
|
||||
// Variable declarations are hoisted to the top of their function scope. They can shadow
|
||||
// block scoped declarations, which bind tighter. this will not be flagged as duplicate definition
|
||||
// by the binder as the declaration scope is different.
|
||||
// A non-initialized declaration is a no-op as the block declaration will resolve before the var
|
||||
// declaration. the problem is if the declaration has an initializer. this will act as a write to the
|
||||
// block declared value. this is fine for let, but not const.
|
||||
//
|
||||
// Only consider declarations with initializers, uninitialized var declarations will not
|
||||
// step on a const variable.
|
||||
// Do not consider let and const declarations, as duplicate block-scoped declarations
|
||||
// are handled by the binder.
|
||||
// We are only looking for var declarations that step on const declarations from a
|
||||
// different scope. e.g.:
|
||||
// var x = 0;
|
||||
// {
|
||||
// const x = 0;
|
||||
// var x = 0;
|
||||
// }
|
||||
if (node.initializer && (node.flags & NodeFlags.BlockScoped) === 0) {
|
||||
var symbol = getSymbolOfNode(node);
|
||||
var localDeclarationSymbol = resolveName(node, node.name.text, SymbolFlags.BlockScoped, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined);
|
||||
if (localDeclarationSymbol && localDeclarationSymbol !== symbol) {
|
||||
if (getDeclarationFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.Const) {
|
||||
error(node, Diagnostics.Cannot_redeclare_constant_0, symbolToString(localDeclarationSymbol));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkVariableDeclaration(node: VariableDeclaration) {
|
||||
checkSourceElement(node.type);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
|
@ -6197,6 +6227,8 @@ module ts {
|
|||
// Use default messages
|
||||
checkTypeAssignableTo(checkAndMarkExpression(node.initializer), type, node, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
|
||||
}
|
||||
|
||||
checkCollisionsWithConstDeclarations(node);
|
||||
}
|
||||
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
|
|
|
@ -272,6 +272,7 @@ module ts {
|
|||
Block_scoped_variable_0_used_before_its_declaration: { code: 2448, category: DiagnosticCategory.Error, key: "Block-scoped variable '{0}' used before its declaration." },
|
||||
The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant: { code: 2449, category: DiagnosticCategory.Error, key: "The operand of an increment or decrement operator cannot be a constant." },
|
||||
Left_hand_side_of_assignment_expression_cannot_be_a_constant: { code: 2450, category: DiagnosticCategory.Error, key: "Left-hand side of assignment expression cannot be a constant." },
|
||||
Cannot_redeclare_constant_0: { code: 2451, category: DiagnosticCategory.Error, key: "Cannot redeclare constant '{0}'." },
|
||||
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4001, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
|
||||
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
|
||||
|
|
|
@ -1080,6 +1080,10 @@
|
|||
"category": "Error",
|
||||
"code": 2450
|
||||
},
|
||||
"Cannot redeclare constant '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 2451
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(7,9): error TS2451: Cannot redeclare constant 'x'.
|
||||
tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(15,13): error TS2451: Cannot redeclare constant 'y'.
|
||||
tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts(22,7): error TS2451: Cannot redeclare constant 'z'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/constDeclarationShadowedByVarDeclaration.ts (3 errors) ====
|
||||
|
||||
// Error as declaration of var would cause a write to the const value
|
||||
var x = 0;
|
||||
{
|
||||
const x = 0;
|
||||
|
||||
var x = 0;
|
||||
~
|
||||
!!! error TS2451: Cannot redeclare constant 'x'.
|
||||
}
|
||||
|
||||
|
||||
var y = 0;
|
||||
{
|
||||
const y = 0;
|
||||
{
|
||||
var y = 0;
|
||||
~
|
||||
!!! error TS2451: Cannot redeclare constant 'y'.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
const z = 0;
|
||||
var z = 0
|
||||
~
|
||||
!!! error TS2451: Cannot redeclare constant 'z'.
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
//// [constDeclarationShadowedByVarDeclaration.ts]
|
||||
|
||||
// Error as declaration of var would cause a write to the const value
|
||||
var x = 0;
|
||||
{
|
||||
const x = 0;
|
||||
|
||||
var x = 0;
|
||||
}
|
||||
|
||||
|
||||
var y = 0;
|
||||
{
|
||||
const y = 0;
|
||||
{
|
||||
var y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
const z = 0;
|
||||
var z = 0
|
||||
}
|
||||
|
||||
//// [constDeclarationShadowedByVarDeclaration.js]
|
||||
// Error as declaration of var would cause a write to the const value
|
||||
var x = 0;
|
||||
{
|
||||
const x = 0;
|
||||
var x = 0;
|
||||
}
|
||||
var y = 0;
|
||||
{
|
||||
const y = 0;
|
||||
{
|
||||
var y = 0;
|
||||
}
|
||||
}
|
||||
{
|
||||
const z = 0;
|
||||
var z = 0;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// @target: ES6
|
||||
|
||||
// Error as declaration of var would cause a write to the const value
|
||||
var x = 0;
|
||||
{
|
||||
const x = 0;
|
||||
|
||||
var x = 0;
|
||||
}
|
||||
|
||||
|
||||
var y = 0;
|
||||
{
|
||||
const y = 0;
|
||||
{
|
||||
var y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
const z = 0;
|
||||
var z = 0
|
||||
}
|
Loading…
Reference in a new issue