Add CSV output to analysis-stats

For easy diffing.
This commit is contained in:
Florian Diebold 2022-02-24 20:44:26 +01:00
parent f6901c952e
commit f807ccd6c0
3 changed files with 74 additions and 6 deletions

View file

@ -10,7 +10,11 @@ use hir::{
db::{AstDatabase, DefDatabase, HirDatabase},
AssocItem, Crate, Function, HasSource, HirDisplay, ModuleDef,
};
use hir_def::{body::BodySourceMap, expr::ExprId, FunctionId};
use hir_def::{
body::{BodySourceMap, SyntheticSyntax},
expr::ExprId,
FunctionId,
};
use hir_ty::{TyExt, TypeWalk};
use ide::{Analysis, AnalysisHost, LineCol, RootDatabase};
use ide_db::base_db::{
@ -28,7 +32,7 @@ use syntax::{AstNode, SyntaxNode};
use vfs::{AbsPathBuf, Vfs, VfsPath};
use crate::cli::{
flags,
flags::{self, OutputFormat},
load_cargo::{load_workspace, LoadCargoConfig},
print_memory_usage,
progress_report::ProgressReport,
@ -191,7 +195,7 @@ impl flags::AnalysisStats {
) {
let mut bar = match verbosity {
Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(),
_ if self.parallel => ProgressReport::hidden(),
_ if self.parallel || self.output.is_some() => ProgressReport::hidden(),
_ => ProgressReport::new(funcs.len() as u64),
};
@ -252,7 +256,7 @@ impl flags::AnalysisStats {
for (expr_id, _) in body.exprs.iter() {
let ty = &inference_result[expr_id];
num_exprs += 1;
if ty.is_unknown() {
let unknown_or_partial = if ty.is_unknown() {
num_exprs_unknown += 1;
if verbosity.is_spammy() {
if let Some((path, start, end)) =
@ -270,6 +274,7 @@ impl flags::AnalysisStats {
bar.println(format!("{}: Unknown type", name,));
}
}
true
} else {
let mut is_partially_unknown = false;
ty.walk(&mut |ty| {
@ -280,7 +285,8 @@ impl flags::AnalysisStats {
if is_partially_unknown {
num_exprs_partially_unknown += 1;
}
}
is_partially_unknown
};
if self.only.is_some() && verbosity.is_spammy() {
// in super-verbose mode for just one function, we print every single expression
if let Some((_, start, end)) =
@ -298,6 +304,13 @@ impl flags::AnalysisStats {
bar.println(format!("unknown location: {}", ty.display(db)));
}
}
if unknown_or_partial && self.output == Some(OutputFormat::Csv) {
println!(
r#"{},type,"{}""#,
location_csv(db, &analysis, vfs, &sm, expr_id),
ty.display(db)
);
}
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
num_type_mismatches += 1;
if verbosity.is_verbose() {
@ -323,6 +336,14 @@ impl flags::AnalysisStats {
));
}
}
if self.output == Some(OutputFormat::Csv) {
println!(
r#"{},mismatch,"{}","{}""#,
location_csv(db, &analysis, vfs, &sm, expr_id),
mismatch.expected.display(db),
mismatch.actual.display(db)
);
}
}
}
if verbosity.is_spammy() {
@ -358,6 +379,28 @@ impl flags::AnalysisStats {
}
}
fn location_csv(
db: &RootDatabase,
analysis: &Analysis,
vfs: &Vfs,
sm: &BodySourceMap,
expr_id: ExprId,
) -> String {
let src = match sm.expr_syntax(expr_id) {
Ok(s) => s,
Err(SyntheticSyntax) => return "synthetic,,".to_string(),
};
let root = db.parse_or_expand(src.file_id).unwrap();
let node = src.map(|e| e.to_node(&root).syntax().clone());
let original_range = node.as_ref().original_file_range(db);
let path = vfs.file_path(original_range.file_id);
let line_index = analysis.file_line_index(original_range.file_id).unwrap();
let text_range = original_range.range;
let (start, end) =
(line_index.line_col(text_range.start()), line_index.line_col(text_range.end()));
format!("{},{}:{},{}:{}", path, start.line + 1, start.col, end.line + 1, end.col)
}
fn expr_syntax_range(
db: &RootDatabase,
analysis: &Analysis,

View file

@ -1,6 +1,6 @@
//! Grammar for the command-line arguments.
#![allow(unreachable_pub)]
use std::path::PathBuf;
use std::{path::PathBuf, str::FromStr};
use ide_ssr::{SsrPattern, SsrRule};
@ -54,6 +54,8 @@ xflags::xflags! {
/// Directory with Cargo.toml.
required path: PathBuf
{
optional --output format: OutputFormat
/// Randomize order in which crates, modules, and items are processed.
optional --randomize
/// Run type inference in parallel.
@ -160,6 +162,7 @@ pub struct Highlight {
pub struct AnalysisStats {
pub path: PathBuf,
pub output: Option<OutputFormat>,
pub randomize: bool,
pub parallel: bool,
pub memory_usage: bool,
@ -215,6 +218,11 @@ impl RustAnalyzer {
}
// generated end
#[derive(Debug, PartialEq, Eq)]
pub enum OutputFormat {
Csv,
}
impl RustAnalyzer {
pub fn verbosity(&self) -> Verbosity {
if self.quiet {
@ -227,3 +235,14 @@ impl RustAnalyzer {
}
}
}
impl FromStr for OutputFormat {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"csv" => Ok(Self::Csv),
_ => Err(format!("unknown output format `{}`", s)),
}
}
}

View file

@ -113,9 +113,15 @@ pub struct Bb {
impl Xtask {
pub const HELP: &'static str = Self::HELP_;
#[allow(dead_code)]
pub fn from_env() -> xflags::Result<Self> {
Self::from_env_()
}
#[allow(dead_code)]
pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
Self::from_vec_(args)
}
}
// generated end