diff --git a/src/cli-constant.js b/src/cli-constant.js index 1b0d19831..01f7fe2e5 100644 --- a/src/cli-constant.js +++ b/src/cli-constant.js @@ -37,6 +37,7 @@ const options = normalizer.normalizeDetailOptions({ }, "cursor-offset": { type: "int", + exception: -1, isFormatOption: true, description: dedent(` Print (to stderr) where a cursor at the given position would move to after formatting. @@ -110,6 +111,7 @@ const options = normalizer.normalizeDetailOptions({ }, parser: { type: "choice", + exception: value => typeof value === "string", isFormatOption: true, choices: ["flow", "babylon", "typescript", "postcss", "json", "graphql"], description: "Specify which parse to use. Defaults to babylon.", @@ -123,6 +125,7 @@ const options = normalizer.normalizeDetailOptions({ }, "range-end": { type: "int", + exception: Infinity, isFormatOption: true, description: dedent(` Format code ending at a given character offset (exclusive). diff --git a/src/cli-normalizer.js b/src/cli-normalizer.js index 0c3d05a5b..56e030ec0 100644 --- a/src/cli-normalizer.js +++ b/src/cli-normalizer.js @@ -1,11 +1,13 @@ "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]; - return Object.assign({}, option, { + const normalizedOption = Object.assign({}, option, { name, choices: option.choices && @@ -13,30 +15,63 @@ function normalizeDetailOptions(detailOptions) { choice => (typeof choice === "string" ? { value: choice } : choice) ), _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; + const normalizedValue = getValue(value, argv); + + if (option.exception !== undefined) { + if (Array.isArray(option.exception)) { + if (option.exception.indexOf(normalizedValue) !== -1) { + return normalizedValue; + } + } else if (typeof option.exception === "function") { + if (option.exception(normalizedValue)) { + return normalizedValue; + } + } else { + if (normalizedValue === option.exception) { + return normalizedValue; + } } } - return value; + + switch (option.type) { + case "int": + validator.validateIntOption(normalizedValue, normalizedOption); + break; + 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 => { diff --git a/src/cli-util.js b/src/cli-util.js index dceb820ad..bf15eae70 100644 --- a/src/cli-util.js +++ b/src/cli-util.js @@ -14,7 +14,6 @@ const prettier = eval("require")("../index"); const cleanAST = require("./clean-ast").cleanAST; const resolver = require("./resolve-config"); const constant = require("./cli-constant"); -const validator = require("./cli-validator"); const normalizer = require("./cli-normalizer"); const apiDefaultOptions = require("./options").defaults; @@ -37,24 +36,11 @@ function getOptions(argv) { } function getIntOption(argv, optionName) { - const value = argv[optionName]; - - validator.validateIntOption(value, constant.options[optionName], { - // cursorOffset defaults to -1 and rangeEnd defaults to Infinity, which is not considered an integer. - exceptions: [apiDefaultOptions[kebabToCamel(optionName)]] - }); - - return Number(value); + return Number(argv[optionName]); } function getTrailingComma(argv) { - const value = argv["trailing-comma"]; - - validator.validateChoiceOption(value, constant.options["trailing-comma"], { - exceptions: [undefined] - }); - - return value; + return argv["trailing-comma"]; } function dashifyObject(object) { @@ -198,11 +184,6 @@ function parseArgsToOptions(argv, overrideDefaults) { function applyConfigPrecedence(argv, options) { try { - validator.validateChoiceOption( - argv["config-precedence"], - constant.options["config-precedence"] - ); - switch (argv["config-precedence"]) { case "cli-override": return parseArgsToOptions(argv, options); diff --git a/src/cli-validator.js b/src/cli-validator.js index 4f240b083..1da7b77c6 100644 --- a/src/cli-validator.js +++ b/src/cli-validator.js @@ -12,11 +12,7 @@ function validateArgv(argv) { } } -function validateIntOption(value, option, opts) { - if (opts && opts.exceptions && opts.exceptions.indexOf(value) !== -1) { - return; - } - +function validateIntOption(value, option) { if (!/^\d+$/.test(value)) { throw new Error( `Invalid --${option.name} value.\nExpected an integer, but received: ${value}`