1# coding: utf-8 2 3require 'rdoc/test_case' 4 5class TestRDocParserRuby < RDoc::TestCase 6 7 def setup 8 super 9 10 @tempfile = Tempfile.new self.class.name 11 @filename = @tempfile.path 12 13 # Some tests need two paths. 14 @tempfile2 = Tempfile.new self.class.name 15 @filename2 = @tempfile2.path 16 17 @top_level = @store.add_file @filename 18 @top_level2 = @store.add_file @filename2 19 20 @options = RDoc::Options.new 21 @options.quiet = true 22 @options.option_parser = OptionParser.new 23 24 @comment = RDoc::Comment.new '', @top_level 25 26 @stats = RDoc::Stats.new @store, 0 27 end 28 29 def teardown 30 super 31 32 @tempfile.close 33 @tempfile2.close 34 end 35 36 def mu_pp obj 37 s = '' 38 s = PP.pp obj, s 39 s = s.force_encoding(Encoding.default_external) if defined? Encoding 40 s.chomp 41 end 42 43 def test_collect_first_comment 44 p = util_parser <<-CONTENT 45# first 46 47# second 48class C; end 49 CONTENT 50 51 comment = p.collect_first_comment 52 53 assert_equal RDoc::Comment.new("# first\n", @top_level), comment 54 end 55 56 def test_collect_first_comment_encoding 57 skip "Encoding not implemented" unless Object.const_defined? :Encoding 58 59 @options.encoding = Encoding::CP852 60 61 p = util_parser <<-CONTENT 62# first 63 64# second 65class C; end 66 CONTENT 67 68 comment = p.collect_first_comment 69 70 assert_equal Encoding::CP852, comment.text.encoding 71 end 72 73 def test_get_class_or_module 74 ctxt = RDoc::Context.new 75 ctxt.store = @store 76 77 cont, name_t, given_name = util_parser('A') .get_class_or_module ctxt 78 79 assert_equal ctxt, cont 80 assert_equal 'A', name_t.text 81 assert_equal 'A', given_name 82 83 cont, name_t, given_name = util_parser('B::C') .get_class_or_module ctxt 84 85 b = @store.find_module_named('B') 86 assert_equal b, cont 87 assert_equal [@top_level], b.in_files 88 assert_equal 'C', name_t.text 89 assert_equal 'B::C', given_name 90 91 cont, name_t, given_name = util_parser('D:: E').get_class_or_module ctxt 92 93 assert_equal @store.find_module_named('D'), cont 94 assert_equal 'E', name_t.text 95 assert_equal 'D::E', given_name 96 97 assert_raises NoMethodError do 98 util_parser("A::\nB").get_class_or_module ctxt 99 end 100 end 101 102 def test_get_class_or_module_document_children 103 ctxt = @top_level.add_class RDoc::NormalClass, 'A' 104 ctxt.stop_doc 105 106 util_parser('B::C').get_class_or_module ctxt 107 108 b = @store.find_module_named('A::B') 109 assert b.ignored? 110 111 d = @top_level.add_class RDoc::NormalClass, 'A::D' 112 113 util_parser('D::E').get_class_or_module ctxt 114 115 refute d.ignored? 116 end 117 118 def test_get_class_or_module_ignore_constants 119 ctxt = RDoc::Context.new 120 ctxt.store = @store 121 122 util_parser('A') .get_class_or_module ctxt, true 123 util_parser('A::B').get_class_or_module ctxt, true 124 125 assert_empty ctxt.constants 126 assert_empty @store.modules_hash.keys 127 assert_empty @store.classes_hash.keys 128 end 129 130 def test_get_class_specification 131 assert_equal 'A', util_parser('A') .get_class_specification 132 assert_equal 'A::B', util_parser('A::B').get_class_specification 133 assert_equal '::A', util_parser('::A').get_class_specification 134 135 assert_equal 'self', util_parser('self').get_class_specification 136 137 assert_equal '', util_parser('').get_class_specification 138 139 assert_equal '', util_parser('$g').get_class_specification 140 end 141 142 def test_get_symbol_or_name 143 util_parser "* & | + 5 / 4" 144 145 assert_equal '*', @parser.get_symbol_or_name 146 147 @parser.skip_tkspace 148 149 assert_equal '&', @parser.get_symbol_or_name 150 151 @parser.skip_tkspace 152 153 assert_equal '|', @parser.get_symbol_or_name 154 155 @parser.skip_tkspace 156 157 assert_equal '+', @parser.get_symbol_or_name 158 159 @parser.skip_tkspace 160 @parser.get_tk 161 @parser.skip_tkspace 162 163 assert_equal '/', @parser.get_symbol_or_name 164 end 165 166 def test_look_for_directives_in_attr 167 util_parser "" 168 169 comment = RDoc::Comment.new "# :attr: my_attr\n", @top_level 170 171 @parser.look_for_directives_in @top_level, comment 172 173 assert_equal "# :attr: my_attr\n", comment.text 174 175 comment = RDoc::Comment.new "# :attr_reader: my_method\n", @top_level 176 177 @parser.look_for_directives_in @top_level, comment 178 179 assert_equal "# :attr_reader: my_method\n", comment.text 180 181 comment = RDoc::Comment.new "# :attr_writer: my_method\n", @top_level 182 183 @parser.look_for_directives_in @top_level, comment 184 185 assert_equal "# :attr_writer: my_method\n", comment.text 186 end 187 188 def test_look_for_directives_in_commented 189 util_parser "" 190 191 comment = RDoc::Comment.new <<-COMMENT, @top_level 192# how to make a section: 193# # :section: new section 194 COMMENT 195 196 @parser.look_for_directives_in @top_level, comment 197 198 section = @top_level.current_section 199 assert_equal nil, section.title 200 assert_equal nil, section.comment 201 202 assert_equal "# how to make a section:\n# # :section: new section\n", 203 comment.text 204 end 205 206 def test_look_for_directives_in_method 207 util_parser "" 208 209 comment = RDoc::Comment.new "# :method: my_method\n", @top_level 210 211 @parser.look_for_directives_in @top_level, comment 212 213 assert_equal "# :method: my_method\n", comment.text 214 215 comment = RDoc::Comment.new "# :singleton-method: my_method\n", @top_level 216 217 @parser.look_for_directives_in @top_level, comment 218 219 assert_equal "# :singleton-method: my_method\n", comment.text 220 end 221 222 def test_look_for_directives_in_section 223 util_parser "" 224 225 comment = RDoc::Comment.new <<-COMMENT, @top_level 226# :section: new section 227# woo stuff 228 COMMENT 229 230 @parser.look_for_directives_in @top_level, comment 231 232 section = @top_level.current_section 233 assert_equal 'new section', section.title 234 assert_equal [comment("# woo stuff\n", @top_level)], section.comments 235 236 assert_empty comment 237 end 238 239 def test_look_for_directives_in_unhandled 240 util_parser "" 241 242 comment = RDoc::Comment.new "# :unhandled: blah\n", @top_level 243 244 @parser.look_for_directives_in @top_level, comment 245 246 assert_equal 'blah', @top_level.metadata['unhandled'] 247 end 248 249 def test_parse_alias 250 klass = RDoc::NormalClass.new 'Foo' 251 klass.parent = @top_level 252 253 util_parser "alias :next= :bar" 254 255 tk = @parser.get_tk 256 257 alas = @parser.parse_alias klass, RDoc::Parser::Ruby::NORMAL, tk, 'comment' 258 259 assert_equal 'bar', alas.old_name 260 assert_equal 'next=', alas.new_name 261 assert_equal klass, alas.parent 262 assert_equal 'comment', alas.comment 263 assert_equal @top_level, alas.file 264 assert_equal 0, alas.offset 265 assert_equal 1, alas.line 266 end 267 268 def test_parse_alias_singleton 269 klass = RDoc::NormalClass.new 'Foo' 270 klass.parent = @top_level 271 272 util_parser "alias :next= :bar" 273 274 tk = @parser.get_tk 275 276 alas = @parser.parse_alias klass, RDoc::Parser::Ruby::SINGLE, tk, 'comment' 277 278 assert_equal 'bar', alas.old_name 279 assert_equal 'next=', alas.new_name 280 assert_equal klass, alas.parent 281 assert_equal 'comment', alas.comment 282 assert_equal @top_level, alas.file 283 assert alas.singleton 284 end 285 286 def test_parse_alias_stopdoc 287 klass = RDoc::NormalClass.new 'Foo' 288 klass.parent = @top_level 289 klass.stop_doc 290 291 util_parser "alias :next= :bar" 292 293 tk = @parser.get_tk 294 295 @parser.parse_alias klass, RDoc::Parser::Ruby::NORMAL, tk, 'comment' 296 297 assert_empty klass.aliases 298 assert_empty klass.unmatched_alias_lists 299 end 300 301 def test_parse_alias_meta 302 klass = RDoc::NormalClass.new 'Foo' 303 klass.parent = @top_level 304 305 util_parser "alias m.chop m" 306 307 tk = @parser.get_tk 308 309 alas = @parser.parse_alias klass, RDoc::Parser::Ruby::NORMAL, tk, 'comment' 310 311 assert_nil alas 312 end 313 314 def test_parse_attr 315 klass = RDoc::NormalClass.new 'Foo' 316 klass.parent = @top_level 317 318 comment = RDoc::Comment.new "##\n# my attr\n", @top_level 319 320 util_parser "attr :foo, :bar" 321 322 tk = @parser.get_tk 323 324 @parser.parse_attr klass, RDoc::Parser::Ruby::NORMAL, tk, comment 325 326 assert_equal 1, klass.attributes.length 327 328 foo = klass.attributes.first 329 assert_equal 'foo', foo.name 330 assert_equal 'my attr', foo.comment.text 331 assert_equal @top_level, foo.file 332 assert_equal 0, foo.offset 333 assert_equal 1, foo.line 334 end 335 336 def test_parse_attr_stopdoc 337 klass = RDoc::NormalClass.new 'Foo' 338 klass.parent = @top_level 339 klass.stop_doc 340 341 comment = RDoc::Comment.new "##\n# my attr\n", @top_level 342 343 util_parser "attr :foo, :bar" 344 345 tk = @parser.get_tk 346 347 @parser.parse_attr klass, RDoc::Parser::Ruby::NORMAL, tk, comment 348 349 assert_empty klass.attributes 350 end 351 352 def test_parse_attr_accessor 353 klass = RDoc::NormalClass.new 'Foo' 354 klass.parent = @top_level 355 356 comment = RDoc::Comment.new "##\n# my attr\n", @top_level 357 358 util_parser "attr_accessor :foo, :bar" 359 360 tk = @parser.get_tk 361 362 @parser.parse_attr_accessor klass, RDoc::Parser::Ruby::NORMAL, tk, comment 363 364 assert_equal 2, klass.attributes.length 365 366 foo = klass.attributes.first 367 assert_equal 'foo', foo.name 368 assert_equal 'RW', foo.rw 369 assert_equal 'my attr', foo.comment.text 370 assert_equal @top_level, foo.file 371 assert_equal 0, foo.offset 372 assert_equal 1, foo.line 373 374 bar = klass.attributes.last 375 assert_equal 'bar', bar.name 376 assert_equal 'RW', bar.rw 377 assert_equal 'my attr', bar.comment.text 378 end 379 380 def test_parse_attr_accessor_nodoc 381 klass = RDoc::NormalClass.new 'Foo' 382 klass.parent = @top_level 383 384 comment = RDoc::Comment.new "##\n# my attr\n", @top_level 385 386 util_parser "attr_accessor :foo, :bar # :nodoc:" 387 388 tk = @parser.get_tk 389 390 @parser.parse_attr_accessor klass, RDoc::Parser::Ruby::NORMAL, tk, comment 391 392 assert_equal 0, klass.attributes.length 393 end 394 395 def test_parse_attr_accessor_stopdoc 396 klass = RDoc::NormalClass.new 'Foo' 397 klass.parent = @top_level 398 klass.stop_doc 399 400 comment = RDoc::Comment.new "##\n# my attr\n", @top_level 401 402 util_parser "attr_accessor :foo, :bar" 403 404 tk = @parser.get_tk 405 406 @parser.parse_attr_accessor klass, RDoc::Parser::Ruby::NORMAL, tk, comment 407 408 assert_empty klass.attributes 409 end 410 411 def test_parse_attr_accessor_writer 412 klass = RDoc::NormalClass.new 'Foo' 413 klass.parent = @top_level 414 415 comment = RDoc::Comment.new "##\n# my attr\n", @top_level 416 417 util_parser "attr_writer :foo, :bar" 418 419 tk = @parser.get_tk 420 421 @parser.parse_attr_accessor klass, RDoc::Parser::Ruby::NORMAL, tk, comment 422 423 assert_equal 2, klass.attributes.length 424 425 foo = klass.attributes.first 426 assert_equal 'foo', foo.name 427 assert_equal 'W', foo.rw 428 assert_equal "my attr", foo.comment.text 429 assert_equal @top_level, foo.file 430 431 bar = klass.attributes.last 432 assert_equal 'bar', bar.name 433 assert_equal 'W', bar.rw 434 assert_equal "my attr", bar.comment.text 435 end 436 437 def test_parse_meta_attr 438 klass = RDoc::NormalClass.new 'Foo' 439 klass.parent = @top_level 440 441 comment = RDoc::Comment.new "##\n# :attr: \n# my method\n", @top_level 442 443 util_parser "add_my_method :foo, :bar" 444 445 tk = @parser.get_tk 446 447 @parser.parse_meta_attr klass, RDoc::Parser::Ruby::NORMAL, tk, comment 448 449 assert_equal 2, klass.attributes.length 450 foo = klass.attributes.first 451 assert_equal 'foo', foo.name 452 assert_equal 'RW', foo.rw 453 assert_equal "my method", foo.comment.text 454 assert_equal @top_level, foo.file 455 end 456 457 def test_parse_meta_attr_accessor 458 klass = RDoc::NormalClass.new 'Foo' 459 klass.parent = @top_level 460 461 comment = 462 RDoc::Comment.new "##\n# :attr_accessor: \n# my method\n", @top_level 463 464 util_parser "add_my_method :foo, :bar" 465 466 tk = @parser.get_tk 467 468 @parser.parse_meta_attr klass, RDoc::Parser::Ruby::NORMAL, tk, comment 469 470 assert_equal 2, klass.attributes.length 471 foo = klass.attributes.first 472 assert_equal 'foo', foo.name 473 assert_equal 'RW', foo.rw 474 assert_equal 'my method', foo.comment.text 475 assert_equal @top_level, foo.file 476 end 477 478 def test_parse_meta_attr_named 479 klass = RDoc::NormalClass.new 'Foo' 480 klass.parent = @top_level 481 482 comment = RDoc::Comment.new "##\n# :attr: foo\n# my method\n", @top_level 483 484 util_parser "add_my_method :foo, :bar" 485 486 tk = @parser.get_tk 487 488 @parser.parse_meta_attr klass, RDoc::Parser::Ruby::NORMAL, tk, comment 489 490 assert_equal 1, klass.attributes.length 491 foo = klass.attributes.first 492 assert_equal 'foo', foo.name 493 assert_equal 'RW', foo.rw 494 assert_equal 'my method', foo.comment.text 495 assert_equal @top_level, foo.file 496 end 497 498 def test_parse_meta_attr_reader 499 klass = RDoc::NormalClass.new 'Foo' 500 klass.parent = @top_level 501 502 comment = 503 RDoc::Comment.new "##\n# :attr_reader: \n# my method\n", @top_level 504 505 util_parser "add_my_method :foo, :bar" 506 507 tk = @parser.get_tk 508 509 @parser.parse_meta_attr klass, RDoc::Parser::Ruby::NORMAL, tk, comment 510 511 foo = klass.attributes.first 512 assert_equal 'foo', foo.name 513 assert_equal 'R', foo.rw 514 assert_equal 'my method', foo.comment.text 515 assert_equal @top_level, foo.file 516 end 517 518 def test_parse_meta_attr_stopdoc 519 klass = RDoc::NormalClass.new 'Foo' 520 klass.parent = @top_level 521 klass.stop_doc 522 523 comment = RDoc::Comment.new "##\n# :attr: \n# my method\n", @top_level 524 525 util_parser "add_my_method :foo, :bar" 526 527 tk = @parser.get_tk 528 529 @parser.parse_meta_attr klass, RDoc::Parser::Ruby::NORMAL, tk, comment 530 531 assert_empty klass.attributes 532 end 533 534 def test_parse_meta_attr_writer 535 klass = RDoc::NormalClass.new 'Foo' 536 klass.parent = @top_level 537 538 comment = 539 RDoc::Comment.new "##\n# :attr_writer: \n# my method\n", @top_level 540 541 util_parser "add_my_method :foo, :bar" 542 543 tk = @parser.get_tk 544 545 @parser.parse_meta_attr klass, RDoc::Parser::Ruby::NORMAL, tk, comment 546 547 foo = klass.attributes.first 548 assert_equal 'foo', foo.name 549 assert_equal 'W', foo.rw 550 assert_equal "my method", foo.comment.text 551 assert_equal @top_level, foo.file 552 end 553 554 def test_parse_class 555 comment = RDoc::Comment.new "##\n# my class\n", @top_level 556 557 util_parser "class Foo\nend" 558 559 tk = @parser.get_tk 560 561 @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment 562 563 foo = @top_level.classes.first 564 assert_equal 'Foo', foo.full_name 565 assert_equal 'my class', foo.comment.text 566 assert_equal [@top_level], foo.in_files 567 assert_equal 0, foo.offset 568 assert_equal 1, foo.line 569 end 570 571 def test_parse_class_ghost_method 572 util_parser <<-CLASS 573class Foo 574 ## 575 # :method: blah 576 # my method 577end 578 CLASS 579 580 tk = @parser.get_tk 581 582 @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment 583 584 foo = @top_level.classes.first 585 assert_equal 'Foo', foo.full_name 586 587 blah = foo.method_list.first 588 assert_equal 'Foo#blah', blah.full_name 589 assert_equal @top_level, blah.file 590 end 591 592 def test_parse_class_multi_ghost_methods 593 util_parser <<-'CLASS' 594class Foo 595 ## 596 # :method: one 597 # 598 # my method 599 600 ## 601 # :method: two 602 # 603 # my method 604 605 [:one, :two].each do |t| 606 eval("def #{t}; \"#{t}\"; end") 607 end 608end 609 CLASS 610 611 tk = @parser.get_tk 612 613 @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment 614 615 foo = @top_level.classes.first 616 assert_equal 'Foo', foo.full_name 617 618 assert_equal 2, foo.method_list.length 619 end 620 621 def test_parse_class_nodoc 622 comment = RDoc::Comment.new "##\n# my class\n", @top_level 623 624 util_parser "class Foo # :nodoc:\nend" 625 626 tk = @parser.get_tk 627 628 @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment 629 630 foo = @top_level.classes.first 631 assert_equal 'Foo', foo.full_name 632 assert_empty foo.comment 633 assert_equal [@top_level], foo.in_files 634 assert_equal 0, foo.offset 635 assert_equal 1, foo.line 636 end 637 638 def test_parse_class_single_root 639 comment = RDoc::Comment.new "##\n# my class\n", @top_level 640 641 util_parser "class << ::Foo\nend" 642 643 tk = @parser.get_tk 644 645 @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment 646 647 foo = @store.all_modules.first 648 assert_equal 'Foo', foo.full_name 649 end 650 651 def test_parse_class_stopdoc 652 @top_level.stop_doc 653 654 comment = RDoc::Comment.new "##\n# my class\n", @top_level 655 656 util_parser "class Foo\nend" 657 658 tk = @parser.get_tk 659 660 @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment 661 662 assert_empty @top_level.classes.first.comment 663 end 664 665 def test_parse_multi_ghost_methods 666 util_parser <<-'CLASS' 667class Foo 668 ## 669 # :method: one 670 # 671 # my method 672 673 ## 674 # :method: two 675 # 676 # my method 677 678 [:one, :two].each do |t| 679 eval("def #{t}; \"#{t}\"; end") 680 end 681end 682 CLASS 683 684 tk = @parser.get_tk 685 686 @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment 687 688 foo = @top_level.classes.first 689 assert_equal 'Foo', foo.full_name 690 691 assert_equal 2, foo.method_list.length 692 end 693 694 def test_parse_const_fail_w_meta 695 util_parser <<-CLASS 696class ConstFailMeta 697 ## 698 # :attr: one 699 # 700 # an attribute 701 702 OtherModule.define_attr(self, :one) 703end 704 CLASS 705 706 tk = @parser.get_tk 707 708 @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment 709 710 const_fail_meta = @top_level.classes.first 711 assert_equal 'ConstFailMeta', const_fail_meta.full_name 712 713 assert_equal 1, const_fail_meta.attributes.length 714 end 715 716 def test_parse_class_nested_superclass 717 foo = @top_level.add_module RDoc::NormalModule, 'Foo' 718 719 util_parser "class Bar < Super\nend" 720 721 tk = @parser.get_tk 722 723 @parser.parse_class foo, RDoc::Parser::Ruby::NORMAL, tk, @comment 724 725 bar = foo.classes.first 726 assert_equal 'Super', bar.superclass 727 end 728 729 def test_parse_module 730 comment = RDoc::Comment.new "##\n# my module\n", @top_level 731 732 util_parser "module Foo\nend" 733 734 tk = @parser.get_tk 735 736 @parser.parse_module @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment 737 738 foo = @top_level.modules.first 739 assert_equal 'Foo', foo.full_name 740 assert_equal 'my module', foo.comment.text 741 end 742 743 def test_parse_module_nodoc 744 @top_level.stop_doc 745 746 comment = RDoc::Comment.new "##\n# my module\n", @top_level 747 748 util_parser "module Foo # :nodoc:\nend" 749 750 tk = @parser.get_tk 751 752 @parser.parse_module @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment 753 754 foo = @top_level.modules.first 755 assert_equal 'Foo', foo.full_name 756 assert_empty foo.comment 757 end 758 759 def test_parse_module_stopdoc 760 @top_level.stop_doc 761 762 comment = RDoc::Comment.new "##\n# my module\n", @top_level 763 764 util_parser "module Foo\nend" 765 766 tk = @parser.get_tk 767 768 @parser.parse_module @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment 769 770 foo = @top_level.modules.first 771 assert_equal 'Foo', foo.full_name 772 assert_empty foo.comment 773 end 774 775 def test_parse_class_colon3 776 code = <<-CODE 777class A 778 class ::B 779 end 780end 781 CODE 782 783 util_parser code 784 785 @parser.parse_class @top_level, false, @parser.get_tk, @comment 786 787 assert_equal %w[A B], @store.all_classes.map { |c| c.full_name }.sort 788 end 789 790 def test_parse_class_colon3_self_reference 791 code = <<-CODE 792class A::B 793 class ::A 794 end 795end 796 CODE 797 798 util_parser code 799 800 @parser.parse_class @top_level, false, @parser.get_tk, @comment 801 802 assert_equal %w[A A::B], @store.all_classes.map { |c| c.full_name }.sort 803 end 804 805 def test_parse_class_single 806 code = <<-CODE 807class A 808 class << B 809 end 810 class << d = Object.new 811 def foo; end 812 alias bar foo 813 end 814end 815 CODE 816 817 util_parser code 818 819 @parser.parse_class @top_level, false, @parser.get_tk, @comment 820 821 assert_equal %w[A], @store.all_classes.map { |c| c.full_name } 822 823 modules = @store.all_modules.sort_by { |c| c.full_name } 824 assert_equal %w[A::B A::d], modules.map { |c| c.full_name } 825 826 b = modules.first 827 assert_equal 10, b.offset 828 assert_equal 2, b.line 829 830 # make sure method/alias was not added to enclosing class/module 831 a = @store.classes_hash['A'] 832 assert_empty a.method_list 833 834 # make sure non-constant-named module will be removed from documentation 835 d = @store.modules_hash['A::d'] 836 assert d.remove_from_documentation? 837 end 838 839 def test_parse_class_single_gvar 840 code = <<-CODE 841class << $g 842 def m 843 end 844end 845 CODE 846 847 util_parser code 848 849 @parser.parse_class @top_level, false, @parser.get_tk, '' 850 851 assert_empty @store.all_classes 852 mod = @store.all_modules.first 853 854 refute mod.document_self 855 856 assert_empty mod.method_list 857 end 858 859 # TODO this is really a Context#add_class test 860 def test_parse_class_object 861 code = <<-CODE 862module A 863 class B 864 end 865 class Object 866 end 867 class C < Object 868 end 869end 870 CODE 871 872 util_parser code 873 874 @parser.parse_module @top_level, false, @parser.get_tk, @comment 875 876 assert_equal %w[A], 877 @store.all_modules.map { |c| c.full_name } 878 assert_equal %w[A::B A::C A::Object], 879 @store.all_classes.map { |c| c.full_name }.sort 880 881 assert_equal 'Object', @store.classes_hash['A::B'].superclass 882 assert_equal 'Object', @store.classes_hash['A::Object'].superclass 883 assert_equal 'A::Object', @store.classes_hash['A::C'].superclass.full_name 884 end 885 886 def test_parse_class_mistaken_for_module 887 # The code below is not strictly legal Ruby (Foo must have been defined 888 # before Foo::Bar is encountered), but RDoc might encounter Foo::Bar 889 # before Foo if they live in different files. 890 891 code = <<-RUBY 892class Foo::Bar 893end 894 895module Foo::Baz 896end 897 898class Foo 899end 900 RUBY 901 902 util_parser code 903 904 @parser.scan 905 906 assert_equal %w[Foo::Baz], @store.modules_hash.keys 907 assert_empty @top_level.modules 908 909 foo = @top_level.classes.first 910 assert_equal 'Foo', foo.full_name 911 912 bar = foo.classes.first 913 assert_equal 'Foo::Bar', bar.full_name 914 915 baz = foo.modules.first 916 assert_equal 'Foo::Baz', baz.full_name 917 end 918 919 def test_parse_class_definition_encountered_after_class_reference 920 # The code below is not legal Ruby (Foo must have been defined before 921 # Foo.bar is encountered), but RDoc might encounter Foo.bar before Foo if 922 # they live in different files. 923 924 code = <<-EOF 925def Foo.bar 926end 927 928class Foo < IO 929end 930 EOF 931 932 util_parser code 933 934 @parser.scan 935 936 assert_empty @store.modules_hash 937 assert_empty @store.all_modules 938 939 foo = @top_level.classes.first 940 assert_equal 'Foo', foo.full_name 941 assert_equal 'IO', foo.superclass 942 943 bar = foo.method_list.first 944 assert_equal 'bar', bar.name 945 end 946 947 def test_parse_module_relative_to_top_level_namespace 948 comment = RDoc::Comment.new <<-EOF, @top_level 949# 950# Weirdly named module 951# 952EOF 953 954 code = <<-EOF 955#{comment.text} 956module ::Foo 957 class Helper 958 end 959end 960EOF 961 962 util_parser code 963 @parser.scan() 964 965 foo = @top_level.modules.first 966 assert_equal 'Foo', foo.full_name 967 assert_equal 'Weirdly named module', foo.comment.text 968 969 helper = foo.classes.first 970 assert_equal 'Foo::Helper', helper.full_name 971 end 972 973 def test_parse_comment_attr 974 klass = RDoc::NormalClass.new 'Foo' 975 klass.parent = @top_level 976 977 comment = RDoc::Comment.new "##\n# :attr: foo\n# my attr\n", @top_level 978 979 util_parser "\n" 980 981 tk = @parser.get_tk 982 983 @parser.parse_comment klass, tk, comment 984 985 foo = klass.attributes.first 986 assert_equal 'foo', foo.name 987 assert_equal 'RW', foo.rw 988 assert_equal 'my attr', foo.comment.text 989 assert_equal @top_level, foo.file 990 assert_equal 0, foo.offset 991 assert_equal 1, foo.line 992 993 assert_equal nil, foo.viewer 994 assert_equal true, foo.document_children 995 assert_equal true, foo.document_self 996 assert_equal false, foo.done_documenting 997 assert_equal false, foo.force_documentation 998 assert_equal klass, foo.parent 999 assert_equal :public, foo.visibility 1000 assert_equal "\n", foo.text 1001 1002 assert_equal klass.current_section, foo.section 1003 end 1004 1005 def test_parse_comment_attr_stopdoc 1006 klass = RDoc::NormalClass.new 'Foo' 1007 klass.parent = @top_level 1008 klass.stop_doc 1009 1010 comment = RDoc::Comment.new "##\n# :attr: foo\n# my attr\n", @top_level 1011 1012 util_parser "\n" 1013 1014 tk = @parser.get_tk 1015 1016 @parser.parse_comment klass, tk, comment 1017 1018 assert_empty klass.attributes 1019 end 1020 1021 def test_parse_comment_method 1022 klass = RDoc::NormalClass.new 'Foo' 1023 klass.parent = @top_level 1024 1025 comment = RDoc::Comment.new "##\n# :method: foo\n# my method\n", @top_level 1026 1027 util_parser "\n" 1028 1029 tk = @parser.get_tk 1030 1031 @parser.parse_comment klass, tk, comment 1032 1033 foo = klass.method_list.first 1034 assert_equal 'foo', foo.name 1035 assert_equal 'my method', foo.comment.text 1036 assert_equal @top_level, foo.file 1037 assert_equal 0, foo.offset 1038 assert_equal 1, foo.line 1039 1040 assert_equal [], foo.aliases 1041 assert_equal nil, foo.block_params 1042 assert_equal nil, foo.call_seq 1043 assert_equal nil, foo.is_alias_for 1044 assert_equal nil, foo.viewer 1045 assert_equal true, foo.document_children 1046 assert_equal true, foo.document_self 1047 assert_equal '', foo.params 1048 assert_equal false, foo.done_documenting 1049 assert_equal false, foo.dont_rename_initialize 1050 assert_equal false, foo.force_documentation 1051 assert_equal klass, foo.parent 1052 assert_equal false, foo.singleton 1053 assert_equal :public, foo.visibility 1054 assert_equal "\n", foo.text 1055 assert_equal klass.current_section, foo.section 1056 1057 stream = [ 1058 tk(:COMMENT, 0, 1, 1, nil, 1059 "# File #{@top_level.relative_name}, line 1"), 1060 RDoc::Parser::Ruby::NEWLINE_TOKEN, 1061 tk(:SPACE, 0, 1, 1, nil, ''), 1062 ] 1063 1064 assert_equal stream, foo.token_stream 1065 end 1066 1067 def test_parse_comment_method_stopdoc 1068 klass = RDoc::NormalClass.new 'Foo' 1069 klass.parent = @top_level 1070 klass.stop_doc 1071 1072 comment = RDoc::Comment.new "##\n# :method: foo\n# my method\n", @top_level 1073 1074 util_parser "\n" 1075 1076 tk = @parser.get_tk 1077 1078 @parser.parse_comment klass, tk, comment 1079 1080 assert_empty klass.method_list 1081 end 1082 1083 def test_parse_constant 1084 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 1085 1086 util_parser "A = v" 1087 1088 tk = @parser.get_tk 1089 1090 @parser.parse_constant klass, tk, @comment 1091 1092 foo = klass.constants.first 1093 1094 assert_equal 'A', foo.name 1095 assert_equal @top_level, foo.file 1096 assert_equal 0, foo.offset 1097 assert_equal 1, foo.line 1098 end 1099 1100 def test_parse_constant_attrasgn 1101 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 1102 1103 util_parser "A[k] = v" 1104 1105 tk = @parser.get_tk 1106 1107 @parser.parse_constant klass, tk, @comment 1108 1109 assert klass.constants.empty? 1110 end 1111 1112 def test_parse_constant_alias 1113 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 1114 klass.add_class RDoc::NormalClass, 'B' 1115 1116 util_parser "A = B" 1117 1118 tk = @parser.get_tk 1119 1120 @parser.parse_constant klass, tk, @comment 1121 1122 assert_equal 'Foo::A', klass.find_module_named('A').full_name 1123 end 1124 1125 def test_parse_constant_alias_same_name 1126 foo = @top_level.add_class RDoc::NormalClass, 'Foo' 1127 @top_level.add_class RDoc::NormalClass, 'Bar' 1128 bar = foo.add_class RDoc::NormalClass, 'Bar' 1129 1130 assert @store.find_class_or_module('::Bar') 1131 1132 util_parser "A = ::Bar" 1133 1134 tk = @parser.get_tk 1135 1136 @parser.parse_constant foo, tk, @comment 1137 1138 assert_equal 'A', bar.find_module_named('A').full_name 1139 end 1140 1141 def test_parse_constant_in_method 1142 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 1143 1144 util_parser 'A::B = v' 1145 1146 tk = @parser.get_tk 1147 1148 @parser.parse_constant klass, tk, @comment, true 1149 1150 assert_empty klass.constants 1151 1152 assert_empty @store.modules_hash.keys 1153 assert_equal %w[Foo], @store.classes_hash.keys 1154 end 1155 1156 def test_parse_constant_rescue 1157 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 1158 1159 util_parser "A => e" 1160 1161 tk = @parser.get_tk 1162 1163 @parser.parse_constant klass, tk, @comment 1164 1165 assert_empty klass.constants 1166 assert_empty klass.modules 1167 1168 assert_empty @store.modules_hash.keys 1169 assert_equal %w[Foo], @store.classes_hash.keys 1170 end 1171 1172 def test_parse_constant_stopdoc 1173 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 1174 klass.stop_doc 1175 1176 util_parser "A = v" 1177 1178 tk = @parser.get_tk 1179 1180 @parser.parse_constant klass, tk, @comment 1181 1182 assert_empty klass.constants 1183 end 1184 1185 def test_parse_comment_nested 1186 content = <<-CONTENT 1187A::B::C = 1 1188 CONTENT 1189 1190 util_parser content 1191 1192 tk = @parser.get_tk 1193 1194 parsed = @parser.parse_constant @top_level, tk, 'comment' 1195 1196 assert parsed 1197 1198 a = @top_level.find_module_named 'A' 1199 b = a.find_module_named 'B' 1200 c = b.constants.first 1201 1202 assert_equal 'A::B::C', c.full_name 1203 assert_equal 'comment', c.comment 1204 end 1205 1206 def test_parse_include 1207 klass = RDoc::NormalClass.new 'C' 1208 klass.parent = @top_level 1209 1210 comment = RDoc::Comment.new "# my include\n", @top_level 1211 1212 util_parser "include I" 1213 1214 @parser.get_tk # include 1215 1216 @parser.parse_include klass, comment 1217 1218 assert_equal 1, klass.includes.length 1219 1220 incl = klass.includes.first 1221 assert_equal 'I', incl.name 1222 assert_equal 'my include', incl.comment.text 1223 assert_equal @top_level, incl.file 1224 end 1225 1226 def test_parse_extend 1227 klass = RDoc::NormalClass.new 'C' 1228 klass.parent = @top_level 1229 1230 comment = RDoc::Comment.new "# my extend\n", @top_level 1231 1232 util_parser "extend I" 1233 1234 @parser.get_tk # extend 1235 1236 @parser.parse_extend klass, comment 1237 1238 assert_equal 1, klass.extends.length 1239 1240 ext = klass.extends.first 1241 assert_equal 'I', ext.name 1242 assert_equal 'my extend', ext.comment.text 1243 assert_equal @top_level, ext.file 1244 end 1245 1246 def test_parse_meta_method 1247 klass = RDoc::NormalClass.new 'Foo' 1248 klass.parent = @top_level 1249 1250 comment = RDoc::Comment.new "##\n# my method\n", @top_level 1251 1252 util_parser "add_my_method :foo, :bar\nadd_my_method :baz" 1253 1254 tk = @parser.get_tk 1255 1256 @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1257 1258 foo = klass.method_list.first 1259 assert_equal 'foo', foo.name 1260 assert_equal 'my method', foo.comment.text 1261 assert_equal @top_level, foo.file 1262 assert_equal 0, foo.offset 1263 assert_equal 1, foo.line 1264 1265 assert_equal [], foo.aliases 1266 assert_equal nil, foo.block_params 1267 assert_equal nil, foo.call_seq 1268 assert_equal true, foo.document_children 1269 assert_equal true, foo.document_self 1270 assert_equal false, foo.done_documenting 1271 assert_equal false, foo.dont_rename_initialize 1272 assert_equal false, foo.force_documentation 1273 assert_equal nil, foo.is_alias_for 1274 assert_equal '', foo.params 1275 assert_equal klass, foo.parent 1276 assert_equal false, foo.singleton 1277 assert_equal 'add_my_method :foo', foo.text 1278 assert_equal nil, foo.viewer 1279 assert_equal :public, foo.visibility 1280 assert_equal klass.current_section, foo.section 1281 1282 stream = [ 1283 tk(:COMMENT, 0, 1, 1, nil, 1284 "# File #{@top_level.relative_name}, line 1"), 1285 RDoc::Parser::Ruby::NEWLINE_TOKEN, 1286 tk(:SPACE, 0, 1, 1, nil, ''), 1287 tk(:IDENTIFIER, 0, 1, 0, 'add_my_method', 'add_my_method'), 1288 tk(:SPACE, 0, 1, 13, nil, ' '), 1289 tk(:SYMBOL, 0, 1, 14, nil, ':foo'), 1290 tk(:COMMA, 0, 1, 18, nil, ','), 1291 tk(:SPACE, 0, 1, 19, nil, ' '), 1292 tk(:SYMBOL, 0, 1, 20, nil, ':bar'), 1293 tk(:NL, 0, 1, 24, nil, "\n"), 1294 ] 1295 1296 assert_equal stream, foo.token_stream 1297 end 1298 1299 def test_parse_meta_method_block 1300 klass = RDoc::NormalClass.new 'Foo' 1301 klass.parent = @top_level 1302 1303 comment = RDoc::Comment.new "##\n# my method\n", @top_level 1304 1305 content = <<-CONTENT 1306inline(:my_method) do |*args| 1307 "this method causes z to disappear" 1308end 1309 CONTENT 1310 1311 util_parser content 1312 1313 tk = @parser.get_tk 1314 1315 @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1316 1317 assert_equal tk(:NL, 0, 3, 3, 3, "\n"), @parser.get_tk 1318 end 1319 1320 def test_parse_meta_method_define_method 1321 klass = RDoc::NormalClass.new 'Foo' 1322 comment = RDoc::Comment.new "##\n# my method\n", @top_level 1323 1324 util_parser "define_method :foo do end" 1325 1326 tk = @parser.get_tk 1327 1328 @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1329 1330 foo = klass.method_list.first 1331 assert_equal 'foo', foo.name 1332 assert_equal 'my method', foo.comment.text 1333 assert_equal @top_level, foo.file 1334 end 1335 1336 def test_parse_meta_method_name 1337 klass = RDoc::NormalClass.new 'Foo' 1338 klass.parent = @top_level 1339 1340 comment = 1341 RDoc::Comment.new "##\n# :method: woo_hoo!\n# my method\n", @top_level 1342 1343 util_parser "add_my_method :foo, :bar\nadd_my_method :baz" 1344 1345 tk = @parser.get_tk 1346 1347 @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1348 1349 foo = klass.method_list.first 1350 assert_equal 'woo_hoo!', foo.name 1351 assert_equal 'my method', foo.comment.text 1352 assert_equal @top_level, foo.file 1353 end 1354 1355 def test_parse_meta_method_singleton 1356 klass = RDoc::NormalClass.new 'Foo' 1357 klass.parent = @top_level 1358 1359 comment = 1360 RDoc::Comment.new "##\n# :singleton-method:\n# my method\n", @top_level 1361 1362 util_parser "add_my_method :foo, :bar\nadd_my_method :baz" 1363 1364 tk = @parser.get_tk 1365 1366 @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1367 1368 foo = klass.method_list.first 1369 assert_equal 'foo', foo.name 1370 assert_equal true, foo.singleton, 'singleton method' 1371 assert_equal 'my method', foo.comment.text 1372 assert_equal @top_level, foo.file 1373 end 1374 1375 def test_parse_meta_method_singleton_name 1376 klass = RDoc::NormalClass.new 'Foo' 1377 klass.parent = @top_level 1378 1379 comment = 1380 RDoc::Comment.new "##\n# :singleton-method: woo_hoo!\n# my method\n", 1381 @top_level 1382 1383 util_parser "add_my_method :foo, :bar\nadd_my_method :baz" 1384 1385 tk = @parser.get_tk 1386 1387 @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1388 1389 foo = klass.method_list.first 1390 assert_equal 'woo_hoo!', foo.name 1391 assert_equal true, foo.singleton, 'singleton method' 1392 assert_equal 'my method', foo.comment.text 1393 assert_equal @top_level, foo.file 1394 end 1395 1396 def test_parse_meta_method_string_name 1397 klass = RDoc::NormalClass.new 'Foo' 1398 comment = RDoc::Comment.new "##\n# my method\n", @top_level 1399 1400 util_parser "add_my_method 'foo'" 1401 1402 tk = @parser.get_tk 1403 1404 @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1405 1406 foo = klass.method_list.first 1407 assert_equal 'foo', foo.name 1408 assert_equal 'my method', foo.comment.text 1409 assert_equal @top_level, foo.file 1410 end 1411 1412 def test_parse_meta_method_stopdoc 1413 klass = RDoc::NormalClass.new 'Foo' 1414 klass.parent = @top_level 1415 klass.stop_doc 1416 1417 comment = RDoc::Comment.new "##\n# my method\n", @top_level 1418 1419 util_parser "add_my_method :foo, :bar\nadd_my_method :baz" 1420 1421 tk = @parser.get_tk 1422 1423 @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1424 1425 assert_empty klass.method_list 1426 end 1427 1428 def test_parse_meta_method_unknown 1429 klass = RDoc::NormalClass.new 'Foo' 1430 comment = RDoc::Comment.new "##\n# my method\n", @top_level 1431 1432 util_parser "add_my_method ('foo')" 1433 1434 tk = @parser.get_tk 1435 1436 @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1437 1438 foo = klass.method_list.first 1439 assert_equal 'unknown', foo.name 1440 assert_equal 'my method', foo.comment.text 1441 assert_equal @top_level, foo.file 1442 end 1443 1444 def test_parse_method 1445 klass = RDoc::NormalClass.new 'Foo' 1446 klass.parent = @top_level 1447 1448 comment = RDoc::Comment.new "##\n# my method\n", @top_level 1449 1450 util_parser "def foo() :bar end" 1451 1452 tk = @parser.get_tk 1453 1454 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1455 1456 foo = klass.method_list.first 1457 assert_equal 'foo', foo.name 1458 assert_equal 'my method', foo.comment.text 1459 assert_equal @top_level, foo.file 1460 assert_equal 0, foo.offset 1461 assert_equal 1, foo.line 1462 1463 assert_equal [], foo.aliases 1464 assert_equal nil, foo.block_params 1465 assert_equal nil, foo.call_seq 1466 assert_equal nil, foo.is_alias_for 1467 assert_equal nil, foo.viewer 1468 assert_equal true, foo.document_children 1469 assert_equal true, foo.document_self 1470 assert_equal '()', foo.params 1471 assert_equal false, foo.done_documenting 1472 assert_equal false, foo.dont_rename_initialize 1473 assert_equal false, foo.force_documentation 1474 assert_equal klass, foo.parent 1475 assert_equal false, foo.singleton 1476 assert_equal :public, foo.visibility 1477 assert_equal 'def foo', foo.text 1478 assert_equal klass.current_section, foo.section 1479 1480 stream = [ 1481 tk(:COMMENT, 0, 1, 1, nil, 1482 "# File #{@top_level.relative_name}, line 1"), 1483 RDoc::Parser::Ruby::NEWLINE_TOKEN, 1484 tk(:SPACE, 0, 1, 1, nil, ''), 1485 tk(:DEF, 0, 1, 0, 'def', 'def'), 1486 tk(:SPACE, 3, 1, 3, nil, ' '), 1487 tk(:IDENTIFIER, 4, 1, 4, 'foo', 'foo'), 1488 tk(:LPAREN, 7, 1, 7, nil, '('), 1489 tk(:RPAREN, 8, 1, 8, nil, ')'), 1490 tk(:SPACE, 9, 1, 9, nil, ' '), 1491 tk(:COLON, 10, 1, 10, nil, ':'), 1492 tk(:IDENTIFIER, 11, 1, 11, 'bar', 'bar'), 1493 tk(:SPACE, 14, 1, 14, nil, ' '), 1494 tk(:END, 15, 1, 15, 'end', 'end'), 1495 ] 1496 1497 assert_equal stream, foo.token_stream 1498 end 1499 1500 def test_parse_method_alias 1501 klass = RDoc::NormalClass.new 'Foo' 1502 klass.parent = @top_level 1503 1504 util_parser "def m() alias a b; end" 1505 1506 tk = @parser.get_tk 1507 1508 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1509 1510 assert klass.aliases.empty? 1511 end 1512 1513 def test_parse_method_ampersand 1514 klass = RDoc::NormalClass.new 'Foo' 1515 klass.parent = @top_level 1516 1517 util_parser "def self.&\nend" 1518 1519 tk = @parser.get_tk 1520 1521 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1522 1523 ampersand = klass.method_list.first 1524 assert_equal '&', ampersand.name 1525 assert ampersand.singleton 1526 end 1527 1528 def test_parse_method_constant 1529 c = RDoc::Constant.new 'CONST', nil, '' 1530 m = @top_level.add_class RDoc::NormalModule, 'M' 1531 m.add_constant c 1532 1533 util_parser "def CONST.m() end" 1534 1535 tk = @parser.get_tk 1536 1537 @parser.parse_method m, RDoc::Parser::Ruby::NORMAL, tk, @comment 1538 1539 assert_empty @store.modules_hash.keys 1540 assert_equal %w[M], @store.classes_hash.keys 1541 end 1542 1543 def test_parse_method_false 1544 util_parser "def false.foo() :bar end" 1545 1546 tk = @parser.get_tk 1547 1548 @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment 1549 1550 klass = @store.find_class_named 'FalseClass' 1551 1552 foo = klass.method_list.first 1553 assert_equal 'foo', foo.name 1554 end 1555 1556 def test_parse_method_funky 1557 klass = RDoc::NormalClass.new 'Foo' 1558 klass.parent = @top_level 1559 1560 util_parser "def (blah).foo() :bar end" 1561 1562 tk = @parser.get_tk 1563 1564 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1565 1566 assert_empty klass.method_list 1567 end 1568 1569 def test_parse_method_gvar 1570 util_parser "def $stdout.foo() :bar end" 1571 1572 tk = @parser.get_tk 1573 1574 @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment 1575 1576 assert @top_level.method_list.empty? 1577 end 1578 1579 def test_parse_method_gvar_insane 1580 util_parser "def $stdout.foo() class << $other; end; end" 1581 1582 tk = @parser.get_tk 1583 1584 @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment 1585 1586 assert @top_level.method_list.empty? 1587 1588 assert_empty @store.all_classes 1589 1590 assert_equal 1, @store.all_modules.length 1591 1592 refute @store.all_modules.first.document_self 1593 end 1594 1595 def test_parse_method_internal_gvar 1596 klass = RDoc::NormalClass.new 'Foo' 1597 klass.parent = @top_level 1598 1599 util_parser "def foo() def $blah.bar() end end" 1600 1601 tk = @parser.get_tk 1602 1603 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1604 1605 assert_equal 1, klass.method_list.length 1606 end 1607 1608 def test_parse_method_internal_ivar 1609 klass = RDoc::NormalClass.new 'Foo' 1610 klass.parent = @top_level 1611 1612 util_parser "def foo() def @blah.bar() end end" 1613 1614 tk = @parser.get_tk 1615 1616 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1617 1618 assert_equal 1, klass.method_list.length 1619 end 1620 1621 def test_parse_method_internal_lvar 1622 klass = RDoc::NormalClass.new 'Foo' 1623 klass.parent = @top_level 1624 1625 util_parser "def foo() def blah.bar() end end" 1626 1627 tk = @parser.get_tk 1628 1629 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1630 1631 assert_equal 1, klass.method_list.length 1632 end 1633 1634 def test_parse_method_nil 1635 util_parser "def nil.foo() :bar end" 1636 1637 tk = @parser.get_tk 1638 1639 @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment 1640 1641 klass = @store.find_class_named 'NilClass' 1642 1643 foo = klass.method_list.first 1644 assert_equal 'foo', foo.name 1645 end 1646 1647 def test_parse_method_no_parens 1648 klass = RDoc::NormalClass.new 'Foo' 1649 klass.parent = @top_level 1650 1651 util_parser "def foo arg1, arg2 = {}\nend" 1652 1653 tk = @parser.get_tk 1654 1655 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1656 1657 foo = klass.method_list.first 1658 assert_equal '(arg1, arg2 = {})', foo.params 1659 assert_equal @top_level, foo.file 1660 end 1661 1662 def test_parse_method_parameters_comment 1663 klass = RDoc::NormalClass.new 'Foo' 1664 klass.parent = @top_level 1665 1666 util_parser "def foo arg1, arg2 # some useful comment\nend" 1667 1668 tk = @parser.get_tk 1669 1670 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1671 1672 foo = klass.method_list.first 1673 assert_equal '(arg1, arg2)', foo.params 1674 end 1675 1676 def test_parse_method_parameters_comment_continue 1677 klass = RDoc::NormalClass.new 'Foo' 1678 klass.parent = @top_level 1679 1680 util_parser "def foo arg1, arg2, # some useful comment\narg3\nend" 1681 1682 tk = @parser.get_tk 1683 1684 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1685 1686 foo = klass.method_list.first 1687 assert_equal '(arg1, arg2, arg3)', foo.params 1688 end 1689 1690 def test_parse_method_star 1691 klass = RDoc::NormalClass.new 'Foo' 1692 klass.parent = @top_level 1693 1694 util_parser "def self.*\nend" 1695 1696 tk = @parser.get_tk 1697 1698 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1699 1700 ampersand = klass.method_list.first 1701 assert_equal '*', ampersand.name 1702 assert ampersand.singleton 1703 end 1704 1705 def test_parse_method_stopdoc 1706 klass = RDoc::NormalClass.new 'Foo' 1707 klass.parent = @top_level 1708 klass.stop_doc 1709 1710 comment = RDoc::Comment.new "##\n# my method\n", @top_level 1711 1712 util_parser "def foo() :bar end" 1713 1714 tk = @parser.get_tk 1715 1716 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment 1717 1718 assert_empty klass.method_list 1719 end 1720 1721 def test_parse_method_toplevel 1722 klass = @top_level 1723 1724 util_parser "def foo arg1, arg2\nend" 1725 1726 tk = @parser.get_tk 1727 1728 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1729 1730 object = @store.find_class_named 'Object' 1731 1732 foo = object.method_list.first 1733 assert_equal 'Object#foo', foo.full_name 1734 assert_equal @top_level, foo.file 1735 end 1736 1737 def test_parse_method_toplevel_class 1738 klass = @top_level 1739 1740 util_parser "def Object.foo arg1, arg2\nend" 1741 1742 tk = @parser.get_tk 1743 1744 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1745 1746 object = @store.find_class_named 'Object' 1747 1748 foo = object.method_list.first 1749 assert_equal 'Object::foo', foo.full_name 1750 end 1751 1752 def test_parse_method_true 1753 util_parser "def true.foo() :bar end" 1754 1755 tk = @parser.get_tk 1756 1757 @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment 1758 1759 klass = @store.find_class_named 'TrueClass' 1760 1761 foo = klass.method_list.first 1762 assert_equal 'foo', foo.name 1763 end 1764 1765 def test_parse_method_utf8 1766 klass = RDoc::NormalClass.new 'Foo' 1767 klass.parent = @top_level 1768 1769 method = "def ��() end" 1770 1771 assert_equal Encoding::UTF_8, method.encoding if 1772 Object.const_defined? :Encoding 1773 1774 util_parser method 1775 1776 tk = @parser.get_tk 1777 1778 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 1779 1780 omega = klass.method_list.first 1781 assert_equal "def \317\211", omega.text 1782 end 1783 1784 def test_parse_method_dummy 1785 util_parser ".method() end" 1786 1787 @parser.parse_method_dummy @top_level 1788 1789 assert_nil @parser.get_tk 1790 end 1791 1792 def test_parse_method_or_yield_parameters_hash 1793 util_parser "({})\n" 1794 1795 m = RDoc::AnyMethod.new nil, 'm' 1796 1797 result = @parser.parse_method_or_yield_parameters m 1798 1799 assert_equal '({})', result 1800 end 1801 1802 def test_parse_statements_class_if 1803 util_parser <<-CODE 1804module Foo 1805 X = if TRUE then 1806 '' 1807 end 1808 1809 def blah 1810 end 1811end 1812 CODE 1813 1814 @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil 1815 1816 foo = @top_level.modules.first 1817 assert_equal 'Foo', foo.full_name, 'module Foo' 1818 1819 methods = foo.method_list 1820 assert_equal 1, methods.length 1821 assert_equal 'Foo#blah', methods.first.full_name 1822 end 1823 1824 def test_parse_statements_class_nested 1825 comment = RDoc::Comment.new "##\n# my method\n", @top_level 1826 1827 util_parser "module Foo\n#{comment.text}class Bar\nend\nend" 1828 1829 @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL 1830 1831 foo = @top_level.modules.first 1832 assert_equal 'Foo', foo.full_name, 'module Foo' 1833 1834 bar = foo.classes.first 1835 assert_equal 'Foo::Bar', bar.full_name, 'class Foo::Bar' 1836 assert_equal 'my method', bar.comment.text 1837 end 1838 1839 def test_parse_statements_def_percent_string_pound 1840 util_parser "class C\ndef a\n%r{#}\nend\ndef b() end\nend" 1841 1842 @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL 1843 1844 x = @top_level.classes.first 1845 1846 assert_equal 2, x.method_list.length 1847 a = x.method_list.first 1848 1849 expected = [ 1850 tk(:COMMENT, 0, 2, 1, nil, "# File #{@filename}, line 2"), 1851 tk(:NL, 0, 0, 0, nil, "\n"), 1852 tk(:SPACE, 0, 1, 1, nil, ''), 1853 tk(:DEF, 8, 2, 0, 'def', 'def'), 1854 tk(:SPACE, 11, 2, 3, nil, ' '), 1855 tk(:IDENTIFIER, 12, 2, 4, 'a', 'a'), 1856 tk(:NL, 13, 2, 5, nil, "\n"), 1857 tk(:DREGEXP, 14, 3, 0, nil, '%r{#}'), 1858 tk(:NL, 19, 3, 5, nil, "\n"), 1859 tk(:END, 20, 4, 0, 'end', 'end'), 1860 ] 1861 1862 assert_equal expected, a.token_stream 1863 end 1864 1865 def test_parse_statements_encoding 1866 skip "Encoding not implemented" unless Object.const_defined? :Encoding 1867 @options.encoding = Encoding::CP852 1868 1869 content = <<-EOF 1870class Foo 1871 ## 1872 # this is my method 1873 add_my_method :foo 1874end 1875 EOF 1876 1877 util_parser content 1878 1879 @parser.parse_statements @top_level 1880 1881 foo = @top_level.classes.first.method_list.first 1882 assert_equal 'foo', foo.name 1883 assert_equal 'this is my method', foo.comment.text 1884 assert_equal Encoding::CP852, foo.comment.text.encoding 1885 end 1886 1887 def test_parse_statements_identifier_meta_method 1888 content = <<-EOF 1889class Foo 1890 ## 1891 # this is my method 1892 add_my_method :foo 1893end 1894 EOF 1895 1896 util_parser content 1897 1898 @parser.parse_statements @top_level 1899 1900 foo = @top_level.classes.first.method_list.first 1901 assert_equal 'foo', foo.name 1902 end 1903 1904 def test_parse_statements_identifier_alias_method 1905 content = <<-RUBY 1906class Foo 1907 def foo() end 1908 alias_method :foo2, :foo 1909end 1910 RUBY 1911 1912 util_parser content 1913 1914 @parser.parse_statements @top_level 1915 1916 foo = @top_level.classes.first.method_list[0] 1917 assert_equal 'foo', foo.name 1918 1919 foo2 = @top_level.classes.first.method_list.last 1920 assert_equal 'foo2', foo2.name 1921 assert_equal 'foo', foo2.is_alias_for.name 1922 assert @top_level.classes.first.aliases.empty? 1923 end 1924 1925 def test_parse_statements_identifier_alias_method_before_original_method 1926 # This is not strictly legal Ruby code, but it simulates finding an alias 1927 # for a method before finding the original method, which might happen 1928 # to rdoc if the alias is in a different file than the original method 1929 # and rdoc processes the alias' file first. 1930 content = <<-EOF 1931class Foo 1932 alias_method :foo2, :foo 1933 1934 alias_method :foo3, :foo 1935 1936 def foo() 1937 end 1938 1939 alias_method :foo4, :foo 1940 1941 alias_method :foo5, :unknown 1942end 1943EOF 1944 1945 util_parser content 1946 1947 @parser.parse_statements @top_level 1948 1949 foo = @top_level.classes.first.method_list[0] 1950 assert_equal 'foo', foo.name 1951 1952 foo2 = @top_level.classes.first.method_list[1] 1953 assert_equal 'foo2', foo2.name 1954 assert_equal 'foo', foo2.is_alias_for.name 1955 1956 foo3 = @top_level.classes.first.method_list[2] 1957 assert_equal 'foo3', foo3.name 1958 assert_equal 'foo', foo3.is_alias_for.name 1959 1960 foo4 = @top_level.classes.first.method_list.last 1961 assert_equal 'foo4', foo4.name 1962 assert_equal 'foo', foo4.is_alias_for.name 1963 1964 assert_equal 'unknown', @top_level.classes.first.external_aliases[0].old_name 1965 end 1966 1967 def test_parse_statements_identifier_args 1968 comment = "##\n# :args: x\n# :method: b\n# my method\n" 1969 1970 util_parser "module M\n#{comment}def_delegator :a, :b, :b\nend" 1971 1972 @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL 1973 1974 m = @top_level.modules.first 1975 assert_equal 'M', m.full_name 1976 1977 b = m.method_list.first 1978 assert_equal 'M#b', b.full_name 1979 assert_equal 'x', b.params 1980 assert_equal 'my method', b.comment.text 1981 1982 assert_nil m.params, 'Module parameter not removed' 1983 end 1984 1985 def test_parse_statements_identifier_constant 1986 sixth_constant = <<-EOF 1987Class.new do 1988 rule :file do 1989 all(x, y, z) { 1990 def value 1991 find(:require).each {|r| require r.value } 1992 find(:grammar).map {|g| g.value } 1993 end 1994 def min; end 1995 } 1996 end 1997end 1998 EOF 1999 2000 content = <<-EOF 2001class Foo 2002 FIRST_CONSTANT = 5 2003 2004 SECOND_CONSTANT = [ 2005 1, 2006 2, 2007 3 2008 ] 2009 2010 THIRD_CONSTANT = { 2011 :foo => 'bar', 2012 :x => 'y' 2013 } 2014 2015 FOURTH_CONSTANT = SECOND_CONSTANT.map do |element| 2016 element + 1 2017 element + 2 2018 end 2019 2020 FIFTH_CONSTANT = SECOND_CONSTANT.map { |element| element + 1 } 2021 2022 SIXTH_CONSTANT = #{sixth_constant} 2023 2024 SEVENTH_CONSTANT = proc { |i| begin i end } 2025end 2026EOF 2027 2028 util_parser content 2029 2030 @parser.parse_statements @top_level 2031 2032 constants = @top_level.classes.first.constants 2033 2034 constant = constants[0] 2035 assert_equal 'FIRST_CONSTANT', constant.name 2036 assert_equal '5', constant.value 2037 assert_equal @top_level, constant.file 2038 2039 constant = constants[1] 2040 assert_equal 'SECOND_CONSTANT', constant.name 2041 assert_equal "[\n1,\n2,\n3\n]", constant.value 2042 assert_equal @top_level, constant.file 2043 2044 constant = constants[2] 2045 assert_equal 'THIRD_CONSTANT', constant.name 2046 assert_equal "{\n:foo => 'bar',\n:x => 'y'\n}", constant.value 2047 assert_equal @top_level, constant.file 2048 2049 constant = constants[3] 2050 assert_equal 'FOURTH_CONSTANT', constant.name 2051 assert_equal "SECOND_CONSTANT.map do |element|\nelement + 1\nelement + 2\nend", constant.value 2052 assert_equal @top_level, constant.file 2053 2054 constant = constants[4] 2055 assert_equal 'FIFTH_CONSTANT', constant.name 2056 assert_equal 'SECOND_CONSTANT.map { |element| element + 1 }', constant.value 2057 assert_equal @top_level, constant.file 2058 2059 # TODO: parse as class 2060 constant = constants[5] 2061 assert_equal 'SIXTH_CONSTANT', constant.name 2062 assert_equal sixth_constant.lines.map(&:strip).join("\n"), constant.value 2063 assert_equal @top_level, constant.file 2064 2065 # TODO: parse as method 2066 constant = constants[6] 2067 assert_equal 'SEVENTH_CONSTANT', constant.name 2068 assert_equal "proc { |i| begin i end }", constant.value 2069 assert_equal @top_level, constant.file 2070 end 2071 2072 def test_parse_statements_identifier_attr 2073 content = "class Foo\nattr :foo\nend" 2074 2075 util_parser content 2076 2077 @parser.parse_statements @top_level 2078 2079 foo = @top_level.classes.first.attributes.first 2080 assert_equal 'foo', foo.name 2081 assert_equal 'R', foo.rw 2082 end 2083 2084 def test_parse_statements_identifier_attr_accessor 2085 content = "class Foo\nattr_accessor :foo\nend" 2086 2087 util_parser content 2088 2089 @parser.parse_statements @top_level 2090 2091 foo = @top_level.classes.first.attributes.first 2092 assert_equal 'foo', foo.name 2093 assert_equal 'RW', foo.rw 2094 end 2095 2096 def test_parse_statements_identifier_define_method 2097 util_parser <<-RUBY 2098class C 2099 ## 2100 # :method: a 2101 define_method :a do end 2102 ## 2103 # :method: b 2104 define_method :b do end 2105end 2106 RUBY 2107 2108 @parser.parse_statements @top_level 2109 c = @top_level.classes.first 2110 2111 assert_equal %w[a b], c.method_list.map { |m| m.name } 2112 end 2113 2114 def test_parse_statements_identifier_include 2115 content = "class Foo\ninclude Bar\nend" 2116 2117 util_parser content 2118 2119 @parser.parse_statements @top_level 2120 2121 foo = @top_level.classes.first 2122 assert_equal 'Foo', foo.name 2123 assert_equal 1, foo.includes.length 2124 end 2125 2126 def test_parse_statements_identifier_module_function 2127 content = "module Foo\ndef foo() end\nmodule_function :foo\nend" 2128 2129 util_parser content 2130 2131 @parser.parse_statements @top_level 2132 2133 foo, s_foo = @top_level.modules.first.method_list 2134 assert_equal 'foo', foo.name, 'instance method name' 2135 assert_equal :private, foo.visibility, 'instance method visibility' 2136 assert_equal false, foo.singleton, 'instance method singleton' 2137 2138 assert_equal 'foo', s_foo.name, 'module function name' 2139 assert_equal :public, s_foo.visibility, 'module function visibility' 2140 assert_equal true, s_foo.singleton, 'module function singleton' 2141 end 2142 2143 def test_parse_statements_identifier_private 2144 content = "class Foo\nprivate\ndef foo() end\nend" 2145 2146 util_parser content 2147 2148 @parser.parse_statements @top_level 2149 2150 foo = @top_level.classes.first.method_list.first 2151 assert_equal 'foo', foo.name 2152 assert_equal :private, foo.visibility 2153 end 2154 2155 def test_parse_statements_identifier_public_class_method 2156 content = <<-CONTENT 2157class Date 2158 def self.now; end 2159 private_class_method :now 2160end 2161 2162class DateTime < Date 2163 public_class_method :now 2164end 2165 CONTENT 2166 2167 util_parser content 2168 2169 @parser.parse_statements @top_level 2170 2171 date, date_time = @top_level.classes.sort_by { |c| c.full_name } 2172 2173 date_now = date.method_list.first 2174 date_time_now = date_time.method_list.sort_by { |m| m.full_name }.first 2175 2176 assert_equal :private, date_now.visibility 2177 assert_equal :public, date_time_now.visibility 2178 end 2179 2180 def test_parse_statements_identifier_private_class_method 2181 content = <<-CONTENT 2182class Date 2183 def self.now; end 2184 public_class_method :now 2185end 2186 2187class DateTime < Date 2188 private_class_method :now 2189end 2190 CONTENT 2191 2192 util_parser content 2193 2194 @parser.parse_statements @top_level 2195 2196 # TODO sort classes by default 2197 date, date_time = @top_level.classes.sort_by { |c| c.full_name } 2198 2199 date_now = date.method_list.first 2200 date_time_now = date_time.method_list.sort_by { |m| m.full_name }.first 2201 2202 assert_equal :public, date_now.visibility, date_now.full_name 2203 assert_equal :private, date_time_now.visibility, date_time_now.full_name 2204 end 2205 2206 def test_parse_statements_identifier_require 2207 content = "require 'bar'" 2208 2209 util_parser content 2210 2211 @parser.parse_statements @top_level 2212 2213 assert_equal 1, @top_level.requires.length 2214 end 2215 2216 def test_parse_statements_identifier_yields 2217 comment = "##\n# :yields: x\n# :method: b\n# my method\n" 2218 2219 util_parser "module M\n#{comment}def_delegator :a, :b, :b\nend" 2220 2221 @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL 2222 2223 m = @top_level.modules.first 2224 assert_equal 'M', m.full_name 2225 2226 b = m.method_list.first 2227 assert_equal 'M#b', b.full_name 2228 assert_equal 'x', b.block_params 2229 assert_equal 'my method', b.comment.text 2230 2231 assert_nil m.params, 'Module parameter not removed' 2232 end 2233 2234 def test_parse_statements_stopdoc_TkALIAS 2235 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 2236 2237 util_parser "\n# :stopdoc:\nalias old new" 2238 2239 @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil 2240 2241 assert_empty klass.aliases 2242 assert_empty klass.unmatched_alias_lists 2243 end 2244 2245 def test_parse_statements_stopdoc_TkIDENTIFIER_alias_method 2246 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 2247 2248 util_parser "\n# :stopdoc:\nalias_method :old :new" 2249 2250 @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil 2251 2252 assert_empty klass.aliases 2253 assert_empty klass.unmatched_alias_lists 2254 end 2255 2256 def test_parse_statements_stopdoc_TkIDENTIFIER_metaprogrammed 2257 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 2258 2259 util_parser "\n# :stopdoc:\n# attr :meta" 2260 2261 @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil 2262 2263 assert_empty klass.method_list 2264 assert_empty klass.attributes 2265 end 2266 2267 def test_parse_statements_stopdoc_TkCONSTANT 2268 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 2269 2270 util_parser "\n# :stopdoc:\nA = v" 2271 2272 @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil 2273 2274 assert_empty klass.constants 2275 end 2276 2277 def test_parse_statements_stopdoc_TkDEF 2278 klass = @top_level.add_class RDoc::NormalClass, 'Foo' 2279 2280 util_parser "\n# :stopdoc:\ndef m\n end" 2281 2282 @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil 2283 2284 assert_empty klass.method_list 2285 end 2286 2287 def test_parse_statements_super 2288 m = RDoc::AnyMethod.new '', 'm' 2289 util_parser 'super' 2290 2291 @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, m 2292 2293 assert m.calls_super 2294 end 2295 2296 def test_parse_statements_super_no_method 2297 content = "super" 2298 2299 util_parser content 2300 2301 @parser.parse_statements @top_level 2302 2303 assert_nil @parser.get_tk 2304 end 2305 2306 def test_parse_statements_while_begin 2307 util_parser <<-RUBY 2308class A 2309 def a 2310 while begin a; b end 2311 end 2312 end 2313 2314 def b 2315 end 2316end 2317 RUBY 2318 2319 @parser.parse_statements @top_level 2320 2321 c_a = @top_level.classes.first 2322 assert_equal 'A', c_a.full_name 2323 2324 assert_equal 1, @top_level.classes.length 2325 2326 m_a = c_a.method_list.first 2327 m_b = c_a.method_list.last 2328 2329 assert_equal 'A#a', m_a.full_name 2330 assert_equal 'A#b', m_b.full_name 2331 end 2332 2333 def test_parse_symbol_in_arg 2334 util_parser ':blah "blah" "#{blah}" blah' 2335 2336 assert_equal 'blah', @parser.parse_symbol_in_arg 2337 2338 @parser.skip_tkspace 2339 2340 assert_equal 'blah', @parser.parse_symbol_in_arg 2341 2342 @parser.skip_tkspace 2343 2344 assert_equal nil, @parser.parse_symbol_in_arg 2345 2346 @parser.skip_tkspace 2347 2348 assert_equal nil, @parser.parse_symbol_in_arg 2349 end 2350 2351 def test_parse_statements_alias_method 2352 content = <<-CONTENT 2353class A 2354 alias_method :a, :[] unless c 2355end 2356 2357B = A 2358 2359class C 2360end 2361 CONTENT 2362 2363 util_parser content 2364 2365 @parser.parse_statements @top_level 2366 2367 # HACK where are the assertions? 2368 end 2369 2370 def test_parse_top_level_statements_stopdoc 2371 @top_level.stop_doc 2372 content = "# this is the top-level comment" 2373 2374 util_parser content 2375 2376 @parser.parse_top_level_statements @top_level 2377 2378 assert_empty @top_level.comment 2379 end 2380 2381 def test_parse_top_level_statements_stopdoc_integration 2382 content = <<-CONTENT 2383# :stopdoc: 2384 2385class Example 2386 def method_name 2387 end 2388end 2389 CONTENT 2390 2391 util_parser content 2392 2393 @parser.parse_top_level_statements @top_level 2394 2395 assert_equal 1, @top_level.classes.length 2396 assert_empty @top_level.modules 2397 2398 assert @top_level.find_module_named('Example').ignored? 2399 end 2400 2401 # This tests parse_comment 2402 def test_parse_top_level_statements_constant_nodoc_integration 2403 content = <<-CONTENT 2404class A 2405 C = A # :nodoc: 2406end 2407 CONTENT 2408 2409 util_parser content 2410 2411 @parser.parse_top_level_statements @top_level 2412 2413 klass = @top_level.find_module_named('A') 2414 2415 c = klass.constants.first 2416 2417 assert_nil c.document_self, 'C should not be documented' 2418 end 2419 2420 def test_parse_yield_in_braces_with_parens 2421 klass = RDoc::NormalClass.new 'Foo' 2422 klass.parent = @top_level 2423 2424 util_parser "def foo\nn.times { |i| yield nth(i) }\nend" 2425 2426 tk = @parser.get_tk 2427 2428 @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment 2429 2430 foo = klass.method_list.first 2431 assert_equal 'nth(i)', foo.block_params 2432 end 2433 2434 def test_read_directive 2435 parser = util_parser '# :category: test' 2436 2437 directive, value = parser.read_directive %w[category] 2438 2439 assert_equal 'category', directive 2440 assert_equal 'test', value 2441 2442 assert_kind_of RDoc::RubyToken::TkNL, parser.get_tk 2443 end 2444 2445 def test_read_directive_allow 2446 parser = util_parser '# :category: test' 2447 2448 directive = parser.read_directive [] 2449 2450 assert_nil directive 2451 2452 assert_kind_of RDoc::RubyToken::TkNL, parser.get_tk 2453 end 2454 2455 def test_read_directive_empty 2456 parser = util_parser '# test' 2457 2458 directive = parser.read_directive %w[category] 2459 2460 assert_nil directive 2461 2462 assert_kind_of RDoc::RubyToken::TkNL, parser.get_tk 2463 end 2464 2465 def test_read_directive_no_comment 2466 parser = util_parser '' 2467 2468 directive = parser.read_directive %w[category] 2469 2470 assert_nil directive 2471 2472 assert_kind_of RDoc::RubyToken::TkNL, parser.get_tk 2473 end 2474 2475 def test_read_directive_one_liner 2476 parser = util_parser '; end # :category: test' 2477 2478 directive, value = parser.read_directive %w[category] 2479 2480 assert_equal 'category', directive 2481 assert_equal 'test', value 2482 2483 assert_kind_of RDoc::RubyToken::TkSEMICOLON, parser.get_tk 2484 end 2485 2486 def test_read_documentation_modifiers 2487 c = RDoc::Context.new 2488 2489 parser = util_parser '# :category: test' 2490 2491 parser.read_documentation_modifiers c, %w[category] 2492 2493 assert_equal 'test', c.current_section.title 2494 end 2495 2496 def test_read_documentation_modifiers_notnew 2497 m = RDoc::AnyMethod.new nil, 'initialize' 2498 2499 parser = util_parser '# :notnew: test' 2500 2501 parser.read_documentation_modifiers m, %w[notnew] 2502 2503 assert m.dont_rename_initialize 2504 end 2505 2506 def test_read_documentation_modifiers_not_dash_new 2507 m = RDoc::AnyMethod.new nil, 'initialize' 2508 2509 parser = util_parser '# :not-new: test' 2510 2511 parser.read_documentation_modifiers m, %w[not-new] 2512 2513 assert m.dont_rename_initialize 2514 end 2515 2516 def test_read_documentation_modifiers_not_new 2517 m = RDoc::AnyMethod.new nil, 'initialize' 2518 2519 parser = util_parser '# :not_new: test' 2520 2521 parser.read_documentation_modifiers m, %w[not_new] 2522 2523 assert m.dont_rename_initialize 2524 end 2525 2526 def test_sanity_integer 2527 util_parser '1' 2528 assert_equal '1', @parser.get_tk.text 2529 2530 util_parser '1.0' 2531 assert_equal '1.0', @parser.get_tk.text 2532 end 2533 2534 def test_sanity_interpolation 2535 last_tk = nil 2536 util_parser 'class A; B = "#{c}"; end' 2537 2538 while tk = @parser.get_tk do last_tk = tk end 2539 2540 assert_equal "\n", last_tk.text 2541 end 2542 2543 # If you're writing code like this you're doing it wrong 2544 2545 def test_sanity_interpolation_crazy 2546 util_parser '"#{"#{"a")}" if b}"' 2547 2548 assert_equal '"#{"#{"a")}" if b}"', @parser.get_tk.text 2549 assert_equal RDoc::RubyToken::TkNL, @parser.get_tk.class 2550 end 2551 2552 def test_sanity_interpolation_curly 2553 util_parser '%{ #{} }' 2554 2555 assert_equal '%Q{ #{} }', @parser.get_tk.text 2556 assert_equal RDoc::RubyToken::TkNL, @parser.get_tk.class 2557 end 2558 2559 def test_sanity_interpolation_format 2560 util_parser '"#{stftime("%m-%d")}"' 2561 2562 while @parser.get_tk do end 2563 end 2564 2565 def test_sanity_symbol_interpolation 2566 util_parser ':"#{bar}="' 2567 2568 while @parser.get_tk do end 2569 end 2570 2571 def test_scan_cr 2572 content = <<-CONTENT 2573class C\r 2574 def m\r 2575 a=\\\r 2576 123\r 2577 end\r 2578end\r 2579 CONTENT 2580 2581 util_parser content 2582 2583 @parser.scan 2584 2585 c = @top_level.classes.first 2586 2587 assert_equal 1, c.method_list.length 2588 end 2589 2590 def test_scan_block_comment 2591 content = <<-CONTENT 2592=begin rdoc 2593Foo comment 2594=end 2595 2596class Foo 2597 2598=begin 2599m comment 2600=end 2601 2602 def m() end 2603end 2604 CONTENT 2605 2606 util_parser content 2607 2608 @parser.scan 2609 2610 foo = @top_level.classes.first 2611 2612 assert_equal 'Foo comment', foo.comment.text 2613 2614 m = foo.method_list.first 2615 2616 assert_equal 'm comment', m.comment.text 2617 end 2618 2619 def test_scan_block_comment_nested # Issue #41 2620 content = <<-CONTENT 2621require 'something' 2622=begin rdoc 2623findmeindoc 2624=end 2625module Foo 2626 class Bar 2627 end 2628end 2629 CONTENT 2630 2631 util_parser content 2632 2633 @parser.scan 2634 2635 foo = @top_level.modules.first 2636 2637 assert_equal 'Foo', foo.full_name 2638 assert_equal 'findmeindoc', foo.comment.text 2639 2640 bar = foo.classes.first 2641 2642 assert_equal 'Foo::Bar', bar.full_name 2643 assert_equal '', bar.comment.text 2644 end 2645 2646 def test_scan_block_comment_notflush 2647 ## 2648 # 2649 # The previous test assumes that between the =begin/=end blocs that there is 2650 # only one line, or minima formatting directives. This test tests for those 2651 # who use the =begin bloc with longer / more advanced formatting within. 2652 # 2653 ## 2654 content = <<-CONTENT 2655=begin rdoc 2656 2657= DESCRIPTION 2658 2659This is a simple test class 2660 2661= RUMPUS 2662 2663Is a silly word 2664 2665=end 2666class StevenSimpleClass 2667 # A band on my iPhone as I wrote this test 2668 FRUIT_BATS="Make nice music" 2669 2670=begin rdoc 2671A nice girl 2672=end 2673 2674 def lauren 2675 puts "Summoning Lauren!" 2676 end 2677end 2678 CONTENT 2679 util_parser content 2680 2681 @parser.scan 2682 2683 foo = @top_level.classes.first 2684 2685 assert_equal "= DESCRIPTION\n\nThis is a simple test class\n\n= RUMPUS\n\nIs a silly word", 2686 foo.comment.text 2687 2688 m = foo.method_list.first 2689 2690 assert_equal 'A nice girl', m.comment.text 2691 end 2692 2693 def test_scan_constant_in_method 2694 content = <<-CONTENT # newline is after M is important 2695module M 2696 def m 2697 A 2698 B::C 2699 end 2700end 2701 CONTENT 2702 2703 util_parser content 2704 2705 @parser.scan 2706 2707 m = @top_level.modules.first 2708 2709 assert_empty m.constants 2710 2711 assert_empty @store.classes_hash.keys 2712 assert_equal %w[M], @store.modules_hash.keys 2713 end 2714 2715 def test_scan_constant_in_rescue 2716 content = <<-CONTENT # newline is after M is important 2717module M 2718 def m 2719 rescue A::B 2720 rescue A::C => e 2721 rescue A::D, A::E 2722 rescue A::F, 2723 A::G 2724 rescue H 2725 rescue I => e 2726 rescue J, K 2727 rescue L => 2728 e 2729 rescue M; 2730 rescue N, 2731 O => e 2732 end 2733end 2734 CONTENT 2735 2736 util_parser content 2737 2738 @parser.scan 2739 2740 m = @top_level.modules.first 2741 2742 assert_empty m.constants 2743 2744 assert_empty @store.classes_hash.keys 2745 assert_equal %w[M], @store.modules_hash.keys 2746 end 2747 2748 def test_scan_constant_nodoc 2749 content = <<-CONTENT # newline is after M is important 2750module M 2751 2752 C = v # :nodoc: 2753end 2754 CONTENT 2755 2756 util_parser content 2757 2758 @parser.scan 2759 2760 c = @top_level.modules.first.constants.first 2761 2762 assert c.documented? 2763 end 2764 2765 def test_scan_constant_nodoc_block 2766 content = <<-CONTENT # newline is after M is important 2767module M 2768 2769 C = v do # :nodoc: 2770 end 2771end 2772 CONTENT 2773 2774 util_parser content 2775 2776 @parser.scan 2777 2778 c = @top_level.modules.first.constants.first 2779 2780 assert c.documented? 2781 end 2782 2783 def test_scan_meta_method_block 2784 content = <<-CONTENT 2785class C 2786 2787 ## 2788 # my method 2789 2790 inline(:my_method) do |*args| 2791 "this method used to cause z to disappear" 2792 end 2793 2794 def z 2795 end 2796 CONTENT 2797 2798 util_parser content 2799 2800 @parser.scan 2801 2802 assert_equal 2, @top_level.classes.first.method_list.length 2803 end 2804 2805 def test_scan_markup_override 2806 content = <<-CONTENT 2807# *awesome* 2808class C 2809 # :markup: rd 2810 # ((*radical*)) 2811 def m 2812 end 2813end 2814 CONTENT 2815 2816 util_parser content 2817 2818 @parser.scan 2819 2820 c = @top_level.classes.first 2821 2822 assert_equal 'rdoc', c.comment.format 2823 2824 assert_equal 'rd', c.method_list.first.comment.format 2825 end 2826 2827 def test_scan_markup_first_comment 2828 content = <<-CONTENT 2829# :markup: rd 2830 2831# ((*awesome*)) 2832class C 2833 # ((*radical*)) 2834 def m 2835 end 2836end 2837 CONTENT 2838 2839 util_parser content 2840 2841 @parser.scan 2842 2843 c = @top_level.classes.first 2844 2845 assert_equal 'rd', c.comment.format 2846 2847 assert_equal 'rd', c.method_list.first.comment.format 2848 end 2849 2850 def test_scan_tomdoc_meta 2851 util_parser <<-RUBY 2852# :markup: tomdoc 2853 2854class C 2855 2856 # Signature 2857 # 2858 # find_by_<field>[_and_<field>...](args) 2859 # 2860 # field - A field name. 2861 2862end 2863 2864 RUBY 2865 2866 @parser.scan 2867 2868 c = @top_level.classes.first 2869 2870 m = c.method_list.first 2871 2872 assert_equal "find_by_<field>[_and_<field>...]", m.name 2873 assert_equal "find_by_<field>[_and_<field>...](args)\n", m.call_seq 2874 2875 expected = 2876 doc( 2877 head(3, 'Signature'), 2878 list(:NOTE, 2879 item(%w[field], 2880 para('A field name.')))) 2881 expected.file = @top_level 2882 2883 assert_equal expected, m.comment.parse 2884 end 2885 2886 def test_scan_stopdoc 2887 util_parser <<-RUBY 2888class C 2889 # :stopdoc: 2890 class Hidden 2891 end 2892end 2893 RUBY 2894 2895 @parser.scan 2896 2897 c = @top_level.classes.first 2898 2899 hidden = c.classes.first 2900 2901 refute hidden.document_self 2902 assert hidden.ignored? 2903 end 2904 2905 def test_scan_stopdoc_class_alias 2906 util_parser <<-RUBY 2907# :stopdoc: 2908module A 2909 B = C 2910end 2911 RUBY 2912 2913 @parser.scan 2914 2915 assert_empty @store.all_classes 2916 2917 assert_equal 1, @store.all_modules.length 2918 m = @store.all_modules.first 2919 2920 assert m.ignored? 2921 end 2922 2923 def test_scan_stopdoc_nested 2924 util_parser <<-RUBY 2925# :stopdoc: 2926class A::B 2927end 2928 RUBY 2929 2930 @parser.scan 2931 2932 a = @store.modules_hash['A'] 2933 a_b = @store.classes_hash['A::B'] 2934 2935 refute a.document_self, 'A is inside stopdoc' 2936 assert a.ignored?, 'A is inside stopdoc' 2937 2938 refute a_b.document_self, 'A::B is inside stopdoc' 2939 assert a_b.ignored?, 'A::B is inside stopdoc' 2940 end 2941 2942 def test_scan_struct_self_brackets 2943 util_parser <<-RUBY 2944class C < M.m 2945 def self.[] 2946 end 2947end 2948 RUBY 2949 2950 @parser.scan 2951 2952 c = @store.find_class_named 'C' 2953 assert_equal %w[C::[]], c.method_list.map { |m| m.full_name } 2954 end 2955 2956 def test_stopdoc_after_comment 2957 util_parser <<-EOS 2958 module Bar 2959 # hello 2960 module Foo 2961 # :stopdoc: 2962 end 2963 # there 2964 class Baz 2965 # :stopdoc: 2966 end 2967 end 2968 EOS 2969 2970 @parser.parse_statements @top_level 2971 2972 foo = @top_level.modules.first.modules.first 2973 assert_equal 'Foo', foo.name 2974 assert_equal 'hello', foo.comment.text 2975 2976 baz = @top_level.modules.first.classes.first 2977 assert_equal 'Baz', baz.name 2978 assert_equal 'there', baz.comment.text 2979 end 2980 2981 def tk klass, scan, line, char, name, text 2982 klass = RDoc::RubyToken.const_get "Tk#{klass.to_s.upcase}" 2983 2984 token = if klass.instance_method(:initialize).arity == 3 then 2985 raise ArgumentError, "name not used for #{klass}" if name 2986 klass.new scan, line, char 2987 else 2988 klass.new scan, line, char, name 2989 end 2990 2991 token.set_text text 2992 2993 token 2994 end 2995 2996 def util_parser(content) 2997 @parser = RDoc::Parser::Ruby.new @top_level, @filename, content, @options, 2998 @stats 2999 end 3000 3001 def util_two_parsers(first_file_content, second_file_content) 3002 util_parser first_file_content 3003 3004 @parser2 = RDoc::Parser::Ruby.new @top_level2, @filename, 3005 second_file_content, @options, @stats 3006 end 3007 3008end 3009 3010