Skip to content

Commit

Permalink
Add IvarType annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
soutaro committed Apr 26, 2024
1 parent bc83f27 commit ab01f83
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lib/rbs/inline/annotation_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ class Tokenizer
"in" => :kIN,
"out" => :kOUT,
"unchecked" => :kUNCHECKED,
"self" => :kSELF,
} #:: Hash[String, Symbol]
KW_RE = /#{Regexp.union(KEYWORDS.keys)}\b/

Expand All @@ -174,6 +175,7 @@ class Tokenizer
"*" => :kSTAR,
"--" => :kMINUS2,
"<" => :kLT,
"." => :kDOT,
} #:: Hash[String, Symbol]
PUNCTS_RE = Regexp.union(PUNCTS.keys) #:: Regexp

Expand Down Expand Up @@ -203,6 +205,8 @@ def advance(tree)
@current_token = [:tIFIDENT, s]
when s = scanner.scan(/[a-z]\w*/)
@current_token = [:tLVAR, s]
when s = scanner.scan(/@\w+/)
@current_token = [:tATIDENT, s]
when s = scanner.scan(/%a\{[^}]+\}/)
@current_token = [:tANNOTATION, s]
when s = scanner.scan(/%a\[[^\]]+\]/)
Expand Down Expand Up @@ -322,6 +326,9 @@ def parse_annotation(comments)
when tokenizer.type?(:kGENERIC)
tree << parse_generic(tokenizer)
AST::Annotations::Generic.new(tree, comments)
when tokenizer.type?(:kSELF, :tATIDENT)
tree << parse_ivar_type(tokenizer)
AST::Annotations::IvarType.new(tree, comments)
end
when tokenizer.type?(:kCOLON2)
tree << tokenizer.current_token
Expand Down Expand Up @@ -708,6 +715,25 @@ def parse_generic(tokenizer)

tree
end

#:: (Tokenizer) -> AST::Tree
def parse_ivar_type(tokenizer)
tree = AST::Tree.new(:ivar_type)

tokenizer.consume_token(:kSELF, tree: tree)
tokenizer.consume_token(:kDOT, tree: tree)

tokenizer.consume_token(:tATIDENT, tree: tree)
tokenizer.consume_token(:kCOLON, tree: tree)

tree << parse_type(tokenizer, tree)

tree << parse_optional(tokenizer, :kMINUS2) do
parse_comment(tokenizer)
end

tree
end
end
end
end
27 changes: 27 additions & 0 deletions lib/rbs/inline/ast/annotations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,33 @@ def complete?
end
end

# `@rbs @foo: T` or `@rbs self.@foo: T`
#
class IvarType < Base
attr_reader :name #:: Symbol

attr_reader :type #:: Types::t?

attr_reader :class_instance #:: bool

attr_reader :comment #:: String?

# @rbs override
def initialize(tree, source)
@tree = tree
@source = source

ivar_tree = tree.nth_tree!(1)
@class_instance = ivar_tree.nth_token?(0).is_a?(Array)
@name = ivar_tree.nth_token!(2).last.to_sym
@type = ivar_tree.nth_type?(4)

if comment = ivar_tree.nth_tree(5)
@comment = comment.to_s
end
end
end

# `#:: TYPE`
#
class Assertion < Base
Expand Down
3 changes: 3 additions & 0 deletions sig/generated/rbs/inline/annotation_parser.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ module RBS
# @rbs tokenizer: Tokenizer
# @rbs returns AST::Tree
def parse_generic: (Tokenizer tokenizer) -> AST::Tree

# :: (Tokenizer) -> AST::Tree
def parse_ivar_type: (Tokenizer) -> AST::Tree
end
end
end
14 changes: 14 additions & 0 deletions sig/generated/rbs/inline/ast/annotations.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ module RBS
def complete?: () -> bool
end

# `@rbs @foo: T` or `@rbs self.@foo: T`
class IvarType < Base
attr_reader name: Symbol

attr_reader type: Types::t?

attr_reader class_instance: bool

attr_reader comment: String?

# @rbs override
def initialize: ...
end

# `#:: TYPE`
class Assertion < Base
attr_reader type: Types::t | MethodType | nil
Expand Down
30 changes: 30 additions & 0 deletions test/rbs/inline/annotation_parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,34 @@ def test_generic
assert_equal "-- Comment", annotation.comment
end
end

def test_ivar_decl_annotation
annots = AnnotationParser.parse(parse_comments(<<~RUBY))
# @rbs @size: Integer -- size of something
# @rbs self.@block: String
# @rbs @y: Array[
RUBY

assert_equal 3, annots[0].annotations.size
annots[0].annotations[0].tap do |annotation|
assert_instance_of AST::Annotations::IvarType, annotation
assert_equal :@size, annotation.name
refute_predicate annotation, :class_instance
assert_equal "Integer", annotation.type.to_s
assert_equal "-- size of something", annotation.comment
end
annots[0].annotations[1].tap do |annotation|
assert_instance_of AST::Annotations::IvarType, annotation
assert_equal :@block, annotation.name
assert_predicate annotation, :class_instance
assert_equal "String", annotation.type.to_s
assert_nil annotation.comment
end
annots[0].annotations[2].tap do |annotation|
assert_instance_of AST::Annotations::IvarType, annotation
assert_equal :@y, annotation.name
assert_nil annotation.type
assert_nil annotation.comment
end
end
end

0 comments on commit ab01f83

Please sign in to comment.