lib/tapioca/runtime/trackers/constant_definition.rb in tapioca-0.9.0 vs lib/tapioca/runtime/trackers/constant_definition.rb in tapioca-0.9.1
- old
+ new
@@ -15,39 +15,57 @@
class ConstantLocation < T::Struct
const :lineno, Integer
const :path, String
end
- @class_files = {}
+ @class_files = {}.compare_by_identity
# Immediately activated upon load. Observes class/module definition.
TracePoint.trace(:class) do |tp|
- unless tp.self.singleton_class?
- key = name_of(tp.self)
- file = tp.path
- lineno = tp.lineno
+ next if tp.self.singleton_class?
- if file == "(eval)"
- caller_location = T.must(caller_locations)
- .drop_while { |loc| loc.path == "(eval)" }
- .first
+ key = tp.self
- file = caller_location&.path
- lineno = caller_location&.lineno
- end
+ if tp.path == "(eval)"
+ caller_location = T.must(caller_locations)
+ .drop_while { |loc| loc.path == "(eval)" }
+ .first
- @class_files[key] ||= Set.new
- @class_files[key] << ConstantLocation.new(path: T.must(file), lineno: T.must(lineno))
+ next unless caller_location
+
+ loc = ConstantLocation.new(path: caller_location.absolute_path || "", lineno: caller_location.lineno)
+ else
+ loc = build_constant_location(tp, caller_locations)
end
+
+ (@class_files[key] ||= Set.new) << loc
end
+ TracePoint.trace(:c_return) do |tp|
+ next unless tp.method_id == :new
+ next unless Module === tp.return_value
+
+ key = tp.return_value
+ loc = build_constant_location(tp, caller_locations)
+ (@class_files[key] ||= Set.new) << loc
+ end
+
+ def self.build_constant_location(tp, locations)
+ file = resolve_loc(caller_locations)
+ lineno = file == File.realpath(tp.path) ? tp.lineno : 0
+
+ ConstantLocation.new(path: file, lineno: lineno)
+ end
+
# Returns the files in which this class or module was opened. Doesn't know
# about situations where the class was opened prior to +require+ing,
# or where metaprogramming was used via +eval+, etc.
def self.files_for(klass)
- name = String === klass ? klass : name_of(klass)
- files = @class_files.fetch(name, [])
- files.map(&:path).to_set
+ locations_for(klass).map(&:path).to_set
+ end
+
+ def self.locations_for(klass)
+ @class_files.fetch(klass, Set.new)
end
end
end
end
end