Skip to content

Commit

Permalink
🐍
Browse files Browse the repository at this point in the history
  • Loading branch information
soutaro committed Apr 12, 2024
1 parent 37c287c commit fc6bb75
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 4 deletions.
1 change: 1 addition & 0 deletions lib/rbs/inline.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require "rbs/inline/ast/comment_lines"
require "rbs/inline/ast/tree"
require "rbs/inline/ast/declarations"
require "rbs/inline/parser"

module RBS
module Inline
Expand Down
12 changes: 10 additions & 2 deletions lib/rbs/inline/ast/declarations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@ class ClassDecl
include ConstantUtil

attr_reader :node
attr_reader :comments
attr_reader :members

def initialize(node)
def initialize(node, comments)
@node = node
@members = []
@comments = comments
end

def class_name
type_name(node.constant_path)
type_name(node.constant_path)
end

def super_class
if node.superclass
type_name(node.superclass)
end
end
end
end
Expand Down
63 changes: 63 additions & 0 deletions lib/rbs/inline/parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
module RBS
module Inline
class Parser < Prism::Visitor
attr_reader :decls, :surrounding_decls, :comments

def initialize()
@decls = []
@surrounding_decls = []
@comments = {}
end

def self.parse(result)
instance = Parser.new()

annots = AnnotationParser.parse(result.comments)
annots.each do |result|
instance.comments[result.line_range.end] = result
end

instance.visit(result.value)

[
[],
instance.decls
]
end

def visit_class_node(node)
visit node.constant_path
visit node.superclass

if node.location
associated_comment = comments[node.location.start_line - 1]
end

class_decl = AST::Declarations::ClassDecl.new(node, associated_comment)

push_class_module_decl(class_decl) do
visit node.body
end
end

def current_class_module_decl
surrounding_decls.last
end

def push_class_module_decl(decl)
if current = current_class_module_decl
current.members << decl
else
decls << decl
end

surrounding_decls.push(decl)
begin
yield
ensure
surrounding_decls.pop()
end
end
end
end
end
6 changes: 5 additions & 1 deletion sig/rbs/inline/ast/declarations.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ module RBS

attr_reader members: Array[Members::t | t]

def initialize: (Prism::ClassNode) -> void
attr_reader comments: AnnotationParser::ParsingResult?

def initialize: (Prism::ClassNode, AnnotationParser::ParsingResult?) -> void

def class_name: () -> TypeName?

def super_class: () -> TypeName?
end
end
end
Expand Down
25 changes: 25 additions & 0 deletions sig/rbs/inline/parser.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use Prism::*

module RBS
module Inline
class Parser < Prism::Visitor
# A mappning from the last line to the result
#
attr_reader comments: Hash[Integer, AnnotationParser::ParsingResult]

attr_reader decls: Array[AST::Declarations::t]

attr_reader surrounding_decls: Array[AST::Declarations::ClassDecl]

def initialize: () -> void

def self.parse: (ParseResult[ProgramNode]) -> [Array[AST::Annotations::Use], Array[AST::Declarations::t]]

def visit_class_node: (ClassNode node) -> void

def current_class_module_decl: () -> AST::Declarations::ClassDecl?

def push_class_module_decl: (AST::Declarations::ClassDecl) { () -> void } -> void
end
end
end
14 changes: 13 additions & 1 deletion test/rbs/inline/declarations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,20 @@ class Hello
end
RUBY

decl = AST::Declarations::ClassDecl.new(result.value.statements.body[0])
decl = AST::Declarations::ClassDecl.new(result.value.statements.body[0], nil)

assert_equal TypeName("Hello"), decl.class_name
end

def test_class_decl__super
result = parse_ruby(<<~RUBY)
class Hello < Object
end
RUBY

decl = AST::Declarations::ClassDecl.new(result.value.statements.body[0], nil)

assert_equal TypeName("Hello"), decl.class_name
assert_equal TypeName("Object"), decl.super_class
end
end
22 changes: 22 additions & 0 deletions test/rbs/inline/parser_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require "test_helper"

class RBS::Inline::ParserTest < Minitest::Test
include RBS::Inline

def parse_ruby(src)
Prism.parse(src, filepath: "a.rb")
end

def test_class_decl
Parser.parse(parse_ruby(<<~RUBY))
class Foo
# Hello world
class Bar < Object
end
end
RUBY
end
end

0 comments on commit fc6bb75

Please sign in to comment.