Skip to content
Merged
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
1 change: 1 addition & 0 deletions lib/rbs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
require "rbs/ast/ruby/helpers/constant_helper"
require "rbs/ast/ruby/helpers/location_helper"
require "rbs/ast/ruby/declarations"
require "rbs/ast/ruby/members"
require "rbs/source"
require "rbs/inline_parser"
require "rbs/environment"
Expand Down
57 changes: 57 additions & 0 deletions lib/rbs/ast/ruby/members.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

module RBS
module AST
module Ruby
module Members
class Base
attr_reader :buffer

def initialize(buffer)
@buffer = buffer
end

include Helpers::LocationHelper
end

class DefMember < Base
Overload = AST::Members::MethodDefinition::Overload

attr_reader :name
attr_reader :node

def initialize(buffer, name, node)
super(buffer)
@name = name
@node = node
end

def location
rbs_location(node.location)
end

def overloads
method_type = MethodType.new(
type_params: [],
type: Types::UntypedFunction.new(return_type: Types::Bases::Any.new(location: nil)),
block: nil,
location: nil
)

[
Overload.new(method_type: method_type, annotations: [])
]
end

def overloading?
false
end

def annotations
[]
end
end
end
end
end
end
7 changes: 6 additions & 1 deletion lib/rbs/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ def hash
end

def comment
member.comment
case member
when AST::Members::Base
member.comment
when AST::Ruby::Members::Base
nil
end
end

def update(type: self.type, member: self.member, defined_in: self.defined_in, implemented_in: self.implemented_in)
Expand Down
31 changes: 31 additions & 0 deletions lib/rbs/definition_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,37 @@ def define_method(methods, definition, method, subst, self_type_methods, defined
)

method_definition.annotations.replace(original.annotations)
when AST::Ruby::Members::DefMember
if duplicated_method = methods[method.name]
raise DuplicatedMethodDefinitionError.new(
type: definition.self_type,
method_name: method.name,
members: [original, *duplicated_method.members]
)
end

defs = original.overloads.map do |overload|
Definition::Method::TypeDef.new(
type: subst.empty? ? overload.method_type : overload.method_type.sub(subst),
member: original,
defined_in: defined_in,
implemented_in: implemented_in
).tap do |type_def|
# Keep the original annotations given to overloads.
type_def.overload_annotations.replace(overload.annotations)
end
end

method_definition = Definition::Method.new(
super_method: existing_method,
defs: defs,
accessibility: :public,
alias_of: nil,
alias_member: nil
)

method_definition.annotations.replace([])

when nil
# Overloading method definition only

Expand Down
15 changes: 14 additions & 1 deletion lib/rbs/definition_builder/method_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ def build_instance(type_name)
Methods.new(type: type).tap do |methods|
entry.each_decl do |decl|
subst = Substitution.build(decl.type_params.each.map(&:name), args)
if decl.is_a?(AST::Declarations::Base)
case decl
when AST::Declarations::Base
each_rbs_member_with_accessibility(decl.members) do |member, accessibility|
case member
when AST::Members::MethodDefinition
Expand Down Expand Up @@ -138,6 +139,18 @@ def build_instance(type_name)
end
end
end
when AST::Ruby::Declarations::Base
decl.members.each do |member|
case member
when AST::Ruby::Members::DefMember
build_method(
methods,
type,
member: member,
accessibility: :public
)
end
end
end
end
end.validate!
Expand Down
2 changes: 2 additions & 0 deletions lib/rbs/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,8 @@ def resolve_ruby_decl(resolver, decl, context:, prefix:)
case member
when AST::Ruby::Declarations::Base
resolved.members << resolve_ruby_decl(resolver, member, context: inner_context, prefix: inner_prefix)
when AST::Ruby::Members::Base
resolved.members << member
else
raise "Unknown member type: #{member.class}"
end
Expand Down
23 changes: 23 additions & 0 deletions lib/rbs/inline_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ def initialize(location, message)
end
end

NotImplementedYet = _ = Class.new(Base)
NonConstantClassName = _ = Class.new(Base)
NonConstantModuleName = _ = Class.new(Base)
TopLevelMethodDefinition = _ = Class.new(Base)
end

def self.parse(buffer, prism)
Expand Down Expand Up @@ -101,6 +103,27 @@ def visit_module_node(node)
end
end

def visit_def_node(node)
if node.receiver
diagnostics << Diagnostic::NotImplementedYet.new(
rbs_location(node.receiver.location),
"Singleton method definition is not supported yet"
)
return
end

case current = current_module
when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node)
current.members << defn
else
diagnostics << Diagnostic::TopLevelMethodDefinition.new(
rbs_location(node.name_loc),
"Top-level method definition is not supported"
)
end
end

def insert_declaration(decl)
if current_module
current_module.members << decl
Expand Down
4 changes: 2 additions & 2 deletions sig/ast/ruby/declarations.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module RBS
end

class ClassDecl < Base
type member = t
type member = t | Members::t

attr_reader class_name: TypeName

Expand All @@ -35,7 +35,7 @@ module RBS
end

class ModuleDecl < Base
type member = t
type member = t | Members::t

