diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index bd578028..e4ade133 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -1317,6 +1317,20 @@ $ prettier --parser babel < test.js [error] Invalid printWidth value. Expected an integer, but received "nope". ``` +#### CLI: Gracefully handle nonexistent paths passed to --stdin-filepath ([#6687] by [@voithos]) + +Previously, if you passed a nonexistent subdirectory to --stdin-filepath, Prettier would throw an error. Now, Prettier gracefully handles this. + +``` +# Prettier stable +$ prettier --stdin-filepath does/not/exist.js < test.js +[error] Invalid configuration file: ENOENT: no such file or directory, scandir '/home/lydell/forks/prettier/does/not' + +# Prettier master +$ prettier --stdin-filepath does/not/exist.js < test.js +test; +``` + [#5682]: https://github.com/prettier/prettier/pull/5682 [#6657]: https://github.com/prettier/prettier/pull/6657 [#5910]: https://github.com/prettier/prettier/pull/5910 @@ -1362,6 +1376,7 @@ $ prettier --parser babel < test.js [#6717]: https://github.com/prettier/prettier/pull/6717 [#6728]: https://github.com/prettier/prettier/pull/6728 [#6708]: https://github.com/prettier/prettier/pull/6708 +[#6687]: https://github.com/prettier/prettier/pull/6687 [@brainkim]: https://github.com/brainkim [@duailibe]: https://github.com/duailibe [@gavinjoyce]: https://github.com/gavinjoyce diff --git a/cspell.json b/cspell.json index dddb81ae..b57e67be 100644 --- a/cspell.json +++ b/cspell.json @@ -91,6 +91,7 @@ "editorconfig", "ekkhus", "elektronik", + "ENOENT", "Eneman", "ericsakmar", "Ericsburgh", @@ -303,6 +304,7 @@ "ruleset", "Sapegin", "sbdchd", + "scandir", "schemastore", "serializer", "setlocal", @@ -393,4 +395,4 @@ "\\[`\\w+`\\]", "ve+r+y+(long\\w+)?" ] -} \ No newline at end of file +} diff --git a/src/config/resolve-config-editorconfig.js b/src/config/resolve-config-editorconfig.js index 07c20925..deab857d 100644 --- a/src/config/resolve-config-editorconfig.js +++ b/src/config/resolve-config-editorconfig.js @@ -1,5 +1,6 @@ "use strict"; +const fs = require("fs"); const path = require("path"); const editorconfig = require("editorconfig"); @@ -8,7 +9,16 @@ const editorConfigToPrettier = require("editorconfig-to-prettier"); const findProjectRoot = require("find-project-root"); const maybeParse = (filePath, config, parse) => { - const root = findProjectRoot(path.dirname(path.resolve(filePath))); + // findProjectRoot will throw an error if we pass a nonexistent directory to + // it, which is possible, for example, when the path is given via + // --stdin-filepath. So, first, traverse up until we find an existing + // directory. + let dirPath = path.dirname(path.resolve(filePath)); + const fsRoot = path.parse(dirPath).root; + while (dirPath !== fsRoot && !fs.existsSync(dirPath)) { + dirPath = path.dirname(dirPath); + } + const root = findProjectRoot(dirPath); return filePath && parse(filePath, { root }); }; diff --git a/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap b/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap index a109655c..2f065a2b 100644 --- a/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap +++ b/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap @@ -1,5 +1,38 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`apply editorconfig for stdin-filepath with nonexistent directory (stderr) 1`] = `""`; + +exports[`apply editorconfig for stdin-filepath with nonexistent directory (stdout) 1`] = ` +"function f() { + console.log(\\"should be indented with a tab\\") +} +" +`; + +exports[`apply editorconfig for stdin-filepath with nonexistent directory (write) 1`] = `Array []`; + +exports[`apply editorconfig for stdin-filepath with nonexistent file (stderr) 1`] = `""`; + +exports[`apply editorconfig for stdin-filepath with nonexistent file (stdout) 1`] = ` +"function f() { + console.log(\\"should be indented with a tab\\") +} +" +`; + +exports[`apply editorconfig for stdin-filepath with nonexistent file (write) 1`] = `Array []`; + +exports[`don’t apply editorconfig outside project for stdin-filepath with nonexistent directory (stderr) 1`] = `""`; + +exports[`don’t apply editorconfig outside project for stdin-filepath with nonexistent directory (stdout) 1`] = ` +"function f() { + console.log(\\"should be indented with 2 spaces\\") +} +" +`; + +exports[`don’t apply editorconfig outside project for stdin-filepath with nonexistent directory (write) 1`] = `Array []`; + exports[`format correctly if stdin content compatible with stdin-filepath (stderr) 1`] = `""`; exports[`format correctly if stdin content compatible with stdin-filepath (stdout) 1`] = ` @@ -11,6 +44,17 @@ exports[`format correctly if stdin content compatible with stdin-filepath (stdou exports[`format correctly if stdin content compatible with stdin-filepath (write) 1`] = `Array []`; +exports[`gracefully handle stdin-filepath with nonexistent directory (stderr) 1`] = `""`; + +exports[`gracefully handle stdin-filepath with nonexistent directory (stdout) 1`] = ` +".name { + display: none; +} +" +`; + +exports[`gracefully handle stdin-filepath with nonexistent directory (write) 1`] = `Array []`; + exports[`output file as-is if stdin-filepath matched patterns in ignore-path (stderr) 1`] = `""`; exports[`output file as-is if stdin-filepath matched patterns in ignore-path (write) 1`] = `Array []`; diff --git a/tests_integration/__tests__/stdin-filepath.js b/tests_integration/__tests__/stdin-filepath.js index bc01b90c..983b6a64 100644 --- a/tests_integration/__tests__/stdin-filepath.js +++ b/tests_integration/__tests__/stdin-filepath.js @@ -22,6 +22,67 @@ describe("throw error if stdin content incompatible with stdin-filepath", () => }); }); +describe("gracefully handle stdin-filepath with nonexistent directory", () => { + runPrettier( + "cli", + ["--stdin-filepath", "definitely/nonexistent/path.css"], + { input: ".name { display: none; }" } // css + ).test({ + status: 0 + }); +}); + +describe("apply editorconfig for stdin-filepath with nonexistent file", () => { + runPrettier( + "cli", + ["--stdin-filepath", "config/editorconfig/nonexistent.js"], + { + input: ` +function f() { + console.log("should be indented with a tab"); +} +`.trim() // js + } + ).test({ + status: 0 + }); +}); + +describe("apply editorconfig for stdin-filepath with nonexistent directory", () => { + runPrettier( + "cli", + ["--stdin-filepath", "config/editorconfig/nonexistent/one/two/three.js"], + { + input: ` +function f() { + console.log("should be indented with a tab"); +} +`.trim() // js + } + ).test({ + status: 0 + }); +}); + +describe("don’t apply editorconfig outside project for stdin-filepath with nonexistent directory", () => { + runPrettier( + "cli", + [ + "--stdin-filepath", + "config/editorconfig/repo-root/nonexistent/one/two/three.js" + ], + { + input: ` +function f() { + console.log("should be indented with 2 spaces"); +} +`.trim() // js + } + ).test({ + status: 0 + }); +}); + describe("output file as-is if stdin-filepath matched patterns in ignore-path", () => { runPrettier("cli/stdin-ignore", ["--stdin-filepath", "ignore/example.js"], { input: "hello_world( );"