readapt 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,42 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Readapt
4
+ # @!method file
5
+ # @return [String]
6
+ # @!method line
7
+ # @return [Integer]
8
+ # @!method binding_id
9
+ # @return [Integer]
10
+ # @!method initialize(file, line, binding_id)
4
11
  class Frame
5
- attr_reader :location
6
-
7
- def initialize location, binding_id
8
- @location = location
9
- @binding = ObjectSpace._id2ref(binding_id)
10
- end
11
-
12
12
  def evaluate code
13
- @binding.eval(code).inspect
13
+ frame_binding.eval(code).inspect
14
14
  rescue Exception => e
15
15
  "[#{e.class}] #{e.message}"
16
16
  end
17
17
 
18
18
  def local_id
19
- @binding.object_id
19
+ frame_binding.object_id
20
20
  end
21
21
 
22
22
  def locals
23
- return [] if @binding.nil?
23
+ return [] if frame_binding.nil?
24
24
  result = []
25
- @binding.local_variables.each do |sym|
26
- var = @binding.local_variable_get(sym)
25
+ frame_binding.local_variables.each do |sym|
26
+ var = frame_binding.local_variable_get(sym)
27
27
  result.push Variable.new(sym, var)
28
28
  end
29
- if @binding.receiver != TOPLEVEL_BINDING.receiver
30
- result.push Variable.new(:self, @binding.receiver)
31
- end
29
+ result.push Variable.new(:self, frame_binding.receiver)
32
30
  result
33
31
  end
34
32
 
35
33
  def local sym
36
- return @binding.receiver if sym == :self
37
- @binding.local_variable_get sym
34
+ return frame_binding.receiver if sym == :self
35
+ frame_binding.local_variable_get sym
38
36
  end
39
37
 
40
- NULL_FRAME = Frame.new(nil, nil.object_id)
38
+ NULL_FRAME = Frame.new("", 0, nil)
41
39
  end
42
40
  end
@@ -29,13 +29,15 @@ module Readapt
29
29
  end
30
30
 
31
31
  def self.process arguments, debugger
32
- message = @@messages[arguments['command']].new(arguments['arguments'], debugger)
33
- message.run
34
- message
35
- rescue Exception => e
36
- STDERR.puts "Skipping error: #{e.message}"
37
- STDERR.puts "Received: #{arguments}"
38
- STDERR.puts e.backtrace
32
+ klass = @@messages[arguments['command']]
33
+ if klass.nil?
34
+ STDERR.puts "Debugger received unrecognized command `#{arguments['command']}`"
35
+ Message::Base.new(arguments, debugger)
36
+ else
37
+ message = klass.new(arguments['arguments'], debugger)
38
+ message.run
39
+ message
40
+ end
39
41
  end
40
42
 
41
43
  register 'initialize', Message::Initialize
@@ -55,5 +57,6 @@ module Readapt
55
57
  register 'disconnect', Message::Disconnect
56
58
  register 'pause', Message::Pause
57
59
  register 'evaluate', Message::Evaluate
60
+ # register 'source', Message::Base # @todo Placeholder
58
61
  end
59
62
  end
@@ -14,7 +14,8 @@ module Readapt
14
14
  },
15
15
  {
16
16
  name: 'Global',
17
- variablesReference: TOPLEVEL_BINDING.receiver.object_id,
17
+ # @todo 1 is a magic number representing the toplevel binding
18
+ variablesReference: 1,
18
19
  expensive: true
19
20
  }
20
21
  ]
@@ -9,7 +9,7 @@ module Readapt
9
9
  lines = []
