Skip to content

Commit cd12ef8

Browse files
authored
Merge pull request #18853 from ChayimFriedman2/no-completion
Fix case where completion inside macro that expands to `#[test]` was unavailable
2 parents ccc7468 + b24142b commit cd12ef8

File tree

3 files changed

+105
-5
lines changed

3 files changed

+105
-5
lines changed

Diff for: crates/hir-def/src/nameres/collector.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,7 @@ impl DefCollector<'_> {
13161316
// being cfg'ed out).
13171317
// Ideally we will just expand them to nothing here. But we are only collecting macro calls,
13181318
// not expanding them, so we have no way to do that.
1319+
// If you add an ignored attribute here, also add it to `Semantics::might_be_inside_macro_call()`.
13191320
if matches!(
13201321
def.kind,
13211322
MacroDefKind::BuiltInAttr(_, expander)

Diff for: crates/hir/src/semantics.rs

+32-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use hir_expand::{
3030
name::AsName,
3131
ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt,
3232
};
33-
use intern::Symbol;
33+
use intern::{sym, Symbol};
3434
use itertools::Itertools;
3535
use rustc_hash::{FxHashMap, FxHashSet};
3636
use smallvec::{smallvec, SmallVec};
@@ -811,10 +811,37 @@ impl<'db> SemanticsImpl<'db> {
811811
item.attrs().any(|attr| {
812812
let Some(meta) = attr.meta() else { return false };
813813
let Some(path) = meta.path() else { return false };
814-
let Some(attr_name) = path.as_single_name_ref() else { return true };
815-
let attr_name = attr_name.text();
816-
let attr_name = attr_name.as_str();
817-
attr_name == "derive" || find_builtin_attr_idx(&Symbol::intern(attr_name)).is_none()
814+
if let Some(attr_name) = path.as_single_name_ref() {
815+
let attr_name = attr_name.text();
816+
let attr_name = Symbol::intern(attr_name.as_str());
817+
if attr_name == sym::derive {
818+
return true;
819+
}
820+
// We ignore `#[test]` and friends in the def map, so we cannot expand them.
821+
// FIXME: We match by text. This is both hacky and incorrect (people can, and do, create
822+
// other macros named `test`). We cannot fix that unfortunately because we use this method
823+
// for speculative expansion in completion, which we cannot analyze. Fortunately, most macros
824+
// named `test` are test-like, meaning their expansion is not terribly important for IDE.
825+
if attr_name == sym::test
826+
|| attr_name == sym::bench
827+
|| attr_name == sym::test_case
828+
|| find_builtin_attr_idx(&attr_name).is_some()
829+
{
830+
return false;
831+
}
832+
}
833+
let mut segments = path.segments();
834+
let mut next_segment_text = || segments.next().and_then(|it| it.name_ref());
835+
// `#[core::prelude::rust_2024::test]` or `#[std::prelude::rust_2024::test]`.
836+
if next_segment_text().is_some_and(|it| matches!(&*it.text(), "core" | "std"))
837+
&& next_segment_text().is_some_and(|it| it.text() == "prelude")
838+
&& next_segment_text().is_some()
839+
&& next_segment_text()
840+
.is_some_and(|it| matches!(&*it.text(), "test" | "bench" | "test_case"))
841+
{
842+
return false;
843+
}
844+
true
818845
})
819846
})
820847
}

Diff for: crates/ide-completion/src/tests/item.rs

+72
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,75 @@ impl Copy for S where $0
241241
"#,
242242
);
243243
}
244+
245+
#[test]
246+
fn test_is_not_considered_macro() {
247+
check(
248+
r#"
249+
#[rustc_builtin]
250+
pub macro test($item:item) {
251+
/* compiler built-in */
252+
}
253+
254+
macro_rules! expand_to_test {
255+
( $i:ident ) => {
256+
#[test]
257+
fn foo() { $i; }
258+
};
259+
}
260+
261+
fn bar() {
262+
let value = 5;
263+
expand_to_test!(v$0);
264+
}
265+
"#,
266+
expect![[r#"
267+
ct CONST Unit
268+
en Enum Enum
269+
fn bar() fn()
270+
fn foo() fn()
271+
fn function() fn()
272+
ma expand_to_test!(…) macro_rules! expand_to_test
273+
ma makro!(…) macro_rules! makro
274+
ma test!(…) macro test
275+
md module
276+
sc STATIC Unit
277+
st Record Record
278+
st Tuple Tuple
279+
st Unit Unit
280+
un Union Union
281+
ev TupleV(…) TupleV(u32)
282+
bt u32 u32
283+
kw async
284+
kw const
285+
kw crate::
286+
kw enum
287+
kw extern
288+
kw false
289+
kw fn
290+
kw for
291+
kw if
292+
kw if let
293+
kw impl
294+
kw let
295+
kw loop
296+
kw match
297+
kw mod
298+
kw return
299+
kw self::
300+
kw static
301+
kw struct
302+
kw trait
303+
kw true
304+
kw type
305+
kw union
306+
kw unsafe
307+
kw use
308+
kw while
309+
kw while let
310+
sn macro_rules
311+
sn pd
312+
sn ppd
313+
"#]],
314+
);
315+
}

0 commit comments

Comments
 (0)