@@ -2605,12 +2605,18 @@ pub struct ExtractVariable<'a> {
2605
2605
module : & ' a Module ,
2606
2606
params : & ' a CodeActionParams ,
2607
2607
edits : TextEdits < ' a > ,
2608
- inside_capture_body : bool ,
2608
+ position : Option < ExtractVariablePosition > ,
2609
2609
selected_expression : Option < SrcSpan > ,
2610
2610
statement_before_selected_expression : Option < SrcSpan > ,
2611
2611
latest_statement : Option < SrcSpan > ,
2612
2612
}
2613
2613
2614
+ #[ derive( PartialEq , Eq , Copy , Clone ) ]
2615
+ enum ExtractVariablePosition {
2616
+ InsideCaptureBody ,
2617
+ TopLevelStatement ,
2618
+ }
2619
+
2614
2620
impl < ' a > ExtractVariable < ' a > {
2615
2621
pub fn new (
2616
2622
module : & ' a Module ,
@@ -2621,7 +2627,7 @@ impl<'a> ExtractVariable<'a> {
2621
2627
module,
2622
2628
params,
2623
2629
edits : TextEdits :: new ( line_numbers) ,
2624
- inside_capture_body : false ,
2630
+ position : None ,
2625
2631
selected_expression : None ,
2626
2632
latest_statement : None ,
2627
2633
statement_before_selected_expression : None ,
@@ -2669,21 +2675,50 @@ impl<'ast> ast::visit::Visit<'ast> for ExtractVariable<'ast> {
2669
2675
// A capture body is comprised of just a single expression statement
2670
2676
// that is inserted by the compiler, we don't really want to put
2671
2677
// anything before that; so in this case we avoid tracking it.
2672
- if ! self . inside_capture_body {
2678
+ if self . position != Some ( ExtractVariablePosition :: InsideCaptureBody ) {
2673
2679
self . latest_statement = Some ( stmt. location ( ) ) ;
2674
2680
}
2681
+
2682
+ let previous_position = self . position ;
2683
+ self . position = Some ( ExtractVariablePosition :: TopLevelStatement ) ;
2675
2684
ast:: visit:: visit_typed_statement ( self , stmt) ;
2685
+ self . position = previous_position;
2676
2686
}
2677
2687
2678
2688
fn visit_typed_expr ( & mut self , expr : & ' ast TypedExpr ) {
2679
2689
let expr_location = expr. location ( ) ;
2680
2690
let expr_range = self . edits . src_span_to_lsp_range ( expr_location) ;
2681
- if within ( self . params . range , expr_range) {
2691
+
2692
+ // If the expression is a top level statement we don't want to extract
2693
+ // it into a variable. It would mean we would turn this:
2694
+ //
2695
+ // ```gleam
2696
+ // pub fn main() {
2697
+ // let wibble = 1
2698
+ // // ^ cursor here
2699
+ // }
2700
+ //
2701
+ // // into:
2702
+ //
2703
+ // pub fn main() {
2704
+ // let value = 1
2705
+ // let wibble = value
2706
+ // }
2707
+ // ```
2708
+ //
2709
+ // Not all that useful!
2710
+ //
2711
+ if self . position != Some ( ExtractVariablePosition :: TopLevelStatement )
2712
+ && within ( self . params . range , expr_range)
2713
+ {
2682
2714
self . selected_expression = Some ( expr_location) ;
2683
2715
self . statement_before_selected_expression = self . latest_statement ;
2684
2716
}
2685
2717
2718
+ let previous_position = self . position ;
2719
+ self . position = None ;
2686
2720
ast:: visit:: visit_typed_expr ( self , expr) ;
2721
+ self . position = previous_position;
2687
2722
}
2688
2723
2689
2724
fn visit_typed_expr_fn (
@@ -2695,15 +2730,18 @@ impl<'ast> ast::visit::Visit<'ast> for ExtractVariable<'ast> {
2695
2730
body : & ' ast [ TypedStatement ] ,
2696
2731
return_annotation : & ' ast Option < ast:: TypeAst > ,
2697
2732
) {
2698
- self . inside_capture_body = match kind {
2733
+ let previous_position = self . position ;
2734
+ self . position = match kind {
2699
2735
// If a fn is a capture `int.wibble(1, _)` its body will consist of
2700
2736
// just a single expression statement. When visiting we must record
2701
2737
// we're inside a capture body.
2702
- FunctionLiteralKind :: Capture => true ,
2703
- FunctionLiteralKind :: Anonymous { .. } | FunctionLiteralKind :: Use { .. } => false ,
2738
+ FunctionLiteralKind :: Capture => Some ( ExtractVariablePosition :: InsideCaptureBody ) ,
2739
+ FunctionLiteralKind :: Anonymous { .. } | FunctionLiteralKind :: Use { .. } => {
2740
+ self . position
2741
+ }
2704
2742
} ;
2705
2743
ast:: visit:: visit_typed_expr_fn ( self , location, type_, kind, args, body, return_annotation) ;
2706
- self . inside_capture_body = false ;
2744
+ self . position = previous_position ;
2707
2745
}
2708
2746
2709
2747
// We don't want to offer the action if the cursor is over a variable
0 commit comments