Skip to content

Commit

Permalink
Add ConstantDecl
Browse files Browse the repository at this point in the history
  • Loading branch information
soutaro committed Apr 25, 2024
1 parent db7f4a6 commit 27bb896
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 18 deletions.
11 changes: 3 additions & 8 deletions lib/rbs/inline/annotation_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class Tokenizer
"*" => :kSTAR,
"--" => :kMINUS2,
} #:: Hash[String, Symbol]
PUNCTS_RE = Regexp.union(PUNCTS.keys)
PUNCTS_RE = Regexp.union(PUNCTS.keys) #:: Regexp

# @rbs scanner: StringScanner
# @rbs return: void
Expand Down Expand Up @@ -643,13 +643,8 @@ def parse_use_clause(tokenizer)
if tokenizer.type?(:kAS)
as_tree = AST::Tree.new(:as)

as_tree << tokenizer.advance(as_tree)

if tokenizer.type?(:tLVAR, :tIFIDENT, :tUIDENT)
as_tree <<tokenizer.advance(as_tree)
else
as_tree << nil
end
tokenizer.consume_token!(:kAS, tree: as_tree)
tokenizer.consume_token(:tLVAR, :tIFIDENT, :tUIDENT, tree: as_tree)

tree << as_tree
else
Expand Down
56 changes: 56 additions & 0 deletions lib/rbs/inline/ast/declarations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,62 @@ def module_selfs
end
end
end

class ConstantDecl < Base
include ConstantUtil

attr_reader :node
attr_reader :comments
attr_reader :assertion

def initialize(node, comments, assertion)
@node = node
@comments = comments
@assertion = assertion
end

def type
if assertion
case assertion.type
when MethodType, nil
# skip
else
return assertion.type
end
end

if literal = literal_type
return literal
end

Types::Bases::Any.new(location: nil)
end

def literal_type
case node.value
when Prism::StringNode, Prism::InterpolatedStringNode
BuiltinNames::String.instance_type
when Prism::SymbolNode, Prism::InterpolatedSymbolNode
BuiltinNames::Symbol.instance_type
when Prism::RegularExpressionNode, Prism::InterpolatedRegularExpressionNode
BuiltinNames::Regexp.instance_type
when Prism::IntegerNode
BuiltinNames::Integer.instance_type
when Prism::FloatNode
BuiltinNames::Float.instance_type
when Prism::ArrayNode
BuiltinNames::Array.instance_type
when Prism::HashNode
BuiltinNames::Hash.instance_type
when Prism::TrueNode, Prism::FalseNode
Types::Bases::Bool.new(location: nil)
end
end

def constant_name
TypeName.new(name: node.name, namespace: Namespace.empty)
end
end
end
end
end
Expand Down
35 changes: 30 additions & 5 deletions lib/rbs/inline/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ def push_class_module_decl(decl)
decls << decl
end

surrounding_decls.push(decl)
begin
yield
ensure
surrounding_decls.pop()
if block_given?
surrounding_decls.push(_ = decl)
begin
yield
ensure
surrounding_decls.pop()
end
end
end

Expand Down Expand Up @@ -224,6 +226,29 @@ def application_annotation(node)
end #: AST::Annotations::Application?
end
end

def assertion_annotation(node)
comment_line, app_comment = comments.find do |_, comment|
comment.line_range.begin == node.location.end_line
end

if app_comment && comment_line
comments.delete(comment_line)
app_comment.annotations.find do |annotation|
annotation.is_a?(AST::Annotations::Assertion)
end #: AST::Annotations::Assertion?
end
end

def visit_constant_write_node(node)
return if ignored_node?(node)

comment = comments.delete(node.location.start_line - 1)
assertion = assertion_annotation(node)

decl = AST::Declarations::ConstantDecl.new(node, comment, assertion)
push_class_module_decl(decl)
end
end
end
end
17 changes: 17 additions & 0 deletions lib/rbs/inline/writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def translate_decl(decl)
translate_class_decl(decl)
when AST::Declarations::ModuleDecl
translate_module_decl(decl)
when AST::Declarations::ConstantDecl
translate_constant_decl(decl)
end
end

