Skip to content
This repository was archived by the owner on Mar 1, 2019. It is now read-only.

Commit d028b89

Browse files
committed
Support multiple crate types/versions
1 parent 05f2336 commit d028b89

File tree

54 files changed

+263
-218
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+263
-218
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ categories = ["development-tools"]
1010
[dependencies]
1111
rustc-serialize = "0.3"
1212
log = "0.3"
13-
rls-data = "= 0.11"
13+
rls-data = { git = "https://github.com/Xanewok/rls-data", branch = "crate-source" }
1414
rls-span = "0.4"
1515
derive-new = "0.5"
1616

benches/std_api_crate.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,13 @@ impl AnalysisLoader for TestAnalysisLoader {
2727
AnalysisHost::new_with_loader(self.clone())
2828
}
2929

30-
fn set_path_prefix(&self, _path_prefix: &Path) {}
30+
fn set_path_prefix(&mut self, _path_prefix: &Path) {}
3131

3232
fn abs_path_prefix(&self) -> Option<PathBuf> {
3333
panic!();
3434
}
3535

36-
fn iter_paths<F, T>(&self, f: F) -> Vec<T>
37-
where
38-
F: Fn(&Path) -> Vec<T>,
39-
{
40-
let paths = &[&self.path];
41-
paths.iter().flat_map(|p| f(p).into_iter()).collect()
42-
}
36+
fn paths(&self) -> Vec<PathBuf> { vec![self.path.clone()] }
4337
}
4438

