Skip to content

Fix selector-no-qualifying-type false negatives for :is/where()#8940

Merged
romainmenke merged 10 commits intov17from
fix-selector-no-qualifying-type-false-negatives-for-is-where--empathetic-stag-beetle-f777388630
Dec 28, 2025
Merged

Fix selector-no-qualifying-type false negatives for :is/where()#8940
romainmenke merged 10 commits intov17from
fix-selector-no-qualifying-type-false-negatives-for-is-where--empathetic-stag-beetle-f777388630

Conversation

@romainmenke
Copy link
Copy Markdown
Member

@romainmenke romainmenke commented Dec 22, 2025

Which issue, if any, is this issue related to?

Closes #8927

Is there anything in the PR that needs further explanation?

These cases added some complexity:

/* each compound individually seems fine, only after traversing UP does it become clear that `a.class`/`b[attribute]` are part of the outcomes */
:is(a, [attribute]):is(b, .class) {}

/* tag names can be added further down the AST, and on the right from non-tagnames */
.class:is(a) {}

I didn't see a way to traverse all tag names in the original AST and do checks from there.

I ended up first building all compounds as a new AST:
:is(a, [attribute]):is(b, .class) -> ab, a.class, ba, b[attribute] (ab are two nodes in the AST)

This new AST can be traversed top down in a single pass.


Because of all the AST mutations I also changed the message.
The message now reports the tag name and the original compound, not the computed compound.

When nesting, this original compound will be from the resolved selector.

