function validate_identifier_name(binding, function_depth) {
	if (!binding) return;

	const declaration_kind = binding.declaration_kind;

	if (
		declaration_kind !== 'synthetic' &&
		declaration_kind !== 'param' &&
		declaration_kind !== 'rest_param' &&
		(!function_depth || function_depth <= 1)
	) {
		const node = binding.node;

		if (node.name === '$') {
			e.dollar_binding_invalid(node);
		} else if (
			node.name.startsWith('$') &&
			// import type { $Type } from "" - these are normally already filtered out,
			// but for the migration they aren't, and throwing here is preventing the migration to complete
			// TODO -> once migration script is gone we can remove this check
			!(
				binding.initial?.type === 'ImportDeclaration' &&
				/** @type {any} */ (binding.initial).importKind === 'type'
			)
		) {
			e.dollar_prefix_invalid(node);
		}
	}
}
Checks if the name is valid, which it is when it's not starting with (or is) a dollar sign or if it's a function parameter.
The second argument is the depth of the scope, which is there for backwards compatibility reasons: In Svelte 4, you
were allowed to define `$`-prefixed variables anywhere below the top level of components. Once legacy mode is gone, this
argument can be removed / the call sites adjusted accordingly.
@param {Binding | null} binding
@param {number | undefined} [function_depth]