All files / src/compiler/phases/2-analyze/visitors SnippetBlock.js

100% Statements 57/57
100% Branches 24/24
100% Functions 1/1
100% Lines 55/55

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 562x 2x 2x 2x 2x 2x 2x 2x 2x 2x 111x 111x 111x 96x 96x 111x 111x 72x 1x 1x 72x 110x 110x 110x 110x 110x 111x 28x 28x 106x 20x 20x 1x 1x 20x 111x 1x 1x 27x 104x 12x 12x 103x 111x 1x 111x 11x 11x 11x 11x 11x 1x 1x 11x 111x  
/** @import { AST } from '#compiler' */
/** @import { Context } from '../types' */
import { validate_block_not_empty, validate_opening_tag } from './shared/utils.js';
import * as e from '../../../errors.js';
 
/**
 * @param {AST.SnippetBlock} node
 * @param {Context} context
 */
export function SnippetBlock(node, context) {
	validate_block_not_empty(node.body, context);
 
	if (context.state.analysis.runes) {
		validate_opening_tag(node, context.state, '#');
	}
 
	for (const arg of node.parameters) {
		if (arg.type === 'RestElement') {
			e.snippet_invalid_rest_parameter(arg);
		}
	}
 
	context.next({ ...context.state, parent_element: null });
 
	const { path } = context;
	const parent = path.at(-2);
	if (!parent) return;
 
	if (
		parent.type === 'Component' &&
		parent.attributes.some(
			(attribute) =>
				(attribute.type === 'Attribute' || attribute.type === 'BindDirective') &&
				attribute.name === node.expression.name
		)
	) {
		e.snippet_shadowing_prop(node, node.expression.name);
	}
 
	if (node.expression.name !== 'children') return;
 
	if (
		parent.type === 'Component' ||
		parent.type === 'SvelteComponent' ||
		parent.type === 'SvelteSelf'
	) {
		if (
			parent.fragment.nodes.some(
				(node) => node.type !== 'SnippetBlock' && (node.type !== 'Text' || node.data.trim())
			)
		) {
			e.snippet_conflict(node);
		}
	}
}