Auto merge of #13221 - mdx97:mdx97/annotations-above-whole-item, r=Veykril
Allow configuration of annotation location. I've added the ability to configure where lens annotations render relevant to the item they describe. Previously, these would render directly above the line the item is declared on. Now, there is the ability to render these annotations above the entire item (including doc comments, and attributes). The names of the config options are up for debate, I did what seemed best to me but if anyone has better ideas let me know. This is my first contribution so if I've missed anything please let me know. Here's a preview of what the new option looks like: <img width="577" alt="Screen Shot 2022-09-11 at 10 39 51 PM" src="https://user-images.githubusercontent.com/33100798/189570298-b4fcbf9c-ee49-4b79-aae6-1037ae4f26af.png"> closes https://github.com/rust-lang/rust-analyzer/issues/13218
This commit is contained in:
commit
dbb8fedf8b
@ -41,6 +41,12 @@ pub struct AnnotationConfig {
|
||||
pub annotate_references: bool,
|
||||
pub annotate_method_references: bool,
|
||||
pub annotate_enum_variant_references: bool,
|
||||
pub 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.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,
|
||||
location: AnnotationLocation::AboveName,
|
||||
};
|
||||
|
||||
fn check_with_config(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())
|
||||
@ -211,6 +228,10 @@ mod tests {
|
||||
expect.assert_debug_eq(&annotations);
|
||||
}
|
||||
|
||||
fn check(ra_fixture: &str, expect: Expect) {
|
||||
check_with_config(ra_fixture, expect, &DEFAULT_CONFIG);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn const_annotations() {
|
||||
check(
|
||||
@ -786,4 +807,40 @@ m!();
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_annotations_appear_above_whole_item_when_configured_to_do_so() {
|
||||
check_with_config(
|
||||
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 { location: AnnotationLocation::AboveWholeItem, ..DEFAULT_CONFIG },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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},
|
||||
|
@ -308,6 +308,7 @@ config_data! {
|
||||
/// Join lines unwraps trivial blocks.
|
||||
joinLines_unwrapTrivialBlock: bool = "true",
|
||||
|
||||
|
||||
/// Whether to show `Debug` lens. Only applies when
|
||||
/// `#rust-analyzer.lens.enable#` is set.
|
||||
lens_debug_enable: bool = "true",
|
||||
@ -319,6 +320,8 @@ config_data! {
|
||||
/// Whether to show `Implementations` lens. Only applies when
|
||||
/// `#rust-analyzer.lens.enable#` is set.
|
||||
lens_implementations_enable: bool = "true",
|
||||
/// Where to render annotations.
|
||||
lens_location: AnnotationLocation = "\"above_name\"",
|
||||
/// Whether to show `References` lens for Struct, Enum, and Union.
|
||||
/// Only applies when `#rust-analyzer.lens.enable#` is set.
|
||||
lens_references_adt_enable: bool = "false",
|
||||
@ -498,6 +501,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 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 {
|
||||
@ -1196,6 +1218,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,
|
||||
location: self.data.lens_location,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1932,6 +1955,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),
|
||||
}
|
||||
|
||||
|
@ -1240,6 +1240,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,
|
||||
location: lens_config.location.into(),
|
||||
},
|
||||
file_id,
|
||||
)?;
|
||||
|
@ -479,6 +479,11 @@ client doesn't set the corresponding capability.
|
||||
Whether to show `Implementations` lens. Only applies when
|
||||
`#rust-analyzer.lens.enable#` is set.
|
||||
--
|
||||
[[rust-analyzer.lens.location]]rust-analyzer.lens.location (default: `"above_name"`)::
|
||||
+
|
||||
--
|
||||
Where to render annotations.
|
||||
--
|
||||
[[rust-analyzer.lens.references.adt.enable]]rust-analyzer.lens.references.adt.enable (default: `false`)::
|
||||
+
|
||||
--
|
||||
|
@ -963,6 +963,19 @@
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.lens.location": {
|
||||
"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.references.adt.enable": {
|
||||
"markdownDescription": "Whether to show `References` lens for Struct, Enum, and Union.\nOnly applies when `#rust-analyzer.lens.enable#` is set.",
|
||||
"default": false,
|
||||
|
Loading…
x
Reference in New Issue
Block a user