Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2c8326a
Start using type builder from RBI gem
paracycle Jun 9, 2023
c45335f
Refactor protobuf DSL compiler to use type builder
paracycle Jun 9, 2023
45ebbfc
Refactor Smart Properties DSL compiler to use type builder
paracycle Jun 9, 2023
08679ce
Refactor Active Model Attributes DSL compiler to use type builder
paracycle Jun 9, 2023
aeec8ff
Refactor Active Record Associations DSL compiler to use type builder
paracycle Jun 9, 2023
7d9eae1
Refactor Active Record Columns DSL compiler to use type builder
paracycle Jun 9, 2023
5b884d5
Refactor Identity Cache DSL compiler to use type builder
paracycle Jun 9, 2023
b04266f
Refactor Active Record Delegated Types DSL compiler to use type builder
paracycle Jun 9, 2023
17ad5d0
Refactor AASM DSL compiler to use type builder
paracycle Jun 9, 2023
0b1e4bf
Refactor Action Controller Helpers compiler to use type builder
paracycle Jun 9, 2023
7987d02
Refactor Action Record Typed Store compiler to use type builder
paracycle Jun 9, 2023
d52d8ac
Refactor Rails Generators compiler to use type builder
paracycle Jun 9, 2023
f445bcc
Refactor GraphQL DSL compilers to use type builder
paracycle Jun 15, 2023
354428d
Refactor Active Record Relations DSL compiler to use type builder
paracycle Jan 15, 2026
10d0972
Refactor Action Mailer DSL compiler to use type builder
paracycle Jun 15, 2023
7de3bfd
Refactor Active Job DSL compiler to use type builder
paracycle Jun 15, 2023
dc43ba7
Refactor Active Record Enum DSL compiler to use type builder
paracycle Jun 15, 2023
4abfa7c
Refactor Active Record Fixtures DSL compiler to use type builder
paracycle Jun 15, 2023
7e6cb03
Refactor Active Record Scope DSL compiler to use type builder
paracycle Jun 15, 2023
ee9b61f
Refactor Active Record Secure Token DSL compiler to use type builder
paracycle Jun 15, 2023
8570d80
Refactor Active Resource DSL compiler to use type builder
paracycle Jun 15, 2023
326e990
Refactor Active Storage DSL compiler to use type builder
paracycle Jun 15, 2023
dca2e85
Refactor Active Support Current Attributes DSL compiler to use type b…
paracycle Jun 15, 2023
92455c2
Refactor Config DSL compiler to use type builder
paracycle Jun 15, 2023
7db52dd
Refactor Frozen Record DSL compiler to use type builder
paracycle Jun 15, 2023
f5f773c
Refactor Kredis DSL compiler to use type builder
paracycle Jun 15, 2023
7ab7d7f
Refactor Sidekiq Worker DSL compiler to use type builder
paracycle Jun 15, 2023
320b447
Refactor State Machines DSL compiler to use type builder
paracycle Jun 15, 2023
7b5d5e6
Refactor URL Helpers DSL compiler to use type builder
paracycle Jun 15, 2023
3bf901a
Refactor JSON API Client Resource DSL compiler to use type builder
paracycle Jan 15, 2026
491bc01
Refactor Active Record Store DSL compiler to use type builder
paracycle Jan 15, 2026
768e97b
Refactor Active Model Secure Password DSL compiler to use type builder
paracycle Jan 15, 2026
fad96a5
Refactor Active Model Validations Confirmation DSL compiler to use ty…
paracycle Jan 15, 2026
bf1a2db
Refactor Active Support Time Ext DSL compiler to use type builder
paracycle Jan 15, 2026
e0671f7
Refactor Action Text DSL compiler to use type builder
paracycle Jan 15, 2026
31fd096
Refactor Active Support Environment Inquirer DSL compiler to use type…
paracycle Jan 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions lib/tapioca/dsl/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,27 +111,29 @@ def add_error(error)
private

# Get the types of each parameter from a method signature
#: ((Method | UnboundMethod) method_def, untyped signature) -> Array[String]
#: ((Method | UnboundMethod) method_def, untyped signature) -> Array[RBI::Type]
def parameters_types_from_signature(method_def, signature)
params = [] #: Array[String]
params = [] #: Array[RBI::Type]

return method_def.parameters.map { "T.untyped" } unless signature
return method_def.parameters.map { RBI::Type.untyped } unless signature

# parameters types
signature.arg_types.each { |arg_type| params << arg_type[1].to_s }
signature.arg_types.each { |arg_type| params << RBI::Type.parse_string(sanitize_signature_types(arg_type[1].to_s)) }

