tapioca 0.5.3 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +114 -23
- data/lib/tapioca/cli.rb +188 -65
- data/lib/tapioca/compilers/dsl/active_record_associations.rb +94 -8
- data/lib/tapioca/compilers/dsl/active_record_columns.rb +5 -4
- data/lib/tapioca/compilers/dsl/active_record_enum.rb +1 -1
- data/lib/tapioca/compilers/dsl/active_record_relations.rb +703 -0
- data/lib/tapioca/compilers/dsl/active_record_scope.rb +43 -13
- data/lib/tapioca/compilers/dsl/active_record_typed_store.rb +39 -33
- data/lib/tapioca/compilers/dsl/base.rb +26 -42
- data/lib/tapioca/compilers/dsl/extensions/frozen_record.rb +29 -0
- data/lib/tapioca/compilers/dsl/frozen_record.rb +37 -0
- data/lib/tapioca/compilers/dsl/helper/active_record_constants.rb +27 -0
- data/lib/tapioca/compilers/dsl/identity_cache.rb +0 -1
- data/lib/tapioca/compilers/dsl/param_helper.rb +52 -0
- data/lib/tapioca/compilers/dsl/rails_generators.rb +120 -0
- data/lib/tapioca/compilers/dsl_compiler.rb +34 -6
- data/lib/tapioca/compilers/sorbet.rb +2 -0
- data/lib/tapioca/compilers/symbol_table/symbol_generator.rb +51 -48
- data/lib/tapioca/executor.rb +79 -0
- data/lib/tapioca/gemfile.rb +28 -4
- data/lib/tapioca/generators/base.rb +11 -18
- data/lib/tapioca/generators/dsl.rb +33 -38
- data/lib/tapioca/generators/gem.rb +64 -34
- data/lib/tapioca/generators/init.rb +41 -16
- data/lib/tapioca/generators/todo.rb +6 -6
- data/lib/tapioca/helpers/cli_helper.rb +26 -0
- data/lib/tapioca/helpers/config_helper.rb +84 -0
- data/lib/tapioca/helpers/test/content.rb +51 -0
- data/lib/tapioca/helpers/test/isolation.rb +125 -0
- data/lib/tapioca/helpers/test/template.rb +34 -0
- data/lib/tapioca/internal.rb +3 -2
- data/lib/tapioca/rbi_ext/model.rb +13 -10
- data/lib/tapioca/reflection.rb +13 -0
- data/lib/tapioca/trackers/autoload.rb +70 -0
- data/lib/tapioca/trackers/constant_definition.rb +42 -0
- data/lib/tapioca/trackers/mixin.rb +78 -0
- data/lib/tapioca/trackers.rb +14 -0
- data/lib/tapioca/version.rb +1 -1
- data/lib/tapioca.rb +28 -2
- metadata +37 -13
- data/lib/tapioca/config.rb +0 -45
- data/lib/tapioca/config_builder.rb +0 -73
- data/lib/tapioca/constant_locator.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a99e7a4475e2991e305c461774e45e128d430632e96581fc541680b61275e4e1
|
4
|
+
data.tar.gz: 8ee7b9b225dd752edf606a98aee1b8490687f351dae642b24060549740d2ab5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ab85b1422fba3aa79de02fad9e164b2013cef3a388ad196e4c11f0c2c6dc142b6a540a430f4a4ace9f3ebe92da2f29fbe733e13ceb481277e7d7e2691db9f0c
|
7
|
+
data.tar.gz: b9f2c2cca77916e08fcbb1ca021818b51bc5edd8d899b2f5e89dae3bfddd38dd8e403b16bacd8c8db37dc630448458d7d6f52e6445cb9ecb96c6bba16c4c20e7
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ Tapioca is a library used to generate RBI (Ruby interface) files for use with [S
|
|
8
8
|
|
9
9
|
As yet, no gem exports type information in a consumable format and it would be a huge effort to manually maintain such an interface file for all the gems that your codebase depends on. Thus, there is a need for an automated way to generate the appropriate RBI file for a given gem. The `tapioca` gem, developed at Shopify, is able to do exactly that to almost 99% accuracy. It can generate the definitions for all statically defined types and most of the runtime defined types exported from Ruby gems (non-Ruby gems are not handled yet).
|
10
10
|
|
11
|
-
When you run `tapioca
|
11
|
+
When you run `tapioca gem` in a project, `tapioca` loads all the gems that are in your dependency list from the Gemfile into memory. It then performs runtime introspection on the loaded types to understand their structure and generates an appropriate RBI file for each gem with a versioned filename.
|
12
12
|
|
13
13
|
## Manual gem requires
|
14
14
|
|
@@ -33,7 +33,7 @@ from (pry):3:in `__pry__`
|
|
33
33
|
|
34
34
|
In order to make sure that `tapioca` can reflect on that type, we need to add the line `require "better_html/parser"` to the `sorbet/tapioca/require.rb` file. This will make sure `BetterHtml::Parser` is loaded into memory and a type annotation is generated for it in the `better_html.rbi` file. If this extra `require` line is not added to `sorbet/tapioca/require.rb` file, then the definition for that type will be missing from the RBI file.
|
35
35
|
|
36
|
-
If you ever run into a case, where you add a gem or update the version of a gem and run `tapioca
|
36
|
+
If you ever run into a case, where you add a gem or update the version of a gem and run `tapioca gem` but don't have some types you expect in the generated gem RBI files, you will need to make sure you have added the necessary requires to the `sorbet/tapioca/require.rb` file.
|
37
37
|
|
38
38
|
You can use the command `tapioca require` to auto-populate the `sorbet/tapioca/require.rb` file with all the requires found
|
39
39
|
in your application. Once the file generated, you should review it, remove all unnecessary requires and commit it.
|
@@ -55,24 +55,21 @@ end
|
|
55
55
|
and do not forget to execute `tapioca` using `bundler`:
|
56
56
|
|
57
57
|
```shell
|
58
|
-
$ bundle exec tapioca
|
58
|
+
$ bundle exec tapioca help
|
59
59
|
Commands:
|
60
60
|
tapioca --version, -v # show version
|
61
|
+
tapioca clean-shims # clean duplicated definitions in shim RBIs
|
61
62
|
tapioca dsl [constant...] # generate RBIs for dynamic methods
|
62
|
-
tapioca
|
63
|
+
tapioca gem [gem...] # generate RBIs from gems
|
63
64
|
tapioca help [COMMAND] # Describe available commands or one specific command
|
64
65
|
tapioca init # initializes folder structure
|
65
66
|
tapioca require # generate the list of files to be required by tapioca
|
66
|
-
tapioca sync # sync RBIs to Gemfile
|
67
67
|
tapioca todo # generate the list of unresolved constants
|
68
68
|
|
69
69
|
Options:
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
--cmd, -c, [--generate-command=command] # The command to run to regenerate RBI files
|
74
|
-
-x, [--exclude=gem [gem ...]] # Excludes the given gem(s) from RBI generation
|
75
|
-
--typed, -t, [--typed-overrides=gem:level [gem:level ...]] # Overrides for typed sigils for generated gem RBIs
|
70
|
+
-c, [--config=<config file path>] # Path to the Tapioca configuration file
|
71
|
+
# Default: sorbet/tapioca/config.yml
|
72
|
+
-V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
|
76
73
|
```
|
77
74
|
|
78
75
|
## Usage
|
@@ -83,17 +80,54 @@ Command: `tapioca init`
|
|
83
80
|
|
84
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.
|
85
82
|
|
86
|
-
|
83
|
+
```shell
|
84
|
+
$ bundle exec tapioca help init
|
85
|
+
Usage:
|
86
|
+
tapioca init
|
87
87
|
|
88
|
-
|
88
|
+
Options:
|
89
|
+
-c, [--config=<config file path>] # Path to the Tapioca configuration file
|
90
|
+
# Default: sorbet/tapioca/config.yml
|
91
|
+
-V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
|
89
92
|
|
90
|
-
|
93
|
+
initializes folder structure
|
94
|
+
```
|
91
95
|
|
92
|
-
### Generate for
|
96
|
+
### Generate RBI files for gems
|
93
97
|
|
94
|
-
Command: `tapioca
|
98
|
+
Command: `tapioca gem [gems...]`
|
95
99
|
|
96
|
-
This will
|
100
|
+
This will generate RBIs for the specified gems and place them in the RBI directory.
|
101
|
+
|
102
|
+
```shell
|
103
|
+
$ bundle exec tapioca help gem
|
104
|
+
Usage:
|
105
|
+
tapioca gem [gem...]
|
106
|
+
|
107
|
+
Options:
|
108
|
+
--out, -o, [--outdir=directory] # The output directory for generated RBI files
|
109
|
+
# Default: sorbet/rbi/gems
|
110
|
+
[--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
|
111
|
+
# Default: true
|
112
|
+
[--all], [--no-all] # Regenerate RBI files for all gems
|
113
|
+
--pre, -b, [--prerequire=file] # A file to be required before Bundler.require is called
|
114
|
+
--post, -a, [--postrequire=file] # A file to be required after Bundler.require is called
|
115
|
+
# 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
|
118
|
+
# Default: {"activesupport"=>"false"}
|
119
|
+
[--verify], [--no-verify] # Verifies RBIs are up-to-date
|
120
|
+
[--doc], [--no-doc] # Include YARD documentation from sources when generating RBIs. Warning: this might be slow
|
121
|
+
[--exported-gem-rbis], [--no-exported-gem-rbis] # Include RBIs found in the `rbi/` directory of the gem
|
122
|
+
# Default: true
|
123
|
+
-w, [--workers=N] # EXPERIMENTAL: Number of parallel workers to use when generating RBIs
|
124
|
+
# Default: 1
|
125
|
+
-c, [--config=<config file path>] # Path to the Tapioca configuration file
|
126
|
+
# Default: sorbet/tapioca/config.yml
|
127
|
+
-V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
|
128
|
+
|
129
|
+
generate RBIs from gems
|
130
|
+
```
|
97
131
|
|
98
132
|
### Generate the list of all unresolved constants
|
99
133
|
|
@@ -101,19 +135,76 @@ Command: `tapioca todo`
|
|
101
135
|
|
102
136
|
This will generate the file `sorbet/rbi/todo.rbi` defining all unresolved constants as empty modules.
|
103
137
|
|
138
|
+
```shell
|
139
|
+
$ bundle exec tapioca help todo
|
140
|
+
Usage:
|
141
|
+
tapioca todo
|
142
|
+
|
143
|
+
Options:
|
144
|
+
[--todo-file=TODO_FILE]
|
145
|
+
# Default: sorbet/rbi/todo.rbi
|
146
|
+
[--file-header], [--no-file-header] # Add a "This file is generated" header on top of each generated RBI file
|
147
|
+
# Default: true
|
148
|
+
-c, [--config=<config file path>] # Path to the Tapioca configuration file
|
149
|
+
# Default: sorbet/tapioca/config.yml
|
150
|
+
-V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
|
151
|
+
|
152
|
+
generate the list of unresolved constants
|
153
|
+
```
|
154
|
+
|
104
155
|
### Generate DSL RBI files
|
105
156
|
|
106
157
|
Command: `tapioca dsl [constant...]`
|
107
158
|
|
108
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).
|
109
160
|
|
110
|
-
|
161
|
+
```shell
|
162
|
+
$ bundle exec tapioca help dsl
|
163
|
+
Usage:
|
164
|
+
tapioca dsl [constant...]
|
165
|
+
|
166
|
+
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
|
180
|
+
|
181
|
+
generate RBIs for dynamic methods
|
182
|
+
```
|
183
|
+
## Configuration
|
184
|
+
|
185
|
+
Tapioca supports loading command defaults from a configuration file. The default configuration
|
186
|
+
file location is `sorbet/tapioca/config.yml` but this default can be changed using the `--config` flag
|
187
|
+
and supplying an alternative configuration file path.
|
188
|
+
|
189
|
+
A configuration file must be a well-formed YAML file with top-level keys for the various Tapioca commands. Keys under each such top-level command should be the underscore version of a long option name for that command and the value for that key should be the value of the option.
|
190
|
+
|
191
|
+
For example, if you always want to generate gem RBIs with inline documentation, then you would create the file `sorbet/tapioca/config.yml` as:
|
111
192
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
193
|
+
```yaml
|
194
|
+
gem:
|
195
|
+
docs: true
|
196
|
+
```
|
197
|
+
|
198
|
+
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
|
+
|
200
|
+
```yaml
|
201
|
+
gem:
|
202
|
+
docs: true
|
203
|
+
dsl:
|
204
|
+
exclude:
|
205
|
+
- UrlHelpers
|
206
|
+
- ActiveRecordFixtures
|
207
|
+
```
|
117
208
|
|
118
209
|
## Contributing
|
119
210
|
|
data/lib/tapioca/cli.rb
CHANGED
@@ -1,46 +1,43 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "thor"
|
5
|
-
|
6
4
|
module Tapioca
|
7
5
|
class Cli < Thor
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
default:
|
19
|
-
desc: "Add a \"This file is generated\" header on top of each generated RBI file"
|
6
|
+
include CliHelper
|
7
|
+
include ConfigHelper
|
8
|
+
|
9
|
+
FILE_HEADER_OPTION_DESC = "Add a \"This file is generated\" header on top of each generated RBI file"
|
10
|
+
|
11
|
+
class_option :config,
|
12
|
+
aliases: ["-c"],
|
13
|
+
banner: "<config file path>",
|
14
|
+
type: :string,
|
15
|
+
desc: "Path to the Tapioca configuration file",
|
16
|
+
default: TAPIOCA_CONFIG_FILE
|
20
17
|
class_option :verbose,
|
21
18
|
aliases: ["-V"],
|
22
19
|
type: :boolean,
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
map T.unsafe(["--version", "-v"] => :__print_version)
|
20
|
+
desc: "Verbose output for debugging purposes",
|
21
|
+
default: false
|
27
22
|
|
28
23
|
desc "init", "initializes folder structure"
|
29
24
|
def init
|
30
25
|
generator = Generators::Init.new(
|
31
|
-
sorbet_config:
|
32
|
-
|
33
|
-
|
26
|
+
sorbet_config: SORBET_CONFIG_FILE,
|
27
|
+
tapioca_config: TAPIOCA_CONFIG_FILE,
|
28
|
+
default_postrequire: DEFAULT_POSTREQUIRE_FILE,
|
29
|
+
default_command: DEFAULT_COMMAND
|
34
30
|
)
|
35
31
|
generator.generate
|
36
32
|
end
|
37
33
|
|
38
34
|
desc "require", "generate the list of files to be required by tapioca"
|
35
|
+
option :postrequire, type: :string, default: DEFAULT_POSTREQUIRE_FILE
|
39
36
|
def require
|
40
37
|
generator = Generators::Require.new(
|
41
|
-
requires_path:
|
42
|
-
sorbet_config_path:
|
43
|
-
default_command:
|
38
|
+
requires_path: options[:postrequire],
|
39
|
+
sorbet_config_path: SORBET_CONFIG_FILE,
|
40
|
+
default_command: DEFAULT_COMMAND
|
44
41
|
)
|
45
42
|
Tapioca.silence_warnings do
|
46
43
|
generator.generate
|
@@ -48,13 +45,18 @@ module Tapioca
|
|
48
45
|
end
|
49
46
|
|
50
47
|
desc "todo", "generate the list of unresolved constants"
|
48
|
+
option :todo_file,
|
49
|
+
type: :string,
|
50
|
+
default: DEFAULT_TODO_FILE
|
51
|
+
option :file_header,
|
52
|
+
type: :boolean,
|
53
|
+
desc: FILE_HEADER_OPTION_DESC,
|
54
|
+
default: true
|
51
55
|
def todo
|
52
|
-
current_command = T.must(current_command_chain.first)
|
53
|
-
config = ConfigBuilder.from_options(current_command, options)
|
54
56
|
generator = Generators::Todo.new(
|
55
|
-
|
56
|
-
file_header:
|
57
|
-
default_command:
|
57
|
+
todo_file: options[:todo_file],
|
58
|
+
file_header: options[:file_header],
|
59
|
+
default_command: DEFAULT_COMMAND
|
58
60
|
)
|
59
61
|
Tapioca.silence_warnings do
|
60
62
|
generator.generate
|
@@ -62,15 +64,25 @@ module Tapioca
|
|
62
64
|
end
|
63
65
|
|
64
66
|
desc "dsl [constant...]", "generate RBIs for dynamic methods"
|
65
|
-
option :
|
67
|
+
option :outdir,
|
68
|
+
aliases: ["--out", "-o"],
|
69
|
+
banner: "directory",
|
70
|
+
desc: "The output directory for generated DSL RBI files",
|
71
|
+
default: DEFAULT_DSL_DIR
|
72
|
+
option :file_header,
|
73
|
+
type: :boolean,
|
74
|
+
desc: FILE_HEADER_OPTION_DESC,
|
75
|
+
default: true
|
76
|
+
option :only,
|
66
77
|
type: :array,
|
67
|
-
aliases: ["--gen", "-g"],
|
68
78
|
banner: "generator [generator ...]",
|
69
|
-
desc: "Only run supplied DSL
|
70
|
-
|
79
|
+
desc: "Only run supplied DSL generator(s)",
|
80
|
+
default: []
|
81
|
+
option :exclude,
|
71
82
|
type: :array,
|
72
83
|
banner: "generator [generator ...]",
|
73
|
-
desc: "Exclude supplied DSL
|
84
|
+
desc: "Exclude supplied DSL generator(s)",
|
85
|
+
default: []
|
74
86
|
option :verify,
|
75
87
|
type: :boolean,
|
76
88
|
default: false,
|
@@ -78,75 +90,111 @@ module Tapioca
|
|
78
90
|
option :quiet,
|
79
91
|
aliases: ["-q"],
|
80
92
|
type: :boolean,
|
81
|
-
desc: "Supresses file creation output"
|
93
|
+
desc: "Supresses file creation output",
|
94
|
+
default: false
|
95
|
+
option :workers,
|
96
|
+
aliases: ["-w"],
|
97
|
+
type: :numeric,
|
98
|
+
desc: "EXPERIMENTAL: Number of parallel workers to use when generating RBIs",
|
99
|
+
default: 1
|
82
100
|
def dsl(*constants)
|
83
|
-
current_command = T.must(current_command_chain.first)
|
84
|
-
config = ConfigBuilder.from_options(current_command, options)
|
85
101
|
generator = Generators::Dsl.new(
|
86
102
|
requested_constants: constants,
|
87
|
-
outpath:
|
88
|
-
|
89
|
-
|
90
|
-
file_header:
|
91
|
-
compiler_path: Tapioca::Compilers::Dsl::
|
92
|
-
tapioca_path:
|
93
|
-
default_command:
|
103
|
+
outpath: Pathname.new(options[:outdir]),
|
104
|
+
only: options[:only],
|
105
|
+
exclude: options[:exclude],
|
106
|
+
file_header: options[:file_header],
|
107
|
+
compiler_path: Tapioca::Compilers::Dsl::DSL_COMPILERS_DIR,
|
108
|
+
tapioca_path: TAPIOCA_DIR,
|
109
|
+
default_command: DEFAULT_COMMAND,
|
94
110
|
should_verify: options[:verify],
|
95
111
|
quiet: options[:quiet],
|
96
|
-
verbose: options[:verbose]
|
112
|
+
verbose: options[:verbose],
|
113
|
+
number_of_workers: options[:workers]
|
97
114
|
)
|
115
|
+
|
116
|
+
if options[:workers] != 1
|
117
|
+
say(
|
118
|
+
"Using more than one worker is experimental and might produce results that are not deterministic",
|
119
|
+
:red
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
98
123
|
Tapioca.silence_warnings do
|
99
124
|
generator.generate
|
100
125
|
end
|
101
126
|
end
|
102
127
|
|
103
128
|
desc "gem [gem...]", "generate RBIs from gems"
|
129
|
+
option :outdir,
|
130
|
+
aliases: ["--out", "-o"],
|
131
|
+
banner: "directory",
|
132
|
+
desc: "The output directory for generated gem RBI files",
|
133
|
+
default: DEFAULT_GEM_DIR
|
134
|
+
option :file_header,
|
135
|
+
type: :boolean,
|
136
|
+
desc: FILE_HEADER_OPTION_DESC,
|
137
|
+
default: true
|
104
138
|
option :all,
|
105
139
|
type: :boolean,
|
106
|
-
|
107
|
-
|
140
|
+
desc: "Regenerate RBI files for all gems",
|
141
|
+
default: false
|
108
142
|
option :prerequire,
|
109
143
|
aliases: ["--pre", "-b"],
|
110
144
|
banner: "file",
|
111
|
-
desc: "A file to be required before Bundler.require is called"
|
145
|
+
desc: "A file to be required before Bundler.require is called",
|
146
|
+
default: nil
|
112
147
|
option :postrequire,
|
113
148
|
aliases: ["--post", "-a"],
|
114
149
|
banner: "file",
|
115
|
-
desc: "A file to be required after Bundler.require is called"
|
150
|
+
desc: "A file to be required after Bundler.require is called",
|
151
|
+
default: DEFAULT_POSTREQUIRE_FILE
|
116
152
|
option :exclude,
|
117
153
|
aliases: ["-x"],
|
118
154
|
type: :array,
|
119
155
|
banner: "gem [gem ...]",
|
120
|
-
desc: "
|
156
|
+
desc: "Exclude the given gem(s) from RBI generation",
|
157
|
+
default: []
|
121
158
|
option :typed_overrides,
|
122
159
|
aliases: ["--typed", "-t"],
|
123
160
|
type: :hash,
|
124
161
|
banner: "gem:level [gem:level ...]",
|
125
|
-
desc: "
|
162
|
+
desc: "Override for typed sigils for generated gem RBIs",
|
163
|
+
default: DEFAULT_OVERRIDES
|
126
164
|
option :verify,
|
127
165
|
type: :boolean,
|
128
|
-
|
129
|
-
|
166
|
+
desc: "Verify RBIs are up-to-date",
|
167
|
+
default: false
|
130
168
|
option :doc,
|
131
169
|
type: :boolean,
|
132
|
-
|
133
|
-
|
170
|
+
desc: "Include YARD documentation from sources when generating RBIs. Warning: this might be slow",
|
171
|
+
default: false
|
172
|
+
option :exported_gem_rbis,
|
173
|
+
type: :boolean,
|
174
|
+
desc: "Include RBIs found in the `rbi/` directory of the gem",
|
175
|
+
default: true
|
176
|
+
option :workers,
|
177
|
+
aliases: ["-w"],
|
178
|
+
type: :numeric,
|
179
|
+
desc: "EXPERIMENTAL: Number of parallel workers to use when generating RBIs",
|
180
|
+
default: 1
|
134
181
|
def gem(*gems)
|
135
182
|
Tapioca.silence_warnings do
|
136
183
|
all = options[:all]
|
137
184
|
verify = options[:verify]
|
138
|
-
|
139
|
-
config = ConfigBuilder.from_options(current_command, options)
|
185
|
+
|
140
186
|
generator = Generators::Gem.new(
|
141
187
|
gem_names: all ? [] : gems,
|
142
|
-
|
143
|
-
prerequire:
|
144
|
-
postrequire:
|
145
|
-
typed_overrides:
|
146
|
-
default_command:
|
147
|
-
outpath:
|
148
|
-
file_header:
|
149
|
-
doc:
|
188
|
+
exclude: options[:exclude],
|
189
|
+
prerequire: options[:prerequire],
|
190
|
+
postrequire: options[:postrequire],
|
191
|
+
typed_overrides: options[:typed_overrides],
|
192
|
+
default_command: DEFAULT_COMMAND,
|
193
|
+
outpath: Pathname.new(options[:outdir]),
|
194
|
+
file_header: options[:file_header],
|
195
|
+
doc: options[:doc],
|
196
|
+
include_exported_rbis: options[:exported_gem_rbis],
|
197
|
+
number_of_workers: options[:workers]
|
150
198
|
)
|
151
199
|
|
152
200
|
raise MalformattedArgumentError, "Options '--all' and '--verify' are mutually exclusive" if all && verify
|
@@ -156,6 +204,13 @@ module Tapioca
|
|
156
204
|
raise MalformattedArgumentError, "Option '--verify' must be provided without any other arguments" if verify
|
157
205
|
end
|
158
206
|
|
207
|
+
if options[:workers] != 1
|
208
|
+
say(
|
209
|
+
"Using more than one worker is experimental and might produce results that are not deterministic",
|
210
|
+
:red
|
211
|
+
)
|
212
|
+
end
|
213
|
+
|
159
214
|
if gems.empty? && !all
|
160
215
|
generator.sync(should_verify: verify)
|
161
216
|
else
|
@@ -164,6 +219,74 @@ module Tapioca
|
|
164
219
|
end
|
165
220
|
end
|
166
221
|
|
222
|
+
desc "clean-shims", "clean duplicated definitions in shim RBIs"
|
223
|
+
option :gem_rbi_dir, type: :string, desc: "Path to gem RBIs", default: DEFAULT_GEM_DIR
|
224
|
+
option :dsl_rbi_dir, type: :string, desc: "Path to DSL RBIs", default: DEFAULT_DSL_DIR
|
225
|
+
option :shim_rbi_dir, type: :string, desc: "Path to shim RBIs", default: DEFAULT_SHIM_DIR
|
226
|
+
def clean_shims(*files_to_clean)
|
227
|
+
index = RBI::Index.new
|
228
|
+
|
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...")
|
252
|
+
end
|
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)
|
258
|
+
|
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)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
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)
|
286
|
+
end
|
287
|
+
|
288
|
+
map T.unsafe(["--version", "-v"] => :__print_version)
|
289
|
+
|
167
290
|
desc "--version, -v", "show version"
|
168
291
|
def __print_version
|
169
292
|
puts "Tapioca v#{Tapioca::VERSION}"
|