debug icon indicating copy to clipboard operation
debug copied to clipboard

Set evaluation result to `_` local variable

Open HeyNonster opened this issue 2 months ago • 2 comments

This resolves #1069.

This PR makes a change to the thread client to set the _ local variable to the result of the last evaluation similar to the behavior in irb^1.

The reason _ doesn't work even when using the irb console is because we leave the irb evaluation early if the input should be handled by the debugger^2. Otherwise, we would end up in IRB::Context#evaluate and we would call set_last_value^3.

There's a bit of a quirk here when using the irb console. I was hoping in thread_client to evaluate the result then set the _ local variable and the @last_value ivar all in the same method, similar to how irb does it^1. However, because we're using the irb console we use a new irb Workspace which nils out _ when initialized^4. To get around that, we set the local variable just before evaluating.

HeyNonster avatar Oct 15 '25 12:10 HeyNonster

:x: 1/689 Tests Failed

/home/runner/work/debug/debug/test/protocol/catch_raw_dap_test.rb#test_catching_any_exception_works_correctly
-------------------------
| All Protocol Messages |
-------------------------

V>D {"seq":1,"command":"initialize","arguments":{"clientID":"vscode","clientName":"Visual Studio Code","adapterID":"rdbg","pathFormat":"path","linesStartAt1":true,"columnsStartAt1":true,"supportsVariableType":true,"supportsVariablePaging":true,"supportsRunInTerminalRequest":true,"locale":"en-us","supportsProgressReporting":true,"supportsInvalidatedEvent":true,"supportsMemoryReferences":true},"type":"request"}
V>D {"seq":2,"command":"attach","arguments":{"type":"rdbg","name":"Attach with rdbg","request":"attach","rdbgPath":"/home/runner/work/debug/debug/exe/rdbg","debugPort":"/var/folders/kv/w1k6nh1x5fl7vx47b2pd005w0000gn/T/ruby-debug-sock-501/ruby-debug-naotto-8845","autoAttach":true,"__sessionId":"141d9c79-3669-43ec-ac1f-e62598c5a65a"},"type":"request"}
V>D {"seq":3,"command":"setFunctionBreakpoints","arguments":{"breakpoints":[]},"type":"request"}
V>D {"seq":4,"command":"setExceptionBreakpoints","arguments":{"filters":[],"filterOptions":[{"filterId":"RuntimeError"}]},"type":"request"}
V>D {"seq":5,"command":"configurationDone","type":"request"}
V<D {"type":"response","command":"initialize","request_seq":1,"success":true,"message":"Success","body":{"supportsConfigurationDoneRequest":true,"supportsFunctionBreakpoints":true,"supportsConditionalBreakpoints":true,"supportTerminateDebuggee":true,"supportsTerminateRequest":true,"exceptionBreakpointFilters":[{"filter":"any","label":"rescue any exception","supportsCondition":true},{"filter":"RuntimeError","label":"rescue RuntimeError","supportsCondition":true}],"supportsExceptionFilterOptions":true,"supportsStepBack":true,"supportsEvaluateForHovers":true,"supportsCompletionsRequest":true},"seq":1}
V<D {"type":"event","event":"initialized","seq":2}
V<D {"type":"event","event":"output","body":{"category":"console","output":"Ruby REPL: You can run any Ruby expression here.\nNote that output to the STDOUT/ERR printed on the TERMINAL.\n[experimental]\n  `,COMMAND` runs `COMMAND` debug command (ex: `,info`).\n  `,help` to list all debug commands.\n"},"seq":3}
V<D {"type":"response","command":"attach","request_seq":2,"success":true,"message":"Success","seq":4}
V<D {"type":"response","command":"setFunctionBreakpoints","request_seq":3,"success":true,"message":"Success","seq":5}
V<D {"type":"response","command":"setExceptionBreakpoints","request_seq":4,"success":true,"message":"Success","body":{"breakpoints":[{"verified":true,"message":"#<DEBUGGER__::CatchBreakpoint:0x00007f71f6f45420 @pat=\"RuntimeError\", @key=[:catch, \"RuntimeError\"], @last_exc=nil, @deleted=false, @cond=nil, @command=nil, @path=nil, @tp=#<TracePoint:enabled>>"}]},"seq":6}
V<D {"type":"response","command":"configurationDone","request_seq":5,"success":true,"message":"Success","seq":7}
V<D {"type":"event","event":"stopped","body":{"reason":"pause","threadId":1,"allThreadsStopped":true},"seq":8}
V>D {"seq":6,"command":"threads","type":"request"}
V<D {"type":"response","command":"threads","request_seq":6,"success":true,"message":"Success","body":{"threads":[{"id":1,"name":"#1 /tmp/debug-20251015-2727-y0wy3o.rb:1:in '<main>'"}]},"seq":9}
V>D {"seq":7,"command":"threads","type":"request"}
V<D {"type":"response","command":"threads","request_seq":7,"success":true,"message":"Success","body":{"threads":[{"id":1,"name":"#1 /tmp/debug-20251015-2727-y0wy3o.rb:1:in '<main>'"}]},"seq":10}
V>D {"seq":8,"command":"stackTrace","arguments":{"threadId":1,"startFrame":0,"levels":20},"type":"request"}
V<D {"type":"response","command":"stackTrace","request_seq":8,"success":true,"message":"Success","body":{"stackFrames":[{"id":1,"name":"<main>","line":1,"column":1,"source":{"name":"debug-20251015-2727-y0wy3o.rb","path":"/tmp/debug-20251015-2727-y0wy3o.rb","sourceReference":0}}],"totalFrames":1},"seq":11}
V>D {"seq":9,"command":"scopes","arguments":{"frameId":1},"type":"request"}
V<D {"type":"response","command":"scopes","request_seq":9,"success":true,"message":"Success","body":{"scopes":[{"name":"Local variables","presentationHint":"locals","namedVariables":0,"indexedVariables":0,"expensive":false,"variablesReference":2},{"name":"Global variables","presentationHint":"globals","variablesReference":1,"namedVariables":41,"indexedVariables":0,"expensive":false}]},"seq":12}
V>D {"seq":10,"command":"variables","arguments":{"variablesReference":2},"type":"request"}
V<D {"type":"response","command":"variables","request_seq":10,"success":true,"message":"Success","body":{"variables":[{"name":"%self","value":"main","type":"Object","variablesReference":3,"indexedVariables":0,"namedVariables":1}]},"seq":13}
V>D {"seq":11,"command":"setExceptionBreakpoints","arguments":{"filters":[],"filterOptions":[{"filterId":"any"},{"filterId":"RuntimeError"}]},"type":"request"}
V<D {"type":"response","command":"setExceptionBreakpoints","request_seq":11,"success":true,"message":"Success","body":{"breakpoints":[{"verified":true,"message":"#<DEBUGGER__::CatchBreakpoint:0x00007f71f6f41ee0 @pat=\"Exception\", @key=[:catch, \"Exception\"], @last_exc=nil, @deleted=false, @cond=nil, @command=nil, @path=nil, @tp=#<TracePoint:enabled>>"},{"verified":true,"message":"#<DEBUGGER__::CatchBreakpoint:0x00007f71f6f41e20 @pat=\"RuntimeError\", @key=[:catch, \"RuntimeError\"], @last_exc=nil, @deleted=false, @cond=nil, @command=nil, @path=nil, @tp=#<TracePoint:enabled>>"}]},"seq":14}
V>D {"seq":12,"command":"continue","arguments":{"threadId":1},"type":"request"}
V<D {"type":"response","command":"continue","request_seq":12,"success":true,"message":"Success","body":{"allThreadsContinued":true},"seq":15}
V<D {"type":"event","event":"stopped","body":{"reason":"exception","description":"#<ZeroDivisionError: divided by 0> is raised.","text":"#<ZeroDivisionError: divided by 0> is raised.","threadId":1,"allThreadsStopped":true},"seq":16}
V>D {"seq":13,"command":"threads","type":"request"}
V<D {"type":"response","command":"threads","request_seq":13,"success":true,"message":"Success","body":{"threads":[{"id":1,"name":"#1 /tmp/debug-20251015-2727-y0wy3o.rb:1:in '<main>'"}]},"seq":17}
V>D {"seq":14,"command":"stackTrace","arguments":{"threadId":1,"startFrame":0,"levels":20},"type":"request"}
V<D {"type":"response","command":"stackTrace","request_seq":14,"success":true,"message":"Success","body":{"stackFrames":[{"id":2,"name":"Foo::Bar.a","line":4,"column":1,"source":{"name":"debug-20251015-2727-y0wy3o.rb","path":"/tmp/debug-20251015-2727-y0wy3o.rb","sourceReference":0}},{"id":3,"name":"<module:Foo>","line":7,"column":1,"source":{"name":"debug-20251015-2727-y0wy3o.rb","path":"/tmp/debug-20251015-2727-y0wy3o.rb","sourceReference":0}},{"id":4,"name":"<main>","line":1,"column":1,"source":{"name":"debug-20251015-2727-y0wy3o.rb","path":"/tmp/debug-20251015-2727-y0wy3o.rb","sourceReference":0}}],"totalFrames":4},"seq":18}

