Skip to content

Commit 4e7b1dd

Browse files
authored
Merge pull request #2390 from ruby/inline-class
Add inline class/module declaration
2 parents 232edac + 68e7331 commit 4e7b1dd

33 files changed

+1017
-155
lines changed

lib/rbs.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
require "logger"
1111
require "tsort"
1212
require "strscan"
13+
require "prism"
1314

1415
require "rbs/errors"
1516
require "rbs/buffer"
@@ -24,7 +25,11 @@
2425
require "rbs/ast/members"
2526
require "rbs/ast/annotation"
2627
require "rbs/ast/visitor"
28+
require "rbs/ast/ruby/helpers/constant_helper"
29+
require "rbs/ast/ruby/helpers/location_helper"
30+
require "rbs/ast/ruby/declarations"
2731
require "rbs/source"
32+
require "rbs/inline_parser"
2833
require "rbs/environment"
2934
require "rbs/environment/use_map"
3035
require "rbs/environment/class_entry"

lib/rbs/ast/ruby/declarations.rb

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# frozen_string_literal: true
2+
3+
module RBS
4+
module AST
5+
module Ruby
6+
module Declarations
7+
class Base
8+
attr_reader :buffer
9+
10+
include Helpers::ConstantHelper
11+
include Helpers::LocationHelper
12+
13+
def initialize(buffer)
14+
@buffer = buffer
15+
end
16+
end
17+
18+
class ClassDecl < Base
19+
attr_reader :class_name
20+
21+
attr_reader :members
22+
23+
attr_reader :node
24+
25+
def initialize(buffer, name, node)
26+
super(buffer)
27+
@class_name = name
28+
@node = node
29+
@members = []
30+
end
31+
32+
def each_decl(&block)
33+
return enum_for(:each_decl) unless block
34+
35+
@members.each do |member|
36+
if member.is_a?(Base)
37+
yield member
38+
end
39+
end
40+
end
41+
42+
def super_class = nil
43+
44+
def type_params = []
45+
46+
def location
47+
rbs_location(node.location)
48+
end
49+
end
50+
51+
class ModuleDecl < Base
52+
attr_reader :module_name
53+
54+
attr_reader :members
55+
56+
attr_reader :node
57+
58+
def initialize(buffer, name, node)
59+
super(buffer)
60+
@module_name = name
61+
@node = node
62+
@members = []
63+
end
64+
65+
def each_decl(&block)
66+
return enum_for(:each_decl) unless block
67+
68+
@members.each do |member|
69+
if member.is_a?(Base)
70+
yield member
71+
end
72+
end
73+
end
74+
75+
def type_params = []
76+
77+
def self_types = []
78+
79+
def location
80+
rbs_location(node.location)
81+
end
82+
end
83+
end
84+
end
85+
end
86+
end
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
module RBS
4+
module AST
5+
module Ruby
6+
module Helpers
7+
module ConstantHelper
8+
module_function
9+
10+
def constant_as_type_name(node)
11+
case node
12+
when Prism::ConstantPathNode, Prism::ConstantReadNode
13+
begin
14+
TypeName.parse(node.full_name)
15+
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError
16+
nil
17+
end
18+
end
19+
end
20+
end
21+
end
22+
end
23+
end
24+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# frozen_string_literal: true
2+
3+
module RBS
4+
module AST
5+
module Ruby
6+
module Helpers
7+
module LocationHelper
8+
def rbs_location(location)
9+
Location.new(buffer, location.start_character_offset, location.end_character_offset)
10+
end
11+
end
12+
end
13+
end
14+
end
15+
end

lib/rbs/cli/validate.rb

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -170,38 +170,43 @@ def validate_class_module_definition
170170
TypeParamDefaultReferenceError.check!(d.type_params)
171171

