about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ide/src/annotations.rs100
-rw-r--r--crates/ide/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs30
-rw-r--r--crates/rust-analyzer/src/handlers.rs1
-rw-r--r--docs/user/generated_config.adoc5
-rw-r--r--editors/code/package.json13
6 files changed, 132 insertions, 19 deletions
diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs
index 210c5c7facd..7019658a167 100644
--- a/crates/ide/src/annotations.rs
+++ b/crates/ide/src/annotations.rs
@@ -41,6 +41,12 @@ pub struct AnnotationConfig {
     pub annotate_references: bool,
     pub annotate_method_references: bool,
     pub annotate_enum_variant_references: bool,
+    pub annotation_location: AnnotationLocation,
+}
+
+pub enum AnnotationLocation {
+    AboveName,
+    AboveWholeItem,
 }
 
 pub(crate) fn annotations(
@@ -65,10 +71,10 @@ pub(crate) fn annotations(
     visit_file_defs(&Semantics::new(db), file_id, &mut |def| {
         let range = match def {
             Definition::Const(konst) if config.annotate_references => {
-                konst.source(db).and_then(|node| name_range(db, node, file_id))
+                konst.source(db).and_then(|node| name_range(db, config, node, file_id))
             }
             Definition::Trait(trait_) if config.annotate_references || config.annotate_impls => {
-                trait_.source(db).and_then(|node| name_range(db, node, file_id))
+                trait_.source(db).and_then(|node| name_range(db, config, node, file_id))
             }
             Definition::Adt(adt) => match adt {
                 hir::Adt::Enum(enum_) => {
@@ -77,7 +83,9 @@ pub(crate) fn annotations(
                             .variants(db)
                             .into_iter()
                             .map(|variant| {
-                                variant.source(db).and_then(|node| name_range(db, node, file_id))
+                                variant
+                                    .source(db)
+                                    .and_then(|node| name_range(db, config, node, file_id))
                             })
                             .flatten()
                             .for_each(|range| {
@@ -88,14 +96,14 @@ pub(crate) fn annotations(
                             })
                     }
                     if config.annotate_references || config.annotate_impls {
-                        enum_.source(db).and_then(|node| name_range(db, node, file_id))
+                        enum_.source(db).and_then(|node| name_range(db, config, node, file_id))
                     } else {
                         None
                     }
                 }
                 _ => {
                     if config.annotate_references || config.annotate_impls {
-                        adt.source(db).and_then(|node| name_range(db, node, file_id))
+                        adt.source(db).and_then(|node| name_range(db, config, node, file_id))
                     } else {
                         None
                     }
@@ -113,6 +121,7 @@ pub(crate) fn annotations(
             annotations
                 .push(Annotation { range, kind: AnnotationKind::HasImpls { file_id, data: None } });
         }
+
         if config.annotate_references {
             annotations.push(Annotation {
                 range,
@@ -122,12 +131,18 @@ pub(crate) fn annotations(
 
         fn name_range<T: HasName>(
             db: &RootDatabase,
+            config: &AnnotationConfig,
             node: InFile<T>,
             source_file_id: FileId,
         ) -> Option<TextRange> {
             if let Some(InFile { file_id, value }) = node.original_ast_node(db) {
                 if file_id == source_file_id.into() {
-                    return value.name().map(|it| it.syntax().text_range());
+                    return match config.annotation_location {
+                        AnnotationLocation::AboveName => {
+                            value.name().map(|name| name.syntax().text_range())
+                        }
+                        AnnotationLocation::AboveWholeItem => Some(value.syntax().text_range()),
+                    };
                 }
             }
             None
@@ -188,21 +203,23 @@ mod tests {
 
     use crate::{fixture, Annotation, AnnotationConfig};
 
-    fn check(ra_fixture: &str, expect: Expect) {
+    use super::AnnotationLocation;
+
+    const DEFAULT_CONFIG: AnnotationConfig = AnnotationConfig {
+        binary_target: true,
+        annotate_runnables: true,
+        annotate_impls: true,
+        annotate_references: true,
+        annotate_method_references: true,
+        annotate_enum_variant_references: true,
+        annotation_location: AnnotationLocation::AboveName,
+    };
+
+    fn check(ra_fixture: &str, expect: Expect, config: &AnnotationConfig) {
         let (analysis, file_id) = fixture::file(ra_fixture);
 
         let annotations: Vec<Annotation> = analysis
-            .annotations(
-                &AnnotationConfig {
-                    binary_target: true,
-                    annotate_runnables: true,
-                    annotate_impls: true,
-                    annotate_references: true,
-                    annotate_method_references: true,
-                    annotate_enum_variant_references: true,
-                },
-                file_id,
-            )
+            .annotations(config, file_id)
             .unwrap()
             .into_iter()
             .map(|annotation| analysis.resolve_annotation(annotation).unwrap())
@@ -286,6 +303,7 @@ fn main() {
                     },
                 ]
             "#]],
+            &DEFAULT_CONFIG,
         );
     }
 
@@ -362,6 +380,7 @@ fn main() {
                     },
                 ]
             "#]],
+            &DEFAULT_CONFIG,
         );
     }
 
@@ -497,6 +516,7 @@ fn main() {
                     },
                 ]
             "#]],
+            &DEFAULT_CONFIG,
         );
     }
 
@@ -540,6 +560,7 @@ fn main() {}
                     },
                 ]
             "#]],
+            &DEFAULT_CONFIG,
         );
     }
 
@@ -654,6 +675,7 @@ fn main() {
                     },
                 ]
             "#]],
+            &DEFAULT_CONFIG,
         );
     }
 
