Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 8a2803d

Browse files
committed
Allow configuration of annotation location.
Previously, annotations would only appear above the name of an item (function signature, struct declaration, etc). Now, rust-analyzer can be configured to show annotations either above the name or above the whole item (including doc comments and attributes).
1 parent 2e9f120 commit 8a2803d

File tree

6 files changed

+132
-19
lines changed

6 files changed

+132
-19
lines changed

crates/ide/src/annotations.rs

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ pub struct AnnotationConfig {
4141
pub annotate_references: bool,
4242
pub annotate_method_references: bool,
4343
pub annotate_enum_variant_references: bool,
44+
pub annotation_location: AnnotationLocation,
45+
}
46+
47+
pub enum AnnotationLocation {
48+
AboveName,
49+
AboveWholeItem,
4450
}
4551

4652
pub(crate) fn annotations(
@@ -65,10 +71,10 @@ pub(crate) fn annotations(
6571
visit_file_defs(&Semantics::new(db), file_id, &mut |def| {
6672
let range = match def {
6773
Definition::Const(konst) if config.annotate_references => {
68-
konst.source(db).and_then(|node| name_range(db, node, file_id))
74+
konst.source(db).and_then(|node| name_range(db, config, node, file_id))
6975
}
7076
Definition::Trait(trait_) if config.annotate_references || config.annotate_impls => {
71-
trait_.source(db).and_then(|node| name_range(db, node, file_id))
77+
trait_.source(db).and_then(|node| name_range(db, config, node, file_id))
7278
}
7379
Definition::Adt(adt) => match adt {
7480
hir::Adt::Enum(enum_) => {
@@ -77,7 +83,9 @@ pub(crate) fn annotations(
7783
.variants(db)
7884
.into_iter()
7985
.map(|variant| {
80-
variant.source(db).and_then(|node| name_range(db, node, file_id))
86+
variant
87+
.source(db)
88+
.and_then(|node| name_range(db, config, node, file_id))
8189
})
8290
.flatten()
8391
.for_each(|range| {
@@ -88,14 +96,14 @@ pub(crate) fn annotations(
8896
})
8997
}
9098
if config.annotate_references || config.annotate_impls {
91-
enum_.source(db).and_then(|node| name_range(db, node, file_id))
99+
enum_.source(db).and_then(|node| name_range(db, config, node, file_id))
92100
} else {
93101
None
94102
}
95103
}
96104
_ => {
97105
if config.annotate_references || config.annotate_impls {
98-
adt.source(db).and_then(|node| name_range(db, node, file_id))
106+
adt.source(db).and_then(|node| name_range(db, config, node, file_id))
99107
} else {
100108
None
101109
}
@@ -113,6 +121,7 @@ pub(crate) fn annotations(
113121
annotations
114122
.push(Annotation { range, kind: AnnotationKind::HasImpls { file_id, data: None } });
115123
}
124+
116125
if config.annotate_references {
117126
annotations.push(Annotation {
118127
range,
@@ -122,12 +131,18 @@ pub(crate) fn annotations(
122131

123132
fn name_range<T: HasName>(
124133
db: &RootDatabase,
134+
config: &AnnotationConfig,
125135
node: InFile<T>,
126136
source_file_id: FileId,
127137
) -> Option<TextRange> {
128138
if let Some(InFile { file_id, value }) = node.original_ast_node(db) {
129139
if file_id == source_file_id.into() {
130-
return value.name().map(|it| it.syntax().text_range());
140+
return match config.annotation_location {
141+
AnnotationLocation::AboveName => {
142+
value.name().map(|name| name.syntax().text_range())
143+
}
144+
AnnotationLocation::AboveWholeItem => Some(value.syntax().text_range()),
145+
};
131146
}
132147
}
133148
None
@@ -188,21 +203,23 @@ mod tests {
188203

189204
use crate::{fixture, Annotation, AnnotationConfig};
190205

191-
fn check(ra_fixture: &str, expect: Expect) {
206+
use super::AnnotationLocation;
207+
208+
const DEFAULT_CONFIG: AnnotationConfig = AnnotationConfig {
209+
binary_target: true,
210+
annotate_runnables: true,
211+
annotate_impls: true,
212+
annotate_references: true,
213+
annotate_method_references: true,
214+
annotate_enum_variant_references: true,
215+
annotation_location: AnnotationLocation::AboveName,
216+
};
217+
218+
fn check(ra_fixture: &str, expect: Expect, config: &AnnotationConfig) {
192219
let (analysis, file_id) = fixture::file(ra_fixture);
193220

194221
let annotations: Vec<Annotation> = analysis
195-
.annotations(
196-
&AnnotationConfig {
197-
binary_target: true,
198-
annotate_runnables: true,
199-
annotate_impls: true,
200-
annotate_references: true,
201-
annotate_method_references: true,
202-
annotate_enum_variant_references: true,
203-
},
204-
file_id,
205-
)
222+
.annotations(config, file_id)
206223
.unwrap()
207224
.into_iter()
208225
.map(|annotation| analysis.resolve_annotation(annotation).unwrap())
@@ -286,6 +303,7 @@ fn main() {
286303
},
287304
]
288305
"#]],
306+
&DEFAULT_CONFIG,
289307
);
290308
}
291309

@@ -362,6 +380,7 @@ fn main() {
362380
},
363381
]
364382
"#]],
383+
&DEFAULT_CONFIG,
365384
);
366385
}
367386

@@ -497,6 +516,7 @@ fn main() {
497516
},
498517
]
499518
"#]],
519+
&DEFAULT_CONFIG,
500520
);
501521
}
502522

@@ -540,6 +560,7 @@ fn main() {}
540560
},
541561
]
542562
"#]],
563+
&DEFAULT_CONFIG,
543564
);
544565
}
545566

@@ -654,6 +675,7 @@ fn main() {
654675
},
655676
]
656677
"#]],
678+
&DEFAULT_CONFIG,
657679
);
658680
}
659681

