diff --git a/lib/tapioca/gem/pipeline.rb b/lib/tapioca/gem/pipeline.rb index ccf22fe5c..f7d3cf74a 100644 --- a/lib/tapioca/gem/pipeline.rb +++ b/lib/tapioca/gem/pipeline.rb @@ -31,8 +31,10 @@ def initialize( @events = [] #: Array[Gem::Event] @payload_symbols = Static::SymbolLoader.payload_symbols #: Set[String] - @bootstrap_symbols = load_bootstrap_symbols(@gem) #: Set[String] - gem_graph = Static::SymbolLoader.graph_from_paths(@gem.files) if include_doc + gem_graph = Static::SymbolLoader.graph_from_paths(@gem.files) #: Rubydex::Graph + gem_symbols = Static::SymbolLoader.symbols_from_graph(gem_graph) + engine_symbols = Static::SymbolLoader.engine_symbols(@gem) + @bootstrap_symbols = gem_symbols.union(engine_symbols) #: Set[String] @bootstrap_symbols.each { |symbol| push_symbol(symbol) } @@ -191,14 +193,6 @@ def name_of(constant) private - #: (Gemfile::GemSpec gem) -> Set[String] - def load_bootstrap_symbols(gem) - engine_symbols = Static::SymbolLoader.engine_symbols(gem) - gem_symbols = Static::SymbolLoader.gem_symbols(gem) - - gem_symbols.union(engine_symbols) - end - # Events handling #: -> Gem::Event diff --git a/lib/tapioca/static/symbol_loader.rb b/lib/tapioca/static/symbol_loader.rb index 7f0c08b09..a070f9a29 100644 --- a/lib/tapioca/static/symbol_loader.rb +++ b/lib/tapioca/static/symbol_loader.rb @@ -26,9 +26,26 @@ def graph_from_paths(paths) graph end - #: (Gemfile::GemSpec gem) -> Set[String] - def gem_symbols(gem) - symbols_from_paths(gem.files) + #: (Rubydex::Graph graph) -> Set[String] + def symbols_from_graph(graph) + graph.declarations.filter_map do |decl| + next unless decl.is_a?(Rubydex::Namespace) || + decl.is_a?(Rubydex::Constant) || + decl.is_a?(Rubydex::ConstantAlias) || + decl.is_a?(Rubydex::Todo) + + # Declarations added by `graph.resolve` only have `rubydex:built-in` definitions. + # We exclude those unless the namespace has method or constant members defined in + # source files, which indicates a class reopening (e.g. `class Object; def Nokogiri(); end`). + if decl.definitions.any? && decl.definitions.all? { |defn| defn.location.uri == "rubydex:built-in" } + next unless decl.is_a?(Rubydex::Namespace) && decl.members.any? do |m| + (m.is_a?(Rubydex::Method) || m.is_a?(Rubydex::Constant) || m.is_a?(Rubydex::ConstantAlias)) && + m.definitions.any? + end + end + + decl.name + end.to_set end #: (Gemfile::GemSpec gem) -> Set[String] @@ -51,7 +68,8 @@ def engine_symbols(gem) Pathname.glob("#{load_path}/**/*.rb") end - symbols_from_paths(paths) + engine_graph = graph_from_paths(paths) + symbols_from_graph(engine_graph) rescue Set.new end