tapioca 0.6.4 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +8 -2
  3. data/README.md +27 -15
  4. data/Rakefile +10 -14
  5. data/lib/tapioca/cli.rb +65 -80
  6. data/lib/tapioca/{generators/base.rb → commands/command.rb} +16 -9
  7. data/lib/tapioca/{generators → commands}/dsl.rb +59 -45
  8. data/lib/tapioca/{generators → commands}/gem.rb +93 -30
  9. data/lib/tapioca/{generators → commands}/init.rb +9 -13
  10. data/lib/tapioca/{generators → commands}/require.rb +8 -10
  11. data/lib/tapioca/commands/todo.rb +84 -0
  12. data/lib/tapioca/commands.rb +13 -0
  13. data/lib/tapioca/dsl/compiler.rb +185 -0
  14. data/lib/tapioca/{compilers/dsl → dsl/compilers}/aasm.rb +12 -9
  15. data/lib/tapioca/{compilers/dsl → dsl/compilers}/action_controller_helpers.rb +13 -20
  16. data/lib/tapioca/{compilers/dsl → dsl/compilers}/action_mailer.rb +10 -8
  17. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_job.rb +11 -9
  18. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_model_attributes.rb +13 -11
  19. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_model_secure_password.rb +10 -12
  20. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_associations.rb +28 -34
  21. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_columns.rb +18 -16
  22. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_enum.rb +14 -12
  23. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_fixtures.rb +10 -8
  24. data/lib/tapioca/dsl/compilers/active_record_relations.rb +712 -0
  25. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_scope.rb +21 -20
  26. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_typed_store.rb +11 -16
  27. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_resource.rb +10 -8
  28. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_storage.rb +11 -11
  29. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_support_concern.rb +19 -14
  30. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_support_current_attributes.rb +16 -21
  31. data/lib/tapioca/{compilers/dsl → dsl/compilers}/config.rb +10 -8
  32. data/lib/tapioca/{compilers/dsl → dsl/compilers}/frozen_record.rb +13 -11
  33. data/lib/tapioca/{compilers/dsl → dsl/compilers}/identity_cache.rb +23 -22
  34. data/lib/tapioca/{compilers/dsl → dsl/compilers}/mixed_in_class_attributes.rb +12 -10
  35. data/lib/tapioca/{compilers/dsl → dsl/compilers}/protobuf.rb +10 -8
  36. data/lib/tapioca/{compilers/dsl → dsl/compilers}/rails_generators.rb +12 -13
  37. data/lib/tapioca/{compilers/dsl → dsl/compilers}/sidekiq_worker.rb +14 -13
  38. data/lib/tapioca/{compilers/dsl → dsl/compilers}/smart_properties.rb +11 -9
  39. data/lib/tapioca/{compilers/dsl → dsl/compilers}/state_machines.rb +12 -10
  40. data/lib/tapioca/{compilers/dsl → dsl/compilers}/url_helpers.rb +16 -14
  41. data/lib/tapioca/dsl/compilers.rb +31 -0
  42. data/lib/tapioca/{compilers/dsl → dsl}/extensions/frozen_record.rb +2 -2
  43. data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +114 -0
  44. data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +29 -0
  45. data/lib/tapioca/{compilers/dsl → dsl/helpers}/param_helper.rb +2 -2
  46. data/lib/tapioca/{compilers/dsl_compiler.rb → dsl/pipeline.rb} +41 -33
  47. data/lib/tapioca/gem/events.rb +120 -0
  48. data/lib/tapioca/gem/listeners/base.rb +48 -0
  49. data/lib/tapioca/gem/listeners/dynamic_mixins.rb +32 -0
  50. data/lib/tapioca/gem/listeners/methods.rb +183 -0
  51. data/lib/tapioca/gem/listeners/mixins.rb +101 -0
  52. data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +21 -0
  53. data/lib/tapioca/gem/listeners/sorbet_enums.rb +26 -0
  54. data/lib/tapioca/gem/listeners/sorbet_helpers.rb +29 -0
  55. data/lib/tapioca/gem/listeners/sorbet_props.rb +33 -0
  56. data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +23 -0
  57. data/lib/tapioca/gem/listeners/sorbet_signatures.rb +79 -0
  58. data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +51 -0
  59. data/lib/tapioca/gem/listeners/subconstants.rb +37 -0
  60. data/lib/tapioca/gem/listeners/yard_doc.rb +96 -0
  61. data/lib/tapioca/gem/listeners.rb +16 -0
  62. data/lib/tapioca/gem/pipeline.rb +365 -0
  63. data/lib/tapioca/helpers/cli_helper.rb +7 -0
  64. data/lib/tapioca/helpers/config_helper.rb +5 -8
  65. data/lib/tapioca/helpers/rbi_helper.rb +17 -0
  66. data/lib/tapioca/helpers/shims_helper.rb +87 -0
  67. data/lib/tapioca/helpers/sorbet_helper.rb +57 -0
  68. data/lib/tapioca/helpers/test/dsl_compiler.rb +118 -0
  69. data/lib/tapioca/helpers/test/isolation.rb +1 -1
  70. data/lib/tapioca/helpers/test/template.rb +13 -2
  71. data/lib/tapioca/internal.rb +17 -10
  72. data/lib/tapioca/rbi_ext/model.rb +2 -48
  73. data/lib/tapioca/rbi_formatter.rb +37 -0
  74. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +227 -0
  75. data/lib/tapioca/runtime/generic_type_registry.rb +166 -0
  76. data/lib/tapioca/runtime/loader.rb +123 -0
  77. data/lib/tapioca/runtime/reflection.rb +153 -0
  78. data/lib/tapioca/runtime/trackers/autoload.rb +72 -0
  79. data/lib/tapioca/runtime/trackers/constant_definition.rb +44 -0
  80. data/lib/tapioca/runtime/trackers/mixin.rb +80 -0
  81. data/lib/tapioca/runtime/trackers/required_ancestor.rb +50 -0
  82. data/lib/tapioca/{trackers.rb → runtime/trackers.rb} +4 -3
  83. data/lib/tapioca/sorbet_ext/generic_name_patch.rb +33 -15
  84. data/lib/tapioca/sorbet_ext/name_patch.rb +7 -1
  85. data/lib/tapioca/{compilers → static}/requires_compiler.rb +2 -2
  86. data/lib/tapioca/static/symbol_loader.rb +83 -0
  87. data/lib/tapioca/static/symbol_table_parser.rb +63 -0
  88. data/lib/tapioca/version.rb +1 -1
  89. data/lib/tapioca.rb +2 -7
  90. metadata +80 -60
  91. data/lib/tapioca/compilers/dsl/active_record_relations.rb +0 -720
  92. data/lib/tapioca/compilers/dsl/base.rb +0 -195
  93. data/lib/tapioca/compilers/dsl/helper/active_record_constants.rb +0 -27
  94. data/lib/tapioca/compilers/dynamic_mixin_compiler.rb +0 -223
  95. data/lib/tapioca/compilers/sorbet.rb +0 -59
  96. data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +0 -780
  97. data/lib/tapioca/compilers/symbol_table/symbol_loader.rb +0 -90
  98. data/lib/tapioca/compilers/symbol_table_compiler.rb +0 -17
  99. data/lib/tapioca/compilers/todos_compiler.rb +0 -32
  100. data/lib/tapioca/generators/todo.rb +0 -76
  101. data/lib/tapioca/generators.rb +0 -9
  102. data/lib/tapioca/generic_type_registry.rb +0 -164
  103. data/lib/tapioca/helpers/active_record_column_type_helper.rb +0 -108
  104. data/lib/tapioca/loader.rb +0 -119
  105. data/lib/tapioca/reflection.rb +0 -151
  106. data/lib/tapioca/trackers/autoload.rb +0 -70
  107. data/lib/tapioca/trackers/constant_definition.rb +0 -42
  108. data/lib/tapioca/trackers/mixin.rb +0 -78
