Skip to content

Commit b662c7f

Browse files
authored
[chore] move compiler warnings/errors to dedicate files (#6503)
1 parent f2ca8bc commit b662c7f

21 files changed

+535
-479
lines changed

src/compiler/compile/Component.ts

Lines changed: 31 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import { apply_preprocessor_sourcemap } from '../utils/mapped_code';
3434
import Element from './nodes/Element';
3535
import { DecodedSourceMap, RawSourceMap } from '@ampproject/remapping/dist/types/types';
3636
import { clone } from '../utils/clone';
37+
import compiler_warnings from './compiler_warnings';
38+
import compiler_errors from './compiler_errors';
3739

3840
interface ComponentOptions {
3941
namespace?: string;
@@ -161,10 +163,7 @@ export default class Component {
161163
const svelteOptions = ast.html.children.find(
162164
child => child.name === 'svelte:options'
163165
) || { start: 0, end: 0 };
164-
this.warn(svelteOptions, {
165-
code: 'custom-element-no-tag',
166-
message: 'No custom element \'tag\' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. <svelte:options tag="my-thing"/>. To hide this warning, use <svelte:options tag={null}/>'
167-
});
166+
this.warn(svelteOptions, compiler_warnings.custom_element_no_tag);
168167
}
169168
this.tag = this.component_options.tag || compile_options.tag;
170169
} else {
@@ -478,18 +477,12 @@ export default class Component {
478477

479478
extract_exports(node) {
480479
if (node.type === 'ExportDefaultDeclaration') {
481-
this.error(node, {
482-
code: 'default-export',
483-
message: 'A component cannot have a default export'
484-
});
480+
this.error(node, compiler_errors.default_export);
485481
}
486482

487483
if (node.type === 'ExportNamedDeclaration') {
488484
if (node.source) {
489-
this.error(node, {
490-
code: 'not-implemented',
491-
message: 'A component currently cannot have an export ... from'
492-
});
485+
this.error(node, compiler_errors.not_implemented);
493486
}
494487
if (node.declaration) {
495488
if (node.declaration.type === 'VariableDeclaration') {
@@ -498,10 +491,7 @@ export default class Component {
498491
const variable = this.var_lookup.get(name);
499492
variable.export_name = name;
500493
if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
501-
this.warn(declarator, {
502-
code: 'unused-export-let',
503-
message: `${this.name.name} has unused export property '${name}'. If it is for external reference only, please consider using \`export const ${name}\``
504-
});
494+
this.warn(declarator, compiler_warnings.unused_export_let(this.name.name, name));
505495
}
506496
});
507497
});
@@ -521,10 +511,7 @@ export default class Component {
521511
variable.export_name = specifier.exported.name;
522512

523513
if (variable.writable && !(variable.referenced || variable.referenced_from_script || variable.subscribable)) {
524-
this.warn(specifier, {
525-
code: 'unused-export-let',
526-
message: `${this.name.name} has unused export property '${specifier.exported.name}'. If it is for external reference only, please consider using \`export const ${specifier.exported.name}\``
527-
});
514+
this.warn(specifier, compiler_warnings.unused_export_let(this.name.name, specifier.exported.name));
528515
}
529516
}
530517
});
@@ -555,10 +542,7 @@ export default class Component {
555542
walk(script.content, {
556543
enter(node: Node) {
557544
if (node.type === 'LabeledStatement' && node.label.name === '$') {
558-
component.warn(node as any, {
559-
code: 'module-script-reactive-declaration',
560-
message: '$: has no effect in a module script'
561-
});
545+
component.warn(node as any, compiler_warnings.module_script_reactive_declaration);
562546
}
563547
}
564548
});
@@ -568,10 +552,7 @@ export default class Component {
568552

569553
scope.declarations.forEach((node, name) => {
570554
if (name[0] === '$') {
571-
this.error(node as any, {
572-
code: 'illegal-declaration',
573-
message: 'The $ prefix is reserved, and cannot be used for variable and import names'
574-
});
555+
this.error(node as any, compiler_errors.illegal_declaration);
575556
}
576557

577558
const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
@@ -586,10 +567,7 @@ export default class Component {
586567

587568
globals.forEach((node, name) => {
588569
if (name[0] === '$') {
589-
this.error(node as any, {
590-
code: 'illegal-subscription',
591-
message: 'Cannot reference store value inside <script context="module">'
592-
});
570+
this.error(node as any, compiler_errors.illegal_subscription);
593571
} else {
594572
this.add_var({
595573
name,
@@ -647,10 +625,7 @@ export default class Component {
647625

648626
instance_scope.declarations.forEach((node, name) => {
649627
if (name[0] === '$') {
650-
this.error(node as any, {
651-
code: 'illegal-declaration',
652-
message: 'The $ prefix is reserved, and cannot be used for variable and import names'
653-
});
628+
this.error(node as any, compiler_errors.illegal_declaration);
654629
}
655630

656631
const writable = node.type === 'VariableDeclaration' && (node.kind === 'var' || node.kind === 'let');
@@ -684,10 +659,7 @@ export default class Component {
684659
});
685660
} else if (name[0] === '$') {
686661
if (name === '$' || name[1] === '$') {
687-
this.error(node as any, {
688-
code: 'illegal-global',
689-
message: `${name} is an illegal variable name`
690-
});
662+
this.error(node as any, compiler_errors.illegal_global(name));
691663
}
692664

693665
this.add_var({
@@ -870,10 +842,7 @@ export default class Component {
870842
node.label.name === '$' &&
871843
parent.type !== 'Program'
872844
) {
873-
this.warn(node as any, {
874-
code: 'non-top-level-reactive-declaration',
875-
message: '$: has no effect outside of the top-level'
876-
});
845+
this.warn(node as any, compiler_warnings.non_top_level_reactive_declaration);
877846
}
878847

879848
if (is_reference(node, parent)) {
@@ -887,10 +856,7 @@ export default class Component {
887856

888857
if (name[1] !== '$' && scope.has(name.slice(1)) && scope.find_owner(name.slice(1)) !== this.instance_scope) {
889858
if (!((/Function/.test(parent.type) && prop === 'params') || (parent.type === 'VariableDeclarator' && prop === 'id'))) {
890-
this.error(node as any, {
891-
code: 'contextual-store',
892-
message: 'Stores must be declared at the top level of the component (this may change in a future version of Svelte)'
893-
});
859+
this.error(node as any, compiler_errors.contextual_store);
894860
}
895861
}
896862
}
@@ -955,10 +921,7 @@ export default class Component {
955921

956922
if (variable.export_name) {
957923
// TODO is this still true post-#3539?
958-
component.error(declarator as any, {
959-
code: 'destructured-prop',
960-
message: 'Cannot declare props in destructured declaration'
961-
});
924+
component.error(declarator as any, compiler_errors.destructured_prop);
962925
}
963926

964927
if (variable.subscribable) {
@@ -1248,10 +1211,7 @@ export default class Component {
12481211
variable.is_reactive_dependency = true;
12491212
if (variable.module) {
12501213
should_add_as_dependency = false;
1251-
component.warn(node as any, {
1252-
code: 'module-script-reactive-declaration',
1253-
message: `"${name}" is declared in a module script and will not be reactive`
1254-
});
1214+
component.warn(node as any, compiler_warnings.module_script_variable_reactive_declaration(name));
12551215
}
12561216
}
12571217
const is_writable_or_mutated =
@@ -1316,10 +1276,7 @@ export default class Component {
13161276
if (cycle && cycle.length) {
13171277
const declarationList = lookup.get(cycle[0]);
13181278
const declaration = declarationList[0];
1319-
this.error(declaration.node, {
1320-
code: 'cyclical-reactive-declaration',
1321-
message: `Cyclical dependency detected: ${cycle.join(' → ')}`
1322-
});
1279+
this.error(declaration.node, compiler_errors.cyclical_reactive_declaration(cycle));
13231280
}
13241281

13251282
const add_declaration = declaration => {
@@ -1342,10 +1299,7 @@ export default class Component {
13421299
warn_if_undefined(name: string, node, template_scope: TemplateScope) {
13431300
if (name[0] === '$') {
13441301
if (name === '$' || name[1] === '$' && !is_reserved_keyword(name)) {
1345-
this.error(node, {
1346-
code: 'illegal-global',
1347-
message: `${name} is an illegal variable name`
1348-
});
1302+
this.error(node, compiler_errors.illegal_global(name));
13491303
}
13501304

13511305
this.has_reactive_assignments = true; // TODO does this belong here?
@@ -1359,15 +1313,7 @@ export default class Component {
13591313
if (template_scope && template_scope.names.has(name)) return;
13601314
if (globals.has(name) && node.type !== 'InlineComponent') return;
13611315

1362-
let message = `'${name}' is not defined`;
1363-
if (!this.ast.instance) {
1364-
message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
1365-
}
1366-
1367-
this.warn(node, {
1368-
code: 'missing-declaration',
1369-
message
1370-
});
1316+
this.warn(node, compiler_warnings.missing_declaration(name, !!this.ast.instance));
13711317
}
13721318

13731319
push_ignores(ignores) {
@@ -1395,7 +1341,7 @@ function process_component_options(component: Component, nodes) {
13951341

13961342
const node = nodes.find(node => node.name === 'svelte:options');
13971343

1398-
function get_value(attribute, code, message) {
1344+
function get_value(attribute, {code, message}) {
13991345
const { value } = attribute;
14001346
const chunk = value[0];
14011347

@@ -1421,54 +1367,34 @@ function process_component_options(component: Component, nodes) {
14211367

14221368
switch (name) {
14231369
case 'tag': {
1424-
const code = 'invalid-tag-attribute';
1425-
const message = "'tag' must be a string literal";
1426-
const tag = get_value(attribute, code, message);
1370+
const tag = get_value(attribute, compiler_errors.invalid_tag_attribute);
14271371

14281372
if (typeof tag !== 'string' && tag !== null) {
1429-
component.error(attribute, { code, message });
1373+
component.error(attribute, compiler_errors.invalid_tag_attribute);
14301374
}
14311375

14321376
if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
1433-
component.error(attribute, {
1434-
code: 'invalid-tag-property',
1435-
message: "tag name must be two or more words joined by the '-' character"
1436-
});
1377+
component.error(attribute, compiler_errors.invalid_tag_property);
14371378
}
14381379

14391380
if (tag && !component.compile_options.customElement) {
1440-
component.warn(attribute, {
1441-
code: 'missing-custom-element-compile-options',
1442-
message: "The 'tag' option is used when generating a custom element. Did you forget the 'customElement: true' compile option?"
1443-
});
1381+
component.warn(attribute, compiler_warnings.missing_custom_element_compile_options);
14441382
}
14451383

14461384
component_options.tag = tag;
14471385
break;
14481386
}
14491387

14501388
case 'namespace': {
1451-
const code = 'invalid-namespace-attribute';
1452-
const message = "The 'namespace' attribute must be a string literal representing a valid namespace";
1453-
const ns = get_value(attribute, code, message);
1389+
const ns = get_value(attribute, compiler_errors.invalid_namespace_attribute);
14541390

14551391
if (typeof ns !== 'string') {
1456-
component.error(attribute, { code, message });
1392+
component.error(attribute, compiler_errors.invalid_namespace_attribute);
14571393
}
14581394

14591395
if (valid_namespaces.indexOf(ns) === -1) {
14601396
const match = fuzzymatch(ns, valid_namespaces);
1461-
if (match) {
1462-
component.error(attribute, {
1463-
code: 'invalid-namespace-property',
1464-
message: `Invalid namespace '${ns}' (did you mean '${match}'?)`
1465-
});
1466-
} else {
1467-
component.error(attribute, {
1468-
code: 'invalid-namespace-property',
1469-
message: `Invalid namespace '${ns}'`
1470-
});
1471-
}
1397+
component.error(attribute, compiler_errors.invalid_namespace_property(ns, match));
14721398
}
14731399

14741400
component_options.namespace = ns;
@@ -1478,29 +1404,21 @@ function process_component_options(component: Component, nodes) {
14781404
case 'accessors':
14791405
case 'immutable':
14801406
case 'preserveWhitespace': {
1481-
const code = `invalid-${name}-value`;
1482-
const message = `${name} attribute must be true or false`;
1483-
const value = get_value(attribute, code, message);
1407+
const value = get_value(attribute, compiler_errors.invalid_attribute_value(name));
14841408

14851409
if (typeof value !== 'boolean') {
1486-
component.error(attribute, { code, message });
1410+
component.error(attribute, compiler_errors.invalid_attribute_value(name));
14871411
}
14881412

14891413
component_options[name] = value;
14901414
break;
14911415
}
14921416

14931417
default:
1494-
component.error(attribute, {
1495-
code: 'invalid-options-attribute',
1496-
message: '<svelte:options> unknown attribute'
1497-
});
1418+
component.error(attribute, compiler_errors.invalid_options_attribute_unknown);
14981419
}
14991420
} else {
1500-
component.error(attribute, {
1501-
code: 'invalid-options-attribute',
1502-
message: "<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes"
1503-
});
1421+
component.error(attribute, compiler_errors.invalid_options_attribute);
15041422
}
15051423
});
15061424
}

0 commit comments

Comments
 (0)