Repository: prettier/prettier (JavaScript)

Issue:
Prettier infinitely suggests additional " ;" to the end of less detached rulesets
**Prettier 2.3.2**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuEABAbgQwE4EtMBGANnEgATAA6UZZAZrnEQCbkDOEAtnDABa5QA5tQC+AbhAAaEBAAOMXNDbJQObBADuABRwJlKTEQ2YAnsukFsmMAGseAZUzcAMgLjI6htnAtXbD2WsBQWQYbABXHxA4TgI4ZmZ450whcMxBOAAxCGxOTBgFIWQQTHCYCCkQXhhOIgB1fng2QLA4ez1cBXROk2KwNnMQAW9sGC0rQTyPLyiAKzYAD3tgkgBFcIh4aaJvaUDsEeKSAcrZPFg63GY+ZAAOAAY99W86q1lis7gR9HdpAEcNvBxnJ9CU2ABaKBweLxSrYOAA3Dw8bpKZITw7KLeTi4UIRLErODrTbudEzaQwQiXa68ZAAJgpVlwRGCAGEuGjomwAKyVcLeAAqhH0GN2IHQkQAklBErB7GA8PIAIIy+wwEwkbZi+YLABCfjsMEcLjcWrgIhEQA)
<!-- prettier-ignore -->
```sh
--parser less
```

**Input:**
<!-- prettier-ignore -->
```less
@variable: {
  field: something;
};
```

**Output:**
<!-- prettier-ignore -->
```less
@variable: {
  field: something;
}; ;

```

(If you test it out in the playground, another space + semicolon are always added, no matter how many are in the "input")