# keyword parameters types
signature.kwarg_types.each { |_, kwarg_type| params << kwarg_type.to_s }
signature.kwarg_types.each do |_, kwarg_type|
params << RBI::Type.parse_string(sanitize_signature_types(kwarg_type.to_s))
end

# rest parameter type
params << signature.rest_type.to_s if signature.has_rest
params << RBI::Type.parse_string(sanitize_signature_types(signature.rest_type.to_s)) if signature.has_rest

# keyrest parameter type
params << signature.keyrest_type.to_s if signature.has_keyrest
params << RBI::Type.parse_string(sanitize_signature_types(signature.keyrest_type.to_s)) if signature.has_keyrest

# special case `.void` in a proc
unless signature.block_name.nil?
params << signature.block_type.to_s.gsub("returns(<VOID>)", "void")
params << RBI::Type.parse_string(sanitize_signature_types(signature.block_type.to_s))
end

params
Expand Down Expand Up @@ -183,11 +185,14 @@ def compile_method_parameters_to_rbi(method_def)
end
end

#: ((Method | UnboundMethod) method_def) -> String
#: ((Method | UnboundMethod) method_def) -> RBI::Type
def compile_method_return_type_to_rbi(method_def)
signature = signature_of(method_def)
return_type = signature.nil? ? "T.untyped" : name_of_type(signature.return_type)
sanitize_signature_types(return_type)
if signature.nil?
RBI::Type.untyped
else
RBI::Type.parse_string(sanitize_signature_types(name_of_type(signature.return_type)))
end
end
end
end
Expand Down
57 changes: 37 additions & 20 deletions lib/tapioca/dsl/compilers/aasm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,17 @@ def decorate
name = state.name
name = "#{namespace}_#{name}" if namespace

model.create_constant("STATE_#{name.upcase}", value: "T.let(T.unsafe(nil), Symbol)")
model.create_method("#{name}?", return_type: "T::Boolean")
model.create_constant("STATE_#{name.upcase}", value: "T.let(T.unsafe(nil), ::Symbol)")
model.create_method("#{name}?", return_type: RBI::Type.boolean)
end

# Create all of the methods for each event
parameters = [create_rest_param("opts", type: "T.untyped")]
parameters = [create_rest_param("opts", type: RBI::Type.untyped)]
state_machine.events.each do |event|
model.create_method(event.name.to_s, parameters: parameters)
model.create_method("#{event.name}!", parameters: parameters)
model.create_method("#{event.name}_without_validation!", parameters: parameters)
model.create_method("may_#{event.name}?", return_type: "T::Boolean")
model.create_method("may_#{event.name}?", return_type: RBI::Type.boolean)

# For events, if there's a namespace the default methods are created in addition to
# namespaced ones.
Expand All @@ -105,7 +105,7 @@ def decorate

model.create_method(name.to_s, parameters: parameters)
model.create_method("#{name}!", parameters: parameters)
model.create_method("may_#{name}?", return_type: "T::Boolean")
model.create_method("may_#{name}?", return_type: RBI::Type.boolean)

# There's no namespaced method created for `_without_validation`, so skip
# defining a method for:
Expand All @@ -118,10 +118,13 @@ def decorate
model.create_method(
"aasm",
parameters: [
create_rest_param("args", type: "T.untyped"),
create_block_param("block", type: "T.nilable(T.proc.bind(PrivateAASMMachine).void)"),
create_rest_param("args", type: RBI::Type.untyped),
create_block_param(
"block",
type: RBI::Type.proc.bind(RBI::Type.simple("PrivateAASMMachine")).void.nilable,
),
],
return_type: "PrivateAASMMachine",
return_type: RBI::Type.simple("PrivateAASMMachine"),
class_method: true,
)

Expand All @@ -132,9 +135,12 @@ def decorate
machine.create_method(
"event",
parameters: [
create_param("name", type: "T.untyped"),
create_opt_param("options", default: "nil", type: "T.untyped"),
create_block_param("block", type: "T.proc.bind(PrivateAASMEvent).void"),
create_param("name", type: RBI::Type.untyped),
create_opt_param("options", default: "nil", type: RBI::Type.untyped),
create_block_param(
"block",
type: RBI::Type.proc.bind("PrivateAASMEvent").void,
),
],
)

