Skip to main content

pedant_graph/
node.rs

1//! A graph node: one structural entity, its language, and where its bytes sit.
2
3use std::sync::Arc;
4
5use pedant_types::{Language, SourceSpan};
6use serde::Serialize;
7
8use crate::id::GraphNodeId;
9
10/// What kind of entity a node is.
11///
12/// The categories are stable graph concepts. The attribute strings are
13/// language-declared vocabulary, so another producer may add a level or a
14/// declaration name without changing the schema. A producer emits a non-empty
15/// lower-snake-case value.
16#[derive(Serialize, Clone, Debug, PartialEq, Eq)]
17#[serde(tag = "category", rename_all = "snake_case")]
18pub enum GraphNodeKind {
19    /// One source artifact, qualified by the unit that instantiates it.
20    File,
21    /// A namespace that owns other entities.
22    Container {
23        /// The language's name for this container level.
24        level: Arc<str>,
25    },
26    /// A callable entity.
27    Function {
28        /// The language's name for this callable declaration.
29        declaration: Arc<str>,
30    },
31    /// A type entity.
32    Type {
33        /// The language's name for this type declaration.
34        declaration: Arc<str>,
35    },
36    /// A named value entity.
37    Value {
38        /// The language's name for this value declaration.
39        declaration: Arc<str>,
40    },
41}
42
43/// Where a node's bytes sit, when it has any.
44///
45/// A span identifies the unit-qualified file node that holds the bytes. That is
46/// a source association, never a containment parent.
47#[derive(Serialize, Clone, Debug, PartialEq, Eq)]
48#[serde(tag = "kind", rename_all = "snake_case")]
49pub enum GraphNodeLocation {
50    /// The node is the source artifact itself.
51    File {
52        /// The normalized repository-relative path.
53        path: Arc<str>,
54    },
55    /// The node is declared at one range of one file node's bytes.
56    Span {
57        /// The unit-qualified file node holding the declaration.
58        file: GraphNodeId,
59        /// The exact declaration range.
60        span: SourceSpan,
61    },
62}
63
64/// One structural entity of a code graph.
65#[derive(Serialize, Clone, Debug, PartialEq, Eq)]
66pub struct GraphNode {
67    id: GraphNodeId,
68    language: Language,
69    name: Arc<str>,
70    kind: GraphNodeKind,
71    location: Option<GraphNodeLocation>,
72}
73
74/// Everything a projection states about one node before it has an identity.
75pub(crate) struct NodeDraft {
76    /// The language of the unit the node belongs to.
77    pub(crate) language: Language,
78    /// The declared name, or the normalized path for a file node.
79    pub(crate) name: Arc<str>,
80    /// What kind of entity the node is.
81    pub(crate) kind: GraphNodeKind,
82    /// Where the node's bytes sit, when it has any.
83    pub(crate) location: Option<GraphNodeLocation>,
84}
85
86impl GraphNode {
87    pub(crate) fn new(id: GraphNodeId, draft: NodeDraft) -> Self {
88        Self {
89            id,
90            language: draft.language,
91            name: draft.name,
92            kind: draft.kind,
93            location: draft.location,
94        }
95    }
96
97    /// This node's dense identity, equal to its position in the graph.
98    pub fn id(&self) -> GraphNodeId {
99        self.id
100    }
101
102    /// The language of the unit this node belongs to.
103    pub fn language(&self) -> Language {
104        self.language
105    }
106
107    /// The declared name, or the normalized path for a file node.
108    pub fn name(&self) -> &str {
109        &self.name
110    }
111
112    /// What kind of entity this node is.
113    pub fn kind(&self) -> &GraphNodeKind {
114        &self.kind
115    }
116
117    /// Where this node's bytes sit, when it has any.
118    pub fn location(&self) -> Option<&GraphNodeLocation> {
119        self.location.as_ref()
120    }
121}