code-moniker-core 0.6.0

Core symbol-graph types and per-language extractors for code-moniker.
Documentation
use std::collections::HashMap;

use tree_sitter::Node;

use crate::core::moniker::Moniker;
use crate::lang::sdk::{DiscoveredDef, ResolvedRef, ResolvedRefDeduper, TypeExpr};

use super::super::Presets;
use super::defs::{collect_defs, predeclare_types};
use super::refs::collect_refs;

pub(super) type CallableTable = HashMap<Vec<u8>, Vec<u8>>;
pub(super) type ReturnTypeTable = HashMap<Vec<u8>, TypeExpr>;
pub(super) type FieldTypeTable = HashMap<(Moniker, Vec<u8>), TypeExpr>;
pub(super) type VarTypeTable = HashMap<Vec<u8>, TypeExpr>;

pub(super) struct DiscoveredCFile {
	pub root: Moniker,
	pub defs: Vec<DiscoveredDef>,
	pub refs: Vec<ResolvedRef>,
}

pub(super) struct CDiscover<'src> {
	pub(super) root: Moniker,
	pub(super) source: &'src [u8],
	pub(super) deep: bool,
	pub(super) defs: Vec<DiscoveredDef>,
	pub(super) refs: Vec<ResolvedRef>,
	ref_deduper: ResolvedRefDeduper,
	pub(super) type_table: HashMap<Vec<u8>, Moniker>,
	pub(super) callables: CallableTable,
	pub(super) macros: CallableTable,
	pub(super) return_types: ReturnTypeTable,
	pub(super) field_types: FieldTypeTable,
	pub(super) var_types: VarTypeTable,
	pub(super) presets: Presets,
}

impl<'src> CDiscover<'src> {
	pub fn run(
		root: Moniker,
		source: &'src [u8],
		deep: bool,
		root_node: Node<'_>,
		presets: &Presets,
	) -> DiscoveredCFile {
		let mut discover = Self {
			root: root.clone(),
			source,
			deep,
			defs: Vec::new(),
			refs: Vec::new(),
			ref_deduper: ResolvedRefDeduper::default(),
			type_table: HashMap::new(),
			callables: CallableTable::new(),
			macros: CallableTable::new(),
			return_types: ReturnTypeTable::new(),
			field_types: FieldTypeTable::new(),
			var_types: VarTypeTable::new(),
			presets: presets.clone(),
		};
		predeclare_types(&mut discover, root_node, &root);
		collect_defs(&mut discover, root_node, &root);
		collect_refs(&mut discover, root_node, &root);
		DiscoveredCFile {
			root,
			defs: discover.defs,
			refs: discover.refs,
		}
	}

	pub(super) fn push_def(&mut self, def: DiscoveredDef) {
		if !self
			.defs
			.iter()
			.any(|existing| existing.moniker == def.moniker)
		{
			self.defs.push(def);
		}
	}

	pub(super) fn upsert_def(&mut self, def: DiscoveredDef) {
		if let Some(existing) = self
			.defs
			.iter_mut()
			.find(|existing| existing.moniker == def.moniker)
		{
			*existing = def;
		} else {
			self.defs.push(def);
		}
	}

	pub(super) fn push_ref(&mut self, reference: ResolvedRef) {
		self.ref_deduper.push(&mut self.refs, reference);
	}
}