# frozen_string_literal: true require_relative 'helper' class TestRDocParserRuby < RDoc::TestCase def setup super @tempfile = Tempfile.new self.class.name @filename = @tempfile.path # Some tests need two paths. @tempfile2 = Tempfile.new self.class.name @filename2 = @tempfile2.path @top_level = @store.add_file @filename @top_level2 = @store.add_file @filename2 @options = RDoc::Options.new @options.quiet = true @options.option_parser = OptionParser.new @comment = RDoc::Comment.new '', @top_level @stats = RDoc::Stats.new @store, 0 end def teardown super @tempfile.close! @tempfile2.close! end def test_collect_first_comment p = util_parser <<-CONTENT # first # second class C; end CONTENT comment = p.collect_first_comment assert_equal RDoc::Comment.new("# first\n", @top_level), comment end def test_collect_first_comment_encoding @options.encoding = Encoding::CP852 p = util_parser <<-CONTENT # first # second class C; end CONTENT comment = p.collect_first_comment assert_equal Encoding::CP852, comment.text.encoding end def test_collect_first_comment_rd_hash parser = util_parser <<-CONTENT =begin first =end # second class C; end CONTENT comment = parser.collect_first_comment assert_equal RDoc::Comment.new("first\n", @top_level), comment end def test_get_class_or_module ctxt = RDoc::Context.new ctxt.store = @store cont, name_t, given_name = util_parser('A') .get_class_or_module ctxt assert_equal ctxt, cont assert_equal 'A', name_t[:text] assert_equal 'A', given_name cont, name_t, given_name = util_parser('B::C') .get_class_or_module ctxt b = @store.find_module_named('B') assert_equal b, cont assert_equal [@top_level], b.in_files assert_equal 'C', name_t[:text] assert_equal 'B::C', given_name cont, name_t, given_name = util_parser('D:: E').get_class_or_module ctxt assert_equal @store.find_module_named('D'), cont assert_equal 'E', name_t[:text] assert_equal 'D::E', given_name assert_nothing_raised do util_parser("A::\nB").get_class_or_module ctxt end end def test_get_class_or_module_document_children ctxt = @top_level.add_class RDoc::NormalClass, 'A' ctxt.stop_doc util_parser('B::C').get_class_or_module ctxt b = @store.find_module_named('A::B') assert b.ignored? d = @top_level.add_class RDoc::NormalClass, 'A::D' util_parser('D::E').get_class_or_module ctxt refute d.ignored? end def test_get_class_or_module_ignore_constants ctxt = RDoc::Context.new ctxt.store = @store util_parser('A') .get_class_or_module ctxt, true util_parser('A::B').get_class_or_module ctxt, true assert_empty ctxt.constants assert_empty @store.modules_hash.keys assert_empty @store.classes_hash.keys end def test_get_class_specification assert_equal 'A', util_parser('A') .get_class_specification assert_equal 'A::B', util_parser('A::B').get_class_specification assert_equal '::A', util_parser('::A').get_class_specification assert_equal 'self', util_parser('self').get_class_specification assert_equal '', util_parser('').get_class_specification assert_equal '', util_parser('$g').get_class_specification end def test_get_symbol_or_name util_parser "* & | + 5 / 4" assert_equal '*', @parser.get_symbol_or_name @parser.skip_tkspace assert_equal '&', @parser.get_symbol_or_name @parser.skip_tkspace assert_equal '|', @parser.get_symbol_or_name @parser.skip_tkspace assert_equal '+', @parser.get_symbol_or_name @parser.skip_tkspace @parser.get_tk @parser.skip_tkspace assert_equal '/', @parser.get_symbol_or_name end def test_suppress_parents a = @top_level.add_class RDoc::NormalClass, 'A' b = a.add_class RDoc::NormalClass, 'B' c = b.add_class RDoc::NormalClass, 'C' util_parser '' @parser.suppress_parents c, a assert c.suppressed? assert b.suppressed? refute a.suppressed? end def test_suppress_parents_documented a = @top_level.add_class RDoc::NormalClass, 'A' b = a.add_class RDoc::NormalClass, 'B' b.add_comment RDoc::Comment.new("hello"), @top_level c = b.add_class RDoc::NormalClass, 'C' util_parser '' @parser.suppress_parents c, a assert c.suppressed? refute b.suppressed? refute a.suppressed? end def test_look_for_directives_in_attr util_parser "" comment = RDoc::Comment.new "# :attr: my_attr\n", @top_level @parser.look_for_directives_in @top_level, comment assert_equal "# :attr: my_attr\n", comment.text comment = RDoc::Comment.new "# :attr_reader: my_method\n", @top_level @parser.look_for_directives_in @top_level, comment assert_equal "# :attr_reader: my_method\n", comment.text comment = RDoc::Comment.new "# :attr_writer: my_method\n", @top_level @parser.look_for_directives_in @top_level, comment assert_equal "# :attr_writer: my_method\n", comment.text end def test_look_for_directives_in_commented util_parser "" comment = RDoc::Comment.new <<-COMMENT, @top_level # how to make a section: # # :section: new section COMMENT @parser.look_for_directives_in @top_level, comment section = @top_level.current_section assert_nil section.title assert_nil section.comment assert_equal "# how to make a section:\n# # :section: new section\n", comment.text end def test_look_for_directives_in_method util_parser "" comment = RDoc::Comment.new "# :method: my_method\n", @top_level @parser.look_for_directives_in @top_level, comment assert_equal "# :method: my_method\n", comment.text comment = RDoc::Comment.new "# :singleton-method: my_method\n", @top_level @parser.look_for_directives_in @top_level, comment assert_equal "# :singleton-method: my_method\n", comment.text end def test_look_for_directives_in_section util_parser "" comment = RDoc::Comment.new <<-COMMENT, @top_level # :section: new section # woo stuff COMMENT @parser.look_for_directives_in @top_level, comment section = @top_level.current_section assert_equal 'new section', section.title assert_equal [comment("# woo stuff\n", @top_level)], section.comments assert_empty comment end def test_look_for_directives_in_unhandled util_parser "" comment = RDoc::Comment.new "# :unhandled: blah\n", @top_level @parser.look_for_directives_in @top_level, comment assert_equal 'blah', @top_level.metadata['unhandled'] end def test_parse_for_in klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level comment = RDoc::Comment.new '', @top_level util_parser <def meth variable # comment .chain end EXPECTED expected = expected.rstrip @parser.scan foo = @store.find_class_named 'Foo' meth = foo.method_list.first assert_equal 'meth', meth.name assert_equal @top_level, meth.file markup_code = meth.markup_code.sub(/^.*\n/, '') assert_equal expected, markup_code end def test_parse_redefined_op_with_constant klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level comment = RDoc::Comment.new '', @top_level util_parser < 2, :char_no => 1, :kind => :on_comment, :text => "# File #{@top_level.relative_name}, line 2" }, { :line_no => 0, :char_no => 0, :kind => :on_nl, :text => "\n" }, { :line_no => 1, :char_no => 1, :kind => :on_sp, :text => '' } ] parsed_stream = foo.token_stream.map { |t| { :line_no => t[:line_no], :char_no => t[:char_no], :kind => t[:kind], :text => t[:text] } } assert_equal stream, parsed_stream end def test_parse_comment_method_args klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "\n" tk = @parser.get_tk @parser.parse_comment klass, tk, comment("##\n# :method: foo\n# :args: a, b\n") foo = klass.method_list.first assert_equal 'foo', foo.name assert_equal 'a, b', foo.params end def test_parse_comment_method_stopdoc klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level klass.stop_doc comment = RDoc::Comment.new "##\n# :method: foo\n# my method\n", @top_level util_parser "\n" tk = @parser.get_tk @parser.parse_comment klass, tk, comment assert_empty klass.method_list end def test_parse_constant klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "A = v" tk = @parser.get_tk @parser.parse_constant klass, tk, @comment foo = klass.constants.first assert_equal 'A', foo.name assert_equal @top_level, foo.file assert_equal 1, foo.line end def test_parse_constant_attrasgn klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "A[k] = v" tk = @parser.get_tk @parser.parse_constant klass, tk, @comment assert klass.constants.empty? end def test_parse_constant_alias klass = @top_level.add_class RDoc::NormalClass, 'Foo' klass.add_class RDoc::NormalClass, 'B' util_parser "A = B" tk = @parser.get_tk @parser.parse_constant klass, tk, @comment assert_equal [], klass.modules.map(&:full_name) assert_equal ['Foo::B', 'Foo::A'], klass.classes.map(&:full_name) assert_equal ['Foo::A'], klass.constants.map(&:full_name) assert_equal 'Foo::A', klass.find_module_named('A').full_name end def test_parse_constant_alias_same_name foo = @top_level.add_class RDoc::NormalClass, 'Foo' @top_level.add_class RDoc::NormalClass, 'Bar' bar = foo.add_class RDoc::NormalClass, 'Bar' assert @store.find_class_or_module('::Bar') util_parser "A = ::Bar" tk = @parser.get_tk @parser.parse_constant foo, tk, @comment assert_equal 'A', bar.find_module_named('A').full_name end def test_parse_constant_in_method klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser 'A::B = v' tk = @parser.get_tk @parser.parse_constant klass, tk, @comment, true assert_empty klass.constants assert_empty @store.modules_hash.keys assert_equal %w[Foo], @store.classes_hash.keys end def test_parse_constant_rescue klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "A => e" tk = @parser.get_tk @parser.parse_constant klass, tk, @comment assert_empty klass.constants assert_empty klass.modules assert_empty @store.modules_hash.keys assert_equal %w[Foo], @store.classes_hash.keys end def test_parse_constant_stopdoc klass = @top_level.add_class RDoc::NormalClass, 'Foo' klass.stop_doc util_parser "A = v" tk = @parser.get_tk @parser.parse_constant klass, tk, @comment assert_empty klass.constants end def test_parse_comment_nested content = <<-CONTENT A::B::C = 1 CONTENT util_parser content tk = @parser.get_tk parsed = @parser.parse_constant @top_level, tk, 'comment' assert parsed a = @top_level.find_module_named 'A' b = a.find_module_named 'B' c = b.constants.first assert_equal 'A::B::C', c.full_name assert_equal 'comment', c.comment end def test_parse_class_the_same_of_outside util_parser <<-RUBY module A class A::B end end RUBY @parser.scan assert_includes @store.modules_hash, 'A' module_a = @store.find_module_named 'A' refute_empty module_a.classes_hash assert_includes module_a.classes_hash, 'B' refute_includes module_a.classes_hash, 'A' end def test_parse_constant_the_same_of_outside util_parser <<-RUBY module A class B class C end end def self.foo A::B::C end end RUBY expected = <def self.foo A::B::C end EXPECTED expected = expected.rstrip @parser.scan module_a = @store.find_module_named 'A' foo = module_a.method_list.first markup_code = foo.markup_code.sub(/^.*\n/, '') assert_equal expected, markup_code end def test_parse_constant_with_bracket util_parser <<-RUBY class Klass end class Klass2 CONSTANT = Klass end class Klass3 CONSTANT_2 = {} CONSTANT_2[1] = Klass end RUBY @parser.scan klass = @store.find_class_named 'Klass' klass2 = @store.find_class_named 'Klass2' klass3 = @store.find_class_named 'Klass3' assert_equal klass, klass2.constants.first.is_alias_for refute_equal klass, klass3.constants.first.is_alias_for assert_nil klass3.find_module_named 'CONSTANT_2' end def test_parse_extend_or_include_extend klass = RDoc::NormalClass.new 'C' klass.parent = @top_level comment = RDoc::Comment.new "# my extend\n", @top_level, :ruby util_parser "extend I" @parser.get_tk # extend @parser.parse_extend_or_include RDoc::Extend, klass, comment assert_equal 1, klass.extends.length ext = klass.extends.first assert_equal 'I', ext.name assert_equal 'my extend', ext.comment.text assert_equal @top_level, ext.file end def test_parse_extend_or_include_include klass = RDoc::NormalClass.new 'C' klass.parent = @top_level comment = RDoc::Comment.new "# my include\n", @top_level, :ruby util_parser "include I" @parser.get_tk # include @parser.parse_extend_or_include RDoc::Include, klass, comment assert_equal 1, klass.includes.length incl = klass.includes.first assert_equal 'I', incl.name assert_equal 'my include', incl.comment.text assert_equal @top_level, incl.file end def test_parse_meta_method klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level comment = RDoc::Comment.new "##\n# my method\n", @top_level, :ruby util_parser "add_my_method :foo, :bar\nadd_my_method :baz" tk = @parser.get_tk @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment foo = klass.method_list.first assert_equal 'foo', foo.name assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file assert_equal 1, foo.line assert_equal [], foo.aliases assert_nil foo.block_params assert_nil foo.call_seq assert_equal true, foo.document_children assert_equal true, foo.document_self assert_equal false, foo.done_documenting assert_equal false, foo.dont_rename_initialize assert_equal false, foo.force_documentation assert_nil foo.is_alias_for assert_equal '', foo.params assert_equal klass, foo.parent assert_equal false, foo.singleton assert_equal 'add_my_method :foo', foo.text assert_nil foo.viewer assert_equal :public, foo.visibility assert_equal klass.current_section, foo.section stream = [ { :line_no => 1, :char_no => 1, :kind => :on_comment, :text => "# File #{@top_level.relative_name}, line 1" }, { :line_no => 0, :char_no => 0, :kind => :on_nl, :text => "\n" }, { :line_no => 1, :char_no => 1, :kind => :on_sp, :text => '' }, { :line_no => 1, :char_no => 0, :kind => :on_ident, :text => 'add_my_method' }, { :line_no => 1, :char_no => 13, :kind => :on_sp, :text => ' ' }, { :line_no => 1, :char_no => 14, :kind => :on_symbol, :text => ':foo' }, { :line_no => 1, :char_no => 18, :kind => :on_comma, :text => ',' }, { :line_no => 1, :char_no => 19, :kind => :on_sp, :text => ' ' }, { :line_no => 1, :char_no => 20, :kind => :on_symbol, :text => ':bar' }, { :line_no => 1, :char_no => 24, :kind => :on_nl, :text => "\n" } ] parsed_stream = foo.token_stream.map { |t| { :line_no => t[:line_no], :char_no => t[:char_no], :kind => t[:kind], :text => t[:text] } } assert_equal stream, parsed_stream end def test_parse_meta_method_block klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level comment = RDoc::Comment.new "##\n# my method\n", @top_level content = <<-CONTENT inline(:my_method) do |*args| "this method causes z to disappear" end CONTENT util_parser content tk = @parser.get_tk @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment rest = { :line_no => 3, :char_no => 3, :kind => :on_nl, :text => "\n" } tk = @parser.get_tk tk = { :line_no => tk[:line_no], :char_no => tk[:char_no], :kind => tk[:kind], :text => tk[:text] } assert_equal rest, tk end def test_parse_meta_method_define_method klass = RDoc::NormalClass.new 'Foo' comment = RDoc::Comment.new "##\n# my method\n", @top_level, :ruby util_parser "define_method :foo do end" tk = @parser.get_tk @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment foo = klass.method_list.first assert_equal 'foo', foo.name assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end def test_parse_meta_method_name klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level comment = RDoc::Comment.new "##\n# :method: woo_hoo!\n# my method\n", @top_level, :ruby util_parser "add_my_method :foo, :bar\nadd_my_method :baz" tk = @parser.get_tk @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment foo = klass.method_list.first assert_equal 'woo_hoo!', foo.name assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end def test_parse_meta_method_singleton klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level comment = RDoc::Comment.new "##\n# :singleton-method:\n# my method\n", @top_level, :ruby util_parser "add_my_method :foo, :bar\nadd_my_method :baz" tk = @parser.get_tk @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment foo = klass.method_list.first assert_equal 'foo', foo.name assert_equal true, foo.singleton, 'singleton method' assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end def test_parse_meta_method_singleton_name klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level comment = RDoc::Comment.new "##\n# :singleton-method: woo_hoo!\n# my method\n", @top_level, :ruby util_parser "add_my_method :foo, :bar\nadd_my_method :baz" tk = @parser.get_tk @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment foo = klass.method_list.first assert_equal 'woo_hoo!', foo.name assert_equal true, foo.singleton, 'singleton method' assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end def test_parse_meta_method_string_name klass = RDoc::NormalClass.new 'Foo' comment = RDoc::Comment.new "##\n# my method\n", @top_level, :ruby util_parser "add_my_method 'foo'" tk = @parser.get_tk @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment foo = klass.method_list.first assert_equal 'foo', foo.name assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end def test_parse_meta_method_stopdoc klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level klass.stop_doc comment = RDoc::Comment.new "##\n# my method\n", @top_level util_parser "add_my_method :foo, :bar\nadd_my_method :baz" tk = @parser.get_tk @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment assert_empty klass.method_list end def test_parse_meta_method_unknown klass = RDoc::NormalClass.new 'Foo' comment = RDoc::Comment.new "##\n# my method\n", @top_level, :ruby util_parser "add_my_method ('foo')" tk = @parser.get_tk @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment foo = klass.method_list.first assert_equal 'unknown', foo.name assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end def test_parse_method klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level comment = RDoc::Comment.new "##\n# my method\n", @top_level, :ruby util_parser "def foo() :bar end" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment foo = klass.method_list.first assert_equal 'foo', foo.name assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file assert_equal 1, foo.line assert_equal [], foo.aliases assert_nil foo.block_params assert_nil foo.call_seq assert_nil foo.is_alias_for assert_nil foo.viewer assert_equal true, foo.document_children assert_equal true, foo.document_self assert_equal '()', foo.params assert_equal false, foo.done_documenting assert_equal false, foo.dont_rename_initialize assert_equal false, foo.force_documentation assert_equal klass, foo.parent assert_equal false, foo.singleton assert_equal :public, foo.visibility assert_equal 'def foo', foo.text assert_equal klass.current_section, foo.section stream = [ { :line_no => 1, :char_no => 1, :kind => :on_comment, :text => "# File #{@top_level.relative_name}, line 1" }, { :line_no => 0, :char_no => 0, :kind => :on_nl, :text => "\n" }, { :line_no => 1, :char_no => 1, :kind => :on_sp, :text => '' }, { :line_no => 1, :char_no => 0, :kind => :on_kw, :text => 'def' }, { :line_no => 1, :char_no => 3, :kind => :on_sp, :text => ' ' }, { :line_no => 1, :char_no => 4, :kind => :on_ident, :text => 'foo' }, { :line_no => 1, :char_no => 7, :kind => :on_lparen, :text => '(' }, { :line_no => 1, :char_no => 8, :kind => :on_rparen, :text => ')' }, { :line_no => 1, :char_no => 9, :kind => :on_sp, :text => ' ' }, { :line_no => 1, :char_no => 10, :kind => :on_symbol, :text => ':bar' }, { :line_no => 1, :char_no => 14, :kind => :on_sp, :text => ' ' }, { :line_no => 1, :char_no => 15, :kind => :on_kw, :text => 'end' } ] parsed_stream = foo.token_stream.map { |t| { :line_no => t[:line_no], :char_no => t[:char_no], :kind => t[:kind], :text => t[:text] } } assert_equal stream, parsed_stream end def test_parse_redefinable_methods klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level comment = RDoc::Comment.new "", @top_level redefinable_ops = %w[| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ +@ -@ [] []= ` ! != !~] redefinable_ops.each do |redefinable_op| util_parser "def #{redefinable_op}\nend\n" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment end klass.method_list.each do |method| assert_equal :on_ident, method.token_stream[5][:kind] assert_includes redefinable_ops, method.token_stream[5][:text] end end def test_parse_method_with_args_directive util_parser <<-RUBY class C def meth_with_args_after # :args: a, b, c end ## # :args: d, e, f def meth_with_args_before end RUBY @parser.scan c = @store.find_class_named 'C' assert_equal 'C#meth_with_args_after', c.method_list[0].full_name assert_equal 'a, b, c', c.method_list[0].params assert_equal 'C#meth_with_args_before', c.method_list[1].full_name assert_equal 'd, e, f', c.method_list[1].params end def test_parse_method_bracket util_parser <<-RUBY class C def [] end def self.[] end def []= end def self.[]= end end RUBY @parser.scan c = @store.find_class_named 'C' assert_equal 4, c.method_list.size assert_equal 'C#[]', c.method_list[0].full_name assert_equal 'C::[]', c.method_list[1].full_name assert_equal 'C#[]=', c.method_list[2].full_name assert_equal 'C::[]=', c.method_list[3].full_name assert c.aliases.empty? end def test_parse_method_alias klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def m() alias a b; end" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment assert klass.aliases.empty? end def test_parse_method_ampersand klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def self.&\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment ampersand = klass.method_list.first assert_equal '&', ampersand.name assert ampersand.singleton end def test_parse_method_constant c = RDoc::Constant.new 'CONST', nil, '' m = @top_level.add_class RDoc::NormalModule, 'M' m.add_constant c util_parser "def CONST.m() end" tk = @parser.get_tk @parser.parse_method m, RDoc::Parser::Ruby::NORMAL, tk, @comment assert_empty @store.modules_hash.keys assert_equal %w[M], @store.classes_hash.keys end def test_parse_method_false util_parser "def false.foo() :bar end" tk = @parser.get_tk @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment klass = @store.find_class_named 'FalseClass' foo = klass.method_list.first assert_equal 'foo', foo.name end def test_parse_method_funky klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def (blah).foo() :bar end" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment assert_empty klass.method_list end def test_parse_method_gvar util_parser "def $stdout.foo() :bar end" tk = @parser.get_tk @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment assert @top_level.method_list.empty? end def test_parse_method_gvar_insane util_parser "def $stdout.foo() class << $other; end; end" tk = @parser.get_tk @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment assert @top_level.method_list.empty? assert_empty @store.all_classes assert_equal 1, @store.all_modules.length refute @store.all_modules.first.document_self end def test_parse_method_internal_gvar klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def foo() def $blah.bar() end end" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment assert_equal 1, klass.method_list.length end def test_parse_method_internal_ivar klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def foo() def @blah.bar() end end" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment assert_equal 1, klass.method_list.length end def test_parse_method_internal_lvar klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def foo() def blah.bar() end end" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment assert_equal 1, klass.method_list.length end def test_parse_method_nil util_parser "def nil.foo() :bar end" tk = @parser.get_tk @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment klass = @store.find_class_named 'NilClass' foo = klass.method_list.first assert_equal 'foo', foo.name end def test_parse_method_nodoc klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def foo # :nodoc:\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment('') assert_empty klass.method_list end def test_parse_method_nodoc_track klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level @options.visibility = :nodoc util_parser "def foo # :nodoc:\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment('') refute_empty klass.method_list end def test_parse_method_no_parens klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def foo arg1, arg2 = {}\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = klass.method_list.first assert_equal '(arg1, arg2 = {})', foo.params assert_equal @top_level, foo.file end def test_parse_method_parameters_comment klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def foo arg1, arg2 # some useful comment\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = klass.method_list.first assert_equal '(arg1, arg2)', foo.params end def test_parse_method_parameters_comment_continue klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def foo arg1, arg2, # some useful comment\narg3\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = klass.method_list.first assert_equal '(arg1, arg2, arg3)', foo.params end def test_parse_method_parameters_with_paren_comment_continue klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def foo(arg1, arg2, # some useful comment\narg3)\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = klass.method_list.first assert_equal '(arg1, arg2, arg3)', foo.params end def test_parse_method_star klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level util_parser "def self.*\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment ampersand = klass.method_list.first assert_equal '*', ampersand.name assert ampersand.singleton end def test_parse_method_stopdoc klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level klass.stop_doc comment = RDoc::Comment.new "##\n# my method\n", @top_level util_parser "def foo() :bar end" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment assert_empty klass.method_list end def test_parse_method_toplevel klass = @top_level util_parser "def foo arg1, arg2\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment object = @store.find_class_named 'Object' foo = object.method_list.first assert_equal 'Object#foo', foo.full_name assert_equal @top_level, foo.file end def test_parse_method_toplevel_class klass = @top_level util_parser "def Object.foo arg1, arg2\nend" tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment object = @store.find_class_named 'Object' foo = object.method_list.first assert_equal 'Object::foo', foo.full_name end def test_parse_method_true util_parser "def true.foo() :bar end" tk = @parser.get_tk @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment klass = @store.find_class_named 'TrueClass' foo = klass.method_list.first assert_equal 'foo', foo.name end def test_parse_method_utf8 klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level method = "def ω() end" assert_equal Encoding::UTF_8, method.encoding util_parser method tk = @parser.get_tk @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment omega = klass.method_list.first assert_equal "def \317\211", omega.text end def test_parse_method_dummy util_parser ".method() end" @parser.parse_method_dummy @top_level assert_nil @parser.get_tk end def test_parse_method_or_yield_parameters_hash util_parser "({})\n" m = RDoc::AnyMethod.new nil, 'm' result = @parser.parse_method_or_yield_parameters m assert_equal '({})', result end def test_parse_statements_class_if util_parser <<-CODE module Foo X = if TRUE then '' end def blah end end CODE @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil foo = @top_level.modules.first assert_equal 'Foo', foo.full_name, 'module Foo' methods = foo.method_list assert_equal 1, methods.length assert_equal 'Foo#blah', methods.first.full_name end def test_parse_statements_postfix_if_unless util_parser <<-CODE class C def foo 1 if nil end def bar 2 unless nil end end CODE @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil c = @top_level.classes.first assert_equal 'C', c.full_name, 'class C' methods = c.method_list assert_equal 2, methods.length assert_equal 'C#foo', methods[0].full_name assert_equal 'C#bar', methods[1].full_name end def test_parse_statements_postfix_if_unless_with_expr_mid util_parser <<-CODE class A class B def foo return if nil end end class C end end CODE @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil a = @top_level.classes.first assert_equal 'A', a.full_name, 'class A' assert_equal 2, a.classes.length b = a.classes[0] assert_equal 'A::B', b.full_name, 'class A::B' c = a.classes[1] assert_equal 'A::C', c.full_name, 'class A::C' end def test_parse_statements_class_nested comment = RDoc::Comment.new "##\n# my method\n", @top_level util_parser "module Foo\n#{comment.text}class Bar\nend\nend" @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL foo = @top_level.modules.first assert_equal 'Foo', foo.full_name, 'module Foo' bar = foo.classes.first assert_equal 'Foo::Bar', bar.full_name, 'class Foo::Bar' assert_equal 'my method', bar.comment.text end def test_parse_statements_def_percent_string_pound util_parser "class C\ndef a\n%r{#}\n%r{\#{}}\nend\ndef b() end\nend" @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL x = @top_level.classes.first assert_equal 2, x.method_list.length a = x.method_list.first expected = [ { :line_no => 2, :char_no => 1, :kind => :on_comment, :text => "# File #{@filename}, line 2" }, { :line_no => 0, :char_no => 0, :kind => :on_nl, :text => "\n" }, { :line_no => 1, :char_no => 1, :kind => :on_sp, :text => '' }, { :line_no => 2, :char_no => 0, :kind => :on_kw, :text => 'def' }, { :line_no => 2, :char_no => 3, :kind => :on_sp, :text => ' ' }, { :line_no => 2, :char_no => 4, :kind => :on_ident, :text => 'a' }, { :line_no => 2, :char_no => 5, :kind => :on_nl, :text => "\n" }, { :line_no => 3, :char_no => 0, :kind => :on_regexp, :text => '%r{#}' }, { :line_no => 3, :char_no => 5, :kind => :on_nl, :text => "\n" }, { :line_no => 4, :char_no => 0, :kind => :on_regexp, :text => '%r{#{}}' }, { :line_no => 4, :char_no => 7, :kind => :on_nl, :text => "\n" }, { :line_no => 5, :char_no => 0, :kind => :on_kw, :text => 'end' } ] parsed_stream = a.token_stream.map { |tk| { :line_no => tk[:line_no], :char_no => tk[:char_no], :kind => tk[:kind], :text => tk[:text] } } assert_equal expected, parsed_stream end def test_parse_statements_encoding @options.encoding = Encoding::CP852 content = <<-EOF class Foo ## # this is my method add_my_method :foo end EOF util_parser content @parser.parse_statements @top_level foo = @top_level.classes.first.method_list.first assert_equal 'foo', foo.name assert_equal 'this is my method', foo.comment.text assert_equal Encoding::CP852, foo.comment.text.encoding end def test_parse_statements_enddoc klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :enddoc:" @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil assert klass.done_documenting end def test_parse_statements_enddoc_top_level util_parser "\n# :enddoc:" assert_throws :eof do @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil end end def test_parse_statements_identifier_meta_method content = <<-EOF class Foo ## # this is my method add_my_method :foo end EOF util_parser content @parser.parse_statements @top_level foo = @top_level.classes.first.method_list.first assert_equal 'foo', foo.name end def test_parse_statements_identifier_alias_method content = <<-RUBY class Foo def foo() end alias_method :foo2, :foo end RUBY util_parser content @parser.parse_statements @top_level foo = @top_level.classes.first.method_list[0] assert_equal 'foo', foo.name foo2 = @top_level.classes.first.method_list.last assert_equal 'foo2', foo2.name assert_equal 'foo', foo2.is_alias_for.name assert @top_level.classes.first.aliases.empty? end def test_parse_statements_identifier_alias_method_before_original_method # This is not strictly legal Ruby code, but it simulates finding an alias # for a method before finding the original method, which might happen # to rdoc if the alias is in a different file than the original method # and rdoc processes the alias' file first. content = <<-EOF class Foo alias_method :foo2, :foo alias_method :foo3, :foo def foo() end alias_method :foo4, :foo alias_method :foo5, :unknown end EOF util_parser content @parser.parse_statements @top_level foo = @top_level.classes.first.method_list[0] assert_equal 'foo', foo.name foo2 = @top_level.classes.first.method_list[1] assert_equal 'foo2', foo2.name assert_equal 'foo', foo2.is_alias_for.name foo3 = @top_level.classes.first.method_list[2] assert_equal 'foo3', foo3.name assert_equal 'foo', foo3.is_alias_for.name foo4 = @top_level.classes.first.method_list.last assert_equal 'foo4', foo4.name assert_equal 'foo', foo4.is_alias_for.name assert_equal 'unknown', @top_level.classes.first.external_aliases[0].old_name end def test_parse_statements_identifier_args comment = "##\n# :args: x\n# :method: b\n# my method\n" util_parser "module M\n#{comment}def_delegator :a, :b, :b\nend" @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL m = @top_level.modules.first assert_equal 'M', m.full_name b = m.method_list.first assert_equal 'M#b', b.full_name assert_equal 'x', b.params assert_equal 'my method', b.comment.text assert_nil m.params, 'Module parameter not removed' end def test_parse_statements_identifier_constant sixth_constant = <<-EOF Class.new do rule :file do all(x, y, z) { def value find(:require).each {|r| require r.value } find(:grammar).map {|g| g.value } end def min; end } end end EOF content = <<-EOF class Foo FIRST_CONSTANT = 5 SECOND_CONSTANT = [ 1, 2, 3 ] THIRD_CONSTANT = { :foo => 'bar', :x => 'y' } FOURTH_CONSTANT = SECOND_CONSTANT.map do |element| element + 1 element + 2 end FIFTH_CONSTANT = SECOND_CONSTANT.map { |element| element + 1 } SIXTH_CONSTANT = #{sixth_constant} SEVENTH_CONSTANT = proc { |i| begin i end } EIGHTH_CONSTANT = "a" \\ "b" end EOF util_parser content @parser.parse_statements @top_level constants = @top_level.classes.first.constants constant = constants[0] assert_equal 'FIRST_CONSTANT', constant.name assert_equal '5', constant.value assert_equal @top_level, constant.file constant = constants[1] assert_equal 'SECOND_CONSTANT', constant.name assert_equal "[\n1,\n2,\n3\n]", constant.value assert_equal @top_level, constant.file constant = constants[2] assert_equal 'THIRD_CONSTANT', constant.name assert_equal "{\n:foo => 'bar',\n:x => 'y'\n}", constant.value assert_equal @top_level, constant.file constant = constants[3] assert_equal 'FOURTH_CONSTANT', constant.name assert_equal "SECOND_CONSTANT.map do |element|\nelement + 1\nelement + 2\nend", constant.value assert_equal @top_level, constant.file constant = constants[4] assert_equal 'FIFTH_CONSTANT', constant.name assert_equal 'SECOND_CONSTANT.map { |element| element + 1 }', constant.value assert_equal @top_level, constant.file # TODO: parse as class constant = constants[5] assert_equal 'SIXTH_CONSTANT', constant.name assert_equal sixth_constant.lines.map(&:strip).join("\n"), constant.value assert_equal @top_level, constant.file # TODO: parse as method constant = constants[6] assert_equal 'SEVENTH_CONSTANT', constant.name assert_equal "proc { |i| begin i end }", constant.value assert_equal @top_level, constant.file constant = constants[7] assert_equal 'EIGHTH_CONSTANT', constant.name assert_equal "\"a\" \\\n\"b\"", constant.value assert_equal @top_level, constant.file end def test_parse_statements_identifier_attr content = "class Foo\nattr :foo\nend" util_parser content @parser.parse_statements @top_level foo = @top_level.classes.first.attributes.first assert_equal 'foo', foo.name assert_equal 'R', foo.rw end def test_parse_statements_identifier_attr_accessor content = "class Foo\nattr_accessor :foo\nend" util_parser content @parser.parse_statements @top_level foo = @top_level.classes.first.attributes.first assert_equal 'foo', foo.name assert_equal 'RW', foo.rw end def test_parse_statements_identifier_define_method util_parser <<-RUBY class C ## # :method: a define_method :a do end ## # :method: b define_method :b do end end RUBY @parser.parse_statements @top_level c = @top_level.classes.first assert_equal %w[a b], c.method_list.map { |m| m.name } end def test_parse_statements_identifier_include content = "class Foo\ninclude Bar\nend" util_parser content @parser.parse_statements @top_level foo = @top_level.classes.first assert_equal 'Foo', foo.name assert_equal 1, foo.includes.length end def test_parse_statements_identifier_module_function content = "module Foo\ndef foo() end\nmodule_function :foo\nend" util_parser content @parser.parse_statements @top_level foo, s_foo = @top_level.modules.first.method_list assert_equal 'foo', foo.name, 'instance method name' assert_equal :private, foo.visibility, 'instance method visibility' assert_equal false, foo.singleton, 'instance method singleton' assert_equal 'foo', s_foo.name, 'module function name' assert_equal :public, s_foo.visibility, 'module function visibility' assert_equal true, s_foo.singleton, 'module function singleton' end def test_parse_statements_identifier_private content = "class Foo\nprivate\ndef foo() end\nend" util_parser content @parser.parse_statements @top_level foo = @top_level.classes.first.method_list.first assert_equal 'foo', foo.name assert_equal :private, foo.visibility end def test_parse_statements_identifier_public_class_method content = <<-CONTENT class Date def self.now; end private_class_method :now end class DateTime < Date public_class_method :now end CONTENT util_parser content @parser.parse_statements @top_level date, date_time = @top_level.classes.sort_by { |c| c.full_name } date_now = date.method_list.first date_time_now = date_time.method_list.sort_by { |m| m.full_name }.first assert_equal :private, date_now.visibility assert_equal :public, date_time_now.visibility end def test_parse_statements_identifier_private_class_method content = <<-CONTENT class Date def self.now; end public_class_method :now end class DateTime < Date private_class_method :now end CONTENT util_parser content @parser.parse_statements @top_level # TODO sort classes by default date, date_time = @top_level.classes.sort_by { |c| c.full_name } date_now = date.method_list.first date_time_now = date_time.method_list.sort_by { |m| m.full_name }.first assert_equal :public, date_now.visibility, date_now.full_name assert_equal :private, date_time_now.visibility, date_time_now.full_name end def test_parse_statements_complex_condition_in_for util_parser <def blah() for i in (k)...n do end for i in (k)...n end end EXPECTED expected = expected.rstrip @parser.scan foo = @top_level.classes.first assert_equal 'Foo', foo.full_name blah = foo.method_list.first markup_code = blah.markup_code.sub(/^.*\n/, '') assert_equal expected, markup_code end def test_parse_instance_operation_method util_parser <<-RUBY class Foo def self.& end end RUBY expected = <def self.& end end EXPECTED expected = expected.rstrip @parser.scan foo = @top_level.classes.first assert_equal 'Foo', foo.full_name blah = foo.method_list.first markup_code = blah.markup_code.sub(/^.*\n/, '') assert_equal expected, markup_code end def test_parse_statements_postfix_if_after_heredocbeg @filename = 'file.rb' util_parser <def blah() <<-EOM if true EOM end EXPECTED expected = expected.rstrip @parser.scan foo = @top_level.classes.first assert_equal 'Foo', foo.full_name blah = foo.method_list.first markup_code = blah.markup_code.sub(/^.*\n/, '') assert_equal expected, markup_code end def test_parse_mutable_heredocbeg @filename = 'file.rb' util_parser <def blah() @str = -<<-EOM EOM end EXPECTED expected = expected.rstrip @parser.scan foo = @top_level.classes.first assert_equal 'Foo', foo.full_name blah = foo.method_list.first markup_code = blah.markup_code.sub(/^.*\n/, '') assert_equal expected, markup_code end def test_parse_heredoc_end code = "A = <def blah() /bar/ end EXPECTED expected = expected.rstrip @parser.scan foo = @top_level.classes.first assert_equal 'Foo', foo.full_name blah = foo.method_list.first markup_code = blah.markup_code.sub(/^.*\n/, '') assert_equal expected, markup_code end def test_parse_statements_embdoc_in_document @filename = 'file.rb' util_parser <doc
=begin
test embdoc
=end
EXPECTED @parser.scan foo = @top_level.classes.first assert_equal 'Foo', foo.full_name blah = foo.method_list.first markup_comment = blah.search_record[6] assert_equal expected, markup_comment end def test_parse_require_dynamic_string content = <<-RUBY prefix = 'path' require "\#{prefix}/a_library" require 'test' RUBY util_parser content @parser.parse_statements @top_level assert_equal 1, @top_level.requires.length end def test_parse_postfix_nodoc util_parser <<-RUBY class A end # :nodoc: class B def a end # :nodoc: def b end end RUBY @parser.parse_statements @top_level c_a = @top_level.classes.select(&:document_self).first assert_equal 'B', c_a.full_name assert_equal 2, @top_level.classes.length assert_equal 1, @top_level.classes.count(&:document_self) assert_equal 1, c_a.method_list.length assert_equal 'B#b', c_a.method_list.first.full_name end def test_parse_statements_identifier_require content = "require 'bar'" util_parser content @parser.parse_statements @top_level assert_equal 1, @top_level.requires.length end def test_parse_statements_identifier_yields comment = "##\n# :yields: x\n# :method: b\n# my method\n" util_parser "module M\n#{comment}def_delegator :a, :b, :b\nend" @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL m = @top_level.modules.first assert_equal 'M', m.full_name b = m.method_list.first assert_equal 'M#b', b.full_name assert_equal 'x', b.block_params assert_equal 'my method', b.comment.text assert_nil m.params, 'Module parameter not removed' end def test_parse_statements_stopdoc_alias klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\nalias old new" @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil assert_empty klass.aliases assert_empty klass.unmatched_alias_lists end def test_parse_statements_stopdoc_identifier_alias_method klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\nalias_method :old :new" @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil assert_empty klass.aliases assert_empty klass.unmatched_alias_lists end def test_parse_statements_stopdoc_identifier_metaprogrammed klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\n# attr :meta" @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil assert_empty klass.method_list assert_empty klass.attributes end def test_parse_statements_stopdoc_constant klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\nA = v" @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil assert_empty klass.constants end def test_parse_statements_stopdoc_def klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\ndef m\n end" @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil assert_empty klass.method_list end def test_parse_statements_super m = RDoc::AnyMethod.new '', 'm' util_parser 'super' @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, m assert m.calls_super end def test_parse_statements_super_no_method content = "super" util_parser content @parser.parse_statements @top_level assert_nil @parser.get_tk end def test_parse_statements_while_begin util_parser <<-RUBY class A def a while begin a; b end end end def b end end RUBY @parser.parse_statements @top_level c_a = @top_level.classes.first assert_equal 'A', c_a.full_name assert_equal 1, @top_level.classes.length m_a = c_a.method_list.first m_b = c_a.method_list.last assert_equal 'A#a', m_a.full_name assert_equal 'A#b', m_b.full_name end def test_parse_symbol_in_paren_arg util_parser < e rescue A::D, A::E rescue A::F, A::G rescue H rescue I => e rescue J, K rescue L => e rescue M; rescue N, O => e end end CONTENT util_parser content @parser.scan m = @top_level.modules.first assert_empty m.constants assert_empty @store.classes_hash.keys assert_equal %w[M], @store.modules_hash.keys end def test_scan_constant_nodoc content = <<-CONTENT # newline is after M is important module M C = v # :nodoc: end CONTENT util_parser content @parser.scan c = @top_level.modules.first.constants.first assert c.documented? end def test_scan_constant_nodoc_block content = <<-CONTENT # newline is after M is important module M C = v do # :nodoc: end end CONTENT util_parser content @parser.scan c = @top_level.modules.first.constants.first assert c.documented? end def test_scan_duplicate_module content = <<-CONTENT # comment a module Foo end # comment b module Foo end CONTENT util_parser content @parser.scan foo = @top_level.modules.first expected = [ RDoc::Comment.new('comment a', @top_level), RDoc::Comment.new('comment b', @top_level) ] assert_equal expected, foo.comment_location.map { |c, l| c } end def test_scan_meta_method_block content = <<-CONTENT class C ## # my method inline(:my_method) do |*args| "this method used to cause z to disappear" end def z end CONTENT util_parser content @parser.scan assert_equal 2, @top_level.classes.first.method_list.length end def test_scan_method_semi_method content = <<-CONTENT class A def self.m() end; def self.m=() end end class B def self.m() end end CONTENT util_parser content @parser.scan a = @store.find_class_named 'A' assert a, 'missing A' assert_equal 2, a.method_list.length b = @store.find_class_named 'B' assert b, 'missing B' assert_equal 1, b.method_list.length end def test_scan_markup_override content = <<-CONTENT # *awesome* class C # :markup: rd # ((*radical*)) def m end end CONTENT util_parser content @parser.scan c = @top_level.classes.first assert_equal 'rdoc', c.comment.format assert_equal 'rd', c.method_list.first.comment.format end def test_scan_markup_first_comment content = <<-CONTENT # :markup: rd # ((*awesome*)) class C # ((*radical*)) def m end end CONTENT util_parser content @parser.scan c = @top_level.classes.first assert_equal 'rd', c.comment.format assert_equal 'rd', c.method_list.first.comment.format end def test_scan_rails_routes util_parser <<-ROUTES_RB namespace :api do scope module: :v1 do end end ROUTES_RB @parser.scan assert_empty @top_level.classes assert_empty @top_level.modules end def test_scan_tomdoc_meta util_parser <<-RUBY # :markup: tomdoc class C # Signature # # find_by_[_and_...](args) # # field - A field name. end RUBY @parser.scan c = @top_level.classes.first m = c.method_list.first assert_equal "find_by_[_and_...]", m.name assert_equal "find_by_[_and_...](args)\n", m.call_seq expected = doc( head(3, 'Signature'), list(:NOTE, item(%w[field], para('A field name.')))) expected.file = @top_level assert_equal expected, m.comment.parse end def test_scan_stopdoc util_parser <<-RUBY class C # :stopdoc: class Hidden end end RUBY @parser.scan c = @top_level.classes.first hidden = c.classes.first refute hidden.document_self assert hidden.ignored? end def test_scan_stopdoc_class_alias util_parser <<-RUBY # :stopdoc: module A B = C end RUBY @parser.scan assert_empty @store.all_classes assert_equal 1, @store.all_modules.length m = @store.all_modules.first assert m.ignored? end def test_scan_stopdoc_nested util_parser <<-RUBY # :stopdoc: class A::B end RUBY @parser.scan a = @store.modules_hash['A'] a_b = @store.classes_hash['A::B'] refute a.document_self, 'A is inside stopdoc' assert a.ignored?, 'A is inside stopdoc' refute a_b.document_self, 'A::B is inside stopdoc' assert a_b.ignored?, 'A::B is inside stopdoc' end def test_scan_struct_self_brackets util_parser <<-RUBY class C < M.m def self.[] end end RUBY @parser.scan c = @store.find_class_named 'C' assert_equal %w[C::[]], c.method_list.map { |m| m.full_name } end def test_scan_visibility util_parser <<-RUBY class C def a() end private :a class << self def b() end private :b end end RUBY @parser.scan c = @store.find_class_named 'C' c_a = c.find_method_named 'a' assert_equal :private, c_a.visibility refute c_a.singleton c_b = c.find_method_named 'b' assert_equal :private, c_b.visibility assert c_b.singleton end def test_scan_visibility_count util_parser <<-RUBY class C < Original::Base class C2 < Original::Base def m0() end def m1() end private def m2() end def m3() end def m4() end end end RUBY @parser.scan c = @store.find_class_named 'C::C2' private_method_count = c.method_list.count { |m| :private == m.visibility } assert_equal 3, private_method_count public_method_count = c.method_list.count { |m| :public == m.visibility } assert_equal 2, public_method_count end def test_scan_constant_visibility util_parser <<-RUBY class C CONST_A = 123 CONST_B = 234 private_constant :CONST_B CONST_C = 345 public_constant :CONST_C end RUBY @parser.scan c = @store.find_class_named 'C' const_a, const_b, const_c = c.constants.sort_by(&:name) assert_equal 'CONST_A', const_a.name assert_equal :public, const_a.visibility assert_equal 'CONST_B', const_b.name assert_equal :private, const_b.visibility assert_equal 'CONST_C', const_c.name assert_equal :public, const_c.visibility end def test_document_after_rescue_inside_paren util_parser <<-RUBY class C attr_accessor :sample if (1.inexistent_method rescue false) # first # second def a end end RUBY @parser.scan c = @store.find_class_named 'C' c_a = c.find_method_named 'a' assert_equal "first\nsecond", c_a.comment.text end def test_singleton_method_via_eigenclass util_parser <<-RUBY class C class << self def a() end end end RUBY @parser.scan c = @store.find_class_named 'C' c_a = c.find_method_named 'a' assert_equal :public, c_a.visibility assert c_a.singleton end def test_stopdoc_after_comment util_parser <<-EOS module Bar # hello module Foo # :stopdoc: end # there class Baz # :stopdoc: end end EOS @parser.parse_statements @top_level foo = @top_level.modules.first.modules.first assert_equal 'Foo', foo.name assert_equal 'hello', foo.comment.text baz = @top_level.modules.first.classes.first assert_equal 'Baz', baz.name assert_equal 'there', baz.comment.text end def util_parser(content) @parser = RDoc::Parser::Ruby.new @top_level, @filename, content, @options, @stats end def util_two_parsers(first_file_content, second_file_content) util_parser first_file_content @parser2 = RDoc::Parser::Ruby.new @top_level2, @filename, second_file_content, @options, @stats end def test_parse_const_third_party util_parser <<-CLASS class A true if B true if B::C true if B::C::D module B end end CLASS tk = @parser.get_tk @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment a = @top_level.classes.first assert_equal 'A', a.full_name visible = @store.all_modules.reject { |mod| mod.suppressed? } visible = visible.map { |mod| mod.full_name } assert_equal ['A::B'], visible end def test_parse_const_alias_defined_elsewhere util_parser <<-CLASS module A Aliased = Defined end module A class Defined end end CLASS @parser.scan a = @top_level.modules.first assert_equal 'A', a.full_name aliased = a.constants.first assert_equal 'A::Aliased', aliased.full_name assert_equal [], a.modules.map(&:full_name) assert_equal ['A::Defined', 'A::Aliased'], a.classes.map(&:full_name) assert_equal ['A::Aliased'], a.constants.map(&:full_name) visible = @store.all_modules.reject { |mod| mod.suppressed? } visible = visible.map { |mod| mod.full_name } assert_equal ['A'], visible end def test_parse_const_alias_defined_far_away util_parser <<-CLASS module A Aliased = ::B::C::Defined end module B module C class Defined end end end CLASS @parser.scan a = @top_level.modules.first assert_equal 'A', a.full_name assert_empty a.classes assert_empty a.modules assert_equal ['A::Aliased'], a.constants.map(&:full_name) defined = @store.find_class_named 'B::C::Defined' assert_equal 'B::C::Defined', defined.full_name aliased = @store.find_class_named 'B::C::Aliased' assert_equal 'B::C::Aliased', aliased.full_name visible = @store.all_modules.reject { |mod| mod.suppressed? } visible = visible.map { |mod| mod.full_name } assert_equal ['A', 'B', 'B::C'], visible end def test_parse_include_by_dynamic_definition util_parser <<-CLASS module A class B include(Module.new do def e(m) end end) end class C end class D end end CLASS @parser.scan a = @store.find_module_named 'A' assert_equal 'A', a.full_name a_b = a.find_class_named 'B' assert_equal 'A::B', a_b.full_name a_c = a.find_class_named 'C' assert_equal 'A::C', a_c.full_name a_d = a.find_class_named 'D' assert_equal 'A::D', a_d.full_name end def test_parse_include_by_dynamic_definition_without_paren util_parser <<-CLASS module A class B include(Module.new do def e m end end) end class C end class D end end CLASS @parser.scan a = @store.find_module_named 'A' assert_equal 'A', a.full_name a_b = a.find_class_named 'B' assert_equal 'A::B', a_b.full_name a_c = a.find_class_named 'C' assert_equal 'A::C', a_c.full_name a_d = a.find_class_named 'D' assert_equal 'A::D', a_d.full_name end def test_parse_include_by_dynamic_definition_via_variable util_parser <<-CLASS module A class B m = Module.new do def e(m) end end include m end class C end class D end end CLASS @parser.scan a = @store.find_module_named 'A' assert_equal 'A', a.full_name a_b = a.find_class_named 'B' assert_equal 'A::B', a_b.full_name a_c = a.find_class_named 'C' assert_equal 'A::C', a_c.full_name a_d = a.find_class_named 'D' assert_equal 'A::D', a_d.full_name end def test_parse_include_by_dynamic_definition_with_brace util_parser <<-CLASS module A class B extend(e { def f(g) end }) end class C end class D end end CLASS @parser.scan a = @store.find_module_named 'A' assert_equal 'A', a.full_name a_b = a.find_class_named 'B' assert_equal 'A::B', a_b.full_name a_c = a.find_class_named 'C' assert_equal 'A::C', a_c.full_name a_d = a.find_class_named 'D' assert_equal 'A::D', a_d.full_name end def test_parse_include_by_dynamic_definition_directly util_parser <<-CLASS module A class B include Module.new do def e m end end end class C end class D end end CLASS @parser.scan a = @store.find_module_named 'A' assert_equal 'A', a.full_name a_b = a.find_class_named 'B' assert_equal 'A::B', a_b.full_name a_c = a.find_class_named 'C' assert_equal 'A::C', a_c.full_name a_d = a.find_class_named 'D' assert_equal 'A::D', a_d.full_name end def test_parse_included util_parser <<-CLASS module A module B extend ActiveSupport::Concern included do ## # :singleton-method: # Hello mattr_accessor :foo end end end CLASS @parser.scan a = @store.find_module_named 'A' assert_equal 'A', a.full_name a_b = a.find_module_named 'B' assert_equal 'A::B', a_b.full_name meth = a_b.method_list.first assert_equal 'foo', meth.name assert_equal 'Hello', meth.comment.text end def test_end_that_doesnt_belong_to_class_doesnt_change_visibility util_parser <<-CLASS class A private begin end # Hello def foo() end end CLASS @parser.scan a = @store.find_class_named 'A' assert_equal 'A', a.full_name assert_equal 'foo', a.find_method_named('foo').name meth = a.method_list.first assert_equal 'Hello', meth.comment.text end def test_parenthesized_cdecl util_parser <<-RUBY module DidYouMean class << (NameErrorCheckers = Object.new) end end RUBY @parser.scan refute_predicate @store.find_class_or_module('DidYouMean'), :nil? refute_predicate @store.find_class_or_module('DidYouMean::NameErrorCheckers'), :nil? end end