@@ -750,6 +772,7 @@ mod tests {
750772
},
751773
]
752774
"#]],
775+
&DEFAULT_CONFIG,
753776
);
754777
}
755778

@@ -765,6 +788,7 @@ struct Foo;
765788
expect![[r#"
766789
[]
767790
"#]],
791+
&DEFAULT_CONFIG,
768792
);
769793
}
770794

@@ -784,6 +808,46 @@ m!();
784808
expect![[r#"
785809
[]
786810
"#]],
811+
&DEFAULT_CONFIG,
812+
);
813+
}
814+
815+
#[test]
816+
fn test_annotations_appear_above_whole_item_when_configured_to_do_so() {
817+
check(
818+
r#"
819+
/// This is a struct named Foo, obviously.
820+
#[derive(Clone)]
821+
struct Foo;
822+
"#,
823+
expect![[r#"
824+
[
825+
Annotation {
826+
range: 0..71,
827+
kind: HasImpls {
828+
file_id: FileId(
829+
0,
830+
),
831+
data: Some(
832+
[],
833+
),
834+
},
835+
},
836+
Annotation {
837+
range: 0..71,
838+
kind: HasReferences {
839+
file_id: FileId(
840+
0,
841+
),
842+
data: None,
843+
},
844+
},
845+
]
846+
"#]],
847+
&AnnotationConfig {
848+
annotation_location: AnnotationLocation::AboveWholeItem,
849+
..DEFAULT_CONFIG
850+
},
787851
);
788852
}
789853
}

crates/ide/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ use syntax::SourceFile;
7474
use crate::navigation_target::{ToNav, TryToNav};
7575

7676
pub use crate::{
77-
annotations::{Annotation, AnnotationConfig, AnnotationKind},
77+
annotations::{Annotation, AnnotationConfig, AnnotationKind, AnnotationLocation},
7878
call_hierarchy::CallItem,
7979
expand_macro::ExpandedMacro,
8080
file_structure::{StructureNode, StructureNodeKind},

crates/rust-analyzer/src/config.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@ config_data! {
307307
/// Join lines unwraps trivial blocks.
308308
joinLines_unwrapTrivialBlock: bool = "true",
309309

310+
/// Where to render annotations.
311+
lens_annotationLocation: AnnotationLocation = "\"above_name\"",
310312
/// Whether to show `Debug` lens. Only applies when
311313
/// `#rust-analyzer.lens.enable#` is set.
312314
lens_debug_enable: bool = "true",
@@ -494,6 +496,25 @@ pub struct LensConfig {
494496
pub refs_adt: bool, // for Struct, Enum, Union and Trait
495497
pub refs_trait: bool, // for Struct, Enum, Union and Trait
496498
pub enum_variant_refs: bool,
499+
500+
// annotations
501+
pub annotation_location: AnnotationLocation,
502+
}
503+
504+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)]
505+
#[serde(rename_all = "snake_case")]
506+
pub enum AnnotationLocation {
507+
AboveName,
508+
AboveWholeItem,
509+
}
510+
511+
impl From<AnnotationLocation> for ide::AnnotationLocation {
512+
fn from(location: AnnotationLocation) -> Self {
513+
match location {
514+
AnnotationLocation::AboveName => ide::AnnotationLocation::AboveName,
515+
AnnotationLocation::AboveWholeItem => ide::AnnotationLocation::AboveWholeItem,
516+
}
517+
}
497518
}
498519

499520
impl LensConfig {
@@ -1185,6 +1206,7 @@ impl Config {
11851206
refs_trait: self.data.lens_enable && self.data.lens_references_trait_enable,
11861207
enum_variant_refs: self.data.lens_enable
11871208
&& self.data.lens_references_enumVariant_enable,
1209+
annotation_location: self.data.lens_annotationLocation,
11881210
}
11891211
}
11901212

@@ -1921,6 +1943,14 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
19211943
"Use server-side file watching",
19221944
],
19231945
},
1946+
"AnnotationLocation" => set! {
1947+
"type": "string",
1948+
"enum": ["above_name", "above_whole_item"],
1949+
"enumDescriptions": [
1950+
"Render annotations above the name of the item.",
1951+
"Render annotations above the whole item, including documentation comments and attributes."
1952+
],
1953+
},
19241954
_ => panic!("missing entry for {}: {}", ty, default),
19251955
}
19261956

