diff --git a/lib/debug/config.rb b/lib/debug/config.rb index 8b176ae09..7e86576ec 100644 --- a/lib/debug/config.rb +++ b/lib/debug/config.rb @@ -42,6 +42,7 @@ module DEBUGGER__ host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host", :string, "127.0.0.1"], sock_path: ['RUBY_DEBUG_SOCK_PATH', "REMOTE: UNIX Domain Socket remote debugging: socket path"], sock_dir: ['RUBY_DEBUG_SOCK_DIR', "REMOTE: UNIX Domain Socket remote debugging: socket directory"], + local_fs_map: ['RUBY_DEBUG_LOCAL_FS_MAP', "REMOTE: Specify local fs map", :path_map], cookie: ['RUBY_DEBUG_COOKIE', "REMOTE: Cookie for negotiation"], open_frontend: ['RUBY_DEBUG_OPEN_FRONTEND',"REMOTE: frontend used by open command (vscode, chrome, default: rdbg)."], chrome_path: ['RUBY_DEBUG_CHROME_PATH', "REMOTE: Platform dependent path of Chrome (For more information, See [here](https://github.com/ruby/debug/pull/334/files#diff-5fc3d0a901379a95bc111b86cf0090b03f857edfd0b99a0c1537e26735698453R55-R64))"], @@ -238,6 +239,8 @@ def self.parse_config_value name, valstr e end } + when :path_map + valstr.split(',').map{|e| e.split(':')} else valstr end @@ -384,6 +387,8 @@ def self.config_to_env_hash config case CONFIG_SET[key][2] when :path valstr = config[key].map{|e| e.kind_of?(Regexp) ? e.inspect : e}.join(':') + when :path_map + valstr = config[key].map{|e| e.join(':')}.join(',') else valstr = config[key].to_s end diff --git a/lib/debug/server_dap.rb b/lib/debug/server_dap.rb index cbb10fe40..8754945c9 100644 --- a/lib/debug/server_dap.rb +++ b/lib/debug/server_dap.rb @@ -70,14 +70,39 @@ def show_protocol dir, msg end end - @local_fs = false + # true: all localfs + # Array: part of localfs + # nil: no localfs + @local_fs_map = nil + + def self.local_fs_map_path path + case @local_fs_map + when nil + false + when true + path + else # Array + @local_fs_map.each do |(remote_path_prefix, local_path_prefix)| + if path.start_with? remote_path_prefix + return path.sub(remote_path_prefix){ local_path_prefix } + end + end - def self.local_fs - @local_fs + nil + end end - def self.local_fs_set - @local_fs = true + def self.local_fs_map_set map + return if @local_fs_map # already setup + + case map + when String + @local_fs_map = map.split(',').map{|e| e.split(':')} + when true + @local_fs_map = map + when nil + @local_fs_map = CONFIG[:local_fs_map] + end end def dap_setup bytes @@ -86,7 +111,7 @@ def dap_setup bytes case self when UI_UnixDomainServer - UI_DAP.local_fs_set + UI_DAP.local_fs_map_set true when UI_TcpServer # TODO: loopback address can be used to connect other FS env, like Docker containers # UI_DAP.local_fs_set if @local_addr.ipv4_loopback? || @local_addr.ipv6_loopback? @@ -228,12 +253,12 @@ def process when 'launch' send_response req @is_attach = false - UI_DAP.local_fs_set if req.dig('arguments', 'localfs') + UI_DAP.local_fs_map_set req.dig('arguments', 'localfs') || req.dig('arguments', 'localfsMap') when 'attach' send_response req Process.kill(UI_ServerBase::TRAP_SIGNAL, Process.pid) @is_attach = true - UI_DAP.local_fs_set if req.dig('arguments', 'localfs') + UI_DAP.local_fs_map_set req.dig('arguments', 'localfs') || req.dig('arguments', 'localfsMap') when 'setBreakpoints' path = args.dig('source', 'path') SESSION.clear_line_breakpoints path @@ -637,7 +662,9 @@ def process_dap args path = frame.realpath || frame.path source_name = path ? File.basename(path) : frame.location.to_s - if !UI_DAP.local_fs || !(path && File.exist?(path)) + if (path && File.exist?(path)) && (local_path = UI_DAP.local_fs_map_path(path)) + # ok + else ref = frame.file_lines end @@ -648,7 +675,7 @@ def process_dap args column: 1, source: { name: source_name, - path: path, + path: (local_path || path), sourceReference: ref, }, }