tapioca 0.17.7 → 0.17.9

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d003e839857cc260e7b1ab86fd4a48d93efc53e4a43ac9ccac6c85d9a89e63a1
4
- data.tar.gz: 900f2d0369802b0fac34f60c04e3c238cd68e439c1d6d60f4b9ed5d8c82770f0
3
+ metadata.gz: 3668f1f1916b284b762a3ed370a2f658b2edd25d1c0c44be37fd7ca321be9200
4
+ data.tar.gz: ce3540ff4aaebab9b9e506c4192ffdee93ef17c09b2399fb114d2b735fbf0b0e
5
5
  SHA512:
6
- metadata.gz: b2f68a283b2499203877730fb5f981ed1e6c09c686a6c3e59297bea18361b5dd2d1831581f7b3edce6cf38936819544feeeebe59b1747520738542b0ae606ffe
7
- data.tar.gz: '09769a8ab2aac1763cadecd013c9979c58d750c052f94c26eccfcbbd0a7ca07e0cb027c18e3737e90b90e85d4bebfca2fb4e8e559fdd9c4a0dd472ce5e59ee77'
6
+ metadata.gz: 648c2bd8e7ef7f14c0bce4736ea47636c043a5ee1e529e676569c85f398b1380838631fab7146439162491523446ac40c112fb8247ca55402947d372b235f5c7
7
+ data.tar.gz: 11370dc255bf5e5508139480e4e9def8a51f145de3574c1f4dd17ad72572f1b64b30d0d876244426542b35d1e639d18662719f47137049d5aaac1fb6bdc7d5c6
@@ -39,14 +39,14 @@ module RubyLsp
39
39
  fork do
40
40
  with_notification_wrapper("route_dsl", "Generating route DSL RBIs") do
41
41
  constants = ::Tapioca::Dsl::Compilers::UrlHelpers.gather_constants
42
- dsl(constants.map(&:name), "--only=Tapioca::Dsl::Compilers::UrlHelpers", "ActiveSupportConcern")
42
+ dsl(constants.map(&:name))
43
43
  end
44
44
  end
45
45
  when "fixtures_dsl"
46
46
  fork do
47
47
  with_notification_wrapper("fixture_dsl", "Generating fixture DSL RBIs") do
48
48
  constants = ::Tapioca::Dsl::Compilers::ActiveRecordFixtures.gather_constants
49
- dsl(constants.map(&:name), "--only=Tapioca::Dsl::Compilers::ActiveRecordFixtures")
49
+ dsl(constants.map(&:name))
50
50
  end
51
51
  end
52
52
  end
@@ -60,7 +60,7 @@ module RubyLsp
60
60
  end
61
61
  end
62
62
 
63
- def dsl(constants, *args)
63
+ def dsl(constants)
64
64
  load("tapioca/cli.rb") # Reload the CLI to reset thor defaults between requests
65
65
 
66
66
  ::Tapioca::Cli.addon_mode!
@@ -68,7 +68,6 @@ module RubyLsp
68
68
  # Order here is important to avoid having Thor confuse arguments. Do not put an array argument at the end before
69
69
  # the list of constants
70
70
  arguments = ["dsl"]
71
- arguments.concat(args)
72
71
  arguments.push("--workers=1")
73
72
  arguments.concat(constants)
74
73
 
data/lib/tapioca/cli.rb CHANGED
@@ -301,6 +301,7 @@ module Tapioca
301
301
  rbi_formatter: rbi_formatter(options),
302
302
  halt_upon_load_error: options[:halt_upon_load_error],
303
303
  lsp_addon: options[:lsp_addon],
304
+ verbose: options[:verbose],
304
305
  }
305
306
 
306
307
  command = if verify
@@ -8,7 +8,7 @@ module Tapioca
8
8
  include SorbetHelper
9
9
  include RBIFilesHelper
10
10
 
11
- #: (gem_names: Array[String], exclude: Array[String], include_dependencies: bool, prerequire: String?, postrequire: String, typed_overrides: Hash[String, String], outpath: Pathname, file_header: bool, include_doc: bool, include_loc: bool, include_exported_rbis: bool, ?number_of_workers: Integer?, ?auto_strictness: bool, ?dsl_dir: String, ?rbi_formatter: RBIFormatter, ?halt_upon_load_error: bool, ?lsp_addon: bool?) -> void
11
+ #: (gem_names: Array[String], exclude: Array[String], include_dependencies: bool, prerequire: String?, postrequire: String, typed_overrides: Hash[String, String], outpath: Pathname, file_header: bool, include_doc: bool, include_loc: bool, include_exported_rbis: bool, ?number_of_workers: Integer?, ?auto_strictness: bool, ?dsl_dir: String, ?rbi_formatter: RBIFormatter, ?halt_upon_load_error: bool, ?lsp_addon: bool?, ?verbose: bool?) -> void
12
12
  def initialize(
13
13
  gem_names:,
14
14
  exclude:,
@@ -26,7 +26,8 @@ module Tapioca
26
26
  dsl_dir: DEFAULT_DSL_DIR,
27
27
  rbi_formatter: DEFAULT_RBI_FORMATTER,
28
28
  halt_upon_load_error: true,
29
- lsp_addon: false
29
+ lsp_addon: false,
30
+ verbose: false
30
31
  )
