mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-26 11:55:04 +00:00
Add CSV output to analysis-stats
For easy diffing.
This commit is contained in:
parent
f6901c952e
commit
f807ccd6c0
3 changed files with 74 additions and 6 deletions
|
@ -10,7 +10,11 @@ use hir::{
|
||||||
db::{AstDatabase, DefDatabase, HirDatabase},
|
db::{AstDatabase, DefDatabase, HirDatabase},
|
||||||
AssocItem, Crate, Function, HasSource, HirDisplay, ModuleDef,
|
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 hir_ty::{TyExt, TypeWalk};
|
||||||
use ide::{Analysis, AnalysisHost, LineCol, RootDatabase};
|
use ide::{Analysis, AnalysisHost, LineCol, RootDatabase};
|
||||||
use ide_db::base_db::{
|
use ide_db::base_db::{
|
||||||
|
@ -28,7 +32,7 @@ use syntax::{AstNode, SyntaxNode};
|
||||||
use vfs::{AbsPathBuf, Vfs, VfsPath};
|
use vfs::{AbsPathBuf, Vfs, VfsPath};
|
||||||
|
|
||||||
use crate::cli::{
|
use crate::cli::{
|
||||||
flags,
|
flags::{self, OutputFormat},
|
||||||
load_cargo::{load_workspace, LoadCargoConfig},
|
load_cargo::{load_workspace, LoadCargoConfig},
|
||||||
print_memory_usage,
|
print_memory_usage,
|
||||||
progress_report::ProgressReport,
|
progress_report::ProgressReport,
|
||||||
|
@ -191,7 +195,7 @@ impl flags::AnalysisStats {
|
||||||
) {
|
) {
|
||||||
let mut bar = match verbosity {
|
let mut bar = match verbosity {
|
||||||
Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(),
|
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),
|
_ => ProgressReport::new(funcs.len() as u64),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -252,7 +256,7 @@ impl flags::AnalysisStats {
|
||||||
for (expr_id, _) in body.exprs.iter() {
|
for (expr_id, _) in body.exprs.iter() {
|
||||||
let ty = &inference_result[expr_id];
|
let ty = &inference_result[expr_id];
|
||||||
num_exprs += 1;
|
num_exprs += 1;
|
||||||
if ty.is_unknown() {
|
let unknown_or_partial = if ty.is_unknown() {
|
||||||
num_exprs_unknown += 1;
|
num_exprs_unknown += 1;
|
||||||
if verbosity.is_spammy() {
|
if verbosity.is_spammy() {
|
||||||
if let Some((path, start, end)) =
|
if let Some((path, start, end)) =
|
||||||
|
@ -270,6 +274,7 @@ impl flags::AnalysisStats {
|
||||||
bar.println(format!("{}: Unknown type", name,));
|
bar.println(format!("{}: Unknown type", name,));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
true
|
||||||
} else {
|
} else {
|
||||||
let mut is_partially_unknown = false;
|
let mut is_partially_unknown = false;
|
||||||
ty.walk(&mut |ty| {
|
ty.walk(&mut |ty| {
|
||||||
|
@ -280,7 +285,8 @@ impl flags::AnalysisStats {
|
||||||
if is_partially_unknown {
|
if is_partially_unknown {
|
||||||
num_exprs_partially_unknown += 1;
|
num_exprs_partially_unknown += 1;
|
||||||
}
|
}
|
||||||
}
|
is_partially_unknown
|
||||||
|
};
|
||||||
if self.only.is_some() && verbosity.is_spammy() {
|
if self.only.is_some() && verbosity.is_spammy() {
|
||||||
// in super-verbose mode for just one function, we print every single expression
|
// in super-verbose mode for just one function, we print every single expression
|
||||||
if let Some((_, start, end)) =
|
if let Some((_, start, end)) =
|
||||||
|
@ -298,6 +304,13 @@ impl flags::AnalysisStats {
|
||||||
bar.println(format!("unknown location: {}", ty.display(db)));
|
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) {
|
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) {
|
||||||
num_type_mismatches += 1;
|
num_type_mismatches += 1;
|
||||||
if verbosity.is_verbose() {
|
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() {
|
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(
|
fn expr_syntax_range(
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
analysis: &Analysis,
|
analysis: &Analysis,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Grammar for the command-line arguments.
|
//! Grammar for the command-line arguments.
|
||||||
#![allow(unreachable_pub)]
|
#![allow(unreachable_pub)]
|
||||||
use std::path::PathBuf;
|
use std::{path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use ide_ssr::{SsrPattern, SsrRule};
|
use ide_ssr::{SsrPattern, SsrRule};
|
||||||
|
|
||||||
|
@ -54,6 +54,8 @@ xflags::xflags! {
|
||||||
/// Directory with Cargo.toml.
|
/// Directory with Cargo.toml.
|
||||||
required path: PathBuf
|
required path: PathBuf
|
||||||
{
|
{
|
||||||
|
optional --output format: OutputFormat
|
||||||
|
|
||||||
/// Randomize order in which crates, modules, and items are processed.
|
/// Randomize order in which crates, modules, and items are processed.
|
||||||
optional --randomize
|
optional --randomize
|
||||||
/// Run type inference in parallel.
|
/// Run type inference in parallel.
|
||||||
|
@ -160,6 +162,7 @@ pub struct Highlight {
|
||||||
pub struct AnalysisStats {
|
pub struct AnalysisStats {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
|
|
||||||
|
pub output: Option<OutputFormat>,
|
||||||
pub randomize: bool,
|
pub randomize: bool,
|
||||||
pub parallel: bool,
|
pub parallel: bool,
|
||||||
pub memory_usage: bool,
|
pub memory_usage: bool,
|
||||||
|
@ -215,6 +218,11 @@ impl RustAnalyzer {
|
||||||
}
|
}
|
||||||
// generated end
|
// generated end
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum OutputFormat {
|
||||||
|
Csv,
|
||||||
|
}
|
||||||
|
|
||||||
impl RustAnalyzer {
|
impl RustAnalyzer {
|
||||||
pub fn verbosity(&self) -> Verbosity {
|
pub fn verbosity(&self) -> Verbosity {
|
||||||
if self.quiet {
|
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)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -113,9 +113,15 @@ pub struct Bb {
|
||||||
impl Xtask {
|
impl Xtask {
|
||||||
pub const HELP: &'static str = Self::HELP_;
|
pub const HELP: &'static str = Self::HELP_;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn from_env() -> xflags::Result<Self> {
|
pub fn from_env() -> xflags::Result<Self> {
|
||||||
Self::from_env_()
|
Self::from_env_()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
|
||||||
|
Self::from_vec_(args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// generated end
|
// generated end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue