Merge pull request #18604 from ChayimFriedman2/complete-helpers

feat: Complete derive helper attributes
This commit is contained in:
Lukas Wirth 2024-12-04 06:33:29 +00:00 committed by GitHub
commit 99c9a9942a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 111 additions and 4 deletions

View file

@ -86,10 +86,21 @@ pub(crate) fn complete_attribute_path(
acc: &mut Completions,
ctx: &CompletionContext<'_>,
path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
&AttrCtx { kind, annotated_item_kind }: &AttrCtx,
&AttrCtx { kind, annotated_item_kind, ref derive_helpers }: &AttrCtx,
) {
let is_inner = kind == AttrKind::Inner;
for (derive_helper, derive_name) in derive_helpers {
let mut item = CompletionItem::new(
SymbolKind::Attribute,
ctx.source_range(),
derive_helper.as_str(),
ctx.edition,
);
item.detail(format!("derive helper of `{derive_name}`"));
item.add_to(acc, ctx.db);
}
match qualified {
Qualified::With {
resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),

View file

@ -7,8 +7,8 @@ mod tests;
use std::{iter, ops::ControlFlow};
use hir::{
HasAttrs, Local, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type,
TypeInfo,
HasAttrs, Local, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope,
Symbol, Type, TypeInfo,
};
use ide_db::{
base_db::SourceDatabase, famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition,
@ -133,6 +133,7 @@ pub(crate) type ExistingDerives = FxHashSet<hir::Macro>;
pub(crate) struct AttrCtx {
pub(crate) kind: AttrKind,
pub(crate) annotated_item_kind: Option<SyntaxKind>,
pub(crate) derive_helpers: Vec<(Symbol, Symbol)>,
}
#[derive(Debug, PartialEq, Eq)]

View file

@ -1129,7 +1129,22 @@ fn classify_name_ref(
let is_trailing_outer_attr = kind != AttrKind::Inner
&& non_trivia_sibling(attr.syntax().clone().into(), syntax::Direction::Next).is_none();
let annotated_item_kind = if is_trailing_outer_attr { None } else { Some(attached.kind()) };
Some(PathKind::Attr { attr_ctx: AttrCtx { kind, annotated_item_kind } })
let derive_helpers = annotated_item_kind
.filter(|kind| {
matches!(
kind,
SyntaxKind::STRUCT
| SyntaxKind::ENUM
| SyntaxKind::UNION
| SyntaxKind::VARIANT
| SyntaxKind::TUPLE_FIELD
| SyntaxKind::RECORD_FIELD
)
})
.and_then(|_| nameref.as_ref()?.syntax().ancestors().find_map(ast::Adt::cast))
.and_then(|adt| sema.derive_helpers_in_scope(&adt))
.unwrap_or_default();
Some(PathKind::Attr { attr_ctx: AttrCtx { kind, annotated_item_kind, derive_helpers } })
};
// Infer the path kind

View file

@ -8,6 +8,70 @@ fn check(ra_fixture: &str, expect: Expect) {
expect.assert_eq(&actual);
}
#[test]
fn derive_helpers() {
check(
r#"
//- /mac.rs crate:mac
#![crate_type = "proc-macro"]
#[proc_macro_derive(MyDerive, attributes(my_cool_helper_attribute))]
pub fn my_derive() {}
//- /lib.rs crate:lib deps:mac
#[rustc_builtin_macro]
pub macro derive($item:item) {}
#[derive(mac::MyDerive)]
pub struct Foo(#[m$0] i32);
"#,
expect![[r#"
at allow()
at automatically_derived
at cfg()
at cfg_attr()
at cold
at deny()
at deprecated
at derive macro derive
at derive()
at doc = ""
at doc(alias = "")
at doc(hidden)
at expect()
at export_name = ""
at forbid()
at global_allocator
at ignore = ""
at inline
at link
at link_name = ""
at link_section = ""
at macro_export
at macro_use
at must_use
at my_cool_helper_attribute derive helper of `MyDerive`
at no_mangle
at non_exhaustive
at panic_handler
at path = ""
at proc_macro
at proc_macro_attribute
at proc_macro_derive()
at repr()
at should_panic
at target_feature(enable = "")
at test
at track_caller
at used
at warn()
md mac
kw crate::
kw self::
"#]],
)
}
#[test]
fn proc_macros() {
check(