Skip to content

Commit 2aa6483

Browse files
bors[bot]Brandon
andauthored
Merge #8183
8183: Fix missing command error with macros r=Veykril a=brandondong **Reproduction:** 1. Define a struct through a macro (can be via `macro_rules`, proc macro, or `include!()`). 2. !!MISSING: command!! annotation appears. Clicking on it results in an error message. No matter where the macro is called/defined, the annotation is always at the start of the file. ![image](https://user-images.githubusercontent.com/13722457/112268785-bce14500-8c34-11eb-9a23-bafd63ffd6ef.png) **Cause:** - For struct `A`, a `HasImpls` annotation is added just like for struct `B`. Unlike `B`, the file id for `A` is not the file we are adding annotations to but a macro file. - The resolving step of the code lens does not succeed. **Fix:** - Check that the files match before computing offsets and adding `HasImpls`/`HasReferences` annotations. Co-authored-by: Brandon <brandondong604@hotmail.com>
2 parents 5f9ba2d + 903a2e9 commit 2aa6483

File tree

1 file changed

+38
-8
lines changed

1 file changed

+38
-8
lines changed

crates/ide/src/annotations.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use either::Either;
2-
use hir::{HasSource, Semantics};
2+
use hir::{HasSource, InFile, Semantics};
33
use ide_db::{
44
base_db::{FileId, FilePosition, FileRange},
55
helpers::visit_file_defs,
@@ -80,19 +80,19 @@ pub(crate) fn annotations(
8080
Either::Left(def) => {
8181
let node = match def {
8282
hir::ModuleDef::Const(konst) => {
83-
konst.source(db).and_then(|node| range_and_position_of(&node.value))
83+
konst.source(db).and_then(|node| range_and_position_of(&node, file_id))
8484
}
8585
hir::ModuleDef::Trait(trait_) => {
86-
trait_.source(db).and_then(|node| range_and_position_of(&node.value))
86+
trait_.source(db).and_then(|node| range_and_position_of(&node, file_id))
8787
}
8888
hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
89-
strukt.source(db).and_then(|node| range_and_position_of(&node.value))
89+
strukt.source(db).and_then(|node| range_and_position_of(&node, file_id))
9090
}
9191
hir::ModuleDef::Adt(hir::Adt::Enum(enum_)) => {
92-
enum_.source(db).and_then(|node| range_and_position_of(&node.value))
92+
enum_.source(db).and_then(|node| range_and_position_of(&node, file_id))
9393
}
9494
hir::ModuleDef::Adt(hir::Adt::Union(union)) => {
95-
union.source(db).and_then(|node| range_and_position_of(&node.value))
95+
union.source(db).and_then(|node| range_and_position_of(&node, file_id))
9696
}
9797
_ => None,
9898
};
@@ -120,8 +120,19 @@ pub(crate) fn annotations(
120120
});
121121
}
122122

123-
fn range_and_position_of(node: &dyn NameOwner) -> Option<(TextSize, TextRange)> {
124-
Some((node.name()?.syntax().text_range().start(), node.syntax().text_range()))
123+
fn range_and_position_of<T: NameOwner>(
124+
node: &InFile<T>,
125+
file_id: FileId,
126+
) -> Option<(TextSize, TextRange)> {
127+
if node.file_id != file_id.into() {
128+
// Node is outside the file we are adding annotations to (e.g. macros).
129+
None
130+
} else {
131+
Some((
132+
node.value.name()?.syntax().text_range().start(),
133+
node.value.syntax().text_range(),
134+
))
135+
}
125136
}
126137
}
127138
Either::Right(_) => (),
@@ -961,6 +972,25 @@ mod tests {
961972
struct Foo;
962973
//- /lib.rs
963974
// this file comes last since `check` checks the first file only
975+
"#,
976+
expect![[r#"
977+
[]
978+
"#]],
979+
);
980+
}
981+
982+
#[test]
983+
fn test_no_annotations_macro_struct_def() {
984+
check(
985+
r#"
986+
//- /lib.rs
987+
macro_rules! m {
988+
() => {
989+
struct A {}
990+
};
991+
}
992+
993+
m!();
964994
"#,
965995
expect![[r#"
966996
[]

0 commit comments

Comments
 (0)