tapioca 0.6.1 → 0.7.0

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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +13 -2
  3. data/README.md +79 -25
  4. data/Rakefile +10 -14
  5. data/lib/tapioca/cli.rb +66 -80
  6. data/lib/tapioca/{generators/base.rb → commands/command.rb} +17 -10
  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 +32 -24
  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 +29 -35
  21. data/lib/tapioca/{compilers/dsl → dsl/compilers}/active_record_columns.rb +26 -24
  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 +12 -17
  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 +28 -25
  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 +13 -14
  37. data/lib/tapioca/{compilers/dsl → dsl/compilers}/sidekiq_worker.rb +14 -13
  38. data/lib/tapioca/{compilers/dsl → dsl/compilers}/smart_properties.rb +12 -13
  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/gemfile.rb +44 -20
  64. data/lib/tapioca/helpers/cli_helper.rb +16 -8
  65. data/lib/tapioca/helpers/config_helper.rb +113 -0
  66. data/lib/tapioca/helpers/rbi_helper.rb +17 -0
  67. data/lib/tapioca/helpers/shims_helper.rb +87 -0
  68. data/lib/tapioca/helpers/sorbet_helper.rb +57 -0
  69. data/lib/tapioca/helpers/test/dsl_compiler.rb +118 -0
  70. data/lib/tapioca/helpers/test/isolation.rb +1 -1
  71. data/lib/tapioca/helpers/test/template.rb +13 -2
  72. data/lib/tapioca/internal.rb +17 -10
  73. data/lib/tapioca/rbi_ext/model.rb +2 -48
  74. data/lib/tapioca/rbi_formatter.rb +37 -0
  75. data/lib/tapioca/runtime/dynamic_mixin_compiler.rb +227 -0
  76. data/lib/tapioca/runtime/generic_type_registry.rb +166 -0
  77. data/lib/tapioca/runtime/loader.rb +123 -0
  78. data/lib/tapioca/runtime/reflection.rb +153 -0
  79. data/lib/tapioca/runtime/trackers/autoload.rb +72 -0
  80. data/lib/tapioca/runtime/trackers/constant_definition.rb +44 -0
  81. data/lib/tapioca/runtime/trackers/mixin.rb +80 -0
  82. data/lib/tapioca/runtime/trackers/required_ancestor.rb +50 -0
  83. data/lib/tapioca/{trackers.rb → runtime/trackers.rb} +4 -3
  84. data/lib/tapioca/sorbet_ext/generic_name_patch.rb +110 -54
  85. data/lib/tapioca/sorbet_ext/name_patch.rb +7 -1
  86. data/lib/tapioca/{compilers → static}/requires_compiler.rb +5 -12
  87. data/lib/tapioca/static/symbol_loader.rb +83 -0
  88. data/lib/tapioca/static/symbol_table_parser.rb +63 -0
  89. data/lib/tapioca/version.rb +1 -1
  90. data/lib/tapioca.rb +2 -7
  91. metadata +82 -62
  92. data/lib/tapioca/compilers/dsl/active_record_relations.rb +0 -711
  93. data/lib/tapioca/compilers/dsl/base.rb +0 -179
  94. data/lib/tapioca/compilers/dsl/helper/active_record_constants.rb +0 -27
  95. data/lib/tapioca/compilers/dynamic_mixin_compiler.rb +0 -198
  96. data/lib/tapioca/compilers/sorbet.rb +0 -59
  97. data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +0 -780
  98. data/lib/tapioca/compilers/symbol_table/symbol_loader.rb +0 -90
  99. data/lib/tapioca/compilers/symbol_table_compiler.rb +0 -17
  100. data/lib/tapioca/compilers/todos_compiler.rb +0 -32
  101. data/lib/tapioca/generators/todo.rb +0 -76
  102. data/lib/tapioca/generators.rb +0 -9
  103. data/lib/tapioca/generic_type_registry.rb +0 -149
  104. data/lib/tapioca/helpers/active_record_column_type_helper.rb +0 -98
  105. data/lib/tapioca/loader.rb +0 -119
  106. data/lib/tapioca/reflection.rb +0 -151
  107. data/lib/tapioca/trackers/autoload.rb +0 -70
  108. data/lib/tapioca/trackers/constant_definition.rb +0 -42
  109. data/lib/tapioca/trackers/mixin.rb +0 -78
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4eea2d365ede4ba5398d65a2042c7dc86270ec7309cb0bc9747357f44ea1c675
4
- data.tar.gz: 7f7252a0619b138664fe5d30acf0858fb09eb9403d513a06266cc58c464dd3b2
3
+ metadata.gz: ef378ec3f3035d85d6aebfa4624896d216bcccd7d9332cbdc9d64be469b79b48
4
+ data.tar.gz: 2f34d64fadd075ed1653ec26d27c73a02bfff949440fc6d1fd8bf80116161b48
5
5
  SHA512:
