5
5
6
6
# Set number_of_workers to 1 to skip parallel.
7
7
with_configurations ( number_of_workers : 1 ) do
8
- definitions = { modules : [ ] , classes : [ ] }
8
+ definitions = { modules : [ ] , classes : [ ] , constants : [ ] }
9
9
current_context = definitions
10
10
context_stack = [ ]
11
11
12
+ helper_method :find_in_definitions do |names , definitions |
13
+ return nil if names . empty? || definitions . nil?
14
+
15
+ if names . length > 1
16
+ # The first name is a module, find it and search within its definitions
17
+ mod_name = names . shift
18
+ definitions [ :modules ] . each do |mod |
19
+ if mod [ :name ] == mod_name
20
+ return find_in_definitions ( names , mod ) # Recurse with the rest of the names
21
+ end
22
+ end
23
+ else
24
+ # The last name is a class, find it in the current definitions
25
+ class_name = names . first
26
+ definitions [ :classes ] . each do |klass |
27
+ return klass if klass [ :name ] == class_name
28
+ end
29
+ definitions [ :modules ] . each do |mod |
30
+ found = find_in_definitions ( [ class_name ] , mod )
31
+ return found if found
32
+ end
33
+ end
34
+
35
+ nil
36
+ end
37
+
38
+ helper_method :find_class do |full_name , definitions |
39
+ names = full_name . split ( '::' )
40
+ find_in_definitions ( names , definitions )
41
+ end
42
+
12
43
within_file Synvert ::ALL_RUBY_FILES do
13
44
add_callback :module_node , at : 'start' do |node |
14
45
name = node . constant_path . to_source
15
46
existing_module = current_context [ :modules ] . find { |mod | mod [ :name ] == name }
16
47
if existing_module
17
48
new_context = existing_module
18
49
else
19
- new_context = { name : name , modules : [ ] , classes : [ ] , methods : [ ] , static_methods : [ ] , constants : [ ] }
50
+ 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 : [ ] }
20
52
current_context [ :modules ] << new_context
21
53
end
22
54
35
67
if existing_class
36
68
new_context = existing_class
37
69
else
38
- new_context = { name : name , superclass : superclass , modules : [ ] , classes : [ ] , methods : [ ] , static_methods : [ ] , singleton : { } , constants : [ ] , included_modules : [ ] }
70
+ 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 : [ ] }
39
72
current_context [ :classes ] << new_context
40
73
end
41
74
52
85
if !existing_singleton . empty?
53
86
new_context = existing_singleton
54
87
else
55
- new_context = { methods : [ ] }
88
+ new_context = { methods : [ ] , constants : [ ] }
56
89
current_context [ :singleton ] = new_context
57
90
end
58
91
72
105
if node . receiver . nil? && node . name == :include
73
106
current_context [ :included_modules ] << node . arguments . arguments . first . to_source
74
107
end
108
+
109
+ if node . name == :class_eval
110
+ klass_definition = find_class ( node . receiver . to_source , definitions )
111
+ current_context = klass_definition if klass_definition
112
+ end
75
113
end
76
114
77
115
add_callback :def_node , at : 'start' do |node |
93
131
end
94
132
end
95
133
96
- def find_class ( name , definitions )
97
- definitions [ :classes ] . each do |klass |
98
- return klass if klass [ :name ] == name
99
- found = find_class ( name , klass )
100
- return found if found
101
- end
134
+ def find_class ( full_name , definitions )
135
+ names = full_name . split ( '::' )
136
+ find_in_definitions ( names , definitions )
137
+ end
102
138
103
- definitions [ :modules ] . each do |mod |
104
- found = find_class ( name , mod )
105
- return found if found
139
+ def find_in_definitions ( names , definitions )
140
+ return nil if names . empty? || definitions . nil?
141
+
142
+ if names . length > 1
143
+ # The first name is a module, find it and search within its definitions
144
+ mod_name = names . shift
145
+ definitions [ :modules ] . each do |mod |
146
+ if mod [ :name ] == mod_name
147
+ return find_in_definitions ( names , mod ) # Recurse with the rest of the names
148
+ end
149
+ end
150
+ else
151
+ # The last name is a class, find it in the current definitions
152
+ class_name = names . first
153
+ definitions [ :classes ] . each do |klass |
154
+ return klass if klass [ :name ] == class_name
155
+ end
156
+ definitions [ :modules ] . each do |mod |
157
+ found = find_in_definitions ( [ class_name ] , mod )
158
+ return found if found
159
+ end
106
160
end
107
161
108
162
nil
@@ -113,8 +167,8 @@ def add_ancestors(definitions)
113
167
ancestors = [ ]
114
168
superclass = klass [ :superclass ]
115
169
while superclass
116
- ancestors << superclass
117
170
superclass_class = find_class ( superclass , definitions )
171
+ ancestors << superclass_class [ :full_name ]
118
172
if superclass_class
119
173
ancestors . concat ( superclass_class [ :included_modules ] ) if superclass_class [ :included_modules ]
120
174
superclass = superclass_class [ :superclass ]
0 commit comments