Skip to content

Commit

Permalink
New: Add --fix-type option to CLI (fixes #10855)
Browse files Browse the repository at this point in the history
  • Loading branch information
nzakas committed Nov 1, 2018
1 parent 44d37ca commit 61034e2
Show file tree
Hide file tree
Showing 280 changed files with 1,212 additions and 43 deletions.
4 changes: 4 additions & 0 deletions docs/developer-guide/working-with-rules.md
Expand Up @@ -26,6 +26,8 @@ Here is the basic format of the source file for a rule:

module.exports = {
meta: {
type: "suggestion",

docs: {
description: "disallow unnecessary semicolons",
category: "Possible Errors",
Expand All @@ -49,6 +51,8 @@ The source file for a rule exports an object with the following properties.

`meta` (object) contains metadata for the rule:

* `type` (string) indicates the type of rule, which is one of `"problem"`, `"suggestion"`, or `"style"`

* `docs` (object) is required for core rules of ESLint:

* `description` (string) provides the short description of the rule in the [rules index](../rules/)
Expand Down
19 changes: 19 additions & 0 deletions docs/user-guide/command-line-interface.md
Expand Up @@ -46,6 +46,7 @@ Specifying rules and plugins:
Fixing problems:
--fix Automatically fix problems
--fix-dry-run Automatically fix problems without saving the changes to the file system
--fix-type Array Specify the types of fixes to apply
Ignoring files:
--ignore-path path::String Specify path of ignore file
Expand Down Expand Up @@ -233,6 +234,24 @@ getSomeText | eslint --stdin --fix-dry-run --format=json

This flag can be useful for integrations (e.g. editor plugins) which need to autofix text from the command line without saving it to the filesystem.

#### `--fix-type`

This option allows you to specify the type of fixes to apply when using either `--fix` or `--fix-dry-run`. The three types of fixes are:

1. `problem` - fix potential errors in the code
1. `suggestion` - apply fixes to the code that improve it
1. `style` - apply fixes that do not mutate the program structure (AST)

You can specify one or more fix type on the command line. Here are some examples:

```
eslint --fix --fix-type suggestion .
eslint --fix --fix-type suggestion --fix-type problem .
eslint --fix --fix-type suggestion,style .
```

This option is helpful if you are using another program to style your code but you would still like ESLint to apply other types of fixes.

### Ignoring files

#### `--ignore-path`
Expand Down
21 changes: 19 additions & 2 deletions lib/cli-engine.js
Expand Up @@ -49,6 +49,7 @@ const resolver = new ModuleResolver();
* @property {string[]} envs An array of environments to load.
* @property {string[]} extensions An array of file extensions to check.
* @property {boolean|Function} fix Execute in autofix mode. If a function, should return a boolean.
* @property {string[]} fixTypes Array of rule types to apply fixes for.
* @property {string[]} globals An array of global variables to declare.
* @property {boolean} ignore False disables use of .eslintignore.
* @property {string} ignorePath The ignore file to use instead of .eslintignore.
Expand Down Expand Up @@ -175,7 +176,6 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
}

const autofixingEnabled = typeof fix !== "undefined" && (!processor || processor.supportsAutofix);

const fixedResult = linter.verifyAndFix(text, config, {
filename: effectiveFilename,
allowInlineConfig,
Expand All @@ -184,7 +184,6 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, repor
preprocess: processor && (rawText => processor.preprocess(rawText, effectiveFilename)),
postprocess: processor && (problemLists => processor.postprocess(problemLists, effectiveFilename))
});

const stats = calculateStatsPerFile(fixedResult.messages);

const result = {
Expand Down Expand Up @@ -459,6 +458,24 @@ class CLIEngine {
*/
this._lintResultCache = new LintResultCache(cacheFile, this.config);
}

// setup special filter for fixes
if (this.options.fixTypes && this.options.fixTypes.length > 0) {

// convert to Set for faster lookup
const fixTypes = new Set(this.options.fixTypes);

// save original value of options.fix in case it's a function
const originalFix = this.options.fix;

this.options.fix = lintResult => {
const rules = this.getRules();
const matches = fixTypes.has(rules.get(lintResult.ruleId).meta.type);

return matches && (typeof originalFix === "function" ? originalFix(lintResult) : true);
};
}

}

getRules() {
Expand Down
7 changes: 6 additions & 1 deletion lib/cli.js
Expand Up @@ -64,6 +64,7 @@ function translateOptions(cliOptions) {
cacheFile: cliOptions.cacheFile,
cacheLocation: cliOptions.cacheLocation,
fix: (cliOptions.fix || cliOptions.fixDryRun) && (cliOptions.quiet ? quietFixPredicate : true),
fixTypes: cliOptions.fixType,
allowInlineConfig: cliOptions.inlineConfig,
reportUnusedDisableDirectives: cliOptions.reportUnusedDisableDirectives
};
Expand Down Expand Up @@ -187,8 +188,12 @@ const cli = {
return 2;
}

const engine = new CLIEngine(translateOptions(currentOptions));
if (currentOptions.fixType && !currentOptions.fix && !currentOptions.fixDryRun) {
log.error("The --fix-type option requires either --fix or --fix-dry-run.");
return 2;
}

const engine = new CLIEngine(translateOptions(currentOptions));
const report = useStdin ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files);

if (currentOptions.fix) {
Expand Down
5 changes: 5 additions & 0 deletions lib/options.js
Expand Up @@ -97,6 +97,11 @@ module.exports = optionator({
default: false,
description: "Automatically fix problems without saving the changes to the file system"
},
{
option: "fix-type",
type: "Array",
description: "Specify the types of fixes to apply"
},
{
heading: "Ignoring files"
},
Expand Down
4 changes: 4 additions & 0 deletions lib/rules/accessor-pairs.js
Expand Up @@ -72,12 +72,15 @@ function isPropertyDescriptor(node) {

module.exports = {
meta: {
type: "suggestion",

docs: {
description: "enforce getter and setter pairs in objects",
category: "Best Practices",
recommended: false,
url: "https://eslint.org/docs/rules/accessor-pairs"
},

schema: [{
type: "object",
properties: {
Expand All @@ -90,6 +93,7 @@ module.exports = {
},
additionalProperties: false
}],

messages: {
getter: "Getter is not present.",
setter: "Setter is not present."
Expand Down
5 changes: 5 additions & 0 deletions lib/rules/array-bracket-newline.js
Expand Up @@ -13,13 +13,17 @@ const astUtils = require("../util/ast-utils");

module.exports = {
meta: {
type: "style",

docs: {
description: "enforce linebreaks after opening and before closing array brackets",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/array-bracket-newline"
},

fixable: "whitespace",

schema: [
{
oneOf: [
Expand All @@ -42,6 +46,7 @@ module.exports = {
]
}
],

messages: {
unexpectedOpeningLinebreak: "There should be no linebreak after '['.",
unexpectedClosingLinebreak: "There should be no linebreak before ']'.",
Expand Down
5 changes: 5 additions & 0 deletions lib/rules/array-bracket-spacing.js
Expand Up @@ -12,13 +12,17 @@ const astUtils = require("../util/ast-utils");

module.exports = {
meta: {
type: "style",

docs: {
description: "enforce consistent spacing inside array brackets",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/array-bracket-spacing"
},

fixable: "whitespace",

schema: [
{
enum: ["always", "never"]
Expand All @@ -39,6 +43,7 @@ module.exports = {
additionalProperties: false
}
],

messages: {
unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.",
unexpectedSpaceBefore: "There should be no space before '{{tokenValue}}'.",
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/array-callback-return.js
Expand Up @@ -141,6 +141,8 @@ function isCallbackOfArrayMethod(node) {

module.exports = {
meta: {
type: "suggestion",

docs: {
description: "enforce `return` statements in callbacks of array methods",
category: "Best Practices",
Expand Down
4 changes: 4 additions & 0 deletions lib/rules/array-element-newline.js
Expand Up @@ -13,13 +13,17 @@ const astUtils = require("../util/ast-utils");

module.exports = {
meta: {
type: "style",

docs: {
description: "enforce line breaks after each array element",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/array-element-newline"
},

fixable: "whitespace",

schema: [
{
oneOf: [
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/arrow-body-style.js
Expand Up @@ -16,6 +16,8 @@ const astUtils = require("../util/ast-utils");

module.exports = {
meta: {
type: "suggestion",

docs: {
description: "require braces around arrow function bodies",
category: "ECMAScript 6",
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/arrow-parens.js
Expand Up @@ -16,6 +16,8 @@ const astUtils = require("../util/ast-utils");

module.exports = {
meta: {
type: "suggestion",

docs: {
description: "require parentheses around arrow function arguments",
category: "ECMAScript 6",
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/arrow-spacing.js
Expand Up @@ -16,6 +16,8 @@ const astUtils = require("../util/ast-utils");

module.exports = {
meta: {
type: "suggestion",

docs: {
description: "enforce consistent spacing before and after the arrow in arrow functions",
category: "ECMAScript 6",
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/block-scoped-var.js
Expand Up @@ -10,6 +10,8 @@

module.exports = {
meta: {
type: "suggestion",

docs: {
description: "enforce the use of variables within the scope they are defined",
category: "Best Practices",
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/block-spacing.js
Expand Up @@ -13,6 +13,8 @@ const util = require("../util/ast-utils");

module.exports = {
meta: {
type: "style",

docs: {
description: "disallow or enforce spaces inside of blocks after opening block and before closing block",
category: "Stylistic Issues",
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/brace-style.js
Expand Up @@ -13,6 +13,8 @@ const astUtils = require("../util/ast-utils");

module.exports = {
meta: {
type: "style",

docs: {
description: "enforce consistent brace style for blocks",
category: "Stylistic Issues",
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/callback-return.js
Expand Up @@ -10,6 +10,8 @@

module.exports = {
meta: {
type: "suggestion",

docs: {
description: "require `return` statements after callbacks",
category: "Node.js and CommonJS",
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/camelcase.js
Expand Up @@ -11,6 +11,8 @@

module.exports = {
meta: {
type: "style",

docs: {
description: "enforce camelcase naming convention",
category: "Stylistic Issues",
Expand Down
4 changes: 4 additions & 0 deletions lib/rules/capitalized-comments.js
Expand Up @@ -108,13 +108,17 @@ function createRegExpForIgnorePatterns(normalizedOptions) {

module.exports = {
meta: {
type: "style",

docs: {
description: "enforce or disallow capitalization of the first letter of a comment",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/capitalized-comments"
},

fixable: "code",

schema: [
{ enum: ["always", "never"] },
{
Expand Down
3 changes: 3 additions & 0 deletions lib/rules/class-methods-use-this.js
Expand Up @@ -11,12 +11,15 @@

module.exports = {
meta: {
type: "suggestion",

docs: {
description: "enforce that class methods utilize `this`",
category: "Best Practices",
recommended: false,
url: "https://eslint.org/docs/rules/class-methods-use-this"
},

schema: [{
type: "object",
properties: {
Expand Down
4 changes: 4 additions & 0 deletions lib/rules/comma-dangle.js
Expand Up @@ -76,13 +76,17 @@ function normalizeOptions(optionValue) {

module.exports = {
meta: {
type: "style",

docs: {
description: "require or disallow trailing commas",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/comma-dangle"
},

fixable: "code",

schema: {
definitions: {
value: {
Expand Down
2 changes: 2 additions & 0 deletions lib/rules/comma-spacing.js
Expand Up @@ -12,6 +12,8 @@ const astUtils = require("../util/ast-utils");

module.exports = {
meta: {
type: "style",

docs: {
description: "enforce consistent spacing before and after commas",
category: "Stylistic Issues",
Expand Down
5 changes: 5 additions & 0 deletions lib/rules/comma-style.js
Expand Up @@ -13,13 +13,17 @@ const astUtils = require("../util/ast-utils");

module.exports = {
meta: {
type: "style",

docs: {
description: "enforce consistent comma style",
category: "Stylistic Issues",
recommended: false,
url: "https://eslint.org/docs/rules/comma-style"
},

fixable: "code",

schema: [
{
enum: ["first", "last"]
Expand All @@ -37,6 +41,7 @@ module.exports = {
additionalProperties: false
}
],

messages: {
unexpectedLineBeforeAndAfterComma: "Bad line breaking before and after ','.",
expectedCommaFirst: "',' should be placed first.",
Expand Down

0 comments on commit 61034e2

Please sign in to comment.