6
- metadata.gz: 1ac4530bd50af56e2acee0a630571dbc7452cf10e55ec89088ddb5ed8f9a350fae0b4031602fa13b5b319390172e55bdebe6a3d3b6a722e88fe7902aceb5bb61
7
- data.tar.gz: 26a6365606966861c36ffcea2b247a7dfc5395925d04a9d89f35273ce6ae9c3f29ee3d94002c3dd49c46f05acda9e202025a79cf9e4dd0fbebe49ff542d575ae
6
+ metadata.gz: 78b6ce07ee08391457763a8e9069b0ff0efaa1be26cdeec7f334d2b45afa6ec12fd152d24c42d4c2b6834db25af77f74d6401bf577fd749ed446ef122dc01161
7
+ data.tar.gz: 0b1998a9a72153d24747838606ff636cf8718efc67aa98e0c9d3ff01849d677840cd73f0adb8f289cc8c6f7e07b20bd37594bbcd1aea1b91761132fd07a1a9db
data/Gemfile CHANGED
@@ -10,6 +10,7 @@ gem("minitest-reporters")
10
10
  gem("pry-byebug")
11
11
  gem("rubocop-shopify", require: false)
12
12
  gem("rubocop-sorbet", ">= 0.4.1")
13
+ gem("rubocop-rspec", require: false)
13
14
  gem("sorbet")
14
15
 
15
16
  group(:deployment, :development) do
@@ -25,8 +26,12 @@ group(:development, :test) do
25
26
  gem("activerecord-typedstore", require: false)
26
27
  gem("sqlite3")
27
28
  gem("identity_cache", require: false)
28
- gem("cityhash", git: "https://github.com/csfrancis/cityhash.git",
29
- ref: "3cfc7d01f333c01811d5e834f1495eaa29f87c36", require: false)
29
+ gem(
30
+ "cityhash",
31
+ git: "https://github.com/csfrancis/cityhash.git",
32
+ ref: "3cfc7d01f333c01811d5e834f1495eaa29f87c36",
33
+ require: false
34
+ )
30
35
  gem("activeresource", require: false)
31
36
  gem("google-protobuf", require: false)
32
37
  gem("shopify-money", require: false)
@@ -36,4 +41,10 @@ group(:development, :test) do
36
41
  gem("aasm", require: false)
37
42
  gem("bcrypt", require: false)
38
43
  gem("xpath", require: false)
44
+ gem("rubocop-lsp", require: false)
45
+
46
+ # net-smtp was removed from default gems in Ruby 3.1, but is used by the `mail` gem.
47
+ # So we need to add it as a dependency until `mail` is fixed:
48
+ # https://github.com/rails/rails/blob/0919aa97260ab8240150278d3b07a1547489e3fd/Gemfile#L178-L191
49
+ gem("net-smtp", "0.3.1", require: false)
39
50
  end
data/README.md CHANGED
@@ -80,8 +80,8 @@ Command: `tapioca init`
80
80
 
81
81
  This will create the `sorbet/config` and `sorbet/tapioca/require.rb` files for you, if they don't exist. If any of the files already exist, they will not be changed.
82
82
 
