Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
873c1df
Add es6 target
mhegazy Oct 11, 2014
778f101
Add basic parsing support for let and const
mhegazy Oct 13, 2014
979d45e
Disallow let and const declarations outside blocks
mhegazy Oct 13, 2014
6f6f4af
Fix line endings
mhegazy Oct 13, 2014
cf89f5c
Add binder support for block scoped variable declarations
mhegazy Oct 14, 2014
1dde985
Do not allow use of block-scoped variable before its definition
mhegazy Oct 14, 2014
318575c
Ensure duplicate let/const declarations accross files are reported
mhegazy Oct 14, 2014
cffc62a
Report duplicate identifier errors on all locations for merged declar…
mhegazy Oct 14, 2014
f5c2740
Flag assignments to a const
mhegazy Oct 14, 2014
82f5fb4
Flag const declarations shodowed by var redeclarations
mhegazy Oct 15, 2014
3e45601
Allow const in for statements
mhegazy Oct 15, 2014
03a100d
Do not allow let and const declarations to be exported from a module
mhegazy Oct 15, 2014
6154923
Fix emitting for const in for loops
mhegazy Oct 15, 2014
e15f4e6
Merge branch 'master' into letAndConst
mhegazy Oct 16, 2014
60bb37b
Add language service support for const
mhegazy Oct 16, 2014
fd469d6
Fix search for shadowed const declarations by a var declarations to s…
mhegazy Oct 17, 2014
4ef68b9
Respond to code review comments
mhegazy Oct 17, 2014
a5a6c6f
Allow const and let declarations to be exported in modules. Also ensu…
mhegazy Oct 17, 2014
0a59cdd
Treat blockScoped variable declarations as a separate category when i…
mhegazy Oct 17, 2014
0e7d8b6
Merge branch 'master' into letAndConst
mhegazy Oct 20, 2014
dd5c89d
Update error messages
mhegazy Oct 20, 2014
91f4098
Simplify the binder logic for managing blockScopeContainer
mhegazy Oct 20, 2014
d5fe43b
allow let and const declarations in module bodies under labels
mhegazy Oct 20, 2014
dd7ca69
Create a new flag for diagnostics 'isEarly' and disable emit if this …
mhegazy Oct 21, 2014
373dc76
respond to code review comments
mhegazy Oct 21, 2014
9353c11
Merge branch 'master' into letAndConst
mhegazy Oct 23, 2014
d1858d0
Merge branch 'master' into letAndConst
mhegazy Oct 23, 2014
e4a2084
Ensure let and const declarations in labels are parsed correctelly
mhegazy Oct 24, 2014
67c78a2
Only check for collisions with variabels and not properties
mhegazy Oct 24, 2014
51e101c
Merge branch 'master' into letAndConst
mhegazy Oct 24, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add basic parsing support for let and const
  • Loading branch information
mhegazy committed Oct 13, 2014
commit 778f101dea279a97349261a802158bd1055b77f9
4 changes: 4 additions & 0 deletions src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ module ts {
Filename_0_differs_from_already_included_filename_1_only_in_casing: { code: 1149, category: DiagnosticCategory.Error, key: "Filename '{0}' differs from already included filename '{1}' only in casing" },
new_T_cannot_be_used_to_create_an_array_Use_new_Array_T_instead: { code: 1150, category: DiagnosticCategory.Error, key: "'new T[]' cannot be used to create an array. Use 'new Array<T>()' instead." },
An_enum_member_cannot_have_a_numeric_name: { code: 1151, category: DiagnosticCategory.Error, key: "An enum member cannot have a numeric name." },
var_let_or_const_expected: { code: 1152, category: DiagnosticCategory.Error, key: "'var', 'let' or 'const' expected." },
let_variable_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1153, category: DiagnosticCategory.Error, key: "'let' variable declarations are only available when targeting ECMAScript 6 and higher." },
const_variable_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1154, category: DiagnosticCategory.Error, key: "'const' variable declarations are only available when targeting ECMAScript 6 and higher." },
Const_must_be_intialized: { code: 1155, category: DiagnosticCategory.Error, key: "Const must be intialized." },
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
Expand Down
16 changes: 16 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,22 @@
"category": "Error",
"code": 1151
},
"'var', 'let' or 'const' expected.": {
"category": "Error",
"code": 1152
},
"'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.": {
"category": "Error",
"code": 1154
},
"Const must be intialized.": {
"category": "Error",
"code": 1155
},