**Expected behavior:**
I would expect `prettier` to be satisfied with zero or one semicolon, not always suggest another. See [detached rulesets docs](https://lesscss.org/features/#detached-rulesets-feature).




Hints:
the problem is only with the last LESS ruleset: https://prettier.io/playground/#N4Igxg9gdgLgprEAuEABAHkgBMAOlAXwG58Ns9CSoyd9j8QAaECABxgEtoBnZUAQwBOgiAHcACkIS8U-ADaj+AT17MARoP5gA1nBgBlfgFs4AGQ5Q4yAGbzucdZp179rLRYDmyGIICuDkDgjNTgAE1Cw034oD19+DzgAMQhBI34YThjkEH5fGAgmEAALGCM5AHUijnhuNzA4fWlqjgA3aqVssG5VEAt7QRhxTQ80mzsAgCtudH1POTgARV8IeDG5e2Y3QX7s+e7C1kELGHKOUJgi5AAOAAZNkXtyzVZsw7h+lqtmAEdl+CG2DIctwALSWMJhQqCOC-DjQobxUZIWzrAL2Iwcbx+NFzOAAQQyRzUeTg4jggnMljWGxA3FxSxWVmR42YMH4alO50uSAATKzNBw5J4AMIQIxIwLcACshV89gAKuyZCiaS1-ABJKARWD6MBHdh4rX6GBKebUybTABCTl0BmMZgsTJVcAIBCAA

maybe caused by https://github.com/prettier/prettier/pull/5353

and https://github.com/prettier/prettier/issues/12540 slightly semicolon related issue for JS

I would appretiate any help as this issue is making the prettier output unstable and prettier impossible to be used CI.
~It seems the problem is in the `postcss` parser - https://github.com/postcss/postcss/issues/1806~

UPDATE: I did a research (and debugging on `node_modules/postcss/lib/parser.js`) and I belive the problem is here

here is a https://prettier.io/playground/#N4Igxg9gdgLgprEAuEABAbgQwE4EtMBGANnAIxIAEwAOlBRQGa5xEAmlAzhALZwwAWuKAHMA3LQC+4qLQw58xOACZKNOo2ZtOPPoJHSptEABoQEAA4xc0DslA5sEAO4AFHAlspMRJ5gCetqYE2JhgANZ8AMqYvAAyQnDIDN4ccEEh4VHmoULCyDDYAK5pIHDcBHCsrJWxmCKFmMJwAGIQ2NyYMFYiyCCYhTAQJiD8MNxEAOqC8BzZYHCRHrhW6Mt+vWAcgSBCqdgwLiHCHUkpJQBWHAAekbkkAIqFEPCnRKmm2dh7vSRbw+Z4WATXCsATIAAcAAYPo5UhMQuZegC4Ht0IlTABHJ7wQ4WTx9DgAWigcEqlWG2DgWNwlMOjROSGSbxKqW4uHyRRZdzgAEEungCAM4C44Nh4iTXu8QBxuY9nolGWdTDBCMDQfxkEplSFcERcgBhHgM0ocACsw0KqQAKoRPEypehigBJKDVWCRMB4Sw812RGB+EiSuASCRAA playground that helps to explain it

AST dump (to see the `raws` content, click `**` in the playground AST dump):
```
{
  "raws": {
    "semicolon": false,
    "after": ";\n"
  },
  "type": "css-root",
  "nodes": [
    {
      "raws": {
        "before": "",
        "between": " ",
        "afterName": ":",
        "semicolon": true,
        "after": "\n",
        "value": "",
        "params": ":"
      },
      "type": "css-atrule",
      "name": "variable1",
      "source": {
        "start": {
          "line": 1,
          "column": 1
        },
        "input": {
          "css": "@variable1: {\n  field: something;\n};\n\n@variable2: {\n  field: something;\n};\n",
          "hasBOM": false,
          "id": "<input css 2>"
        },
        "end": {
          "line": 3,
          "column": 1
        },
        "startOffset": 0,
        "endOffset": 35
      },
      "nodes": [
        {
          ...
        }
      ],
      "variable": true,
      "value": ""
    },
    {
      "raws": {
        "before": ";\n\n",
        "between": " ",
        "afterName": ":",
        "semicolon": true,
        "after": "\n",
        "value": "",
        "params": ":"
      },
      "type": "css-atrule",
      "name": "variable2",
      "source": {
        "start": {
          "line": 5,
          "column": 1
        },
        "input": {
          "css": "@variable1: {\n  field: something;\n};\n\n@variable2: {\n  field: something;\n};\n",
          "hasBOM": false,
          "id": "<input css 2>"
        },
        "end": {
          "line": 7,
          "column": 1
        },
        "startOffset": 38,
        "endOffset": 73
      },
      "nodes": [
        {
        ...
        }
      ],
      "variable": true,
      "value": ""
    }
  ],
  "source": {
    "input": {
      "css": "@variable1: {\n  field: something;\n};\n\n@variable2: {\n  field: something;\n};\n",
      "hasBOM": false,
      "id": "<input css 2>"
    },
    "start": {
      "line": 1,
      "column": 1
    },
    "startOffset": 0,
    "endOffset": 73
  }
}
```

when `postless` parses `raws.semicolon: true`, it does not consume the `;` char but keeps in in `raws.after`, this is why prettier prints it twice

Patch:
diff --git a/src/language-css/printer-postcss.js b/src/language-css/printer-postcss.js
--- a/src/language-css/printer-postcss.js
+++ b/src/language-css/printer-postcss.js
@@ -101,7 +101,10 @@ function genericPrint(path, options, print) {
       return [node.raw, hardline];
     case "css-root": {
       const nodes = printNodeSequence(path, options, print);
-      const after = node.raws.after.trim();
+      let after = node.raws.after.trim();
+      if (after.startsWith(";")) {
+        after = after.slice(1).trim();
+      }
 
       return [
         nodes,


Test patch:
diff --git a/tests/format/less/less/__snapshots__/jsfmt.spec.js.snap b/tests/format/less/less/__snapshots__/jsfmt.spec.js.snap
--- a/tests/format/less/less/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/format/less/less/__snapshots__/jsfmt.spec.js.snap
@@ -83,6 +83,24 @@ a: b;
 ================================================================================
 `;
 
+exports[`issue-11483--never-append-anything.less format 1`] = `
+====================================options=====================================
+parsers: ["less"]
+printWidth: 80
+                                                                                | printWidth
+=====================================input======================================
+@variable: {
+  field: something;
+};
+
+=====================================output=====================================
+@variable: {
+  field: something;
+};
+
+================================================================================
+`;
+
 exports[`less.less format 1`] = `
 ====================================options=====================================
 parsers: ["less"]
diff --git a/tests/format/less/less/issue-11483--never-append-anything.less b/tests/format/less/less/issue-11483--never-append-anything.less
new file mode 100644
--- /dev/null
+++ b/tests/format/less/less/issue-11483--never-append-anything.less
@@ -0,0 +1,3 @@
+@variable: {
+  field: something;
+};