Skip to content

Commit 02a4f89

Browse files
authored
Merge pull request #2392 from ruby/inline-def
Inline `def` support
2 parents f0c02da + 4e159be commit 02a4f89

16 files changed

+296
-10
lines changed

lib/rbs.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
require "rbs/ast/ruby/helpers/constant_helper"
2929
require "rbs/ast/ruby/helpers/location_helper"
3030
require "rbs/ast/ruby/declarations"
31+
require "rbs/ast/ruby/members"
3132
require "rbs/source"
3233
require "rbs/inline_parser"
3334
require "rbs/environment"

lib/rbs/ast/ruby/members.rb

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# frozen_string_literal: true
2+
3+
module RBS
4+
module AST
5+
module Ruby
6+
module Members
7+
class Base
8+
attr_reader :buffer
9+
10+
def initialize(buffer)
11+
@buffer = buffer
12+
end
13+
14+
include Helpers::LocationHelper
15+
end
16+
17+
class DefMember < Base
18+
Overload = AST::Members::MethodDefinition::Overload
19+
20+
attr_reader :name
21+
attr_reader :node
22+
23+
def initialize(buffer, name, node)
24+
super(buffer)
25+
@name = name
26+
@node = node
27+
end
28+
29+
def location
30+
rbs_location(node.location)
31+
end
32+
33+
def overloads
34+
method_type = MethodType.new(
35+
type_params: [],
36+
type: Types::UntypedFunction.new(return_type: Types::Bases::Any.new(location: nil)),
37+
block: nil,
38+
location: nil
39+
)
40+
41+
[
42+
Overload.new(method_type: method_type, annotations: [])
43+
]
44+
end
45+
46+
def overloading?
47+
false
48+
end
49+
50+
def annotations
51+
[]
52+
end
53+
end
54+
end
55+
end
56+
end
57+
end

lib/rbs/definition.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ def hash
6262
end
6363

6464
def comment
65-
member.comment
65+
case member
66+
when AST::Members::Base
67+
member.comment
68+
when AST::Ruby::Members::Base
69+
nil
70+
end
6671
end
6772

6873
def update(type: self.type, member: self.member, defined_in: self.defined_in, implemented_in: self.implemented_in)

lib/rbs/definition_builder.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,37 @@ def define_method(methods, definition, method, subst, self_type_methods, defined
766766
)
767767

768768
method_definition.annotations.replace(original.annotations)
769+
when AST::Ruby::Members::DefMember
770+
if duplicated_method = methods[method.name]
771+
raise DuplicatedMethodDefinitionError.new(
772+
type: definition.self_type,
773+
method_name: method.name,
774+
members: [original, *duplicated_method.members]
775+
)
776+
end
777+
778+
defs = original.overloads.map do |overload|
779+
Definition::Method::TypeDef.new(
780+
type: subst.empty? ? overload.method_type : overload.method_type.sub(subst),
781+
member: original,
782+
defined_in: defined_in,
783+
implemented_in: implemented_in
784+
).tap do |type_def|
785+
# Keep the original annotations given to overloads.
786+
type_def.overload_annotations.replace(overload.annotations)
787+
end
788+
end
789+
790+
method_definition = Definition::Method.new(
791+
super_method: existing_method,
792+
defs: defs,
793+
accessibility: :public,
794+
alias_of: nil,
795+
alias_member: nil
796+
)
797+
798+
method_definition.annotations.replace([])
799+
769800
when nil
770801
# Overloading method definition only
771802

lib/rbs/definition_builder/method_builder.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ def build_instance(type_name)
105105
Methods.new(type: type).tap do |methods|
106106
entry.each_decl do |decl|
107107
subst = Substitution.build(decl.type_params.each.map(&:name), args)
108-
if decl.is_a?(AST::Declarations::Base)
108+
case decl
109+
when AST::Declarations::Base
109110
each_rbs_member_with_accessibility(decl.members) do |member, accessibility|
110111
case member
111112
when AST::Members::MethodDefinition
@@ -138,6 +139,18 @@ def build_instance(type_name)
138139
end
139140
end
140141
end
142+
when AST::Ruby::Declarations::Base
143+
decl.members.each do |member|
144+
case member
145+
when AST::Ruby::Members::DefMember
146+
build_method(
147+
methods,
148+
type,
149+
member: member,
150+
accessibility: :public
151+
)
152+
end
153+
end
141154
end
142155
end
143156
end.validate!