crates/rust-analyzer/src/handlers.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,7 @@ pub(crate) fn handle_code_lens(
12341234
annotate_references: lens_config.refs_adt,
12351235
annotate_method_references: lens_config.method_refs,
12361236
annotate_enum_variant_references: lens_config.enum_variant_refs,
1237+
annotation_location: lens_config.annotation_location.into(),
12371238
},
12381239
file_id,
12391240
)?;

docs/user/generated_config.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,11 @@ Join lines removes trailing commas.
451451
--
452452
Join lines unwraps trivial blocks.
453453
--
454+
[[rust-analyzer.lens.annotation.location]]rust-analyzer.lens.annotation.location (default: `above_name`)::
455+
+
456+
--
457+
Where to render annotations.
458+
--
454459
[[rust-analyzer.lens.debug.enable]]rust-analyzer.lens.debug.enable (default: `true`)::
455460
+
456461
--

editors/code/package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,19 @@
943943
"default": true,
944944
"type": "boolean"
945945
},
946+
"rust-analyzer.lens.annotationLocation": {
947+
"markdownDescription": "Where to render annotations.",
948+
"default": "above_name",
949+
"type": "string",
950+
"enum": [
951+
"above_name",
952+
"above_whole_item"
953+
],
954+
"enumDescriptions": [
955+
"Render annotations above the name of the item.",
956+
"Render annotations above the whole item, including documentation comments and attributes."
957+
]
958+
},
946959
"rust-analyzer.lens.debug.enable": {
947960
"markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
948961
"default": true,

0 commit comments

Comments
 (0)