Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ PATH
bundler (>= 2.2.25)
netrc (>= 0.11.0)
parallel (>= 1.21.0)
rbi (>= 0.3.7)
rbi (>= 0.4.1)
require-hooks (>= 0.2.2)
rubydex (>= 0.1.0.beta10)
sorbet-static-and-runtime (>= 0.6.12698)
Expand Down Expand Up @@ -307,7 +307,7 @@ GEM
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.4.2)
rbi (0.4.0)
rbi (0.4.1)
prism (~> 1.0)
rbs (>= 4.0.1)
rbs (4.1.0)
Expand Down Expand Up @@ -582,7 +582,7 @@ CHECKSUMS
railties (8.1.3) sha256=913eb0e0cb520aac687ffd74916bd726d48fa21f47833c6292576ef6a286de22
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
rbi (0.4.0) sha256=cb54fe8ba39c113e7c8ce93b411d2681cf9c67d95c2da779906d61d6ecb902d3
rbi (0.4.1) sha256=66611ca331b0b47d98607a7afda12ab44e0a98297d5393d4b93b846b9786d44d
rbs (4.1.0) sha256=8baba59008b0643b4ba2090e9b1d0149655b0bbd42eb2ffe42b1d0eb6923fd72
rdoc (7.2.0) sha256=8650f76cd4009c3b54955eb5d7e3a075c60a57276766ebf36f9085e8c9f23192
redis (5.4.0) sha256=798900d869418a9fc3977f916578375b45c38247a556b61d58cba6bb02f7d06b
Expand Down
20 changes: 11 additions & 9 deletions lib/tapioca/dsl/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -163,25 +163,27 @@ def compile_method_parameters_to_rbi(method_def)
parameters.each_with_index.map do |(type, name), index|
fallback_arg_name = "_arg#{index}"

name = name ? name.to_s : fallback_arg_name
name = fallback_arg_name unless valid_parameter_name?(name)
sig_name = name ? name.to_s : fallback_arg_name
is_anonymous_parameter = anonymous_parameter_name?(type, sig_name)
sig_name = fallback_arg_name unless is_anonymous_parameter || valid_parameter_name?(sig_name)
param_name = is_anonymous_parameter ? nil : sig_name
method_type = T.must(method_types[index])

