From 87503e5ef776990aeb88d57d97c33544e8ccf264 Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Wed, 6 Sep 2017 09:52:59 +1000 Subject: [PATCH] Refactor error handling (#2750) --- src/cli-constant.js | 10 ++- src/cli-util.js | 85 ++++++++++++------- .../__snapshots__/config-invalid.js.snap | 21 +++-- 3 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/cli-constant.js b/src/cli-constant.js index c929936de..516475bd2 100644 --- a/src/cli-constant.js +++ b/src/cli-constant.js @@ -17,6 +17,12 @@ const stringOptionNames = [ "trailing-comma" ]; +const defaultOptions = { + "bracket-spacing": true, + semi: true, + parser: "babylon" +}; + const options = { boolean: [ "write", @@ -45,7 +51,8 @@ const options = { ].concat(stringOptionNames), default: { color: true, - "ignore-path": ".prettierignore" + "ignore-path": ".prettierignore", + "config-precedence": "cli-override" }, alias: { help: "h", @@ -111,6 +118,7 @@ Available options: module.exports = { booleanOptionNames, stringOptionNames, + defaultOptions, options, usage }; diff --git a/src/cli-util.js b/src/cli-util.js index 5c938ced1..201d16178 100644 --- a/src/cli-util.js +++ b/src/cli-util.js @@ -61,32 +61,35 @@ function getIntOption(argv, optionName) { return Number(value); } - console.error( + throw new Error( "Invalid --" + optionName + - " value. Expected an integer, but received: " + + " value.\nExpected an integer, but received: " + JSON.stringify(value) ); - process.exit(1); } function getTrailingComma(argv) { - switch (argv["trailing-comma"]) { - case undefined: - case "none": - return "none"; + const value = argv["trailing-comma"]; + + switch (value) { case "": console.warn( "Warning: `--trailing-comma` was used without an argument. This is deprecated. " + 'Specify "none", "es5", or "all".' ); return "es5"; + case undefined: + return "none"; + case "none": case "es5": - return "es5"; case "all": - return "all"; + return value; default: - throw new Error("Invalid option for --trailing-comma"); + throw new Error( + "Invalid option for --trailing-comma.\n" + + `Expected "none", "es5" or "all", but received: "${value}"` + ); } } @@ -195,41 +198,57 @@ function format(argv, input, opt) { return prettier.formatWithCursor(input, opt); } -function getOptionsForFile(argv, filePath) { - const options = - argv["config"] === false ? null : resolver.resolveConfig.sync(filePath); - +function getOptionsOrDie(argv, filePath) { try { - const dashifiedConfig = dashifyObject(options); - const parsedArgs = minimist(argv.__args, { + return argv["config"] === false + ? null + : resolver.resolveConfig.sync(filePath); + } catch (error) { + console.error("Error: Invalid configuration file."); + console.error(error.message); + process.exit(2); + } +} + +function getOptionsForFile(argv, filePath) { + const options = getOptionsOrDie(argv, filePath); + const configPrecedence = argv["config-precedence"]; + return applyConfigPrecedence(argv.__args, options, configPrecedence); +} + +function parseArgsToOptions(args, defaults) { + return getOptions( + minimist(args, { boolean: constant.booleanOptionNames, string: constant.stringOptionNames, default: Object.assign( - { - semi: true, - "bracket-spacing": true, - "config-precedence": "cli-override", - parser: "babylon" - }, - dashifiedConfig + {}, + constant.defaultOptions, + dashifyObject(defaults) ) - }); + }) + ); +} - switch (parsedArgs["config-precedence"]) { +function applyConfigPrecedence(args, options, configPrecedence) { + try { + switch (configPrecedence) { case "cli-override": - return getOptions(parsedArgs); + return parseArgsToOptions(args, options); case "file-override": - return getOptions(Object.assign({}, parsedArgs, dashifiedConfig)); + return Object.assign({}, parseArgsToOptions(args), options); case "prefer-file": - if (!options) { - return getOptions(parsedArgs); - } - return getOptions(dashifiedConfig); + return options || parseArgsToOptions(args); + default: - throw new Error("Invalid option for --config-precedence"); + throw new Error( + "Invalid option for --config-precedence.\n" + + 'Expected "cli-override", "file-override" or "prefer-file", ' + + `but received: "${configPrecedence}"` + ); } } catch (error) { - console.error("Invalid configuration:", error.toString()); + console.error(error.toString()); process.exit(2); } } diff --git a/tests_integration/__tests__/__snapshots__/config-invalid.js.snap b/tests_integration/__tests__/__snapshots__/config-invalid.js.snap index e01fcfd96..6af7802ca 100644 --- a/tests_integration/__tests__/__snapshots__/config-invalid.js.snap +++ b/tests_integration/__tests__/__snapshots__/config-invalid.js.snap @@ -1,20 +1,31 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`throw error with invalid config format 1`] = `"Failed to parse \\"/tests_integration/cli/config/invalid/file/.prettierrc\\" as JSON, JS, or YAML."`; +exports[`throw error with invalid config format 1`] = ` +"Error: Invalid configuration file. +Failed to parse \\"/tests_integration/cli/config/invalid/file/.prettierrc\\" as JSON, JS, or YAML. +" +`; exports[`throw error with invalid config option (int) 1`] = ` -"Invalid --tab-width value. Expected an integer, but received: 0.5 +"Error: Invalid --tab-width value. +Expected an integer, but received: 0.5 " `; exports[`throw error with invalid config option (trailingComma) 1`] = ` -"Invalid configuration: +"Error: Invalid option for --trailing-comma. +Expected \\"none\\", \\"es5\\" or \\"all\\", but received: \\"wow\\" " `; exports[`throw error with invalid config precedence option (configPrecedence) 1`] = ` -"Invalid configuration: +"Error: 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`] = `"EISDIR: illegal operation on a directory, read"`; +exports[`throw error with invalid config target (directory) 1`] = ` +"Error: Invalid configuration file. +EISDIR: illegal operation on a directory, read +" +`;