code-moniker-core 0.4.0

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

use crate::core::code_graph::Position;
use crate::core::moniker::Moniker;

use super::scope::{Namespace, ScopeId, ScopeTree};

#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub struct DefNameKey {
	pub namespace: Namespace,
	pub name: Vec<u8>,
}

impl DefNameKey {
	pub fn new(namespace: Namespace, name: impl Into<Vec<u8>>) -> Self {
		Self {
			namespace,
			name: name.into(),
		}
	}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiscoveredDef {
	pub moniker: Moniker,
	pub parent: Moniker,
	pub namespace: Namespace,
	pub name: Vec<u8>,
	pub kind: &'static [u8],
	pub visibility: &'static [u8],
	pub signature: Vec<u8>,
	pub position: Option<Position>,
	pub call_name: Vec<u8>,
	pub call_arity: Option<usize>,
}

impl DiscoveredDef {
	pub fn key(&self) -> DefNameKey {
		DefNameKey::new(self.namespace, self.name.clone())
	}
}

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct DefIndex {
	by_moniker: BTreeMap<Moniker, DiscoveredDef>,
	by_name: BTreeMap<DefNameKey, Vec<Moniker>>,
}

impl DefIndex {
	pub fn from_defs(defs: &[DiscoveredDef]) -> Self {
		let mut index = Self::default();
		for def in defs {
			index.insert(def.clone());
		}
		index
	}

	pub fn insert(&mut self, def: DiscoveredDef) {
		self.by_name
			.entry(def.key())
			.or_default()
			.push(def.moniker.clone());
		self.by_moniker.insert(def.moniker.clone(), def);
	}

	pub fn contains(&self, moniker: &Moniker) -> bool {
		self.by_moniker.contains_key(moniker)
	}

	pub fn get(&self, moniker: &Moniker) -> Option<&DiscoveredDef> {
		self.by_moniker.get(moniker)
	}

	pub fn by_name(&self, namespace: Namespace, name: &[u8]) -> &[Moniker] {
		self.by_name
			.get(&DefNameKey::new(namespace, name.to_vec()))
			.map(Vec::as_slice)
			.unwrap_or_default()
	}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ImportKind {
	Symbol,
	Module,
	Wildcard,
	Alias,
	Reexport,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ImportTarget {
	pub kind: ImportKind,
	pub namespace: Namespace,
	pub alias: Vec<u8>,
	pub target: Moniker,
	pub confidence: &'static [u8],
}

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ImportTable {
	by_scope: BTreeMap<ScopeId, Vec<ImportTarget>>,
}

impl ImportTable {
	pub fn insert(&mut self, scope: ScopeId, target: ImportTarget) {
		self.by_scope.entry(scope).or_default().push(target);
	}

	pub fn scoped(&self, scope: ScopeId) -> &[ImportTarget] {
		self.by_scope
			.get(&scope)
			.map(Vec::as_slice)
			.unwrap_or_default()
	}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DiscoveredFile {
	pub root: Moniker,
	pub root_kind: &'static [u8],
	pub defs: Vec<DiscoveredDef>,
	pub def_index: DefIndex,
	pub scopes: ScopeTree,
	pub imports: ImportTable,
}

impl DiscoveredFile {
	pub fn new(
		root: Moniker,
		root_kind: &'static [u8],
		defs: Vec<DiscoveredDef>,
		scopes: ScopeTree,
		imports: ImportTable,
	) -> Self {
		let def_index = DefIndex::from_defs(&defs);
		Self {
			root,
			root_kind,
			defs,
			def_index,
			scopes,
			imports,
		}
	}
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum TargetExpr {
	Bare(Vec<u8>),
	Path(Vec<Vec<u8>>),
	Receiver {
		receiver: Box<TargetExpr>,
		name: Vec<u8>,
	},
	SelfType(Vec<u8>),
	External {
		package: Vec<u8>,
		path: Vec<Vec<u8>>,
	},
}

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RefHints {
	pub receiver_hint: Vec<u8>,
	pub alias: Vec<u8>,
	pub namespace: Option<Namespace>,
	pub call_name: Vec<u8>,
	pub call_arity: Option<usize>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UnresolvedRef {
	pub source: Moniker,
	pub kind: &'static [u8],
	pub source_scope: ScopeId,
	pub position: Option<Position>,
	pub target: TargetExpr,
	pub hints: RefHints,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ResolvedRef {
	pub source: Moniker,
	pub target: Moniker,
	pub kind: &'static [u8],
	pub position: Option<Position>,
	pub confidence: &'static [u8],
	pub hints: RefHints,
}