Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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