tapioca 0.16.9 → 0.17.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -0
  3. data/exe/tapioca +6 -1
  4. data/lib/ruby_lsp/tapioca/addon.rb +73 -43
  5. data/lib/ruby_lsp/tapioca/run_gem_rbi_check.rb +43 -43
  6. data/lib/ruby_lsp/tapioca/server_addon.rb +13 -10
  7. data/lib/tapioca/bundler_ext/auto_require_hook.rb +6 -14
  8. data/lib/tapioca/cli.rb +16 -8
  9. data/lib/tapioca/commands/abstract_dsl.rb +39 -66
  10. data/lib/tapioca/commands/abstract_gem.rb +25 -46
  11. data/lib/tapioca/commands/annotations.rb +28 -34
  12. data/lib/tapioca/commands/check_shims.rb +6 -15
  13. data/lib/tapioca/commands/command.rb +12 -26
  14. data/lib/tapioca/commands/command_without_tracker.rb +2 -5
  15. data/lib/tapioca/commands/configure.rb +11 -16
  16. data/lib/tapioca/commands/dsl_compiler_list.rb +2 -1
  17. data/lib/tapioca/commands/dsl_generate.rb +2 -1
  18. data/lib/tapioca/commands/dsl_verify.rb +2 -1
  19. data/lib/tapioca/commands/gem_generate.rb +5 -9
  20. data/lib/tapioca/commands/gem_sync.rb +2 -1
  21. data/lib/tapioca/commands/gem_verify.rb +3 -2
  22. data/lib/tapioca/commands/require.rb +3 -7
  23. data/lib/tapioca/commands/todo.rb +6 -10
  24. data/lib/tapioca/dsl/compiler.rb +36 -63
  25. data/lib/tapioca/dsl/compilers/aasm.rb +33 -44
  26. data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +8 -7
  27. data/lib/tapioca/dsl/compilers/action_mailer.rb +6 -5
  28. data/lib/tapioca/dsl/compilers/action_text.rb +6 -5
  29. data/lib/tapioca/dsl/compilers/active_job.rb +6 -10
  30. data/lib/tapioca/dsl/compilers/active_model_attributes.rb +10 -11
  31. data/lib/tapioca/dsl/compilers/active_model_secure_password.rb +5 -6
  32. data/lib/tapioca/dsl/compilers/active_model_validations_confirmation.rb +5 -12
  33. data/lib/tapioca/dsl/compilers/active_record_associations.rb +17 -44
  34. data/lib/tapioca/dsl/compilers/active_record_columns.rb +20 -26
  35. data/lib/tapioca/dsl/compilers/active_record_delegated_types.rb +9 -8
  36. data/lib/tapioca/dsl/compilers/active_record_enum.rb +7 -6
  37. data/lib/tapioca/dsl/compilers/active_record_fixtures.rb +54 -62
  38. data/lib/tapioca/dsl/compilers/active_record_relations.rb +148 -209
  39. data/lib/tapioca/dsl/compilers/active_record_scope.rb +8 -13
  40. data/lib/tapioca/dsl/compilers/active_record_secure_token.rb +5 -4
  41. data/lib/tapioca/dsl/compilers/active_record_store.rb +5 -4
  42. data/lib/tapioca/dsl/compilers/active_record_typed_store.rb +19 -28
  43. data/lib/tapioca/dsl/compilers/active_resource.rb +19 -21
  44. data/lib/tapioca/dsl/compilers/active_storage.rb +6 -14
  45. data/lib/tapioca/dsl/compilers/active_support_concern.rb +9 -8
  46. data/lib/tapioca/dsl/compilers/active_support_current_attributes.rb +8 -7
  47. data/lib/tapioca/dsl/compilers/active_support_time_ext.rb +5 -4
  48. data/lib/tapioca/dsl/compilers/config.rb +5 -4
  49. data/lib/tapioca/dsl/compilers/frozen_record.rb +7 -11
  50. data/lib/tapioca/dsl/compilers/graphql_input_object.rb +9 -10
  51. data/lib/tapioca/dsl/compilers/graphql_mutation.rb +6 -10
  52. data/lib/tapioca/dsl/compilers/identity_cache.rb +11 -39
  53. data/lib/tapioca/dsl/compilers/json_api_client_resource.rb +9 -18
  54. data/lib/tapioca/dsl/compilers/kredis.rb +7 -8
  55. data/lib/tapioca/dsl/compilers/mixed_in_class_attributes.rb +5 -4
  56. data/lib/tapioca/dsl/compilers/protobuf.rb +13 -26
  57. data/lib/tapioca/dsl/compilers/rails_generators.rb +9 -11
  58. data/lib/tapioca/dsl/compilers/sidekiq_worker.rb +23 -13
  59. data/lib/tapioca/dsl/compilers/smart_properties.rb +32 -38
  60. data/lib/tapioca/dsl/compilers/state_machines.rb +15 -26
  61. data/lib/tapioca/dsl/compilers/url_helpers.rb +10 -9
  62. data/lib/tapioca/dsl/compilers.rb +4 -7
  63. data/lib/tapioca/dsl/helpers/active_model_type_helper.rb +13 -16
  64. data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +13 -28
  65. data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +19 -15
  66. data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +5 -24
  67. data/lib/tapioca/dsl/pipeline.rb +30 -58
  68. data/lib/tapioca/executor.rb +6 -12
  69. data/lib/tapioca/gem/events.rb +24 -34
  70. data/lib/tapioca/gem/listeners/base.rb +7 -10
  71. data/lib/tapioca/gem/listeners/dynamic_mixins.rb +4 -2
  72. data/lib/tapioca/gem/listeners/foreign_constants.rb +5 -7
  73. data/lib/tapioca/gem/listeners/methods.rb +36 -47
  74. data/lib/tapioca/gem/listeners/mixins.rb +6 -18
  75. data/lib/tapioca/gem/listeners/remove_empty_payload_scopes.rb +4 -2
  76. data/lib/tapioca/gem/listeners/sorbet_enums.rb +4 -2
  77. data/lib/tapioca/gem/listeners/sorbet_helpers.rb +4 -2
  78. data/lib/tapioca/gem/listeners/sorbet_props.rb +4 -2
  79. data/lib/tapioca/gem/listeners/sorbet_required_ancestors.rb +4 -2
  80. data/lib/tapioca/gem/listeners/sorbet_signatures.rb +7 -5
  81. data/lib/tapioca/gem/listeners/sorbet_type_variables.rb +6 -4
  82. data/lib/tapioca/gem/listeners/source_location.rb +15 -8
  83. data/lib/tapioca/gem/listeners/subconstants.rb +5 -4
  84. data/lib/tapioca/gem/listeners/yard_doc.rb +30 -23
  85. data/lib/tapioca/gem/pipeline.rb +107 -91
  86. data/lib/tapioca/gem_info.rb +1 -1
  87. data/lib/tapioca/gemfile.rb +64 -73
  88. data/lib/tapioca/helpers/cli_helper.rb +4 -7
  89. data/lib/tapioca/helpers/config_helper.rb +17 -29
  90. data/lib/tapioca/helpers/env_helper.rb +2 -5
  91. data/lib/tapioca/helpers/gem_helper.rb +5 -5
  92. data/lib/tapioca/helpers/git_attributes.rb +3 -3
  93. data/lib/tapioca/helpers/rbi_files_helper.rb +76 -73
  94. data/lib/tapioca/helpers/rbi_helper.rb +14 -22
  95. data/lib/tapioca/helpers/sorbet_helper.rb +9 -18
  96. data/lib/tapioca/helpers/source_uri.rb +15 -25
  97. data/lib/tapioca/helpers/test/content.rb +7 -10
  98. data/lib/tapioca/helpers/test/dsl_compiler.rb +20 -33
  99. data/lib/tapioca/helpers/test/isolation.rb +10 -14
  100. data/lib/tapioca/helpers/test/template.rb +6 -11
  101. data/lib/tapioca/internal.rb +18 -8
  102. data/lib/tapioca/loaders/dsl.rb +11 -19
  103. data/lib/tapioca/loaders/gem.rb +6 -21
  104. data/lib/tapioca/loaders/loader.rb +21 -39
  105. data/lib/tapioca/rbi_ext/model.rb +12 -37
  106. data/lib/tapioca/rbi_formatter.rb +10 -19
  107. data/lib/tapioca/rbs/rewriter.rb +55 -0
  108. data/lib/tapioca/repo_index.rb +7 -9
  109. data/lib/tapioca/runtime/attached_class_of_32.rb +1 -1
  110. data/lib/tapioca/runtime/attached_class_of_legacy.rb +2 -5
  111. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +23 -23
  112. data/lib/tapioca/runtime/generic_type_registry.rb +13 -23
  113. data/lib/tapioca/runtime/reflection.rb +81 -60
  114. data/lib/tapioca/runtime/source_location.rb +44 -0
  115. data/lib/tapioca/runtime/trackers/autoload.rb +7 -9
  116. data/lib/tapioca/runtime/trackers/constant_definition.rb +18 -14
  117. data/lib/tapioca/runtime/trackers/method_definition.rb +65 -0
  118. data/lib/tapioca/runtime/trackers/mixin.rb +8 -11
  119. data/lib/tapioca/runtime/trackers/required_ancestor.rb +3 -3
  120. data/lib/tapioca/runtime/trackers/tracker.rb +3 -6
  121. data/lib/tapioca/runtime/trackers.rb +5 -8
  122. data/lib/tapioca/sorbet_ext/generic_name_patch.rb +9 -15
  123. data/lib/tapioca/sorbet_ext/name_patch.rb +2 -2
  124. data/lib/tapioca/sorbet_ext/proc_bind_patch.rb +1 -1
  125. data/lib/tapioca/static/requires_compiler.rb +6 -6
  126. data/lib/tapioca/static/symbol_loader.rb +14 -16
  127. data/lib/tapioca/static/symbol_table_parser.rb +8 -8
  128. data/lib/tapioca/version.rb +1 -1
  129. data/lib/tapioca.rb +22 -29
  130. metadata +27 -10