@@ -750,6 +772,7 @@ mod tests {
                     },
                 ]
             "#]],
+            &DEFAULT_CONFIG,
         );
     }
 
@@ -765,6 +788,7 @@ struct Foo;
             expect![[r#"
                 []
             "#]],
+            &DEFAULT_CONFIG,
         );
     }
 
@@ -784,6 +808,46 @@ m!();
             expect![[r#"
                 []
             "#]],
+            &DEFAULT_CONFIG,
+        );
+    }
+
+    #[test]
+    fn test_annotations_appear_above_whole_item_when_configured_to_do_so() {
+        check(
+            r#"
+/// This is a struct named Foo, obviously.
+#[derive(Clone)]
+struct Foo;
+"#,
+            expect![[r#"
+                [
+                    Annotation {
+                        range: 0..71,
+                        kind: HasImpls {
+                            file_id: FileId(
+                                0,
+                            ),
+                            data: Some(
+                                [],
+                            ),
+                        },
+                    },
+                    Annotation {
+                        range: 0..71,
+                        kind: HasReferences {
+                            file_id: FileId(
+                                0,
+                            ),
+                            data: None,
+                        },
+                    },
+                ]
+            "#]],
+            &AnnotationConfig {
+                annotation_location: AnnotationLocation::AboveWholeItem,
+                ..DEFAULT_CONFIG
+            },
         );
     }
 }
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 0552330814a..c1ef25b592b 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -74,7 +74,7 @@ use syntax::SourceFile;
 use crate::navigation_target::{ToNav, TryToNav};
 
 pub use crate::{
-    annotations::{Annotation, AnnotationConfig, AnnotationKind},
+    annotations::{Annotation, AnnotationConfig, AnnotationKind, AnnotationLocation},
     call_hierarchy::CallItem,
     expand_macro::ExpandedMacro,
     file_structure::{StructureNode, StructureNodeKind},
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 54dcb42d99c..6c6ad5f43a8 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -307,6 +307,8 @@ config_data! {
         /// Join lines unwraps trivial blocks.
         joinLines_unwrapTrivialBlock: bool = "true",
 
+        /// Where to render annotations.
+        lens_annotationLocation: AnnotationLocation = "\"above_name\"",
         /// Whether to show `Debug` lens. Only applies when
         /// `#rust-analyzer.lens.enable#` is set.
         lens_debug_enable: bool            = "true",
@@ -494,6 +496,25 @@ pub struct LensConfig {
     pub refs_adt: bool,   // for Struct, Enum, Union and Trait
     pub refs_trait: bool, // for Struct, Enum, Union and Trait
     pub enum_variant_refs: bool,
+
+    // annotations
+    pub annotation_location: AnnotationLocation,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum AnnotationLocation {
+    AboveName,
+    AboveWholeItem,
+}
+
+impl From<AnnotationLocation> for ide::AnnotationLocation {
+    fn from(location: AnnotationLocation) -> Self {
+        match location {
+            AnnotationLocation::AboveName => ide::AnnotationLocation::AboveName,
+            AnnotationLocation::AboveWholeItem => ide::AnnotationLocation::AboveWholeItem,
+        }
+    }
 }
 
 impl LensConfig {
@@ -1185,6 +1206,7 @@ impl Config {
             refs_trait: self.data.lens_enable && self.data.lens_references_trait_enable,
             enum_variant_refs: self.data.lens_enable
                 && self.data.lens_references_enumVariant_enable,
+            annotation_location: self.data.lens_annotationLocation,
         }
     }
 
@@ -1921,6 +1943,14 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
                 "Use server-side file watching",
             ],
         },
+        "AnnotationLocation" => set! {
+            "type": "string",
+            "enum": ["above_name", "above_whole_item"],
+            "enumDescriptions": [
+                "Render annotations above the name of the item.",
+                "Render annotations above the whole item, including documentation comments and attributes."
+            ],
+        },
         _ => panic!("missing entry for {}: {}", ty, default),
     }
 
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index e79cf3d3fd6..edac9de69aa 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -1234,6 +1234,7 @@ pub(crate) fn handle_code_lens(
             annotate_references: lens_config.refs_adt,
             annotate_method_references: lens_config.method_refs,
             annotate_enum_variant_references: lens_config.enum_variant_refs,
+            annotation_location: lens_config.annotation_location.into(),
         },
         file_id,
     )?;
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index 72b92572647..3cd49bc5d8c 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -451,6 +451,11 @@ Join lines removes trailing commas.
 --
 Join lines unwraps trivial blocks.
 --
+[[rust-analyzer.lens.annotation.location]]rust-analyzer.lens.annotation.location (default: `above_name`)::
++
+--
+Where to render annotations.
+--
 [[rust-analyzer.lens.debug.enable]]rust-analyzer.lens.debug.enable (default: `true`)::
 +
 --
diff --git a/editors/code/package.json b/editors/code/package.json
index 767c5875bf7..465d8660215 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -943,6 +943,19 @@
                     "default": true,
                     "type": "boolean"
                 },
+                "rust-analyzer.lens.annotationLocation": {
+                    "markdownDescription": "Where to render annotations.",
+                    "default": "above_name",
+                    "type": "string",
+                    "enum": [
+                        "above_name",
+                        "above_whole_item"
+                    ],
+                    "enumDescriptions": [
+                        "Render annotations above the name of the item.",
+                        "Render annotations above the whole item, including documentation comments and attributes."
+                    ]
+                },
                 "rust-analyzer.lens.debug.enable": {
                     "markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
                     "default": true,