mirror of
https://github.com/astro/deadnix.git
synced 2024-09-17 13:17:18 +03:00
rowan: 0.12 -> 0.15
This commit is contained in:
parent
ea55361244
commit
8e2e6af26e
49
Cargo.lock
generated
49
Cargo.lock
generated
@ -72,15 +72,6 @@ version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cbitset"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29b6ad25ae296159fb0da12b970b2fe179b234584d7cd294c891e2bbb284466b"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
@ -123,9 +114,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "countme"
|
||||
version = "2.0.4"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "328b822bdcba4d4e402be8d9adb6eebf269f969f8eadef977a553ff3c4fbcb58"
|
||||
checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"
|
||||
|
||||
[[package]]
|
||||
name = "deadnix"
|
||||
@ -163,9 +154,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.9.1"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
@ -216,38 +207,27 @@ checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rnix"
|
||||
version = "0.10.2"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8024a523e8836f1a5d051203dc00d833357fee94e351b51348dfaeca5364daa9"
|
||||
checksum = "bb35cedbeb70e0ccabef2a31bcff0aebd114f19566086300b8f42c725fc2cb5f"
|
||||
dependencies = [
|
||||
"cbitset",
|
||||
"rowan",
|
||||
"smol_str",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rowan"
|
||||
version = "0.12.6"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1b36e449f3702f3b0c821411db1cbdf30fb451726a9456dce5dabcd44420043"
|
||||
checksum = "64449cfef9483a475ed56ae30e2da5ee96448789fb2aa240a04beb6a055078bf"
|
||||
dependencies = [
|
||||
"countme",
|
||||
"hashbrown",
|
||||
@ -308,15 +288,6 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smol_str"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
|
@ -10,8 +10,8 @@ repository = "https://github.com/astro/deadnix.git"
|
||||
documentation = "https://docs.rs/deadnix"
|
||||
|
||||
[dependencies]
|
||||
rowan = "0.12" # dependency version of rnix-0.10.1
|
||||
rnix = "0.10"
|
||||
rowan = "0.15" # dependency version of rnix-0.11.0
|
||||
rnix = "0.11"
|
||||
clap = "4"
|
||||
walkdir = "2"
|
||||
ariadne = "0.1"
|
||||
|
@ -1,5 +1,5 @@
|
||||
use rnix::{
|
||||
types::{Ident, TokenWrapper},
|
||||
ast::Ident,
|
||||
NixLanguage,
|
||||
};
|
||||
use rowan::api::SyntaxNode;
|
||||
@ -14,7 +14,8 @@ pub struct Binding {
|
||||
|
||||
impl PartialEq for Binding {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.decl_node == other.decl_node && self.name.as_str() == other.name.as_str()
|
||||
self.decl_node == other.decl_node &&
|
||||
self.name.syntax().text() == other.name.syntax().text()
|
||||
}
|
||||
}
|
||||
impl Eq for Binding {}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use crate::{binding::Binding, scope::Scope, usage};
|
||||
use rnix::{
|
||||
types::{TokenWrapper, TypedNode},
|
||||
NixLanguage,
|
||||
};
|
||||
use rowan::api::SyntaxNode;
|
||||
use rowan::{api::SyntaxNode, ast::AstNode};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fmt,
|
||||
@ -17,7 +16,7 @@ pub struct DeadCode {
|
||||
|
||||
impl fmt::Display for DeadCode {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(fmt, "Unused {}: {}", self.scope, self.binding.name.as_str())
|
||||
write!(fmt, "Unused {}: {}", self.scope, self.binding.name)
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +40,7 @@ impl Settings {
|
||||
}
|
||||
|
||||
let mut results = results.into_values().collect::<Vec<_>>();
|
||||
results.sort_unstable_by_key(|result| result.binding.name.node().text_range().start());
|
||||
results.sort_unstable_by_key(|result| result.binding.name.syntax().text_range().start());
|
||||
results
|
||||
}
|
||||
|
||||
@ -65,7 +64,7 @@ impl Settings {
|
||||
// find if used anywhere
|
||||
usage::find(&binding.name, &body)
|
||||
})
|
||||
|| self.no_underscore && binding.name.as_str().starts_with('_')
|
||||
|| self.no_underscore && binding.name.syntax().text().char_at(0.into()) == Some('_')
|
||||
|| self.no_lambda_pattern_names
|
||||
&& scope.is_lambda_pattern_name(&binding.name))
|
||||
{
|
||||
|
@ -1,10 +1,9 @@
|
||||
#![cfg(test)]
|
||||
|
||||
use crate::dead_code::{DeadCode, Settings};
|
||||
use rnix::types::TokenWrapper;
|
||||
|
||||
fn run(content: &str) -> Vec<DeadCode> {
|
||||
let ast = rnix::parse(content);
|
||||
let ast = rnix::Root::parse(content);
|
||||
assert_eq!(0, ast.errors().len());
|
||||
|
||||
Settings {
|
||||
@ -12,7 +11,7 @@ fn run(content: &str) -> Vec<DeadCode> {
|
||||
no_lambda_pattern_names: false,
|
||||
no_underscore: false,
|
||||
}
|
||||
.find_dead_code(&ast.node())
|
||||
.find_dead_code(&ast.syntax())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -31,39 +30,39 @@ fn let_in_alive_deep() {
|
||||
fn let_in_dead() {
|
||||
let results = run("let dead = 23; in false");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn let_in_dead_multi() {
|
||||
let results = run("let dead1 = 23; dead2 = 5; dead3 = 42; in false");
|
||||
assert_eq!(3, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead1");
|
||||
assert_eq!(results[1].binding.name.as_str(), "dead2");
|
||||
assert_eq!(results[2].binding.name.as_str(), "dead3");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead1");
|
||||
assert_eq!(results[1].binding.name.to_string(), "dead2");
|
||||
assert_eq!(results[2].binding.name.to_string(), "dead3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn let_in_dead_multi_recursive() {
|
||||
let results = run("let dead1 = dead2; dead2 = dead3; dead3 = 42; in false");
|
||||
assert_eq!(3, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead1");
|
||||
assert_eq!(results[1].binding.name.as_str(), "dead2");
|
||||
assert_eq!(results[2].binding.name.as_str(), "dead3");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead1");
|
||||
assert_eq!(results[1].binding.name.to_string(), "dead2");
|
||||
assert_eq!(results[2].binding.name.to_string(), "dead3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn let_in_dead_recursive() {
|
||||
let results = run("let dead = dead; in false");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn let_in_shadowed() {
|
||||
let results = run("let dead = true; in let dead = false; in dead");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -76,16 +75,16 @@ fn let_in_inherit_alive() {
|
||||
fn let_in_inherit_dead() {
|
||||
let results = run("let inherit (alive) dead; in alive");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn let_in_inherit_dead_multi() {
|
||||
let results = run("let inherit (grave) dead1 dead2 dead3; in false");
|
||||
assert_eq!(3, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead1");
|
||||
assert_eq!(results[1].binding.name.as_str(), "dead2");
|
||||
assert_eq!(results[2].binding.name.as_str(), "dead3");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead1");
|
||||
assert_eq!(results[1].binding.name.to_string(), "dead2");
|
||||
assert_eq!(results[2].binding.name.to_string(), "dead3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -93,16 +92,16 @@ fn let_in_inherit_dead_recursive_multi() {
|
||||
let results =
|
||||
run("let inherit (grave) dead1; inherit (dead1) dead2; inherit (dead2) dead3; in false");
|
||||
assert_eq!(3, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead1");
|
||||
assert_eq!(results[1].binding.name.as_str(), "dead2");
|
||||
assert_eq!(results[2].binding.name.as_str(), "dead3");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead1");
|
||||
assert_eq!(results[1].binding.name.to_string(), "dead2");
|
||||
assert_eq!(results[2].binding.name.to_string(), "dead3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn let_in_inherit_shadowed() {
|
||||
let results = run("let inherit (dead) dead; in let inherit (alive) dead; in dead");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -121,14 +120,14 @@ fn lambda_arg_underscore() {
|
||||
fn lambda_arg_dead() {
|
||||
let results = run("dead: false");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lambda_arg_shadowed() {
|
||||
let results = run("dead: dead: dead");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -147,14 +146,14 @@ fn lambda_at_pattern_alive() {
|
||||
fn lambda_at_dead() {
|
||||
let results = run("dead@{ ... }: false");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lambda_at_shadowed() {
|
||||
let results = run("dead@{ ... }: dead@{ ... }: dead");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -167,43 +166,43 @@ fn lambda_pattern_alive() {
|
||||
fn lambda_pattern_dead_ellipsis_alias() {
|
||||
let results = run("alive@{ dead, ... }: alive");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lambda_pattern_dead_simple() {
|
||||
let results = run("{ dead }: false");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lambda_pattern_alias() {
|
||||
let results = run("{ dead }@args: args");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lambda_pattern_shadowed() {
|
||||
let results = run("{ dead, ... }: { dead, ... }: dead");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn looped() {
|
||||
let results = run("let dead1 = dead2; dead2 = {}; in false");
|
||||
assert_eq!(2, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead1");
|
||||
assert_eq!(results[1].binding.name.as_str(), "dead2");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead1");
|
||||
assert_eq!(results[1].binding.name.to_string(), "dead2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rec_attrset_shadowed() {
|
||||
let results = run("let dead = false; in rec { dead = true; alive = dead; }");
|
||||
assert_eq!(1, results.len());
|
||||
assert_eq!(results[0].binding.name.as_str(), "dead");
|
||||
assert_eq!(results[0].binding.name.to_string(), "dead");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
38
src/edit.rs
38
src/edit.rs
@ -1,9 +1,9 @@
|
||||
use crate::{dead_code::DeadCode, scope::Scope};
|
||||
use rnix::{
|
||||
types::{EntryHolder, Inherit, LetIn, TokenWrapper, TypedNode},
|
||||
ast::{Inherit, LetIn, HasEntry},
|
||||
NixLanguage, SyntaxKind,
|
||||
};
|
||||
use rowan::api::SyntaxNode;
|
||||
use rowan::{api::SyntaxNode, ast::AstNode};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Edit {
|
||||
@ -44,9 +44,9 @@ pub fn edit_dead_code(original: &str, dead: impl Iterator<Item = DeadCode>) -> (
|
||||
let edited = apply_edits(original, edits.iter());
|
||||
|
||||
// remove empty `let in`
|
||||
let ast = rnix::parse(&edited);
|
||||
let ast = rnix::Root::parse(&edited);
|
||||
let mut let_in_edits = Vec::new();
|
||||
remove_empty_scopes(&ast.node(), &mut let_in_edits);
|
||||
remove_empty_scopes(&ast.syntax(), &mut let_in_edits);
|
||||
if let_in_edits.is_empty() {
|
||||
(edited, has_changes)
|
||||
} else {
|
||||
@ -63,11 +63,11 @@ fn dead_to_edit(dead_code: DeadCode) -> Option<Edit> {
|
||||
match dead_code.scope {
|
||||
Scope::LambdaPattern(pattern, _) => {
|
||||
if pattern
|
||||
.at()
|
||||
.map_or(false, |at| *at.node() == dead_code.binding.decl_node)
|
||||
.pat_bind()
|
||||
.map_or(false, |at| at.ident().expect("at.ident").syntax() == &dead_code.binding.decl_node)
|
||||
{
|
||||
if let Some(pattern_bind_node) = pattern
|
||||
.node()
|
||||
.syntax()
|
||||
.children()
|
||||
.find(|child| child.kind() == SyntaxKind::NODE_PAT_BIND)
|
||||
{
|
||||
@ -85,7 +85,7 @@ fn dead_to_edit(dead_code: DeadCode) -> Option<Edit> {
|
||||
replace_node = pattern_bind_node;
|
||||
}
|
||||
} else {
|
||||
let mut tokens = pattern.node().children_with_tokens().skip_while(|node| {
|
||||
let mut tokens = pattern.syntax().children_with_tokens().skip_while(|node| {
|
||||
node.as_node()
|
||||
.map_or(true, |node| *node != dead_code.binding.decl_node)
|
||||
});
|
||||
@ -105,28 +105,28 @@ fn dead_to_edit(dead_code: DeadCode) -> Option<Edit> {
|
||||
}
|
||||
|
||||
Scope::LambdaArg(name, _) => {
|
||||
replacement = Some(format!("_{}", name.as_str()));
|
||||
replacement = Some(format!("_{}", name));
|
||||
}
|
||||
|
||||
Scope::LetIn(let_in) => {
|
||||
if let_in
|
||||
.entries()
|
||||
.any(|entry| *entry.node() == dead_code.binding.decl_node)
|
||||
.attrpath_values()
|
||||
.any(|entry| *entry.syntax() == dead_code.binding.decl_node)
|
||||
{
|
||||
replacement = Some(String::new());
|
||||
} else if let Some(ident) = let_in
|
||||
.inherits()
|
||||
.flat_map(|inherit| {
|
||||
inherit
|
||||
.idents()
|
||||
.filter(|ident| *ident.node() == dead_code.binding.decl_node)
|
||||
.attrs()
|
||||
.filter(|attr| attr.syntax() == &dead_code.binding.decl_node)
|
||||
})
|
||||
.next()
|
||||
{
|
||||
let range = ident.node().text_range();
|
||||
let range = ident.syntax().text_range();
|
||||
start = usize::from(range.start());
|
||||
end = usize::from(range.end());
|
||||
replace_node = ident.node().clone();
|
||||
replace_node = ident.syntax().clone();
|
||||
replacement = Some(String::new());
|
||||
}
|
||||
}
|
||||
@ -157,11 +157,11 @@ fn remove_empty_scopes(node: &SyntaxNode<NixLanguage>, edits: &mut Vec<Edit>) {
|
||||
let let_in = LetIn::cast(node.clone()).expect("LetIn::cast");
|
||||
if let_in
|
||||
.inherits()
|
||||
.all(|inherit| inherit.idents().next().is_none())
|
||||
&& let_in.entries().next().is_none()
|
||||
.all(|inherit| inherit.attrs().next().is_none())
|
||||
&& let_in.attrpath_values().next().is_none()
|
||||
{
|
||||
let start = usize::from(node.text_range().start());
|
||||
let end = usize::from(let_in.body().expect("let_in.body").text_range().start());
|
||||
let end = usize::from(let_in.body().expect("let_in.body").syntax().text_range().start());
|
||||
edits.push(Edit {
|
||||
start,
|
||||
end,
|
||||
@ -173,7 +173,7 @@ fn remove_empty_scopes(node: &SyntaxNode<NixLanguage>, edits: &mut Vec<Edit>) {
|
||||
// remove empty `inherit;` and `inherit (...);` constructs
|
||||
SyntaxKind::NODE_INHERIT => {
|
||||
let inherit = Inherit::cast(node.clone()).expect("Inherit::cast");
|
||||
if inherit.idents().next().is_none() {
|
||||
if inherit.attrs().next().is_none() {
|
||||
let mut start = usize::from(node.text_range().start());
|
||||
// remove whitespace before node
|
||||
if let Some(prev) = node.prev_sibling_or_token() {
|
||||
|
@ -3,7 +3,7 @@
|
||||
use crate::dead_code::Settings;
|
||||
|
||||
fn run(content: &str) -> (String, bool) {
|
||||
let ast = rnix::parse(content);
|
||||
let ast = rnix::Root::parse(content);
|
||||
assert_eq!(0, ast.errors().len());
|
||||
|
||||
let results = Settings {
|
||||
@ -11,7 +11,7 @@ fn run(content: &str) -> (String, bool) {
|
||||
no_lambda_pattern_names: false,
|
||||
no_underscore: false,
|
||||
}
|
||||
.find_dead_code(&ast.node());
|
||||
.find_dead_code(&ast.syntax());
|
||||
crate::edit::edit_dead_code(content, results.into_iter())
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@ fn main() {
|
||||
}
|
||||
};
|
||||
|
||||
let ast = rnix::parse(&content);
|
||||
let ast = rnix::Root::parse(&content);
|
||||
let errors = ast.errors();
|
||||
|
||||
if !errors.is_empty() {
|
||||
@ -240,7 +240,7 @@ fn main() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let results = settings.find_dead_code(&ast.node());
|
||||
let results = settings.find_dead_code(&ast.syntax());
|
||||
report_count += results.len();
|
||||
if !quiet && !results.is_empty() {
|
||||
match output_format {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::dead_code::DeadCode;
|
||||
use ariadne::{sources, Config, Label, Report, ReportKind};
|
||||
use rnix::{types::TypedNode, TextSize};
|
||||
use rnix::TextSize;
|
||||
use rowan::ast::AstNode;
|
||||
use std::env;
|
||||
|
||||
#[cfg(feature = "json-out")]
|
||||
@ -10,7 +11,7 @@ use serde_json::json;
|
||||
pub fn print(file: String, content: &str, results: &[DeadCode]) {
|
||||
let no_color = env::var("NO_COLOR").is_ok();
|
||||
|
||||
let first_result_range = results[0].binding.name.node().text_range();
|
||||
let first_result_range = results[0].binding.name.syntax().text_range();
|
||||
let mut builder = Report::build(
|
||||
ReportKind::Warning,
|
||||
file.clone(),
|
||||
@ -28,7 +29,7 @@ pub fn print(file: String, content: &str, results: &[DeadCode]) {
|
||||
for result in results {
|
||||
order -= 1;
|
||||
|
||||
let range = result.binding.name.node().text_range();
|
||||
let range = result.binding.name.syntax().text_range();
|
||||
let start_byte = usize::from(range.start());
|
||||
while content_bytes < start_byte {
|
||||
content_bytes += char_bytes.next().unwrap();
|
||||
@ -71,7 +72,7 @@ pub fn print_json(file: &str, content: &str, results: &[DeadCode]) {
|
||||
let json = json!({
|
||||
"file": file,
|
||||
"results": results.iter().map(|result| {
|
||||
let range = result.binding.name.node().text_range();
|
||||
let range = result.binding.name.syntax().text_range();
|
||||
let start = usize::from(range.start());
|
||||
let mut line_number = 0;
|
||||
let mut line_offset = 0;
|
||||
|
152
src/scope.rs
152
src/scope.rs
@ -1,10 +1,10 @@
|
||||
use crate::{binding::Binding, usage};
|
||||
use ariadne::Color;
|
||||
use rnix::{
|
||||
types::{AttrSet, EntryHolder, Ident, Lambda, LetIn, Pattern, TokenWrapper, TypedNode},
|
||||
ast::{AttrSet, Ident, Lambda, LetIn, Pattern, Param, HasEntry, Attr},
|
||||
NixLanguage, SyntaxKind,
|
||||
};
|
||||
use rowan::api::SyntaxNode;
|
||||
use rowan::{api::SyntaxNode, ast::AstNode};
|
||||
use std::fmt;
|
||||
|
||||
/// AST subtree that declares variables
|
||||
@ -33,18 +33,16 @@ impl Scope {
|
||||
match node.kind() {
|
||||
SyntaxKind::NODE_LAMBDA => {
|
||||
let lambda = Lambda::cast(node.clone()).expect("Lambda::cast");
|
||||
let arg = lambda.arg().expect("lambda.arg()");
|
||||
let body = lambda.body().expect("lambda.body()");
|
||||
match arg.kind() {
|
||||
SyntaxKind::NODE_IDENT => {
|
||||
let name = Ident::cast(arg).expect("Ident::cast");
|
||||
Some(Scope::LambdaArg(name, body))
|
||||
let param = lambda.param().expect("lambda.param()");
|
||||
let body = lambda.body().expect("lambda.body()").syntax().clone();
|
||||
match param {
|
||||
Param::IdentParam(ident_param) => {
|
||||
let name = ident_param.ident().expect("IdentParam.ident()");
|
||||
Some(Scope::LambdaArg(name, body.clone()))
|
||||
}
|
||||
SyntaxKind::NODE_PATTERN => {
|
||||
let pattern = Pattern::cast(arg).expect("Pattern::cast");
|
||||
Param::Pattern(pattern) => {
|
||||
Some(Scope::LambdaPattern(pattern, body))
|
||||
}
|
||||
_ => panic!("Unhandled arg kind: {:?}", arg.kind()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +53,7 @@ impl Scope {
|
||||
|
||||
SyntaxKind::NODE_ATTR_SET => {
|
||||
let attr_set = AttrSet::cast(node.clone()).expect("AttrSet::cast");
|
||||
if attr_set.recursive() {
|
||||
if attr_set.rec_token().is_some() {
|
||||
Some(Scope::RecAttrSet(attr_set))
|
||||
} else {
|
||||
None
|
||||
@ -73,8 +71,8 @@ impl Scope {
|
||||
pub fn is_lambda_pattern_name(&self, name: &Ident) -> bool {
|
||||
if let Scope::LambdaPattern(pattern, _) = self {
|
||||
pattern
|
||||
.entries()
|
||||
.any(|entry| entry.name().expect("entry.name").as_str() == name.as_str())
|
||||
.pat_entries()
|
||||
.any(|entry| entry.ident().expect("entry.ident").syntax().text() == name.syntax().text())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -85,25 +83,23 @@ impl Scope {
|
||||
match self {
|
||||
Scope::LambdaPattern(pattern, _) => Box::new(
|
||||
pattern
|
||||
.at()
|
||||
.map(|name| {
|
||||
let binding_node = name.node().clone();
|
||||
Binding::new(name, binding_node.clone(), binding_node, true)
|
||||
})
|
||||
.pat_bind()
|
||||
.and_then(|name| name.ident())
|
||||
.map(|name| Binding::new(name.clone(), name.syntax().clone(), name.syntax().clone(), true))
|
||||
.into_iter()
|
||||
.chain(pattern.entries().map(move |entry| {
|
||||
let name = entry.name().expect("entry.name");
|
||||
Binding::new(name, entry.node().clone(), entry.node().clone(), true)
|
||||
.chain(pattern.pat_entries().map(move |entry| {
|
||||
let name = entry.ident().expect("entry.ident");
|
||||
Binding::new(name, entry.syntax().clone(), entry.syntax().clone(), true)
|
||||
})),
|
||||
),
|
||||
|
||||
Scope::LambdaArg(name, _) => {
|
||||
let mortal = !name.as_str().starts_with('_');
|
||||
let mortal = name.syntax().text().char_at(0.into()) != Some('_');
|
||||
Box::new(
|
||||
Some(Binding::new(
|
||||
name.clone(),
|
||||
name.node().clone(),
|
||||
name.node().clone(),
|
||||
name.syntax().clone(),
|
||||
name.syntax().clone(),
|
||||
mortal,
|
||||
))
|
||||
.into_iter(),
|
||||
@ -115,24 +111,34 @@ impl Scope {
|
||||
.inherits()
|
||||
.flat_map(|inherit| {
|
||||
let body_node = if let Some(from) = inherit.from() {
|
||||
from.node().clone()
|
||||
from.syntax().clone()
|
||||
} else {
|
||||
inherit.node().clone()
|
||||
inherit.syntax().clone()
|
||||
};
|
||||
inherit.idents().map(move |name| {
|
||||
let name_node = name.node().clone();
|
||||
Binding::new(name, body_node.clone(), name_node, true)
|
||||
inherit.attrs().filter_map(move |attr|
|
||||
match attr {
|
||||
Attr::Ident(ident) => Some(ident),
|
||||
_ => None,
|
||||
}
|
||||
).map(move |ident| {
|
||||
Binding::new(
|
||||
ident.clone(),
|
||||
body_node.clone(),
|
||||
ident.syntax().clone(),
|
||||
true
|
||||
)
|
||||
})
|
||||
})
|
||||
.chain(let_in.entries().map(|entry| {
|
||||
let key = entry
|
||||
.key()
|
||||
.expect("entry.key")
|
||||
.path()
|
||||
.next()
|
||||
.expect("key.path.next");
|
||||
let name = Ident::cast(key).expect("Ident::cast");
|
||||
Binding::new(name, entry.node().clone(), entry.node().clone(), true)
|
||||
.chain(let_in.attrpath_values().filter_map(|entry| {
|
||||
let attrpath = entry.attrpath()
|
||||
.expect("entry.attrpath");
|
||||
match attrpath.attrs().next() {
|
||||
Some(Attr::Ident(name)) =>
|
||||
Some(
|
||||
Binding::new(name, entry.syntax().clone(), entry.syntax().clone(), true)
|
||||
),
|
||||
_ => None,
|
||||
}
|
||||
})),
|
||||
),
|
||||
|
||||
@ -140,29 +146,29 @@ impl Scope {
|
||||
attr_set
|
||||
.inherits()
|
||||
.flat_map(|inherit| {
|
||||
let binding_node = inherit.node().clone();
|
||||
inherit.idents().map(move |name| {
|
||||
let name_node = name.node().clone();
|
||||
Binding::new(name, binding_node.clone(), name_node, false)
|
||||
inherit.attrs().filter_map(move |attr| {
|
||||
match attr {
|
||||
Attr::Ident(ref name) =>
|
||||
Some(
|
||||
Binding::new(name.clone(), inherit.syntax().clone(), attr.syntax().clone(), false)
|
||||
),
|
||||
_ =>
|
||||
None,
|
||||
}
|
||||
})
|
||||
})
|
||||
.chain(attr_set.entries().filter_map(|entry| {
|
||||
.chain(attr_set.attrpath_values().filter_map(|entry| {
|
||||
let key = entry
|
||||
.key()
|
||||
.expect("entry.key")
|
||||
.path()
|
||||
.next()
|
||||
.expect("key.path.next");
|
||||
if key.kind() == SyntaxKind::NODE_IDENT {
|
||||
let name = Ident::cast(key).expect("Ident::cast");
|
||||
Some(Binding::new(
|
||||
name,
|
||||
entry.node().clone(),
|
||||
entry.node().clone(),
|
||||
false,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
.attrpath()
|
||||
.expect("entry.attrpath")
|
||||
.attrs()
|
||||
.next();
|
||||
match key {
|
||||
Some(Attr::Ident(name)) =>
|
||||
Some(
|
||||
Binding::new(name, entry.syntax().clone(), entry.syntax().clone(), false)
|
||||
),
|
||||
_ => None,
|
||||
}
|
||||
})),
|
||||
),
|
||||
@ -176,8 +182,8 @@ impl Scope {
|
||||
match self {
|
||||
Scope::LambdaPattern(pattern, body) => Box::new(
|
||||
pattern
|
||||
.entries()
|
||||
.map(|entry| entry.node().clone())
|
||||
.pat_entries()
|
||||
.map(|entry| entry.syntax().clone())
|
||||
.chain(Some(body.clone()).into_iter()),
|
||||
),
|
||||
|
||||
@ -186,16 +192,20 @@ impl Scope {
|
||||
Scope::LetIn(let_in) => Box::new(
|
||||
let_in
|
||||
.inherits()
|
||||
.filter_map(|inherit| inherit.from().map(|from| from.node().clone()))
|
||||
.chain(let_in.entries().map(|entry| entry.node().clone()))
|
||||
.chain(let_in.body()),
|
||||
),
|
||||
.filter_map(|inherit| inherit.from().map(|from| from.syntax().clone()))
|
||||
.chain(
|
||||
let_in.attrpath_values().map(|entry| entry.syntax().clone())
|
||||
)
|
||||
.chain(
|
||||
let_in.body().map(|body| body.syntax().clone())
|
||||
),
|
||||
) },
|
||||
|
||||
Scope::RecAttrSet(attr_set) => Box::new(
|
||||
attr_set
|
||||
.inherits()
|
||||
.map(|inherit| inherit.node().clone())
|
||||
.chain(attr_set.entries().map(|entry| entry.node().clone())),
|
||||
.map(|inherit| inherit.syntax().clone())
|
||||
.chain(attr_set.attrpath_values().map(|entry| entry.syntax().clone())),
|
||||
),
|
||||
}
|
||||
}
|
||||
@ -211,15 +221,15 @@ impl Scope {
|
||||
|
||||
Scope::LetIn(let_in) => let_in.inherits().any(|inherit| {
|
||||
inherit.from().map_or_else(
|
||||
|| usage::find(name, inherit.node()),
|
||||
|from| usage::find(name, from.node()),
|
||||
|| usage::find(name, inherit.syntax()),
|
||||
|from| usage::find(name, from.syntax()),
|
||||
)
|
||||
}),
|
||||
|
||||
Scope::RecAttrSet(attr_set) => attr_set.inherits().any(|inherit| {
|
||||
inherit.from().map_or_else(
|
||||
|| usage::find(name, inherit.node()),
|
||||
|from| usage::find(name, from.node()),
|
||||
|| usage::find(name, inherit.syntax()),
|
||||
|from| usage::find(name, from.syntax()),
|
||||
)
|
||||
}),
|
||||
}
|
||||
|
19
src/usage.rs
19
src/usage.rs
@ -1,9 +1,9 @@
|
||||
use crate::scope::Scope;
|
||||
use rnix::{
|
||||
types::{Ident, TokenWrapper, TypedNode},
|
||||
ast::Ident,
|
||||
NixLanguage, SyntaxKind,
|
||||
};
|
||||
use rowan::api::SyntaxNode;
|
||||
use rowan::{api::SyntaxNode, ast::AstNode};
|
||||
|
||||
/// find out if `name` is used in `node`
|
||||
pub fn find(name: &Ident, node: &SyntaxNode<NixLanguage>) -> bool {
|
||||
@ -13,7 +13,7 @@ pub fn find(name: &Ident, node: &SyntaxNode<NixLanguage>) -> bool {
|
||||
}
|
||||
|
||||
for binding in scope.bindings() {
|
||||
if binding.name.as_str() == name.as_str() {
|
||||
if binding.name.syntax().text() == name.syntax().text() {
|
||||
// shadowed by a a new child scope that redefines the
|
||||
// variable with the same name
|
||||
return false;
|
||||
@ -21,8 +21,17 @@ pub fn find(name: &Ident, node: &SyntaxNode<NixLanguage>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
if node.kind() == SyntaxKind::NODE_IDENT {
|
||||
Ident::cast(node.clone()).expect("Ident::cast").as_str() == name.as_str()
|
||||
let ident = if node.kind() == SyntaxKind::NODE_IDENT {
|
||||
if let Some(ident) = Ident::cast(node.clone()) {
|
||||
Some(ident)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(ident) = &ident {
|
||||
ident.syntax().text() == name.syntax().text()
|
||||
} else {
|
||||
node.children().any(|node| find(name, &node))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user