debug 1.6.2 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,7 +18,7 @@ module DEBUGGER__
18
18
  end
19
19
 
20
20
  at_exit do
21
- CONFIG.skip_all
21
+ DEBUGGER__.skip_all
22
22
  FileUtils.rm_rf dir if tempdir
23
23
  end
24
24
 
@@ -128,7 +128,8 @@ module DEBUGGER__
128
128
 
129
129
  case self
130
130
  when UI_UnixDomainServer
131
- UI_DAP.local_fs_map_set true
131
+ # If the user specified a mapping, respect it, otherwise, make sure that no mapping is used
132
+ UI_DAP.local_fs_map_set CONFIG[:local_fs_map] || true
132
133
  when UI_TcpServer
133
134
  # TODO: loopback address can be used to connect other FS env, like Docker containers
134
135
  # UI_DAP.local_fs_set if @local_addr.ipv4_loopback? || @local_addr.ipv6_loopback?
@@ -198,6 +199,13 @@ module DEBUGGER__
198
199
  # supportsInstructionBreakpoints:
199
200
  )
200
201
  send_event 'initialized'
202
+ puts <<~WELCOME
203
+ Ruby REPL: You can run any Ruby expression here.
204
+ Note that output to the STDOUT/ERR printed on the TERMINAL.
205
+ [experimental]
206
+ `,COMMAND` runs `COMMAND` debug command (ex: `,info`).
207
+ `,help` to list all debug commands.
208
+ WELCOME
201
209
  end
202
210
 
203
211
  def send **kw
@@ -271,18 +279,24 @@ module DEBUGGER__
271
279
  ## boot/configuration
272
280
  when 'launch'
273
281
  send_response req
274
- UI_DAP.local_fs_map_set req.dig('arguments', 'localfs') || req.dig('arguments', 'localfsMap')
275
- @is_launch = true
282
+ # `launch` runs on debuggee on the same file system
283
+ UI_DAP.local_fs_map_set req.dig('arguments', 'localfs') || req.dig('arguments', 'localfsMap') || true
284
+ @nonstop = true
276
285
 
277
286
  when 'attach'
278
287
  send_response req
279
288
  UI_DAP.local_fs_map_set req.dig('arguments', 'localfs') || req.dig('arguments', 'localfsMap')
280
- @is_launch = false
289
+
290
+ if req.dig('arguments', 'nonstop') == true
291
+ @nonstop = true
292
+ else
293
+ @nonstop = false
294
+ end
281
295
 
282
296
  when 'configurationDone'
283
297
  send_response req
284
298
 
285
- if @is_launch
299
+ if @nonstop
286
300
  @q_msg << 'continue'
287
301
  else
288
302
  if SESSION.in_subsession?
@@ -419,16 +433,30 @@ module DEBUGGER__
419
433
  }
420
434
  }
421
435
 
436
+ when 'evaluate'
437
+ expr = req.dig('arguments', 'expression')
438
+ if /\A\s*,(.+)\z/ =~ expr
439
+ dbg_expr = $1
440
+ send_response req,
441
+ result: "",
442
+ variablesReference: 0
443
+ debugger do: dbg_expr
444
+ else
445
+ @q_msg << req
446
+ end
422
447
  when 'stackTrace',
423
448
  'scopes',
424
449
  'variables',
425
- 'evaluate',
426
450
  'source',
427
451
  'completions'
428
452
  @q_msg << req
429
453
 
430
454
  else
431
- raise "Unknown request: #{req.inspect}"
455
+ if respond_to? mid = "request_#{req['command']}"
456
+ send mid, req
457
+ else
458
+ raise "Unknown request: #{req.inspect}"
459
+ end
432
460
  end
433
461
  end
434
462
  ensure
@@ -443,7 +471,11 @@ module DEBUGGER__
443
471
 
444
472
  def puts result
445
473
  # STDERR.puts "puts: #{result}"
446
- # send_event 'output', category: 'stderr', output: "PUTS!!: " + result.to_s
474
+ send_event 'output', category: 'console', output: "#{result&.chomp}\n"
475
+ end
476
+
477
+ def ignore_output_on_suspend?
478
+ true
447
479
  end
448
480
 
449
481
  def event type, *args
@@ -488,6 +520,8 @@ module DEBUGGER__
488
520
  end
489
521
 
490
522
  class Session
523
+ include GlobalVariablesHelper
524
+
491
525
  def find_waiting_tc id
