Skip to content

Commit 6e5918e

Browse files
immitsuybiquitous
andauthored
Add no-descending-specificity line number to the referenced selector in message (#8666)
Co-authored-by: Masafumi Koba <473530+ybiquitous@users.noreply.github.com>
1 parent 8e7ca69 commit 6e5918e

File tree

5 files changed

+60
-34
lines changed

5 files changed

+60
-34
lines changed

.changeset/thin-carrots-shop.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"stylelint": minor
3+
---
4+
5+
Added: `no-descending-specificity` report message includes line number of the anchoring selector

lib/rules/no-descending-specificity/__tests__/index.mjs

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -129,63 +129,63 @@ testRule({
129129
reject: [
130130
{
131131
code: 'b a { color: red; } a { color: red; }',
132-
message: messages.expected('a', 'b a'),
132+
message: messages.expected('a', 'b a', 1),
133133
line: 1,
134134
column: 21,
135135
endLine: 1,
136136
endColumn: 22,
137137
},
138138
{
139139
code: 'b a, { color: red; } a, { color: red; }',
140-
message: messages.expected('a', 'b a'),
140+
message: messages.expected('a', 'b a', 1),
141141
line: 1,
142142
column: 22,
143143
endLine: 1,
144144
endColumn: 23,
145145
},
146146
{
147147
code: 'a + a { color: red; } a { color: red; }',
148-
message: messages.expected('a', 'a + a'),
148+
message: messages.expected('a', 'a + a', 1),
149149
line: 1,
150150
column: 23,
151151
endLine: 1,
152152
endColumn: 24,
153153
},
154154
{
155155
code: 'b > a[foo] { color: red; } a[foo] { color: red; }',
156-
message: messages.expected('a[foo]', 'b > a[foo]'),
156+
message: messages.expected('a[foo]', 'b > a[foo]', 1),
157157
line: 1,
158158
column: 28,
159159
endLine: 1,
160160
endColumn: 34,
161161
},
162162
{
163163
code: 'e > f, b + e + a { color: red; } c { color: red; } a d { color: red; } z, f + a, y { color: red; }',
164-
message: messages.expected('f + a', 'b + e + a'),
164+
message: messages.expected('f + a', 'b + e + a', 1),
165165
line: 1,
166166
column: 75,
167167
endLine: 1,
168168
endColumn: 80,
169169
},
170170
{
171171
code: 'e > f, b + e + a { color: red; } c { color: red; } a d { color: red; } z, f + a, y { color: red; }',
172-
message: messages.expected('f + a', 'b + e + a'),
172+
message: messages.expected('f + a', 'b + e + a', 1),
173173
line: 1,
174174
column: 75,
175175
endLine: 1,
176176
endColumn: 80,
177177
},
178178
{
179179
code: 'a { & > b { color: red; } } b { color: red; }',
180-
message: messages.expected('b', 'a > b'),
180+
message: messages.expected('b', 'a > b', 1),
181181
line: 1,
182182
column: 29,
183183
endLine: 1,
184184
endColumn: 30,
185185
},
186186
{
187187
code: 'b a { color: red; } @media print { #c a { color: red; } a { color: red; } }',
188-
message: messages.expected('a', '#c a'),
188+
message: messages.expected('a', '#c a', 1),
189189
line: 1,
190190
column: 57,
191191
endLine: 1,
@@ -194,7 +194,7 @@ testRule({
194194
{
195195
code: 'a:hover { color: red; } a { color: red; } ',
196196
description: 'pseudo-class first',
197-
message: messages.expected('a', 'a:hover'),
197+
message: messages.expected('a', 'a:hover', 1),
198198
line: 1,
199199
column: 25,
200200
endLine: 1,
@@ -203,7 +203,7 @@ testRule({
203203
{
204204
code: 'a:hover::before { color: red; } a::before { color: red; } a { color: red; } a:hover ',
205205
description: 'pseudo-element with pseudo-class',
206-
message: messages.expected('a::before', 'a:hover::before'),
206+
message: messages.expected('a::before', 'a:hover::before', 1),
207207
line: 1,
208208
column: 33,
209209
endLine: 1,
@@ -213,14 +213,14 @@ testRule({
213213
code: '.a .b .c { color: red; } .b .c { color: red; } .c { color: red; }',
214214
warnings: [
215215
{
216-
message: messages.expected('.b .c', '.a .b .c'),
216+
message: messages.expected('.b .c', '.a .b .c', 1),
217217
line: 1,
218218
column: 26,
219219
endLine: 1,
220220
endColumn: 31,
221221
},
222222
{
223-
message: messages.expected('.c', '.a .b .c'),
223+
message: messages.expected('.c', '.a .b .c', 1),
224224
line: 1,
225225
column: 48,
226226
endLine: 1,
@@ -232,28 +232,28 @@ testRule({
232232
code: '.a .b .c { color: red; } .b .c { color: red; } .c { color: red; } .d .b .c { color: red; } .b .c { color: red; } .c { color: red; }',
233233
warnings: [
234234
{
235-
message: messages.expected('.b .c', '.a .b .c'),
235+
message: messages.expected('.b .c', '.a .b .c', 1),
236236
line: 1,
237237
column: 26,
238238
endLine: 1,
239239
endColumn: 31,
240240
},
241241
{
242-
message: messages.expected('.c', '.a .b .c'),
242+
message: messages.expected('.c', '.a .b .c', 1),
243243
line: 1,
244244
column: 48,
245245
endLine: 1,
246246
endColumn: 50,
247247
},
248248
{
249-
message: messages.expected('.b .c', '.a .b .c'),
249+
message: messages.expected('.b .c', '.a .b .c', 1),
250250
line: 1,
251251
column: 92,
252252
endLine: 1,
253253
endColumn: 97,
254254
},
255255
{
256-
message: messages.expected('.c', '.a .b .c'),
256+
message: messages.expected('.c', '.a .b .c', 1),
257257
line: 1,
258258
column: 114,
259259
endLine: 1,
@@ -265,14 +265,14 @@ testRule({
265265
code: 'a { .foo.bar & { color: red; } } a { color: red; .foo & { color: red; } }',
266266
warnings: [
267267
{
268-
message: messages.expected('a', '.foo.bar a'),
268+
message: messages.expected('a', '.foo.bar a', 1),
269269
line: 1,
270270
column: 34,
271271
endLine: 1,
272272
endColumn: 35,
273273
},
274274
{
275-
message: messages.expected('.foo &', '.foo.bar a'),
275+
message: messages.expected('.foo &', '.foo.bar a', 1),
276276
line: 1,
277277
column: 50,
278278
endLine: 1,
@@ -283,7 +283,7 @@ testRule({
283283
{
284284
code: '.foo { & h2 { @media { color: red; } } } h1 { & h2 { @media { color: red; } } }',
285285
description: 'at rules',
286-
message: messages.expected('& h2', '.foo h2'),
286+
message: messages.expected('& h2', '.foo h2', 1),
287287
line: 1,
288288
column: 47,
289289
endLine: 1,
@@ -301,28 +301,47 @@ testRule({
301301
`,
302302
warnings: [
303303
{
304-
message: messages.expected('a', 'b a'),
304+
message: messages.expected('a', 'b a', 1),
305305
line: 3,
306306
column: 1,
307307
endLine: 3,
308308
endColumn: 2,
309309
},
310310
{
311-
message: messages.expected('aa', 'b aa'),
311+
message: messages.expected('aa', 'b aa', 1),
312312
line: 4,
313313
column: 1,
314314
endLine: 4,
315315
endColumn: 3,
316316
},
317317
{
318-
message: messages.expected('aaa', 'b aaa'),
318+
message: messages.expected('aaa', 'b aaa', 1),
319319
line: 6,
320320
column: 1,
321321
endLine: 6,
322322
endColumn: 4,
323323
},
324324
],
325325
},
326+
{
327+
code: stripIndent`
328+
a {color: red }
329+
/* a comment */
330+
b:hover { color: red; }
331+
c { color: red; }
332+
/* b comment */
333+
b { color: red; }
334+
`,
335+
warnings: [
336+
{
337+
message: messages.expected('b', 'b:hover', 3),
338+
line: 6,
339+
column: 1,
340+
endLine: 6,
341+
endColumn: 2,
342+
},
343+
],
344+
},
326345
],
327346
});
328347

@@ -371,11 +390,11 @@ testRule({
371390
reject: [
372391
{
373392
code: 'css` &:hover { a { color: red; } } \n a { color: red; } `;',
374-
message: messages.expected('a', '&:hover a'),
393+
message: messages.expected('a', '&:hover a', 1),
375394
},
376395
{
377396
code: 'css` &.active { a { color: red; } } \n a { color: red; } `;',
378-
message: messages.expected('a', '&.active a'),
397+
message: messages.expected('a', '&.active a', 1),
379398
},
380399
],
381400
});
@@ -396,7 +415,7 @@ testRule({
396415
reject: [
397416
{
398417
code: 'b a { color: red; } h1 { color: red; } h2 { color: red; } h3 { color: red; } a { color: red; }',
399-
message: messages.expected('a', 'b a'),
418+
message: messages.expected('a', 'b a', 1),
400419
line: 1,
401420
column: 78,
402421
endLine: 1,

lib/rules/no-descending-specificity/index.cjs

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/rules/no-descending-specificity/index.mjs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@ import validateOptions from '../../utils/validateOptions.mjs';
1616
const ruleName = 'no-descending-specificity';
1717

1818
const messages = ruleMessages(ruleName, {
19-
expected: (b, a) => {
20-
return `Expected selector "${b}" to come before selector "${a}"`;
19+
expected: (b, a, line) => {
20+
return `Expected selector "${b}" to come before selector "${a}", at line ${line}`;
2121
},
2222
});
2323

2424
const meta = {
2525
url: 'https://stylelint.io/user-guide/rules/no-descending-specificity',
2626
};
2727

28-
/** @typedef {{ selector: string, specificity: import('@csstools/selector-specificity').Specificity }} Entry */
28+
/** @typedef {{ selector: string, specificity: import('@csstools/selector-specificity').Specificity, line: number }} Entry */
2929

3030
/** @type {import('stylelint').CoreRules[ruleName]} */
3131
const rule = (primary, secondaryOptions) => {
@@ -102,6 +102,7 @@ const rule = (primary, secondaryOptions) => {
102102
const entry = {
103103
selector: resolvedSelectorNode.toString().trim(),
104104
specificity,
105+
line: ruleNode.source?.start?.line ?? 1,
105106
};
106107
const priorComparableSelectors = comparisonContext.get(referenceSelector);
107108

@@ -124,7 +125,7 @@ const rule = (primary, secondaryOptions) => {
124125
result,
125126
node: ruleNode,
126127
message: messages.expected,
127-
messageArgs: [selectorStr, priorEntry.selector],
128+
messageArgs: [selectorStr, priorEntry.selector, priorEntry.line],
128129
index,
129130
endIndex,
130131
});

types/stylelint/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,7 @@ declare namespace stylelint {
770770
'no-descending-specificity': CoreRule<
771771
true,
772772
{ ignore: OneOrMany<'selectors-within-list'> },
773-
ExpectedMessage<[selector: string, selector: string]>
773+
ExpectedMessage<[selector: string, selector: string, line: number]>
774774
>;
775775
'no-duplicate-at-import-rules': CoreRule<true, {}, RejectedMessage<[url: string]>>;
776776
'no-duplicate-selectors': CoreRule<

0 commit comments

Comments
 (0)