From 20249e5c4a66e5abef595c52e87be5b1eabff468 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 24 Jan 2017 13:42:05 -0800 Subject: [PATCH] More exhaustive needsDotDotForPropertyAccess --- src/compiler/emitter.ts | 6 ++- src/compiler/utilities.ts | 42 +++++++++++++++++-- .../propertyAccessNumericLiterals.es6.js | 14 +++++++ .../propertyAccessNumericLiterals.es6.symbols | 21 ++++++++++ .../propertyAccessNumericLiterals.es6.types | 31 ++++++++++++++ .../propertyAccessNumericLiterals.js | 15 +++++++ .../propertyAccessNumericLiterals.symbols | 25 +++++++++++ .../propertyAccessNumericLiterals.types | 37 ++++++++++++++++ .../propertyAccessNumericLiterals.es6.ts | 6 +++ .../propertyAccessNumericLiterals.ts | 7 ++++ 10 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/propertyAccessNumericLiterals.es6.js create mode 100644 tests/baselines/reference/propertyAccessNumericLiterals.es6.symbols create mode 100644 tests/baselines/reference/propertyAccessNumericLiterals.es6.types create mode 100644 tests/baselines/reference/propertyAccessNumericLiterals.js create mode 100644 tests/baselines/reference/propertyAccessNumericLiterals.symbols create mode 100644 tests/baselines/reference/propertyAccessNumericLiterals.types create mode 100644 tests/cases/conformance/es6/propertyAccess/propertyAccessNumericLiterals.es6.ts create mode 100644 tests/cases/conformance/expressions/propertyAccess/propertyAccessNumericLiterals.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index cc006a06637..27285a4c2dc 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1054,9 +1054,11 @@ namespace ts { // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal function needsDotDotForPropertyAccess(expression: Expression) { if (expression.kind === SyntaxKind.NumericLiteral) { - // check if numeric literal was originally written with a dot + // check if numeric literal is a decimal literal that was originally written with a dot const text = getLiteralTextOfNode(expression); - return text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0; + return getNumericLiteralFlags(text, /*hint*/ NumericLiteralFlags.All) === NumericLiteralFlags.None + && !(expression).isOctalLiteral + && text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0; } else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) { // check if constant enum value is integer diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b7cc0f0de6d..b1d2ba0854c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -341,16 +341,52 @@ namespace ts { } export function isBinaryOrOctalIntegerLiteral(node: LiteralLikeNode, text: string) { - if (node.kind === SyntaxKind.NumericLiteral && text.length > 1) { + return node.kind === SyntaxKind.NumericLiteral + && (getNumericLiteralFlags(text, /*hint*/ NumericLiteralFlags.BinaryOrOctal) & NumericLiteralFlags.BinaryOrOctal) !== 0; + } + + export const enum NumericLiteralFlags { + None = 0, + Hexadecimal = 1 << 0, + Binary = 1 << 1, + Octal = 1 << 2, + Scientific = 1 << 3, + + BinaryOrOctal = Binary | Octal, + BinaryOrOctalOrHexadecimal = BinaryOrOctal | Hexadecimal, + All = Hexadecimal | Binary | Octal | Scientific, + } + + /** + * Scans a numeric literal string to determine the form of the number. + * @param text Numeric literal text + * @param hint If `Scientific` or `All` is specified, performs a more expensive check to scan for scientific notation. + */ + export function getNumericLiteralFlags(text: string, hint?: NumericLiteralFlags) { + if (text.length > 1) { switch (text.charCodeAt(1)) { case CharacterCodes.b: case CharacterCodes.B: + return NumericLiteralFlags.Binary; case CharacterCodes.o: case CharacterCodes.O: - return true; + return NumericLiteralFlags.Octal; + case CharacterCodes.x: + case CharacterCodes.X: + return NumericLiteralFlags.Hexadecimal; + } + + if (hint & NumericLiteralFlags.Scientific) { + for (let i = text.length - 1; i >= 0; i--) { + switch (text.charCodeAt(i)) { + case CharacterCodes.e: + case CharacterCodes.E: + return NumericLiteralFlags.Scientific; + } + } } } - return false; + return NumericLiteralFlags.None; } function getQuotedEscapedLiteralText(leftQuote: string, text: string, rightQuote: string) { diff --git a/tests/baselines/reference/propertyAccessNumericLiterals.es6.js b/tests/baselines/reference/propertyAccessNumericLiterals.es6.js new file mode 100644 index 00000000000..66ac4178155 --- /dev/null +++ b/tests/baselines/reference/propertyAccessNumericLiterals.es6.js @@ -0,0 +1,14 @@ +//// [propertyAccessNumericLiterals.es6.ts] +0xffffffff.toString(); +0o01234.toString(); +0b01101101.toString(); +1234..toString(); +1e0.toString(); + + +//// [propertyAccessNumericLiterals.es6.js] +0xffffffff.toString(); +0o01234.toString(); +0b01101101.toString(); +1234..toString(); +1e0.toString(); diff --git a/tests/baselines/reference/propertyAccessNumericLiterals.es6.symbols b/tests/baselines/reference/propertyAccessNumericLiterals.es6.symbols new file mode 100644 index 00000000000..dc0be21d84f --- /dev/null +++ b/tests/baselines/reference/propertyAccessNumericLiterals.es6.symbols @@ -0,0 +1,21 @@ +=== tests/cases/conformance/es6/propertyAccess/propertyAccessNumericLiterals.es6.ts === +0xffffffff.toString(); +>0xffffffff.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + +0o01234.toString(); +>0o01234.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + +0b01101101.toString(); +>0b01101101.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + +1234..toString(); +>1234..toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + +1e0.toString(); +>1e0.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/propertyAccessNumericLiterals.es6.types b/tests/baselines/reference/propertyAccessNumericLiterals.es6.types new file mode 100644 index 00000000000..9d32cc5b6e8 --- /dev/null +++ b/tests/baselines/reference/propertyAccessNumericLiterals.es6.types @@ -0,0 +1,31 @@ +=== tests/cases/conformance/es6/propertyAccess/propertyAccessNumericLiterals.es6.ts === +0xffffffff.toString(); +>0xffffffff.toString() : string +>0xffffffff.toString : (radix?: number) => string +>0xffffffff : 4294967295 +>toString : (radix?: number) => string + +0o01234.toString(); +>0o01234.toString() : string +>0o01234.toString : (radix?: number) => string +>0o01234 : 668 +>toString : (radix?: number) => string + +0b01101101.toString(); +>0b01101101.toString() : string +>0b01101101.toString : (radix?: number) => string +>0b01101101 : 109 +>toString : (radix?: number) => string + +1234..toString(); +>1234..toString() : string +>1234..toString : (radix?: number) => string +>1234. : 1234 +>toString : (radix?: number) => string + +1e0.toString(); +>1e0.toString() : string +>1e0.toString : (radix?: number) => string +>1e0 : 1 +>toString : (radix?: number) => string + diff --git a/tests/baselines/reference/propertyAccessNumericLiterals.js b/tests/baselines/reference/propertyAccessNumericLiterals.js new file mode 100644 index 00000000000..1a7eb6c0a21 --- /dev/null +++ b/tests/baselines/reference/propertyAccessNumericLiterals.js @@ -0,0 +1,15 @@ +//// [propertyAccessNumericLiterals.ts] +0xffffffff.toString(); +0o01234.toString(); +0b01101101.toString(); +1234..toString(); +1e0.toString(); +000.toString(); + +//// [propertyAccessNumericLiterals.js] +0xffffffff.toString(); +668..toString(); +109..toString(); +1234..toString(); +1e0.toString(); +000.toString(); diff --git a/tests/baselines/reference/propertyAccessNumericLiterals.symbols b/tests/baselines/reference/propertyAccessNumericLiterals.symbols new file mode 100644 index 00000000000..5be13615e90 --- /dev/null +++ b/tests/baselines/reference/propertyAccessNumericLiterals.symbols @@ -0,0 +1,25 @@ +=== tests/cases/conformance/expressions/propertyAccess/propertyAccessNumericLiterals.ts === +0xffffffff.toString(); +>0xffffffff.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) + +0o01234.toString(); +>0o01234.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) + +0b01101101.toString(); +>0b01101101.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) + +1234..toString(); +>1234..toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) + +1e0.toString(); +>1e0.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) + +000.toString(); +>000.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) +>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --)) + diff --git a/tests/baselines/reference/propertyAccessNumericLiterals.types b/tests/baselines/reference/propertyAccessNumericLiterals.types new file mode 100644 index 00000000000..a2567ff2537 --- /dev/null +++ b/tests/baselines/reference/propertyAccessNumericLiterals.types @@ -0,0 +1,37 @@ +=== tests/cases/conformance/expressions/propertyAccess/propertyAccessNumericLiterals.ts === +0xffffffff.toString(); +>0xffffffff.toString() : string +>0xffffffff.toString : (radix?: number) => string +>0xffffffff : 4294967295 +>toString : (radix?: number) => string + +0o01234.toString(); +>0o01234.toString() : string +>0o01234.toString : (radix?: number) => string +>0o01234 : 668 +>toString : (radix?: number) => string + +0b01101101.toString(); +>0b01101101.toString() : string +>0b01101101.toString : (radix?: number) => string +>0b01101101 : 109 +>toString : (radix?: number) => string + +1234..toString(); +>1234..toString() : string +>1234..toString : (radix?: number) => string +>1234. : 1234 +>toString : (radix?: number) => string + +1e0.toString(); +>1e0.toString() : string +>1e0.toString : (radix?: number) => string +>1e0 : 1 +>toString : (radix?: number) => string + +000.toString(); +>000.toString() : string +>000.toString : (radix?: number) => string +>000 : 0 +>toString : (radix?: number) => string + diff --git a/tests/cases/conformance/es6/propertyAccess/propertyAccessNumericLiterals.es6.ts b/tests/cases/conformance/es6/propertyAccess/propertyAccessNumericLiterals.es6.ts new file mode 100644 index 00000000000..81e39965a6a --- /dev/null +++ b/tests/cases/conformance/es6/propertyAccess/propertyAccessNumericLiterals.es6.ts @@ -0,0 +1,6 @@ +// @target: es6 +0xffffffff.toString(); +0o01234.toString(); +0b01101101.toString(); +1234..toString(); +1e0.toString(); diff --git a/tests/cases/conformance/expressions/propertyAccess/propertyAccessNumericLiterals.ts b/tests/cases/conformance/expressions/propertyAccess/propertyAccessNumericLiterals.ts new file mode 100644 index 00000000000..318b05fc0b5 --- /dev/null +++ b/tests/cases/conformance/expressions/propertyAccess/propertyAccessNumericLiterals.ts @@ -0,0 +1,7 @@ +// @target: es3 +0xffffffff.toString(); +0o01234.toString(); +0b01101101.toString(); +1234..toString(); +1e0.toString(); +000.toString(); \ No newline at end of file