use anyhow::Result;
use llvm_profparser::*;
use std::fs;
use std::path::PathBuf;
use structopt::StructOpt;
use tracing_subscriber::filter::filter_fn;
use tracing_subscriber::{Layer, Registry};
#[derive(Clone, Debug, Eq, PartialEq, StructOpt)]
pub struct Opts {
#[structopt(subcommand)]
cmd: Command,
}
#[derive(Clone, Debug, Eq, PartialEq, StructOpt)]
pub enum Command {
Show {
#[structopt(flatten)]
show: ShowCommand,
},
}
#[derive(Clone, Debug, Eq, PartialEq, StructOpt)]
pub struct ShowCommand {
#[structopt(long = "instr-profile")]
instr_profile: Vec<PathBuf>,
#[structopt(long = "object")]
objects: Vec<PathBuf>,
#[structopt(long = "path-equivalence")]
path_remapping: Option<PathRemapping>,
#[structopt(long)]
debug: bool,
}
impl ShowCommand {
fn run(&self) -> Result<()> {
if self.debug {
let _ = enable_debug_logging();
}
let instr_prof = if self.instr_profile.len() == 1 {
parse(&self.instr_profile[0])?
} else if self.instr_profile.len() > 1 {
merge_profiles(&self.instr_profile)?
} else {
panic!("Must provide an instrumentation profile");
};
let mapping = CoverageMapping::new(&self.objects, &instr_prof, false)?;
let mut report = mapping.generate_report();
if let Some(remapping) = self.path_remapping.as_ref() {
report.apply_remapping(remapping);
}
for (path, result) in report.files.iter() {
if let Ok(source) = fs::read_to_string(path) {
if report.files.len() > 1 {
println!("{}", path.display());
}
for (line, source) in source.lines().enumerate() {
print!("{: >5}|", line + 1);
if let Some(hits) = result.hits_for_line(line + 1) {
println!("{: >7}|{}", hits, source);
} else {
println!(" |{}", source);
}
}
println!();
}
}
Ok(())
}
}
fn enable_debug_logging() -> anyhow::Result<()> {
let fmt = tracing_subscriber::fmt::Layer::default();
let subscriber = fmt
.with_filter(filter_fn(|metadata| {
metadata.target().contains("llvm_profparser")
}))
.with_subscriber(Registry::default());
tracing::subscriber::set_global_default(subscriber)?;
Ok(())
}
fn main() -> Result<()> {
let opts = Opts::from_args();
match opts.cmd {
Command::Show { show } => show.run(),
}
}