hyperlayer 0.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +38 -0
- data/Rakefile +8 -0
- data/app/assets/config/manifest.js +7 -0
- data/app/assets/stylesheets/application.bootstrap.scss +2 -0
- data/app/assets/stylesheets/hyperlayer/app.css +47 -0
- data/app/assets/stylesheets/hyperlayer/application.css +18774 -0
- data/app/assets/stylesheets/hyperlayer/prism.css +3 -0
- data/app/controllers/hyperlayer/application_controller.rb +4 -0
- data/app/controllers/hyperlayer/events_controller.rb +95 -0
- data/app/controllers/hyperlayer/example_groups_controller.rb +9 -0
- data/app/controllers/hyperlayer/paths_controller.rb +18 -0
- data/app/controllers/hyperlayer/runs_controller.rb +7 -0
- data/app/controllers/hyperlayer/specs_controller.rb +8 -0
- data/app/javascript/controllers/application.js +9 -0
- data/app/javascript/controllers/index.js +11 -0
- data/app/javascript/hyperlayer/application.js +7 -0
- data/app/javascript/hyperlayer/prism.js +8 -0
- data/app/models/application_record.rb +3 -0
- data/app/models/hyperlayer/event.rb +28 -0
- data/app/models/hyperlayer/example_group.rb +6 -0
- data/app/models/hyperlayer/path.rb +35 -0
- data/app/models/hyperlayer/run.rb +5 -0
- data/app/models/hyperlayer/spec.rb +8 -0
- data/app/services/build_file_overlay.rb +26 -0
- data/app/services/callable.rb +129 -0
- data/app/services/file_builder.rb +260 -0
- data/app/services/find_method_from_event.rb +65 -0
- data/app/services/find_method_in_path.rb +98 -0
- data/app/services/generate_buffer.rb +116 -0
- data/app/services/import_events.rb +56 -0
- data/app/services/split_methods.rb +50 -0
- data/app/services/test_one.rb +34 -0
- data/app/services/update_code.rb +111 -0
- data/app/views/hyperlayer/events/_code.html.erb +36 -0
- data/app/views/hyperlayer/events/_event.html.erb +15 -0
- data/app/views/hyperlayer/events/_tree-text.html.erb +22 -0
- data/app/views/hyperlayer/events/_tree.html.erb +15 -0
- data/app/views/hyperlayer/events/index.html.erb +41 -0
- data/app/views/hyperlayer/example_groups/index.html.erb +25 -0
- data/app/views/hyperlayer/paths/_path.html.erb +52 -0
- data/app/views/hyperlayer/paths/index.html.erb +5 -0
- data/app/views/hyperlayer/paths/show.html.erb +3 -0
- data/app/views/hyperlayer/runs/index.html.erb +23 -0
- data/app/views/hyperlayer/specs/index.html.erb +24 -0
- data/app/views/layouts/_nav.html.erb +8 -0
- data/app/views/layouts/hyperlayer/application.html.erb +30 -0
- data/app/views/layouts/hyperlayer/mailer.html.erb +13 -0
- data/app/views/layouts/hyperlayer/mailer.text.erb +1 -0
- data/config/initializers/engine_migrations.rb +3 -0
- data/config/routes.rb +11 -0
- data/db/migrate/20231009165755_create_hyperlayer_events.rb +19 -0
- data/db/migrate/20231009165919_create_hyperlayer_example_groups.rb +12 -0
- data/db/migrate/20231009165952_create_hyperlayer_runs.rb +9 -0
- data/db/migrate/20231009170101_create_hyperlayer_paths.rb +10 -0
- data/db/migrate/20231009170121_create_hyperlayer_specs.rb +12 -0
- data/lib/hyperlayer/engine.rb +22 -0
- data/lib/hyperlayer/method_tracer.rb +12 -0
- data/lib/hyperlayer/tracer.rb +78 -0
- data/lib/hyperlayer/version.rb +3 -0
- data/lib/hyperlayer.rb +15 -0
- data/lib/tasks/listen.rake +8 -0
- metadata +207 -0
@@ -0,0 +1,260 @@
|
|
1
|
+
class FileBuilder
|
2
|
+
def initialize(options = {})
|
3
|
+
@options = options
|
4
|
+
|
5
|
+
if options[:url]
|
6
|
+
parts = options[:url].split('/')
|
7
|
+
|
8
|
+
if parts.count > 1
|
9
|
+
options[:object] = parts.last.singularize
|
10
|
+
options[:class] = parts.last.singularize.capitalize
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :options
|
16
|
+
|
17
|
+
OPTION_KLASS_MAP = {
|
18
|
+
'authorisation' => 'Authorisation',
|
19
|
+
'url' => 'ClassDefinition',
|
20
|
+
'request' => 'BuildStrongParams',
|
21
|
+
'controller_action' => 'ControllerAction',
|
22
|
+
'skip-csrf' => 'SkipCsrf'
|
23
|
+
}
|
24
|
+
|
25
|
+
def call
|
26
|
+
options.to_h.each_with_object(parts) do |(option, _value), output|
|
27
|
+
klass = OPTION_KLASS_MAP[option]
|
28
|
+
|
29
|
+
next unless klass
|
30
|
+
|
31
|
+
fragments = "FileBuilder::#{klass}".constantize.call(options: options)
|
32
|
+
|
33
|
+
fragments.each do |part, code|
|
34
|
+
output[part] ||= []
|
35
|
+
|
36
|
+
output[part] << code
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def parts
|
44
|
+
{
|
45
|
+
definition_start: [],
|
46
|
+
before_actions: [],
|
47
|
+
public_methods: [],
|
48
|
+
private_methods: [],
|
49
|
+
definition_finish: []
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
class Authorisation
|
54
|
+
include Callable
|
55
|
+
expects :options
|
56
|
+
|
57
|
+
def call
|
58
|
+
if options['authorisation'] == '1'
|
59
|
+
{
|
60
|
+
before_actions: authorisation
|
61
|
+
}
|
62
|
+
else
|
63
|
+
{}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def authorisation
|
70
|
+
template.tap do |temp|
|
71
|
+
temp.scan(/\%(.*?)\%/).flatten.uniq.each do |value|
|
72
|
+
temp.gsub!("%#{value}%", options[value])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def template
|
78
|
+
File.read('app/views/code/authorisation.erb')[0..-2]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class ControllerAction
|
83
|
+
include Callable
|
84
|
+
expects :options
|
85
|
+
|
86
|
+
def call
|
87
|
+
if options['controller_action'].present?
|
88
|
+
{
|
89
|
+
public_methods: code
|
90
|
+
}
|
91
|
+
else
|
92
|
+
{}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def code
|
99
|
+
template.tap do |temp|
|
100
|
+
temp.scan(/\%(.*?)\%/).flatten.uniq.each do |value|
|
101
|
+
temp.gsub!("%#{value}%", options[value])
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def template
|
107
|
+
File.read("app/views/code/controller_actions/#{controller_action}.erb")[0..-2]
|
108
|
+
end
|
109
|
+
|
110
|
+
def controller_action
|
111
|
+
options['controller_action']
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class TrackEvent
|
116
|
+
include Callable
|
117
|
+
expects :options
|
118
|
+
|
119
|
+
def call
|
120
|
+
if options['track_event'].present?
|
121
|
+
{
|
122
|
+
before_action: code,
|
123
|
+
private_methods: code
|
124
|
+
}
|
125
|
+
else
|
126
|
+
{}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def code
|
133
|
+
template.tap do |temp|
|
134
|
+
temp.scan(/\%(.*?)\%/).flatten.uniq.each do |value|
|
135
|
+
temp.gsub!("%#{value}%", options[value])
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def template
|
141
|
+
File.read("app/views/code/controller_actions/#{controller_action}.erb")[0..-2]
|
142
|
+
end
|
143
|
+
|
144
|
+
def controller_action
|
145
|
+
options['controller_action']
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class ClassDefinition
|
150
|
+
include Callable
|
151
|
+
expects :options
|
152
|
+
|
153
|
+
def call
|
154
|
+
return {} unless options[:url].present?
|
155
|
+
|
156
|
+
{
|
157
|
+
definition_start: start,
|
158
|
+
definition_finish: finish
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def start
|
165
|
+
levels.map.with_index(1) do |level, index|
|
166
|
+
if index == count
|
167
|
+
"class #{level.capitalize}Controller < ApplicationController"
|
168
|
+
else
|
169
|
+
"module #{level.capitalize}"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def levels
|
175
|
+
options[:url].split('/').select(&:present?)
|
176
|
+
end
|
177
|
+
|
178
|
+
def count
|
179
|
+
levels.count
|
180
|
+
end
|
181
|
+
|
182
|
+
def finish
|
183
|
+
levels.map { 'end' }
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class SkipCsrf
|
188
|
+
include Callable
|
189
|
+
expects :options
|
190
|
+
|
191
|
+
def call
|
192
|
+
return {} unless options['skip-csrf'] == '1'
|
193
|
+
|
194
|
+
{ private_methods: code }
|
195
|
+
end
|
196
|
+
|
197
|
+
private
|
198
|
+
|
199
|
+
def code
|
200
|
+
template.tap do |temp|
|
201
|
+
temp.scan(/\%(.*?)\%/).flatten.uniq.each do |value|
|
202
|
+
temp.gsub!("%#{value}%", options[value].to_s)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def template
|
208
|
+
File.read('app/views/code/strong_params.erb')
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
class BuildStrongParams
|
213
|
+
include Callable
|
214
|
+
expects :options
|
215
|
+
|
216
|
+
def call
|
217
|
+
return {} unless options[:request].present?
|
218
|
+
|
219
|
+
options[:keys] = keys
|
220
|
+
|
221
|
+
{ private_methods: code }
|
222
|
+
end
|
223
|
+
|
224
|
+
private
|
225
|
+
|
226
|
+
def code
|
227
|
+
template.tap do |temp|
|
228
|
+
temp.scan(/\%(.*?)\%/).flatten.uniq.each do |value|
|
229
|
+
temp.gsub!("%#{value}%", options[value].to_s)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def template
|
235
|
+
File.read('app/views/code/strong_params.erb')
|
236
|
+
end
|
237
|
+
|
238
|
+
def keys
|
239
|
+
JSON.parse(options[:request]).keys
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
############################################
|
244
|
+
# def parts
|
245
|
+
# {
|
246
|
+
# definition_start: {
|
247
|
+
# def_strong_params: {
|
248
|
+
# open: [],
|
249
|
+
# body: [],
|
250
|
+
# end: []
|
251
|
+
# }
|
252
|
+
# },
|
253
|
+
# before_actions: {},
|
254
|
+
# public_methods: {},
|
255
|
+
# private_methods: {},
|
256
|
+
# definition_finish: {}
|
257
|
+
# }
|
258
|
+
# end
|
259
|
+
############################################
|
260
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# require 'fast'
|
2
|
+
|
3
|
+
class FindMethodFromEvent < Parser::AST::Processor
|
4
|
+
include RuboCop::AST::Traversal
|
5
|
+
|
6
|
+
def self.call(event)
|
7
|
+
new.call(event)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Have a "Exists?" method that checks to see if something exists
|
11
|
+
# If it doesn't use an Insert class and define which section it should go into
|
12
|
+
# If it does, work out the differences(?) and update them
|
13
|
+
|
14
|
+
def call(event)
|
15
|
+
code = File.readlines(event.path.path).join
|
16
|
+
source = RuboCop::ProcessedSource.new(code, 2.7)
|
17
|
+
|
18
|
+
return unless source.present?
|
19
|
+
|
20
|
+
node = FindMethod.call(
|
21
|
+
type: :def,
|
22
|
+
name: event.method.to_sym,
|
23
|
+
source: source
|
24
|
+
)
|
25
|
+
|
26
|
+
return unless node.present?
|
27
|
+
|
28
|
+
DisplayMethod
|
29
|
+
.call(node: node, code: code)
|
30
|
+
.split("\n")
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
class FindMethod
|
36
|
+
include Callable
|
37
|
+
expects :type, :name, :source
|
38
|
+
|
39
|
+
def call
|
40
|
+
source.ast
|
41
|
+
.each_node
|
42
|
+
.map { |n| n if n.type == type && n.method_name == name }
|
43
|
+
.compact
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class DisplayMethod
|
48
|
+
include Callable
|
49
|
+
expects :code, :node
|
50
|
+
|
51
|
+
def call
|
52
|
+
code[begin_pos...end_pos]
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
delegate :begin_pos, :end_pos, to: :expression
|
58
|
+
|
59
|
+
def expression
|
60
|
+
node.first
|
61
|
+
.loc
|
62
|
+
.expression
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# require 'fast'
|
2
|
+
|
3
|
+
class FindMethodInPath < Parser::AST::Processor
|
4
|
+
include RuboCop::AST::Traversal
|
5
|
+
|
6
|
+
def self.call(path_id)
|
7
|
+
new.call(path_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Have a "Exists?" method that checks to see if something exists
|
11
|
+
# If it doesn't use an Insert class and define which section it should go into
|
12
|
+
# If it does, work out the differences(?) and update them
|
13
|
+
|
14
|
+
def call(path_id)
|
15
|
+
path = Path.find(path_id)
|
16
|
+
code = File.readlines(path.path).join
|
17
|
+
source = RuboCop::ProcessedSource.new(code, 2.7)
|
18
|
+
|
19
|
+
path.events.call.each_with_object({}) do |event, methods|
|
20
|
+
methods[event.method.to_sym] = ''
|
21
|
+
|
22
|
+
node = FindMethod.call(
|
23
|
+
type: :def,
|
24
|
+
name: event.method.to_sym,
|
25
|
+
source: source
|
26
|
+
)
|
27
|
+
|
28
|
+
next unless node.present?
|
29
|
+
|
30
|
+
methods[event.method.to_sym] = DisplayMethod.call(node: node, code: code)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
class FindMethod
|
37
|
+
include Callable
|
38
|
+
expects :type, :name, :source
|
39
|
+
|
40
|
+
def call
|
41
|
+
binding.pry
|
42
|
+
|
43
|
+
source.ast
|
44
|
+
.each_node
|
45
|
+
.map { |n| n if n.type == type && n.method_name == name }
|
46
|
+
.compact
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class AddMethod
|
51
|
+
include Callable
|
52
|
+
expects :code, :pos
|
53
|
+
|
54
|
+
def call
|
55
|
+
code.insert(pos, "def code \n inserted.here! \n end")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class Replace
|
60
|
+
include Callable
|
61
|
+
expects :code, :node, :with
|
62
|
+
|
63
|
+
def call
|
64
|
+
code[begin_pos...end_pos] = with
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
delegate :begin_pos, :end_pos, to: :expression
|
70
|
+
|
71
|
+
def expression
|
72
|
+
node.first
|
73
|
+
.arguments
|
74
|
+
.first
|
75
|
+
.loc
|
76
|
+
.expression
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class DisplayMethod
|
81
|
+
include Callable
|
82
|
+
expects :code, :node
|
83
|
+
|
84
|
+
def call
|
85
|
+
code[begin_pos...end_pos]
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
delegate :begin_pos, :end_pos, to: :expression
|
91
|
+
|
92
|
+
def expression
|
93
|
+
node.first
|
94
|
+
.loc
|
95
|
+
.expression
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
class GenerateBuffer < Parser::AST::Processor
|
2
|
+
include RuboCop::AST::Traversal
|
3
|
+
include Callable
|
4
|
+
|
5
|
+
expects :params
|
6
|
+
|
7
|
+
DEFAULT_BUFFER = <<~NODE
|
8
|
+
module Fresco
|
9
|
+
class Dev
|
10
|
+
end
|
11
|
+
end
|
12
|
+
NODE
|
13
|
+
|
14
|
+
def call
|
15
|
+
@code = DEFAULT_BUFFER
|
16
|
+
@buffer = RuboCop::ProcessedSource.new(@code, 2.7)
|
17
|
+
|
18
|
+
fields.each do |field|
|
19
|
+
@buffer = "#{self.class}::#{field.classify}"
|
20
|
+
.constantize
|
21
|
+
.call(buffer: @buffer, params: params)
|
22
|
+
end
|
23
|
+
|
24
|
+
@buffer
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def fields
|
30
|
+
params.slice(:url).keys
|
31
|
+
end
|
32
|
+
|
33
|
+
class Url
|
34
|
+
include Callable
|
35
|
+
expects :buffer, :params
|
36
|
+
|
37
|
+
def call
|
38
|
+
node = FindMethod.call(
|
39
|
+
meth_name: :module,
|
40
|
+
source: buffer
|
41
|
+
)
|
42
|
+
|
43
|
+
Replace.call(
|
44
|
+
buffer: code,
|
45
|
+
node: node,
|
46
|
+
with: InitializeModuleClass.call(url: params[:url])
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class InitializeModuleClass
|
52
|
+
include Callable
|
53
|
+
expects :url
|
54
|
+
|
55
|
+
def call
|
56
|
+
return {} unless url.present?
|
57
|
+
|
58
|
+
[start, finish].flatten.join("\n")
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def start
|
64
|
+
levels.map.with_index(1) do |level, index|
|
65
|
+
if index == count
|
66
|
+
"class #{level.capitalize}Controller < ApplicationController"
|
67
|
+
else
|
68
|
+
"module #{level.capitalize}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def levels
|
74
|
+
url.split('/').select(&:present?)
|
75
|
+
end
|
76
|
+
|
77
|
+
def count
|
78
|
+
levels.count
|
79
|
+
end
|
80
|
+
|
81
|
+
def finish
|
82
|
+
levels.map { 'end' }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class FindMethod
|
87
|
+
include Callable
|
88
|
+
expects :meth_name, :source
|
89
|
+
|
90
|
+
def call
|
91
|
+
source.ast
|
92
|
+
.each_node
|
93
|
+
.map { |n| n if n.type == :send && n.method_name == meth_name }
|
94
|
+
.compact
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class Replace
|
99
|
+
include Callable
|
100
|
+
expects :code, :node, :with
|
101
|
+
|
102
|
+
def call
|
103
|
+
code[start...finish] = with
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def start
|
109
|
+
node.first.arguments.first.loc.expression.begin_pos
|
110
|
+
end
|
111
|
+
|
112
|
+
def finish
|
113
|
+
node.first.arguments.first.loc.expression.end_pos
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# ["#{tp.path}:#{tp.lineno}", tp.defined_class, tp.event, tp.method_id, rv]
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
class ImportEvents
|
6
|
+
def self.call
|
7
|
+
# Connect to a Redis server
|
8
|
+
redis = Redis.new(url: 'redis://localhost:6379')
|
9
|
+
|
10
|
+
begin
|
11
|
+
# Subscribe to a Redis channel
|
12
|
+
redis.subscribe('events') do |on|
|
13
|
+
on.message do |channel, message|
|
14
|
+
puts "Received message on channel #{channel}: #{message}"
|
15
|
+
|
16
|
+
event = Hashie::Mash.new(JSON.parse(message))
|
17
|
+
|
18
|
+
run = Hyperlayer::Run.where(process: event.spec.process).first_or_create
|
19
|
+
path = Hyperlayer::Path.where(path: event.path).first_or_create
|
20
|
+
|
21
|
+
spec_file = event.spec.tree.reverse.first
|
22
|
+
spec = run.specs.where(
|
23
|
+
location: spec_file.file_path,
|
24
|
+
description: spec_file.description, # sometimes a class, could also be a string for a feature spec,
|
25
|
+
data: spec_file.except(:file_path, :description)
|
26
|
+
).first_or_create
|
27
|
+
|
28
|
+
example_groups = event.spec.tree.reverse[1..]
|
29
|
+
groups = example_groups.map do |example_group|
|
30
|
+
spec.example_groups.where(
|
31
|
+
location: example_group.location,
|
32
|
+
description: example_group.description,
|
33
|
+
data: example_group.except(:location, :description)
|
34
|
+
).first_or_create
|
35
|
+
end
|
36
|
+
|
37
|
+
example_group = groups.last
|
38
|
+
example_group.events.create(
|
39
|
+
path: path,
|
40
|
+
line_number: event.line_number,
|
41
|
+
defined_class: event.defined_class,
|
42
|
+
event_type: event.event,
|
43
|
+
method: event.method_id,
|
44
|
+
return_value: event.return_value,
|
45
|
+
arguments: event.arguments,
|
46
|
+
variables: event.variables
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
rescue Redis::BaseConnectionError => error
|
51
|
+
puts "#{error}, retrying in 1s"
|
52
|
+
sleep 1
|
53
|
+
retry
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# require 'fast'
|
2
|
+
|
3
|
+
class SplitMethods < Parser::AST::Processor
|
4
|
+
include RuboCop::AST::Traversal
|
5
|
+
|
6
|
+
def self.call(event)
|
7
|
+
new.call(event)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(event)
|
11
|
+
raw_code = File.readlines(event.path.path)
|
12
|
+
code = raw_code.join
|
13
|
+
source = RuboCop::ProcessedSource.new(code, 3.2)
|
14
|
+
|
15
|
+
method_name = event.method.to_sym
|
16
|
+
|
17
|
+
method = source.ast
|
18
|
+
.each_node
|
19
|
+
.select do |n|
|
20
|
+
# Will need to add method name here, and the delegate param
|
21
|
+
#
|
22
|
+
n.type == :def && method_name == n.method_name # || n.type == :send && n.method_name == :delegate
|
23
|
+
end
|
24
|
+
|
25
|
+
method = method.first
|
26
|
+
|
27
|
+
DisplayMethod.call(code: code, node: method)
|
28
|
+
rescue => e
|
29
|
+
Rails.logger.info("Missing method: #{method_name}")
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
class DisplayMethod
|
35
|
+
include Callable
|
36
|
+
expects :code, :node
|
37
|
+
|
38
|
+
def call
|
39
|
+
code[begin_pos...end_pos]
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
delegate :begin_pos, :end_pos, to: :expression
|
45
|
+
|
46
|
+
def expression
|
47
|
+
node.loc.expression
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class TestOne
|
2
|
+
include Callable
|
3
|
+
expects :path
|
4
|
+
|
5
|
+
def call
|
6
|
+
@file = []
|
7
|
+
@raw_file = File.readlines(path.path).join
|
8
|
+
|
9
|
+
return @raw_file
|
10
|
+
|
11
|
+
path.events.where(event_type: 'return').each do |event|
|
12
|
+
href = "<a href='#'>#{event.method}</a>"
|
13
|
+
|
14
|
+
matches = @raw_file.gsub!(/#{event.method}/, href)
|
15
|
+
end
|
16
|
+
|
17
|
+
return @raw_file
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
@display_file = @raw_file.map.with_index(1) do |line, index|
|
22
|
+
@file << line
|
23
|
+
|
24
|
+
events = path.events.where(event_type: 'return', line_number: index)
|
25
|
+
|
26
|
+
events.map do |event|
|
27
|
+
@file << ">>> #{event.return_value.inspect} (#{event.method})"
|
28
|
+
@file << "\n"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
@file
|
33
|
+
end
|
34
|
+
end
|