use std::path::PathBuf;
use std::sync::Arc;
use std::time::Instant;
use mir_analyzer::{discover_files, AnalysisSession, IndexCancel, Name, PhpVersion};
fn main() {
let fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("benches/fixtures/laravel");
if !fixture.join("vendor").exists() || !fixture.join("src").exists() {
eprintln!(
"Laravel fixture not found at {}; run `bash {}/benches/download-fixtures.sh`",
fixture.display(),
env!("CARGO_MANIFEST_DIR")
);
std::process::exit(2);
}
let psr4 = Arc::new(
mir_analyzer::composer::Psr4Map::from_composer(&fixture)
.expect("failed to load composer.json"),
);
let session = AnalysisSession::new(PhpVersion::LATEST).with_psr4(psr4);
session.ensure_all_stubs();
let project_files = discover_files(&fixture.join("src"));
let vendor_files = discover_files(&fixture.join("vendor"));
eprintln!(
"loaded {} project files, {} vendor files",
project_files.len(),
vendor_files.len()
);
let workspace: Vec<(Arc<str>, Arc<str>)> = project_files
.iter()
.chain(vendor_files.iter())
.filter_map(|p| {
let src = std::fs::read_to_string(p).ok()?;
Some((
Arc::<str>::from(p.to_string_lossy().as_ref()),
Arc::<str>::from(src),
))
})
.collect();
session.set_workspace_files(workspace);
let project_paths: Vec<Arc<str>> = project_files
.iter()
.map(|p| Arc::<str>::from(p.to_string_lossy().as_ref()))
.collect();
let target = Name::class("Illuminate\\Support\\Str");
let t0 = Instant::now();
let refs = session
.indexed_references_to(&target, &project_paths, false, &|| false)
.expect("not cancelled");
let cold_elapsed = t0.elapsed();
eprintln!(
"cold indexed_references_to({target:?}): {:.3}s, {} references found",
cold_elapsed.as_secs_f64(),
refs.len()
);
let t1 = Instant::now();
let refs_warm = session
.indexed_references_to(&target, &project_paths, false, &|| false)
.expect("not cancelled");
eprintln!(
"warm repeat: {:.3}s, {} references found",
t1.elapsed().as_secs_f64(),
refs_warm.len()
);
assert_eq!(
refs.len(),
refs_warm.len(),
"warm repeat must match cold results"
);
let cancel = IndexCancel::new();
let dependents_target = project_files
.iter()
.find(|p| p.to_string_lossy().ends_with("Arr.php"))
.expect("Arr.php present in fixture");
let t2 = Instant::now();
let dependents =
session.reanalyze_dependents_cancellable(&dependents_target.to_string_lossy(), &cancel);
eprintln!(
"reanalyze_dependents(Arr.php): {:.3}s, {} dependents",
t2.elapsed().as_secs_f64(),
dependents.len()
);
let t3 = Instant::now();
let subtypes = session.subtype_files("Illuminate\\Support\\ServiceProvider");
eprintln!(
"subtype_files(ServiceProvider) cold: {:.3}s, {} files",
t3.elapsed().as_secs_f64(),
subtypes.len()
);
let t4 = Instant::now();
let n = 5;
for _ in 0..n {
let repeat = session.subtype_files("Illuminate\\Support\\ServiceProvider");
assert_eq!(repeat.len(), subtypes.len());
}
eprintln!(
"subtype_files(ServiceProvider) repeat: {:.3}s avg over {n}",
t4.elapsed().as_secs_f64() / n as f64
);
}