31
32
  @gem_names = gem_names
32
33
  @exclude = exclude
@@ -41,6 +42,7 @@ module Tapioca
41
42
  @dsl_dir = dsl_dir
42
43
  @rbi_formatter = rbi_formatter
43
44
  @lsp_addon = lsp_addon
45
+ @verbose = verbose
44
46
 
45
47
  super()
46
48
 
@@ -58,6 +60,7 @@ module Tapioca
58
60
  #: (Gemfile::GemSpec gem) -> void
59
61
  def compile_gem_rbi(gem)
60
62
  gem_name = set_color(gem.name, :yellow, :bold)
63
+ say("Currently compiling #{gem_name}", :cyan) if @verbose
61
64
 
62
65
  rbi = RBI::File.new(strictness: @typed_overrides[gem.name] || "true")
63
66
 
@@ -67,7 +70,7 @@ module Tapioca
67
70
  reason: "types exported from the `#{gem.name}` gem",
68
71
  ) if @file_header
69
72
 
70
- rbi.root = Runtime::Trackers::Autoload.with_disabled_exits do
73
+ rbi.root = Runtime.with_disabled_exits do
71
74
  Tapioca::Gem::Pipeline.new(
72
75
  gem,
73
76
  include_doc: @include_doc,
@@ -41,10 +41,11 @@ module Tapioca
41
41
 
42
42
  #: -> Array[GemInfo]
43
43
  def list_gemfile_gems
44
- say("Listing gems from Gemfile.lock... ", [:blue, :bold])
45
- gemfile = Bundler.read_file("Gemfile.lock")
46
- parser = Bundler::LockfileParser.new(gemfile)
47
- gem_info = parser.specs.map { |spec| GemInfo.from_spec(spec) }
44
+ lockfile_path = Bundler.definition.lockfile.basename
45
+ say("Listing gems from #{lockfile_path}... ", [:blue, :bold])
46
+
47
+ specs = Bundler.definition.specs
48
+ gem_info = specs.map { |spec| GemInfo.from_spec(spec) }
48
49
  say("Done", :green)
49
50
  gem_info
50
51
  end
@@ -21,7 +21,7 @@ module Tapioca
21
21
  # @final
22
22
  #: -> void
23
23
  def run
24
- Tapioca.silence_warnings do
24
+ Runtime.silence_warnings do
25
25
  execute
26
26
  end
27
27
  end
@@ -26,12 +26,16 @@ module Tapioca
26
26
  # # typed: true
27
27
  #
28
28
  # class Shop
29
+ # include GeneratedAttributeMethods
29
30
  #
30
- # sig { returns(T.nilable(::String)) }
31
- # def name; end
31
+ # module GeneratedAttributeMethods
32
+ # sig { returns(T.nilable(::String)) }
33
+ # def name; end
34
+ #
35
+ # sig { params(name: T.nilable(::String)).returns(T.nilable(::String)) }
36
+ # def name=(name); end
37
+ # end
32
38
  #
33
- # sig { params(name: T.nilable(::String)).returns(T.nilable(::String)) }
34
- # def name=(name); end
35
39
  # end
36
40
  # ~~~
37
41
  #: [ConstantType = (Class[::ActiveModel::Attributes] & ::ActiveModel::Attributes::ClassMethods)]
@@ -45,9 +49,13 @@ module Tapioca
45
49
  return if attribute_methods.empty?
46
50
 
47
51
  root.create_path(constant) do |klass|
48
- attribute_methods.each do |method, attribute_type|
49
- generate_method(klass, method, attribute_type)
52
+ klass.create_module("GeneratedAttributeMethods") do |mod|
53
+ attribute_methods.each do |method, attribute_type|
54
+ generate_method(mod, method, attribute_type)
55
+ end
50
56
  end
57
+
58
+ klass.create_include("GeneratedAttributeMethods")
51
59
  end
52
60
  end
53
61
 
@@ -95,6 +95,12 @@ module Tapioca
95
95
  # @override
96
96
  #: -> T::Enumerable[Module]
97
97
  def gather_constants
98
+ # In some versions of Rails 8.1, `ActiveModel::SecurePassword` uses `Numeric#minutes`
99
+ # which isn't explicitly required in the gem, and it might not be loaded already.
100
+ # We might need to require it before referencing the constant to avoid a NoMethodError when
101
+ # the constant is autoloaded.
102
+ require "active_support/core_ext/numeric/time" unless defined?(1.minutes)
103
+
98
104
  # This selects all classes that are `ActiveModel::SecurePassword::ClassMethods === klass`.
99
105
  # In other words, we select all classes that have `ActiveModel::SecurePassword::ClassMethods`
100
106
  # as an ancestor of its singleton class, i.e. all classes that have extended the
@@ -13,7 +13,7 @@ module Tapioca
13
13
  #
14
14
  # ~~~rb
15
15
  # class Post < ApplicationRecord
16
- # enum title_type: %i(book all web), _suffix: :title
16
+ # enum :title_type, %i(book all web), suffix: :title
17
17
  # end
18
18
  # ~~~
19
19
  #
@@ -4,6 +4,7 @@
4
4
  return unless defined?(ActiveRecord::Base)
5
5
 
6
6
  require "tapioca/dsl/helpers/active_model_type_helper"
7
+ require "tapioca/dsl/helpers/active_record_column_type_helper"
7
8
  require "tapioca/dsl/helpers/active_record_constants_helper"
8
9
 
9
10
  module Tapioca
@@ -228,15 +229,7 @@ module Tapioca
228
229
  use_ranges: ["T.untyped", "nil"],
229
230
  } #: Hash[Symbol, [String, String]]