Expand All @@ -144,8 +150,19 @@ def decorate
machine.create_method(
method,
parameters: [
create_rest_param("callbacks", type: "T.any(String, Symbol, T::Class[T.anything], Proc)"),
create_block_param("block", type: "T.nilable(T.proc.bind(#{constant_name}).void)"),
create_rest_param(
"callbacks",
type: RBI::Type.any(
RBI::Type.simple("String"),
RBI::Type.simple("Symbol"),
RBI::Type.t_class(RBI::Type.anything),
RBI::Type.proc,
),
),
create_block_param(
"block",
type: RBI::Type.proc.bind(constant_name).void.nilable,
),
],
)
end
Expand All @@ -158,10 +175,10 @@ def decorate
event.create_method(
method,
parameters: [
create_opt_param("symbol", type: "T.nilable(Symbol)", default: "nil"),
create_opt_param("symbol", type: RBI::Type.simple("::Symbol").nilable, default: "nil"),
create_block_param(
"block",
type: "T.nilable(T.proc.bind(#{constant_name}).params(opts: T.untyped).void)",
type: RBI::Type.proc.bind(constant_name).params(opts: RBI::Type.untyped).void.nilable,
),
],
)
Expand All @@ -170,23 +187,23 @@ def decorate
event.create_method(
"transitions",
parameters: [
create_opt_param("definitions", default: "nil", type: "T.untyped"),
create_block_param("block", type: "T.nilable(T.proc.bind(PrivateAASMTransition).void)"),
create_opt_param("definitions", default: "nil", type: RBI::Type.untyped),
create_block_param("block", type: RBI::Type.proc.bind("PrivateAASMTransition").void.nilable),
],
)
end

machine.create_class("PrivateAASMTransition", superclass_name: "AASM::Core::Transition") do |transition|
TRANSITION_CALLBACKS.each do |method|
return_type = "T.untyped"
return_type = "T::Boolean" if method == "guard"
return_type = RBI::Type.untyped
return_type = RBI::Type.boolean if method == "guard"

