Skip to content

Commit 1edf6d2

Browse files
bors[bot]matklad
andauthored
Merge #4730
4730: Document rust-project.json r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
2 parents e644f64 + fa019c8 commit 1edf6d2

File tree

5 files changed

+118
-20
lines changed

5 files changed

+118
-20
lines changed

crates/ra_project_model/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ pub enum ProjectWorkspace {
3232
Json { project: JsonProject },
3333
}
3434

35+
impl From<JsonProject> for ProjectWorkspace {
36+
fn from(project: JsonProject) -> ProjectWorkspace {
37+
ProjectWorkspace::Json { project }
38+
}
39+
}
40+
3541
/// `PackageRoot` describes a package root folder.
3642
/// Which may be an external dependency, or a member of
3743
/// the current workspace.
@@ -144,11 +150,11 @@ impl ProjectManifest {
144150

145151
impl ProjectWorkspace {
146152
pub fn load(
147-
root: ProjectManifest,
153+
manifest: ProjectManifest,
148154
cargo_features: &CargoConfig,
149155
with_sysroot: bool,
150156
) -> Result<ProjectWorkspace> {
151-
let res = match root {
157+
let res = match manifest {
152158
ProjectManifest::ProjectJson(project_json) => {
153159
let file = File::open(&project_json).with_context(|| {
154160
format!("Failed to open json file {}", project_json.display())

crates/rust-analyzer/src/config.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,22 @@ impl Config {
261261
self.lens = LensConfig::NO_LENS;
262262
}
263263

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+
264280
log::info!("Config::update() = {:#?}", self);
265281

266282
fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> {
@@ -324,3 +340,10 @@ impl Config {
324340
}
325341
}
326342
}
343+
344+
#[derive(Deserialize)]
345+
#[serde(untagged)]
346+
enum ManifestOrJsonProject {
347+
Manifest(PathBuf),
348+
JsonProject(JsonProject),
349+
}

crates/rust-analyzer/src/main_loop.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -105,24 +105,23 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
105105
.linked_projects
106106
.iter()
107107
.filter_map(|project| match project {
108-
LinkedProject::ProjectManifest(it) => Some(it),
109-
LinkedProject::JsonProject(_) => None,
110-
})
111-
.filter_map(|root| {
112-
ra_project_model::ProjectWorkspace::load(
113-
root.clone(),
114-
&config.cargo,
115-
config.with_sysroot,
116-
)
117-
.map_err(|err| {
118-
log::error!("failed to load workspace: {:#}", err);
119-
show_message(
120-
lsp_types::MessageType::Error,
121-
format!("rust-analyzer failed to load workspace: {:#}", err),
122-
&connection.sender,
123-
);
124-
})
125-
.ok()
108+
LinkedProject::ProjectManifest(manifest) => {
109+
ra_project_model::ProjectWorkspace::load(
110+
manifest.clone(),
111+
&config.cargo,
112+
config.with_sysroot,
113+
)
114+
.map_err(|err| {
115+
log::error!("failed to load workspace: {:#}", err);
116+
show_message(
117+
lsp_types::MessageType::Error,
118+
format!("rust-analyzer failed to load workspace: {:#}", err),
119+
&connection.sender,
120+
);
121+
})
122+
.ok()
123+
}
124+
LinkedProject::JsonProject(it) => Some(it.clone().into()),
126125
})
127126
.collect::<Vec<_>>()
128127
};

docs/user/manual.adoc

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,57 @@ Gnome Builder currently has support for RLS, and there's no way to configure the
269269
1. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`).
270270
2. Enable the Rust Builder plugin.
271271

272+
== Non-Cargo Based Projects
273+
274+
rust-analyzer does not require Cargo.
275+
However, 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+
----
279+
interface 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+
288+
interface 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+
304+
interface 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+
312+
This format is provisional and subject to change.
313+
Specifically, the `roots` setup will be different eventually.
314+
315+
There 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+
321+
See https://github.com/rust-analyzer/rust-project.json-example for a small example.
322+
272323
== Features
273324

274325
include::./generated_features.adoc[]

editors/code/package.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,25 @@
475475
"markdownDescription": "Whether to show Implementations lens. Only applies when `#rust-analyzer.lens.enable#` is set.",
476476
"type": "boolean",
477477
"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
478497
}
479498
}
480499
},

0 commit comments

Comments
 (0)