Repository: prettier/prettier (JavaScript)
Date: 2020-04-02 05:54:21+00:00
Task type: Feature

Issue:
Throw on Less syntax when the `css` parser is used
Not really sure this is really needed, but evilebottnawi asked to open this issue [here](https://github.com/prettier/prettier/pull/6981/files#r371918167).


Issue discussion:

Solution patch:
diff --git a/changelog_unreleased/css/pr-7933.md b/changelog_unreleased/css/pr-7933.md
new file mode 100644
index 000000000000..16d9f059c39b
--- /dev/null
+++ b/changelog_unreleased/css/pr-7933.md
@@ -0,0 +1,41 @@
+#### [BREAKING] Add pure css parser ([#7933](https://github.com/prettier/prettier/pull/7933) by [@fisker](https://github.com/fisker))
+
+Previously when `--parser=css` passed, we try `postcss-scss`/`postcss-less` to parse content, this cause confusion, and hard to check syntax error. Now `--parser=css` only works on css syntax.
+
+_If you're setting `parser="css"` for your `.less`/`.scss` file, you'll need update it to correct parser, or let prettier decide._
+
+<!-- prettier-ignore -->
+```less
+/* Input */
+/* Less Syntax with `--parser=css` */
+a {.bordered();}
+
+/* Prettier stable */
+/* Less Syntax with `--parser=css` */
+a {
+  .bordered();
+}
+
+/* Prettier master */
+SyntaxError: (postcss) CssSyntaxError Unknown word (2:4)
+  1 | /* Less Syntax with `--parser=css` */
+> 2 | a {.bordered();}
+```
+
+<!-- prettier-ignore -->
+```scss
+/* Input */
+/* Scss Syntax with `--parser=css` */
+::before {content: #{$foo}}
+
+/* Prettier stable */
+/* Scss Syntax with `--parser=css` */
+::before {
+  content: #{$foo};
+}
+
+/* Prettier master */
+SyntaxError: (postcss) CssSyntaxError Unknown word (2:22)
+  1 | /* Scss Syntax with `--parser=css` */
+> 2 | ::before {content: #{$foo}}
+```
diff --git a/docs/options.md b/docs/options.md
index c3be3220c1b7..38d6000adecd 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -211,9 +211,9 @@ Valid options:
 - `"babel-ts"` (similar to `"typescript"` but uses Babel and its TypeScript plugin) _First available in v2.0.0_
 - `"flow"` (via [flow-parser](https://github.com/facebook/flow/tree/master/src/parser))
 - `"typescript"` (via [@typescript-eslint/typescript-estree](https://github.com/typescript-eslint/typescript-eslint)) _First available in v1.4.0_
-- `"css"` (via [postcss-scss](https://github.com/postcss/postcss-scss) and [postcss-less](https://github.com/shellscape/postcss-less), autodetects which to use) _First available in v1.7.1_
-- `"scss"` (same parsers as `"css"`, prefers postcss-scss) _First available in v1.7.1_
-- `"less"` (same parsers as `"css"`, prefers postcss-less) _First available in v1.7.1_
+- `"css"` (via [postcss](https://github.com/postcss/postcss)) _First available in v1.7.1_
+- `"scss"` (via [postcss-scss](https://github.com/postcss/postcss-scss)) _First available in v1.7.1_
+- `"less"` (via [postcss-less](https://github.com/shellscape/postcss-less) _First available in v1.7.1_
 - `"json"` (via [@babel/parser parseExpression](https://babeljs.io/docs/en/next/babel-parser.html#babelparserparseexpressioncode-options)) _First available in v1.5.0_
 - `"json5"` (same parser as `"json"`, but outputs as [json5](https://json5.org/)) _First available in v1.13.0_
 - `"json-stringify"` (same parser as `"json"`, but outputs like `JSON.stringify`) _First available in v1.13.0_
diff --git a/package.json b/package.json
index ebeb18654644..b22a86d5d863 100644
--- a/package.json
+++ b/package.json
@@ -64,6 +64,7 @@
     "outdent": "0.7.1",
     "parse-srcset": "ikatyang/parse-srcset#54eb9c1cb21db5c62b4d0e275d7249516df6f0ee",
     "please-upgrade-node": "3.2.0",
+    "postcss": "7.0.30",
     "postcss-less": "3.1.4",
     "postcss-media-query-parser": "0.2.3",
     "postcss-scss": "2.1.1",
diff --git a/src/language-css/parser-postcss.js b/src/language-css/parser-postcss.js
index e8e503d49030..8430cdc08fb6 100644
--- a/src/language-css/parser-postcss.js
+++ b/src/language-css/parser-postcss.js
@@ -606,26 +606,9 @@ function parseWithParser(parse, text, options) {
   return result;
 }
 
-// TODO: make this only work on css
 function parseCss(text, parsers, options) {
-  const isSCSSParser = isSCSS(options.parser, text);
-  const parseFunctions = isSCSSParser
-    ? [parseScss, parseLess]
-    : [parseLess, parseScss];
-
-  let error;
-  for (const parse of parseFunctions) {
-    try {
-      return parse(text, parsers, options);
-    } catch (parseError) {
-      error = error || parseError;
-    }
-  }
-
-  /* istanbul ignore next */
-  if (error) {
-    throw error;
-  }
+  const { parse } = require("postcss");
+  return parseWithParser(parse, text, options);
 }
 
 function parseLess(text, parsers, options) {
diff --git a/yarn.lock b/yarn.lock
index 35791f76b7b6..e0c8e250cdfe 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6462,6 +6462,15 @@ postcss-values-parser@2.0.1:
     indexes-of "^1.0.1"
     uniq "^1.0.1"
 
+postcss@7.0.30:
+  version "7.0.30"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.30.tgz#cc9378beffe46a02cbc4506a0477d05fcea9a8e2"
+  integrity sha512-nu/0m+NtIzoubO+xdAlwZl/u5S5vi/y6BCsoL8D+8IxsD3XvBS8X4YEADNIVXKVuQvduiucnRv+vPIqj56EGMQ==
+  dependencies:
+    chalk "^2.4.2"
+    source-map "^0.6.1"
+    supports-color "^6.1.0"
+
 postcss@^7.0.14, postcss@^7.0.6:
   version "7.0.32"
   resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d"


Test patch:
diff --git a/tests/misc/errors/css/__snapshots__/jsfmt.spec.js.snap b/tests/misc/errors/css/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000000..36d3dad90c37
--- /dev/null
+++ b/tests/misc/errors/css/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,15 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`less-syntax.css error test 1`] = `
+"(postcss) CssSyntaxError Unknown word (1:4)
+> 1 | a {.bordered();}
+    |    ^
+  2 | "
+`;
+
+exports[`scss-syntax.css error test 1`] = `
+"(postcss) CssSyntaxError Unknown word (1:15)
+> 1 | a {content: #{$foo}}
+    |               ^
+  2 | "
+`;
diff --git a/tests/misc/errors/css/jsfmt.spec.js b/tests/misc/errors/css/jsfmt.spec.js
new file mode 100644
index 000000000000..7d3726c81147
--- /dev/null
+++ b/tests/misc/errors/css/jsfmt.spec.js
@@ -0,0 +1,1 @@
+run_spec(__dirname, ["css"]);
diff --git a/tests/misc/errors/css/less-syntax.css b/tests/misc/errors/css/less-syntax.css
new file mode 100644
index 000000000000..c093b5027076
--- /dev/null
+++ b/tests/misc/errors/css/less-syntax.css
@@ -0,0 +1,1 @@
+a {.bordered();}
diff --git a/tests/misc/errors/css/scss-syntax.css b/tests/misc/errors/css/scss-syntax.css
new file mode 100644
index 000000000000..b3d023332364
--- /dev/null
+++ b/tests/misc/errors/css/scss-syntax.css
@@ -0,0 +1,1 @@
+a {content: #{$foo}}
diff --git a/tests/misc/errors/less/__snapshots__/jsfmt.spec.js.snap b/tests/misc/errors/less/__snapshots__/jsfmt.spec.js.snap
index e113e898d77e..2897e4871174 100644
--- a/tests/misc/errors/less/__snapshots__/jsfmt.spec.js.snap
+++ b/tests/misc/errors/less/__snapshots__/jsfmt.spec.js.snap
@@ -28,3 +28,10 @@ exports[`open-sigle-quote.less error test 1`] = `
   3 | }
   4 | "
 `;
+
+exports[`scss-syntax.css error test 1`] = `
+"(postcss) CssSyntaxError Unknown word (1:15)
+> 1 | a {content: #{$foo}}
+    |               ^
+  2 | "
+`;
diff --git a/tests/misc/errors/less/scss-syntax.css b/tests/misc/errors/less/scss-syntax.css
new file mode 100644
index 000000000000..b3d023332364
--- /dev/null
+++ b/tests/misc/errors/less/scss-syntax.css
@@ -0,0 +1,1 @@
+a {content: #{$foo}}
diff --git a/tests/misc/errors/scss/__snapshots__/jsfmt.spec.js.snap b/tests/misc/errors/scss/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000000..cd42dd0812d1
--- /dev/null
+++ b/tests/misc/errors/scss/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,8 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`less-syntax.css error test 1`] = `
+"(postcss) CssSyntaxError Unknown word (1:4)
+> 1 | a {.bordered();}
+    |    ^
+  2 | "
+`;
diff --git a/tests/misc/errors/scss/jsfmt.spec.js b/tests/misc/errors/scss/jsfmt.spec.js
new file mode 100644
index 000000000000..539bde0869da
--- /dev/null
+++ b/tests/misc/errors/scss/jsfmt.spec.js
@@ -0,0 +1,1 @@
+run_spec(__dirname, ["scss"]);
diff --git a/tests/misc/errors/scss/less-syntax.css b/tests/misc/errors/scss/less-syntax.css
new file mode 100644
index 000000000000..c093b5027076
--- /dev/null
+++ b/tests/misc/errors/scss/less-syntax.css
@@ -0,0 +1,1 @@
+a {.bordered();}