readapt 0.3.1

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG.md +15 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +29 -0
  9. data/Rakefile +25 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/exe/readapt +5 -0
  13. data/ext/readapt/extconf.rb +3 -0
  14. data/ext/readapt/monitor.c +332 -0
  15. data/ext/readapt/monitor.h +1 -0
  16. data/ext/readapt/readapt.c +12 -0
  17. data/ext/readapt/threads.c +101 -0
  18. data/ext/readapt/threads.h +18 -0
  19. data/lib/readapt.rb +34 -0
  20. data/lib/readapt/adapter.rb +138 -0
  21. data/lib/readapt/breakpoint.rb +16 -0
  22. data/lib/readapt/breakpoints.rb +58 -0
  23. data/lib/readapt/debugger.rb +173 -0
  24. data/lib/readapt/finder.rb +20 -0
  25. data/lib/readapt/frame.rb +68 -0
  26. data/lib/readapt/location.rb +25 -0
  27. data/lib/readapt/message.rb +57 -0
  28. data/lib/readapt/message/attach.rb +11 -0
  29. data/lib/readapt/message/base.rb +32 -0
  30. data/lib/readapt/message/configuration_done.rb +11 -0
  31. data/lib/readapt/message/continue.rb +15 -0
  32. data/lib/readapt/message/disconnect.rb +14 -0
  33. data/lib/readapt/message/initialize.rb +13 -0
  34. data/lib/readapt/message/launch.rb +11 -0
  35. data/lib/readapt/message/next.rb +12 -0
  36. data/lib/readapt/message/pause.rb +11 -0
  37. data/lib/readapt/message/scopes.rb +25 -0
  38. data/lib/readapt/message/set_breakpoints.rb +26 -0
  39. data/lib/readapt/message/set_exception_breakpoints.rb +8 -0
  40. data/lib/readapt/message/stack_trace.rb +26 -0
  41. data/lib/readapt/message/step_in.rb +11 -0
  42. data/lib/readapt/message/step_out.rb +11 -0
  43. data/lib/readapt/message/threads.rb +18 -0
  44. data/lib/readapt/message/variables.rb +57 -0
  45. data/lib/readapt/monitor.rb +31 -0
  46. data/lib/readapt/shell.rb +48 -0
  47. data/lib/readapt/snapshot.rb +50 -0
  48. data/lib/readapt/thread.rb +39 -0
  49. data/lib/readapt/variable.rb +70 -0
  50. data/lib/readapt/version.rb +3 -0
  51. data/readapt.gemspec +39 -0
  52. metadata +184 -0
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Variables < Base
6
+ def run
7
+ ref = arguments['variablesReference']
8
+ frame = debugger.frame(ref)
9
+ vars = if frame
10
+ frame.locals
11
+ elsif ref == TOPLEVEL_BINDING.receiver.object_id
12
+ global_variables.map do |gv|
13
+ Variable.new(gv, eval(gv.to_s))
14
+ end
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
26
+ 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))
32
+ end
33
+ end
34
+ result
35
+ end
36
+ set_body({
37
+ variables: vars.map do |var|
38
+ {
39
+ name: var.name,
40
+ value: var.value,
41
+ type: var.type,
42
+ variablesReference: var.reference
43
+ }
44
+ end
45
+ })
46
+ end
47
+
48
+ private
49
+
50
+ def object_reference
51
+ ObjectSpace._id2ref(arguments['variablesReference'])
52
+ rescue RangeError
53
+ nil
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,31 @@
1
+ module Readapt
2
+ # The module responsible for stepping through code and providing snapshots.
3
+ #
4
+ # @!method self.start &block
5
+ # Enable tracepoints. Yield a Snapshot to the provided block for every
6
+ # stop (breakpoints, steps, etc.).
7
+ # @yieldparam [Snapshot]
8
+ # @return [Boolean]
9
+ #
10
+ # @!method self.stop
11
+ # Disable tracepoints.
12
+ # @return [Boolean]
13
+ module Monitor
14
+ @@breakpoints = Breakpoints.new
15
+
16
+ # @return [Breakpoints]
17
+ def self.breakpoints
18
+ @@breakpoints
19
+ end
20
+
21
+ def self.set_breakpoints bps
22
+ @@breakpoints = bps
23
+ end
24
+
25
+ def self.update
26
+ know_breakpoints
27
+ end
28
+
29
+ @@breakpoints.add_observer self
30
+ end
31
+ end
@@ -0,0 +1,48 @@
1
+ require 'thor'
2
+ require 'socket'
3
+ require 'stringio'
4
+ require 'backport'
5
+
6
+ module Readapt
7
+ class Shell < Thor
8
+ map %w[--version -v] => :version
9
+
10
+ desc "--version, -v", "Print the version"
11
+ def version
12
+ puts Readapt::VERSION
13
+ end
14
+
15
+ desc 'serve', 'Run a DAP server'
16
+ option :host, type: :string, aliases: :h, description: 'The server host', default: '127.0.0.1'
17
+ option :port, type: :numeric, aliases: :p, description: 'The server port', default: 1234
18
+ def serve
19
+ machine = Backport::Machine.new
20
+ machine.run do
21
+ Signal.trap("INT") do
22
+ Backport.stop
23
+ end
24
+ Signal.trap("TERM") do
25
+ Backport.stop
26
+ end
27
+ debugger = Readapt::Debugger.new(machine)
28
+ ::Thread.new do
29
+ Readapt::Adapter.host debugger
30
+ machine.prepare Backport::Server::Tcpip.new(host: options[:host], port: options[:port], adapter: Readapt::Adapter)
31
+ end
32
+ STDERR.puts "Readapt Debugger #{Readapt::VERSION} is listening HOST=#{options[:host]} PORT=#{options[:port]}"
33
+ # Redirect STDOUT and STDERR through the adapter protocol
34
+ # @todo This feature does not always work with STDERR, e.g, when
35
+ # running RSpec
36
+ cats = ['stdout', 'stderr']
37
+ [STDOUT, STDERR].each do |io|
38
+ cat = cats.shift
39
+ io.instance_eval do
40
+ define_singleton_method :write do |*args, &block|
41
+ debugger.output args.join, cat
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ # Information about the state of the debugger.
5
+ #
6
+ class Snapshot
7
+ # @return [Integer]
8
+ attr_reader :thread_id
9
+
10
+ # @return [Integer]
11
+ attr_reader :binding_id
12
+
13
+ # @return [String]
14
+ attr_reader :file
15
+
16
+ # @return [Integer]
17
+ attr_reader :line
18
+
19
+ # @return [Symbol]
20
+ attr_reader :method_name
21
+
22
+ # The reason for pausing the debugging, e.g., "breakpoint" or "step"
23
+ # @return [String, Symbol]
24
+ attr_reader :event
25
+
26
+ # @return [Integer]
27
+ attr_reader :depth
28
+
29
+ # @return [Symbol]
30
+ attr_accessor :control
31
+
32
+ # @param thread_id [Integer]
33
+ # @param binding_id [Integer]
34
+ # @param file [String]
35
+ # @param line [Integer]
36
+ # @param method_name [Symbol]
37
+ # @param event [String, Symbol]
38
+ # @param depth [Integer]
39
+ def initialize thread_id, binding_id, file, line, method_name, event, depth
40
+ @thread_id = thread_id
41
+ @binding_id = binding_id
42
+ @file = file
43
+ @line = line
44
+ @method_name = method_name
45
+ @event = event
46
+ @depth = depth
47
+ @control = :pause
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ostruct'
4
+
5
+ module Readapt
6
+ class Thread
7
+ @@next_id = 0
8
+
9
+ # @return [Integer]
10
+ attr_reader :id
11
+
12
+ # @return [String]
13
+ attr_reader :name
14
+
15
+ # @return [Symbol]
16
+ attr_accessor :control
17
+
18
+ def initialize id
19
+ @id = id
20
+ @@next_id += 1
21
+ @name = "Thread #{@@next_id}"
22
+ end
23
+
24
+ def frames
25
+ @frames ||= []
26
+ end
27
+
28
+ class NullThread < Thread
29
+ def initialize
30
+ @id = 0
31
+ @name = 'Null Thread'
32
+ @frames = [].freeze
33
+ end
34
+ end
35
+ private_constant :NullThread
36
+
37
+ NULL_THREAD = NullThread.new
38
+ end
39
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ # Data retrieved from variable reference in the debugger.
5
+ #
6
+ class Variable
7
+ # @return [String]
8
+ attr_reader :name
9
+
10
+ # @param name [String, Symbol]
11
+ # @param object [Object]
12
+ def initialize name, object
13
+ @name = name
14
+ @object = object
15
+ end
16
+
17
+ # @return [Integer]
18
+ def reference
19
+ @reference ||= unstructured || object.object_id
20
+ end
21
+
22
+ # @return [String]
23
+ def value
24
+ @value ||= if object.nil?
25
+ 'nil'
26
+ elsif show_class_for_value?
27
+ "#{empty? ? 'Empty ' : ''}#{object.class}"
28
+ else
29
+ object.to_s
30
+ end
31
+ end
32
+
33
+ # @return [String]
34
+ def type
35
+ object.class.to_s
36
+ end
37
+
38
+ private
39
+
40
+ UNSTRUCTURED_TYPES = [NilClass, String, TrueClass, FalseClass, Numeric].freeze
41
+ private_constant :UNSTRUCTURED_TYPES
42
+
43
+ # @return [Object]
44
+ attr_reader :object
45
+
46
+ # @return [Integer, nil]
47
+ def unstructured
48
+ 0 if UNSTRUCTURED_TYPES.any? { |cls| object.is_a?(cls) } || no_references?
49
+ end
50
+
51
+ # @return [Boolean]
52
+ def show_class_for_value?
53
+ object.is_a?(Array) || object.is_a?(Hash)
54
+ end
55
+
56
+ def no_references?
57
+ (object.instance_variables.empty? &&
58
+ object.class.class_variables.empty?) &&
59
+ (!enumerable? || object.empty?)
60
+ end
61
+
62
+ def enumerable?
63
+ object.is_a?(Array) || object.is_a?(Hash)
64
+ end
65
+
66
+ def empty?
67
+ enumerable? && object.empty?
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,3 @@
1
+ module Readapt
2
+ VERSION = "0.3.1"
3
+ end
data/readapt.gemspec ADDED
@@ -0,0 +1,39 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "readapt/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "readapt"
7
+ spec.version = Readapt::VERSION
8
+ spec.authors = ["Fred Snyder"]
9
+ spec.email = ["fsnyder@castwide.com"]
10
+
11
+ spec.summary = 'A Ruby debugger for the Debug Adapter Protocol'
12
+ spec.description = 'Readapt is a Ruby debugger that natively supports the Debug Adapter Protocol. Features include next/step in/step out, local and global variable data, and individual thread control.'
13
+ spec.homepage = "https://castwide.com"
14
+ spec.license = "MIT"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/castwide/readapt"
18
+ spec.metadata["changelog_uri"] = "https://github.com/castwide/readapt/blob/master/CHANGELOG.md"
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+ spec.extensions = ['ext/readapt/extconf.rb']
29
+
30
+ spec.required_ruby_version = '>= 2.2'
31
+
32
+ spec.add_dependency 'backport', '~> 1.1'
33
+ spec.add_dependency 'thor', '~> 0.20'
34
+
35
+ spec.add_development_dependency "rake", "~> 10.0"
36
+ spec.add_development_dependency "rake-compiler", "~> 1.0"
37
+ spec.add_development_dependency "rspec", "~> 3.0"
38
+ spec.add_development_dependency 'simplecov', '~> 0.14'
39
+ end
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: readapt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Fred Snyder
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-08-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: backport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.20'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.20'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake-compiler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.14'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.14'
97
+ description: Readapt is a Ruby debugger that natively supports the Debug Adapter Protocol.
98
+ Features include next/step in/step out, local and global variable data, and individual
99
+ thread control.
100
+ email:
101
+ - fsnyder@castwide.com
102
+ executables:
103
+ - readapt
104
+ extensions:
105
+ - ext/readapt/extconf.rb
106
+ extra_rdoc_files: []
107
+ files:
108
+ - ".gitignore"
109
+ - ".rspec"
110
+ - ".travis.yml"
111
+ - CHANGELOG.md
112
+ - Gemfile
113
+ - LICENSE.txt
114
+ - README.md
115
+ - Rakefile
116
+ - bin/console
117
+ - bin/setup
118
+ - exe/readapt
119
+ - ext/readapt/extconf.rb
120
+ - ext/readapt/monitor.c
121
+ - ext/readapt/monitor.h
122
+ - ext/readapt/readapt.c
123
+ - ext/readapt/threads.c
124
+ - ext/readapt/threads.h
125
+ - lib/readapt.rb
126
+ - lib/readapt/adapter.rb
127
+ - lib/readapt/breakpoint.rb
128
+ - lib/readapt/breakpoints.rb
129
+ - lib/readapt/debugger.rb
130
+ - lib/readapt/finder.rb
131
+ - lib/readapt/frame.rb
132
+ - lib/readapt/location.rb
133
+ - lib/readapt/message.rb
134
+ - lib/readapt/message/attach.rb
135
+ - lib/readapt/message/base.rb
136
+ - lib/readapt/message/configuration_done.rb
137
+ - lib/readapt/message/continue.rb
138
+ - lib/readapt/message/disconnect.rb
139
+ - lib/readapt/message/initialize.rb
140
+ - lib/readapt/message/launch.rb
141
+ - lib/readapt/message/next.rb
142
+ - lib/readapt/message/pause.rb
143
+ - lib/readapt/message/scopes.rb
144
+ - lib/readapt/message/set_breakpoints.rb
145
+ - lib/readapt/message/set_exception_breakpoints.rb
146
+ - lib/readapt/message/stack_trace.rb
147
+ - lib/readapt/message/step_in.rb
148
+ - lib/readapt/message/step_out.rb
149
+ - lib/readapt/message/threads.rb
150
+ - lib/readapt/message/variables.rb
151
+ - lib/readapt/monitor.rb
152
+ - lib/readapt/shell.rb
153
+ - lib/readapt/snapshot.rb
154
+ - lib/readapt/thread.rb
155
+ - lib/readapt/variable.rb
156
+ - lib/readapt/version.rb
157
+ - readapt.gemspec
158
+ homepage: https://castwide.com
159
+ licenses:
160
+ - MIT
161
+ metadata:
162
+ homepage_uri: https://castwide.com
163
+ source_code_uri: https://github.com/castwide/readapt
164
+ changelog_uri: https://github.com/castwide/readapt/blob/master/CHANGELOG.md
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '2.2'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubygems_version: 3.0.3
181
+ signing_key:
182
+ specification_version: 4
183
+ summary: A Ruby debugger for the Debug Adapter Protocol
184
+ test_files: []