Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --fix=lax and --fix=strict #7497

Open
ybiquitous opened this issue Jan 25, 2024 · 34 comments
Open

Add --fix=lax and --fix=strict #7497

ybiquitous opened this issue Jan 25, 2024 · 34 comments
Labels
status: ready to implement is ready to be worked on by someone type: enhancement a new feature that isn't related to rules

Comments

@ybiquitous
Copy link
Member

ybiquitous commented Jan 25, 2024

What minimal example or steps are needed to reproduce the bug?

Analyzing a CSS file with an invalid syntax raises a syntax error expectedly, while doing the same specifying --fix succeeds unexpectedly.

test.css:

// comment

For reference, this behavior difference depends on postcss-safe-parser:

const parse = await (fix ? import('postcss-safe-parser').then((m) => m.default) : postcss.parse);

Note: we found this problem in #7494.

What minimal configuration is needed to reproduce the bug?

{"rules": {}}

How did you run Stylelint?

Run the following commands in my console.

$ npx stylelint test.css

test.css
 1:1  ✖  Unknown word  CssSyntaxError

1 problem (1 error, 0 warnings)

$ npx stylelint test.css --fix

$ echo $?
0

Which Stylelint-related dependencies are you using?

package.json:

{
  "dependencies": {
    "stylelint": "16.2.0"
  }
}

What did you expect to happen?

Expect to raise a syntax error. E.g.

$ npx stylelint test.css --fix

test.css
 1:1  ✖  Unknown word  CssSyntaxError

1 problem (1 error, 0 warnings)

What actually happened?

A syntax error does not happen, and then Stylelint exits normally. E.g.

$ npx stylelint test.css --fix

$ echo $?
0

Do you have a proposal to fix the bug?

  1. do something similar to https://github.com/noahbrenner/xo/blob/8e4f4355c4b8e62bc28f37e3673bb6872e693bb0/main.js#L119-L133

  2. update fix option

true maps to "lax"
false doesn't change
"lax" aliases to true
"strict" added

@Mouvedia
Copy link
Contributor

Mouvedia commented Jan 25, 2024

I've labeled the issue as ready to implement. Please consider contributing if you have time.

@Mouvedia Mouvedia added status: ready to implement is ready to be worked on by someone type: bug a problem with a feature or rule and removed status: needs discussion triage needs further discussion labels Jan 25, 2024
@ybiquitous
Copy link
Member Author

I looked into the introduction of postcss-safe-parser. The PR was #2886.

postcss-safe-parser can fix syntax errors like this:

$ echo 'a {' | npx stylelint

<input css 1>
 1:1  ✖  Unclosed block  CssSyntaxError

1 problem (1 error, 0 warnings)


$ echo 'a {' | npx stylelint --fix
a {
}%

Of course, this package cannot fix some syntax errors like // comment:

$ echo '// comment' | npx stylelint

<input css 1>
 1:1  ✖  Unknown word  CssSyntaxError

1 problem (1 error, 0 warnings)


$ echo '// comment' | npx stylelint --fix
// comment

For now, I cannot find a solution, but let us know if anyone has some information.

@ybiquitous ybiquitous added status: needs investigation triage needs further investigation help wanted is likely non-trival and help is wanted status: ready to implement is ready to be worked on by someone type: bug a problem with a feature or rule and removed status: ready to implement is ready to be worked on by someone type: bug a problem with a feature or rule status: needs investigation triage needs further investigation labels Jan 29, 2024
@ybiquitous
Copy link
Member Author

For reference, an incomplete comment like /* comment is fixable:

$ echo '/* comment' | npx stylelint --fix
/* comment
*/%

@Mouvedia
Copy link
Contributor

What about some heuristics based on the previous iteration that switch between postcss.parse and postcss-safe-parser?
i.e. a partial revert of #7357

@ybiquitous
Copy link
Member Author

That heuristics use file extensions supporting the // comment form (e.g. .scss, .less etc.), right? I think the way is against our standard CSS preferred policy:

- for standard CSS syntax only

@Mouvedia
Copy link
Contributor

Mouvedia commented Jan 29, 2024

The alternative of not using postcss-safe-parser for --fix is worse though.

