tapioca 0.11.1 → 0.11.2

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: aa8f364e4169fb5f723942c3e96a7d4dc1790f59d64cb46cfc509ee55259f4cb
4
- data.tar.gz: b49aa47178045a367967b8c0b0731270ea8bb008edd2815711cb4764ca6adda6
3
+ metadata.gz: f19238941e4e663cef8326fc3cd46a9e9fb80b19130b676509d17e9081881fea
4
+ data.tar.gz: aa1db65b32badf4df8937a9d6566ac409b788cc746c714b40f5f7f0098cd062c
5
5
  SHA512:
6
- metadata.gz: 0e21aaff68f12f20fcb844153b57bca75cf56765ab21ed1375a5b3c7d9610bc60c4e815b84522dbd27497699675ac27a7a4066e4032cb15b3d00355b5cc4b3d0
7
- data.tar.gz: 87f26576c955e276801df3e8e00d3ed222374b430ea2012984127a10da0cc85ba0b166fa381bae6a627c5526d3af3079c63d22c3ef967a527df6b5502143c81e
6
+ metadata.gz: ba99ab5d35eb0d88cd671370bfbee1e73b72e1a6828c083915c32ed36d7142291b93b79d9258cca9a7bd7d41fcf31770f00865c12c0fe5395cba0d439b9bd850
7
+ data.tar.gz: 93d5fa3abba74e8919415d494bf47416a36721f4689d5ce893831b39cf4a8f00ca1f9d9c3500fcd70fa574fe2230d9aca6f743bf4c9642817ce969bbbdb6c431
@@ -93,7 +93,7 @@ module Tapioca
93
93
  def execute
94
94
  Loaders::Dsl.load_application(
95
95
  tapioca_path: @tapioca_path,
96
- eager_load: @requested_constants.empty?,
96
+ eager_load: @requested_constants.empty? && @requested_paths.empty?,
97
97
  app_root: @app_root,
98
98
  )
99
99
 
@@ -104,17 +104,10 @@ module Tapioca
104
104
  end
105
105
  say("")
106
106
 
107
- unless @requested_paths.empty?
108
- constants_from_paths = Static::SymbolLoader.symbols_from_paths(@requested_paths).to_a
109
- if constants_from_paths.empty?
110
- say_error("\nWarning: No constants found in: #{@requested_paths.map(&:to_s).join(", ")}", :yellow)
111
- end
112
-
113
- @requested_constants += constants_from_paths
114
- end
107
+ all_requested_constants = @requested_constants + constants_from_requested_paths
115
108
 
116
109
  outpath = @should_verify ? Pathname.new(Dir.mktmpdir) : @outpath
117
- rbi_files_to_purge = existing_rbi_filenames(@requested_constants)
110
+ rbi_files_to_purge = existing_rbi_filenames(all_requested_constants)
118
111
 
119
112
  pipeline = create_pipeline
120
113
 
@@ -146,7 +139,7 @@ module Tapioca
146
139
  if @auto_strictness
147
140
  say("")
