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 117x 117x 117x 98x 98x 117x 117x 74x 1x 1x 74x 116x 116x 116x 116x 116x 117x 32x 32x 114x 22x 22x 1x 1x 22x 117x 1x 1x 31x 108x 14x 14x 105x 117x 1x 117x 13x 13x 13x 13x 13x 1x 1x 13x 117x  
/** @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);
		}
	}
}