172172
entry.each_decl do |decl|
173-
decl.each_member do |member|
174-
case member
175-
when AST::Members::MethodDefinition
176-
@validator.validate_method_definition(member, type_name: name)
177-
member.overloads.each do |ov|
178-
void_type_context_validator(ov.method_type)
179-
end
180-
when AST::Members::Attribute
181-
void_type_context_validator(member.type)
182-
when AST::Members::Mixin
183-
member.args.each do |arg|
184-
no_self_type_validator(arg)
185-
unless arg.is_a?(Types::Bases::Void)
186-
void_type_context_validator(arg, true)
173+
case decl
174+
when AST::Declarations::Base
175+
decl.each_member do |member|
176+
case member
177+
when AST::Members::MethodDefinition
178+
@validator.validate_method_definition(member, type_name: name)
179+
member.overloads.each do |ov|
180+
void_type_context_validator(ov.method_type)
187181
end
188-
end
189-
params =
190-
if member.name.class?
191-
module_decl = @env.normalized_module_entry(member.name) or raise
192-
module_decl.type_params
193-
else
194-
interface_decl = @env.interface_decls.fetch(member.name)
195-
interface_decl.decl.type_params
182+
when AST::Members::Attribute
183+
void_type_context_validator(member.type)
184+
when AST::Members::Mixin
185+
member.args.each do |arg|
186+
no_self_type_validator(arg)
187+
unless arg.is_a?(Types::Bases::Void)
188+
void_type_context_validator(arg, true)
189+
end
190+
end
191+
params =
192+
if member.name.class?
193+
module_decl = @env.normalized_module_entry(member.name) or raise
194+
module_decl.type_params
195+
else
196+
interface_decl = @env.interface_decls.fetch(member.name)
197+
interface_decl.decl.type_params
198+
end
199+
InvalidTypeApplicationError.check!(type_name: member.name, params: params, args: member.args, location: member.location)
200+
when AST::Members::Var
201+
@validator.validate_variable(member)
202+
void_type_context_validator(member.type)
203+
if member.is_a?(AST::Members::ClassVariable)
204+
no_self_type_validator(member.type)
196205
end
197-
InvalidTypeApplicationError.check!(type_name: member.name, params: params, args: member.args, location: member.location)
198-
when AST::Members::Var
199-
@validator.validate_variable(member)
200-
void_type_context_validator(member.type)
201-
if member.is_a?(AST::Members::ClassVariable)
202-
no_self_type_validator(member.type)
203206
end
204207
end
208+
else
209+
raise "Unknown declaration: #{decl.class}"
205210
end
206211
end
207212
rescue BaseError => error

lib/rbs/definition_builder.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,10 @@ def source_location(source, decl)
452452
case decl
453453
when AST::Declarations::Class
454454
decl.super_class&.location
455+
when AST::Ruby::Declarations::ClassDecl
456+
nil
457+
else
458+
raise "Unexpected `:super` source location with #{decl.class}"
455459
end
456460
else
457461
source.location

lib/rbs/definition_builder/ancestor_builder.rb

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -348,68 +348,73 @@ def one_interface_ancestors(type_name)
348348
end
349349

350350
def mixin_ancestors0(decl, type_name, align_params:, included_modules:, included_interfaces:, extended_modules:, prepended_modules:, extended_interfaces:)
351-
decl.each_mixin do |member|
352-
case member
353-
when AST::Members::Include
354-
module_name = member.name
355-
module_args = member.args.map {|type| align_params ? type.sub(align_params) : type }
351+
case decl
352+
when AST::Declarations::Base
353+
decl.each_mixin do |member|
354+
case member
355+
when AST::Members::Include
356+
module_name = member.name
357+
module_args = member.args.map {|type| align_params ? type.sub(align_params) : type }
356358

357-
case
358-
when member.name.class? && included_modules
359-
MixinClassError.check!(type_name: type_name, env: env, member: member)
360-
NoMixinFoundError.check!(member.name, env: env, member: member)
359+
case
360+
when member.name.class? && included_modules
361+
MixinClassError.check!(type_name: type_name, env: env, member: member)
362+
NoMixinFoundError.check!(member.name, env: env, member: member)
361363