Expand Down Expand Up @@ -116,6 +118,21 @@ def translate_module_decl(decl)
)
end

def translate_constant_decl(decl)
return unless decl.constant_name

if decl.comments
comment = RBS::AST::Comment.new(string: decl.comments.content, location: nil)
end

RBS::AST::Declarations::Constant.new(
name: decl.constant_name,
type: decl.type,
comment: comment,
location: nil
)
end

def translate_member(member)
case member
when AST::Members::RubyDef
Expand Down
8 changes: 8 additions & 0 deletions sig/generated/rbs/inline/annotation_parser.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ module RBS

attr_reader current_token: token?

KEYWORDS: Hash[String, Symbol]

KW_RE: ::Regexp

PUNCTS: Hash[String, Symbol]

PUNCTS_RE: Regexp

# @rbs scanner: StringScanner
# @rbs return: void
def initialize: (StringScanner scanner) -> void
Expand Down
20 changes: 19 additions & 1 deletion sig/rbs/inline/ast/declarations.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module RBS
module Inline
module AST
module Declarations
type t = ClassDecl | ModuleDecl
type t = ClassDecl | ModuleDecl | ConstantDecl

module ConstantUtil
def type_name: (Prism::Node) -> TypeName?
Expand Down Expand Up @@ -46,6 +46,24 @@ module RBS

%a{pure} def module_selfs: () -> Array[Annotations::ModuleSelf]
end

class ConstantDecl < Base
include ConstantUtil

attr_reader node: Prism::ConstantWriteNode

attr_reader comments: AnnotationParser::ParsingResult?

attr_reader assertion: Annotations::Assertion?

def initialize: (Prism::ConstantWriteNode, AnnotationParser::ParsingResult?, Annotations::Assertion?) -> void

%a{pure} def type: () -> Types::t

%a{pure} def literal_type: () -> Types::t?

%a{pure} def constant_name: () -> TypeName?
end
end
end
end
Expand Down
11 changes: 7 additions & 4 deletions sig/rbs/inline/parser.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,29 @@ module RBS

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

attr_reader surrounding_decls: Array[AST::Declarations::t]
attr_reader surrounding_decls: Array[AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl]

attr_reader current_visibility: RBS::AST::Members::visibility?

def initialize: () -> void

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

def current_class_module_decl: () -> AST::Declarations::t?
def current_class_module_decl: () -> (AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl | nil)

def current_class_module_decl!: () -> AST::Declarations::t
def current_class_module_decl!: () -> (AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl)

def push_class_module_decl: (AST::Declarations::t) { () -> void } -> void
def push_class_module_decl: (AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl) { () -> void } -> void
| (AST::Declarations::ConstantDecl) -> void

def ignored_node?: (Node) -> bool

def visit_class_node: (ClassNode node) -> void

def application_annotation: (Node node) -> AST::Annotations::Application?

def assertion_annotation: (Node node) -> AST::Annotations::Assertion?

def push_visibility: (RBS::AST::Members::visibility | nil) { () -> void } -> void
end
end
Expand Down
2 changes: 2 additions & 0 deletions sig/rbs/inline/writer.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ module RBS

def translate_module_decl: (AST::Declarations::ModuleDecl) -> RBS::AST::Declarations::Module?

def translate_constant_decl: (AST::Declarations::ConstantDecl) -> RBS::AST::Declarations::Constant?

def translate_member: (AST::Members::t) -> Array[RBS::AST::Members::t]?
end
end
Expand Down
21 changes: 21 additions & 0 deletions test/rbs/inline/writer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -366,4 +366,25 @@ def foo: () -> untyped
end
RBS
end

def test_constant_decl
output = translate(<<~RUBY)
VERSION = "hogehoge"
SIZE = [123] #:: Array[Integer]
NAMES = __dir__
# @rbs skip
SKIP = 123
RUBY

assert_equal <<~RBS, output
VERSION: ::String
SIZE: Array[Integer]
NAMES: untyped
RBS
end
end

0 comments on commit 27bb896

Please sign in to comment.