"Duplicate identifier '{0}'.": {
"category": "Error",
Expand Down
46 changes: 41 additions & 5 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,12 @@ module ts {
write(" ");
endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
if (node.declarations) {
emitToken(SyntaxKind.VarKeyword, endPos);
if (node.declarations[0] && node.declarations[0].flags & NodeFlags.Let) {
emitToken(SyntaxKind.LetKeyword, endPos);
}
else {
emitToken(SyntaxKind.VarKeyword, endPos);
}
write(" ");
emitCommaList(node.declarations, /*includeTrailingComma*/ false);
}
Expand All @@ -1169,7 +1174,12 @@ module ts {
write(" ");
endPos = emitToken(SyntaxKind.OpenParenToken, endPos);
if (node.declaration) {
emitToken(SyntaxKind.VarKeyword, endPos);
if (node.declaration.flags & NodeFlags.Let) {
emitToken(SyntaxKind.LetKeyword, endPos);
}
else {
emitToken(SyntaxKind.VarKeyword, endPos);
}
write(" ");
emit(node.declaration);
}
Expand Down Expand Up @@ -1298,7 +1308,17 @@ module ts {

function emitVariableStatement(node: VariableStatement) {
emitLeadingComments(node);
if (!(node.flags & NodeFlags.Export)) write("var ");
if (!(node.flags & NodeFlags.Export)) {
if (node.flags & NodeFlags.Let) {
write("let ");
}
else if (node.flags & NodeFlags.Const) {
write("const ");
}
else {
write("var ");
}
}
emitCommaList(node.declarations, /*includeTrailingComma*/ false);
write(";");
emitTrailingComments(node);
Expand Down Expand Up @@ -1774,7 +1794,15 @@ module ts {
if (node.flags & NodeFlags.Export) {
writeLine();
emitStart(node);
write("var ");
if (node.flags & NodeFlags.Let) {
write("let ");
}
else if (node.flags & NodeFlags.Const) {
write("const ");
}
else {
write("var ");
}
emit(node.name);
write(" = ");
emitModuleMemberName(node);
Expand Down Expand Up @@ -2822,7 +2850,15 @@ module ts {
if (hasDeclarationWithEmit) {
emitJsDocComments(node);
emitDeclarationFlags(node);
write("var ");
if (node.flags & NodeFlags.Let) {
write("let ");
}
else if (node.flags & NodeFlags.Const) {
write("const ");
}
else {
write("var ");
}
emitCommaList(node.declarations, emitVariableDeclaration);
write(";");
writeLine();
Expand Down
41 changes: 39 additions & 2 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2645,6 +2645,15 @@ module ts {
error(Diagnostics.Variable_declaration_list_cannot_be_empty);
}
}
else if (parseOptional(SyntaxKind.LetKeyword)) {
var declarations = parseVariableDeclarationList(NodeFlags.Let, true);
if (!declarations.length) {
error(Diagnostics.Variable_declaration_list_cannot_be_empty);
}
if (languageVersion < ScriptTarget.ES6) {
grammarErrorAtPos(declarations.pos, declarations.end - declarations.pos, Diagnostics.let_variable_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
}
else {
var varOrInit = parseExpression(true);
}
Expand Down Expand Up @@ -2970,6 +2979,8 @@ module ts {
return !inErrorRecovery;
case SyntaxKind.OpenBraceToken:
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.FunctionKeyword:
case SyntaxKind.IfKeyword:
case SyntaxKind.DoKeyword:
Expand Down Expand Up @@ -3016,6 +3027,8 @@ module ts {
case SyntaxKind.OpenBraceToken:
return parseBlock(/* ignoreMissingOpenBrace */ false, /*checkForStrictMode*/ false);
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.ConstKeyword:
return parseVariableStatement();
case SyntaxKind.FunctionKeyword:
return parseFunctionDeclaration();
Expand Down Expand Up @@ -3095,6 +3108,9 @@ module ts {
if (inAmbientContext && node.initializer && errorCountBeforeVariableDeclaration === file.syntacticErrors.length) {
grammarErrorAtPos(initializerStart, initializerFirstTokenLength, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts);
}
if (!inAmbientContext && !node.initializer && flags & NodeFlags.Const) {
grammarErrorOnNode(node, Diagnostics.Const_must_be_intialized);
}
if (isInStrictMode && isEvalOrArgumentsIdentifier(node.name)) {
// It is a SyntaxError if a VariableDeclaration or VariableDeclarationNoIn occurs within strict code
// and its Identifier is eval or arguments
Expand All @@ -3112,13 +3128,30 @@ module ts {
var node = <VariableStatement>createNode(SyntaxKind.VariableStatement, pos);
if (flags) node.flags = flags;
var errorCountBeforeVarStatement = file.syntacticErrors.length;
parseExpected(SyntaxKind.VarKeyword);
node.declarations = parseVariableDeclarationList(flags, /*noIn*/false);
if (token === SyntaxKind.LetKeyword) {
node.flags |= NodeFlags.Let;
}
else if (token === SyntaxKind.ConstKeyword) {
node.flags |= NodeFlags.Const;
}
else if (token !== SyntaxKind.VarKeyword) {
error(Diagnostics.var_let_or_const_expected);
}
nextToken();
node.declarations = parseVariableDeclarationList(node.flags, /*noIn*/false);
parseSemicolon();
finishNode(node);
if (!node.declarations.length && file.syntacticErrors.length === errorCountBeforeVarStatement) {
grammarErrorOnNode(node, Diagnostics.Variable_declaration_list_cannot_be_empty);
}
if (languageVersion < ScriptTarget.ES6) {
if (node.flags & NodeFlags.Let) {
grammarErrorOnNode(node, Diagnostics.let_variable_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
else if (node.flags & NodeFlags.Const) {
grammarErrorOnNode(node, Diagnostics.const_variable_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
}
return node;
}

Expand Down Expand Up @@ -3697,6 +3730,8 @@ module ts {
function isDeclaration(): boolean {
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.FunctionKeyword:
return true;
case SyntaxKind.ClassKeyword:
Expand Down Expand Up @@ -3747,6 +3782,8 @@ module ts {
var result: Declaration;
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.ConstKeyword:
result = parseVariableStatement(pos, flags);
break;
case SyntaxKind.FunctionKeyword:
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ module ts {
MultiLine = 0x00000100, // Multi-line array or object literal
Synthetic = 0x00000200, // Synthetic node (for full fidelity)
DeclarationFile = 0x00000400, // Node is a .d.ts file
Let = 0x00000800,
Const = 0x00001000,

Modifier = Export | Ambient | Public | Private | Protected | Static,
AccessibilityModifier = Public | Private | Protected
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
tests/cases/compiler/constDeclarations-ambient-errors.ts(3,27): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/compiler/constDeclarations-ambient-errors.ts(4,26): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/compiler/constDeclarations-ambient-errors.ts(5,18): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/compiler/constDeclarations-ambient-errors.ts(5,37): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/compiler/constDeclarations-ambient-errors.ts(5,51): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/compiler/constDeclarations-ambient-errors.ts(8,14): error TS1039: Initializers are not allowed in ambient contexts.
tests/cases/compiler/constDeclarations-ambient-errors.ts(9,22): error TS1039: Initializers are not allowed in ambient contexts.


==== tests/cases/compiler/constDeclarations-ambient-errors.ts (7 errors) ====

// error: no intialization expected in ambient declarations
declare const c1: boolean = true;
~
!!! error TS1039: Initializers are not allowed in ambient contexts.
declare const c2: number = 0;
~
!!! error TS1039: Initializers are not allowed in ambient contexts.
declare const c3 = null, c4 :string = "", c5: any = 0;
~
!!! error TS1039: Initializers are not allowed in ambient contexts.
~
!!! error TS1039: Initializers are not allowed in ambient contexts.
~
!!! error TS1039: Initializers are not allowed in ambient contexts.

declare module M {
const c6 = 0;
~
!!! error TS1039: Initializers are not allowed in ambient contexts.
const c7: number = 7;
~
!!! error TS1039: Initializers are not allowed in ambient contexts.
}
13 changes: 13 additions & 0 deletions tests/baselines/reference/constDeclarations-ambient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//// [constDeclarations-ambient.ts]

// No error
declare const c1: boolean;
declare const c2: number;
declare const c3, c4 :string, c5: any;

declare module M {
const c6;
const c7: number;
}

//// [constDeclarations-ambient.js]
23 changes: 23 additions & 0 deletions tests/baselines/reference/constDeclarations-ambient.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
=== tests/cases/compiler/constDeclarations-ambient.ts ===

// No error
declare const c1: boolean;
>c1 : boolean

declare const c2: number;
>c2 : number

declare const c3, c4 :string, c5: any;
>c3 : any
>c4 : string
>c5 : any

declare module M {
>M : typeof M

const c6;
>c6 : any

const c7: number;
>c7 : number
}
62 changes: 62 additions & 0 deletions tests/baselines/reference/constDeclarations-errors.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
tests/cases/compiler/constDeclarations-errors.ts(3,7): error TS1155: const must be intialized.
tests/cases/compiler/constDeclarations-errors.ts(4,7): error TS1155: const must be intialized.
tests/cases/compiler/constDeclarations-errors.ts(5,7): error TS1155: const must be intialized.
tests/cases/compiler/constDeclarations-errors.ts(5,11): error TS1155: const must be intialized.
tests/cases/compiler/constDeclarations-errors.ts(5,15): error TS1155: const must be intialized.
tests/cases/compiler/constDeclarations-errors.ts(5,27): error TS1155: const must be intialized.
tests/cases/compiler/constDeclarations-errors.ts(8,5): error TS1109: Expression expected.
tests/cases/compiler/constDeclarations-errors.ts(8,5): error TS1156: const must be declared inside a block.
tests/cases/compiler/constDeclarations-errors.ts(8,11): error TS1155: const must be intialized.
tests/cases/compiler/constDeclarations-errors.ts(8,13): error TS1005: ';' expected.
tests/cases/compiler/constDeclarations-errors.ts(8,13): error TS1128: Declaration or statement expected.
tests/cases/compiler/constDeclarations-errors.ts(8,18): error TS1128: Declaration or statement expected.
tests/cases/compiler/constDeclarations-errors.ts(10,5): error TS1109: Expression expected.
tests/cases/compiler/constDeclarations-errors.ts(10,5): error TS1156: const must be declared inside a block.
tests/cases/compiler/constDeclarations-errors.ts(10,28): error TS1005: ';' expected.
tests/cases/compiler/constDeclarations-errors.ts(10,11): error TS2403: Subsequent variable declarations must have the same type. Variable 'c' must be of type 'any', but here has type 'number'.


==== tests/cases/compiler/constDeclarations-errors.ts (16 errors) ====

// error, missing intialicer
const c1;
~~
!!! error TS1155: const must be intialized.
const c2: number;
~~
!!! error TS1155: const must be intialized.
const c3, c4, c5 :string, c6; // error, missing initialicer
~~
!!! error TS1155: const must be intialized.
~~
!!! error TS1155: const must be intialized.
~~
!!! error TS1155: const must be intialized.
~~
!!! error TS1155: const must be intialized.

// error, wrong context
for(const c in {}) { }
~~~~~
!!! error TS1109: Expression expected.
~~~~~~~
!!! error TS1156: const must be declared inside a block.
~
!!! error TS1155: const must be intialized.
~~
!!! error TS1005: ';' expected.
~~
!!! error TS1128: Declaration or statement expected.
~
!!! error TS1128: Declaration or statement expected.

for(const c = 0; c < 9; c++) { }
~~~~~
!!! error TS1109: Expression expected.
~~~~~~~~~~~~
!!! error TS1156: const must be declared inside a block.
~
!!! error TS1005: ';' expected.
~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'c' must be of type 'any', but here has type 'number'.

17 changes: 17 additions & 0 deletions tests/baselines/reference/constDeclarations-es5.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
tests/cases/compiler/constDeclarations-es5.ts(2,1): error TS1154: 'const' variable declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/constDeclarations-es5.ts(3,1): error TS1154: 'const' variable declarations are only available when targeting ECMAScript 6 and higher.
tests/cases/compiler/constDeclarations-es5.ts(4,1): error TS1154: 'const' variable declarations are only available when targeting ECMAScript 6 and higher.


==== tests/cases/compiler/constDeclarations-es5.ts (3 errors) ====

const z7 = false;
~~~~~~~~~~~~~~~~~
!!! error TS1154: 'const' variable declarations are only available when targeting ECMAScript 6 and higher.
const z8: number = 23;
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1154: 'const' variable declarations are only available when targeting ECMAScript 6 and higher.
const z9 = 0, z10 :string = "", z11 = null;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1154: 'const' variable declarations are only available when targeting ECMAScript 6 and higher.

19 changes: 19 additions & 0 deletions tests/baselines/reference/constDeclarations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//// [constDeclarations.ts]

// No error
const c1 = false;
const c2: number = 23;
const c3 = 0, c4 :string = "", c5 = null;


//// [constDeclarations.js]
// No error
const c1 = false;
const c2 = 23;
const c3 = 0, c4 = "", c5 = null;


//// [constDeclarations.d.ts]
declare const c1: boolean;
declare const c2: number;
declare const c3: number, c4: string, c5: any;
Loading