tapioca 0.10.2 → 0.10.4
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 +4 -4
- data/README.md +5 -0
- data/exe/tapioca +15 -13
- data/lib/tapioca/cli.rb +15 -2
- data/lib/tapioca/commands/check_shims.rb +11 -19
- data/lib/tapioca/commands/configure.rb +2 -2
- data/lib/tapioca/commands/dsl.rb +6 -1
- data/lib/tapioca/dsl/compiler.rb +4 -4
- data/lib/tapioca/dsl/compilers/active_record_associations.rb +35 -0
- data/lib/tapioca/dsl/compilers/active_record_delegated_types.rb +163 -0
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +29 -9
- data/lib/tapioca/dsl/compilers/protobuf.rb +17 -1
- data/lib/tapioca/dsl/extensions/active_record.rb +29 -0
- data/lib/tapioca/dsl/helpers/active_record_column_type_helper.rb +19 -0
- data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +1 -0
- data/lib/tapioca/dsl/helpers/graphql_type_helper.rb +1 -1
- data/lib/tapioca/dsl/pipeline.rb +3 -1
- data/lib/tapioca/gem/pipeline.rb +5 -8
- data/lib/tapioca/helpers/gem_helper.rb +1 -1
- data/lib/tapioca/helpers/rbi_files_helper.rb +2 -1
- data/lib/tapioca/helpers/rbi_helper.rb +4 -12
- data/lib/tapioca/helpers/sorbet_helper.rb +2 -3
- data/lib/tapioca/loaders/dsl.rb +8 -6
- data/lib/tapioca/loaders/loader.rb +5 -5
- data/lib/tapioca/rbi_ext/model.rb +5 -2
- data/lib/tapioca/runtime/reflection.rb +55 -0
- data/lib/tapioca/sorbet_ext/generic_name_patch.rb +35 -13
- data/lib/tapioca/static/symbol_loader.rb +3 -3
- data/lib/tapioca/static/symbol_table_parser.rb +6 -0
- data/lib/tapioca/version.rb +1 -1
- metadata +8 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bbed9bfddb52a94735d9455ed4351c4ef1389236ceba2e19ce46d999a05536b0
|
4
|
+
data.tar.gz: b1a35528c1e9cfa5fd735a64d4988bfd72c0f980835d58e4a37c62d5694e3daa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6138060ec0cea66dda6f96484329626d613494404cf99f851d1dbd59249546ffdfa0b0dd58236ef63d65b93acd250eb3a46b5a3eb1a3f8491014125b18a50800
|
7
|
+
data.tar.gz: 266205a5dd212e87836d1d26f1f018ab83d64aaacc9b793e9a01b88c6213bda834991194896a602ce6f267ef96e3ef8f78d14464005cefcfc010bb666ddc6f3e
|
data/README.md
CHANGED
@@ -473,6 +473,8 @@ Options:
|
|
473
473
|
-e, [--environment=ENVIRONMENT] # The Rack/Rails environment to use when generating RBIs
|
474
474
|
# Default: development
|
475
475
|
-l, [--list-compilers], [--no-list-compilers] # List all loaded compilers
|
476
|
+
[--app-root=APP_ROOT] # The path to the Rails application
|
477
|
+
# Default: .
|
476
478
|
-c, [--config=<config file path>] # Path to the Tapioca configuration file
|
477
479
|
# Default: sorbet/tapioca/config.yml
|
478
480
|
-V, [--verbose], [--no-verbose] # Verbose output for debugging purposes
|
@@ -635,6 +637,8 @@ There are two main parts to the DSL compiler API: `gather_constants` and `decora
|
|
635
637
|
* The `gather_constants` class method collects all classes (or modules) that should be processed by this specific DSL compiler.
|
636
638
|
* The `decorate` method defines how to generate the necessary RBI definitions for the gathered constants.
|
637
639
|
|
640
|
+
Every compiler must declare the type member `ConstantType` in order for Sorbet to understand what the return type of the `constant` attribute reader is. It needs to be assigned the correct type variable matching the type of constants that `gather_constants` returns. This generic variable allows Sorbet to type-check method calls on the `constant` reader in your `decorate` method. See the Sorbet documentation on [generics](https://sorbet.org/docs/generics) for more information.
|
641
|
+
|
638
642
|
You can now run the new RBI compiler through the normal DSL generation process (your custom compiler will be loaded automatically by Tapioca):
|
639
643
|
|
640
644
|
```shell
|
@@ -822,6 +826,7 @@ dsl:
|
|
822
826
|
rbi_max_line_length: 120
|
823
827
|
environment: development
|
824
828
|
list_compilers: false
|
829
|
+
app_root: "."
|
825
830
|
gem:
|
826
831
|
outdir: sorbet/rbi/gems
|
827
832
|
file_header: true
|
data/exe/tapioca
CHANGED
@@ -3,19 +3,21 @@
|
|
3
3
|
|
4
4
|
require "sorbet-runtime"
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
6
|
+
unless ENV["ENFORCE_TYPECHECKING"] == "1"
|
7
|
+
begin
|
8
|
+
T::Configuration.default_checked_level = :never
|
9
|
+
# Suppresses call validation errors
|
10
|
+
T::Configuration.call_validation_error_handler = ->(*) {}
|
11
|
+
# Suppresses errors caused by T.cast, T.let, T.must, etc.
|
12
|
+
T::Configuration.inline_type_error_handler = ->(*) {}
|
13
|
+
# Suppresses errors caused by incorrect parameter ordering
|
14
|
+
T::Configuration.sig_validation_error_handler = ->(*) {}
|
15
|
+
rescue
|
16
|
+
# Need this rescue so that if another gem has
|
17
|
+
# already set the checked level by the time we
|
18
|
+
# get to it, we don't fail outright.
|
19
|
+
nil
|
20
|
+
end
|
19
21
|
end
|
20
22
|
|
21
23
|
require_relative "../lib/tapioca/internal"
|
data/lib/tapioca/cli.rb
CHANGED
@@ -9,6 +9,8 @@ module Tapioca
|
|
9
9
|
|
10
10
|
FILE_HEADER_OPTION_DESC = "Add a \"This file is generated\" header on top of each generated RBI file"
|
11
11
|
|
12
|
+
check_unknown_options!
|
13
|
+
|
12
14
|
class_option :config,
|
13
15
|
aliases: ["-c"],
|
14
16
|
banner: "<config file path>",
|
@@ -121,6 +123,10 @@ module Tapioca
|
|
121
123
|
type: :boolean,
|
122
124
|
desc: "List all loaded compilers",
|
123
125
|
default: false
|
126
|
+
option :app_root,
|
127
|
+
type: :string,
|
128
|
+
desc: "The path to the Rails application",
|
129
|
+
default: "."
|
124
130
|
def dsl(*constants)
|
125
131
|
set_environment(options)
|
126
132
|
|
@@ -136,6 +142,7 @@ module Tapioca
|
|
136
142
|
verbose: options[:verbose],
|
137
143
|
number_of_workers: options[:workers],
|
138
144
|
rbi_formatter: rbi_formatter(options),
|
145
|
+
app_root: options[:app_root],
|
139
146
|
)
|
140
147
|
|
141
148
|
Tapioca.silence_warnings do
|
@@ -279,7 +286,10 @@ module Tapioca
|
|
279
286
|
payload: options[:payload],
|
280
287
|
number_of_workers: options[:workers],
|
281
288
|
)
|
282
|
-
|
289
|
+
|
290
|
+
Tapioca.silence_warnings do
|
291
|
+
command.execute
|
292
|
+
end
|
283
293
|
end
|
284
294
|
|
285
295
|
desc "annotations", "Pull gem RBI annotations from remote sources"
|
@@ -305,7 +315,10 @@ module Tapioca
|
|
305
315
|
netrc_file: netrc_file(options),
|
306
316
|
typed_overrides: options[:typed_overrides],
|
307
317
|
)
|
308
|
-
|
318
|
+
|
319
|
+
Tapioca.silence_warnings do
|
320
|
+
command.execute
|
321
|
+
end
|
309
322
|
end
|
310
323
|
|
311
324
|
map ["--version", "-v"] => :__print_version
|
@@ -51,26 +51,18 @@ module Tapioca
|
|
51
51
|
payload_path = T.let(nil, T.nilable(String))
|
52
52
|
|
53
53
|
if @payload
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
ERROR
|
64
|
-
end
|
65
|
-
|
66
|
-
index_rbis(index, "payload", payload_path, number_of_workers: @number_of_workers)
|
54
|
+
Dir.mktmpdir do |dir|
|
55
|
+
payload_path = dir
|
56
|
+
result = sorbet("--no-config --print=payload-sources:#{payload_path}")
|
57
|
+
|
58
|
+
unless result.status
|
59
|
+
raise Thor::Error, <<~ERROR
|
60
|
+
"Sorbet failed to dump payload"
|
61
|
+
#{result.err}
|
62
|
+
ERROR
|
67
63
|
end
|
68
|
-
|
69
|
-
|
70
|
-
The version of Sorbet used in your Gemfile.lock does not support `--print=payload-sources`
|
71
|
-
Current: v#{SORBET_GEM_SPEC.version}
|
72
|
-
Required: #{FEATURE_REQUIREMENTS[:print_payload_sources]}
|
73
|
-
ERROR
|
64
|
+
|
65
|
+
index_rbis(index, "payload", payload_path, number_of_workers: @number_of_workers)
|
74
66
|
end
|
75
67
|
end
|
76
68
|
|
@@ -70,7 +70,7 @@ module Tapioca
|
|
70
70
|
# typed: true
|
71
71
|
# frozen_string_literal: true
|
72
72
|
|
73
|
-
# Add your extra requires here (`#{default_command(:require)}` can be used to
|
73
|
+
# Add your extra requires here (`#{default_command(:require)}` can be used to bootstrap this list)
|
74
74
|
CONTENT
|
75
75
|
end
|
76
76
|
|
@@ -92,7 +92,7 @@ module Tapioca
|
|
92
92
|
@installer ||= Bundler::Installer.new(Bundler.root, Bundler.definition)
|
93
93
|
end
|
94
94
|
|
95
|
-
sig { returns(Bundler::StubSpecification) }
|
95
|
+
sig { returns(T.any(Bundler::StubSpecification, ::Gem::Specification)) }
|
96
96
|
def spec
|
97
97
|
@spec ||= Bundler.definition.specs.find { |s| s.name == "tapioca" }
|
98
98
|
end
|
data/lib/tapioca/commands/dsl.rb
CHANGED
@@ -22,6 +22,7 @@ module Tapioca
|
|
22
22
|
auto_strictness: T::Boolean,
|
23
23
|
gem_dir: String,
|
24
24
|
rbi_formatter: RBIFormatter,
|
25
|
+
app_root: String,
|
25
26
|
).void
|
26
27
|
end
|
27
28
|
def initialize(
|
@@ -37,7 +38,8 @@ module Tapioca
|
|
37
38
|
number_of_workers: nil,
|
38
39
|
auto_strictness: true,
|
39
40
|
gem_dir: DEFAULT_GEM_DIR,
|
40
|
-
rbi_formatter: DEFAULT_RBI_FORMATTER
|
41
|
+
rbi_formatter: DEFAULT_RBI_FORMATTER,
|
42
|
+
app_root: "."
|
41
43
|
)
|
42
44
|
@requested_constants = requested_constants
|
43
45
|
@outpath = outpath
|
@@ -52,6 +54,7 @@ module Tapioca
|
|
52
54
|
@auto_strictness = auto_strictness
|
53
55
|
@gem_dir = gem_dir
|
54
56
|
@rbi_formatter = rbi_formatter
|
57
|
+
@app_root = app_root
|
55
58
|
|
56
59
|
super()
|
57
60
|
end
|
@@ -61,6 +64,7 @@ module Tapioca
|
|
61
64
|
Loaders::Dsl.load_application(
|
62
65
|
tapioca_path: @tapioca_path,
|
63
66
|
eager_load: @requested_constants.empty?,
|
67
|
+
app_root: @app_root,
|
64
68
|
)
|
65
69
|
|
66
70
|
pipeline = create_pipeline
|
@@ -87,6 +91,7 @@ module Tapioca
|
|
87
91
|
Loaders::Dsl.load_application(
|
88
92
|
tapioca_path: @tapioca_path,
|
89
93
|
eager_load: @requested_constants.empty?,
|
94
|
+
app_root: @app_root,
|
90
95
|
)
|
91
96
|
|
92
97
|
if @should_verify
|
data/lib/tapioca/dsl/compiler.rb
CHANGED
@@ -101,6 +101,9 @@ module Tapioca
|
|
101
101
|
# rest parameter type
|
102
102
|
params << signature.rest_type.to_s if signature.has_rest
|
103
103
|
|
104
|
+
# keyrest parameter type
|
105
|
+
params << signature.keyrest_type.to_s if signature.has_keyrest
|
106
|
+
|
104
107
|
# special case `.void` in a proc
|
105
108
|
unless signature.block_name.nil?
|
106
109
|
params << signature.block_type.to_s.gsub("returns(<VOID>)", "void")
|
@@ -159,10 +162,7 @@ module Tapioca
|
|
159
162
|
def compile_method_return_type_to_rbi(method_def)
|
160
163
|
signature = signature_of(method_def)
|
161
164
|
return_type = signature.nil? ? "T.untyped" : name_of_type(signature.return_type)
|
162
|
-
return_type
|
163
|
-
# Map <NOT-TYPED> to `T.untyped`
|
164
|
-
return_type = "T.untyped" if return_type == "<NOT-TYPED>"
|
165
|
-
return_type
|
165
|
+
sanitize_signature_types(return_type)
|
166
166
|
end
|
167
167
|
end
|
168
168
|
end
|
@@ -241,6 +241,7 @@ module Tapioca
|
|
241
241
|
|
242
242
|
klass.create_method(
|
243
243
|
association_name.to_s,
|
244
|
+
comments: association_comments(reflection),
|
244
245
|
return_type: relation_class,
|
245
246
|
)
|
246
247
|
klass.create_method(
|
@@ -320,6 +321,40 @@ module Tapioca
|
|
320
321
|
end
|
321
322
|
end
|
322
323
|
|
324
|
+
sig { params(reflection: ReflectionType).returns(T::Array[RBI::Comment]) }
|
325
|
+
def association_comments(reflection)
|
326
|
+
anchor_name = case reflection
|
327
|
+
when ActiveRecord::Reflection::HasOneReflection
|
328
|
+
"the-has-one-association"
|
329
|
+
when ActiveRecord::Reflection::HasManyReflection
|
330
|
+
"the-has-many-association"
|
331
|
+
when ActiveRecord::Reflection::HasAndBelongsToManyReflection
|
332
|
+
"the-has-and-belongs-to-many-association"
|
333
|
+
when ActiveRecord::Reflection::BelongsToReflection
|
334
|
+
"the-belongs-to-association"
|
335
|
+
when ActiveRecord::Reflection::ThroughReflection
|
336
|
+
delegate_reflection = reflection.send(:delegate_reflection)
|
337
|
+
declaration = declaration(delegate_reflection)
|
338
|
+
if T.must(declaration).match?("has_one")
|
339
|
+
"the-has-one-through-association"
|
340
|
+
else
|
341
|
+
"the-has-many-through-association"
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
if anchor_name
|
346
|
+
url = "https://guides.rubyonrails.org/association_basics.html##{anchor_name}"
|
347
|
+
association_name = anchor_name.sub(/^the-(.*)-association$/, '\1')
|
348
|
+
comment = <<~MSG
|
349
|
+
This method is created by ActiveRecord on the `#{reflection.active_record.name}` class because it declared `#{declaration(reflection)}`.
|
350
|
+
🔗 [Rails guide for `#{association_name.gsub("-", "_")}` association](#{url})
|
351
|
+
MSG
|
352
|
+
[RBI::Comment.new(comment)]
|
353
|
+
else
|
354
|
+
[]
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
323
358
|
sig do
|
324
359
|
params(
|
325
360
|
reflection: ReflectionType,
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
begin
|
5
|
+
require "active_record"
|
6
|
+
rescue LoadError
|
7
|
+
return
|
8
|
+
end
|
9
|
+
|
10
|
+
require "tapioca/dsl/helpers/active_record_column_type_helper"
|
11
|
+
require "tapioca/dsl/helpers/active_record_constants_helper"
|
12
|
+
|
13
|
+
module Tapioca
|
14
|
+
module Dsl
|
15
|
+
module Compilers
|
16
|
+
# `Tapioca::Dsl::Compilers::DelegatedTypes` defines RBI files for subclasses of
|
17
|
+
# [`ActiveRecord::Base`](https://api.rubyonrails.org/classes/ActiveRecord/Base.html).
|
18
|
+
# This compiler is only responsible for defining the methods that would be created for delegated_types that
|
19
|
+
# are defined in the Active Record model.
|
20
|
+
#
|
21
|
+
# For example, with the following model class:
|
22
|
+
#
|
23
|
+
# ~~~rb
|
24
|
+
# class Entry < ActiveRecord::Base
|
25
|
+
# delegated_type :entryable, types: %w[ Message Comment ]
|
26
|
+
# end
|
27
|
+
# ~~~
|
28
|
+
#
|
29
|
+
# this compiler will produce the following methods in the RBI file
|
30
|
+
# `entry.rbi`:
|
31
|
+
#
|
32
|
+
# ~~~rbi
|
33
|
+
# # entry.rbi
|
34
|
+
# # typed: true
|
35
|
+
#
|
36
|
+
# class Entry
|
37
|
+
# include GeneratedDelegatedTypeMethods
|
38
|
+
#
|
39
|
+
# module GeneratedDelegatedTypeMethods
|
40
|
+
# sig { params(args: T.untyped).returns(T.any(Message, Comment)) }
|
41
|
+
# def build_entryable(*args); end
|
42
|
+
#
|
43
|
+
# sig { returns(Class) }
|
44
|
+
# def entryable_class; end
|
45
|
+
#
|
46
|
+
# sig { returns(ActiveSupport::StringInquirer) }
|
47
|
+
# def entryable_name; end
|
48
|
+
#
|
49
|
+
# sig { returns(T::Boolean) }
|
50
|
+
# def message?; end
|
51
|
+
#
|
52
|
+
# sig { returns(T.nilable(Message)) }
|
53
|
+
# def message; end
|
54
|
+
#
|
55
|
+
# sig { returns(T.nilable(Integer)) }
|
56
|
+
# def message_id; end
|
57
|
+
#
|
58
|
+
# sig { returns(T::Boolean) }
|
59
|
+
# def comment?; end
|
60
|
+
#
|
61
|
+
# sig { returns(T.nilable(Comment)) }
|
62
|
+
# def comment; end
|
63
|
+
#
|
64
|
+
# sig { returns(T.nilable(Integer)) }
|
65
|
+
# def comment_id; end
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# ~~~
|
70
|
+
class ActiveRecordDelegatedTypes < Compiler
|
71
|
+
extend T::Sig
|
72
|
+
include Helpers::ActiveRecordConstantsHelper
|
73
|
+
|
74
|
+
ConstantType = type_member { { fixed: T.all(T.class_of(ActiveRecord::Base), Extensions::ActiveRecord) } }
|
75
|
+
|
76
|
+
sig { override.void }
|
77
|
+
def decorate
|
78
|
+
return if constant.__tapioca_delegated_types.nil?
|
79
|
+
|
80
|
+
root.create_path(constant) do |model|
|
81
|
+
model.create_module(DelegatedTypesModuleName) do |mod|
|
82
|
+
constant.__tapioca_delegated_types.each do |role, data|
|
83
|
+
types = data.fetch(:types)
|
84
|
+
options = data.fetch(:options, {})
|
85
|
+
populate_role_accessors(mod, role, types)
|
86
|
+
populate_type_helpers(mod, role, types, options)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
model.create_include(DelegatedTypesModuleName)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class << self
|
95
|
+
extend T::Sig
|
96
|
+
|
97
|
+
sig { override.returns(T::Enumerable[Module]) }
|
98
|
+
def gather_constants
|
99
|
+
descendants_of(::ActiveRecord::Base).reject(&:abstract_class?)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
sig { params(mod: RBI::Scope, role: Symbol, types: T::Array[String]).void }
|
106
|
+
def populate_role_accessors(mod, role, types)
|
107
|
+
mod.create_method(
|
108
|
+
"#{role}_name",
|
109
|
+
parameters: [],
|
110
|
+
return_type: "ActiveSupport::StringInquirer",
|
111
|
+
)
|
112
|
+
|
113
|
+
mod.create_method(
|
114
|
+
"#{role}_class",
|
115
|
+
parameters: [],
|
116
|
+
return_type: "Class",
|
117
|
+
)
|
118
|
+
|
119
|
+
mod.create_method(
|
120
|
+
"build_#{role}",
|
121
|
+
parameters: [create_rest_param("args", type: "T.untyped")],
|
122
|
+
return_type: "T.any(#{types.join(", ")})",
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
sig { params(mod: RBI::Scope, role: Symbol, types: T::Array[String], options: T::Hash[Symbol, T.untyped]).void }
|
127
|
+
def populate_type_helpers(mod, role, types, options)
|
128
|
+
types.each do |type|
|
129
|
+
populate_type_helper(mod, role, type, options)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
sig { params(mod: RBI::Scope, role: Symbol, type: String, options: T::Hash[Symbol, T.untyped]).void }
|
134
|
+
def populate_type_helper(mod, role, type, options)
|
135
|
+
singular = type.tableize.tr("/", "_").singularize
|
136
|
+
query = "#{singular}?"
|
137
|
+
primary_key = options[:primary_key] || "id"
|
138
|
+
role_id = options[:foreign_key] || "#{role}_id"
|
139
|
+
|
140
|
+
getter_type, _ = Helpers::ActiveRecordColumnTypeHelper.new(constant).type_for(role_id.to_s)
|
141
|
+
|
142
|
+
mod.create_method(
|
143
|
+
query,
|
144
|
+
parameters: [],
|
145
|
+
return_type: "T::Boolean",
|
146
|
+
)
|
147
|
+
|
148
|
+
mod.create_method(
|
149
|
+
singular,
|
150
|
+
parameters: [],
|
151
|
+
return_type: "T.nilable(#{type})",
|
152
|
+
)
|
153
|
+
|
154
|
+
mod.create_method(
|
155
|
+
"#{singular}_#{primary_key}",
|
156
|
+
parameters: [],
|
157
|
+
return_type: as_nilable_type(getter_type),
|
158
|
+
)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -217,6 +217,7 @@ module Tapioca
|
|
217
217
|
T::Array[Symbol],
|
218
218
|
)
|
219
219
|
FINDER_METHODS = T.let(ActiveRecord::FinderMethods.instance_methods(false), T::Array[Symbol])
|
220
|
+
SIGNED_FINDER_METHODS = T.let(ActiveRecord::SignedId::ClassMethods.instance_methods(false), T::Array[Symbol])
|
220
221
|
CALCULATION_METHODS = T.let(ActiveRecord::Calculations.instance_methods(false), T::Array[Symbol])
|
221
222
|
ENUMERABLE_QUERY_METHODS = T.let([:any?, :many?, :none?, :one?], T::Array[Symbol])
|
222
223
|
FIND_OR_CREATE_METHODS = T.let(
|
@@ -243,15 +244,9 @@ module Tapioca
|
|
243
244
|
# The model always extends the generated relation module
|
244
245
|
model.create_extend(RelationMethodsModuleName)
|
245
246
|
|
246
|
-
#
|
247
|
-
#
|
248
|
-
|
249
|
-
# `T::Array[NilClass]`, otherwise.
|
250
|
-
if sorbet_supports?(:to_ary_nil_support)
|
251
|
-
# Type the `to_ary` method as returning `NilClass` so that flatten stops recursing
|
252
|
-
# See https://github.com/sorbet/sorbet/pull/4706 for details
|
253
|
-
model.create_method("to_ary", return_type: "NilClass", visibility: RBI::Private.new)
|
254
|
-
end
|
247
|
+
# Type the `to_ary` method as returning `NilClass` so that flatten stops recursing
|
248
|
+
# See https://github.com/sorbet/sorbet/pull/4706 for details
|
249
|
+
model.create_method("to_ary", return_type: "NilClass", visibility: RBI::Private.new)
|
255
250
|
|
256
251
|
create_relation_class(model)
|
257
252
|
create_association_relation_class(model)
|
@@ -599,6 +594,31 @@ module Tapioca
|
|
599
594
|
end
|
600
595
|
end
|
601
596
|
|
597
|
+
SIGNED_FINDER_METHODS.each do |method_name|
|
598
|
+
case method_name
|
599
|
+
when :find_signed
|
600
|
+
create_common_method(
|
601
|
+
"find_signed",
|
602
|
+
common_relation_methods_module,
|
603
|
+
parameters: [
|
604
|
+
create_param("signed_id", type: "T.untyped"),
|
605
|
+
create_kw_opt_param("purpose", type: "T.untyped", default: "nil"),
|
606
|
+
],
|
607
|
+
return_type: as_nilable_type(constant_name),
|
608
|
+
)
|
609
|
+
when :find_signed!
|
610
|
+
create_common_method(
|
611
|
+
"find_signed!",
|
612
|
+
common_relation_methods_module,
|
613
|
+
parameters: [
|
614
|
+
create_param("signed_id", type: "T.untyped"),
|
615
|
+
create_kw_opt_param("purpose", type: "T.untyped", default: "nil"),
|
616
|
+
],
|
617
|
+
return_type: constant_name,
|
618
|
+
)
|
619
|
+
end
|
620
|
+
end
|
621
|
+
|
602
622
|
CALCULATION_METHODS.each do |method_name|
|
603
623
|
case method_name
|
604
624
|
when :average, :maximum, :minimum
|
@@ -95,7 +95,18 @@ module Tapioca
|
|
95
95
|
case descriptor
|
96
96
|
when Google::Protobuf::EnumDescriptor
|
97
97
|
descriptor.to_h.each do |sym, val|
|
98
|
-
|
98
|
+
# For each enum value, create a namespaced constant on the root rather than an un-namespaced
|
99
|
+
# constant within the class. This is because un-namespaced constants might conflict with reserved
|
100
|
+
# Ruby words, such as "BEGIN." By namespacing them, we avoid this problem.
|
101
|
+
#
|
102
|
+
# Invalid syntax:
|
103
|
+
# class Foo
|
104
|
+
# BEGIN = 3
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# Valid syntax:
|
108
|
+
# Foo::BEGIN = 3
|
109
|
+
root.create_constant("#{constant}::#{sym}", value: val.to_s)
|
99
110
|
end
|
100
111
|
|
101
112
|
klass.create_method(
|
@@ -273,6 +284,11 @@ module Tapioca
|
|
273
284
|
return_type: "void",
|
274
285
|
)
|
275
286
|
|
287
|
+
klass.create_method(
|
288
|
+
"clear_#{field.name}",
|
289
|
+
return_type: "void",
|
290
|
+
)
|
291
|
+
|
276
292
|
field
|
277
293
|
end
|
278
294
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
begin
|
5
|
+
require "active_record"
|
6
|
+
rescue LoadError
|
7
|
+
return
|
8
|
+
end
|
9
|
+
|
10
|
+
module Tapioca
|
11
|
+
module Dsl
|
12
|
+
module Compilers
|
13
|
+
module Extensions
|
14
|
+
module ActiveRecord
|
15
|
+
attr_reader :__tapioca_delegated_types
|
16
|
+
|
17
|
+
def delegated_type(role, types:, **options)
|
18
|
+
@__tapioca_delegated_types ||= {}
|
19
|
+
@__tapioca_delegated_types[role] = { types: types, options: options }
|
20
|
+
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
::ActiveRecord::Base.singleton_class.prepend(self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -41,6 +41,8 @@ module Tapioca
|
|
41
41
|
"::ActiveSupport::TimeWithZone"
|
42
42
|
when ActiveRecord::Enum::EnumType
|
43
43
|
"::String"
|
44
|
+
when ActiveRecord::Type::Serialized
|
45
|
+
serialized_column_type(column_type)
|
44
46
|
else
|
45
47
|
handle_unknown_type(column_type)
|
46
48
|
end
|
@@ -119,6 +121,23 @@ module Tapioca
|
|
119
121
|
"T.any(::String, ::Symbol)"
|
120
122
|
end
|
121
123
|
end
|
124
|
+
|
125
|
+
sig { params(column_type: ActiveRecord::Type::Serialized).returns(String) }
|
126
|
+
def serialized_column_type(column_type)
|
127
|
+
case column_type.coder
|
128
|
+
when ActiveRecord::Coders::YAMLColumn
|
129
|
+
case column_type.coder.object_class
|
130
|
+
when Array.singleton_class
|
131
|
+
"T::Array[T.untyped]"
|
132
|
+
when Hash.singleton_class
|
133
|
+
"T::Hash[T.untyped, T.untyped]"
|
134
|
+
else
|
135
|
+
"T.untyped"
|
136
|
+
end
|
137
|
+
else
|
138
|
+
"T.untyped"
|
139
|
+
end
|
140
|
+
end
|
122
141
|
end
|
123
142
|
end
|
124
143
|
end
|
@@ -13,6 +13,7 @@ module Tapioca
|
|
13
13
|
|
14
14
|
AttributeMethodsModuleName = T.let("GeneratedAttributeMethods", String)
|
15
15
|
AssociationMethodsModuleName = T.let("GeneratedAssociationMethods", String)
|
16
|
+
DelegatedTypesModuleName = T.let("GeneratedDelegatedTypeMethods", String)
|
16
17
|
|
17
18
|
RelationMethodsModuleName = T.let("GeneratedRelationMethods", String)
|
18
19
|
AssociationRelationMethodsModuleName = T.let("GeneratedAssociationRelationMethods", String)
|
@@ -25,7 +25,7 @@ module Tapioca
|
|
25
25
|
when GraphQL::Types::ISO8601Date.singleton_class
|
26
26
|
type_for_constant(Date)
|
27
27
|
when GraphQL::Types::ISO8601DateTime.singleton_class
|
28
|
-
type_for_constant(
|
28
|
+
type_for_constant(Time)
|
29
29
|
when GraphQL::Types::JSON.singleton_class
|
30
30
|
"T::Hash[::String, T.untyped]"
|
31
31
|
when GraphQL::Schema::Enum.singleton_class
|
data/lib/tapioca/dsl/pipeline.rb
CHANGED
@@ -128,9 +128,11 @@ module Tapioca
|
|
128
128
|
def filter_anonymous_and_reloaded_constants(constants)
|
129
129
|
# Group constants by their names
|
130
130
|
constants_by_name = constants
|
131
|
-
.group_by { |c|
|
131
|
+
.group_by { |c| Runtime::Reflection.name_of(c) }
|
132
132
|
.select { |name, _| !name.nil? }
|
133
133
|
|
134
|
+
constants_by_name = T.cast(constants_by_name, T::Hash[String, T::Array[Module]])
|
135
|
+
|
134
136
|
# Find the constants that have been reloaded
|
135
137
|
reloaded_constants = constants_by_name.select { |_, constants| constants.size > 1 }.keys
|
136
138
|
|
data/lib/tapioca/gem/pipeline.rb
CHANGED
@@ -241,8 +241,7 @@ module Tapioca
|
|
241
241
|
klass = class_of(value)
|
242
242
|
|
243
243
|
klass_name = if klass == ObjectSpace::WeakMap
|
244
|
-
|
245
|
-
"ObjectSpace::WeakMap[T.untyped]"
|
244
|
+
sorbet_supports?(:non_generic_weak_map) ? "ObjectSpace::WeakMap" : "ObjectSpace::WeakMap[T.untyped]"
|
246
245
|
elsif T::Generic === klass
|
247
246
|
generic_name_of(klass)
|
248
247
|
else
|
@@ -342,7 +341,7 @@ module Tapioca
|
|
342
341
|
|
343
342
|
sig { params(constant: Module, strict: T::Boolean).returns(T::Boolean) }
|
344
343
|
def defined_in_gem?(constant, strict: true)
|
345
|
-
files =
|
344
|
+
files = get_file_candidates(constant)
|
346
345
|
.merge(Runtime::Trackers::ConstantDefinition.files_for(constant))
|
347
346
|
|
348
347
|
return !strict if files.empty?
|
@@ -352,13 +351,11 @@ module Tapioca
|
|
352
351
|
end
|
353
352
|
end
|
354
353
|
|
355
|
-
sig { params(constant: Module).returns(T::
|
354
|
+
sig { params(constant: Module).returns(T::Set[String]) }
|
356
355
|
def get_file_candidates(constant)
|
357
|
-
|
358
|
-
|
359
|
-
wrapped_module.send(:method_candidates).flatten.filter_map(&:source_file).uniq
|
356
|
+
file_candidates_for(constant)
|
360
357
|
rescue ArgumentError, NameError
|
361
|
-
|
358
|
+
Set.new
|
362
359
|
end
|
363
360
|
|
364
361
|
sig { params(name: String).void }
|
@@ -5,7 +5,7 @@ module Tapioca
|
|
5
5
|
module GemHelper
|
6
6
|
extend T::Sig
|
7
7
|
|
8
|
-
sig { params(app_dir: String, full_gem_path: String).returns(T::Boolean) }
|
8
|
+
sig { params(app_dir: T.any(String, Pathname), full_gem_path: String).returns(T::Boolean) }
|
9
9
|
def gem_in_app_dir?(app_dir, full_gem_path)
|
10
10
|
app_dir = to_realpath(app_dir)
|
11
11
|
full_gem_path = to_realpath(full_gem_path)
|
@@ -23,22 +23,14 @@ module Tapioca
|
|
23
23
|
def serialize_type_variable(type, variance, fixed, upper, lower)
|
24
24
|
variance = nil if variance == :invariant
|
25
25
|
|
26
|
-
bounds = []
|
27
|
-
bounds << "fixed: #{fixed}" if fixed
|
28
|
-
bounds << "lower: #{lower}" if lower
|
29
|
-
bounds << "upper: #{upper}" if upper
|
30
|
-
|
31
|
-
parameters = []
|
32
26
|
block = []
|
27
|
+
block << "fixed: #{fixed}" if fixed
|
28
|
+
block << "lower: #{lower}" if lower
|
29
|
+
block << "upper: #{upper}" if upper
|
33
30
|
|
31
|
+
parameters = []
|
34
32
|
parameters << ":#{variance}" if variance
|
35
33
|
|
36
|
-
if sorbet_supports?(:type_variable_block_syntax)
|
37
|
-
block = bounds
|
38
|
-
else
|
39
|
-
parameters.concat(bounds)
|
40
|
-
end
|
41
|
-
|
42
34
|
serialized = type.dup
|
43
35
|
serialized << "(#{parameters.join(", ")})" unless parameters.empty?
|
44
36
|
serialized << " { { #{block.join(", ")} } }" unless block.empty?
|
@@ -20,9 +20,8 @@ module Tapioca
|
|
20
20
|
SORBET_PAYLOAD_URL = "https://github.com/sorbet/sorbet/tree/master/rbi"
|
21
21
|
|
22
22
|
FEATURE_REQUIREMENTS = T.let({
|
23
|
-
|
24
|
-
|
25
|
-
type_variable_block_syntax: ::Gem::Requirement.new(">= 0.5.9892"), # https://github.com/sorbet/sorbet/pull/5639
|
23
|
+
# feature_name: ::Gem::Requirement.new(">= ___"), # https://github.com/sorbet/sorbet/pull/___
|
24
|
+
non_generic_weak_map: ::Gem::Requirement.new(">= 0.5.10587"), # https://github.com/sorbet/sorbet/pull/6610
|
26
25
|
}.freeze, T::Hash[Symbol, ::Gem::Requirement])
|
27
26
|
|
28
27
|
sig { params(sorbet_args: String).returns(Spoom::ExecResult) }
|
data/lib/tapioca/loaders/dsl.rb
CHANGED
@@ -9,9 +9,9 @@ module Tapioca
|
|
9
9
|
class << self
|
10
10
|
extend T::Sig
|
11
11
|
|
12
|
-
sig { params(tapioca_path: String, eager_load: T::Boolean).void }
|
13
|
-
def load_application(tapioca_path:, eager_load: true)
|
14
|
-
loader = new(tapioca_path: tapioca_path)
|
12
|
+
sig { params(tapioca_path: String, eager_load: T::Boolean, app_root: String).void }
|
13
|
+
def load_application(tapioca_path:, eager_load: true, app_root: ".")
|
14
|
+
loader = new(tapioca_path: tapioca_path, app_root: app_root)
|
15
15
|
loader.load
|
16
16
|
end
|
17
17
|
end
|
@@ -26,12 +26,13 @@ module Tapioca
|
|
26
26
|
|
27
27
|
protected
|
28
28
|
|
29
|
-
sig { params(tapioca_path: String, eager_load: T::Boolean).void }
|
30
|
-
def initialize(tapioca_path:, eager_load: true)
|
29
|
+
sig { params(tapioca_path: String, eager_load: T::Boolean, app_root: String).void }
|
30
|
+
def initialize(tapioca_path:, eager_load: true, app_root: ".")
|
31
31
|
super()
|
32
32
|
|
33
33
|
@tapioca_path = tapioca_path
|
34
34
|
@eager_load = eager_load
|
35
|
+
@app_root = app_root
|
35
36
|
end
|
36
37
|
|
37
38
|
sig { void }
|
@@ -64,6 +65,7 @@ module Tapioca
|
|
64
65
|
load_rails_application(
|
65
66
|
environment_load: true,
|
66
67
|
eager_load: @eager_load,
|
68
|
+
app_root: @app_root,
|
67
69
|
)
|
68
70
|
|
69
71
|
say("Done", :green)
|
@@ -71,7 +73,7 @@ module Tapioca
|
|
71
73
|
|
72
74
|
sig { void }
|
73
75
|
def abort_if_pending_migrations!
|
74
|
-
return unless File.exist?("config/application.rb")
|
76
|
+
return unless File.exist?("#{@app_root}/config/application.rb")
|
75
77
|
return unless defined?(::Rake)
|
76
78
|
|
77
79
|
Rails.application.load_tasks
|
@@ -33,16 +33,16 @@ module Tapioca
|
|
33
33
|
load_rails_engines
|
34
34
|
end
|
35
35
|
|
36
|
-
sig { params(environment_load: T::Boolean, eager_load: T::Boolean).void }
|
37
|
-
def load_rails_application(environment_load: false, eager_load: false)
|
38
|
-
return unless File.exist?("config/application.rb")
|
36
|
+
sig { params(environment_load: T::Boolean, eager_load: T::Boolean, app_root: String).void }
|
37
|
+
def load_rails_application(environment_load: false, eager_load: false, app_root: ".")
|
38
|
+
return unless File.exist?("#{app_root}/config/application.rb")
|
39
39
|
|
40
40
|
silence_deprecations
|
41
41
|
|
42
42
|
if environment_load
|
43
|
-
require "
|
43
|
+
require "./#{app_root}/config/environment"
|
44
44
|
else
|
45
|
-
require "
|
45
|
+
require "./#{app_root}/config/application"
|
46
46
|
end
|
47
47
|
|
48
48
|
eager_load_rails_app if eager_load
|
@@ -83,13 +83,16 @@ module RBI
|
|
83
83
|
return_type: String,
|
84
84
|
class_method: T::Boolean,
|
85
85
|
visibility: RBI::Visibility,
|
86
|
+
comments: T::Array[RBI::Comment],
|
86
87
|
).void
|
87
88
|
end
|
88
|
-
def create_method(name, parameters: [], return_type: "T.untyped", class_method: false, visibility: RBI::Public.new
|
89
|
+
def create_method(name, parameters: [], return_type: "T.untyped", class_method: false, visibility: RBI::Public.new,
|
90
|
+
comments: [])
|
89
91
|
return unless Tapioca::RBIHelper.valid_method_name?(name)
|
90
92
|
|
91
93
|
sig = RBI::Sig.new(return_type: return_type)
|
92
|
-
method = RBI::Method.new(name, sigs: [sig], is_singleton: class_method, visibility: visibility
|
94
|
+
method = RBI::Method.new(name, sigs: [sig], is_singleton: class_method, visibility: visibility,
|
95
|
+
comments: comments)
|
93
96
|
parameters.each do |param|
|
94
97
|
method << param.param
|
95
98
|
sig << RBI::SigParam.new(param.param.name, param.type)
|
@@ -183,6 +183,61 @@ module Tapioca
|
|
183
183
|
|
184
184
|
T.cast(result, Module)
|
185
185
|
end
|
186
|
+
|
187
|
+
sig { params(constant: Module).returns(T::Set[String]) }
|
188
|
+
def file_candidates_for(constant)
|
189
|
+
relevant_methods_for(constant).filter_map do |method|
|
190
|
+
method.source_location&.first
|
191
|
+
end.to_set
|
192
|
+
end
|
193
|
+
|
194
|
+
private
|
195
|
+
|
196
|
+
sig { params(constant: Module).returns(T::Array[UnboundMethod]) }
|
197
|
+
def relevant_methods_for(constant)
|
198
|
+
methods = methods_for(constant).select(&:source_location)
|
199
|
+
.reject { |x| method_defined_by_forwardable_module?(x) }
|
200
|
+
|
201
|
+
return methods unless methods.empty?
|
202
|
+
|
203
|
+
constants_of(constant).flat_map do |const_name|
|
204
|
+
if (mod = child_module_for_parent_with_name(constant, const_name.to_s))
|
205
|
+
relevant_methods_for(mod)
|
206
|
+
else
|
207
|
+
[]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
sig { params(constant: Module).returns(T::Array[UnboundMethod]) }
|
213
|
+
def methods_for(constant)
|
214
|
+
modules = [constant, singleton_class_of(constant)]
|
215
|
+
method_list_methods = [
|
216
|
+
PUBLIC_INSTANCE_METHODS_METHOD,
|
217
|
+
PROTECTED_INSTANCE_METHODS_METHOD,
|
218
|
+
PRIVATE_INSTANCE_METHODS_METHOD,
|
219
|
+
]
|
220
|
+
|
221
|
+
modules.product(method_list_methods).flat_map do |mod, method_list_method|
|
222
|
+
method_list_method.bind_call(mod, false).map { |name| mod.instance_method(name) }
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
sig { params(parent: Module, name: String).returns(T.nilable(Module)) }
|
227
|
+
def child_module_for_parent_with_name(parent, name)
|
228
|
+
return if parent.autoload?(name)
|
229
|
+
|
230
|
+
child = constantize(name, inherit: true, namespace: parent)
|
231
|
+
return unless Module === child
|
232
|
+
return unless name_of(child) == "#{name_of(parent)}::#{name}"
|
233
|
+
|
234
|
+
child
|
235
|
+
end
|
236
|
+
|
237
|
+
sig { params(method: UnboundMethod).returns(T::Boolean) }
|
238
|
+
def method_defined_by_forwardable_module?(method)
|
239
|
+
method.source_location&.first == Object.const_source_location(:Forwardable)&.first
|
240
|
+
end
|
186
241
|
end
|
187
242
|
end
|
188
243
|
end
|
@@ -62,8 +62,8 @@ module T
|
|
62
62
|
# we've created a clone of that type with the `name` method returning the
|
63
63
|
# appropriate name for that specific concrete type.
|
64
64
|
def name
|
65
|
-
if T::Generic === @raw_type
|
66
|
-
# for types that are generic
|
65
|
+
if T::Generic === @raw_type
|
66
|
+
# for types that are generic, use the name
|
67
67
|
# returned by the "name" method of this instance
|
68
68
|
@name ||= T.unsafe(@raw_type).name.freeze
|
69
69
|
else
|
@@ -78,20 +78,42 @@ module T
|
|
78
78
|
end
|
79
79
|
|
80
80
|
module Utils
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
val
|
87
|
-
|
88
|
-
|
81
|
+
# This duplication is required to preserve backwards compatibility with sorbet-runtime versions prior to the
|
82
|
+
# introduction of the `Private` module in https://github.com/sorbet/sorbet/pull/6559.
|
83
|
+
if defined?(T::Utils::Private)
|
84
|
+
module Private
|
85
|
+
module PrivateCoercePatch
|
86
|
+
def coerce_and_check_module_types(val, check_val, check_module_type)
|
87
|
+
if val.is_a?(Tapioca::TypeVariableModule)
|
88
|
+
val.coerce_to_type_variable
|
89
|
+
elsif val.respond_to?(:__tapioca_override_type)
|
90
|
+
val.__tapioca_override_type
|
91
|
+
else
|
92
|
+
super
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class << self
|
98
|
+
prepend(PrivateCoercePatch)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
else
|
102
|
+
module CoercePatch
|
103
|
+
def coerce(val)
|
104
|
+
if val.is_a?(Tapioca::TypeVariableModule)
|
105
|
+
val.coerce_to_type_variable
|
106
|
+
elsif val.respond_to?(:__tapioca_override_type)
|
107
|
+
val.__tapioca_override_type
|
108
|
+
else
|
109
|
+
super
|
110
|
+
end
|
89
111
|
end
|
90
112
|
end
|
91
|
-
end
|
92
113
|
|
93
|
-
|
94
|
-
|
114
|
+
class << self
|
115
|
+
prepend(CoercePatch)
|
116
|
+
end
|
95
117
|
end
|
96
118
|
end
|
97
119
|
end
|
@@ -62,14 +62,14 @@ module Tapioca
|
|
62
62
|
|
63
63
|
sig { params(paths: T::Array[Pathname]).returns(T::Set[String]) }
|
64
64
|
def symbols_from_paths(paths)
|
65
|
-
output =
|
65
|
+
output = Tempfile.create("sorbet") do |file|
|
66
66
|
file.write(Array(paths).join("\n"))
|
67
67
|
file.flush
|
68
68
|
|
69
69
|
symbol_table_json_from("@#{file.path.shellescape}")
|
70
|
-
end
|
70
|
+
end
|
71
71
|
|
72
|
-
return Set.new if output.
|
72
|
+
return Set.new if output.empty?
|
73
73
|
|
74
74
|
SymbolTableParser.parse_json(output)
|
75
75
|
end
|
@@ -43,6 +43,12 @@ module Tapioca
|
|
43
43
|
|
44
44
|
next if name.nil?
|
45
45
|
next unless SKIP_PARSE_KINDS.include?(kind)
|
46
|
+
|
47
|
+
# Turn singleton class names to attached class names
|
48
|
+
if (match_data = name.match(/<Class:(.*)>/))
|
49
|
+
name = match_data[1]
|
50
|
+
end
|
51
|
+
|
46
52
|
next if name.match?(/[<>()$]/)
|
47
53
|
next if name.match?(/^[0-9]+$/)
|
48
54
|
next if name == "T::Helpers"
|
data/lib/tapioca/version.rb
CHANGED
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.10.
|
4
|
+
version: 0.10.4
|
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: 2022-
|
14
|
+
date: 2022-12-19 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -55,20 +55,6 @@ dependencies:
|
|
55
55
|
- - ">="
|
56
56
|
- !ruby/object:Gem::Version
|
57
57
|
version: 1.21.0
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: pry
|
60
|
-
requirement: !ruby/object:Gem::Requirement
|
61
|
-
requirements:
|
62
|
-
- - ">="
|
63
|
-
- !ruby/object:Gem::Version
|
64
|
-
version: 0.12.2
|
65
|
-
type: :runtime
|
66
|
-
prerelease: false
|
67
|
-
version_requirements: !ruby/object:Gem::Requirement
|
68
|
-
requirements:
|
69
|
-
- - ">="
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
version: 0.12.2
|
72
58
|
- !ruby/object:Gem::Dependency
|
73
59
|
name: rbi
|
74
60
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,7 +64,7 @@ dependencies:
|
|
78
64
|
version: 0.0.0
|
79
65
|
- - ">="
|
80
66
|
- !ruby/object:Gem::Version
|
81
|
-
version: 0.0.
|
67
|
+
version: 0.0.16
|
82
68
|
type: :runtime
|
83
69
|
prerelease: false
|
84
70
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -88,21 +74,21 @@ dependencies:
|
|
88
74
|
version: 0.0.0
|
89
75
|
- - ">="
|
90
76
|
- !ruby/object:Gem::Version
|
91
|
-
version: 0.0.
|
77
|
+
version: 0.0.16
|
92
78
|
- !ruby/object:Gem::Dependency
|
93
79
|
name: sorbet-static-and-runtime
|
94
80
|
requirement: !ruby/object:Gem::Requirement
|
95
81
|
requirements:
|
96
82
|
- - ">="
|
97
83
|
- !ruby/object:Gem::Version
|
98
|
-
version: 0.5.
|
84
|
+
version: 0.5.10187
|
99
85
|
type: :runtime
|
100
86
|
prerelease: false
|
101
87
|
version_requirements: !ruby/object:Gem::Requirement
|
102
88
|
requirements:
|
103
89
|
- - ">="
|
104
90
|
- !ruby/object:Gem::Version
|
105
|
-
version: 0.5.
|
91
|
+
version: 0.5.10187
|
106
92
|
- !ruby/object:Gem::Dependency
|
107
93
|
name: spoom
|
108
94
|
requirement: !ruby/object:Gem::Requirement
|
@@ -185,6 +171,7 @@ files:
|
|
185
171
|
- lib/tapioca/dsl/compilers/active_model_secure_password.rb
|
186
172
|
- lib/tapioca/dsl/compilers/active_record_associations.rb
|
187
173
|
- lib/tapioca/dsl/compilers/active_record_columns.rb
|
174
|
+
- lib/tapioca/dsl/compilers/active_record_delegated_types.rb
|
188
175
|
- lib/tapioca/dsl/compilers/active_record_enum.rb
|
189
176
|
- lib/tapioca/dsl/compilers/active_record_fixtures.rb
|
190
177
|
- lib/tapioca/dsl/compilers/active_record_relations.rb
|
@@ -206,6 +193,7 @@ files:
|
|
206
193
|
- lib/tapioca/dsl/compilers/smart_properties.rb
|
207
194
|
- lib/tapioca/dsl/compilers/state_machines.rb
|
208
195
|
- lib/tapioca/dsl/compilers/url_helpers.rb
|
196
|
+
- lib/tapioca/dsl/extensions/active_record.rb
|
209
197
|
- lib/tapioca/dsl/extensions/frozen_record.rb
|
210
198
|
- lib/tapioca/dsl/helpers/active_record_column_type_helper.rb
|
211
199
|
- lib/tapioca/dsl/helpers/active_record_constants_helper.rb
|