Skip to content

Commit 8716c4c

Browse files
committed
Move ide::AnalysisChange -> base_db::Change
This seems like a better factoring logically; ideally, clients shouldn't touch `set_` methods of the database directly. Additionally, I think this should remove the unfortunate duplication in fixture code.
1 parent 700c9bc commit 8716c4c

File tree

11 files changed

+122
-93
lines changed

11 files changed

+122
-93
lines changed

crates/base_db/src/change.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//! Defines a unit of change that can applied to the database to get the next
2+
//! state. Changes are transactional.
3+
4+
use std::{fmt, sync::Arc};
5+
6+
use rustc_hash::FxHashSet;
7+
use salsa::Durability;
8+
use vfs::FileId;
9+
10+
use crate::{CrateGraph, SourceDatabaseExt, SourceRoot, SourceRootId};
11+
12+
/// Encapsulate a bunch of raw `.set` calls on the database.
13+
#[derive(Default)]
14+
pub struct Change {
15+
pub roots: Option<Vec<SourceRoot>>,
16+
pub files_changed: Vec<(FileId, Option<Arc<String>>)>,
17+
pub crate_graph: Option<CrateGraph>,
18+
}
19+
20+
impl fmt::Debug for Change {
21+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
22+
let mut d = fmt.debug_struct("AnalysisChange");
23+
if let Some(roots) = &self.roots {
24+
d.field("roots", roots);
25+
}
26+
if !self.files_changed.is_empty() {
27+
d.field("files_changed", &self.files_changed.len());
28+
}
29+
if self.crate_graph.is_some() {
30+
d.field("crate_graph", &self.crate_graph);
31+
}
32+
d.finish()
33+
}
34+
}
35+
36+
impl Change {
37+
pub fn new() -> Change {
38+
Change::default()
39+
}
40+
41+
pub fn set_roots(&mut self, roots: Vec<SourceRoot>) {
42+
self.roots = Some(roots);
43+
}
44+
45+
pub fn change_file(&mut self, file_id: FileId, new_text: Option<Arc<String>>) {
46+
self.files_changed.push((file_id, new_text))
47+
}
48+
49+
pub fn set_crate_graph(&mut self, graph: CrateGraph) {
50+
self.crate_graph = Some(graph);
51+
}
52+
53+
pub fn apply(self, db: &mut dyn SourceDatabaseExt) {
54+
let _p = profile::span("RootDatabase::apply_change");
55+
// db.request_cancellation();
56+
// log::info!("apply_change {:?}", change);
57+
if let Some(roots) = self.roots {
58+
let mut local_roots = FxHashSet::default();
59+
let mut library_roots = FxHashSet::default();
60+
for (idx, root) in roots.into_iter().enumerate() {
61+
let root_id = SourceRootId(idx as u32);
62+
let durability = durability(&root);
63+
if root.is_library {
64+
library_roots.insert(root_id);
65+
} else {
66+
local_roots.insert(root_id);
67+
}
68+
for file_id in root.iter() {
69+
db.set_file_source_root_with_durability(file_id, root_id, durability);
70+
}
71+
db.set_source_root_with_durability(root_id, Arc::new(root), durability);
72+
}
73+
// db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
74+
// db.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH);
75+
}
76+
77+
for (file_id, text) in self.files_changed {
78+
let source_root_id = db.file_source_root(file_id);
79+
let source_root = db.source_root(source_root_id);
80+
let durability = durability(&source_root);
81+
// XXX: can't actually remove the file, just reset the text
82+
let text = text.unwrap_or_default();
83+
db.set_file_text_with_durability(file_id, text, durability)
84+
}
85+
if let Some(crate_graph) = self.crate_graph {
86+
db.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
87+
}
88+
}
89+
}
90+
91+
fn durability(source_root: &SourceRoot) -> Durability {
92+
if source_root.is_library {
93+
Durability::HIGH
94+
} else {
95+
Durability::LOW
96+
}
97+
}