492
526
  @th_clients.each{|th, tc|
493
527
  return tc if tc.id == id && tc.waiting?
@@ -534,8 +568,12 @@ module DEBUGGER__
534
568
  if ref = @var_map[varid]
535
569
  case ref[0]
536
570
  when :globals
537
- vars = global_variables.map do |name|
538
- gv = 'Not implemented yet...'
571
+ vars = safe_global_variables.sort.map do |name|
572
+ begin
573
+ gv = eval(name.to_s)
574
+ rescue Exception => e
575
+ gv = e.inspect
576
+ end
539
577
  {
540
578
  name: name,
541
579
  value: gv.inspect,
@@ -580,6 +618,7 @@ module DEBUGGER__
580
618
  if @frame_map[frame_id]
581
619
  tid, fid = @frame_map[frame_id]
582
620
  expr = req.dig('arguments', 'expression')
621
+
583
622
  if tc = find_waiting_tc(tid)
584
623
  request_tc [:dap, :evaluate, req, fid, expr, context]
585
624
  else
@@ -684,10 +723,33 @@ module DEBUGGER__
684
723
  end
685
724
  end
686
725
 
726
+ class NaiveString
727
+ attr_reader :str
728
+ def initialize str
729
+ @str = str
730
+ end
731
+ end
732
+
687
733
  class ThreadClient
688
- def value_inspect obj
734
+ MAX_LENGTH = 180
735
+
736
+ def value_inspect obj, short: true
689
737
  # TODO: max length should be configuarable?
690
- DEBUGGER__.safe_inspect obj, short: true, max_length: 4 * 1024
738
+ str = DEBUGGER__.safe_inspect obj, short: short, max_length: MAX_LENGTH
739
+
740
+ if str.encoding == Encoding::UTF_8
741
+ str.scrub
742
+ else
743
+ str.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
744
+ end
745
+ end
746
+
747
+ def dap_eval b, expr, _context, prompt: '(repl_eval)'
748
+ begin
749
+ b.eval(expr.to_s, prompt)
750
+ rescue Exception => e
751
+ e
752
+ end
691
753
  end
692
754
 
693
755
  def process_dap args
@@ -702,9 +764,10 @@ module DEBUGGER__
702
764
  frames = []
703
765
  @target_frames.each_with_index do |frame, i|
704
766
  next if i < start_frame
705
- break if (levels -= 1) < 0
706
767
 
707
768
  path = frame.realpath || frame.path
769
+ next if skip_path?(path) && !SESSION.stop_stepping?(path, frame.location.lineno)
770
+ break if (levels -= 1) < 0
708
771
  source_name = path ? File.basename(path) : frame.location.to_s
709
772
 
710
773
  if (path && File.exist?(path)) && (local_path = UI_DAP.remote_to_local_path(path))
@@ -754,7 +817,7 @@ module DEBUGGER__
754
817
  name: 'Global variables',
755
818
  presentationHint: 'globals',
756
819
  variablesReference: 1, # GLOBAL
757
- namedVariables: global_variables.size,
820
+ namedVariables: safe_global_variables.size,
758
821
  indexedVariables: 0,
759
822
  expensive: false,
760
823
  }]
@@ -791,14 +854,13 @@ module DEBUGGER__
791
854
  }
792
855
  when String
793
856
  vars = [
794
- variable('#length', obj.length),
795
- variable('#encoding', obj.encoding)
857
+ variable('#lengthddsfsd', obj.length),
858
+ variable('#encoding', obj.encoding),
796
859
  ]
860
+ printed_str = value_inspect(obj)
861
+ vars << variable('#dump', NaiveString.new(obj)) if printed_str.end_with?('...')
797
862
  when Class, Module
798
- vars = obj.instance_variables.map{|iv|
799
- variable(iv, obj.instance_variable_get(iv))
800
- }
801
- vars.unshift variable('%ancestors', obj.ancestors[1..])
863
+ vars << variable('%ancestors', obj.ancestors[1..])
802
864
  when Range
803
865
  vars = [
804
866
  variable('#begin', obj.begin),
@@ -806,10 +868,12 @@ module DEBUGGER__
806
868
  ]
807
869
  end
808
870
 
809
- vars += M_INSTANCE_VARIABLES.bind_call(obj).map{|iv|
810
- variable(iv, M_INSTANCE_VARIABLE_GET.bind_call(obj, iv))
811
- }
812
- vars.unshift variable('#class', M_CLASS.bind_call(obj))
871
+ unless NaiveString === obj
872
+ vars += M_INSTANCE_VARIABLES.bind_call(obj).sort.map{|iv|
873
+ variable(iv, M_INSTANCE_VARIABLE_GET.bind_call(obj, iv))
874
+ }
875
+ vars.unshift variable('#class', M_CLASS.bind_call(obj))
876
+ end
813
877
  end
