diff options
-rw-r--r-- | crates/assists/src/ast_transform.rs | 28 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 19 |
2 files changed, 47 insertions, 0 deletions
diff --git a/crates/assists/src/ast_transform.rs b/crates/assists/src/ast_transform.rs index bbcd2d488..835da3bb2 100644 --- a/crates/assists/src/ast_transform.rs +++ b/crates/assists/src/ast_transform.rs | |||
@@ -18,6 +18,34 @@ pub fn apply<'a, N: AstNode>(transformer: &dyn AstTransform<'a>, node: N) -> N { | |||
18 | .rewrite_ast(&node) | 18 | .rewrite_ast(&node) |
19 | } | 19 | } |
20 | 20 | ||
21 | /// `AstTransform` helps with applying bulk transformations to syntax nodes. | ||
22 | /// | ||
23 | /// This is mostly useful for IDE code generation. If you paste some existing | ||
24 | /// code into a new context (for example, to add method overrides to an `impl` | ||
25 | /// block), you generally want to appropriately qualify the names, and sometimes | ||
26 | /// you might want to substitute generic parameters as well: | ||
27 | /// | ||
28 | /// ``` | ||
29 | /// mod x { | ||
30 | /// pub struct A; | ||
31 | /// pub trait T<U> { fn foo(&self, _: U) -> A; } | ||
32 | /// } | ||
33 | /// | ||
34 | /// mod y { | ||
35 | /// use x::T; | ||
36 | /// | ||
37 | /// impl T<()> for () { | ||
38 | /// // If we invoke **Add Missing Members** here, we want to copy-paste `foo`. | ||
39 | /// // But we want a slightly-modified version of it: | ||
40 | /// fn foo(&self, _: ()) -> x::A {} | ||
41 | /// } | ||
42 | /// } | ||
43 | /// ``` | ||
44 | /// | ||
45 | /// So, a single `AstTransform` describes such function from `SyntaxNode` to | ||
46 | /// `SyntaxNode`. Note that the API here is a bit too high-order and high-brow. | ||
47 | /// We'd want to somehow express this concept simpler, but so far nobody got to | ||
48 | /// simplifying this! | ||
21 | pub trait AstTransform<'a> { | 49 | pub trait AstTransform<'a> { |
22 | fn get_substitution(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode>; | 50 | fn get_substitution(&self, node: &syntax::SyntaxNode) -> Option<syntax::SyntaxNode>; |
23 | 51 | ||
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 0516a05b4..c61a430e1 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -697,6 +697,25 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode { | |||
697 | node.ancestors().last().unwrap() | 697 | node.ancestors().last().unwrap() |
698 | } | 698 | } |
699 | 699 | ||
700 | /// `SemanticScope` encapsulates the notion of a scope (the set of visible | ||
701 | /// names) at a particular program point. | ||
702 | /// | ||
703 | /// It is a bit tricky, as scopes do not really exist inside the compiler. | ||
704 | /// Rather, the compiler directly computes for each reference the definition it | ||
705 | /// refers to. It might transiently compute the explicit scope map while doing | ||
706 | /// so, but, generally, this is not something left after the analysis. | ||
707 | /// | ||
708 | /// However, we do very much need explicit scopes for IDE purposes -- | ||
709 | /// completion, at its core, lists the contents of the current scope. The notion | ||
710 | /// of scope is also useful to answer questions like "what would be the meaning | ||
711 | /// of this piece of code if we inserted it into this position?". | ||
712 | /// | ||
713 | /// So `SemanticsScope` is constructed from a specific program point (a syntax | ||
714 | /// node or just a raw offset) and provides access to the set of visible names | ||
715 | /// on a somewhat best-effort basis. | ||
716 | /// | ||
717 | /// Note that if you are wondering "what does this specific existing name mean?", | ||
718 | /// you'd better use the `resolve_` family of methods. | ||
700 | #[derive(Debug)] | 719 | #[derive(Debug)] |
701 | pub struct SemanticsScope<'a> { | 720 | pub struct SemanticsScope<'a> { |
702 | pub db: &'a dyn HirDatabase, | 721 | pub db: &'a dyn HirDatabase, |