Repository: prettier/prettier (JavaScript) — Bug Fix

Issue:
.prettierignore displays no output when running on ignored file breaking editor integrations
This may seem at first glance the ideal behaviour, when trying to run the prettie CLI on an ignored file. However for editor integrations such as `vim-prettier` where it does not have any knowledge about the ignored files from `.prettierignore` it means it will then wipe all the contents of the ignored file.  

see https://github.com/prettier/vim-prettier/issues/92

Would be great if there was an `option` or any other way to simply print the ignored file as it is instead of just having an empty `stdout`, other valid options would be display an error or warning message.

@ikatyang, @azz, @suchipi  please let me know what are your thoughts around it, happy to submit a PR for this


Discussion:
Sounds reasonable to me to warn if the use passed a specific path (i.e. not a glob) of an ignored file
I think adding a warning (only when `--stdin-filepath` applied) for it should be better, but I'm not sure if it can fix your case since IIRC you seem to use `--loglevel silent` for `vim-prettier`?
This sounds like a bug.

```bash
echo "foo()" > foo.js
echo "foo.js" > .prettierignore
prettier --stdin-filepath=foo.js < foo.js
```

Should output the contents of `foo.js`.

Edit: Not limited to stdin.

```bash
echo "foo()" > foo.js
echo "foo.js" > .prettierignore
prettier foo.js
```

Maybe this should output `foo.js` untouched too? 
So basically we want two modes:

* With `--write`, don't read or write to the ignored file
* Without `--write`, read the ignored file and output as-is.
@azz  I really like your approach!

I think `Without --write, read the ignored file and output as-is.` is exactly what we need for `vim-prettier`  

Resolving patch:
diff --git a/src/cli/util.js b/src/cli/util.js
index 1ac7f526cf77..5d7172fb6a3d 100644
--- a/src/cli/util.js
+++ b/src/cli/util.js
@@ -242,11 +242,12 @@ function formatStdin(argv) {
   const ignorer = createIgnorer(argv);
   const relativeFilepath = path.relative(process.cwd(), filepath);
 
-  if (relativeFilepath && ignorer.filter([relativeFilepath]).length === 0) {
-    return;
-  }
-
   thirdParty.getStream(process.stdin).then(input => {
+    if (relativeFilepath && ignorer.filter([relativeFilepath]).length === 0) {
+      writeOutput({ formatted: input }, {});
+      return;
+    }
+
     const options = getOptionsForFile(argv, filepath);
 
     if (listDifferent(argv, input, options, "(stdin)")) {
@@ -279,10 +280,6 @@ function createIgnorer(argv) {
 
 function eachFilename(argv, patterns, callback) {
   const ignoreNodeModules = argv["with-node-modules"] === false;
-  // The ignorer will be used to filter file paths after the glob is checked,
-  // before any files are actually read
-  const ignorer = createIgnorer(argv);
-
   if (ignoreNodeModules) {
     patterns = patterns.concat(["!**/node_modules/**", "!./node_modules/**"]);
   }
@@ -297,11 +294,9 @@ function eachFilename(argv, patterns, callback) {
       process.exitCode = 2;
       return;
     }
-    ignorer
-      .filter(filePaths)
-      .forEach(filePath =>
-        callback(filePath, getOptionsForFile(argv, filePath))
-      );
+    filePaths.forEach(filePath =>
+      callback(filePath, getOptionsForFile(argv, filePath))
+    );
   } catch (error) {
     logger.error(
       `Unable to expand glob patterns: ${patterns.join(" ")}\n${error.message}`
@@ -312,7 +307,16 @@ function eachFilename(argv, patterns, callback) {
 }
 
 function formatFiles(argv) {
+  // The ignorer will be used to filter file paths after the glob is checked,
+  // before any files are actually written
+  const ignorer = createIgnorer(argv);
+
   eachFilename(argv, argv.__filePatterns, (filename, options) => {
+    const fileIgnored = ignorer.filter([filename]).length === 0;
+    if (fileIgnored && (argv["write"] || argv["list-different"])) {
+      return;
+    }
+
     if (argv["write"] && process.stdout.isTTY) {
       // Don't use `console.log` here since we need to replace this line.
       logger.log(filename, { newline: false });
@@ -331,6 +335,11 @@ function formatFiles(argv) {
       return;
     }
 
+    if (fileIgnored) {
+      writeOutput({ formatted: input }, options);
+      return;
+    }
+
     listDifferent(argv, input, options, filename);
 
     const start = Date.now();


Test patch:
diff --git a/tests_integration/__tests__/__snapshots__/ignore-path.js.snap b/tests_integration/__tests__/__snapshots__/ignore-path.js.snap
index 32cd5821d0dc..11e9966c1696 100644
--- a/tests_integration/__tests__/__snapshots__/ignore-path.js.snap
+++ b/tests_integration/__tests__/__snapshots__/ignore-path.js.snap
@@ -9,6 +9,15 @@ exports[`ignore path (stdout) 1`] = `
 
 exports[`ignore path (write) 1`] = `Array []`;
 
+exports[`outputs files as-is if no --write (stderr) 1`] = `""`;
+
+exports[`outputs files as-is if no --write (stdout) 1`] = `
+"'use strict';
+"
+`;
+
+exports[`outputs files as-is if no --write (write) 1`] = `Array []`;
+
 exports[`support .prettierignore (stderr) 1`] = `""`;
 
 exports[`support .prettierignore (stdout) 1`] = `
diff --git a/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap b/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap
index fe293fe93f30..eded2d6a4374 100644
--- a/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap
+++ b/tests_integration/__tests__/__snapshots__/stdin-filepath.js.snap
@@ -11,9 +11,9 @@ 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[`output nothing if stdin-filepath matched patterns in ignore-path (stderr) 1`] = `""`;
+exports[`output file as-is if stdin-filepath matched patterns in ignore-path (stderr) 1`] = `""`;
 
-exports[`output nothing if stdin-filepath matched patterns in ignore-path (write) 1`] = `Array []`;
+exports[`output file as-is if stdin-filepath matched patterns in ignore-path (write) 1`] = `Array []`;
 
 exports[`throw error if stdin content incompatible with stdin-filepath (stderr) 1`] = `
 "[error] stdin: SyntaxError: Unexpected token (1:1)
diff --git a/tests_integration/__tests__/ignore-path.js b/tests_integration/__tests__/ignore-path.js
index f6a4936390df..ce5d1aa2c41e 100644
--- a/tests_integration/__tests__/ignore-path.js
+++ b/tests_integration/__tests__/ignore-path.js
@@ -18,3 +18,9 @@ describe("support .prettierignore", () => {
     status: 1
   });
 });
+
+describe("outputs files as-is if no --write", () => {
+  runPrettier("cli/ignore-path", ["regular-module.js"]).test({
+    status: 0
+  });
+});
diff --git a/tests_integration/__tests__/stdin-filepath.js b/tests_integration/__tests__/stdin-filepath.js
index 19037daa1678..bc01b90c8d1d 100644
--- a/tests_integration/__tests__/stdin-filepath.js
+++ b/tests_integration/__tests__/stdin-filepath.js
@@ -22,11 +22,11 @@ describe("throw error if stdin content incompatible with stdin-filepath", () =>
   });
 });
 
-describe("output nothing if stdin-filepath matched patterns in ignore-path", () => {
+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();"
+    input: "hello_world( );"
   }).test({
-    stdout: "",
+    stdout: "hello_world( );",
     status: 0
   });
 });