@@ -1,195 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "tapioca/rbi_ext/model"
5
- require "tapioca/compilers/dsl/param_helper"
6
- require "tapioca/compilers/dsl_compiler"
7
-
8
- module Tapioca
9
- module Compilers
10
- module Dsl
11
- DSL_COMPILERS_DIR = T.let(File.expand_path("..", __FILE__).to_s, String)
12
-
13
- class Base
14
- extend T::Sig
15
- extend T::Helpers
16
-
17
- include Reflection
18
-
19
- abstract!
20
-
21
- sig { returns(T::Set[Module]) }
22
- attr_reader :processable_constants
23
-
24
- sig { returns(T::Array[String]) }
25
- attr_reader :errors
26
-
27
- sig { params(name: String).returns(T.nilable(T.class_of(Tapioca::Compilers::Dsl::Base))) }
28
- def self.resolve(name)
29
- # Try to find built-in tapioca generator first, then globally defined generator.
30
- potentials = ["Tapioca::Compilers::Dsl::#{name}", name].map do |potential_name|
31
- Object.const_get(potential_name)
32
- rescue NameError
33
- # Skip if we can't find generator by the potential name
34
- nil
35
- end
36
-
37
- potentials.compact.first
38
- end
39
-
40
- sig { params(compiler: Tapioca::Compilers::DslCompiler).void }
41
- def initialize(compiler)
42
- @compiler = compiler
43
- @processable_constants = T.let(Set.new(gather_constants), T::Set[Module])
44
- @processable_constants.compare_by_identity
45
- @errors = T.let([], T::Array[String])
46
- end
47
-
48
- sig { params(constant: Module).returns(T::Boolean) }
49
- def handles?(constant)
50
- processable_constants.include?(constant)
51
- end
52
-
53
- sig { params(generator_name: String).returns(T::Boolean) }
54
- def generator_enabled?(generator_name)
55
- @compiler.generator_enabled?(generator_name)
56
- end
57
-
58
- sig do
59
- abstract
60
- .type_parameters(:T)
61
- .params(
62
- tree: RBI::Tree,
63
- constant: T.type_parameter(:T)
64
- )
65
- .void
66
- end
67
- def decorate(tree, constant); end
68
-
69
- sig { abstract.returns(T::Enumerable[Module]) }
70
- def gather_constants; end
71
-
72
- # NOTE: This should eventually accept an `Error` object or `Exception` rather than simply a `String`.
73
- sig { params(error: String).void }
74
- def add_error(error)
75
- @errors << error
76
- end
77
-
78
- private
79
-
80
- sig { returns(T::Enumerable[Class]) }
81
- def all_classes
82
- @all_classes = T.let(@all_classes, T.nilable(T::Enumerable[Class]))
83
- @all_classes ||= T.cast(ObjectSpace.each_object(Class), T::Enumerable[Class]).each
84
- end
85
-
86
- sig { returns(T::Enumerable[Module]) }
87
- def all_modules
88
- @all_modules = T.let(@all_modules, T.nilable(T::Enumerable[Module]))
89
- @all_modules ||= T.cast(ObjectSpace.each_object(Module), T::Enumerable[Module]).each
90
- end
91
-
92
- # Get the types of each parameter from a method signature
93
- sig do
94
- params(
95
- method_def: T.any(Method, UnboundMethod),
96
- signature: T.untyped # as `T::Private::Methods::Signature` is private
97
- ).returns(T::Array[String])
98
- end
99
- def parameters_types_from_signature(method_def, signature)
100
- params = T.let([], T::Array[String])
101
-
102
- return method_def.parameters.map { "T.untyped" } unless signature
103
-
104
- # parameters types
105
- signature.arg_types.each { |arg_type| params << arg_type[1].to_s }
106
-
107
- # keyword parameters types
108
- signature.kwarg_types.each { |_, kwarg_type| params << kwarg_type.to_s }
109
-
110
- # rest parameter type
111
- params << signature.rest_type.to_s if signature.has_rest
112
-
113
- # special case `.void` in a proc
114
- unless signature.block_name.nil?
115
- params << signature.block_type.to_s.gsub("returns(<VOID>)", "void")
116
- end
117
-
118
- params
119
- end
120
-
121
- sig { params(scope: RBI::Scope, method_def: T.any(Method, UnboundMethod), class_method: T::Boolean).void }
122
- def create_method_from_def(scope, method_def, class_method: false)
123
- scope.create_method(
124
- method_def.name.to_s,
125
- parameters: compile_method_parameters_to_rbi(method_def),
126
- return_type: compile_method_return_type_to_rbi(method_def),
127
- class_method: class_method
128
- )
129
- end
130
-
131
- include ParamHelper
132
-
133
- sig { params(method_def: T.any(Method, UnboundMethod)).returns(T::Array[RBI::TypedParam]) }
134
- def compile_method_parameters_to_rbi(method_def)
135
- signature = T::Private::Methods.signature_for_method(method_def)
136
- method_def = signature.nil? ? method_def : signature.method
137
- method_types = parameters_types_from_signature(method_def, signature)
138
-
139
- parameters = T.let(method_def.parameters, T::Array[[Symbol, T.nilable(Symbol)]])
140
-
141
- parameters.each_with_index.map do |(type, name), index|
142
- fallback_arg_name = "_arg#{index}"
143
-
144
- name = name ? name.to_s : fallback_arg_name
145
- name = fallback_arg_name unless valid_parameter_name?(name)
146
- method_type = T.must(method_types[index])
147
-
148
- case type
149
- when :req
150
- create_param(name, type: method_type)
151
- when :opt
152
- create_opt_param(name, type: method_type, default: "T.unsafe(nil)")
153
- when :rest
154
- create_rest_param(name, type: method_type)
155
- when :keyreq
156
- create_kw_param(name, type: method_type)
157
- when :key
158
- create_kw_opt_param(name, type: method_type, default: "T.unsafe(nil)")
159
- when :keyrest
160
- create_kw_rest_param(name, type: method_type)
161
- when :block
162
- create_block_param(name, type: method_type)
163
- else
164
- raise "Unknown type `#{type}`."
165
- end
166
- end
167
- end
168
-
169
- sig { params(method_def: T.any(Method, UnboundMethod)).returns(String) }
170
- def compile_method_return_type_to_rbi(method_def)
171
- signature = T::Private::Methods.signature_for_method(method_def)
172
- return_type = signature.nil? ? "T.untyped" : name_of_type(signature.return_type)
173
- return_type = "void" if return_type == "<VOID>"
174
- # Map <NOT-TYPED> to `T.untyped`
175
- return_type = "T.untyped" if return_type == "<NOT-TYPED>"
176
- return_type
177
- end
178
-
179
- sig { params(type: String).returns(String) }
180
- def as_nilable_type(type)
181
- if type.start_with?("T.nilable(", "::T.nilable(") || type == "T.untyped" || type == "::T.untyped"
182
- type
183
- else
184
- "T.nilable(#{type})"
185
- end
186
- end
187
-
188
- sig { params(name: String).returns(T::Boolean) }
189
- def valid_parameter_name?(name)
190
- name.match?(/^[[[:alnum:]]_]+$/)
191
- end
192
- end
193
- end
194
- end
195
- end
@@ -1,27 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module Tapioca
5
- module Compilers
6
- module Dsl
7
- module Helper
8
- module ActiveRecordConstants
9
- extend T::Sig
10
-
11
- AttributeMethodsModuleName = T.let("GeneratedAttributeMethods", String)
12
- AssociationMethodsModuleName = T.let("GeneratedAssociationMethods", String)
13
-
14
- RelationMethodsModuleName = T.let("GeneratedRelationMethods", String)
15
- AssociationRelationMethodsModuleName = T.let("GeneratedAssociationRelationMethods", String)
16
- CommonRelationMethodsModuleName = T.let("CommonRelationMethods", String)
17
-
18
- RelationClassName = T.let("PrivateRelation", String)
19
- RelationWhereChainClassName = T.let("PrivateRelationWhereChain", String)
20
- AssociationRelationClassName = T.let("PrivateAssociationRelation", String)
21
- AssociationRelationWhereChainClassName = T.let("PrivateAssociationRelationWhereChain", String)
22
- AssociationsCollectionProxyClassName = T.let("PrivateCollectionProxy", String)
23
- end
24
- end
25
- end
26
- end
27
- end
@@ -1,223 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- class DynamicMixinCompiler
5
- extend T::Sig
6
- include Tapioca::Reflection
7
-
8
- sig { returns(T::Array[Module]) }
9
- attr_reader :dynamic_extends, :dynamic_includes
10
-
11
- sig { returns(T::Array[Symbol]) }
12
- attr_reader :class_attribute_readers, :class_attribute_writers, :class_attribute_predicates
13
-
14
- sig { returns(T::Array[Symbol]) }
15
- attr_reader :instance_attribute_readers, :instance_attribute_writers, :instance_attribute_predicates
16
-
17
- sig { params(constant: Module).void }
18
- def initialize(constant)
19
- @constant = constant
20
- mixins_from_modules = {}.compare_by_identity
21
- class_attribute_readers = T.let([], T::Array[Symbol])
22
- class_attribute_writers = T.let([], T::Array[Symbol])
23
- class_attribute_predicates = T.let([], T::Array[Symbol])
24
-
25
- instance_attribute_readers = T.let([], T::Array[Symbol])
26
- instance_attribute_writers = T.let([], T::Array[Symbol])
27
- instance_attribute_predicates = T.let([], T::Array[Symbol])
28
-
29
- Class.new do
30
- # Override the `self.include` method
31
- define_singleton_method(:include) do |mod|
32
- # Take a snapshot of the list of singleton class ancestors
33
- # before the actual include
34
- before = singleton_class.ancestors
35
- # Call the actual `include` method with the supplied module
36
- super(mod).tap do
37
- # Take a snapshot of the list of singleton class ancestors
38
- # after the actual include
39
- after = singleton_class.ancestors
40
- # The difference is the modules that are added to the list
41
- # of ancestors of the singleton class. Those are all the
42
- # modules that were `extend`ed due to the `include` call.
43
- #
44
- # We record those modules on our lookup table keyed by
45
- # the included module with the values being all the modules
46
- # that that module pulls into the singleton class.
47
- #
48
- # We need to reverse the order, since the extend order should
49
- # be the inverse of the ancestor order. That is, earlier
50
- # extended modules would be later in the ancestor chain.
51
- mixins_from_modules[mod] = (after - before).reverse!
52
- end
53
- rescue Exception # rubocop:disable Lint/RescueException
54
- # this is a best effort, bail if we can't perform this
55
- end
56
-
57
- define_singleton_method(:class_attribute) do |*attrs, **kwargs|
58
- class_attribute_readers.concat(attrs)
59
- class_attribute_writers.concat(attrs)
60
-
61
- instance_predicate = kwargs.fetch(:instance_predicate, true)
62
- instance_accessor = kwargs.fetch(:instance_accessor, true)
63
- instance_reader = kwargs.fetch(:instance_reader, instance_accessor)
64
- instance_writer = kwargs.fetch(:instance_writer, instance_accessor)
65
-
66
- if instance_reader
67
- instance_attribute_readers.concat(attrs)
68
- end
69
-
70
- if instance_writer
71
- instance_attribute_writers.concat(attrs)
72
- end
73
-
74
- if instance_predicate
75
- class_attribute_predicates.concat(attrs)
76
-
77
- if instance_reader
78
- instance_attribute_predicates.concat(attrs)
79
- end
80
- end
81
-
82
- super(*attrs, **kwargs) if defined?(super)
83
- end
84
-
85
- # rubocop:disable Style/MissingRespondToMissing
86
- T::Sig::WithoutRuntime.sig { params(symbol: Symbol, args: T.untyped).returns(T.untyped) }
87
- def method_missing(symbol, *args)
88
- # We need this here so that we can handle any random instance
89
- # method calls on the fake including class that may be done by
90
- # the included module during the `self.included` hook.
91
- end
92
-
93
- class << self
94
- extend T::Sig
95
-
96
- T::Sig::WithoutRuntime.sig { params(symbol: Symbol, args: T.untyped).returns(T.untyped) }
97
- def method_missing(symbol, *args)
98
- # Similarly, we need this here so that we can handle any
99
- # random class method calls on the fake including class
100
- # that may be done by the included module during the
101
- # `self.included` hook.
102
- end
103
- end
104
- # rubocop:enable Style/MissingRespondToMissing
105
- end.include(constant)
106
-
107
- # The value that corresponds to the original included constant
108
- # is the list of all dynamically extended modules because of that
109
- # constant. We grab that value by deleting the key for the original
110
- # constant.
111
- @dynamic_extends = T.let(mixins_from_modules.delete(constant) || [], T::Array[Module])
112
-
113
- # Since we deleted the original constant from the list of keys, all
114
- # the keys that remain are the ones that are dynamically included modules
115
- # during the include of the original constant.
116
- @dynamic_includes = T.let(mixins_from_modules.keys, T::Array[Module])
117
-
118
- @class_attribute_readers = T.let(class_attribute_readers, T::Array[Symbol])
119
- @class_attribute_writers = T.let(class_attribute_writers, T::Array[Symbol])
120
- @class_attribute_predicates = T.let(class_attribute_predicates, T::Array[Symbol])
121
-
122
- @instance_attribute_readers = T.let(instance_attribute_readers, T::Array[Symbol])
123
- @instance_attribute_writers = T.let(instance_attribute_writers, T::Array[Symbol])
124
- @instance_attribute_predicates = T.let(instance_attribute_predicates, T::Array[Symbol])
125
- end
126
-
127
- sig { returns(T::Boolean) }
128
- def empty_attributes?
129
- @class_attribute_readers.empty? && @class_attribute_writers.empty?
130
- end
131
-
132
- sig { params(tree: RBI::Tree).void }
133
- def compile_class_attributes(tree)
134
- return if empty_attributes?
135
-
136
- # Create a synthetic module to hold the generated class methods
137
- tree << RBI::Module.new("GeneratedClassMethods") do |mod|
138
- class_attribute_readers.each do |attribute|
139
- mod << RBI::Method.new(attribute.to_s)
140
- end
141
-
142
- class_attribute_writers.each do |attribute|
143
- mod << RBI::Method.new("#{attribute}=") do |method|
144
- method << RBI::Param.new("value")
145
- end
146
- end
147
-
148
- class_attribute_predicates.each do |attribute|
149
- mod << RBI::Method.new("#{attribute}?")
150
- end
151
- end
152
-
153
- # Create a synthetic module to hold the generated instance methods
154
- tree << RBI::Module.new("GeneratedInstanceMethods") do |mod|
155
- instance_attribute_readers.each do |attribute|
156
- mod << RBI::Method.new(attribute.to_s)
157
- end
158
-
159
- instance_attribute_writers.each do |attribute|
160
- mod << RBI::Method.new("#{attribute}=") do |method|
161
- method << RBI::Param.new("value")
162
- end
163
- end
164
-
165
- instance_attribute_predicates.each do |attribute|
166
- mod << RBI::Method.new("#{attribute}?")
167
- end
168
- end
169
-
170
- # Add a mixes_in_class_methods and include for the generated modules
171
- tree << RBI::MixesInClassMethods.new("GeneratedClassMethods")
172
- tree << RBI::Include.new("GeneratedInstanceMethods")
173
- end
174
-
175
- sig { params(tree: RBI::Tree).returns([T::Array[Module], T::Array[Module]]) }
176
- def compile_mixes_in_class_methods(tree)
177
- includes = dynamic_includes.map do |mod|
178
- qname = qualified_name_of(mod)
179
-
180
- next if qname.nil? || qname.empty?
181
- next if filtered_mixin?(qname)
182
-
183
- tree << RBI::Include.new(qname)
184
-
185
- mod
186
- end.compact
187
-
188
- # If we can generate multiple mixes_in_class_methods, then we want to use all dynamic extends that are not the
189
- # constant itself
190
- mixed_in_class_methods = dynamic_extends.select do |mod|
191
- mod != @constant && !module_included_by_another_dynamic_extend?(mod, dynamic_extends)
192
- end
193
-
194
- return [[], []] if mixed_in_class_methods.empty?
195
-
196
- mixed_in_class_methods.each do |mod|
197
- qualified_name = qualified_name_of(mod)
198
-
199
- next if qualified_name.nil? || qualified_name.empty?
200
- next if filtered_mixin?(qualified_name)
201
-
202
- tree << RBI::MixesInClassMethods.new(qualified_name)
203
- end
204
-
205
- [mixed_in_class_methods, includes]
206
- rescue
207
- [[], []] # silence errors
208
- end
209
-
210
- sig { params(mod: Module, dynamic_extends: T::Array[Module]).returns(T::Boolean) }
211
- def module_included_by_another_dynamic_extend?(mod, dynamic_extends)
212
- dynamic_extends.any? do |dynamic_extend|
213
- mod != dynamic_extend && ancestors_of(dynamic_extend).include?(mod)
214
- end
215
- end
216
-
217
- sig { params(qualified_mixin_name: String).returns(T::Boolean) }
218
- def filtered_mixin?(qualified_mixin_name)
219
- # filter T:: namespace mixins that aren't T::Props
220
- # T::Props and subconstants have semantic value
221
- qualified_mixin_name.start_with?("::T::") && !qualified_mixin_name.start_with?("::T::Props")
222
- end
223
- end
@@ -1,59 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "pathname"
5
- require "shellwords"
6
-
7
- module Tapioca
8
- module Compilers
9
- module Sorbet
10
- SORBET_GEM_SPEC = T.let(
11
- Gem::Specification.find_by_name("sorbet-static"),
12
- Gem::Specification
13
- )
14
- SORBET = T.let(
15
- Pathname.new(SORBET_GEM_SPEC.full_gem_path) / "libexec" / "sorbet",
16
- Pathname
17
- )
18
- EXE_PATH_ENV_VAR = "TAPIOCA_SORBET_EXE"
19
-
20
- FEATURE_REQUIREMENTS = T.let({
21
- # First tag that includes https://github.com/sorbet/sorbet/pull/4706
22
- to_ary_nil_support: Gem::Requirement.new(">= 0.5.9220"),
23
- }.freeze, T::Hash[Symbol, Gem::Requirement])
24
-
25
- class << self
26
- extend(T::Sig)
27
-
28
- sig { params(args: String).returns(String) }
29
- def run(*args)
30
- IO.popen(
31
- [
32
- sorbet_path,
33
- "--quiet",
34
- *args,
35
- ].join(" "),
36
- err: "/dev/null"
37
- ).read
38
- end
39
-
40
- sig { returns(String) }
41
- def sorbet_path
42
- sorbet_path = ENV.fetch(EXE_PATH_ENV_VAR, SORBET)
43
- sorbet_path = SORBET if sorbet_path.empty?
44
- sorbet_path.to_s.shellescape
45
- end
46
-
47
- sig { params(feature: Symbol, version: T.nilable(Gem::Version)).returns(T::Boolean) }
48
- def supports?(feature, version: nil)
49
- version = SORBET_GEM_SPEC.version unless version
50
- requirement = FEATURE_REQUIREMENTS[feature]
51
-
52
- raise "Invalid Sorbet feature #{feature}" unless requirement
53
-
54
- requirement.satisfied_by?(version)
55
- end
56
- end
57
- end
58
- end
59
- end