Skip to content

Commit b5fc999

Browse files
bors[bot]matklad
andcommitted
Merge #765
765: Jettison `imp` module r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 9a1d2a4 + 884f046 commit b5fc999

File tree

11 files changed

+428
-441
lines changed

11 files changed

+428
-441
lines changed

crates/ra_ide_api/src/call_info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
2020
let name_ref = calling_node.name_ref()?;
2121

2222
// Resolve the function's NameRef (NOTE: this isn't entirely accurate).
23-
let file_symbols = db.index_resolve(name_ref);
23+
let file_symbols = crate::symbol_index::index_resolve(db, name_ref);
2424
let symbol = file_symbols
2525
.into_iter()
2626
.find(|it| it.ptr.kind() == FN_DEF)?;

crates/ra_ide_api/src/change.rs

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
use std::{
2+
fmt, time,
3+
sync::Arc,
4+
};
5+
6+
use rustc_hash::FxHashMap;
7+
use ra_db::{
8+
SourceRootId, FileId, CrateGraph, SourceDatabase, SourceRoot,
9+
salsa::{Database, SweepStrategy},
10+
};
11+
use ra_syntax::SourceFile;
12+
use relative_path::RelativePathBuf;
13+
use rayon::prelude::*;
14+
15+
use crate::{
16+
db::RootDatabase,
17+
symbol_index::{SymbolIndex, SymbolsDatabase},
18+
status::syntax_tree_stats,
19+
};
20+
21+
#[derive(Default)]
22+
pub struct AnalysisChange {
23+
new_roots: Vec<(SourceRootId, bool)>,
24+
roots_changed: FxHashMap<SourceRootId, RootChange>,
25+
files_changed: Vec<(FileId, Arc<String>)>,
26+
libraries_added: Vec<LibraryData>,
27+
crate_graph: Option<CrateGraph>,
28+
}
29+
30+
impl fmt::Debug for AnalysisChange {
31+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
32+
let mut d = fmt.debug_struct("AnalysisChange");
33+
if !self.new_roots.is_empty() {
34+
d.field("new_roots", &self.new_roots);
35+
}
36+
if !self.roots_changed.is_empty() {
37+
d.field("roots_changed", &self.roots_changed);
38+
}
39+
if !self.files_changed.is_empty() {
40+
d.field("files_changed", &self.files_changed.len());
41+
}
42+
if !self.libraries_added.is_empty() {
43+
d.field("libraries_added", &self.libraries_added.len());
44+
}
45+
if !self.crate_graph.is_some() {
46+
d.field("crate_graph", &self.crate_graph);
47+
}
48+
d.finish()
49+
}
50+
}
51+
52+
impl AnalysisChange {
53+
pub fn new() -> AnalysisChange {
54+
AnalysisChange::default()
55+
}
56+
57+
pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) {
58+
self.new_roots.push((root_id, is_local));
59+
}
60+
61+
pub fn add_file(
62+
&mut self,
63+
root_id: SourceRootId,
64+
file_id: FileId,
65+
path: RelativePathBuf,
66+
text: Arc<String>,
67+
) {
68+
let file = AddFile {
69+
file_id,
70+
path,
71+
text,
72+
};
73+
self.roots_changed
74+
.entry(root_id)
75+
.or_default()
76+
.added
77+
.push(file);
78+
}
79+
80+
pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) {
81+
self.files_changed.push((file_id, new_text))
82+
}
83+
84+
pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) {
85+
let file = RemoveFile { file_id, path };
86+
self.roots_changed
87+
.entry(root_id)
88+
.or_default()
89+
.removed
90+
.push(file);
91+
}
92+
93+
pub fn add_library(&mut self, data: LibraryData) {
94+
self.libraries_added.push(data)
95+
}
96+
97+
pub fn set_crate_graph(&mut self, graph: CrateGraph) {
98+
self.crate_graph = Some(graph);
99+
}
100+
}
101+
102+
#[derive(Debug)]
103+
struct AddFile {
104+
file_id: FileId,
105+
path: RelativePathBuf,
106+
text: Arc<String>,
107+
}
108+
109+
#[derive(Debug)]
110+
struct RemoveFile {
111+
file_id: FileId,
112+
path: RelativePathBuf,
113+
}
114+
115+
#[derive(Default)]
116+
struct RootChange {
117+
added: Vec<AddFile>,
118+
removed: Vec<RemoveFile>,
119+
}
120+
121+
impl fmt::Debug for RootChange {
122+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
123+
fmt.debug_struct("AnalysisChange")
124+
.field("added", &self.added.len())
125+
.field("removed", &self.removed.len())
126+
.finish()
127+
}
128+
}
129+
130+
pub struct LibraryData {
131+
root_id: SourceRootId,
132+
root_change: RootChange,
133+
symbol_index: SymbolIndex,
134+
}
135+
136+
impl fmt::Debug for LibraryData {
137+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138+
f.debug_struct("LibraryData")
139+
.field("root_id", &self.root_id)
140+
.field("root_change", &self.root_change)
141+
.field("n_symbols", &self.symbol_index.len())
142+
.finish()
143+
}
144+
}
145+
146+
impl LibraryData {
147+
pub fn prepare(
148+
root_id: SourceRootId,
149+
files: Vec<(FileId, RelativePathBuf, Arc<String>)>,
150+
) -> LibraryData {
151+
let symbol_index = SymbolIndex::for_files(files.par_iter().map(|(file_id, _, text)| {
152+
let file = SourceFile::parse(text);
153+
(*file_id, file)
154+
}));
155+
let mut root_change = RootChange::default();
156+
root_change.added = files
157+
.into_iter()
158+
.map(|(file_id, path, text)| AddFile {
159+
file_id,
160+
path,
161+
text,
162+
})
163+
.collect();
164+
LibraryData {
165+
root_id,
166+
root_change,
167+
symbol_index,
168+
}
169+
}
170+
}
171+
172+
const GC_COOLDOWN: time::Duration = time::Duration::from_millis(100);
173+
174+
impl RootDatabase {
175+
pub(crate) fn apply_change(&mut self, change: AnalysisChange) {
176+
log::info!("apply_change {:?}", change);
177+
if !change.new_roots.is_empty() {
178+
let mut local_roots = Vec::clone(&self.local_roots());
179+
for (root_id, is_local) in change.new_roots {
180+
self.set_source_root(root_id, Default::default());
181+
if is_local {
182+
local_roots.push(root_id);
183+
}
184+
}
185+
self.set_local_roots(Arc::new(local_roots));
186+
}
187+
188+
for (root_id, root_change) in change.roots_changed {
189+
self.apply_root_change(root_id, root_change);
190+
}
191+
for (file_id, text) in change.files_changed {
192+
self.set_file_text(file_id, text)
193+
}
194+
if !change.libraries_added.is_empty() {
195+
let mut libraries = Vec::clone(&self.library_roots());
196+
for library in change.libraries_added {
197+
libraries.push(library.root_id);
198+
self.set_source_root(library.root_id, Default::default());
199+
self.set_constant_library_symbols(library.root_id, Arc::new(library.symbol_index));
200+
self.apply_root_change(library.root_id, library.root_change);
201+
}
202+
self.set_library_roots(Arc::new(libraries));
203+
}
204+
if let Some(crate_graph) = change.crate_graph {
205+
self.set_crate_graph(Arc::new(crate_graph))
206+
}
207+
}
208+
209+
fn apply_root_change(&mut self, root_id: SourceRootId, root_change: RootChange) {
210+
let mut source_root = SourceRoot::clone(&self.source_root(root_id));
211+
for add_file in root_change.added {
212+
self.set_file_text(add_file.file_id, add_file.text);
213+
self.set_file_relative_path(add_file.file_id, add_file.path.clone());
214+
self.set_file_source_root(add_file.file_id, root_id);
215+
source_root.files.insert(add_file.path, add_file.file_id);
216+
}
217+
for remove_file in root_change.removed {
218+
self.set_file_text(remove_file.file_id, Default::default());
219+
source_root.files.remove(&remove_file.path);
220+
}
221+
self.set_source_root(root_id, Arc::new(source_root));
222+
}
223+
224+
pub(crate) fn maybe_collect_garbage(&mut self) {
225+
if self.last_gc_check.elapsed() > GC_COOLDOWN {
226+
self.last_gc_check = time::Instant::now();
227+
let retained_trees = syntax_tree_stats(self).retained;
228+
if retained_trees > 100 {
229+
log::info!(
230+
"automatic garbadge collection, {} retained trees",
231+
retained_trees
232+
);
233+
self.collect_garbage();
234+
}
235+
}
236+
}
237+
238+
pub(crate) fn collect_garbage(&mut self) {
239+
self.last_gc = time::Instant::now();
240+
241+
let sweep = SweepStrategy::default()
242+
.discard_values()
243+
.sweep_all_revisions();
244+
245+
self.query(ra_db::ParseQuery).sweep(sweep);
246+
247+
self.query(hir::db::HirParseQuery).sweep(sweep);
248+
self.query(hir::db::FileItemsQuery).sweep(sweep);
249+
self.query(hir::db::FileItemQuery).sweep(sweep);
250+
251+
self.query(hir::db::LowerModuleQuery).sweep(sweep);
252+
self.query(hir::db::LowerModuleSourceMapQuery).sweep(sweep);
253+
self.query(hir::db::BodySyntaxMappingQuery).sweep(sweep);
254+
}
255+
}

