Class: Byebug::DAP::Session

Inherits:
Object
  • Object
show all
Includes:
SafeHelpers
Defined in:
lib/byebug/dap/session.rb

Overview

A Byebug DAP session

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SafeHelpers

#safe

Constructor Details

#initialize(connection, ios = nil) { ... } ⇒ Session

Create a new session instance.

Parameters:

  • connection (std:IO)

    the connection to the client

  • ios (CapturedIO) (defaults to: nil)

    the captured IO

Yields:

  • called once the client is done configuring the session (optional)



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/byebug/dap/session.rb', line 39

def initialize(connection, ios = nil, &block)
  @connection = connection
  @ios = ios
  @on_configured = block
  @pid = Process.pid
  @log_points = {}
  @frame_ids = Handles.new
  @variable_refs = Handles.new
  @trace = TracePoint.new(:thread_begin, :thread_end) { |t| process_trace t }

  notify_of_children
end

Class Method Details

.child_spawned(name, pid, socket) ⇒ Object

Record a childSpawned event and send the event to the current session’s client, if gem:byebug:Byebuggem:byebug:Byebug::Contextgem:byebug:Byebug::Context.interface is a Byebug::DAP::Session.



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/byebug/dap/session.rb', line 21

def self.child_spawned(name, pid, socket)
  child = ChildSpawnedEventBody.new(name: name, pid: pid, socket: socket)
  (@@children ||= []) << child

  session = Context.interface
  return false unless session.is_a?(Session)

  session.event! child
  return true

rescue IOError, Errno::EPIPE, Errno::ECONNRESET, Errno::ECONNABORTED
  return false
end

.stop!Boolean

Call #stop! on gem:byebug:Byebuggem:byebug:Byebug::Contextgem:byebug:Byebug::Context.interface if it is a Byebug::DAP::Session.

Returns:

  • (Boolean)

    whether gem:byebug:Byebuggem:byebug:Byebug::Contextgem:byebug:Byebug::Context.interface was a Byebug::DAP::Session



10
11
12
13
14
15
16
# File 'lib/byebug/dap/session.rb', line 10

def self.stop!
  session = Byebug::Context.interface
  return false unless session.is_a?(Session)

  session.stop!
  true
end

Instance Method Details

#clear_breakpoints(*breakpoints) ⇒ Object

Delete the specified breakpoints and any log points associated with them.

Parameters:

  • breakpoints (std:Array<gem:byebug:Byebug::Breakpoint>)

    the breakpoints



191
192
193
194
195
196
# File 'lib/byebug/dap/session.rb', line 191

def clear_breakpoints(*breakpoints)
  breakpoints.each do |breakpoint|
    Byebug.breakpoints.delete(breakpoint)
    @log_points.delete(breakpoint.id)
  end
end

#configured!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

This should only be used by the configurationDone commands

Call the block passed to #initialize.



97
98
99
100
101
102
# File 'lib/byebug/dap/session.rb', line 97

def configured!
  return unless @on_configured

  callback, @on_configured = @on_configured, callback
  callback.call
end

#event!(event, **values) ⇒ Object

Send an event to the client. Either call with an event name and body attributes, or call with an already constructed body.

Parameters:

  • event (std:String|Protocol::Base)

    the event name or event body

  • values (std:Hash)

    event body attributes



119
120
121
122
123
124
125
126
127
128
# File 'lib/byebug/dap/session.rb', line 119

def event!(event, **values)
  if (cls = event.class.name.split('::').last) && cls.end_with?('EventBody')
    body, event = event, cls[0].downcase + cls[1...-9]

  elsif event.is_a?(String) && !values.empty?
    body = Protocol.const_get("#{event[0].upcase}#{event[1..]}EventBody").new(values)
  end

  send Protocol::Event.new(event: event, body: body)
end

#executeObject

Execute requests from the client until the connection is closed.



66
67
68
69
70
71
72
73
# File 'lib/byebug/dap/session.rb', line 66

