vize_l2 0.544.0

L2 - the Davinci semantic IR (codename Disegno): the neutral op family every input dialect lowers into
Documentation
extern crate std;

use super::{
    Allocator, FileBuilder, FileIssueKind, FileProducer, ProgramScope, SourceRoot, SourceType,
    Span, TemplateScope, Values, append, file, offset, refused,
};
use crate::artifact::ComponentFactory;
use crate::expr::JsExpr;
use crate::file::ScriptUnit;
use crate::lang::js::{CallEvent, DeclaredEvent, FileObserver, ProgramInput, StatementEvent};
use crate::resolution::ResolutionErrorKind;
use alloc::boxed::Box;
use oxc_parser::Parser;

#[test]
fn successful_structural_finish_does_not_admit_unresolved_or_unsupported_semantics() {
    let arena = Allocator::default();
    for source in [
        "const known = 1; missing;",
        "const known = 1; const later = known + (() => missing);",
    ] {
        let owner = file(&arena, source, SourceType::mjs());
        assert!(!owner.is_complete());
        assert!(owner.bindings().next().is_some());
        assert!(!owner.issues().is_empty());
        refused(&owner);
    }
}

#[test]
fn script_profile_refusal_keeps_queries_unavailable_after_structural_finish() {
    let arena = Allocator::default();
    let owner = file(&arena, "const value = 1; value;", SourceType::cjs());
    assert_eq!(owner.issues()[0].kind, FileIssueKind::InvalidProfile);
    refused(&owner);
}

#[test]
fn interrupted_template_driver_prevents_script_position_publication() {
    let arena = Allocator::default();
    let source = "const value = 1;\nvalue";
    let end = offset(source, "\n");
    let root = SourceRoot::new(source).unwrap();
    let mut producer = FileProducer::new(&arena, source).unwrap();
    append(
        &arena,
        &mut producer,
        root.block(source.get(..end as usize).unwrap(), 0).unwrap(),
        0,
        SourceType::mjs(),
        ProgramScope::Nested,
    );
    {
        let mut region = producer
            .template_region(TemplateScope::LastUnit, Values)
            .unwrap();
        let _walk = region
            .walk(Span::new(end + 1, source.len() as u32))
            .unwrap();
    }
    let owner = producer.finish().unwrap();
    assert!(owner.issues().is_empty());
    assert_eq!(
        owner.template_interruption().unwrap().kind,
        FileIssueKind::InterruptedTemplate
    );
    refused(&owner);
}

#[test]
fn canonical_text_and_empty_original_units_do_not_create_name_or_scope_sites() {
    let arena = Allocator::default();
    let source = "text";
    let mut builder = FileBuilder::new(&arena, source).unwrap();
    builder.text(source, Span::new(0, 4)).unwrap();
    let owner = builder.finish().unwrap();
    assert!(owner.is_complete());
    assert!(owner.scope_at_offset(0).unwrap().is_none());
    assert!(owner.binding_at_offset(0).unwrap().is_none());
    assert!(owner.reference_at_offset(0).unwrap().is_none());
    let empty = file(&arena, "", SourceType::mjs());
    assert!(empty.is_complete());
    assert_eq!(empty.units()[0].span, Span::new(0, 0));
    assert!(empty.scope_at_offset(0).unwrap().is_none());
}

#[test]
fn completed_template_occurrences_do_not_become_script_position_sites() {
    let arena = Allocator::default();
    let source = "const value = 1;\nvalue";
    let end = offset(source, "\n");
    let root = SourceRoot::new(source).unwrap();
    let mut producer = FileProducer::new(&arena, source).unwrap();
    append(
        &arena,
        &mut producer,
        root.block(source.get(..end as usize).unwrap(), 0).unwrap(),
        0,
        SourceType::mjs(),
        ProgramScope::Nested,
    );
    let span = Span::new(end + 1, source.len() as u32);
    let expression =
        JsExpr::parse_in(&arena, source.get((end + 1) as usize..).unwrap(), span).unwrap();
    let node;
    {
        let mut region = producer
            .template_region(TemplateScope::LastUnit, Values)
            .unwrap();
        let mut walk = region.walk(span).unwrap();
        node = walk.interpolation(expression, span).unwrap();
        walk.complete().unwrap();
    }
    let owner = producer.finish().unwrap();
    assert!(owner.is_complete());
    assert_eq!(
        owner.expression(node).unwrap().scope(),
        Some(owner.units()[0].scope)
    );
    assert!(owner.reference_at_offset(span.start).unwrap().is_none());
    assert!(owner.binding_at_offset(span.start).unwrap().is_none());
    assert!(owner.scope_at_offset(span.start).unwrap().is_none());
}

struct Interrupt;
impl<'a> FileObserver<'a> for Interrupt {
    type Checkpoint = ();
    fn unit(&mut self, _: &ScriptUnit) {}
    fn statement(&mut self, _: StatementEvent<'_, 'a>) {}
    fn declared(&mut self, _: DeclaredEvent<'_, 'a>) {
        std::panic::resume_unwind(Box::new("original declaration observation interrupted"));
    }
    fn checkpoint(&self) {}
    fn call(&mut self, _: CallEvent<'_, 'a>) -> Result<(), ResolutionErrorKind> {
        Ok(())
    }
    fn rollback(&mut self, _: ()) {}
}

#[test]
fn interrupted_original_program_keeps_retained_declarations_unavailable_to_queries() {
    let arena = Allocator::default();
    let source = "const value = 1;";
    let root = SourceRoot::new(source).unwrap();
    let syntax = Parser::new(&arena, source, SourceType::mjs()).parse_observed();
    let input = ProgramInput::checked(syntax.admitted().unwrap(), root.whole_block(), 0).unwrap();
    let mut producer = FileProducer::new(&arena, source).unwrap();
    assert!(
        std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
            producer.program_observed(input, ProgramScope::Module, &mut Interrupt)
        }))
        .is_err()
    );
    let owner = producer.finish().unwrap();
    assert!(owner.issues().is_empty());
    assert_eq!(owner.bindings().count(), 1);
    assert_eq!(
        owner.interrupted_programs().next().unwrap().kind,
        FileIssueKind::InterruptedProgram
    );
    refused(&owner);
}