use std::sync::Arc;
use pedant_core::resolution::rust::{CargoDependencyKind, CargoTargetKind, DependencyActivation};
use pedant_types::{ReferenceKind, ResolutionCertainty, SymbolKind};
use crate::edge::{GraphCertainty, GraphDependencyKind, GraphEdgeKind};
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) -> GraphNodeKind {
let (category, declaration) = self.declared(kind);
category.node(Arc::clone(declaration))
}
pub(crate) fn states_definition(&self, held: &GraphNodeKind, kind: SymbolKind) -> bool {
DefinitionCategory::stated(held) == Some(self.declared(kind))
}
fn declared(&self, kind: SymbolKind) -> (DefinitionCategory, &Arc<str>) {
match kind {
SymbolKind::Module => (DefinitionCategory::Container, &self.module_level),
SymbolKind::Function => (DefinitionCategory::Function, &self.function),
SymbolKind::Method => (DefinitionCategory::Function, &self.method),
SymbolKind::Struct => (DefinitionCategory::Type, &self.structure),
SymbolKind::Enum => (DefinitionCategory::Type, &self.enumeration),
SymbolKind::Union => (DefinitionCategory::Type, &self.union),
SymbolKind::Trait => (DefinitionCategory::Type, &self.trait_declaration),
SymbolKind::TypeAlias => (DefinitionCategory::Type, &self.type_alias),
SymbolKind::Constant => (DefinitionCategory::Value, &self.constant),
SymbolKind::Static => (DefinitionCategory::Value, &self.static_declaration),
}
}
}
#[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) -> GraphReferenceKind {
match kind {
ReferenceKind::Call => GraphReferenceKind::Call,
ReferenceKind::Import => GraphReferenceKind::Import,
ReferenceKind::Implementation => GraphReferenceKind::Implementation,
ReferenceKind::Module | ReferenceKind::Type => GraphReferenceKind::Reference,
}
}
pub(crate) fn candidate_edge_kind(kind: GraphReferenceKind) -> GraphEdgeKind {
match kind {
GraphReferenceKind::Call => GraphEdgeKind::Call,
GraphReferenceKind::Import => GraphEdgeKind::Import,
GraphReferenceKind::Implementation => GraphEdgeKind::Implementation,
GraphReferenceKind::Reference => GraphEdgeKind::Reference,
}
}
pub(crate) fn certainty(certainty: ResolutionCertainty) -> GraphCertainty {
match certainty {
ResolutionCertainty::Resolved => GraphCertainty::Resolved,
ResolutionCertainty::Possible => GraphCertainty::Possible,
}
}
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)))
}
}
}