Repository: prettier/prettier (JavaScript)
Date: 2021-02-16 14:25:05+00:00
Task type: Bug Fix

Issue:
Bug with no-semi, private fields and computed method
<!--

BEFORE SUBMITTING AN ISSUE:

1.  Search for your issue on GitHub: https://github.com/prettier/prettier/issues
    A large number of opened issues are duplicates of existing issues.
    If someone has already opened an issue for what you are experiencing,
    you do not need to open a new issue — please add a 👍 reaction to the
    existing issue instead.

2.  We get a lot of requests for adding options, but Prettier is
    built on the principle of being opinionated about code formatting.
    This means we have a very high bar for adding new options.
    Find out more: https://prettier.io/docs/en/option-philosophy.html

Tip! Don't write this stuff manually.

1. Go to https://prettier.io/playground
2. Paste your code and set options
3. Press the "Report issue" button in the lower right

-->

**Prettier 2.2.1**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAucAbAhgZ0wAgMI7AA6UOOAxAGYCWcqAJjgLw4DkAbuqgK5yslkA2kRABbODAAWEeiIC6ACgCUhAL4l1UEABoQEAA4xq0TMlDoAThYgB3AAqWEplFxvoAnqd0AjC+jAA1hIAyvr+1FAA5sgwFry6cKLecPT0KQAy6FHc6JFwAGIQFqLoMEZRyCDo3DAQOiCSMKKoAOqS1PCYYWBwwU4d1Owd7pVg2PURmHAWMHZ+kSXIlFxTugBWmAAeAEJ+gSHo4ukRcEsrcOtbwRGRqHAAitwQ8GeoqyBhFlMWld7oyah6voLBEYC1qPQpMgABwABl0wIgUxafn0lWBcG+7FOugAjk94HMDM4qpgALRQOApFL1CxwfHUOlzXKLJDLN4XEBTUTUV7vTA3O6PZ6nNnnXQwf7gyGSZAAJglfmoqBueAgolZIExAFZ6twpgAVf7Odnvdi8ACSUDSsGCYBBhgAgtbgjB3Hc+XBVKogA)

```sh
--no-semi
```

**Input:**

```jsx
class C {
  #field = 'value';
  ["method"]() {}
}
```

**Output:**

```jsx
class C {
  #field = "value"
  ["method"]() {}
}
```

**Expected behavior:**

```jsx
class C {
  #field = "value"
  ;["method"]() {}
}
```

Without the semi-colon, the code is no longer valid.


Issue discussion:

Solution patch:
diff --git a/changelog_unreleased/javascript/10334.md b/changelog_unreleased/javascript/10334.md
new file mode 100644
index 000000000000..8d41c6fe8421
--- /dev/null
+++ b/changelog_unreleased/javascript/10334.md
@@ -0,0 +1,22 @@
+#### Fix ASI protection for private fields (#10334 by @thorn0)
+
+<!-- prettier-ignore -->
+```jsx
+// Input
+class C {
+  #field = 'value';
+  ["method"]() {}
+}
+
+// Prettier stable (with --no-semi)
+class C {
+  #field = "value"
+  ["method"]() {}
+}
+
+// Prettier main (with --no-semi)
+class C {
+  #field = "value";
+  ["method"]() {}
+}
+```
diff --git a/src/language-js/print/statement.js b/src/language-js/print/statement.js
index cc70d2f38adc..24f5cdbc7118 100644
--- a/src/language-js/print/statement.js
+++ b/src/language-js/print/statement.js
@@ -59,7 +59,8 @@ function printStatementSequence(path, options, print, property) {
         parts.push(";");
       } else if (
         node.type === "ClassProperty" ||
-        node.type === "PropertyDefinition"
+        node.type === "PropertyDefinition" ||
+        node.type === "ClassPrivateProperty"
       ) {
         // `ClassBody` don't allow `EmptyStatement`,
         // so we can use `statements` to get next node


Test patch:
diff --git a/tests/js/no-semi/__snapshots__/jsfmt.spec.js.snap b/tests/js/no-semi/__snapshots__/jsfmt.spec.js.snap
index 609486589aa0..5435656fc172 100644
--- a/tests/js/no-semi/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/js/no-semi/__snapshots__/jsfmt.spec.js.snap
@@ -1007,3 +1007,64 @@ aReallyLongLine012345678901234567890123456789012345678901234567890123456789 *
 
 ================================================================================
 `;
+
+exports[`private-field.js [espree] format 1`] = `
+"Unexpected character '#' (2:3)
+  1 | class C {
+> 2 |   #field = 'value';
+    |   ^
+  3 |   [\\"method\\"]() {}
+  4 | }
+  5 |"
+`;
+
+exports[`private-field.js - {"semi":false} [espree] format 1`] = `
+"Unexpected character '#' (2:3)
+  1 | class C {
+> 2 |   #field = 'value';
+    |   ^
+  3 |   [\\"method\\"]() {}
+  4 | }
+  5 |"
+`;
+
+exports[`private-field.js - {"semi":false} format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow"]
+printWidth: 80
+semi: false
+                                                                                | printWidth
+=====================================input======================================
+class C {
+  #field = 'value';
+  ["method"]() {}
+}
+
+=====================================output=====================================
+class C {
+  #field = "value";
+  ["method"]() {}
+}
+
+================================================================================
+`;
+
+exports[`private-field.js format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow"]
+printWidth: 80
+                                                                                | printWidth
+=====================================input======================================
+class C {
+  #field = 'value';
+  ["method"]() {}
+}
+
+=====================================output=====================================
+class C {
+  #field = "value";
+  ["method"]() {}
+}
+
+================================================================================
+`;
diff --git a/tests/js/no-semi/jsfmt.spec.js b/tests/js/no-semi/jsfmt.spec.js
index 98d0477a5ebf..c5222b708f1f 100644
--- a/tests/js/no-semi/jsfmt.spec.js
+++ b/tests/js/no-semi/jsfmt.spec.js
@@ -1,4 +1,4 @@
-const errors = { espree: ["class.js"] };
+const errors = { espree: ["class.js", "private-field.js"] };
 
 run_spec(__dirname, ["babel", "flow"], { errors });
 run_spec(__dirname, ["babel", "flow"], { semi: false, errors });
diff --git a/tests/js/no-semi/private-field.js b/tests/js/no-semi/private-field.js
new file mode 100644
index 000000000000..feca225a4937
--- /dev/null
+++ b/tests/js/no-semi/private-field.js
@@ -0,0 +1,4 @@
+class C {
+  #field = 'value';
+  ["method"]() {}
+}