Class: Tapioca::Dsl::Compilers::Config

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

Overview

‘Tapioca::Dsl::Compilers::Config` generates RBI files for classes generated by the [`config`](github.com/rubyconfig/config) gem.

The gem creates a ‘Config::Options` instance based on the settings files and/or env variables. It then assigns this instance to a constant with a configurable name, by default `Settings`. Application code uses methods on this constant to read off config values.

For a setting file like the following: “‘yaml


github:

token: 12345
client_id: 54321
client_secret: super_secret

“‘ and a `Config` setup like: “`ruby Config.setup do |config|

config.const_name = "AppSettings"

end “‘ this compiler will produce the following RBI file: “`rbi AppSettings = T.let(T.unsafe(nil), AppSettingsConfigOptions)

class AppSettingsConfigOptions < ::Config::Options

sig { returns(T.untyped) }
def github; end

sig { params(value: T.untyped).returns(T.untyped) }
def github=(value); end

end “‘

Constant Summary collapse

CONFIG_OPTIONS_SUFFIX =
"ConfigOptions"
ConstantType =
type_member { { fixed: 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

Constants included from SorbetHelper

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

Instance Attribute Summary

Attributes inherited from Tapioca::Dsl::Compiler

#constant, #root

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Tapioca::Dsl::Compiler

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

Methods included from T::Generic::TypeStoragePatch

#[], #type_member, #type_template

Methods included from Runtime::Reflection

#ancestors_of, #are_equal?, #class_of, #constant_from_singleton_class, #constant_name_from_singleton_class, #constantize, #constants_of, #descendants_of, #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, #signature_of, #singleton_class_of, #superclass_of

Methods included from RBIHelper

#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



100
101
102
103
104
105
106
107
108
109
# File 'lib/tapioca/dsl/compilers/config.rb', line 100

def self.gather_constants
  name = ::Config.const_name
  return [] unless Object.const_defined?(name)

  config_object = Object.const_get(name)
  options_class_name = "#{name}#{CONFIG_OPTIONS_SUFFIX}"
  Object.const_set(options_class_name, config_object.singleton_class)

  Array(config_object.singleton_class)
end

Instance Method Details

#decorateObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/tapioca/dsl/compilers/config.rb', line 55

def decorate
  # The constant we are given is the specialized config options type
  option_class_name = constant.name
  return unless option_class_name

  # Grab the config constant name and the actual config constant
  config_constant_name = option_class_name
    .gsub(/#{CONFIG_OPTIONS_SUFFIX}$/, "")
  config_constant = Object.const_get(config_constant_name)

  # Look up method names from the keys of the config constant
  method_names = config_constant.keys

  return if method_names.empty?

  root.create_constant(config_constant_name, value: "T.let(T.unsafe(nil), #{option_class_name})")

  root.create_class(option_class_name, superclass_name: "::Config::Options") do |mod|
    # We need this to be generic only becuase `Config::Options` is an
    # enumerable and, thus, needs to redeclare the `Elem` type member.
    #
    # We declare it as a fixed member of `T.untyped` so that if anyone
    # enumerates the entries, we don't make any assumptions about their
    # types.
    mod.create_extend("T::Generic")
    mod.create_type_variable("Elem", type: "type_member", fixed: "T.untyped")

    method_names.each do |method_name|
      # Create getter method
      mod.create_method(
        method_name.to_s,
        return_type: "T.untyped"
      )

      # Create setter method
      mod.create_method(
        "#{method_name}=",
        parameters: [create_param("value", type: "T.untyped")],
        return_type: "T.untyped"
      )
    end
  end
end