Repository: prettier/prettier (JavaScript)
Date: 2023-05-03 08:50:13+00:00
Task type: Bug Fix

Issue:
--list-different logs errors after file path instead of in a new line
**Environments:**

- Prettier Version: 2.8.2
- Running Prettier via: CLI
- Operating System: all

**Steps to reproduce:**

create a index.js file with a syntax issue in it, then run:
```bash
npx prettier --list-different "./**/*.{js,jsx,ts,tsx,scss,json}"
```


**Actual behavior:**
the output will be:
```log
path/to/file/index.js[error] path/to/file/index.js: SyntaxError: Unexpected token, expected "," (5:1)
[error]   3 |
[error]   4 | console.log("test: create a js syntax error here"
[error] > 5 | export { test };
[error]     | ^
[error]   6 |
```

**Expected behavior:**
```log
path/to/file/index.js
[error] path/to/file/index.js: SyntaxError: Unexpected token, expected "," (5:1)
[error]   3 |
[error]   4 | console.log("test: create a js syntax error here"
[error] > 5 | export { test };
[error]     | ^
[error]   6 |
```
Also, it would be great to have a flag (e.g. `--no-error`) that will stop prettier from logging errors, and it will just log the file path, so the output will be:
```log
path/to/file/index.js
```


Issue discussion:
@fisker, @thorn0, @sosukesuzuki sorry for disturbing you, would you please have a look at this issue?

