tapioca 0.16.3 → 0.16.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61d9bbc2b60ce6dda54eea3d826374ca132938ddcdcc8185a731124bbad31704
4
- data.tar.gz: 35aec9d2e19694a7737ff32b7a1d1863b24e255f327d87adbc42e435bcef048c
3
+ metadata.gz: 80c01f44b0600c3a471756da73e43322f23a951c8f3ebc15c922173a0ccf4d3c
4
+ data.tar.gz: c778cfa78b0494513f5ad329e432c534486c3ba75fcf83969462a874c7dc7654
5
5
  SHA512:
6
- metadata.gz: 0d09845c43897689c8b04ca565d22a9dc817fd8100276624ffc21a83538d3584e70909df6007aee6d360abbd63ff2842132db1346483d1faf9615500e4b3c988
7
- data.tar.gz: b6ec214e91ed9b14fea2eefc00e396c4ea45157995dfdc52f98494da9498025bfa033b807324757f877768819e68ff04ff32dd0e10f93642dbb48e89dcd77451
6
+ metadata.gz: f12a7fbe0d64109a5de03d8a98f564413bee79dc0db1ced8c1eaeae8dae73e68c73e8e76a188a06ddfefa333b11024d606359b7f706d13e15dacea081b0a19ea
7
+ data.tar.gz: 99ef8194c8dab5e776b591992aefa8b59b0b8e2d8927caecfc68d63bf7bb4c7687a92af772c6f8ac5fcfbdd8ebe1f9c1b748a2334b8207d233939d35d02d2b26
@@ -69,6 +69,17 @@ module Tapioca
69
69
  T::Array[String],
70
70
  )
71
71
 
72
+ TRANSITION_CALLBACKS =
73
+ T.let(
74
+ [
75
+ "on_transition",
76
+ "guard",
77
+ "after",
78
+ "success",
79
+ ].freeze,
80
+ T::Array[String],
81
+ )
82
+
72
83
  ConstantType = type_member { { fixed: T.all(T::Class[::AASM], ::AASM::ClassMethods) } }
73
84
 
74
85
  sig { override.void }
@@ -162,8 +173,37 @@ module Tapioca
162
173
  method,
163
174
  parameters: [
164
175
  create_opt_param("symbol", type: "T.nilable(Symbol)", default: "nil"),
165
- create_block_param("block", type: "T.nilable(T.proc.bind(#{constant_name}).void)"),
176
+ create_block_param(
177
+ "block",
178
+ type: "T.nilable(T.proc.bind(#{constant_name}).params(opts: T.untyped).void)",
179
+ ),
180
+ ],
181
+ )
182
+ end
183
+
184
+ event.create_method(
185
+ "transitions",
186
+ parameters: [
187
+ create_opt_param("definitions", default: "nil", type: "T.untyped"),
188
+ create_block_param("block", type: "T.nilable(T.proc.bind(PrivateAASMTransition).void)"),
189
+ ],
190
+ )
191
+ end
192
+
193
+ machine.create_class("PrivateAASMTransition", superclass_name: "AASM::Core::Transition") do |transition|
194
+ TRANSITION_CALLBACKS.each do |method|
195
+ return_type = "T.untyped"
196
+ return_type = "T::Boolean" if method == "guard"
197
+
198
+ transition.create_method(
199
+ method,
200
+ parameters: [
201
+ create_block_param(
202
+ "block",
203
+ type: "T.nilable(T.proc.bind(#{constant_name}).params(opts: T.untyped).void)",
204
+ ),
166
205
  ],
206
+ return_type: return_type,
167
207
  )
168
208
  end
169
209
  end
@@ -107,36 +107,12 @@ module Tapioca
107
107
 
108
108
  sig { params(name: String).returns(T::Boolean) }
109
109
  def valid_method_name?(name)