83
+ <!-- START_HELP_COMMAND_INIT -->
83
84
  ```shell
84
- $ bundle exec tapioca help init
85
85
  Usage:
86
86
  tapioca init
87
87
 
@@ -92,6 +92,7 @@ Options:
92
92
 
93
93
  initializes folder structure
94
94
  ```
95
+ <!-- END_HELP_COMMAND_INIT -->
95
96
 
96
97
  ### Generate RBI files for gems
97
98
 
@@ -99,13 +100,13 @@ Command: `tapioca gem [gems...]`
99
100
 
100
101
  This will generate RBIs for the specified gems and place them in the RBI directory.
101
102
 
103
+ <!-- START_HELP_COMMAND_GEM -->
102
104
  ```shell
103
- $ bundle exec tapioca help gem
104
105
  Usage:
105
106
  tapioca gem [gem...]
106
107
 
107
108
  Options:
108
- --out, -o, [--outdir=directory] # The output directory for generated RBI files
109
+ --out, -o, [--outdir=directory] # The output directory for generated gem RBI files
109
110
  # Default: sorbet/rbi/gems
110
111
  [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
111
112
  # Default: true
@@ -113,21 +114,28 @@ Options:
113
114
  --pre, -b, [--prerequire=file] # A file to be required before Bundler.require is called
114
115
  --post, -a, [--postrequire=file] # A file to be required after Bundler.require is called
115
116
  # Default: sorbet/tapioca/require.rb
116
- -x, [--exclude=gem [gem ...]] # Excludes the given gem(s) from RBI generation
117
- --typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Overrides for typed sigils for generated gem RBIs
117
+ -x, [--exclude=gem [gem ...]] # Exclude the given gem(s) from RBI generation
118
+ --typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Override for typed sigils for generated gem RBIs
118
119
  # Default: {"activesupport"=>"false"}
119
- [--verify], [--no-verify] # Verifies RBIs are up-to-date
120
+ [--verify], [--no-verify] # Verify RBIs are up-to-date
120
121
  [--doc], [--no-doc] # Include YARD documentation from sources when generating RBIs. Warning: this might be slow
121
122
  [--exported-gem-rbis], [--no-exported-gem-rbis] # Include RBIs found in the `rbi/` directory of the gem
122
123
  # Default: true
123
124
  -w, [--workers=N] # EXPERIMENTAL: Number of parallel workers to use when generating RBIs
124
125
  # Default: 1
126
+ [--auto-strictness], [--no-auto-strictness] # Autocorrect strictness in gem RBIs in case of conflict with the DSL RBIs
127
+ # Default: true
128
+ --dsl-dir, [--dsl-dir=directory] # The DSL directory used to correct gems strictnesses
129
+ # Default: sorbet/rbi/dsl
130
+ [--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
131
+ # Default: 120
125
132
  -c, [--config=<config file path>] # Path to the Tapioca configuration file
126
133
  # Default: sorbet/tapioca/config.yml
127
134
  -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
128
135
 
129
136
  generate RBIs from gems
130
137
  ```
138
+ <!-- END_HELP_COMMAND_GEM -->
131
139
 
132
140
  ### Generate the list of all unresolved constants
133
141
 
@@ -135,13 +143,13 @@ Command: `tapioca todo`
135
143
 
136
144
  This will generate the file `sorbet/rbi/todo.rbi` defining all unresolved constants as empty modules.
137
145
 
146
+ <!-- START_HELP_COMMAND_TODO -->
138
147
  ```shell
139
- $ bundle exec tapioca help todo
140
148
  Usage:
141
149
  tapioca todo
142
150
 
143
151
  Options:
144
- [--todo-file=TODO_FILE]
152
+ [--todo-file=TODO_FILE] # Path to the generated todo RBI file
145
153
  # Default: sorbet/rbi/todo.rbi
146
154
  [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
147
155
  # Default: true
@@ -151,35 +159,40 @@ Options:
151
159
 
152
160
  generate the list of unresolved constants
153
161
  ```
162
+ <!-- END_HELP_COMMAND_TODO -->
154
163
 
