diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 3d346b60ab..2e8342e4e0 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(&self, def: Def) -> Option> + 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(&self, def: Def) -> Option> + 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 509758a582..d070eefd9c 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 19abb129ef..1062cc3953 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 9e22dae072..31accd035f 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 b47912d07d..1148c6c35c 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, Item: Display, Item<'a> = Item>>(printables: T) {} - IDENT if [T![<], T![=], T![:]].contains(&p.nth(1)) => { + + // test macro_inside_generic_arg + // type A = Foo; + 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 0000000000..37306ba6ac --- /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 0000000000..8d43a53d97 --- /dev/null +++ b/crates/syntax/test_data/parser/inline/ok/0194_macro_inside_generic_arg.rs @@ -0,0 +1 @@ +type A = Foo;