debug 1.6.3 → 1.7.0
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.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +19 -7
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +37 -14
- data/Rakefile +0 -0
- data/TODO.md +0 -0
- data/debug.gemspec +1 -1
- data/exe/rdbg +1 -1
- data/ext/debug/debug.c +15 -1
- data/ext/debug/extconf.rb +0 -0
- data/ext/debug/iseq_collector.c +0 -0
- data/lib/debug/abbrev_command.rb +77 -0
- data/lib/debug/breakpoint.rb +17 -11
- data/lib/debug/client.rb +26 -9
- data/lib/debug/color.rb +0 -0
- data/lib/debug/config.rb +34 -16
- data/lib/debug/console.rb +0 -0
- data/lib/debug/frame_info.rb +0 -0
- data/lib/debug/local.rb +16 -10
- data/lib/debug/open.rb +0 -0
- data/lib/debug/open_nonstop.rb +0 -0
- data/lib/debug/prelude.rb +0 -0
- data/lib/debug/server.rb +25 -21
- data/lib/debug/server_cdp.rb +281 -80
- data/lib/debug/server_dap.rb +109 -37
- data/lib/debug/session.rb +384 -204
- data/lib/debug/source_repository.rb +39 -19
- data/lib/debug/start.rb +1 -1
- data/lib/debug/thread_client.rb +186 -60
- data/lib/debug/tracer.rb +0 -0
- data/lib/debug/version.rb +1 -1
- data/lib/debug.rb +7 -3
- data/misc/README.md.erb +9 -3
- metadata +5 -4
data/lib/debug/server_dap.rb
CHANGED
@@ -18,7 +18,7 @@ module DEBUGGER__
|
|
18
18
|
end
|
19
19
|
|
20
20
|
at_exit do
|
21
|
-
|
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
|
-
|
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
|
-
|
275
|
-
|
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
|
-
|
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 @
|
299
|
+
if @nonstop
|
286
300
|
@q_msg << 'continue'
|
287
301
|
else
|
288
302
|
if SESSION.in_subsession?
|
@@ -419,10 +433,20 @@ 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
|
@@ -443,7 +467,11 @@ module DEBUGGER__
|
|
443
467
|
|
444
468
|
def puts result
|
445
469
|
# STDERR.puts "puts: #{result}"
|
446
|
-
|
470
|
+
send_event 'output', category: 'console', output: "#{result&.chomp}\n"
|
471
|
+
end
|
472
|
+
|
473
|
+
def ignore_output_on_suspend?
|
474
|
+
true
|
447
475
|
end
|
448
476
|
|
449
477
|
def event type, *args
|
@@ -534,8 +562,8 @@ module DEBUGGER__
|
|
534
562
|
if ref = @var_map[varid]
|
535
563
|
case ref[0]
|
536
564
|
when :globals
|
537
|
-
vars = global_variables.map do |name|
|
538
|
-
gv =
|
565
|
+
vars = global_variables.sort.map do |name|
|
566
|
+
gv = eval(name.to_s)
|
539
567
|
{
|
540
568
|
name: name,
|
541
569
|
value: gv.inspect,
|
@@ -580,6 +608,7 @@ module DEBUGGER__
|
|
580
608
|
if @frame_map[frame_id]
|
581
609
|
tid, fid = @frame_map[frame_id]
|
582
610
|
expr = req.dig('arguments', 'expression')
|
611
|
+
|
583
612
|
if tc = find_waiting_tc(tid)
|
584
613
|
request_tc [:dap, :evaluate, req, fid, expr, context]
|
585
614
|
else
|
@@ -684,10 +713,26 @@ module DEBUGGER__
|
|
684
713
|
end
|
685
714
|
end
|
686
715
|
|
716
|
+
class NaiveString
|
717
|
+
attr_reader :str
|
718
|
+
def initialize str
|
719
|
+
@str = str
|
720
|
+
end
|
721
|
+
end
|
722
|
+
|
687
723
|
class ThreadClient
|
688
|
-
|
724
|
+
|
725
|
+
MAX_LENGTH = 180
|
726
|
+
|
727
|
+
def value_inspect obj, short: true
|
689
728
|
# TODO: max length should be configuarable?
|
690
|
-
DEBUGGER__.safe_inspect obj, short:
|
729
|
+
str = DEBUGGER__.safe_inspect obj, short: short, max_length: MAX_LENGTH
|
730
|
+
|
731
|
+
if str.encoding == Encoding::UTF_8
|
732
|
+
str.scrub
|
733
|
+
else
|
734
|
+
str.encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
|
735
|
+
end
|
691
736
|
end
|
692
737
|
|
693
738
|
def process_dap args
|
@@ -702,9 +747,10 @@ module DEBUGGER__
|
|
702
747
|
frames = []
|
703
748
|
@target_frames.each_with_index do |frame, i|
|
704
749
|
next if i < start_frame
|
705
|
-
break if (levels -= 1) < 0
|
706
750
|
|
707
751
|
path = frame.realpath || frame.path
|
752
|
+
next if skip_path?(path) && !SESSION.stop_stepping?(path, frame.location.lineno)
|
753
|
+
break if (levels -= 1) < 0
|
708
754
|
source_name = path ? File.basename(path) : frame.location.to_s
|
709
755
|
|
710
756
|
if (path && File.exist?(path)) && (local_path = UI_DAP.remote_to_local_path(path))
|
@@ -792,13 +838,11 @@ module DEBUGGER__
|
|
792
838
|
when String
|
793
839
|
vars = [
|
794
840
|
variable('#length', obj.length),
|
795
|
-
variable('#encoding', obj.encoding)
|
841
|
+
variable('#encoding', obj.encoding),
|
796
842
|
]
|
843
|
+
vars << variable('#dump', NaiveString.new(obj)) if obj.length > MAX_LENGTH
|
797
844
|
when Class, Module
|
798
|
-
vars
|
799
|
-
variable(iv, obj.instance_variable_get(iv))
|
800
|
-
}
|
801
|
-
vars.unshift variable('%ancestors', obj.ancestors[1..])
|
845
|
+
vars << variable('%ancestors', obj.ancestors[1..])
|
802
846
|
when Range
|
803
847
|
vars = [
|
804
848
|
variable('#begin', obj.begin),
|
@@ -806,10 +850,12 @@ module DEBUGGER__
|
|
806
850
|
]
|
807
851
|
end
|
808
852
|
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
853
|
+
unless NaiveString === obj
|
854
|
+
vars += M_INSTANCE_VARIABLES.bind_call(obj).sort.map{|iv|
|
855
|
+
variable(iv, M_INSTANCE_VARIABLE_GET.bind_call(obj, iv))
|
856
|
+
}
|
857
|
+
vars.unshift variable('#class', M_CLASS.bind_call(obj))
|
858
|
+
end
|
813
859
|
end
|
814
860
|
end
|
815
861
|
event! :dap_result, :variable, req, variables: (vars || []), tid: self.id
|
@@ -914,7 +960,11 @@ module DEBUGGER__
|
|
914
960
|
[Object, *b.eval('::Module.nesting')].reverse_each{|mod|
|
915
961
|
if cs.all?{|c|
|
916
962
|
if mod.const_defined?(c)
|
917
|
-
|
963
|
+
begin
|
964
|
+
mod = mod.const_get(c)
|
965
|
+
rescue Exception
|
966
|
+
false
|
967
|
+
end
|
918
968
|
else
|
919
969
|
false
|
920
970
|
end
|
@@ -927,11 +977,17 @@ module DEBUGGER__
|
|
927
977
|
end
|
928
978
|
|
929
979
|
def evaluate_result r
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
980
|
+
variable nil, r
|
981
|
+
end
|
982
|
+
|
983
|
+
def type_name obj
|
984
|
+
klass = M_CLASS.bind_call(obj)
|
985
|
+
|
986
|
+
begin
|
987
|
+
klass.name || klass.to_s
|
988
|
+
rescue Exception => e
|
989
|
+
"<Error: #{e.message} (#{e.backtrace.first}>"
|
990
|
+
end
|
935
991
|
end
|
936
992
|
|
937
993
|
def variable_ name, obj, indexedVariables: 0, namedVariables: 0
|
@@ -942,15 +998,31 @@ module DEBUGGER__
|
|
942
998
|
vid = 0
|
943
999
|
end
|
944
1000
|
|
945
|
-
|
1001
|
+
namedVariables += M_INSTANCE_VARIABLES.bind_call(obj).size
|
946
1002
|
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
1003
|
+
if NaiveString === obj
|
1004
|
+
str = obj.str.dump
|
1005
|
+
vid = indexedVariables = namedVariables = 0
|
1006
|
+
else
|
1007
|
+
str = value_inspect(obj)
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
if name
|
1011
|
+
{ name: name,
|
1012
|
+
value: str,
|
1013
|
+
type: type_name(obj),
|
1014
|
+
variablesReference: vid,
|
1015
|
+
indexedVariables: indexedVariables,
|
1016
|
+
namedVariables: namedVariables,
|
1017
|
+
}
|
1018
|
+
else
|
1019
|
+
{ result: str,
|
1020
|
+
type: type_name(obj),
|
1021
|
+
variablesReference: vid,
|
1022
|
+
indexedVariables: indexedVariables,
|
1023
|
+
namedVariables: namedVariables,
|
1024
|
+
}
|
1025
|
+
end
|
954
1026
|
end
|
955
1027
|
|
956
1028
|
def variable name, obj
|
@@ -960,7 +1032,7 @@ module DEBUGGER__
|
|
960
1032
|
when Hash
|
961
1033
|
variable_ name, obj, namedVariables: obj.size
|
962
1034
|
when String
|
963
|
-
variable_ name, obj, namedVariables: 3 # #
|
1035
|
+
variable_ name, obj, namedVariables: 3 # #length, #encoding, #to_str
|
964
1036
|
when Struct
|
965
1037
|
variable_ name, obj, namedVariables: obj.size
|
966
1038
|
when Class, Module
|