Module: MilkTea::DAP::Server::ServerDebugMap
- Included in:
- MilkTea::DAP::Server
- Defined in:
- lib/milk_tea/dap/server/debug_map.rb
Instance Method Summary collapse
- #accessor_identifier?(expression, index) ⇒ Boolean
- #clear_debug_context ⇒ Object
- #copy_quoted_segment(expression, index, output) ⇒ Object
- #debug_function_for_frame(frame_id) ⇒ Object
- #debug_function_for_variables_reference(variables_reference) ⇒ Object
- #identifier_continue_char?(char) ⇒ Boolean
- #identifier_start_char?(char) ⇒ Boolean
- #load_debug_map(runnable_path) ⇒ Object
- #maybe_load_debug_map_from_backend_modules ⇒ Object
- #request_set_variable(arguments) ⇒ Object
- #rewrite_data_breakpoint_info_arguments(arguments) ⇒ Object
- #rewrite_evaluate_arguments(arguments) ⇒ Object
- #rewrite_expression_for_frame(expression, frame_id) ⇒ Object
- #rewrite_expression_for_function(expression, function) ⇒ Object
- #rewrite_scopes_response(backend_response, frame_id) ⇒ Object
- #rewrite_set_expression_arguments(arguments) ⇒ Object
- #rewrite_set_variable_arguments(arguments) ⇒ Object
- #rewrite_stack_trace_response(backend_response) ⇒ Object
- #rewrite_variables_response(backend_response, variables_reference) ⇒ Object
- #variables_reference_context(variables_reference) ⇒ Object
- #whitespace_char?(char) ⇒ Boolean
Instance Method Details
#accessor_identifier?(expression, index) ⇒ Boolean
262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 262 def accessor_identifier?(expression, index) previous_index = index - 1 previous_index -= 1 while previous_index >= 0 && whitespace_char?(expression[previous_index]) return false if previous_index < 0 return true if expression[previous_index] == "." return false unless expression[previous_index] == ">" previous_index -= 1 previous_index -= 1 while previous_index >= 0 && whitespace_char?(expression[previous_index]) previous_index >= 0 && expression[previous_index] == "-" end |
#clear_debug_context ⇒ Object
38 39 40 41 42 43 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 38 def clear_debug_context @debug_map = nil @frame_debug_functions = {} @variables_reference_debug_functions = {} @backend_stopped_thread_id = nil end |
#copy_quoted_segment(expression, index, output) ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 240 def copy_quoted_segment(expression, index, output) quote = expression[index] output << quote index += 1 while index < expression.length char = expression[index] output << char index += 1 if char == "\\" && index < expression.length output << expression[index] index += 1 next end break if char == quote end index end |
#debug_function_for_frame(frame_id) ⇒ Object
227 228 229 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 227 def debug_function_for_frame(frame_id) @frame_debug_functions[normalize_reference_key(frame_id)] end |
#debug_function_for_variables_reference(variables_reference) ⇒ Object
231 232 233 234 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 231 def debug_function_for_variables_reference(variables_reference) context = variables_reference_context(variables_reference) context && context[:function] end |
#identifier_continue_char?(char) ⇒ Boolean
279 280 281 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 279 def identifier_continue_char?(char) char.match?(/[A-Za-z0-9_]/) end |
#identifier_start_char?(char) ⇒ Boolean
275 276 277 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 275 def identifier_start_char?(char) char.match?(/[A-Za-z_]/) end |
#load_debug_map(runnable_path) ⇒ Object
7 8 9 10 11 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 7 def load_debug_map(runnable_path) @debug_map = runnable_path ? DebugMap.load_for_binary(runnable_path) : nil @frame_debug_functions = {} @variables_reference_debug_functions = {} end |
#maybe_load_debug_map_from_backend_modules ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 13 def maybe_load_debug_map_from_backend_modules return if @debug_map return unless capability_enabled?("supportsModulesRequest") response = backend_request("modules", {}) return unless response["success"] modules = response.dig("body", "modules") return unless modules.is_a?(Array) modules.each do |mod| candidate_path = dap_value(mod, "path") || dap_value(mod, "symbolFilePath") next if candidate_path.to_s.empty? candidate_path = File.(candidate_path) debug_map = DebugMap.load_for_binary(candidate_path) next unless debug_map @debug_map = debug_map @frame_debug_functions = {} @variables_reference_debug_functions = {} return end end |
#request_set_variable(arguments) ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 157 def request_set_variable(arguments) return backend_request("setVariable", arguments) if backend_supports_set_variable? unless backend_supports_set_expression? return { "success" => false, "message" => "setVariable is not supported by the lldb-dap backend" } end context = variables_reference_context(arguments["variablesReference"]) frame_id = context && context[:frame_id] unless frame_id return { "success" => false, "message" => "setVariable requires a scope frame context" } end set_expression_arguments = { "expression" => arguments["name"], "value" => arguments["value"], "frameId" => frame_id, } set_expression_arguments["format"] = arguments["format"] if arguments.key?("format") backend_request("setExpression", set_expression_arguments) end |
#rewrite_data_breakpoint_info_arguments(arguments) ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 140 def rewrite_data_breakpoint_info_arguments(arguments) rewritten = arguments.dup if arguments.key?("variablesReference") function = debug_function_for_variables_reference(arguments["variablesReference"]) return rewritten unless function if (entry = @debug_map.source_variable_for(function.linkage_name, arguments["name"])) rewritten["name"] = entry.linkage_name end return rewritten end rewritten["name"] = rewrite_expression_for_frame(arguments["name"], arguments["frameId"]) rewritten end |
#rewrite_evaluate_arguments(arguments) ⇒ Object
115 116 117 118 119 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 115 def rewrite_evaluate_arguments(arguments) rewritten = arguments.dup rewritten["expression"] = rewrite_expression_for_frame(arguments["expression"], arguments["frameId"]) rewritten end |
#rewrite_expression_for_frame(expression, frame_id) ⇒ Object
186 187 188 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 186 def rewrite_expression_for_frame(expression, frame_id) rewrite_expression_for_function(expression, debug_function_for_frame(frame_id)) end |
#rewrite_expression_for_function(expression, function) ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 190 def rewrite_expression_for_function(expression, function) return expression unless @debug_map return expression unless function return expression unless expression.is_a?(String) return expression if expression.empty? rewritten = +"" index = 0 while index < expression.length char = expression[index] if char == '"' || char == "'" index = copy_quoted_segment(expression, index, rewritten) next end if identifier_start_char?(char) start = index index += 1 index += 1 while index < expression.length && identifier_continue_char?(expression[index]) identifier = expression[start...index] if accessor_identifier?(expression, start) rewritten << identifier next end entry = @debug_map.source_variable_for(function.linkage_name, identifier) rewritten << (entry ? entry.linkage_name : identifier) next end rewritten << char index += 1 end rewritten end |
#rewrite_scopes_response(backend_response, frame_id) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 64 def rewrite_scopes_response(backend_response, frame_id) return unless backend_response["success"] normalized_frame_id = normalize_reference_key(frame_id) function = @frame_debug_functions[normalized_frame_id] body = backend_response["body"] scopes = dap_value(body, "scopes") return unless scopes.is_a?(Array) scopes.each do |scope| reference = normalize_reference_key(dap_value(scope, "variablesReference")) next unless reference scope_name = dap_value(scope, "name").to_s @variables_reference_debug_functions[reference] = { frame_id: normalized_frame_id, function: scope_name == "Locals" ? function : nil, } end end |
#rewrite_set_expression_arguments(arguments) ⇒ Object
121 122 123 124 125 126 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 121 def rewrite_set_expression_arguments(arguments) rewritten = arguments.dup rewritten["expression"] = rewrite_expression_for_frame(arguments["expression"], arguments["frameId"]) rewritten["value"] = rewrite_expression_for_frame(arguments["value"], arguments["frameId"]) rewritten end |
#rewrite_set_variable_arguments(arguments) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 128 def rewrite_set_variable_arguments(arguments) rewritten = arguments.dup function = debug_function_for_variables_reference(arguments["variablesReference"]) return rewritten unless function if (entry = @debug_map.source_variable_for(function.linkage_name, arguments["name"])) rewritten["name"] = entry.linkage_name end rewritten["value"] = rewrite_expression_for_function(arguments["value"], function) rewritten end |
#rewrite_stack_trace_response(backend_response) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 45 def rewrite_stack_trace_response(backend_response) return unless @debug_map return unless backend_response["success"] body = backend_response["body"] stack_frames = dap_value(body, "stackFrames") return unless stack_frames.is_a?(Array) @frame_debug_functions.clear stack_frames.each do |frame| function = @debug_map.function_for_c_name(dap_value(frame, "name")) next unless function dap_set(frame, "name", function.name) frame_id = normalize_reference_key(dap_value(frame, "id")) @frame_debug_functions[frame_id] = function if frame_id end end |
#rewrite_variables_response(backend_response, variables_reference) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 86 def rewrite_variables_response(backend_response, variables_reference) return unless @debug_map return unless backend_response["success"] function = debug_function_for_variables_reference(variables_reference) return unless function body = backend_response["body"] variables = dap_value(body, "variables") return unless variables.is_a?(Array) rewritten = variables.each_with_object([]) do |variable, kept| raw_name = dap_value(variable, "name").to_s entry = @debug_map.variable_for(function.linkage_name, raw_name) if entry dap_set(variable, "name", entry.name) kept << variable next end next if raw_name.start_with?("__mt_") kept << variable end dap_set(body, "variables", rewritten) end |
#variables_reference_context(variables_reference) ⇒ Object
236 237 238 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 236 def variables_reference_context(variables_reference) @variables_reference_debug_functions[normalize_reference_key(variables_reference)] end |
#whitespace_char?(char) ⇒ Boolean
283 284 285 |
# File 'lib/milk_tea/dap/server/debug_map.rb', line 283 def whitespace_char?(char) char.match?(/\s/) end |