vize_l1 0.545.0

L1 - the lossless Vue-template surface tree (codename Sinopia, Davinci P2-7)
Documentation
use super::{assert_own_original_root, selected};
use crate::embed::{Grammar, Lang, Shape};
use crate::markup::{NativeConditionKind, NativeTemplateGrammar};
use oxc_ast::ast::{Expression, TSType};
use oxc_span::GetSpan;
use vize_l0::{Allocator, Span};

#[test]
fn js_and_setup_ts_profiles_retain_each_routes_own_original_ast_and_spans() {
    let arena = Allocator::default();
    for (source, raw, lang, grammar, value_span) in [
        (
            "前\n<template><p v-if='(value)'/></template>",
            "(value)",
            Lang::Js,
            NativeTemplateGrammar::JavaScriptModule,
            Span::new(23, 30),
        ),
        (
            "前\n<template><p v-if='value as boolean'/></template><script setup lang=ts>const value=true</script>",
            "value as boolean",
            Lang::Ts,
            NativeTemplateGrammar::TypeScriptModule,
            Span::new(23, 39),
        ),
    ] {
        let old_owner = selected(&arena, source);
        let new_owner = selected(&arena, source);
        let old_element = old_owner.children().next().unwrap().into_element().unwrap();
        let new_element = new_owner.children().next().unwrap().into_element().unwrap();
        let head = new_owner
            .observe_attribute_head(new_element.attributes().next().unwrap())
            .unwrap();
        assert_eq!(head.name_block().span(), Span::new(17, 21));
        assert_eq!(head.name_block().source(), "v-if");
        assert_eq!(head.condition_kind(), Some(NativeConditionKind::If));
        let old = old_owner
            .observe_attribute_expression(old_element.attributes().next().unwrap())
            .unwrap();
        let new = head.observe_expression().unwrap();
        assert_eq!(old_owner.grammar(), grammar);
        assert_eq!(new_owner.grammar(), grammar);
        for operand in [&old, &new] {
            let syntax = operand.syntax();
            assert_eq!(operand.name_span(), Span::new(17, 21));
            assert_eq!(operand.value_span(), value_span);
            assert_eq!(operand.raw_value(), raw);
            assert_eq!(syntax.source().span(), value_span);
            assert_eq!(syntax.source().text(), raw);
            assert!(core::ptr::eq(syntax.source().authored_root(), source));
            assert_eq!(
                syntax.grammar(),
                Grammar {
                    shape: Shape::Expr,
                    lang
                }
            );
            assert!(syntax.source_type().is_module());
            assert_eq!(syntax.source_type().is_typescript(), lang == Lang::Ts);
            assert_eq!(syntax.parser_prefix(), 2);
            assert_eq!(syntax.hole(), None);
            assert_eq!(syntax.comments().count(), 0);
            assert_eq!(syntax.diagnostics().count(), 0);
            let root = syntax.expression().unwrap();
            assert_eq!(syntax.authored_span(root.span()), Ok(value_span));
            if lang == Lang::Js {
                let Expression::ParenthesizedExpression(parentheses) = root else {
                    panic!("authored JS parentheses must survive")
                };
                assert_eq!(parentheses.span, oxc_span::Span::new(2, 9));
                assert_eq!(syntax.decoded_span(parentheses.span), Ok(Span::new(0, 7)));
                let Expression::Identifier(identifier) = &parentheses.expression else {
                    panic!("the original JS child must be an identifier")
                };
                assert_eq!(identifier.name.as_str(), "value");
                assert_eq!(identifier.span, oxc_span::Span::new(3, 8));
                assert_eq!(syntax.authored_span(identifier.span), Ok(Span::new(24, 29)));
            } else {
                let Expression::TSAsExpression(cast) = root else {
                    panic!("the intrinsically selected TS cast must survive")
                };
                assert_eq!(cast.span, oxc_span::Span::new(2, 18));
                assert_eq!(syntax.decoded_span(cast.span), Ok(Span::new(0, 16)));
                let Expression::Identifier(identifier) = &cast.expression else {
                    panic!("the original TS child must be an identifier")
                };
                assert_eq!(identifier.name.as_str(), "value");
                assert_eq!(identifier.span, oxc_span::Span::new(2, 7));
                assert_eq!(syntax.authored_span(identifier.span), Ok(Span::new(23, 28)));
                let TSType::TSBooleanKeyword(keyword) = &cast.type_annotation else {
                    panic!("the original erased type must be boolean")
                };
                assert_eq!(keyword.span, oxc_span::Span::new(11, 18));
                assert_eq!(syntax.authored_span(keyword.span), Ok(Span::new(32, 39)));
            }
        }
        assert_own_original_root(&old, &old_owner, 0);
        assert_own_original_root(&new, &new_owner, 0);
        assert!(!core::ptr::eq(
            old.syntax().expression().unwrap(),
            new.syntax().expression().unwrap()
        ));
    }
}