4539
lazy_static! {

src/analysis.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ use std::path::{Path, PathBuf};
1111
use std::time::SystemTime;
1212

1313
use {Id, Span};
14-
use raw::DefKind;
14+
use raw::{CrateId, DefKind};
1515

16+
/// This is the main database that contains all the collected symbol information,
17+
/// such as definitions, their mapping between spans, hierarchy and so on,
18+
/// organized in a per-crate fashion.
1619
#[derive(Debug)]
1720
pub struct Analysis {
18-
// The primary crate will have its data passed directly, not via a file, so
19-
// there is no path for it. Because of this key into the hashmap, this means
20-
// we can only pass the data for one crate directly.
21-
pub per_crate: HashMap<Option<PathBuf>, PerCrateAnalysis>,
21+
/// Contains lowered data with global inter-crate `Id`s per each crate.
22+
pub per_crate: HashMap<CrateId, PerCrateAnalysis>,
2223

2324
pub doc_url_base: String,
2425
pub src_url_base: String,
@@ -36,7 +37,7 @@ pub struct PerCrateAnalysis {
3637
pub globs: HashMap<Span, Glob>,
3738
pub impls: HashMap<Id, Vec<Span>>,
3839

39-
pub name: String,
40+
pub crate_id: CrateId,
4041
pub root_id: Option<Id>,
4142
pub timestamp: SystemTime,
4243
}
@@ -78,7 +79,7 @@ pub struct Glob {
7879

7980

8081
impl PerCrateAnalysis {
81-
pub fn new(timestamp: SystemTime) -> PerCrateAnalysis {
82+
pub fn new(crate_id: CrateId, timestamp: SystemTime) -> PerCrateAnalysis {
8283
PerCrateAnalysis {
8384
def_id_for_span: HashMap::new(),
8485
defs: HashMap::new(),
@@ -88,7 +89,7 @@ impl PerCrateAnalysis {
8889
ref_spans: HashMap::new(),
8990
globs: HashMap::new(),
9091
impls: HashMap::new(),
91-
name: String::new(),
92+
crate_id,
9293
root_id: None,
9394
timestamp,
9495
}
@@ -105,20 +106,19 @@ impl Analysis {
105106
}
106107
}
107108

108-
pub fn timestamps(&self) -> HashMap<PathBuf, SystemTime> {
109+
pub fn timestamps(&self) -> HashMap<CrateId, SystemTime> {
109110
self.per_crate
110111
.iter()
111-
.filter_map(|(s, pc)| s.as_ref().map(|s| (s.clone(), pc.timestamp)))
112+
.map(|(id,c)| (id.clone(), c.timestamp.clone()))
112113
.collect()
113114
}
114115

115-
pub fn update(&mut self, per_crate: PerCrateAnalysis, path: Option<PathBuf>) {
116-
self.per_crate.insert(path, per_crate);
116+
pub fn update(&mut self, crate_id: CrateId, per_crate: PerCrateAnalysis) {
117+
self.per_crate.insert(crate_id, per_crate);
117118
}
118119

119120
pub fn has_def(&self, id: Id) -> bool {
120-
self.for_each_crate(|c| c.defs.get(&id).map(|_| ()))
121-
.is_some()
121+
self.per_crate.values().any(|c| c.defs.contains_key(&id))
122122
}
123123

124124
pub fn for_each_crate<F, T>(&self, f: F) -> Option<T>

src/lib.rs

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ mod test;
2727

2828
pub use analysis::Def;
2929
use analysis::Analysis;
30-
pub use raw::{name_space_for_def_kind, read_analysis_incremental, DefKind, Target};
31-
pub use loader::{AnalysisLoader, CargoAnalysisLoader};
30+
pub use raw::{name_space_for_def_kind, read_analysis_from_files, CrateId, DefKind};
31+
pub use loader::{AnalysisLoader, CargoAnalysisLoader, Target};
3232

3333
use std::collections::HashMap;
3434
use std::path::{Path, PathBuf};
@@ -39,8 +39,8 @@ use std::u64;
3939
#[derive(Debug)]
4040
pub struct AnalysisHost<L: AnalysisLoader = CargoAnalysisLoader> {
4141
analysis: Mutex<Option<Analysis>>,
42-
master_crate_map: Mutex<HashMap<String, u32>>,
43-
loader: L,
42+
master_crate_map: Mutex<HashMap<CrateId, u32>>,
43+
loader: Mutex<L>,
4444
}
4545

4646
pub type AResult<T> = Result<T, AError>;
@@ -72,10 +72,13 @@ impl SymbolResult {
7272

7373
pub type Span = span::Span<span::ZeroIndexed>;
7474

75+
/// A common identifier for definitions, references etc. This is effectively a
76+
/// `DefId` with globally unique crate number (instead of a compiler generated
77+
/// crate-local number).
7578
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, new)]
7679
pub struct Id(u64);
7780

78-
// Used to indicate a missing index in the Id.
81+
/// Used to indicate a missing index in the Id.
7982
pub const NULL: Id = Id(u64::MAX);
8083

8184
type Blacklist<'a> = &'a [&'static str];
@@ -95,10 +98,7 @@ impl AnalysisHost<CargoAnalysisLoader> {
9598
AnalysisHost {
9699
analysis: Mutex::new(None),
97100
master_crate_map: Mutex::new(HashMap::new()),
98-
loader: CargoAnalysisLoader {
99-
path_prefix: Mutex::new(None),
100-
target,
101-
},
101+
loader: Mutex::new(CargoAnalysisLoader::new(target)),
102102
}
103103
}
104104
}
@@ -108,7 +108,7 @@ impl<L: AnalysisLoader> AnalysisHost<L> {
108108
Self {
109109
analysis: Mutex::new(None),
110110
master_crate_map: Mutex::new(HashMap::new()),
111-
loader,
111+
loader: Mutex::new(loader),
112112
}
113113
}
114114

@@ -117,20 +117,24 @@ impl<L: AnalysisLoader> AnalysisHost<L> {
117117
/// passing in directly.
118118
pub fn reload_from_analysis(
119119
&self,
120-
analysis: data::Analysis,
120+
analysis: Vec<data::Analysis>,
121121
path_prefix: &Path,
122122
base_dir: &Path,
123123
blacklist: Blacklist,
124124
) -> AResult<()> {
125125
self.reload_with_blacklist(path_prefix, base_dir, blacklist)?;
126126

127+
let crates: Vec<_> = analysis.into_iter()
128+
.map(|analysis| raw::Crate::new(analysis, SystemTime::now()))
129+
.collect();
130+
127131
lowering::lower(
128-
vec![raw::Crate::new(analysis, SystemTime::now(), None)],
132+
crates,
129133
base_dir,
130134
self,
131-
|host, per_crate, path| {
135+
|host, per_crate, id| {
132136
let mut a = host.analysis.lock()?;
133-
a.as_mut().unwrap().update(per_crate, path);
137+
a.as_mut().unwrap().update(id, per_crate);
134138
Ok(())
135139
},
136140
)
@@ -152,29 +156,23 @@ impl<L: AnalysisLoader> AnalysisHost<L> {
152156
base_dir,
153157
blacklist
154158
);
155-
let empty = {
156-
let a = self.analysis.lock()?;
157-
a.is_none()
158-
};
159-
if empty || self.loader.needs_hard_reload(path_prefix) {
159+
let empty = self.analysis.lock()?.is_none();
160+
if empty || self.loader.lock()?.needs_hard_reload(path_prefix) {
160161
return self.hard_reload_with_blacklist(path_prefix, base_dir, blacklist);
161162
}
162163

163-
let timestamps = {
164-
let a = self.analysis.lock()?;
165-
a.as_ref().unwrap().timestamps()
166-
};
167-
168-
let raw_analysis = read_analysis_incremental(&self.loader, timestamps, blacklist);
164+
let timestamps = self.analysis.lock()?.as_ref().unwrap().timestamps();
165+
let loader = self.loader.lock()?;
166+
let raw_analysis = read_analysis_from_files(&*loader, timestamps, blacklist);
169167

170-
lowering::lower(raw_analysis, base_dir, self, |host, per_crate, path| {
168+
lowering::lower(raw_analysis, base_dir, self, |host, per_crate, id| {
171169
let mut a = host.analysis.lock()?;
172-
a.as_mut().unwrap().update(per_crate, path);
170+
a.as_mut().unwrap().update(id, per_crate);
173171
Ok(())
174172
})
175173
}
176174

177-
// Reloads the entire project's analysis data.
175+
/// Reloads the entire project's analysis data.
178176
pub fn hard_reload(&self, path_prefix: &Path, base_dir: &Path) -> AResult<()> {
179177
self.hard_reload_with_blacklist(path_prefix, base_dir, &[])
180178
}
@@ -186,42 +184,42 @@ impl<L: AnalysisLoader> AnalysisHost<L> {
186184
blacklist: Blacklist,
187185
) -> AResult<()> {
188186
trace!("hard_reload {:?} {:?}", path_prefix, base_dir);
189-
self.loader.set_path_prefix(path_prefix);
190-
let raw_analysis = read_analysis_incremental(&self.loader, HashMap::new(), blacklist);
191-
192187
// We're going to create a dummy AnalysisHost that we will fill with data,
193188
// then once we're done, we'll swap its data into self.
194-
let mut fresh_host = self.loader.fresh_host();
189+
let mut fresh_host = self.loader.lock()?.fresh_host();
195190
fresh_host.analysis = Mutex::new(Some(Analysis::new()));
196-
let lowering_result = lowering::lower(
197-
raw_analysis,
198-
base_dir,
199-
&fresh_host,
200-
|host, per_crate, path| {
201-
host.analysis
202-
.lock()
203-
.unwrap()
204-
.as_mut()
205-
.unwrap()
206-
.per_crate
207-
.insert(path, per_crate);
208-
Ok(())
209-
},
210-
);
211191

212-
if let Err(s) = lowering_result {
213-
let mut a = self.analysis.lock()?;
214-
*a = None;
215-
return Err(s);
192+
{
193+
let mut fresh_loader = fresh_host.loader.lock().unwrap();
194+
fresh_loader.set_path_prefix(path_prefix); // TODO: Needed?
195+
196+
let raw_analysis = read_analysis_from_files(&*fresh_loader,
197+
HashMap::new(),
198+
blacklist);
199+
lowering::lower(raw_analysis, base_dir, &fresh_host, |host, per_crate, id| {
200+
let mut a = host.analysis.lock()?;
201+
a.as_mut().unwrap().update(id, per_crate);
202+
Ok(())
203+
})?;
216204
}
217205

218-
{
219-
let mut mcm = self.master_crate_map.lock()?;
220-
*mcm = fresh_host.master_crate_map.into_inner().unwrap();
206+
// To guarantee a consistent state and no corruption in case an error
207+
// happens during reloading, we need to swap data with a dummy host in
208+
// a single atomic step. We can't lock and swap every member at a time,
209+
// as this can possibly lead to inconsistent state, but now this can possibly
210+
// deadlock, which isn't that good. Ideally we should have guaranteed
211+
// exclusive access to AnalysisHost as a whole to perform a reliable swap.
212+
macro_rules! swap_mutex_fields {
213+
($($name:ident),*) => {
214+
// First, we need exclusive access to every field before swapping
215+
$(let mut $name = self.$name.lock()?;)*
216+
// Then, we can swap every field
217+
$(*$name = fresh_host.$name.into_inner().unwrap();)*
218+
};
221219
}
222220

223-
let mut a = self.analysis.lock()?;
224-
*a = Some(fresh_host.analysis.into_inner().unwrap().unwrap());
221+
swap_mutex_fields!(analysis, master_crate_map, loader);
222+
225223
Ok(())
226224
}
227225

@@ -275,7 +273,7 @@ impl<L: AnalysisLoader> AnalysisHost<L> {
275273
pub fn def_roots(&self) -> AResult<Vec<(Id, String)>> {
276274
self.with_analysis(|a| {
277275
Some(
278-
a.for_all_crates(|c| c.root_id.map(|id| vec![(id, c.name.clone())])),
276+
a.for_all_crates(|c| c.root_id.map(|id| vec![(id, c.crate_id.name.clone())])),
279277
)
280278
})
281279
}
@@ -448,7 +446,7 @@ impl<L: AnalysisLoader> AnalysisHost<L> {
448446
// e.g., https://github.com/rust-lang/rust/blob/master/src/liballoc/string.rs#L261-L263
449447
pub fn src_url(&self, span: &Span) -> AResult<String> {
450448
// FIXME would be nice not to do this every time.
451-
let path_prefix = &self.loader.abs_path_prefix();
449+
let path_prefix = self.loader.lock().unwrap().abs_path_prefix();
452450

453451
self.with_analysis(|a| {
454452
a.def_id_for_span(span).and_then(|id| {

src/listings/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl DirectoryListing {
5959
path: path.components()
6060
.map(|c| c.as_os_str().to_str().unwrap().to_owned())
6161
.collect(),
62-
files: files,
62+
files,
6363
})
6464
}
6565
}

0 commit comments

Comments
 (0)