mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-27 20:35:09 +00:00
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).
This commit is contained in:
parent
2e9f1204ca
commit
8a2803d9ae
6 changed files with 132 additions and 19 deletions
|
@ -41,6 +41,12 @@ pub struct AnnotationConfig {
|
||||||
pub annotate_references: bool,
|
pub annotate_references: bool,
|
||||||
pub annotate_method_references: bool,
|
pub annotate_method_references: bool,
|
||||||
pub annotate_enum_variant_references: bool,
|
pub annotate_enum_variant_references: bool,
|
||||||
|
pub annotation_location: AnnotationLocation,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum AnnotationLocation {
|
||||||
|
AboveName,
|
||||||
|
AboveWholeItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn annotations(
|
pub(crate) fn annotations(
|
||||||
|
@ -65,10 +71,10 @@ pub(crate) fn annotations(
|
||||||
visit_file_defs(&Semantics::new(db), file_id, &mut |def| {
|
visit_file_defs(&Semantics::new(db), file_id, &mut |def| {
|
||||||
let range = match def {
|
let range = match def {
|
||||||
Definition::Const(konst) if config.annotate_references => {
|
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 => {
|
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 {
|
Definition::Adt(adt) => match adt {
|
||||||
hir::Adt::Enum(enum_) => {
|
hir::Adt::Enum(enum_) => {
|
||||||
|
@ -77,7 +83,9 @@ pub(crate) fn annotations(
|
||||||
.variants(db)
|
.variants(db)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|variant| {
|
.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()
|
.flatten()
|
||||||
.for_each(|range| {
|
.for_each(|range| {
|
||||||
|
@ -88,14 +96,14 @@ pub(crate) fn annotations(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if config.annotate_references || config.annotate_impls {
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if config.annotate_references || config.annotate_impls {
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -113,6 +121,7 @@ pub(crate) fn annotations(
|
||||||
annotations
|
annotations
|
||||||
.push(Annotation { range, kind: AnnotationKind::HasImpls { file_id, data: None } });
|
.push(Annotation { range, kind: AnnotationKind::HasImpls { file_id, data: None } });
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.annotate_references {
|
if config.annotate_references {
|
||||||
annotations.push(Annotation {
|
annotations.push(Annotation {
|
||||||
range,
|
range,
|
||||||
|
@ -122,12 +131,18 @@ pub(crate) fn annotations(
|
||||||
|
|
||||||
fn name_range<T: HasName>(
|
fn name_range<T: HasName>(
|
||||||
db: &RootDatabase,
|
db: &RootDatabase,
|
||||||
|
config: &AnnotationConfig,
|
||||||
node: InFile<T>,
|
node: InFile<T>,
|
||||||
source_file_id: FileId,
|
source_file_id: FileId,
|
||||||
) -> Option<TextRange> {
|
) -> Option<TextRange> {
|
||||||
if let Some(InFile { file_id, value }) = node.original_ast_node(db) {
|
if let Some(InFile { file_id, value }) = node.original_ast_node(db) {
|
||||||
if file_id == source_file_id.into() {
|
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
|
None
|
||||||
|
@ -188,21 +203,23 @@ mod tests {
|
||||||
|
|
||||||
use crate::{fixture, Annotation, AnnotationConfig};
|
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 (analysis, file_id) = fixture::file(ra_fixture);
|
||||||
|
|
||||||
let annotations: Vec<Annotation> = analysis
|
let annotations: Vec<Annotation> = analysis
|
||||||
.annotations(
|
.annotations(config, file_id)
|
||||||
&AnnotationConfig {
|
|
||||||
binary_target: true,
|
|
||||||
annotate_runnables: true,
|
|
||||||
annotate_impls: true,
|
|
||||||
annotate_references: true,
|
|
||||||
annotate_method_references: true,
|
|
||||||
annotate_enum_variant_references: true,
|
|
||||||
},
|
|
||||||
file_id,
|
|
||||||
)
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|annotation| analysis.resolve_annotation(annotation).unwrap())
|
.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#"
|
expect![[r#"
|
||||||
[]
|
[]
|
||||||
"#]],
|
"#]],
|
||||||
|
&DEFAULT_CONFIG,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,6 +808,46 @@ m!();
|
||||||
expect![[r#"
|
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
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ use syntax::SourceFile;
|
||||||
use crate::navigation_target::{ToNav, TryToNav};
|
use crate::navigation_target::{ToNav, TryToNav};
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
annotations::{Annotation, AnnotationConfig, AnnotationKind},
|
annotations::{Annotation, AnnotationConfig, AnnotationKind, AnnotationLocation},
|
||||||
call_hierarchy::CallItem,
|
call_hierarchy::CallItem,
|
||||||
expand_macro::ExpandedMacro,
|
expand_macro::ExpandedMacro,
|
||||||
file_structure::{StructureNode, StructureNodeKind},
|
file_structure::{StructureNode, StructureNodeKind},
|
||||||
|
|
|
@ -307,6 +307,8 @@ config_data! {
|
||||||
/// Join lines unwraps trivial blocks.
|
/// Join lines unwraps trivial blocks.
|
||||||
joinLines_unwrapTrivialBlock: bool = "true",
|
joinLines_unwrapTrivialBlock: bool = "true",
|
||||||
|
|
||||||
|
/// Where to render annotations.
|
||||||
|
lens_annotationLocation: AnnotationLocation = "\"above_name\"",
|
||||||
/// Whether to show `Debug` lens. Only applies when
|
/// Whether to show `Debug` lens. Only applies when
|
||||||
/// `#rust-analyzer.lens.enable#` is set.
|
/// `#rust-analyzer.lens.enable#` is set.
|
||||||
lens_debug_enable: bool = "true",
|
lens_debug_enable: bool = "true",
|
||||||
|
@ -494,6 +496,25 @@ pub struct LensConfig {
|
||||||
pub refs_adt: bool, // for Struct, Enum, Union and Trait
|
pub refs_adt: bool, // for Struct, Enum, Union and Trait
|
||||||
pub refs_trait: bool, // for Struct, Enum, Union and Trait
|
pub refs_trait: bool, // for Struct, Enum, Union and Trait
|
||||||
pub enum_variant_refs: bool,
|
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 {
|
impl LensConfig {
|
||||||
|
@ -1185,6 +1206,7 @@ impl Config {
|
||||||
refs_trait: self.data.lens_enable && self.data.lens_references_trait_enable,
|
refs_trait: self.data.lens_enable && self.data.lens_references_trait_enable,
|
||||||
enum_variant_refs: self.data.lens_enable
|
enum_variant_refs: self.data.lens_enable
|
||||||
&& self.data.lens_references_enumVariant_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",
|
"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),
|
_ => panic!("missing entry for {}: {}", ty, default),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1234,6 +1234,7 @@ pub(crate) fn handle_code_lens(
|
||||||
annotate_references: lens_config.refs_adt,
|
annotate_references: lens_config.refs_adt,
|
||||||
annotate_method_references: lens_config.method_refs,
|
annotate_method_references: lens_config.method_refs,
|
||||||
annotate_enum_variant_references: lens_config.enum_variant_refs,
|
annotate_enum_variant_references: lens_config.enum_variant_refs,
|
||||||
|
annotation_location: lens_config.annotation_location.into(),
|
||||||
},
|
},
|
||||||
file_id,
|
file_id,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -451,6 +451,11 @@ Join lines removes trailing commas.
|
||||||
--
|
--
|
||||||
Join lines unwraps trivial blocks.
|
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`)::
|
[[rust-analyzer.lens.debug.enable]]rust-analyzer.lens.debug.enable (default: `true`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
|
|
|
@ -943,6 +943,19 @@
|
||||||
"default": true,
|
"default": true,
|
||||||
"type": "boolean"
|
"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": {
|
"rust-analyzer.lens.debug.enable": {
|
||||||
"markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
|
"markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
|
||||||
"default": true,
|
"default": true,
|
||||||
|
|
Loading…
Reference in a new issue