lib/rbs/environment.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,8 @@ def resolve_ruby_decl(resolver, decl, context:, prefix:)
672672
case member
673673
when AST::Ruby::Declarations::Base
674674
resolved.members << resolve_ruby_decl(resolver, member, context: inner_context, prefix: inner_prefix)
675+
when AST::Ruby::Members::Base
676+
resolved.members << member
675677
else
676678
raise "Unknown member type: #{member.class}"
677679
end

lib/rbs/inline_parser.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ def initialize(location, message)
2323
end
2424
end
2525

26+
NotImplementedYet = _ = Class.new(Base)
2627
NonConstantClassName = _ = Class.new(Base)
2728
NonConstantModuleName = _ = Class.new(Base)
29+
TopLevelMethodDefinition = _ = Class.new(Base)
2830
end
2931

3032
def self.parse(buffer, prism)
@@ -101,6 +103,27 @@ def visit_module_node(node)
101103
end
102104
end
103105

106+
def visit_def_node(node)
107+
if node.receiver
108+
diagnostics << Diagnostic::NotImplementedYet.new(
109+
rbs_location(node.receiver.location),
110+
"Singleton method definition is not supported yet"
111+
)
112+
return
113+
end
114+
115+
case current = current_module
116+
when AST::Ruby::Declarations::ClassDecl, AST::Ruby::Declarations::ModuleDecl
117+
defn = AST::Ruby::Members::DefMember.new(buffer, node.name, node)
118+
current.members << defn
119+
else
120+
diagnostics << Diagnostic::TopLevelMethodDefinition.new(
121+
rbs_location(node.name_loc),
122+
"Top-level method definition is not supported"
123+
)
124+
end
125+
end
126+
104127
def insert_declaration(decl)
105128
if current_module
106129
current_module.members << decl

sig/ast/ruby/declarations.rbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module RBS
1414
end
1515

1616
class ClassDecl < Base
17-
type member = t
17+
type member = t | Members::t
1818

1919
attr_reader class_name: TypeName
2020

@@ -35,7 +35,7 @@ module RBS
3535
end
3636

3737
class ModuleDecl < Base
38-
type member = t
38+
type member = t | Members::t
3939

4040
attr_reader module_name: TypeName
4141

sig/ast/ruby/members.rbs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module RBS
2+
module AST
3+
module Ruby
4+
module Members
5+
class Base
6+
attr_reader buffer: Buffer
7+
8+
def initialize: (Buffer) -> void
9+
10+
include Helpers::LocationHelper
11+
end
12+
13+
type t = DefMember
14+
15+
class DefMember < Base
16+
class Overload = AST::Members::MethodDefinition::Overload
17+
18+
attr_reader name: Symbol
19+
attr_reader node: Prism::DefNode
20+
21+
def initialize: (Buffer, Symbol name, Prism::DefNode node) -> void
22+
23+
def location: () -> Location
24+
25+
def overloads: () -> Array[Overload]
26+
27+
def overloading?: () -> bool
28+
29+
def annotations: () -> Array[AST::Annotation]
30+
end
31+
end
32+
end
33+
end
34+
end

sig/definition.rbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ module RBS
2121

2222
class Method
2323
type method_member = AST::Members::MethodDefinition | AST::Members::AttrReader | AST::Members::AttrAccessor | AST::Members::AttrWriter
24+
| AST::Ruby::Members::DefMember
2425

2526
class TypeDef
2627
attr_reader type: MethodType

0 commit comments

Comments
 (0)