-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
163 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
--- | ||
title: "Rust-analyzer on files outside of the module tree" | ||
date: 2023-11-09T22:22:21+01:00 | ||
draft: true | ||
tags: ["tutorial"] | ||
--- | ||
|
||
There's this [Rust-Analyzer](https://github.com/rust-lang/rust-analyzer) functionality that not a lot of people know about, but has a great potential. And while the feature is documented, I heard of it just a few days ago. | ||
|
||
Yeah, you can use Rust-Analyzer even for standalone files that are not on a Cargo workspace. While not mind-blowing, it's still an interesting piece of this software that many Rust developers use on a daily basis in their IDEs. | ||
|
||
## `rust-project.json` | ||
|
||
The trick is using a file with the name of `rust-project.json` and quite a weird schema (Obviously, written in JSON). This file can be used to designate any Rust file as its own root of module. For example, a `rust-project.json` is used in the [rustlings](https://github.com/rust-lang/rustlings) codebase (Rust's official interactive learning materials) to designate each exercise as its own module, so that they have Rust-Analyzer's benefits like syntax highlighting and autocompletion. | ||
|
||
### The schema | ||
|
||
The schema for `rust-project.json` is the following: | ||
|
||
|
||
{{< code language="TypeScript" id="1" expand="Show" collapse="Hide" isCollapsed="false" >}} | ||
interface JsonProject { | ||
/// $ rustc --print sysroot | ||
sysroot?: string; | ||
/// By default, this is `lib/rustlib/src/rust/library` | ||
/// relative to the sysroot. | ||
sysroot_src?: string; | ||
/// The set of crates comprising the current | ||
/// project. Must include all transitive | ||
/// dependencies as well as sysroot crate (libstd, | ||
/// libcore and such). | ||
crates: Crate[]; | ||
} | ||
|
||
interface Crate { | ||
/// Optional crate name used for display purposes, | ||
/// without affecting semantics. See the `deps` | ||
/// key for semantically-significant crate names. | ||
display_name?: string; | ||
/// Path to the root module of the crate. | ||
root_module: string; | ||
/// Edition of the crate. | ||
edition: "2015" | "2018" | "2021"; | ||
/// Dependencies | ||
deps: Dep[]; | ||
/// Set this to `false` for things like standard | ||
/// library and 3rd party crates to enable | ||
/// performance optimizations (rust-analyzer | ||
/// assumes that non-member crates don't change). | ||
is_workspace_member?: boolean; | ||
/// Optionally specify the (super)set of `.rs` | ||
/// files comprising this crate. | ||
source?: { | ||
include_dirs: string[], | ||
exclude_dirs: string[], | ||
}, | ||
/// The set of cfgs activated for a given crate, like | ||
/// `["unix", "feature=\"foo\"", "feature=\"bar\""]`. | ||
cfg: string[]; | ||
/// Target triple for this Crate. | ||
/// | ||
/// Used when running `rustc --print cfg` | ||
/// to get target-specific cfgs. | ||
target?: string; | ||
/// Environment variables, used for | ||
/// the `env!` macro | ||
env: { [key: string]: string; }, | ||
/// Whether the crate is a proc-macro crate. | ||
is_proc_macro: boolean; | ||
/// For proc-macro crates, path to compiled | ||
/// proc-macro (.so file). | ||
proc_macro_dylib_path?: string; | ||
} | ||
|
||
interface Dep { | ||
/// Index of a crate in the `crates` array. | ||
crate: number, | ||
/// Name as should appear in the (implicit) | ||
/// `extern crate name` declaration. | ||
name: string, | ||
} | ||
{{< /code >}} | ||
|
||
Quite a lengthy schema definition (even though I cut some documentation), luckily a lot of these do have sensible defaults, and we can just piggyback of what Rust-Analyzer assumes about the codebase. | ||
|
||
## Implementing `rust-project.json` in our project | ||
|
||
Firstly, we have to take into account what IDEs are our developers using. In the majority of cases it will be VSCode, but we also have to take into account that some may be using NeoVim or a JetBrains solution. We can consult the [configuration path in RA's documentation](https://rust-analyzer.github.io/manual.html#configuration). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<nav class="menu"> | ||
<ul class="menu__inner menu__inner--desktop"> | ||
{{ if or $.Site.Params.showMenuItems (eq $.Site.Params.showMenuItems 0) }} | ||
{{ range first $.Site.Params.showMenuItems $.Site.Menus.main }} | ||
{{ if not .HasChildren }} | ||
<li id="{{ .Identifier }}"><a href="{{ .URL }}">{{ .Name }}</a></li> | ||
{{ end }} | ||
{{ end }} | ||
{{ if gt (len $.Site.Menus.main) $.Site.Params.showMenuItems }} | ||
<ul class="menu__sub-inner"> | ||
<li class="menu__sub-inner-more-trigger"> | ||
{{ $.Site.Params.MenuMore | default "Show more" }} | ||
<span class="menu__sub-inner-more-trigger-icon" | ||
>{{ partial "greater-icon.html" . }}</span | ||
> | ||
</li> | ||
<ul class="menu__sub-inner-more hidden"> | ||
{{ range last (sub (len $.Site.Menus.main) $.Site.Params.showMenuItems) $.Site.Menus.main }} | ||
{{ if not .HasChildren }} | ||
<li><a href="{{ .URL }}">{{ .Name }}</a></li> | ||
{{ end }} | ||
{{ end }} | ||
</ul> | ||
</ul> | ||
{{ end }} | ||
{{ else }} | ||
{{ range $.Site.Menus.main }} | ||
{{ if not .HasChildren }} | ||
<li><a href="{{ .URL }}">{{ .Name }}</a></li> | ||
{{ end }} | ||
{{ end }} | ||
{{ end }} | ||
</ul> | ||
|
||
<ul class="menu__inner menu__inner--mobile"> | ||
{{ range $.Site.Menus.main }} | ||
{{ if not .HasChildren }} | ||
<li><a href="{{ .URL }}">{{ .Name }}</a></li> | ||
{{ end }} | ||
{{ end }} | ||
</ul> | ||
</nav> |