diff options
author | Aleksey Kladov <[email protected]> | 2018-08-21 20:24:59 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-21 20:24:59 +0100 |
commit | ecc9df5f009deb8e8bbd8e52db9afbe41f8f880c (patch) | |
tree | 562598b1215fd67dc93860acca66852c114bc5c0 /crates/libanalysis/src/module_map.rs | |
parent | b937262c9b75a361b95a6a27260a71c737e035bf (diff) |
simpler update
Diffstat (limited to 'crates/libanalysis/src/module_map.rs')
-rw-r--r-- | crates/libanalysis/src/module_map.rs | 148 |
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 | ||
5 | use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard}; | ||
5 | use libsyntax2::{ | 6 | use libsyntax2::{ |
6 | ast::{self, AstNode, NameOwner}, | 7 | ast::{self, AstNode, NameOwner, ParsedFile}, |
7 | SyntaxNode, ParsedFile, SmolStr, | 8 | SyntaxNode, SmolStr, |
8 | }; | 9 | }; |
9 | use {FileId, FileResolver}; | 10 | use {FileId, FileResolver}; |
10 | 11 | ||
12 | type SyntaxProvider<'a> = dyn Fn(FileId) -> ParsedFile + 'a; | ||
13 | |||
11 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 14 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
12 | pub struct ModuleId(FileId); | 15 | pub struct ModuleId(FileId); |
13 | 16 | ||
14 | #[derive(Clone, Debug, Default)] | 17 | #[derive(Debug, Default)] |
15 | pub struct ModuleMap { | 18 | pub struct ModuleMap { |
19 | state: RwLock<State>, | ||
20 | } | ||
21 | |||
22 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
23 | pub enum ChangeKind { | ||
24 | Delete, Insert, Update | ||
25 | } | ||
26 | |||
27 | impl 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)] | ||
35 | struct 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 | ||
26 | impl ModuleMap { | 47 | impl 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 | |||
115 | impl 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 | ||