From 66351887d3e900c96d265249de2dd9db4ea53d69 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Tue, 10 Jul 2018 09:41:08 -0700 Subject: [PATCH] Run Prettier checks on CI (#2212) Summary: This will fail CI if we forgot to run `yarn prettier` before committing. We do the same in React repo. It prevents committing stale files that later cause unexpected changes. Pull Request resolved: https://github.com/facebook/prepack/pull/2212 Differential Revision: D8784406 Pulled By: gaearon fbshipit-source-id: ca948b8e088be8886c8ba865f280ba8d72750f69 --- .circleci/config.yml | 1 + .prettierrc | 5 ++ package.json | 1 + scripts/prettier.js | 70 +++++++++++++--------- test/react/FBMocks/fb24.js | 6 +- test/react/FBMocks/fb25.js | 6 +- test/react/ReactNative-test.js | 2 +- test/react/ReactNative/simple.js | 6 +- test/react/ReactNative/simple2.js | 2 +- test/react/Reconciliation/key-nesting-4.js | 11 ++-- test/react/Reconciliation/key-nesting-5.js | 11 ++-- test/react/Reconciliation/key-nesting-6.js | 11 ++-- test/react/Reconciliation/key-nesting-7.js | 11 ++-- test/react/Reconciliation/key-nesting-8.js | 11 ++-- 14 files changed, 83 insertions(+), 71 deletions(-) create mode 100644 .prettierrc diff --git a/.circleci/config.yml b/.circleci/config.yml index 3b5600fc4..b989f4321 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -90,6 +90,7 @@ jobs: - run: name: "Run Checks" command: | + yarn prettier-ci yarn lint yarn flow yarn depcheck diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..cd6d97fdd --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "trailingComma": "es5", + "parser": "babylon", + "printWidth": 120 +} \ No newline at end of file diff --git a/package.json b/package.json index 9d854b54f..35ba32363 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "depcheck": "babel-node scripts/detect_bad_deps.js", "prettier": "node ./scripts/prettier.js write-changed", "prettier-all": "node ./scripts/prettier.js write", + "prettier-ci": "node ./scripts/prettier.js", "debug-fb-www": "node --stack_trace_limit=200 --stack_size=10000 --max_old_space_size=16384 ./scripts/debug-fb-www.js" }, "dependencies": { diff --git a/scripts/prettier.js b/scripts/prettier.js index 9459c9700..f90dde7cd 100644 --- a/scripts/prettier.js +++ b/scripts/prettier.js @@ -13,21 +13,16 @@ // https://github.com/facebook/react/blob/master/scripts/prettier/index.js const chalk = require("chalk"); +const fs = require("fs"); const glob = require("glob"); -const path = require("path"); +const prettier = require("prettier"); const execFileSync = require("child_process").execFileSync; const mode = process.argv[2] || "check"; +const prettierConfigPath = require.resolve("../.prettierrc"); const shouldWrite = mode === "write" || mode === "write-changed"; const onlyChanged = mode === "check-changed" || mode === "write-changed"; -const isWindows = process.platform === "win32"; -const prettier = isWindows ? "prettier.cmd" : "prettier"; -const prettierCmd = path.resolve(__dirname, "../node_modules/.bin/" + prettier); -const defaultOptions = { - "trailing-comma": "es5", - "print-width": 120, -}; const config = { default: { patterns: ["src/**/*.js"], @@ -52,7 +47,6 @@ const changedFiles = new Set( Object.keys(config).forEach(key => { const patterns = config[key].patterns; - const options = config[key].options; const ignore = config[key].ignore; const globPattern = patterns.length > 1 ? `{${patterns.join(",")}}` : `${patterns.join(",")}`; @@ -62,27 +56,45 @@ Object.keys(config).forEach(key => { return; } - const args = Object.keys(defaultOptions).map(k => `--${k}=${(options && options[k]) || defaultOptions[k]}`); - args.push(`--${shouldWrite ? "write" : "l"}`); + let didWarn = false; + let didError = false; - let result; - try { - result = exec(prettierCmd, [...args, ...files]); - } catch (e) { - if (!shouldWrite) { - console.log( - "\n" + - e.output[1] + - "\n" + - chalk.red(` This project uses prettier to format all JavaScript code.\n`) + - chalk.dim(` Please run `) + - chalk.reset("yarn prettier") + - chalk.dim(` and add changes to files listed above to your commit.`) + - `\n` - ); - process.exit(1); + files.forEach(file => { + const options = prettier.resolveConfig.sync(file, { + config: prettierConfigPath, + }); + try { + const input = fs.readFileSync(file, "utf8"); + if (shouldWrite) { + const output = prettier.format(input, options); + if (output !== input) { + fs.writeFileSync(file, output, "utf8"); + } + } else { + if (!prettier.check(input, options)) { + if (!didWarn) { + console.log( + "\n" + + chalk.red(` This project uses prettier to format all JavaScript code.\n`) + + chalk.dim(` Please run `) + + chalk.reset("yarn prettier-all") + + chalk.dim(` and add changes to files listed below to your commit:`) + + `\n` + ); + didWarn = true; + } + console.log(` ${file}`); + } + } + } catch (error) { + didError = true; + console.log("\n\n" + error.message); + console.log(file); } - throw e; + }); + + if (didWarn || didError) { + console.log(); + process.exit(1); } - console.log("\n" + result); }); diff --git a/test/react/FBMocks/fb24.js b/test/react/FBMocks/fb24.js index 3014f4af5..04aae3de9 100644 --- a/test/react/FBMocks/fb24.js +++ b/test/react/FBMocks/fb24.js @@ -4,9 +4,9 @@ function App(props) { var data = {}; var someProps = Object.assign(data, props, { text: "Text!", - }) + }); var propsWithout = babelHelpers.objectWithoutProperties(data, []); - return
{propsWithout.text}
+ return
{propsWithout.text}
; } App.getTrials = function(renderer, Root, data, isCompiled) { @@ -25,4 +25,4 @@ if (this.__optimizeReactComponentTree) { __optimizeReactComponentTree(App); } -module.exports = App; \ No newline at end of file +module.exports = App; diff --git a/test/react/FBMocks/fb25.js b/test/react/FBMocks/fb25.js index 7b34c84be..8c86161fe 100644 --- a/test/react/FBMocks/fb25.js +++ b/test/react/FBMocks/fb25.js @@ -3,9 +3,9 @@ var React = require("react"); function App(props) { var someProps = Object.assign({}, props, { text: "Text!", - }) + }); var propsWithout = babelHelpers.objectWithoutProperties(someProps, []); - return
{propsWithout.text}
+ return
{propsWithout.text}
; } App.getTrials = function(renderer, Root, data, isCompiled) { @@ -24,4 +24,4 @@ if (this.__optimizeReactComponentTree) { __optimizeReactComponentTree(App); } -module.exports = App; \ No newline at end of file +module.exports = App; diff --git a/test/react/ReactNative-test.js b/test/react/ReactNative-test.js index 3a6b3ce81..425d81298 100644 --- a/test/react/ReactNative-test.js +++ b/test/react/ReactNative-test.js @@ -26,4 +26,4 @@ it("Simple", async () => { it("Simple 2", async () => { runTest(__dirname + "/ReactNative/simple2.js"); -}); \ No newline at end of file +}); diff --git a/test/react/ReactNative/simple.js b/test/react/ReactNative/simple.js index 22c797ace..5bd81b06f 100644 --- a/test/react/ReactNative/simple.js +++ b/test/react/ReactNative/simple.js @@ -25,9 +25,7 @@ class App extends React.Component { return ( Welcome to React Native! - - This is a React Native test. - + This is a React Native test. ); } @@ -44,4 +42,4 @@ if (this.__optimizeReactComponentTree) { }); } -module.exports = App; \ No newline at end of file +module.exports = App; diff --git a/test/react/ReactNative/simple2.js b/test/react/ReactNative/simple2.js index 14c38da43..2bd996bb4 100644 --- a/test/react/ReactNative/simple2.js +++ b/test/react/ReactNative/simple2.js @@ -45,4 +45,4 @@ if (this.__optimizeReactComponentTree) { }); } -module.exports = App; \ No newline at end of file +module.exports = App; diff --git a/test/react/Reconciliation/key-nesting-4.js b/test/react/Reconciliation/key-nesting-4.js index 1e061a4ac..1c03aa85e 100644 --- a/test/react/Reconciliation/key-nesting-4.js +++ b/test/react/Reconciliation/key-nesting-4.js @@ -1,5 +1,4 @@ -var React = require('react'); -this['React'] = React; +var React = require("react"); function Foo(props) { return [
]; @@ -31,10 +30,10 @@ App.getTrials = function(renderer, Root) { renderer.update(); renderer.update(); let results = []; - results.push(['ensure ref is called on every change', counter]); - results.push(['ensure refs are cleared', nodes.map(Boolean)]); - results.push(['ensure refs are different', new Set(nodes).size]); + results.push(["ensure ref is called on every change", counter]); + results.push(["ensure refs are cleared", nodes.map(Boolean)]); + results.push(["ensure refs are different", new Set(nodes).size]); return results; }; -module.exports = App; \ No newline at end of file +module.exports = App; diff --git a/test/react/Reconciliation/key-nesting-5.js b/test/react/Reconciliation/key-nesting-5.js index 7d8db0bb4..00aa06865 100644 --- a/test/react/Reconciliation/key-nesting-5.js +++ b/test/react/Reconciliation/key-nesting-5.js @@ -1,5 +1,4 @@ -var React = require('react'); -this['React'] = React; +var React = require("react"); function Foo(props) { return [
]; @@ -31,10 +30,10 @@ App.getTrials = function(renderer, Root) { renderer.update(); renderer.update(); let results = []; - results.push(['ensure ref is called on every change', counter]); - results.push(['ensure refs are cleared', nodes.map(Boolean)]); - results.push(['ensure refs are different', new Set(nodes).size]); + results.push(["ensure ref is called on every change", counter]); + results.push(["ensure refs are cleared", nodes.map(Boolean)]); + results.push(["ensure refs are different", new Set(nodes).size]); return results; }; -module.exports = App; \ No newline at end of file +module.exports = App; diff --git a/test/react/Reconciliation/key-nesting-6.js b/test/react/Reconciliation/key-nesting-6.js index a218d593f..b7422e81a 100644 --- a/test/react/Reconciliation/key-nesting-6.js +++ b/test/react/Reconciliation/key-nesting-6.js @@ -1,5 +1,4 @@ -var React = require('react'); -this['React'] = React; +var React = require("react"); function Foo(props) { return [[
]]; @@ -31,10 +30,10 @@ App.getTrials = function(renderer, Root) { renderer.update(); renderer.update(); let results = []; - results.push(['ensure ref is called on every change', counter]); - results.push(['ensure refs are cleared', nodes.map(Boolean)]); - results.push(['ensure refs are different', new Set(nodes).size]); + results.push(["ensure ref is called on every change", counter]); + results.push(["ensure refs are cleared", nodes.map(Boolean)]); + results.push(["ensure refs are different", new Set(nodes).size]); return results; }; -module.exports = App; \ No newline at end of file +module.exports = App; diff --git a/test/react/Reconciliation/key-nesting-7.js b/test/react/Reconciliation/key-nesting-7.js index 6fb29d61c..6ba33b108 100644 --- a/test/react/Reconciliation/key-nesting-7.js +++ b/test/react/Reconciliation/key-nesting-7.js @@ -1,5 +1,4 @@ -var React = require('react'); -this['React'] = React; +var React = require("react"); function Foo(props) { return [[
]]; @@ -31,10 +30,10 @@ App.getTrials = function(renderer, Root) { renderer.update(); renderer.update(); let results = []; - results.push(['ensure ref is called on every change', counter]); - results.push(['ensure refs are cleared', nodes.map(Boolean)]); - results.push(['ensure refs are different', new Set(nodes).size]); + results.push(["ensure ref is called on every change", counter]); + results.push(["ensure refs are cleared", nodes.map(Boolean)]); + results.push(["ensure refs are different", new Set(nodes).size]); return results; }; -module.exports = App; \ No newline at end of file +module.exports = App; diff --git a/test/react/Reconciliation/key-nesting-8.js b/test/react/Reconciliation/key-nesting-8.js index 02d72275b..02be8f46c 100644 --- a/test/react/Reconciliation/key-nesting-8.js +++ b/test/react/Reconciliation/key-nesting-8.js @@ -1,5 +1,4 @@ -var React = require('react'); -this['React'] = React; +var React = require("react"); function Foo(props) { return [
]; @@ -31,10 +30,10 @@ App.getTrials = function(renderer, Root) { renderer.update(); renderer.update(); let results = []; - results.push(['ensure ref is called on every change', counter]); - results.push(['ensure refs are cleared', nodes.map(Boolean)]); - results.push(['ensure refs are different', new Set(nodes).size]); + results.push(["ensure ref is called on every change", counter]); + results.push(["ensure refs are cleared", nodes.map(Boolean)]); + results.push(["ensure refs are different", new Set(nodes).size]); return results; }; -module.exports = App; \ No newline at end of file +module.exports = App;