@@ -4,18 +4,15 @@
4
4
  module Tapioca
5
5
  module Gem
6
6
  module Listeners
7
+ # @abstract
7
8
  class Base
8
9
  extend T::Sig
9
- extend T::Helpers
10
-
11
- abstract!
12
-
13
- sig { params(pipeline: Pipeline).void }
10
+ #: (Pipeline pipeline) -> void
14
11
  def initialize(pipeline)
15
12
  @pipeline = pipeline
16
13
  end
17
14
 
18
- sig { params(event: NodeAdded).void }
15
+ #: (NodeAdded event) -> void
19
16
  def dispatch(event)
20
17
  return if ignore?(event)
21
18
 
@@ -33,19 +30,19 @@ module Tapioca
33
30
 
34
31
  private
35
32
 
36
- sig { params(event: ConstNodeAdded).void }
33
+ #: (ConstNodeAdded event) -> void
37
34
  def on_const(event)
38
35
  end
39
36
 
40
- sig { params(event: ScopeNodeAdded).void }
37
+ #: (ScopeNodeAdded event) -> void
41
38
  def on_scope(event)
42
39
  end
43
40
 
44
- sig { params(event: MethodNodeAdded).void }
41
+ #: (MethodNodeAdded event) -> void
45
42
  def on_method(event)
