code_split_plugin_api/lib.rs
1//! # code-split-plugin-api
2//!
3//! The contract everything in Code Split builds on: a **generic property-graph
4//! model** plus the [`LanguagePlugin`](plugin::LanguagePlugin) trait. This crate is the foundation — it
5//! depends on **nothing** else from Code Split and re-exports nothing. Every
6//! other crate (graph operations, complexity, language plugins, viewer, cli)
7//! depends on *this*.
8//!
9//! ## Model
10//!
11//! Analysis produces a [`Graph`](graph::Graph) of **[`Node`](node::Node)**s connected by **[`Edge`](edge::Edge)**s.
12//! A node is *anything we analyze*: today a source file (`kind == "file"`),
13//! tomorrow a folder, module, function, variable or line — with **no model
14//! change**. `kind` is a free-form [`String`] (the plugin's own vocabulary);
15//! the core never interprets it, it only stores and projects.
16//!
17//! Both nodes and edges carry free-form **[`Attributes`](attrs::Attributes)** (string key →
18//! scalar [`AttrValue`](attrs::AttrValue)). There is no fixed, file/language-specific field set:
19//! the plugin chooses keys (`path`, `loc`, `visibility`, `version`, or
20//! language-specific ones), the orchestrator adds computed keys (metrics,
21//! cycle), and the core reads only the keys it understands. Each level describes
22//! its keys with an [`AttributeSpec`](level::AttributeSpec) dictionary (type + label/hint), so the UI
23//! knows what each key means and what it can do with it.
24//!
25//! ## Responsibilities
26//!
27//! A [`LanguagePlugin`](plugin::LanguagePlugin) is a **pure parser**: it turns a workspace into nodes +
28//! edges at a requested level (by name; see [`Level`](level::Level)). It does **not**
29//! compute metrics — complexity / cycles / Henry-Kafura / stats are filled in
30//! centrally, for all languages, by the orchestrator. The plugin also describes
31//! its edge kinds ([`EdgeKindSpec`](level::EdgeKindSpec)) and attribute keys
32//! ([`AttributeSpec`](level::AttributeSpec)), so the core scores, draws and labels unknown
33//! kinds/keys without hardcoding their names.
34
35pub mod attrs;
36pub mod edge;
37pub mod graph;
38pub mod level;
39pub mod log;
40pub mod node;
41pub mod plugin;
42
43pub use attrs::{AttrValue, Attributes, ValueType};
44pub use edge::Edge;
45pub use graph::Graph;
46pub use level::{
47 AttributeGroup, AttributeSpec, CycleKindSpec, EdgeKindSpec, Level, NodeKindSpec, Thresholds,
48};
49pub use node::{Node, NodeId};
50pub use plugin::{LanguagePlugin, Options, PluginInput, Preset};
51
52use std::collections::BTreeMap;
53
54/// The generic node-kind palette every file-based plugin seeds its level with:
55/// `file` (a project source unit, blue) and `external` (a third-party library,
56/// amber, flagged external). A plugin may recolor or add kinds.
57pub fn default_node_kinds() -> BTreeMap<String, NodeKindSpec> {
58 BTreeMap::from([
59 (
60 "file".to_string(),
61 NodeKindSpec {
62 label: Some("File".into()),
63 plural: Some("Files".into()),
64 fill: Some("#dbe9f4".into()),
65 stroke: Some("#4d6f9c".into()),
66 external: None,
67 },
68 ),
69 (
70 "external".to_string(),
71 NodeKindSpec {
72 label: Some("Library".into()),
73 plural: Some("Libraries".into()),
74 fill: Some("#f6e2c0".into()),
75 stroke: Some("#b3801f".into()),
76 external: Some(true),
77 },
78 ),
79 ])
80}
81
82/// The generic cycle-kind vocabulary (`mutual` / `chain`).
83pub fn default_cycle_kinds() -> BTreeMap<String, CycleKindSpec> {
84 let k = |label: &str, desc: &str| CycleKindSpec {
85 label: Some(label.to_string()),
86 description: Some(desc.to_string()),
87 };
88 BTreeMap::from([
89 (
90 "mutual".to_string(),
91 k(
92 "Mutual",
93 "Two nodes that directly depend on each other (A ↔ B).",
94 ),
95 ),
96 (
97 "chain".to_string(),
98 k(
99 "Chain",
100 "Three or more nodes forming a dependency cycle (A → B → C → A).",
101 ),
102 ),
103 ])
104}