code_ranker_plugin_api/lib.rs
1//! # code-ranker-plugin-api
2//!
3//! The contract everything in Code Ranker 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 Ranker 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, Direction, EdgeKindSpec, Level, NodeKindSpec,
48 SpecRow, Thresholds, attr_dict, group,
49};
50pub use node::{Node, NodeId};
51pub use plugin::{LanguagePlugin, Options, PluginInput, Preset};
52
53use std::collections::BTreeMap;
54
55/// The generic node-kind palette every file-based plugin seeds its level with:
56/// `file` (a project source unit, blue) and `external` (a third-party library,
57/// amber, flagged external). A plugin may recolor or add kinds.
58pub fn default_node_kinds() -> BTreeMap<String, NodeKindSpec> {
59 BTreeMap::from([
60 (
61 "file".to_string(),
62 NodeKindSpec {
63 label: Some("File".into()),
64 plural: Some("Files".into()),
65 fill: Some("#dbe9f4".into()),
66 stroke: Some("#4d6f9c".into()),
67 external: None,
68 },
69 ),
70 (
71 "external".to_string(),
72 NodeKindSpec {
73 label: Some("Library".into()),
74 plural: Some("Libraries".into()),
75 fill: Some("#f6e2c0".into()),
76 stroke: Some("#b3801f".into()),
77 external: Some(true),
78 },
79 ),
80 ])
81}
82
83/// The generic cycle-kind vocabulary (`mutual` / `chain`).
84pub fn default_cycle_kinds() -> BTreeMap<String, CycleKindSpec> {
85 let k = |label: &str, desc: &str| CycleKindSpec {
86 label: Some(label.to_string()),
87 description: Some(desc.to_string()),
88 };
89 BTreeMap::from([
90 (
91 "mutual".to_string(),
92 k(
93 "Mutual",
94 "Two nodes that directly depend on each other (A ↔ B).",
95 ),
96 ),
97 (
98 "chain".to_string(),
99 k(
100 "Chain",
101 "Three or more nodes forming a dependency cycle (A → B → C → A).",
102 ),
103 ),
104 ])
105}