230
231
  CALCULATION_METHODS = ActiveRecord::Calculations.instance_methods(false) #: Array[Symbol]
231
- ENUMERABLE_QUERY_METHODS = [:any?, :many?, :none?, :one?] #: Array[Symbol]
232
- FIND_OR_CREATE_METHODS = [
233
- :find_or_create_by,
234
- :find_or_create_by!,
235
- :find_or_initialize_by,
236
- :create_or_find_by,
237
- :create_or_find_by!,
238
- ] #: Array[Symbol]
239
- BUILDER_METHODS = [:new, :create, :create!, :build] #: Array[Symbol]
232
+ RELATION_METHODS = ActiveRecord::Relation.instance_methods(false) #: Array[Symbol]
240
233
  TO_ARRAY_METHODS = [:to_ary, :to_a] #: Array[Symbol]
241
234
 
242
235
  private
@@ -837,9 +830,13 @@ module Tapioca
837
830
  end
838
831
  when :ids
839
832
  if constant.table_exists?
840
- primary_key_type = constant.type_for_attribute(constant.primary_key)
841
- type = Tapioca::Dsl::Helpers::ActiveModelTypeHelper.type_for(primary_key_type)
842
- type = RBIHelper.as_non_nilable_type(type)
833
+ column_type_helper = Tapioca::Dsl::Helpers::ActiveRecordColumnTypeHelper.new(
834
+ constant,
835
+ column_type_option: Tapioca::Dsl::Helpers::ActiveRecordColumnTypeHelper::ColumnTypeOption::Persisted,
836
+ )
837
+ primary_key = constant.primary_key
838
+ getter_type, _setter_type = column_type_helper.type_for(primary_key)
839
+ type = getter_type
843
840
  create_common_method("ids", return_type: "T::Array[#{type}]")
844
841
  else
845
842
  create_common_method("ids", return_type: "Array")
@@ -902,61 +899,132 @@ module Tapioca
902
899
  end
903
900
  end
904
901
 
905
- ENUMERABLE_QUERY_METHODS.each do |method_name|
906
- block_type = "T.nilable(T.proc.params(record: #{constant_name}).returns(T.untyped))"
907
- create_common_method(
908
- method_name,
909
- parameters: [
910
- create_block_param("block", type: block_type),
911
- ],
912
- return_type: "T::Boolean",
913
- )
914
- end
902
+ RELATION_METHODS.each do |method_name|
903
+ case method_name
904
+ when :any?, :many?, :none?, :one? # enumerable query methods
905
+ block_type = "T.nilable(T.proc.params(record: #{constant_name}).returns(T.untyped))"
906
+ create_common_method(
907
+ method_name,
908
+ parameters: [
909
+ create_block_param("block", type: block_type),
910
+ ],
911
+ return_type: "T::Boolean",
912
+ )
913
+ when :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, :create_or_find_by, :create_or_find_by! # find or create methods
914
+ common_relation_methods_module.create_method(method_name.to_s) do |method|
915
+ method.add_param("attributes")
916
+ method.add_block_param("block")
915
917
 