div a { &[attribute] {}
  • a tag name
  • [attribute]:is(div a) compound
a :is(a, [attribute]):is(b, .class) a {}
  • b tag name
  • :is(a, [attribute]):is(b, .class) compound
  • a tag name
  • :is(a, [attribute]):is(b, .class) compound

The report range will be that of only the tag name.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Dec 22, 2025

🦋 Changeset detected

Latest commit: b1dfcf3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
stylelint Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@jeddy3
Copy link
Copy Markdown
Member

jeddy3 commented Dec 22, 2025

Nicely done! Thank you for tackling this tricky one.

The approach and implementation LGTM:

  • The report range will be that of only the tag name. 👍
  • The message now reports the tag name and the original compound, not the computed compound. 👍
  • When nesting, this original compound will be from the resolved selector. 👍

…where--empathetic-stag-beetle-f777388630' of https://github.com/stylelint/stylelint into fix-selector-no-qualifying-type-false-negatives-for-is-where--empathetic-stag-beetle-f777388630
@ybiquitous ybiquitous linked an issue Dec 23, 2025 that may be closed by this pull request
Copy link
Copy Markdown
Member

@ybiquitous ybiquitous left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@romainmenke Thanks for the pull request. Overall LGTM 👍🏼

I've left some minor suggestions for code improvements. I'd appreciate it if you could take a look.


[suggestion] What if we could add a few examples for the new problem types to the rule README?

  • Using & nesting selector
  • Using :is() pseudo-class

Comment thread lib/rules/selector-no-qualifying-type/index.mjs Outdated
Comment thread lib/rules/selector-no-qualifying-type/index.mjs Outdated
Comment thread lib/rules/selector-no-qualifying-type/index.mjs Outdated
Comment thread lib/rules/selector-no-qualifying-type/index.mjs Outdated
Comment thread lib/rules/selector-no-qualifying-type/__tests__/index.mjs Outdated
Comment thread lib/rules/selector-no-qualifying-type/index.mjs Outdated
Comment thread lib/rules/selector-no-qualifying-type/index.mjs Outdated
Comment thread lib/rules/selector-no-qualifying-type/index.mjs Outdated
romainmenke and others added 5 commits December 24, 2025 08:41
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
@romainmenke
Copy link
Copy Markdown
Member Author

Thank you for the review @ybiquitous,
I've applied the suggestions and have one question.
Please take a look when you have time 🙇

Copy link
Copy Markdown
Member

@jeddy3 jeddy3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely done!

LGTM, thank you.

Copy link
Copy Markdown
Member

@ybiquitous ybiquitous left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for addressing my reviews. The changed code looks good enough to me 👍🏼

@romainmenke romainmenke merged commit 595d930 into v17 Dec 28, 2025
17 checks passed
@romainmenke romainmenke deleted the fix-selector-no-qualifying-type-false-negatives-for-is-where--empathetic-stag-beetle-f777388630 branch December 28, 2025 08:00
renovate Bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Jan 15, 2026
| datasource | package   | from    | to     |
| ---------- | --------- | ------- | ------ |
| npm        | stylelint | 16.26.1 | 17.0.0 |


## [v17.0.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1700---2026-01-15)

It contains 14 breaking changes, which we've detailed in the [migrating to `17.0.0` guide](docs/migration-guide/to-17.md). Additionally, it adds 3 options to the rules and fixes 9 bugs. We've also released compatible versions of our [shared config](https://www.npmjs.com/package/stylelint-config-standard), [Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint), [Node.js Rule Tester](https://www.npmjs.com/package/stylelint-test-rule-node) and [Jest preset](https://www.npmjs.com/package/jest-preset-stylelint).

- Removed: CommonJS Node.js API ([#8859](stylelint/stylelint#8859)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: `output` property in the Node.js API returned resolved object ([#8878](stylelint/stylelint#8878)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: support for Node.js less than 20.19.0 ([#8867](stylelint/stylelint#8867)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: GitHub formatter ([#8888](stylelint/stylelint#8888)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: `resolveNestedSelectors` option from `selector-class-pattern` ([#8931](stylelint/stylelint#8931)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: `checkContextFunctionalPseudoClasses` option from `selector-max-id` ([#8913](stylelint/stylelint#8913)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: default `fix` mode to `strict` ([#8889](stylelint/stylelint#8889)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `report` to be consistent and predictable in how it handles the provided position arguments ([#8217](stylelint/stylelint#8217)) ([@romainmenke](https://github.com/romainmenke)).
- Changed: `selector-max-*` syntax rules for standard CSS nesting and modern functional pseudo-classes ([#8913](stylelint/stylelint#8913)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `*-specificity` semantic rules for standard CSS nesting ([#8913](stylelint/stylelint#8913)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `no-duplicate-selectors` and `selector-no-qualifying-type` for standard CSS nesting ([#8913](stylelint/stylelint#8913)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `*-list` rules to have consistent behaviour for vendor prefixes and case ([#8912](stylelint/stylelint#8912)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `*-no-vendor-prefix` rules to have consistent behaviour for their `ignore*: []` secondary options ([#8924](stylelint/stylelint#8924)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `declaration-property-max-values` rule to have consistent behaviour for vendor prefixes ([#8926](stylelint/stylelint#8926)) ([@jeddy3](https://github.com/jeddy3)).
- Added: `except: ["after-block"]` to `custom-property-empty-line-before` ([#8921](stylelint/stylelint#8921)) ([@kovsu](https://github.com/kovsu)).
- Added: `except: ["after-block"]` to `declaration-empty-line-before` ([#8910](stylelint/stylelint#8910)) ([@kovsu](https://github.com/kovsu)).
- Added: `ignoreSelectors: []` to `no-duplicate-selectors` ([#8883](stylelint/stylelint#8883)) ([@kovsu](https://github.com/kovsu)).
- Fixed: Windows drive letter casing inconsistencies when matching patterns against file paths ([#8941](stylelint/stylelint#8941)) ([@adalinesimonian](https://github.com/adalinesimonian)).
- Fixed: CLI help to include TypeScript config files ([#8908](stylelint/stylelint#8908)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `at-rule-descriptor-no-unknown` false positives for declarations within feature-value-blocks ([#8868](stylelint/stylelint#8868)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `declaration-block-no-redundant-longhand-properties` false negatives for short and long combinations ([#8892](stylelint/stylelint#8892)) ([@nathannewyen](https://github.com/nathannewyen)).
- Fixed: `media-feature-name-no-unknown` false positives for namespaced dollar variables and range context queries ([#8890](stylelint/stylelint#8890)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `nesting-selector-no-missing-scoping-root` false positives for CSS-in-JS ([#8905](stylelint/stylelint#8905)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `no-invalid-position-declaration` false negatives for embedded blocks ([#8907](stylelint/stylelint#8907)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `selector-no-qualifying-type` false negatives for `:is/where()` ([#8940](stylelint/stylelint#8940)) ([@romainmenke](https://github.com/romainmenke)).
- Fixed: `selector-type-no-unknown` false positives for MathML 4 tags ([#8874](stylelint/stylelint#8874)) ([@jeddy3](https://github.com/jeddy3)).
renovate Bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Jan 17, 2026
| datasource | package   | from    | to     |
| ---------- | --------- | ------- | ------ |
| npm        | stylelint | 16.26.1 | 17.0.0 |


## [v17.0.0](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1700---2026-01-15)

It contains 14 breaking changes, which we've detailed in the [migrating to `17.0.0` guide](docs/migration-guide/to-17.md). Additionally, it adds 3 options to the rules and fixes 9 bugs. We've also released compatible versions of our [shared config](https://www.npmjs.com/package/stylelint-config-standard), [Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint), [Node.js Rule Tester](https://www.npmjs.com/package/stylelint-test-rule-node) and [Jest preset](https://www.npmjs.com/package/jest-preset-stylelint).

- Removed: CommonJS Node.js API ([#8859](stylelint/stylelint#8859)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: `output` property in the Node.js API returned resolved object ([#8878](stylelint/stylelint#8878)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: support for Node.js less than 20.19.0 ([#8867](stylelint/stylelint#8867)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: GitHub formatter ([#8888](stylelint/stylelint#8888)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: `resolveNestedSelectors` option from `selector-class-pattern` ([#8931](stylelint/stylelint#8931)) ([@jeddy3](https://github.com/jeddy3)).
- Removed: `checkContextFunctionalPseudoClasses` option from `selector-max-id` ([#8913](stylelint/stylelint#8913)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: default `fix` mode to `strict` ([#8889](stylelint/stylelint#8889)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `report` to be consistent and predictable in how it handles the provided position arguments ([#8217](stylelint/stylelint#8217)) ([@romainmenke](https://github.com/romainmenke)).
- Changed: `selector-max-*` syntax rules for standard CSS nesting and modern functional pseudo-classes ([#8913](stylelint/stylelint#8913)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `*-specificity` semantic rules for standard CSS nesting ([#8913](stylelint/stylelint#8913)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `no-duplicate-selectors` and `selector-no-qualifying-type` for standard CSS nesting ([#8913](stylelint/stylelint#8913)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `*-list` rules to have consistent behaviour for vendor prefixes and case ([#8912](stylelint/stylelint#8912)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `*-no-vendor-prefix` rules to have consistent behaviour for their `ignore*: []` secondary options ([#8924](stylelint/stylelint#8924)) ([@jeddy3](https://github.com/jeddy3)).
- Changed: `declaration-property-max-values` rule to have consistent behaviour for vendor prefixes ([#8926](stylelint/stylelint#8926)) ([@jeddy3](https://github.com/jeddy3)).
- Added: `except: ["after-block"]` to `custom-property-empty-line-before` ([#8921](stylelint/stylelint#8921)) ([@kovsu](https://github.com/kovsu)).
- Added: `except: ["after-block"]` to `declaration-empty-line-before` ([#8910](stylelint/stylelint#8910)) ([@kovsu](https://github.com/kovsu)).
- Added: `ignoreSelectors: []` to `no-duplicate-selectors` ([#8883](stylelint/stylelint#8883)) ([@kovsu](https://github.com/kovsu)).
- Fixed: Windows drive letter casing inconsistencies when matching patterns against file paths ([#8941](stylelint/stylelint#8941)) ([@adalinesimonian](https://github.com/adalinesimonian)).
- Fixed: CLI help to include TypeScript config files ([#8908](stylelint/stylelint#8908)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `at-rule-descriptor-no-unknown` false positives for declarations within feature-value-blocks ([#8868](stylelint/stylelint#8868)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `declaration-block-no-redundant-longhand-properties` false negatives for short and long combinations ([#8892](stylelint/stylelint#8892)) ([@nathannewyen](https://github.com/nathannewyen)).
- Fixed: `media-feature-name-no-unknown` false positives for namespaced dollar variables and range context queries ([#8890](stylelint/stylelint#8890)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `nesting-selector-no-missing-scoping-root` false positives for CSS-in-JS ([#8905](stylelint/stylelint#8905)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `no-invalid-position-declaration` false negatives for embedded blocks ([#8907](stylelint/stylelint#8907)) ([@kovsu](https://github.com/kovsu)).
- Fixed: `selector-no-qualifying-type` false negatives for `:is/where()` ([#8940](stylelint/stylelint#8940)) ([@romainmenke](https://github.com/romainmenke)).
- Fixed: `selector-type-no-unknown` false positives for MathML 4 tags ([#8874](stylelint/stylelint#8874)) ([@jeddy3](https://github.com/jeddy3)).
robbevp pushed a commit to robbevp/website-robbevanpetegem that referenced this pull request Jan 20, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [stylelint](https://stylelint.io) ([source](https://github.com/stylelint/stylelint)) | devDependencies | major | [`^16.23.1` -> `^17.0.0`](https://renovatebot.com/diffs/npm/stylelint/16.26.1/17.0.0) |

---

### Release Notes

<details>
<summary>stylelint/stylelint (stylelint)</summary>

### [`v17.0.0`](https://github.com/stylelint/stylelint/blob/HEAD/CHANGELOG.md#1700---2026-01-15)

[Compare Source](stylelint/stylelint@16.26.1...17.0.0)

It contains 14 breaking changes, which we've detailed in the [migrating to `17.0.0` guide](docs/migration-guide/to-17.md). Additionally, it adds 3 options to the rules and fixes 9 bugs. We've also released compatible versions of our [shared config](https://www.npmjs.com/package/stylelint-config-standard), [Visual Studio Code extension](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint), [Node.js Rule Tester](https://www.npmjs.com/package/stylelint-test-rule-node) and [Jest preset](https://www.npmjs.com/package/jest-preset-stylelint).

- Removed: CommonJS Node.js API ([#&#8203;8859](stylelint/stylelint#8859)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Removed: `output` property in the Node.js API returned resolved object ([#&#8203;8878](stylelint/stylelint#8878)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Removed: support for Node.js less than 20.19.0 ([#&#8203;8867](stylelint/stylelint#8867)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Removed: GitHub formatter ([#&#8203;8888](stylelint/stylelint#8888)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Removed: `resolveNestedSelectors` option from `selector-class-pattern` ([#&#8203;8931](stylelint/stylelint#8931)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Removed: `checkContextFunctionalPseudoClasses` option from `selector-max-id` ([#&#8203;8913](stylelint/stylelint#8913)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Changed: default `fix` mode to `strict` ([#&#8203;8889](stylelint/stylelint#8889)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Changed: `report` to be consistent and predictable in how it handles the provided position arguments ([#&#8203;8217](stylelint/stylelint#8217)) ([@&#8203;romainmenke](https://github.com/romainmenke)).
- Changed: `selector-max-*` syntax rules for standard CSS nesting and modern functional pseudo-classes ([#&#8203;8913](stylelint/stylelint#8913)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Changed: `*-specificity` semantic rules for standard CSS nesting ([#&#8203;8913](stylelint/stylelint#8913)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Changed: `no-duplicate-selectors` and `selector-no-qualifying-type` for standard CSS nesting ([#&#8203;8913](stylelint/stylelint#8913)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Changed: `*-list` rules to have consistent behaviour for vendor prefixes and case ([#&#8203;8912](stylelint/stylelint#8912)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Changed: `*-no-vendor-prefix` rules to have consistent behaviour for their `ignore*: []` secondary options ([#&#8203;8924](stylelint/stylelint#8924)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Changed: `declaration-property-max-values` rule to have consistent behaviour for vendor prefixes ([#&#8203;8926](stylelint/stylelint#8926)) ([@&#8203;jeddy3](https://github.com/jeddy3)).
- Added: `except: ["after-block"]` to `custom-property-empty-line-before` ([#&#8203;8921](stylelint/stylelint#8921)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Added: `except: ["after-block"]` to `declaration-empty-line-before` ([#&#8203;8910](stylelint/stylelint#8910)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Added: `ignoreSelectors: []` to `no-duplicate-selectors` ([#&#8203;8883](stylelint/stylelint#8883)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Fixed: Windows drive letter casing inconsistencies when matching patterns against file paths ([#&#8203;8941](stylelint/stylelint#8941)) ([@&#8203;adalinesimonian](https://github.com/adalinesimonian)).
- Fixed: CLI help to include TypeScript config files ([#&#8203;8908](stylelint/stylelint#8908)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Fixed: `at-rule-descriptor-no-unknown` false positives for declarations within feature-value-blocks ([#&#8203;8868](stylelint/stylelint#8868)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Fixed: `declaration-block-no-redundant-longhand-properties` false negatives for short and long combinations ([#&#8203;8892](stylelint/stylelint#8892)) ([@&#8203;nathannewyen](https://github.com/nathannewyen)).
- Fixed: `media-feature-name-no-unknown` false positives for namespaced dollar variables and range context queries ([#&#8203;8890](stylelint/stylelint#8890)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Fixed: `nesting-selector-no-missing-scoping-root` false positives for CSS-in-JS ([#&#8203;8905](stylelint/stylelint#8905)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Fixed: `no-invalid-position-declaration` false negatives for embedded blocks ([#&#8203;8907](stylelint/stylelint#8907)) ([@&#8203;kovsu](https://github.com/kovsu)).
- Fixed: `selector-no-qualifying-type` false negatives for `:is/where()` ([#&#8203;8940](stylelint/stylelint#8940)) ([@&#8203;romainmenke](https://github.com/romainmenke)).
- Fixed: `selector-type-no-unknown` false positives for MathML 4 tags ([#&#8203;8874](stylelint/stylelint#8874)) ([@&#8203;jeddy3](https://github.com/jeddy3)).

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS42MS4wIiwidXBkYXRlZEluVmVyIjoiNDEuNjEuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Reviewed-on: https://git.robbevp.be/robbevp/website-robbevanpetegem/pulls/504
Co-authored-by: Renovate Bot <renovate@robbevp.be>
Co-committed-by: Renovate Bot <renovate@robbevp.be>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Fix selector-no-qualifying-type false negatives for :is/where()

3 participants