Skip to content

Commit 5405ec6

Browse files
authored
chore: refactor logic for ignoring warnings (#11300)
* reimplement svelte-ignore logic * simplify * remove unused code * remove ignores array from comment node * unused * regenerate types * types * oops, again
1 parent 73490bb commit 5405ec6

File tree

13 files changed

+132
-143
lines changed

13 files changed

+132
-143
lines changed

packages/svelte/src/compiler/legacy.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
regex_not_whitespace,
55
regex_starts_with_whitespaces
66
} from './phases/patterns.js';
7+
import { extract_svelte_ignore } from './utils/extract_svelte_ignore.js';
78

89
/**
910
* Some of the legacy Svelte AST nodes remove whitespace from the start and end of their children.
@@ -197,7 +198,13 @@ export function convert(source, ast) {
197198
ClassDirective(node) {
198199
return { ...node, type: 'Class' };
199200
},
200-
ComplexSelector(node, { visit }) {
201+
Comment(node) {
202+
return {
203+
...node,
204+
ignores: extract_svelte_ignore(node.data)
205+
};
206+
},
207+
ComplexSelector(node) {
201208
const children = [];
202209

203210
for (const child of node.children) {

packages/svelte/src/compiler/phases/1-parse/state/element.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { extract_svelte_ignore } from '../../../utils/extract_svelte_ignore.js';
2-
import fuzzymatch from '../utils/fuzzymatch.js';
31
import { is_void } from '../utils/names.js';
42
import read_expression from '../read/expression.js';
53
import { read_script } from '../read/script.js';
@@ -87,8 +85,7 @@ export default function tag(parser) {
8785
type: 'Comment',
8886
start,
8987
end: parser.index,
90-
data,
91-
ignores: extract_svelte_ignore(data)
88+
data
9289
});
9390

9491
return;

packages/svelte/src/compiler/phases/2-analyze/a11y.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -667,9 +667,8 @@ function get_static_text_value(attribute) {
667667
/**
668668
* @param {import('#compiler').RegularElement | import('#compiler').SvelteElement} node
669669
* @param {import('./types.js').AnalysisState} state
670-
* @param {import('#compiler').SvelteNode[]} path
671670
*/
672-
function check_element(node, state, path) {
671+
function check_element(node, state) {
673672
// foreign namespace means elements can have completely different meanings, therefore we don't check them
674673
if (state.options.namespace === 'foreign') return;
675674

@@ -680,8 +679,7 @@ function check_element(node, state, path) {
680679
* @param {Parameters<import('../../warnings.js').AllWarnings[T]>} args
681680
* @returns {void}
682681
*/
683-
const push_warning = (node, code, ...args) =>
684-
warn(state.analysis.warnings, node, path, code, ...args);
682+
const push_warning = (node, code, ...args) => warn(state.analysis.warnings, node, code, ...args);
685683

686684
/** @type {Map<string, import('#compiler').Attribute>} */
687685
const attribute_map = new Map();
@@ -1165,9 +1163,9 @@ function check_element(node, state, path) {
11651163
*/
11661164
export const a11y_validators = {
11671165
RegularElement(node, context) {
1168-
check_element(node, context.state, context.path);
1166+
check_element(node, context.state);
11691167
},
11701168
SvelteElement(node, context) {
1171-
check_element(node, context.state, context.path);
1169+
check_element(node, context.state);
11721170
}
11731171
};

packages/svelte/src/compiler/phases/2-analyze/css/css-warn.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const visitors = {
2626
if (!node.metadata.used) {
2727
const content = context.state.stylesheet.content;
2828
const text = content.styles.substring(node.start - content.start, node.end - content.start);
29-
warn(context.state.warnings, node, context.path, 'css-unused-selector', text);
29+
warn(context.state.warnings, node, 'css-unused-selector', text);
3030
}
3131

3232
context.next();

packages/svelte/src/compiler/phases/2-analyze/index.js

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { analyze_css } from './css/css-analyze.js';
2424
import { prune } from './css/css-prune.js';
2525
import { hash } from './utils.js';
2626
import { warn_unused } from './css/css-warn.js';
27+
import { extract_svelte_ignore } from '../../utils/extract_svelte_ignore.js';
2728

2829
/**
2930
* @param {import('#compiler').Script | null} script
@@ -330,7 +331,7 @@ export function analyze_component(root, source, options) {
330331
} else if (declaration !== null && Runes.includes(/** @type {any} */ (name))) {
331332
for (const { node, path } of references) {
332333
if (path.at(-1)?.type === 'CallExpression') {
333-
warn(warnings, node, [], 'store-with-rune-name', store_name);
334+
warn(warnings, node, 'store-with-rune-name', store_name);
334335
}
335336
}
336337
}
@@ -407,7 +408,7 @@ export function analyze_component(root, source, options) {
407408
};
408409

409410
if (!options.customElement && root.options?.customElement) {
410-
warn(analysis.warnings, root.options, [], 'missing-custom-element-compile-option');
411+
warn(analysis.warnings, root.options, 'missing-custom-element-compile-option');
411412
}
412413

413414
if (analysis.runes) {
@@ -433,7 +434,8 @@ export function analyze_component(root, source, options) {
433434
component_slots: new Set(),
434435
expression: null,
435436
private_derived_state: [],
436-
function_depth: scope.function_depth
437+
function_depth: scope.function_depth,
438+
ignores: new Set()
437439
};
438440

439441
walk(
@@ -475,7 +477,8 @@ export function analyze_component(root, source, options) {
475477
component_slots: new Set(),
476478
expression: null,
477479
private_derived_state: [],
478-
function_depth: scope.function_depth
480+
function_depth: scope.function_depth,
481+
ignores: new Set()
479482
};
480483

481484
walk(
@@ -495,7 +498,7 @@ export function analyze_component(root, source, options) {
495498
(r) => r.node !== binding.node && r.path.at(-1)?.type !== 'ExportSpecifier'
496499
);
497500
if (!references.length && !instance.scope.declarations.has(`$${name}`)) {
498-
warn(warnings, binding.node, [], 'unused-export-let', name);
501+
warn(warnings, binding.node, 'unused-export-let', name);
499502
}
500503
}
501504
}
@@ -535,15 +538,15 @@ export function analyze_component(root, source, options) {
535538
type === 'AwaitBlock' ||
536539
type === 'KeyBlock'
537540
) {
538-
warn(warnings, binding.node, [], 'non-state-reference', name);
541+
warn(warnings, binding.node, 'non-state-reference', name);
539542
continue outer;
540543
}
541544
}
542545
continue inner;
543546
}
544547
}
545548

546-
warn(warnings, binding.node, [], 'non-state-reference', name);
549+
warn(warnings, binding.node, 'non-state-reference', name);
547550
continue outer;
548551
}
549552
}
@@ -557,7 +560,13 @@ export function analyze_component(root, source, options) {
557560
for (const element of analysis.elements) {
558561
prune(analysis.css.ast, element);
559562
}
560-
warn_unused(analysis.css.ast, analysis.warnings);
563+
564+
if (
565+
!analysis.css.ast.content.comment ||
566+
!extract_svelte_ignore(analysis.css.ast.content.comment.data).includes('css-unused-selector')
567+
) {
568+
warn_unused(analysis.css.ast, analysis.warnings);
569+
}
561570

562571
outer: for (const element of analysis.elements) {
563572
if (element.metadata.scoped) {
@@ -679,7 +688,7 @@ const legacy_scope_tweaker = {
679688
(d) => d.scope === state.analysis.module.scope && d.declaration_kind !== 'const'
680689
)
681690
) {
682-
warn(state.analysis.warnings, node, path, 'module-script-reactive-declaration');
691+
warn(state.analysis.warnings, node, 'module-script-reactive-declaration');
683692
}
684693

685694
if (
@@ -1045,6 +1054,65 @@ const function_visitor = (node, context) => {
10451054

10461055
/** @type {import('./types').Visitors} */
10471056
const common_visitors = {
1057+
_(node, context) {
1058+
// @ts-expect-error
1059+
const comments = /** @type {import('estree').Comment[]} */ (node.leadingComments);
1060+
1061+
if (comments) {
1062+
/** @type {string[]} */
1063+
const ignores = [];
1064+
1065+
for (const comment of comments) {
1066+
ignores.push(...extract_svelte_ignore(comment.value));
1067+
}
1068+
1069+
if (ignores.length > 0) {
1070+
// @ts-expect-error see below
1071+
node.ignores = new Set([...context.state.ignores, ...ignores]);
1072+
}
1073+
}
1074+
1075+
// @ts-expect-error
1076+
if (node.ignores) {
1077+
context.next({
1078+
...context.state,
1079+
// @ts-expect-error see below
1080+
ignores: node.ignores
1081+
});
1082+
} else if (context.state.ignores.size > 0) {
1083+
// @ts-expect-error
1084+
node.ignores = context.state.ignores;
1085+
}
1086+
},
1087+
Fragment(node, context) {
1088+
/** @type {string[]} */
1089+
let ignores = [];
1090+
1091+
for (const child of node.nodes) {
1092+
if (child.type === 'Text' && child.data.trim() === '') {
1093+
continue;
1094+
}
1095+
1096+
if (child.type === 'Comment') {
1097+
ignores.push(...extract_svelte_ignore(child.data));
1098+
} else {
1099+
const combined_ignores = new Set(context.state.ignores);
1100+
for (const ignore of ignores) combined_ignores.add(ignore);
1101+
1102+
if (combined_ignores.size > 0) {
1103+
// TODO this is a grotesque hack that's made necessary by the fact that
1104+
// we can't call `context.visit(...)` here, because we do the convoluted
1105+
// visitor merging thing. I'm increasingly of the view that we should
1106+
// rearchitect this stuff and have a single visitor per node. It'd be
1107+
// more efficient and much simpler.
1108+
// @ts-expect-error
1109+
child.ignores = combined_ignores;
1110+
}
1111+
1112+
ignores = [];
1113+
}
1114+
}
1115+
},
10481116
Attribute(node, context) {
10491117
if (node.value === true) return;
10501118

@@ -1142,7 +1210,7 @@ const common_visitors = {
11421210
binding.kind === 'derived') &&
11431211
context.state.function_depth === binding.scope.function_depth
11441212
) {
1145-
warn(context.state.analysis.warnings, node, context.path, 'static-state-reference');
1213+
warn(context.state.analysis.warnings, node, 'static-state-reference');
11461214
}
11471215
}
11481216
},

packages/svelte/src/compiler/phases/2-analyze/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export interface AnalysisState {
2222
expression: ExpressionTag | ClassDirective | SpreadAttribute | null;
2323
private_derived_state: string[];
2424
function_depth: number;
25+
ignores: Set<string>;
2526
}
2627

2728
export interface LegacyAnalysisState extends AnalysisState {

0 commit comments

Comments
 (0)