@@ -20,11 +20,12 @@ def initialize(line, column)
20
20
21
21
# This entry represents a class definition using the class keyword.
22
22
class ClassDefinition
23
- attr_reader :nesting , :name , :location , :comments
23
+ attr_reader :nesting , :name , :superclass , : location, :comments
24
24
25
- def initialize ( nesting , name , location , comments )
25
+ def initialize ( nesting , name , superclass , location , comments )
26
26
@nesting = nesting
27
27
@name = name
28
+ @superclass = superclass
28
29
@location = location
29
30
@comments = comments
30
31
end
@@ -182,7 +183,7 @@ def find_constant_path(insns, index)
182
183
if insn . is_a? ( Array ) && insn [ 0 ] == :opt_getconstant_path
183
184
# In this case we're on Ruby 3.2+ and we have an opt_getconstant_path
184
185
# instruction, so we already know all of the symbols in the nesting.
185
- insn [ 1 ]
186
+ [ index - 1 , insn [ 1 ] ]
186
187
elsif insn . is_a? ( Symbol ) && insn . match? ( /\A label_\d +/ )
187
188
# Otherwise, if we have a label then this is very likely the
188
189
# destination of an opt_getinlinecache instruction, in which case
@@ -195,7 +196,9 @@ def find_constant_path(insns, index)
195
196
index -= 1
196
197
end
197
198
198
- names
199
+ [ index - 1 , names ]
200
+ else
201
+ [ index , [ ] ]
199
202
end
200
203
end
201
204
@@ -213,7 +216,24 @@ def index_iseq(iseq, file_comments)
213
216
_ , name , class_iseq , flags = insn
214
217
next_nesting = current_nesting . dup
215
218
216
- if ( nesting = find_constant_path ( insns , index - 2 ) )
219
+ # This is the index we're going to search for the nested constant
220
+ # path within the declaration name.
221
+ constant_index = index - 2
222
+
223
+ # This is the superclass of the class being defined.
224
+ superclass = [ ]
225
+
226
+ # If there is a superclass, then we're going to find it here and
227
+ # then update the constant_index as necessary.
228
+ if flags & VM_DEFINECLASS_FLAG_HAS_SUPERCLASS > 0
229
+ constant_index , superclass = find_constant_path ( insns , index - 1 )
230
+
231
+ if superclass . empty?
232
+ raise NotImplementedError , "superclass with non constant path"
233
+ end
234
+ end
235
+
236
+ if ( _ , nesting = find_constant_path ( insns , constant_index ) )
217
237
# If there is a constant path in the class name, then we need to
218
238
# handle that by updating the nesting.
219
239
next_nesting << ( nesting << name )
@@ -243,6 +263,7 @@ def index_iseq(iseq, file_comments)
243
263
results << ClassDefinition . new (
244
264
next_nesting ,
245
265
name ,
266
+ superclass ,
246
267
location ,
247
268
EntryComments . new ( file_comments , location )
248
269
)
@@ -299,9 +320,23 @@ def visit_class(node)
299
320
location =
300
321
Location . new ( node . location . start_line , node . location . start_column )
301
322
323
+ superclass =
324
+ if node . superclass
325
+ visited = visit ( node . superclass )
326
+
327
+ if visited == [ [ ] ]
328
+ raise NotImplementedError , "superclass with non constant path"
329
+ end
330
+
331
+ visited
332
+ else
333
+ [ ]
334
+ end
335
+
302
336
results << ClassDefinition . new (
303
337
nesting . dup ,
304
338
names . last ,
339
+ superclass ,
305
340
location ,
306
341
comments_for ( node )
307
342
)
@@ -315,14 +350,7 @@ def visit_const_ref(node)
315
350
end
316
351
317
352
def visit_const_path_ref ( node )
318
- names =
319
- if node . parent . is_a? ( ConstPathRef )
320
- visit ( node . parent )
321
- else
322
- [ visit ( node . parent ) ]
323
- end
324
-
325
- names << node . constant . value . to_sym
353
+ visit ( node . parent ) << node . constant . value . to_sym
326
354
end
327
355
328
356
def visit_def ( node )
@@ -376,7 +404,7 @@ def visit_statements(node)
376
404
end
377
405
378
406
def visit_var_ref ( node )
379
- node . value . value . to_sym
407
+ [ node . value . value . to_sym ]
380
408
end
381
409
end
382
410
0 commit comments