about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/semantics.rs23
-rw-r--r--crates/ide_assists/src/handlers/inline_call.rs4
-rw-r--r--crates/ide_assists/src/handlers/replace_let_with_if_let.rs2
-rw-r--r--crates/ide_completion/src/completions/trait_impl.rs2
-rw-r--r--crates/parser/src/grammar/generic_args.rs5
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rast36
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rs1
7 files changed, 65 insertions, 8 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 3d346b60ab4..2e8342e4e01 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -25,9 +25,9 @@ use crate::{
     db::HirDatabase,
     semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
     source_analyzer::{resolve_hir_path, SourceAnalyzer},
-    Access, AssocItem, Callable, ConstParam, Crate, Field, Function, HirFileId, Impl, InFile,
-    Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type,
-    TypeAlias, TypeParam, VariantDef,
+    Access, AssocItem, Callable, ConstParam, Crate, Field, Function, HasSource, HirFileId, Impl,
+    InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait,
+    Type, TypeAlias, TypeParam, VariantDef,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -190,6 +190,14 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.descend_node_into_attributes(node)
     }
 
+    /// Search for a definition's source and cache its syntax tree
+    pub fn source<Def: HasSource>(&self, def: Def) -> Option<InFile<Def::Ast>>
+    where
+        Def::Ast: AstNode,
+    {
+        self.imp.source(def)
+    }
+
     pub fn hir_file_for(&self, syntax_node: &SyntaxNode) -> HirFileId {
         self.imp.find_file(syntax_node.clone()).file_id
     }
@@ -845,6 +853,15 @@ impl<'db> SemanticsImpl<'db> {
         SemanticsScope { db: self.db, file_id, resolver }
     }
 
+    fn source<Def: HasSource>(&self, def: Def) -> Option<InFile<Def::Ast>>
+    where
+        Def::Ast: AstNode,
+    {
+        let res = def.source(self.db)?;
+        self.cache(find_root(res.value.syntax()), res.file_id);
+        Some(res)
+    }
+
     fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer {
         self.analyze_impl(node, None)
     }
diff --git a/crates/ide_assists/src/handlers/inline_call.rs b/crates/ide_assists/src/handlers/inline_call.rs
index 509758a5822..d070eefd9c6 100644
--- a/crates/ide_assists/src/handlers/inline_call.rs
+++ b/crates/ide_assists/src/handlers/inline_call.rs
@@ -1,6 +1,6 @@
 use ast::make;
 use either::Either;
-use hir::{db::HirDatabase, HasSource, PathResolution, Semantics, TypeInfo};
+use hir::{db::HirDatabase, PathResolution, Semantics, TypeInfo};
 use ide_db::{
     base_db::{FileId, FileRange},
     defs::Definition,
@@ -194,7 +194,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
         }
     };
 
-    let fn_source = function.source(ctx.db())?;
+    let fn_source = ctx.sema.source(function)?;
     let fn_body = fn_source.value.body()?;
     let param_list = fn_source.value.param_list()?;
 
diff --git a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
index 19abb129efc..1062cc39537 100644
--- a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
+++ b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs
@@ -38,7 +38,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
 // ```
 pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     let let_kw = ctx.find_token_syntax_at_offset(T![let])?;
-    let let_stmt = let_kw.ancestors().find_map(ast::LetStmt::cast)?;
+    let let_stmt = let_kw.parent().and_then(ast::LetStmt::cast)?;
     let init = let_stmt.initializer()?;
     let original_pat = let_stmt.pat()?;
 
diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs
index 9e22dae072c..31accd035f7 100644
--- a/crates/ide_completion/src/completions/trait_impl.rs
+++ b/crates/ide_completion/src/completions/trait_impl.rs
@@ -185,7 +185,7 @@ fn get_transformed_assoc_item(
     let assoc_item = assoc_item.clone_for_update();
     let trait_ = impl_def.trait_(ctx.db)?;
     let source_scope = &ctx.sema.scope_for_def(trait_);
-    let target_scope = &ctx.sema.scope(impl_def.source(ctx.db)?.syntax().value);
+    let target_scope = &ctx.sema.scope(ctx.sema.source(impl_def)?.syntax().value);
     let transform = PathTransform::trait_impl(
         target_scope,
         source_scope,
diff --git a/crates/parser/src/grammar/generic_args.rs b/crates/parser/src/grammar/generic_args.rs
index b47912d07d4..1148c6c35c5 100644
--- a/crates/parser/src/grammar/generic_args.rs
+++ b/crates/parser/src/grammar/generic_args.rs
@@ -32,7 +32,10 @@ fn generic_arg(p: &mut Parser) {
         k if k.is_literal() => const_arg(p),
         // test associated_type_bounds
         // fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {}
-        IDENT if [T![<], T![=], T![:]].contains(&p.nth(1)) => {
+
+        // test macro_inside_generic_arg
+        // type A = Foo<syn::Token![_]>;
+        IDENT if [T![<], T![=], T![:]].contains(&p.nth(1)) && !p.nth_at(1, T![::]) => {
             let m = p.start();
             name_ref(p);
             opt_generic_arg_list(p, false);
diff --git a/crates/syntax/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rast b/crates/syntax/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rast
new file mode 100644
index 00000000000..37306ba6ac0
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rast
@@ -0,0 +1,36 @@
+SOURCE_FILE@0..30
+  TYPE_ALIAS@0..29
+    TYPE_KW@0..4 "type"
+    WHITESPACE@4..5 " "
+    NAME@5..6
+      IDENT@5..6 "A"
+    WHITESPACE@6..7 " "
+    EQ@7..8 "="
+    WHITESPACE@8..9 " "
+    PATH_TYPE@9..28
+      PATH@9..28
+        PATH_SEGMENT@9..28
+          NAME_REF@9..12
+            IDENT@9..12 "Foo"
+          GENERIC_ARG_LIST@12..28
+            L_ANGLE@12..13 "<"
+            TYPE_ARG@13..27
+              MACRO_TYPE@13..27
+                MACRO_CALL@13..27
+                  PATH@13..23
+                    PATH@13..16
+                      PATH_SEGMENT@13..16
+                        NAME_REF@13..16
+                          IDENT@13..16 "syn"
+                    COLON2@16..18 "::"
+                    PATH_SEGMENT@18..23
+                      NAME_REF@18..23
+                        IDENT@18..23 "Token"
+                  BANG@23..24 "!"
+                  TOKEN_TREE@24..27
+                    L_BRACK@24..25 "["
+                    UNDERSCORE@25..26 "_"
+                    R_BRACK@26..27 "]"
+            R_ANGLE@27..28 ">"
+    SEMICOLON@28..29 ";"
+  WHITESPACE@29..30 "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rs b/crates/syntax/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rs
new file mode 100644
index 00000000000..8d43a53d97f
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rs
@@ -0,0 +1 @@
+type A = Foo<syn::Token![_]>;