@@ -4453,6 +4453,7 @@ pub struct PatternMatchOnValue<'a, A> {
4453
4453
/// print and format the corresponding pattern matching code; that's why you'll
4454
4454
/// see `Range`s and `SrcSpan` besides the type of the thing being matched.
4455
4455
///
4456
+ #[ derive( Clone ) ]
4456
4457
pub enum PatternMatchedValue < ' a > {
4457
4458
FunctionArgument {
4458
4459
/// The argument being pattern matched on.
@@ -4467,16 +4468,16 @@ pub enum PatternMatchedValue<'a> {
4467
4468
function_range : Range ,
4468
4469
} ,
4469
4470
LetVariable {
4470
- variable_name : & ' a EcoString ,
4471
- variable_type : & ' a Arc < Type > ,
4471
+ variable_name : EcoString ,
4472
+ variable_type : Arc < Type > ,
4472
4473
/// The location of the entire let assignment the variable is part of,
4473
4474
/// so that we can add the pattern matching _after_ it.
4474
4475
///
4475
4476
assignment_location : SrcSpan ,
4476
4477
} ,
4477
4478
UseVariable {
4478
- variable_name : & ' a EcoString ,
4479
- variable_type : & ' a Arc < Type > ,
4479
+ variable_name : EcoString ,
4480
+ variable_type : Arc < Type > ,
4480
4481
/// The location of the entire use expression the variable is part of,
4481
4482
/// so that we can add the pattern matching _after_ it.
4482
4483
///
@@ -4506,7 +4507,7 @@ where
4506
4507
pub fn code_actions ( mut self ) -> Vec < CodeAction > {
4507
4508
self . visit_typed_module ( & self . module . ast ) ;
4508
4509
4509
- let action_title = match self . selected_value {
4510
+ let action_title = match self . selected_value . clone ( ) {
4510
4511
Some ( PatternMatchedValue :: FunctionArgument {
4511
4512
arg,
4512
4513
first_statement : function_body,
@@ -4614,8 +4615,8 @@ where
4614
4615
4615
4616
fn match_on_let_variable (
4616
4617
& mut self ,
4617
- variable_name : & EcoString ,
4618
- variable_type : & Arc < Type > ,
4618
+ variable_name : EcoString ,
4619
+ variable_type : Arc < Type > ,
4619
4620
assignment_location : SrcSpan ,
4620
4621
) {
4621
4622
let Some ( patterns) = self . type_to_destructure_patterns ( variable_type. as_ref ( ) ) else {
@@ -4780,6 +4781,94 @@ where
4780
4781
pattern. push ( ')' ) ;
4781
4782
Some ( pattern)
4782
4783
}
4784
+
4785
+ fn pattern_variable_under_cursor (
4786
+ & self ,
4787
+ pattern : & ' a TypedPattern ,
4788
+ ) -> Option < ( & ' a EcoString , Arc < Type > ) > {
4789
+ match pattern {
4790
+ Pattern :: Int { .. }
4791
+ | Pattern :: Float { .. }
4792
+ | Pattern :: String { .. }
4793
+ | Pattern :: BitArraySize ( _)
4794
+ | Pattern :: Discard { .. }
4795
+ | Pattern :: Invalid { .. } => None ,
4796
+
4797
+ Pattern :: Variable {
4798
+ location,
4799
+ name,
4800
+ type_,
4801
+ ..
4802
+ } => {
4803
+ if within (
4804
+ self . params . range ,
4805
+ self . edits . src_span_to_lsp_range ( * location) ,
4806
+ ) {
4807
+ Some ( ( name, type_. clone ( ) ) )
4808
+ } else {
4809
+ None
4810
+ }
4811
+ }
4812
+
4813
+ Pattern :: Assign { pattern, .. } => self . pattern_variable_under_cursor ( pattern) ,
4814
+
4815
+ Pattern :: Constructor { arguments, .. } => arguments
4816
+ . iter ( )
4817
+ . find_map ( |argument| self . pattern_variable_under_cursor ( & argument. value ) ) ,
4818
+
4819
+ Pattern :: Tuple { elements, .. } => elements
4820
+ . iter ( )
4821
+ . find_map ( |element| self . pattern_variable_under_cursor ( element) ) ,
4822
+
4823
+ Pattern :: List { elements, tail, .. } => elements
4824
+ . iter ( )
4825
+ . find_map ( |element| self . pattern_variable_under_cursor ( element) )
4826
+ . or_else ( || {
4827
+ tail. as_ref ( )
4828
+ . and_then ( |tail| self . pattern_variable_under_cursor ( tail) )
4829
+ } ) ,
4830
+
4831
+ Pattern :: BitArray { segments, .. } => segments
4832
+ . iter ( )
4833
+ . flat_map ( |segment| & segment. options )
4834
+ . find_map ( |option| {
4835
+ option
4836
+ . value ( )
4837
+ . and_then ( |pattern| self . pattern_variable_under_cursor ( pattern) )
4838
+ } ) ,
4839
+
4840
+ Pattern :: StringPrefix {
4841
+ left_side_assignment : Some ( ( name, location) ) ,
4842
+ ..
4843
+ } => {
4844
+ if within (
4845
+ self . params . range ,
4846
+ self . edits . src_span_to_lsp_range ( * location) ,
4847
+ ) {
4848
+ Some ( ( name, type_:: string ( ) ) )
4849
+ } else {
4850
+ None
4851
+ }
4852
+ }
4853
+
4854
+ Pattern :: StringPrefix {
4855
+ right_side_assignment : AssignName :: Variable ( name) ,
4856
+ right_location,
4857
+ ..
4858
+ } => {
4859
+ if within (
4860
+ self . params . range ,
4861
+ self . edits . src_span_to_lsp_range ( * right_location) ,
4862
+ ) {
4863
+ Some ( ( name, type_:: string ( ) ) )
4864
+ } else {
4865
+ None
4866
+ }
4867
+ }
4868
+
4869
+ Pattern :: StringPrefix { .. } => None ,
4870
+ }
4871
+ }
4783
4872
}
4784
4873
4785
4874
impl < ' ast , IO > ast:: visit:: Visit < ' ast > for PatternMatchOnValue < ' ast , IO >
@@ -4863,24 +4952,15 @@ where
4863
4952
}
4864
4953
4865
4954
fn visit_typed_assignment ( & mut self , assignment : & ' ast TypedAssignment ) {
4866
- if let Pattern :: Variable {
4867
- name,
4868
- location,
4869
- type_,
4870
- ..
4871
- } = & assignment. pattern
4872
- {
4873
- let variable_range = self . edits . src_span_to_lsp_range ( * location) ;
4874
- if within ( self . params . range , variable_range) {
4875
- self . selected_value = Some ( PatternMatchedValue :: LetVariable {
4876
- variable_name : name,
4877
- variable_type : type_,
4878
- assignment_location : assignment. location ,
4879
- } ) ;
4880
- // If we've found the variable to pattern match on, there's no
4881
- // point in keeping traversing the AST.
4882
- return ;
4883
- }
4955
+ if let Some ( ( name, type_) ) = self . pattern_variable_under_cursor ( & assignment. pattern ) {
4956
+ self . selected_value = Some ( PatternMatchedValue :: LetVariable {
4957
+ variable_name : name. clone ( ) ,
4958
+ variable_type : type_,
4959
+ assignment_location : assignment. location ,
4960
+ } ) ;
4961
+ // If we've found the variable to pattern match on, there's no
4962
+ // point in keeping traversing the AST.
4963
+ return ;
4884
4964
}
4885
4965
4886
4966
ast:: visit:: visit_typed_assignment ( self , assignment) ;
@@ -4909,8 +4989,8 @@ where
4909
4989
let variable_range = self . edits . src_span_to_lsp_range ( * variable_location) ;
4910
4990
if within ( self . params . range , variable_range) {
4911
4991
self . selected_value = Some ( PatternMatchedValue :: UseVariable {
4912
- variable_name : name,
4913
- variable_type : type_,
4992
+ variable_name : name. clone ( ) ,
4993
+ variable_type : type_. clone ( ) ,
4914
4994
use_location : use_. location ,
4915
4995
} ) ;
4916
4996
// If we've found the variable to pattern match on, there's no
0 commit comments