10
10
  set_body(
11
11
  breakpoints: arguments['breakpoints'].map do |val|
12
- debugger.set_breakpoint path, val['line'], val['condition']
12
+ debugger.set_breakpoint path, val['line'], val['condition'], val['hitCondition']
13
13
  lines.push val['line']
14
14
  {
15
15
  verified: true, # @todo Verify
@@ -3,24 +3,36 @@
3
3
  module Readapt
4
4
  module Message
5
5
  class StackTrace < Base
6
+ @@file_hash = {}
7
+
6
8
  def run
7
9
  frames = debugger.thread(arguments['threadId']).frames
8
10
  set_body({
9
11
  stackFrames: frames.map do |frm|
10
12
  {
11
- name: "#{File.basename(frm.location.file)}:#{frm.location.line}",
13
+ name: frame_code(frm.file, frm.line),
12
14
  source: {
13
- name: File.basename(frm.location.file),
14
- path: frm.location.file
15
+ name: frm.file ? File.basename(frm.file) : nil,
16
+ path: frm.file
15
17
  },
16
18
  id: frm.local_id,
17
- line: frm.location.line,
19
+ line: frm.line,
18
20
  column: 0
19
21
  }
20
22
  end,
21
23
  totalFrames: frames.length
22
24
  })
23
25
  end
26
+
27
+ private
28
+
29
+ def read_file file
30
+ @@file_hash[file] ||= File.read(file)
31
+ end
32
+
33
+ def frame_code file, line
34
+ read_file(file).lines[line - 1].strip
35
+ end
24
36
  end
25
37
  end
26
38
  end
@@ -6,32 +6,36 @@ module Readapt
6
6
  def run
7
7
  ref = arguments['variablesReference']
8
8
  frame = debugger.frame(ref)
9
- vars = if frame != Frame::NULL_FRAME && !frame.nil?
10
- frame.locals
11
- elsif ref == TOPLEVEL_BINDING.receiver.object_id
9
+ # @todo 1 is a magic number representing the toplevel binding (see
10
+ # Message::Scopes)
11
+ vars = if ref == 1
12
12
  global_variables.map do |gv|
13
13
  Variable.new(gv, eval(gv.to_s))
14
14
  end
15
15
  else
16
- obj = object_reference
17
- result = []
18
- if obj.is_a?(Array)
19
- obj.each_with_index do |itm, idx|
20
- result.push Variable.new("[#{idx}]", itm)
21
- end
22
- elsif obj.is_a?(Hash)
23
- obj.each_pair do |idx, itm|
24
- result.push Variable.new("[#{idx}]", itm)
25
- end
16
+ if frame != Frame::NULL_FRAME && !frame.nil?
17
+ frame.locals
26
18
  else
27
- obj.instance_variables.each do |iv|
28
- result.push Variable.new(iv, obj.instance_variable_get(iv))
29
- end
30
- obj.class.class_variables.each do |cv|
31
- result.push Variable.new(cv, obj.class.class_variable_get(cv))
19
+ obj = object_reference
20
+ result = []
21
+ if obj.is_a?(Array)
22
+ obj.each_with_index do |itm, idx|
23
+ result.push Variable.new("[#{idx}]", itm)
24
+ end
25
+ elsif obj.is_a?(Hash)
26
+ obj.each_pair do |idx, itm|
27
+ result.push Variable.new("[#{idx}]", itm)
28
+ end
29
+ else
30
+ obj.instance_variables.each do |iv|
31
+ result.push Variable.new(iv, obj.instance_variable_get(iv))
32
+ end
33
+ obj.class.class_variables.each do |cv|
34
+ result.push Variable.new(cv, obj.class.class_variable_get(cv))
35
+ end
32
36
  end
37
+ result
33
38
  end
34
- result
35
39
  end
36
40
  set_body({
37
41
  variables: vars.map do |var|
@@ -14,6 +14,8 @@ module Readapt
14
14
  option :host, type: :string, aliases: :h, description: 'The server host', default: '127.0.0.1'
15
15
  option :port, type: :numeric, aliases: :p, description: 'The server port', default: 1234
16
16
  def serve
17
+ STDOUT.sync = true
18
+ STDERR.sync = true
17
19
  machine = Backport::Machine.new
18
20
  machine.run do
19
21
  Signal.trap("INT") do
@@ -7,25 +7,16 @@ module Readapt
7
7
  # @return [Integer]
8
8
  attr_reader :thread_id
9
9
 
10
- # @return [Integer]
11
- attr_reader :binding_id
12
-
13
10
  # @return [String]
14
11
  attr_reader :file
15
12
 
16
13
  # @return [Integer]
17
14
  attr_reader :line
18
15
 
19
- # @return [Symbol]
20
- attr_reader :method_name
21
-
22
16
  # The reason for pausing the debugging, e.g., "breakpoint" or "step"
23
17
  # @return [String, Symbol]
24
18
  attr_reader :event
25
19
 
26
- # @return [Integer]
27
- attr_reader :depth
28
-
29
20
  # @return [Symbol]
30
21
  attr_accessor :control
31
22
 
@@ -36,14 +27,11 @@ module Readapt
36
27
  # @param method_name [Symbol]
37
28
  # @param event [String, Symbol]
38
29
  # @param depth [Integer]
39
- def initialize thread_id, binding_id, file, line, method_name, event, depth
30
+ def initialize thread_id, file, line, event
40
31
  @thread_id = thread_id
41
- @binding_id = binding_id
42
32
  @file = file
43
33
  @line = line
44
- @method_name = method_name
45
34
  @event = event
46
- @depth = depth
47
35
  @control = :pause
48
36
  end
49
37
  end
@@ -6,34 +6,23 @@ module Readapt
6
6
  class Thread
7
7
  @@next_id = 0
8
8
 
9
- # @return [Integer]
10
- attr_reader :id
11
-
12
- # @return [String]
13
- attr_reader :name
14
-
15
9
  # @return [Symbol]
16
10
  attr_accessor :control
17
11
 
18
- def initialize id
19
- @id = id
20
- @@next_id += 1
21
- @name = "Thread #{@@next_id}"
22
- end
23
-
24
- def frames
25
- @frames ||= []
12
+ def name
13
+ @name ||= begin
14
+ @@next_id += 1
15
+ "Thread #{@@next_id}"
16
+ end
26
17
  end
27
18
 
28
- class NullThread < Thread
29
- def initialize
30
- @id = 0
31
- @name = 'Null Thread'
32
- @frames = [].freeze
33
- end
19
+ def object
20
+ STDERR.puts "Getting #{id}"
21
+ ObjectSpace._id2ref(id)
34
22
  end
35
- private_constant :NullThread
36
23
 
37
- NULL_THREAD = NullThread.new
24
+ # def frames
25
+ # @frames ||= []
26
+ # end
38
27
  end
39
28
  end
@@ -1,3 +1,3 @@
1
1
  module Readapt
2
- VERSION = "0.7.1"
2
+ VERSION = "0.8.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: readapt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-14 00:00:00.000000000 Z
11
+ date: 2019-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backport
@@ -119,13 +119,19 @@ files:
119
119
  - ext/readapt/breakpoints.c
120
120
  - ext/readapt/breakpoints.h
121
121
  - ext/readapt/extconf.rb
122
+ - ext/readapt/frame.c
123
+ - ext/readapt/frame.h
122
124
  - ext/readapt/hash_table.c
123
125
  - ext/readapt/hash_table.h
126
+ - ext/readapt/inspector.c
127
+ - ext/readapt/inspector.h
124
128
  - ext/readapt/monitor.c
125
129
  - ext/readapt/monitor.h
126
130
  - ext/readapt/normalize.c
127
131
  - ext/readapt/normalize.h
128
132
  - ext/readapt/readapt.c
133
+ - ext/readapt/stack.c
134
+ - ext/readapt/stack.h
129
135
  - ext/readapt/threads.c
130
136
  - ext/readapt/threads.h
131
137
  - lib/readapt.rb
@@ -134,7 +140,6 @@ files:
134
140
  - lib/readapt/debugger.rb
135
141
  - lib/readapt/finder.rb
136
142
  - lib/readapt/frame.rb
137
- - lib/readapt/location.rb
138
143
  - lib/readapt/message.rb
139
144
  - lib/readapt/message/attach.rb
140
145
  - lib/readapt/message/base.rb
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- # A simple file/line reference.
5
- #
6
- class Location
7
- # @return [String]
8
- attr_reader :file
9
-
10
- # @return [Integer]
11
- attr_reader :line
12
-
13
- # @param file [String]
14
- # @param line [Integer]
15
- def initialize file, line
16
- @file = file
17
- @line = line
18
- end
19
-
20
- def match? other
21
- return false unless other.is_a?(Location)
22
- file == other.file && line == other.line
23
- end
24
- end
25
- end