lib/tapioca/compilers/dsl/base.rb in tapioca-0.4.27 vs lib/tapioca/compilers/dsl/base.rb in tapioca-0.5.0
- old
+ new
@@ -1,17 +1,19 @@
# typed: strict
# frozen_string_literal: true
-require "parlour"
+require "tapioca/rbi_ext/model"
module Tapioca
module Compilers
module Dsl
class Base
extend T::Sig
extend T::Helpers
+ include Reflection
+
abstract!
sig { returns(T::Set[Module]) }
attr_reader :processable_constants
@@ -27,142 +29,154 @@
sig do
abstract
.type_parameters(:T)
.params(
- root: Parlour::RbiGenerator::Namespace,
+ tree: RBI::Tree,
constant: T.type_parameter(:T)
)
.void
end
- def decorate(root, constant); end
+ def decorate(tree, constant); end
sig { abstract.returns(T::Enumerable[Module]) }
def gather_constants; end
private
- SPECIAL_METHOD_NAMES = T.let(
- %w[! ~ +@ ** -@ * / % + - << >> & | ^ < <= => > >= == === != =~ !~ <=> [] []= `].freeze,
- T::Array[String]
- )
-
- sig { params(name: String).returns(T::Boolean) }
- def valid_method_name?(name)
- return true if SPECIAL_METHOD_NAMES.include?(name)
- !!name.match(/^[a-zA-Z_][[:word:]]*[?!=]?$/)
+ sig { returns(T::Enumerable[Class]) }
+ def all_classes
+ @all_classes = T.let(@all_classes, T.nilable(T::Enumerable[Class]))
+ @all_classes ||= T.cast(ObjectSpace.each_object(Class), T::Enumerable[Class]).each
end
- sig do
- params(
- namespace: Parlour::RbiGenerator::Namespace,
- name: String,
- options: T::Hash[T.untyped, T.untyped]
- ).void
+ sig { returns(T::Enumerable[Module]) }
+ def all_modules
+ @all_modules = T.let(@all_modules, T.nilable(T::Enumerable[Module]))
+ @all_modules ||= T.cast(ObjectSpace.each_object(Module), T::Enumerable[Module]).each
end
- def create_method(namespace, name, options = {})
- return unless valid_method_name?(name)
- T.unsafe(namespace).create_method(name, **options)
- end
- # Create a Parlour method inside `namespace` from its Ruby definition
+ # Get the types of each parameter from a method signature
sig do
params(
- namespace: Parlour::RbiGenerator::Namespace,
method_def: T.any(Method, UnboundMethod),
- class_method: T::Boolean
- ).void
+ signature: T.untyped # as `T::Private::Methods::Signature` is private
+ ).returns(T::Array[String])
end
- def create_method_from_def(namespace, method_def, class_method: false)
- create_method(
- namespace,
+ def parameters_types_from_signature(method_def, signature)
+ params = T.let([], T::Array[String])
+
+ return method_def.parameters.map { "T.untyped" } unless signature
+
+ # parameters types
+ signature.arg_types.each { |arg_type| params << arg_type[1].to_s }
+
+ # keyword parameters types
+ signature.kwarg_types.each { |_, kwarg_type| params << kwarg_type.to_s }
+
+ # rest parameter type
+ params << signature.rest_type.to_s if signature.has_rest
+
+ # special case `.void` in a proc
+ unless signature.block_name.nil?
+ params << signature.block_type.to_s.gsub("returns(<VOID>)", "void")
+ end
+
+ params
+ end
+
+ sig { params(scope: RBI::Scope, method_def: T.any(Method, UnboundMethod), class_method: T::Boolean).void }
+ def create_method_from_def(scope, method_def, class_method: false)
+ scope.create_method(
method_def.name.to_s,
- parameters: compile_method_parameters_to_parlour(method_def),
- return_type: compile_method_return_type_to_parlour(method_def),
+ parameters: compile_method_parameters_to_rbi(method_def),
+ return_type: compile_method_return_type_to_rbi(method_def),
class_method: class_method
)
end
- # Compile a Ruby method parameters into Parlour parameters
- sig do
- params(method_def: T.any(Method, UnboundMethod))
- .returns(T::Array[Parlour::RbiGenerator::Parameter])
+ sig { params(name: String, type: String).returns(RBI::TypedParam) }
+ def create_param(name, type:)
+ create_typed_param(RBI::Param.new(name), type)
end
- def compile_method_parameters_to_parlour(method_def)
+
+ sig { params(name: String, type: String, default: String).returns(RBI::TypedParam) }
+ def create_opt_param(name, type:, default:)
+ create_typed_param(RBI::OptParam.new(name, default), type)
+ end
+
+ sig { params(name: String, type: String).returns(RBI::TypedParam) }
+ def create_rest_param(name, type:)
+ create_typed_param(RBI::RestParam.new(name), type)
+ end
+
+ sig { params(name: String, type: String).returns(RBI::TypedParam) }
+ def create_kw_param(name, type:)
+ create_typed_param(RBI::KwParam.new(name), type)
+ end
+
+ sig { params(name: String, type: String, default: String).returns(RBI::TypedParam) }
+ def create_kw_opt_param(name, type:, default:)
+ create_typed_param(RBI::KwOptParam.new(name, default), type)
+ end
+
+ sig { params(name: String, type: String).returns(RBI::TypedParam) }
+ def create_kw_rest_param(name, type:)
+ create_typed_param(RBI::KwRestParam.new(name), type)
+ end
+
+ sig { params(name: String, type: String).returns(RBI::TypedParam) }
+ def create_block_param(name, type:)
+ create_typed_param(RBI::BlockParam.new(name), type)
+ end
+
+ sig { params(param: RBI::Param, type: String).returns(RBI::TypedParam) }
+ def create_typed_param(param, type)
+ RBI::TypedParam.new(param: param, type: type)
+ end
+
+ sig { params(method_def: T.any(Method, UnboundMethod)).returns(T::Array[RBI::TypedParam]) }
+ def compile_method_parameters_to_rbi(method_def)
signature = T::Private::Methods.signature_for_method(method_def)
method_def = signature.nil? ? method_def : signature.method
method_types = parameters_types_from_signature(method_def, signature)
method_def.parameters.each_with_index.map do |(type, name), index|
fallback_arg_name = "_arg#{index}"
name ||= fallback_arg_name
name = name.to_s.gsub(/&|\*/, fallback_arg_name) # avoid incorrect names from `delegate`
- method_type = method_types[index]
+ method_type = T.must(method_types[index])
case type
when :req
- ::Parlour::RbiGenerator::Parameter.new(name, type: method_type)
+ create_param(name, type: method_type)
when :opt
- ::Parlour::RbiGenerator::Parameter.new(name, type: method_type, default: 'T.unsafe(nil)')
+ create_opt_param(name, type: method_type, default: "T.unsafe(nil)")
when :rest
- ::Parlour::RbiGenerator::Parameter.new("*#{name}", type: method_type)
+ create_rest_param(name, type: method_type)
when :keyreq
- ::Parlour::RbiGenerator::Parameter.new("#{name}:", type: method_type)
+ create_kw_param(name, type: method_type)
when :key
- ::Parlour::RbiGenerator::Parameter.new("#{name}:", type: method_type, default: 'T.unsafe(nil)')
+ create_kw_opt_param(name, type: method_type, default: "T.unsafe(nil)")
when :keyrest
- ::Parlour::RbiGenerator::Parameter.new("**#{name}", type: method_type)
+ create_kw_rest_param(name, type: method_type)
when :block
- ::Parlour::RbiGenerator::Parameter.new("&#{name}", type: method_type)
+ create_block_param(name, type: method_type)
else
raise "Unknown type `#{type}`."
end
end
end
- # Compile a Ruby method return type into a Parlour type
- sig do
- params(method_def: T.any(Method, UnboundMethod))
- .returns(T.nilable(String))
- end
- def compile_method_return_type_to_parlour(method_def)
+ sig { params(method_def: T.any(Method, UnboundMethod)).returns(String) }
+ def compile_method_return_type_to_rbi(method_def)
signature = T::Private::Methods.signature_for_method(method_def)
- return_type = signature.nil? ? 'T.untyped' : signature.return_type.to_s
- # Map <VOID> to `nil` since `nil` means a `void` return for Parlour
- return_type = nil if return_type == "<VOID>"
+ return_type = signature.nil? ? "T.untyped" : name_of_type(signature.return_type)
+ return_type = "void" if return_type == "<VOID>"
# Map <NOT-TYPED> to `T.untyped`
return_type = "T.untyped" if return_type == "<NOT-TYPED>"
return_type
- end
-
- # Get the types of each parameter from a method signature
- sig do
- params(
- method_def: T.any(Method, UnboundMethod),
- signature: T.untyped # as `T::Private::Methods::Signature` is private
- ).returns(T::Array[String])
- end
- def parameters_types_from_signature(method_def, signature)
- params = T.let([], T::Array[String])
-
- return method_def.parameters.map { 'T.untyped' } unless signature
-
- # parameters types
- signature.arg_types.each { |arg_type| params << arg_type[1].to_s }
-
- # keyword parameters types
- signature.kwarg_types.each { |_, kwarg_type| params << kwarg_type.to_s }
-
- # rest parameter type
- params << signature.rest_type.to_s if signature.has_rest
-
- # special case `.void` in a proc
- unless signature.block_name.nil?
- params << signature.block_type.to_s.gsub('returns(<VOID>)', 'void')
- end
-
- params
end
end
end
end
end