--------------------------
| Last Protocol Messages |
--------------------------

{
  "seq": 13,
  "command": "threads",
  "type": "request"
}
{
  "type": "response",
  "command": "threads",
  "request_seq": 13,
  "success": true,
  "message": "Success",
  "body": {
    "threads": [
      {
        "id": 1,
        "name": "#1 /tmp/debug-20251015-2727-y0wy3o.rb:1:in '<main>'"
      }
    ]
  },
  "seq": 17
}
{
  "seq": 14,
  "command": "stackTrace",
  "arguments": {
    "threadId": 1,
    "startFrame": 0,
    "levels": 20
  },
  "type": "request"
}
{
  "type": "response",
  "command": "stackTrace",
  "request_seq": 14,
  "success": true,
  "message": "Success",
  "body": {
    "stackFrames": [
      {
        "id": 2,
        "name": "Foo::Bar.a",
        "line": 4,
        "column": 1,
        "source": {
          "name": "debug-20251015-2727-y0wy3o.rb",
          "path": "/tmp/debug-20251015-2727-y0wy3o.rb",
          "sourceReference": 0
        }
      },
      {
        "id": 3,
        "name": "<module:Foo>",
        "line": 7,
        "column": 1,
        "source": {
          "name": "debug-20251015-2727-y0wy3o.rb",
          "path": "/tmp/debug-20251015-2727-y0wy3o.rb",
          "sourceReference": 0
        }
      },
      {
        "id": 4,
        "name": "<main>",
        "line": 1,
        "column": 1,
        "source": {
          "name": "debug-20251015-2727-y0wy3o.rb",
          "path": "/tmp/debug-20251015-2727-y0wy3o.rb",
          "sourceReference": 0
        }
      }
    ],
    "totalFrames": 4
  },
  "seq": 18
}

