diff --git a/README.md b/README.md index 0958e3d3..81a84327 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ Pinterest. - [ESLint](#eslint) - [Go Vet](#go-vet) - [Prettier](#prettier) +- [Prettier ESLint](#prettier-eslint) - [Python Imports](#python-imports) - [Python isort](#python-isort) - [Python Requirements](#python-requirements) @@ -85,6 +86,17 @@ Lints JavaScript and JSX files using [ESLint](https://eslint.org/). } ``` +### Go Vet + +Uses the [Go vet command](https://golang.org/cmd/vet/) to lint for suspicious +code constructs. + +```json +{ + "type": "govet", + "include": "(^src/example.com/.*\\.go$)" +} +``` ### Prettier @@ -99,15 +111,17 @@ Formats JavaScript using [Prettier](https://prettier.io/). } ``` -### Go Vet -Uses the [Go vet command](https://golang.org/cmd/vet/) to lint for suspicious -code constructs. +### Prettier ESLint + +Formats JavaScript using [Prettier](https://prettier.io/) and then fixes with [ESLint](https://eslint.org/). ```json { - "type": "govet", - "include": "(^src/example.com/.*\\.go$)" + "type": "prettier-eslint", + "include": "(\\.js$)", + "bin": "./node_modules/.bin/prettier-eslint", + "prettier-eslint.cwd": "./" } ``` diff --git a/__phutil_library_map__.php b/__phutil_library_map__.php index 90e4b1c4..edd92798 100644 --- a/__phutil_library_map__.php +++ b/__phutil_library_map__.php @@ -11,10 +11,11 @@ 'class' => array( 'ApacheThriftGeneratedLinter' => 'src/ApacheThriftGeneratedLinter.php', 'ApacheThriftLinter' => 'src/ApacheThriftLinter.php', - 'PrettierLinter' => 'src/PrettierLinter.php', 'CheckstyleLinter' => 'src/CheckstyleLinter.php', 'ESLintLinter' => 'src/ESLintLinter.php', 'GoVetLinter' => 'src/GoVetLinter.php', + 'PrettierESLintLinter' => 'src/PrettierESLintLinter.php', + 'PrettierLinter' => 'src/PrettierLinter.php', 'PythonImportsLinter' => 'src/PythonImportsLinter.php', 'PythonIsortLinter' => 'src/PythonIsortLinter.php', 'PythonRequirementsLinter' => 'src/PythonRequirementsLinter.php', @@ -23,10 +24,11 @@ 'xmap' => array( 'ApacheThriftGeneratedLinter' => 'ArcanistLinter', 'ApacheThriftLinter' => 'ArcanistExternalLinter', - 'PrettierLinter' => 'ArcanistExternalLinter', 'CheckstyleLinter' => 'ArcanistExternalLinter', 'ESLintLinter' => 'ArcanistExternalLinter', 'GoVetLinter' => 'ArcanistExternalLinter', + 'PrettierESLintLinter' => 'ArcanistExternalLinter', + 'PrettierLinter' => 'ArcanistExternalLinter', 'PythonImportsLinter' => 'ArcanistLinter', 'PythonIsortLinter' => 'ArcanistExternalLinter', 'PythonRequirementsLinter' => 'ArcanistLinter', diff --git a/src/PrettierESLintLinter.php b/src/PrettierESLintLinter.php new file mode 100644 index 00000000..f62aad6f --- /dev/null +++ b/src/PrettierESLintLinter.php @@ -0,0 +1,151 @@ +getProjectRoot() . '/' . $this->cwd); + $binaryPath = strtok($stdout, "\n"); + if (!empty($stderr)) { + // Copied from arcanist/master/src/lint/linter/ArcanistExternalLinter.php + throw new ArcanistMissingLinterException( + sprintf( + "%s\n%s", + pht( + 'Unable to locate script "%s" to run linter %s. You may need '. + 'to install the script, or adjust your linter configuration.', + 'yarn@1', + get_class($this)), + pht( + 'TO INSTALL: %s', + $this->getInstallInstructions()))); + } + return $binaryPath; + } + + public function getVersion() { + list($err, $stdout, $stderr) = exec_manual('%C -v', $this->getExecutableCommand()); + return $stdout; + } + + protected function getMandatoryFlags() { + return array( + '--log-level=silent', + ); + } + + public function getLinterConfigurationOptions() { + $options = array( + 'prettier-eslint.cwd' => array( + 'type' => 'optional string', + 'help' => pht('Specify a project sub-directory for both the local prettier-eslint-cli install and the sub-directory to lint within.'), + ), + ); + return $options + parent::getLinterConfigurationOptions(); + } + + public function setLinterConfigurationValue($key, $value) { + switch ($key) { + case 'prettier-eslint.cwd': + $this->cwd = $value; + return; + } + return parent::setLinterConfigurationValue($key, $value); + } + + public function getInstallInstructions() { + return pht( + 'run `%s` to install yarn@1 globally (needed for specifying --cwd & `yarn which`), and `%s` to add prettier-eslint-cli to your project (configurable at prettier-eslint.cwd).', + 'npm install --global yarn@1', + 'yarn add --dev prettier-eslint-cli' + ); + } + + protected function parseLinterOutput($path, $err, $stdout, $stderr) { + if ($err) { + return false; + } + + $originalText = $this->getData($path); + $messages = array(); + + // Note: $stdout is empty for ignored files + if ($stdout && $stdout != $originalText) { + $message = new ArcanistLintMessage(); + $message->setPath($path); + $message->setSeverity(ArcanistLintSeverity::SEVERITY_AUTOFIX); + $message->setName('Prettier-Eslint Format'); + $message->setLine(1); + $message->setCode($this->getLinterName()); + $message->setChar(1); + $message->setDescription('Your file has not been prettier-eslint-ified'); + $message->setOriginalText($originalText); + $message->setReplacementText($stdout); + $messages[] = $message; + } + + return $messages; + } +} diff --git a/src/node4_proxy b/src/node4_proxy new file mode 100755 index 00000000..f3b9b7d0 --- /dev/null +++ b/src/node4_proxy @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +node --harmony_array_includes "$@"