feat(xatu): add lexical scope graph

This commit is contained in:
2026-09-26 15:07:30 -04:00
parent 16ce11fc52
commit 4b388264ee
4 changed files with 262 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
use googletest::matchers::eq;
use googletest::{expect_that, gtest};
use xatu::{PathStep, Resolution, ResolutionPath, ScopeGraph};
#[gtest]
fn resolves_a_local_declaration() {
let mut graph = ScopeGraph::new();
let scope = graph.root_scope();
let declaration = graph.add_declaration(scope, "value");
let reference = graph.add_reference(scope, "value");
let expected = vec![resolution(declaration, vec![PathStep::Declaration(declaration)])];
expect_that!(graph.resolve(reference), eq(&expected));
}
#[gtest]
fn resolves_a_parent_declaration() {
let mut graph = ScopeGraph::new();
let parent = graph.root_scope();
let declaration = graph.add_declaration(parent, "value");
let child = graph.add_scope(parent);
let reference = graph.add_reference(child, "value");
let expected = vec![resolution(
declaration,
vec![PathStep::Parent, PathStep::Declaration(declaration)],
)];
expect_that!(graph.resolve(reference), eq(&expected));
}
#[gtest]
fn local_declarations_shadow_parent_declarations() {
let mut graph = ScopeGraph::new();
let parent = graph.root_scope();
graph.add_declaration(parent, "value");
let child = graph.add_scope(parent);
let declaration = graph.add_declaration(child, "value");
let reference = graph.add_reference(child, "value");
let expected = vec![resolution(declaration, vec![PathStep::Declaration(declaration)])];
expect_that!(graph.resolve(reference), eq(&expected));
}
#[gtest]
fn preserves_ambiguous_local_declarations() {
let mut graph = ScopeGraph::new();
let scope = graph.root_scope();
let first = graph.add_declaration(scope, "value");
let second = graph.add_declaration(scope, "value");
let reference = graph.add_reference(scope, "value");
let expected = vec![
resolution(first, vec![PathStep::Declaration(first)]),
resolution(second, vec![PathStep::Declaration(second)]),
];
expect_that!(graph.resolve(reference), eq(&expected));
}
#[gtest]
fn leaves_unresolved_references_without_resolutions() {
let mut graph = ScopeGraph::new();
let reference = graph.add_reference(graph.root_scope(), "value");
let expected = Vec::<Resolution>::new();
expect_that!(graph.resolve(reference), eq(&expected));
}
fn resolution(
declaration: xatu::DeclarationId,
steps: Vec<PathStep>,
) -> Resolution {
Resolution {
declaration,
path: ResolutionPath { steps },
}
}