@@ -35,7 +35,12 @@ defmodule ElixirLS.Debugger.Server do
35
35
task_ref: nil ,
36
36
threads: % { } ,
37
37
threads_inverse: % { } ,
38
- paused_processes: % { } ,
38
+ paused_processes: % {
39
+ evaluator: % {
40
+ vars: % { } ,
41
+ vars_inverse: % { }
42
+ }
43
+ } ,
39
44
next_id: 1 ,
40
45
output: Output ,
41
46
breakpoints: % { } ,
@@ -499,15 +504,26 @@ defmodule ElixirLS.Debugger.Server do
499
504
end
500
505
501
506
defp handle_request (
502
- request ( _cmd , "evaluate" , % { "expression" => expr } = _args ) ,
507
+ request ( _cmd , "evaluate" , % { "expression" => expr } = args ) ,
503
508
state = % __MODULE__ { }
504
509
) do
505
510
timeout = Map . get ( state . config , "debugExpressionTimeoutMs" , 10_000 )
506
- bindings = all_variables ( state . paused_processes )
511
+ bindings = all_variables ( state . paused_processes , args [ "frameId" ] )
512
+
513
+ value = evaluate_code_expression ( expr , bindings , timeout )
507
514
508
- result = evaluate_code_expression ( expr , bindings , timeout )
515
+ child_type = Variables . child_type ( value )
516
+ { state , var_id } = get_variable_reference ( child_type , state , :evaluator , value )
517
+
518
+ json =
519
+ % {
520
+ "result" => inspect ( value ) ,
521
+ "variablesReference" => var_id
522
+ }
523
+ |> maybe_append_children_number ( state . client_info , child_type , value )
524
+ |> maybe_append_variable_type ( state . client_info , value )
509
525
510
- { % { "result" => inspect ( result ) , "variablesReference" => 0 } , state }
526
+ { json , state }
511
527
end
512
528
513
529
defp handle_request ( continue_req ( _ , thread_id ) , state = % __MODULE__ { } ) do
@@ -623,34 +639,39 @@ defmodule ElixirLS.Debugger.Server do
623
639
end
624
640
625
641
Enum . reduce ( children , { state , [ ] } , fn { name , value } , { state = % __MODULE__ { } , result } ->
626
- num_children = Variables . num_children ( value )
627
642
child_type = Variables . child_type ( value )
628
-
629
- { state , var_id } =
630
- if child_type do
631
- ensure_var_id ( state , pid , value )
632
- else
633
- { state , 0 }
634
- end
635
-
636
- json = % {
637
- "name" => to_string ( name ) ,
638
- "value" => inspect ( value ) ,
639
- "variablesReference" => var_id ,
640
- "type" => Variables . type ( value )
641
- }
643
+ { state , var_id } = get_variable_reference ( child_type , state , pid , value )
642
644
643
645
json =
644
- case child_type do
645
- :indexed -> Map . put ( json , "indexedVariables" , num_children )
646
- :named -> Map . put ( json , "namedVariables" , num_children )
647
- nil -> json
648
- end
646
+ % {
647
+ "name" => to_string ( name ) ,
648
+ "value" => inspect ( value ) ,
649
+ "variablesReference" => var_id
650
+ }
651
+ |> maybe_append_children_number ( state . client_info , child_type , value )
652
+ |> maybe_append_variable_type ( state . client_info , value )
649
653
650
654
{ state , result ++ [ json ] }
651
655
end )
652
656
end
653
657
658
+ defp get_variable_reference ( nil , state , _pid , _value ) , do: { state , 0 }
659
+
660
+ defp get_variable_reference ( _child_type , state , pid , value ) ,
661
+ do: ensure_var_id ( state , pid , value )
662
+
663
+ defp maybe_append_children_number ( map , % { "supportsVariablePaging" => true } , atom , value )
664
+ when atom in [ :indexed , :named ] ,
665
+ do: Map . put ( map , Atom . to_string ( atom ) <> "Variables" , Variables . num_children ( value ) )
666
+
667
+ defp maybe_append_children_number ( map , _ , _ , _value ) , do: map
668
+
669
+ defp maybe_append_variable_type ( map , % { "supportsVariableType" => true } , value ) do
670
+ Map . put ( map , "type" , Variables . type ( value ) )
671
+ end
672
+
673
+ defp maybe_append_variable_type ( map , _ , _value ) , do: map
674
+
654
675
defp evaluate_code_expression ( expr , bindings , timeout ) do
655
676
task =
656
677
Task . async ( fn ->
@@ -678,34 +699,53 @@ defmodule ElixirLS.Debugger.Server do
678
699
end
679
700
end
680
701
681
- defp all_variables ( paused_processes ) do
702
+ defp all_variables ( paused_processes , nil ) do
682
703
paused_processes
683
- |> Enum . flat_map ( fn { _pid , % PausedProcess { } = paused_process } ->
684
- paused_process . frames |> Map . values ( )
704
+ |> Enum . flat_map ( fn
705
+ { :evaluator , _ } ->
706
+ # TODO setVariable?
707
+ [ ]
708
+
709
+ { _pid , % PausedProcess { } = paused_process } ->
710
+ paused_process . frames |> Map . values ( )
685
711
end )
686
712
|> Enum . filter ( & match? ( % Frame { bindings: bindings } when is_map ( bindings ) , & 1 ) )
687
713
|> Enum . flat_map ( fn % Frame { bindings: bindings } ->
688
714
Binding . to_elixir_variable_names ( bindings )
689
715
end )
690
716
end
691
717
718
+ defp all_variables ( paused_processes , frame_id ) do
719
+ case find_frame ( paused_processes , frame_id ) do
720
+ { _pid , % Frame { bindings: bindings } } when is_map ( bindings ) ->
721
+ Binding . to_elixir_variable_names ( bindings )
722
+
723
+ _ ->
724
+ [ ]
725
+ end
726
+ end
727
+
692
728
defp find_var ( paused_processes , var_id ) do
693
- Enum . find_value ( paused_processes , fn { pid , % PausedProcess { } = paused_process } ->
694
- if Map . has_key? ( paused_process . vars , var_id ) do
695
- { pid , paused_process . vars [ var_id ] }
729
+ Enum . find_value ( paused_processes , fn { pid , % { vars: vars } } ->
730
+ if Map . has_key? ( vars , var_id ) do
731
+ { pid , vars [ var_id ] }
696
732
end
697
733
end )
698
734
end
699
735
700
736
defp find_frame ( paused_processes , frame_id ) do
701
- Enum . find_value ( paused_processes , fn { pid , % PausedProcess { } = paused_process } ->
702
- if Map . has_key? ( paused_process . frames , frame_id ) do
703
- { pid , paused_process . frames [ frame_id ] }
704
- end
737
+ Enum . find_value ( paused_processes , fn
738
+ { pid , % { frames: frames } } ->
739
+ if Map . has_key? ( frames , frame_id ) do
740
+ { pid , frames [ frame_id ] }
741
+ end
742
+
743
+ { :evaluator , _ } ->
744
+ nil
705
745
end )
706
746
end
707
747
708
- defp ensure_thread_id ( state = % __MODULE__ { } , pid ) do
748
+ defp ensure_thread_id ( state = % __MODULE__ { } , pid ) when is_pid ( pid ) do
709
749
if Map . has_key? ( state . threads_inverse , pid ) do
710
750
{ state , state . threads_inverse [ pid ] }
711
751
else
@@ -724,7 +764,7 @@ defmodule ElixirLS.Debugger.Server do
724
764
end )
725
765
end
726
766
727
- defp ensure_var_id ( state = % __MODULE__ { } , pid , var ) do
767
+ defp ensure_var_id ( state = % __MODULE__ { } , pid , var ) when is_pid ( pid ) or pid == :evaluator do
728
768
unless Map . has_key? ( state . paused_processes , pid ) do
729
769
raise ArgumentError , message: "paused process #{ inspect ( pid ) } not found"
730
770
end
@@ -747,7 +787,7 @@ defmodule ElixirLS.Debugger.Server do
747
787
end )
748
788
end
749
789
750
- defp ensure_frame_id ( state = % __MODULE__ { } , pid , % Frame { } = frame ) do
790
+ defp ensure_frame_id ( state = % __MODULE__ { } , pid , % Frame { } = frame ) when is_pid ( pid ) do
751
791
unless Map . has_key? ( state . paused_processes , pid ) do
752
792
raise ArgumentError , message: "paused process #{ inspect ( pid ) } not found"
753
793
end
0 commit comments