Skip to content

Commit d9569d0

Browse files
feat: add ability to ignore warnings through compiler option (#12296)
* feat: add ability to ignore warnings through compiler option Some people want to disable certain warnings for their whole application without having to add svelte-ignore comments everywhere. This new option makes that possible. closes #9188 part of sveltejs/language-tools#650 * make it a function * singular * warningFilter * make internal filter non-nullable * Update .changeset/little-seals-reflect.md * filter_warning -> warning_filter, for symmetry with public option * fix --------- Co-authored-by: Rich Harris <rich.harris@vercel.com>
1 parent c92620d commit d9569d0

File tree

12 files changed

+104
-14
lines changed

12 files changed

+104
-14
lines changed

.changeset/little-seals-reflect.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
feat: add ability to ignore warnings through `warningFilter` compiler option

packages/svelte/scripts/process-messages/templates/compile-warnings.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { warnings, ignore_stack, ignore_map } from './state.js';
1+
import { warnings, ignore_stack, ignore_map, warning_filter } from './state.js';
22
import { CompileDiagnostic } from './utils/compile_diagnostic.js';
33

44
/** @typedef {{ start?: number, end?: number }} NodeLike */
@@ -28,13 +28,15 @@ function w(node, code, message) {
2828
}
2929
if (stack && stack.at(-1)?.has(code)) return;
3030

31-
warnings.push(
32-
new InternalCompileWarning(
33-
code,
34-
message,
35-
node && node.start !== undefined ? [node.start, node.end ?? node.start] : undefined
36-
)
31+
const warning = new InternalCompileWarning(
32+
code,
33+
message,
34+
node && node.start !== undefined ? [node.start, node.end ?? node.start] : undefined
3735
);
36+
37+
if (!warning_filter(warning)) return;
38+
39+
warnings.push(warning);
3840
}
3941

4042
export const codes = CODES;

packages/svelte/src/compiler/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export { default as preprocess } from './preprocess/index.js';
2020
* @returns {CompileResult}
2121
*/
2222
export function compile(source, options) {
23+
state.reset_warning_filter(options.warningFilter);
2324
const validated = validate_component_options(options, '');
2425
state.reset(source, validated);
2526

@@ -58,6 +59,7 @@ export function compile(source, options) {
5859
* @returns {CompileResult}
5960
*/
6061
export function compileModule(source, options) {
62+
state.reset_warning_filter(options.warningFilter);
6163
const validated = validate_module_options(options, '');
6264
state.reset(source, validated);
6365

@@ -103,6 +105,7 @@ export function compileModule(source, options) {
103105
* @returns {Root | LegacyRoot}
104106
*/
105107
export function parse(source, { filename, rootDir, modern } = {}) {
108+
state.reset_warning_filter(() => false);
106109
state.reset(source, { filename, rootDir }); // TODO it's weird to require filename/rootDir here. reconsider the API
107110

108111
const ast = _parse(source);

packages/svelte/src/compiler/migrate/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { parse } from '../phases/1-parse/index.js';
1010
import { analyze_component } from '../phases/2-analyze/index.js';
1111
import { validate_component_options } from '../validate-options.js';
1212
import { get_rune } from '../phases/scope.js';
13-
import { reset } from '../state.js';
13+
import { reset, reset_warning_filter } from '../state.js';
1414
import { extract_identifiers } from '../utils/ast.js';
1515
import { regex_is_valid_identifier } from '../phases/patterns.js';
1616
import { migrate_svelte_ignore } from '../utils/extract_svelte_ignore.js';
@@ -24,6 +24,7 @@ import { migrate_svelte_ignore } from '../utils/extract_svelte_ignore.js';
2424
*/
2525
export function migrate(source) {
2626
try {
27+
reset_warning_filter(() => false);
2728
reset(source, { filename: 'migrate.svelte' });
2829

2930
let parsed = parse(source);

packages/svelte/src/compiler/state.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** @import { SvelteNode } from './types' */
1+
/** @import { CompileOptions, SvelteNode } from './types' */
22
/** @import { Warning } from '#compiler' */
33
import { getLocator } from 'locate-character';
44

@@ -22,6 +22,9 @@ export let source;
2222

2323
export let locator = getLocator('', { offsetLine: 1 });
2424

25+
/** @type {NonNullable<CompileOptions['warningFilter']>} */
26+
export let warning_filter;
27+
2528
/**
2629
* The current stack of ignored warnings
2730
* @type {Set<string>[]}
@@ -48,6 +51,14 @@ export function pop_ignore() {
4851
ignore_stack.pop();
4952
}
5053

54+
/**
55+
*
56+
* @param {(warning: Warning) => boolean} fn
57+
*/
58+
export function reset_warning_filter(fn = () => true) {
59+
warning_filter = fn;
60+
}
61+
5162
/**
5263
* @param {string} _source
5364
* @param {{ filename?: string, rootDir?: string }} options

packages/svelte/src/compiler/types/index.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,16 @@ export interface ModuleCompileOptions {
203203
* Used for debugging hints and sourcemaps. Your bundler plugin will set it automatically.
204204
*/
205205
filename?: string;
206-
207206
/**
208207
* Used for ensuring filenames don't leak filesystem information. Your bundler plugin will set it automatically.
209208
* @default process.cwd() on node-like environments, undefined elsewhere
210209
*/
211210
rootDir?: string;
211+
/**
212+
* A function that gets a `Warning` as an argument and returns a boolean.
213+
* Use this to filter out warnings. Return `true` to keep the warning, `false` to discard it.
214+
*/
215+
warningFilter?: (warning: Warning) => boolean;
212216
}
213217

214218
// The following two somewhat scary looking types ensure that certain types are required but can be undefined still

packages/svelte/src/compiler/validate-options.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ export const validate_component_options =
104104

105105
hmr: boolean(false),
106106

107+
warningFilter: fun(() => true),
108+
107109
sourcemap: validator(undefined, (input) => {
108110
// Source maps can take on a variety of values, including string, JSON, map objects from magic-string and source-map,
109111
// so there's no good way to check type validity here
@@ -259,6 +261,20 @@ function string(fallback, allow_empty = true) {
259261
});
260262
}
261263

264+
/**
265+
* @param {string[]} fallback
266+
* @returns {Validator}
267+
*/
268+
function string_array(fallback) {
269+
return validator(fallback, (input, keypath) => {
270+
if (input && !Array.isArray(input)) {
271+
throw_error(`${keypath} should be a string array, if specified`);
272+
}
273+
274+
return input;
275+
});
276+
}
277+
262278
/**
263279
* @param {boolean | undefined} fallback
264280
* @returns {Validator}

packages/svelte/src/compiler/warnings.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
/* This file is generated by scripts/process-messages/index.js. Do not edit! */
22

3-
import { warnings, ignore_stack, ignore_map } from './state.js';
3+
import {
4+
warnings,
5+
ignore_stack,
6+
ignore_map,
7+
warning_filter
8+
} from './state.js';
9+
410
import { CompileDiagnostic } from './utils/compile_diagnostic.js';
511

612
/** @typedef {{ start?: number, end?: number }} NodeLike */
@@ -30,7 +36,11 @@ function w(node, code, message) {
3036
}
3137

3238
if (stack && stack.at(-1)?.has(code)) return;
33-
warnings.push(new InternalCompileWarning(code, message, node && node.start !== undefined ? [node.start, node.end ?? node.start] : undefined));
39+
40+
const warning = new InternalCompileWarning(code, message, node && node.start !== undefined ? [node.start, node.end ?? node.start] : undefined);
41+
42+
if (!warning_filter(warning)) return;
43+
warnings.push(warning);
3444
}
3545

3646
export const codes = [
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
compileOptions: {
5+
warningFilter: (warning) =>
6+
!['a11y_missing_attribute', 'a11y_misplaced_scope'].includes(warning.code)
7+
}
8+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<div>
2+
<img src="this-is-fine.jpg" />
3+
<marquee>but this is still discouraged</marquee>
4+
</div>
5+
6+
<div scope></div>
7+
8+
<img src="potato.jpg" />
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"code": "a11y_distracting_elements",
4+
"end": {
5+
"column": 49,
6+
"line": 3
7+
},
8+
"message": "Avoid `<marquee>` elements",
9+
"start": {
10+
"column": 1,
11+
"line": 3
12+
}
13+
}
14+
]

packages/svelte/types/index.d.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -864,12 +864,16 @@ declare module 'svelte/compiler' {
864864
* Used for debugging hints and sourcemaps. Your bundler plugin will set it automatically.
865865
*/
866866
filename?: string;
867-
868867
/**
869868
* Used for ensuring filenames don't leak filesystem information. Your bundler plugin will set it automatically.
870869
* @default process.cwd() on node-like environments, undefined elsewhere
871870
*/
872871
rootDir?: string;
872+
/**
873+
* A function that gets a `Warning` as an argument and returns a boolean.
874+
* Use this to filter out warnings. Return `true` to keep the warning, `false` to discard it.
875+
*/
876+
warningFilter?: (warning: Warning) => boolean;
873877
}
874878

875879
type DeclarationKind =
@@ -2673,12 +2677,16 @@ declare module 'svelte/types/compiler/interfaces' {
26732677
* Used for debugging hints and sourcemaps. Your bundler plugin will set it automatically.
26742678
*/
26752679
filename?: string;
2676-
26772680
/**
26782681
* Used for ensuring filenames don't leak filesystem information. Your bundler plugin will set it automatically.
26792682
* @default process.cwd() on node-like environments, undefined elsewhere
26802683
*/
26812684
rootDir?: string;
2685+
/**
2686+
* A function that gets a `Warning` as an argument and returns a boolean.
2687+
* Use this to filter out warnings. Return `true` to keep the warning, `false` to discard it.
2688+
*/
2689+
warningFilter?: (warning: Warning_1) => boolean;
26822690
}
26832691
/**
26842692
* - `html` — the default, for e.g. `<div>` or `<span>`

0 commit comments

Comments
 (0)