916
- FIND_OR_CREATE_METHODS.each do |method_name|
917
- common_relation_methods_module.create_method(method_name.to_s) do |method|
918
- method.add_param("attributes")
919
- method.add_block_param("block")
918
+ # `T.untyped` matches `T::Array[T.untyped]` so the array signature
919
+ # must be defined first for Sorbet to pick it, if valid.
920
+ method.add_sig do |sig|
921
+ sig.add_param("attributes", "T::Array[T.untyped]")
922
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
923
+ sig.return_type = "T::Array[#{constant_name}]"
924
+ end
920
925
 
921
- # `T.untyped` matches `T::Array[T.untyped]` so the array signature
922
- # must be defined first for Sorbet to pick it, if valid.
923
- method.add_sig do |sig|
924
- sig.add_param("attributes", "T::Array[T.untyped]")
925
- sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
926
- sig.return_type = "T::Array[#{constant_name}]"
926
+ method.add_sig do |sig|
927
+ sig.add_param("attributes", "T.untyped")
928
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
929
+ sig.return_type = constant_name
930
+ end
927
931
  end
932
+ when :new, :create, :create!, :build # builder methods
933
+ common_relation_methods_module.create_method(method_name.to_s) do |method|
934
+ method.add_opt_param("attributes", "nil")
935
+ method.add_block_param("block")
928
936
 
929
- method.add_sig do |sig|
930
- sig.add_param("attributes", "T.untyped")
931
- sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
932
- sig.return_type = constant_name
933
- end
934
- end
935
- end
937
+ method.add_sig do |sig|
938
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
939
+ sig.return_type = constant_name
940
+ end
936
941
 
937
- BUILDER_METHODS.each do |method_name|
938
- common_relation_methods_module.create_method(method_name.to_s) do |method|
939
- method.add_opt_param("attributes", "nil")
940
- method.add_block_param("block")
942
+ # `T.untyped` matches `T::Array[T.untyped]` so the array signature
943
+ # must be defined first for Sorbet to pick it, if valid.
944
+ method.add_sig do |sig|
945
+ sig.add_param("attributes", "T::Array[T.untyped]")
946
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
947
+ sig.return_type = "T::Array[#{constant_name}]"
948
+ end
941
949
 
942
- method.add_sig do |sig|
943
- sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
944
- sig.return_type = constant_name
950
+ method.add_sig do |sig|
951
+ sig.add_param("attributes", "T.untyped")
952
+ sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
953
+ sig.return_type = constant_name
954
+ end
945
955
  end
956
+ when :insert_all, :insert_all!, :upsert_all # insert all methods
957
+ returning_type = "T.nilable(T.any(T::Array[Symbol], FalseClass))"
958
+ unique_by_type = "T.nilable(T.any(T::Array[Symbol], Symbol))"
946
959
 
947
- # `T.untyped` matches `T::Array[T.untyped]` so the array signature
948
- # must be defined first for Sorbet to pick it, if valid.
949
- method.add_sig do |sig|
950
- sig.add_param("attributes", "T::Array[T.untyped]")
951
- sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
952
- sig.return_type = "T::Array[#{constant_name}]"
960
+ parameters = [
961
+ create_param("attributes", type: "T::Array[Hash]"),
962
+ create_kw_opt_param("returning", type: returning_type, default: "nil"),
963
+ ]
964
+
965
+ # Bang methods don't have the `unique_by` parameter
966
+ unless bang_method?(method_name)
967
+ parameters << create_kw_opt_param("unique_by", type: unique_by_type, default: "nil")
953
968
  end
954
969
 
955
- method.add_sig do |sig|
956
- sig.add_param("attributes", "T.untyped")
957
- sig.add_param("block", "T.nilable(T.proc.params(object: #{constant_name}).void)")
958
- sig.return_type = constant_name
970
+ common_relation_methods_module.create_method(
971
+ method_name.to_s,
972
+ parameters: parameters,
973
+ return_type: "ActiveRecord::Result",
974
+ )
975
+ when :insert, :insert!, :upsert # insert methods
976
+ returning_type = "T.nilable(T.any(T::Array[Symbol], FalseClass))"
977
+ unique_by_type = "T.nilable(T.any(T::Array[Symbol], Symbol))"
978
+
979
+ parameters = [
980
+ create_param("attributes", type: "Hash"),
981
+ create_kw_opt_param("returning", type: returning_type, default: "nil"),
982
+ ]
983
+
984
+ # Bang methods don't have the `unique_by` parameter
985
+ unless bang_method?(method_name)
986
+ parameters << create_kw_opt_param("unique_by", type: unique_by_type, default: "nil")
959
987
  end
