Class: RBS::Inline::AnnotationParser
- Inherits:
-
Object
- Object
- RBS::Inline::AnnotationParser
- Includes:
- Tokens
- Defined in:
- lib/rbs/inline/annotation_parser.rb,
lib/rbs/inline/annotation_parser/tokenizer.rb,
sig/generated/rbs/inline/annotation_parser.rbs,
sig/generated/rbs/inline/annotation_parser/tokenizer.rbs
Defined Under Namespace
Modules: Tokens Classes: ParsingResult, Tokenizer
Constant Summary
Constants included from Tokens
Tokens::K_AMP, Tokens::K_ARROW, Tokens::K_AS, Tokens::K_CLASS, Tokens::K_COLON, Tokens::K_COLON2, Tokens::K_COMMA, Tokens::K_DOT, Tokens::K_DOT3, Tokens::K_EOF, Tokens::K_GENERIC, Tokens::K_IN, Tokens::K_INHERITS, Tokens::K_LBRACE, Tokens::K_LBRACKET, Tokens::K_LPAREN, Tokens::K_LT, Tokens::K_MINUS2, Tokens::K_MODULE, Tokens::K_MODULE_SELF, Tokens::K_OUT, Tokens::K_OVERRIDE, Tokens::K_QUESTION, Tokens::K_RBRACKET, Tokens::K_RBS, Tokens::K_RBSE, Tokens::K_RETURN, Tokens::K_SELF, Tokens::K_SKIP, Tokens::K_STAR, Tokens::K_STAR2, Tokens::K_UNCHECKED, Tokens::K_USE, Tokens::K_VBAR, Tokens::K_YIELDS, Tokens::T_ANNOTATION, Tokens::T_ATIDENT, Tokens::T_BLOCKSTR, Tokens::T_COMMENT, Tokens::T_ELVAR, Tokens::T_IFIDENT, Tokens::T_LVAR, Tokens::T_SOURCE, Tokens::T_UIDENT, Tokens::T_WHITESPACE
Instance Attribute Summary collapse
-
#input ⇒ Array[Prism::Comment]
readonly
: Array.
Class Method Summary collapse
Instance Method Summary collapse
-
#annotation_comment?(comment) ⇒ Integer, ...
Test if the comment is an annotation comment.
-
#each_annotation_paragraph(result) {|arg0, is_annotation| ... } ⇒ void
Split lines of comments in
resultinto paragraphs. -
#initialize(input) ⇒ AnnotationParser
constructor
A new instance of AnnotationParser.
- #parse ⇒ Array[ParsingResult]
- #parse_annotation(comments) ⇒ AST::Annotations::t?
-
#parse_block_type(tokenizer) ⇒ AST::Tree
: (Tokenizer) -> AST::Tree.
- #parse_class_decl(tokenizer) ⇒ AST::Tree
- #parse_comment(tokenizer) ⇒ AST::Tree
- #parse_generic(tokenizer) ⇒ AST::Tree
- #parse_inherits(tokenizer) ⇒ AST::Tree
-
#parse_ivar_type(tokenizer) ⇒ AST::Tree
: (Tokenizer) -> AST::Tree.
-
#parse_method_type(tokenizer, parent_tree) ⇒ MethodType, AST::Tree
Parse a RBS method type.
- #parse_method_type_annotation(tokenizer) ⇒ AST::Tree
- #parse_module_decl(tokenizer) ⇒ AST::Tree
- #parse_module_name(tokenizer) ⇒ AST::Tree
- #parse_module_self(tokenizer) ⇒ AST::Tree
- #parse_module_selfs(tokenizer) ⇒ AST::Tree
-
#parse_optional(tokenizer, *types, tree: nil) { ... } ⇒ AST::Tree?
Yield the block and return the resulting tree if tokenizer has current token of
types. -
#parse_override(tokenizer) ⇒ AST::Tree
Parse
@rbs overrideannotation. - #parse_rbs_annotation(tokenizer) ⇒ AST::Tree
- #parse_return_type_decl(tokenizer) ⇒ AST::Tree
-
#parse_splat_param_type(tokenizer) ⇒ AST::Tree
: (Tokenizer) -> AST::Tree.
-
#parse_type(tokenizer, parent_tree) ⇒ Types::t, ...
Parse a RBS type and returns it.
- #parse_type_app(tokenizer) ⇒ AST::Tree
-
#parse_type_method_type(tokenizer, parent_tree) ⇒ MethodType, ...
Parse a RBS method type or type and returns it.
- #parse_type_param(tokenizer) ⇒ AST::Tree
- #parse_type_params(tokenizer) ⇒ AST::Tree
-
#parse_use(tokenizer) ⇒ AST::Tree
Parse
@rbs use [CLAUSES]annotation. -
#parse_use_clause(tokenizer) ⇒ AST::Tree
Parses use clause.
- #parse_var_decl(tokenizer) ⇒ AST::Tree
-
#yield_annotation(comments, lines, offset, allow_empty_lines:) {|arg0, is_annotation| ... } ⇒ void
The first annotation line is already detected and consumed.
-
#yield_empty_annotation(comments, empty_comments, lines, offset) {|arg0, is_annotation| ... } ⇒ void
Consumes empty lines between annotation lines.
-
#yield_paragraph(comments, lines) {|arg0, is_annotation| ... } ⇒ void
The first line is NOT consumed.
Constructor Details
#initialize(input) ⇒ AnnotationParser
Returns a new instance of AnnotationParser.
108 109 110 |
# File 'lib/rbs/inline/annotation_parser.rb', line 108 def initialize(input) #: void @input = input end |
Instance Attribute Details
#input ⇒ Array[Prism::Comment] (readonly)
: Array
105 106 107 |
# File 'lib/rbs/inline/annotation_parser.rb', line 105 def input @input end |
Class Method Details
.parse(input) ⇒ Array[ParsingResult]
114 115 116 |
# File 'lib/rbs/inline/annotation_parser.rb', line 114 def self.parse(input) new(input).parse end |
Instance Method Details
#annotation_comment?(comment) ⇒ Integer, ...
Test if the comment is an annotation comment
- Returns
nilif the comment is not an annotation. - Returns
trueif the comment is#:or#[annotation. (Offset is1) - Returns Integer if the comment is
#@rbsannotation. (Offset is the number of leading spaces including#)
: (Prism::Comment) -> (Integer | true | nil)
159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/rbs/inline/annotation_parser.rb', line 159 def annotation_comment?(comment) line = comment.location.slice # No leading whitespace is allowed return true if line.start_with?("#:") return true if line.start_with?("#[") if match = line.match(/\A#(\s*)@rbs(\b|!)/) leading_spaces = match[1] or raise leading_spaces.size + 1 end end |
#each_annotation_paragraph(result) {|arg0, is_annotation| ... } ⇒ void
This method returns an undefined value.
Split lines of comments in result into paragraphs
A paragraph consists of:
- An annotation syntax constructs -- starting with
@rbsor::, or - A lines something else
Yields an array of comments, and a boolean indicating if the comments may be an annotation.
: (ParsingResult) { (Array, bool is_annotation) -> void } -> void
182 183 184 |
# File 'lib/rbs/inline/annotation_parser.rb', line 182 def each_annotation_paragraph(result, &block) yield_paragraph([], result.comments.dup, &block) end |
#parse ⇒ Array[ParsingResult]
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/rbs/inline/annotation_parser.rb', line 119 def parse results = [] #: Array[ParsingResult] first_comment, *rest = input first_comment or return results result = ParsingResult.new(first_comment) results << result rest.each do |comment| unless result.add_comment(comment) result = ParsingResult.new(comment) results << result end end results.each do |result| each_annotation_paragraph(result) do |comments, annotation| lines = AST::CommentLines.new(comments) if annotation && annot = parse_annotation(lines) result.annotations << annot else result.annotations << lines end end end results end |
#parse_annotation(comments) ⇒ AST::Annotations::t?
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
# File 'lib/rbs/inline/annotation_parser.rb', line 299 def parse_annotation(comments) scanner = StringScanner.new(comments.string) tokenizer = Tokenizer.new(scanner) tree = AST::Tree.new(:rbs_annotation) tokenizer.advance(tree) tokenizer.advance(tree) case when tokenizer.type?(K_RBSE) tokenizer.consume_trivias(tree) tree << tokenizer.lookahead1 rest = tokenizer.rest rest.delete_prefix!("@rbs!") tree << [:EMBEDDED_RBS, rest] tokenizer.scanner.terminate AST::Annotations::Embedded.new(tree, comments) when tokenizer.type?(K_RBS) tokenizer.advance(tree, eat: true) case when tokenizer.type?(T_LVAR, :tELVAR) tree << parse_var_decl(tokenizer) AST::Annotations::VarType.new(tree, comments) when tokenizer.type?(K_SKIP, K_INHERITS, K_OVERRIDE, K_USE, K_GENERIC, K_MODULE, K_CLASS) && tokenizer.type2?(K_COLON) tree << parse_var_decl(tokenizer) AST::Annotations::VarType.new(tree, comments) when tokenizer.type?(K_MODULE) tree << parse_module_decl(tokenizer) AST::Annotations::ModuleDecl.new(tree, comments) when tokenizer.type?(K_CLASS) tree << parse_class_decl(tokenizer) AST::Annotations::ClassDecl.new(tree, comments) when tokenizer.type?(K_SKIP) AST::Annotations::Skip.new(tree, comments) when tokenizer.type?(K_RETURN) tree << parse_return_type_decl(tokenizer) AST::Annotations::ReturnType.new(tree, comments) when tokenizer.type?(T_ANNOTATION) tree << parse_rbs_annotation(tokenizer) AST::Annotations::RBSAnnotation.new(tree, comments) when tokenizer.type?(K_INHERITS) tree << parse_inherits(tokenizer) AST::Annotations::Inherits.new(tree, comments) when tokenizer.type?(K_OVERRIDE) tree << parse_override(tokenizer) AST::Annotations::Override.new(tree, comments) when tokenizer.type?(K_USE) tree << parse_use(tokenizer) AST::Annotations::Use.new(tree, comments) when tokenizer.type?(K_MODULE_SELF) tree << parse_module_self(tokenizer) AST::Annotations::ModuleSelf.new(tree, comments) when tokenizer.type?(K_GENERIC) tree << parse_generic(tokenizer) AST::Annotations::Generic.new(tree, comments) when tokenizer.type?(K_SELF, T_ATIDENT) tree << parse_ivar_type(tokenizer) AST::Annotations::IvarType.new(tree, comments) when tokenizer.type?(K_STAR) tree << parse_splat_param_type(tokenizer) AST::Annotations::SplatParamType.new(tree, comments) when tokenizer.type?(K_STAR2) tree << parse_splat_param_type(tokenizer) AST::Annotations::DoubleSplatParamType.new(tree, comments) when tokenizer.type?(K_AMP) tree << parse_block_type(tokenizer) AST::Annotations::BlockType.new(tree, comments) when tokenizer.type?(K_LPAREN, K_ARROW, K_LBRACE, K_LBRACKET, K_DOT3) tree << parse_method_type_annotation(tokenizer) AST::Annotations::Method.new(tree, comments) end when tokenizer.type?(K_COLON) tokenizer.advance(tree, eat: true) if tokenizer.type?(K_DOT3) tokenizer.advance(tree, eat: true) AST::Annotations::Dot3Assertion.new(tree, comments) else type = parse_type_method_type(tokenizer, tree) tree << type case type when MethodType AST::Annotations::MethodTypeAssertion.new(tree, comments) when AST::Tree, nil AST::Annotations::SyntaxErrorAssertion.new(tree, comments) else AST::Annotations::TypeAssertion.new(tree, comments) end end when tokenizer.type?(K_LBRACKET) tree << parse_type_app(tokenizer) AST::Annotations::Application.new(tree, comments) end end |
#parse_block_type(tokenizer) ⇒ AST::Tree
: (Tokenizer) -> AST::Tree
873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 |
# File 'lib/rbs/inline/annotation_parser.rb', line 873 def parse_block_type(tokenizer) tree = AST::Tree.new(:block_type) tokenizer.consume_token!(K_AMP, tree: tree) tokenizer.consume_token(T_LVAR, tree: tree) tokenizer.consume_token(K_COLON, tree: tree) tokenizer.consume_token(K_QUESTION, tree: tree) tokenizer.consume_trivias(tree) unless (string = tokenizer.skip_to_comment()).empty? tree << [T_BLOCKSTR, string] else tree << nil end tree << parse_optional(tokenizer, K_MINUS2, tree: tree) do parse_comment(tokenizer) end tree end |
#parse_class_decl(tokenizer) ⇒ AST::Tree
917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 |
# File 'lib/rbs/inline/annotation_parser.rb', line 917 def parse_class_decl(tokenizer) tree = AST::Tree.new(:class_decl) tokenizer.consume_token!(K_CLASS, tree: tree) tree << parse_module_name(tokenizer) tree << parse_optional(tokenizer, K_LBRACKET) do parse_type_params(tokenizer) end tree << parse_optional(tokenizer, K_LT) do super_class = AST::Tree.new(:super_class) tokenizer.consume_token!(K_LT, tree: super_class) super_class << parse_type(tokenizer, super_class) super_class end tree end |
#parse_comment(tokenizer) ⇒ AST::Tree
438 439 440 441 442 443 444 445 446 447 448 |
# File 'lib/rbs/inline/annotation_parser.rb', line 438 def parse_comment(tokenizer) tree = AST::Tree.new(:comment) tokenizer.consume_token(K_MINUS2, tree: tree) rest = tokenizer.rest tokenizer.scanner.terminate tree << [T_COMMENT, rest] tree end |
#parse_generic(tokenizer) ⇒ AST::Tree
801 802 803 804 805 806 807 808 809 810 811 812 813 |
# File 'lib/rbs/inline/annotation_parser.rb', line 801 def parse_generic(tokenizer) tree = AST::Tree.new(:generic) tokenizer.consume_token!(K_GENERIC, tree: tree) tree << parse_type_param(tokenizer) tree << parse_optional(tokenizer, K_MINUS2, tree: tree) do parse_comment(tokenizer) end tree end |
#parse_inherits(tokenizer) ⇒ AST::Tree
639 640 641 642 643 644 645 646 647 648 649 650 |
# File 'lib/rbs/inline/annotation_parser.rb', line 639 def parse_inherits(tokenizer) tree = AST::Tree.new(:rbs_inherits) if tokenizer.type?(K_INHERITS) tree << tokenizer.lookahead1 tokenizer.advance(tree) end tree << parse_type(tokenizer, tree) tree end |
#parse_ivar_type(tokenizer) ⇒ AST::Tree
: (Tokenizer) -> AST::Tree
837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 |
# File 'lib/rbs/inline/annotation_parser.rb', line 837 def parse_ivar_type(tokenizer) tree = AST::Tree.new(:ivar_type) tokenizer.consume_token(K_SELF, tree: tree) tokenizer.consume_token(K_DOT, tree: tree) tokenizer.consume_token(T_ATIDENT, tree: tree) tokenizer.consume_token(K_COLON, tree: tree) tree << parse_type(tokenizer, tree) tree << parse_optional(tokenizer, K_MINUS2, tree: tree) do parse_comment(tokenizer) end tree end |
#parse_method_type(tokenizer, parent_tree) ⇒ MethodType, AST::Tree
Parse a RBS method type
If parsing failed, it returns a Tree(`:type_syntax_error), consuming all of the remaining input.
Note that this doesn't recognize -- comment unlike parse_type.
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
# File 'lib/rbs/inline/annotation_parser.rb', line 567 def parse_method_type(tokenizer, parent_tree) tokenizer.consume_trivias(parent_tree) buffer = RBS::Buffer.new(name: Pathname.new(""), content: tokenizer.scanner.string) byte_range = (tokenizer.current_position..) begin if type = RBS::Parser.parse_method_type(buffer, byte_range: byte_range, require_eof: false) loc = type.location or raise tokenizer.reset(loc.end_pos, parent_tree) type else tree = AST::Tree.new(:type_syntax_error) tree << [T_SOURCE, tokenizer.rest] tokenizer.scanner.terminate tree end rescue RBS::ParsingError tree = AST::Tree.new(:type_syntax_error) tree << [T_SOURCE, tokenizer.rest] tokenizer.scanner.terminate tree end end |
#parse_method_type_annotation(tokenizer) ⇒ AST::Tree
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 |
# File 'lib/rbs/inline/annotation_parser.rb', line 488 def parse_method_type_annotation(tokenizer) tree = AST::Tree.new(:method_type_annotation) until tokenizer.type?(K_EOF) if tokenizer.type?(K_DOT3) tree << tokenizer.lookahead1 tokenizer.advance(tree) break else method_type = parse_method_type(tokenizer, tree) case method_type when MethodType tree << method_type if tokenizer.type?(K_VBAR) tokenizer.advance(tree, eat: true) else break end when AST::Tree tree << method_type break end end end tree end |
#parse_module_decl(tokenizer) ⇒ AST::Tree
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 |
# File 'lib/rbs/inline/annotation_parser.rb', line 898 def parse_module_decl(tokenizer) tree = AST::Tree.new(:module_decl) tokenizer.consume_token!(K_MODULE, tree: tree) tree << parse_module_name(tokenizer) tree << parse_optional(tokenizer, K_LBRACKET) do parse_type_params(tokenizer) end tree << parse_optional(tokenizer, K_COLON) do parse_module_selfs(tokenizer) end tree end |
#parse_module_name(tokenizer) ⇒ AST::Tree
939 940 941 942 943 944 945 946 947 948 949 950 951 952 |
# File 'lib/rbs/inline/annotation_parser.rb', line 939 def parse_module_name(tokenizer) tree = AST::Tree.new(:module_name) tokenizer.consume_token(K_COLON2, tree: tree) while tokenizer.type?(T_UIDENT) && tokenizer.type2?(K_COLON2) tokenizer.consume_token!(T_UIDENT, tree: tree) tokenizer.consume_token!(K_COLON2, tree: tree) end tokenizer.consume_token(T_UIDENT, tree: tree) tree end |
#parse_module_self(tokenizer) ⇒ AST::Tree
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 |
# File 'lib/rbs/inline/annotation_parser.rb', line 753 def parse_module_self(tokenizer) tree = AST::Tree.new(:module_self) tokenizer.consume_token!(K_MODULE_SELF, tree: tree) while true tree << parse_type(tokenizer, tree) if tokenizer.type?(K_COMMA) tokenizer.advance(tree, eat: true) else break end end tree << parse_optional(tokenizer, K_MINUS2, tree: tree) do parse_comment(tokenizer) end tree end |
#parse_module_selfs(tokenizer) ⇒ AST::Tree
976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 |
# File 'lib/rbs/inline/annotation_parser.rb', line 976 def parse_module_selfs(tokenizer) tree = AST::Tree.new(:module_selfs) tokenizer.consume_token!(K_COLON, tree: tree) while true tree << parse_type(tokenizer, tree) if tokenizer.type?(K_COMMA) tokenizer.advance(tree, eat: true) else break end end tree end |
#parse_optional(tokenizer, *types, tree: nil) { ... } ⇒ AST::Tree?
Yield the block and return the resulting tree if tokenizer has current token of types
# Test if tokenize has `--` token, then parse comment or insert `nil` to tree
tree << parse_optional(tokenizer, K_MINUS2) do
parse_comment(tokenizer)
end
If tree: is given, it consumes trivia tokens before yielding the block.
790 791 792 793 794 795 796 797 |
# File 'lib/rbs/inline/annotation_parser.rb', line 790 def parse_optional(tokenizer, *types, tree: nil, &block) if tokenizer.type?(*types) if tree tokenizer.consume_trivias(tree) end yield end end |
#parse_override(tokenizer) ⇒ AST::Tree
Parse @rbs override annotation
656 657 658 659 660 661 662 663 664 665 |
# File 'lib/rbs/inline/annotation_parser.rb', line 656 def parse_override(tokenizer) tree = AST::Tree.new(:override) if tokenizer.type?(K_OVERRIDE) tree << tokenizer.lookahead1 tokenizer.advance(tree) end tree end |
#parse_rbs_annotation(tokenizer) ⇒ AST::Tree
626 627 628 629 630 631 632 633 634 635 |
# File 'lib/rbs/inline/annotation_parser.rb', line 626 def parse_rbs_annotation(tokenizer) tree = AST::Tree.new(:rbs_annotation) while tokenizer.type?(T_ANNOTATION) tree << tokenizer.lookahead1 tokenizer.advance(tree) end tree end |
#parse_return_type_decl(tokenizer) ⇒ AST::Tree
423 424 425 426 427 428 429 430 431 432 433 434 |
# File 'lib/rbs/inline/annotation_parser.rb', line 423 def parse_return_type_decl(tokenizer) tree = AST::Tree.new(:return_type_decl) tokenizer.consume_token!(K_RETURN, tree: tree) tokenizer.consume_token(K_COLON, tree: tree) tree << parse_type(tokenizer, tree) tree << parse_optional(tokenizer, K_MINUS2, tree: tree) do parse_comment(tokenizer) end tree end |
#parse_splat_param_type(tokenizer) ⇒ AST::Tree
: (Tokenizer) -> AST::Tree
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 |
# File 'lib/rbs/inline/annotation_parser.rb', line 856 def parse_splat_param_type(tokenizer) tree = AST::Tree.new(:splat_param_type) tokenizer.consume_token!(K_STAR, :kSTAR2, tree: tree) tokenizer.consume_token(T_LVAR, tree: tree) tokenizer.consume_token(K_COLON, tree: tree) tree << parse_type(tokenizer, tree) tree << parse_optional(tokenizer, K_MINUS2, tree: tree) do parse_comment(tokenizer) end tree end |
#parse_type(tokenizer, parent_tree) ⇒ Types::t, ...
Parse a RBS type and returns it
If parsing failed, it returns a Tree(`:type_syntax_error), consuming
- All of the input with
--token if exists (for comments) - All of the input (for anything else)
Integer -- Foo # => Returns `Integer`, tokenizer has `--` as its current token
Integer[ -- Foo # => Returns a tree for `Integer[`, tokenizer has `--` as its current token
Integer[ Foo # => Returns a tree for `Integer[ Foo`, tokenizer is at the end of the input
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 |
# File 'lib/rbs/inline/annotation_parser.rb', line 606 def parse_type(tokenizer, parent_tree) tokenizer.consume_trivias(parent_tree) buffer = RBS::Buffer.new(name: Pathname.new(""), content: tokenizer.scanner.string) byte_range = (tokenizer.current_position..) if type = RBS::Parser.parse_type(buffer, byte_range: byte_range, require_eof: false) loc = type.location or raise tokenizer.reset(loc.end_pos, parent_tree) type else nil end rescue RBS::ParsingError content = tokenizer.skip_to_comment tree = AST::Tree.new(:type_syntax_error) tree << [T_SOURCE, content] tree end |
#parse_type_app(tokenizer) ⇒ AST::Tree
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 |
# File 'lib/rbs/inline/annotation_parser.rb', line 452 def parse_type_app(tokenizer) tree = AST::Tree.new(:tapp) if tokenizer.type?(K_LBRACKET) tree << tokenizer.lookahead1 tokenizer.advance(tree) end types = AST::Tree.new(:types) while true type = parse_type(tokenizer, types) types << type break unless type break if type.is_a?(AST::Tree) if tokenizer.type?(K_COMMA) types << tokenizer.lookahead1 tokenizer.advance(types) end if tokenizer.type?(K_RBRACKET) break end end tree << types if tokenizer.type?(K_RBRACKET) tree << tokenizer.lookahead1 tokenizer.advance(tree) end tree end |
#parse_type_method_type(tokenizer, parent_tree) ⇒ MethodType, ...
Parse a RBS method type or type and returns it
It tries parsing a method type, and then parsing a type if failed.
If both parsing failed, it returns a Tree(`:type_syntax_error), consuming all of the remaining input.
Note that this doesn't recognize -- comment unlike parse_type.
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 |
# File 'lib/rbs/inline/annotation_parser.rb', line 528 def parse_type_method_type(tokenizer, parent_tree) tokenizer.consume_trivias(parent_tree) buffer = RBS::Buffer.new(name: Pathname.new(""), content: tokenizer.scanner.string) byte_range = (tokenizer.current_position..) begin if type = RBS::Parser.parse_method_type(buffer, byte_range: byte_range, require_eof: false) loc = type.location or raise tokenizer.reset(loc.end_pos, parent_tree) type else nil end rescue RBS::ParsingError begin if type = RBS::Parser.parse_type(buffer, byte_range: byte_range, require_eof: false) loc = type.location or raise tokenizer.reset(loc.end_pos, parent_tree) type else nil end rescue RBS::ParsingError tree = AST::Tree.new(:type_syntax_error) tree << [T_SOURCE, tokenizer.rest] tokenizer.scanner.terminate tree end end end |
#parse_type_param(tokenizer) ⇒ AST::Tree
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 |
# File 'lib/rbs/inline/annotation_parser.rb', line 816 def parse_type_param(tokenizer) tree = AST::Tree.new(:type_param) tokenizer.consume_token(K_UNCHECKED, tree: tree) tokenizer.consume_token(K_IN, K_OUT, tree: tree) tokenizer.consume_token(T_UIDENT, tree: tree) tree << parse_optional(tokenizer, K_LT, tree: tree) do bound = AST::Tree.new(:upper_bound) tokenizer.consume_token!(K_LT, tree: bound) bound << parse_type(tokenizer, bound) bound end tree end |
#parse_type_params(tokenizer) ⇒ AST::Tree
955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 |
# File 'lib/rbs/inline/annotation_parser.rb', line 955 def parse_type_params(tokenizer) tree = AST::Tree.new(:type_params) tokenizer.consume_token!(K_LBRACKET, tree: tree) while true if type_param = parse_optional(tokenizer, T_UIDENT, K_UNCHECKED, K_IN, K_OUT) { parse_type_param(tokenizer) } tree << type_param break if tokenizer.type?(K_RBRACKET) tokenizer.consume_token(K_COMMA, tree: tree) else break end end tokenizer.consume_token(K_RBRACKET, tree: tree) tree end |
#parse_use(tokenizer) ⇒ AST::Tree
Parse @rbs use [CLAUSES] annotation
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 |
# File 'lib/rbs/inline/annotation_parser.rb', line 671 def parse_use(tokenizer) tree = AST::Tree.new(:use) if tokenizer.type?(K_USE) tree << tokenizer.lookahead1 tokenizer.advance(tree) end while tokenizer.type?(K_COLON2, T_UIDENT, :tIFIDENT, :tLVAR) tree << parse_use_clause(tokenizer) if tokenizer.type?(K_COMMA) tokenizer.advance(tree, eat: true) else tree << nil end end tree end |
#parse_use_clause(tokenizer) ⇒ AST::Tree
Parses use clause
Returns one of the following form:
- [
::?, [UIDENT,::]*, LIDENT, [asLIDENT]?] - [
::?, [UIDENT,::]*, UIDENT, [asUIDENT]?] - [
::?, [UIDENT,::]*, IFIDENT, [as, IFIDENT]?] - [
::?, [UIDENT)::]*,*]
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 |
# File 'lib/rbs/inline/annotation_parser.rb', line 703 def parse_use_clause(tokenizer) tree = AST::Tree.new(:use_clause) if tokenizer.type?(K_COLON2) tree << tokenizer.lookahead1 tokenizer.advance(tree) end while true case when tokenizer.type?(T_UIDENT) tokenizer.advance(tree, eat: true) case when tokenizer.type?(K_COLON2) tokenizer.advance(tree, eat: true) else break end else break end end case when tokenizer.type?(T_LVAR) tokenizer.advance(tree, eat: true) when tokenizer.type?(T_IFIDENT) tokenizer.advance(tree, eat: true) when tokenizer.type?(K_STAR) tokenizer.advance(tree, eat: true) return tree end if tokenizer.type?(K_AS) as_tree = AST::Tree.new(:as) tokenizer.consume_token!(K_AS, tree: as_tree) tokenizer.consume_token(T_LVAR, T_IFIDENT, T_UIDENT, tree: as_tree) tree << as_tree else tree << nil end tree end |
#parse_var_decl(tokenizer) ⇒ AST::Tree
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
# File 'lib/rbs/inline/annotation_parser.rb', line 399 def parse_var_decl(tokenizer) tree = AST::Tree.new(:var_decl) tokenizer.advance(tree, eat: true) if tokenizer.type?(K_COLON) tree << tokenizer.lookahead1 tokenizer.advance(tree) else tree << nil end tokenizer.consume_trivias(tree) tree << parse_type(tokenizer, tree) tree << parse_optional(tokenizer, K_MINUS2, tree: tree) do parse_comment(tokenizer) end tree end |
#yield_annotation(comments, lines, offset, allow_empty_lines:) {|arg0, is_annotation| ... } ⇒ void
This method returns an undefined value.
The first annotation line is already detected and consumed.
The annotation comment is already in comments.
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/rbs/inline/annotation_parser.rb', line 195 def yield_annotation(comments, lines, offset, allow_empty_lines:, &block) first_comment = lines.first if first_comment nonspace_index = first_comment.location.slice.index(/\S/, 1) case when nonspace_index.nil? if allow_empty_lines lines.shift yield_empty_annotation(comments, [first_comment], lines, offset, &block) else # Starting next paragraph (or annotation) yield(comments, true) yield_paragraph([], lines, &block) end when nonspace_index > offset # Continuation of the annotation lines.shift comments.push(first_comment) yield_annotation(comments, lines, offset, allow_empty_lines: allow_empty_lines, &block) else # Starting next paragraph (or annotation) yield(comments, true) yield_paragraph([], lines, &block) end else yield(comments, true) end end |
#yield_empty_annotation(comments, empty_comments, lines, offset) {|arg0, is_annotation| ... } ⇒ void
This method returns an undefined value.
Consumes empty lines between annotation lines
An empty line is already detected and consumed.
The line is already removed from lines and put in empty_comments.
Note that the arguments, comments, empty_comments, and lines are modified in place.
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 |
# File 'lib/rbs/inline/annotation_parser.rb', line 268 def yield_empty_annotation(comments, empty_comments, lines, offset, &block) first_comment = lines.first if first_comment nonspace_index = first_comment.location.slice.index(/\S/, 1) case when nonspace_index.nil? # Empty line, possibly continues the annotation lines.shift empty_comments << first_comment yield_empty_annotation(comments, empty_comments, lines, offset, &block) when nonspace_index > offset # Continuation of the annotation lines.shift comments.concat(empty_comments) comments.push(first_comment) yield_annotation(comments, lines, offset, allow_empty_lines: true, &block) else yield comments, true yield_paragraph(empty_comments, lines, &block) end else # EOF yield comments, true yield empty_comments, false end end |
#yield_paragraph(comments, lines) {|arg0, is_annotation| ... } ⇒ void
This method returns an undefined value.
The first line is NOT consumed.
The comments may be empty.
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/rbs/inline/annotation_parser.rb', line 234 def yield_paragraph(comments, lines, &block) while first_comment = lines.first if offset = annotation_comment?(first_comment) yield comments, false unless comments.empty? lines.shift case offset when Integer yield_annotation([first_comment], lines, offset, allow_empty_lines: true, &block) when true yield_annotation([first_comment], lines, 1, allow_empty_lines: false, &block) end return else lines.shift comments.push(first_comment) end end yield comments, false unless comments.empty? end |