mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
source map pattern
This commit is contained in:
parent
c00059c822
commit
43e7d80ec4
1 changed files with 57 additions and 0 deletions
57
guide.md
57
guide.md
|
@ -426,8 +426,65 @@ actually written by the user.
|
||||||
|
|
||||||
[`HirFileId`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L18-L125
|
[`HirFileId`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/ids.rs#L18-L125
|
||||||
|
|
||||||
|
Now that we understand how to identify a definition, in a source or in a
|
||||||
|
macro-generated file, we can discuss name resolution a bit.
|
||||||
|
|
||||||
## Name resolution
|
## Name resolution
|
||||||
|
|
||||||
|
Name resolution faces the same problem as the module tree: if we look at the
|
||||||
|
syntax tree directly, we'll have to recompute name resolution after every
|
||||||
|
modification. The solution to the problem is the same: we [lower] source code of
|
||||||
|
each module into a position-independent representation which does not change if
|
||||||
|
we modify bodies of the items. After that we [loop] resolving all imports until
|
||||||
|
we've reached a fixed point.
|
||||||
|
|
||||||
|
[lower]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L113-L117
|
||||||
|
[loop]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L113-L117
|
||||||
|
|
||||||
|
And, given all our preparation with ids and position-independent representation,
|
||||||
|
it is satisfying to [test] that typing inside function body does not invalidate
|
||||||
|
name resolution results.
|
||||||
|
|
||||||
|
[test]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/tests.rs#L376
|
||||||
|
|
||||||
|
An interesting fact about name resolution is that it "erases" all of
|
||||||
|
intermediate paths from the imports: in the end, we know which items are defined
|
||||||
|
and which items are imported in each module, but, if the import was `use
|
||||||
|
foo::bar::baz`, we deliberately forget what modules `foo` and `bar` resolve to.
|
||||||
|
|
||||||
|
To serve "goto definition" requests on intermediate segments we need this info
|
||||||
|
in IDE. Luckily, we need it only for a tiny fraction of imports, so we just ask
|
||||||
|
the module explicitly, "where does `foo::bar` path resolve to?". This is a
|
||||||
|
general pattern: we try to compute the minimal possible amount of information
|
||||||
|
during analysis while allowing IDE to ask for additional specific bits.
|
||||||
|
|
||||||
|
Name resolution is also a good place to introduce another salsa pattern used
|
||||||
|
throughout the analyzer:
|
||||||
|
|
||||||
## Source Map pattern
|
## Source Map pattern
|
||||||
|
|
||||||
|
Due to an obscure edge case in completion, IDE needs to know the syntax node of
|
||||||
|
an use statement which imported the given completion candidate. We can't just
|
||||||
|
store the syntax node as a part of name resolution: this will break
|
||||||
|
incrementality, due to the fact that syntax changes after every file
|
||||||
|
modification.
|
||||||
|
|
||||||
|
We solve this problem during the lowering step of name resolution. Lowering
|
||||||
|
query actually produces a *pair* of outputs: `LoweredModule` and [`SourceMap`].
|
||||||
|
`LoweredModule` module contains [imports], but in a position-independent form.
|
||||||
|
The `SourceMap` contains a mapping from position-independent imports to
|
||||||
|
(position-dependent) syntax nodes.
|
||||||
|
|
||||||
|
The result of this basic lowering query changes after every modification. But
|
||||||
|
there's an intermediate [projection query] which returns only the first
|
||||||
|
position-independent part of the lowering. The result of this query is stable.
|
||||||
|
Naturally, name resolution [uses] this stable projection query.
|
||||||
|
|
||||||
|
[imports]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59
|
||||||
|
[`SourceMap`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L52-L59
|
||||||
|
[projection query]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/nameres/lower.rs#L97-L103
|
||||||
|
[uses]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_hir/src/query_definitions.rs#L49
|
||||||
|
|
||||||
|
## Type inference
|
||||||
|
|
||||||
## Tying it all together: completion
|
## Tying it all together: completion
|
||||||
|
|
Loading…
Reference in a new issue