debug 1.6.3 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
@@ -914,7 +973,11 @@ module DEBUGGER__
914
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