155
164
  ### Generate DSL RBI files
156
165
 
157
166
  Command: `tapioca dsl [constant...]`
158
167
 
159
- This will generate DSL RBIs for specified constants (or for all handled constants, if a constant name is not supplied). You can read about DSL RBI generators supplied by `tapioca` in [the manual](manual/generators.md).
168
+ This will generate DSL RBIs for specified constants (or for all handled constants, if a constant name is not supplied). You can read about DSL RBI compilers supplied by `tapioca` in [the manual](manual/compilers.md).
160
169
 
170
+ <!-- START_HELP_COMMAND_DSL -->
161
171
  ```shell
162
- $ bundle exec tapioca help dsl
163
172
  Usage:
164
173
  tapioca dsl [constant...]
165
174
 
166
175
  Options:
167
- --out, -o, [--outdir=directory] # The output directory for generated RBI files
168
- # Default: sorbet/rbi/dsl
169
- [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
170
- # Default: true
171
- [--only=generator [generator ...]] # Only run supplied DSL generators
172
- [--exclude=generator [generator ...]] # Exclude supplied DSL generators
173
- [--verify], [--no-verify] # Verifies RBIs are up-to-date
174
- -q, [--quiet], [--no-quiet] # Supresses file creation output
175
- -w, [--workers=N] # EXPERIMENTAL: Number of parallel workers to use when generating RBIs
176
- # Default: 1
177
- -c, [--config=<config file path>] # Path to the Tapioca configuration file
178
- # Default: sorbet/tapioca/config.yml
179
- -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
176
+ --out, -o, [--outdir=directory] # The output directory for generated DSL RBI files
177
+ # Default: sorbet/rbi/dsl
178
+ [--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
179
+ # Default: true
180
+ [--only=compiler [compiler ...]] # Only run supplied DSL compiler(s)
181
+ [--exclude=compiler [compiler ...]] # Exclude supplied DSL compiler(s)
182
+ [--verify], [--no-verify] # Verifies RBIs are up-to-date
183
+ -q, [--quiet], [--no-quiet] # Supresses file creation output
184
+ -w, [--workers=N] # EXPERIMENTAL: Number of parallel workers to use when generating RBIs
185
+ # Default: 1
186
+ [--rbi-max-line-length=N] # Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped
187
+ # Default: 120
188
+ -c, [--config=<config file path>] # Path to the Tapioca configuration file
189
+ # Default: sorbet/tapioca/config.yml
190
+ -V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
180
191
 
181
192
  generate RBIs for dynamic methods
182
193
  ```
194
+ <!-- END_HELP_COMMAND_DSL -->
195
+
183
196
  ## Configuration
184
197
 
185
198
  Tapioca supports loading command defaults from a configuration file. The default configuration
@@ -192,20 +205,61 @@ For example, if you always want to generate gem RBIs with inline documentation,
192
205
 
193
206
  ```yaml
194
207
  gem:
195
- docs: true
208
+ doc: true
196
209
  ```
197
210
 
198
211
  Additionally, if you always want to exclude the `AASM` and `ActiveRecordFixtures` DSL compilers in your DSL RBI generation runs, your config file would then look like this:
199
212
 
200
213
  ```yaml
201
214
  gem:
202
- docs: true
215
+ doc: true
203
216
  dsl:
204
217
  exclude:
205
218
  - UrlHelpers
206
219
  - ActiveRecordFixtures
207
220
  ```
208
221
 
