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 106x 106x 106x 92x 92x 106x 106x 70x 1x 1x 70x 105x 105x 105x 105x 105x 106x 26x 26x 102x 18x 18x 1x 1x 18x 106x 1x 1x 25x 100x 12x 12x 99x 106x 1x 106x 11x 11x 11x 11x 11x 1x 1x 11x 106x  
/** @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);
		}
	}
}