lib/rbi/parser.rb in rbi-0.0.16 vs lib/rbi/parser.rb in rbi-0.0.17
- old
+ new
@@ -64,37 +64,41 @@
def initialize
# Delay load unparser and only if it has not been loaded already.
require "unparser" unless defined?(::Unparser)
end
- sig { params(string: String).returns(Tree) }
- def self.parse_string(string)
- Parser.new.parse_string(string)
- end
+ class << self
+ extend T::Sig
- sig { params(path: String).returns(Tree) }
- def self.parse_file(path)
- Parser.new.parse_file(path)
- end
+ sig { params(string: String).returns(Tree) }
+ def parse_string(string)
+ Parser.new.parse_string(string)
+ end
- sig { params(paths: T::Array[String]).returns(T::Array[Tree]) }
- def self.parse_files(paths)
- parser = Parser.new
- paths.map { |path| parser.parse_file(path) }
+ sig { params(path: String).returns(Tree) }
+ def parse_file(path)
+ Parser.new.parse_file(path)
+ end
+
+ sig { params(paths: T::Array[String]).returns(T::Array[Tree]) }
+ def parse_files(paths)
+ parser = Parser.new
+ paths.map { |path| parser.parse_file(path) }
+ end
+
+ sig { params(strings: T::Array[String]).returns(T::Array[Tree]) }
+ def parse_strings(strings)
+ parser = Parser.new
+ strings.map { |string| parser.parse_string(string) }
+ end
end
sig { params(string: String).returns(Tree) }
def parse_string(string)
parse(string, file: "-")
end
- sig { params(strings: T::Array[String]).returns(T::Array[Tree]) }
- def self.parse_strings(strings)
- parser = Parser.new
- strings.map { |string| parser.parse_string(string) }
- end
-
sig { params(path: String).returns(Tree) }
def parse_file(path)
parse(::File.read(path), file: path)
end
@@ -164,11 +168,11 @@
sig do
params(
file: String,
comments: T::Array[::Parser::Source::Comment],
- nodes_comments_assoc: T::Hash[::Parser::Source::Map, T::Array[::Parser::Source::Comment]]
+ nodes_comments_assoc: T::Hash[::Parser::Source::Map, T::Array[::Parser::Source::Comment]],
).void
end
def initialize(file:, comments: [], nodes_comments_assoc: {})
super()
@file = file
@@ -190,10 +194,11 @@
end
sig { override.params(node: T.nilable(Object)).void }
def visit(node)
return unless node.is_a?(AST::Node)
+
@last_node = node
case node.type
when :module, :class, :sclass
scope = parse_scope(node)
@@ -248,10 +253,12 @@
sig { params(node: AST::Node).returns(RBI::Node) }
def parse_const_assign(node)
node_value = node.children[2]
if struct_definition?(node_value)
parse_struct(node)
+ elsif type_variable_definition?(node_value)
+ parse_type_variable(node)
else
name = parse_name(node)
value = parse_expr(node_value)
loc = node_loc(node)
comments = node_comments(node)
@@ -268,20 +275,20 @@
Method.new(
node.children[0].to_s,
params: node.children[1].children.map { |child| parse_param(child) },
sigs: current_sigs,
loc: loc,
- comments: current_sigs_comments + node_comments(node)
+ comments: current_sigs_comments + node_comments(node),
)
when :defs
Method.new(
node.children[1].to_s,
params: node.children[2].children.map { |child| parse_param(child) },
is_singleton: true,
sigs: current_sigs,
loc: loc,
- comments: current_sigs_comments + node_comments(node)
+ comments: current_sigs_comments + node_comments(node),
)
else
raise ParseError.new("Unsupported def node type `#{node.type}`", loc)
end
end
@@ -315,11 +322,11 @@
end
sig { params(node: AST::Node).returns(T.nilable(RBI::Node)) }
def parse_send(node)
recv = node.children[0]
- return nil if recv && recv != :self
+ return if recv && recv != :self
method_name = node.children[1]
loc = node_loc(node)
comments = node_comments(node)
@@ -360,10 +367,11 @@
method.visibility = visibility
method
when :send
snode = parse_send(nested_node)
raise ParseError.new("Unexpected token `private` before `#{nested_node.type}`", loc) unless snode.is_a?(Attr)
+
snode.visibility = visibility
snode
when nil
visibility
else
@@ -457,10 +465,28 @@
@scopes_stack.pop
struct
end
+ sig { params(node: AST::Node).returns(T::Boolean) }
+ def type_variable_definition?(node)
+ (node.type == :send && node.children[0].nil? && (node.children[1] == :type_member ||
+ node.children[1] == :type_template)) ||
+ (node.type == :block && type_variable_definition?(node.children[0]))
+ end
+
+ sig { params(node: AST::Node).returns(RBI::TypeMember) }
+ def parse_type_variable(node)
+ name = parse_name(node)
+ loc = node_loc(node)
+ comments = node_comments(node)
+
+ send = node.children[2]
+
+ TypeMember.new(name, send.location.expression.source, loc: loc, comments: comments)
+ end
+
sig { params(node: AST::Node).returns([String, String, T.nilable(String)]) }
def parse_tstruct_prop(node)
name = node.children[2].children[0].to_s
type = parse_expr(node.children[3])
has_default = node.children[4]
@@ -514,10 +540,11 @@
sig { params(node: AST::Node).returns(T::Array[Comment]) }
def node_comments(node)
comments = @nodes_comments_assoc[node.location]
return [] unless comments
+
comments.map do |comment|
text = comment.text[1..-1].strip
loc = Loc.from_ast_loc(@file, comment.location)
Comment.new(text, loc: loc)
end
@@ -590,38 +617,44 @@
@tree.loc = Loc.new(
file: @file,
begin_line: first_loc&.begin_line || 0,
begin_column: first_loc&.begin_column || 0,
end_line: last_loc&.end_line || 0,
- end_column: last_loc&.end_column || 0
+ end_column: last_loc&.end_column || 0,
)
end
end
class ConstBuilder < ASTVisitor
extend T::Sig
- sig { params(node: T.nilable(AST::Node)).returns(T.nilable(String)) }
- def self.visit(node)
- v = ConstBuilder.new
- v.visit(node)
- return nil if v.names.empty?
- v.names.join("::")
- end
-
sig { returns(T::Array[String]) }
attr_accessor :names
sig { void }
def initialize
super
@names = T.let([], T::Array[String])
end
+ class << self
+ extend T::Sig
+
+ sig { params(node: T.nilable(AST::Node)).returns(T.nilable(String)) }
+ def visit(node)
+ v = ConstBuilder.new
+ v.visit(node)
+ return if v.names.empty?
+
+ v.names.join("::")
+ end
+ end
+
sig { override.params(node: T.nilable(AST::Node)).void }
def visit(node)
return unless node
+
case node.type
when :const, :casgn
visit(node.children[0])
@names << node.children[1].to_s
when :cbase
@@ -633,29 +666,34 @@
end
class SigBuilder < ASTVisitor
extend T::Sig
- sig { params(node: AST::Node).returns(Sig) }
- def self.build(node)
- v = SigBuilder.new
- v.visit_all(node.children)
- v.current
- end
-
sig { returns(Sig) }
- attr_accessor :current
+ attr_reader :current
sig { void }
def initialize
super
@current = T.let(Sig.new, Sig)
end
+ class << self
+ extend T::Sig
+
+ sig { params(node: AST::Node).returns(Sig) }
+ def build(node)
+ v = SigBuilder.new
+ v.visit_all(node.children)
+ v.current
+ end
+ end
+
sig { override.params(node: T.nilable(AST::Node)).void }
def visit(node)
return unless node
+
case node.type
when :send
visit_send(node)
end
end
@@ -701,17 +739,21 @@
end
end
end
class Loc
- sig { params(file: String, ast_loc: T.any(::Parser::Source::Map, ::Parser::Source::Range)).returns(Loc) }
- def self.from_ast_loc(file, ast_loc)
- Loc.new(
- file: file,
- begin_line: ast_loc.line,
- begin_column: ast_loc.column,
- end_line: ast_loc.last_line,
- end_column: ast_loc.last_column
- )
+ class << self
+ extend T::Sig
+
+ sig { params(file: String, ast_loc: T.any(::Parser::Source::Map, ::Parser::Source::Range)).returns(Loc) }
+ def from_ast_loc(file, ast_loc)
+ Loc.new(
+ file: file,
+ begin_line: ast_loc.line,
+ begin_column: ast_loc.column,
+ end_line: ast_loc.last_line,
+ end_column: ast_loc.last_column,
+ )
+ end
end
end
end