lib/rbi/parser.rb in rbi-0.1.14 vs lib/rbi/parser.rb in rbi-0.2.0
- old
+ new
@@ -167,26 +167,42 @@
@tree = T.let(Tree.new, Tree)
@scopes_stack = T.let([@tree], T::Array[Tree])
@last_node = T.let(nil, T.nilable(Prism::Node))
@last_sigs = T.let([], T::Array[RBI::Sig])
- @last_sigs_comments = T.let([], T::Array[Comment])
end
sig { override.params(node: Prism::ClassNode).void }
def visit_class_node(node)
@last_node = node
- scope = Class.new(
- node_string!(node.constant_path),
- superclass_name: node_string(node.superclass),
- loc: node_loc(node),
- comments: node_comments(node),
- )
+ superclass_name = node_string(node.superclass)
+ scope = case superclass_name
+ when /^(::)?T::Struct$/
+ TStruct.new(
+ node_string!(node.constant_path),
+ loc: node_loc(node),
+ comments: node_comments(node),
+ )
+ when /^(::)?T::Enum$/
+ TEnum.new(
+ node_string!(node.constant_path),
+ loc: node_loc(node),
+ comments: node_comments(node),
+ )
+ else
+ Class.new(
+ node_string!(node.constant_path),
+ superclass_name: superclass_name,
+ loc: node_loc(node),
+ comments: node_comments(node),
+ )
+ end
current_scope << scope
@scopes_stack << scope
visit(node.body)
+ scope.nodes.concat(current_sigs)
collect_dangling_comments(node)
@scopes_stack.pop
@last_node = nil
end
@@ -238,16 +254,23 @@
end
sig { override.params(node: Prism::DefNode).void }
def visit_def_node(node)
@last_node = node
+
+ # We need to collect the comments with `current_sigs_comments` _before_ visiting the parameters to make sure
+ # the method comments are properly associated with the sigs and not the parameters.
+ sigs = current_sigs
+ comments = detach_comments_from_sigs(sigs) + node_comments(node)
+ params = parse_params(node.parameters)
+
current_scope << Method.new(
node.name.to_s,
- params: parse_params(node.parameters),
- sigs: current_sigs,
+ params: params,
+ sigs: sigs,
loc: node_loc(node),
- comments: current_sigs_comments + node_comments(node),
+ comments: comments,
is_singleton: !!node.receiver,
)
@last_node = nil
end
@@ -261,20 +284,21 @@
)
current_scope << scope
@scopes_stack << scope
visit(node.body)
+ scope.nodes.concat(current_sigs)
collect_dangling_comments(node)
@scopes_stack.pop
@last_node = nil
end
sig { override.params(node: Prism::ProgramNode).void }
def visit_program_node(node)
@last_node = node
super
-
+ @tree.nodes.concat(current_sigs)
collect_orphan_comments
separate_header_comments
set_root_tree_loc
@last_node = nil
end
@@ -288,10 +312,11 @@
)
current_scope << scope
@scopes_stack << scope
visit(node.body)
+ scope.nodes.concat(current_sigs)
collect_dangling_comments(node)
@scopes_stack.pop
@last_node = nil
end
@@ -312,64 +337,68 @@
unless args.is_a?(Prism::ArgumentsNode) && args.arguments.any?
@last_node = nil
return
end
+ sigs = current_sigs
+ comments = detach_comments_from_sigs(sigs) + node_comments(node)
+
current_scope << AttrReader.new(
*T.unsafe(args.arguments.map { |arg| node_string!(arg).delete_prefix(":").to_sym }),
- sigs: current_sigs,
+ sigs: sigs,
loc: node_loc(node),
- comments: current_sigs_comments + node_comments(node),
+ comments: comments,
)
when "attr_writer"
args = node.arguments
unless args.is_a?(Prism::ArgumentsNode) && args.arguments.any?
@last_node = nil
return
end
+ sigs = current_sigs
+ comments = detach_comments_from_sigs(sigs) + node_comments(node)
+
current_scope << AttrWriter.new(
*T.unsafe(args.arguments.map { |arg| node_string!(arg).delete_prefix(":").to_sym }),
- sigs: current_sigs,
+ sigs: sigs,
loc: node_loc(node),
- comments: current_sigs_comments + node_comments(node),
+ comments: comments,
)
when "attr_accessor"
args = node.arguments
unless args.is_a?(Prism::ArgumentsNode) && args.arguments.any?
@last_node = nil
return
end
+ sigs = current_sigs
+ comments = detach_comments_from_sigs(sigs) + node_comments(node)
+
current_scope << AttrAccessor.new(
*T.unsafe(args.arguments.map { |arg| node_string!(arg).delete_prefix(":").to_sym }),
- sigs: current_sigs,
+ sigs: sigs,
loc: node_loc(node),
- comments: current_sigs_comments + node_comments(node),
+ comments: comments,
)
when "enums"
- block = node.block
-
- unless block.is_a?(Prism::BlockNode)
- @last_node = nil
- return
+ if node.block && node.arguments.nil?
+ scope = TEnumBlock.new(loc: node_loc(node), comments: node_comments(node))
+ current_scope << scope
+ @scopes_stack << scope
+ visit(node.block)
+ @scopes_stack.pop
+ else
+ current_scope << Send.new(
+ message,
+ parse_send_args(node.arguments),
+ loc: node_loc(node),
+ comments: node_comments(node),
+ )
end
-
- body = block.body
-
- unless body.is_a?(Prism::StatementsNode)
- @last_node = nil
- return
- end
-
- current_scope << TEnumBlock.new(
- body.body.map { |stmt| T.cast(stmt, Prism::ConstantWriteNode).name.to_s },
- loc: node_loc(node),
- comments: node_comments(node),
- )
when "extend"
args = node.arguments
unless args.is_a?(Prism::ArgumentsNode) && args.arguments.any?
@last_node = nil
@@ -413,10 +442,17 @@
visit(node.arguments)
last_node = @scopes_stack.last&.nodes&.last
case last_node
when Method, Attr
last_node.visibility = parse_visibility(node.name.to_s, node)
+ when Send
+ current_scope << Send.new(
+ message,
+ parse_send_args(node.arguments),
+ loc: node_loc(node),
+ comments: node_comments(node),
+ )
else
raise ParseError.new(
"Unexpected token `#{node.message}` before `#{last_node&.string&.strip}`",
node_loc(node),
)
@@ -468,11 +504,11 @@
first_line = node.location.start_line
last_line = node.location.end_line
last_node_last_line = node.child_nodes.last&.location&.end_line
- last_line.downto(first_line) do |line|
+ first_line.upto(last_line) do |line|
comment = @comments_by_line[line]
next unless comment
break if last_node_last_line && line <= last_node_last_line
current_scope << parse_comment(comment)
@@ -514,14 +550,19 @@
sigs = @last_sigs.dup
@last_sigs.clear
sigs
end
- sig { returns(T::Array[Comment]) }
- def current_sigs_comments
- comments = @last_sigs_comments.dup
- @last_sigs_comments.clear
+ sig { params(sigs: T::Array[Sig]).returns(T::Array[Comment]) }
+ def detach_comments_from_sigs(sigs)
+ comments = T.let([], T::Array[Comment])
+
+ sigs.each do |sig|
+ comments += sig.comments.dup
+ sig.comments.clear
+ end
+
comments
end
sig { params(node: Prism::Node).returns(T::Array[Comment]) }
def node_comments(node)
@@ -644,15 +685,14 @@
params
end
sig { params(node: Prism::CallNode).returns(Sig) }
def parse_sig(node)
- @last_sigs_comments = node_comments(node)
-
builder = SigBuilder.new(@source, file: @file)
builder.current.loc = node_loc(node)
builder.visit_call_node(node)
+ builder.current.comments = node_comments(node)
builder.current
end
sig { params(node: T.any(Prism::ConstantWriteNode, Prism::ConstantPathWriteNode)).returns(T.nilable(Struct)) }
def parse_struct(node)
@@ -743,15 +783,15 @@
sig { params(name: String, node: Prism::Node).returns(Visibility) }
def parse_visibility(name, node)
case name
when "public"
- Public.new(loc: node_loc(node))
+ Public.new(loc: node_loc(node), comments: node_comments(node))
when "protected"
- Protected.new(loc: node_loc(node))
+ Protected.new(loc: node_loc(node), comments: node_comments(node))
when "private"
- Private.new(loc: node_loc(node))
+ Private.new(loc: node_loc(node), comments: node_comments(node))
else
raise ParseError.new("Unexpected visibility `#{name}`", node_loc(node))
end
end
@@ -779,14 +819,11 @@
)
end
sig { params(node: T.nilable(Prism::Node)).returns(T::Boolean) }
def type_variable_definition?(node)
- return false unless node.is_a?(Prism::CallNode)
- return false unless node.block
-
- node.message == "type_member" || node.message == "type_template"
+ node.is_a?(Prism::CallNode) && (node.message == "type_member" || node.message == "type_template")
end
end
class SigBuilder < Visitor
extend T::Sig
@@ -837,10 +874,10 @@
args.arguments.each do |arg|
@current.type_params << node_string!(arg).delete_prefix(":")
end
end
when "void"
- @current.return_type = nil
+ @current.return_type = "void"
end
visit(node.receiver)
visit(node.block)
end