110
- # try to parse a method definition with this name
111
- iseq = RubyVM::InstructionSequence.compile("def #{name}; end", nil, nil, 0, false)
112
- # pull out the first operation in the instruction sequence and its first argument
113
- op, arg, _data = iseq.to_a.dig(-1, 0)
114
- # make sure that the operation is a method definition and the method that was
115
- # defined has the expected name, for example, for `def !foo; end` we don't get
116
- # a syntax error but instead get a method defined as `"foo"`
117
- op == :definemethod && arg == name.to_sym
118
- rescue SyntaxError
119
- false
110
+ Prism.parse_success?("def self.#{name}(a); end")
120
111
  end
121
112
 
122
113
  sig { params(name: String).returns(T::Boolean) }
123
114
  def valid_parameter_name?(name)
124
- sentinel_method_name = :sentinel_method_name
125
- # try to parse a method definition with this name as the name of a
126
- # keyword parameter. If we use a positional parameter, then parameter names
127
- # like `&` (and maybe others) will be treated like `def foo(&); end` and will
128
- # thus be considered valid. Using a required keyword parameter prevents that
129
- # confusion between Ruby syntax and parameter name.
130
- iseq = RubyVM::InstructionSequence.compile("def #{sentinel_method_name}(#{name}:); end", nil, nil, 0, false)
131
- # pull out the first operation in the instruction sequence and its first argument and data
132
- op, arg, data = iseq.to_a.dig(-1, 0)
133
- # make sure that:
134
- # 1. a method was defined, and
135
- # 2. the method has the expected method name, and
136
- # 3. the method has a keyword parameter with the expected name
137
- op == :definemethod && arg == sentinel_method_name && data.dig(11, :keyword, 0) == name.to_sym
138
- rescue SyntaxError
139
- false
115
+ Prism.parse_success?("def sentinel_method_name(#{name}:); end")
140
116
  end
141
117
  end
142
118
  end
@@ -23,6 +23,7 @@ require "tempfile"
23
23
  require "thor"
24
24
  require "yaml"
25
25
  require "yard-sorbet"
26
+ require "prism"
26
27
 
27
28
  require "tapioca/runtime/dynamic_mixin_compiler"
28
29
  require "tapioca/sorbet_ext/backcompat_patches"
@@ -178,13 +178,19 @@ module Tapioca
178
178
  end
179
179
 
180
180
  # Examines the call stack to identify the closest location where a "require" is performed
181
- # by searching for the label "<top (required)>". If none is found, it returns the location
181
+ # by searching for the label "<top (required)>" or "block in <class:...>" in the
182
+ # case of an ActiveSupport.on_load hook. If none is found, it returns the location
182
183
  # labeled "<main>", which is the original call site.
183
184
  sig { params(locations: T.nilable(T::Array[Thread::Backtrace::Location])).returns(String) }
184
185
  def resolve_loc(locations)
185
186
  return "" unless locations
186
187
 
187
- resolved_loc = locations.find { |loc| REQUIRED_FROM_LABELS.include?(loc.label) }
188
+ resolved_loc = locations.find do |loc|
189
+ label = loc.label
190
+ next unless label
191
+
192
+ REQUIRED_FROM_LABELS.include?(label) || label.start_with?("block in <class:")
193
+ end
188
194
  return "" unless resolved_loc
189
195
 
190
196
  resolved_loc.absolute_path || ""
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Tapioca
5
- VERSION = "0.16.3"
5
+ VERSION = "0.16.4"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tapioca
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.3
4
+ version: 0.16.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: 2024-10-03 00:00:00.000000000 Z
14
+ date: 2024-11-07 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -284,7 +284,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
284
284
  - !ruby/object:Gem::Version
285
285
  version: '0'
286
286
  requirements: []
287
- rubygems_version: 3.5.20
287
+ rubygems_version: 3.5.23
288
288
  signing_key:
289
289
  specification_version: 4
290
290
  summary: A Ruby Interface file generator for gems, core types and the Ruby standard