mirror of
https://github.com/astro/deadnix.git
synced 2025-01-06 04:37:06 +03:00
report: reuse ariadne
This commit is contained in:
parent
9f115c5beb
commit
ae4cf0aef4
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -2,6 +2,15 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ariadne"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7080ae01b2f0c312065d4914cd0f0de045eb8832e9415b355106a6cff3073cb4"
|
||||
dependencies = [
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
@ -59,6 +68,7 @@ checksum = "328b822bdcba4d4e402be8d9adb6eebf269f969f8eadef977a553ff3c4fbcb58"
|
||||
name = "deadnix"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"ariadne",
|
||||
"clap",
|
||||
"rnix",
|
||||
"rowan",
|
||||
@ -257,3 +267,9 @@ name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71"
|
||||
|
@ -14,3 +14,4 @@ rowan = "0.12"
|
||||
rnix = "0.10"
|
||||
clap = "3"
|
||||
walkdir = "2"
|
||||
ariadne = "0.1"
|
||||
|
58
README.md
58
README.md
@ -38,38 +38,32 @@ $ nix run github:astro/deadnix test.nix
|
||||
```
|
||||
|
||||
```
|
||||
test.nix:1:
|
||||
> unusedArgs@{ unusedArg, usedArg, ... }:
|
||||
> ^^^^^^^^^^ ^^^^^^^^^
|
||||
> | |
|
||||
> | Unused lambda pattern: unusedArg
|
||||
> Unused lambda pattern: unusedArgs
|
||||
test.nix:3:
|
||||
> inherit (builtins) unused_inherit;
|
||||
> ^^^^^^^^^^^^^^
|
||||
> |
|
||||
> Unused let binding: unused_inherit
|
||||
test.nix:5:
|
||||
> unused = "fnord";
|
||||
> ^^^^^^
|
||||
> |
|
||||
> Unused let binding: unused
|
||||
test.nix:10:
|
||||
> shadowed = 42;
|
||||
> ^^^^^^^^
|
||||
> |
|
||||
> Unused let binding: shadowed
|
||||
test.nix:11:
|
||||
> _unused = unused: false;
|
||||
> ^^^^^^^ ^^^^^^
|
||||
> | |
|
||||
> | Unused lambda argument: unused
|
||||
> Unused let binding: _unused
|
||||
test.nix:13:
|
||||
> x = { unusedArg2, x ? args.y, ... }@args: used1 + x;
|
||||
> ^^^^^^^^^^
|
||||
> |
|
||||
> Unused lambda pattern: unusedArg2
|
||||
Warning: Unused declarations were found.
|
||||
╭─[example.nix:1:1]
|
||||
│
|
||||
1 │ unusedArgs@{ unusedArg, usedArg, ... }:
|
||||
· ─────┬──── ────┬────
|
||||
· │ ╰────── Unused lambda pattern: unusedArg
|
||||
· │
|
||||
· ╰────────────────── Unused lambda pattern: unusedArgs
|
||||
3 │ inherit (builtins) unused_inherit;
|
||||
· ───────┬──────
|
||||
· ╰──────── Unused let binding: unused_inherit
|
||||
5 │ unused = "fnord";
|
||||
· ───┬──
|
||||
· ╰──── Unused let binding: unused
|
||||
10 │ shadowed = 42;
|
||||
· ────┬───
|
||||
· ╰───── Unused let binding: shadowed
|
||||
11 │ _unused = unused: false;
|
||||
· ───┬─── ───┬──
|
||||
· │ ╰──── Unused lambda argument: unused
|
||||
· │
|
||||
· ╰────────────── Unused let binding: _unused
|
||||
13 │ x = { unusedArg2, x ? args.y, ... }@args: used1 + x;
|
||||
· ─────┬────
|
||||
· ╰────── Unused lambda pattern: unusedArg2
|
||||
────╯
|
||||
```
|
||||
|
||||
|
||||
|
@ -125,7 +125,7 @@ fn main() {
|
||||
let results = settings.find_dead_code(&ast.node());
|
||||
report_count += results.len();
|
||||
if !quiet && !results.is_empty() {
|
||||
crate::report::Report::new(file.to_string(), &content, results.clone()).print();
|
||||
crate::report::print(file.to_string(), &content, &results);
|
||||
}
|
||||
if edit {
|
||||
let new_ast = crate::edit::edit_dead_code(&content, results.into_iter());
|
||||
|
114
src/report.rs
114
src/report.rs
@ -1,98 +1,32 @@
|
||||
use ariadne::{Label, Report, ReportKind, sources};
|
||||
use crate::dead_code::DeadCode;
|
||||
use rnix::types::TypedNode;
|
||||
|
||||
pub struct LineReport {
|
||||
line_start: usize,
|
||||
line_number: usize,
|
||||
line: String,
|
||||
results: Vec<DeadCode>,
|
||||
}
|
||||
pub fn print(file: String, content: &str, results: &[DeadCode]) {
|
||||
let first_result_range = results[0].binding.name.node().text_range();
|
||||
let mut builder = Report::build(
|
||||
ReportKind::Warning,
|
||||
file.clone(),
|
||||
first_result_range.start().into()
|
||||
)
|
||||
.with_message("Unused declarations were found.");
|
||||
|
||||
pub struct Report {
|
||||
file_path: String,
|
||||
line_reports: Vec<LineReport>,
|
||||
}
|
||||
// reverse order to avoid overlapping lanes
|
||||
let mut order = results.len();
|
||||
for result in results {
|
||||
let range = result.binding.name.node().text_range();
|
||||
builder = builder.with_label(Label::new((file.clone(), range.start().into()..range.end().into()))
|
||||
.with_message(format!("{}", result))
|
||||
.with_color(result.scope.color())
|
||||
.with_order(order as i32)
|
||||
);
|
||||
|
||||
impl Report {
|
||||
/// Create a report grouped by line
|
||||
///
|
||||
/// Assumes results are pre-sorted by order of appearance.
|
||||
pub fn new(file_path: String, content: &str, results: Vec<DeadCode>) -> Self {
|
||||
let mut lines = Vec::new();
|
||||
let mut offset = 0;
|
||||
while let Some(next) = content[offset..].find('\n') {
|
||||
let line = &content[offset..offset + next];
|
||||
lines.push((offset, line));
|
||||
offset += next + 1;
|
||||
}
|
||||
lines.push((offset, &content[offset..]));
|
||||
|
||||
let mut last_line = 0;
|
||||
let mut line_reports = Vec::new();
|
||||
for result in results {
|
||||
let range = result.binding.name.node().text_range();
|
||||
let start = usize::from(range.start());
|
||||
let line_number = lines.iter().filter(|(offset, _)| *offset <= start).count();
|
||||
if line_number != last_line {
|
||||
last_line = line_number;
|
||||
line_reports.push(LineReport {
|
||||
line_start: lines[line_number - 1].0,
|
||||
line_number,
|
||||
line: lines[line_number - 1].1.to_string(),
|
||||
results: Vec::new(),
|
||||
});
|
||||
}
|
||||
let line_results = &mut line_reports.last_mut().unwrap().results;
|
||||
line_results.push(result);
|
||||
}
|
||||
|
||||
Report {
|
||||
file_path,
|
||||
line_reports,
|
||||
}
|
||||
order -= 1;
|
||||
}
|
||||
|
||||
pub fn print(&self) {
|
||||
for LineReport {
|
||||
line_start,
|
||||
line_number,
|
||||
line,
|
||||
results,
|
||||
} in &self.line_reports
|
||||
{
|
||||
// file location
|
||||
println!("{}:{}:", self.file_path, line_number);
|
||||
// line
|
||||
println!("> {}", line);
|
||||
|
||||
// underscores ^^^^^^^^^
|
||||
let mut pos = *line_start;
|
||||
print!("> ");
|
||||
for result in results.iter() {
|
||||
let range = result.binding.name.node().text_range();
|
||||
let start = usize::from(range.start());
|
||||
let end = usize::from(range.end());
|
||||
print!("{0: <1$}{2:^<3$}", "", start - pos, "", end - start);
|
||||
pos = end;
|
||||
}
|
||||
println!();
|
||||
|
||||
let mut bars = String::new();
|
||||
let mut pos = *line_start;
|
||||
for result in results.iter() {
|
||||
let range = result.binding.name.node().text_range();
|
||||
let start = usize::from(range.start());
|
||||
bars = format!("{}{1: <2$}|", bars, "", start - pos);
|
||||
pos = start + 1;
|
||||
}
|
||||
println!("> {}", bars);
|
||||
|
||||
// messages
|
||||
for result in results.iter().rev() {
|
||||
let range = result.binding.name.node().text_range();
|
||||
let start = usize::from(range.start());
|
||||
println!("> {}{}", &bars[..start - line_start], result);
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.finish()
|
||||
.print(sources(vec![
|
||||
(file, content)
|
||||
]))
|
||||
.unwrap()
|
||||
}
|
||||
|
18
src/scope.rs
18
src/scope.rs
@ -1,10 +1,11 @@
|
||||
use crate::{binding::Binding, usage};
|
||||
use std::fmt;
|
||||
use rnix::{
|
||||
types::{AttrSet, EntryHolder, Ident, Lambda, LetIn, Pattern, TokenWrapper, TypedNode},
|
||||
NixLanguage, SyntaxKind,
|
||||
};
|
||||
use rowan::api::SyntaxNode;
|
||||
use std::fmt;
|
||||
use ariadne::Color;
|
||||
use crate::{binding::Binding, usage};
|
||||
|
||||
/// AST subtree that declares variables
|
||||
#[derive(Debug, Clone)]
|
||||
@ -217,4 +218,17 @@ impl Scope {
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn color(&self) -> Color {
|
||||
match self {
|
||||
Scope::LambdaPattern(_, _) =>
|
||||
Color::Magenta,
|
||||
Scope::LambdaArg(_, _) =>
|
||||
Color::Cyan,
|
||||
Scope::LetIn(_) =>
|
||||
Color::Red,
|
||||
Scope::RecAttrSet(_) =>
|
||||
Color::Yellow,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user