Skip to content

Commit f5c2740

Browse files
committed
Flag assignments to a const
1 parent cffc62a commit f5c2740

12 files changed

+480
-6
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,9 @@ module ts {
318318
if (!s && nameNotFoundMessage) {
319319
error(errorLocation, nameNotFoundMessage, nameArg);
320320
}
321+
321322
if (s && s.flags & SymbolFlags.BlockScoped) {
323+
// Block-scoped variables can not be used before thier definition
322324
var declaration = forEach(s.declarations, d => d.flags & NodeFlags.BlockScoped ? d : undefined);
323325
Debug.assert(declaration, "Bock-scoped variable declaration is undefined");
324326
var declarationSourceFile = getSourceFileOfNode(declaration);
@@ -4923,7 +4925,7 @@ module ts {
49234925
return true;
49244926
}
49254927

4926-
function checkReferenceExpression(n: Node, message: DiagnosticMessage): boolean {
4928+
function checkReferenceExpression(n: Node, invalidReferenceMessage: DiagnosticMessage, constantVarianleMessage: DiagnosticMessage): boolean {
49274929
function findSymbol(n: Node): Symbol {
49284930
var symbol = getNodeLinks(n).resolvedSymbol;
49294931
// Because we got the symbol from the resolvedSymbol property, it might be of kind
@@ -4962,8 +4964,20 @@ module ts {
49624964
}
49634965
}
49644966

4967+
function isConstVariableReference(n: Node) {
4968+
if (n.kind === SyntaxKind.Identifier) {
4969+
var symbol = findSymbol(n);
4970+
return symbol && (symbol.flags & SymbolFlags.Variable) !== 0 && (getDeclarationFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0;
4971+
}
4972+
return false;
4973+
}
4974+
49654975
if (!isReferenceOrErrorExpression(n)) {
4966-
error(n, message);
4976+
error(n, invalidReferenceMessage);
4977+
return false;
4978+
}
4979+
if (isConstVariableReference(n)) {
4980+
error(n, constantVarianleMessage);
49674981
return false;
49684982
}
49694983
return true;
@@ -4988,7 +5002,9 @@ module ts {
49885002
var ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
49895003
if (ok) {
49905004
// run check only if former checks succeeded to avoid reporting cascading errors
4991-
checkReferenceExpression(node.operand, Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer);
5005+
checkReferenceExpression(node.operand,
5006+
Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer,
5007+
Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
49925008
}
49935009
return numberType;
49945010
}
@@ -5000,7 +5016,9 @@ module ts {
50005016
var ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
50015017
if (ok) {
50025018
// run check only if former checks succeeded to avoid reporting cascading errors
5003-
checkReferenceExpression(node.operand, Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer);
5019+
checkReferenceExpression(node.operand,
5020+
Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_property_or_indexer,
5021+
Diagnostics.The_operand_of_an_increment_or_decrement_operator_cannot_be_a_constant);
50045022
}
50055023
return numberType;
50065024
}
@@ -5177,7 +5195,7 @@ module ts {
51775195
// requires VarExpr to be classified as a reference
51785196
// A compound assignment furthermore requires VarExpr to be classified as a reference (section 4.1)
51795197
// and the type of the non - compound operation to be assignable to the type of VarExpr.
5180-
var ok = checkReferenceExpression(node.left, Diagnostics.Invalid_left_hand_side_of_assignment_expression);
5198+
var ok = checkReferenceExpression(node.left, Diagnostics.Invalid_left_hand_side_of_assignment_expression, Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant);
51815199
// Use default messages
51825200
if (ok) {
51835201
// to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported
@@ -6252,7 +6270,7 @@ module ts {
62526270
}
62536271
else {
62546272
// run check only former check succeeded to avoid cascading errors
6255-
checkReferenceExpression(node.variable, Diagnostics.Invalid_left_hand_side_in_for_in_statement);
6273+
checkReferenceExpression(node.variable, Diagnostics.Invalid_left_hand_side_in_for_in_statement, Diagnostics.Left_hand_side_of_assignment_expression_cannot_be_a_constant);
62566274
}
62576275
}
62586276

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ module ts {
270270
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}'." },
271271
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." },
272272
Block_scoped_variable_0_used_before_its_declaration: { code: 2448, category: DiagnosticCategory.Error, key: "Block-scoped variable '{0}' used before its declaration." },
273+
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." },
274+
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." },
273275
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
274276
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}'." },
275277
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}'." },

src/compiler/diagnosticMessages.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,14 @@
10721072
"category": "Error",
10731073
"code": 2448
10741074
},
1075+
"The operand of an increment or decrement operator cannot be a constant.": {
1076+
"category": "Error",
1077+
"code": 2449
1078+
},
1079+
"Left-hand side of assignment expression cannot be a constant.": {
1080+
"category": "Error",
1081+
"code": 2450
1082+
},
10751083

10761084
"Import declaration '{0}' is using private name '{1}'.": {
10771085
"category": "Error",
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
tests/cases/compiler/file2.ts(1,1): error TS2449: The operand of an increment or decrement operator cannot be a constant.
2+
3+
4+
==== tests/cases/compiler/file1.ts (0 errors) ====
5+
6+
const x = 0
7+
8+
==== tests/cases/compiler/file2.ts (1 errors) ====
9+
x++;
10+
~
11+
!!! error TS2449: The operand of an increment or decrement operator cannot be a constant.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//// [tests/cases/compiler/constDeclarations-access.ts] ////
2+
3+
//// [file1.ts]
4+
5+
const x = 0
6+
7+
//// [file2.ts]
8+
x++;
9+
10+
//// [file1.js]
11+
const x = 0;
12+
//// [file2.js]
13+
x++;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
tests/cases/compiler/constDeclarations-access2.ts(5,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
2+
tests/cases/compiler/constDeclarations-access2.ts(6,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
3+
tests/cases/compiler/constDeclarations-access2.ts(7,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
4+
tests/cases/compiler/constDeclarations-access2.ts(8,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
5+
tests/cases/compiler/constDeclarations-access2.ts(9,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
6+
tests/cases/compiler/constDeclarations-access2.ts(10,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
7+
tests/cases/compiler/constDeclarations-access2.ts(11,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
8+
tests/cases/compiler/constDeclarations-access2.ts(12,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
9+
tests/cases/compiler/constDeclarations-access2.ts(13,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
10+
tests/cases/compiler/constDeclarations-access2.ts(14,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
11+
tests/cases/compiler/constDeclarations-access2.ts(15,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
12+
tests/cases/compiler/constDeclarations-access2.ts(16,1): error TS2450: Left-hand side of assignment expression cannot be a constant.
13+
tests/cases/compiler/constDeclarations-access2.ts(18,1): error TS2449: The operand of an increment or decrement operator cannot be a constant.
14+
tests/cases/compiler/constDeclarations-access2.ts(19,1): error TS2449: The operand of an increment or decrement operator cannot be a constant.
15+
tests/cases/compiler/constDeclarations-access2.ts(20,3): error TS2449: The operand of an increment or decrement operator cannot be a constant.
16+
tests/cases/compiler/constDeclarations-access2.ts(21,3): error TS2449: The operand of an increment or decrement operator cannot be a constant.
17+
18+
19+
==== tests/cases/compiler/constDeclarations-access2.ts (16 errors) ====
20+
21+
const x = 0
22+
23+
// Errors
24+
x = 1;
25+
~
26+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
27+
x += 2;
28+
~
29+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
30+
x -= 3;
31+
~
32+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
33+
x *= 4;
34+
~
35+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
36+
x /= 5;
37+
~
38+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
39+
x %= 6;
40+
~
41+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
42+
x <<= 7;
43+
~
44+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
45+
x >>= 8;
46+
~
47+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
48+
x >>>= 9;
49+
~
50+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
51+
x &= 10;
52+
~
53+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
54+
x |= 11;
55+
~
56+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
57+
x ^= 12;
58+
~
59+
!!! error TS2450: Left-hand side of assignment expression cannot be a constant.
60+
61+
x++;
62+
~
63+
!!! error TS2449: The operand of an increment or decrement operator cannot be a constant.
64+
x--;
65+
~
66+
!!! error TS2449: The operand of an increment or decrement operator cannot be a constant.
67+
++x;
68+
~
69+
!!! error TS2449: The operand of an increment or decrement operator cannot be a constant.
70+
--x;
71+
~
72+
!!! error TS2449: The operand of an increment or decrement operator cannot be a constant.
73+
74+
// OK
75+
var a = x + 1;
76+
77+
function f(v: number) { }
78+
f(x);
79+
80+
if (x) { }
81+
82+
x;
83+
(x);
84+
85+
-x;
86+
+x;
87+
88+
x.toString();
89+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//// [constDeclarations-access2.ts]
2+
3+
const x = 0
4+
5+
// Errors
6+
x = 1;
7+
x += 2;
8+
x -= 3;
9+
x *= 4;
10+
x /= 5;
11+
x %= 6;
12+
x <<= 7;
13+
x >>= 8;
14+
x >>>= 9;
15+
x &= 10;
16+
x |= 11;
17+
x ^= 12;
18+
19+
x++;
20+
x--;
21+
++x;
22+
--x;
23+
24+
// OK
25+
var a = x + 1;
26+
27+
function f(v: number) { }
28+
f(x);
29+
30+
if (x) { }
31+
32+
x;
33+
(x);
34+
35+
-x;
36+
+x;
37+
38+
x.toString();
39+
40+
41+
//// [constDeclarations-access2.js]
42+
const x = 0;
43+
// Errors
44+
x = 1;
45+
x += 2;
46+
x -= 3;
47+
x *= 4;
48+
x /= 5;
49+
x %= 6;
50+
x <<= 7;
51+
x >>= 8;
52+
x >>>= 9;
53+
x &= 10;
54+
x |= 11;
55+
x ^= 12;
56+
x++;
57+
x--;
58+
++x;
59+
--x;
60+
// OK
61+
var a = x + 1;
62+
function f(v) {
63+
}
64+
f(x);
65+
if (x) {
66+
}
67+
x;
68+
(x);
69+
-x;
70+
+x;
71+
x.toString();
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//// [letDeclarations-access.ts]
2+
3+
let x = 0
4+
5+
// No errors
6+
7+
x = 1;
8+
x += 2;
9+
x -= 3;
10+
x *= 4;
11+
x /= 5;
12+
x %= 6;
13+
x <<= 7;
14+
x >>= 8;
15+
x >>>= 9;
16+
x &= 10;
17+
x |= 11;
18+
x ^= 12;
19+
20+
x++;
21+
x--;
22+
++x;
23+
--x;
24+
25+
var a = x + 1;
26+
27+
function f(v: number) { }
28+
f(x);
29+
30+
if (x) { }
31+
32+
x;
33+
(x);
34+
35+
-x;
36+
+x;
37+
38+
x.toString();
39+
40+
41+
//// [letDeclarations-access.js]
42+
let x = 0;
43+
// No errors
44+
x = 1;
45+
x += 2;
46+
x -= 3;
47+
x *= 4;
48+
x /= 5;
49+
x %= 6;
50+
x <<= 7;
51+
x >>= 8;
52+
x >>>= 9;
53+
x &= 10;
54+
x |= 11;
55+
x ^= 12;
56+
x++;
57+
x--;
58+
++x;
59+
--x;
60+
var a = x + 1;
61+
function f(v) {
62+
}
63+
f(x);
64+
if (x) {
65+
}
66+
x;
67+
(x);
68+
-x;
69+
+x;
70+
x.toString();

0 commit comments

Comments
 (0)