From a0bb31587e4bbf1151fc4587de1b5d4e81a94e9d Mon Sep 17 00:00:00 2001 From: Eric Sampson Date: Mon, 4 Oct 2021 02:18:31 -0500 Subject: [PATCH 1/5] Add enum variant references CodeLens. --- crates/ide/src/annotations.rs | 53 +++++++++++++++++++++++----- crates/rust-analyzer/src/config.rs | 11 ++++-- crates/rust-analyzer/src/handlers.rs | 1 + editors/code/package.json | 7 +++- 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index 472b396ac5..6c75bf3492 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -5,7 +5,7 @@ use ide_db::{ helpers::visit_file_defs, RootDatabase, }; -use syntax::{ast::HasName, AstNode, TextRange}; +use syntax::{ast::HasName, AstNode, TextRange, TextSize}; use crate::{ fn_references::find_all_methods, @@ -40,6 +40,7 @@ pub struct AnnotationConfig { pub annotate_impls: bool, pub annotate_references: bool, pub annotate_method_references: bool, + pub annotate_enum_variant_references: bool, } pub(crate) fn annotations( @@ -63,18 +64,33 @@ pub(crate) fn annotations( visit_file_defs(&Semantics::new(db), file_id, &mut |def| match def { Either::Left(def) => { - let range = match def { + let (range, ranges_variants) = match def { hir::ModuleDef::Const(konst) => { - konst.source(db).and_then(|node| name_range(&node, file_id)) + (konst.source(db).and_then(|node| name_range(&node, file_id)), vec![None]) } hir::ModuleDef::Trait(trait_) => { - trait_.source(db).and_then(|node| name_range(&node, file_id)) + (trait_.source(db).and_then(|node| name_range(&node, file_id)), vec![None]) } - hir::ModuleDef::Adt(adt) => { - adt.source(db).and_then(|node| name_range(&node, file_id)) - } - _ => None, + hir::ModuleDef::Adt(adt) => match adt { + hir::Adt::Enum(enum_) => ( + enum_.source(db).and_then(|node| name_range(&node, file_id)), + if config.annotate_enum_variant_references { + enum_ + .variants(db) + .into_iter() + .map(|variant| { + variant.source(db).and_then(|node| name_range(&node, file_id)) + }) + .collect() + } else { + vec![None] + }, + ), + _ => (adt.source(db).and_then(|node| name_range(&node, file_id)), vec![None]), + }, + _ => (None, vec![None]), }; + let (range, offset) = match range { Some(range) => (range, range.start()), None => return, @@ -99,6 +115,26 @@ pub(crate) fn annotations( }); } + if config.annotate_enum_variant_references { + let mut variants_metadata: Vec<(TextRange, TextSize)> = Vec::new(); + for range_variant in ranges_variants.into_iter() { + let (range, offset) = match range_variant { + Some(range) => (range, range.start()), + None => return, + }; + variants_metadata.push((range, offset)) + } + for variant_metadata in variants_metadata.into_iter() { + annotations.push(Annotation { + range: variant_metadata.0, + kind: AnnotationKind::HasReferences { + position: FilePosition { file_id, offset: variant_metadata.1 }, + data: None, + }, + }); + } + } + fn name_range(node: &InFile, file_id: FileId) -> Option { if node.file_id == file_id.into() { node.value.name().map(|it| it.syntax().text_range()) @@ -173,6 +209,7 @@ mod tests { annotate_impls: true, annotate_references: true, annotate_method_references: true, + annotate_enum_variant_references: true, }, file_id, ) diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 6c09833368..505123fc6a 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -225,9 +225,12 @@ config_data! { /// Whether to show `Method References` lens. Only applies when /// `#rust-analyzer.lens.enable#` is set. lens_methodReferences: bool = "false", - /// Whether to show `References` lens. Only applies when - /// `#rust-analyzer.lens.enable#` is set. + /// Whether to show `References` lens for Struct, Enum, Union and Trait. + /// Only applies when `#rust-analyzer.lens.enable#` is set. lens_references: bool = "false", + /// Whether to show `References` lens for Enum Variants. + /// Only applies when `#rust-analyzer.lens.enable#` is set. + lens_enumVariantReferences: bool = "false", /// Internal config: use custom client-side commands even when the /// client doesn't set the corresponding capability. lens_forceCustomCommands: bool = "true", @@ -323,6 +326,7 @@ pub struct LensConfig { pub implementations: bool, pub method_refs: bool, pub refs: bool, // for Struct, Enum, Union and Trait + pub enum_variant_refs: bool, } impl LensConfig { @@ -339,7 +343,7 @@ impl LensConfig { } pub fn references(&self) -> bool { - self.method_refs || self.refs + self.method_refs || self.refs || self.enum_variant_refs } } @@ -805,6 +809,7 @@ impl Config { implementations: self.data.lens_enable && self.data.lens_implementations, method_refs: self.data.lens_enable && self.data.lens_methodReferences, refs: self.data.lens_enable && self.data.lens_references, + enum_variant_refs: self.data.lens_enable && self.data.lens_enumVariantReferences, } } pub fn hover_actions(&self) -> HoverActionsConfig { diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index e62bb9499f..412a52d1c3 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -1135,6 +1135,7 @@ pub(crate) fn handle_code_lens( annotate_impls: lens_config.implementations, annotate_references: lens_config.refs, annotate_method_references: lens_config.method_refs, + annotate_enum_variant_references: lens_config.enum_variant_refs, }, file_id, )?; diff --git a/editors/code/package.json b/editors/code/package.json index 4ca93b17bc..9e08e638bb 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -793,7 +793,12 @@ "type": "boolean" }, "rust-analyzer.lens.references": { - "markdownDescription": "Whether to show `References` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.", + "markdownDescription": "Whether to show `References` lens for Struct, Enum, Union and Trait. Only applies when\n`#rust-analyzer.lens.enable#` is set.", + "default": false, + "type": "boolean" + }, + "rust-analyzer.lens.enumVariantReferences": { + "markdownDescription": "Whether to show `References` lens for Enum Variants. Only applies when\n`#rust-analyzer.lens.enable#` is set.", "default": false, "type": "boolean" }, From 99dd8066d9787a3e8664b3845ca04b3af502301b Mon Sep 17 00:00:00 2001 From: Eric Sampson Date: Mon, 4 Oct 2021 02:30:46 -0500 Subject: [PATCH 2/5] need to update some generated files. --- docs/user/generated_config.adoc | 10 ++++++++-- editors/code/package.json | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 768216fed9..3d05e8b4cf 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -355,8 +355,14 @@ Whether to show `Method References` lens. Only applies when [[rust-analyzer.lens.references]]rust-analyzer.lens.references (default: `false`):: + -- -Whether to show `References` lens. Only applies when -`#rust-analyzer.lens.enable#` is set. +Whether to show `References` lens for Struct, Enum, Union and Trait. +Only applies when `#rust-analyzer.lens.enable#` is set. +-- +[[rust-analyzer.lens.enumVariantReferences]]rust-analyzer.lens.enumVariantReferences (default: `false`):: ++ +-- +Whether to show `References` lens for Enum Variants. +Only applies when `#rust-analyzer.lens.enable#` is set. -- [[rust-analyzer.lens.forceCustomCommands]]rust-analyzer.lens.forceCustomCommands (default: `true`):: + diff --git a/editors/code/package.json b/editors/code/package.json index 9e08e638bb..d7a883bdca 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -793,12 +793,12 @@ "type": "boolean" }, "rust-analyzer.lens.references": { - "markdownDescription": "Whether to show `References` lens for Struct, Enum, Union and Trait. Only applies when\n`#rust-analyzer.lens.enable#` is set.", + "markdownDescription": "Whether to show `References` lens for Struct, Enum, Union and Trait.\nOnly applies when `#rust-analyzer.lens.enable#` is set.", "default": false, "type": "boolean" }, "rust-analyzer.lens.enumVariantReferences": { - "markdownDescription": "Whether to show `References` lens for Enum Variants. Only applies when\n`#rust-analyzer.lens.enable#` is set.", + "markdownDescription": "Whether to show `References` lens for Enum Variants.\nOnly applies when `#rust-analyzer.lens.enable#` is set.", "default": false, "type": "boolean" }, From 5df6259996f3c8998d4b158ff7f29338843dc851 Mon Sep 17 00:00:00 2001 From: Eric Sampson Date: Mon, 4 Oct 2021 02:42:13 -0500 Subject: [PATCH 3/5] tweak variable names. --- crates/ide/src/annotations.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index 6c75bf3492..2650c3ef01 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -64,7 +64,7 @@ pub(crate) fn annotations( visit_file_defs(&Semantics::new(db), file_id, &mut |def| match def { Either::Left(def) => { - let (range, ranges_variants) = match def { + let (range, ranges_enum_variants) = match def { hir::ModuleDef::Const(konst) => { (konst.source(db).and_then(|node| name_range(&node, file_id)), vec![None]) } @@ -116,19 +116,19 @@ pub(crate) fn annotations( } if config.annotate_enum_variant_references { - let mut variants_metadata: Vec<(TextRange, TextSize)> = Vec::new(); - for range_variant in ranges_variants.into_iter() { - let (range, offset) = match range_variant { + let mut enum_variants_metadata: Vec<(TextRange, TextSize)> = Vec::new(); + for range_enum_variant in ranges_enum_variants.into_iter() { + let (range, offset) = match range_enum_variant { Some(range) => (range, range.start()), None => return, }; - variants_metadata.push((range, offset)) + enum_variants_metadata.push((range, offset)) } - for variant_metadata in variants_metadata.into_iter() { + for enum_variant_metadata in enum_variants_metadata.into_iter() { annotations.push(Annotation { - range: variant_metadata.0, + range: enum_variant_metadata.0, kind: AnnotationKind::HasReferences { - position: FilePosition { file_id, offset: variant_metadata.1 }, + position: FilePosition { file_id, offset: enum_variant_metadata.1 }, data: None, }, }); From 160a7b097a1bccba925afd4517ebfb10c3168931 Mon Sep 17 00:00:00 2001 From: Eric Sampson Date: Mon, 4 Oct 2021 16:14:01 -0500 Subject: [PATCH 4/5] initialize vector to required size. --- crates/ide/src/annotations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index 2650c3ef01..5c951b85a1 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -116,7 +116,7 @@ pub(crate) fn annotations( } if config.annotate_enum_variant_references { - let mut enum_variants_metadata: Vec<(TextRange, TextSize)> = Vec::new(); + let mut enum_variants_metadata: Vec<(TextRange, TextSize)> = Vec::with_capacity(ranges_enum_variants.len()); for range_enum_variant in ranges_enum_variants.into_iter() { let (range, offset) = match range_enum_variant { Some(range) => (range, range.start()), From 6d05b07f7d64e2dd04bd8704b597d3aaf143964f Mon Sep 17 00:00:00 2001 From: Eric Sampson Date: Tue, 5 Oct 2021 15:42:45 -0500 Subject: [PATCH 5/5] Refactor according to PR comments to remove allocations. --- crates/ide/src/annotations.rs | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index 5c951b85a1..12c6852ea0 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -5,7 +5,7 @@ use ide_db::{ helpers::visit_file_defs, RootDatabase, }; -use syntax::{ast::HasName, AstNode, TextRange, TextSize}; +use syntax::{ast::HasName, AstNode, TextRange}; use crate::{ fn_references::find_all_methods, @@ -66,10 +66,10 @@ pub(crate) fn annotations( Either::Left(def) => { let (range, ranges_enum_variants) = match def { hir::ModuleDef::Const(konst) => { - (konst.source(db).and_then(|node| name_range(&node, file_id)), vec![None]) + (konst.source(db).and_then(|node| name_range(&node, file_id)), vec![]) } hir::ModuleDef::Trait(trait_) => { - (trait_.source(db).and_then(|node| name_range(&node, file_id)), vec![None]) + (trait_.source(db).and_then(|node| name_range(&node, file_id)), vec![]) } hir::ModuleDef::Adt(adt) => match adt { hir::Adt::Enum(enum_) => ( @@ -83,12 +83,12 @@ pub(crate) fn annotations( }) .collect() } else { - vec![None] + vec![] }, ), - _ => (adt.source(db).and_then(|node| name_range(&node, file_id)), vec![None]), + _ => (adt.source(db).and_then(|node| name_range(&node, file_id)), vec![]), }, - _ => (None, vec![None]), + _ => (None, vec![]), }; let (range, offset) = match range { @@ -116,19 +116,13 @@ pub(crate) fn annotations( } if config.annotate_enum_variant_references { - let mut enum_variants_metadata: Vec<(TextRange, TextSize)> = Vec::with_capacity(ranges_enum_variants.len()); - for range_enum_variant in ranges_enum_variants.into_iter() { - let (range, offset) = match range_enum_variant { - Some(range) => (range, range.start()), - None => return, - }; - enum_variants_metadata.push((range, offset)) - } - for enum_variant_metadata in enum_variants_metadata.into_iter() { + for range_enum_variant in + ranges_enum_variants.into_iter().filter_map(std::convert::identity) + { annotations.push(Annotation { - range: enum_variant_metadata.0, + range: range_enum_variant, kind: AnnotationKind::HasReferences { - position: FilePosition { file_id, offset: enum_variant_metadata.1 }, + position: FilePosition { file_id, offset: range_enum_variant.start() }, data: None, }, });