222
+ The full configuration file, with each option and its default value, would look something like this:
223
+ <!-- START_CONFIG_TEMPLATE -->
224
+ ```yaml
225
+ ---
226
+ require:
227
+ postrequire: sorbet/tapioca/require.rb
228
+ todo:
229
+ todo_file: sorbet/rbi/todo.rbi
230
+ file_header: true
231
+ dsl:
232
+ outdir: sorbet/rbi/dsl
233
+ file_header: true
234
+ only: []
235
+ exclude: []
236
+ verify: false
237
+ quiet: false
238
+ workers: 1
239
+ rbi_max_line_length: 120
240
+ gem:
241
+ outdir: sorbet/rbi/gems
242
+ file_header: true
243
+ all: false
244
+ prerequire: ''
245
+ postrequire: sorbet/tapioca/require.rb
246
+ exclude: []
247
+ typed_overrides:
248
+ activesupport: 'false'
249
+ verify: false
250
+ doc: false
251
+ exported_gem_rbis: true
252
+ workers: 1
253
+ auto_strictness: true
254
+ dsl_dir: sorbet/rbi/dsl
255
+ rbi_max_line_length: 120
256
+ check_shims:
257
+ gem_rbi_dir: sorbet/rbi/gems
258
+ dsl_rbi_dir: sorbet/rbi/dsl
259
+ shim_rbi_dir: sorbet/rbi/shims
260
+ ```
261
+ <!-- END_CONFIG_TEMPLATE -->
262
+
209
263
  ## Contributing
210
264
 
211
265
  Bug reports and pull requests are welcome on GitHub at https://github.com/Shopify/tapioca. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](https://github.com/Shopify/tapioca/blob/main/CODE_OF_CONDUCT.md) code of conduct.
data/Rakefile CHANGED
@@ -1,22 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
- require "rake/testtask"
5
4
  Dir["tasks/**/*.rake"].each { |t| load t }
6
5
 
7
- Rake.application.options.trace = false
6
+ require "rubocop/rake_task"
7
+ RuboCop::RakeTask.new
8
8
 
9
- Rake::TestTask.new do |t|
10
- t.libs << "lib"
11
- t.libs << "spec"
12
- t.warning = false
13
- t.test_files = FileList["spec/**/*_spec.rb"]
9
+ desc "Run tests"
10
+ task :test do
11
+ require "shellwords"
12
+ test = Array(ENV.fetch("TEST", []))
13
+ test_opts = Shellwords.split(ENV.fetch("TESTOPTS", ""))
14
+ success = system("bin/test", *test, *test_opts)
15
+ success || exit(false)
14
16
  end
15
17
 
16
- task(:spec) do
17
- Rake::Task[:test].execute
18
- rescue RuntimeError
19
- exit(1)
20
- end
21
-
22
- task(default: :spec)
18
+ task(default: :test)
data/lib/tapioca/cli.rb CHANGED
@@ -5,6 +5,7 @@ module Tapioca
5
5
  class Cli < Thor
6
6
  include CliHelper
7
7
  include ConfigHelper
8
+ include ShimsHelper
8
9
 
9
10
  FILE_HEADER_OPTION_DESC = "Add a \"This file is generated\" header on top of each generated RBI file"
10
11
 
@@ -22,44 +23,42 @@ module Tapioca
22
23
 
23
24
  desc "init", "initializes folder structure"
24
25
  def init