def execute
  Context.interface = self
  Context.processor = DAP::CommandProcessor

  Command.execute(self, receive) until @connection.closed?

  Context.interface = LocalInterface.new
end

#get_log_point(breakpoint) ⇒ std:String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

This should only be used by a command processor

Get the log point expression associated with ‘breakpoint`.

Parameters:

  • breakpoint (gem:byebug:Byebug::Breakpoint)

    the breakpoint

Returns:

  • (std:String)

    the log point expression



171
172
173
# File 'lib/byebug/dap/session.rb', line 171

def get_log_point(breakpoint)
  @log_points[breakpoint.id]
end

#invalidate_handles!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

This should only be used by a contextual command that un-pauses its context

Invalidate frame IDs and variables references.



78
79
80
81
# File 'lib/byebug/dap/session.rb', line 78

def invalidate_handles!
  @frame_ids.clear!
  @variable_refs.clear!
end

#log(*args) ⇒ Object

Write a message to the log.



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/byebug/dap/session.rb', line 53

def log(*args)
  logger =
    if @ios
      @ios.log
    elsif defined?(LOG)
      LOG
    else
      STDERR
    end
  logger.puts(*args)
end

#respond!(request, body = nil, success: true, message: 'Success', **values) ⇒ Object

Send a response to the client.

Parameters:

  • request (Protocol::Request)

    the request to respond to

  • body (std:Hash|Protocol::Base) (defaults to: nil)

    the response body

  • success (std:Boolean) (defaults to: true)

    whether the request was successful

  • message (std:String) (defaults to: 'Success')

    the response message

  • values (std:Hash)

    additional response attributes



136
137
138
139
140
141
142
143
144
# File 'lib/byebug/dap/session.rb', line 136

def respond!(request, body = nil, success: true, message: 'Success', **values)
  send Protocol::Response.new(
    request_seq: request.seq,
    command: request.command,
    success: success,
    message: message,
    body: body,
    **values)
end

#restore_frame(id) ⇒ Object

Restore a frame from an ID.



162
163
164
# File 'lib/byebug/dap/session.rb', line 162

def restore_frame(id)
  @frame_ids[id]
end

#restore_variables(ref) ⇒ Object

Retrieve variables from a reference.



152
153
154
# File 'lib/byebug/dap/session.rb', line 152

def restore_variables(ref)
  @variable_refs[ref]
end

#save_frame(*args) ⇒ Object

Create a frame ID.



157
158
159
# File 'lib/byebug/dap/session.rb', line 157

def save_frame(*args)
  @frame_ids << args
end

#save_variables(*args) ⇒ Object

Create a variables reference.



147
148
149
# File 'lib/byebug/dap/session.rb', line 147

def save_variables(*args)
  @variable_refs << args
end

#set_log_point(breakpoint, expr) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

This should only be used by a command processor

Associate a log point expression with ‘breakpoint`.

Parameters:

  • breakpoint (gem:byebug:Byebug::Breakpoint)

    the breakpoint

  • expr (std:String)

    the log point expression



180
181
182
183
184
185
186
# File 'lib/byebug/dap/session.rb', line 180

def set_log_point(breakpoint, expr)
  if expr.nil? || expr.empty?
    @log_points.delete(breakpoint.id)
  else
    @log_points[breakpoint.id] = expr
  end
end

#start!(mode) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

This should only be used by the attach or launch commands

Start Byebug.

Parameters:

  • mode (std:Symbol)

    ‘:attached` or `:launched`



87
88
89
90
91
92
# File 'lib/byebug/dap/session.rb', line 87

def start!(mode)
  @trace.enable
  Byebug.mode = mode
  Byebug.start
  @exit_on_stop = true if mode == :launched
end

#stop!Object

Note:

If the session was started with the ‘launch` command, this will exit

Stop Byebug and close the client’s connection.



106
107
108
109
110
111
112
113
# File 'lib/byebug/dap/session.rb', line 106

def stop!
  exit if @exit_on_stop && @pid == Process.pid

  Byebug.mode = :off
  Byebug.stop
  @trace.disable
  @connection.close
end