Solution patch:
diff --git a/changelog_unreleased/cli/14788.md b/changelog_unreleased/cli/14788.md
new file mode 100644
index 000000000000..d9c4a25910d9
--- /dev/null
+++ b/changelog_unreleased/cli/14788.md
@@ -0,0 +1,20 @@
+#### Print line breaking after file path with errors (#14788 by @sosukesuzuki)
+
+Previously, only the `--write` option printed a newline before the error, but other options and no options print a newline as well.
+
+<!-- prettier-ignore -->
+```sh
+# Input
+prettier ./test.js
+
+# Prettier stable
+test.js[error] test.js: SyntaxError: Unexpected token: ')' (1:6)
+[error] > 1 | 1 (+-) hoge
+[error]     |      ^
+
+# Prettier main
+test.js
+[error] test.js: SyntaxError: Unexpected token: ')' (1:6)
+[error] > 1 | 1 (+-) hoge
+[error]     |
+```
diff --git a/src/cli/format.js b/src/cli/format.js
index 3723232c5040..ca4809518b06 100644
--- a/src/cli/format.js
+++ b/src/cli/format.js
@@ -21,13 +21,24 @@ function diff(a, b) {
 class DebugError extends Error {}
 
 function handleError(context, filename, error, printedFilename) {
-  if (error instanceof errors.UndefinedParserError) {
+  const errorIsUndefinedParseError =
+    error instanceof errors.UndefinedParserError;
+
+  if (printedFilename) {
     // Can't test on CI, `isTTY()` is always false, see ./is-tty.js
     /* c8 ignore next 3 */
-    if ((context.argv.write || context.argv.ignoreUnknown) && printedFilename) {
+    if (
+      (context.argv.write || context.argv.ignoreUnknown) &&
+      errorIsUndefinedParseError
+    ) {
       printedFilename.clear();
+    } else {
+      // Add newline to split errors from filename line.
+      process.stdout.write("\n");
     }
+  }
 
+  if (errorIsUndefinedParseError) {
     if (context.argv.ignoreUnknown) {
       return;
     }
@@ -38,11 +49,6 @@ function handleError(context, filename, error, printedFilename) {
     return;
   }
 
-  if (context.argv.write) {
-    // Add newline to split errors from filename line.
-    process.stdout.write("\n");
-  }
-
   const isParseError = Boolean(error?.loc);
   const isValidationError = /^Invalid \S+ value\./.test(error?.message);
 


Test patch:
diff --git a/tests/integration/__tests__/__snapshots__/line-after-filepath-with-errors.js.snap b/tests/integration/__tests__/__snapshots__/line-after-filepath-with-errors.js.snap
new file mode 100644
index 000000000000..1571cd02c9e9
--- /dev/null
+++ b/tests/integration/__tests__/__snapshots__/line-after-filepath-with-errors.js.snap
@@ -0,0 +1,85 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Line breaking after filepath with errors (stderr) 1`] = `
+"[error] invalid-1.js: SyntaxError: Unexpected token (1:8)
+[error] > 1 | foo (+-) bar
+[error]     |        ^
+[error]   2 |
+[error] invalid-2.js: SyntaxError: Unexpected token (1:8)
+[error] > 1 | foo (+-) bar
+[error]     |        ^
+[error]   2 |
+[error] No parser could be inferred for file "<cli>/syntax-errors/invalid-2.unknown"."
+`;
+
+exports[`Line breaking after filepath with errors (stderr) 2`] = `
+"[error] invalid-1.js: SyntaxError: Unexpected token (1:8)
+[error] > 1 | foo (+-) bar
+[error]     |        ^
+[error]   2 |
+[error] invalid-2.js: SyntaxError: Unexpected token (1:8)
+[error] > 1 | foo (+-) bar
+[error]     |        ^
+[error]   2 |
+[error] No parser could be inferred for file "<cli>/syntax-errors/invalid-2.unknown"."
+`;
+
+exports[`Line breaking after filepath with errors (stderr) 3`] = `
+"[error] invalid-1.js: SyntaxError: Unexpected token (1:8)
+[error] > 1 | foo (+-) bar
+[error]     |        ^
+[error]   2 |
+[error] invalid-2.js: SyntaxError: Unexpected token (1:8)
+[error] > 1 | foo (+-) bar
+[error]     |        ^
+[error]   2 |
+[error] No parser could be inferred for file "<cli>/syntax-errors/invalid-2.unknown"."
+`;
+
+exports[`Line breaking after filepath with errors (stderr) 4`] = `
+"[error] invalid-1.js: SyntaxError: Unexpected token (1:8)
+[error] > 1 | foo (+-) bar
+[error]     |        ^
+[error]   2 |
+[error] invalid-2.js: SyntaxError: Unexpected token (1:8)
+[error] > 1 | foo (+-) bar
+[error]     |        ^
+[error]   2 |
+[error] No parser could be inferred for file "<cli>/syntax-errors/invalid-2.unknown"."
+`;
+
+exports[`Line breaking after filepath with errors (stdout) 1`] = `
+"invalid-1.js
+invalid-2.js
+invalid-2.unknown
+valid-1.jsfunction foo() {}"
+`;
+
+exports[`Line breaking after filepath with errors (stdout) 2`] = `
+"invalid-1.js
+invalid-2.js
+invalid-2.unknown
+valid-1.js"
+`;
+
+exports[`Line breaking after filepath with errors (stdout) 3`] = `
+"Checking formatting...
+invalid-1.js
+invalid-2.js
+invalid-2.unknown
+valid-1.jsAll matched files use Prettier code style!"
+`;
+
+exports[`Line breaking after filepath with errors (stdout) 4`] = `
+"invalid-1.js
+invalid-2.js
+invalid-2.unknownvalid-1.jsvalid-1.js 0ms"
+`;
+
+exports[`Line breaking after filepath with errors (write) 1`] = `[]`;
+
+exports[`Line breaking after filepath with errors (write) 2`] = `[]`;
+
+exports[`Line breaking after filepath with errors (write) 3`] = `[]`;
+
+exports[`Line breaking after filepath with errors (write) 4`] = `[]`;
diff --git a/tests/integration/__tests__/line-after-filepath-with-errors.js b/tests/integration/__tests__/line-after-filepath-with-errors.js
new file mode 100644
index 000000000000..3f7dacaad3fb
--- /dev/null
+++ b/tests/integration/__tests__/line-after-filepath-with-errors.js
@@ -0,0 +1,18 @@
+import jestPathSerializer from "../path-serializer.js";
+
+expect.addSnapshotSerializer(jestPathSerializer);
+
+describe("Line breaking after filepath with errors", () => {
+  runCli("cli/syntax-errors", ["./*.{js,unknown}"], {
+    stdoutIsTTY: true,
+  }).test({ status: 2 });
+  runCli("cli/syntax-errors", ["--list-different", "./*.{js,unknown}"], {
+    stdoutIsTTY: true,
+  }).test({ status: 2 });
+  runCli("cli/syntax-errors", ["--check", "./*.{js,unknown}"], {
+    stdoutIsTTY: true,
+  }).test({ status: 2 });
+  runCli("cli/syntax-errors", ["--write", "./*.{js,unknown}"], {
+    stdoutIsTTY: true,
+  }).test({ status: 2 });
+});
diff --git a/tests/integration/cli/syntax-errors/invalid-1.js b/tests/integration/cli/syntax-errors/invalid-1.js
new file mode 100644
index 000000000000..fe569e81405a
--- /dev/null
+++ b/tests/integration/cli/syntax-errors/invalid-1.js
@@ -0,0 +1,1 @@
+foo (+-) bar
diff --git a/tests/integration/cli/syntax-errors/invalid-2.js b/tests/integration/cli/syntax-errors/invalid-2.js
new file mode 100644
index 000000000000..fe569e81405a
--- /dev/null
+++ b/tests/integration/cli/syntax-errors/invalid-2.js
@@ -0,0 +1,1 @@
+foo (+-) bar
diff --git a/tests/integration/cli/syntax-errors/invalid-2.unknown b/tests/integration/cli/syntax-errors/invalid-2.unknown
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/tests/integration/cli/syntax-errors/valid-1.js b/tests/integration/cli/syntax-errors/valid-1.js
new file mode 100644
index 000000000000..b0400ee9b26e
--- /dev/null
+++ b/tests/integration/cli/syntax-errors/valid-1.js
@@ -0,0 +1,1 @@
+function foo() {}