crates/base_db/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! base_db defines basic database traits. The concrete DB is defined by ide.
22
mod cancellation;
33
mod input;
4+
mod change;
45
pub mod fixture;
56

67
use std::{panic, sync::Arc};
@@ -10,6 +11,7 @@ use syntax::{ast, Parse, SourceFile, TextRange, TextSize};
1011

1112
pub use crate::{
1213
cancellation::Canceled,
14+
change::Change,
1315
input::{
1416
CrateData, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, FileId, ProcMacroId,
1517
SourceRoot, SourceRootId,

crates/ide/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,11 @@ pub use assists::{
8787
utils::MergeBehaviour, Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist,
8888
};
8989
pub use base_db::{
90-
Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,
90+
Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,
9191
SourceRootId,
9292
};
9393
pub use hir::{Documentation, Semantics};
9494
pub use ide_db::{
95-
change::AnalysisChange,
9695
label::Label,
9796
line_index::{LineCol, LineIndex},
9897
search::SearchScope,
@@ -141,7 +140,7 @@ impl AnalysisHost {
141140

142141
/// Applies changes to the current state of the world. If there are
143142
/// outstanding snapshots, they will be canceled.
144-
pub fn apply_change(&mut self, change: AnalysisChange) {
143+
pub fn apply_change(&mut self, change: Change) {
145144
self.db.apply_change(change)
146145
}
147146

@@ -195,7 +194,7 @@ impl Analysis {
195194
file_set.insert(file_id, VfsPath::new_virtual_path("/main.rs".to_string()));
196195
let source_root = SourceRoot::new_local(file_set);
197196

198-
let mut change = AnalysisChange::new();
197+
let mut change = Change::new();
199198
change.set_roots(vec![source_root]);
200199
let mut crate_graph = CrateGraph::default();
201200
// FIXME: cfg options

crates/ide/src/mock_analysis.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ use test_utils::{
77
extract_annotations, extract_range_or_offset, Fixture, RangeOrOffset, CURSOR_MARKER,
88
};
99

10-
use crate::{
11-
Analysis, AnalysisChange, AnalysisHost, CrateGraph, Edition, FileId, FilePosition, FileRange,
12-
};
10+
use crate::{Analysis, AnalysisHost, Change, CrateGraph, Edition, FileId, FilePosition, FileRange};
1311

1412
/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis
1513
/// from a set of in-memory files.
@@ -95,7 +93,7 @@ impl MockAnalysis {
9593
}
9694
pub(crate) fn analysis_host(self) -> AnalysisHost {
9795
let mut host = AnalysisHost::default();
98-
let mut change = AnalysisChange::new();
96+
let mut change = Change::new();
9997
let mut file_set = FileSet::default();
10098
let mut crate_graph = CrateGraph::default();
10199
let mut root_crate = None;

crates/ide/src/parent_module.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ mod tests {
6969

7070
use crate::{
7171
mock_analysis::{analysis_and_position, MockAnalysis},
72-
AnalysisChange, CrateGraph,
72+
Change, CrateGraph,
7373
Edition::Edition2018,
7474
};
7575

@@ -146,7 +146,7 @@ mod foo;
146146
Env::default(),
147147
Default::default(),
148148
);
149-
let mut change = AnalysisChange::new();
149+
let mut change = Change::new();
150150
change.set_crate_graph(crate_graph);
151151
host.apply_change(change);
152152

crates/ide_db/src/change.rs renamed to crates/ide_db/src/apply_change.rs

Lines changed: 6 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,16 @@
1-
//! Defines a unit of change that can applied to a state of IDE to get the next
2-
//! state. Changes are transactional.
1+
//! Applies changes to the IDE state transactionally.
32
43
use std::{fmt, sync::Arc};
54

65
use base_db::{
76
salsa::{Database, Durability, SweepStrategy},
8-
CrateGraph, FileId, SourceDatabase, SourceDatabaseExt, SourceRoot, SourceRootId,
7+
Change, FileId, SourceRootId,
98
};
109
use profile::{memory_usage, Bytes};
1110
use rustc_hash::FxHashSet;
1211

1312
use crate::{symbol_index::SymbolsDatabase, RootDatabase};
1413

15-
#[derive(Default)]
16-
pub struct AnalysisChange {
17-
roots: Option<Vec<SourceRoot>>,
18-
files_changed: Vec<(FileId, Option<Arc<String>>)>,
19-
crate_graph: Option<CrateGraph>,
20-
}
21-
22-
impl fmt::Debug for AnalysisChange {
23-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
24-
let mut d = fmt.debug_struct("AnalysisChange");
25-
if let Some(roots) = &self.roots {
26-
d.field("roots", roots);
27-
}
28-
if !self.files_changed.is_empty() {
29-
d.field("files_changed", &self.files_changed.len());
30-
}
31-
if self.crate_graph.is_some() {
32-
d.field("crate_graph", &self.crate_graph);
33-
}
34-
d.finish()
35-
}
36-
}
37-
38-
impl AnalysisChange {
39-
pub fn new() -> AnalysisChange {
40-
AnalysisChange::default()
41-
}
42-
43-
pub fn set_roots(&mut self, roots: Vec<SourceRoot>) {
44-
self.roots = Some(roots);
45-
}
46-
47-
pub fn change_file(&mut self, file_id: FileId, new_text: Option<Arc<String>>) {
48-
self.files_changed.push((file_id, new_text))
49-
}
50-
51-
pub fn set_crate_graph(&mut self, graph: CrateGraph) {
52-
self.crate_graph = Some(graph);
53-
}
54-
}
55-
5614
#[derive(Debug)]
5715
struct AddFile {
5816
file_id: FileId,
@@ -87,41 +45,25 @@ impl RootDatabase {
8745
self.salsa_runtime_mut().synthetic_write(Durability::LOW);
8846
}
8947

90-
pub fn apply_change(&mut self, change: AnalysisChange) {
48+
pub fn apply_change(&mut self, change: Change) {
9149
let _p = profile::span("RootDatabase::apply_change");
9250
self.request_cancellation();
9351
log::info!("apply_change {:?}", change);
94-
if let Some(roots) = change.roots {
52+
if let Some(roots) = &change.roots {
9553
let mut local_roots = FxHashSet::default();
9654
let mut library_roots = FxHashSet::default();
97-
for (idx, root) in roots.into_iter().enumerate() {
55+
for (idx, root) in roots.iter().enumerate() {
9856
let root_id = SourceRootId(idx as u32);
99-
let durability = durability(&root);
10057
if root.is_library {
10158
library_roots.insert(root_id);
10259
} else {
10360
local_roots.insert(root_id);
10461
}
105-
for file_id in root.iter() {
106-
self.set_file_source_root_with_durability(file_id, root_id, durability);
107-
}
108-
self.set_source_root_with_durability(root_id, Arc::new(root), durability);
10962
}
11063
self.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH);
11164
self.set_library_roots_with_durability(Arc::new(library_roots), Durability::HIGH);
11265
}
113-
114-
for (file_id, text) in change.files_changed {
115-
let source_root_id = self.file_source_root(file_id);
116-
let source_root = self.source_root(source_root_id);
117-
let durability = durability(&source_root);
118-
// XXX: can't actually remove the file, just reset the text
119-
let text = text.unwrap_or_default();
120-
self.set_file_text_with_durability(file_id, text, durability)
121-
}
122-
if let Some(crate_graph) = change.crate_graph {
123-
self.set_crate_graph_with_durability(Arc::new(crate_graph), Durability::HIGH)
124-
}
66+
change.apply(self);
12567
}
12668

12769
pub fn collect_garbage(&mut self) {
@@ -295,11 +237,3 @@ impl RootDatabase {
295237
acc
296238
}
297239
}
298-
299-
fn durability(source_root: &SourceRoot) -> Durability {
300-
if source_root.is_library {
301-
Durability::HIGH
302-
} else {
303-
Durability::LOW
304-
}
305-
}

crates/ide_db/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
//!
33
//! It is mainly a `HirDatabase` for semantic analysis, plus a `SymbolsDatabase`, for fuzzy search.
44
5+
mod apply_change;
56
pub mod label;
67
pub mod line_index;
78
pub mod symbol_index;
8-
pub mod change;
99
pub mod defs;
1010
pub mod search;
1111
pub mod imports_locator;

crates/rust-analyzer/src/cli/analysis_bench.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ use base_db::{
88
FileId,
99
};
1010
use ide::{
11-
Analysis, AnalysisChange, AnalysisHost, CompletionConfig, DiagnosticsConfig, FilePosition,
12-
LineCol,
11+
Analysis, AnalysisHost, Change, CompletionConfig, DiagnosticsConfig, FilePosition, LineCol,
1312
};
1413
use vfs::AbsPathBuf;
1514

@@ -143,7 +142,7 @@ fn do_work<F: Fn(&Analysis) -> T, T>(host: &mut AnalysisHost, file_id: FileId, w
143142
{
144143
let mut text = host.analysis().file_text(file_id).unwrap().to_string();
145144
text.push_str("\n/* Hello world */\n");
146-
let mut change = AnalysisChange::new();
145+
let mut change = Change::new();
147146
change.change_file(file_id, Some(Arc::new(text)));
148147
host.apply_change(change);
149148
}
@@ -156,7 +155,7 @@ fn do_work<F: Fn(&Analysis) -> T, T>(host: &mut AnalysisHost, file_id: FileId, w
156155
{
157156
let mut text = host.analysis().file_text(file_id).unwrap().to_string();
158157
text.push_str("\npub fn _dummy() {}\n");
159-
let mut change = AnalysisChange::new();
158+
let mut change = Change::new();
160159
change.change_file(file_id, Some(Arc::new(text)));
161160
host.apply_change(change);
162161
}

crates/rust-analyzer/src/cli/load_cargo.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{path::Path, sync::Arc};
55
use anyhow::Result;
66
use base_db::CrateGraph;
77
use crossbeam_channel::{unbounded, Receiver};
8-
use ide::{AnalysisChange, AnalysisHost};
8+
use ide::{AnalysisHost, Change};
99
use project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace};
1010
use vfs::{loader::Handle, AbsPath, AbsPathBuf};
1111

@@ -62,7 +62,7 @@ fn load(
6262
) -> AnalysisHost {
6363
let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
6464
let mut host = AnalysisHost::new(lru_cap);
65-
let mut analysis_change = AnalysisChange::new();
65+
let mut analysis_change = Change::new();
6666

6767
// wait until Vfs has loaded all roots
6868
for task in receiver {

crates/rust-analyzer/src/global_state.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{sync::Arc, time::Instant};
88
use base_db::{CrateId, VfsPath};
99
use crossbeam_channel::{unbounded, Receiver, Sender};
1010
use flycheck::FlycheckHandle;
11-
use ide::{Analysis, AnalysisChange, AnalysisHost, FileId};
11+
use ide::{Analysis, AnalysisHost, Change, FileId};
1212
use lsp_types::{SemanticTokens, Url};
1313
use parking_lot::{Mutex, RwLock};
1414
use project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target};
@@ -139,7 +139,7 @@ impl GlobalState {
139139
let mut has_fs_changes = false;
140140

141141
let change = {
142-
let mut change = AnalysisChange::new();
142+
let mut change = Change::new();
143143
let (vfs, line_endings_map) = &mut *self.vfs.write();
144144
let changed_files = vfs.take_changes();
145145
if changed_files.is_empty() {

0 commit comments

Comments
 (0)