Unnamed repository; edit this file 'description' to name the repository.
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).
Mathew Horner 2022-09-12
parent 2e9f120 · commit 8a2803d
-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 210c5c7fac..7019658a16 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 0552330814..c1ef25b592 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 54dcb42d99..6c6ad5f43a 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 e79cf3d3fd..edac9de69a 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 72b9257264..3cd49bc5d8 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 767c5875bf..465d866021 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,