diff --git a/lib/cli-engine.js b/lib/cli-engine.js index 46628c1e4a22..25cb101b54b2 100644 --- a/lib/cli-engine.js +++ b/lib/cli-engine.js @@ -23,11 +23,9 @@ const fs = require("fs"), Config = require("./config"), fileEntryCache = require("file-entry-cache"), globUtil = require("./util/glob-util"), - SourceCodeFixer = require("./util/source-code-fixer"), validator = require("./config/config-validator"), stringify = require("json-stable-stringify"), hash = require("./util/hash"), - pkg = require("../package.json"); const debug = require("debug")("eslint:cli-engine"); @@ -132,80 +130,6 @@ function calculateStatsPerRun(results) { }); } -/** - * Performs multiple autofix passes over the text until as many fixes as possible - * have been applied. - * @param {string} text The source text to apply fixes to. - * @param {Object} config The ESLint config object to use. - * @param {Object} options The ESLint options object to use. - * @param {string} options.filename The filename from which the text was read. - * @param {boolean} options.allowInlineConfig Flag indicating if inline comments - * should be allowed. - * @param {Linter} linter Linter context - * @returns {Object} The result of the fix operation as returned from the - * SourceCodeFixer. - * @private - */ -function multipassFix(text, config, options, linter) { - const MAX_PASSES = 10; - let messages = [], - fixedResult, - fixed = false, - passNumber = 0; - - /** - * This loop continues until one of the following is true: - * - * 1. No more fixes have been applied. - * 2. Ten passes have been made. - * - * That means anytime a fix is successfully applied, there will be another pass. - * Essentially, guaranteeing a minimum of two passes. - */ - do { - passNumber++; - - debug(`Linting code for ${options.filename} (pass ${passNumber})`); - messages = linter.verify(text, config, options); - - debug(`Generating fixed text for ${options.filename} (pass ${passNumber})`); - fixedResult = SourceCodeFixer.applyFixes(linter.getSourceCode(), messages); - - // stop if there are any syntax errors. - // 'fixedResult.output' is a empty string. - if (messages.length === 1 && messages[0].fatal) { - break; - } - - // keep track if any fixes were ever applied - important for return value - fixed = fixed || fixedResult.fixed; - - // update to use the fixed output instead of the original text - text = fixedResult.output; - - } while ( - fixedResult.fixed && - passNumber < MAX_PASSES - ); - - - /* - * If the last result had fixes, we need to lint again to be sure we have - * the most up-to-date information. - */ - if (fixedResult.fixed) { - fixedResult.messages = linter.verify(text, config, options); - } - - - // ensure the last result properly reflects if fixes were done - fixedResult.fixed = fixed; - fixedResult.output = text; - - return fixedResult; - -} - /** * Processes an source code using ESLint. * @param {string} text The source code to check. @@ -269,7 +193,7 @@ function processText(text, configHelper, filename, fix, allowInlineConfig, linte } else { if (fix) { - fixedResult = multipassFix(text, config, { + fixedResult = linter.verifyAndFix(text, config, { filename, allowInlineConfig }, linter); diff --git a/lib/linter.js b/lib/linter.js index 25af05223d01..b9844b5872b5 100755 --- a/lib/linter.js +++ b/lib/linter.js @@ -27,9 +27,11 @@ const assert = require("assert"), Rules = require("./rules"), timing = require("./timing"), astUtils = require("./ast-utils"), + pkg = require("../package.json"), + SourceCodeFixer = require("./util/source-code-fixer"); - pkg = require("../package.json"); - +const debug = require("debug")("eslint:linter"); +const MAX_PASSES = 10; //------------------------------------------------------------------------------ // Typedefs @@ -1185,6 +1187,74 @@ class Linter extends EventEmitter { getDeclaredVariables(node) { return (this.scopeManager && this.scopeManager.getDeclaredVariables(node)) || []; } + + /** + * Performs multiple autofix passes over the text until as many fixes as possible + * have been applied. + * @param {string} text The source text to apply fixes to. + * @param {Object} config The ESLint config object to use. + * @param {Object} options The ESLint options object to use. + * @param {string} options.filename The filename from which the text was read. + * @param {boolean} options.allowInlineConfig Flag indicating if inline comments + * should be allowed. + * @returns {Object} The result of the fix operation as returned from the + * SourceCodeFixer. + */ + verifyAndFix(text, config, options) { + let messages = [], + fixedResult, + fixed = false, + passNumber = 0; + + /** + * This loop continues until one of the following is true: + * + * 1. No more fixes have been applied. + * 2. Ten passes have been made. + * + * That means anytime a fix is successfully applied, there will be another pass. + * Essentially, guaranteeing a minimum of two passes. + */ + do { + passNumber++; + + debug(`Linting code for ${options.filename} (pass ${passNumber})`); + messages = this.verify(text, config, options); + + debug(`Generating fixed text for ${options.filename} (pass ${passNumber})`); + fixedResult = SourceCodeFixer.applyFixes(this.getSourceCode(), messages); + + // stop if there are any syntax errors. + // 'fixedResult.output' is a empty string. + if (messages.length === 1 && messages[0].fatal) { + break; + } + + // keep track if any fixes were ever applied - important for return value + fixed = fixed || fixedResult.fixed; + + // update to use the fixed output instead of the original text + text = fixedResult.output; + + } while ( + fixedResult.fixed && + passNumber < MAX_PASSES + ); + + /* + * If the last result had fixes, we need to lint again to be sure we have + * the most up-to-date information. + */ + if (fixedResult.fixed) { + fixedResult.messages = this.verify(text, config, options); + } + + // ensure the last result properly reflects if fixes were done + fixedResult.fixed = fixed; + fixedResult.output = text; + + return fixedResult; + } } // methods that exist on SourceCode object