use std::sync::Arc;
use pedant_core::resolution::rust::{CargoDependencyKind, CargoTargetKind, DependencyActivation};
use pedant_types::{ReferenceKind, SymbolKind};
use crate::edge::{GraphCertainty, GraphDependencyKind};
use crate::node::GraphNodeKind;
use crate::reference::GraphReferenceKind;
pub(crate) struct Vocabulary {
library: Arc<str>,
binary: Arc<str>,
example: Arc<str>,
test: Arc<str>,
benchmark: Arc<str>,
build_script: Arc<str>,
module_level: Arc<str>,
function: Arc<str>,
method: Arc<str>,
structure: Arc<str>,
enumeration: Arc<str>,
union: Arc<str>,
trait_declaration: Arc<str>,
type_alias: Arc<str>,
constant: Arc<str>,
static_declaration: Arc<str>,
}
impl Vocabulary {
pub(crate) fn new() -> Self {
Self {
library: Arc::from("library"),
binary: Arc::from("binary"),
example: Arc::from("example"),
test: Arc::from("test"),
benchmark: Arc::from("benchmark"),
build_script: Arc::from("build_script"),
module_level: Arc::from("module"),
function: Arc::from("function"),
method: Arc::from("method"),
structure: Arc::from("struct"),
enumeration: Arc::from("enum"),
union: Arc::from("union"),
trait_declaration: Arc::from("trait"),
type_alias: Arc::from("type_alias"),
constant: Arc::from("constant"),
static_declaration: Arc::from("static"),
}
}
pub(crate) fn unit_root(&self, kind: CargoTargetKind) -> GraphNodeKind {
GraphNodeKind::Container {
level: Arc::clone(self.target_level(kind)),
}
}
fn target_level(&self, kind: CargoTargetKind) -> &Arc<str> {
match kind {
CargoTargetKind::Library => &self.library,
CargoTargetKind::Binary => &self.binary,
CargoTargetKind::Example => &self.example,
CargoTargetKind::Test => &self.test,
CargoTargetKind::Benchmark => &self.benchmark,
CargoTargetKind::BuildScript => &self.build_script,
}
}
pub(crate) fn definition(&self, kind: SymbolKind) -> Option<GraphNodeKind> {
let (category, declaration) = self.declared(kind)?;
Some(category.node(Arc::clone(declaration)))
}
pub(crate) fn states_definition(&self, held: &GraphNodeKind, kind: SymbolKind) -> bool {
self.declared(kind)
.is_some_and(|stated| DefinitionCategory::stated(held) == Some(stated))
}
fn declared(&self, kind: SymbolKind) -> Option<(DefinitionCategory, &Arc<str>)> {
match kind {
SymbolKind::Module => Some((DefinitionCategory::Container, &self.module_level)),
SymbolKind::Function => Some((DefinitionCategory::Function, &self.function)),
SymbolKind::Method => Some((DefinitionCategory::Function, &self.method)),
SymbolKind::Struct => Some((DefinitionCategory::Type, &self.structure)),
SymbolKind::Enum => Some((DefinitionCategory::Type, &self.enumeration)),
SymbolKind::Union => Some((DefinitionCategory::Type, &self.union)),
SymbolKind::Trait => Some((DefinitionCategory::Type, &self.trait_declaration)),
SymbolKind::TypeAlias => Some((DefinitionCategory::Type, &self.type_alias)),
SymbolKind::Constant => Some((DefinitionCategory::Value, &self.constant)),
SymbolKind::Static => Some((DefinitionCategory::Value, &self.static_declaration)),
SymbolKind::Package
| SymbolKind::Interface
| SymbolKind::DefinedType
| SymbolKind::Variable
| SymbolKind::Field => None,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum DefinitionCategory {
Container,
Function,
Type,
Value,
}
impl DefinitionCategory {
fn node(self, declaration: Arc<str>) -> GraphNodeKind {
match self {
Self::Container => GraphNodeKind::Container { level: declaration },
Self::Function => GraphNodeKind::Function { declaration },
Self::Type => GraphNodeKind::Type { declaration },
Self::Value => GraphNodeKind::Value { declaration },
}
}
fn stated(held: &GraphNodeKind) -> Option<(Self, &Arc<str>)> {
match held {
GraphNodeKind::File => None,
GraphNodeKind::Container { level } => Some((Self::Container, level)),
GraphNodeKind::Function { declaration } => Some((Self::Function, declaration)),
GraphNodeKind::Type { declaration } => Some((Self::Type, declaration)),
GraphNodeKind::Value { declaration } => Some((Self::Value, declaration)),
}
}
}
pub(crate) fn reference_kind(kind: ReferenceKind) -> Option<GraphReferenceKind> {
match kind {
ReferenceKind::Call => Some(GraphReferenceKind::Call),
ReferenceKind::Import => Some(GraphReferenceKind::Import),
ReferenceKind::Implementation => Some(GraphReferenceKind::Implementation),
ReferenceKind::Module | ReferenceKind::Type => Some(GraphReferenceKind::Reference),
ReferenceKind::Value => None,
}
}
pub(crate) fn dependency_kind(kind: CargoDependencyKind) -> GraphDependencyKind {
match kind {
CargoDependencyKind::Normal => GraphDependencyKind::Normal,
CargoDependencyKind::Development => GraphDependencyKind::Development,
CargoDependencyKind::Build => GraphDependencyKind::Build,
}
}
pub(crate) fn activation(activation: &DependencyActivation) -> (GraphCertainty, Option<Arc<str>>) {
match activation {
DependencyActivation::Always => (GraphCertainty::Resolved, None),
DependencyActivation::Conditional(predicate) => {
(GraphCertainty::Possible, Some(Arc::clone(predicate)))
}
}
}