Skip to content

Commit

Permalink
[[FIX]] Improve numeric literal warnings/errors
Browse files Browse the repository at this point in the history
Previously, JSHint issued the warning W045 in response to invalid
numeric literals and numeric literals which could not be represented
with the JavaScript "number" type. (The existing code comment which
claims otherwise is erroneous.) While the warning's message was generic
enough to describe both cases ("Bad number"), the dual usage undermined
JSHint's distinction between "errors" and "warnings."

Create a new error to describe the invalid syntax and emit it as
appropriate. Reword the existing warning to more precisely describe the
likely programming error it reflects.
  • Loading branch information
jugglinmike authored and rwaldron committed Jun 16, 2020
1 parent cd3fda0 commit 370e159
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 20 deletions.
16 changes: 11 additions & 5 deletions src/lex.js
Expand Up @@ -966,11 +966,19 @@ Lexer.prototype = {
}
}

// TODO: Extend this check to other numeric literals
this.triggerAsync("warning", {
code: "W045",
line: this.line,
character: this.char + value.length,
data: [ value ]
}, checks, function() { return !isFinite(value); });

return {
type: Token.NumericLiteral,
value: value,
base: base,
isMalformed: !isFinite(value)
isMalformed: false
};
},

Expand Down Expand Up @@ -2143,10 +2151,8 @@ Lexer.prototype = {

case Token.NumericLiteral:
if (token.isMalformed) {
// This condition unequivocally describes a syntax error.
// TODO: Re-factor as an "error" (not a "warning").
this.trigger("warning", {
code: "W045",
this.trigger("error", {
code: "E067",
line: this.line,
character: this.char,
data: [ token.value ]
Expand Down
6 changes: 4 additions & 2 deletions src/messages.js
Expand Up @@ -82,7 +82,8 @@ var errors = {
E064: "Super call may only be used within class method bodies.",
E065: "Functions defined outside of strict mode with non-simple parameter lists may not " +
"enable strict mode.",
E066: "Asynchronous iteration is only available with for-of loops."
E066: "Asynchronous iteration is only available with for-of loops.",
E067: "Malformed numeric literal: '{a}'."
};

var warnings = {
Expand Down Expand Up @@ -131,7 +132,8 @@ var warnings = {
W042: "Avoid EOL escaping.",
W043: "Bad escaping of EOL. Use option multistr if needed.",
W044: "Bad or unnecessary escaping.", /* TODO(caitp): remove W044 */
W045: "Bad number '{a}'.",
W045: "Value described by numeric literal cannot be accurately " +
"represented with a number value: '{a}'.",
W046: "Don't use extra leading zeros '{a}'.",
W047: "A trailing decimal point can be confused with a dot: '{a}'.",
W048: "Unexpected control character in regular expression.",
Expand Down
8 changes: 0 additions & 8 deletions tests/test262/expectations.txt
Expand Up @@ -150,15 +150,7 @@ test/language/rest-parameters/object-pattern.js(strict mode)
test/language/arguments-object/10.6-13-c-1-s.js(strict mode)
test/language/arguments-object/10.6-1gs.js(strict mode)
test/language/arguments-object/10.6-2gs.js(strict mode)
test/language/literals/numeric/S7.8.3_A6.1_T1.js(default)
test/language/literals/numeric/S7.8.3_A6.1_T1.js(strict mode)
test/language/literals/numeric/S7.8.3_A6.1_T2.js(default)
test/language/literals/numeric/S7.8.3_A6.1_T2.js(strict mode)
test/language/literals/numeric/binary-invalid-truncated.js(default)
test/language/literals/numeric/binary-invalid-truncated.js(strict mode)
test/language/literals/numeric/non-octal-decimal-integer-strict.js(strict mode)
test/language/literals/numeric/octal-invalid-truncated.js(default)
test/language/literals/numeric/octal-invalid-truncated.js(strict mode)
test/language/block-scope/syntax/function-declarations/in-statement-position-if-expression-statement-else-statement.js(strict mode)
test/language/block-scope/syntax/function-declarations/in-statement-position-if-expression-statement.js(strict mode)
test/language/destructuring/binding/syntax/array-elements-with-initializer.js(default)
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/parser.js
Expand Up @@ -537,7 +537,7 @@ exports.numbers = function (test) {
];

TestRun(test)
.addError(2, 15, "Bad number '10e308'.")
.addError(2, 15, "Value described by numeric literal cannot be accurately represented with a number value: '10e308'.")
.addError(5, 11, "A leading decimal point can be confused with a dot: '.3'.")
.addError(6, 9, "Unexpected '0'.")
.addError(7, 1, "Expected an identifier and instead saw 'var'.")
Expand All @@ -547,7 +547,7 @@ exports.numbers = function (test) {
.addError(9, 9, "A dot following a number can be confused with a decimal point.")
.addError(11, 9, "'Octal integer literal' is only available in ES6 (use 'esversion: 6').")
.addError(12, 9, "'Binary integer literal' is only available in ES6 (use 'esversion: 6').")
.addError(13, 11, "Bad number '0x'.")
.addError(13, 11, "Malformed numeric literal: '0x'.")
.addError(15, 9, "Unexpected '1'.")
.addError(16, 11, "Expected an identifier and instead saw ';'.")
.addError(16, 1, "Expected an identifier and instead saw 'var'.")
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/unstable/bigint.js
Expand Up @@ -75,19 +75,19 @@ exports.invalid = function (test) {
.test("void 1e3n;", {esversion: 6, unstable: {bigint: true}});

TestRun(test, "invalid hex digit")
.addError(1, 8, "Bad number '0x'.")
.addError(1, 8, "Malformed numeric literal: '0x'.")
.addError(1, 8, "Missing semicolon.")
.addError(1, 8, "Expected an assignment or function call and instead saw an expression.")
.test("void 0xgn;", {esversion: 6, unstable: {bigint: true}});

TestRun(test, "invalid binary digit")
.addError(1, 8, "Bad number '0b'.")
.addError(1, 8, "Malformed numeric literal: '0b'.")
.addError(1, 8, "Missing semicolon.")
.addError(1, 8, "Expected an assignment or function call and instead saw an expression.")
.test("void 0b2n;", {esversion: 6, unstable: {bigint: true}});

TestRun(test, "invalid octal digit")
.addError(1, 8, "Bad number '0o'.")
.addError(1, 8, "Malformed numeric literal: '0o'.")
.addError(1, 8, "Missing semicolon.")
.addError(1, 8, "Expected an assignment or function call and instead saw an expression.")
.test("void 0o8n;", {esversion: 6, unstable: {bigint: true}});
Expand Down

0 comments on commit 370e159

Please sign in to comment.