46
43
  end
47
44
 
48
- sig { params(event: NodeAdded).returns(T::Boolean) }
45
+ #: (NodeAdded event) -> bool
49
46
  def ignore?(event)
50
47
  # Some listeners do not have to take any action on certain events. For example,
51
48
  # almost every listener should skip ForeignScopeNodeAdded events in order not to generate
@@ -11,7 +11,8 @@ module Tapioca
11
11
 
12
12
  private
13
13
 
14
- sig { override.params(event: ScopeNodeAdded).void }
14
+ # @override
15
+ #: (ScopeNodeAdded event) -> void
15
16
  def on_scope(event)
16
17
  constant = event.constant
17
18
  return if constant.is_a?(Class)
@@ -27,7 +28,8 @@ module Tapioca
27
28
  end
28
29
  end
29
30
 
30
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
31
+ # @override
32
+ #: (NodeAdded event) -> bool
31
33
  def ignore?(event)
32
34
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
33
35
  end
@@ -11,7 +11,8 @@ module Tapioca
11
11
 
12
12
  private
13
13
 
14
- sig { override.params(event: ScopeNodeAdded).void }
14
+ # @override
15
+ #: (ScopeNodeAdded event) -> void
15
16
  def on_scope(event)
16
17
  mixin = event.constant
17
18
  return if Class === mixin # Classes can't be mixed into other constants
@@ -47,16 +48,13 @@ module Tapioca
47
48
  end
48
49
  end
49
50
 
50
- sig do
51
- params(
52
- location: String,
53
- ).returns(T::Boolean)
54
- end
51
+ #: (String location) -> bool
55
52
  def mixed_in_by_gem?(location)
56
53
  @pipeline.gem.contains_path?(location)
57
54
  end
58
55
 
59
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
56
+ # @override
57
+ #: (NodeAdded event) -> bool
60
58
  def ignore?(event)
61
59
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
62
60
  end
@@ -12,7 +12,8 @@ module Tapioca
12
12
 
13
13
  private
14
14
 
15
- sig { override.params(event: ScopeNodeAdded).void }
15
+ # @override
16
+ #: (ScopeNodeAdded event) -> void
16
17
  def on_scope(event)
17
18
  symbol = event.symbol
18
19
  constant = event.constant
@@ -23,15 +24,7 @@ module Tapioca
23
24
  compile_directly_owned_methods(node, symbol, singleton_class_of(constant), attached_class: constant)
