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

100% Statements 50/50
90.9% Branches 10/11
100% Functions 1/1
100% Lines 47/47

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 482x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 14446x 14446x 14446x 14446x 14446x 14446x 14446x 14446x 1607x 14446x 1564x 1564x 1564x 1564x 1564x 108x 108x 108x 108x 108x 108x 108x 2x 1x 1x 1x 1x 1x 108x 1562x 1564x 2x 2x 1564x 14446x 14446x  
/** @import { Expression, Identifier } from 'estree' */
/** @import { Context } from '../types' */
import is_reference from 'is-reference';
import * as e from '../../../errors.js';
import { Runes } from '../../constants.js';
 
/**
 * @param {Identifier} node
 * @param {Context} context
 */
export function Identifier(node, context) {
	if (context.state.analysis.runes) {
		let i = context.path.length;
		let parent = /** @type {Expression} */ (context.path[--i]);
 
		if (
			Runes.includes(/** @type {Runes[number]} */ (node.name)) &&
			is_reference(node, parent) &&
			context.state.scope.get(node.name) === null &&
			context.state.scope.get(node.name.slice(1)) === null
		) {
			/** @type {Expression} */
			let current = node;
			let name = node.name;
 
			while (parent.type === 'MemberExpression') {
				if (parent.computed) e.rune_invalid_computed_property(parent);
				name += `.${/** @type {Identifier} */ (parent.property).name}`;
 
				current = parent;
				parent = /** @type {Expression} */ (context.path[--i]);
 
				if (!Runes.includes(/** @type {Runes[number]} */ (name))) {
					if (name === '$effect.active') {
						e.rune_renamed(parent, '$effect.active', '$effect.tracking');
					}
 
					e.rune_invalid_name(parent, name);
				}
			}
 
			if (parent.type !== 'CallExpression') {
				e.rune_missing_parentheses(current);
			}
		}
	}
}