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

100% Statements 57/57
100% Branches 25/25
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 108x 108x 108x 94x 94x 108x 108x 70x 1x 1x 70x 107x 107x 107x 107x 107x 108x 26x 26x 104x 18x 18x 1x 1x 18x 108x 1x 1x 25x 102x 12x 12x 101x 108x 1x 108x 11x 11x 11x 11x 11x 1x 1x 11x 108x  
/** @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);
		}
	}
}