Skip to content

Commit f5dac8b

Browse files
committed
Use inheritence to better signal what the return value of method_definition_in_gem will be
1 parent 773ef04 commit f5dac8b

File tree

3 files changed

+41
-10
lines changed

3 files changed

+41
-10
lines changed

lib/tapioca/gem/listeners/methods.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ def compile_method(tree, symbol_name, constant, method, visibility = RBI::Public
7777
method = T.let(signature.method, UnboundMethod) if signature
7878

7979
case @pipeline.method_definition_in_gem(method.name, constant)
80-
when nil
80+
when Pipeline::MethodUnknown
8181
# This means that this is a C-method. Thus, we want to
8282
# skip it only if the constant is an ignored one, since
8383
# that probably means that we've hit a C-method for a
8484
# core type.
8585
return if @pipeline.symbol_in_payload?(symbol_name)
86-
when false
86+
when Pipeline::MethodNotInGem
8787
# Do not process this method, if it is not defined by the current gem
8888
return
8989
end

lib/tapioca/gem/listeners/source_location.rb

+1-3
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ def on_scope(event)
3535
def on_method(event)
3636
definition = @pipeline.method_definition_in_gem(event.method.name, event.constant)
3737

38-
case definition
39-
when NilClass, FalseClass, TrueClass
40-
else
38+
if Pipeline::MethodInGemWithLocation === definition
4139
loc = definition.location
4240
add_source_location_comment(event.node, loc.file, loc.line)
4341
end

lib/tapioca/gem/pipeline.rb

+38-5
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,45 @@ def constant_in_gem?(name)
136136
gem.contains_path?(loc.file)
137137
end
138138

139-
sig { params(method_name: Symbol, owner: Module).returns(T.any([String, Integer], NilClass, T::Boolean)) }
139+
class MethodDefinitionLookupResult
140+
extend T::Helpers
141+
abstract!
142+
end
143+
144+
# The method doesn't seem to exist
145+
class MethodUnknown < MethodDefinitionLookupResult; end
146+
147+
# The method is not defined in the gem
148+
class MethodNotInGem < MethodDefinitionLookupResult; end
149+
150+
# The method probably defined in the gem but doesn't have a source location
151+
class MethodInGemWithoutLocation < MethodDefinitionLookupResult; end
152+
153+
# The method defined in gem and has a source location
154+
class MethodInGemWithLocation < MethodDefinitionLookupResult
155+
extend T::Sig
156+
157+
sig { returns(Runtime::SourceLocation) }
158+
attr_reader :location
159+
160+
sig { params(location: Runtime::SourceLocation).void }
161+
def initialize(location)
162+
@location = location
163+
super()
164+
end
165+
end
166+
167+
sig do
168+
params(
169+
method_name: Symbol,
170+
owner: Module,
171+
).returns(MethodDefinitionLookupResult)
172+
end
140173
def method_definition_in_gem(method_name, owner)
141174
definitions = Tapioca::Runtime::Trackers::MethodDefinition.method_definitions_for(method_name, owner)
142175

143176
# If the source location of the method isn't available, signal that by returning nil.
144-
return if definitions.empty?
177+
return MethodUnknown.new if definitions.empty?
145178

146179
# Look up the first entry that matches a file in the gem.
147180
found = definitions.find { |loc| @gem.contains_path?(loc.file) }
@@ -151,13 +184,13 @@ def method_definition_in_gem(method_name, owner)
151184
found = definitions.find { |loc| loc.file == "(eval)" }
152185
# However, we can just return true to signal that the method should be included.
153186
# We can't provide a source location for it, but we want it to be included in the gem RBI.
154-
return true if found
187+
return MethodInGemWithoutLocation.new if found
155188
end
156189

157190
# If we searched but couldn't find a source location in the gem, return false to signal that.
158-
return false unless found
191+
return MethodNotInGem.new unless found
159192

160-
found
193+
MethodInGemWithLocation.new(found)
161194
end
162195

163196
# Helpers

0 commit comments

Comments
 (0)