From 41b1e4308c1cb01c8b00cc8adc36440e77854117 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Sun, 10 Nov 2019 09:15:58 +0800 Subject: [PATCH] New: add option for camelcase (fixes #12527) (#12528) * New: add option for camelcase (fixes #12527) * Docs: add docs about `ignoreImports` * Chore: add more tests * Docs: add notice --- docs/rules/camelcase.md | 32 ++++++++++++++++++++ lib/rules/camelcase.js | 25 ++++++++++++---- tests/lib/rules/camelcase.js | 58 ++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 6 deletions(-) diff --git a/docs/rules/camelcase.md b/docs/rules/camelcase.md index 1765f1852c4..5c4efcfe400 100644 --- a/docs/rules/camelcase.md +++ b/docs/rules/camelcase.md @@ -14,6 +14,8 @@ This rule has an object option: * `"properties": "never"` does not check property names * `"ignoreDestructuring": false` (default) enforces camelcase style for destructured identifiers * `"ignoreDestructuring": true` does not check destructured identifiers +* `"ignoreImports": false` (default) enforces camelcase style for ES2015 imports +* `"ignoreImports": true` does not check ES2015 imports (but still checks any use of the imports later in the code except function arguments) * `allow` (`string[]`) list of properties to accept. Accept regex. ### properties: "always" @@ -152,6 +154,36 @@ var { category_id = 1 } = query; var { category_id: category_id } = query; ``` +### ignoreImports: false + +Examples of **incorrect** code for this rule with the default `{ "ignoreImports": false }` option: + +```js +/*eslint camelcase: "error"*/ + +import { snake_cased } from 'mod'; +``` + +### ignoreImports: true + +Examples of **incorrect** code for this rule with the `{ "ignoreImports": true }` option: + +```js +/*eslint camelcase: ["error", {ignoreImports: true}]*/ + +import default_import from 'mod'; + +import * as namespaced_import from 'mod'; +``` + +Examples of **correct** code for this rule with the `{ "ignoreImports": true }` option: + +```js +/*eslint camelcase: ["error", {ignoreImports: true}]*/ + +import { snake_cased } from 'mod'; +``` + ## allow Examples of **correct** code for this rule with the `allow` option: diff --git a/lib/rules/camelcase.js b/lib/rules/camelcase.js index cdc16fab9f9..a06c7f94042 100644 --- a/lib/rules/camelcase.js +++ b/lib/rules/camelcase.js @@ -28,6 +28,10 @@ module.exports = { type: "boolean", default: false }, + ignoreImports: { + type: "boolean", + default: false + }, properties: { enum: ["always", "never"] }, @@ -56,6 +60,7 @@ module.exports = { const options = context.options[0] || {}; let properties = options.properties || ""; const ignoreDestructuring = options.ignoreDestructuring; + const ignoreImports = options.ignoreImports; const allow = options.allow || []; if (properties !== "always" && properties !== "never") { @@ -79,7 +84,7 @@ module.exports = { function isUnderscored(name) { // if there's an underscore, it might be A_CONSTANT, which is okay - return name.indexOf("_") > -1 && name !== name.toUpperCase(); + return name.includes("_") && name !== name.toUpperCase(); } /** @@ -89,9 +94,9 @@ module.exports = { * @private */ function isAllowed(name) { - return allow.findIndex( + return allow.some( entry => name === entry || name.match(new RegExp(entry, "u")) - ) !== -1; + ); } /** @@ -127,7 +132,7 @@ module.exports = { * @private */ function report(node) { - if (reported.indexOf(node) < 0) { + if (!reported.includes(node)) { reported.push(node); context.report({ node, messageId: "notCamelCase", data: { name: node.name } }); } @@ -209,10 +214,18 @@ module.exports = { } // Check if it's an import specifier - } else if (["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"].indexOf(node.parent.type) >= 0) { + } else if (["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"].includes(node.parent.type)) { + + if (node.parent.type === "ImportSpecifier" && ignoreImports) { + return; + } // Report only if the local imported identifier is underscored - if (node.parent.local && node.parent.local.name === node.name && nameIsUnderscored) { + if ( + node.parent.local && + node.parent.local.name === node.name && + nameIsUnderscored + ) { report(node); } diff --git a/tests/lib/rules/camelcase.js b/tests/lib/rules/camelcase.js index 4aa77abed2a..1181561efa8 100644 --- a/tests/lib/rules/camelcase.js +++ b/tests/lib/rules/camelcase.js @@ -151,6 +151,16 @@ ruleTester.run("camelcase", rule, { code: "import { no_camelcased as camelCased, anoterCamelCased } from \"external-module\";", parserOptions: { ecmaVersion: 6, sourceType: "module" } }, + { + code: "import { snake_cased } from 'mod'", + options: [{ ignoreImports: true }], + parserOptions: { ecmaVersion: 6, sourceType: "module" } + }, + { + code: "import { camelCased } from 'mod'", + options: [{ ignoreImports: false }], + parserOptions: { ecmaVersion: 6, sourceType: "module" } + }, { code: "function foo({ no_camelcased: camelCased }) {};", parserOptions: { ecmaVersion: 6 } @@ -532,6 +542,54 @@ ruleTester.run("camelcase", rule, { } ] }, + { + code: "import snake_cased from 'mod'", + options: [{ ignoreImports: true }], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "notCamelCase", + data: { name: "snake_cased" }, + type: "Identifier" + } + ] + }, + { + code: "import * as snake_cased from 'mod'", + options: [{ ignoreImports: true }], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "notCamelCase", + data: { name: "snake_cased" }, + type: "Identifier" + } + ] + }, + { + code: "import snake_cased from 'mod'", + options: [{ ignoreImports: false }], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "notCamelCase", + data: { name: "snake_cased" }, + type: "Identifier" + } + ] + }, + { + code: "import * as snake_cased from 'mod'", + options: [{ ignoreImports: false }], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "notCamelCase", + data: { name: "snake_cased" }, + type: "Identifier" + } + ] + }, { code: "function foo({ no_camelcased }) {};", parserOptions: { ecmaVersion: 6 },