diff --git a/PRIVACY.md b/PRIVACY.md index dd165c0e2c1..27e39ca6073 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -14,4 +14,4 @@ Any other editor plugins that integrate with `rust-analyzer` are not under the c ## Others -If `cargo check` is enabled (the default), any build scripts or procedural macros used by the project or its dependencies will be executed. This is also the case when `cargo check` is disabled, but build script or procedural macro support is enabled in `rust-analyzer` (off by default). +If `cargo check` is enabled (the default), any build scripts or procedural macros used by the project or its dependencies will be executed. This is also the case when `cargo check` is disabled, but build script or procedural macro support is enabled in `rust-analyzer` (on by default). diff --git a/README.md b/README.md index 085c8c0f63f..5fbc039644f 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,9 @@ For usage and troubleshooting requests, please use "IDEs and Editors" category o https://users.rust-lang.org/c/ide/14 -For questions about development and implementation, join rls-2.0 working group on Zulip: +For questions about development and implementation, join rust-analyzer working group on Zulip: -https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 +https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer ## Quick Links diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs index 8d464135572..04e2be39069 100644 --- a/crates/base_db/src/fixture.rs +++ b/crates/base_db/src/fixture.rs @@ -1,62 +1,4 @@ -//! Fixtures are strings containing rust source code with optional metadata. -//! A fixture without metadata is parsed into a single source file. -//! Use this to test functionality local to one file. -//! -//! Simple Example: -//! ``` -//! r#" -//! fn main() { -//! println!("Hello World") -//! } -//! "# -//! ``` -//! -//! Metadata can be added to a fixture after a `//-` comment. -//! The basic form is specifying filenames, -//! which is also how to define multiple files in a single test fixture -//! -//! Example using two files in the same crate: -//! ``` -//! " -//! //- /main.rs -//! mod foo; -//! fn main() { -//! foo::bar(); -//! } -//! -//! //- /foo.rs -//! pub fn bar() {} -//! " -//! ``` -//! -//! Example using two crates with one file each, with one crate depending on the other: -//! ``` -//! r#" -//! //- /main.rs crate:a deps:b -//! fn main() { -//! b::foo(); -//! } -//! //- /lib.rs crate:b -//! pub fn b() { -//! println!("Hello World") -//! } -//! "# -//! ``` -//! -//! Metadata allows specifying all settings and variables -//! that are available in a real rust project: -//! - crate names via `crate:cratename` -//! - dependencies via `deps:dep1,dep2` -//! - configuration settings via `cfg:dbg=false,opt_level=2` -//! - environment variables via `env:PATH=/bin,RUST_LOG=debug` -//! -//! Example using all available metadata: -//! ``` -//! " -//! //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo -//! fn insert_source_code_here() {} -//! " -//! ``` +//! A set of high-level utility fixture methods to use in tests. use std::{mem, str::FromStr, sync::Arc}; use cfg::CfgOptions; diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs index 6bc824e9437..099baeca2fc 100644 --- a/crates/test_utils/src/fixture.rs +++ b/crates/test_utils/src/fixture.rs @@ -1,5 +1,65 @@ //! Defines `Fixture` -- a convenient way to describe the initial state of //! rust-analyzer database from a single string. +//! +//! Fixtures are strings containing rust source code with optional metadata. +//! A fixture without metadata is parsed into a single source file. +//! Use this to test functionality local to one file. +//! +//! Simple Example: +//! ``` +//! r#" +//! fn main() { +//! println!("Hello World") +//! } +//! "# +//! ``` +//! +//! Metadata can be added to a fixture after a `//-` comment. +//! The basic form is specifying filenames, +//! which is also how to define multiple files in a single test fixture +//! +//! Example using two files in the same crate: +//! ``` +//! " +//! //- /main.rs +//! mod foo; +//! fn main() { +//! foo::bar(); +//! } +//! +//! //- /foo.rs +//! pub fn bar() {} +//! " +//! ``` +//! +//! Example using two crates with one file each, with one crate depending on the other: +//! ``` +//! r#" +//! //- /main.rs crate:a deps:b +//! fn main() { +//! b::foo(); +//! } +//! //- /lib.rs crate:b +//! pub fn b() { +//! println!("Hello World") +//! } +//! "# +//! ``` +//! +//! Metadata allows specifying all settings and variables +//! that are available in a real rust project: +//! - crate names via `crate:cratename` +//! - dependencies via `deps:dep1,dep2` +//! - configuration settings via `cfg:dbg=false,opt_level=2` +//! - environment variables via `env:PATH=/bin,RUST_LOG=debug` +//! +//! Example using all available metadata: +//! ``` +//! " +//! //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo +//! fn insert_source_code_here() {} +//! " +//! ``` use rustc_hash::FxHashMap; use stdx::{lines_with_ends, split_once, trim_indent}; @@ -24,7 +84,7 @@ impl Fixture { /// //- some meta /// line 1 /// line 2 - /// // - other meta + /// //- other meta /// ``` pub fn parse(ra_fixture: &str) -> Vec { let fixture = trim_indent(ra_fixture); diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md index fb991133aa7..3ffd9e8cbb2 100644 --- a/docs/dev/architecture.md +++ b/docs/dev/architecture.md @@ -42,7 +42,7 @@ The underlying engine makes sure that model is computed lazily (on-demand) and c ## Entry Points `crates/rust-analyzer/src/bin/main.rs` contains the main function which spawns LSP. -This is *the* entry point, but it front-loads a lot of complexity, so its fine to just skim through it. +This is *the* entry point, but it front-loads a lot of complexity, so it's fine to just skim through it. `crates/rust-analyzer/src/handlers.rs` implements all LSP requests and is a great place to start if you are already familiar with LSP. @@ -67,7 +67,7 @@ They are handled by Rust code in the xtask directory. VS Code plugin. -### `libs/` +### `lib/` rust-analyzer independent libraries which we publish to crates.io. It's not heavily utilized at the moment. @@ -139,7 +139,8 @@ If an AST method returns an `Option`, it *can* be `None` at runtime, even if thi ### `crates/base_db` We use the [salsa](https://github.com/salsa-rs/salsa) crate for incremental and on-demand computation. -Roughly, you can think of salsa as a key-value store, but it can also compute derived values using specified functions. The `base_db` crate provides basic infrastructure for interacting with salsa. +Roughly, you can think of salsa as a key-value store, but it can also compute derived values using specified functions. +The `base_db` crate provides basic infrastructure for interacting with salsa. Crucially, it defines most of the "input" queries: facts supplied by the client of the analyzer. Reading the docs of the `base_db::input` module should be useful: everything else is strictly derived from those inputs. @@ -221,7 +222,7 @@ Internally, `ide` is split across several crates. `ide_assists`, `ide_completion The `ide` contains a public API/façade, as well as implementation for a plethora of smaller features. **Architecture Invariant:** `ide` crate strives to provide a _perfect_ API. -Although at the moment it has only one consumer, the LSP server, LSP *does not* influence it's API design. +Although at the moment it has only one consumer, the LSP server, LSP *does not* influence its API design. Instead, we keep in mind a hypothetical _ideal_ client -- an IDE tailored specifically for rust, every nook and cranny of which is packed with Rust-specific goodies. ### `crates/rust-analyzer` @@ -307,7 +308,7 @@ This sections talks about the things which are everywhere and nowhere in particu ### Code generation -Some of the components of this repository are generated through automatic processes. +Some ]components in this repository are generated through automatic processes. Generated code is updated automatically on `cargo test`. Generated code is generally committed to the git repository. @@ -389,7 +390,7 @@ fn spam() { ``` To specify input data, we use a single string literal in a special format, which can describe a set of rust files. -See the `Fixture` type. +See the `Fixture` its module for fixture examples and documentation. **Architecture Invariant:** all code invariants are tested by `#[test]` tests. There's no additional checks in CI, formatting and tidy tests are run with `cargo test`. diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 989771ac6ff..a46121bb2ed 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md @@ -51,8 +51,8 @@ interface SnippetTextEdit extends TextEdit { ```typescript export interface TextDocumentEdit { - textDocument: OptionalVersionedTextDocumentIdentifier; - edits: (TextEdit | SnippetTextEdit)[]; + textDocument: OptionalVersionedTextDocumentIdentifier; + edits: (TextEdit | SnippetTextEdit)[]; } ``` @@ -145,9 +145,9 @@ mod foo; ### Unresolved Question * An alternative would be to use a more general "gotoSuper" request, which would work for super methods, super classes and super modules. - This is the approach IntelliJ Rust is takeing. + This is the approach IntelliJ Rust is taking. However, experience shows that super module (which generally has a feeling of navigation between files) should be separate. - If you want super module, but the cursor happens to be inside an overriden function, the behavior with single "gotoSuper" request is surprising. + If you want super module, but the cursor happens to be inside an overridden function, the behavior with single "gotoSuper" request is surprising. ## Join Lines @@ -193,7 +193,7 @@ fn main() { ### Unresolved Question * What is the position of the cursor after `joinLines`? - Currently this is left to editor's discretion, but it might be useful to specify on the server via snippets. + Currently, this is left to editor's discretion, but it might be useful to specify on the server via snippets. However, it then becomes unclear how it works with multi cursor. ## On Enter @@ -330,7 +330,7 @@ Moreover, it would be cool if editors didn't need to implement even basic langua ### Unresolved Question -* Should we return a a nested brace structure, to allow paredit-like actions of jump *out* of the current brace pair? +* Should we return a nested brace structure, to allow paredit-like actions of jump *out* of the current brace pair? This is how `SelectionRange` request works. * Alternatively, should we perhaps flag certain `SelectionRange`s as being brace pairs? @@ -511,7 +511,7 @@ Expands macro call at a given position. This request is sent from client to server to render "inlay hints" -- virtual text inserted into editor to show things like inferred types. Generally, the client should re-query inlay hints after every modification. Note that we plan to move this request to `experimental/inlayHints`, as it is not really Rust-specific, but the current API is not necessary the right one. -Upstream issue: https://github.com/microsoft/language-server-protocol/issues/956 +Upstream issues: https://github.com/microsoft/language-server-protocol/issues/956 , https://github.com/rust-analyzer/rust-analyzer/issues/2797 **Request:** diff --git a/docs/dev/style.md b/docs/dev/style.md index 48ce4b92a6e..468dedff20d 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md @@ -53,9 +53,9 @@ https://www.tedinski.com/2018/02/06/system-boundaries.html ## Crates.io Dependencies We try to be very conservative with usage of crates.io dependencies. -Don't use small "helper" crates (exception: `itertools` is allowed). +Don't use small "helper" crates (exception: `itertools` and `either` are allowed). If there's some general reusable bit of code you need, consider adding it to the `stdx` crate. -A useful exercise is to read Cargo.lock and see if some of the *transitive* dependencies do not make sense for rust-analyzer. +A useful exercise is to read Cargo.lock and see if some *transitive* dependencies do not make sense for rust-analyzer. **Rationale:** keep compile times low, create ecosystem pressure for faster compiles, reduce the number of things which might break. @@ -330,7 +330,7 @@ When implementing `do_thing`, it might be very useful to create a context object ```rust pub fn do_thing(arg1: Arg1, arg2: Arg2) -> Res { - let mut ctx = Ctx { arg1, arg2 } + let mut ctx = Ctx { arg1, arg2 }; ctx.run() } @@ -586,7 +586,7 @@ use super::{} **Rationale:** consistency. Reading order is important for new contributors. -Grouping by crate allows to spot unwanted dependencies easier. +Grouping by crate allows spotting unwanted dependencies easier. ## Import Style @@ -779,7 +779,7 @@ assert!(x < y); assert!(x > 0); // BAD -assert!(x >= lo && x <= hi>); +assert!(x >= lo && x <= hi); assert!(r1 < l2 || l1 > r2); assert!(y > x); assert!(0 > x); diff --git a/docs/dev/syntax.md b/docs/dev/syntax.md index 737cc7a7297..f7a0c09fc1e 100644 --- a/docs/dev/syntax.md +++ b/docs/dev/syntax.md @@ -145,7 +145,7 @@ Another alternative (used by swift and roslyn) is to explicitly divide the set o ```rust struct Token { - kind: NonTriviaTokenKind + kind: NonTriviaTokenKind, text: String, leading_trivia: Vec, trailing_trivia: Vec, @@ -240,7 +240,7 @@ impl SyntaxNode { let child_offset = offset; offset += green_child.text_len; Arc::new(SyntaxData { - offset: child_offset; + offset: child_offset, parent: Some(Arc::clone(self)), green: Arc::clone(green_child), }) @@ -249,7 +249,7 @@ impl SyntaxNode { } impl PartialEq for SyntaxNode { - fn eq(&self, other: &SyntaxNode) { + fn eq(&self, other: &SyntaxNode) -> bool { self.offset == other.offset && Arc::ptr_eq(&self.green, &other.green) } @@ -273,7 +273,7 @@ This is OK because trees traversals mostly (always, in case of rust-analyzer) ru The other thread can restore the `SyntaxNode` by traversing from the root green node and looking for a node with specified range. You can also use the similar trick to store a `SyntaxNode`. That is, a data structure that holds a `(GreenNode, Range)` will be `Sync`. -However rust-analyzer goes even further. +However, rust-analyzer goes even further. It treats trees as semi-transient and instead of storing a `GreenNode`, it generally stores just the id of the file from which the tree originated: `(FileId, Range)`. The `SyntaxNode` is the restored by reparsing the file and traversing it from root. With this trick, rust-analyzer holds only a small amount of trees in memory at the same time, which reduces memory usage.