aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-06-03 13:48:38 +0100
committerAleksey Kladov <[email protected]>2020-06-03 14:17:26 +0100
commitfa019c8f562326a720d2ef9165626c4c5703f67b (patch)
treedac38194fb66e0d563ffb52bbbc0e740f824cfd8
parent2e7d12d2f3ccfd1ef9946d1212e2455e5937c521 (diff)
Document rust-project.json
-rw-r--r--crates/ra_project_model/src/lib.rs10
-rw-r--r--crates/rust-analyzer/src/config.rs23
-rw-r--r--crates/rust-analyzer/src/main_loop.rs35
-rw-r--r--docs/user/manual.adoc51
-rw-r--r--editors/code/package.json19
5 files changed, 118 insertions, 20 deletions
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index a99612690..7ad941279 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -32,6 +32,12 @@ pub enum ProjectWorkspace {
32 Json { project: JsonProject }, 32 Json { project: JsonProject },
33} 33}
34 34
35impl From<JsonProject> for ProjectWorkspace {
36 fn from(project: JsonProject) -> ProjectWorkspace {
37 ProjectWorkspace::Json { project }
38 }
39}
40
35/// `PackageRoot` describes a package root folder. 41/// `PackageRoot` describes a package root folder.
36/// Which may be an external dependency, or a member of 42/// Which may be an external dependency, or a member of
37/// the current workspace. 43/// the current workspace.
@@ -144,11 +150,11 @@ impl ProjectManifest {
144 150
145impl ProjectWorkspace { 151impl ProjectWorkspace {
146 pub fn load( 152 pub fn load(
147 root: ProjectManifest, 153 manifest: ProjectManifest,
148 cargo_features: &CargoConfig, 154 cargo_features: &CargoConfig,
149 with_sysroot: bool, 155 with_sysroot: bool,
150 ) -> Result<ProjectWorkspace> { 156 ) -> Result<ProjectWorkspace> {
151 let res = match root { 157 let res = match manifest {
152 ProjectManifest::ProjectJson(project_json) => { 158 ProjectManifest::ProjectJson(project_json) => {
153 let file = File::open(&project_json).with_context(|| { 159 let file = File::open(&project_json).with_context(|| {
154 format!("Failed to open json file {}", project_json.display()) 160 format!("Failed to open json file {}", project_json.display())
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 761bc9c2d..0e5dc56fd 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -261,6 +261,22 @@ impl Config {
261 self.lens = LensConfig::NO_LENS; 261 self.lens = LensConfig::NO_LENS;
262 } 262 }
263 263
264 if let Some(linked_projects) = get::<Vec<ManifestOrJsonProject>>(value, "/linkedProjects") {
265 if !linked_projects.is_empty() {
266 self.linked_projects.clear();
267 for linked_project in linked_projects {
268 let linked_project = match linked_project {
269 ManifestOrJsonProject::Manifest(it) => match ProjectManifest::from_manifest_file(it) {
270 Ok(it) => it.into(),
271 Err(_) => continue,
272 }
273 ManifestOrJsonProject::JsonProject(it) => it.into(),
274 };
275 self.linked_projects.push(linked_project);
276 }
277 }
278 }
279
264 log::info!("Config::update() = {:#?}", self); 280 log::info!("Config::update() = {:#?}", self);
265 281
266 fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> { 282 fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> {
@@ -324,3 +340,10 @@ impl Config {
324 } 340 }
325 } 341 }
326} 342}
343
344#[derive(Deserialize)]
345#[serde(untagged)]
346enum ManifestOrJsonProject {
347 Manifest(PathBuf),
348 JsonProject(JsonProject),
349}
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index d901f21d7..1f8f6b978 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -105,24 +105,23 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
105 .linked_projects 105 .linked_projects
106 .iter() 106 .iter()
107 .filter_map(|project| match project { 107 .filter_map(|project| match project {
108 LinkedProject::ProjectManifest(it) => Some(it), 108 LinkedProject::ProjectManifest(manifest) => {
109 LinkedProject::JsonProject(_) => None, 109 ra_project_model::ProjectWorkspace::load(
110 }) 110 manifest.clone(),
111 .filter_map(|root| { 111 &config.cargo,
112 ra_project_model::ProjectWorkspace::load( 112 config.with_sysroot,
113 root.clone(), 113 )
114 &config.cargo, 114 .map_err(|err| {
115 config.with_sysroot, 115 log::error!("failed to load workspace: {:#}", err);
116 ) 116 show_message(
117 .map_err(|err| { 117 lsp_types::MessageType::Error,
118 log::error!("failed to load workspace: {:#}", err); 118 format!("rust-analyzer failed to load workspace: {:#}", err),
119 show_message( 119 &connection.sender,
120 lsp_types::MessageType::Error, 120 );
121 format!("rust-analyzer failed to load workspace: {:#}", err), 121 })
122 &connection.sender, 122 .ok()
123 ); 123 }
124 }) 124 LinkedProject::JsonProject(it) => Some(it.clone().into()),
125 .ok()
126 }) 125 })
127 .collect::<Vec<_>>() 126 .collect::<Vec<_>>()
128 }; 127 };
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 202783fd9..ea714f49a 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -269,6 +269,57 @@ Gnome Builder currently has support for RLS, and there's no way to configure the
2691. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`). 2691. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`).
2702. Enable the Rust Builder plugin. 2702. Enable the Rust Builder plugin.
271 271
272== Non-Cargo Based Projects
273
274rust-analyzer does not require Cargo.
275However, if you use some other build system, you'll have to describe the structure of your project for rust-analyzer in the `rust-project.json` format:
276
277[source,TypeScript]
278----
279interface JsonProject {
280 /// The set of paths containing the crates for this project.
281 /// Any `Crate` must be nested inside some `root`.
282 roots: string[];
283 /// The set of crates comprising the current project.
284 /// Must include all transitive dependencies as well as sysroot crate (libstd, libcore and such).
285 crates: Crate[];
286}
287
288interface Crate {
289 /// Path to the root module of the crate.
290 root_module: string;
291 /// Edition of the crate.
292 edition: "2015" | "2018";
293 /// Dependencies
294 deps: Dep[];
295 /// The set of cfgs activated for a given crate, like `["unix", "feature=foo", "feature=bar"]`.
296 cfg: string[];
297
298 /// value of the OUT_DIR env variable.
299 out_dir?: string;
300 /// For proc-macro crates, path to compiles proc-macro (.so file).
301 proc_macro_dylib_path?: string;
302}
303
304interface Dep {
305 /// Index of a crate in the `crates` array.
306 crate: number,
307 /// Name as should appear in the (implicit) `extern crate name` declaration.
308 name: string,
309}
310----
311
312This format is provisional and subject to change.
313Specifically, the `roots` setup will be different eventually.
314
315There are tree ways to feed `rust-project.json` to rust-analyzer:
316
317* Place `rust-project.json` file at the root of the project, and rust-anlayzer will discover it.
318* 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).
319* Specify `"rust-analyzer.linkedProjects": [ { "roots": [...], "crates": [...] }]` inline.
320
321See https://github.com/rust-analyzer/rust-project.json-example for a small example.
322
272== Features 323== Features
273 324
274include::./generated_features.adoc[] 325include::./generated_features.adoc[]
diff --git a/editors/code/package.json b/editors/code/package.json
index d8f4287fd..30ab7ba4a 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -475,6 +475,25 @@
475 "markdownDescription": "Whether to show Implementations lens. Only applies when `#rust-analyzer.lens.enable#` is set.", 475 "markdownDescription": "Whether to show Implementations lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
476 "type": "boolean", 476 "type": "boolean",
477 "default": true 477 "default": true
478 },
479 "rust-analyzer.linkedProjects": {
480 "markdownDescription": [
481 "Disable project auto-discovery in favor of explicitly specified set of projects.",
482 "Elements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format"
483 ],
484 "type": "array",
485 "items": {
486 "type": [
487 "string",
488 "object"
489 ]
490 },
491 "default": null
492 },
493 "rust-analyzer.withSysroot": {
494 "markdownDescription": "Internal config for debugging, disables loading of sysroot crates",
495 "type": "boolean",
496 "default": true
478 } 497 }
479 } 498 }
480 }, 499 },