case type
when :req
create_param(name, type: method_type)
create_param(sig_name, type: method_type)
when :opt
create_opt_param(name, type: method_type, default: "T.unsafe(nil)")
create_opt_param(sig_name, type: method_type, default: "T.unsafe(nil)")
when :rest
create_rest_param(name, type: method_type)
create_rest_param(param_name, type: method_type)
when :keyreq
create_kw_param(name, type: method_type)
create_kw_param(sig_name, type: method_type)
when :key
create_kw_opt_param(name, type: method_type, default: "T.unsafe(nil)")
create_kw_opt_param(sig_name, type: method_type, default: "T.unsafe(nil)")
when :keyrest
create_kw_rest_param(name, type: method_type)
create_kw_rest_param(param_name, type: method_type)
when :block
create_block_param(name, type: method_type)
create_block_param(param_name, type: method_type)
else
raise "Unknown type `#{type}`."
end
Expand Down
31 changes: 18 additions & 13 deletions lib/tapioca/gem/listeners/methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def compile_method(tree, symbol_name, constant, method, visibility = RBI::Public
sanitized_parameters = parameters.each_with_index.map do |(type, name), index|
fallback_arg_name = "_arg#{index}"

name = if name
sig_name = if name
name.to_s
else
# For attr_writer methods, Sorbet signatures have the name
Expand All @@ -126,10 +126,14 @@ def compile_method(tree, symbol_name, constant, method, visibility = RBI::Public
end
end

# Sanitize param names
name = fallback_arg_name unless valid_parameter_name?(name)
# Sanitize param names, except for anonymous splat, keyword splat,
# and block parameters. Ruby reflects those as `:*`, `:**`, and `:&`,
# and Sorbet signatures use the same names to store their types.
is_anonymous_parameter = anonymous_parameter_name?(type, sig_name)
sig_name = fallback_arg_name unless is_anonymous_parameter || valid_parameter_name?(sig_name)
param_name = is_anonymous_parameter ? nil : sig_name

[type, name]
[type, param_name, sig_name]
end

rbi_method = RBI::Method.new(
Expand All @@ -138,26 +142,27 @@ def compile_method(tree, symbol_name, constant, method, visibility = RBI::Public
visibility: visibility,
)

sanitized_parameters.each do |type, name|
sanitized_parameters.each do |type, param_name, _sig_name|
case type
when :req
rbi_method << RBI::ReqParam.new(name)
rbi_method << RBI::ReqParam.new(param_name)
when :opt
rbi_method << RBI::OptParam.new(name, "T.unsafe(nil)")
rbi_method << RBI::OptParam.new(param_name, "T.unsafe(nil)")
when :rest
rbi_method << RBI::RestParam.new(name)
rbi_method << RBI::RestParam.new(param_name)
when :keyreq
rbi_method << RBI::KwParam.new(name)
rbi_method << RBI::KwParam.new(param_name)
when :key
rbi_method << RBI::KwOptParam.new(name, "T.unsafe(nil)")
rbi_method << RBI::KwOptParam.new(param_name, "T.unsafe(nil)")
when :keyrest
rbi_method << RBI::KwRestParam.new(name)
rbi_method << RBI::KwRestParam.new(param_name)
when :block
rbi_method << RBI::BlockParam.new(name)
rbi_method << RBI::BlockParam.new(param_name)
end
end

@pipeline.push_method(symbol_name, constant, method, rbi_method, signature, sanitized_parameters)
parameters_for_signature = sanitized_parameters.map { |type, _param_name, sig_name| [type, sig_name] }
@pipeline.push_method(symbol_name, constant, method, rbi_method, signature, parameters_for_signature)
tree << rbi_method
end

Expand Down
20 changes: 17 additions & 3 deletions lib/tapioca/helpers/rbi_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def create_opt_param(name, type:, default:)
create_typed_param(RBI::OptParam.new(name, default), type)
end

#: (String name, type: String) -> RBI::TypedParam
#: (String? name, type: String) -> RBI::TypedParam
def create_rest_param(name, type:)
create_typed_param(RBI::RestParam.new(name), type)
end
Expand All @@ -52,12 +52,12 @@ def create_kw_opt_param(name, type:, default:)
create_typed_param(RBI::KwOptParam.new(name, default), type)
end

#: (String name, type: String) -> RBI::TypedParam
#: (String? name, type: String) -> RBI::TypedParam
def create_kw_rest_param(name, type:)
create_typed_param(RBI::KwRestParam.new(name), type)
end

#: (String name, type: String) -> RBI::TypedParam
#: (String? name, type: String) -> RBI::TypedParam
def create_block_param(name, type:)
create_typed_param(RBI::BlockParam.new(name), type)
end
Expand Down Expand Up @@ -110,5 +110,19 @@ def valid_method_name?(name)
def valid_parameter_name?(name)
Prism.parse_success?("def sentinel_method_name(#{name}:); end")
end

#: (Symbol type, String name) -> bool
def anonymous_parameter_name?(type, name)
case type
when :rest
name == "*"
when :keyrest
name == "**"
when :block
name == "&"
else
false
end
end
end
end
2 changes: 1 addition & 1 deletion lib/tapioca/helpers/sorbet_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def sorbet(*sorbet_args)

#: (String, rbi_mode: bool) { (String stderr) -> void } -> void
def sorbet_syntax_check!(source, rbi_mode:, &on_failure)
quoted_source = "\"#{source}\""
quoted_source = source.shellescape

result = if rbi_mode
# --e-rbi cannot be used on its own, so we pass a dummy value like `-e ""`
Expand Down
18 changes: 16 additions & 2 deletions lib/tapioca/rbi_ext/model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,10 @@ def create_method(name, parameters: [], return_type: nil, class_method: false, v
if !block || !parameters.empty? || return_type
# If there is no block, and the params and return type have not been supplied, then
# we create a single signature with the given parameters and return type
params = parameters.map { |param| RBI::SigParam.new(param.param.name.to_s, param.type) }
return_type ||= "T.untyped"
type_params = Tapioca::RBIHelper.extract_type_parameters(parameters.map(&:type).append(return_type))

sig = RBI::Sig.new(params: params, return_type: return_type, type_params: type_params)
sig = RBI::Sig.new(params: parameters.map(&:to_sig_param), return_type: return_type, type_params: type_params)
sigs << sig
end

Expand Down Expand Up @@ -117,5 +116,20 @@ def create_node(node)
class TypedParam < T::Struct
const :param, RBI::Param
const :type, String

#: -> RBI::SigParam
def to_sig_param
name = case param
when RestParam
param.anonymous? ? "*".inspect : param.name.to_s
when KwRestParam
param.anonymous? ? "**".inspect : param.name.to_s
when BlockParam
param.anonymous? ? "&".inspect : param.name.to_s
else
param.name.to_s
end
RBI::SigParam.new(name, type)
end
end
end
Loading
Loading