362-
module_decl = env.normalized_module_entry(module_name) or raise
363-
module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args)
364+
module_decl = env.normalized_module_entry(module_name) or raise
365+
module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args)
364366

365-
module_name = env.normalize_module_name(module_name)
366-
included_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
367-
when member.name.interface? && included_interfaces
368-
NoMixinFoundError.check!(member.name, env: env, member: member)
367+
module_name = env.normalize_module_name(module_name)
368+
included_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
369+
when member.name.interface? && included_interfaces
370+
NoMixinFoundError.check!(member.name, env: env, member: member)
369371

370-
interface_decl = env.interface_decls.fetch(module_name)
371-
module_args = AST::TypeParam.normalize_args(interface_decl.decl.type_params, module_args)
372+
interface_decl = env.interface_decls.fetch(module_name)
373+
module_args = AST::TypeParam.normalize_args(interface_decl.decl.type_params, module_args)
372374

373-
included_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
374-
end
375+
included_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
376+
end
375377

376-
when AST::Members::Prepend
377-
if prepended_modules
378-
MixinClassError.check!(type_name: type_name, env: env, member: member)
379-
NoMixinFoundError.check!(member.name, env: env, member: member)
378+
when AST::Members::Prepend
379+
if prepended_modules
380+
MixinClassError.check!(type_name: type_name, env: env, member: member)
381+
NoMixinFoundError.check!(member.name, env: env, member: member)
380382

381-
module_decl = env.normalized_module_entry(member.name) or raise
382-
module_name = module_decl.name
383+
module_decl = env.normalized_module_entry(member.name) or raise
384+
module_name = module_decl.name
383385

384-
module_args = member.args.map {|type| align_params ? type.sub(align_params) : type }
385-
module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args)
386+
module_args = member.args.map {|type| align_params ? type.sub(align_params) : type }
387+
module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args)
386388

387-
prepended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
388-
end
389+
prepended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
390+
end
389391

390-
when AST::Members::Extend
391-
module_name = member.name
392-
module_args = member.args
392+
when AST::Members::Extend
393+
module_name = member.name
394+
module_args = member.args
393395

394-
case
395-
when member.name.class? && extended_modules
396-
MixinClassError.check!(type_name: type_name, env: env, member: member)
397-
NoMixinFoundError.check!(member.name, env: env, member: member)
396+
case
397+
when member.name.class? && extended_modules
398+
MixinClassError.check!(type_name: type_name, env: env, member: member)
399+
NoMixinFoundError.check!(member.name, env: env, member: member)
398400

399-
module_decl = env.normalized_module_entry(module_name) or raise
400-
module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args)
401+
module_decl = env.normalized_module_entry(module_name) or raise
402+
module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args)
401403

402-
module_name = env.normalize_module_name(module_name)
403-
extended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
404-
when member.name.interface? && extended_interfaces
405-
NoMixinFoundError.check!(member.name, env: env, member: member)
404+
module_name = env.normalize_module_name(module_name)
405+
extended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
406+
when member.name.interface? && extended_interfaces
407+
NoMixinFoundError.check!(member.name, env: env, member: member)
406408

407-
interface_decl = env.interface_decls.fetch(module_name)
408-
module_args = AST::TypeParam.normalize_args(interface_decl.decl.type_params, module_args)
409+
interface_decl = env.interface_decls.fetch(module_name)
410+
module_args = AST::TypeParam.normalize_args(interface_decl.decl.type_params, module_args)
409411

410-
extended_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
412+
extended_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
413+
end
411414
end
412415
end
416+
when AST::Ruby::Declarations::Base
417+
# noop
413418
end
414419
end
415420

0 commit comments

Comments
 (0)