Skip to content

Commit 18346f8

Browse files
committed
rewrite parse_ruby helper
1 parent 7de5b63 commit 18346f8

File tree

2 files changed

+40
-27
lines changed

2 files changed

+40
-27
lines changed

lib/helpers/parse_ruby.rb

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
with_configurations(number_of_workers: 1) do
88
definitions = { modules: [], classes: [], constants: [] }
99
current_context = definitions
10-
context_stack = []
10+
context_stack = [current_context]
1111

1212
helper_method :find_in_definitions do |names, definitions|
1313
return nil if names.empty? || definitions.nil?
@@ -48,16 +48,17 @@
4848
new_context = existing_module
4949
else
5050
full_name = [current_context[:full_name], name].compact.join('::')
51-
new_context = { name: name, full_name: full_name, modules: [], classes: [], methods: [], static_methods: [], singleton: [], constants: [] }
51+
new_context = { name: name, full_name: full_name, type: "module", modules: [], classes: [], methods: [], static_methods: [], singleton: {}, constants: [] }
5252
current_context[:modules] << new_context
5353
end
5454

55-
context_stack.push(current_context)
55+
context_stack.push(new_context)
5656
current_context = new_context
5757
end
5858

5959
add_callback :module_node, at: 'end' do |node|
60-
current_context = context_stack.pop
60+
context_stack.pop
61+
current_context = context_stack.last
6162
end
6263

6364
add_callback :class_node, at: 'start' do |node|
@@ -68,66 +69,79 @@
6869
new_context = existing_class
6970
else
7071
full_name = [current_context[:full_name], name].compact.join('::')
71-
new_context = { name: name, full_name: full_name, superclass: superclass, modules: [], classes: [], methods: [], static_methods: [], singleton: {}, constants: [], included_modules: [] }
72+
new_context = { name: name, full_name: full_name, type: "class", superclass: superclass, modules: [], classes: [], methods: [], static_methods: [], singleton: {}, constants: [], included_modules: [] }
7273
current_context[:classes] << new_context
7374
end
7475

75-
context_stack.push(current_context)
76+
context_stack.push(new_context)
7677
current_context = new_context
7778
end
7879

7980
add_callback :class_node, at: 'end' do |node|
80-
current_context = context_stack.pop
81+
context_stack.pop
82+
current_context = context_stack.last
8183
end
8284

8385
add_callback :singleton_class_node, at: 'start' do |node|
8486
existing_singleton = current_context[:singleton]
8587
if !existing_singleton.empty?
8688
new_context = existing_singleton
8789
else
88-
new_context = { methods: [], constants: [] }
90+
new_context = { type: 'singleton', methods: [], constants: [] }
8991
current_context[:singleton] = new_context
9092
end
9193

92-
context_stack.push(current_context)
94+
context_stack.push(new_context)
9395
current_context = new_context
9496
end
9597

9698
add_callback :singleton_class_node, at: 'end' do |node|
97-
current_context = context_stack.pop
99+
context_stack.pop
100+
current_context = context_stack.last
98101
end
99102

100103
add_callback :constant_write_node do |node|
101104
current_context[:constants] << { name: node.name.to_s }
102105
end
103106

104107
add_callback :call_node, at: 'start' do |node|
105-
if node.receiver.nil? && node.name == :include
108+
if node.receiver.nil? && node.name == :include && current_context[:type] == "class" && !node.arguments.nil? && %i[constant_read_node constant_path_node].include?(node.arguments.arguments.first.type)
106109
current_context[:included_modules] << node.arguments.arguments.first.to_source
107110
end
111+
end
108112

109-
if node.name == :class_eval
110-
klass_definition = find_class(node.receiver.to_source, definitions)
111-
current_context = klass_definition if klass_definition
113+
add_callback :call_node, at: 'start' do |node|
114+
# we can't handle the class_eval / included / class_methods
115+
if !node.receiver.nil? && %i[class_eval included class_methods].include?(node.name)
116+
throw(:abort)
112117
end
113118
end
114119

115120
add_callback :def_node, at: 'start' do |node|
116-
name = node.name.to_s
121+
# we can't handle `def self.inclueded` method
122+
if !node.receiver.nil? && node.name == :included
123+
throw(:abort)
124+
end
125+
end
126+
127+
add_callback :def_node, at: 'start' do |node|
128+
throw(:abort) unless context_stack.last[:type]
117129

130+
name = node.name.to_s
118131
new_context = { name: name }
119132
if node.receiver.nil?
120133
current_context[:methods] << new_context
121134
else
122135
current_context[:static_methods] << new_context
123136
end
124137

125-
context_stack.push(current_context)
138+
context_stack.push(new_context)
126139
current_context = new_context
127140
end
128141

129142
add_callback :def_node, at: 'end' do |node|
130-
current_context = context_stack.pop
143+
context_stack.pop
144+
current_context = context_stack.last
131145
end
132146
end
133147

@@ -168,11 +182,12 @@ def add_ancestors(definitions)
168182
superclass = klass[:superclass]
169183
while superclass
170184
superclass_class = find_class(superclass, definitions)
171-
ancestors << superclass_class[:full_name]
172185
if superclass_class
186+
ancestors << superclass_class[:full_name]
173187
ancestors.concat(superclass_class[:included_modules]) if superclass_class[:included_modules]
174188
superclass = superclass_class[:superclass]
175189
else
190+
ancestors << superclass
176191
superclass = nil
177192
end
178193
end

spec/helpers/parse_ruby_spec.rb

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
File.write('app/models/user.rb', <<~EOF)
1515
module Synvert
1616
class User
17+
include Trackable
18+
1719
ROLES = %w[user admin].freeze
1820
1921
class << self
@@ -42,14 +44,6 @@ def user_type
4244
end
4345
end
4446
EOF
45-
FileUtils.mkdir_p('config/initializers')
46-
File.write('config/initializers/trackable.rb', <<~EOF)
47-
Rails.config.application.after_initialize do
48-
Synvert::User.class_eval do
49-
include Trackable
50-
end
51-
end
52-
EOF
5347

5448
rewriter.process
5549

@@ -59,11 +53,13 @@ def user_type
5953
{
6054
name: "Synvert",
6155
full_name: "Synvert",
56+
type: "module",
6257
classes: [
6358
{
6459
name: "Admin",
6560
full_name: "Synvert::Admin",
6661
superclass: "User",
62+
type: "class",
6763
singleton: {},
6864
classes: [],
6965
constants: [],
@@ -77,8 +73,10 @@ def user_type
7773
{
7874
name: "User",
7975
full_name: "Synvert::User",
76+
type: "class",
8077
superclass: nil,
8178
singleton: {
79+
type: 'singleton',
8280
constants: [],
8381
methods: [
8482
{ name: 'system' },
@@ -97,7 +95,7 @@ def user_type
9795
],
9896
modules: [],
9997
methods: [],
100-
singleton: [],
98+
singleton: {},
10199
static_methods: [],
102100
constants: []
103101
}

0 commit comments

Comments
 (0)