Class: PinkSpoon::RbiIndex

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

Overview

Parses every sorbet/rbi/*/.rbi file in the project and builds:

@sigs[type][method]   → sig string
@types[type][method]  → return type string
@mixins[type]         → [mixin_type, ...] from extend/include calls

Type keys are fully qualified with “::” prefix normalised away. Lookups walk the mixin chain so Hesiod.register_gauge resolves even though the method is defined on Hesiod::Gauge (which Hesiod extends).

Defined Under Namespace

Classes: RbiVisitor

Instance Method Summary collapse

Constructor Details

#initialize(root_path) ⇒ RbiIndex

Returns a new instance of RbiIndex.



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/pink_spoon/rbi_index.rb', line 16

def initialize(root_path)
  @root_path = root_path
  @sigs      = Hash.new { |h, k| h[k] = {} }
  @types     = Hash.new { |h, k| h[k] = {} }
  @defs      = Hash.new { |h, k| h[k] = {} }
  @sources   = Hash.new { |h, k| h[k] = {} }
  @locations = Hash.new { |h, k| h[k] = {} }
  @mixins    = Hash.new { |h, k| h[k] = [] }
  @params    = Hash.new { |h, k| h[k] = {} }
  build
end

Instance Method Details

#hover_content_for(type, method_name, _seen = []) ⇒ Object

Returns markdown hover content for type#method, or nil if we know nothing about the method at all. Prefers the Sorbet sig; falls back to the plain def line so callers always get something useful.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/pink_spoon/rbi_index.rb', line 65

def hover_content_for(type, method_name, _seen = [])
  t = normalise(type)
  return nil if _seen.include?(t)

  sig      = @sigs[t][method_name.to_s]
  def_line = @defs[t][method_name.to_s]
  source   = @sources[t][method_name.to_s]

  if sig || def_line
    parts = []
    parts << source   if source
    parts << sig      if sig
    parts << def_line if def_line
    body = parts.join("\n")
    return "**`#{t}##{method_name}`** _(via RBI)_\n\n```ruby\n#{body}\n```"
  end

  @mixins[t].each do |mixin|
    result = hover_content_for(mixin, method_name, _seen + [t])
    return result if result
  end

  nil
end

#methods_for(type, _seen = []) ⇒ Object

Returns { method_name => sig_or_def_line } for a type including all mixins. Used by the completion listener to enumerate available methods.



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/pink_spoon/rbi_index.rb', line 131

def methods_for(type, _seen = [])
  t = normalise(type)
  return {} if _seen.include?(t)

  result = {}
  @mixins[t].each do |mixin|
    result.merge!(methods_for(mixin, _seen + [t]))
  end

  @defs[t].each do |method, def_line|
    result[method] = @sigs[t][method] || def_line
  end

  result
end

#mixins_for(type) ⇒ Object

Returns the direct parent/mixin types for the given type (one level, no chain walk).



108
109
110
# File 'lib/pink_spoon/rbi_index.rb', line 108

def mixins_for(type)
  @mixins[normalise(type)].dup
end

#params_for(type, method_name, _seen = []) ⇒ Object

Returns { param_name => type_string } for type#method, or nil. Follows the mixin chain.



114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/pink_spoon/rbi_index.rb', line 114

def params_for(type, method_name, _seen = [])
  t = normalise(type)
  return nil if _seen.include?(t)

  direct = @params[t][method_name.to_s]
  return direct if direct && !direct.empty?

  @mixins[t].each do |mixin|
    result = params_for(mixin, method_name, _seen + [t])
    return result if result && !result.empty?
  end

  nil
end

#rbi_location_for(type, method_name, _seen = []) ⇒ Object

Returns { file:, line: } for the .rbi definition of type#method, or nil. Follows extend/include/superclass chain when not found directly.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/pink_spoon/rbi_index.rb', line 92

def rbi_location_for(type, method_name, _seen = [])
  t = normalise(type)
  return nil if _seen.include?(t)

  loc = @locations[t][method_name.to_s]
  return loc if loc

  @mixins[t].each do |mixin|
    result = rbi_location_for(mixin, method_name, _seen + [t])
    return result if result
  end

  nil
end

#return_type_for(type, method_name, _seen = []) ⇒ Object

Returns the return-type string for type#method, or nil. Follows extend/include chain when not found directly.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/pink_spoon/rbi_index.rb', line 47

def return_type_for(type, method_name, _seen = [])
  t = normalise(type)
  return nil if _seen.include?(t)

  direct = @types[t][method_name.to_s]
  return direct if direct

  @mixins[t].each do |mixin|
    result = return_type_for(mixin, method_name, _seen + [t])
    return result if result
  end

  nil
end

#signature_for(type, method_name, _seen = []) ⇒ Object

Returns the sig string for type#method, or nil. Follows extend/include chain when not found directly.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/pink_spoon/rbi_index.rb', line 30

def signature_for(type, method_name, _seen = [])
  t = normalise(type)
  return nil if _seen.include?(t)

  direct = @sigs[t][method_name.to_s]
  return direct if direct

  @mixins[t].each do |mixin|
    result = signature_for(mixin, method_name, _seen + [t])
    return result if result
  end

  nil
end

#typesObject

All known types (for debugging / testing).



148
# File 'lib/pink_spoon/rbi_index.rb', line 148

def types = @sigs.keys