FragmentKind played two roles:
* entry point to the parser
* syntactic category of a macro call
These are different use-cases, and warrant different types. For example,
macro can't expand to visibility, but we have such fragment today.
This PR introduces `ExpandsTo` enum to separate this two use-cases.
I suspect we might further split `FragmentKind` into `$x:specifier` enum
specific to MBE, and a general parser entry point, but that's for
another PR!
9970: feat: Implement attribute input token mapping, fix attribute item token mapping r=Veykril a=Veykril
![image](https://user-images.githubusercontent.com/3757771/130328577-4c1ad72c-51b1-47c3-8d3d-3242ec44a355.png)
The token mapping for items with attributes got overwritten partially by the attributes non-item input, since attributes have two different inputs, the item and the direct input both.
This PR gives attributes a second TokenMap for its direct input. We now shift all normal input IDs by the item input maximum(we maybe wanna swap this see below) similar to what we do for macro-rules/def. For mapping down we then have to figure out whether we are inside the direct attribute input or its item input to pick the appropriate mapping which can be done with some token range comparisons.
Fixes https://github.com/rust-analyzer/rust-analyzer/issues/9867
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
Today, rust-analyzer (and rustc, and bat, and IntelliJ) fail badly on
some kinds of maliciously constructed code, like a deep sequence of
nested parenthesis.
"Who writes 100k nested parenthesis" you'd ask?
Well, in a language with macros, a run-away macro expansion might do
that (see the added tests)! Such expansion can be broad, rather than
deep, so it bypasses recursion check at the macro-expansion layer, but
triggers deep recursion in parser.
In the ideal world, the parser would just handle deeply nested structs
gracefully. We'll get there some day, but at the moment, let's try to be
simple, and just avoid expanding macros with unbalanced parenthesis in
the first place.
closes#9358
We generally avoid "syntax only" helper wrappers, which don't do much:
they make code easier to write, but harder to read. They also make
investigations harder, as "find_usages" needs to be invoked both for the
wrapped and unwrapped APIs
9260: tree-wide: make rustdoc links spiky so they are clickable r=matklad a=lf-
Rustdoc was complaining about these while I was running with --document-private-items and I figure they should be fixed.
Co-authored-by: Jade <software@lfcode.ca>
The idea here is to eventually get rid of `dyn Diagnostic` and
`DiagnosticSink` infrastructure altogether, and just have a `enum
hir::Diagnostic` instead.
The problem with `dyn Diagnostic` is that it is defined in the lowest
level of the stack (hir_expand), but is used by the highest level (ide).
As a first step, we free hir_expand and hir_def from `dyn Diagnostic`
and kick the can up to `hir_ty`, as an intermediate state. The plan is
then to move DiagnosticSink similarly to the hir crate, and, as final
third step, remove its usage from the ide.
One currently unsolved problem is testing. You can notice that the test
which checks precise diagnostic ranges, unresolved_import_in_use_tree,
was moved to the ide layer. Logically, only IDE should have the infra to
render a specific range.
At the same time, the range is determined with the data produced in
hir_def and hir crates, so this layering is rather unfortunate. Working
on hir_def shouldn't require compiling `ide` for testing.
8776: fix: fix unnecessary recomputations due to macros r=jonas-schievink a=jonas-schievink
This computes a macro's fragment kind eagerly (when the calling file is still available in parsed form) and stores it in the `MacroCallLoc`. This means that during expansion we no longer have to reparse the file containing the macro call, avoiding the unnecessary salsa dependencies (https://github.com/rust-analyzer/rust-analyzer/pull/8746#issuecomment-834776349).
Marking as draft until I manage to find a test for this problem, since for some reason `typing_inside_a_function_should_not_invalidate_expansions` does not catch this (which might indicate that I misunderstand the problem).
I've manually confirmed that this fixes the issue described in https://github.com/rust-analyzer/rust-analyzer/pull/8746#issuecomment-834776349:
```
7ms - parse_query @ FileId(179)
12ms - SourceBinder::to_module_def
12ms - crate_def_map:wait
5ms - item_tree_query (1 calls)
7ms - ???
```
Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
8280: Borrow text of immutable syntax node r=iDawer a=iDawer
In https://github.com/rust-analyzer/rowan/pull/101 `rowan::SyntaxNode::green` returns `Cow<'_, GreenNodeData>`. It returns borrow of green node of immutable syntax tree node.
Using this we can return borrowed text from `ast::Name::text`.
~~However now it allocates in case of mutable syntax trees.~~ (see next comment)
The idea comes from https://github.com/rust-analyzer/rowan/pull/100#issuecomment-809330325
Co-authored-by: Dawer <7803845+iDawer@users.noreply.github.com>
8201: Fix recursive macro statements expansion r=edwin0cheng a=edwin0cheng
This PR attempts to properly handle macro statement expansion by implementing the following:
1. Merge macro expanded statements to parent scope statements.
2. Add a new hir `Expr::MacroStmts` for handle tail expression infer.
PS : The scope of macro expanded statements are so strange that it took more time than I thought to understand and implement it :(
Fixes #8171
Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
8134: Correct the paths of submodules from the include! macro r=edwin0cheng a=sticnarf
This PR should fix#7846. It mostly follows the instructions from @edwin0cheng in that issue.
Co-authored-by: Yilin Chen <sticnarf@gmail.com>
8063: couple clippy::complexity fixes r=matklad a=matthiaskrgr
avoid redundant `.into()` calls to convert T into identical T (`let x: String = String::from("hello").into();`)
use `if let Some(x)` instead of `.is_some()` + `.unwrap()`
don't clone Copy types
remove redundant wrapped ?s: `Some(Some(3)?)` can just be `Some(3)`
use `.map(|x| y)` instead of `and_then(|x| Some(y)` on `Option`s
Co-authored-by: Matthias Krüger <matthias.krueger@famsik.de>
use vec![] instead of Vec::new() + push()
avoid redundant clones
use chars instead of &str for single char patterns in ends_with() and starts_with()
allocate some Vecs with capacity to avoid unneccessary resizing
7994: Speed up mbe matching in heavy recursive cases r=edwin0cheng a=edwin0cheng
In some cases (e.g. #4186), mbe matching is very slow due to a lot of copy and allocation for bindings, this PR try to solve this problem by introduce a semi "link-list" approach for bindings building.
I used this [test case](https://github.com/weiznich/minimal_example_for_rust_81262) (for `features(32-column-tables)`) to run following command to benchmark:
```
time rust-analyzer analysis-stats --load-output-dirs ./
```
Before this PR : 2 mins
After this PR: 3 seconds.
However, for 64-column-tables cases, we still need 4 mins to complete.
I will try to investigate in the following weeks.
bors r+
Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
7359: ItemTree: store a mapping from blocks to inner items r=jonas-schievink a=jonas-schievink
To do name resolution within block expressions, we need to know which inner items are located inside each block expression. This adds such a mapping to `ItemTree`, replacing the previous one, which was seemingly unused other than to access all the inner items.
This also assigns `AstId`s to block expressions, which is needed to store the mapping in salsa.
Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>