code-moniker-workspace 0.7.1

Workspace model, ports, snapshots, linkage, and change analysis for code-moniker.
Documentation
use code_moniker_core::core::moniker::query::bare_callable_name;
use code_moniker_core::lang::kinds;

use crate::linkage::catalog::{LinkageCandidate, LinkageQuery};
use crate::linkage::language::generic_matches;
use crate::snapshot::{DynamicReason, ReferenceRecord};
use crate::source::CodeIndexMaterial;

pub(super) fn matches(query: &LinkageQuery<'_>, candidate: &LinkageCandidate<'_>) -> bool {
	generic_matches(query, candidate) || csharp_name_target_matches_def(query, candidate)
}

fn csharp_name_target_matches_def(
	query: &LinkageQuery<'_>,
	candidate: &LinkageCandidate<'_>,
) -> bool {
	let Some(target) = query.target_last else {
		return false;
	};
	let Some(candidate_segment) = candidate.last_segment else {
		return false;
	};
	if is_type_kind(target.kind) && is_type_kind(candidate_segment.kind) {
		return target.name == candidate_segment.name
			|| (query.reference_kind == "annotates"
				&& candidate_segment
					.name
					.strip_suffix(b"Attribute")
					.is_some_and(|short_name| short_name == target.name));
	}
	if !is_target_callable_kind(target.kind) || !is_def_callable_kind(candidate_segment.kind) {
		return false;
	}
	let target_name = query
		.call_name
		.map(str::as_bytes)
		.unwrap_or_else(|| bare_callable_name(target.name));
	let candidate_name = candidate
		.call_name
		.unwrap_or_else(|| bare_callable_name(candidate_segment.name));
	target_name == candidate_name && call_arity_matches(query.call_arity, candidate.call_arity)
}

fn call_arity_matches(call: Option<usize>, definition: Option<usize>) -> bool {
	match (call, definition) {
		(Some(call), Some(definition)) => call == definition,
		_ => true,
	}
}

fn is_type_kind(kind: &[u8]) -> bool {
	matches!(
		kind,
		kinds::CLASS | kinds::INTERFACE | kinds::STRUCT | kinds::RECORD | kinds::ENUM | b"delegate"
	)
}

fn is_target_callable_kind(kind: &[u8]) -> bool {
	matches!(kind, kinds::FUNCTION | kinds::METHOD | kinds::CONSTRUCTOR)
}

fn is_def_callable_kind(kind: &[u8]) -> bool {
	matches!(kind, kinds::METHOD | kinds::CONSTRUCTOR)
}

pub(super) fn classify_open_reference(
	material: &CodeIndexMaterial,
	decision: &mut crate::linkage::binding::ReferenceLinkageDecision,
	reference_idx: usize,
	reference: &ReferenceRecord,
) {
	let imported_external = reference.confidence.as_deref() == Some("imported")
		&& material
			.reference_target(&reference.id)
			.is_some_and(super::external_target_shape);
	let reason = if imported_external {
		Some(DynamicReason::ExternalDependencyUnindexed)
	} else if reference.confidence.as_deref() == Some("name_match")
		&& matches!(
			reference.kind.as_str(),
			"method_call"
				| "calls" | "uses_type"
				| "typed_as" | "annotates"
				| "instantiates"
				| "extends"
		) {
		Some(DynamicReason::InsufficientLocalFacts)
	} else {
		None
	};
	let Some(reason) = reason else { return };
	let candidates = decision
		.linkage_targets()
		.cloned()
		.unwrap_or_else(crate::linkage::catalog::SymbolSet::new);
	*decision = crate::linkage::binding::ReferenceLinkageDecision::dynamic(
		reason,
		reference_idx,
		reference.id,
		candidates,
	);
}