The worst that can happen with the partial revert is having someone using CSS-compatible code in a scss file that would trigger the warning erroneously. In that case it's just a matter of detecting the absence of CSS syntax error and adding a hint regarding the possibility of changing the extension.

The list maintenance is not a strong argument against it IMHO.
It's either a blacklist—e.g. sss, sass, scss, styl, less—or the previous whitelist plus mcss.
In both cases, it won't probably be touched for years because it covers most use cases.
i.e. the regression of the DX matters more than strictly enforcing our policy

@ybiquitous
Copy link
Member Author

Hum..., I'm still concerned that the file extension list based on heuristics may grow at people's request. In addition, if we'd like to remove the list itself or some extensions from the list, we must care about backward compatibility.

First of all, performing autofix first is an edge case, right? I believe normal use cases are below:

  1. Run stylelint test.scss -> raises a syntax error.
  2. Then, most users should notice something wrong with their code.

Furthermore, we encourage using the customSyntax option in the "Getting started" guide:

### Using a custom syntax directly

So, I doubt the worth of this heuristic, though ideally, the bug should not exist.

@Mouvedia
Copy link
Contributor

We can wait for the resolution of stylelint/vscode-stylelint#490 and reevaluate then.
IMHO the 3 issues related to this issue that were either closed or transferred won't be the last.
Personally I think that the message was useful and helping.
I disagree about the list maintenance; new extensions are pretty rare.

@ybiquitous
Copy link
Member Author

For reference, we previously removed an inaccurate syntax inference (heuristic) with PR #6645.

@Mouvedia
Copy link
Contributor

Mouvedia commented Jan 29, 2024

For reference, we previously removed an inaccurate syntax inference (heuristic) with PR #6645.

That one looks more like something I wouldn't recommend we maintain, I agree for that list.

@ybiquitous
Copy link
Member Author

We can wait for the resolution of stylelint/vscode-stylelint#490 and reevaluate then.

Agree. We can revisit this issue if many people complain.

@ybiquitous ybiquitous added status: needs discussion triage needs further discussion and removed status: ready to implement is ready to be worked on by someone type: bug a problem with a feature or rule help wanted is likely non-trival and help is wanted labels Jan 29, 2024
@ybiquitous
Copy link
Member Author

Also, we can revisit if a better solution is found.

@Mouvedia
Copy link
Contributor

Mouvedia commented Apr 24, 2024

Also, we can revisit if a better solution is found.

What about a new flag?
i.e. --validate-syntax or --force-validation which defaults to false (i.e. not being passed) when using --fix

We could use a different validator for that flag or simply postcss.parse.
e.g. csstree has a validator plugin
In that regard the only criterium should be spec compliancy, not speed.
i.e. I would expect that passing that new flag without fix: true could switch to a stricter validator
@romainmenke which one is the best in terms of strictness?

@ybiquitous
Copy link
Member Author

If most people don't care about this bug, I guess adding a new flag is too much.

@Mouvedia
Copy link
Contributor

Any thoughts?

It's elegant because it doesn't require a new flag.
I would support

  • --fix=lax as you described, uses postcss-safe-parser
  • --fix=strict uses postcss (as previously)
  • --fix=stricter uses a stricter parser (to be chosen in a dedicated issue)
  • Make --fix=strict default in the next major version
  • Remove --fix=lax in the future

I don't have an opinion. As long as it's configurable I am satisfied.

@ybiquitous
Copy link
Member Author

At this time, what is "a stricter parser"?

@ybiquitous ybiquitous added status: needs discussion triage needs further discussion and removed status: ready to implement is ready to be worked on by someone type: documentation an improvement to the documentation labels Apr 24, 2024
@ybiquitous ybiquitous changed the title Document autofix behavior for syntax errors Add support for stricter --fix Apr 24, 2024
@ybiquitous ybiquitous changed the title Add support for stricter --fix Add support for stricter fix option Apr 24, 2024
@Mouvedia
Copy link
Contributor

what is "a stricter parser"?

Let's say that as a prerequisite, it should take into account the values.
e.g. it throws for a { border-style: foo; border-width: -1px; } but validates a { -webkit-line-clamp: none; }

It's a can of worms if the dependency is not well maintained but if stricter is considered experimental having edge cases would be acceptable.
i.e. if it's that strict it might throw perfectly valid CSS erroneously

