Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prototype rb: Extract instance variables and class variables #1343

Merged
merged 8 commits into from
Jun 26, 2023
42 changes: 42 additions & 0 deletions lib/rbs/prototype/rb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ def process(node, decls:, comments:, context:)
process child, decls: kls.members, comments: comments, context: new_ctx
end
remove_unnecessary_accessibility_methods! kls.members
sort_members! kls.members

when :MODULE
module_name, *module_body = node.children
Expand Down Expand Up @@ -195,6 +196,11 @@ def process(node, decls:, comments:, context:)

decls.push member unless decls.include?(member)

new_ctx = Context.initial.tap { |ctx| ctx.singleton = kind == :singleton }
tk0miya marked this conversation as resolved.
Show resolved Hide resolved
each_node def_body.children do |child|
process child, decls: decls, comments: comments, context: new_ctx
end

when :ALIAS
new_name, old_name = node.children.map { |c| literal_to_symbol(c) }
member = AST::Members::Alias.new(
Expand Down Expand Up @@ -377,6 +383,32 @@ def process(node, decls:, comments:, context:)
comment: comments[node.first_lineno - 1]
)

when :IASGN
if context.singleton || !context.namespace.empty?
member = AST::Members::ClassVariable.new(
tk0miya marked this conversation as resolved.
Show resolved Hide resolved
name: "@#{node.children.first}".to_sym,
type: Types::Bases::Any.new(location: nil),
location: nil,
comment: comments[node.first_lineno - 1]
)
else
member = AST::Members::InstanceVariable.new(
name: node.children.first,
type: Types::Bases::Any.new(location: nil),
location: nil,
comment: comments[node.first_lineno - 1]
)
end
decls.push member unless decls.include?(member)

when :CVASGN
member = AST::Members::ClassVariable.new(
name: node.children.first,
type: Types::Bases::Any.new(location: nil),
location: nil,
comment: comments[node.first_lineno - 1]
)
decls.push member unless decls.include?(member)
else
process_children(node, decls: decls, comments: comments, context: context)
end
Expand Down Expand Up @@ -743,6 +775,16 @@ def find_def_index_by_name(decls, name)
]
end
end

def sort_members!(decls)
i = 0
orders = {
AST::Members::ClassVariable => -2,
AST::Members::InstanceVariable => -1,
}
decls.sort_by! { |decl| [orders.fetch(decl.class, 0), i += 1] }
end
end
end
end

2 changes: 2 additions & 0 deletions sig/prototype/rb.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ module RBS
def is_accessibility?: (decl) -> bool

def find_def_index_by_name: (Array[decl] decls, Symbol name) -> [Integer, AST::Members::MethodDefinition | AST::Members::AttrReader | AST::Members::AttrWriter]?

def sort_members!: (Array[decl] decls) -> void
end
end
end
70 changes: 70 additions & 0 deletions test/rbs/rb_prototype_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,76 @@ def hello: () -> untyped
RBS
end

def test_instance_variables
parser = RB.new

rb = <<-EOR
class Hello
def message(message)
# comment for ivar
@message = message
end
end
EOR

parser.parse(rb)

assert_write parser.decls, <<-EOF
class Hello
# comment for ivar
@message: untyped

def message: (untyped message) -> untyped
end
EOF
end

def test_class_variables
parser = RB.new

rb = <<-EOR
class Hello
def self.foo
@foo = 42
end

class << self
def bar
@bar = 42
end
end

@baz = 42

def message(message)
# comment for cvar
@@message = message
end
end
EOR

parser.parse(rb)

assert_write parser.decls, <<-EOF
class Hello
@@foo: untyped

@@bar: untyped

@@baz: untyped

# comment for cvar
@@message: untyped

def self.foo: () -> untyped

def self.bar: () -> untyped

def message: (untyped message) -> untyped
end
EOF
end

def test_literal_to_type
parser = RBS::Prototype::RB.new
[
Expand Down