Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking: some rules recognize bigint literals (fixes #11803) #12701

Merged
merged 14 commits into from Jan 17, 2020
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .eslintrc.js
Expand Up @@ -19,6 +19,9 @@ module.exports = {
"eslint",
"plugin:eslint-plugin/recommended"
],
parserOptions: {
ecmaVersion: 2020
},
rules: {
"eslint-plugin/consistent-output": "error",
"eslint-plugin/no-deprecated-context-methods": "error",
Expand Down
10 changes: 3 additions & 7 deletions .github/workflows/ci.yml
Expand Up @@ -26,20 +26,16 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
node: [13.x, 12.x, 10.x, 8.x, "8.10.0"]
node: [13.x, 12.x, 10.x, "10.12.0"]
exclude:
- os: windows-latest
node: "8.10.0"
- os: windows-latest
node: 8.x
node: "10.12.0"
- os: windows-latest
node: 10.x
- os: windows-latest
node: 13.x
- os: macOS-latest
node: "8.10.0"
- os: macOS-latest
node: 8.x
node: "10.12.0"
- os: macOS-latest
node: 10.x
- os: macOS-latest
Expand Down
11 changes: 11 additions & 0 deletions conf/json-schema/README.md
@@ -0,0 +1,11 @@
# the JSON Schema of JSON Schema

This is downloaded from https://json-schema.org/draft-04/schema and modifies a line in order to support `bigint` type.

```diff
@@ -18,3 +18,3 @@
"simpleTypes": {
- "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
+ "enum": [ "array", "boolean", "integer", "null", "number", "object", "string", "bigint" ]
mysticatea marked this conversation as resolved.
Show resolved Hide resolved
}
```
149 changes: 149 additions & 0 deletions conf/json-schema/json-schema.json
@@ -0,0 +1,149 @@
{
"id": "http://json-schema.org/draft-04/schema#",
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Core schema meta-schema",
"definitions": {
"schemaArray": {
"type": "array",
"minItems": 1,
"items": { "$ref": "#" }
},
"positiveInteger": {
"type": "integer",
"minimum": 0
},
"positiveIntegerDefault0": {
"allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ]
},
"simpleTypes": {
"enum": [ "array", "boolean", "integer", "null", "number", "object", "string", "bigint" ]
},
"stringArray": {
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"uniqueItems": true
}
},
"type": "object",
"properties": {
"id": {
"type": "string"
},
"$schema": {
"type": "string"
},
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"default": {},
"multipleOf": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
},
"maximum": {
"type": "number"
},
"exclusiveMaximum": {
"type": "boolean",
"default": false
},
"minimum": {
"type": "number"
},
"exclusiveMinimum": {
"type": "boolean",
"default": false
},
"maxLength": { "$ref": "#/definitions/positiveInteger" },
"minLength": { "$ref": "#/definitions/positiveIntegerDefault0" },
"pattern": {
"type": "string",
"format": "regex"
},
"additionalItems": {
"anyOf": [
{ "type": "boolean" },
{ "$ref": "#" }
],
"default": {}
},
"items": {
"anyOf": [
{ "$ref": "#" },
{ "$ref": "#/definitions/schemaArray" }
],
"default": {}
},
"maxItems": { "$ref": "#/definitions/positiveInteger" },
"minItems": { "$ref": "#/definitions/positiveIntegerDefault0" },
"uniqueItems": {
"type": "boolean",
"default": false
},
"maxProperties": { "$ref": "#/definitions/positiveInteger" },
"minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" },
"required": { "$ref": "#/definitions/stringArray" },
"additionalProperties": {
"anyOf": [
{ "type": "boolean" },
{ "$ref": "#" }
],
"default": {}
},
"definitions": {
"type": "object",
"additionalProperties": { "$ref": "#" },
"default": {}
},
"properties": {
"type": "object",
"additionalProperties": { "$ref": "#" },
"default": {}
},
"patternProperties": {
"type": "object",
"additionalProperties": { "$ref": "#" },
"default": {}
},
"dependencies": {
"type": "object",
"additionalProperties": {
"anyOf": [
{ "$ref": "#" },
{ "$ref": "#/definitions/stringArray" }
]
}
},
"enum": {
"type": "array",
"minItems": 1,
"uniqueItems": true
},
"type": {
"anyOf": [
{ "$ref": "#/definitions/simpleTypes" },
{
"type": "array",
"items": { "$ref": "#/definitions/simpleTypes" },
"minItems": 1,
"uniqueItems": true
}
]
},
"format": { "type": "string" },
"allOf": { "$ref": "#/definitions/schemaArray" },
"anyOf": { "$ref": "#/definitions/schemaArray" },
"oneOf": { "$ref": "#/definitions/schemaArray" },
"not": { "$ref": "#" }
},
"dependencies": {
"exclusiveMaximum": [ "maximum" ],
"exclusiveMinimum": [ "minimum" ]
},
"default": {}
}
3 changes: 1 addition & 2 deletions lib/rules/key-spacing.js
Expand Up @@ -414,8 +414,7 @@ module.exports = {
if (property.computed) {
return sourceCode.getText().slice(key.range[0], key.range[1]);
}

return property.key.name || property.key.value;
return astUtils.getStaticPropertyName(property);
}

