Do not allow use of block-scoped variable before its definition

This commit is contained in:
Mohamed Hegazy 2014-10-13 22:19:19 -07:00
parent cf89f5cf58
commit 1dde985f1d
16 changed files with 220 additions and 6 deletions

View file

@ -314,6 +314,21 @@ module ts {
if (!s && nameNotFoundMessage) {
error(errorLocation, nameNotFoundMessage, nameArg);
}
if (s && s.flags & SymbolFlags.BlockScoped) {
var declaration = forEach(s.declarations, d => d.flags & NodeFlags.BlockScoped ? d : undefined);
Debug.assert(declaration, "Bock-scoped variable declaration is undefined");
var declarationSourceFile = getSourceFileOfNode(declaration);
var referenceSourceFile = getSourceFileOfNode(errorLocation);
if (declarationSourceFile === referenceSourceFile && declaration.pos > errorLocation.pos) {
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, identifierToString(declaration.name));
}
else if (compilerOptions.out) {
var sourceFiles = program.getSourceFiles();
if (sourceFiles.indexOf(referenceSourceFile) < sourceFiles.indexOf(declarationSourceFile)) {
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, identifierToString(declaration.name));
}
}
}
return s;
}

View file

@ -269,6 +269,7 @@ module ts {
Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2445, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible within class '{1}' and its subclasses." },
Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1: { code: 2446, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible through an instance of class '{1}'." },
The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead: { code: 2447, category: DiagnosticCategory.Error, key: "The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead." },
Block_scoped_variable_0_used_before_its_declaration: { code: 2448, category: DiagnosticCategory.Error, key: "Block-scoped variable '{0}' used before its declaration." },
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}'." },

View file

@ -451,27 +451,27 @@
"category": "Error",
"code": 1151
},
"'var', 'let' or 'const' expected.": {
"'var', 'let' or 'const' expected.": {
"category": "Error",
"code": 1152
},
"'let' variable declarations are only available when targeting ECMAScript 6 and higher.": {
"'let' variable declarations are only available when targeting ECMAScript 6 and higher.": {
"category": "Error",
"code": 1153
},
"'const' variable declarations are only available when targeting ECMAScript 6 and higher.": {
"'const' variable declarations are only available when targeting ECMAScript 6 and higher.": {
"category": "Error",
"code": 1154
},
"const must be intialized.": {
"const must be intialized.": {
"category": "Error",
"code": 1155
},
"const must be declared inside a block.": {
"const must be declared inside a block.": {
"category": "Error",
"code": 1156
},
"let must be declared inside a block.": {
"let must be declared inside a block.": {
"category": "Error",
"code": 1157
},
@ -1068,6 +1068,10 @@
"category": "Error",
"code": 2447
},
"Block-scoped variable '{0}' used before its declaration.": {
"category": "Error",
"code": 2448
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",

View file

@ -0,0 +1,21 @@
tests/cases/compiler/constDeclarations-useBeforeDefinition.ts(3,5): error TS2448: Block-scoped variable 'c1' used before its declaration.
tests/cases/compiler/constDeclarations-useBeforeDefinition.ts(9,5): error TS2448: Block-scoped variable 'v1' used before its declaration.
==== tests/cases/compiler/constDeclarations-useBeforeDefinition.ts (2 errors) ====
{
c1;
~~
!!! error TS2448: Block-scoped variable 'c1' used before its declaration.
const c1 = 0;
}
var v1;
{
v1;
~~
!!! error TS2448: Block-scoped variable 'v1' used before its declaration.
const v1 = 0;
}

View file

@ -0,0 +1,24 @@
//// [constDeclarations-useBeforeDefinition.ts]
{
c1;
const c1 = 0;
}
var v1;
{
v1;
const v1 = 0;
}
//// [constDeclarations-useBeforeDefinition.js]
{
c1;
const c1 = 0;
}
var v1;
{
v1;
const v1 = 0;
}

View file

@ -0,0 +1,11 @@
tests/cases/compiler/file1.ts(2,1): error TS2448: Block-scoped variable 'c' used before its declaration.
==== tests/cases/compiler/file1.ts (1 errors) ====
c;
~
!!! error TS2448: Block-scoped variable 'c' used before its declaration.
==== tests/cases/compiler/file2.ts (0 errors) ====
const c = 0;

View file

@ -0,0 +1,12 @@
//// [tests/cases/compiler/constDeclarations-useBeforeDefinition2.ts] ////
//// [file1.ts]
c;
//// [file2.ts]
const c = 0;
//// [out.js]
c;
const c = 0;

View file

@ -0,0 +1,21 @@
tests/cases/compiler/letDeclarations-useBeforeDefinition.ts(3,5): error TS2448: Block-scoped variable 'l1' used before its declaration.
tests/cases/compiler/letDeclarations-useBeforeDefinition.ts(9,5): error TS2448: Block-scoped variable 'v1' used before its declaration.
==== tests/cases/compiler/letDeclarations-useBeforeDefinition.ts (2 errors) ====
{
l1;
~~
!!! error TS2448: Block-scoped variable 'l1' used before its declaration.
let l1;
}
var v1;
{
v1;
~~
!!! error TS2448: Block-scoped variable 'v1' used before its declaration.
let v1 = 0;
}

View file

@ -0,0 +1,24 @@
//// [letDeclarations-useBeforeDefinition.ts]
{
l1;
let l1;
}
var v1;
{
v1;
let v1 = 0;
}
//// [letDeclarations-useBeforeDefinition.js]
{
l1;
let l1;
}
var v1;
{
v1;
let v1 = 0;
}

View file

@ -0,0 +1,11 @@
tests/cases/compiler/file1.ts(2,1): error TS2448: Block-scoped variable 'l' used before its declaration.
==== tests/cases/compiler/file1.ts (1 errors) ====
l;
~
!!! error TS2448: Block-scoped variable 'l' used before its declaration.
==== tests/cases/compiler/file2.ts (0 errors) ====
const l = 0;

View file

@ -0,0 +1,12 @@
//// [tests/cases/compiler/letDeclarations-useBeforeDefinition2.ts] ////
//// [file1.ts]
l;
//// [file2.ts]
const l = 0;
//// [out.js]
l;
const l = 0;

View file

@ -0,0 +1,18 @@
tests/cases/compiler/letDeclarations3.ts(3,5): error TS2300: Duplicate identifier 'l1'.
tests/cases/compiler/letDeclarations3.ts(3,9): error TS2300: Duplicate identifier 'l1'.
tests/cases/compiler/letDeclarations3.ts(3,13): error TS2300: Duplicate identifier 'l1'.
==== tests/cases/compiler/letDeclarations3.ts (3 errors) ====
// Duplicate variables
let l1, l1, l1;
~~
!!! error TS2300: Duplicate identifier 'l1'.
~~
!!! error TS2300: Duplicate identifier 'l1'.
~~
!!! error TS2300: Duplicate identifier 'l1'.
// unexpected 'let'
let l2, let, l3;

View file

@ -0,0 +1,12 @@
// @target: ES6
{
c1;
const c1 = 0;
}
var v1;
{
v1;
const v1 = 0;
}

View file

@ -0,0 +1,8 @@
// @target: ES6
// @out: out.js
// @Filename: file1.ts
c;
// @Filename: file2.ts
const c = 0;

View file

@ -0,0 +1,12 @@
// @target: ES6
{
l1;
let l1;
}
var v1;
{
v1;
let v1 = 0;
}

View file

@ -0,0 +1,8 @@
// @target: ES6
// @out: out.js
// @Filename: file1.ts
l;
// @Filename: file2.ts
const l = 0;