Skip to content

Commit

Permalink
Merge pull request #1935 from Shopify/Alex/optimize-URLHelpers-gather…
Browse files Browse the repository at this point in the history
…_constants

Optimize `URLHelpers.gather_constants`
  • Loading branch information
amomchilov authored Jul 15, 2024
2 parents b3cec5b + ef5e6c9 commit f6028d6
Showing 1 changed file with 25 additions and 13 deletions.
38 changes: 25 additions & 13 deletions lib/tapioca/dsl/compilers/url_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,28 @@ def gather_constants
routes_reloader = Rails.application.routes_reloader
routes_reloader.execute_unless_loaded if routes_reloader&.respond_to?(:execute_unless_loaded)

Object.const_set(:GeneratedUrlHelpersModule, Rails.application.routes.named_routes.url_helpers_module)
Object.const_set(:GeneratedPathHelpersModule, Rails.application.routes.named_routes.path_helpers_module)
url_helpers_module = Rails.application.routes.named_routes.url_helpers_module
path_helpers_module = Rails.application.routes.named_routes.path_helpers_module

Object.const_set(:GeneratedUrlHelpersModule, url_helpers_module)
Object.const_set(:GeneratedPathHelpersModule, path_helpers_module)

constants = all_modules.select do |mod|
next unless name_of(mod)

includes_helper?(mod, GeneratedUrlHelpersModule) ||
includes_helper?(mod, GeneratedPathHelpersModule) ||
includes_helper?(mod.singleton_class, GeneratedUrlHelpersModule) ||
includes_helper?(mod.singleton_class, GeneratedPathHelpersModule)
# Fast-path to quickly disqualify most cases
next false unless url_helpers_module > mod || # rubocop:disable Style/InvertibleUnlessCondition
path_helpers_module > mod ||
url_helpers_module > mod.singleton_class ||
path_helpers_module > mod.singleton_class

includes_helper?(mod, url_helpers_module) ||
includes_helper?(mod, path_helpers_module) ||
includes_helper?(mod.singleton_class, url_helpers_module) ||
includes_helper?(mod.singleton_class, path_helpers_module)
end

constants.concat(NON_DISCOVERABLE_INCLUDERS)
constants.concat(NON_DISCOVERABLE_INCLUDERS).push(GeneratedUrlHelpersModule, GeneratedPathHelpersModule)
end

sig { returns(T::Array[Module]) }
Expand All @@ -134,17 +143,20 @@ def gather_non_discoverable_includers
end.freeze
end

# Returns `true` if `mod` "directly" includes `helper`.
# For classes, this method will return false if the `helper` is included only by a superclass
sig { params(mod: Module, helper: Module).returns(T::Boolean) }
private def includes_helper?(mod, helper)
superclass_ancestors = []
ancestors = ancestors_of(mod)

if Class === mod
superclass = superclass_of(mod)
superclass_ancestors = ancestors_of(superclass) if superclass
own_ancestors = if Class === mod && (superclass = superclass_of(mod))
# These ancestors are unique to `mod`, and exclude those in common with `superclass`.
ancestors.take(ancestors.count - ancestors_of(superclass).size)
else
ancestors
end

ancestors = Set.new.compare_by_identity.merge(ancestors_of(mod)).subtract(superclass_ancestors)
ancestors.any? { |ancestor| helper == ancestor }
own_ancestors.include?(helper)
end
end

Expand Down

0 comments on commit f6028d6

Please sign in to comment.