6238: Split punctuation semantic highlighting up into more tags r=matklad a=Veykril
Open question would be the name of the delimiter modifiers. I chose them this was as I see them this way but from what I remember people tend to mix the names however they like. So maybe using `delimSquare`, `delimCurly`, `delimRound` would be better. That would also go well with `angle` becoming `delimAngle`?
Closes#6152
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
6980: Implement to support intra-doc link r=matklad a=sasurau4
Helps with #6168
This PR is very limited implementation to support intra-doc. It only support links indicate same file function.
I want someone to feedback me about this implementation. If the approach is good, I will continue this PR to support other symbols like enum and struct.
Co-authored-by: Daiki Ihara <sasurau4@gmail.com>
7224: Remove unnecessary allocation when checking whether to hide argument name hint r=jhpratt a=jhpratt
The case-insensitive prefix/suffix check can be performed
character-by-character. This allows the check to be done without having
to allocate a new string. As a side effect, it's also no longer
necessary to convert the entire string to lowercase, as it's done as
needed. As the only case equality we're handling is ASCII, this
operation can be further optimized by using byte equality, rather than
character equality.
cc @SomeoneToIgnore, as it's an update on my PR from yesterday.
Co-authored-by: Jacob Pratt <jacob@jhpratt.dev>
The case-insensitive prefix/suffix check can be performed
character-by-character. This allows the check to be done without having
to allocate a new string. As a side effect, it's also no longer
necessary to convert the entire string to lowercase, as it's done as
needed. As the only case equality we're handling is ASCII, this
operation can be further optimized by using byte equality, rather than
character equality.
7145: Proper handling $crate Take 2 [DO NOT MERGE] r=edwin0cheng a=edwin0cheng
Similar to previous PR (#7133) , but improved the following things :
1. Instead of storing the whole `ExpansionInfo`, we store a similar but stripped version `HygieneInfo`.
2. Instread of storing the `SyntaxNode` (because every token we are interested are IDENT), we store the `TextRange` only.
3. Because of 2, we now can put it in Salsa.
4. And most important improvement: Instead of computing the whole frames every single time, we compute it recursively through salsa: (Such that in the best scenario, we only need to compute the first layer of frame)
```rust
let def_site = db.hygiene_frame(info.def.file_id);
let call_site = db.hygiene_frame(info.arg.file_id);
HygieneFrame { expansion: Some(info), local_inner, krate, call_site, def_site }
```
The overall speed compared to previous PR is much faster (65s vs 45s) :
```
[WITH old PR]
Database loaded 644.86ms, 284mi
Crates in this dir: 36
Total modules found: 576
Total declarations: 11153
Total functions: 8715
Item Collection: 15.78s, 91562mi
Total expressions: 240721
Expressions of unknown type: 2635 (1%)
Expressions of partially unknown type: 2064 (0%)
Type mismatches: 865
Inference: 49.84s, 250747mi
Total: 65.62s, 342310mi
rust-analyzer -q analysis-stats . 66.72s user 0.57s system 99% cpu 1:07.40 total
[WITH this PR]
Database loaded 665.83ms, 284mi
Crates in this dir: 36
Total modules found: 577
Total declarations: 11188
Total functions: 8743
Item Collection: 15.28s, 84919mi
Total expressions: 241229
Expressions of unknown type: 2637 (1%)
Expressions of partially unknown type: 2064 (0%)
Type mismatches: 868
Inference: 30.15s, 135293mi
Total: 45.43s, 220213mi
rust-analyzer -q analysis-stats . 46.26s user 0.74s system 99% cpu 47.294 total
```
*HOWEVER*, it is still a perf regression (35s vs 45s):
```
[WITHOUT this PR]
Database loaded 657.42ms, 284mi
Crates in this dir: 36
Total modules found: 577
Total declarations: 11177
Total functions: 8735
Item Collection: 12.87s, 72407mi
Total expressions: 239380
Expressions of unknown type: 2643 (1%)
Expressions of partially unknown type: 2064 (0%)
Type mismatches: 868
Inference: 22.88s, 97889mi
Total: 35.74s, 170297mi
rust-analyzer -q analysis-stats . 36.71s user 0.63s system 99% cpu 37.498 total
```
Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This leaks a lot of LSP details into ide layer, which we want to avoid:
c9cec381bc/docs/dev (lsp-independence)
Additionally, all what this infra does is providing a toggle for
auto-import completion, but we already have one!
7181: Document project_model::PackageData and project_model::TargetData r=arnaudgolfouse a=arnaudgolfouse
This PR adds some documentation for the `project_model` crate.
Some of the field descriptions were taken directly from their `cargo_metadata` counterpart :
- `PackageData` -> `cargo_metadata::Package`
- `TargetData` -> `cargo_metadata::Target`
Co-authored-by: Arnaud <arnaud.golfouse@free.fr>
Rather than eagerly converting JSON, we losslessly keep it as is, and
change the shape of user-submitted data at the last moment.
This also allows us to remove a bunch of wrong Defaults
7176: Attribute completion r=matklad a=FlowerBOII
Solve #7167.
I removed the optional args for the attributes ```deprecated```, ```must_use``` and ```should_panic```.
I also updated their respective tests.
Please let me know if I missed something.
Co-authored-by: FlowerBOII <42295129+FlowerBOII@users.noreply.github.com>
7140: Store trait associated items in fst r=matklad a=SomeoneToIgnore
Store imported traits' associated function/methods and constants into `ImportMap.fst` and pefrorm the imports search on them.
This is a first step towards trait autoimport during completion functionality, the way I see it, after this PR, only a few major things are left to be done:
* store all traits' assoc items into fst, not only the ones in scope, as we do now. Any code pointers on how to do this are welcome 😄
* adjust a few modules in completions crate (`dot.rs`, `qualified_path.rs` at least) to query the import map, reusing the `import_assets` logic heavily
==
With the current import and autoimport implementations, it looks like for a single query, we're either interested in either associated items lookup or in all other `fst` contents lookup, but never both simultaneously.
I would rather not split `fst` in two but add another `Query` parameter to separate those, but let me know if you have any ideas.
Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
7131: Created an assist for inlining a function's body into its caller r=matklad a=Michael-F-Bryan
This introduces an `inline_function` assist which will convert code like this:
```rust
fn add(a: u32, b: u32) -> u32 { a + b }
fn main() {
let x = add<|>(1, 2);
}
```
Into something like this:
```rust
fn add(a: u32, b: u32) -> u32 { a + b }
fn main() {
let x = {
let a = 1;
let b = 2;
a + b
};
}
```
Fixes#6863.
Co-authored-by: Michael-F-Bryan <michaelfbryan@gmail.com>
7162: Introduce queries to avoid problems when performing completion for enums with many variants r=matklad a=danielframpton
This change introduces two new queries to compute:
1) attributes for all variants of an enum, and
2) attributes for all fields of a variant.
The purpose of this change is to avoid the current n^2 behavior when rendering completion for variants (which prevents completion for enums with large numbers of variants).
Co-authored-by: Daniel Frampton <Daniel.Frampton@microsoft.com>
1) the set of attributes for all variants of an enum, and
2) the set of attributes for all fields of a variant.
This avoids the current n^2 behavior when rendering completion for variants, which
prevents completion for enums with large numbers of variants.
7160: Get `hir::Function` return type r=flodiebold a=arnaudgolfouse
Hello !
As said in #7158, I noticed that `hir::Function` has no direct way of getting the return type, so this PR adds this functionality.
Co-authored-by: Arnaud <arnaud.golfouse@free.fr>
7147: ssr: Allow replacing expressions with statements r=davidlattimore a=MarijnS95
Depends on #6587
Until that is merged, the diff is https://github.com/MarijnS95/rust-analyzer/compare/stmt..replace-expr-with-stmt
---
Now that statements can be matched and replaced (#6587) some usecases require expressions to be replaced with statements as well. This happens when something that can ambiguously be an expression or statement like `if` and loop blocks appear in the last position of a block, as trailing expression. In this case a replacement pattern of the form `if foo(){$a();}==>>$a();` will only substitute `if` blocks in the list of statements but not if they (implicitly) end up in the trailing expression, where they are not wrapped by an EXPR_STMT (but the pattern and template are, as parsing only succeeds for the `stmt ==>> stmt` case).
Instead of adding two rules that match an expression - and emit duplicate matching errors - allow the template for expressions to be a statement if it fails to parse as an expression.
---
Another gross change that does not seem to break any tests currently, but perhaps a safeguard should be added to only allow this kind of replacement in blocks by "pushing" the replacement template to the statement list and clearing the trailing expression?
CC @davidlattimore
Co-authored-by: Marijn Suijten <marijn@traverseresearch.nl>
This is done by adding a `ret_type` method to `hir::Function`.
I followed `assoc_fn_params` convention by creating a new `RetType` type,
that contains the actual return type accessible via a `ty` method.
6587: SSR: Support statement matching and replacing r=davidlattimore a=MarijnS95
For #3186
Hi!
This is a smaller initial patchset that came up while working on support for statement lists (and my first time working on RA 😁). It has me stuck on trailing semicolons for which I hope to receive some feedback. Matching (and replacing) `let` bindings with a trailing semicolon works fine, but trying to omit these (to make patterns more ergonomic) turns out more complex than expected.
The "optional trailing semicolon solution" implemented in this PR is ugly because `Matcher::attempt_match_token` should only consume a trailing `;` when parsing `let` bindings to prevent other code from breaking. That at the same time has a nasty side-effect of `;` ending up in the matched code: any replacements on that should include the trailing semicolon as well even if it was not in the pattern. A better example is in the tests:
3ae1649c24/crates/ssr/src/tests.rs (L178-L184)
The end result to achieve is (I guess) allowing replacement of let bindings without trailing semicolon like `let x = $a ==>> let x = 1` (but including them on both sides is still fine), and should make replacement in a macro call (where `foo!(let a = 2;)` for a `$x:stmt` is invalid syntax) possible as well. That should allow to enable/fix these tests:
3ae1649c24/crates/ssr/src/tests.rs (L201-L214)
A possible MVP of this PR might be to drop this optional `;' handling entirely and only allow an SSR pattern/template with semicolons on either side.
Co-authored-by: Marijn Suijten <marijn@traverseresearch.nl>
Now that statements can be matched and replaced (#6587) some usecases
require expressions to be replaced with statements as well. This happens
when something that can ambiguously be an expression or statement like
`if` and loop blocks appear in the last position of a block, as trailing
expression. In this case a replacement pattern of the form `if
foo(){$a();}==>>$a();` will only substitute `if` blocks in the list of
statements but not if they (implicitly) end up in the trailing
expression, where they are not wrapped by an EXPR_STMT (but the pattern
and template are, as parsing only succeeds for the `stmt ==>> stmt`
case).
Instead of adding two rules that match an expression - and emit
duplicate matching errors - allow the template for expressions to be a
statement if it fails to parse as an expression.
7068: Add VSCode command to view the hir of a function body r=theotherphil a=theotherphil
Will fix https://github.com/rust-analyzer/rust-analyzer/issues/7061. Very rough initial version just to work out where I needed to wire everything up.
@matklad would you be happy merging a hir visualiser of some kind? If so, do you have any thoughts on what you'd like it show, and how?
I've spent very little time on this thus far, so I'm fine with throwing away the contents of this PR, but I want to avoid taking the time to make this more polished/interactive/useful only to discover that no-one else has any interest in this functionality.
![image](https://user-images.githubusercontent.com/1974256/103236081-bb58f700-493b-11eb-9d12-55ae1b870f8f.png)
Co-authored-by: Phil Ellison <phil.j.ellison@gmail.com>
7115: Migrate HasSource::source to return Option r=matklad a=nick96
I've made a start on fixing #6913 based on the provided work plan, migrating `HasSource::source` to return an `Option`. The simple cases are migrated but there are a few that I'm unsure exactly how they should be handled:
- Logging the processing of functions in `AnalysisStatsCmd::run`: In verbose mode it includes the path to the module containing the function and the syntax range. I've handled this with an if-let but would it be better to blow up here with `expect`? I'm not 100% on the code paths but if we're processing a function definition then the source should exist.
I've handled `source()` in all code paths as `None` being a valid return value but are there some cases where we should just blow up? Also, all I've done is bubble up the returned `None`s, there may be some places where we can recover and still provide something.
Co-authored-by: Nick Spain <nicholas.spain@stileeducation.com>
Co-authored-by: Nick Spain <nicholas.spain96@gmail.com>
7133: Proper handling $crate and local_inner_macros r=jonas-schievink a=edwin0cheng
This PR introduces `HygineFrames` to store the macro definition/call site hierarchy in hyginee and when resolving `local_inner_macros` and `$crate`, we use the token to look up the corresponding frame and return the correct value.
See also: https://rustc-dev-guide.rust-lang.org/macro-expansion.html#hygiene-and-hierarchies
fixe #6890 and #6788
r? @jonas-schievink
Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>