--------------------
| Debuggee Session |
--------------------

> DEBUGGER: Debugger can attach via UNIX domain socket (/run/user/1001/rdbg-2727-17)
> DEBUGGER: wait for debugger connection...
> DEBUGGER: Connected.


-------------------
| Failure Message |
-------------------

expected:
{
  "type": "response",
  "command": "stackTrace",
  "request_seq": 14,
  "success": true,
  "message": "Success",
  "body": {
    "stackFrames": [
      {
        "name": "[C] Integer#/",
        "line": 4,
        "column": 1,
        "source": {
          "name": "(?-mix:debug-20251015-2727-y0wy3o.rb)",
          "path": "(?-mix:\\/tmp\\/debug-20251015-2727-y0wy3o.rb)",
          "sourceReference": 0
        },
        "id": 2
      },
      {
        "name": "Foo::Bar.a",
        "line": 4,
        "column": 1,
        "source": {
          "name": "(?-mix:debug-20251015-2727-y0wy3o.rb)",
          "path": "(?-mix:\\/tmp\\/debug-20251015-2727-y0wy3o.rb)",
          "sourceReference": 0
        },
        "id": 3
      },
      {
        "name": "<module:Foo>",
        "line": 7,
        "column": 1,
        "source": {
          "name": "(?-mix:debug-20251015-2727-y0wy3o.rb)",
          "path": "(?-mix:\\/tmp\\/debug-20251015-2727-y0wy3o.rb)",
          "sourceReference": 0
        },
        "id": 4
      },
      {
        "name": "<main>",
        "line": 1,
        "column": 1,
        "source": {
          "name": "(?-mix:debug-20251015-2727-y0wy3o.rb)",
          "path": "(?-mix:\\/tmp\\/debug-20251015-2727-y0wy3o.rb)",
          "sourceReference": 0
        },
        "id": 5
      }
    ]
  }
}

result:
{
  "type": "response",
  "command": "stackTrace",
  "request_seq": 14,
  "success": true,
  "message": "Success",
  "body": {
    "stackFrames": [
      {
        "id": 2,
        "name": "Foo::Bar.a",
        "line": 4,
        "column": 1,
        "source": {
          "name": "debug-20251015-2727-y0wy3o.rb",
          "path": "/tmp/debug-20251015-2727-y0wy3o.rb",
          "sourceReference": 0
        }
      },
      {
        "id": 3,
        "name": "<module:Foo>",
        "line": 7,
        "column": 1,
        "source": {
          "name": "debug-20251015-2727-y0wy3o.rb",
          "path": "/tmp/debug-20251015-2727-y0wy3o.rb",
          "sourceReference": 0
        }
      },
      {
        "id": 4,
        "name": "<main>",
        "line": 1,
        "column": 1,
        "source": {
          "name": "debug-20251015-2727-y0wy3o.rb",
          "path": "/tmp/debug-20251015-2727-y0wy3o.rb",
          "sourceReference": 0
        }
      }
    ],
    "totalFrames": 4
  },
  "seq": 18
}.
<"[C] Integer#/"> expected but was
<"Foo::Bar.a">.

[-> View Test suite health in main branch]

launchable-app[bot] avatar Oct 15 '25 12:10 launchable-app[bot]

how to handle _ if it is already available?

ko1 avatar Dec 05 '25 07:12 ko1