Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix case where completion inside macro that expands to #[test] was unavailable #18853

Merged
merged 1 commit into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/hir-def/src/nameres/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,7 @@ impl DefCollector<'_> {
// being cfg'ed out).
// Ideally we will just expand them to nothing here. But we are only collecting macro calls,
// not expanding them, so we have no way to do that.
// If you add an ignored attribute here, also add it to `Semantics::might_be_inside_macro_call()`.
if matches!(
def.kind,
MacroDefKind::BuiltInAttr(_, expander)
Expand Down
37 changes: 32 additions & 5 deletions crates/hir/src/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use hir_expand::{
name::AsName,
ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt,
};
use intern::Symbol;
use intern::{sym, Symbol};
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::{smallvec, SmallVec};
Expand Down Expand Up @@ -811,10 +811,37 @@ impl<'db> SemanticsImpl<'db> {
item.attrs().any(|attr| {
let Some(meta) = attr.meta() else { return false };
let Some(path) = meta.path() else { return false };
let Some(attr_name) = path.as_single_name_ref() else { return true };
let attr_name = attr_name.text();
let attr_name = attr_name.as_str();
attr_name == "derive" || find_builtin_attr_idx(&Symbol::intern(attr_name)).is_none()
if let Some(attr_name) = path.as_single_name_ref() {
let attr_name = attr_name.text();
let attr_name = Symbol::intern(attr_name.as_str());
if attr_name == sym::derive {
return true;
}
// We ignore `#[test]` and friends in the def map, so we cannot expand them.
// FIXME: We match by text. This is both hacky and incorrect (people can, and do, create
// other macros named `test`). We cannot fix that unfortunately because we use this method
// for speculative expansion in completion, which we cannot analyze. Fortunately, most macros
// named `test` are test-like, meaning their expansion is not terribly important for IDE.
if attr_name == sym::test
|| attr_name == sym::bench
|| attr_name == sym::test_case
|| find_builtin_attr_idx(&attr_name).is_some()
{
return false;
}
}
let mut segments = path.segments();
let mut next_segment_text = || segments.next().and_then(|it| it.name_ref());
// `#[core::prelude::rust_2024::test]` or `#[std::prelude::rust_2024::test]`.
if next_segment_text().is_some_and(|it| matches!(&*it.text(), "core" | "std"))
&& next_segment_text().is_some_and(|it| it.text() == "prelude")
&& next_segment_text().is_some()
&& next_segment_text()
.is_some_and(|it| matches!(&*it.text(), "test" | "bench" | "test_case"))
{
return false;
}
true
})
})
}
Expand Down
72 changes: 72 additions & 0 deletions crates/ide-completion/src/tests/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,75 @@ impl Copy for S where $0
"#,
);
}

#[test]
fn test_is_not_considered_macro() {
check(
r#"
#[rustc_builtin]
pub macro test($item:item) {
/* compiler built-in */
}

macro_rules! expand_to_test {
( $i:ident ) => {
#[test]
fn foo() { $i; }
};
}

fn bar() {
let value = 5;
expand_to_test!(v$0);
}
"#,
expect![[r#"
ct CONST Unit
en Enum Enum
fn bar() fn()
fn foo() fn()
fn function() fn()
ma expand_to_test!(…) macro_rules! expand_to_test
ma makro!(…) macro_rules! makro
ma test!(…) macro test
md module
sc STATIC Unit
st Record Record
st Tuple Tuple
st Unit Unit
un Union Union
ev TupleV(…) TupleV(u32)
bt u32 u32
kw async
kw const
kw crate::
kw enum
kw extern
kw false
kw fn
kw for
kw if
kw if let
kw impl
kw let
kw loop
kw match
kw mod
kw return
kw self::
kw static
kw struct
kw trait
kw true
kw type
kw union
kw unsafe
kw use
kw while
kw while let
sn macro_rules
sn pd
sn ppd
"#]],
);
}
Loading