-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathmod.rs
More file actions
145 lines (120 loc) · 4.48 KB
/
mod.rs
File metadata and controls
145 lines (120 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use bimap::BiMap;
use derive_new::new;
use getset::{CopyGetters, Getters};
use rustc_hash::{FxHashMap, FxHashSet};
use slotmap::{SecondaryMap, SlotMap, new_key_type};
use std::sync::{LazyLock, RwLock};
use string_interner::backend::StringBackend;
use string_interner::{DefaultSymbol, StringInterner};
pub mod cycles;
pub mod direct_import_queries;
pub mod graph_manipulation;
pub mod hierarchy_queries;
pub mod higher_order_queries;
pub mod import_chain_queries;
pub(crate) mod pathfinding;
static MODULE_NAMES: LazyLock<RwLock<StringInterner<StringBackend>>> =
LazyLock::new(|| RwLock::new(StringInterner::default()));
static IMPORT_LINE_CONTENTS: LazyLock<RwLock<StringInterner<StringBackend>>> =
LazyLock::new(|| RwLock::new(StringInterner::default()));
static EMPTY_MODULE_TOKENS: LazyLock<FxHashSet<ModuleToken>> = LazyLock::new(FxHashSet::default);
static EMPTY_IMPORT_DETAILS: LazyLock<FxHashSet<ImportDetails>> = LazyLock::new(FxHashSet::default);
new_key_type! { pub struct ModuleToken; }
#[derive(Debug, Clone, PartialEq, Eq, Hash, Getters, CopyGetters)]
pub struct Module {
#[getset(get_copy = "pub")]
token: ModuleToken,
#[getset(get_copy = "pub")]
interned_name: DefaultSymbol,
// Invisible modules exist in the hierarchy but haven't been explicitly added to the graph.
#[getset(get_copy = "pub")]
is_invisible: bool,
#[getset(get_copy = "pub")]
is_squashed: bool,
}
impl Module {
pub fn name(&self) -> String {
let interner = MODULE_NAMES.read().unwrap();
interner.resolve(self.interned_name).unwrap().to_owned()
}
}
#[derive(Default, Clone)]
pub struct Graph {
// Hierarchy
modules_by_name: BiMap<DefaultSymbol, ModuleToken>,
modules: SlotMap<ModuleToken, Module>,
module_parents: SecondaryMap<ModuleToken, Option<ModuleToken>>,
module_children: SecondaryMap<ModuleToken, FxHashSet<ModuleToken>>,
// Imports
imports: SecondaryMap<ModuleToken, FxHashSet<ModuleToken>>,
reverse_imports: SecondaryMap<ModuleToken, FxHashSet<ModuleToken>>,
import_details: FxHashMap<(ModuleToken, ModuleToken), FxHashSet<ImportDetails>>,
}
impl From<ModuleToken> for Vec<ModuleToken> {
fn from(value: ModuleToken) -> Self {
vec![value]
}
}
impl From<ModuleToken> for FxHashSet<ModuleToken> {
fn from(value: ModuleToken) -> Self {
FxHashSet::from_iter([value])
}
}
pub trait ExtendWithDescendants:
Sized + Clone + IntoIterator<Item = ModuleToken> + Extend<ModuleToken>
{
/// Extend this collection of module tokens with all descendant items.
fn extend_with_descendants(&mut self, graph: &Graph) {
for item in self.clone().into_iter() {
let descendants = graph.get_module_descendants(item).map(|item| item.token());
self.extend(descendants);
}
}
/// Extend this collection of module tokens with all descendant items.
fn with_descendants(mut self, graph: &Graph) -> Self {
self.extend_with_descendants(graph);
self
}
}
impl<T: Sized + Clone + IntoIterator<Item = ModuleToken> + Extend<ModuleToken>>
ExtendWithDescendants for T
{
}
pub trait ModuleIterator<'a>: Iterator<Item = &'a Module> + Sized {
fn tokens(self) -> impl Iterator<Item = ModuleToken> {
self.map(|m| m.token)
}
fn interned_names(self) -> impl Iterator<Item = DefaultSymbol> {
self.map(|m| m.interned_name)
}
fn names(self) -> impl Iterator<Item = String> {
let interner = MODULE_NAMES.read().unwrap();
self.map(move |m| interner.resolve(m.interned_name).unwrap().to_owned())
}
fn visible(self) -> impl ModuleIterator<'a> {
self.filter(|m| !m.is_invisible)
}
}
impl<'a, T: Iterator<Item = &'a Module>> ModuleIterator<'a> for T {}
pub trait ModuleTokenIterator<'a>: Iterator<Item = &'a ModuleToken> + Sized {
fn into_module_iterator(self, graph: &'a Graph) -> impl ModuleIterator<'a> {
self.map(|m| graph.get_module(*m).unwrap())
}
}
impl<'a, T: Iterator<Item = &'a ModuleToken>> ModuleTokenIterator<'a> for T {}
#[derive(Debug, Clone, PartialEq, Eq, Hash, new, Getters, CopyGetters)]
pub struct ImportDetails {
#[getset(get_copy = "pub")]
line_number: u32,
#[getset(get_copy = "pub")]
interned_line_contents: DefaultSymbol,
}
impl ImportDetails {
pub fn line_contents(&self) -> String {
let interner = IMPORT_LINE_CONTENTS.read().unwrap();
interner
.resolve(self.interned_line_contents)
.unwrap()
.to_owned()
}
}