diff options
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | crates/ra_project_model/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 2 | ||||
-rw-r--r-- | crates/ra_project_model/src/json_project.rs | 95 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 81 | ||||
-rw-r--r-- | crates/ra_project_model/src/project_json.rs | 117 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cargo_target_spec.rs | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 11 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 18 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 13 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 2 | ||||
-rw-r--r-- | crates/vfs-notify/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/vfs/src/loader.rs | 4 | ||||
-rw-r--r-- | docs/user/manual.adoc | 2 |
16 files changed, 179 insertions, 182 deletions
diff --git a/Cargo.lock b/Cargo.lock index 91a932549..7bd2144a7 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -1183,6 +1183,7 @@ dependencies = [ | |||
1183 | "rustc-hash", | 1183 | "rustc-hash", |
1184 | "serde", | 1184 | "serde", |
1185 | "serde_json", | 1185 | "serde_json", |
1186 | "stdx", | ||
1186 | ] | 1187 | ] |
1187 | 1188 | ||
1188 | [[package]] | 1189 | [[package]] |
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml index 818947014..b1b44dcf7 100644 --- a/crates/ra_project_model/Cargo.toml +++ b/crates/ra_project_model/Cargo.toml | |||
@@ -19,6 +19,7 @@ ra_db = { path = "../ra_db" } | |||
19 | ra_toolchain = { path = "../ra_toolchain" } | 19 | ra_toolchain = { path = "../ra_toolchain" } |
20 | ra_proc_macro = { path = "../ra_proc_macro" } | 20 | ra_proc_macro = { path = "../ra_proc_macro" } |
21 | paths = { path = "../paths" } | 21 | paths = { path = "../paths" } |
22 | stdx = { path = "../stdx" } | ||
22 | 23 | ||
23 | serde = { version = "1.0.106", features = ["derive"] } | 24 | serde = { version = "1.0.106", features = ["derive"] } |
24 | serde_json = "1.0.48" | 25 | serde_json = "1.0.48" |
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 8ce63ab3c..3b124020d 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -260,7 +260,7 @@ impl CargoWorkspace { | |||
260 | .copied() | 260 | .copied() |
261 | } | 261 | } |
262 | 262 | ||
263 | pub fn workspace_root(&self) -> &Path { | 263 | pub fn workspace_root(&self) -> &AbsPath { |
264 | &self.workspace_root | 264 | &self.workspace_root |
265 | } | 265 | } |
266 | 266 | ||
diff --git a/crates/ra_project_model/src/json_project.rs b/crates/ra_project_model/src/json_project.rs deleted file mode 100644 index ee2de4c25..000000000 --- a/crates/ra_project_model/src/json_project.rs +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use std::path::PathBuf; | ||
4 | |||
5 | use rustc_hash::FxHashSet; | ||
6 | use serde::Deserialize; | ||
7 | |||
8 | /// Roots and crates that compose this Rust project. | ||
9 | #[derive(Clone, Debug, Deserialize)] | ||
10 | pub struct JsonProject { | ||
11 | pub(crate) roots: Vec<Root>, | ||
12 | pub(crate) crates: Vec<Crate>, | ||
13 | } | ||
14 | |||
15 | /// A root points to the directory which contains Rust crates. rust-analyzer watches all files in | ||
16 | /// all roots. Roots might be nested. | ||
17 | #[derive(Clone, Debug, Deserialize)] | ||
18 | #[serde(transparent)] | ||
19 | pub struct Root { | ||
20 | pub(crate) path: PathBuf, | ||
21 | } | ||
22 | |||
23 | /// A crate points to the root module of a crate and lists the dependencies of the crate. This is | ||
24 | /// useful in creating the crate graph. | ||
25 | #[derive(Clone, Debug, Deserialize)] | ||
26 | pub struct Crate { | ||
27 | pub(crate) root_module: PathBuf, | ||
28 | pub(crate) edition: Edition, | ||
29 | pub(crate) deps: Vec<Dep>, | ||
30 | |||
31 | #[serde(default)] | ||
32 | pub(crate) cfg: FxHashSet<String>, | ||
33 | |||
34 | pub(crate) out_dir: Option<PathBuf>, | ||
35 | pub(crate) proc_macro_dylib_path: Option<PathBuf>, | ||
36 | } | ||
37 | |||
38 | #[derive(Clone, Copy, Debug, Deserialize)] | ||
39 | #[serde(rename = "edition")] | ||
40 | pub enum Edition { | ||
41 | #[serde(rename = "2015")] | ||
42 | Edition2015, | ||
43 | #[serde(rename = "2018")] | ||
44 | Edition2018, | ||
45 | } | ||
46 | |||
47 | /// Identifies a crate by position in the crates array. | ||
48 | #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd)] | ||
49 | #[serde(transparent)] | ||
50 | pub struct CrateId(pub usize); | ||
51 | |||
52 | /// A dependency of a crate, identified by its id in the crates array and name. | ||
53 | #[derive(Clone, Debug, Deserialize)] | ||
54 | pub struct Dep { | ||
55 | #[serde(rename = "crate")] | ||
56 | pub(crate) krate: CrateId, | ||
57 | pub(crate) name: String, | ||
58 | } | ||
59 | |||
60 | #[cfg(test)] | ||
61 | mod tests { | ||
62 | use super::*; | ||
63 | use serde_json::json; | ||
64 | |||
65 | #[test] | ||
66 | fn test_crate_deserialization() { | ||
67 | let raw_json = json!( { | ||
68 | "crate_id": 2, | ||
69 | "root_module": "this/is/a/file/path.rs", | ||
70 | "deps": [ | ||
71 | { | ||
72 | "crate": 1, | ||
73 | "name": "some_dep_crate" | ||
74 | }, | ||
75 | ], | ||
76 | "edition": "2015", | ||
77 | "cfg": [ | ||
78 | "atom_1", | ||
79 | "atom_2", | ||
80 | "feature=feature_1", | ||
81 | "feature=feature_2", | ||
82 | "other=value", | ||
83 | ], | ||
84 | |||
85 | }); | ||
86 | |||
87 | let krate: Crate = serde_json::from_value(raw_json).unwrap(); | ||
88 | |||
89 | assert!(krate.cfg.contains(&"atom_1".to_string())); | ||
90 | assert!(krate.cfg.contains(&"atom_2".to_string())); | ||
91 | assert!(krate.cfg.contains(&"feature=feature_1".to_string())); | ||
92 | assert!(krate.cfg.contains(&"feature=feature_2".to_string())); | ||
93 | assert!(krate.cfg.contains(&"other=value".to_string())); | ||
94 | } | ||
95 | } | ||
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index ac88532f0..8b85b4831 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -1,12 +1,12 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | mod cargo_workspace; | 3 | mod cargo_workspace; |
4 | mod json_project; | 4 | mod project_json; |
5 | mod sysroot; | 5 | mod sysroot; |
6 | 6 | ||
7 | use std::{ | 7 | use std::{ |
8 | fs::{read_dir, File, ReadDir}, | 8 | fs::{self, read_dir, ReadDir}, |
9 | io::{self, BufReader}, | 9 | io, |
10 | path::Path, | 10 | path::Path, |
11 | process::{Command, Output}, | 11 | process::{Command, Output}, |
12 | }; | 12 | }; |
@@ -14,13 +14,12 @@ use std::{ | |||
14 | use anyhow::{bail, Context, Result}; | 14 | use anyhow::{bail, Context, Result}; |
15 | use paths::{AbsPath, AbsPathBuf}; | 15 | use paths::{AbsPath, AbsPathBuf}; |
16 | use ra_cfg::CfgOptions; | 16 | use ra_cfg::CfgOptions; |
17 | use ra_db::{CrateGraph, CrateName, Edition, Env, FileId}; | 17 | use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId}; |
18 | use rustc_hash::{FxHashMap, FxHashSet}; | 18 | use rustc_hash::{FxHashMap, FxHashSet}; |
19 | use serde_json::from_reader; | ||
20 | 19 | ||
21 | pub use crate::{ | 20 | pub use crate::{ |
22 | cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind}, | 21 | cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind}, |
23 | json_project::JsonProject, | 22 | project_json::{ProjectJson, ProjectJsonData}, |
24 | sysroot::Sysroot, | 23 | sysroot::Sysroot, |
25 | }; | 24 | }; |
26 | pub use ra_proc_macro::ProcMacroClient; | 25 | pub use ra_proc_macro::ProcMacroClient; |
@@ -30,7 +29,7 @@ pub enum ProjectWorkspace { | |||
30 | /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. | 29 | /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. |
31 | Cargo { cargo: CargoWorkspace, sysroot: Sysroot }, | 30 | Cargo { cargo: CargoWorkspace, sysroot: Sysroot }, |
32 | /// Project workspace was manually specified using a `rust-project.json` file. | 31 | /// Project workspace was manually specified using a `rust-project.json` file. |
33 | Json { project: JsonProject, project_location: AbsPathBuf }, | 32 | Json { project: ProjectJson }, |
34 | } | 33 | } |
35 | 34 | ||
36 | /// `PackageRoot` describes a package root folder. | 35 | /// `PackageRoot` describes a package root folder. |
@@ -156,17 +155,15 @@ impl ProjectWorkspace { | |||
156 | ) -> Result<ProjectWorkspace> { | 155 | ) -> Result<ProjectWorkspace> { |
157 | let res = match manifest { | 156 | let res = match manifest { |
158 | ProjectManifest::ProjectJson(project_json) => { | 157 | ProjectManifest::ProjectJson(project_json) => { |
159 | let file = File::open(&project_json).with_context(|| { | 158 | let file = fs::read_to_string(&project_json).with_context(|| { |
160 | format!("Failed to open json file {}", project_json.display()) | 159 | format!("Failed to read json file {}", project_json.display()) |
160 | })?; | ||
161 | let data = serde_json::from_str(&file).with_context(|| { | ||
162 | format!("Failed to deserialize json file {}", project_json.display()) | ||
161 | })?; | 163 | })?; |
162 | let reader = BufReader::new(file); | ||
163 | let project_location = project_json.parent().unwrap().to_path_buf(); | 164 | let project_location = project_json.parent().unwrap().to_path_buf(); |
164 | ProjectWorkspace::Json { | 165 | let project = ProjectJson::new(&project_location, data); |
165 | project: from_reader(reader).with_context(|| { | 166 | ProjectWorkspace::Json { project } |
166 | format!("Failed to deserialize json file {}", project_json.display()) | ||
167 | })?, | ||
168 | project_location, | ||
169 | } | ||
170 | } | 167 | } |
171 | ProjectManifest::CargoToml(cargo_toml) => { | 168 | ProjectManifest::CargoToml(cargo_toml) => { |
172 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features) | 169 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features) |
@@ -198,11 +195,9 @@ impl ProjectWorkspace { | |||
198 | /// the root is a member of the current workspace | 195 | /// the root is a member of the current workspace |
199 | pub fn to_roots(&self) -> Vec<PackageRoot> { | 196 | pub fn to_roots(&self) -> Vec<PackageRoot> { |
200 | match self { | 197 | match self { |
201 | ProjectWorkspace::Json { project, project_location } => project | 198 | ProjectWorkspace::Json { project } => { |
202 | .roots | 199 | project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() |
203 | .iter() | 200 | } |
204 | .map(|r| PackageRoot::new_member(project_location.join(&r.path))) | ||
205 | .collect(), | ||
206 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo | 201 | ProjectWorkspace::Cargo { cargo, sysroot } => cargo |
207 | .packages() | 202 | .packages() |
208 | .map(|pkg| PackageRoot { | 203 | .map(|pkg| PackageRoot { |
@@ -219,11 +214,11 @@ impl ProjectWorkspace { | |||
219 | 214 | ||
220 | pub fn proc_macro_dylib_paths(&self) -> Vec<AbsPathBuf> { | 215 | pub fn proc_macro_dylib_paths(&self) -> Vec<AbsPathBuf> { |
221 | match self { | 216 | match self { |
222 | ProjectWorkspace::Json { project, project_location } => project | 217 | ProjectWorkspace::Json { project } => project |
223 | .crates | 218 | .crates |
224 | .iter() | 219 | .iter() |
225 | .filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) | 220 | .filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) |
226 | .map(|it| project_location.join(it)) | 221 | .cloned() |
227 | .collect(), | 222 | .collect(), |
228 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo | 223 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo |
229 | .packages() | 224 | .packages() |
@@ -246,36 +241,18 @@ impl ProjectWorkspace { | |||
246 | &self, | 241 | &self, |
247 | target: Option<&str>, | 242 | target: Option<&str>, |
248 | proc_macro_client: &ProcMacroClient, | 243 | proc_macro_client: &ProcMacroClient, |
249 | load: &mut dyn FnMut(&Path) -> Option<FileId>, | 244 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, |
250 | ) -> CrateGraph { | 245 | ) -> CrateGraph { |
251 | let mut crate_graph = CrateGraph::default(); | 246 | let mut crate_graph = CrateGraph::default(); |
252 | match self { | 247 | match self { |
253 | ProjectWorkspace::Json { project, project_location } => { | 248 | ProjectWorkspace::Json { project } => { |
254 | let crates: FxHashMap<_, _> = project | 249 | let crates: FxHashMap<_, _> = project |
255 | .crates | 250 | .crates |
256 | .iter() | 251 | .iter() |
257 | .enumerate() | 252 | .enumerate() |
258 | .filter_map(|(seq_index, krate)| { | 253 | .filter_map(|(seq_index, krate)| { |
259 | let file_path = project_location.join(&krate.root_module); | 254 | let file_path = &krate.root_module; |
260 | let file_id = load(&file_path)?; | 255 | let file_id = load(&file_path)?; |
261 | let edition = match krate.edition { | ||
262 | json_project::Edition::Edition2015 => Edition::Edition2015, | ||
263 | json_project::Edition::Edition2018 => Edition::Edition2018, | ||
264 | }; | ||
265 | let cfg_options = { | ||
266 | let mut opts = CfgOptions::default(); | ||
267 | for cfg in &krate.cfg { | ||
268 | match cfg.find('=') { | ||
269 | None => opts.insert_atom(cfg.into()), | ||
270 | Some(pos) => { | ||
271 | let key = &cfg[..pos]; | ||
272 | let value = cfg[pos + 1..].trim_matches('"'); | ||
273 | opts.insert_key_value(key.into(), value.into()); | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | opts | ||
278 | }; | ||
279 | 256 | ||
280 | let mut env = Env::default(); | 257 | let mut env = Env::default(); |
281 | if let Some(out_dir) = &krate.out_dir { | 258 | if let Some(out_dir) = &krate.out_dir { |
@@ -290,13 +267,13 @@ impl ProjectWorkspace { | |||
290 | .map(|it| proc_macro_client.by_dylib_path(&it)); | 267 | .map(|it| proc_macro_client.by_dylib_path(&it)); |
291 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env | 268 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env |
292 | Some(( | 269 | Some(( |
293 | json_project::CrateId(seq_index), | 270 | CrateId(seq_index as u32), |
294 | crate_graph.add_crate_root( | 271 | crate_graph.add_crate_root( |
295 | file_id, | 272 | file_id, |
296 | edition, | 273 | krate.edition, |
297 | // FIXME json definitions can store the crate name | 274 | // FIXME json definitions can store the crate name |
298 | None, | 275 | None, |
299 | cfg_options, | 276 | krate.cfg.clone(), |
300 | env, | 277 | env, |
301 | proc_macro.unwrap_or_default(), | 278 | proc_macro.unwrap_or_default(), |
302 | ), | 279 | ), |
@@ -306,8 +283,8 @@ impl ProjectWorkspace { | |||
306 | 283 | ||
307 | for (id, krate) in project.crates.iter().enumerate() { | 284 | for (id, krate) in project.crates.iter().enumerate() { |
308 | for dep in &krate.deps { | 285 | for dep in &krate.deps { |
309 | let from_crate_id = json_project::CrateId(id); | 286 | let from_crate_id = CrateId(id as u32); |
310 | let to_crate_id = dep.krate; | 287 | let to_crate_id = dep.crate_id; |
311 | if let (Some(&from), Some(&to)) = | 288 | if let (Some(&from), Some(&to)) = |
312 | (crates.get(&from_crate_id), crates.get(&to_crate_id)) | 289 | (crates.get(&from_crate_id), crates.get(&to_crate_id)) |
313 | { | 290 | { |
@@ -523,15 +500,15 @@ impl ProjectWorkspace { | |||
523 | crate_graph | 500 | crate_graph |
524 | } | 501 | } |
525 | 502 | ||
526 | pub fn workspace_root_for(&self, path: &Path) -> Option<&Path> { | 503 | pub fn workspace_root_for(&self, path: &Path) -> Option<&AbsPath> { |
527 | match self { | 504 | match self { |
528 | ProjectWorkspace::Cargo { cargo, .. } => { | 505 | ProjectWorkspace::Cargo { cargo, .. } => { |
529 | Some(cargo.workspace_root()).filter(|root| path.starts_with(root)) | 506 | Some(cargo.workspace_root()).filter(|root| path.starts_with(root)) |
530 | } | 507 | } |
531 | ProjectWorkspace::Json { project: JsonProject { roots, .. }, .. } => roots | 508 | ProjectWorkspace::Json { project: ProjectJson { roots, .. }, .. } => roots |
532 | .iter() | 509 | .iter() |
533 | .find(|root| path.starts_with(&root.path)) | 510 | .find(|root| path.starts_with(&root.path)) |
534 | .map(|root| root.path.as_ref()), | 511 | .map(|root| root.path.as_path()), |
535 | } | 512 | } |
536 | } | 513 | } |
537 | } | 514 | } |
diff --git a/crates/ra_project_model/src/project_json.rs b/crates/ra_project_model/src/project_json.rs new file mode 100644 index 000000000..4b5dcd634 --- /dev/null +++ b/crates/ra_project_model/src/project_json.rs | |||
@@ -0,0 +1,117 @@ | |||
1 | //! FIXME: write short doc here | ||
2 | |||
3 | use std::path::PathBuf; | ||
4 | |||
5 | use paths::{AbsPath, AbsPathBuf}; | ||
6 | use ra_cfg::CfgOptions; | ||
7 | use ra_db::{CrateId, Dependency, Edition}; | ||
8 | use rustc_hash::FxHashSet; | ||
9 | use serde::Deserialize; | ||
10 | use stdx::split_delim; | ||
11 | |||
12 | /// Roots and crates that compose this Rust project. | ||
13 | #[derive(Clone, Debug)] | ||
14 | pub struct ProjectJson { | ||
15 | pub(crate) roots: Vec<Root>, | ||
16 | pub(crate) crates: Vec<Crate>, | ||
17 | } | ||
18 | |||
19 | /// A root points to the directory which contains Rust crates. rust-analyzer watches all files in | ||
20 | /// all roots. Roots might be nested. | ||
21 | #[derive(Clone, Debug)] | ||
22 | pub struct Root { | ||
23 | pub(crate) path: AbsPathBuf, | ||
24 | } | ||
25 | |||
26 | /// A crate points to the root module of a crate and lists the dependencies of the crate. This is | ||
27 | /// useful in creating the crate graph. | ||
28 | #[derive(Clone, Debug)] | ||
29 | pub struct Crate { | ||
30 | pub(crate) root_module: AbsPathBuf, | ||
31 | pub(crate) edition: Edition, | ||
32 | pub(crate) deps: Vec<Dependency>, | ||
33 | pub(crate) cfg: CfgOptions, | ||
34 | pub(crate) out_dir: Option<AbsPathBuf>, | ||
35 | pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>, | ||
36 | } | ||
37 | |||
38 | impl ProjectJson { | ||
39 | pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson { | ||
40 | ProjectJson { | ||
41 | roots: data.roots.into_iter().map(|path| Root { path: base.join(path) }).collect(), | ||
42 | crates: data | ||
43 | .crates | ||
44 | .into_iter() | ||
45 | .map(|crate_data| Crate { | ||
46 | root_module: base.join(crate_data.root_module), | ||
47 | edition: crate_data.edition.into(), | ||
48 | deps: crate_data | ||
49 | .deps | ||
50 | .into_iter() | ||
51 | .map(|dep_data| Dependency { | ||
52 | crate_id: CrateId(dep_data.krate as u32), | ||
53 | name: dep_data.name.into(), | ||
54 | }) | ||
55 | .collect::<Vec<_>>(), | ||
56 | cfg: { | ||
57 | let mut cfg = CfgOptions::default(); | ||
58 | for entry in &crate_data.cfg { | ||
59 | match split_delim(entry, '=') { | ||
60 | Some((key, value)) => { | ||
61 | cfg.insert_key_value(key.into(), value.into()); | ||
62 | } | ||
63 | None => cfg.insert_atom(entry.into()), | ||
64 | } | ||
65 | } | ||
66 | cfg | ||
67 | }, | ||
68 | out_dir: crate_data.out_dir.map(|it| base.join(it)), | ||
69 | proc_macro_dylib_path: crate_data.proc_macro_dylib_path.map(|it| base.join(it)), | ||
70 | }) | ||
71 | .collect::<Vec<_>>(), | ||
72 | } | ||
73 | } | ||
74 | } | ||
75 | |||
76 | #[derive(Deserialize)] | ||
77 | pub struct ProjectJsonData { | ||
78 | roots: Vec<PathBuf>, | ||
79 | crates: Vec<CrateData>, | ||
80 | } | ||
81 | |||
82 | #[derive(Deserialize)] | ||
83 | struct CrateData { | ||
84 | root_module: PathBuf, | ||
85 | edition: EditionData, | ||
86 | deps: Vec<DepData>, | ||
87 | #[serde(default)] | ||
88 | cfg: FxHashSet<String>, | ||
89 | out_dir: Option<PathBuf>, | ||
90 | proc_macro_dylib_path: Option<PathBuf>, | ||
91 | } | ||
92 | |||
93 | #[derive(Deserialize)] | ||
94 | #[serde(rename = "edition")] | ||
95 | enum EditionData { | ||
96 | #[serde(rename = "2015")] | ||
97 | Edition2015, | ||
98 | #[serde(rename = "2018")] | ||
99 | Edition2018, | ||
100 | } | ||
101 | |||
102 | impl From<EditionData> for Edition { | ||
103 | fn from(data: EditionData) -> Self { | ||
104 | match data { | ||
105 | EditionData::Edition2015 => Edition::Edition2015, | ||
106 | EditionData::Edition2018 => Edition::Edition2018, | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | |||
111 | #[derive(Deserialize)] | ||
112 | struct DepData { | ||
113 | /// Identifies a crate by position in the crates array. | ||
114 | #[serde(rename = "crate")] | ||
115 | krate: usize, | ||
116 | name: String, | ||
117 | } | ||
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index 65f90c83c..e98d0f868 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs | |||
@@ -1,8 +1,7 @@ | |||
1 | //! See `CargoTargetSpec` | 1 | //! See `CargoTargetSpec` |
2 | 2 | ||
3 | use std::path::PathBuf; | ||
4 | |||
5 | use ra_cfg::CfgExpr; | 3 | use ra_cfg::CfgExpr; |
4 | use ra_db::AbsPathBuf; | ||
6 | use ra_ide::{FileId, RunnableKind, TestId}; | 5 | use ra_ide::{FileId, RunnableKind, TestId}; |
7 | use ra_project_model::{self, TargetKind}; | 6 | use ra_project_model::{self, TargetKind}; |
8 | 7 | ||
@@ -14,7 +13,7 @@ use crate::{global_state::GlobalStateSnapshot, Result}; | |||
14 | /// build/test/run the target. | 13 | /// build/test/run the target. |
15 | #[derive(Clone)] | 14 | #[derive(Clone)] |
16 | pub(crate) struct CargoTargetSpec { | 15 | pub(crate) struct CargoTargetSpec { |
17 | pub(crate) workspace_root: PathBuf, | 16 | pub(crate) workspace_root: AbsPathBuf, |
18 | pub(crate) package: String, | 17 | pub(crate) package: String, |
19 | pub(crate) target: String, | 18 | pub(crate) target: String, |
20 | pub(crate) target_kind: TargetKind, | 19 | pub(crate) target_kind: TargetKind, |
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index e910db6eb..9c510bb62 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | //! Loads a Cargo project into a static instance of analysis, without support | 1 | //! Loads a Cargo project into a static instance of analysis, without support |
2 | //! for incorporating changes. | 2 | //! for incorporating changes. |
3 | use std::{convert::TryFrom, path::Path, sync::Arc}; | 3 | use std::{path::Path, sync::Arc}; |
4 | 4 | ||
5 | use anyhow::Result; | 5 | use anyhow::Result; |
6 | use crossbeam_channel::{unbounded, Receiver}; | 6 | use crossbeam_channel::{unbounded, Receiver}; |
7 | use ra_db::{AbsPathBuf, CrateGraph}; | 7 | use ra_db::{AbsPathBuf, CrateGraph}; |
8 | use ra_ide::{AnalysisChange, AnalysisHost}; | 8 | use ra_ide::{AnalysisChange, AnalysisHost}; |
9 | use ra_project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace}; | 9 | use ra_project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace}; |
10 | use vfs::loader::Handle; | 10 | use vfs::{loader::Handle, AbsPath}; |
11 | 11 | ||
12 | use crate::global_state::{ProjectFolders, SourceRootConfig}; | 12 | use crate::global_state::{ProjectFolders, SourceRootConfig}; |
13 | 13 | ||
@@ -39,10 +39,9 @@ pub fn load_cargo( | |||
39 | ProcMacroClient::dummy() | 39 | ProcMacroClient::dummy() |
40 | }; | 40 | }; |
41 | 41 | ||
42 | let crate_graph = ws.to_crate_graph(None, &proc_macro_client, &mut |path: &Path| { | 42 | let crate_graph = ws.to_crate_graph(None, &proc_macro_client, &mut |path: &AbsPath| { |
43 | let path = AbsPathBuf::try_from(path.to_path_buf()).unwrap(); | 43 | let contents = loader.load_sync(path); |
44 | let contents = loader.load_sync(&path); | 44 | let path = vfs::VfsPath::from(path.to_path_buf()); |
45 | let path = vfs::VfsPath::from(path); | ||
46 | vfs.set_file_contents(path.clone(), contents); | 45 | vfs.set_file_contents(path.clone(), contents); |
47 | vfs.file_id(&path) | 46 | vfs.file_id(&path) |
48 | }); | 47 | }); |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 0be34c43f..8f69de968 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -14,7 +14,7 @@ use lsp_types::ClientCapabilities; | |||
14 | use ra_db::AbsPathBuf; | 14 | use ra_db::AbsPathBuf; |
15 | use ra_flycheck::FlycheckConfig; | 15 | use ra_flycheck::FlycheckConfig; |
16 | use ra_ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; | 16 | use ra_ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; |
17 | use ra_project_model::{CargoConfig, JsonProject, ProjectManifest}; | 17 | use ra_project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; |
18 | use serde::Deserialize; | 18 | use serde::Deserialize; |
19 | 19 | ||
20 | #[derive(Debug, Clone)] | 20 | #[derive(Debug, Clone)] |
@@ -47,7 +47,7 @@ pub struct Config { | |||
47 | #[derive(Debug, Clone)] | 47 | #[derive(Debug, Clone)] |
48 | pub enum LinkedProject { | 48 | pub enum LinkedProject { |
49 | ProjectManifest(ProjectManifest), | 49 | ProjectManifest(ProjectManifest), |
50 | InlineJsonProject(JsonProject), | 50 | InlineJsonProject(ProjectJson), |
51 | } | 51 | } |
52 | 52 | ||
53 | impl From<ProjectManifest> for LinkedProject { | 53 | impl From<ProjectManifest> for LinkedProject { |
@@ -56,8 +56,8 @@ impl From<ProjectManifest> for LinkedProject { | |||
56 | } | 56 | } |
57 | } | 57 | } |
58 | 58 | ||
59 | impl From<JsonProject> for LinkedProject { | 59 | impl From<ProjectJson> for LinkedProject { |
60 | fn from(v: JsonProject) -> Self { | 60 | fn from(v: ProjectJson) -> Self { |
61 | LinkedProject::InlineJsonProject(v) | 61 | LinkedProject::InlineJsonProject(v) |
62 | } | 62 | } |
63 | } | 63 | } |
@@ -273,19 +273,19 @@ impl Config { | |||
273 | self.lens = LensConfig::NO_LENS; | 273 | self.lens = LensConfig::NO_LENS; |
274 | } | 274 | } |
275 | 275 | ||
276 | if let Some(linked_projects) = get::<Vec<ManifestOrJsonProject>>(value, "/linkedProjects") { | 276 | if let Some(linked_projects) = get::<Vec<ManifestOrProjectJson>>(value, "/linkedProjects") { |
277 | if !linked_projects.is_empty() { | 277 | if !linked_projects.is_empty() { |
278 | self.linked_projects.clear(); | 278 | self.linked_projects.clear(); |
279 | for linked_project in linked_projects { | 279 | for linked_project in linked_projects { |
280 | let linked_project = match linked_project { | 280 | let linked_project = match linked_project { |
281 | ManifestOrJsonProject::Manifest(it) => { | 281 | ManifestOrProjectJson::Manifest(it) => { |
282 | let path = self.root_path.join(it); | 282 | let path = self.root_path.join(it); |
283 | match ProjectManifest::from_manifest_file(path) { | 283 | match ProjectManifest::from_manifest_file(path) { |
284 | Ok(it) => it.into(), | 284 | Ok(it) => it.into(), |
285 | Err(_) => continue, | 285 | Err(_) => continue, |
286 | } | 286 | } |
287 | } | 287 | } |
288 | ManifestOrJsonProject::JsonProject(it) => it.into(), | 288 | ManifestOrProjectJson::ProjectJson(it) => ProjectJson::new(&self.root_path, it).into(), |
289 | }; | 289 | }; |
290 | self.linked_projects.push(linked_project); | 290 | self.linked_projects.push(linked_project); |
291 | } | 291 | } |
@@ -371,7 +371,7 @@ impl Config { | |||
371 | 371 | ||
372 | #[derive(Deserialize)] | 372 | #[derive(Deserialize)] |
373 | #[serde(untagged)] | 373 | #[serde(untagged)] |
374 | enum ManifestOrJsonProject { | 374 | enum ManifestOrProjectJson { |
375 | Manifest(PathBuf), | 375 | Manifest(PathBuf), |
376 | JsonProject(JsonProject), | 376 | ProjectJson(ProjectJsonData), |
377 | } | 377 | } |
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index f18694feb..e7eeb60ee 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | //! | 3 | //! |
4 | //! Each tick provides an immutable snapshot of the state as `WorldSnapshot`. | 4 | //! Each tick provides an immutable snapshot of the state as `WorldSnapshot`. |
5 | 5 | ||
6 | use std::{convert::TryFrom, path::Path, sync::Arc}; | 6 | use std::{convert::TryFrom, sync::Arc}; |
7 | 7 | ||
8 | use crossbeam_channel::{unbounded, Receiver}; | 8 | use crossbeam_channel::{unbounded, Receiver}; |
9 | use lsp_types::Url; | 9 | use lsp_types::Url; |
@@ -13,7 +13,7 @@ use ra_flycheck::{Flycheck, FlycheckConfig}; | |||
13 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId}; | 13 | use ra_ide::{Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId}; |
14 | use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; | 14 | use ra_project_model::{CargoWorkspace, ProcMacroClient, ProjectWorkspace, Target}; |
15 | use stdx::format_to; | 15 | use stdx::format_to; |
16 | use vfs::{file_set::FileSetConfig, loader::Handle, AbsPathBuf}; | 16 | use vfs::{file_set::FileSetConfig, loader::Handle, AbsPath, AbsPathBuf}; |
17 | 17 | ||
18 | use crate::{ | 18 | use crate::{ |
19 | config::{Config, FilesWatcher}, | 19 | config::{Config, FilesWatcher}, |
@@ -31,7 +31,7 @@ fn create_flycheck(workspaces: &[ProjectWorkspace], config: &FlycheckConfig) -> | |||
31 | workspaces.iter().find_map(|w| match w { | 31 | workspaces.iter().find_map(|w| match w { |
32 | ProjectWorkspace::Cargo { cargo, .. } => { | 32 | ProjectWorkspace::Cargo { cargo, .. } => { |
33 | let cargo_project_root = cargo.workspace_root().to_path_buf(); | 33 | let cargo_project_root = cargo.workspace_root().to_path_buf(); |
34 | Some(Flycheck::new(config.clone(), cargo_project_root)) | 34 | Some(Flycheck::new(config.clone(), cargo_project_root.into())) |
35 | } | 35 | } |
36 | ProjectWorkspace::Json { .. } => { | 36 | ProjectWorkspace::Json { .. } => { |
37 | log::warn!("Cargo check watching only supported for cargo workspaces, disabling"); | 37 | log::warn!("Cargo check watching only supported for cargo workspaces, disabling"); |
@@ -112,10 +112,9 @@ impl GlobalState { | |||
112 | 112 | ||
113 | // Create crate graph from all the workspaces | 113 | // Create crate graph from all the workspaces |
114 | let mut crate_graph = CrateGraph::default(); | 114 | let mut crate_graph = CrateGraph::default(); |
115 | let mut load = |path: &Path| { | 115 | let mut load = |path: &AbsPath| { |
116 | let path = AbsPathBuf::try_from(path.to_path_buf()).ok()?; | 116 | let contents = loader.load_sync(path); |
117 | let contents = loader.load_sync(&path); | 117 | let path = vfs::VfsPath::from(path.to_path_buf()); |
118 | let path = vfs::VfsPath::from(path); | ||
119 | vfs.set_file_contents(path.clone(), contents); | 118 | vfs.set_file_contents(path.clone(), contents); |
120 | vfs.file_id(&path) | 119 | vfs.file_id(&path) |
121 | }; | 120 | }; |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index b9d296856..390c66dfc 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -114,10 +114,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
114 | .ok() | 114 | .ok() |
115 | } | 115 | } |
116 | LinkedProject::InlineJsonProject(it) => { | 116 | LinkedProject::InlineJsonProject(it) => { |
117 | Some(ra_project_model::ProjectWorkspace::Json { | 117 | Some(ra_project_model::ProjectWorkspace::Json { project: it.clone() }) |
118 | project: it.clone(), | ||
119 | project_location: config.root_path.clone(), | ||
120 | }) | ||
121 | } | 118 | } |
122 | }) | 119 | }) |
123 | .collect::<Vec<_>>() | 120 | .collect::<Vec<_>>() |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index 221b902b2..a1e2432cf 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -419,7 +419,7 @@ pub fn handle_runnables( | |||
419 | location: None, | 419 | location: None, |
420 | kind: lsp_ext::RunnableKind::Cargo, | 420 | kind: lsp_ext::RunnableKind::Cargo, |
421 | args: lsp_ext::CargoRunnable { | 421 | args: lsp_ext::CargoRunnable { |
422 | workspace_root: Some(spec.workspace_root.clone()), | 422 | workspace_root: Some(spec.workspace_root.clone().into()), |
423 | cargo_args: vec![ | 423 | cargo_args: vec![ |
424 | cmd.to_string(), | 424 | cmd.to_string(), |
425 | "--package".to_string(), | 425 | "--package".to_string(), |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index da9887a9a..88d1c0d8a 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -663,7 +663,7 @@ pub(crate) fn runnable( | |||
663 | location: Some(location), | 663 | location: Some(location), |
664 | kind: lsp_ext::RunnableKind::Cargo, | 664 | kind: lsp_ext::RunnableKind::Cargo, |
665 | args: lsp_ext::CargoRunnable { | 665 | args: lsp_ext::CargoRunnable { |
666 | workspace_root: workspace_root, | 666 | workspace_root: workspace_root.map(|it| it.into()), |
667 | cargo_args, | 667 | cargo_args, |
668 | executable_args, | 668 | executable_args, |
669 | }, | 669 | }, |
diff --git a/crates/vfs-notify/src/lib.rs b/crates/vfs-notify/src/lib.rs index baee6ddc8..5b4978285 100644 --- a/crates/vfs-notify/src/lib.rs +++ b/crates/vfs-notify/src/lib.rs | |||
@@ -45,7 +45,7 @@ impl loader::Handle for LoaderHandle { | |||
45 | fn invalidate(&mut self, path: AbsPathBuf) { | 45 | fn invalidate(&mut self, path: AbsPathBuf) { |
46 | self.sender.send(Message::Invalidate(path)).unwrap(); | 46 | self.sender.send(Message::Invalidate(path)).unwrap(); |
47 | } | 47 | } |
48 | fn load_sync(&mut self, path: &AbsPathBuf) -> Option<Vec<u8>> { | 48 | fn load_sync(&mut self, path: &AbsPath) -> Option<Vec<u8>> { |
49 | read(path) | 49 | read(path) |
50 | } | 50 | } |
51 | } | 51 | } |
diff --git a/crates/vfs/src/loader.rs b/crates/vfs/src/loader.rs index a216b5f13..052803dd9 100644 --- a/crates/vfs/src/loader.rs +++ b/crates/vfs/src/loader.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Object safe interface for file watching and reading. | 1 | //! Object safe interface for file watching and reading. |
2 | use std::fmt; | 2 | use std::fmt; |
3 | 3 | ||
4 | use paths::AbsPathBuf; | 4 | use paths::{AbsPath, AbsPathBuf}; |
5 | 5 | ||
6 | #[derive(Debug)] | 6 | #[derive(Debug)] |
7 | pub enum Entry { | 7 | pub enum Entry { |
@@ -28,7 +28,7 @@ pub trait Handle: fmt::Debug { | |||
28 | Self: Sized; | 28 | Self: Sized; |
29 | fn set_config(&mut self, config: Config); | 29 | fn set_config(&mut self, config: Config); |
30 | fn invalidate(&mut self, path: AbsPathBuf); | 30 | fn invalidate(&mut self, path: AbsPathBuf); |
31 | fn load_sync(&mut self, path: &AbsPathBuf) -> Option<Vec<u8>>; | 31 | fn load_sync(&mut self, path: &AbsPath) -> Option<Vec<u8>>; |
32 | } | 32 | } |
33 | 33 | ||
34 | impl Entry { | 34 | impl Entry { |
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc index f1b7ed7fc..0dc1dc2ae 100644 --- a/docs/user/manual.adoc +++ b/docs/user/manual.adoc | |||
@@ -322,6 +322,8 @@ There are tree ways to feed `rust-project.json` to rust-analyzer: | |||
322 | * Specify `"rust-analyzer.linkedProjects": [ "path/to/rust-project.json" ]` in the settings (and make sure that your LSP client sends settings as a part of initialize request). | 322 | * Specify `"rust-analyzer.linkedProjects": [ "path/to/rust-project.json" ]` in the settings (and make sure that your LSP client sends settings as a part of initialize request). |
323 | * Specify `"rust-analyzer.linkedProjects": [ { "roots": [...], "crates": [...] }]` inline. | 323 | * Specify `"rust-analyzer.linkedProjects": [ { "roots": [...], "crates": [...] }]` inline. |
324 | 324 | ||
325 | Relative paths are interpreted relative to `rust-project.json` file location or (for inline JSON) relative to `rootUri`. | ||
326 | |||
325 | See https://github.com/rust-analyzer/rust-project.json-example for a small example. | 327 | See https://github.com/rust-analyzer/rust-project.json-example for a small example. |
326 | 328 | ||
327 | == Features | 329 | == Features |