Merge pull request #16 from ilkecan/json-output

report: add alternative output in JSON
This commit is contained in:
Astro 2022-02-09 21:29:44 +01:00 committed by GitHub
commit 0f78b370f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 1 deletions

25
Cargo.lock generated
View File

@ -72,6 +72,8 @@ dependencies = [
"clap",
"rnix",
"rowan",
"serde",
"serde_json",
"walkdir",
]
@ -106,6 +108,12 @@ dependencies = [
"hashbrown 0.11.2",
]
[[package]]
name = "itoa"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "libc"
version = "0.2.117"
@ -175,6 +183,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "ryu"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
[[package]]
name = "same-file"
version = "1.0.6"
@ -190,6 +204,17 @@ version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
[[package]]
name = "serde_json"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "smol_str"
version = "0.1.21"

View File

@ -15,3 +15,9 @@ rnix = "0.10"
clap = "3"
walkdir = "2"
ariadne = "0.1"
serde = { version = "1.0.136", optional = true }
serde_json = { version = "1.0.78", optional = true }
[features]
default = []
json-out = [ "serde", "serde_json" ]

View File

@ -56,6 +56,16 @@ fn main() {
.long("fail")
.help("Exit with 1 if unused code has been found"),
)
.arg(
clap::Arg::new("OUTPUT_FORMAT")
.short('o')
.long("output-format")
.takes_value(true)
.possible_value("human-readable")
.possible_value("json")
.default_value("human-readable")
.help("Output format to use"),
)
.arg(
clap::Arg::new("FILE_PATHS")
.multiple_values(true)
@ -80,6 +90,7 @@ fn main() {
.to_str()
.map_or(false, |s| s == "." || ! s.starts_with('.'))
};
let output_format = matches.value_of("OUTPUT_FORMAT");
let file_paths = matches.values_of("FILE_PATHS").expect("FILE_PATHS");
let files = file_paths.flat_map(|path| {
@ -125,7 +136,14 @@ fn main() {
let results = settings.find_dead_code(&ast.node());
report_count += results.len();
if !quiet && !results.is_empty() {
crate::report::print(file.to_string(), &content, &results);
match output_format {
Some("human-readable") => crate::report::print(file.to_string(), &content, &results),
#[cfg(feature = "json-out")]
Some("json") => crate::report::print_json(&file.to_string(), &content, &results),
#[cfg(not(feature = "json-out"))]
Some("json") => println!("`deadnix` needs to be built with `json-out` feature flag for JSON output format."),
_ => println!("Unknown output format."), // clap shouldn't allow this case
};
}
if edit {
let new_ast = crate::edit::edit_dead_code(&content, results.into_iter());

View File

@ -2,6 +2,9 @@ use ariadne::{Config, Label, Report, ReportKind, sources};
use crate::dead_code::DeadCode;
use rnix::{TextSize, types::TypedNode};
#[cfg(feature = "json-out")]
use serde_json::json;
// assumes results to be sorted by occurrence in file
pub fn print(file: String, content: &str, results: &[DeadCode]) {
let first_result_range = results[0].binding.name.node().text_range();
@ -55,3 +58,37 @@ pub fn print(file: String, content: &str, results: &[DeadCode]) {
]))
.unwrap();
}
#[cfg(feature = "json-out")]
pub fn print_json(file: &str, content: &str, results: &[DeadCode]) {
let mut offset = 0;
let mut offsets = vec![offset];
while let Some(next) = content[offset..].find('\n') {
offset += next + 1;
offsets.push(offset);
}
let json = json!({
"file": file,
"results": results.iter().map(|result| {
let range = result.binding.name.node().text_range();
let start = usize::from(range.start());
let mut line_number = 0;
let mut line_offset = 0;
for &offset in &offsets {
if start < offset {
break;
}
line_number += 1;
line_offset = offset;
}
json!({
"message": format!("{}", result),
"line": line_number,
"column": start - line_offset + 1,
"endColumn": usize::from(range.end()) - line_offset + 1,
})
}).collect::<serde_json::Value>(),
});
println!("{}", json);
}