crates/ra_ide_api/src/diagnostics.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use hir::{Problem, source_binder};
2+
use ra_ide_api_light::Severity;
3+
use ra_db::SourceDatabase;
4+
5+
use crate::{Diagnostic, FileId, FileSystemEdit, SourceChange, db::RootDatabase};
6+
7+
pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> {
8+
let syntax = db.parse(file_id);
9+
10+
let mut res = ra_ide_api_light::diagnostics(&syntax)
11+
.into_iter()
12+
.map(|d| Diagnostic {
13+
range: d.range,
14+
message: d.msg,
15+
severity: d.severity,
16+
fix: d.fix.map(|fix| SourceChange::from_local_edit(file_id, fix)),
17+
})
18+
.collect::<Vec<_>>();
19+
if let Some(m) = source_binder::module_from_file_id(db, file_id) {
20+
for (name_node, problem) in m.problems(db) {
21+
let source_root = db.file_source_root(file_id);
22+
let diag = match problem {
23+
Problem::UnresolvedModule { candidate } => {
24+
let create_file = FileSystemEdit::CreateFile {
25+
source_root,
26+
path: candidate.clone(),
27+
};
28+
let fix = SourceChange {
29+
label: "create module".to_string(),
30+
source_file_edits: Vec::new(),
31+
file_system_edits: vec![create_file],
32+
cursor_position: None,
33+
};
34+
Diagnostic {
35+
range: name_node.range(),
36+
message: "unresolved module".to_string(),
37+
severity: Severity::Error,
38+
fix: Some(fix),
39+
}
40+
}
41+
Problem::NotDirOwner { move_to, candidate } => {
42+
let move_file = FileSystemEdit::MoveFile {
43+
src: file_id,
44+
dst_source_root: source_root,
45+
dst_path: move_to.clone(),
46+
};
47+
let create_file = FileSystemEdit::CreateFile {
48+
source_root,
49+
path: move_to.join(candidate),
50+
};
51+
let fix = SourceChange {
52+
label: "move file and create module".to_string(),
53+
source_file_edits: Vec::new(),
54+
file_system_edits: vec![move_file, create_file],
55+
cursor_position: None,
56+
};
57+
Diagnostic {
58+
range: name_node.range(),
59+
message: "can't declare module at this location".to_string(),
60+
severity: Severity::Error,
61+
fix: Some(fix),
62+
}
63+
}
64+
};
65+
res.push(diag)
66+
}
67+
};
68+
res
69+
}

crates/ra_ide_api/src/goto_definition.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ pub(crate) fn reference_definition(
118118
}
119119
}
120120
// If that fails try the index based approach.
121-
let navs = db
122-
.index_resolve(name_ref)
121+
let navs = crate::symbol_index::index_resolve(db, name_ref)
123122
.into_iter()
124123
.map(NavigationTarget::from_symbol)
125124
.collect();

0 commit comments

Comments
 (0)