attr_reader module_name: TypeName

Expand Down
34 changes: 34 additions & 0 deletions sig/ast/ruby/members.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module RBS
module AST
module Ruby
module Members
class Base
attr_reader buffer: Buffer

def initialize: (Buffer) -> void

include Helpers::LocationHelper
end

type t = DefMember

class DefMember < Base
class Overload = AST::Members::MethodDefinition::Overload

attr_reader name: Symbol
attr_reader node: Prism::DefNode

def initialize: (Buffer, Symbol name, Prism::DefNode node) -> void

def location: () -> Location

def overloads: () -> Array[Overload]

def overloading?: () -> bool

def annotations: () -> Array[AST::Annotation]
end
end
end
end
end
1 change: 1 addition & 0 deletions sig/definition.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module RBS

class Method
type method_member = AST::Members::MethodDefinition | AST::Members::AttrReader | AST::Members::AttrAccessor | AST::Members::AttrWriter
| AST::Ruby::Members::DefMember

class TypeDef
attr_reader type: MethodType
Expand Down
6 changes: 4 additions & 2 deletions sig/errors.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -226,12 +226,14 @@ module RBS
class InvalidOverloadMethodError < DefinitionError
include DetailedMessageable

type member = AST::Members::MethodDefinition | AST::Ruby::Members::DefMember

attr_reader type_name: TypeName
attr_reader method_name: Symbol
attr_reader kind: :instance | :singleton
attr_reader members: Array[AST::Members::MethodDefinition]
attr_reader members: Array[member]

def initialize: (type_name: TypeName, method_name: Symbol, kind: :instance | :singleton, members: Array[AST::Members::MethodDefinition]) -> void
def initialize: (type_name: TypeName, method_name: Symbol, kind: :instance | :singleton, members: Array[member]) -> void

def location: () -> AST::Members::MethodDefinition::loc?
end
Expand Down
10 changes: 9 additions & 1 deletion sig/inline_parser.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,21 @@ module RBS
def initialize: (Location, String) -> void
end

class NotImplementedYet < Base
end

class NonConstantClassName < Base
end

class NonConstantModuleName < Base
end

type t = NonConstantClassName | NonConstantModuleName
class TopLevelMethodDefinition < Base
end

type t = NotImplementedYet
| NonConstantClassName | NonConstantModuleName
| TopLevelMethodDefinition
end

def self.parse: (Buffer, Prism::ParseResult) -> Result
Expand Down
9 changes: 6 additions & 3 deletions sig/method_builder.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ module RBS
#
class Definition
type original = AST::Members::MethodDefinition | AST::Members::Alias | AST::Members::AttrAccessor | AST::Members::AttrWriter | AST::Members::AttrReader
| AST::Ruby::Members::DefMember

type overloading_definition = AST::Members::MethodDefinition | AST::Ruby::Members::DefMember

type accessibility = RBS::Definition::accessibility

attr_reader name: Symbol
attr_reader type: instance_type
attr_reader originals: Array[original]
attr_reader overloads: Array[AST::Members::MethodDefinition]
attr_reader overloads: Array[overloading_definition]
attr_reader accessibilities: Array[accessibility]

def initialize: (name: Symbol, type: instance_type, originals: Array[original], overloads: Array[AST::Members::MethodDefinition], accessibilities: Array[accessibility]) -> void
def initialize: (name: Symbol, type: instance_type, originals: Array[original], overloads: Array[overloading_definition], accessibilities: Array[accessibility]) -> void

def original: () -> original?

Expand Down Expand Up @@ -74,7 +77,7 @@ module RBS

def build_attribute: (Methods, Methods::instance_type, member: AST::Members::AttrAccessor | AST::Members::AttrReader | AST::Members::AttrWriter, accessibility: Definition::accessibility) -> void

def build_method: (Methods, Methods::instance_type, member: AST::Members::MethodDefinition, accessibility: Definition::accessibility) -> void
def build_method: (Methods, Methods::instance_type, member: AST::Members::MethodDefinition | AST::Ruby::Members::DefMember, accessibility: Definition::accessibility) -> void

def each_rbs_member_with_accessibility: (Array[AST::Members::t | AST::Declarations::t], ?accessibility: Definition::accessibility) { (AST::Members::t | AST::Declarations::t, Definition::accessibility) -> void } -> void

Expand Down
26 changes: 26 additions & 0 deletions test/rbs/definition_builder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3200,4 +3200,30 @@ module A
end
end
end

def test_inline_decl__class_def
SignatureManager.new do |manager|
manager.add_ruby_file("inherited.rbs", <<~RUBY)
class A
def hello(x) = 123
end
RUBY

manager.build do |env|
builder = DefinitionBuilder.new(env: env)

builder.build_instance(type_name("::A")).tap do |definition|
definition.methods[:hello].tap do |method|
assert_equal type_name("::A"), method.defined_in
assert_equal type_name("::A"), method.implemented_in

assert_equal [parse_method_type("(?) -> untyped")], method.method_types
assert_equal [parse_method_type("(?) -> untyped")], method.defs.map(&:type)

assert_equal [], method.annotations
end
end
end
end
end
end
Loading