Class: Tapioca::Dsl::Compilers::UrlHelpers

Inherits:
Tapioca::Dsl::Compiler show all
Extended by:
T::Sig
Defined in:
lib/tapioca/dsl/compilers/url_helpers.rb

Overview

‘Tapioca::Dsl::Compilers::UrlHelpers` generates RBI files for classes that include or extend [`Rails.application.routes.url_helpers`](api.rubyonrails.org/v5.1.7/classes/ActionDispatch/Routing/UrlFor.html#module-ActionDispatch::Routing::UrlFor-label-URL+generation+for+named+routes).

For example, with the following setup:

~~~rb # config/application.rb class Application < Rails::Application

routes.draw do
  resource :index
end

end ~~~

~~~rb app/models/post.rb class Post

# Use `T.unsafe` so that Sorbet does not complain about a dynamic
# module being included. This allows the `include` to happen properly
# at runtime but Sorbet won't see the include. However, since this
# compiler will generate the proper RBI files for the include,
# static type checking will work as expected.
T.unsafe(self).include Rails.application.routes.url_helpers

end ~~~

this compiler will produce the following RBI files:

~~~rbi # generated_path_helpers_module.rbi # typed: true module GeneratedPathHelpersModule

include ActionDispatch::Routing::PolymorphicRoutes
include ActionDispatch::Routing::UrlFor

sig { params(args: T.untyped).returns(String) }
def edit_index_path(*args); end

sig { params(args: T.untyped).returns(String) }
def index_path(*args); end

sig { params(args: T.untyped).returns(String) }
def new_index_path(*args); end

end ~~~

~~~rbi # generated_url_helpers_module.rbi # typed: true module GeneratedUrlHelpersModule

include ActionDispatch::Routing::PolymorphicRoutes
include ActionDispatch::Routing::UrlFor

sig { params(args: T.untyped).returns(String) }
def edit_index_url(*args); end

sig { params(args: T.untyped).returns(String) }
def index_url(*args); end

sig { params(args: T.untyped).returns(String) }
def new_index_url(*args); end

end ~~~

~~~rbi # post.rbi # typed: true class Post

include GeneratedPathHelpersModule
include GeneratedUrlHelpersModule

end ~~~

Constant Summary collapse

ConstantType =
type_member { { fixed: Module } }
NON_DISCOVERABLE_INCLUDERS =
T.let(gather_non_discoverable_includers, T::Array[Module])

Constants included from Runtime::Reflection

Runtime::Reflection::ANCESTORS_METHOD, Runtime::Reflection::CLASS_METHOD, Runtime::Reflection::CONSTANTS_METHOD, Runtime::Reflection::EQUAL_METHOD, Runtime::Reflection::METHOD_METHOD, Runtime::Reflection::NAME_METHOD, Runtime::Reflection::OBJECT_ID_METHOD, Runtime::Reflection::PRIVATE_INSTANCE_METHODS_METHOD, Runtime::Reflection::PROTECTED_INSTANCE_METHODS_METHOD, Runtime::Reflection::PUBLIC_INSTANCE_METHODS_METHOD, Runtime::Reflection::REQUIRED_FROM_LABELS, Runtime::Reflection::SINGLETON_CLASS_METHOD, Runtime::Reflection::SUPERCLASS_METHOD, Runtime::Reflection::UNDEFINED_CONSTANT

Constants included from SorbetHelper

SorbetHelper::FEATURE_REQUIREMENTS, SorbetHelper::SORBET_BIN, SorbetHelper::SORBET_EXE_PATH_ENV_VAR, SorbetHelper::SORBET_GEM_SPEC, SorbetHelper::SORBET_PAYLOAD_URL, SorbetHelper::SPOOM_CONTEXT

Instance Attribute Summary

Attributes inherited from Tapioca::Dsl::Compiler

#constant, #options, #root

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Tapioca::Dsl::Compiler

#add_error, #compiler_enabled?, handles?, #initialize, processable_constants, requested_constants=

Methods included from T::Generic::TypeStoragePatch

#[], #has_attached_class!, #type_member, #type_template

Methods included from Runtime::Reflection

#abstract_type_of, #ancestors_of, #are_equal?, #class_of, #constant_defined?, #constantize, #constants_of, #descendants_of, #file_candidates_for, #final_module?, #inherited_ancestors_of, #method_of, #name_of, #name_of_type, #object_id_of, #private_instance_methods_of, #protected_instance_methods_of, #public_instance_methods_of, #qualified_name_of, #resolve_loc, #sealed_module?, #signature_of, #signature_of!, #singleton_class_of, #superclass_of

Methods included from Runtime::AttachedClassOf

#attached_class_of

Methods included from RBIHelper

#as_nilable_type, #as_non_nilable_type, #create_block_param, #create_kw_opt_param, #create_kw_param, #create_kw_rest_param, #create_opt_param, #create_param, #create_rest_param, #create_typed_param, #sanitize_signature_types, serialize_type_variable, #valid_method_name?, #valid_parameter_name?

Methods included from SorbetHelper

#sorbet, #sorbet_path, #sorbet_supports?

Constructor Details

This class inherits a constructor from Tapioca::Dsl::Compiler

Class Method Details

.gather_constantsObject



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/tapioca/dsl/compilers/url_helpers.rb', line 102

def gather_constants
  return [] unless defined?(Rails.application) && Rails.application

  # Load routes if they haven't been loaded yet (see https://github.com/rails/rails/pull/51614).
  routes_reloader = Rails.application.routes_reloader
  routes_reloader.execute_unless_loaded if routes_reloader&.respond_to?(:execute_unless_loaded)

  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)

    # 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).push(GeneratedUrlHelpersModule, GeneratedPathHelpersModule)
end

.gather_non_discoverable_includersObject



134
135
136
137
138
139
140
141
142
143
144
# File 'lib/tapioca/dsl/compilers/url_helpers.rb', line 134

def gather_non_discoverable_includers
  [].tap do |includers|
    if defined?(ActionController::TemplateAssertions) && defined?(ActionDispatch::IntegrationTest)
      includers << ActionDispatch::IntegrationTest
    end

    if defined?(ActionView::Helpers)
      includers << ActionView::Helpers
    end
  end.freeze
end

Instance Method Details

#decorateObject



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/tapioca/dsl/compilers/url_helpers.rb', line 87

def decorate
  case constant
  when GeneratedPathHelpersModule.singleton_class, GeneratedUrlHelpersModule.singleton_class
    generate_module_for(root, constant)
  else
    root.create_path(constant) do |mod|
      create_mixins_for(mod, GeneratedUrlHelpersModule)
      create_mixins_for(mod, GeneratedPathHelpersModule)
    end
  end
end