Skip to content

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)