24
25
  end
25
26
 
26
- sig do
27
- params(
28
- tree: RBI::Tree,
29
- module_name: String,
30
- mod: Module,
31
- for_visibility: T::Array[Symbol],
32
- attached_class: T.nilable(Module),
33
- ).void
34
- end
27
+ #: (RBI::Tree tree, String module_name, Module mod, ?Array[Symbol] for_visibility, ?attached_class: Module?) -> void
35
28
  def compile_directly_owned_methods(
36
29
  tree,
37
30
  module_name,
@@ -59,29 +52,41 @@ module Tapioca
59
52
  end
60
53
  end
61
54
 
62
- sig do
63
- params(
64
- tree: RBI::Tree,
65
- symbol_name: String,
66
- constant: Module,
67
- method: T.nilable(UnboundMethod),
68
- visibility: RBI::Visibility,
69
- ).void
70
- end
55
+ #: (RBI::Tree tree, String symbol_name, Module constant, UnboundMethod? method, ?RBI::Visibility visibility) -> void
71
56
  def compile_method(tree, symbol_name, constant, method, visibility = RBI::Public.new)
72
57
  return unless method
73
58
  return unless method_owned_by_constant?(method, constant)
74
- return if @pipeline.symbol_in_payload?(symbol_name) && !@pipeline.method_in_gem?(method)
75
59
 
76
- signature = lookup_signature_of(method)
77
- method = T.let(signature.method, UnboundMethod) if signature
60
+ begin
61
+ signature = signature_of!(method)
62
+ method = signature.method if signature #: UnboundMethod
63
+
64
+ case @pipeline.method_definition_in_gem(method.name, constant)
65
+ when Pipeline::MethodUnknown
66
+ # This means that this is a C-method. Thus, we want to
67
+ # skip it only if the constant is an ignored one, since
68
+ # that probably means that we've hit a C-method for a
69
+ # core type.
70
+ return if @pipeline.symbol_in_payload?(symbol_name)
71
+ when Pipeline::MethodNotInGem
72
+ # Do not process this method, if it is not defined by the current gem
73
+ return
74
+ end
75
+ rescue SignatureBlockError => error
76
+ @pipeline.error_handler.call(<<~MSG)
77
+ Unable to compile signature for method: #{method.owner}##{method.name}
78
+ Exception raised when loading signature: #{error.cause.inspect}
79
+ MSG
80
+
81
+ signature = nil
82
+ end
78
83
 
79
84
  method_name = method.name.to_s
80
85
  return unless valid_method_name?(method_name)
81
86
  return if struct_method?(constant, method_name)
82
87
  return if method_name.start_with?("__t_props_generated_")
83
88
 
84
- parameters = T.let(method.parameters, T::Array[[Symbol, T.nilable(Symbol)]])
89
+ parameters = method.parameters #: Array[[Symbol, Symbol?]]
85
90
 
86
91
  sanitized_parameters = parameters.each_with_index.map do |(type, name), index|
87
92
  fallback_arg_name = "_arg#{index}"
@@ -154,10 +159,10 @@ module Tapioca
154
159
  # This method implements a better way of checking whether a constant defines a method.
155
160
  # It walks up the ancestor tree via the `super_method` method; if any of the super
156
161
  # methods are owned by the constant, it means that the constant declares the method.
157
- sig { params(method: UnboundMethod, constant: Module).returns(T::Boolean) }
162
+ #: (UnboundMethod method, Module constant) -> bool
158
163
  def method_owned_by_constant?(method, constant)
159
164
  # Widen the type of `method` to be nilable
160
- method = T.let(method, T.nilable(UnboundMethod))
165
+ method = method #: UnboundMethod?
161
166
 
162
167
  while method
163
168
  return true if method.owner == constant
@@ -168,7 +173,7 @@ module Tapioca
168
173
  false
169
174
  end
170
175
 
171
- sig { params(mod: Module).returns(T::Hash[Symbol, T::Array[Symbol]]) }
176
+ #: (Module mod) -> Hash[Symbol, Array[Symbol]]
172
177
  def method_names_by_visibility(mod)
173
178
  {
174
179
  public: public_instance_methods_of(mod),
@@ -177,7 +182,7 @@ module Tapioca
177
182
  }
178
183
  end
179
184
 
180
- sig { params(constant: Module, method_name: String).returns(T::Boolean) }
185
+ #: (Module constant, String method_name) -> bool
181
186
  def struct_method?(constant, method_name)
182
187
  return false unless T::Props::ClassMethods === constant
183
188
 
@@ -187,12 +192,7 @@ module Tapioca
187
192
  .include?(method_name.gsub(/=$/, "").to_sym)
188
193
  end
189
194
 
190
- sig do
191
- params(
192
- attached_class: T.nilable(Module),
193
- method_name: Symbol,
194
- ).returns(T.nilable(T::Boolean))
195
- end
195
+ #: (Module? attached_class, Symbol method_name) -> bool?
196
196
  def method_new_in_abstract_class?(attached_class, method_name)
197
197
  attached_class &&
198
198
  method_name == :new &&
@@ -200,29 +200,18 @@ module Tapioca
200
200
  Class === attached_class.singleton_class
201
201
  end
202
202
 
203
- sig { params(constant: Module).returns(T.nilable(UnboundMethod)) }
203
+ #: (Module constant) -> UnboundMethod?
204
204
  def initialize_method_for(constant)
205
205
  constant.instance_method(:initialize)
206
206
  rescue
207
207
  nil
208
208
  end
209
209
 
210
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
210
+ # @override
211
+ #: (NodeAdded event) -> bool
211
212
  def ignore?(event)
212
213
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
213
214
  end
214
-
215
- sig { params(method: UnboundMethod).returns(T.untyped) }
216
- def lookup_signature_of(method)
217
- signature_of!(method)
218
- rescue LoadError, StandardError => error
219
- @pipeline.error_handler.call(<<~MSG)
220
- Unable to compile signature for method: #{method.owner}##{method.name}
221
- Exception raised when loading signature: #{error.inspect}
222
- MSG
223
-
224
- nil
225
- end
226
215
  end
227
216
  end
228
217
  end
@@ -11,7 +11,8 @@ module Tapioca
11
11
 
12
12
  private
13
13
 
14
- sig { override.params(event: ScopeNodeAdded).void }
14
+ # @override
15
+ #: (ScopeNodeAdded event) -> void
15
16
  def on_scope(event)
16
17
  constant = event.constant
17
18
  singleton_class = singleton_class_of(constant)
@@ -31,14 +32,7 @@ module Tapioca
31
32
  add_mixins(node, constant, extends.reverse, Runtime::Trackers::Mixin::Type::Extend)
32
33
  end
33
34
 
34
- sig do
35
- params(
36
- tree: RBI::Tree,
37
- constant: Module,
38
- mods: T::Array[Module],
39
- mixin_type: Runtime::Trackers::Mixin::Type,
40
- ).void
41
- end
35
+ #: (RBI::Tree tree, Module constant, Array[Module] mods, Runtime::Trackers::Mixin::Type mixin_type) -> void
42
36
  def add_mixins(tree, constant, mods, mixin_type)
43
37
  mods
44
38
  .select do |mod|
@@ -65,13 +59,7 @@ module Tapioca
65
59
  end
66
60
  end
67
61
 
68
- sig do
69
- params(
70
- constant: Module,
71
- mixin: Module,
72
- mixin_type: Runtime::Trackers::Mixin::Type,
73
- ).returns(T::Boolean)
74
- end
62
+ #: (Module constant, Module mixin, Runtime::Trackers::Mixin::Type mixin_type) -> bool
75
63
  def mixed_in_by_gem?(constant, mixin, mixin_type)
76
64
  mixin_location = Runtime::Trackers::Mixin.mixin_location(mixin, mixin_type, constant)
77
65
 
@@ -80,14 +68,14 @@ module Tapioca
80
68
  @pipeline.gem.contains_path?(mixin_location)
81
69
  end
82
70
 
83
- sig { params(mixin_name: String).returns(T::Boolean) }
71
+ #: (String mixin_name) -> bool
84
72
  def filtered_mixin?(mixin_name)
85
73
  # filter T:: namespace mixins that aren't T::Props
86
74
  # T::Props and subconstants have semantic value
87
75
  mixin_name.start_with?("T::") && !mixin_name.start_with?("T::Props")
88
76
  end
89
77
 
90
- sig { params(constant: Module).returns(T::Array[Module]) }
78
+ #: (Module constant) -> Array[Module]
91
79
  def interesting_ancestors_of(constant)
92
80
  inherited_ancestors = Set.new.compare_by_identity.merge(inherited_ancestors_of(constant))
93
81
 
@@ -11,12 +11,14 @@ module Tapioca
11
11
 
12
12
  private
13
13
 
14
- sig { override.params(event: ScopeNodeAdded).void }
14
+ # @override
15
+ #: (ScopeNodeAdded event) -> void
15
16
  def on_scope(event)
16
17
  event.node.detach if @pipeline.symbol_in_payload?(event.symbol) && event.node.empty?
17
18
  end
18
19
 
19
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
20
+ # @override
21
+ #: (NodeAdded event) -> bool
20
22
  def ignore?(event)
21
23
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
22
24
  end
@@ -9,7 +9,8 @@ module Tapioca
9
9
 
10
10
  private
11
11
 
12
- sig { override.params(event: ScopeNodeAdded).void }
12
+ # @override
13
+ #: (ScopeNodeAdded event) -> void
13
14
  def on_scope(event)
14
15
  constant = event.constant
15
16
  return unless T::Enum > event.constant # rubocop:disable Style/InvertibleUnlessCondition
@@ -24,7 +25,8 @@ module Tapioca
24
25
  event.node << enum_block
25
26
  end
26
27
 
27
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
28
+ # @override
29
+ #: (NodeAdded event) -> bool
28
30
  def ignore?(event)
29
31
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
30
32
  end
@@ -11,7 +11,8 @@ module Tapioca
11
11
 
12
12
  private
13
13
 
14
- sig { override.params(event: ScopeNodeAdded).void }
14
+ # @override
15
+ #: (ScopeNodeAdded event) -> void
15
16
  def on_scope(event)
16
17
  constant = event.constant
17
18
  node = event.node
@@ -23,7 +24,8 @@ module Tapioca
23
24
  node << RBI::Helper.new("sealed") if sealed_module?(constant)
24
25
  end
25
26
 
26
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
27
+ # @override
28
+ #: (NodeAdded event) -> bool
27
29
  def ignore?(event)
28
30
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
29
31
  end
@@ -10,7 +10,8 @@ module Tapioca
10
10
 
11
11
  private
12
12
 
13
- sig { override.params(event: ScopeNodeAdded).void }
13
+ # @override
14
+ #: (ScopeNodeAdded event) -> void
14
15
  def on_scope(event)
15
16
  constant = event.constant
16
17
  node = event.node
@@ -29,7 +30,8 @@ module Tapioca
29
30
  end
30
31
  end
31
32
 
32
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
33
+ # @override
34
+ #: (NodeAdded event) -> bool
33
35
  def ignore?(event)
34
36
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
35
37
  end
@@ -9,7 +9,8 @@ module Tapioca
9
9
 
10
10
  private
11
11
 
12
- sig { override.params(event: ScopeNodeAdded).void }
12
+ # @override
13
+ #: (ScopeNodeAdded event) -> void
13
14
  def on_scope(event)
14
15
  ancestors = Runtime::Trackers::RequiredAncestor.required_ancestors_by(event.constant)
15
16
  ancestors.each do |ancestor|
@@ -19,7 +20,8 @@ module Tapioca
19
20
  end
20
21
  end
21
22
 
22
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
23
+ # @override
24
+ #: (NodeAdded event) -> bool
23
25
  def ignore?(event)
24
26
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
25
27
  end
@@ -14,7 +14,8 @@ module Tapioca
14
14
 
15
15
  private
16
16
 
17
- sig { override.params(event: MethodNodeAdded).void }
17
+ # @override
18
+ #: (MethodNodeAdded event) -> void
18
19
  def on_method(event)
19
20
  signature = event.signature
20
21
  return unless signature
@@ -22,9 +23,9 @@ module Tapioca
22
23
  event.node.sigs << compile_signature(signature, event.parameters)
23
24
  end
24
25
 
25
- sig { params(signature: T.untyped, parameters: T::Array[[Symbol, String]]).returns(RBI::Sig) }
26
+ #: (untyped signature, Array[[Symbol, String]] parameters) -> RBI::Sig
26
27
  def compile_signature(signature, parameters)
27
- parameter_types = T.let(signature.arg_types.to_h, T::Hash[Symbol, T::Types::Base])
28
+ parameter_types = signature.arg_types.to_h #: Hash[Symbol, T::Types::Base]
28
29
  parameter_types.merge!(signature.kwarg_types)
29
30
  parameter_types[signature.rest_name] = signature.rest_type if signature.has_rest
30
31
  parameter_types[signature.keyrest_name] = signature.keyrest_type if signature.has_keyrest
@@ -64,7 +65,7 @@ module Tapioca
64
65
  sig
65
66
  end
66
67
 
67
- sig { params(signature: T.untyped).returns(T::Boolean) }
68
+ #: (untyped signature) -> bool
68
69
  def signature_final?(signature)
69
70
  modules_with_final = T::Private::Methods.instance_variable_get(:@modules_with_final)
70
71
  # In https://github.com/sorbet/sorbet/pull/7531, Sorbet changed internal hashes to be compared by identity,
@@ -75,7 +76,8 @@ module Tapioca
75
76
  final_methods.include?(signature.method_name)
76
77
  end
77
78
 
78
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
79
+ # @override
80
+ #: (NodeAdded event) -> bool
79
81
  def ignore?(event)
80
82
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
81
83
  end
@@ -11,7 +11,8 @@ module Tapioca
11
11
 
12
12
  private
13
13
 
14
- sig { override.params(event: ScopeNodeAdded).void }
14
+ # @override
15
+ #: (ScopeNodeAdded event) -> void
15
16
  def on_scope(event)
16
17
  constant = event.constant
17
18
  node = event.node
@@ -23,7 +24,7 @@ module Tapioca
23
24
  node << sclass if sclass.nodes.length > 1
24
25
  end
25
26
 
26
- sig { params(tree: RBI::Tree, constant: Module).void }
27
+ #: (RBI::Tree tree, Module constant) -> void
27
28
  def compile_type_variable_declarations(tree, constant)
28
29
  # Try to find the type variables defined on this constant, bail if we can't
29
30
  type_variables = Runtime::GenericTypeRegistry.lookup_type_variables(constant)
@@ -46,7 +47,7 @@ module Tapioca
46
47
  tree << RBI::Extend.new("T::Generic")
47
48
  end
48
49
 
49
- sig { params(type_variable: Tapioca::TypeVariableModule).returns(T.nilable(RBI::Node)) }
50
+ #: (Tapioca::TypeVariableModule type_variable) -> RBI::Node?
50
51
  def node_from_type_variable(type_variable)
51
52
  case type_variable.type
52
53
  when Tapioca::TypeVariableModule::Type::HasAttachedClass
@@ -59,7 +60,8 @@ module Tapioca
59
60
  end
60
61
  end
61
62
 
62
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
63
+ # @override
64
+ #: (NodeAdded event) -> bool
63
65
  def ignore?(event)
64
66
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
65
67
  end
@@ -9,35 +9,42 @@ module Tapioca
9
9
 
10
10
  private
11
11
 
12
- sig { override.params(event: ConstNodeAdded).void }
12
+ # @override
13
+ #: (ConstNodeAdded event) -> void
13
14
  def on_const(event)
14
15
  file, line = Object.const_source_location(event.symbol)
15
16
  add_source_location_comment(event.node, file, line)
16
17
  end
17
18
 
18
- sig { override.params(event: ScopeNodeAdded).void }
19
+ # @override
20
+ #: (ScopeNodeAdded event) -> void
19
21
  def on_scope(event)
20
22
  # Instead of using `const_source_location`, which always reports the first place where a constant is defined,
21
23
  # we filter the locations tracked by ConstantDefinition. This allows us to provide the correct location for
22
24
  # constants that are defined by multiple gems.
23
25
  locations = Runtime::Trackers::ConstantDefinition.locations_for(event.constant)
24
26
  location = locations.find do |loc|
25
- Pathname.new(loc.path).realpath.to_s.include?(@pipeline.gem.full_gem_path)
27
+ Pathname.new(loc.file).realpath.to_s.include?(@pipeline.gem.full_gem_path)
26
28
  end
27
29
 
28
30
  # The location may still be nil in some situations, like constant aliases (e.g.: MyAlias = OtherConst). These
29
31
  # are quite difficult to attribute a correct location, given that the source location points to the original
30
32
  # constants and not the alias
31
- add_source_location_comment(event.node, location.path, location.lineno) unless location.nil?
33
+ add_source_location_comment(event.node, location.file, location.line) unless location.nil?
32
34
  end
33
35
 
34
- sig { override.params(event: MethodNodeAdded).void }
36
+ # @override
37
+ #: (MethodNodeAdded event) -> void
35
38
  def on_method(event)
36
- file, line = event.method.source_location
37
- add_source_location_comment(event.node, file, line)
39
+ definition = @pipeline.method_definition_in_gem(event.method.name, event.constant)
40
+
41
+ if Pipeline::MethodInGemWithLocation === definition
42
+ loc = definition.location
43
+ add_source_location_comment(event.node, loc.file, loc.line)
44
+ end
38
45
  end
39
46
 
40
- sig { params(node: RBI::NodeWithComments, file: T.nilable(String), line: T.nilable(Integer)).void }
47
+ #: (RBI::NodeWithComments node, String? file, Integer? line) -> void
41
48
  def add_source_location_comment(node, file, line)
42
49
  return unless file && line
43
50
 
@@ -11,14 +11,14 @@ module Tapioca
11
11
 
12
12
  private
13
13
 
14
- sig { override.params(event: ScopeNodeAdded).void }
14
+ # @override
15
+ #: (ScopeNodeAdded event) -> void
15
16
  def on_scope(event)
16
17
  symbol = event.symbol
17
- return if @pipeline.symbol_in_payload?(symbol) && event.node.empty?
18
+ constant = event.constant
18
19
 
19
20
  prefix = symbol == "Object" ? "" : symbol
20
21
 
21
- constant = event.constant
22
22
  constants_of(constant).sort.uniq.map do |constant_name|
23
23
  name = "#{prefix}::#{constant_name}"
24
24
  subconstant = constantize(name)
@@ -32,7 +32,8 @@ module Tapioca
32
32
  end
33
33
  end
34
34
 
35
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
35
+ # @override
36
+ #: (NodeAdded event) -> bool
36
37
  def ignore?(event)
37
38
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
38
39
  end
@@ -7,23 +7,21 @@ module Tapioca
7
7
  class YardDoc < Base
8
8
  extend T::Sig
9
9
 
10
- IGNORED_COMMENTS = T.let(
11
- [
12
- ":doc:",
13
- ":nodoc:",
14
- "typed:",
15
- "frozen_string_literal:",
16
- "encoding:",
17
- "warn_indent:",
18
- "shareable_constant_value:",
19
- "rubocop:",
20
- ],
21
- T::Array[String],
22
- )
23
-
24
- IGNORED_SIG_TAGS = T.let(["param", "return"], T::Array[String])
25
-
26
- sig { params(pipeline: Pipeline).void }
10
+ IGNORED_COMMENTS = [
11
+ ":doc:",
12
+ ":nodoc:",
13
+ "typed:",
14
+ "frozen_string_literal:",
15
+ "encoding:",
16
+ "warn_indent:",
17
+ "shareable_constant_value:",
18
+ "rubocop:",
19
+ "@requires_ancestor:",
20
+ ] #: Array[String]
21
+
22
+ IGNORED_SIG_TAGS = ["param", "return"] #: Array[String]
23
+
24
+ #: (Pipeline pipeline) -> void
27
25
  def initialize(pipeline)
28
26
  YARD::Registry.clear
29
27
  super(pipeline)
@@ -32,17 +30,25 @@ module Tapioca
32
30
 
33
31
  private
34
32
 
35
- sig { override.params(event: ConstNodeAdded).void }
33
+ #: (String line) -> bool
34
+ def rbs_comment?(line)
35
+ line.strip.start_with?(": ", "| ")
36
+ end
37
+
38
+ # @override
39
+ #: (ConstNodeAdded event) -> void
36
40
  def on_const(event)
37
41
  event.node.comments = documentation_comments(event.symbol)
38
42
  end
39
43
 
40
- sig { override.params(event: ScopeNodeAdded).void }
44
+ # @override
45
+ #: (ScopeNodeAdded event) -> void
41
46
  def on_scope(event)
42
47
  event.node.comments = documentation_comments(event.symbol)
43
48
  end
44
49
 
45
- sig { override.params(event: MethodNodeAdded).void }
50
+ # @override
51
+ #: (MethodNodeAdded event) -> void
46
52
  def on_method(event)
47
53
  separator = event.constant.singleton_class? ? "." : "#"
48
54
  event.node.comments = documentation_comments(
@@ -51,7 +57,7 @@ module Tapioca
51
57
  )
52
58
  end
53
59
 
54
- sig { params(name: String, sigs: T::Array[RBI::Sig]).returns(T::Array[RBI::Comment]) }
60
+ #: (String name, ?sigs: Array[RBI::Sig]) -> Array[RBI::Comment]
55
61
  def documentation_comments(name, sigs: [])
56
62
  yard_docs = YARD::Registry.at(name)
57
63
  return [] unless yard_docs
@@ -60,7 +66,7 @@ module Tapioca
60
66
  return [] if /(copyright|license)/i.match?(docstring)
61
67
 
62
68
  comments = docstring.lines
63
- .reject { |line| IGNORED_COMMENTS.any? { |comment| line.include?(comment) } }
69
+ .reject { |line| IGNORED_COMMENTS.any? { |comment| line.include?(comment) } || rbs_comment?(line) }
64
70
  .map! { |line| RBI::Comment.new(line) }
65
71
 
66
72
  tags = yard_docs.tags
@@ -95,7 +101,8 @@ module Tapioca
95
101
  comments
96
102
  end
97
103
 
98
- sig { override.params(event: NodeAdded).returns(T::Boolean) }
104
+ # @override
105
+ #: (NodeAdded event) -> bool
99
106
  def ignore?(event)
100
107
  event.is_a?(Tapioca::Gem::ForeignScopeNodeAdded)
101
108
  end