diff --git a/src/cli-constant.js b/src/cli-constant.js index b8b38948..8dd4ac42 100644 --- a/src/cli-constant.js +++ b/src/cli-constant.js @@ -1,8 +1,6 @@ "use strict"; -const normalizer = require("./cli-normalizer"); - -const detailOptions = normalizer.normalizeDetailOptions({ +const detailOptions = normalizeDetailOptions({ "bracket-spacing": { type: "boolean", category: "format", @@ -241,6 +239,29 @@ function dedent(str) { return str.replace(new RegExp(`^ {${spaces}}`, "gm"), "").trim(); } +function normalizeDetailOptions(rawDetailOptions) { + const names = Object.keys(rawDetailOptions).sort(); + + const normaliezd = names.map(name => { + const option = rawDetailOptions[name]; + return Object.assign({}, option, { + name, + choices: + option.choices && + option.choices.map( + choice => (typeof choice === "object" ? choice : { value: choice }) + ), + getter: option.getter || (value => value) + }); + }); + + normaliezd.forEach(normalizedOption => { + normaliezd[normalizedOption.name] = normalizedOption; + }); + + return normaliezd; +} + module.exports = { minimistOptions, detailOptions diff --git a/src/cli-normalizer.js b/src/cli-normalizer.js deleted file mode 100644 index bfad72c8..00000000 --- a/src/cli-normalizer.js +++ /dev/null @@ -1,95 +0,0 @@ -"use strict"; - -const validator = require("./cli-validator"); - -function normalizeDetailOptions(detailOptions) { - const names = Object.keys(detailOptions).sort(); - - const normaliezdOptions = names.map(name => { - const option = detailOptions[name]; - const normalizedOption = Object.assign({}, option, { - name, - choices: - option.choices && - option.choices.map( - choice => (typeof choice === "string" ? { value: choice } : choice) - ), - _getValue: (value, argv) => { - const normalizedValue = getValue(value, argv); - - if (option.exception !== undefined) { - if (typeof option.exception === "function") { - if (option.exception(normalizedValue)) { - return normalizedValue; - } - } else { - if (normalizedValue === option.exception) { - return normalizedValue; - } - } - } - - switch (option.type) { - case "int": - validator.validateIntOption(normalizedValue, normalizedOption); - return Number(normalizedValue); - case "choice": - validator.validateChoiceOption(normalizedValue, normalizedOption); - break; - } - - return normalizedValue; - } - }); - - return normalizedOption; - - function getValue(value, argv) { - if (value && option.deprecated) { - let warning = `\`--${name}\` is deprecated.`; - if (typeof option.deprecated === "string") { - warning += ` ${option.deprecated}`; - } - console.warn(warning); - } - if (typeof option.getter === "function") { - return option.getter(value, argv); - } - if (option.type === "choice") { - const choice = option.choices.find(choice => choice.value === value); - if (choice !== undefined && choice.deprecated) { - const warningValue = - value === "" ? "without an argument" : `with value \`${value}\``; - console.warn( - `\`--${name}\` ${warningValue} is deprecated. Automatically redirect to \`--${name}=${choice.redirect}\`.` - ); - return choice.redirect; - } - } - return value; - } - }); - - normaliezdOptions.forEach(normalizedOption => { - normaliezdOptions[normalizedOption.name] = normalizedOption; - }); - - return normaliezdOptions; -} - -function normalizeArgv(argv, detailOptions) { - const normalizedArgv = { _: argv["_"] }; - - detailOptions.forEach(option => { - Object.defineProperty(normalizedArgv, option.name, { - get: () => option._getValue(argv[option.name], normalizedArgv) - }); - }); - - return normalizedArgv; -} - -module.exports = { - normalizeArgv, - normalizeDetailOptions -}; diff --git a/src/cli-util.js b/src/cli-util.js index c5270198..90a4eb17 100644 --- a/src/cli-util.js +++ b/src/cli-util.js @@ -14,7 +14,7 @@ const prettier = eval("require")("../index"); const cleanAST = require("./clean-ast").cleanAST; const resolver = require("./resolve-config"); const constant = require("./cli-constant"); -const normalizer = require("./cli-normalizer"); +const validator = require("./cli-validator"); const apiDefaultOptions = require("./options").defaults; function getOptions(argv) { @@ -159,7 +159,7 @@ function getOptionsForFile(argv, filePath) { function parseArgsToOptions(argv, overrideDefaults) { return getOptions( - normalizer.normalizeArgv( + normalizeArgv( minimist( argv.__args, Object.assign({ @@ -172,7 +172,7 @@ function parseArgsToOptions(argv, overrideDefaults) { ) }) ), - constant.detailOptions + { warning: false } ) ); } @@ -398,10 +398,99 @@ function indent(str, spaces) { return str.replace(/^/gm, " ".repeat(spaces)); } +function normalizeArgv(rawArgv, options) { + options = options || {}; + + const consoleWarn = options.warning === false ? () => {} : console.warn; + + const normalized = {}; + + Object.keys(rawArgv).forEach(key => { + const rawValue = rawArgv[key]; + + if (key === "_") { + normalized[key] = rawValue; + return; + } + + if (key.length === 1) { + // do nothing with alias + return; + } + + const option = constant.detailOptions[key]; + + if (option === undefined) { + // unknown option + return; + } + + const value = getValue(rawValue, option); + + if (option.exception !== undefined) { + if (typeof option.exception === "function") { + if (option.exception(value)) { + normalized[key] = value; + return; + } + } else { + if (value === option.exception) { + normalized[key] = value; + return; + } + } + } + + switch (option.type) { + case "int": + validator.validateIntOption(value, option); + normalized[key] = Number(value); + break; + case "choice": + validator.validateChoiceOption(value, option); + // eslint-disable-next-line no-fallthrough + default: + normalized[key] = value; + break; + } + }); + + return normalized; + + function getValue(rawValue, option) { + if (rawValue && option.deprecated) { + let warning = `\`--${option.name}\` is deprecated.`; + if (typeof option.deprecated === "string") { + warning += ` ${option.deprecated}`; + } + consoleWarn(warning); + } + + const value = option.getter(rawValue, rawArgv); + + if (option.type === "choice") { + const choice = option.choices.find(choice => choice.value === rawValue); + if (choice !== undefined && choice.deprecated) { + const warningDescription = + rawValue === "" + ? "without an argument" + : `with value \`${rawValue}\``; + consoleWarn( + `\`--${option.name}\` ${warningDescription} is deprecated. Automatically redirect to \`--${option.name}=${choice.redirect}\`.` + ); + return choice.redirect; + } + } + + return value; + } +} + module.exports = { logResolvedConfigPathOrDie, format, formatStdin, formatFiles, - createUsage + createUsage, + normalizeArgv }; diff --git a/src/cli.js b/src/cli.js index f40623bc..889009f5 100644 --- a/src/cli.js +++ b/src/cli.js @@ -6,13 +6,9 @@ const prettier = eval("require")("../index"); const constant = require("./cli-constant"); const util = require("./cli-util"); const validator = require("./cli-validator"); -const normalizer = require("./cli-normalizer"); function run(args) { - const argv = normalizer.normalizeArgv( - minimist(args, constant.minimistOptions), - constant.detailOptions - ); + const argv = util.normalizeArgv(minimist(args, constant.minimistOptions)); argv.__args = args; argv.__filePatterns = argv["_"]; diff --git a/tests_integration/__tests__/__snapshots__/config-invalid.js.snap b/tests_integration/__tests__/__snapshots__/config-invalid.js.snap index 6af7802c..6f911812 100644 --- a/tests_integration/__tests__/__snapshots__/config-invalid.js.snap +++ b/tests_integration/__tests__/__snapshots__/config-invalid.js.snap @@ -19,9 +19,8 @@ Expected \\"none\\", \\"es5\\" or \\"all\\", but received: \\"wow\\" `; exports[`throw error with invalid config precedence option (configPrecedence) 1`] = ` -"Error: Invalid option for --config-precedence. -Expected \\"cli-override\\", \\"file-override\\" or \\"prefer-file\\", but received: \\"option/configPrecedence\\" -" +"Invalid option for --config-precedence. +Expected \\"cli-override\\", \\"file-override\\" or \\"prefer-file\\", but received: \\"option/configPrecedence\\"" `; exports[`throw error with invalid config target (directory) 1`] = `