25
- generator = Generators::Init.new(
26
+ command = Commands::Init.new(
26
27
  sorbet_config: SORBET_CONFIG_FILE,
27
28
  tapioca_config: TAPIOCA_CONFIG_FILE,
28
- default_postrequire: DEFAULT_POSTREQUIRE_FILE,
29
- default_command: DEFAULT_COMMAND
29
+ default_postrequire: DEFAULT_POSTREQUIRE_FILE
30
30
  )
31
- generator.generate
31
+ command.execute
32
32
  end
33
33
 
34
34
  desc "require", "generate the list of files to be required by tapioca"
35
35
  option :postrequire, type: :string, default: DEFAULT_POSTREQUIRE_FILE
36
36
  def require
37
- generator = Generators::Require.new(
37
+ command = Commands::Require.new(
38
38
  requires_path: options[:postrequire],
39
- sorbet_config_path: SORBET_CONFIG_FILE,
40
- default_command: DEFAULT_COMMAND
39
+ sorbet_config_path: SORBET_CONFIG_FILE
41
40
  )
42
41
  Tapioca.silence_warnings do
43
- generator.generate
42
+ command.execute
44
43
  end
45
44
  end
46
45
 
47
46
  desc "todo", "generate the list of unresolved constants"
48
47
  option :todo_file,
49
48
  type: :string,
49
+ desc: "Path to the generated todo RBI file",
50
50
  default: DEFAULT_TODO_FILE
51
51
  option :file_header,
52
52
  type: :boolean,
53
53
  desc: FILE_HEADER_OPTION_DESC,
54
54
  default: true
55
55
  def todo
56
- generator = Generators::Todo.new(
56
+ command = Commands::Todo.new(
57
57
  todo_file: options[:todo_file],
58
- file_header: options[:file_header],
59
- default_command: DEFAULT_COMMAND
58
+ file_header: options[:file_header]
60
59
  )
61
60
  Tapioca.silence_warnings do
62
- generator.generate
61
+ command.execute
63
62
  end
64
63
  end
65
64
 
@@ -75,13 +74,13 @@ module Tapioca
75
74
  default: true
76
75
  option :only,
77
76
  type: :array,
78
- banner: "generator [generator ...]",
79
- desc: "Only run supplied DSL generator(s)",
77
+ banner: "compiler [compiler ...]",
78
+ desc: "Only run supplied DSL compiler(s)",
80
79
  default: []
81
80
  option :exclude,
82
81
  type: :array,
83
- banner: "generator [generator ...]",
84
- desc: "Exclude supplied DSL generator(s)",
82
+ banner: "compiler [compiler ...]",
83
+ desc: "Exclude supplied DSL compiler(s)",
85
84
  default: []
86
85
  option :verify,
87
86
  type: :boolean,
@@ -97,20 +96,24 @@ module Tapioca
97
96
  type: :numeric,
98
97
  desc: "EXPERIMENTAL: Number of parallel workers to use when generating RBIs",
99
98
  default: 1
99
+ option :rbi_max_line_length,
100
+ type: :numeric,
101
+ desc: "Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped",
102
+ default: 120
100
103
  def dsl(*constants)
101
- generator = Generators::Dsl.new(
104
+ command = Commands::Dsl.new(
102
105
  requested_constants: constants,
103
106
  outpath: Pathname.new(options[:outdir]),
104
107
  only: options[:only],
105
108
  exclude: options[:exclude],
106
109
  file_header: options[:file_header],
107
- compiler_path: Tapioca::Compilers::Dsl::DSL_COMPILERS_DIR,
110
+ compiler_path: Tapioca::Dsl::Compilers::DIRECTORY,
108
111
  tapioca_path: TAPIOCA_DIR,
109
- default_command: DEFAULT_COMMAND,
110
112
  should_verify: options[:verify],
111
113
  quiet: options[:quiet],
112
114
  verbose: options[:verbose],
113
- number_of_workers: options[:workers]
115
+ number_of_workers: options[:workers],
116
+ rbi_formatter: rbi_formatter(options)
114
117
  )
115
118
 
116
119
  if options[:workers] != 1
@@ -121,7 +124,7 @@ module Tapioca
121
124
  end
122
125
 
123
126
  Tapioca.silence_warnings do
124
- generator.generate
127
+ command.execute
125
128
  end
126
129
  end
127
130
 
@@ -178,23 +181,38 @@ module Tapioca
178
181
  type: :numeric,
179
182
  desc: "EXPERIMENTAL: Number of parallel workers to use when generating RBIs",
180
183
  default: 1
184
+ option :auto_strictness,
185
+ type: :boolean,
186
+ desc: "Autocorrect strictness in gem RBIs in case of conflict with the DSL RBIs",
187
+ default: true
188
+ option :dsl_dir,
189
+ aliases: ["--dsl-dir"],
190
+ banner: "directory",
191
+ desc: "The DSL directory used to correct gems strictnesses",
192
+ default: DEFAULT_DSL_DIR
193
+ option :rbi_max_line_length,
194
+ type: :numeric,
195
+ desc: "Set the max line length of generated RBIs. Signatures longer than the max line length will be wrapped",
196
+ default: 120
181
197
  def gem(*gems)
182
198
  Tapioca.silence_warnings do
183
199
  all = options[:all]
184
200
  verify = options[:verify]
185
201
 
186
- generator = Generators::Gem.new(
202
+ command = Commands::Gem.new(
187
203
  gem_names: all ? [] : gems,
188
204
  exclude: options[:exclude],
189
205
  prerequire: options[:prerequire],
190
206
  postrequire: options[:postrequire],
191
207
  typed_overrides: options[:typed_overrides],
192
- default_command: DEFAULT_COMMAND,
193
208
  outpath: Pathname.new(options[:outdir]),
194
209
  file_header: options[:file_header],
195
210
  doc: options[:doc],
196
211
  include_exported_rbis: options[:exported_gem_rbis],
197
- number_of_workers: options[:workers]
212
+ number_of_workers: options[:workers],
213
+ auto_strictness: options[:auto_strictness],
214
+ dsl_dir: options[:dsl_dir],
215
+ rbi_formatter: rbi_formatter(options)
198
216
  )
199
217
 
200
218
  raise MalformattedArgumentError, "Options '--all' and '--verify' are mutually exclusive" if all && verify
@@ -212,80 +230,48 @@ module Tapioca
212
230
  end
213
231
 
214
232
  if gems.empty? && !all
215
- generator.sync(should_verify: verify)
233
+ command.sync(should_verify: verify)
216
234
  else
217
- generator.generate
235
+ command.execute
218
236
  end
219
237
  end
220
238
  end
239
+ map "gems" => :gem
221
240
 
222
- desc "clean-shims", "clean duplicated definitions in shim RBIs"
241
+ desc "check-shims", "check duplicated definitions in shim RBIs"
223
242
  option :gem_rbi_dir, type: :string, desc: "Path to gem RBIs", default: DEFAULT_GEM_DIR
224
243
  option :dsl_rbi_dir, type: :string, desc: "Path to DSL RBIs", default: DEFAULT_DSL_DIR
225
244
  option :shim_rbi_dir, type: :string, desc: "Path to shim RBIs", default: DEFAULT_SHIM_DIR
226
- def clean_shims(*files_to_clean)
245
+ def check_shims
227
246
  index = RBI::Index.new
228
247
 
229
- # Index gem RBIs
230
- gem_rbi_dir = options[:gem_rbi_dir]
231
- say("Loading gem RBIs from #{gem_rbi_dir}... ")
232
- gem_rbis_files = Dir.glob("#{gem_rbi_dir}/**/*.rbi").sort
233
- gem_rbis_trees = RBI::Parser.parse_files(gem_rbis_files)
234
- index.visit_all(gem_rbis_trees)
235
- say(" Done", :green)
236
-
237
- # Index dsl RBIs
238
- dsl_rbi_dir = options[:dsl_rbi_dir]
239
- say("Loading dsl RBIs from #{dsl_rbi_dir}... ")
240
- dsl_rbis_files = Dir.glob("#{dsl_rbi_dir}/**/*.rbi").sort
241
- dsl_rbis_trees = RBI::Parser.parse_files(dsl_rbis_files)
242
- index.visit_all(dsl_rbis_trees)
243
- say(" Done", :green)
244
-
245
- # Clean shim RBIs
246
- if files_to_clean.empty?
247
- shim_rbi_dir = options[:shim_rbi_dir]
248
- print("Cleaning shim RBIs from #{shim_rbi_dir}...")
249
- files_to_clean = Dir.glob("#{shim_rbi_dir}/*.rbi")
250
- else
251
- print("Cleaning shim RBIs...")
248
+ shim_rbi_dir = options[:shim_rbi_dir]
249
+ if !Dir.exist?(shim_rbi_dir) || Dir.empty?(shim_rbi_dir)
250
+ say("No shim RBIs to check", :green)
251
+ exit(0)
252
252
  end
253
253
 
254
- done_something = T.let(false, T::Boolean)
255
- files_to_clean.sort.each do |path|
256
- original = RBI::Parser.parse_file(path)
257
- cleaned, operations = RBI::Rewriters::RemoveKnownDefinitions.remove(original, index)
254
+ index_rbis(index, "shim", shim_rbi_dir)
255
+ index_rbis(index, "gem", options[:gem_rbi_dir])
256
+ index_rbis(index, "dsl", options[:dsl_rbi_dir])
258
257
 
259
- next if operations.empty?
260
- done_something = true
261
-
262
- operations.each do |operation|
263
- print("\n #{operation}")
264
- end
265
-
266
- if cleaned.empty?
267
- print("\n Deleted empty file #{path}")
268
- FileUtils.rm(path)
269
- else
270
- File.write(path, cleaned.string)
258
+ duplicates = duplicated_nodes_from_index(index, shim_rbi_dir)
259
+ unless duplicates.empty?
260
+ duplicates.each do |key, nodes|
261
+ say_error("\nDuplicated RBI for #{key}:", :red)
262
+ nodes.each do |node|
263
+ say_error(" * #{node.loc}", :red)
264
+ end
271
265
  end
266
+ say_error("\nPlease remove the duplicated definitions from the #{shim_rbi_dir} directory.", :red)
267
+ exit(1)
272
268
  end
273
269
 
274
- if done_something
275
- say("\nDone", :green)
276
- else
277
- say(" Done ", :green)
278
- say("(nothing to do)", :yellow)
279
- end
280
- rescue Errno::ENOENT => e
281
- say_error("\nCan't read RBI: #{e}")
282
- exit(1)
283
- rescue RBI::ParseError => e
284
- say_error("\nCan't parse RBI: #{e} (#{e.location})")
285
- exit(1)
270
+ say("\nNo duplicates found in shim RBIs", :green)
271
+ exit(0)
286
272
  end
287
273
 
288
- map T.unsafe(["--version", "-v"] => :__print_version)
274
+ map ["--version", "-v"] => :__print_version
289
275
 
290
276
  desc "--version, -v", "show version"
291
277
  def __print_version
@@ -2,8 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- module Generators
6
- class Base
5
+ module Commands
6
+ class Command
7
7
  extend T::Sig
8
8
  extend T::Helpers
9
9
 
@@ -11,22 +11,29 @@ module Tapioca
11
11
  include Thor::Actions
12
12
  end
13
13
 
14
- include CliHelper
15
14
  include Thor::Base
15
+ include CliHelper
16
16
 
17
17
  abstract!
18
18
 
19
- sig { params(default_command: String, file_writer: Thor::Actions).void }
20
- def initialize(default_command:, file_writer: FileWriter.new)
21
- @file_writer = file_writer
22
- @default_command = default_command
19
+ sig { void }
20
+ def initialize
21
+ @file_writer = T.let(FileWriter.new, Thor::Actions)
23
22
  end
24
23
 
25
24
  sig { abstract.void }
26
- def generate; end
25
+ def execute; end
27
26
 
28
27
  private
29
28
 
29
+ sig { params(command: Symbol, args: String).returns(String) }
30
+ def default_command(command, *args)
31
+ [Tapioca::BINARY_FILE, command.to_s, *args].join(" ")
32
+ end
33
+
34
+ sig { returns(Thor::Actions) }
35
+ attr_reader :file_writer
36
+
30
37
  sig do
31
38
  params(
32
39
  path: T.any(String, Pathname),
@@ -37,7 +44,7 @@ module Tapioca
37
44
  ).void
38
45
  end
39
46
  def create_file(path, content, force: true, skip: false, verbose: true)
40
- @file_writer.create_file(path, force: force, skip: skip, verbose: verbose) { content }
47
+ file_writer.create_file(path, force: force, skip: skip, verbose: verbose) { content }
41
48
  end
42
49
 
43
50
  sig do
@@ -47,7 +54,7 @@ module Tapioca
47
54
  ).void
48
55
  end
49
56
  def remove_file(path, verbose: true)
50
- @file_writer.remove_file(path, verbose: verbose)
57
+ file_writer.remove_file(path, verbose: verbose)
51
58
  end
52
59
  end
53
60
  end