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

100% Statements 57/57
100% Branches 27/27
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 115x 115x 115x 96x 96x 115x 115x 72x 1x 1x 72x 114x 114x 114x 114x 114x 115x 30x 30x 112x 20x 20x 1x 1x 20x 115x 1x 1x 29x 106x 12x 12x 103x 115x 1x 115x 11x 11x 11x 11x 11x 1x 1x 11x 115x  
/** @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);
		}
	}
}