Skip to content

Commit

Permalink
Give aliases of .new methods correct type
Browse files Browse the repository at this point in the history
  • Loading branch information
soutaro committed Aug 24, 2022
1 parent 05406d7 commit d63521e
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
10 changes: 10 additions & 0 deletions lib/rbs/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,16 @@ def map_method_type(&block)
alias_of: alias_of
)
end

def update(super_method: self.super_method, defs: self.defs, accessibility: self.accessibility, alias_of: self.alias_of, annotations: self.annotations)
self.class.new(
super_method: super_method,
defs: defs,
accessibility: accessibility,
alias_of: alias_of,
annotations: annotations
)
end
end

module Ancestor
Expand Down
22 changes: 21 additions & 1 deletion lib/rbs/definition_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,17 @@ def build_singleton(type_name)
if entry.is_a?(Environment::ClassEntry)
new_method = definition.methods[:new]
if new_method.defs.all? {|d| d.defined_in == BuiltinNames::Class.name }
alias_methods = definition.methods.filter_map do |name, method|
# @type block: Symbol | nil | false
# @type var method: Definition::Method?
while method
if method.alias_of == new_method
break name
end
method = method.alias_of
end
end

# The method is _untyped new_.

instance = build_instance(type_name)
Expand All @@ -389,7 +400,7 @@ def build_singleton(type_name)

# Inject a virtual _typed new_.
initialize_defs = initialize.defs
definition.methods[:new] = Definition::Method.new(
typed_new = Definition::Method.new(
super_method: new_method,
defs: initialize_defs.map do |initialize_def|
method_type = initialize_def.type
Expand Down Expand Up @@ -442,6 +453,15 @@ def build_singleton(type_name)
annotations: [],
alias_of: nil
)

definition.methods[:new] = typed_new

alias_methods.each do |alias_name|
definition.methods[alias_name] = definition.methods[alias_name].update(
alias_of: typed_new,
defs: typed_new.defs
)
end
end
end
end
Expand Down
8 changes: 8 additions & 0 deletions sig/definition.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ module RBS
def map_type_bound: () { (AST::TypeParam::bound) -> AST::TypeParam::bound } -> Method

def map_method_type: () { (MethodType) -> MethodType } -> Method

def update: (
?super_method: Method?,
?defs: Array[TypeDef],
?accessibility: accessibility,
?alias_of: Method?,
?annotations: Array[AST::Annotation]
) -> Method
end

module Ancestor
Expand Down
31 changes: 31 additions & 0 deletions test/rbs/definition_builder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2163,4 +2163,35 @@ module M
end
end
end

def test_new_alias
SignatureManager.new do |manager|
manager.files.merge!(Pathname("foo.rbs") => <<-EOF)
class C
def initialize: (String) -> void
alias self.compile self.new
alias self.start self.compile
end
EOF
manager.build do |env|
builder = DefinitionBuilder.new(env: env)

builder.build_singleton(type_name("::C")).tap do |definition|
definition.methods[:new].tap do |a|
assert_equal ["(::String) -> ::C"], a.method_types.map(&:to_s)
end

definition.methods[:compile].tap do |a|
assert_equal ["(::String) -> ::C"], a.method_types.map(&:to_s)
end

definition.methods[:start].tap do |a|
assert_equal ["(::String) -> ::C"], a.method_types.map(&:to_s)
end
end
end
end
end
end

0 comments on commit d63521e

Please sign in to comment.