readapt 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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