/**
Expand Down
10 changes: 3 additions & 7 deletions lib/rules/new-cap.js
Expand Up @@ -9,6 +9,8 @@
// Requirements
//------------------------------------------------------------------------------

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -160,13 +162,7 @@ module.exports = {
let name = "";

if (node.callee.type === "MemberExpression") {
const property = node.callee.property;

if (property.type === "Literal" && (typeof property.value === "string")) {
name = property.value;
} else if (property.type === "Identifier" && !node.callee.computed) {
name = property.name;
}
name = astUtils.getStaticPropertyName(node.callee) || "";
} else {
name = node.callee.name;
}
Expand Down
19 changes: 3 additions & 16 deletions lib/rules/no-dupe-class-members.js
Expand Up @@ -5,6 +5,8 @@

"use strict";

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -53,21 +55,6 @@ module.exports = {
return stateMap[key][isStatic ? "static" : "nonStatic"];
}

/**
* Gets the name text of a given node.
* @param {ASTNode} node A node to get the name.
* @returns {string} The name text of the node.
*/
function getName(node) {
switch (node.type) {
case "Identifier": return node.name;
case "Literal": return String(node.value);

/* istanbul ignore next: syntax error */
default: return "";
}
}

return {

// Initializes the stack of state of member declarations.
Expand All @@ -91,7 +78,7 @@ module.exports = {
return;
}

const name = getName(node.key);
const name = astUtils.getStaticPropertyName(node) || "";
const state = getState(name, node.static);
let isDuplicate = false;

Expand Down
15 changes: 4 additions & 11 deletions lib/rules/no-magic-numbers.js
Expand Up @@ -5,6 +5,8 @@

"use strict";

const { isNumericLiteral } = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -34,7 +36,7 @@ module.exports = {
ignore: {
type: "array",
items: {
type: "number"
type: ["number", "bigint"]
},
uniqueItems: true
},
Expand All @@ -59,15 +61,6 @@ module.exports = {
ignore = config.ignore || [],
ignoreArrayIndexes = !!config.ignoreArrayIndexes;

/**
* Returns whether the node is number literal
* @param {Node} node the node literal being evaluated
* @returns {boolean} true if the node is a number literal
*/
function isNumber(node) {
return typeof node.value === "number";
}

/**
* Returns whether the number should be ignored
* @param {number} num the number
Expand Down Expand Up @@ -113,7 +106,7 @@ module.exports = {
Literal(node) {
const okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"];

if (!isNumber(node)) {
if (!isNumericLiteral(node)) {
return;
}

Expand Down
26 changes: 17 additions & 9 deletions lib/rules/no-useless-computed-key.js
Expand Up @@ -65,20 +65,21 @@ module.exports = {
allowedKey = "__proto__";
}

if (key.type === "Literal" && (nodeType === "string" || nodeType === "number") && key.value !== allowedKey) {
if (
key.type === "Literal" &&
(nodeType === "string" || nodeType === "number" || nodeType === "bigint") &&
key.value !== allowedKey
) {
context.report({
node,
message: MESSAGE_UNNECESSARY_COMPUTED,
data: { property: sourceCode.getText(key) },
fix(fixer) {
const leftSquareBracket = sourceCode.getFirstToken(node, astUtils.isOpeningBracketToken);
const rightSquareBracket = sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isClosingBracketToken);
const tokensBetween = sourceCode.getTokensBetween(leftSquareBracket, rightSquareBracket, 1);
const leftSquareBracket = sourceCode.getTokenBefore(key, astUtils.isOpeningBracketToken);
const rightSquareBracket = sourceCode.getTokenAfter(key, astUtils.isClosingBracketToken);

if (tokensBetween.slice(0, -1).some((token, index) =>
sourceCode.getText().slice(token.range[1], tokensBetween[index + 1].range[0]).trim())) {

// If there are comments between the brackets and the property name, don't do a fix.
// If there are comments between the brackets and the property name, don't do a fix.
if (sourceCode.commentsExistBetween(leftSquareBracket, rightSquareBracket)) {
return null;
}

Expand All @@ -88,7 +89,14 @@ module.exports = {
const needsSpaceBeforeKey = tokenBeforeLeftBracket.range[1] === leftSquareBracket.range[0] &&
!astUtils.canTokensBeAdjacent(tokenBeforeLeftBracket, sourceCode.getFirstToken(key));

const replacementKey = (needsSpaceBeforeKey ? " " : "") + key.raw;
/*
* Well-known browsers throw syntax errors on bigint literals of property name,
* so convert bigint to string.
* TODO(mysticatea): remove this conversion in the future.
*/
const replacementKey =
(needsSpaceBeforeKey ? " " : "") +
(nodeType === "bigint" ? `"${key.value}"` : key.raw);

return fixer.replaceTextRange([leftSquareBracket.range[0], rightSquareBracket.range[1]], replacementKey);
}
Expand Down
7 changes: 4 additions & 3 deletions lib/rules/quote-props.js
Expand Up @@ -8,8 +8,9 @@
// Requirements
//------------------------------------------------------------------------------

const espree = require("espree"),
keywords = require("./utils/keywords");
const espree = require("espree");
const astUtils = require("./utils/ast-utils");
const keywords = require("./utils/keywords");

//------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -177,7 +178,7 @@ module.exports = {
data: { property: key.name },
fix: fixer => fixer.replaceText(key, getQuotedKey(key))
});
} else if (NUMBERS && key.type === "Literal" && typeof key.value === "number") {
} else if (NUMBERS && key.type === "Literal" && astUtils.isNumericLiteral(key)) {
context.report({
node,
message: MESSAGE_NUMERIC,
Expand Down