814
878
  end
815
879
  event! :dap_result, :variable, req, variables: (vars || []), tid: self.id
@@ -826,12 +890,7 @@ module DEBUGGER__
826
890
 
827
891
  case context
828
892
  when 'repl', 'watch'
829
- begin
830
- result = b.eval(expr.to_s, '(DEBUG CONSOLE)')
831
- rescue Exception => e
832
- result = e
833
- end
834
-
893
+ result = dap_eval b, expr, context, prompt: '(DEBUG CONSOLE)'
835
894
  when 'hover'
836
895
  case expr
837
896
  when /\A\@\S/
@@ -841,7 +900,7 @@ module DEBUGGER__
841
900
  message = "Error: Not defined instance variable: #{expr.inspect}"
842
901
  end
843
902
  when /\A\$\S/
844
- global_variables.each{|gvar|
903
+ safe_global_variables.each{|gvar|
845
904
  if gvar.to_s == expr
846
905
  result = eval(gvar.to_s)
847
906
  break false
@@ -911,10 +970,14 @@ module DEBUGGER__
911
970
 
912
971
  def search_const b, expr
913
972
  cs = expr.delete_prefix('::').split('::')
914
- [Object, *b.eval('Module.nesting')].reverse_each{|mod|
973
+ [Object, *b.eval('::Module.nesting')].reverse_each{|mod|
915
974
  if cs.all?{|c|
916
975
  if mod.const_defined?(c)
917
- mod = mod.const_get(c)
976
+ begin
977
+ mod = mod.const_get(c)
978
+ rescue Exception
979
+ false
980
+ end
918
981
  else
919
982
  false
920
983
  end
@@ -927,11 +990,17 @@ module DEBUGGER__
927
990
  end
928
991
 
929
992
  def evaluate_result r
930
- v = variable nil, r
931
- v.delete :name
932
- v.delete :value
933
- v[:result] = value_inspect(r)
934
- v
993
+ variable nil, r
994
+ end
995
+
996
+ def type_name obj
997
+ klass = M_CLASS.bind_call(obj)
998
+
999
+ begin
1000
+ klass.name || klass.to_s
1001
+ rescue Exception => e
1002
+ "<Error: #{e.message} (#{e.backtrace.first}>"
1003
+ end
935
1004
  end
936
1005
 
937
1006
  def variable_ name, obj, indexedVariables: 0, namedVariables: 0
@@ -942,15 +1011,31 @@ module DEBUGGER__
942
1011
  vid = 0
943
1012
  end
944
1013
 
945
- ivnum = M_INSTANCE_VARIABLES.bind_call(obj).size
1014
+ namedVariables += M_INSTANCE_VARIABLES.bind_call(obj).size
946
1015
 
947
- { name: name,
948
- value: value_inspect(obj),
949
- type: (klass = M_CLASS.bind_call(obj)).name || klass.to_s,
950
- variablesReference: vid,
951
- indexedVariables: indexedVariables,
952
- namedVariables: namedVariables + ivnum,
953
- }
1016
+ if NaiveString === obj
1017
+ str = obj.str.dump
1018
+ vid = indexedVariables = namedVariables = 0
1019
+ else
1020
+ str = value_inspect(obj)
1021
+ end
1022
+
1023
+ if name
1024
+ { name: name,
1025
+ value: str,
1026
+ type: type_name(obj),
1027
+ variablesReference: vid,
1028
+ indexedVariables: indexedVariables,
1029
+ namedVariables: namedVariables,
1030
+ }
1031
+ else
1032
+ { result: str,
1033
+ type: type_name(obj),
1034
+ variablesReference: vid,
1035
+ indexedVariables: indexedVariables,
1036
+ namedVariables: namedVariables,
1037
+ }
1038
+ end
954
1039
  end
955
1040
 
956
1041
  def variable name, obj
@@ -960,7 +1045,7 @@ module DEBUGGER__
960
1045
  when Hash
961
1046
  variable_ name, obj, namedVariables: obj.size
962
1047
  when String
963
- variable_ name, obj, namedVariables: 3 # #to_str, #length, #encoding
1048
+ variable_ name, obj, namedVariables: 3 # #length, #encoding, #to_str
964
1049
  when Struct
965
1050
  variable_ name, obj, namedVariables: obj.size
966
1051
  when Class, Module