code-moniker-workspace 0.6.1

Workspace model, ports, snapshots, linkage, and change analysis for code-moniker.
Documentation
use std::time::Instant;

use rayon::prelude::*;

use crate::linkage::binding::LinkageStore;
use crate::linkage::catalog::CandidateCatalog;
use crate::linkage::catalog::ReferenceLocations;
use crate::linkage::resolve::BindingForwards;
use crate::linkage::resolve::ManifestPolicy;
use crate::linkage::resolve::MethodIndexer;
use crate::linkage::resolve::{LinkagePolicies, ReferenceResolver};
use crate::linkage::resolve::{
	LinkageRefiner, MethodTable, RefinementPolicies, WorkspacePackageIndex,
};
use crate::linkage::source_groups::SourceGroupPolicy;
use crate::linkage::{LinkageTimings, LocalLinkage, TimedLinkageSnapshot};
use crate::snapshot::{CodeIndex, ResourceGeneration, WorkspaceResult};
use crate::source::CodeIndexMaterial;

pub(in crate::linkage) fn run_full_linkage_with_timings(
	linkage: &mut LocalLinkage,
	index: &CodeIndex,
) -> WorkspaceResult<TimedLinkageSnapshot> {
	let total_timer = Instant::now();
	let material = linkage.linkage_material(index)?;
	let generation = linkage.cache.next_generation();
	let candidate_timer = Instant::now();
	let candidates =
		CandidateCatalog::new(&material, std::sync::Arc::clone(index.inventory.catalog()));
	let mut candidate_index = candidate_timer.elapsed();
	let method_timer = Instant::now();
	let method_indexer = MethodIndexer::new(&material, &candidates);
	candidate_index += method_timer.elapsed();
	let LinkageResolution { store, mut timings } = resolve_full_linkage(
		&material,
		index,
		generation,
		method_indexer.methods(),
		&candidates,
		candidate_index,
	);
	let report_timer = Instant::now();
	let snapshot =
		store.project_snapshot(&index.references, &material.identity, candidates.symbols());
	let memory = store.memory_metrics(candidates.symbols());
	timings.project_snapshot = report_timer.elapsed();
	timings.total = total_timer.elapsed();
	linkage.store = Some(store);
	linkage.candidates = Some(candidates);
	linkage.method_indexer = Some(method_indexer);
	linkage.memory = memory;
	Ok(TimedLinkageSnapshot {
		snapshot,
		timings,
		memory,
	})
}

fn resolve_full_linkage(
	material: &CodeIndexMaterial,
	index: &CodeIndex,
	generation: ResourceGeneration,
	methods: &MethodTable,
	candidates: &CandidateCatalog,
	candidate_index_elapsed: std::time::Duration,
) -> LinkageResolution {
	let mut timings = LinkageTimings {
		candidate_index: candidate_index_elapsed,
		..LinkageTimings::default()
	};
	let manifest_timer = Instant::now();
	let manifests = ManifestPolicy::build(material);
	trace_pass("manifest_policy", manifest_timer.elapsed());
	let source_groups = SourceGroupPolicy::build(material);
	trace_pass("source_groups", manifest_timer.elapsed());
	let packages = WorkspacePackageIndex::build(material);
	trace_pass("workspace_packages", manifest_timer.elapsed());
	let forwards = BindingForwards::build(material, &manifests);
	trace_pass("binding_forwards", manifest_timer.elapsed());
	let java_on_demand = crate::linkage::resolve::JavaOnDemandImports::build(material);
	timings.manifest_policy = manifest_timer.elapsed();
	trace_pass("linkage_policies", timings.manifest_policy);
	let policies = LinkagePolicies {
		candidates,
		manifests: &manifests,
		source_groups: &source_groups,
		packages: &packages,
		forwards: &forwards,
		java_on_demand: &java_on_demand,
	};
	let resolver = ReferenceResolver::new(material, &policies);
	let resolve_timer = Instant::now();
	let locations = ReferenceLocations::from_material(material);
	let mut decisions = (0..index.references.len())
		.into_par_iter()
		.map(|reference_idx| {
			resolver.resolve_reference(
				reference_idx,
				&index.references[reference_idx],
				locations.get(reference_idx),
			)
		})
		.collect::<Vec<_>>();
	timings.resolve_references = resolve_timer.elapsed();
	trace_pass("resolve_references", timings.resolve_references);
	let refinement_timer = Instant::now();
	LinkageRefiner::new(
		material,
		methods,
		candidates,
		&locations,
		RefinementPolicies::new(&source_groups, &packages, &manifests),
	)
	.refine(&mut decisions, &index.references);
	timings.semantic_refinement = refinement_timer.elapsed();
	let store_timer = Instant::now();
	let store = LinkageStore::new(
		generation,
		index.generation,
		decisions,
		&index.references,
		material,
		candidates,
	);
	timings.store_index = store_timer.elapsed();
	LinkageResolution { store, timings }
}

fn trace_pass(name: &str, elapsed: std::time::Duration) {
	if std::env::var_os("CODE_MONIKER_BENCH_TRACE").is_some() {
		eprintln!(
			"bench_linkage: {name} reached after {:.3} ms",
			elapsed.as_secs_f64() * 1_000.0
		);
	}
}

struct LinkageResolution {
	store: LinkageStore,
	timings: LinkageTimings,
}