Skip to content

Proposal: Refactor server_dap to use command-registration style #931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 59 additions & 26 deletions lib/debug/server_dap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
module DEBUGGER__
module UI_DAP
SHOW_PROTOCOL = ENV['DEBUG_DAP_SHOW_PROTOCOL'] == '1' || ENV['RUBY_DEBUG_DAP_SHOW_PROTOCOL'] == '1'
REGISTERED_REQUESTS = {}

def self.setup debug_port
if File.directory? '.vscode'
Expand Down Expand Up @@ -64,6 +65,12 @@ def self.setup debug_port
end
end

def self.register_request *names, &b
names.each{|name|
REGISTERED_REQUESTS[name] = b
}
end

def show_protocol dir, msg
if SHOW_PROTOCOL
$stderr.puts "\##{Process.pid}:[#{dir}] #{msg}"
Expand Down Expand Up @@ -274,21 +281,15 @@ def recv_request
retry
end

def process
while req = recv_request
raise "not a request: #{req.inspect}" unless req['type'] == 'request'
args = req.dig('arguments')

case req['command']

## boot/configuration
when 'launch'
register_request 'launch' do |req|
send_response req
# `launch` runs on debuggee on the same file system
UI_DAP.local_fs_map_set req.dig('arguments', 'localfs') || req.dig('arguments', 'localfsMap') || true
@nonstop = true
end

when 'attach'
register_request 'attach' do |req|
send_response req
UI_DAP.local_fs_map_set req.dig('arguments', 'localfs') || req.dig('arguments', 'localfsMap')

Expand All @@ -297,8 +298,9 @@ def process
else
@nonstop = false
end
end

when 'configurationDone'
register_request 'configurationDone' do |req|
send_response req

if @nonstop
Expand All @@ -310,8 +312,9 @@ def process
allThreadsStopped: true
end
end
end

when 'setBreakpoints'
register_request 'setBreakpoints' do |req, args|
req_path = args.dig('source', 'path')
path = UI_DAP.local_to_remote_path(req_path)

Expand All @@ -331,11 +334,13 @@ def process
else
send_response req, success: false, message: "#{req_path} is not available"
end
end

when 'setFunctionBreakpoints'
register_request 'setFunctionBreakpoints' do |req|
send_response req
end

when 'setExceptionBreakpoints'
register_request 'setExceptionBreakpoints' do |req, args|
process_filter = ->(filter_id, cond = nil) {
bp =
case filter_id
Expand Down Expand Up @@ -363,8 +368,9 @@ def process
}

send_response req, breakpoints: filters
end

when 'disconnect'
register_request('disconnect') do |req, args|
terminate = args.fetch("terminateDebuggee", false)

SESSION.clear_all_breakpoints
Expand All @@ -382,12 +388,15 @@ def process
pause
end
end
end

## control
when 'continue'
register_request 'continue' do |req|
@q_msg << 'c'
send_response req, allThreadsContinued: true
when 'next'
end

register_request 'next' do |req|
begin
@session.check_postmortem
@q_msg << 'n'
Expand All @@ -397,7 +406,9 @@ def process
success: false, message: 'postmortem mode',
result: "'Next' is not supported while postmortem mode"
end
when 'stepIn'
end

register_request 'stepIn' do |req|
begin
@session.check_postmortem
@q_msg << 's'
Expand All @@ -407,7 +418,9 @@ def process
success: false, message: 'postmortem mode',
result: "'stepIn' is not supported while postmortem mode"
end
when 'stepOut'
end

register_request 'stepOut' do |req|
begin
@session.check_postmortem
@q_msg << 'fin'
Expand All @@ -417,28 +430,38 @@ def process
success: false, message: 'postmortem mode',
result: "'stepOut' is not supported while postmortem mode"
end
when 'terminate'
end

register_request 'terminate' do |req|
send_response req
exit
when 'pause'
end

register_request 'pause' do |req|
send_response req
Process.kill(UI_ServerBase::TRAP_SIGNAL, Process.pid)
when 'reverseContinue'
end

register_request 'reverseContinue' do |req|
send_response req,
success: false, message: 'cancelled',
result: "Reverse Continue is not supported. Only \"Step back\" is supported."
when 'stepBack'
end

register_request 'stepBack' do |req|
@q_msg << req
end

## query
when 'threads'
register_request 'threads' do |req|
send_response req, threads: SESSION.managed_thread_clients.map{|tc|
{ id: tc.id,
name: tc.name,
}
}
end

when 'evaluate'
register_request 'evaluate' do |req|
expr = req.dig('arguments', 'expression')
if /\A\s*,(.+)\z/ =~ expr
dbg_expr = $1
Expand All @@ -449,13 +472,23 @@ def process
else
@q_msg << req
end
when 'stackTrace',
end

register_request 'stackTrace',
'scopes',
'variables',
'source',
'completions'
'completions' do |req|
@q_msg << req
end

def process
while req = recv_request
raise "not a request: #{req.inspect}" unless req['type'] == 'request'
args = req.dig('arguments')

if (cmd = REGISTERED_REQUESTS[req['command']])
self.instance_exec(req, args, &cmd)
else
if respond_to? mid = "request_#{req['command']}"
__send__ mid, req
Expand Down