tapioca 0.10.5 → 0.11.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.
- checksums.yaml +4 -4
- data/lib/tapioca/cli.rb +5 -1
- data/lib/tapioca/commands/annotations.rb +2 -0
- data/lib/tapioca/commands/configure.rb +1 -0
- data/lib/tapioca/commands/dsl.rb +17 -3
- data/lib/tapioca/dsl/compilers/aasm.rb +67 -15
- data/lib/tapioca/dsl/compilers/action_controller_helpers.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_columns.rb +3 -3
- data/lib/tapioca/dsl/compilers/active_record_relations.rb +117 -66
- data/lib/tapioca/dsl/compilers/active_record_scope.rb +1 -1
- data/lib/tapioca/dsl/compilers/active_record_secure_token.rb +74 -0
- data/lib/tapioca/dsl/compilers/graphql_input_object.rb +21 -1
- data/lib/tapioca/dsl/compilers/kredis.rb +130 -0
- data/lib/tapioca/dsl/extensions/active_record.rb +9 -0
- data/lib/tapioca/dsl/extensions/kredis.rb +114 -0
- data/lib/tapioca/dsl/helpers/active_record_constants_helper.rb +1 -0
- data/lib/tapioca/dsl/pipeline.rb +12 -5
- data/lib/tapioca/gem/listeners/sorbet_enums.rb +1 -1
- data/lib/tapioca/gem/pipeline.rb +14 -0
- data/lib/tapioca/loaders/loader.rb +93 -32
- data/lib/tapioca/rbi_ext/model.rb +1 -1
- data/lib/tapioca/runtime/attached_class_of_32.rb +20 -0
- data/lib/tapioca/runtime/attached_class_of_legacy.rb +27 -0
- data/lib/tapioca/runtime/reflection.rb +11 -10
- data/lib/tapioca/static/symbol_loader.rb +14 -14
- data/lib/tapioca/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f32d4fd559ee85f540926b3faa454aaf2ddd919b502438bf2deda24a4b04f855
|
4
|
+
data.tar.gz: 9368c2329923554e639310003630d36f9bf7a2f895df619cfe844dacd9a2c176
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c997e7598a5cef84e52935b0f9681ca636fef5fb866d30f1e6d19e2912ae38b5ec7499e69cde6cd147b4a723214d80abb109dbd523e48f143eae0b1edbefd46e
|
7
|
+
data.tar.gz: 33882ab5de1b8b43d775bdb20b0fab39d97ebe2ce7b346bb9828b64e27dd99bb7d46814ac441dd1b6b7aadb3b4aa02f93a652d4e6fa42c34ac83241eb9eb78d7
|
data/lib/tapioca/cli.rb
CHANGED
@@ -130,11 +130,15 @@ module Tapioca
|
|
130
130
|
type: :string,
|
131
131
|
desc: "The path to the Rails application",
|
132
132
|
default: "."
|
133
|
-
def dsl(*
|
133
|
+
def dsl(*constant_or_paths)
|
134
134
|
set_environment(options)
|
135
135
|
|
136
|
+
# Assume anything starting with a capital letter or colon is a class, otherwise a path
|
137
|
+
constants, paths = constant_or_paths.partition { |c| c =~ /\A[A-Z:]/ }
|
138
|
+
|
136
139
|
command = Commands::Dsl.new(
|
137
140
|
requested_constants: constants,
|
141
|
+
requested_paths: paths.map { |p| Pathname.new(p) },
|
138
142
|
outpath: Pathname.new(options[:outdir]),
|
139
143
|
only: options[:only],
|
140
144
|
exclude: options[:exclude],
|
@@ -189,6 +189,8 @@ module Tapioca
|
|
189
189
|
|
190
190
|
sig { params(name: String, content: String).returns(String) }
|
191
191
|
def add_header(name, content)
|
192
|
+
# WARNING: Changing this header could impact how GitHub determines if the file should be hidden:
|
193
|
+
# https://github.com/github/linguist/pull/6143
|
192
194
|
header = <<~COMMENT
|
193
195
|
# DO NOT EDIT MANUALLY
|
194
196
|
# This file was pulled from a central RBI files repository.
|
data/lib/tapioca/commands/dsl.rb
CHANGED
@@ -10,6 +10,7 @@ module Tapioca
|
|
10
10
|
sig do
|
11
11
|
params(
|
12
12
|
requested_constants: T::Array[String],
|
13
|
+
requested_paths: T::Array[Pathname],
|
13
14
|
outpath: Pathname,
|
14
15
|
only: T::Array[String],
|
15
16
|
exclude: T::Array[String],
|
@@ -27,6 +28,7 @@ module Tapioca
|
|
27
28
|
end
|
28
29
|
def initialize(
|
29
30
|
requested_constants:,
|
31
|
+
requested_paths:,
|
30
32
|
outpath:,
|
31
33
|
only:,
|
32
34
|
exclude:,
|
@@ -42,6 +44,7 @@ module Tapioca
|
|
42
44
|
app_root: "."
|
43
45
|
)
|
44
46
|
@requested_constants = requested_constants
|
47
|
+
@requested_paths = requested_paths
|
45
48
|
@outpath = outpath
|
46
49
|
@only = only
|
47
50
|
@exclude = exclude
|
@@ -63,7 +66,7 @@ module Tapioca
|
|
63
66
|
def list_compilers
|
64
67
|
Loaders::Dsl.load_application(
|
65
68
|
tapioca_path: @tapioca_path,
|
66
|
-
eager_load: @requested_constants.empty?,
|
69
|
+
eager_load: @requested_constants.empty? && @requested_paths.empty?,
|
67
70
|
app_root: @app_root,
|
68
71
|
)
|
69
72
|
|
@@ -101,6 +104,15 @@ module Tapioca
|
|
101
104
|
end
|
102
105
|
say("")
|
103
106
|
|
107
|
+
unless @requested_paths.empty?
|
108
|
+
constants_from_paths = Static::SymbolLoader.symbols_from_paths(@requested_paths).to_a
|
109
|
+
if constants_from_paths.empty?
|
110
|
+
say_error("\nWarning: No constants found in: #{@requested_paths.map(&:to_s).join(", ")}", :yellow)
|
111
|
+
end
|
112
|
+
|
113
|
+
@requested_constants += constants_from_paths
|
114
|
+
end
|
115
|
+
|
104
116
|
outpath = @should_verify ? Pathname.new(Dir.mktmpdir) : @outpath
|
105
117
|
rbi_files_to_purge = existing_rbi_filenames(@requested_constants)
|
106
118
|
|
@@ -153,6 +165,7 @@ module Tapioca
|
|
153
165
|
def create_pipeline
|
154
166
|
Tapioca::Dsl::Pipeline.new(
|
155
167
|
requested_constants: constantize(@requested_constants),
|
168
|
+
requested_paths: @requested_paths,
|
156
169
|
requested_compilers: constantize_compilers(@only),
|
157
170
|
excluded_compilers: constantize_compilers(@exclude),
|
158
171
|
error_handler: ->(error) {
|
@@ -167,8 +180,9 @@ module Tapioca
|
|
167
180
|
filenames = if requested_constants.empty?
|
168
181
|
Pathname.glob(path / "**/*.rbi")
|
169
182
|
else
|
170
|
-
requested_constants.
|
171
|
-
dsl_rbi_filename(constant_name)
|
183
|
+
requested_constants.filter_map do |constant_name|
|
184
|
+
filename = dsl_rbi_filename(constant_name)
|
185
|
+
filename if File.exist?(filename)
|
172
186
|
end
|
173
187
|
end
|
174
188
|
|
@@ -58,27 +58,67 @@ module Tapioca
|
|
58
58
|
T::Array[String],
|
59
59
|
)
|
60
60
|
|
61
|
+
# Taken directly from the AASM::Base class, here:
|
62
|
+
# https://github.com/aasm/aasm/blob/0e03746a2b86558ee1bf7bd7db873938cbb3b29b/lib/aasm/base.rb#L145-L171
|
63
|
+
GLOBAL_CALLBACKS =
|
64
|
+
T.let(
|
65
|
+
[
|
66
|
+
"after_all_transitions",
|
67
|
+
"after_all_transactions",
|
68
|
+
"before_all_transactions",
|
69
|
+
"before_all_events",
|
70
|
+
"after_all_events",
|
71
|
+
"error_on_all_events",
|
72
|
+
"ensure_on_all_events",
|
73
|
+
].freeze,
|
74
|
+
T::Array[String],
|
75
|
+
)
|
76
|
+
|
61
77
|
ConstantType = type_member { { fixed: T.all(::AASM::ClassMethods, Class) } }
|
62
78
|
|
63
79
|
sig { override.void }
|
64
80
|
def decorate
|
65
|
-
|
66
|
-
return
|
81
|
+
state_machine_store = ::AASM::StateMachineStore.fetch(constant)
|
82
|
+
return unless state_machine_store
|
83
|
+
|
84
|
+
state_machines = state_machine_store.machine_names.map { |n| constant.aasm(n) }
|
85
|
+
return if state_machines.all? { |m| m.states.empty? }
|
67
86
|
|
68
87
|
root.create_path(constant) do |model|
|
69
|
-
|
70
|
-
|
71
|
-
model.create_constant("STATE_#{state.name.upcase}", value: "T.let(T.unsafe(nil), Symbol)")
|
72
|
-
model.create_method("#{state.name}?", return_type: "T::Boolean")
|
73
|
-
end
|
88
|
+
state_machines.each do |state_machine|
|
89
|
+
namespace = state_machine.__send__(:namespace)
|
74
90
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
91
|
+
# Create all of the constants and methods for each state
|
92
|
+
state_machine.states.each do |state|
|
93
|
+
name = state.name
|
94
|
+
name = "#{namespace}_#{name}" if namespace
|
95
|
+
|
96
|
+
model.create_constant("STATE_#{name.upcase}", value: "T.let(T.unsafe(nil), Symbol)")
|
97
|
+
model.create_method("#{name}?", return_type: "T::Boolean")
|
98
|
+
end
|
99
|
+
|
100
|
+
# Create all of the methods for each event
|
101
|
+
parameters = [create_rest_param("opts", type: "T.untyped")]
|
102
|
+
state_machine.events.each do |event|
|
103
|
+
model.create_method(event.name.to_s, parameters: parameters)
|
104
|
+
model.create_method("#{event.name}!", parameters: parameters)
|
105
|
+
model.create_method("#{event.name}_without_validation!", parameters: parameters)
|
106
|
+
model.create_method("may_#{event.name}?", return_type: "T::Boolean")
|
107
|
+
|
108
|
+
# For events, if there's a namespace the default methods are created in addition to
|
109
|
+
# namespaced ones.
|
110
|
+
next unless namespace
|
111
|
+
|
112
|
+
name = "#{event.name}_#{namespace}"
|
113
|
+
|
114
|
+
model.create_method(name.to_s, parameters: parameters)
|
115
|
+
model.create_method("#{name}!", parameters: parameters)
|
116
|
+
model.create_method("may_#{name}?", return_type: "T::Boolean")
|
117
|
+
|
118
|
+
# There's no namespaced method created for `_without_validation`, so skip
|
119
|
+
# defining a method for:
|
120
|
+
# "#{name}_without_validation!"
|
121
|
+
end
|
82
122
|
end
|
83
123
|
|
84
124
|
# Create the overall state machine method, which will return an
|
@@ -106,6 +146,18 @@ module Tapioca
|
|
106
146
|
],
|
107
147
|
)
|
108
148
|
|
149
|
+
constant_name = name_of(constant)
|
150
|
+
|
151
|
+
GLOBAL_CALLBACKS.each do |method|
|
152
|
+
machine.create_method(
|
153
|
+
method,
|
154
|
+
parameters: [
|
155
|
+
create_opt_param("symbol", type: "T.nilable(Symbol)", default: "nil"),
|
156
|
+
create_block_param("block", type: "T.nilable(T.proc.bind(#{constant_name}).void)"),
|
157
|
+
],
|
158
|
+
)
|
159
|
+
end
|
160
|
+
|
109
161
|
# Create a private event class that we can pass around for the
|
110
162
|
# purpose of binding all of the callbacks without having to
|
111
163
|
# explicitly bind self in each one.
|
@@ -115,7 +167,7 @@ module Tapioca
|
|
115
167
|
method,
|
116
168
|
parameters: [
|
117
169
|
create_opt_param("symbol", type: "T.nilable(Symbol)", default: "nil"),
|
118
|
-
create_block_param("block", type: "T.nilable(T.proc.bind(#{
|
170
|
+
create_block_param("block", type: "T.nilable(T.proc.bind(#{constant_name}).void)"),
|
119
171
|
],
|
120
172
|
)
|
121
173
|
end
|
@@ -156,7 +156,7 @@ module Tapioca
|
|
156
156
|
sig { params(mod: Module).returns(T::Array[String]) }
|
157
157
|
def gather_includes(mod)
|
158
158
|
mod.ancestors
|
159
|
-
.reject { |ancestor| ancestor.is_a?(Class) || ancestor == mod || ancestor.
|
159
|
+
.reject { |ancestor| ancestor.is_a?(Class) || ancestor == mod || name_of(ancestor).nil? }
|
160
160
|
.map { |ancestor| T.must(qualified_name_of(ancestor)) }
|
161
161
|
.reverse
|
162
162
|
end
|
@@ -16,7 +16,8 @@ module Tapioca
|
|
16
16
|
# `Tapioca::Dsl::Compilers::ActiveRecordColumns` refines RBI files for subclasses of
|
17
17
|
# [`ActiveRecord::Base`](https://api.rubyonrails.org/classes/ActiveRecord/Base.html).
|
18
18
|
# This compiler is only responsible for defining the attribute methods that would be
|
19
|
-
# created for
|
19
|
+
# created for columns and virtual attributes that are defined in the Active Record
|
20
|
+
# model.
|
20
21
|
#
|
21
22
|
# For example, with the following model class:
|
22
23
|
# ~~~rb
|
@@ -109,8 +110,7 @@ module Tapioca
|
|
109
110
|
|
110
111
|
root.create_path(constant) do |model|
|
111
112
|
model.create_module(AttributeMethodsModuleName) do |mod|
|
112
|
-
constant.
|
113
|
-
column_name = column_name.to_s
|
113
|
+
constant.attribute_names.each do |column_name|
|
114
114
|
add_methods_for_attribute(mod, column_name)
|
115
115
|
end
|
116
116
|
|