debug 1.6.3 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|