148
141
  validate_rbi_files(
149
- command: default_command(:dsl, @requested_constants.join(" ")),
142
+ command: default_command(:dsl, all_requested_constants.join(" ")),
150
143
  gem_dir: @gem_dir,
151
144
  dsl_dir: @outpath.to_s,
152
145
  auto_strictness: @auto_strictness,
@@ -164,7 +157,8 @@ module Tapioca
164
157
  sig { returns(Tapioca::Dsl::Pipeline) }
165
158
  def create_pipeline
166
159
  Tapioca::Dsl::Pipeline.new(
167
- requested_constants: constantize(@requested_constants),
160
+ requested_constants:
161
+ constantize(@requested_constants) + constantize(constants_from_requested_paths, ignore_missing: true),
168
162
  requested_paths: @requested_paths,
169
163
  requested_compilers: constantize_compilers(@only),
170
164
  excluded_compilers: constantize_compilers(@exclude),
@@ -189,17 +183,17 @@ module Tapioca
189
183
  filenames.to_set
190
184
  end
191
185
 
192
- sig { params(constant_names: T::Array[String]).returns(T::Array[Module]) }
193
- def constantize(constant_names)
186
+ sig { params(constant_names: T::Array[String], ignore_missing: T::Boolean).returns(T::Array[Module]) }
187
+ def constantize(constant_names, ignore_missing: false)
194
188
  constant_map = constant_names.to_h do |name|
195
189
  [name, Object.const_get(name)]
196
190
  rescue NameError
197
191
  [name, nil]
198
192
  end
199
193
 
200
- unprocessable_constants = constant_map.select { |_, v| v.nil? }
194
+ processable_constants, unprocessable_constants = constant_map.partition { |_, v| !v.nil? }
201
195
 
202
- unless unprocessable_constants.empty?
196
+ unless unprocessable_constants.empty? || ignore_missing
203
197
  unprocessable_constants.each do |name, _|
204
198
  say("Error: Cannot find constant '#{name}'", :red)
205
199
  filename = dsl_rbi_filename(name)
@@ -209,7 +203,7 @@ module Tapioca
209
203
  raise Thor::Error, ""
210
204
  end
211
205
 
212
- constant_map.values
206
+ processable_constants.map { |_, constant| constant }
213
207
  end
214
208
 
215
209
  sig { params(compiler_names: T::Array[String]).returns(T::Array[T.class_of(Tapioca::Dsl::Compiler)]) }
@@ -384,6 +378,14 @@ module Tapioca
384
378
  def generate_command_for(constant)
385
379
  default_command(:dsl, constant)
386
380
  end
381
+
382
+ sig { returns(T::Array[String]) }
383
+ def constants_from_requested_paths
384
+ @constants_from_requested_paths ||= T.let(
385
+ Static::SymbolLoader.symbols_from_paths(@requested_paths).to_a,
386
+ T.nilable(T::Array[String]),
387
+ )
388
+ end
387
389
  end
388
390
  end
389
391
  end
@@ -41,7 +41,7 @@ module Tapioca
41
41
  sig { override.void }
42
42
  def decorate
43
43
  root.create_path(constant) do |mailer|
44
- constant.action_methods.to_a.each do |mailer_method|
44
+ action_methods_for_constant.each do |mailer_method|
45
45
  method_def = constant.instance_method(mailer_method)
46
46
  parameters = compile_method_parameters_to_rbi(method_def)
47
47
  mailer.create_method(
@@ -62,6 +62,13 @@ module Tapioca
62
62
  descendants_of(::ActionMailer::Base).reject(&:abstract?)
63
63
  end
64
64
  end
65
+
66
+ private
67
+
68
+ sig { returns(T::Array[String]) }
69
+ def action_methods_for_constant
70
+ constant.action_methods.to_a
71
+ end
65
72
  end
66
73
  end
67
74
  end
@@ -175,7 +175,7 @@ module Tapioca
175
175
 
176
176
  sig { override.returns(T::Enumerable[Module]) }
177
177
  def gather_constants
178
- descendants_of(ActiveRecord::Base).reject(&:abstract_class?)
178
+ ActiveRecord::Base.descendants.reject(&:abstract_class?)
179
179
  end
180
180
  end
181
181
 
@@ -83,7 +83,7 @@ module Tapioca
83
83
  class << self
84
84
  sig { override.returns(T::Enumerable[Module]) }
85
85
  def gather_constants
86
- descendants_of(::ActiveRecord::Base)
86
+ descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
87
87
  end
88
88
  end
89
89
 
@@ -17,11 +17,9 @@ module Tapioca
17
17
  def type_for(column_name)
18
18
  return ["T.untyped", "T.untyped"] if do_not_generate_strong_types?(@constant)
19
19
 
20
+ column = @constant.columns_hash[column_name]
20
21
  column_type = @constant.attribute_types[column_name]
21
-
22
22
  getter_type = type_for_activerecord_value(column_type)
23
-
24
- column = @constant.columns_hash[column_name]
25
23
  setter_type =
26
24
  case column_type
27
25
  when ActiveRecord::Enum::EnumType
@@ -31,7 +29,8 @@ module Tapioca
31
29
  end
32
30
 
33
31
  if column&.null
34
- return [as_nilable_type(getter_type), as_nilable_type(setter_type)]
32
+ getter_type = as_nilable_type(getter_type) unless not_nilable_serialized_column?(column_type)
33
+ return [getter_type, as_nilable_type(setter_type)]
35
34
  end
36
35
 
37
36
  if column_name == @constant.primary_key ||
@@ -148,6 +147,14 @@ module Tapioca
148
147
  "T.untyped"
149
148
  end
150
149
  end
150
+
151
+ sig { params(column_type: T.untyped).returns(T::Boolean) }
152
+ def not_nilable_serialized_column?(column_type)
153
+ return false unless column_type.is_a?(ActiveRecord::Type::Serialized)
154
+ return false unless column_type.coder.is_a?(ActiveRecord::Coders::YAMLColumn)
155
+
156
+ [Array.singleton_class, Hash.singleton_class].include?(column_type.coder.object_class.singleton_class)
157
+ end
151
158
  end
152
159
  end
153
160
  end
@@ -68,6 +68,10 @@ module Tapioca
68
68
  ERROR
69
69
  end
70
70
 
71
+ if defined?(::ActiveRecord::Base) && constants_to_process.any? { |c| ::ActiveRecord::Base > c }
72
+ abort_if_pending_migrations!
73
+ end
74
+
71
75
  result = Executor.new(
72
76
  constants_to_process,
73
77
  number_of_workers: @number_of_workers,
@@ -184,6 +188,16 @@ module Tapioca
184
188
  handler.call(error)
185
189
  exit(1)
186
190
  end
191
+
192
+ sig { void }
193
+ def abort_if_pending_migrations!
194
+ return unless defined?(::Rake)
195
+
196
+ Rails.application.load_tasks
197
+ if Rake::Task.task_defined?("db:abort_if_pending_migrations")
198
+ Rake::Task["db:abort_if_pending_migrations"].invoke
199
+ end
200
+ end
187
201
  end
188
202
  end
189
203
  end
@@ -25,6 +25,7 @@ module Tapioca
25
25
 
26
26
  sig { params(pipeline: Pipeline).void }
27
27
  def initialize(pipeline)
28
+ YARD::Registry.clear
28
29
  super(pipeline)
29
30
  pipeline.gem.parse_yard_docs
30
31
  end
@@ -96,7 +96,7 @@ module Tapioca
96
96
  )
97
97
  say(" Done", :green)
98
98
 
99
- errors = Spoom::Sorbet::Errors::Parser.parse_string(res.err)
99
+ errors = Spoom::Sorbet::Errors::Parser.parse_string(res.err || "")
100
100
 
101
101
  if errors.empty?
102
102
  say(" No errors found\n\n", [:green, :bold])
@@ -11,7 +11,7 @@ module Tapioca
11
11
 
12
12
  sig { params(tapioca_path: String, eager_load: T::Boolean, app_root: String).void }
13
13
  def load_application(tapioca_path:, eager_load: true, app_root: ".")
14
- loader = new(tapioca_path: tapioca_path, app_root: app_root)
14
+ loader = new(tapioca_path: tapioca_path, eager_load: eager_load, app_root: app_root)
15
15
  loader.load
16
16
  end
17
17
  end
@@ -20,7 +20,6 @@ module Tapioca
20
20
  def load
21
21
  load_dsl_extensions
22
22
  load_application
23
- abort_if_pending_migrations!
24
23
  load_dsl_compilers
25
24
  end
26
25
 
@@ -70,17 +69,6 @@ module Tapioca
70
69
 
71
70
  say("Done", :green)
72
71
  end
73
-
74
- sig { void }
75
- def abort_if_pending_migrations!
76
- return unless File.exist?("#{@app_root}/config/application.rb")
77
- return unless defined?(::Rake)
78
-
79
- Rails.application.load_tasks
80
- if Rake::Task.task_defined?("db:abort_if_pending_migrations")
81
- Rake::Task["db:abort_if_pending_migrations"].invoke
82
- end
83
- end
84
72
  end
85
73
  end
86
74
  end
@@ -48,11 +48,15 @@ module Tapioca
48
48
  eager_load_rails_app if eager_load
49
49
  rescue LoadError, StandardError => e
50
50
  say(
51
- "Tapioca attempted to load the Rails application after encountering a `config/application.rb` file, " \
51
+ "\nTapioca attempted to load the Rails application after encountering a `config/application.rb` file, " \
52
52
  "but it failed. If your application uses Rails please ensure it can be loaded correctly before " \
53
53
  "generating RBIs.\n#{e}",
54
54
  :yellow,
55
55
  )
56
+ if e.backtrace
57
+ backtrace = T.must(e.backtrace).join("\n")
58
+ say(backtrace, :cyan) # TODO: Check verbose flag to print backtrace.
59
+ end
56
60
  say("Continuing RBI generation without loading the Rails application.")
57
61
  end
58
62
 
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- VERSION = "0.11.1"
5
+ VERSION = "0.11.2"
6
6
  end
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.11.1
4
+ version: 0.11.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ufuk Kayserilioglu
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2023-02-23 00:00:00.000000000 Z
14
+ date: 2023-03-10 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler