refactor(natu): rename xatu

This commit was merged in pull request #97.
This commit is contained in:
2026-09-26 20:12:57 -04:00
parent 27d9194ac3
commit 0c1a1c1ffa
26 changed files with 82 additions and 81 deletions

View File

@@ -0,0 +1,71 @@
use crate::{
ast,
scope_graph::{LetScope, NodeId, ScopeGraph},
};
pub struct Finding {
pub range: ast::SourceRange,
pub binding: String,
}
pub fn check(graph: &ScopeGraph) -> Vec<Finding> {
graph
.let_scopes()
.iter()
.flat_map(|let_scope| {
let expected = expected_order(graph, let_scope);
let positions = expected
.iter()
.enumerate()
.map(|(position, declaration)| (*declaration, position))
.collect::<Vec<_>>();
let_scope
.bindings
.iter()
.enumerate()
.filter_map(move |(position, binding)| {
positions
.iter()
.find(|(declaration, _)| *declaration == binding.declaration)
.filter(|(_, expected_position)| position != *expected_position)
.map(|_| Finding {
range: binding.range,
binding: binding.name.clone(),
})
})
})
.collect()
}
fn expected_order(graph: &ScopeGraph, let_scope: &LetScope) -> Vec<NodeId> {
let mut order = Vec::new();
visit_references(graph, &let_scope.entry_references, let_scope, &mut order);
order
}
fn visit_references(
graph: &ScopeGraph,
references: &[NodeId],
let_scope: &LetScope,
order: &mut Vec<NodeId>,
) {
for reference in references {
for declaration in graph.resolve(*reference) {
let Some(binding) = let_scope
.bindings
.iter()
.find(|binding| binding.declaration == declaration)
else {
continue;
};
if order.contains(&declaration) {
continue;
}
order.push(declaration);
visit_references(graph, &binding.references, let_scope, order);
}
}
}

View File

@@ -0,0 +1,24 @@
use crate::{ast, rules::NodeRule};
pub struct ManualInherit;
impl NodeRule for ManualInherit {
type Node = ast::Binding;
const ID: &'static str = "manual_inherit";
fn select(data: &ast::NodeData) -> Option<&Self::Node> {
let ast::NodeData::Binding(binding) = data;
Some(binding)
}
fn check(node: &Self::Node) -> Option<&'static str> {
match &node.value {
ast::Expr::Ident(value) if node.key == *value => {
Some("Use `inherit` for this assignment")
}
_ => None,
}
}
}

View File

@@ -0,0 +1,24 @@
use crate::{ast, rules::NodeRule};
pub struct ManualInheritFrom;
impl NodeRule for ManualInheritFrom {
type Node = ast::Binding;
const ID: &'static str = "manual_inherit_from";
fn select(data: &ast::NodeData) -> Option<&Self::Node> {
let ast::NodeData::Binding(binding) = data;
Some(binding)
}
fn check(node: &Self::Node) -> Option<&'static str> {
match &node.value {
ast::Expr::Select(select) if node.key == select.attr => {
Some("Use `inherit` for this selected attribute")
}
_ => None,
}
}
}

View File

@@ -0,0 +1,19 @@
use crate::{ast, rules::TokenRule};
pub struct UnquotedUri;
impl TokenRule for UnquotedUri {
type Token = String;
const ID: &'static str = "unquoted_uri";
fn select(data: &ast::TokenData) -> Option<&Self::Token> {
match data {
ast::TokenData::UnquotedUri(uri) => Some(uri),
}
}
fn check(_token: &Self::Token) -> Option<&'static str> {
Some("URI literals should be quoted")
}
}