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