Skip to content

Commit

Permalink
Merge pull request #2684 from Microsoft/migrateStrictModeCheck
Browse files Browse the repository at this point in the history
Migrate strict mode check
  • Loading branch information
yuit committed Apr 12, 2015
2 parents 1c7d8a2 + 63a2359 commit 96995e7
Show file tree
Hide file tree
Showing 88 changed files with 1,420 additions and 665 deletions.
183 changes: 169 additions & 14 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/compiler/diagnosticInformationMap.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ module ts {
Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided: { code: 1209, category: DiagnosticCategory.Error, key: "Ambient const enums are not allowed when the '--separateCompilation' flag is provided." },
Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode: { code: 1210, category: DiagnosticCategory.Error, key: "Invalid use of '{0}'. Class definitions are automatically in strict mode." },
A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1211, category: DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" },
Identifier_expected_0_is_a_reserved_word_in_strict_mode: { code: 1212, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode" },
Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1213, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
Identifier_expected_0_is_a_reserved_word_in_strict_mode_External_Module_is_automatically_in_strict_mode: { code: 1214, category: DiagnosticCategory.Error, key: "Identifier expected. '{0}' is a reserved word in strict mode. External Module is automatically in strict mode." },
Type_expected_0_is_a_reserved_word_in_strict_mode: { code: 1215, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode" },
Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1216, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
Type_expected_0_is_a_reserved_word_in_strict_mode_Module_is_automatically_in_strict_mode: { code: 1217, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Module is automatically in strict mode." },
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
26 changes: 25 additions & 1 deletion src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -657,12 +657,36 @@
},
"Invalid use of '{0}'. Class definitions are automatically in strict mode.": {
"category": "Error",
"code": 1210
"code": 1210
},
"A class declaration without the 'default' modifier must have a name": {
"category": "Error",
"code": 1211
},
"Identifier expected. '{0}' is a reserved word in strict mode": {
"category": "Error",
"code": 1212
},
"Identifier expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode.": {
"category": "Error",
"code": 1213
},
"Identifier expected. '{0}' is a reserved word in strict mode. External Module is automatically in strict mode.": {
"category": "Error",
"code": 1214
},
"Type expected. '{0}' is a reserved word in strict mode": {
"category": "Error",
"code": 1215
},
"Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode.": {
"category": "Error",
"code": 1216
},
"Type expected. '{0}' is a reserved word in strict mode. Module is automatically in strict mode.": {
"category": "Error",
"code": 1217
},
"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2300
Expand Down
30 changes: 29 additions & 1 deletion src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,7 @@ module ts {
return speculationHelper(callback, /*isLookAhead:*/ false);
}

// Ignore strict mode flag because we will report an error in type checker instead.
function isIdentifier(): boolean {
if (token === SyntaxKind.Identifier) {
return true;
Expand All @@ -1360,7 +1361,7 @@ module ts {
return false;
}

return inStrictModeContext() ? token > SyntaxKind.LastFutureReservedWord : token > SyntaxKind.LastReservedWord;
return token > SyntaxKind.LastReservedWord;
}

function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage): boolean {
Expand Down Expand Up @@ -1484,6 +1485,11 @@ module ts {
identifierCount++;
if (isIdentifier) {
let node = <Identifier>createNode(SyntaxKind.Identifier);

// Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker
if (token !== SyntaxKind.Identifier) {
node.originalKeywordKind = token;
}
node.text = internIdentifier(scanner.getTokenValue());
nextToken();
return finishNode(node);
Expand Down Expand Up @@ -4599,6 +4605,18 @@ module ts {
return finishNode(node);
}

function isClassMemberModifier(idToken: SyntaxKind) {
switch (idToken) {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
return true;
default:
return false;
}
}

function isClassMemberStart(): boolean {
let idToken: SyntaxKind;

Expand All @@ -4609,6 +4627,16 @@ module ts {
// Eat up all modifiers, but hold on to the last one in case it is actually an identifier.
while (isModifier(token)) {
idToken = token;
// If the idToken is a class modifier (protected, private, public, and static), it is
// certain that we are starting to parse class member. This allows better error recovery
// Example:
// public foo() ... // true
// public @dec blah ... // true; we will then report an error later
// export public ... // true; we will then report an error later
if (isClassMemberModifier(idToken)) {
return true;
}

nextToken();
}

Expand Down
3 changes: 2 additions & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,8 @@ module ts {
}

export interface Identifier extends PrimaryExpression {
text: string; // Text of identifier (with escapes converted to characters)
text: string; // Text of identifier (with escapes converted to characters)
originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later
}

export interface QualifiedName extends Node {
Expand Down
22 changes: 14 additions & 8 deletions tests/baselines/reference/classUpdateTests.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ tests/cases/compiler/classUpdateTests.ts(95,1): error TS1128: Declaration or sta
tests/cases/compiler/classUpdateTests.ts(99,3): error TS1129: Statement expected.
tests/cases/compiler/classUpdateTests.ts(101,1): error TS1128: Declaration or statement expected.
tests/cases/compiler/classUpdateTests.ts(105,3): error TS1129: Statement expected.
tests/cases/compiler/classUpdateTests.ts(105,15): error TS2339: Property 'p1' does not exist on type 'Q'.
tests/cases/compiler/classUpdateTests.ts(105,14): error TS1005: ';' expected.
tests/cases/compiler/classUpdateTests.ts(107,1): error TS1128: Declaration or statement expected.
tests/cases/compiler/classUpdateTests.ts(111,3): error TS1129: Statement expected.
tests/cases/compiler/classUpdateTests.ts(111,16): error TS2339: Property 'p1' does not exist on type 'R'.
tests/cases/compiler/classUpdateTests.ts(111,15): error TS1005: ';' expected.
tests/cases/compiler/classUpdateTests.ts(113,1): error TS1128: Declaration or statement expected.


==== tests/cases/compiler/classUpdateTests.ts (16 errors) ====
==== tests/cases/compiler/classUpdateTests.ts (18 errors) ====
//
// test codegen for instance properties
//
Expand Down Expand Up @@ -158,17 +160,21 @@ tests/cases/compiler/classUpdateTests.ts(111,16): error TS2339: Property 'p1' do
public this.p1 = 0; // ERROR
~~~~~~
!!! error TS1129: Statement expected.
~~
!!! error TS2339: Property 'p1' does not exist on type 'Q'.
~
!!! error TS1005: ';' expected.
}
}
~
!!! error TS1128: Declaration or statement expected.

class R {
constructor() {
private this.p1 = 0; // ERROR
~~~~~~~
!!! error TS1129: Statement expected.
~~
!!! error TS2339: Property 'p1' does not exist on type 'R'.
~
!!! error TS1005: ';' expected.
}
}
}
~
!!! error TS1128: Declaration or statement expected.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tests/cases/compiler/constructorStaticParamName.ts(4,18): error TS1003: Identifier expected.
tests/cases/compiler/constructorStaticParamName.ts(4,18): error TS1213: Identifier expected. 'static' is a reserved word in strict mode. Class definitions are automatically in strict mode.


==== tests/cases/compiler/constructorStaticParamName.ts (1 errors) ====
Expand All @@ -7,6 +7,6 @@ tests/cases/compiler/constructorStaticParamName.ts(4,18): error TS1003: Identifi
class test {
constructor (static) { }
~~~~~~
!!! error TS1003: Identifier expected.
!!! error TS1213: Identifier expected. 'static' is a reserved word in strict mode. Class definitions are automatically in strict mode.
}

2 changes: 1 addition & 1 deletion tests/baselines/reference/constructorStaticParamName.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class test {
//// [constructorStaticParamName.js]
// static as constructor parameter name should only give error if 'use strict'
var test = (function () {
function test() {
function test(static) {
}
return test;
})();
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
tests/cases/compiler/constructorStaticParamNameErrors.ts(4,18): error TS1003: Identifier expected.
tests/cases/compiler/constructorStaticParamNameErrors.ts(4,18): error TS1213: Identifier expected. 'static' is a reserved word in strict mode. Class definitions are automatically in strict mode.


==== tests/cases/compiler/constructorStaticParamNameErrors.ts (1 errors) ====
Expand All @@ -7,5 +7,5 @@ tests/cases/compiler/constructorStaticParamNameErrors.ts(4,18): error TS1003: Id
class test {
constructor (static) { }
~~~~~~
!!! error TS1003: Identifier expected.
!!! error TS1213: Identifier expected. 'static' is a reserved word in strict mode. Class definitions are automatically in strict mode.
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class test {
'use strict';
// static as constructor parameter name should give error if 'use strict'
var test = (function () {
function test() {
function test(static) {
}
return test;
})();
Loading

0 comments on commit 96995e7

Please sign in to comment.