988
+
989
+ common_relation_methods_module.create_method(
990
+ method_name.to_s,
991
+ parameters: parameters,
992
+ return_type: "ActiveRecord::Result",
993
+ )
994
+ when :delete, :destroy
995
+ # For these cases, it is valid to pass the above kind of things, but also:
996
+ # - a model identifier, which can be:
997
+ # - a numeric id, thus `Integer`
998
+ # - a string id, thus `String`
999
+ # - a collection of identifiers
1000
+ # - a collection of identifiers, thus `T::Enumerable[T.any(Integer, String)]`
1001
+ # which, coupled with the above case, gives us:
1002
+ # `T.any(Model, Integer, String, T::Enumerable[T.any(Model, Integer, String, T::Enumerable[Model])])`
1003
+
1004
+ common_relation_methods_module.create_method(
1005
+ method_name.to_s,
1006
+ parameters: [
1007
+ create_rest_param(
1008
+ "records",
1009
+ type: "T.any(#{constant_name}, Integer, String" \
1010
+ ", T::Enumerable[T.any(#{constant_name}, Integer, String, T::Enumerable[#{constant_name}])])",
1011
+ ),
1012
+ ],
1013
+ return_type: method_name == :delete ? "Integer" : "T::Array[#{constant_name}]",
1014
+ )
1015
+ when :delete_all, :destroy_all
1016
+ common_relation_methods_module.create_method(
1017
+ method_name.to_s,
1018
+ return_type: method_name == :delete_all ? "Integer" : "T::Array[#{constant_name}]",
1019
+ )
1020
+ when :delete_by, :destroy_by
1021
+ common_relation_methods_module.create_method(
1022
+ method_name.to_s,
1023
+ parameters: [
1024
+ create_param("args", type: "T.untyped"),
1025
+ ],
1026
+ return_type: method_name == :delete_by ? "Integer" : "T::Array[#{constant_name}]",
1027
+ )
960
1028
  end
961
1029
  end
962
1030
 
@@ -269,7 +269,11 @@ module Tapioca
269
269
  Field.new(
270
270
  name: descriptor.name,
271
271
  type: type,
272
- init_type: "T.nilable(T.any(#{type}, T::Array[#{elem_type}]))",
272
+ # The FFI implementation accepts Enumerables:
273
+ # https://github.com/protocolbuffers/protobuf/blob/fc0eda1fd4eff075f1fb2e9249fa4209f0227e33/ruby/lib/google/protobuf/ffi/repeated_field.rb#L361-L366
274
+ # However the C implementation of the initializer specifically checks for Arrays:
275
+ # https://github.com/protocolbuffers/protobuf/blob/fc0eda1fd4eff075f1fb2e9249fa4209f0227e33/ruby/ext/google/protobuf_c/message.c#L568-L573
276
+ init_type: "T.nilable(T::Array[#{elem_type}])",
273
277
  default: "T.unsafe(nil)",
274
278
  )
275
279
  end
@@ -152,8 +152,10 @@ module Tapioca
152
152
  when ActiveRecord::Type::Serialized
153
153
  serialized_column_type(column_type)
154
154
  when ->(type) {
155
- defined?(ActiveRecord::Normalization::NormalizedValueType) &&
156
- ActiveRecord::Normalization::NormalizedValueType === type
155
+ (defined?(ActiveRecord::Normalization::NormalizedValueType) &&
156
+ ActiveRecord::Normalization::NormalizedValueType === type) ||
157
+ (defined?(ActiveModel::Attributes::Normalization::NormalizedValueType) &&
158
+ ActiveModel::Attributes::Normalization::NormalizedValueType === type)
157
159
  }
158
160
  type_for_activerecord_value(column_type.cast_type, column_nullability:)