@romainmenke
Copy link
Member

what is "a stricter parser"?

it throws for a { border-style: foo; border-width: -1px; } but validates a { -webkit-line-clamp: none; }

I would narrow the scope as much as possible so that it doesn't overlap with any other rule.

@Mouvedia
Copy link
Contributor

Mouvedia commented Apr 24, 2024

I would narrow the scope as much as possible so that it doesn't overlap with any other rule.

That would either

  1. require the parser to have many option that we can disable or
  2. to filter the errors in a switch-case (i.e. the parser provides a good granularity for the errors)

I would prefer 1. but I am pretty sure we won't find one, so 2. will be a hard requirement if we want to avoid overlaps.
FYI biome has the same problem: biomejs/biome#2422
i.e. its parser covers the job of existing rules

@romainmenke
Copy link
Member

romainmenke commented Apr 24, 2024

I see what you mean, but I fear that this stricter parser would in a way become an entirely new Stylelint :D

I am sure that there will be some overlap and that is fine, but I would still like to minimize this as much as possible.

You could see it as a layer cake:

  1. does it tokenize without producing errors?
  2. does it parse according to css-syntax-3 without producing parse errors?
  3. do individual features parse correctly? (e.g. media-query-no-invalid)
  4. are the value types correct?
  5. does the stylesheet adhere to user preferences and conventions?

For me a strict parser would only check layers 1 and 2.

@ybiquitous
Copy link
Member Author

I also want to keep things simple. And, if the current --fix (lax) can produce invalid results, --fix should be strict. I think we should keep only --fix after making strict default in the future.

@Mouvedia
Copy link
Contributor

Mouvedia commented Apr 24, 2024

Let's split this proposal into 2:

  1. add "strict"/"lax" support to the flag/option --fix/fix
  2. define "stricter" precisely and then eventually add it if we reach a consensus

Concerning 2. I think that it's simpler to handle value position/type/enum validation when it matters (i.e. before --fix) than to add the validation for all affected rules one by one.

@ybiquitous
Copy link
Member Author

Please read #7497 (comment)
I think it's better to provide only --fix finally.

@Mouvedia Mouvedia changed the title Add support for stricter fix option Change fix flag type to "string" with choices: ['strict', 'lax'] Apr 28, 2024
@Mouvedia Mouvedia added type: enhancement a new feature that isn't related to rules status: ask to implement ask before implementing as may no longer be relevant status: needs discussion triage needs further discussion and removed status: needs discussion triage needs further discussion type: enhancement a new feature that isn't related to rules status: ask to implement ask before implementing as may no longer be relevant labels Apr 28, 2024
@Mouvedia
Copy link
Contributor

Mouvedia commented Apr 28, 2024

I am dropping my "stricter" proposal so that we can move on with the issue at hand.
For reference here's the issue that proposed to change the parser: #7116
I have updated the Do you have a proposal to fix the bug? section.

related: sindresorhus/meow#44
We want --fix to map to --fix="lax" so that existing code remains backward-compatible.

@Mouvedia Mouvedia changed the title Change fix flag type to "string" with choices: ['strict', 'lax'] Add --fix="lax" and --fix="strict" Apr 28, 2024
@Mouvedia Mouvedia changed the title Add --fix="lax" and --fix="strict" Add --fix=lax and --fix=strict Apr 28, 2024
@ybiquitous
Copy link
Member Author

@Mouvedia Thanks for sharing the Meow issue. Is there any workaround for the problem if Meow doesn't address it?

@Mouvedia
Copy link
Contributor

Mouvedia commented Apr 30, 2024

There is, if you switch to ready to implement I will show you.
i.e. --fix=foo doesn't throw so you can retrieve the value even if the type remains "boolean"

@ybiquitous ybiquitous added status: ready to implement is ready to be worked on by someone type: enhancement a new feature that isn't related to rules and removed status: needs discussion triage needs further discussion labels May 1, 2024
@ybiquitous
Copy link
Member Author

Alright. I've labeled the issue as ready to implement. Please consider contributing if you have time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: ready to implement is ready to be worked on by someone type: enhancement a new feature that isn't related to rules
Development

No branches or pull requests

3 participants