convert special_element errors

pull/11294/head
Rich Harris 2 years ago
parent e2963d5f42
commit 5d85ba708d

@ -1,10 +1,10 @@
## invalid_svelte_option_attribute
<svelte:options> can only receive static attributes
`<svelte:options>` can only receive static attributes
## invalid_svelte_option_namespace
Unsupported <svelte:option> value for "namespace". Valid values are "html", "svg" or "foreign".
Unsupported `<svelte:option>` value for "namespace". Valid values are "html", "svg" or "foreign"
## tag_option_deprecated
@ -12,55 +12,55 @@ Unsupported <svelte:option> value for "namespace". Valid values are "html", "svg
## invalid_svelte_option_runes
Unsupported <svelte:option> value for "runes". Valid values are true or false.
Unsupported `<svelte:option>` value for "runes". Valid values are true or false
## invalid_svelte_option_accessors
TODO
Unsupported `<svelte:option>` value for "accessors". Valid values are true or false
## invalid_svelte_option_preserveWhitespace
TODO
Unsupported `<svelte:option>` value for "preserveWhitespace". Valid values are true or false
## invalid_svelte_option_immutable
TODO
Unsupported `<svelte:option>` value for "immutable". Valid values are true or false
## invalid_tag_property
TODO
Tag name must be two or more words joined by the "-" character
## invalid_svelte_option_customElement
TODO
"customElement" must be a string literal defining a valid custom element name or an object of the form { tag: string; shadow?: "open" | "none"; props?: { [key: string]: { attribute?: string; reflect?: boolean; type: .. } } }
## invalid_customElement_props_attribute
TODO
"props" must be a statically analyzable object literal of the form "{ [key: string]: { attribute?: string; reflect?: boolean; type?: "String" | "Boolean" | "Number" | "Array" | "Object" }"
## invalid_customElement_shadow_attribute
TODO
"shadow" must be either "open" or "none"
## unknown_svelte_option_attribute
<svelte:options> unknown attribute '%name%'
`<svelte:options>` unknown attribute '%name%'
## illegal_svelte_head_attribute
TODO
`<svelte:head>` cannot have attributes nor directives
## invalid_svelte_fragment_attribute
<svelte:fragment> can only have a slot attribute and (optionally) a let: directive
`<svelte:fragment>` can only have a slot attribute and (optionally) a let: directive
## invalid_svelte_fragment_slot
<svelte:fragment> slot attribute must have a static value
`<svelte:fragment>` slot attribute must have a static value
## invalid_svelte_fragment_placement
<svelte:fragment> must be the direct child of a component
`<svelte:fragment>` must be the direct child of a component
## invalid_svelte_element_placement
@ -72,15 +72,15 @@ A component can only have one <%name%> element
## invalid_self_placement
<svelte:self> components can only exist inside {#if} blocks, {#each} blocks, {#snippet} blocks or slots passed to components
`<svelte:self>` components can only exist inside {#if} blocks, {#each} blocks, {#snippet} blocks or slots passed to components
## missing_svelte_element_definition
<svelte:element> must have a 'this' attribute
`<svelte:element>` must have a 'this' attribute
## missing_svelte_component_definition
<svelte:component> must have a 'this' attribute
`<svelte:component>` must have a 'this' attribute
## invalid_svelte_element_definition
@ -92,8 +92,8 @@ Invalid component definition — must be an {expression}
## invalid_svelte_tag
Valid <svelte:...> tag names are %list(tags)%%match ? ' (did you mean ' + match + '?)' : ''%
Valid `<svelte:...>` tag names are %list%
## conflicting_slot_usage
Cannot use <slot> syntax and {@render ...} tags in the same component. Migrate towards {@render ...} tags completely.
Cannot use `<slot>` syntax and `{@render ...}` tags in the same component. Migrate towards `{@render ...}` tags completely.

@ -168,12 +168,10 @@ function transform(name, dest) {
for (let i = 0; i < parts.length; i += 1) {
const part = parts[i];
if (i % 2 === 0) {
const str = part.replace(/(`|\$)/g, '\\$1');
quasis.push({
type: 'TemplateElement',
value: {
raw: part,
cooked: part
},
value: { raw: str, cooked: str },
tail: i === parts.length - 1
});
} else {

@ -53,7 +53,7 @@ export class CompileError extends Error {
* @param {string} message
* @returns {never}
*/
function __error(node, code, message) {
function e(node, code, message) {
const start = typeof node === 'number' ? node : node?.start;
const end = typeof node === 'number' ? node : node?.end;
@ -70,5 +70,5 @@ function __error(node, code, message) {
* @returns {never}
*/
export function CODE(node, PARAMETER) {
__error(node, 'CODE', MESSAGE);
e(node, 'CODE', MESSAGE);
}

@ -279,7 +279,6 @@ const const_tag = {
/** @satisfies {Errors} */
const errors = {
...internal,
...special_elements,
...runes,
...elements,
...components,

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
import { namespace_svg } from '../../../../constants.js';
import { error } from '../../../errors-tmp.js';
import * as e from '../../../errors.js';
const regex_valid_tag_name = /^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/;
@ -22,24 +22,18 @@ export default function read_options(node) {
for (const attribute of node.attributes) {
if (attribute.type !== 'Attribute') {
error(attribute, 'invalid-svelte-option-attribute');
e.invalid_svelte_option_attribute(attribute);
}
const { name } = attribute;
switch (name) {
case 'runes': {
const value = get_static_value(attribute, () =>
error(attribute, 'invalid-svelte-option-runes')
);
if (typeof value !== 'boolean') {
error(attribute, 'invalid-svelte-option-runes');
}
component_options.runes = value;
component_options.runes = get_boolean_value(attribute, e.invalid_svelte_option_runes);
break;
}
case 'tag': {
error(attribute, 'tag-option-deprecated');
e.tag_option_deprecated(attribute);
break; // eslint doesn't know this is unnecessary
}
case 'customElement': {
@ -48,9 +42,9 @@ export default function read_options(node) {
const { value } = attribute;
if (value === true) {
error(attribute, 'invalid-svelte-option-customElement');
e.invalid_svelte_option_customElement(attribute);
} else if (value[0].type === 'Text') {
const tag = get_static_value(attribute, () => error(attribute, 'invalid-tag-property'));
const tag = get_static_value(attribute, () => e.invalid_tag_property(attribute));
validate_tag(attribute, tag);
ce.tag = tag;
component_options.customElement = ce;
@ -61,7 +55,7 @@ export default function read_options(node) {
if (value[0].expression.type === 'Literal' && value[0].expression.value === null) {
break;
}
error(attribute, 'invalid-svelte-option-customElement');
e.invalid_svelte_option_customElement(attribute);
}
/** @type {Array<[string, any]>} */
@ -72,7 +66,7 @@ export default function read_options(node) {
property.computed ||
property.key.type !== 'Identifier'
) {
error(attribute, 'invalid-svelte-option-customElement');
e.invalid_svelte_option_customElement(attribute);
}
properties.push([property.key.name, property.value]);
}
@ -83,13 +77,13 @@ export default function read_options(node) {
validate_tag(tag, tag_value);
ce.tag = tag_value;
} else {
error(attribute, 'invalid-svelte-option-customElement');
e.invalid_svelte_option_customElement(attribute);
}
const props = properties.find(([name]) => name === 'props')?.[1];
if (props) {
if (props.type !== 'ObjectExpression') {
error(attribute, 'invalid-customElement-props-attribute');
e.invalid_customElement_props_attribute(attribute);
}
ce.props = {};
for (const property of /** @type {import('estree').ObjectExpression} */ (props)
@ -100,7 +94,7 @@ export default function read_options(node) {
property.key.type !== 'Identifier' ||
property.value.type !== 'ObjectExpression'
) {
error(attribute, 'invalid-customElement-props-attribute');
e.invalid_customElement_props_attribute(attribute);
}
ce.props[property.key.name] = {};
for (const prop of property.value.properties) {
@ -110,7 +104,7 @@ export default function read_options(node) {
prop.key.type !== 'Identifier' ||
prop.value.type !== 'Literal'
) {
error(attribute, 'invalid-customElement-props-attribute');
e.invalid_customElement_props_attribute(attribute);
}
if (prop.key.name === 'type') {
@ -119,21 +113,21 @@ export default function read_options(node) {
/** @type {string} */ (prop.value.value)
) === -1
) {
error(attribute, 'invalid-customElement-props-attribute');
e.invalid_customElement_props_attribute(attribute);
}
ce.props[property.key.name].type = /** @type {any} */ (prop.value.value);
} else if (prop.key.name === 'reflect') {
if (typeof prop.value.value !== 'boolean') {
error(attribute, 'invalid-customElement-props-attribute');
e.invalid_customElement_props_attribute(attribute);
}
ce.props[property.key.name].reflect = prop.value.value;
} else if (prop.key.name === 'attribute') {
if (typeof prop.value.value !== 'string') {
error(attribute, 'invalid-customElement-props-attribute');
e.invalid_customElement_props_attribute(attribute);
}
ce.props[property.key.name].attribute = prop.value.value;
} else {
error(attribute, 'invalid-customElement-props-attribute');
e.invalid_customElement_props_attribute(attribute);
}
}
}
@ -143,7 +137,7 @@ export default function read_options(node) {
if (shadow) {
const shadowdom = shadow?.value;
if (shadowdom !== 'open' && shadowdom !== 'none') {
error(shadow, 'invalid-customElement-shadow-attribute');
e.invalid_customElement_shadow_attribute(shadow);
}
ce.shadow = shadowdom;
}
@ -158,10 +152,10 @@ export default function read_options(node) {
}
case 'namespace': {
const value = get_static_value(attribute, () =>
error(attribute, 'invalid-svelte-option-namespace')
e.invalid_svelte_option_namespace(attribute)
);
if (typeof value !== 'string') {
error(attribute, 'invalid-svelte-option-namespace');
e.invalid_svelte_option_namespace(attribute);
}
if (value === namespace_svg) {
@ -169,43 +163,34 @@ export default function read_options(node) {
} else if (value === 'html' || value === 'svg' || value === 'foreign') {
component_options.namespace = value;
} else {
error(attribute, 'invalid-svelte-option-namespace');
e.invalid_svelte_option_namespace(attribute);
}
break;
}
case 'immutable': {
const value = get_static_value(attribute, () =>
error(attribute, 'invalid-svelte-option-immutable')
component_options.immutable = get_boolean_value(
attribute,
e.invalid_svelte_option_immutable
);
if (typeof value !== 'boolean') {
error(attribute, 'invalid-svelte-option-immutable');
}
component_options.immutable = value;
break;
}
case 'preserveWhitespace': {
const value = get_static_value(attribute, () =>
error(attribute, 'invalid-svelte-option-preserveWhitespace')
component_options.preserveWhitespace = get_boolean_value(
attribute,
e.invalid_svelte_option_preserveWhitespace
);
if (typeof value !== 'boolean') {
error(attribute, 'invalid-svelte-option-preserveWhitespace');
}
component_options.preserveWhitespace = value;
break;
}
case 'accessors': {
const value = get_static_value(attribute, () =>
error(attribute, 'invalid-svelte-option-accessors')
component_options.accessors = get_boolean_value(
attribute,
e.invalid_svelte_option_accessors
);
if (typeof value !== 'boolean') {
error(attribute, 'invalid-svelte-option-accessors');
}
component_options.accessors = value;
break;
}
default:
error(attribute, 'unknown-svelte-option-attribute', name);
e.unknown_svelte_option_attribute(attribute, name);
}
}
@ -230,6 +215,18 @@ function get_static_value(attribute, error) {
return chunk.expression.value;
}
/**
* @param {any} attribute
* @param {(attribute: any) => never} error
*/
function get_boolean_value(attribute, error) {
const value = get_static_value(attribute, () => error(attribute));
if (typeof value !== 'boolean') {
error(attribute);
}
return value;
}
/**
* @param {any} attribute
* @param {string} tag
@ -237,10 +234,10 @@ function get_static_value(attribute, error) {
*/
function validate_tag(attribute, tag) {
if (typeof tag !== 'string' && tag !== null) {
error(attribute, 'invalid-tag-property');
e.invalid_tag_property(attribute);
}
if (tag && !regex_valid_tag_name.test(tag)) {
error(attribute, 'invalid-tag-property');
e.invalid_tag_property(attribute);
}
// TODO do we still need this?
// if (tag && !component.compile_options.customElement) {

@ -113,11 +113,11 @@ export default function tag(parser) {
}
} else {
if (name in parser.meta_tags) {
error(start, 'duplicate-svelte-element', name);
e.duplicate_svelte_element(start, name);
}
if (parent.type !== 'Root') {
error(start, 'invalid-svelte-element-placement', name);
e.invalid_svelte_element_placement(start, name);
}
parser.meta_tags[name] = true;
@ -238,7 +238,7 @@ export default function tag(parser) {
(attr) => attr.type === 'Attribute' && attr.name === 'this'
);
if (index === -1) {
error(start, 'missing-svelte-component-definition');
e.missing_svelte_component_definition(start);
}
const definition = /** @type {import('#compiler').Attribute} */ (
@ -249,7 +249,7 @@ export default function tag(parser) {
definition.value.length !== 1 ||
definition.value[0].type === 'Text'
) {
error(definition.start, 'invalid-svelte-component-definition');
e.invalid_svelte_component_definition(definition.start);
}
element.expression = definition.value[0].expression;
@ -261,14 +261,14 @@ export default function tag(parser) {
(attr) => attr.type === 'Attribute' && attr.name === 'this'
);
if (index === -1) {
error(start, 'missing-svelte-element-definition');
e.missing_svelte_element_definition(start);
}
const definition = /** @type {import('#compiler').Attribute} */ (
element.attributes.splice(index, 1)[0]
);
if (definition.value === true || definition.value.length !== 1) {
error(definition.start, 'invalid-svelte-element-definition');
e.invalid_svelte_element_definition(definition.start);
}
const chunk = definition.value[0];
element.tag =
@ -392,7 +392,7 @@ function read_tag_name(parser) {
}
if (!legal) {
error(start, 'invalid-self-placement');
e.invalid_self_placement(start);
}
return 'svelte:self';
@ -409,7 +409,10 @@ function read_tag_name(parser) {
if (name.startsWith('svelte:')) {
const match = fuzzymatch(name.slice(7), valid_meta_tags);
error(start, 'invalid-svelte-tag', valid_meta_tags, match);
if (match === null) {
}
const list = `${valid_meta_tags.slice(0, -1).join(', ')} or ${valid_meta_tags[valid_meta_tags.length - 1]}`;
e.invalid_svelte_tag(start, list);
}
if (!valid_tag_name.test(name)) {

@ -505,7 +505,7 @@ export function analyze_component(root, source, options) {
}
if (analysis.uses_render_tags && (analysis.uses_slots || analysis.slot_names.size > 0)) {
error(analysis.slot_names.values().next().value, 'conflicting-slot-usage');
e.conflicting_slot_usage(analysis.slot_names.values().next().value);
}
// warn on any nonstate declarations that are a) reassigned and b) referenced in the template

@ -679,7 +679,7 @@ const validation = {
SvelteHead(node) {
const attribute = node.attributes[0];
if (attribute) {
error(attribute, 'illegal-svelte-head-attribute');
e.illegal_svelte_head_attribute(attribute);
}
},
SvelteElement(node, context) {
@ -692,7 +692,7 @@ const validation = {
SvelteFragment(node, context) {
const parent = context.path.at(-2);
if (parent?.type !== 'Component' && parent?.type !== 'SvelteComponent') {
error(node, 'invalid-svelte-fragment-placement');
e.invalid_svelte_fragment_placement(node);
}
for (const attribute of node.attributes) {
@ -701,7 +701,7 @@ const validation = {
validate_slot_attribute(context, attribute);
}
} else if (attribute.type !== 'LetDirective') {
error(attribute, 'invalid-svelte-fragment-attribute');
e.invalid_svelte_fragment_attribute(attribute);
}
}
},

Loading…
Cancel
Save