159
161
  when ->(type) {
@@ -98,7 +98,13 @@ module Tapioca
98
98
  # inherited ancestors, past the location of the constant itself.
99
99
  ancestors = Set.new.compare_by_identity.merge(ancestors_of(constant))
100
100
 
101
- (ancestors - inherited_ancestors).to_a
101
+ result = (ancestors - inherited_ancestors).to_a
102
+
103
+ # Filter out Kernel for modules (but not classes) since modules shouldn't
104
+ # need to explicitly include Kernel in RBIs
105
+ result.delete(Kernel) unless Class === constant
106
+
107
+ result
102
108
  end
103
109
  end
104
110
  end
@@ -32,7 +32,7 @@ module Tapioca
32
32
 
33
33
  #: (String line) -> bool
34
34
  def rbs_comment?(line)
35
- line.strip.start_with?(": ", "| ")
35
+ line.start_with?(": ", "| ")
36
36
  end
37
37
 
38
38
  # @override
@@ -74,7 +74,7 @@ module Tapioca
74
74
 
75
75
  comments << RBI::Comment.new("") if comments.any? && tags.any?
76
76
 
77
- tags.sort_by(&:tag_name).each do |tag|
77
+ tags.sort_by { |tag| [tag.tag_name, tag.name.to_s] }.each do |tag|
78
78
  line = +"@#{tag.tag_name}"
79
79
 
80
80
  tag_name = tag.name
@@ -9,7 +9,7 @@ module Tapioca
9
9
  class << self
10
10
  extend(T::Sig)
11
11
 
12
- #: (Bundler::LazySpecification spec) -> GemInfo
12
+ #: (::Bundler::StubSpecification | ::Gem::Specification spec) -> GemInfo
13
13
  def from_spec(spec)
14
14
  new(name: spec.name, version: spec.version)
15
15
  end
@@ -28,7 +28,7 @@ module Tapioca
28
28
  #: (String name, String content, ?require_file: bool) -> String
29
29
  def add_ruby_file(name, content, require_file: true)
30
30
  add_content_file(name, content).tap do |file_name|
31
- Tapioca.silence_warnings { require(file_name) } if require_file
31
+ Runtime.silence_warnings { require(file_name) } if require_file
32
32
  end
33
33
  end
34
34
 
@@ -4,6 +4,7 @@
4
4
  require "set"
5
5
 
6
6
  require "tapioca"
7
+ require "tapioca/runtime/helpers"
7
8
  require "tapioca/runtime/reflection"
8
9
  require "tapioca/runtime/trackers"
9
10
 
@@ -44,13 +44,20 @@ module Tapioca
44
44
  #: -> void
45
45
  def require_gem_file
46
46
  say("Requiring all gems to prepare for compiling... ")
47
- begin
47
+
48
+ bundle_loaded = true #: bool
49
+
50
+ Runtime.with_disabled_exits do
48
51
  load_bundle(@bundle, @prerequire, @postrequire, @halt_upon_load_error)
49
52
  rescue LoadError => e
53
+ bundle_loaded = false
50
54
  explain_failed_require(@postrequire, e)
51
- exit(1)
52
55
  end
53
56
 
57
+ # Can't call exit in the rescue block above, since it will be disabled,
58
+ # so we check the flag after the block.
59
+ exit(1) unless bundle_loaded
60
+
54
61
  Runtime::Trackers::Autoload.eager_load_all!
55
62
 
56
63
  say(" Done", :green)
@@ -0,0 +1,40 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Tapioca
5
+ module Runtime
6
+ NOOP_METHOD = ->(*_args, **_kwargs, &_block) {} #: ^() -> void
7
+ private_constant :NOOP_METHOD
8
+
9
+ class << self
10
+ #: [Result] { -> Result } -> Result
11
+ def silence_warnings(&blk)
12
+ original_verbosity = $VERBOSE
13
+ $VERBOSE = nil
14
+ ::Gem::DefaultUserInteraction.use_ui(::Gem::SilentUI.new) do
15
+ blk.call
16
+ end
17
+ ensure
18
+ $VERBOSE = original_verbosity
19
+ end
20
+
21
+ #: [Result] { -> Result } -> Result
22
+ def with_disabled_exits(&block)
23
+ original_abort = Kernel.instance_method(:abort)
24
+ original_exit = Kernel.instance_method(:exit)
25
+
26
+ begin
27
+ Kernel.define_method(:abort, NOOP_METHOD)
28
+ Kernel.define_method(:exit, NOOP_METHOD)
29
+
30
+ silence_warnings do
31
+ block.call
32
+ end
33
+ ensure
34
+ Kernel.define_method(:exit, original_exit)
35
+ Kernel.define_method(:abort, original_abort)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -8,8 +8,6 @@ module Tapioca
8
8
  extend Tracker
9
9
  extend T::Sig
10
10
 
11
- NOOP_METHOD = ->(*_args, **_kwargs, &_block) {}
12
-
13
11
  @constant_names_registered_for_autoload = [] #: Array[String]
14
12
 
15
13
  class << self
@@ -17,7 +15,7 @@ module Tapioca
17
15
 
18
16
  #: -> void
19
17
  def eager_load_all!
20
- with_disabled_exits do
18
+ Runtime.with_disabled_exits do
21
19
  until @constant_names_registered_for_autoload.empty?
22
20
  # Grab the next constant name
23
21
  constant_name = T.must(@constant_names_registered_for_autoload.shift)
@@ -33,24 +31,6 @@ module Tapioca
33
31
 
34
32
  @constant_names_registered_for_autoload << constant_name
35
33
  end
36
-
37
- #: [Result] { -> Result } -> Result
38
- def with_disabled_exits(&block)
39
- original_abort = Kernel.instance_method(:abort)
40
- original_exit = Kernel.instance_method(:exit)
41
-
42
- begin
43
- Kernel.define_method(:abort, NOOP_METHOD)
44
- Kernel.define_method(:exit, NOOP_METHOD)
45
-
46
- Tapioca.silence_warnings do
47
- block.call
48
- end
49
- ensure
50
- Kernel.define_method(:exit, original_exit)
51
- Kernel.define_method(:abort, original_abort)
52
- end
53
- end
54
34
  end
55
35
  end
56
36
  end
@@ -52,7 +52,7 @@ end
52
52
 
53
53
  module T
54
54
  module Helpers
55
- prepend(Module.new do
55
+ prepend(::Module.new do
56
56
  def requires_ancestor(&block)
57
57
  # We can't directly call the block since the ancestor might not be loaded yet.
58
58
  # We save the block in the map and will resolve it later.
@@ -22,7 +22,7 @@ module T
22
22
  # `T::Generic#type_member` just instantiates a `T::Type::TypeMember` instance and returns it.
23
23
  # We use that when registering the type member and then later return it from this method.
24
24
  Tapioca::TypeVariableModule.new(
25
- T.cast(self, Module),
25
+ T.cast(self, ::Module),
26
26
  Tapioca::TypeVariableModule::Type::Member,
27
27
  variance,
28
28
  bounds_proc,
@@ -35,7 +35,7 @@ module T
35
35
  # `T::Generic#type_template` just instantiates a `T::Type::TypeTemplate` instance and returns it.
36
36
  # We use that when registering the type template and then later return it from this method.
37
37
  Tapioca::TypeVariableModule.new(
38
- T.cast(self, Module),
38
+ T.cast(self, ::Module),
39
39
  Tapioca::TypeVariableModule::Type::Template,
40
40
  variance,
41
41
  bounds_proc,
@@ -48,7 +48,7 @@ module T
48
48
  Tapioca::Runtime::GenericTypeRegistry.register_type_variable(
49
49
  self,
50
50
  Tapioca::TypeVariableModule.new(
51
- T.cast(self, Module),
51
+ T.cast(self, ::Module),
52
52
  Tapioca::TypeVariableModule::Type::HasAttachedClass,
53
53
  variance,
54
54
  bounds_proc,
@@ -5,24 +5,13 @@ module T
5
5
  module Types
6
6
  class Simple
7
7
  module NamePatch
8
- NAME_METHOD = Module.instance_method(:name) #: UnboundMethod
9
-
10
8
  def name
11
9
  # Sorbet memoizes this method into the `@name` instance variable but
12
10
  # doing so means that types get memoized before this patch is applied
13
- qualified_name_of(@raw_type)
14
- end
15
-
16
- def qualified_name_of(constant)
17
- name = NAME_METHOD.bind_call(constant)
18
- name = nil if name&.start_with?("#<")
19
- return "::T.untyped" if name.nil?
11
+ name = Tapioca::Runtime::Reflection.qualified_name_of(@raw_type)
12
+ name = "::T.untyped" if name.nil?
20
13
 
21
- if name.start_with?("::")
22
- name
23
- else
24
- "::#{name}"
25
- end
14
+ name
26
15
  end
27
16
  end
28
17
 
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- VERSION = "0.17.7"
5
+ VERSION = "0.17.9"
6
6
  end
data/lib/tapioca.rb CHANGED
@@ -9,21 +9,6 @@ module Tapioca
9
9
 
10
10
  @traces = [] #: Array[TracePoint]
11
11
 
12
- class << self
13
- extend T::Sig
14
-
15
- #: [Result] { -> Result } -> Result
16
- def silence_warnings(&blk)
17
- original_verbosity = $VERBOSE
18
- $VERBOSE = nil
19
- ::Gem::DefaultUserInteraction.use_ui(::Gem::SilentUI.new) do
20
- blk.call
21
- end
22
- ensure
23
- $VERBOSE = original_verbosity
24
- end
25
- end
26
-
27
12
  class Error < StandardError; end
28
13
 
29
14
  LIB_ROOT_DIR = T.must(__dir__) #: String
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tapioca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.7
4
+ version: 0.17.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu
@@ -69,89 +69,89 @@ dependencies:
69
69
  - !ruby/object:Gem::Version
70
70
  version: 1.21.0
71
71
  - !ruby/object:Gem::Dependency
72
- name: rbi
72
+ name: require-hooks
73
73
  requirement: !ruby/object:Gem::Requirement
74
74
  requirements:
75
75
  - - ">="
76
76
  - !ruby/object:Gem::Version
77
- version: 0.3.1
77
+ version: 0.2.2
78
78
  type: :runtime
79
79
  prerelease: false
80
80
  version_requirements: !ruby/object:Gem::Requirement
81
81
  requirements:
82
82
  - - ">="
83
83
  - !ruby/object:Gem::Version
84
- version: 0.3.1
84
+ version: 0.2.2
85
85
  - !ruby/object:Gem::Dependency
86
- name: require-hooks
86
+ name: sorbet-static-and-runtime
87
87
  requirement: !ruby/object:Gem::Requirement
88
88
  requirements:
89
89
  - - ">="
90
90
  - !ruby/object:Gem::Version
91
- version: 0.2.2
91
+ version: 0.5.11087
92
92
  type: :runtime
93
93
  prerelease: false
94
94
  version_requirements: !ruby/object:Gem::Requirement
95
95
  requirements:
96
96
  - - ">="
97
97
  - !ruby/object:Gem::Version
98
- version: 0.2.2
98
+ version: 0.5.11087
99
99
  - !ruby/object:Gem::Dependency
100
- name: sorbet-static-and-runtime
100
+ name: thor
101
101
  requirement: !ruby/object:Gem::Requirement
102
102
  requirements:
103
103
  - - ">="
104
104
  - !ruby/object:Gem::Version
105
- version: 0.5.11087
105
+ version: 1.2.0
106
106
  type: :runtime
107
107
  prerelease: false
108
108
  version_requirements: !ruby/object:Gem::Requirement
109
109
  requirements:
110
110
  - - ">="
111
111
  - !ruby/object:Gem::Version
112
- version: 0.5.11087
112
+ version: 1.2.0
113
113
  - !ruby/object:Gem::Dependency
114
- name: spoom
114
+ name: yard-sorbet
115
115
  requirement: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ">="
118
118
  - !ruby/object:Gem::Version
119
- version: 1.7.0
119
+ version: '0'
120
120
  type: :runtime
121
121
  prerelease: false
122
122
  version_requirements: !ruby/object:Gem::Requirement
123
123
  requirements:
124
124
  - - ">="
125
125
  - !ruby/object:Gem::Version
126
- version: 1.7.0
126
+ version: '0'
127
127
  - !ruby/object:Gem::Dependency
128
- name: thor
128
+ name: rbi
129
129
  requirement: !ruby/object:Gem::Requirement
130
130
  requirements:
131
131
  - - ">="
132
132
  - !ruby/object:Gem::Version
133
- version: 1.2.0
133
+ version: 0.3.7
134
134
  type: :runtime
135
135
  prerelease: false
136
136
  version_requirements: !ruby/object:Gem::Requirement
137
137
  requirements:
138
138
  - - ">="
139
139
  - !ruby/object:Gem::Version
140
- version: 1.2.0
140
+ version: 0.3.7
141
141
  - !ruby/object:Gem::Dependency
142
- name: yard-sorbet
142
+ name: spoom
143
143
  requirement: !ruby/object:Gem::Requirement
144
144
  requirements:
145
145
  - - ">="
146
146
  - !ruby/object:Gem::Version
147
- version: '0'
147
+ version: 1.7.9
148
148
  type: :runtime
149
149
  prerelease: false
150
150
  version_requirements: !ruby/object:Gem::Requirement
151
151
  requirements:
152
152
  - - ">="
153
153
  - !ruby/object:Gem::Version
154
- version: '0'
154
+ version: 1.7.9
155
155
  email:
156
156
  - ruby@shopify.com
157
157
  executables:
@@ -280,6 +280,7 @@ files:
280
280
  - lib/tapioca/runtime/attached_class_of_legacy.rb
281
281
  - lib/tapioca/runtime/dynamic_mixin_compiler.rb
282
282
  - lib/tapioca/runtime/generic_type_registry.rb
283
+ - lib/tapioca/runtime/helpers.rb
283
284
  - lib/tapioca/runtime/reflection.rb
284
285
  - lib/tapioca/runtime/source_location.rb
285
286
  - lib/tapioca/runtime/trackers.rb
@@ -316,7 +317,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
316
317
  - !ruby/object:Gem::Version
317
318
  version: '0'
318
319
  requirements: []
319
- rubygems_version: 3.6.9
320
+ rubygems_version: 3.7.2
320
321
  specification_version: 4
321
322
  summary: A Ruby Interface file generator for gems, core types and the Ruby standard
322
323
  library