From 670a8c0a76d077d609f0a7951c4b823ac4f04155 Mon Sep 17 00:00:00 2001 From: Yui T Date: Fri, 21 Nov 2014 18:09:50 -0800 Subject: [PATCH 1/9] Binary and octal integer literal support --- .../diagnosticInformationMap.generated.ts | 4 +- src/compiler/diagnosticMessages.json | 11 ++++- src/compiler/emitter.ts | 6 ++- src/compiler/scanner.ts | 41 +++++++++++++++++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index a87b1f8cc28..13587df29e0 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -124,7 +124,9 @@ module ts { Tagged_templates_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1159, category: DiagnosticCategory.Error, key: "Tagged templates are only available when targeting ECMAScript 6 and higher." }, Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." }, Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." }, - An_object_member_cannot_be_declared_optional: { code: 1160, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." }, + An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." }, + Binary_digits_expected: { code: 1163, category: DiagnosticCategory.Error, key: "Binary digits expected." }, + Octal_digits_expected: { code: 1164, category: DiagnosticCategory.Error, key: "Octal digits expected." }, 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." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 7c966f7c954..427eba4531d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -487,10 +487,17 @@ "category": "Error", "code": 1161 }, - "An object member cannot be declared optional.": { "category": "Error", - "code": 1160 + "code": 1162 + }, + "Binary digits expected.": { + "category": "Error", + "code": 1163 + }, + "Octal digits expected.": { + "category": "Error", + "code": 1164 }, "Duplicate identifier '{0}'.": { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index bc74f8304df..9e7b831fd2b 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -794,6 +794,11 @@ module ts { if (compilerOptions.sourceMap && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { writer.writeLiteral(text); } + else if (node.kind === SyntaxKind.NumericLiteral && compilerOptions.target < ScriptTarget.ES6 && + ((text.charCodeAt(1) === CharacterCodes.B || text.charCodeAt(1) === CharacterCodes.b || + text.charCodeAt(1) === CharacterCodes.O || text.charCodeAt(1) === CharacterCodes.o))) { + write(node.text); + } else { write(text); } @@ -802,7 +807,6 @@ module ts { if (compilerOptions.target < ScriptTarget.ES6 && isTemplateLiteralKind(node.kind)) { return getTemplateLiteralAsStringLiteral(node) } - return getSourceTextOfLocalNode(node); } } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index e08f481ba9c..596155c8137 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -520,6 +520,27 @@ module ts { return +(text.substring(start, pos)); } + function scanBinaryOrOctalDigits(base: number): number { + if (base !== 2 && base !== 8) { + return -1; + } + var value = 0; + while (true) { + var ch = text.charCodeAt(pos); + var valueOfCh = ch - CharacterCodes._0; + if (!isDigit(ch)) { + break; + } + // We know at this point that ch must be digit + if (valueOfCh >= base) { + return -1; + } + value = value * base + valueOfCh; + pos++; + } + return value; + } + function scanHexDigits(count: number, mustMatchCount?: boolean): number { var digits = 0; var value = 0; @@ -933,6 +954,26 @@ module ts { tokenValue = "" + value; return SyntaxKind.NumericLiteral; } + else if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) { + pos += 2; + var value = scanBinaryOrOctalDigits(/* binary */2); + if (value < 0) { + error(Diagnostics.Binary_digits_expected); + value = 0; + } + tokenValue = "" + value; + return SyntaxKind.NumericLiteral; + } + else if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) { + pos += 2; + var value = scanBinaryOrOctalDigits(/* octal */8); + if (value < 0) { + error(Diagnostics.Octal_digits_expected); + value = 0; + } + tokenValue = "" + value; + return SyntaxKind.NumericLiteral; + } // Try to parse as an octal if (pos + 1 < len && isOctalDigit(text.charCodeAt(pos + 1))) { tokenValue = "" + scanOctalDigits(); From 5774e64d92789064c76c126e7b0cb8dbcad2062a Mon Sep 17 00:00:00 2001 From: Yui T Date: Sun, 23 Nov 2014 16:23:24 -0800 Subject: [PATCH 2/9] Add test cases --- .../reference/binaryIntegerLiteral.js | 65 +++++++++++++ .../reference/binaryIntegerLiteral.types | 96 +++++++++++++++++++ .../reference/binaryIntegerLiteralES6.js | 64 +++++++++++++ .../reference/binaryIntegerLiteralES6.types | 95 ++++++++++++++++++ .../binaryIntegerLiteralError.errors.txt | 28 ++++++ ...jectTypesWithOptionalProperties.errors.txt | 4 +- .../reference/octalIntegerLiteral.js | 63 ++++++++++++ .../reference/octalIntegerLiteral.types | 95 ++++++++++++++++++ .../reference/octalIntegerLiteralES6.js | 63 ++++++++++++ .../reference/octalIntegerLiteralES6.types | 95 ++++++++++++++++++ .../octalIntegerLiteralError.errors.txt | 28 ++++++ .../binaryIntegerLiteral.ts | 34 +++++++ .../binaryIntegerLiteralES6.ts | 33 +++++++ .../binaryIntegerLiteralError.ts | 9 ++ .../octalIntegerLiteral.ts | 32 +++++++ .../octalIntegerLiteralES6.ts | 32 +++++++ .../octalIntegerLiteralError.ts | 9 ++ 17 files changed, 843 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/binaryIntegerLiteral.js create mode 100644 tests/baselines/reference/binaryIntegerLiteral.types create mode 100644 tests/baselines/reference/binaryIntegerLiteralES6.js create mode 100644 tests/baselines/reference/binaryIntegerLiteralES6.types create mode 100644 tests/baselines/reference/binaryIntegerLiteralError.errors.txt create mode 100644 tests/baselines/reference/octalIntegerLiteral.js create mode 100644 tests/baselines/reference/octalIntegerLiteral.types create mode 100644 tests/baselines/reference/octalIntegerLiteralES6.js create mode 100644 tests/baselines/reference/octalIntegerLiteralES6.types create mode 100644 tests/baselines/reference/octalIntegerLiteralError.errors.txt create mode 100644 tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteral.ts create mode 100644 tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralES6.ts create mode 100644 tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts create mode 100644 tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteral.ts create mode 100644 tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralES6.ts create mode 100644 tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts diff --git a/tests/baselines/reference/binaryIntegerLiteral.js b/tests/baselines/reference/binaryIntegerLiteral.js new file mode 100644 index 00000000000..7e3245d8036 --- /dev/null +++ b/tests/baselines/reference/binaryIntegerLiteral.js @@ -0,0 +1,65 @@ +//// [binaryIntegerLiteral.ts] +var bin1 = 0b11010; +var bin2 = 0B11010; + +var obj1 = { + 0b11010: "Hello", + a: bin1, + bin1, + b: 0b11010, +} + +var obj2 = { + 0B11010: "World", + a: bin2, + bin2, + b: 0B11010, +} + +obj1[0b11010]; // string +obj1[26]; // string +obj1["26"]; // string +obj1["0b11010"]; // any +obj1["a"]; // number +obj1["b"]; // number +obj1["bin1"]; // number + +obj2[0B11010]; // string +obj2[26]; // string +obj2["26"]; // string +obj2["0B11010"]; // any +obj2["a"]; // number +obj2["b"]; // number +obj2["bin2"]; // number + + + +//// [binaryIntegerLiteral.js] +var bin1 = 26; +var bin2 = 26; +var obj1 = { + 26: "Hello", + a: bin1, + bin1: bin1, + b: 26, +}; +var obj2 = { + 26: "World", + a: bin2, + bin2: bin2, + b: 26, +}; +obj1[26]; // string +obj1[26]; // string +obj1["26"]; // string +obj1["0b11010"]; // any +obj1["a"]; // number +obj1["b"]; // number +obj1["bin1"]; // number +obj2[26]; // string +obj2[26]; // string +obj2["26"]; // string +obj2["0B11010"]; // any +obj2["a"]; // number +obj2["b"]; // number +obj2["bin2"]; // number diff --git a/tests/baselines/reference/binaryIntegerLiteral.types b/tests/baselines/reference/binaryIntegerLiteral.types new file mode 100644 index 00000000000..093cb0c46ee --- /dev/null +++ b/tests/baselines/reference/binaryIntegerLiteral.types @@ -0,0 +1,96 @@ +=== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteral.ts === +var bin1 = 0b11010; +>bin1 : number + +var bin2 = 0B11010; +>bin2 : number + +var obj1 = { +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } +>{ 0b11010: "Hello", a: bin1, bin1, b: 0b11010,} : { 0b11010: string; a: number; bin1: number; b: number; } + + 0b11010: "Hello", + a: bin1, +>a : number +>bin1 : number + + bin1, +>bin1 : number + + b: 0b11010, +>b : number +} + +var obj2 = { +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } +>{ 0B11010: "World", a: bin2, bin2, b: 0B11010,} : { 0B11010: string; a: number; bin2: number; b: number; } + + 0B11010: "World", + a: bin2, +>a : number +>bin2 : number + + bin2, +>bin2 : number + + b: 0B11010, +>b : number +} + +obj1[0b11010]; // string +>obj1[0b11010] : string +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1[26]; // string +>obj1[26] : string +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["26"]; // string +>obj1["26"] : string +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["0b11010"]; // any +>obj1["0b11010"] : any +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["a"]; // number +>obj1["a"] : number +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["b"]; // number +>obj1["b"] : number +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["bin1"]; // number +>obj1["bin1"] : number +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj2[0B11010]; // string +>obj2[0B11010] : string +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2[26]; // string +>obj2[26] : string +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["26"]; // string +>obj2["26"] : string +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["0B11010"]; // any +>obj2["0B11010"] : any +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["a"]; // number +>obj2["a"] : number +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["b"]; // number +>obj2["b"] : number +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["bin2"]; // number +>obj2["bin2"] : number +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + + diff --git a/tests/baselines/reference/binaryIntegerLiteralES6.js b/tests/baselines/reference/binaryIntegerLiteralES6.js new file mode 100644 index 00000000000..c8ec7e50632 --- /dev/null +++ b/tests/baselines/reference/binaryIntegerLiteralES6.js @@ -0,0 +1,64 @@ +//// [binaryIntegerLiteralES6.ts] +var bin1 = 0b11010; +var bin2 = 0B11010; + +var obj1 = { + 0b11010: "Hello", + a: bin1, + bin1, + b: 0b11010, +} + +var obj2 = { + 0B11010: "World", + a: bin2, + bin2, + b: 0B11010, +} + +obj1[0b11010]; // string +obj1[26]; // string +obj1["26"]; // string +obj1["0b11010"]; // any +obj1["a"]; // number +obj1["b"]; // number +obj1["bin1"]; // number + +obj2[0B11010]; // string +obj2[26]; // string +obj2["26"]; // string +obj2["0B11010"]; // any +obj2["a"]; // number +obj2["b"]; // number +obj2["bin2"]; // number + + +//// [binaryIntegerLiteralES6.js] +var bin1 = 0b11010; +var bin2 = 0B11010; +var obj1 = { + 0b11010: "Hello", + a: bin1, + bin1, + b: 0b11010, +}; +var obj2 = { + 0B11010: "World", + a: bin2, + bin2, + b: 0B11010, +}; +obj1[0b11010]; // string +obj1[26]; // string +obj1["26"]; // string +obj1["0b11010"]; // any +obj1["a"]; // number +obj1["b"]; // number +obj1["bin1"]; // number +obj2[0B11010]; // string +obj2[26]; // string +obj2["26"]; // string +obj2["0B11010"]; // any +obj2["a"]; // number +obj2["b"]; // number +obj2["bin2"]; // number diff --git a/tests/baselines/reference/binaryIntegerLiteralES6.types b/tests/baselines/reference/binaryIntegerLiteralES6.types new file mode 100644 index 00000000000..b28b68032f3 --- /dev/null +++ b/tests/baselines/reference/binaryIntegerLiteralES6.types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralES6.ts === +var bin1 = 0b11010; +>bin1 : number + +var bin2 = 0B11010; +>bin2 : number + +var obj1 = { +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } +>{ 0b11010: "Hello", a: bin1, bin1, b: 0b11010,} : { 0b11010: string; a: number; bin1: number; b: number; } + + 0b11010: "Hello", + a: bin1, +>a : number +>bin1 : number + + bin1, +>bin1 : number + + b: 0b11010, +>b : number +} + +var obj2 = { +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } +>{ 0B11010: "World", a: bin2, bin2, b: 0B11010,} : { 0B11010: string; a: number; bin2: number; b: number; } + + 0B11010: "World", + a: bin2, +>a : number +>bin2 : number + + bin2, +>bin2 : number + + b: 0B11010, +>b : number +} + +obj1[0b11010]; // string +>obj1[0b11010] : string +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1[26]; // string +>obj1[26] : string +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["26"]; // string +>obj1["26"] : string +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["0b11010"]; // any +>obj1["0b11010"] : any +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["a"]; // number +>obj1["a"] : number +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["b"]; // number +>obj1["b"] : number +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj1["bin1"]; // number +>obj1["bin1"] : number +>obj1 : { 0b11010: string; a: number; bin1: number; b: number; } + +obj2[0B11010]; // string +>obj2[0B11010] : string +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2[26]; // string +>obj2[26] : string +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["26"]; // string +>obj2["26"] : string +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["0B11010"]; // any +>obj2["0B11010"] : any +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["a"]; // number +>obj2["a"] : number +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["b"]; // number +>obj2["b"] : number +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + +obj2["bin2"]; // number +>obj2["bin2"] : number +>obj2 : { 0B11010: string; a: number; bin2: number; b: number; } + diff --git a/tests/baselines/reference/binaryIntegerLiteralError.errors.txt b/tests/baselines/reference/binaryIntegerLiteralError.errors.txt new file mode 100644 index 00000000000..3346ee33774 --- /dev/null +++ b/tests/baselines/reference/binaryIntegerLiteralError.errors.txt @@ -0,0 +1,28 @@ +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(2,17): error TS1163: Binary digits expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(3,17): error TS1163: Binary digits expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(6,5): error TS2300: Duplicate identifier '0b11010'. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(7,5): error TS2300: Duplicate identifier '26'. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(8,5): error TS2300: Duplicate identifier '"26"'. + + +==== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts (5 errors) ==== + // error + var bin1 = 0B1102110; + +!!! error TS1163: Binary digits expected. + var bin1 = 0b11023410; + +!!! error TS1163: Binary digits expected. + + var obj1 = { + 0b11010: "hi", + ~~~~~~~ +!!! error TS2300: Duplicate identifier '0b11010'. + 26: "Hello", + ~~ +!!! error TS2300: Duplicate identifier '26'. + "26": "world", + ~~~~ +!!! error TS2300: Duplicate identifier '"26"'. + }; + \ No newline at end of file diff --git a/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt b/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt index 14afcebd213..3f5321734d1 100644 --- a/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt +++ b/tests/baselines/reference/objectTypesWithOptionalProperties.errors.txt @@ -1,6 +1,6 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(12,6): error TS1112: A class member cannot be declared optional. tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(20,6): error TS1112: A class member cannot be declared optional. -tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(24,6): error TS1160: An object member cannot be declared optional. +tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts(24,6): error TS1162: An object member cannot be declared optional. ==== tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWithOptionalProperties.ts (3 errors) ==== @@ -33,5 +33,5 @@ tests/cases/conformance/types/objectTypeLiteral/methodSignatures/objectTypesWith var b = { x?: 1 // error -!!! error TS1160: An object member cannot be declared optional. +!!! error TS1162: An object member cannot be declared optional. } \ No newline at end of file diff --git a/tests/baselines/reference/octalIntegerLiteral.js b/tests/baselines/reference/octalIntegerLiteral.js new file mode 100644 index 00000000000..5e2dabdeaef --- /dev/null +++ b/tests/baselines/reference/octalIntegerLiteral.js @@ -0,0 +1,63 @@ +//// [octalIntegerLiteral.ts] +var oct1 = 0o45436; +var oct2 = 0O45436; +var obj1 = { + 0o45436: "Hello", + a: 0o45436, + b: oct1, + oct1, +} + +var obj2 = { + 0O45436: "hi", + a: 0O45436, + b: oct2, + oct2, +} + +obj1[0o45436]; // string +obj1["0o45436"]; // any +obj1["19230"]; // string +obj1[19230]; // string +obj1["a"]; // number +obj1["b"]; // number +obj1["oct1"]; // number + +obj2[0O45436]; // string +obj2["0O45436"]; // any +obj2["19230"]; // string +obj2[19230]; // string +obj2["a"]; // number +obj2["b"]; // number +obj2["oct2"]; // number + + +//// [octalIntegerLiteral.js] +var oct1 = 19230; +var oct2 = 19230; +var obj1 = { + 19230: "Hello", + a: 19230, + b: oct1, + oct1: oct1, +}; +var obj2 = { + 19230: "hi", + a: 19230, + b: oct2, + oct2: oct2, +}; +obj1[19230]; // string +obj1["0o45436"]; // any +obj1["19230"]; // string +obj1[19230]; // string +obj1["a"]; // number +obj1["b"]; // number +obj1["oct1"]; // number +obj2[19230]; // string +obj2["0O45436"]; // any +obj2["19230"]; // string +obj2[19230]; // string +obj2["a"]; // number +obj2["b"]; // number +obj2["oct2"]; // number diff --git a/tests/baselines/reference/octalIntegerLiteral.types b/tests/baselines/reference/octalIntegerLiteral.types new file mode 100644 index 00000000000..90cf8c16f1b --- /dev/null +++ b/tests/baselines/reference/octalIntegerLiteral.types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteral.ts === +var oct1 = 0o45436; +>oct1 : number + +var oct2 = 0O45436; +>oct2 : number + +var obj1 = { +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } +>{ 0o45436: "Hello", a: 0o45436, b: oct1, oct1,} : { 0o45436: string; a: number; b: number; oct1: number; } + + 0o45436: "Hello", + a: 0o45436, +>a : number + + b: oct1, +>b : number +>oct1 : number + + oct1, +>oct1 : number +} + +var obj2 = { +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } +>{ 0O45436: "hi", a: 0O45436, b: oct2, oct2,} : { 0O45436: string; a: number; b: number; oct2: number; } + + 0O45436: "hi", + a: 0O45436, +>a : number + + b: oct2, +>b : number +>oct2 : number + + oct2, +>oct2 : number +} + +obj1[0o45436]; // string +>obj1[0o45436] : string +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["0o45436"]; // any +>obj1["0o45436"] : any +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["19230"]; // string +>obj1["19230"] : string +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1[19230]; // string +>obj1[19230] : string +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["a"]; // number +>obj1["a"] : number +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["b"]; // number +>obj1["b"] : number +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["oct1"]; // number +>obj1["oct1"] : number +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj2[0O45436]; // string +>obj2[0O45436] : string +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["0O45436"]; // any +>obj2["0O45436"] : any +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["19230"]; // string +>obj2["19230"] : string +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2[19230]; // string +>obj2[19230] : string +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["a"]; // number +>obj2["a"] : number +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["b"]; // number +>obj2["b"] : number +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["oct2"]; // number +>obj2["oct2"] : number +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + diff --git a/tests/baselines/reference/octalIntegerLiteralES6.js b/tests/baselines/reference/octalIntegerLiteralES6.js new file mode 100644 index 00000000000..b69cd6f457a --- /dev/null +++ b/tests/baselines/reference/octalIntegerLiteralES6.js @@ -0,0 +1,63 @@ +//// [octalIntegerLiteralES6.ts] +var oct1 = 0o45436; +var oct2 = 0O45436; +var obj1 = { + 0o45436: "Hello", + a: 0o45436, + b: oct1, + oct1, +} + +var obj2 = { + 0O45436: "hi", + a: 0O45436, + b: oct2, + oct2, +} + +obj1[0o45436]; // string +obj1["0o45436"]; // any +obj1["19230"]; // string +obj1[19230]; // string +obj1["a"]; // number +obj1["b"]; // number +obj1["oct1"]; // number + +obj2[0O45436]; // string +obj2["0O45436"]; // any +obj2["19230"]; // string +obj2[19230]; // string +obj2["a"]; // number +obj2["b"]; // number +obj2["oct2"]; // number + + +//// [octalIntegerLiteralES6.js] +var oct1 = 0o45436; +var oct2 = 0O45436; +var obj1 = { + 0o45436: "Hello", + a: 0o45436, + b: oct1, + oct1, +}; +var obj2 = { + 0O45436: "hi", + a: 0O45436, + b: oct2, + oct2, +}; +obj1[0o45436]; // string +obj1["0o45436"]; // any +obj1["19230"]; // string +obj1[19230]; // string +obj1["a"]; // number +obj1["b"]; // number +obj1["oct1"]; // number +obj2[0O45436]; // string +obj2["0O45436"]; // any +obj2["19230"]; // string +obj2[19230]; // string +obj2["a"]; // number +obj2["b"]; // number +obj2["oct2"]; // number diff --git a/tests/baselines/reference/octalIntegerLiteralES6.types b/tests/baselines/reference/octalIntegerLiteralES6.types new file mode 100644 index 00000000000..d913109b7f5 --- /dev/null +++ b/tests/baselines/reference/octalIntegerLiteralES6.types @@ -0,0 +1,95 @@ +=== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralES6.ts === +var oct1 = 0o45436; +>oct1 : number + +var oct2 = 0O45436; +>oct2 : number + +var obj1 = { +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } +>{ 0o45436: "Hello", a: 0o45436, b: oct1, oct1,} : { 0o45436: string; a: number; b: number; oct1: number; } + + 0o45436: "Hello", + a: 0o45436, +>a : number + + b: oct1, +>b : number +>oct1 : number + + oct1, +>oct1 : number +} + +var obj2 = { +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } +>{ 0O45436: "hi", a: 0O45436, b: oct2, oct2,} : { 0O45436: string; a: number; b: number; oct2: number; } + + 0O45436: "hi", + a: 0O45436, +>a : number + + b: oct2, +>b : number +>oct2 : number + + oct2, +>oct2 : number +} + +obj1[0o45436]; // string +>obj1[0o45436] : string +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["0o45436"]; // any +>obj1["0o45436"] : any +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["19230"]; // string +>obj1["19230"] : string +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1[19230]; // string +>obj1[19230] : string +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["a"]; // number +>obj1["a"] : number +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["b"]; // number +>obj1["b"] : number +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj1["oct1"]; // number +>obj1["oct1"] : number +>obj1 : { 0o45436: string; a: number; b: number; oct1: number; } + +obj2[0O45436]; // string +>obj2[0O45436] : string +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["0O45436"]; // any +>obj2["0O45436"] : any +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["19230"]; // string +>obj2["19230"] : string +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2[19230]; // string +>obj2[19230] : string +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["a"]; // number +>obj2["a"] : number +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["b"]; // number +>obj2["b"] : number +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + +obj2["oct2"]; // number +>obj2["oct2"] : number +>obj2 : { 0O45436: string; a: number; b: number; oct2: number; } + diff --git a/tests/baselines/reference/octalIntegerLiteralError.errors.txt b/tests/baselines/reference/octalIntegerLiteralError.errors.txt new file mode 100644 index 00000000000..d0e2531796a --- /dev/null +++ b/tests/baselines/reference/octalIntegerLiteralError.errors.txt @@ -0,0 +1,28 @@ +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(2,19): error TS1164: Octal digits expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(3,18): error TS1164: Octal digits expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(6,5): error TS2300: Duplicate identifier '0O45436'. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(7,5): error TS2300: Duplicate identifier '19230'. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(8,5): error TS2300: Duplicate identifier '"19230"'. + + +==== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts (5 errors) ==== + // error + var oct1 = 0O13334823; + +!!! error TS1164: Octal digits expected. + var oct2 = 0o34318592; + +!!! error TS1164: Octal digits expected. + + var obj1 = { + 0O45436: "hi", + ~~~~~~~ +!!! error TS2300: Duplicate identifier '0O45436'. + 19230: "Hello", + ~~~~~ +!!! error TS2300: Duplicate identifier '19230'. + "19230": "world", + ~~~~~~~ +!!! error TS2300: Duplicate identifier '"19230"'. + }; + \ No newline at end of file diff --git a/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteral.ts b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteral.ts new file mode 100644 index 00000000000..23b1674391e --- /dev/null +++ b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteral.ts @@ -0,0 +1,34 @@ +// @target: es5 +var bin1 = 0b11010; +var bin2 = 0B11010; + +var obj1 = { + 0b11010: "Hello", + a: bin1, + bin1, + b: 0b11010, +} + +var obj2 = { + 0B11010: "World", + a: bin2, + bin2, + b: 0B11010, +} + +obj1[0b11010]; // string +obj1[26]; // string +obj1["26"]; // string +obj1["0b11010"]; // any +obj1["a"]; // number +obj1["b"]; // number +obj1["bin1"]; // number + +obj2[0B11010]; // string +obj2[26]; // string +obj2["26"]; // string +obj2["0B11010"]; // any +obj2["a"]; // number +obj2["b"]; // number +obj2["bin2"]; // number + diff --git a/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralES6.ts b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralES6.ts new file mode 100644 index 00000000000..9f8de23c0e4 --- /dev/null +++ b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralES6.ts @@ -0,0 +1,33 @@ +// @target: es6 +var bin1 = 0b11010; +var bin2 = 0B11010; + +var obj1 = { + 0b11010: "Hello", + a: bin1, + bin1, + b: 0b11010, +} + +var obj2 = { + 0B11010: "World", + a: bin2, + bin2, + b: 0B11010, +} + +obj1[0b11010]; // string +obj1[26]; // string +obj1["26"]; // string +obj1["0b11010"]; // any +obj1["a"]; // number +obj1["b"]; // number +obj1["bin1"]; // number + +obj2[0B11010]; // string +obj2[26]; // string +obj2["26"]; // string +obj2["0B11010"]; // any +obj2["a"]; // number +obj2["b"]; // number +obj2["bin2"]; // number diff --git a/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts new file mode 100644 index 00000000000..b889aac5d9c --- /dev/null +++ b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts @@ -0,0 +1,9 @@ +// error +var bin1 = 0B1102110; +var bin1 = 0b11023410; + +var obj1 = { + 0b11010: "hi", + 26: "Hello", + "26": "world", +}; diff --git a/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteral.ts b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteral.ts new file mode 100644 index 00000000000..a68531d396a --- /dev/null +++ b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteral.ts @@ -0,0 +1,32 @@ +// @target: es5 +var oct1 = 0o45436; +var oct2 = 0O45436; +var obj1 = { + 0o45436: "Hello", + a: 0o45436, + b: oct1, + oct1, +} + +var obj2 = { + 0O45436: "hi", + a: 0O45436, + b: oct2, + oct2, +} + +obj1[0o45436]; // string +obj1["0o45436"]; // any +obj1["19230"]; // string +obj1[19230]; // string +obj1["a"]; // number +obj1["b"]; // number +obj1["oct1"]; // number + +obj2[0O45436]; // string +obj2["0O45436"]; // any +obj2["19230"]; // string +obj2[19230]; // string +obj2["a"]; // number +obj2["b"]; // number +obj2["oct2"]; // number diff --git a/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralES6.ts b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralES6.ts new file mode 100644 index 00000000000..22ca686f809 --- /dev/null +++ b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralES6.ts @@ -0,0 +1,32 @@ +// @target: es6 +var oct1 = 0o45436; +var oct2 = 0O45436; +var obj1 = { + 0o45436: "Hello", + a: 0o45436, + b: oct1, + oct1, +} + +var obj2 = { + 0O45436: "hi", + a: 0O45436, + b: oct2, + oct2, +} + +obj1[0o45436]; // string +obj1["0o45436"]; // any +obj1["19230"]; // string +obj1[19230]; // string +obj1["a"]; // number +obj1["b"]; // number +obj1["oct1"]; // number + +obj2[0O45436]; // string +obj2["0O45436"]; // any +obj2["19230"]; // string +obj2[19230]; // string +obj2["a"]; // number +obj2["b"]; // number +obj2["oct2"]; // number diff --git a/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts new file mode 100644 index 00000000000..06e7b5ddf38 --- /dev/null +++ b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts @@ -0,0 +1,9 @@ +// error +var oct1 = 0O13334823; +var oct2 = 0o34318592; + +var obj1 = { + 0O45436: "hi", + 19230: "Hello", + "19230": "world", +}; From d04a3c7c23f56d60486c4b4004febff45390a055 Mon Sep 17 00:00:00 2001 From: Yui T Date: Sun, 23 Nov 2014 18:19:10 -0800 Subject: [PATCH 3/9] Add comment --- src/compiler/emitter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 9e7b831fd2b..0bf6c1f635b 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -794,7 +794,8 @@ module ts { if (compilerOptions.sourceMap && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { writer.writeLiteral(text); } - else if (node.kind === SyntaxKind.NumericLiteral && compilerOptions.target < ScriptTarget.ES6 && + // For version below ES6, emit binary integer literal and octal integer literal as decimal value + else if (compilerOptions.target < ScriptTarget.ES6 && node.kind === SyntaxKind.NumericLiteral && ((text.charCodeAt(1) === CharacterCodes.B || text.charCodeAt(1) === CharacterCodes.b || text.charCodeAt(1) === CharacterCodes.O || text.charCodeAt(1) === CharacterCodes.o))) { write(node.text); From a5800408636e824929abf2523c7b50907e8a2434 Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 24 Nov 2014 14:36:05 -0800 Subject: [PATCH 4/9] Address code review --- .../diagnosticInformationMap.generated.ts | 4 +- src/compiler/diagnosticMessages.json | 4 +- src/compiler/emitter.ts | 16 ++++-- src/compiler/scanner.ts | 49 +++++++++---------- .../binaryIntegerLiteralError.errors.txt | 12 ++--- .../octalIntegerLiteralError.errors.txt | 12 ++--- 6 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 13587df29e0..e4094b25812 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -125,8 +125,8 @@ module ts { Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." }, Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." }, An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." }, - Binary_digits_expected: { code: 1163, category: DiagnosticCategory.Error, key: "Binary digits expected." }, - Octal_digits_expected: { code: 1164, category: DiagnosticCategory.Error, key: "Octal digits expected." }, + Binary_digit_expected: { code: 1163, category: DiagnosticCategory.Error, key: "Binary digit expected." }, + Octal_digit_expected: { code: 1164, category: DiagnosticCategory.Error, key: "Octal digit expected." }, 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." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 427eba4531d..1cca0aa130d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -491,11 +491,11 @@ "category": "Error", "code": 1162 }, - "Binary digits expected.": { + "Binary digit expected.": { "category": "Error", "code": 1163 }, - "Octal digits expected.": { + "Octal digit expected.": { "category": "Error", "code": 1164 }, diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0bf6c1f635b..4b4535616da 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -788,6 +788,18 @@ module ts { } } + function isBinaryOrOctalIntegerLiteral(text: string): boolean { + if (text.length <= 0) { + return false; + } + + if (text.charCodeAt(1) === CharacterCodes.B || text.charCodeAt(1) === CharacterCodes.b || + text.charCodeAt(1) === CharacterCodes.O || text.charCodeAt(1) === CharacterCodes.o) { + return true; + } + return false; + } + function emitLiteral(node: LiteralExpression): void { var text = getLiteralText(); @@ -795,9 +807,7 @@ module ts { writer.writeLiteral(text); } // For version below ES6, emit binary integer literal and octal integer literal as decimal value - else if (compilerOptions.target < ScriptTarget.ES6 && node.kind === SyntaxKind.NumericLiteral && - ((text.charCodeAt(1) === CharacterCodes.B || text.charCodeAt(1) === CharacterCodes.b || - text.charCodeAt(1) === CharacterCodes.O || text.charCodeAt(1) === CharacterCodes.o))) { + else if (compilerOptions.target < ScriptTarget.ES6 && node.kind === SyntaxKind.NumericLiteral && isBinaryOrOctalIntegerLiteral(text)) { write(node.text); } else { diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 596155c8137..3c75580e7e7 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -520,27 +520,6 @@ module ts { return +(text.substring(start, pos)); } - function scanBinaryOrOctalDigits(base: number): number { - if (base !== 2 && base !== 8) { - return -1; - } - var value = 0; - while (true) { - var ch = text.charCodeAt(pos); - var valueOfCh = ch - CharacterCodes._0; - if (!isDigit(ch)) { - break; - } - // We know at this point that ch must be digit - if (valueOfCh >= base) { - return -1; - } - value = value * base + valueOfCh; - pos++; - } - return value; - } - function scanHexDigits(count: number, mustMatchCount?: boolean): number { var digits = 0; var value = 0; @@ -774,6 +753,26 @@ module ts { return token = SyntaxKind.Identifier; } + function scanBinaryOrOctalDigits(base: number): number { + Debug.assert(base !== 2 || base !== 8, "Expected either base 2 or base 8"); + + var value = 0; + while (true) { + var ch = text.charCodeAt(pos); + var valueOfCh = ch - CharacterCodes._0; + if (!isDigit(ch)) { + break; + } + // We know at this point that ch must be digit + if (valueOfCh >= base) { + break; + } + value = value * base + valueOfCh; + pos++; + } + return value; + } + function scan(): SyntaxKind { startPos = pos; precedingLineBreak = false; @@ -956,9 +955,9 @@ module ts { } else if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) { pos += 2; - var value = scanBinaryOrOctalDigits(/* binary */2); + var value = scanBinaryOrOctalDigits(/* base */ 2); if (value < 0) { - error(Diagnostics.Binary_digits_expected); + error(Diagnostics.Binary_digit_expected); value = 0; } tokenValue = "" + value; @@ -966,9 +965,9 @@ module ts { } else if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) { pos += 2; - var value = scanBinaryOrOctalDigits(/* octal */8); + var value = scanBinaryOrOctalDigits(/* base */ 8); if (value < 0) { - error(Diagnostics.Octal_digits_expected); + error(Diagnostics.Octal_digit_expected); value = 0; } tokenValue = "" + value; diff --git a/tests/baselines/reference/binaryIntegerLiteralError.errors.txt b/tests/baselines/reference/binaryIntegerLiteralError.errors.txt index 3346ee33774..20358a8406d 100644 --- a/tests/baselines/reference/binaryIntegerLiteralError.errors.txt +++ b/tests/baselines/reference/binaryIntegerLiteralError.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(2,17): error TS1163: Binary digits expected. -tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(3,17): error TS1163: Binary digits expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(2,17): error TS1005: ',' expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(3,17): error TS1005: ',' expected. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(6,5): error TS2300: Duplicate identifier '0b11010'. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(7,5): error TS2300: Duplicate identifier '26'. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(8,5): error TS2300: Duplicate identifier '"26"'. @@ -8,11 +8,11 @@ tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralErr ==== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts (5 errors) ==== // error var bin1 = 0B1102110; - -!!! error TS1163: Binary digits expected. + ~~~~ +!!! error TS1005: ',' expected. var bin1 = 0b11023410; - -!!! error TS1163: Binary digits expected. + ~~~~~ +!!! error TS1005: ',' expected. var obj1 = { 0b11010: "hi", diff --git a/tests/baselines/reference/octalIntegerLiteralError.errors.txt b/tests/baselines/reference/octalIntegerLiteralError.errors.txt index d0e2531796a..f1386f75b87 100644 --- a/tests/baselines/reference/octalIntegerLiteralError.errors.txt +++ b/tests/baselines/reference/octalIntegerLiteralError.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(2,19): error TS1164: Octal digits expected. -tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(3,18): error TS1164: Octal digits expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(2,19): error TS1005: ',' expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(3,18): error TS1005: ',' expected. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(6,5): error TS2300: Duplicate identifier '0O45436'. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(7,5): error TS2300: Duplicate identifier '19230'. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(8,5): error TS2300: Duplicate identifier '"19230"'. @@ -8,11 +8,11 @@ tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralErro ==== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts (5 errors) ==== // error var oct1 = 0O13334823; - -!!! error TS1164: Octal digits expected. + ~~~ +!!! error TS1005: ',' expected. var oct2 = 0o34318592; - -!!! error TS1164: Octal digits expected. + ~~~~ +!!! error TS1005: ',' expected. var obj1 = { 0O45436: "hi", From 30d58dd2207e384cdf40826f65bedab4e7e33bb8 Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 24 Nov 2014 14:36:05 -0800 Subject: [PATCH 5/9] Address code review --- .../diagnosticInformationMap.generated.ts | 4 +- src/compiler/diagnosticMessages.json | 4 +- src/compiler/emitter.ts | 16 ++++-- src/compiler/scanner.ts | 49 +++++++++---------- .../binaryIntegerLiteralError.errors.txt | 12 ++--- .../octalIntegerLiteralError.errors.txt | 12 ++--- 6 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 13587df29e0..e4094b25812 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -125,8 +125,8 @@ module ts { Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." }, Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." }, An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." }, - Binary_digits_expected: { code: 1163, category: DiagnosticCategory.Error, key: "Binary digits expected." }, - Octal_digits_expected: { code: 1164, category: DiagnosticCategory.Error, key: "Octal digits expected." }, + Binary_digit_expected: { code: 1163, category: DiagnosticCategory.Error, key: "Binary digit expected." }, + Octal_digit_expected: { code: 1164, category: DiagnosticCategory.Error, key: "Octal digit expected." }, 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." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 427eba4531d..1cca0aa130d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -491,11 +491,11 @@ "category": "Error", "code": 1162 }, - "Binary digits expected.": { + "Binary digit expected.": { "category": "Error", "code": 1163 }, - "Octal digits expected.": { + "Octal digit expected.": { "category": "Error", "code": 1164 }, diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 0bf6c1f635b..4b4535616da 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -788,6 +788,18 @@ module ts { } } + function isBinaryOrOctalIntegerLiteral(text: string): boolean { + if (text.length <= 0) { + return false; + } + + if (text.charCodeAt(1) === CharacterCodes.B || text.charCodeAt(1) === CharacterCodes.b || + text.charCodeAt(1) === CharacterCodes.O || text.charCodeAt(1) === CharacterCodes.o) { + return true; + } + return false; + } + function emitLiteral(node: LiteralExpression): void { var text = getLiteralText(); @@ -795,9 +807,7 @@ module ts { writer.writeLiteral(text); } // For version below ES6, emit binary integer literal and octal integer literal as decimal value - else if (compilerOptions.target < ScriptTarget.ES6 && node.kind === SyntaxKind.NumericLiteral && - ((text.charCodeAt(1) === CharacterCodes.B || text.charCodeAt(1) === CharacterCodes.b || - text.charCodeAt(1) === CharacterCodes.O || text.charCodeAt(1) === CharacterCodes.o))) { + else if (compilerOptions.target < ScriptTarget.ES6 && node.kind === SyntaxKind.NumericLiteral && isBinaryOrOctalIntegerLiteral(text)) { write(node.text); } else { diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 596155c8137..3c75580e7e7 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -520,27 +520,6 @@ module ts { return +(text.substring(start, pos)); } - function scanBinaryOrOctalDigits(base: number): number { - if (base !== 2 && base !== 8) { - return -1; - } - var value = 0; - while (true) { - var ch = text.charCodeAt(pos); - var valueOfCh = ch - CharacterCodes._0; - if (!isDigit(ch)) { - break; - } - // We know at this point that ch must be digit - if (valueOfCh >= base) { - return -1; - } - value = value * base + valueOfCh; - pos++; - } - return value; - } - function scanHexDigits(count: number, mustMatchCount?: boolean): number { var digits = 0; var value = 0; @@ -774,6 +753,26 @@ module ts { return token = SyntaxKind.Identifier; } + function scanBinaryOrOctalDigits(base: number): number { + Debug.assert(base !== 2 || base !== 8, "Expected either base 2 or base 8"); + + var value = 0; + while (true) { + var ch = text.charCodeAt(pos); + var valueOfCh = ch - CharacterCodes._0; + if (!isDigit(ch)) { + break; + } + // We know at this point that ch must be digit + if (valueOfCh >= base) { + break; + } + value = value * base + valueOfCh; + pos++; + } + return value; + } + function scan(): SyntaxKind { startPos = pos; precedingLineBreak = false; @@ -956,9 +955,9 @@ module ts { } else if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) { pos += 2; - var value = scanBinaryOrOctalDigits(/* binary */2); + var value = scanBinaryOrOctalDigits(/* base */ 2); if (value < 0) { - error(Diagnostics.Binary_digits_expected); + error(Diagnostics.Binary_digit_expected); value = 0; } tokenValue = "" + value; @@ -966,9 +965,9 @@ module ts { } else if (pos + 2 < len && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) { pos += 2; - var value = scanBinaryOrOctalDigits(/* octal */8); + var value = scanBinaryOrOctalDigits(/* base */ 8); if (value < 0) { - error(Diagnostics.Octal_digits_expected); + error(Diagnostics.Octal_digit_expected); value = 0; } tokenValue = "" + value; diff --git a/tests/baselines/reference/binaryIntegerLiteralError.errors.txt b/tests/baselines/reference/binaryIntegerLiteralError.errors.txt index 3346ee33774..20358a8406d 100644 --- a/tests/baselines/reference/binaryIntegerLiteralError.errors.txt +++ b/tests/baselines/reference/binaryIntegerLiteralError.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(2,17): error TS1163: Binary digits expected. -tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(3,17): error TS1163: Binary digits expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(2,17): error TS1005: ',' expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(3,17): error TS1005: ',' expected. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(6,5): error TS2300: Duplicate identifier '0b11010'. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(7,5): error TS2300: Duplicate identifier '26'. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts(8,5): error TS2300: Duplicate identifier '"26"'. @@ -8,11 +8,11 @@ tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralErr ==== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/binaryIntegerLiteralError.ts (5 errors) ==== // error var bin1 = 0B1102110; - -!!! error TS1163: Binary digits expected. + ~~~~ +!!! error TS1005: ',' expected. var bin1 = 0b11023410; - -!!! error TS1163: Binary digits expected. + ~~~~~ +!!! error TS1005: ',' expected. var obj1 = { 0b11010: "hi", diff --git a/tests/baselines/reference/octalIntegerLiteralError.errors.txt b/tests/baselines/reference/octalIntegerLiteralError.errors.txt index d0e2531796a..f1386f75b87 100644 --- a/tests/baselines/reference/octalIntegerLiteralError.errors.txt +++ b/tests/baselines/reference/octalIntegerLiteralError.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(2,19): error TS1164: Octal digits expected. -tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(3,18): error TS1164: Octal digits expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(2,19): error TS1005: ',' expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(3,18): error TS1005: ',' expected. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(6,5): error TS2300: Duplicate identifier '0O45436'. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(7,5): error TS2300: Duplicate identifier '19230'. tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts(8,5): error TS2300: Duplicate identifier '"19230"'. @@ -8,11 +8,11 @@ tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralErro ==== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/octalIntegerLiteralError.ts (5 errors) ==== // error var oct1 = 0O13334823; - -!!! error TS1164: Octal digits expected. + ~~~ +!!! error TS1005: ',' expected. var oct2 = 0o34318592; - -!!! error TS1164: Octal digits expected. + ~~~~ +!!! error TS1005: ',' expected. var obj1 = { 0O45436: "hi", From 123b2ebda7207a977a148238e073f240ef515cff Mon Sep 17 00:00:00 2001 From: Yui T Date: Tue, 25 Nov 2014 10:19:29 -0800 Subject: [PATCH 6/9] address code review --- src/compiler/scanner.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 3c75580e7e7..b55fd53e0cc 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -760,11 +760,7 @@ module ts { while (true) { var ch = text.charCodeAt(pos); var valueOfCh = ch - CharacterCodes._0; - if (!isDigit(ch)) { - break; - } - // We know at this point that ch must be digit - if (valueOfCh >= base) { + if (!isDigit(ch) || valueOfCh >= base) { break; } value = value * base + valueOfCh; From 77b8f461a3dd55ea9241f01d46a5808c7aa2c39a Mon Sep 17 00:00:00 2001 From: Yui T Date: Sat, 29 Nov 2014 16:46:01 -0800 Subject: [PATCH 7/9] Add check and testcases for invalid binary digits and octal digits --- src/compiler/scanner.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index b55fd53e0cc..45723de983d 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -757,6 +757,9 @@ module ts { Debug.assert(base !== 2 || base !== 8, "Expected either base 2 or base 8"); var value = 0; + // For counting number of digits; Valid binaryIntegerLiteral must have at least one binary digit following B or b. + // Similarly valid octalIntegerLiteral must have at least one octal digit following o or O. + var numberOfDigits = 0; while (true) { var ch = text.charCodeAt(pos); var valueOfCh = ch - CharacterCodes._0; @@ -765,6 +768,11 @@ module ts { } value = value * base + valueOfCh; pos++; + numberOfDigits++; + } + // Invalid binaryIntegerLiteral or octalIntegerLiteral + if (numberOfDigits === 0) { + return -1; } return value; } From db51fbd65c13ed000f0a0a09c9300a9799ebcdfa Mon Sep 17 00:00:00 2001 From: Yui T Date: Sat, 29 Nov 2014 16:46:01 -0800 Subject: [PATCH 8/9] Add check and testcases for invalid binary digits and octal digits --- src/compiler/scanner.ts | 8 ++++++++ .../invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts | 5 +++++ 2 files changed, 13 insertions(+) create mode 100644 tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index b55fd53e0cc..45723de983d 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -757,6 +757,9 @@ module ts { Debug.assert(base !== 2 || base !== 8, "Expected either base 2 or base 8"); var value = 0; + // For counting number of digits; Valid binaryIntegerLiteral must have at least one binary digit following B or b. + // Similarly valid octalIntegerLiteral must have at least one octal digit following o or O. + var numberOfDigits = 0; while (true) { var ch = text.charCodeAt(pos); var valueOfCh = ch - CharacterCodes._0; @@ -765,6 +768,11 @@ module ts { } value = value * base + valueOfCh; pos++; + numberOfDigits++; + } + // Invalid binaryIntegerLiteral or octalIntegerLiteral + if (numberOfDigits === 0) { + return -1; } return value; } diff --git a/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts new file mode 100644 index 00000000000..850b71c6702 --- /dev/null +++ b/tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts @@ -0,0 +1,5 @@ +// Error +var binary = 0b21010; +var binary1 = 0B21010; +var octal = 0o81010; +var octal = 0O91010; \ No newline at end of file From 847eb097cb131ffb28ba3cabf9198cdf68f6f7b7 Mon Sep 17 00:00:00 2001 From: Yui T Date: Mon, 1 Dec 2014 10:52:49 -0800 Subject: [PATCH 9/9] Add baseline --- ...erLiteralAndOctalIntegerLiteral.errors.txt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tests/baselines/reference/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.errors.txt diff --git a/tests/baselines/reference/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.errors.txt b/tests/baselines/reference/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.errors.txt new file mode 100644 index 00000000000..1ff2501e278 --- /dev/null +++ b/tests/baselines/reference/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.errors.txt @@ -0,0 +1,20 @@ +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts(2,16): error TS1163: Binary digit expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts(3,17): error TS1163: Binary digit expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts(4,15): error TS1164: Octal digit expected. +tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts(5,15): error TS1164: Octal digit expected. + + +==== tests/cases/conformance/es6/binaryAndOctalIntegerLiteral/invalidBinaryIntegerLiteralAndOctalIntegerLiteral.ts (4 errors) ==== + // Error + var binary = 0b21010; + +!!! error TS1163: Binary digit expected. + var binary1 = 0B21010; + +!!! error TS1163: Binary digit expected. + var octal = 0o81010; + +!!! error TS1164: Octal digit expected. + var octal = 0O91010; + +!!! error TS1164: Octal digit expected. \ No newline at end of file