fix(natu): report let locations
This commit is contained in:
@@ -49,6 +49,7 @@ pub enum Expr {
|
|||||||
Ident(Ident),
|
Ident(Ident),
|
||||||
Select(Select),
|
Select(Select),
|
||||||
Let {
|
Let {
|
||||||
|
range: SourceRange,
|
||||||
bindings: Vec<Binding>,
|
bindings: Vec<Binding>,
|
||||||
body: Box<Expr>,
|
body: Box<Expr>,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ impl std::fmt::Display for Report {
|
|||||||
finding.finding.expected_order.as_ref().expect("let order");
|
finding.finding.expected_order.as_ref().expect("let order");
|
||||||
writeln!(
|
writeln!(
|
||||||
formatter,
|
formatter,
|
||||||
" let whose first binding starts at line {start}: {}",
|
" let at line {start}: {}",
|
||||||
expected_order.join(", ")
|
expected_order.join(", ")
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ fn natu_reports_out_of_order_let_bindings() -> googletest::Result<()> {
|
|||||||
"testdata/lint_findings.nix:12 [manual_inherit_from] Use `inherit` for this selected attribute\n",
|
"testdata/lint_findings.nix:12 [manual_inherit_from] Use `inherit` for this selected attribute\n",
|
||||||
"testdata/lint_findings.nix:13 [unquoted_uri] URI literals should be quoted\n",
|
"testdata/lint_findings.nix:13 [unquoted_uri] URI literals should be quoted\n",
|
||||||
"testdata/lint_findings.nix [let_order] Let bindings must follow dependency order\n",
|
"testdata/lint_findings.nix [let_order] Let bindings must follow dependency order\n",
|
||||||
" let whose first binding starts at line 2: first, second, nested\n",
|
" let at line 1: first, second, nested\n",
|
||||||
" let whose first binding starts at line 5: nestedSecond, nestedFirst\n",
|
" let at line 4: nestedSecond, nestedFirst\n",
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ fn convert_expr(expr: rnix::ast::Expr) -> ast::Expr {
|
|||||||
match expr {
|
match expr {
|
||||||
rnix::ast::Expr::Ident(ident) => ast::Expr::Ident(ident.into()),
|
rnix::ast::Expr::Ident(ident) => ast::Expr::Ident(ident.into()),
|
||||||
rnix::ast::Expr::LetIn(let_in) => ast::Expr::Let {
|
rnix::ast::Expr::LetIn(let_in) => ast::Expr::Let {
|
||||||
|
range: let_in.syntax().text_range().into(),
|
||||||
bindings: let_in
|
bindings: let_in
|
||||||
.attrpath_values()
|
.attrpath_values()
|
||||||
.filter_map(convert_binding_ast)
|
.filter_map(convert_binding_ast)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ pub fn check(graph: &ScopeGraph) -> Vec<Finding> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
(!is_ordered).then(|| Finding {
|
(!is_ordered).then(|| Finding {
|
||||||
range: let_scope.bindings[0].range,
|
range: let_scope.range,
|
||||||
expected_order: expected
|
expected_order: expected
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|declaration| {
|
.filter_map(|declaration| {
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ impl ScopeGraph {
|
|||||||
fn build_expr(&mut self, expr: &ast::Expr, scope: NodeId) -> Vec<NodeId> {
|
fn build_expr(&mut self, expr: &ast::Expr, scope: NodeId) -> Vec<NodeId> {
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expr::Ident(ident) => vec![self.add_reference(&ident.name, scope)],
|
ast::Expr::Ident(ident) => vec![self.add_reference(&ident.name, scope)],
|
||||||
ast::Expr::Let { bindings, body } => self.build_let(bindings, body, scope),
|
ast::Expr::Let {
|
||||||
|
range,
|
||||||
|
bindings,
|
||||||
|
body,
|
||||||
|
} => self.build_let(*range, bindings, body, scope),
|
||||||
ast::Expr::AttrSet(bindings) => bindings
|
ast::Expr::AttrSet(bindings) => bindings
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|binding| self.build_expr(&binding.value, scope))
|
.flat_map(|binding| self.build_expr(&binding.value, scope))
|
||||||
@@ -48,6 +52,7 @@ impl ScopeGraph {
|
|||||||
|
|
||||||
fn build_let(
|
fn build_let(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
range: ast::SourceRange,
|
||||||
bindings: &[ast::Binding],
|
bindings: &[ast::Binding],
|
||||||
body: &ast::Expr,
|
body: &ast::Expr,
|
||||||
parent: NodeId,
|
parent: NodeId,
|
||||||
@@ -74,6 +79,7 @@ impl ScopeGraph {
|
|||||||
.chain(entry_references.iter().copied())
|
.chain(entry_references.iter().copied())
|
||||||
.collect();
|
.collect();
|
||||||
self.lets.push(LetScope {
|
self.lets.push(LetScope {
|
||||||
|
range,
|
||||||
bindings: graph_bindings,
|
bindings: graph_bindings,
|
||||||
entry_references,
|
entry_references,
|
||||||
});
|
});
|
||||||
@@ -181,6 +187,7 @@ struct Edge {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct LetScope {
|
pub(crate) struct LetScope {
|
||||||
|
pub(crate) range: ast::SourceRange,
|
||||||
pub(crate) bindings: Vec<Binding>,
|
pub(crate) bindings: Vec<Binding>,
|
||||||
pub(crate) entry_references: Vec<NodeId>,
|
pub(crate) entry_references: Vec<NodeId>,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user