transition.create_method(
method,
parameters: [
create_block_param(
"block",
type: "T.nilable(T.proc.bind(#{constant_name}).params(opts: T.untyped).void)",
type: RBI::Type.proc.bind(constant_name).params(opts: RBI::Type.untyped).void.nilable,
),
],
return_type: return_type,
Expand Down
10 changes: 5 additions & 5 deletions lib/tapioca/dsl/compilers/action_controller_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def decorate

# Define the helpers method
root.create_path(constant) do |controller|
controller.create_method("helpers", return_type: helper_proxy_name)
controller.create_method("helpers", return_type: RBI::Type.simple(helper_proxy_name))

# Create helper method module
controller.create_module(helper_methods_name) do |helper_methods|
Expand Down Expand Up @@ -140,11 +140,11 @@ def create_unknown_proxy_method(helper_methods, method_name)
helper_methods.create_method(
method_name.to_s,
parameters: [
create_rest_param("args", type: "T.untyped"),
create_kw_rest_param("kwargs", type: "T.untyped"),
create_block_param("blk", type: "T.untyped"),
create_rest_param("args", type: RBI::Type.untyped),
create_kw_rest_param("kwargs", type: RBI::Type.untyped),
create_block_param("blk", type: RBI::Type.untyped),
],
return_type: "T.untyped",
return_type: RBI::Type.untyped,
)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/tapioca/dsl/compilers/action_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def decorate
mailer.create_method(
mailer_method,
parameters: parameters,
return_type: "::ActionMailer::MessageDelivery",
return_type: RBI::Type.simple("::ActionMailer::MessageDelivery"),
class_method: true,
)
end
Expand Down
9 changes: 5 additions & 4 deletions lib/tapioca/dsl/compilers/action_text.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,21 @@ def decorate
root.create_path(constant) do |scope|
self.class.action_text_associations(constant).each do |name|
reflection = constant.reflections.fetch(name)
type = reflection.options.fetch(:class_name)
type = RBI::Type.simple(reflection.options.fetch(:class_name))
name = reflection.name.to_s.sub("rich_text_", "")

scope.create_method(
name,
return_type: type,
)
scope.create_method(
"#{name}?",
return_type: "T::Boolean",
return_type: RBI::Type.boolean,
)
scope.create_method(
"#{name}=",
parameters: [create_param("value", type: "T.nilable(T.any(#{type}, String))")],
return_type: "T.untyped",
parameters: [create_param("value", type: RBI::Type.any(type, RBI::Type.simple("::String")).nilable)],
return_type: RBI::Type.untyped,
)
end
end
Expand Down
7 changes: 5 additions & 2 deletions lib/tapioca/dsl/compilers/active_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ def decorate
job.create_method(
"perform_later",
parameters: perform_later_parameters(parameters, constant_name),
return_type: "T.any(#{constant_name}, FalseClass)",
return_type: RBI::Type.any(
RBI::Type.simple(T.must(qualified_name_of(constant))),
RBI::Type.simple("::FalseClass"),
),
class_method: true,
)

Expand All @@ -75,7 +78,7 @@ def perform_later_parameters(parameters, constant_name)
parameters.reject! { |typed_param| RBI::BlockParam === typed_param.param }
parameters + [create_block_param(
"block",
type: "T.nilable(T.proc.params(job: #{constant_name}).void)",
type: RBI::Type.proc.params(job: RBI::Type.simple(constant_name)).void.nilable,
)]
else
parameters
Expand Down
24 changes: 12 additions & 12 deletions lib/tapioca/dsl/compilers/active_model_attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def gather_constants

HANDLED_METHOD_TARGETS = ["attribute", "attribute="] #: Array[String]

#: -> Array[[::String, ::String]]
#: -> Array[[::String, ::RBI::Type]]
def attribute_methods_for_constant
patterns = if constant.respond_to?(:attribute_method_patterns)
# https://github.com/rails/rails/pull/44367
Expand Down Expand Up @@ -102,31 +102,31 @@ def handle_method_pattern?(pattern)
HANDLED_METHOD_TARGETS.include?(target.to_s)
end

#: (untyped attribute_type_value) -> ::String
#: (untyped attribute_type_value) -> ::RBI::Type
def type_for(attribute_type_value)
case attribute_type_value
when ActiveModel::Type::Boolean
as_nilable_type("T::Boolean")
RBI::Type.boolean.nilable
when ActiveModel::Type::Date
as_nilable_type("::Date")
RBI::Type.simple("::Date").nilable
when ActiveModel::Type::DateTime, ActiveModel::Type::Time
as_nilable_type("::Time")
RBI::Type.simple("::Time").nilable
when ActiveModel::Type::Decimal
as_nilable_type("::BigDecimal")
RBI::Type.simple("::BigDecimal").nilable
when ActiveModel::Type::Float
as_nilable_type("::Float")
RBI::Type.simple("::Float").nilable
when ActiveModel::Type::Integer
as_nilable_type("::Integer")
RBI::Type.simple("::Integer").nilable
when ActiveModel::Type::String
as_nilable_type("::String")
RBI::Type.simple("::String").nilable
else
type = Helpers::ActiveModelTypeHelper.type_for(attribute_type_value)
type = as_nilable_type(type) if Helpers::ActiveModelTypeHelper.assume_nilable?(attribute_type_value)
type = RBI::Type.parse_string(Helpers::ActiveModelTypeHelper.type_for(attribute_type_value))
type = type.nilable if Helpers::ActiveModelTypeHelper.assume_nilable?(attribute_type_value)
type
end
end

#: (RBI::Scope klass, String method, String type) -> void
#: (RBI::Scope klass, String method, RBI::Type type) -> void
def generate_method(klass, method, type)
if method.end_with?("=")
parameter = create_param("value", type: type)
Expand Down
4 changes: 2 additions & 2 deletions lib/tapioca/dsl/compilers/active_model_secure_password.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ def decorate
if method == :authenticate || method.start_with?("authenticate_")
klass.create_method(
method.to_s,
parameters: [create_param("unencrypted_password", type: "T.untyped")],
return_type: "T.any(#{constant}, FalseClass)",
parameters: [create_param("unencrypted_password", type: RBI::Type.untyped)],
return_type: RBI::Type.any(RBI::Type.simple(T.must(qualified_name_of(constant))), RBI::Type.boolean),
)
else
create_method_from_def(klass, constant.instance_method(method))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ def decorate
# Create RBI definitions for all the attributes that use confirmation validation
confirmation_validators.each do |validator|
validator.attributes.each do |attr_name|
klass.create_method("#{attr_name}_confirmation", return_type: "T.untyped")
klass.create_method("#{attr_name}_confirmation", return_type: RBI::Type.untyped)
klass.create_method(
"#{attr_name}_confirmation=",
parameters: [create_param("#{attr_name}_confirmation", type: "T.untyped")],
return_type: "T.untyped",
parameters: [create_param("#{attr_name}_confirmation", type: RBI::Type.untyped)],
return_type: RBI::Type.untyped,
)
end
end
Expand Down
Loading
Loading