Class: PinkSpoon::RbiIndex::RbiVisitor

Inherits:
Prism::Visitor
  • Object
show all
Defined in:
lib/pink_spoon/rbi_index.rb

Overview


Prism AST visitor that walks RBI files and extracts:

- sig+def pairs (entries)
- extend/include calls (mixins)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(comment_map = {}) ⇒ RbiVisitor

Returns a new instance of RbiVisitor.



257
258
259
260
261
262
263
264
# File 'lib/pink_spoon/rbi_index.rb', line 257

def initialize(comment_map = {})
  @entries       = []
  @mixins        = Hash.new { |h, k| h[k] = [] }
  @const_sources = {}
  @scope         = []
  @pending_sig   = nil
  @comment_map   = comment_map
end

Instance Attribute Details

#const_sourcesObject (readonly)

Returns the value of attribute const_sources.



255
256
257
# File 'lib/pink_spoon/rbi_index.rb', line 255

def const_sources
  @const_sources
end

#entriesObject (readonly)

Returns the value of attribute entries.



255
256
257
# File 'lib/pink_spoon/rbi_index.rb', line 255

def entries
  @entries
end

#mixinsObject (readonly)

Returns the value of attribute mixins.



255
256
257
# File 'lib/pink_spoon/rbi_index.rb', line 255

def mixins
  @mixins
end

Instance Method Details

#visit_call_node(node) ⇒ Object



287
288
289
290
291
292
293
294
# File 'lib/pink_spoon/rbi_index.rb', line 287

def visit_call_node(node)
  if node.name == :sig && node.receiver.nil?
    @pending_sig = node.slice
  elsif (node.name == :extend || node.name == :include) && node.receiver.nil?
    record_mixins(node)
  end
  super
end

#visit_class_node(node) ⇒ Object



274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/pink_spoon/rbi_index.rb', line 274

def visit_class_node(node)
  source_comment = source_comment_at(node.location.start_line)
  push_scope(node.constant_path) do
    type = @scope.join("::")
    @const_sources[type] = source_comment if source_comment
    if node.superclass
      parent = const_path_to_string(node.superclass).delete_prefix("::")
      @mixins[type] << parent unless @mixins[type].include?(parent)
    end
    super
  end
end

#visit_def_node(node) ⇒ Object



296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/pink_spoon/rbi_index.rb', line 296

def visit_def_node(node)
  method_name  = node.name.to_s
  sig          = @pending_sig
  @pending_sig = nil

  # Build a plain def line even when no Sorbet sig exists.
  # e.g. "def init_label_set(labels)"
  params    = node.parameters&.slice
  def_line  = params ? "def #{method_name}(#{params})" : "def #{method_name}"

  # Check for a "# source://" comment on the line immediately before this def.
  preceding = @comment_map[node.location.start_line - 1]
  source    = preceding&.match?(/# source:\/\//) ? preceding : nil

  @entries << {
    type:        @scope.join("::"),
    method:      method_name,
    sig:         sig,
    def_line:    def_line,
    return_type: sig ? extract_return_type(sig) : nil,
    params:      sig ? extract_params(sig) : {},
    source:      source,
    line:        node.location.start_line,
  }

  super
end

#visit_module_node(node) ⇒ Object



266
267
268
269
270
271
272
# File 'lib/pink_spoon/rbi_index.rb', line 266

def visit_module_node(node)
  source_comment = source_comment_at(node.location.start_line)
  push_scope(node.constant_path) do
    @const_sources[@scope.join("::")] = source_comment if source_comment
    super
  end
end