mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-11 20:58:54 +00:00
Merge pull request #18853 from ChayimFriedman2/no-completion
Fix case where completion inside macro that expands to `#[test]` was unavailable
This commit is contained in:
commit
cd12ef8547
3 changed files with 105 additions and 5 deletions
|
@ -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)
|
||||
|
|
|
@ -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};
|
||||
|
@ -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
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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…
Reference in a new issue