vize_l2 0.485.0

L2 - the Davinci semantic IR (codename Disegno): the neutral op family every input dialect lowers into
Documentation
use super::{Allocator, BindingPattern, GetSpan, Lang, NativeForInput, NativeForRefusal, Span};
use vize_l0::config::{VueDialect, VueVersion};
use vize_l1::container::{Vue, vue::DescriptorOptions};
use vize_l1::markup::NativeTemplateComponent;

fn selected<'a>(arena: &'a Allocator, source: &'a str) -> NativeTemplateComponent<'a> {
    let descriptor = Vue.observe_descriptor(
        arena,
        source,
        DescriptorOptions {
            version: VueVersion::V3,
            dialect: VueDialect::Vue,
            template: vize_l1::SurfaceParseOptions::default(),
        },
    );
    NativeTemplateComponent::parse_in(arena, descriptor.admitted().unwrap())
        .unwrap()
        .unwrap()
}

#[test]
fn one_original_header_visit_parks_both_observations_and_joins_the_same_token() {
    let arena = Allocator::default();
    let source = "頭<script lang='ts'></script><template><b v-for='(α, key) in items'/></template>";
    let selected = selected(&arena, source);
    let element = selected.children().next().unwrap().into_element().unwrap();
    let mut visits = 0;
    for attribute in element.attributes() {
        visits += 1;
        let operand = selected
            .observe_attribute_for_head(attribute.reborrow())
            .unwrap();
        let aliases = operand
            .syntax()
            .aliases()
            .unwrap()
            .unwrap()
            .parameters()
            .unwrap()
            .as_ptr();
        let collection = operand
            .syntax()
            .collection()
            .unwrap()
            .unwrap()
            .expression()
            .unwrap() as *const _;
        let input = NativeForInput::new(operand).unwrap();
        let mut pending = alloc::vec::Vec::new();
        pending.push(input);
        pending.reserve(32);
        let input = pending.pop().unwrap();
        assert_eq!(input.aliases().as_ptr(), aliases);
        assert_eq!(input.collection() as *const _, collection);
        assert_eq!(input.operand().syntax().grammar().lang, Lang::Ts);
        let joined = input.admitted_for(&selected, attribute).unwrap();
        let admitted = joined.for_head().unwrap();
        assert_eq!(admitted.aliases().parameters().items.as_ptr(), aliases);
        assert_eq!(admitted.collection().expression() as *const _, collection);
        assert!(core::ptr::eq(joined.selected(), &selected));
        let BindingPattern::BindingIdentifier(alias) = &input.aliases()[0].pattern else {
            panic!("original alias")
        };
        let authored = input.alias_authored_span(alias.span).unwrap();
        assert_eq!(authored.slice(source), "α");
        let authored = input
            .collection_authored_span(input.collection().span())
            .unwrap();
        assert_eq!(authored.slice(source), "items");
        let operand = input.into_operand();
        assert_eq!(operand.raw_value(), "(α, key) in items");
        assert_eq!(
            operand
                .syntax()
                .aliases()
                .unwrap()
                .unwrap()
                .parameters()
                .unwrap()
                .as_ptr(),
            aliases
        );
    }
    assert_eq!(visits, 1);
}

#[test]
fn sibling_equal_parse_and_foreign_equal_file_cannot_replace_the_selected_header() {
    let arena = Allocator::default();
    let source = "<template><b v-for='item in items' v-for='item in items'/></template>";
    let selected = selected(&arena, source);
    let foreign = self::selected(&arena, source);
    let element = selected.children().next().unwrap().into_element().unwrap();
    let operand = selected
        .observe_attribute_for_head(element.attributes().next().unwrap())
        .unwrap();
    let input = NativeForInput::new(operand).unwrap();
    assert!(
        input
            .admitted_for(&selected, element.attributes().next().unwrap())
            .is_some()
    );
    assert!(
        input
            .admitted_for(&selected, element.attributes().nth(1).unwrap())
            .is_none()
    );
    let other = foreign.children().next().unwrap().into_element().unwrap();
    assert!(
        input
            .admitted_for(&foreign, other.attributes().next().unwrap())
            .is_none()
    );
}

#[test]
fn selected_refusal_retains_the_complete_original_attribute_and_syntax() {
    let arena = Allocator::default();
    let source = "<template><b v-for='item in /*kept*/items'/></template>";
    let selected = selected(&arena, source);
    let element = selected.children().next().unwrap().into_element().unwrap();
    let attribute = element.attributes().next().unwrap();
    let operand = selected
        .observe_attribute_for_head(attribute.reborrow())
        .unwrap();
    let span = operand.value_span();
    let comment = operand
        .syntax()
        .comments()
        .next()
        .unwrap()
        .1
        .text()
        .unwrap()
        .as_ptr();
    let rejected = NativeForInput::new(operand).unwrap_err();
    assert_eq!(rejected.kind, NativeForRefusal::Comment);
    assert_eq!(rejected.span, span);
    assert_eq!(
        rejected
            .operand()
            .syntax()
            .comments()
            .next()
            .unwrap()
            .1
            .text()
            .unwrap()
            .as_ptr(),
        comment
    );
    let operand = rejected.into_operand();
    assert_eq!(operand.raw_value(), "item in /*kept*/items");
    assert!(operand.admitted_for(&selected, attribute).is_none());
    assert_eq!(span.slice(source), operand.raw_value());
    assert_ne!(span, Span::new(0, source.len() as u32));
}