aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/module_map.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis/src/module_map.rs')
-rw-r--r--crates/libanalysis/src/module_map.rs148
1 files changed, 115 insertions, 33 deletions
diff --git a/crates/libanalysis/src/module_map.rs b/crates/libanalysis/src/module_map.rs
index 9b4c778b6..83e6e57f7 100644
--- a/crates/libanalysis/src/module_map.rs
+++ b/crates/libanalysis/src/module_map.rs
@@ -2,17 +2,38 @@ use std::{
2 path::{PathBuf}, 2 path::{PathBuf},
3}; 3};
4 4
5use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
5use libsyntax2::{ 6use libsyntax2::{
6 ast::{self, AstNode, NameOwner}, 7 ast::{self, AstNode, NameOwner, ParsedFile},
7 SyntaxNode, ParsedFile, SmolStr, 8 SyntaxNode, SmolStr,
8}; 9};
9use {FileId, FileResolver}; 10use {FileId, FileResolver};
10 11
12type SyntaxProvider<'a> = dyn Fn(FileId) -> ParsedFile + 'a;
13
11#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] 14#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
12pub struct ModuleId(FileId); 15pub struct ModuleId(FileId);
13 16
14#[derive(Clone, Debug, Default)] 17#[derive(Debug, Default)]
15pub struct ModuleMap { 18pub struct ModuleMap {
19 state: RwLock<State>,
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum ChangeKind {
24 Delete, Insert, Update
25}
26
27impl Clone for ModuleMap {
28 fn clone(&self) -> ModuleMap {
29 let state = self.state.read().clone();
30 ModuleMap { state: RwLock::new(state) }
31 }
32}
33
34#[derive(Clone, Debug, Default)]
35struct State {
36 changes: Vec<(FileId, ChangeKind)>,
16 links: Vec<Link>, 37 links: Vec<Link>,
17} 38}
18 39
@@ -24,31 +45,8 @@ struct Link {
24} 45}
25 46
26impl ModuleMap { 47impl ModuleMap {
27 pub fn update_file( 48 pub fn update_file(&mut self, file: FileId, change_kind: ChangeKind) {
28 &mut self, 49 self.state.get_mut().changes.push((file, change_kind));
29 file_id: FileId,
30 syntax: Option<&ParsedFile>,
31 file_resolver: &FileResolver,
32 ) {
33 let mod_id = ModuleId(file_id);
34 self.links.retain(|link| link.owner != mod_id);
35 match syntax {
36 None => {
37 for link in self.links.iter_mut() {
38 link.points_to.retain(|&x| x != mod_id);
39 }
40 }
41 Some(syntax) => {
42 self.links.extend(
43 syntax.ast().modules().filter_map(|it| {
44 Link::new(mod_id, it)
45 })
46 )
47 }
48 }
49 self.links.iter_mut().for_each(|link| {
50 link.resolve(file_resolver)
51 })
52 } 50 }
53 51
54 pub fn module2file(&self, m: ModuleId) -> FileId { 52 pub fn module2file(&self, m: ModuleId) -> FileId {
@@ -59,8 +57,15 @@ impl ModuleMap {
59 ModuleId(file_id) 57 ModuleId(file_id)
60 } 58 }
61 59
62 pub fn child_module_by_name(&self, parent_mod: ModuleId, child_mod: &str) -> Vec<ModuleId> { 60 pub fn child_module_by_name<'a>(
63 self.links 61 &self,
62 parent_mod: ModuleId,
63 child_mod: &str,
64 file_resolver: &FileResolver,
65 syntax_provider: &SyntaxProvider,
66 ) -> Vec<ModuleId> {
67 self.links(file_resolver, syntax_provider)
68 .links
64 .iter() 69 .iter()
65 .filter(|link| link.owner == parent_mod) 70 .filter(|link| link.owner == parent_mod)
66 .filter(|link| link.name() == child_mod) 71 .filter(|link| link.name() == child_mod)
@@ -69,13 +74,90 @@ impl ModuleMap {
69 .collect() 74 .collect()
70 } 75 }
71 76
72 pub fn parent_modules<'a>(&'a self, m: ModuleId) -> impl Iterator<Item=(ModuleId, ast::Module<'a>)> + 'a { 77 pub fn parent_modules(
73 self.links 78 &self,
79 m: ModuleId,
80 file_resolver: &FileResolver,
81 syntax_provider: &SyntaxProvider,
82 ) -> Vec<(ModuleId, SmolStr, SyntaxNode)> {
83 let links = self.links(file_resolver, syntax_provider);
84 let res = links
85 .links
74 .iter() 86 .iter()
75 .filter(move |link| link.points_to.iter().any(|&it| it == m)) 87 .filter(move |link| link.points_to.iter().any(|&it| it == m))
76 .map(|link| { 88 .map(|link| {
77 (link.owner, link.ast()) 89 (link.owner, link.name().clone(), link.syntax.clone())
78 }) 90 })
91 .collect();
92 res
93 }
94
95 fn links(
96 &self,
97 file_resolver: &FileResolver,
98 syntax_provider: &SyntaxProvider,
99 ) -> RwLockReadGuard<State> {
100 {
101 let guard = self.state.read();
102 if guard.changes.is_empty() {
103 return guard;
104 }
105 }
106 let mut guard = self.state.write();
107 if !guard.changes.is_empty() {
108 guard.apply_changes(file_resolver, syntax_provider);
109 }
110 assert!(guard.changes.is_empty());
111 RwLockWriteGuard::downgrade(guard)
112 }
113}
114
115impl State {
116 pub fn apply_changes(
117 &mut self,
118 file_resolver: &FileResolver,
119 syntax_provider: &SyntaxProvider,
120 ) {
121 let mut reresolve = false;
122 for (file_id, kind) in self.changes.drain(..) {
123 let mod_id = ModuleId(file_id);
124 self.links.retain(|link| link.owner != mod_id);
125 match kind {
126 ChangeKind::Delete => {
127 for link in self.links.iter_mut() {
128 link.points_to.retain(|&x| x != mod_id);
129 }
130 }
131 ChangeKind::Insert => {
132 let file = syntax_provider(file_id);
133 self.links.extend(
134 file
135 .ast()
136 .modules()
137 .filter_map(|it| Link::new(mod_id, it))
138 );
139 reresolve = true;
140 }
141 ChangeKind::Update => {
142 let file = syntax_provider(file_id);
143 self.links.extend(
144 file
145 .ast()
146 .modules()
147 .filter_map(|it| Link::new(mod_id, it))
148 .map(|mut link| {
149 link.resolve(file_resolver);
150 link
151 })
152 );
153 }
154 }
155 }
156 if reresolve {
157 for link in self.links.iter_mut() {
158 link.resolve(file_resolver)
159 }
160 }
79 } 161 }
80} 162}
81 163