From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 18:49:26 +0900 Subject: Fresh start --- jni/ruby/lib/rdoc/alias.rb | 111 + jni/ruby/lib/rdoc/anon_class.rb | 10 + jni/ruby/lib/rdoc/any_method.rb | 316 + jni/ruby/lib/rdoc/attr.rb | 175 + jni/ruby/lib/rdoc/class_module.rb | 799 + jni/ruby/lib/rdoc/code_object.rb | 429 + jni/ruby/lib/rdoc/code_objects.rb | 5 + jni/ruby/lib/rdoc/comment.rb | 229 + jni/ruby/lib/rdoc/constant.rb | 186 + jni/ruby/lib/rdoc/context.rb | 1211 ++ jni/ruby/lib/rdoc/context/section.rb | 238 + jni/ruby/lib/rdoc/cross_reference.rb | 183 + jni/ruby/lib/rdoc/encoding.rb | 99 + jni/ruby/lib/rdoc/erb_partial.rb | 18 + jni/ruby/lib/rdoc/erbio.rb | 37 + jni/ruby/lib/rdoc/extend.rb | 9 + jni/ruby/lib/rdoc/generator.rb | 51 + jni/ruby/lib/rdoc/generator/darkfish.rb | 760 + jni/ruby/lib/rdoc/generator/json_index.rb | 292 + jni/ruby/lib/rdoc/generator/markup.rb | 169 + jni/ruby/lib/rdoc/generator/pot.rb | 97 + .../lib/rdoc/generator/pot/message_extractor.rb | 67 + jni/ruby/lib/rdoc/generator/pot/po.rb | 83 + jni/ruby/lib/rdoc/generator/pot/po_entry.rb | 140 + jni/ruby/lib/rdoc/generator/ri.rb | 30 + .../lib/rdoc/generator/template/darkfish/.document | 0 .../rdoc/generator/template/darkfish/_footer.rhtml | 5 + .../rdoc/generator/template/darkfish/_head.rhtml | 19 + .../template/darkfish/_sidebar_VCS_info.rhtml | 19 + .../template/darkfish/_sidebar_classes.rhtml | 9 + .../template/darkfish/_sidebar_extends.rhtml | 15 + .../template/darkfish/_sidebar_in_files.rhtml | 9 + .../template/darkfish/_sidebar_includes.rhtml | 15 + .../template/darkfish/_sidebar_installed.rhtml | 15 + .../template/darkfish/_sidebar_methods.rhtml | 12 + .../template/darkfish/_sidebar_navigation.rhtml | 11 + .../template/darkfish/_sidebar_pages.rhtml | 12 + .../template/darkfish/_sidebar_parent.rhtml | 11 + .../template/darkfish/_sidebar_search.rhtml | 14 + .../template/darkfish/_sidebar_sections.rhtml | 11 + .../darkfish/_sidebar_table_of_contents.rhtml | 18 + .../rdoc/generator/template/darkfish/class.rhtml | 174 + .../rdoc/generator/template/darkfish/css/fonts.css | 167 + .../rdoc/generator/template/darkfish/css/rdoc.css | 590 + .../template/darkfish/fonts/Lato-Light.ttf | Bin 0 -> 94668 bytes .../template/darkfish/fonts/Lato-LightItalic.ttf | Bin 0 -> 94196 bytes .../template/darkfish/fonts/Lato-Regular.ttf | Bin 0 -> 96184 bytes .../template/darkfish/fonts/Lato-RegularItalic.ttf | Bin 0 -> 95316 bytes .../template/darkfish/fonts/SourceCodePro-Bold.ttf | Bin 0 -> 71200 bytes .../darkfish/fonts/SourceCodePro-Regular.ttf | Bin 0 -> 71692 bytes .../generator/template/darkfish/images/add.png | Bin 0 -> 733 bytes .../template/darkfish/images/arrow_up.png | Bin 0 -> 372 bytes .../generator/template/darkfish/images/brick.png | Bin 0 -> 452 bytes .../template/darkfish/images/brick_link.png | Bin 0 -> 764 bytes .../generator/template/darkfish/images/bug.png | Bin 0 -> 774 bytes .../template/darkfish/images/bullet_black.png | Bin 0 -> 211 bytes .../darkfish/images/bullet_toggle_minus.png | Bin 0 -> 207 bytes .../darkfish/images/bullet_toggle_plus.png | Bin 0 -> 209 bytes .../generator/template/darkfish/images/date.png | Bin 0 -> 626 bytes .../generator/template/darkfish/images/delete.png | Bin 0 -> 715 bytes .../generator/template/darkfish/images/find.png | Bin 0 -> 659 bytes .../template/darkfish/images/loadingAnimation.gif | Bin 0 -> 5886 bytes .../template/darkfish/images/macFFBgHack.png | Bin 0 -> 207 bytes .../generator/template/darkfish/images/package.png | Bin 0 -> 853 bytes .../template/darkfish/images/page_green.png | Bin 0 -> 621 bytes .../template/darkfish/images/page_white_text.png | Bin 0 -> 342 bytes .../template/darkfish/images/page_white_width.png | Bin 0 -> 309 bytes .../generator/template/darkfish/images/plugin.png | Bin 0 -> 591 bytes .../generator/template/darkfish/images/ruby.png | Bin 0 -> 592 bytes .../template/darkfish/images/tag_blue.png | Bin 0 -> 1880 bytes .../template/darkfish/images/tag_green.png | Bin 0 -> 613 bytes .../template/darkfish/images/transparent.png | Bin 0 -> 97 bytes .../generator/template/darkfish/images/wrench.png | Bin 0 -> 610 bytes .../template/darkfish/images/wrench_orange.png | Bin 0 -> 584 bytes .../generator/template/darkfish/images/zoom.png | Bin 0 -> 692 bytes .../rdoc/generator/template/darkfish/index.rhtml | 23 + .../generator/template/darkfish/js/darkfish.js | 161 + .../rdoc/generator/template/darkfish/js/jquery.js | 4 + .../rdoc/generator/template/darkfish/js/search.js | 109 + .../rdoc/generator/template/darkfish/page.rhtml | 18 + .../template/darkfish/servlet_not_found.rhtml | 18 + .../generator/template/darkfish/servlet_root.rhtml | 63 + .../template/darkfish/table_of_contents.rhtml | 58 + .../rdoc/generator/template/json_index/.document | 1 + .../generator/template/json_index/js/navigation.js | 142 + .../generator/template/json_index/js/searcher.js | 228 + jni/ruby/lib/rdoc/ghost_method.rb | 6 + jni/ruby/lib/rdoc/i18n.rb | 9 + jni/ruby/lib/rdoc/i18n/locale.rb | 101 + jni/ruby/lib/rdoc/i18n/text.rb | 125 + jni/ruby/lib/rdoc/include.rb | 9 + jni/ruby/lib/rdoc/known_classes.rb | 72 + jni/ruby/lib/rdoc/markdown.rb | 16133 +++++++++++++++++++ jni/ruby/lib/rdoc/markdown/entities.rb | 2131 +++ jni/ruby/lib/rdoc/markdown/literals_1_9.rb | 420 + jni/ruby/lib/rdoc/markup.rb | 869 + jni/ruby/lib/rdoc/markup/attr_changer.rb | 22 + jni/ruby/lib/rdoc/markup/attr_span.rb | 29 + jni/ruby/lib/rdoc/markup/attribute_manager.rb | 343 + jni/ruby/lib/rdoc/markup/attributes.rb | 70 + jni/ruby/lib/rdoc/markup/blank_line.rb | 27 + jni/ruby/lib/rdoc/markup/block_quote.rb | 14 + jni/ruby/lib/rdoc/markup/document.rb | 164 + jni/ruby/lib/rdoc/markup/formatter.rb | 264 + jni/ruby/lib/rdoc/markup/formatter_test_case.rb | 767 + jni/ruby/lib/rdoc/markup/hard_break.rb | 31 + jni/ruby/lib/rdoc/markup/heading.rb | 78 + jni/ruby/lib/rdoc/markup/include.rb | 42 + jni/ruby/lib/rdoc/markup/indented_paragraph.rb | 47 + jni/ruby/lib/rdoc/markup/inline.rb | 1 + jni/ruby/lib/rdoc/markup/list.rb | 101 + jni/ruby/lib/rdoc/markup/list_item.rb | 99 + jni/ruby/lib/rdoc/markup/paragraph.rb | 28 + jni/ruby/lib/rdoc/markup/parser.rb | 558 + jni/ruby/lib/rdoc/markup/pre_process.rb | 293 + jni/ruby/lib/rdoc/markup/raw.rb | 69 + jni/ruby/lib/rdoc/markup/rule.rb | 20 + jni/ruby/lib/rdoc/markup/special.rb | 40 + .../lib/rdoc/markup/text_formatter_test_case.rb | 114 + jni/ruby/lib/rdoc/markup/to_ansi.rb | 93 + jni/ruby/lib/rdoc/markup/to_bs.rb | 78 + jni/ruby/lib/rdoc/markup/to_html.rb | 398 + jni/ruby/lib/rdoc/markup/to_html_crossref.rb | 160 + jni/ruby/lib/rdoc/markup/to_html_snippet.rb | 284 + jni/ruby/lib/rdoc/markup/to_joined_paragraph.rb | 71 + jni/ruby/lib/rdoc/markup/to_label.rb | 74 + jni/ruby/lib/rdoc/markup/to_markdown.rb | 191 + jni/ruby/lib/rdoc/markup/to_rdoc.rb | 333 + jni/ruby/lib/rdoc/markup/to_table_of_contents.rb | 87 + jni/ruby/lib/rdoc/markup/to_test.rb | 69 + jni/ruby/lib/rdoc/markup/to_tt_only.rb | 120 + jni/ruby/lib/rdoc/markup/verbatim.rb | 83 + jni/ruby/lib/rdoc/meta_method.rb | 6 + jni/ruby/lib/rdoc/method_attr.rb | 418 + jni/ruby/lib/rdoc/mixin.rb | 120 + jni/ruby/lib/rdoc/normal_class.rb | 92 + jni/ruby/lib/rdoc/normal_module.rb | 73 + jni/ruby/lib/rdoc/options.rb | 1251 ++ jni/ruby/lib/rdoc/parser.rb | 310 + jni/ruby/lib/rdoc/parser/c.rb | 1229 ++ jni/ruby/lib/rdoc/parser/changelog.rb | 198 + jni/ruby/lib/rdoc/parser/markdown.rb | 23 + jni/ruby/lib/rdoc/parser/rd.rb | 22 + jni/ruby/lib/rdoc/parser/ruby.rb | 2160 +++ jni/ruby/lib/rdoc/parser/ruby_tools.rb | 167 + jni/ruby/lib/rdoc/parser/simple.rb | 61 + jni/ruby/lib/rdoc/parser/text.rb | 11 + jni/ruby/lib/rdoc/rd.rb | 99 + jni/ruby/lib/rdoc/rd/block_parser.rb | 1055 ++ jni/ruby/lib/rdoc/rd/inline.rb | 71 + jni/ruby/lib/rdoc/rd/inline_parser.rb | 1207 ++ jni/ruby/lib/rdoc/rdoc.rb | 570 + jni/ruby/lib/rdoc/require.rb | 51 + jni/ruby/lib/rdoc/ri.rb | 20 + jni/ruby/lib/rdoc/ri/driver.rb | 1497 ++ jni/ruby/lib/rdoc/ri/formatter.rb | 5 + jni/ruby/lib/rdoc/ri/paths.rb | 187 + jni/ruby/lib/rdoc/ri/store.rb | 6 + jni/ruby/lib/rdoc/ri/task.rb | 71 + jni/ruby/lib/rdoc/ruby_lex.rb | 1377 ++ jni/ruby/lib/rdoc/ruby_token.rb | 460 + jni/ruby/lib/rdoc/rubygems_hook.rb | 253 + jni/ruby/lib/rdoc/servlet.rb | 441 + jni/ruby/lib/rdoc/single_class.rb | 25 + jni/ruby/lib/rdoc/stats.rb | 461 + jni/ruby/lib/rdoc/stats/normal.rb | 59 + jni/ruby/lib/rdoc/stats/quiet.rb | 59 + jni/ruby/lib/rdoc/stats/verbose.rb | 45 + jni/ruby/lib/rdoc/store.rb | 979 ++ jni/ruby/lib/rdoc/task.rb | 330 + jni/ruby/lib/rdoc/test_case.rb | 217 + jni/ruby/lib/rdoc/text.rb | 324 + jni/ruby/lib/rdoc/token_stream.rb | 95 + jni/ruby/lib/rdoc/tom_doc.rb | 257 + jni/ruby/lib/rdoc/top_level.rb | 282 + 175 files changed, 49476 insertions(+) create mode 100644 jni/ruby/lib/rdoc/alias.rb create mode 100644 jni/ruby/lib/rdoc/anon_class.rb create mode 100644 jni/ruby/lib/rdoc/any_method.rb create mode 100644 jni/ruby/lib/rdoc/attr.rb create mode 100644 jni/ruby/lib/rdoc/class_module.rb create mode 100644 jni/ruby/lib/rdoc/code_object.rb create mode 100644 jni/ruby/lib/rdoc/code_objects.rb create mode 100644 jni/ruby/lib/rdoc/comment.rb create mode 100644 jni/ruby/lib/rdoc/constant.rb create mode 100644 jni/ruby/lib/rdoc/context.rb create mode 100644 jni/ruby/lib/rdoc/context/section.rb create mode 100644 jni/ruby/lib/rdoc/cross_reference.rb create mode 100644 jni/ruby/lib/rdoc/encoding.rb create mode 100644 jni/ruby/lib/rdoc/erb_partial.rb create mode 100644 jni/ruby/lib/rdoc/erbio.rb create mode 100644 jni/ruby/lib/rdoc/extend.rb create mode 100644 jni/ruby/lib/rdoc/generator.rb create mode 100644 jni/ruby/lib/rdoc/generator/darkfish.rb create mode 100644 jni/ruby/lib/rdoc/generator/json_index.rb create mode 100644 jni/ruby/lib/rdoc/generator/markup.rb create mode 100644 jni/ruby/lib/rdoc/generator/pot.rb create mode 100644 jni/ruby/lib/rdoc/generator/pot/message_extractor.rb create mode 100644 jni/ruby/lib/rdoc/generator/pot/po.rb create mode 100644 jni/ruby/lib/rdoc/generator/pot/po_entry.rb create mode 100644 jni/ruby/lib/rdoc/generator/ri.rb create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/.document create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_footer.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_head.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/class.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/css/fonts.css create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/css/rdoc.css create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/add.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/arrow_up.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/brick.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/brick_link.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/bug.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_black.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/date.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/delete.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/find.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/package.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/page_green.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/page_white_text.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/page_white_width.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/plugin.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/ruby.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/tag_blue.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/tag_green.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/transparent.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/wrench.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/wrench_orange.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/images/zoom.png create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/index.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/js/darkfish.js create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/js/jquery.js create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/js/search.js create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/page.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/servlet_root.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml create mode 100644 jni/ruby/lib/rdoc/generator/template/json_index/.document create mode 100644 jni/ruby/lib/rdoc/generator/template/json_index/js/navigation.js create mode 100644 jni/ruby/lib/rdoc/generator/template/json_index/js/searcher.js create mode 100644 jni/ruby/lib/rdoc/ghost_method.rb create mode 100644 jni/ruby/lib/rdoc/i18n.rb create mode 100644 jni/ruby/lib/rdoc/i18n/locale.rb create mode 100644 jni/ruby/lib/rdoc/i18n/text.rb create mode 100644 jni/ruby/lib/rdoc/include.rb create mode 100644 jni/ruby/lib/rdoc/known_classes.rb create mode 100644 jni/ruby/lib/rdoc/markdown.rb create mode 100644 jni/ruby/lib/rdoc/markdown/entities.rb create mode 100644 jni/ruby/lib/rdoc/markdown/literals_1_9.rb create mode 100644 jni/ruby/lib/rdoc/markup.rb create mode 100644 jni/ruby/lib/rdoc/markup/attr_changer.rb create mode 100644 jni/ruby/lib/rdoc/markup/attr_span.rb create mode 100644 jni/ruby/lib/rdoc/markup/attribute_manager.rb create mode 100644 jni/ruby/lib/rdoc/markup/attributes.rb create mode 100644 jni/ruby/lib/rdoc/markup/blank_line.rb create mode 100644 jni/ruby/lib/rdoc/markup/block_quote.rb create mode 100644 jni/ruby/lib/rdoc/markup/document.rb create mode 100644 jni/ruby/lib/rdoc/markup/formatter.rb create mode 100644 jni/ruby/lib/rdoc/markup/formatter_test_case.rb create mode 100644 jni/ruby/lib/rdoc/markup/hard_break.rb create mode 100644 jni/ruby/lib/rdoc/markup/heading.rb create mode 100644 jni/ruby/lib/rdoc/markup/include.rb create mode 100644 jni/ruby/lib/rdoc/markup/indented_paragraph.rb create mode 100644 jni/ruby/lib/rdoc/markup/inline.rb create mode 100644 jni/ruby/lib/rdoc/markup/list.rb create mode 100644 jni/ruby/lib/rdoc/markup/list_item.rb create mode 100644 jni/ruby/lib/rdoc/markup/paragraph.rb create mode 100644 jni/ruby/lib/rdoc/markup/parser.rb create mode 100644 jni/ruby/lib/rdoc/markup/pre_process.rb create mode 100644 jni/ruby/lib/rdoc/markup/raw.rb create mode 100644 jni/ruby/lib/rdoc/markup/rule.rb create mode 100644 jni/ruby/lib/rdoc/markup/special.rb create mode 100644 jni/ruby/lib/rdoc/markup/text_formatter_test_case.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_ansi.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_bs.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_html.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_html_crossref.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_html_snippet.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_joined_paragraph.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_label.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_markdown.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_rdoc.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_table_of_contents.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_test.rb create mode 100644 jni/ruby/lib/rdoc/markup/to_tt_only.rb create mode 100644 jni/ruby/lib/rdoc/markup/verbatim.rb create mode 100644 jni/ruby/lib/rdoc/meta_method.rb create mode 100644 jni/ruby/lib/rdoc/method_attr.rb create mode 100644 jni/ruby/lib/rdoc/mixin.rb create mode 100644 jni/ruby/lib/rdoc/normal_class.rb create mode 100644 jni/ruby/lib/rdoc/normal_module.rb create mode 100644 jni/ruby/lib/rdoc/options.rb create mode 100644 jni/ruby/lib/rdoc/parser.rb create mode 100644 jni/ruby/lib/rdoc/parser/c.rb create mode 100644 jni/ruby/lib/rdoc/parser/changelog.rb create mode 100644 jni/ruby/lib/rdoc/parser/markdown.rb create mode 100644 jni/ruby/lib/rdoc/parser/rd.rb create mode 100644 jni/ruby/lib/rdoc/parser/ruby.rb create mode 100644 jni/ruby/lib/rdoc/parser/ruby_tools.rb create mode 100644 jni/ruby/lib/rdoc/parser/simple.rb create mode 100644 jni/ruby/lib/rdoc/parser/text.rb create mode 100644 jni/ruby/lib/rdoc/rd.rb create mode 100644 jni/ruby/lib/rdoc/rd/block_parser.rb create mode 100644 jni/ruby/lib/rdoc/rd/inline.rb create mode 100644 jni/ruby/lib/rdoc/rd/inline_parser.rb create mode 100644 jni/ruby/lib/rdoc/rdoc.rb create mode 100644 jni/ruby/lib/rdoc/require.rb create mode 100644 jni/ruby/lib/rdoc/ri.rb create mode 100644 jni/ruby/lib/rdoc/ri/driver.rb create mode 100644 jni/ruby/lib/rdoc/ri/formatter.rb create mode 100644 jni/ruby/lib/rdoc/ri/paths.rb create mode 100644 jni/ruby/lib/rdoc/ri/store.rb create mode 100644 jni/ruby/lib/rdoc/ri/task.rb create mode 100644 jni/ruby/lib/rdoc/ruby_lex.rb create mode 100644 jni/ruby/lib/rdoc/ruby_token.rb create mode 100644 jni/ruby/lib/rdoc/rubygems_hook.rb create mode 100644 jni/ruby/lib/rdoc/servlet.rb create mode 100644 jni/ruby/lib/rdoc/single_class.rb create mode 100644 jni/ruby/lib/rdoc/stats.rb create mode 100644 jni/ruby/lib/rdoc/stats/normal.rb create mode 100644 jni/ruby/lib/rdoc/stats/quiet.rb create mode 100644 jni/ruby/lib/rdoc/stats/verbose.rb create mode 100644 jni/ruby/lib/rdoc/store.rb create mode 100644 jni/ruby/lib/rdoc/task.rb create mode 100644 jni/ruby/lib/rdoc/test_case.rb create mode 100644 jni/ruby/lib/rdoc/text.rb create mode 100644 jni/ruby/lib/rdoc/token_stream.rb create mode 100644 jni/ruby/lib/rdoc/tom_doc.rb create mode 100644 jni/ruby/lib/rdoc/top_level.rb (limited to 'jni/ruby/lib/rdoc') diff --git a/jni/ruby/lib/rdoc/alias.rb b/jni/ruby/lib/rdoc/alias.rb new file mode 100644 index 0000000..39d2694 --- /dev/null +++ b/jni/ruby/lib/rdoc/alias.rb @@ -0,0 +1,111 @@ +## +# Represent an alias, which is an old_name/new_name pair associated with a +# particular context +#-- +# TODO implement Alias as a proxy to a method/attribute, inheriting from +# MethodAttr + +class RDoc::Alias < RDoc::CodeObject + + ## + # Aliased method's name + + attr_reader :new_name + + alias name new_name + + ## + # Aliasee method's name + + attr_reader :old_name + + ## + # Is this an alias declared in a singleton context? + + attr_accessor :singleton + + ## + # Source file token stream + + attr_reader :text + + ## + # Creates a new Alias with a token stream of +text+ that aliases +old_name+ + # to +new_name+, has +comment+ and is a +singleton+ context. + + def initialize(text, old_name, new_name, comment, singleton = false) + super() + + @text = text + @singleton = singleton + @old_name = old_name + @new_name = new_name + self.comment = comment + end + + ## + # Order by #singleton then #new_name + + def <=>(other) + [@singleton ? 0 : 1, new_name] <=> [other.singleton ? 0 : 1, other.new_name] + end + + ## + # HTML fragment reference for this alias + + def aref + type = singleton ? 'c' : 'i' + "#alias-#{type}-#{html_name}" + end + + ## + # Full old name including namespace + + def full_old_name + @full_name || "#{parent.name}#{pretty_old_name}" + end + + ## + # HTML id-friendly version of +#new_name+. + + def html_name + CGI.escape(@new_name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '') + end + + def inspect # :nodoc: + parent_name = parent ? parent.name : '(unknown)' + "#<%s:0x%x %s.alias_method %s, %s>" % [ + self.class, object_id, + parent_name, @old_name, @new_name, + ] + end + + ## + # '::' for the alias of a singleton method/attribute, '#' for instance-level. + + def name_prefix + singleton ? '::' : '#' + end + + ## + # Old name with prefix '::' or '#'. + + def pretty_old_name + "#{singleton ? '::' : '#'}#{@old_name}" + end + + ## + # New name with prefix '::' or '#'. + + def pretty_new_name + "#{singleton ? '::' : '#'}#{@new_name}" + end + + alias pretty_name pretty_new_name + + def to_s # :nodoc: + "alias: #{self.new_name} -> #{self.pretty_old_name} in: #{parent}" + end + +end + diff --git a/jni/ruby/lib/rdoc/anon_class.rb b/jni/ruby/lib/rdoc/anon_class.rb new file mode 100644 index 0000000..c23d8e5 --- /dev/null +++ b/jni/ruby/lib/rdoc/anon_class.rb @@ -0,0 +1,10 @@ +## +# An anonymous class like: +# +# c = Class.new do end +# +# AnonClass is currently not used. + +class RDoc::AnonClass < RDoc::ClassModule +end + diff --git a/jni/ruby/lib/rdoc/any_method.rb b/jni/ruby/lib/rdoc/any_method.rb new file mode 100644 index 0000000..ae022d7 --- /dev/null +++ b/jni/ruby/lib/rdoc/any_method.rb @@ -0,0 +1,316 @@ +## +# AnyMethod is the base class for objects representing methods + +class RDoc::AnyMethod < RDoc::MethodAttr + + ## + # 2:: + # RDoc 4 + # Added calls_super + # Added parent name and class + # Added section title + # 3:: + # RDoc 4.1 + # Added is_alias_for + + MARSHAL_VERSION = 3 # :nodoc: + + ## + # Don't rename \#initialize to \::new + + attr_accessor :dont_rename_initialize + + ## + # The C function that implements this method (if it was defined in a C file) + + attr_accessor :c_function + + ## + # Different ways to call this method + + attr_reader :call_seq + + ## + # Parameters for this method + + attr_accessor :params + + ## + # If true this method uses +super+ to call a superclass version + + attr_accessor :calls_super + + include RDoc::TokenStream + + ## + # Creates a new AnyMethod with a token stream +text+ and +name+ + + def initialize text, name + super + + @c_function = nil + @dont_rename_initialize = false + @token_stream = nil + @calls_super = false + @superclass_method = nil + end + + ## + # Adds +an_alias+ as an alias for this method in +context+. + + def add_alias an_alias, context = nil + method = self.class.new an_alias.text, an_alias.new_name + + method.record_location an_alias.file + method.singleton = self.singleton + method.params = self.params + method.visibility = self.visibility + method.comment = an_alias.comment + method.is_alias_for = self + @aliases << method + context.add_method method if context + method + end + + ## + # Prefix for +aref+ is 'method'. + + def aref_prefix + 'method' + end + + ## + # The call_seq or the param_seq with method name, if there is no call_seq. + # + # Use this for displaying a method's argument lists. + + def arglists + if @call_seq then + @call_seq + elsif @params then + "#{name}#{param_seq}" + end + end + + ## + # Sets the different ways you can call this method. If an empty +call_seq+ + # is given nil is assumed. + # + # See also #param_seq + + def call_seq= call_seq + return if call_seq.empty? + + @call_seq = call_seq + end + + ## + # Loads is_alias_for from the internal name. Returns nil if the alias + # cannot be found. + + def is_alias_for # :nodoc: + case @is_alias_for + when RDoc::MethodAttr then + @is_alias_for + when Array then + return nil unless @store + + klass_name, singleton, method_name = @is_alias_for + + return nil unless klass = @store.find_class_or_module(klass_name) + + @is_alias_for = klass.find_method method_name, singleton + end + end + + ## + # Dumps this AnyMethod for use by ri. See also #marshal_load + + def marshal_dump + aliases = @aliases.map do |a| + [a.name, parse(a.comment)] + end + + is_alias_for = [ + @is_alias_for.parent.full_name, + @is_alias_for.singleton, + @is_alias_for.name + ] if @is_alias_for + + [ MARSHAL_VERSION, + @name, + full_name, + @singleton, + @visibility, + parse(@comment), + @call_seq, + @block_params, + aliases, + @params, + @file.relative_name, + @calls_super, + @parent.name, + @parent.class, + @section.title, + is_alias_for, + ] + end + + ## + # Loads this AnyMethod from +array+. For a loaded AnyMethod the following + # methods will return cached values: + # + # * #full_name + # * #parent_name + + def marshal_load array + initialize_visibility + + @dont_rename_initialize = nil + @token_stream = nil + @aliases = [] + @parent = nil + @parent_name = nil + @parent_class = nil + @section = nil + @file = nil + + version = array[0] + @name = array[1] + @full_name = array[2] + @singleton = array[3] + @visibility = array[4] + @comment = array[5] + @call_seq = array[6] + @block_params = array[7] + # 8 handled below + @params = array[9] + # 10 handled below + @calls_super = array[11] + @parent_name = array[12] + @parent_title = array[13] + @section_title = array[14] + @is_alias_for = array[15] + + array[8].each do |new_name, comment| + add_alias RDoc::Alias.new(nil, @name, new_name, comment, @singleton) + end + + @parent_name ||= if @full_name =~ /#/ then + $` + else + name = @full_name.split('::') + name.pop + name.join '::' + end + + @file = RDoc::TopLevel.new array[10] if version > 0 + end + + ## + # Method name + # + # If the method has no assigned name, it extracts it from #call_seq. + + def name + return @name if @name + + @name = + @call_seq[/^.*?\.(\w+)/, 1] || + @call_seq[/^.*?(\w+)/, 1] || + @call_seq if @call_seq + end + + ## + # A list of this method's method and yield parameters. +call-seq+ params + # are preferred over parsed method and block params. + + def param_list + if @call_seq then + params = @call_seq.split("\n").last + params = params.sub(/.*?\((.*)\)/, '\1') + params = params.sub(/(\{|do)\s*\|([^|]*)\|.*/, ',\2') + elsif @params then + params = @params.sub(/\((.*)\)/, '\1') + + params << ",#{@block_params}" if @block_params + elsif @block_params then + params = @block_params + else + return [] + end + + if @block_params then + # If this method has explicit block parameters, remove any explicit + # &block + params.sub!(/,?\s*&\w+/, '') + else + params.sub!(/\&(\w+)/, '\1') + end + + params = params.gsub(/\s+/, '').split(',').reject(&:empty?) + + params.map { |param| param.sub(/=.*/, '') } + end + + ## + # Pretty parameter list for this method. If the method's parameters were + # given by +call-seq+ it is preferred over the parsed values. + + def param_seq + if @call_seq then + params = @call_seq.split("\n").last + params = params.sub(/[^( ]+/, '') + params = params.sub(/(\|[^|]+\|)\s*\.\.\.\s*(end|\})/, '\1 \2') + elsif @params then + params = @params.gsub(/\s*\#.*/, '') + params = params.tr("\n", " ").squeeze(" ") + params = "(#{params})" unless params[0] == ?( + else + params = '' + end + + if @block_params then + # If this method has explicit block parameters, remove any explicit + # &block + params.sub!(/,?\s*&\w+/, '') + + block = @block_params.gsub(/\s*\#.*/, '') + block = block.tr("\n", " ").squeeze(" ") + if block[0] == ?( + block.sub!(/^\(/, '').sub!(/\)/, '') + end + params << " { |#{block}| ... }" + end + + params + end + + ## + # Sets the store for this method and its referenced code objects. + + def store= store + super + + @file = @store.add_file @file.full_name if @file + end + + ## + # For methods that +super+, find the superclass method that would be called. + + def superclass_method + return unless @calls_super + return @superclass_method if @superclass_method + + parent.each_ancestor do |ancestor| + if method = ancestor.method_list.find { |m| m.name == @name } then + @superclass_method = method + break + end + end + + @superclass_method + end + +end + diff --git a/jni/ruby/lib/rdoc/attr.rb b/jni/ruby/lib/rdoc/attr.rb new file mode 100644 index 0000000..960e1d1 --- /dev/null +++ b/jni/ruby/lib/rdoc/attr.rb @@ -0,0 +1,175 @@ +## +# An attribute created by \#attr, \#attr_reader, \#attr_writer or +# \#attr_accessor + +class RDoc::Attr < RDoc::MethodAttr + + ## + # 3:: + # RDoc 4 + # Added parent name and class + # Added section title + + MARSHAL_VERSION = 3 # :nodoc: + + ## + # Is the attribute readable ('R'), writable ('W') or both ('RW')? + + attr_accessor :rw + + ## + # Creates a new Attr with body +text+, +name+, read/write status +rw+ and + # +comment+. +singleton+ marks this as a class attribute. + + def initialize(text, name, rw, comment, singleton = false) + super text, name + + @rw = rw + @singleton = singleton + self.comment = comment + end + + ## + # Attributes are equal when their names, singleton and rw are identical + + def == other + self.class == other.class and + self.name == other.name and + self.rw == other.rw and + self.singleton == other.singleton + end + + ## + # Add +an_alias+ as an attribute in +context+. + + def add_alias(an_alias, context) + new_attr = self.class.new(self.text, an_alias.new_name, self.rw, + self.comment, self.singleton) + + new_attr.record_location an_alias.file + new_attr.visibility = self.visibility + new_attr.is_alias_for = self + @aliases << new_attr + context.add_attribute new_attr + new_attr + end + + ## + # The #aref prefix for attributes + + def aref_prefix + 'attribute' + end + + ## + # Attributes never call super. See RDoc::AnyMethod#calls_super + # + # An RDoc::Attr can show up in the method list in some situations (see + # Gem::ConfigFile) + + def calls_super # :nodoc: + false + end + + ## + # Returns attr_reader, attr_writer or attr_accessor as appropriate. + + def definition + case @rw + when 'RW' then 'attr_accessor' + when 'R' then 'attr_reader' + when 'W' then 'attr_writer' + end + end + + def inspect # :nodoc: + alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil + visibility = self.visibility + visibility = "forced #{visibility}" if force_documentation + "#<%s:0x%x %s %s (%s)%s>" % [ + self.class, object_id, + full_name, + rw, + visibility, + alias_for, + ] + end + + ## + # Dumps this Attr for use by ri. See also #marshal_load + + def marshal_dump + [ MARSHAL_VERSION, + @name, + full_name, + @rw, + @visibility, + parse(@comment), + singleton, + @file.relative_name, + @parent.full_name, + @parent.class, + @section.title + ] + end + + ## + # Loads this Attr from +array+. For a loaded Attr the following + # methods will return cached values: + # + # * #full_name + # * #parent_name + + def marshal_load array + initialize_visibility + + @aliases = [] + @parent = nil + @parent_name = nil + @parent_class = nil + @section = nil + @file = nil + + version = array[0] + @name = array[1] + @full_name = array[2] + @rw = array[3] + @visibility = array[4] + @comment = array[5] + @singleton = array[6] || false # MARSHAL_VERSION == 0 + # 7 handled below + @parent_name = array[8] + @parent_class = array[9] + @section_title = array[10] + + @file = RDoc::TopLevel.new array[7] if version > 1 + + @parent_name ||= @full_name.split('#', 2).first + end + + def pretty_print q # :nodoc: + q.group 2, "[#{self.class.name} #{full_name} #{rw} #{visibility}", "]" do + unless comment.empty? then + q.breakable + q.text "comment:" + q.breakable + q.pp @comment + end + end + end + + def to_s # :nodoc: + "#{definition} #{name} in: #{parent}" + end + + ## + # Attributes do not have token streams. + # + # An RDoc::Attr can show up in the method list in some situations (see + # Gem::ConfigFile) + + def token_stream # :nodoc: + end + +end + diff --git a/jni/ruby/lib/rdoc/class_module.rb b/jni/ruby/lib/rdoc/class_module.rb new file mode 100644 index 0000000..71566f0 --- /dev/null +++ b/jni/ruby/lib/rdoc/class_module.rb @@ -0,0 +1,799 @@ +## +# ClassModule is the base class for objects representing either a class or a +# module. + +class RDoc::ClassModule < RDoc::Context + + ## + # 1:: + # RDoc 3.7 + # * Added visibility, singleton and file to attributes + # * Added file to constants + # * Added file to includes + # * Added file to methods + # 2:: + # RDoc 3.13 + # * Added extends + # 3:: + # RDoc 4.0 + # * Added sections + # * Added in_files + # * Added parent name + # * Complete Constant dump + + MARSHAL_VERSION = 3 # :nodoc: + + ## + # Constants that are aliases for this class or module + + attr_accessor :constant_aliases + + ## + # Comment and the location it came from. Use #add_comment to add comments + + attr_accessor :comment_location + + attr_accessor :diagram # :nodoc: + + ## + # Class or module this constant is an alias for + + attr_accessor :is_alias_for + + ## + # Return a RDoc::ClassModule of class +class_type+ that is a copy + # of module +module+. Used to promote modules to classes. + #-- + # TODO move to RDoc::NormalClass (I think) + + def self.from_module class_type, mod + klass = class_type.new mod.name + + mod.comment_location.each do |comment, location| + klass.add_comment comment, location + end + + klass.parent = mod.parent + klass.section = mod.section + klass.viewer = mod.viewer + + klass.attributes.concat mod.attributes + klass.method_list.concat mod.method_list + klass.aliases.concat mod.aliases + klass.external_aliases.concat mod.external_aliases + klass.constants.concat mod.constants + klass.includes.concat mod.includes + klass.extends.concat mod.extends + + klass.methods_hash.update mod.methods_hash + klass.constants_hash.update mod.constants_hash + + klass.current_section = mod.current_section + klass.in_files.concat mod.in_files + klass.sections.concat mod.sections + klass.unmatched_alias_lists = mod.unmatched_alias_lists + klass.current_section = mod.current_section + klass.visibility = mod.visibility + + klass.classes_hash.update mod.classes_hash + klass.modules_hash.update mod.modules_hash + klass.metadata.update mod.metadata + + klass.document_self = mod.received_nodoc ? nil : mod.document_self + klass.document_children = mod.document_children + klass.force_documentation = mod.force_documentation + klass.done_documenting = mod.done_documenting + + # update the parent of all children + + (klass.attributes + + klass.method_list + + klass.aliases + + klass.external_aliases + + klass.constants + + klass.includes + + klass.extends + + klass.classes + + klass.modules).each do |obj| + obj.parent = klass + obj.full_name = nil + end + + klass + end + + ## + # Creates a new ClassModule with +name+ with optional +superclass+ + # + # This is a constructor for subclasses, and must never be called directly. + + def initialize(name, superclass = nil) + @constant_aliases = [] + @diagram = nil + @is_alias_for = nil + @name = name + @superclass = superclass + @comment_location = [] # [[comment, location]] + + super() + end + + ## + # Adds +comment+ to this ClassModule's list of comments at +location+. This + # method is preferred over #comment= since it allows ri data to be updated + # across multiple runs. + + def add_comment comment, location + return unless document_self + + original = comment + + comment = case comment + when RDoc::Comment then + comment.normalize + else + normalize_comment comment + end + + @comment_location.delete_if { |(_, l)| l == location } + + @comment_location << [comment, location] + + self.comment = original + end + + def add_things my_things, other_things # :nodoc: + other_things.each do |group, things| + my_things[group].each { |thing| yield false, thing } if + my_things.include? group + + things.each do |thing| + yield true, thing + end + end + end + + ## + # Ancestors list for this ClassModule: the list of included modules + # (classes will add their superclass if any). + # + # Returns the included classes or modules, not the includes + # themselves. The returned values are either String or + # RDoc::NormalModule instances (see RDoc::Include#module). + # + # The values are returned in reverse order of their inclusion, + # which is the order suitable for searching methods/attributes + # in the ancestors. The superclass, if any, comes last. + + def ancestors + includes.map { |i| i.module }.reverse + end + + def aref_prefix # :nodoc: + raise NotImplementedError, "missing aref_prefix for #{self.class}" + end + + ## + # HTML fragment reference for this module or class. See + # RDoc::NormalClass#aref and RDoc::NormalModule#aref + + def aref + "#{aref_prefix}-#{full_name}" + end + + ## + # Ancestors of this class or module only + + alias direct_ancestors ancestors + + ## + # Clears the comment. Used by the Ruby parser. + + def clear_comment + @comment = '' + end + + ## + # This method is deprecated, use #add_comment instead. + # + # Appends +comment+ to the current comment, but separated by a rule. Works + # more like +=. + + def comment= comment # :nodoc: + comment = case comment + when RDoc::Comment then + comment.normalize + else + normalize_comment comment + end + + comment = "#{@comment}\n---\n#{comment}" unless @comment.empty? + + super comment + end + + ## + # Prepares this ClassModule for use by a generator. + # + # See RDoc::Store#complete + + def complete min_visibility + update_aliases + remove_nodoc_children + update_includes + remove_invisible min_visibility + end + + ## + # Does this ClassModule or any of its methods have document_self set? + + def document_self_or_methods + document_self || method_list.any?{ |m| m.document_self } + end + + ## + # Does this class or module have a comment with content or is + # #received_nodoc true? + + def documented? + return true if @received_nodoc + return false if @comment_location.empty? + @comment_location.any? { |comment, _| not comment.empty? } + end + + ## + # Iterates the ancestors of this class or module for which an + # RDoc::ClassModule exists. + + def each_ancestor # :yields: module + return enum_for __method__ unless block_given? + + ancestors.each do |mod| + next if String === mod + next if self == mod + yield mod + end + end + + ## + # Looks for a symbol in the #ancestors. See Context#find_local_symbol. + + def find_ancestor_local_symbol symbol + each_ancestor do |m| + res = m.find_local_symbol(symbol) + return res if res + end + + nil + end + + ## + # Finds a class or module with +name+ in this namespace or its descendants + + def find_class_named name + return self if full_name == name + return self if @name == name + + @classes.values.find do |klass| + next if klass == self + klass.find_class_named name + end + end + + ## + # Return the fully qualified name of this class or module + + def full_name + @full_name ||= if RDoc::ClassModule === parent then + "#{parent.full_name}::#{@name}" + else + @name + end + end + + ## + # TODO: filter included items by #display? + + def marshal_dump # :nodoc: + attrs = attributes.sort.map do |attr| + next unless attr.display? + [ attr.name, attr.rw, + attr.visibility, attr.singleton, attr.file_name, + ] + end.compact + + method_types = methods_by_type.map do |type, visibilities| + visibilities = visibilities.map do |visibility, methods| + method_names = methods.map do |method| + next unless method.display? + [method.name, method.file_name] + end.compact + + [visibility, method_names.uniq] + end + + [type, visibilities] + end + + [ MARSHAL_VERSION, + @name, + full_name, + @superclass, + parse(@comment_location), + attrs, + constants.select { |constant| constant.display? }, + includes.map do |incl| + next unless incl.display? + [incl.name, parse(incl.comment), incl.file_name] + end.compact, + method_types, + extends.map do |ext| + next unless ext.display? + [ext.name, parse(ext.comment), ext.file_name] + end.compact, + @sections.values, + @in_files.map do |tl| + tl.relative_name + end, + parent.full_name, + parent.class, + ] + end + + def marshal_load array # :nodoc: + initialize_visibility + initialize_methods_etc + @current_section = nil + @document_self = true + @done_documenting = false + @parent = nil + @temporary_section = nil + @visibility = nil + @classes = {} + @modules = {} + + @name = array[1] + @full_name = array[2] + @superclass = array[3] + @comment = array[4] + + @comment_location = if RDoc::Markup::Document === @comment.parts.first then + @comment + else + RDoc::Markup::Document.new @comment + end + + array[5].each do |name, rw, visibility, singleton, file| + singleton ||= false + visibility ||= :public + + attr = RDoc::Attr.new nil, name, rw, nil, singleton + + add_attribute attr + attr.visibility = visibility + attr.record_location RDoc::TopLevel.new file + end + + array[6].each do |constant, comment, file| + case constant + when RDoc::Constant then + add_constant constant + else + constant = add_constant RDoc::Constant.new(constant, nil, comment) + constant.record_location RDoc::TopLevel.new file + end + end + + array[7].each do |name, comment, file| + incl = add_include RDoc::Include.new(name, comment) + incl.record_location RDoc::TopLevel.new file + end + + array[8].each do |type, visibilities| + visibilities.each do |visibility, methods| + @visibility = visibility + + methods.each do |name, file| + method = RDoc::AnyMethod.new nil, name + method.singleton = true if type == 'class' + method.record_location RDoc::TopLevel.new file + add_method method + end + end + end + + array[9].each do |name, comment, file| + ext = add_extend RDoc::Extend.new(name, comment) + ext.record_location RDoc::TopLevel.new file + end if array[9] # Support Marshal version 1 + + sections = (array[10] || []).map do |section| + [section.title, section] + end + + @sections = Hash[*sections.flatten] + @current_section = add_section nil + + @in_files = [] + + (array[11] || []).each do |filename| + record_location RDoc::TopLevel.new filename + end + + @parent_name = array[12] + @parent_class = array[13] + end + + ## + # Merges +class_module+ into this ClassModule. + # + # The data in +class_module+ is preferred over the receiver. + + def merge class_module + @parent = class_module.parent + @parent_name = class_module.parent_name + + other_document = parse class_module.comment_location + + if other_document then + document = parse @comment_location + + document = document.merge other_document + + @comment = @comment_location = document + end + + cm = class_module + other_files = cm.in_files + + merge_collections attributes, cm.attributes, other_files do |add, attr| + if add then + add_attribute attr + else + @attributes.delete attr + @methods_hash.delete attr.pretty_name + end + end + + merge_collections constants, cm.constants, other_files do |add, const| + if add then + add_constant const + else + @constants.delete const + @constants_hash.delete const.name + end + end + + merge_collections includes, cm.includes, other_files do |add, incl| + if add then + add_include incl + else + @includes.delete incl + end + end + + @includes.uniq! # clean up + + merge_collections extends, cm.extends, other_files do |add, ext| + if add then + add_extend ext + else + @extends.delete ext + end + end + + @extends.uniq! # clean up + + merge_collections method_list, cm.method_list, other_files do |add, meth| + if add then + add_method meth + else + @method_list.delete meth + @methods_hash.delete meth.pretty_name + end + end + + merge_sections cm + + self + end + + ## + # Merges collection +mine+ with +other+ preferring other. +other_files+ is + # used to help determine which items should be deleted. + # + # Yields whether the item should be added or removed (true or false) and the + # item to be added or removed. + # + # merge_collections things, other.things, other.in_files do |add, thing| + # if add then + # # add the thing + # else + # # remove the thing + # end + # end + + def merge_collections mine, other, other_files, &block # :nodoc: + my_things = mine. group_by { |thing| thing.file } + other_things = other.group_by { |thing| thing.file } + + remove_things my_things, other_files, &block + add_things my_things, other_things, &block + end + + ## + # Merges the comments in this ClassModule with the comments in the other + # ClassModule +cm+. + + def merge_sections cm # :nodoc: + my_sections = sections.group_by { |section| section.title } + other_sections = cm.sections.group_by { |section| section.title } + + other_files = cm.in_files + + remove_things my_sections, other_files do |_, section| + @sections.delete section.title + end + + other_sections.each do |group, sections| + if my_sections.include? group + my_sections[group].each do |my_section| + other_section = cm.sections_hash[group] + + my_comments = my_section.comments + other_comments = other_section.comments + + other_files = other_section.in_files + + merge_collections my_comments, other_comments, other_files do |add, comment| + if add then + my_section.add_comment comment + else + my_section.remove_comment comment + end + end + end + else + sections.each do |section| + add_section group, section.comments + end + end + end + end + + ## + # Does this object represent a module? + + def module? + false + end + + ## + # Allows overriding the initial name. + # + # Used for modules and classes that are constant aliases. + + def name= new_name + @name = new_name + end + + ## + # Parses +comment_location+ into an RDoc::Markup::Document composed of + # multiple RDoc::Markup::Documents with their file set. + + def parse comment_location + case comment_location + when String then + super + when Array then + docs = comment_location.map do |comment, location| + doc = super comment + doc.file = location + doc + end + + RDoc::Markup::Document.new(*docs) + when RDoc::Comment then + doc = super comment_location.text, comment_location.format + doc.file = comment_location.location + doc + when RDoc::Markup::Document then + return comment_location + else + raise ArgumentError, "unknown comment class #{comment_location.class}" + end + end + + ## + # Path to this class or module for use with HTML generator output. + + def path + http_url @store.rdoc.generator.class_dir + end + + ## + # Name to use to generate the url: + # modules and classes that are aliases for another + # module or class return the name of the latter. + + def name_for_path + is_alias_for ? is_alias_for.full_name : full_name + end + + ## + # Returns the classes and modules that are not constants + # aliasing another class or module. For use by formatters + # only (caches its result). + + def non_aliases + @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for } + end + + ## + # Updates the child modules or classes of class/module +parent+ by + # deleting the ones that have been removed from the documentation. + # + # +parent_hash+ is either parent.modules_hash or + # parent.classes_hash and +all_hash+ is ::all_modules_hash or + # ::all_classes_hash. + + def remove_nodoc_children + prefix = self.full_name + '::' + + modules_hash.each_key do |name| + full_name = prefix + name + modules_hash.delete name unless @store.modules_hash[full_name] + end + + classes_hash.each_key do |name| + full_name = prefix + name + classes_hash.delete name unless @store.classes_hash[full_name] + end + end + + def remove_things my_things, other_files # :nodoc: + my_things.delete_if do |file, things| + next false unless other_files.include? file + + things.each do |thing| + yield false, thing + end + + true + end + end + + ## + # Search record used by RDoc::Generator::JsonIndex + + def search_record + [ + name, + full_name, + full_name, + '', + path, + '', + snippet(@comment_location), + ] + end + + ## + # Sets the store for this class or module and its contained code objects. + + def store= store + super + + @attributes .each do |attr| attr.store = store end + @constants .each do |const| const.store = store end + @includes .each do |incl| incl.store = store end + @extends .each do |ext| ext.store = store end + @method_list.each do |meth| meth.store = store end + end + + ## + # Get the superclass of this class. Attempts to retrieve the superclass + # object, returns the name if it is not known. + + def superclass + @store.find_class_named(@superclass) || @superclass + end + + ## + # Set the superclass of this class to +superclass+ + + def superclass=(superclass) + raise NoMethodError, "#{full_name} is a module" if module? + @superclass = superclass + end + + def to_s # :nodoc: + if is_alias_for then + "#{self.class.name} #{self.full_name} -> #{is_alias_for}" + else + super + end + end + + ## + # 'module' or 'class' + + def type + module? ? 'module' : 'class' + end + + ## + # Updates the child modules & classes by replacing the ones that are + # aliases through a constant. + # + # The aliased module/class is replaced in the children and in + # RDoc::Store#modules_hash or RDoc::Store#classes_hash + # by a copy that has RDoc::ClassModule#is_alias_for set to + # the aliased module/class, and this copy is added to #aliases + # of the aliased module/class. + # + # Formatters can use the #non_aliases method to retrieve children that + # are not aliases, for instance to list the namespace content, since + # the aliased modules are included in the constants of the class/module, + # that are listed separately. + + def update_aliases + constants.each do |const| + next unless cm = const.is_alias_for + cm_alias = cm.dup + cm_alias.name = const.name + + # Don't move top-level aliases under Object, they look ugly there + unless RDoc::TopLevel === cm_alias.parent then + cm_alias.parent = self + cm_alias.full_name = nil # force update for new parent + end + + cm_alias.aliases.clear + cm_alias.is_alias_for = cm + + if cm.module? then + @store.modules_hash[cm_alias.full_name] = cm_alias + modules_hash[const.name] = cm_alias + else + @store.classes_hash[cm_alias.full_name] = cm_alias + classes_hash[const.name] = cm_alias + end + + cm.aliases << cm_alias + end + end + + ## + # Deletes from #includes those whose module has been removed from the + # documentation. + #-- + # FIXME: includes are not reliably removed, see _possible_bug test case + + def update_includes + includes.reject! do |include| + mod = include.module + !(String === mod) && @store.modules_hash[mod.full_name].nil? + end + + includes.uniq! + end + + ## + # Deletes from #extends those whose module has been removed from the + # documentation. + #-- + # FIXME: like update_includes, extends are not reliably removed + + def update_extends + extends.reject! do |ext| + mod = ext.module + + !(String === mod) && @store.modules_hash[mod.full_name].nil? + end + + extends.uniq! + end + +end + diff --git a/jni/ruby/lib/rdoc/code_object.rb b/jni/ruby/lib/rdoc/code_object.rb new file mode 100644 index 0000000..4620fa5 --- /dev/null +++ b/jni/ruby/lib/rdoc/code_object.rb @@ -0,0 +1,429 @@ +## +# Base class for the RDoc code tree. +# +# We contain the common stuff for contexts (which are containers) and other +# elements (methods, attributes and so on) +# +# Here's the tree of the CodeObject subclasses: +# +# * RDoc::Context +# * RDoc::TopLevel +# * RDoc::ClassModule +# * RDoc::AnonClass (never used so far) +# * RDoc::NormalClass +# * RDoc::NormalModule +# * RDoc::SingleClass +# * RDoc::MethodAttr +# * RDoc::Attr +# * RDoc::AnyMethod +# * RDoc::GhostMethod +# * RDoc::MetaMethod +# * RDoc::Alias +# * RDoc::Constant +# * RDoc::Mixin +# * RDoc::Require +# * RDoc::Include + +class RDoc::CodeObject + + include RDoc::Text + + ## + # Our comment + + attr_reader :comment + + ## + # Do we document our children? + + attr_reader :document_children + + ## + # Do we document ourselves? + + attr_reader :document_self + + ## + # Are we done documenting (ie, did we come across a :enddoc:)? + + attr_reader :done_documenting + + ## + # Which file this code object was defined in + + attr_reader :file + + ## + # Force documentation of this CodeObject + + attr_reader :force_documentation + + ## + # Line in #file where this CodeObject was defined + + attr_accessor :line + + ## + # Hash of arbitrary metadata for this CodeObject + + attr_reader :metadata + + ## + # Offset in #file where this CodeObject was defined + #-- + # TODO character or byte? + + attr_accessor :offset + + ## + # Sets the parent CodeObject + + attr_writer :parent + + ## + # Did we ever receive a +:nodoc:+ directive? + + attr_reader :received_nodoc + + ## + # Set the section this CodeObject is in + + attr_writer :section + + ## + # The RDoc::Store for this object. + + attr_reader :store + + ## + # We are the model of the code, but we know that at some point we will be + # worked on by viewers. By implementing the Viewable protocol, viewers can + # associated themselves with these objects. + + attr_accessor :viewer + + ## + # Creates a new CodeObject that will document itself and its children + + def initialize + @metadata = {} + @comment = '' + @parent = nil + @parent_name = nil # for loading + @parent_class = nil # for loading + @section = nil + @section_title = nil # for loading + @file = nil + @full_name = nil + @store = nil + @track_visibility = true + + initialize_visibility + end + + ## + # Initializes state for visibility of this CodeObject and its children. + + def initialize_visibility # :nodoc: + @document_children = true + @document_self = true + @done_documenting = false + @force_documentation = false + @received_nodoc = false + @ignored = false + @suppressed = false + @track_visibility = true + end + + ## + # Replaces our comment with +comment+, unless it is empty. + + def comment=(comment) + @comment = case comment + when NilClass then '' + when RDoc::Markup::Document then comment + when RDoc::Comment then comment.normalize + else + if comment and not comment.empty? then + normalize_comment comment + else + # HACK correct fix is to have #initialize create @comment + # with the correct encoding + if String === @comment and + Object.const_defined? :Encoding and @comment.empty? then + @comment.force_encoding comment.encoding + end + @comment + end + end + end + + ## + # Should this CodeObject be displayed in output? + # + # A code object should be displayed if: + # + # * The item didn't have a nodoc or wasn't in a container that had nodoc + # * The item wasn't ignored + # * The item has documentation and was not suppressed + + def display? + @document_self and not @ignored and + (documented? or not @suppressed) + end + + ## + # Enables or disables documentation of this CodeObject's children unless it + # has been turned off by :enddoc: + + def document_children=(document_children) + return unless @track_visibility + + @document_children = document_children unless @done_documenting + end + + ## + # Enables or disables documentation of this CodeObject unless it has been + # turned off by :enddoc:. If the argument is +nil+ it means the + # documentation is turned off by +:nodoc:+. + + def document_self=(document_self) + return unless @track_visibility + return if @done_documenting + + @document_self = document_self + @received_nodoc = true if document_self.nil? + end + + ## + # Does this object have a comment with content or is #received_nodoc true? + + def documented? + @received_nodoc or !@comment.empty? + end + + ## + # Turns documentation on/off, and turns on/off #document_self + # and #document_children. + # + # Once documentation has been turned off (by +:enddoc:+), + # the object will refuse to turn #document_self or + # #document_children on, so +:doc:+ and +:start_doc:+ directives + # will have no effect in the current file. + + def done_documenting=(value) + return unless @track_visibility + @done_documenting = value + @document_self = !value + @document_children = @document_self + end + + ## + # Yields each parent of this CodeObject. See also + # RDoc::ClassModule#each_ancestor + + def each_parent + code_object = self + + while code_object = code_object.parent do + yield code_object + end + + self + end + + ## + # File name where this CodeObject was found. + # + # See also RDoc::Context#in_files + + def file_name + return unless @file + + @file.absolute_name + end + + ## + # Force the documentation of this object unless documentation + # has been turned off by :enddoc: + #-- + # HACK untested, was assigning to an ivar + + def force_documentation=(value) + @force_documentation = value unless @done_documenting + end + + ## + # Sets the full_name overriding any computed full name. + # + # Set to +nil+ to clear RDoc's cached value + + def full_name= full_name + @full_name = full_name + end + + ## + # Use this to ignore a CodeObject and all its children until found again + # (#record_location is called). An ignored item will not be displayed in + # documentation. + # + # See github issue #55 + # + # The ignored status is temporary in order to allow implementation details + # to be hidden. At the end of processing a file RDoc allows all classes + # and modules to add new documentation to previously created classes. + # + # If a class was ignored (via stopdoc) then reopened later with additional + # documentation it should be displayed. If a class was ignored and never + # reopened it should not be displayed. The ignore flag allows this to + # occur. + + def ignore + return unless @track_visibility + + @ignored = true + + stop_doc + end + + ## + # Has this class been ignored? + # + # See also #ignore + + def ignored? + @ignored + end + + ## + # The options instance from the store this CodeObject is attached to, or a + # default options instance if the CodeObject is not attached. + # + # This is used by Text#snippet + + def options + if @store and @store.rdoc then + @store.rdoc.options + else + RDoc::Options.new + end + end + + ## + # Our parent CodeObject. The parent may be missing for classes loaded from + # legacy RI data stores. + + def parent + return @parent if @parent + return nil unless @parent_name + + if @parent_class == RDoc::TopLevel then + @parent = @store.add_file @parent_name + else + @parent = @store.find_class_or_module @parent_name + + return @parent if @parent + + begin + @parent = @store.load_class @parent_name + rescue RDoc::Store::MissingFileError + nil + end + end + end + + ## + # File name of our parent + + def parent_file_name + @parent ? @parent.base_name : '(unknown)' + end + + ## + # Name of our parent + + def parent_name + @parent ? @parent.full_name : '(unknown)' + end + + ## + # Records the RDoc::TopLevel (file) where this code object was defined + + def record_location top_level + @ignored = false + @suppressed = false + @file = top_level + end + + ## + # The section this CodeObject is in. Sections allow grouping of constants, + # attributes and methods inside a class or module. + + def section + return @section if @section + + @section = parent.add_section @section_title if parent + end + + ## + # Enable capture of documentation unless documentation has been + # turned off by :enddoc: + + def start_doc + return if @done_documenting + + @document_self = true + @document_children = true + @ignored = false + @suppressed = false + end + + ## + # Disable capture of documentation + + def stop_doc + return unless @track_visibility + + @document_self = false + @document_children = false + end + + ## + # Sets the +store+ that contains this CodeObject + + def store= store + @store = store + + return unless @track_visibility + + if :nodoc == options.visibility then + initialize_visibility + @track_visibility = false + end + end + + ## + # Use this to suppress a CodeObject and all its children until the next file + # it is seen in or documentation is discovered. A suppressed item with + # documentation will be displayed while an ignored item with documentation + # may not be displayed. + + def suppress + return unless @track_visibility + + @suppressed = true + + stop_doc + end + + ## + # Has this class been suppressed? + # + # See also #suppress + + def suppressed? + @suppressed + end + +end + diff --git a/jni/ruby/lib/rdoc/code_objects.rb b/jni/ruby/lib/rdoc/code_objects.rb new file mode 100644 index 0000000..f1a626c --- /dev/null +++ b/jni/ruby/lib/rdoc/code_objects.rb @@ -0,0 +1,5 @@ +# This file was used to load all the RDoc::CodeObject subclasses at once. Now +# autoload handles this. + +require 'rdoc' + diff --git a/jni/ruby/lib/rdoc/comment.rb b/jni/ruby/lib/rdoc/comment.rb new file mode 100644 index 0000000..33ced18 --- /dev/null +++ b/jni/ruby/lib/rdoc/comment.rb @@ -0,0 +1,229 @@ +## +# A comment holds the text comment for a RDoc::CodeObject and provides a +# unified way of cleaning it up and parsing it into an RDoc::Markup::Document. +# +# Each comment may have a different markup format set by #format=. By default +# 'rdoc' is used. The :markup: directive tells RDoc which format to use. +# +# See RDoc::Markup@Other+directives for instructions on adding an alternate +# format. + +class RDoc::Comment + + include RDoc::Text + + ## + # The format of this comment. Defaults to RDoc::Markup + + attr_reader :format + + ## + # The RDoc::TopLevel this comment was found in + + attr_accessor :location + + ## + # For duck-typing when merging classes at load time + + alias file location # :nodoc: + + ## + # The text for this comment + + attr_reader :text + + ## + # Overrides the content returned by #parse. Use when there is no #text + # source for this comment + + attr_writer :document + + ## + # Creates a new comment with +text+ that is found in the RDoc::TopLevel + # +location+. + + def initialize text = nil, location = nil + @location = location + @text = text + + @document = nil + @format = 'rdoc' + @normalized = false + end + + ## + #-- + # TODO deep copy @document + + def initialize_copy copy # :nodoc: + @text = copy.text.dup + end + + def == other # :nodoc: + self.class === other and + other.text == @text and other.location == @location + end + + ## + # Look for a 'call-seq' in the comment to override the normal parameter + # handling. The :call-seq: is indented from the baseline. All lines of the + # same indentation level and prefix are consumed. + # + # For example, all of the following will be used as the :call-seq: + # + # # :call-seq: + # # ARGF.readlines(sep=$/) -> array + # # ARGF.readlines(limit) -> array + # # ARGF.readlines(sep, limit) -> array + # # + # # ARGF.to_a(sep=$/) -> array + # # ARGF.to_a(limit) -> array + # # ARGF.to_a(sep, limit) -> array + + def extract_call_seq method + # we must handle situations like the above followed by an unindented first + # comment. The difficulty is to make sure not to match lines starting + # with ARGF at the same indent, but that are after the first description + # paragraph. + if @text =~ /^\s*:?call-seq:(.*?(?:\S).*?)^\s*$/m then + all_start, all_stop = $~.offset(0) + seq_start, seq_stop = $~.offset(1) + + # we get the following lines that start with the leading word at the + # same indent, even if they have blank lines before + if $1 =~ /(^\s*\n)+^(\s*\w+)/m then + leading = $2 # ' * ARGF' in the example above + re = %r% + \A( + (^\s*\n)+ + (^#{Regexp.escape leading}.*?\n)+ + )+ + ^\s*$ + %xm + + if @text[seq_stop..-1] =~ re then + all_stop = seq_stop + $~.offset(0).last + seq_stop = seq_stop + $~.offset(1).last + end + end + + seq = @text[seq_start..seq_stop] + seq.gsub!(/^\s*(\S|\n)/m, '\1') + @text.slice! all_start...all_stop + + method.call_seq = seq.chomp + + elsif @text.sub!(/^\s*:?call-seq:(.*?)(^\s*$|\z)/m, '') then + seq = $1 + seq.gsub!(/^\s*/, '') + method.call_seq = seq + end + + method + end + + ## + # A comment is empty if its text String is empty. + + def empty? + @text.empty? + end + + ## + # HACK dubious + + def force_encoding encoding + @text.force_encoding encoding + end + + ## + # Sets the format of this comment and resets any parsed document + + def format= format + @format = format + @document = nil + end + + def inspect # :nodoc: + location = @location ? @location.relative_name : '(unknown)' + + "#<%s:%x %s %p>" % [self.class, object_id, location, @text] + end + + ## + # Normalizes the text. See RDoc::Text#normalize_comment for details + + def normalize + return self unless @text + return self if @normalized # TODO eliminate duplicate normalization + + @text = normalize_comment @text + + @normalized = true + + self + end + + ## + # Was this text normalized? + + def normalized? # :nodoc: + @normalized + end + + ## + # Parses the comment into an RDoc::Markup::Document. The parsed document is + # cached until the text is changed. + + def parse + return @document if @document + + @document = super @text, @format + @document.file = @location + @document + end + + ## + # Removes private sections from this comment. Private sections are flush to + # the comment marker and start with -- and end with ++. + # For C-style comments, a private marker may not start at the opening of the + # comment. + # + # /* + # *-- + # * private + # *++ + # * public + # */ + + def remove_private + # Workaround for gsub encoding for Ruby 1.9.2 and earlier + empty = '' + empty.force_encoding @text.encoding if Object.const_defined? :Encoding + + @text = @text.gsub(%r%^\s*([#*]?)--.*?^\s*(\1)\+\+\n?%m, empty) + @text = @text.sub(%r%^\s*[#*]?--.*%m, '') + end + + ## + # Replaces this comment's text with +text+ and resets the parsed document. + # + # An error is raised if the comment contains a document but no text. + + def text= text + raise RDoc::Error, 'replacing document-only comment is not allowed' if + @text.nil? and @document + + @document = nil + @text = text + end + + ## + # Returns true if this comment is in TomDoc format. + + def tomdoc? + @format == 'tomdoc' + end + +end + diff --git a/jni/ruby/lib/rdoc/constant.rb b/jni/ruby/lib/rdoc/constant.rb new file mode 100644 index 0000000..97985cb --- /dev/null +++ b/jni/ruby/lib/rdoc/constant.rb @@ -0,0 +1,186 @@ +## +# A constant + +class RDoc::Constant < RDoc::CodeObject + + MARSHAL_VERSION = 0 # :nodoc: + + ## + # Sets the module or class this is constant is an alias for. + + attr_writer :is_alias_for + + ## + # The constant's name + + attr_accessor :name + + ## + # The constant's value + + attr_accessor :value + + ## + # The constant's visibility + + attr_accessor :visibility + + ## + # Creates a new constant with +name+, +value+ and +comment+ + + def initialize(name, value, comment) + super() + + @name = name + @value = value + + @is_alias_for = nil + @visibility = nil + + self.comment = comment + end + + ## + # Constants are ordered by name + + def <=> other + return unless self.class === other + + [parent_name, name] <=> [other.parent_name, other.name] + end + + ## + # Constants are equal when their #parent and #name is the same + + def == other + self.class == other.class and + @parent == other.parent and + @name == other.name + end + + ## + # A constant is documented if it has a comment, or is an alias + # for a documented class or module. + + def documented? + return true if super + return false unless @is_alias_for + case @is_alias_for + when String then + found = @store.find_class_or_module @is_alias_for + return false unless found + @is_alias_for = found + end + @is_alias_for.documented? + end + + ## + # Full constant name including namespace + + def full_name + @full_name ||= "#{parent_name}::#{@name}" + end + + ## + # The module or class this constant is an alias for + + def is_alias_for + case @is_alias_for + when String then + found = @store.find_class_or_module @is_alias_for + @is_alias_for = found if found + @is_alias_for + else + @is_alias_for + end + end + + def inspect # :nodoc: + "#<%s:0x%x %s::%s>" % [ + self.class, object_id, + parent_name, @name, + ] + end + + ## + # Dumps this Constant for use by ri. See also #marshal_load + + def marshal_dump + alias_name = case found = is_alias_for + when RDoc::CodeObject then found.full_name + else found + end + + [ MARSHAL_VERSION, + @name, + full_name, + @visibility, + alias_name, + parse(@comment), + @file.relative_name, + parent.name, + parent.class, + section.title, + ] + end + + ## + # Loads this Constant from +array+. For a loaded Constant the following + # methods will return cached values: + # + # * #full_name + # * #parent_name + + def marshal_load array + initialize array[1], nil, array[5] + + @full_name = array[2] + @visibility = array[3] + @is_alias_for = array[4] + # 5 handled above + # 6 handled below + @parent_name = array[7] + @parent_class = array[8] + @section_title = array[9] + + @file = RDoc::TopLevel.new array[6] + end + + ## + # Path to this constant for use with HTML generator output. + + def path + "#{@parent.path}##{@name}" + end + + def pretty_print q # :nodoc: + q.group 2, "[#{self.class.name} #{full_name}", "]" do + unless comment.empty? then + q.breakable + q.text "comment:" + q.breakable + q.pp @comment + end + end + end + + ## + # Sets the store for this class or module and its contained code objects. + + def store= store + super + + @file = @store.add_file @file.full_name if @file + end + + def to_s # :nodoc: + parent_name = parent ? parent.full_name : '(unknown)' + if is_alias_for + "constant #{parent_name}::#@name -> #{is_alias_for}" + else + "constant #{parent_name}::#@name" + end + end + +end + diff --git a/jni/ruby/lib/rdoc/context.rb b/jni/ruby/lib/rdoc/context.rb new file mode 100644 index 0000000..5eb86dd --- /dev/null +++ b/jni/ruby/lib/rdoc/context.rb @@ -0,0 +1,1211 @@ +require 'cgi' + +## +# A Context is something that can hold modules, classes, methods, attributes, +# aliases, requires, and includes. Classes, modules, and files are all +# Contexts. + +class RDoc::Context < RDoc::CodeObject + + include Comparable + + ## + # Types of methods + + TYPES = %w[class instance] + + ## + # If a context has these titles it will be sorted in this order. + + TOMDOC_TITLES = [nil, 'Public', 'Internal', 'Deprecated'] # :nodoc: + TOMDOC_TITLES_SORT = TOMDOC_TITLES.sort_by { |title| title.to_s } # :nodoc: + + ## + # Class/module aliases + + attr_reader :aliases + + ## + # All attr* methods + + attr_reader :attributes + + ## + # Block params to be used in the next MethodAttr parsed under this context + + attr_accessor :block_params + + ## + # Constants defined + + attr_reader :constants + + ## + # Sets the current documentation section of documentation + + attr_writer :current_section + + ## + # Files this context is found in + + attr_reader :in_files + + ## + # Modules this context includes + + attr_reader :includes + + ## + # Modules this context is extended with + + attr_reader :extends + + ## + # Methods defined in this context + + attr_reader :method_list + + ## + # Name of this class excluding namespace. See also full_name + + attr_reader :name + + ## + # Files this context requires + + attr_reader :requires + + ## + # Use this section for the next method, attribute or constant added. + + attr_accessor :temporary_section + + ## + # Hash old_name => [aliases], for aliases + # that haven't (yet) been resolved to a method/attribute. + # (Not to be confused with the aliases of the context.) + + attr_accessor :unmatched_alias_lists + + ## + # Aliases that could not be resolved. + + attr_reader :external_aliases + + ## + # Current visibility of this context + + attr_accessor :visibility + + ## + # Hash of registered methods. Attributes are also registered here, + # twice if they are RW. + + attr_reader :methods_hash + + ## + # Params to be used in the next MethodAttr parsed under this context + + attr_accessor :params + + ## + # Hash of registered constants. + + attr_reader :constants_hash + + ## + # Creates an unnamed empty context with public current visibility + + def initialize + super + + @in_files = [] + + @name ||= "unknown" + @parent = nil + @visibility = :public + + @current_section = Section.new self, nil, nil + @sections = { nil => @current_section } + @temporary_section = nil + + @classes = {} + @modules = {} + + initialize_methods_etc + end + + ## + # Sets the defaults for methods and so-forth + + def initialize_methods_etc + @method_list = [] + @attributes = [] + @aliases = [] + @requires = [] + @includes = [] + @extends = [] + @constants = [] + @external_aliases = [] + + # This Hash maps a method name to a list of unmatched aliases (aliases of + # a method not yet encountered). + @unmatched_alias_lists = {} + + @methods_hash = {} + @constants_hash = {} + + @params = nil + + @store ||= nil + end + + ## + # Contexts are sorted by full_name + + def <=>(other) + return nil unless RDoc::CodeObject === other + + full_name <=> other.full_name + end + + ## + # Adds an item of type +klass+ with the given +name+ and +comment+ to the + # context. + # + # Currently only RDoc::Extend and RDoc::Include are supported. + + def add klass, name, comment + if RDoc::Extend == klass then + ext = RDoc::Extend.new name, comment + add_extend ext + elsif RDoc::Include == klass then + incl = RDoc::Include.new name, comment + add_include incl + else + raise NotImplementedError, "adding a #{klass} is not implemented" + end + end + + ## + # Adds +an_alias+ that is automatically resolved + + def add_alias an_alias + return an_alias unless @document_self + + method_attr = find_method(an_alias.old_name, an_alias.singleton) || + find_attribute(an_alias.old_name, an_alias.singleton) + + if method_attr then + method_attr.add_alias an_alias, self + else + add_to @external_aliases, an_alias + unmatched_alias_list = + @unmatched_alias_lists[an_alias.pretty_old_name] ||= [] + unmatched_alias_list.push an_alias + end + + an_alias + end + + ## + # Adds +attribute+ if not already there. If it is (as method(s) or attribute), + # updates the comment if it was empty. + # + # The attribute is registered only if it defines a new method. + # For instance, attr_reader :foo will not be registered + # if method +foo+ exists, but attr_accessor :foo will be registered + # if method +foo+ exists, but foo= does not. + + def add_attribute attribute + return attribute unless @document_self + + # mainly to check for redefinition of an attribute as a method + # TODO find a policy for 'attr_reader :foo' + 'def foo=()' + register = false + + key = nil + + if attribute.rw.index 'R' then + key = attribute.pretty_name + known = @methods_hash[key] + + if known then + known.comment = attribute.comment if known.comment.empty? + elsif registered = @methods_hash[attribute.pretty_name << '='] and + RDoc::Attr === registered then + registered.rw = 'RW' + else + @methods_hash[key] = attribute + register = true + end + end + + if attribute.rw.index 'W' then + key = attribute.pretty_name << '=' + known = @methods_hash[key] + + if known then + known.comment = attribute.comment if known.comment.empty? + elsif registered = @methods_hash[attribute.pretty_name] and + RDoc::Attr === registered then + registered.rw = 'RW' + else + @methods_hash[key] = attribute + register = true + end + end + + if register then + attribute.visibility = @visibility + add_to @attributes, attribute + resolve_aliases attribute + end + + attribute + end + + ## + # Adds a class named +given_name+ with +superclass+. + # + # Both +given_name+ and +superclass+ may contain '::', and are + # interpreted relative to the +self+ context. This allows handling correctly + # examples like these: + # class RDoc::Gauntlet < Gauntlet + # module Mod + # class Object # implies < ::Object + # class SubObject < Object # this is _not_ ::Object + # + # Given class Container::Item RDoc assumes +Container+ is a module + # unless it later sees class Container. +add_class+ automatically + # upgrades +given_name+ to a class in this case. + + def add_class class_type, given_name, superclass = '::Object' + # superclass +nil+ is passed by the C parser in the following cases: + # - registering Object in 1.8 (correct) + # - registering BasicObject in 1.9 (correct) + # - registering RubyVM in 1.9 in iseq.c (incorrect: < Object in vm.c) + # + # If we later find a superclass for a registered class with a nil + # superclass, we must honor it. + + # find the name & enclosing context + if given_name =~ /^:+(\w+)$/ then + full_name = $1 + enclosing = top_level + name = full_name.split(/:+/).last + else + full_name = child_name given_name + + if full_name =~ /^(.+)::(\w+)$/ then + name = $2 + ename = $1 + enclosing = @store.classes_hash[ename] || @store.modules_hash[ename] + # HACK: crashes in actionpack/lib/action_view/helpers/form_helper.rb (metaprogramming) + unless enclosing then + # try the given name at top level (will work for the above example) + enclosing = @store.classes_hash[given_name] || + @store.modules_hash[given_name] + return enclosing if enclosing + # not found: create the parent(s) + names = ename.split('::') + enclosing = self + names.each do |n| + enclosing = enclosing.classes_hash[n] || + enclosing.modules_hash[n] || + enclosing.add_module(RDoc::NormalModule, n) + end + end + else + name = full_name + enclosing = self + end + end + + # fix up superclass + if full_name == 'BasicObject' then + superclass = nil + elsif full_name == 'Object' then + superclass = defined?(::BasicObject) ? '::BasicObject' : nil + end + + # find the superclass full name + if superclass then + if superclass =~ /^:+/ then + superclass = $' #' + else + if superclass =~ /^(\w+):+(.+)$/ then + suffix = $2 + mod = find_module_named($1) + superclass = mod.full_name + '::' + suffix if mod + else + mod = find_module_named(superclass) + superclass = mod.full_name if mod + end + end + + # did we believe it was a module? + mod = @store.modules_hash.delete superclass + + upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod + + # e.g., Object < Object + superclass = nil if superclass == full_name + end + + klass = @store.classes_hash[full_name] + + if klass then + # if TopLevel, it may not be registered in the classes: + enclosing.classes_hash[name] = klass + + # update the superclass if needed + if superclass then + existing = klass.superclass + existing = existing.full_name unless existing.is_a?(String) if existing + if existing.nil? || + (existing == 'Object' && superclass != 'Object') then + klass.superclass = superclass + end + end + else + # this is a new class + mod = @store.modules_hash.delete full_name + + if mod then + klass = upgrade_to_class mod, RDoc::NormalClass, enclosing + + klass.superclass = superclass unless superclass.nil? + else + klass = class_type.new name, superclass + + enclosing.add_class_or_module(klass, enclosing.classes_hash, + @store.classes_hash) + end + end + + klass.parent = self + + klass + end + + ## + # Adds the class or module +mod+ to the modules or + # classes Hash +self_hash+, and to +all_hash+ (either + # TopLevel::modules_hash or TopLevel::classes_hash), + # unless #done_documenting is +true+. Sets the #parent of +mod+ + # to +self+, and its #section to #current_section. Returns +mod+. + + def add_class_or_module mod, self_hash, all_hash + mod.section = current_section # TODO declaring context? something is + # wrong here... + mod.parent = self + mod.store = @store + + unless @done_documenting then + self_hash[mod.name] = mod + # this must be done AFTER adding mod to its parent, so that the full + # name is correct: + all_hash[mod.full_name] = mod + end + + mod + end + + ## + # Adds +constant+ if not already there. If it is, updates the comment, + # value and/or is_alias_for of the known constant if they were empty/nil. + + def add_constant constant + return constant unless @document_self + + # HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code) + # (this is a #ifdef: should be handled by the C parser) + known = @constants_hash[constant.name] + + if known then + known.comment = constant.comment if known.comment.empty? + + known.value = constant.value if + known.value.nil? or known.value.strip.empty? + + known.is_alias_for ||= constant.is_alias_for + else + @constants_hash[constant.name] = constant + add_to @constants, constant + end + + constant + end + + ## + # Adds included module +include+ which should be an RDoc::Include + + def add_include include + add_to @includes, include + + include + end + + ## + # Adds extension module +ext+ which should be an RDoc::Extend + + def add_extend ext + add_to @extends, ext + + ext + end + + ## + # Adds +method+ if not already there. If it is (as method or attribute), + # updates the comment if it was empty. + + def add_method method + return method unless @document_self + + # HACK: avoid duplicate 'new' in io.c & struct.c (1.8.7 source code) + key = method.pretty_name + known = @methods_hash[key] + + if known then + if @store then # otherwise we are loading + known.comment = method.comment if known.comment.empty? + previously = ", previously in #{known.file}" unless + method.file == known.file + @store.rdoc.options.warn \ + "Duplicate method #{known.full_name} in #{method.file}#{previously}" + end + else + @methods_hash[key] = method + method.visibility = @visibility + add_to @method_list, method + resolve_aliases method + end + + method + end + + ## + # Adds a module named +name+. If RDoc already knows +name+ is a class then + # that class is returned instead. See also #add_class. + + def add_module(class_type, name) + mod = @classes[name] || @modules[name] + return mod if mod + + full_name = child_name name + mod = @store.modules_hash[full_name] || class_type.new(name) + + add_class_or_module mod, @modules, @store.modules_hash + end + + ## + # Adds an alias from +from+ (a class or module) to +name+ which was defined + # in +file+. + + def add_module_alias from, name, file + return from if @done_documenting + + to_name = child_name name + + # if we already know this name, don't register an alias: + # see the metaprogramming in lib/active_support/basic_object.rb, + # where we already know BasicObject is a class when we find + # BasicObject = BlankSlate + return from if @store.find_class_or_module to_name + + to = from.dup + to.name = name + to.full_name = nil + + if to.module? then + @store.modules_hash[to_name] = to + @modules[name] = to + else + @store.classes_hash[to_name] = to + @classes[name] = to + end + + # Registers a constant for this alias. The constant value and comment + # will be updated later, when the Ruby parser adds the constant + const = RDoc::Constant.new name, nil, to.comment + const.record_location file + const.is_alias_for = from + add_constant const + + to + end + + ## + # Adds +require+ to this context's top level + + def add_require(require) + return require unless @document_self + + if RDoc::TopLevel === self then + add_to @requires, require + else + parent.add_require require + end + end + + ## + # Returns a section with +title+, creating it if it doesn't already exist. + # +comment+ will be appended to the section's comment. + # + # A section with a +title+ of +nil+ will return the default section. + # + # See also RDoc::Context::Section + + def add_section title, comment = nil + if section = @sections[title] then + section.add_comment comment if comment + else + section = Section.new self, title, comment + @sections[title] = section + end + + section + end + + ## + # Adds +thing+ to the collection +array+ + + def add_to array, thing + array << thing if @document_self + + thing.parent = self + thing.store = @store if @store + thing.section = current_section + end + + ## + # Is there any content? + # + # This means any of: comment, aliases, methods, attributes, external + # aliases, require, constant. + # + # Includes and extends are also checked unless includes == false. + + def any_content(includes = true) + @any_content ||= !( + @comment.empty? && + @method_list.empty? && + @attributes.empty? && + @aliases.empty? && + @external_aliases.empty? && + @requires.empty? && + @constants.empty? + ) + @any_content || (includes && !(@includes + @extends).empty? ) + end + + ## + # Creates the full name for a child with +name+ + + def child_name name + if name =~ /^:+/ + $' #' + elsif RDoc::TopLevel === self then + name + else + "#{self.full_name}::#{name}" + end + end + + ## + # Class attributes + + def class_attributes + @class_attributes ||= attributes.select { |a| a.singleton } + end + + ## + # Class methods + + def class_method_list + @class_method_list ||= method_list.select { |a| a.singleton } + end + + ## + # Array of classes in this context + + def classes + @classes.values + end + + ## + # All classes and modules in this namespace + + def classes_and_modules + classes + modules + end + + ## + # Hash of classes keyed by class name + + def classes_hash + @classes + end + + ## + # The current documentation section that new items will be added to. If + # temporary_section is available it will be used. + + def current_section + if section = @temporary_section then + @temporary_section = nil + else + section = @current_section + end + + section + end + + ## + # Is part of this thing was defined in +file+? + + def defined_in?(file) + @in_files.include?(file) + end + + def display(method_attr) # :nodoc: + if method_attr.is_a? RDoc::Attr + "#{method_attr.definition} #{method_attr.pretty_name}" + else + "method #{method_attr.pretty_name}" + end + end + + ## + # Iterator for ancestors for duck-typing. Does nothing. See + # RDoc::ClassModule#each_ancestor. + # + # This method exists to make it easy to work with Context subclasses that + # aren't part of RDoc. + + def each_ancestor # :nodoc: + end + + ## + # Iterator for attributes + + def each_attribute # :yields: attribute + @attributes.each { |a| yield a } + end + + ## + # Iterator for classes and modules + + def each_classmodule(&block) # :yields: module + classes_and_modules.sort.each(&block) + end + + ## + # Iterator for constants + + def each_constant # :yields: constant + @constants.each {|c| yield c} + end + + ## + # Iterator for included modules + + def each_include # :yields: include + @includes.each do |i| yield i end + end + + ## + # Iterator for extension modules + + def each_extend # :yields: extend + @extends.each do |e| yield e end + end + + ## + # Iterator for methods + + def each_method # :yields: method + return enum_for __method__ unless block_given? + + @method_list.sort.each { |m| yield m } + end + + ## + # Iterator for each section's contents sorted by title. The +section+, the + # section's +constants+ and the sections +attributes+ are yielded. The + # +constants+ and +attributes+ collections are sorted. + # + # To retrieve methods in a section use #methods_by_type with the optional + # +section+ parameter. + # + # NOTE: Do not edit collections yielded by this method + + def each_section # :yields: section, constants, attributes + return enum_for __method__ unless block_given? + + constants = @constants.group_by do |constant| constant.section end + attributes = @attributes.group_by do |attribute| attribute.section end + + constants.default = [] + attributes.default = [] + + sort_sections.each do |section| + yield section, constants[section].sort, attributes[section].sort + end + end + + ## + # Finds an attribute +name+ with singleton value +singleton+. + + def find_attribute(name, singleton) + name = $1 if name =~ /^(.*)=$/ + @attributes.find { |a| a.name == name && a.singleton == singleton } + end + + ## + # Finds an attribute with +name+ in this context + + def find_attribute_named(name) + case name + when /\A#/ then + find_attribute name[1..-1], false + when /\A::/ then + find_attribute name[2..-1], true + else + @attributes.find { |a| a.name == name } + end + end + + ## + # Finds a class method with +name+ in this context + + def find_class_method_named(name) + @method_list.find { |meth| meth.singleton && meth.name == name } + end + + ## + # Finds a constant with +name+ in this context + + def find_constant_named(name) + @constants.find {|m| m.name == name} + end + + ## + # Find a module at a higher scope + + def find_enclosing_module_named(name) + parent && parent.find_module_named(name) + end + + ## + # Finds an external alias +name+ with singleton value +singleton+. + + def find_external_alias(name, singleton) + @external_aliases.find { |m| m.name == name && m.singleton == singleton } + end + + ## + # Finds an external alias with +name+ in this context + + def find_external_alias_named(name) + case name + when /\A#/ then + find_external_alias name[1..-1], false + when /\A::/ then + find_external_alias name[2..-1], true + else + @external_aliases.find { |a| a.name == name } + end + end + + ## + # Finds a file with +name+ in this context + + def find_file_named name + @store.find_file_named name + end + + ## + # Finds an instance method with +name+ in this context + + def find_instance_method_named(name) + @method_list.find { |meth| !meth.singleton && meth.name == name } + end + + ## + # Finds a method, constant, attribute, external alias, module or file + # named +symbol+ in this context. + + def find_local_symbol(symbol) + find_method_named(symbol) or + find_constant_named(symbol) or + find_attribute_named(symbol) or + find_external_alias_named(symbol) or + find_module_named(symbol) or + find_file_named(symbol) + end + + ## + # Finds a method named +name+ with singleton value +singleton+. + + def find_method(name, singleton) + @method_list.find { |m| m.name == name && m.singleton == singleton } + end + + ## + # Finds a instance or module method with +name+ in this context + + def find_method_named(name) + case name + when /\A#/ then + find_method name[1..-1], false + when /\A::/ then + find_method name[2..-1], true + else + @method_list.find { |meth| meth.name == name } + end + end + + ## + # Find a module with +name+ using ruby's scoping rules + + def find_module_named(name) + res = @modules[name] || @classes[name] + return res if res + return self if self.name == name + find_enclosing_module_named name + end + + ## + # Look up +symbol+, first as a module, then as a local symbol. + + def find_symbol(symbol) + find_symbol_module(symbol) || find_local_symbol(symbol) + end + + ## + # Look up a module named +symbol+. + + def find_symbol_module(symbol) + result = nil + + # look for a class or module 'symbol' + case symbol + when /^::/ then + result = @store.find_class_or_module symbol + when /^(\w+):+(.+)$/ + suffix = $2 + top = $1 + searched = self + while searched do + mod = searched.find_module_named(top) + break unless mod + result = @store.find_class_or_module "#{mod.full_name}::#{suffix}" + break if result || searched.is_a?(RDoc::TopLevel) + searched = searched.parent + end + else + searched = self + while searched do + result = searched.find_module_named(symbol) + break if result || searched.is_a?(RDoc::TopLevel) + searched = searched.parent + end + end + + result + end + + ## + # The full name for this context. This method is overridden by subclasses. + + def full_name + '(unknown)' + end + + ## + # Does this context and its methods and constants all have documentation? + # + # (Yes, fully documented doesn't mean everything.) + + def fully_documented? + documented? and + attributes.all? { |a| a.documented? } and + method_list.all? { |m| m.documented? } and + constants.all? { |c| c.documented? } + end + + ## + # URL for this with a +prefix+ + + def http_url(prefix) + path = name_for_path + path = path.gsub(/<<\s*(\w*)/, 'from-\1') if path =~ /<'class' or + # 'instance') and visibility (+:public+, +:protected+, +:private+). + # + # If +section+ is provided only methods in that RDoc::Context::Section will + # be returned. + + def methods_by_type section = nil + methods = {} + + TYPES.each do |type| + visibilities = {} + RDoc::VISIBILITIES.each do |vis| + visibilities[vis] = [] + end + + methods[type] = visibilities + end + + each_method do |method| + next if section and not method.section == section + methods[method.type][method.visibility] << method + end + + methods + end + + ## + # Yields AnyMethod and Attr entries matching the list of names in +methods+. + + def methods_matching(methods, singleton = false, &block) + (@method_list + @attributes).each do |m| + yield m if methods.include?(m.name) and m.singleton == singleton + end + + each_ancestor do |parent| + parent.methods_matching(methods, singleton, &block) + end + end + + ## + # Array of modules in this context + + def modules + @modules.values + end + + ## + # Hash of modules keyed by module name + + def modules_hash + @modules + end + + ## + # Name to use to generate the url. + # #full_name by default. + + def name_for_path + full_name + end + + ## + # Changes the visibility for new methods to +visibility+ + + def ongoing_visibility=(visibility) + @visibility = visibility + end + + ## + # Record +top_level+ as a file +self+ is in. + + def record_location(top_level) + @in_files << top_level unless @in_files.include?(top_level) + end + + ## + # Should we remove this context from the documentation? + # + # The answer is yes if: + # * #received_nodoc is +true+ + # * #any_content is +false+ (not counting includes) + # * All #includes are modules (not a string), and their module has + # #remove_from_documentation? == true + # * All classes and modules have #remove_from_documentation? == true + + def remove_from_documentation? + @remove_from_documentation ||= + @received_nodoc && + !any_content(false) && + @includes.all? { |i| !i.module.is_a?(String) && i.module.remove_from_documentation? } && + classes_and_modules.all? { |cm| cm.remove_from_documentation? } + end + + ## + # Removes methods and attributes with a visibility less than +min_visibility+. + #-- + # TODO mark the visibility of attributes in the template (if not public?) + + def remove_invisible min_visibility + return if [:private, :nodoc].include? min_visibility + remove_invisible_in @method_list, min_visibility + remove_invisible_in @attributes, min_visibility + end + + ## + # Only called when min_visibility == :public or :private + + def remove_invisible_in array, min_visibility # :nodoc: + if min_visibility == :public then + array.reject! { |e| + e.visibility != :public and not e.force_documentation + } + else + array.reject! { |e| + e.visibility == :private and not e.force_documentation + } + end + end + + ## + # Tries to resolve unmatched aliases when a method or attribute has just + # been added. + + def resolve_aliases added + # resolve any pending unmatched aliases + key = added.pretty_name + unmatched_alias_list = @unmatched_alias_lists[key] + return unless unmatched_alias_list + unmatched_alias_list.each do |unmatched_alias| + added.add_alias unmatched_alias, self + @external_aliases.delete unmatched_alias + end + @unmatched_alias_lists.delete key + end + + ## + # Returns RDoc::Context::Section objects referenced in this context for use + # in a table of contents. + + def section_contents + used_sections = {} + + each_method do |method| + next unless method.display? + + used_sections[method.section] = true + end + + # order found sections + sections = sort_sections.select do |section| + used_sections[section] + end + + # only the default section is used + return [] if + sections.length == 1 and not sections.first.title + + sections + end + + ## + # Sections in this context + + def sections + @sections.values + end + + def sections_hash # :nodoc: + @sections + end + + ## + # Sets the current section to a section with +title+. See also #add_section + + def set_current_section title, comment + @current_section = add_section title, comment + end + + ## + # Given an array +methods+ of method names, set the visibility of each to + # +visibility+ + + def set_visibility_for(methods, visibility, singleton = false) + methods_matching methods, singleton do |m| + m.visibility = visibility + end + end + + ## + # Sorts sections alphabetically (default) or in TomDoc fashion (none, + # Public, Internal, Deprecated) + + def sort_sections + titles = @sections.map { |title, _| title } + + if titles.length > 1 and + TOMDOC_TITLES_SORT == + (titles | TOMDOC_TITLES).sort_by { |title| title.to_s } then + @sections.values_at(*TOMDOC_TITLES).compact + else + @sections.sort_by { |title, _| + title.to_s + }.map { |_, section| + section + } + end + end + + def to_s # :nodoc: + "#{self.class.name} #{self.full_name}" + end + + ## + # Return the TopLevel that owns us + #-- + # FIXME we can be 'owned' by several TopLevel (see #record_location & + # #in_files) + + def top_level + return @top_level if defined? @top_level + @top_level = self + @top_level = @top_level.parent until RDoc::TopLevel === @top_level + @top_level + end + + ## + # Upgrades NormalModule +mod+ in +enclosing+ to a +class_type+ + + def upgrade_to_class mod, class_type, enclosing + enclosing.modules_hash.delete mod.name + + klass = RDoc::ClassModule.from_module class_type, mod + klass.store = @store + + # if it was there, then we keep it even if done_documenting + @store.classes_hash[mod.full_name] = klass + enclosing.classes_hash[mod.name] = klass + + klass + end + + autoload :Section, 'rdoc/context/section' + +end + diff --git a/jni/ruby/lib/rdoc/context/section.rb b/jni/ruby/lib/rdoc/context/section.rb new file mode 100644 index 0000000..580f07d --- /dev/null +++ b/jni/ruby/lib/rdoc/context/section.rb @@ -0,0 +1,238 @@ +## +# A section of documentation like: +# +# # :section: The title +# # The body +# +# Sections can be referenced multiple times and will be collapsed into a +# single section. + +class RDoc::Context::Section + + include RDoc::Text + + MARSHAL_VERSION = 0 # :nodoc: + + ## + # Section comment + + attr_reader :comment + + ## + # Section comments + + attr_reader :comments + + ## + # Context this Section lives in + + attr_reader :parent + + ## + # Section title + + attr_reader :title + + @@sequence = "SEC00000" + + ## + # Creates a new section with +title+ and +comment+ + + def initialize parent, title, comment + @parent = parent + @title = title ? title.strip : title + + @@sequence.succ! + @sequence = @@sequence.dup + + @comments = [] + + add_comment comment + end + + ## + # Sections are equal when they have the same #title + + def == other + self.class === other and @title == other.title + end + + ## + # Adds +comment+ to this section + + def add_comment comment + comment = extract_comment comment + + return if comment.empty? + + case comment + when RDoc::Comment then + @comments << comment + when RDoc::Markup::Document then + @comments.concat comment.parts + when Array then + @comments.concat comment + else + raise TypeError, "unknown comment type: #{comment.inspect}" + end + end + + ## + # Anchor reference for linking to this section + + def aref + title = @title || '[untitled]' + + CGI.escape(title).gsub('%', '-').sub(/^-/, '') + end + + ## + # Extracts the comment for this section from the original comment block. + # If the first line contains :section:, strip it and use the rest. + # Otherwise remove lines up to the line containing :section:, and look + # for those lines again at the end and remove them. This lets us write + # + # # :section: The title + # # The body + + def extract_comment comment + case comment + when Array then + comment.map do |c| + extract_comment c + end + when nil + RDoc::Comment.new '' + when RDoc::Comment then + if comment.text =~ /^#[ \t]*:section:.*\n/ then + start = $` + rest = $' + + comment.text = if start.empty? then + rest + else + rest.sub(/#{start.chomp}\Z/, '') + end + end + + comment + when RDoc::Markup::Document then + comment + else + raise TypeError, "unknown comment #{comment.inspect}" + end + end + + def inspect # :nodoc: + "#<%s:0x%x %p>" % [self.class, object_id, title] + end + + ## + # The files comments in this section come from + + def in_files + return [] if @comments.empty? + + case @comments + when Array then + @comments.map do |comment| + comment.file + end + when RDoc::Markup::Document then + @comment.parts.map do |document| + document.file + end + else + raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" + end + end + + ## + # Serializes this Section. The title and parsed comment are saved, but not + # the section parent which must be restored manually. + + def marshal_dump + [ + MARSHAL_VERSION, + @title, + parse, + ] + end + + ## + # De-serializes this Section. The section parent must be restored manually. + + def marshal_load array + @parent = nil + + @title = array[1] + @comments = array[2] + end + + ## + # Parses +comment_location+ into an RDoc::Markup::Document composed of + # multiple RDoc::Markup::Documents with their file set. + + def parse + case @comments + when String then + super + when Array then + docs = @comments.map do |comment, location| + doc = super comment + doc.file = location if location + doc + end + + RDoc::Markup::Document.new(*docs) + when RDoc::Comment then + doc = super @comments.text, comments.format + doc.file = @comments.location + doc + when RDoc::Markup::Document then + return @comments + else + raise ArgumentError, "unknown comment class #{comments.class}" + end + end + + ## + # The section's title, or 'Top Section' if the title is nil. + # + # This is used by the table of contents template so the name is silly. + + def plain_html + @title || 'Top Section' + end + + ## + # Removes a comment from this section if it is from the same file as + # +comment+ + + def remove_comment comment + return if @comments.empty? + + case @comments + when Array then + @comments.delete_if do |my_comment| + my_comment.file == comment.file + end + when RDoc::Markup::Document then + @comments.parts.delete_if do |document| + document.file == comment.file.name + end + else + raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" + end + end + + ## + # Section sequence number (deprecated) + + def sequence + warn "RDoc::Context::Section#sequence is deprecated, use #aref" + @sequence + end + +end + diff --git a/jni/ruby/lib/rdoc/cross_reference.rb b/jni/ruby/lib/rdoc/cross_reference.rb new file mode 100644 index 0000000..5b08d52 --- /dev/null +++ b/jni/ruby/lib/rdoc/cross_reference.rb @@ -0,0 +1,183 @@ +## +# RDoc::CrossReference is a reusable way to create cross references for names. + +class RDoc::CrossReference + + ## + # Regular expression to match class references + # + # 1. There can be a '\\' in front of text to suppress the cross-reference + # 2. There can be a '::' in front of class names to reference from the + # top-level namespace. + # 3. The method can be followed by parenthesis (not recommended) + + CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)' + + ## + # Regular expression to match method references. + # + # See CLASS_REGEXP_STR + + METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%|===|\[\]=?|<<|>>)(?:\([\w.+*/=<>-]*\))?' + + ## + # Regular expressions matching text that should potentially have + # cross-reference links generated are passed to add_special. Note that + # these expressions are meant to pick up text for which cross-references + # have been suppressed, since the suppression characters are removed by the + # code that is triggered. + + CROSSREF_REGEXP = /(?:^|\s) + ( + (?: + # A::B::C.meth + #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} + + # Stand-alone method (preceded by a #) + | \\?\##{METHOD_REGEXP_STR} + + # Stand-alone method (preceded by ::) + | ::#{METHOD_REGEXP_STR} + + # A::B::C + # The stuff after CLASS_REGEXP_STR is a + # nasty hack. CLASS_REGEXP_STR unfortunately matches + # words like dog and cat (these are legal "class" + # names in Fortran 95). When a word is flagged as a + # potential cross-reference, limitations in the markup + # engine suppress other processing, such as typesetting. + # This is particularly noticeable for contractions. + # In order that words like "can't" not + # be flagged as potential cross-references, only + # flag potential class cross-references if the character + # after the cross-reference is a space, sentence + # punctuation, tag start character, or attribute + # marker. + | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z) + + # Things that look like filenames + # The key thing is that there must be at least + # one special character (period, slash, or + # underscore). + | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+ + + # Things that have markup suppressed + # Don't process things like '\<' in \, though. + # TODO: including < is a hack, not very satisfying. + | \\[^\s<] + ) + + # labels for headings + (?:@[\w+%-]+(?:\.[\w|%-]+)?)? + )/x + + ## + # Version of CROSSREF_REGEXP used when --hyperlink-all is specified. + + ALL_CROSSREF_REGEXP = / + (?:^|\s) + ( + (?: + # A::B::C.meth + #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} + + # Stand-alone method + | \\?#{METHOD_REGEXP_STR} + + # A::B::C + | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z) + + # Things that look like filenames + | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+ + + # Things that have markup suppressed + | \\[^\s<] + ) + + # labels for headings + (?:@[\w+%-]+)? + )/x + + ## + # Hash of references that have been looked-up to their replacements + + attr_accessor :seen + + ## + # Allows cross-references to be created based on the given +context+ + # (RDoc::Context). + + def initialize context + @context = context + @store = context.store + + @seen = {} + end + + ## + # Returns a reference to +name+. + # + # If the reference is found and +name+ is not documented +text+ will be + # returned. If +name+ is escaped +name+ is returned. If +name+ is not + # found +text+ is returned. + + def resolve name, text + return @seen[name] if @seen.include? name + + if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then + type = $2 + type = '' if type == '.' # will find either #method or ::method + method = "#{type}#{$3}" + container = @context.find_symbol_module($1) + elsif /^([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then + type = $1 + type = '' if type == '.' + method = "#{type}#{$2}" + container = @context + else + container = nil + end + + if container then + ref = container.find_local_symbol method + + unless ref || RDoc::TopLevel === container then + ref = container.find_ancestor_local_symbol method + end + end + + ref = case name + when /^\\(#{CLASS_REGEXP_STR})$/o then + @context.find_symbol $1 + else + @context.find_symbol name + end unless ref + + # Try a page name + ref = @store.page name if not ref and name =~ /^\w+$/ + + ref = nil if RDoc::Alias === ref # external alias, can't link to it + + out = if name == '\\' then + name + elsif name =~ /^\\/ then + # we remove the \ only in front of what we know: + # other backslashes are treated later, only outside of + ref ? $' : name + elsif ref then + if ref.display? then + ref + else + text + end + else + text + end + + @seen[name] = out + + out + end + +end + diff --git a/jni/ruby/lib/rdoc/encoding.rb b/jni/ruby/lib/rdoc/encoding.rb new file mode 100644 index 0000000..b3515a4 --- /dev/null +++ b/jni/ruby/lib/rdoc/encoding.rb @@ -0,0 +1,99 @@ +# coding: US-ASCII + +## +# This class is a wrapper around File IO and Encoding that helps RDoc load +# files and convert them to the correct encoding. + +module RDoc::Encoding + + ## + # Reads the contents of +filename+ and handles any encoding directives in + # the file. + # + # The content will be converted to the +encoding+. If the file cannot be + # converted a warning will be printed and nil will be returned. + # + # If +force_transcode+ is true the document will be transcoded and any + # unknown character in the target encoding will be replaced with '?' + + def self.read_file filename, encoding, force_transcode = false + content = open filename, "rb" do |f| f.read end + content.gsub!("\r\n", "\n") if RUBY_PLATFORM =~ /mswin|mingw/ + + utf8 = content.sub!(/\A\xef\xbb\xbf/, '') + + RDoc::Encoding.set_encoding content + + if Object.const_defined? :Encoding then + begin + encoding ||= Encoding.default_external + orig_encoding = content.encoding + + if not orig_encoding.ascii_compatible? then + content.encode! encoding + elsif utf8 then + content.force_encoding Encoding::UTF_8 + content.encode! encoding + else + # assume the content is in our output encoding + content.force_encoding encoding + end + + unless content.valid_encoding? then + # revert and try to transcode + content.force_encoding orig_encoding + content.encode! encoding + end + + unless content.valid_encoding? then + warn "unable to convert #{filename} to #{encoding}, skipping" + content = nil + end + rescue Encoding::InvalidByteSequenceError, + Encoding::UndefinedConversionError => e + if force_transcode then + content.force_encoding orig_encoding + content.encode!(encoding, + :invalid => :replace, :undef => :replace, + :replace => '?') + return content + else + warn "unable to convert #{e.message} for #{filename}, skipping" + return nil + end + end + end + + content + rescue ArgumentError => e + raise unless e.message =~ /unknown encoding name - (.*)/ + warn "unknown encoding name \"#{$1}\" for #{filename}, skipping" + nil + rescue Errno::EISDIR, Errno::ENOENT + nil + end + + ## + # Sets the encoding of +string+ based on the magic comment + + def self.set_encoding string + string =~ /\A(?:#!.*\n)?(.*\n)/ + + first_line = $1 + + name = case first_line + when /^<\?xml[^?]*encoding=(["'])(.*?)\1/ then $2 + when /\b(?:en)?coding[=:]\s*([^\s;]+)/i then $1 + else return + end + + string.sub! first_line, '' + + return unless Object.const_defined? :Encoding + + enc = Encoding.find name + string.force_encoding enc if enc + end + +end + diff --git a/jni/ruby/lib/rdoc/erb_partial.rb b/jni/ruby/lib/rdoc/erb_partial.rb new file mode 100644 index 0000000..910d1e0 --- /dev/null +++ b/jni/ruby/lib/rdoc/erb_partial.rb @@ -0,0 +1,18 @@ +## +# Allows an ERB template to be rendered in the context (binding) of an +# existing ERB template evaluation. + +class RDoc::ERBPartial < ERB + + ## + # Overrides +compiler+ startup to set the +eoutvar+ to an empty string only + # if it isn't already set. + + def set_eoutvar compiler, eoutvar = '_erbout' + super + + compiler.pre_cmd = ["#{eoutvar} ||= ''"] + end + +end + diff --git a/jni/ruby/lib/rdoc/erbio.rb b/jni/ruby/lib/rdoc/erbio.rb new file mode 100644 index 0000000..04a89fb --- /dev/null +++ b/jni/ruby/lib/rdoc/erbio.rb @@ -0,0 +1,37 @@ +require 'erb' + +## +# A subclass of ERB that writes directly to an IO. Credit to Aaron Patterson +# and Masatoshi SEKI. +# +# To use: +# +# erbio = RDoc::ERBIO.new '<%= "hello world" %>', nil, nil +# +# open 'hello.txt', 'w' do |io| +# erbio.result binding +# end +# +# Note that binding must enclose the io you wish to output on. + +class RDoc::ERBIO < ERB + + ## + # Defaults +eoutvar+ to 'io', otherwise is identical to ERB's initialize + + def initialize str, safe_level = nil, trim_mode = nil, eoutvar = 'io' + super + end + + ## + # Instructs +compiler+ how to write to +io_variable+ + + def set_eoutvar compiler, io_variable + compiler.put_cmd = "#{io_variable}.write" + compiler.insert_cmd = "#{io_variable}.write" + compiler.pre_cmd = [] + compiler.post_cmd = [] + end + +end + diff --git a/jni/ruby/lib/rdoc/extend.rb b/jni/ruby/lib/rdoc/extend.rb new file mode 100644 index 0000000..efa2c69 --- /dev/null +++ b/jni/ruby/lib/rdoc/extend.rb @@ -0,0 +1,9 @@ +## +# A Module extension to a class with \#extend +# +# RDoc::Extend.new 'Enumerable', 'comment ...' + +class RDoc::Extend < RDoc::Mixin + +end + diff --git a/jni/ruby/lib/rdoc/generator.rb b/jni/ruby/lib/rdoc/generator.rb new file mode 100644 index 0000000..7d3989d --- /dev/null +++ b/jni/ruby/lib/rdoc/generator.rb @@ -0,0 +1,51 @@ +## +# RDoc uses generators to turn parsed source code in the form of an +# RDoc::CodeObject tree into some form of output. RDoc comes with the HTML +# generator RDoc::Generator::Darkfish and an ri data generator +# RDoc::Generator::RI. +# +# == Registering a Generator +# +# Generators are registered by calling RDoc::RDoc.add_generator with the class +# of the generator: +# +# class My::Awesome::Generator +# RDoc::RDoc.add_generator self +# end +# +# == Adding Options to +rdoc+ +# +# Before option processing in +rdoc+, RDoc::Options will call ::setup_options +# on the generator class with an RDoc::Options instance. The generator can +# use RDoc::Options#option_parser to add command-line options to the +rdoc+ +# tool. See RDoc::Options@Custom+Options for an example and see OptionParser +# for details on how to add options. +# +# You can extend the RDoc::Options instance with additional accessors for your +# generator. +# +# == Generator Instantiation +# +# After parsing, RDoc::RDoc will instantiate a generator by calling +# #initialize with an RDoc::Store instance and an RDoc::Options instance. +# +# The RDoc::Store instance holds documentation for parsed source code. In +# RDoc 3 and earlier the RDoc::TopLevel class held this data. When upgrading +# a generator from RDoc 3 and earlier you should only need to replace +# RDoc::TopLevel with the store instance. +# +# RDoc will then call #generate on the generator instance. You can use the +# various methods on RDoc::Store and in the RDoc::CodeObject tree to create +# your desired output format. + +module RDoc::Generator + + autoload :Markup, 'rdoc/generator/markup' + + autoload :Darkfish, 'rdoc/generator/darkfish' + autoload :JsonIndex, 'rdoc/generator/json_index' + autoload :RI, 'rdoc/generator/ri' + autoload :POT, 'rdoc/generator/pot' + +end + diff --git a/jni/ruby/lib/rdoc/generator/darkfish.rb b/jni/ruby/lib/rdoc/generator/darkfish.rb new file mode 100644 index 0000000..0240404 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/darkfish.rb @@ -0,0 +1,760 @@ +# -*- mode: ruby; ruby-indent-level: 2; tab-width: 2 -*- + +require 'erb' +require 'fileutils' +require 'pathname' +require 'rdoc/generator/markup' + +## +# Darkfish RDoc HTML Generator +# +# $Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $ +# +# == Author/s +# * Michael Granger (ged@FaerieMUD.org) +# +# == Contributors +# * Mahlon E. Smith (mahlon@martini.nu) +# * Eric Hodel (drbrain@segment7.net) +# +# == License +# +# Copyright (c) 2007, 2008, Michael Granger. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of the author/s, nor the names of the project's +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# == Attributions +# +# Darkfish uses the {Silk Icons}[http://www.famfamfam.com/lab/icons/silk/] set +# by Mark James. + +class RDoc::Generator::Darkfish + + RDoc::RDoc.add_generator self + + include ERB::Util + + ## + # Stylesheets, fonts, etc. that are included in RDoc. + + BUILTIN_STYLE_ITEMS = # :nodoc: + %w[ + css/fonts.css + fonts/Lato-Light.ttf + fonts/Lato-LightItalic.ttf + fonts/Lato-Regular.ttf + fonts/Lato-RegularItalic.ttf + fonts/SourceCodePro-Bold.ttf + fonts/SourceCodePro-Regular.ttf + css/rdoc.css + ] + + ## + # Path to this file's parent directory. Used to find templates and other + # resources. + + GENERATOR_DIR = File.join 'rdoc', 'generator' + + ## + # Release Version + + VERSION = '3' + + ## + # Description of this generator + + DESCRIPTION = 'HTML generator, written by Michael Granger' + + ## + # The relative path to style sheets and javascript. By default this is set + # the same as the rel_prefix. + + attr_accessor :asset_rel_path + + ## + # The path to generate files into, combined with --op from the + # options for a full path. + + attr_reader :base_dir + + ## + # Classes and modules to be used by this generator, not necessarily + # displayed. See also #modsort + + attr_reader :classes + + ## + # No files will be written when dry_run is true. + + attr_accessor :dry_run + + ## + # When false the generate methods return a String instead of writing to a + # file. The default is true. + + attr_accessor :file_output + + ## + # Files to be displayed by this generator + + attr_reader :files + + ## + # The JSON index generator for this Darkfish generator + + attr_reader :json_index + + ## + # Methods to be displayed by this generator + + attr_reader :methods + + ## + # Sorted list of classes and modules to be displayed by this generator + + attr_reader :modsort + + ## + # The RDoc::Store that is the source of the generated content + + attr_reader :store + + ## + # The directory where the template files live + + attr_reader :template_dir # :nodoc: + + ## + # The output directory + + attr_reader :outputdir + + ## + # Initialize a few instance variables before we start + + def initialize store, options + @store = store + @options = options + + @asset_rel_path = '' + @base_dir = Pathname.pwd.expand_path + @dry_run = @options.dry_run + @file_output = true + @template_dir = Pathname.new options.template_dir + @template_cache = {} + + @classes = nil + @context = nil + @files = nil + @methods = nil + @modsort = nil + + @json_index = RDoc::Generator::JsonIndex.new self, options + end + + ## + # Output progress information if debugging is enabled + + def debug_msg *msg + return unless $DEBUG_RDOC + $stderr.puts(*msg) + end + + ## + # Directory where generated class HTML files live relative to the output + # dir. + + def class_dir + nil + end + + ## + # Directory where generated class HTML files live relative to the output + # dir. + + def file_dir + nil + end + + ## + # Create the directories the generated docs will live in if they don't + # already exist. + + def gen_sub_directories + @outputdir.mkpath + end + + ## + # Copy over the stylesheet into the appropriate place in the output + # directory. + + def write_style_sheet + debug_msg "Copying static files" + options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } + + BUILTIN_STYLE_ITEMS.each do |item| + install_rdoc_static_file @template_dir + item, "./#{item}", options + end + + @options.template_stylesheets.each do |stylesheet| + FileUtils.cp stylesheet, '.', options + end + + Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path| + next if File.directory? path + next if File.basename(path) =~ /^\./ + + dst = Pathname.new(path).relative_path_from @template_dir + + install_rdoc_static_file @template_dir + path, dst, options + end + end + + ## + # Build the initial indices and output objects based on an array of TopLevel + # objects containing the extracted information. + + def generate + setup + + write_style_sheet + generate_index + generate_class_files + generate_file_files + generate_table_of_contents + @json_index.generate + @json_index.generate_gzipped + + copy_static + + rescue => e + debug_msg "%s: %s\n %s" % [ + e.class.name, e.message, e.backtrace.join("\n ") + ] + + raise + end + + ## + # Copies static files from the static_path into the output directory + + def copy_static + return if @options.static_path.empty? + + fu_options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } + + @options.static_path.each do |path| + unless File.directory? path then + FileUtils.install path, @outputdir, fu_options.merge(:mode => 0644) + next + end + + Dir.chdir path do + Dir[File.join('**', '*')].each do |entry| + dest_file = @outputdir + entry + + if File.directory? entry then + FileUtils.mkdir_p entry, fu_options + else + FileUtils.install entry, dest_file, fu_options.merge(:mode => 0644) + end + end + end + end + end + + ## + # Return a list of the documented modules sorted by salience first, then + # by name. + + def get_sorted_module_list classes + classes.select do |klass| + klass.display? + end.sort + end + + ## + # Generate an index page which lists all the classes which are documented. + + def generate_index + setup + + template_file = @template_dir + 'index.rhtml' + return unless template_file.exist? + + debug_msg "Rendering the index page..." + + out_file = @base_dir + @options.op_dir + 'index.html' + rel_prefix = @outputdir.relative_path_from out_file.dirname + search_index_rel_prefix = rel_prefix + search_index_rel_prefix += @asset_rel_path if @file_output + + # suppress 1.9.3 warning + asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path + + @title = @options.title + + render_template template_file, out_file do |io| binding end + rescue => e + error = RDoc::Error.new \ + "error generating index.html: #{e.message} (#{e.class})" + error.set_backtrace e.backtrace + + raise error + end + + ## + # Generates a class file for +klass+ + + def generate_class klass, template_file = nil + setup + + current = klass + + template_file ||= @template_dir + 'class.rhtml' + + debug_msg " working on %s (%s)" % [klass.full_name, klass.path] + out_file = @outputdir + klass.path + rel_prefix = @outputdir.relative_path_from out_file.dirname + search_index_rel_prefix = rel_prefix + search_index_rel_prefix += @asset_rel_path if @file_output + + # suppress 1.9.3 warning + asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path + svninfo = svninfo = get_svninfo(current) + + @title = "#{klass.type} #{klass.full_name} - #{@options.title}" + + debug_msg " rendering #{out_file}" + render_template template_file, out_file do |io| binding end + end + + ## + # Generate a documentation file for each class and module + + def generate_class_files + setup + + template_file = @template_dir + 'class.rhtml' + template_file = @template_dir + 'classpage.rhtml' unless + template_file.exist? + return unless template_file.exist? + debug_msg "Generating class documentation in #{@outputdir}" + + current = nil + + @classes.each do |klass| + current = klass + + generate_class klass, template_file + end + rescue => e + error = RDoc::Error.new \ + "error generating #{current.path}: #{e.message} (#{e.class})" + error.set_backtrace e.backtrace + + raise error + end + + ## + # Generate a documentation file for each file + + def generate_file_files + setup + + page_file = @template_dir + 'page.rhtml' + fileinfo_file = @template_dir + 'fileinfo.rhtml' + + # for legacy templates + filepage_file = @template_dir + 'filepage.rhtml' unless + page_file.exist? or fileinfo_file.exist? + + return unless + page_file.exist? or fileinfo_file.exist? or filepage_file.exist? + + debug_msg "Generating file documentation in #{@outputdir}" + + out_file = nil + current = nil + + @files.each do |file| + current = file + + if file.text? and page_file.exist? then + generate_page file + next + end + + template_file = nil + out_file = @outputdir + file.path + debug_msg " working on %s (%s)" % [file.full_name, out_file] + rel_prefix = @outputdir.relative_path_from out_file.dirname + search_index_rel_prefix = rel_prefix + search_index_rel_prefix += @asset_rel_path if @file_output + + # suppress 1.9.3 warning + asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path + + unless filepage_file then + if file.text? then + next unless page_file.exist? + template_file = page_file + @title = file.page_name + else + next unless fileinfo_file.exist? + template_file = fileinfo_file + @title = "File: #{file.base_name}" + end + end + + @title += " - #{@options.title}" + template_file ||= filepage_file + + render_template template_file, out_file do |io| binding end + end + rescue => e + error = + RDoc::Error.new "error generating #{out_file}: #{e.message} (#{e.class})" + error.set_backtrace e.backtrace + + raise error + end + + ## + # Generate a page file for +file+ + + def generate_page file + setup + + template_file = @template_dir + 'page.rhtml' + + out_file = @outputdir + file.path + debug_msg " working on %s (%s)" % [file.full_name, out_file] + rel_prefix = @outputdir.relative_path_from out_file.dirname + search_index_rel_prefix = rel_prefix + search_index_rel_prefix += @asset_rel_path if @file_output + + # suppress 1.9.3 warning + current = current = file + asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path + + @title = "#{file.page_name} - #{@options.title}" + + debug_msg " rendering #{out_file}" + render_template template_file, out_file do |io| binding end + end + + ## + # Generates the 404 page for the RDoc servlet + + def generate_servlet_not_found message + setup + + template_file = @template_dir + 'servlet_not_found.rhtml' + return unless template_file.exist? + + debug_msg "Rendering the servlet 404 Not Found page..." + + rel_prefix = rel_prefix = '' + search_index_rel_prefix = rel_prefix + search_index_rel_prefix += @asset_rel_path if @file_output + + # suppress 1.9.3 warning + asset_rel_prefix = asset_rel_prefix = '' + + @title = 'Not Found' + + render_template template_file do |io| binding end + rescue => e + error = RDoc::Error.new \ + "error generating servlet_not_found: #{e.message} (#{e.class})" + error.set_backtrace e.backtrace + + raise error + end + + ## + # Generates the servlet root page for the RDoc servlet + + def generate_servlet_root installed + setup + + template_file = @template_dir + 'servlet_root.rhtml' + return unless template_file.exist? + + debug_msg 'Rendering the servlet root page...' + + rel_prefix = '.' + asset_rel_prefix = rel_prefix + search_index_rel_prefix = asset_rel_prefix + search_index_rel_prefix += @asset_rel_path if @file_output + + @title = 'Local RDoc Documentation' + + render_template template_file do |io| binding end + rescue => e + error = RDoc::Error.new \ + "error generating servlet_root: #{e.message} (#{e.class})" + error.set_backtrace e.backtrace + + raise error + end + + ## + # Generate an index page which lists all the classes which are documented. + + def generate_table_of_contents + setup + + template_file = @template_dir + 'table_of_contents.rhtml' + return unless template_file.exist? + + debug_msg "Rendering the Table of Contents..." + + out_file = @outputdir + 'table_of_contents.html' + rel_prefix = @outputdir.relative_path_from out_file.dirname + search_index_rel_prefix = rel_prefix + search_index_rel_prefix += @asset_rel_path if @file_output + + # suppress 1.9.3 warning + asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path + + @title = "Table of Contents - #{@options.title}" + + render_template template_file, out_file do |io| binding end + rescue => e + error = RDoc::Error.new \ + "error generating table_of_contents.html: #{e.message} (#{e.class})" + error.set_backtrace e.backtrace + + raise error + end + + def install_rdoc_static_file source, destination, options # :nodoc: + return unless source.exist? + + begin + FileUtils.mkdir_p File.dirname(destination), options + + begin + FileUtils.ln source, destination, options + rescue Errno::EEXIST + FileUtils.rm destination + retry + end + rescue + FileUtils.cp source, destination, options + end + end + + ## + # Prepares for generation of output from the current directory + + def setup + return if instance_variable_defined? :@outputdir + + @outputdir = Pathname.new(@options.op_dir).expand_path @base_dir + + return unless @store + + @classes = @store.all_classes_and_modules.sort + @files = @store.all_files.sort + @methods = @classes.map { |m| m.method_list }.flatten.sort + @modsort = get_sorted_module_list @classes + end + + ## + # Return a string describing the amount of time in the given number of + # seconds in terms a human can understand easily. + + def time_delta_string seconds + return 'less than a minute' if seconds < 60 + return "#{seconds / 60} minute#{seconds / 60 == 1 ? '' : 's'}" if + seconds < 3000 # 50 minutes + return 'about one hour' if seconds < 5400 # 90 minutes + return "#{seconds / 3600} hours" if seconds < 64800 # 18 hours + return 'one day' if seconds < 86400 # 1 day + return 'about one day' if seconds < 172800 # 2 days + return "#{seconds / 86400} days" if seconds < 604800 # 1 week + return 'about one week' if seconds < 1209600 # 2 week + return "#{seconds / 604800} weeks" if seconds < 7257600 # 3 months + return "#{seconds / 2419200} months" if seconds < 31536000 # 1 year + return "#{seconds / 31536000} years" + end + + # %q$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $" + SVNID_PATTERN = / + \$Id:\s + (\S+)\s # filename + (\d+)\s # rev + (\d{4}-\d{2}-\d{2})\s # Date (YYYY-MM-DD) + (\d{2}:\d{2}:\d{2}Z)\s # Time (HH:MM:SSZ) + (\w+)\s # committer + \$$ + /x + + ## + # Try to extract Subversion information out of the first constant whose + # value looks like a subversion Id tag. If no matching constant is found, + # and empty hash is returned. + + def get_svninfo klass + constants = klass.constants or return {} + + constants.find { |c| c.value =~ SVNID_PATTERN } or return {} + + filename, rev, date, time, committer = $~.captures + commitdate = Time.parse "#{date} #{time}" + + return { + :filename => filename, + :rev => Integer(rev), + :commitdate => commitdate, + :commitdelta => time_delta_string(Time.now - commitdate), + :committer => committer, + } + end + + ## + # Creates a template from its components and the +body_file+. + # + # For backwards compatibility, if +body_file+ contains " + + + +#{head_file.read} + +#{body} + +#{footer_file.read} + TEMPLATE + end + + ## + # Renders the ERb contained in +file_name+ relative to the template + # directory and returns the result based on the current context. + + def render file_name + template_file = @template_dir + file_name + + template = template_for template_file, false, RDoc::ERBPartial + + template.filename = template_file.to_s + + template.result @context + end + + ## + # Load and render the erb template in the given +template_file+ and write + # it out to +out_file+. + # + # Both +template_file+ and +out_file+ should be Pathname-like objects. + # + # An io will be yielded which must be captured by binding in the caller. + + def render_template template_file, out_file = nil # :yield: io + io_output = out_file && !@dry_run && @file_output + erb_klass = io_output ? RDoc::ERBIO : ERB + + template = template_for template_file, true, erb_klass + + if io_output then + debug_msg "Outputting to %s" % [out_file.expand_path] + + out_file.dirname.mkpath + out_file.open 'w', 0644 do |io| + io.set_encoding @options.encoding if Object.const_defined? :Encoding + + @context = yield io + + template_result template, @context, template_file + end + else + @context = yield nil + + output = template_result template, @context, template_file + + debug_msg " would have written %d characters to %s" % [ + output.length, out_file.expand_path + ] if @dry_run + + output + end + end + + ## + # Creates the result for +template+ with +context+. If an error is raised a + # Pathname +template_file+ will indicate the file where the error occurred. + + def template_result template, context, template_file + template.filename = template_file.to_s + template.result context + rescue NoMethodError => e + raise RDoc::Error, "Error while evaluating %s: %s" % [ + template_file.expand_path, + e.message, + ], e.backtrace + end + + ## + # Retrieves a cache template for +file+, if present, or fills the cache. + + def template_for file, page = true, klass = ERB + template = @template_cache[file] + + return template if template + + if page then + template = assemble_template file + erbout = 'io' + else + template = file.read + template = template.encode @options.encoding if + Object.const_defined? :Encoding + + file_var = File.basename(file).sub(/\..*/, '') + + erbout = "_erbout_#{file_var}" + end + + template = klass.new template, nil, '<>', erbout + @template_cache[file] = template + template + end + +end + diff --git a/jni/ruby/lib/rdoc/generator/json_index.rb b/jni/ruby/lib/rdoc/generator/json_index.rb new file mode 100644 index 0000000..9d6f0d4 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/json_index.rb @@ -0,0 +1,292 @@ +require 'json' +require 'zlib' + +## +# The JsonIndex generator is designed to complement an HTML generator and +# produces a JSON search index. This generator is derived from sdoc by +# Vladimir Kolesnikov and contains verbatim code written by him. +# +# This generator is designed to be used with a regular HTML generator: +# +# class RDoc::Generator::Darkfish +# def initialize options +# # ... +# @base_dir = Pathname.pwd.expand_path +# +# @json_index = RDoc::Generator::JsonIndex.new self, options +# end +# +# def generate +# # ... +# @json_index.generate +# end +# end +# +# == Index Format +# +# The index is output as a JSON file assigned to the global variable +# +search_data+. The structure is: +# +# var search_data = { +# "index": { +# "searchIndex": +# ["a", "b", ...], +# "longSearchIndex": +# ["a", "a::b", ...], +# "info": [ +# ["A", "A", "A.html", "", ""], +# ["B", "A::B", "A::B.html", "", ""], +# ... +# ] +# } +# } +# +# The same item is described across the +searchIndex+, +longSearchIndex+ and +# +info+ fields. The +searchIndex+ field contains the item's short name, the +# +longSearchIndex+ field contains the full_name (when appropriate) and the +# +info+ field contains the item's name, full_name, path, parameters and a +# snippet of the item's comment. +# +# == LICENSE +# +# Copyright (c) 2009 Vladimir Kolesnikov +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +class RDoc::Generator::JsonIndex + + include RDoc::Text + + ## + # Where the search index lives in the generated output + + SEARCH_INDEX_FILE = File.join 'js', 'search_index.js' + + attr_reader :index # :nodoc: + + ## + # Creates a new generator. +parent_generator+ is used to determine the + # class_dir and file_dir of links in the output index. + # + # +options+ are the same options passed to the parent generator. + + def initialize parent_generator, options + @parent_generator = parent_generator + @store = parent_generator.store + @options = options + + @template_dir = File.expand_path '../template/json_index', __FILE__ + @base_dir = @parent_generator.base_dir + + @classes = nil + @files = nil + @index = nil + end + + ## + # Builds the JSON index as a Hash. + + def build_index + reset @store.all_files.sort, @store.all_classes_and_modules.sort + + index_classes + index_methods + index_pages + + { :index => @index } + end + + ## + # Output progress information if debugging is enabled + + def debug_msg *msg + return unless $DEBUG_RDOC + $stderr.puts(*msg) + end + + ## + # Writes the JSON index to disk + + def generate + debug_msg "Generating JSON index" + + debug_msg " writing search index to %s" % SEARCH_INDEX_FILE + data = build_index + + return if @options.dry_run + + out_dir = @base_dir + @options.op_dir + index_file = out_dir + SEARCH_INDEX_FILE + + FileUtils.mkdir_p index_file.dirname, :verbose => $DEBUG_RDOC + + index_file.open 'w', 0644 do |io| + io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding + io.write 'var search_data = ' + + JSON.dump data, io, 0 + end + + Dir.chdir @template_dir do + Dir['**/*.js'].each do |source| + dest = File.join out_dir, source + + FileUtils.install source, dest, :mode => 0644, :verbose => $DEBUG_RDOC + end + end + end + + ## + # Compress the search_index.js file using gzip + + def generate_gzipped + debug_msg "Compressing generated JSON index" + out_dir = @base_dir + @options.op_dir + + search_index_file = out_dir + SEARCH_INDEX_FILE + outfile = out_dir + "#{search_index_file}.gz" + + debug_msg "Reading the JSON index file from %s" % search_index_file + search_index = search_index_file.read + + debug_msg "Writing gzipped search index to %s" % outfile + + Zlib::GzipWriter.open(outfile) do |gz| + gz.mtime = File.mtime(search_index_file) + gz.orig_name = search_index_file.to_s + gz.write search_index + gz.close + end + + # GZip the rest of the js files + Dir.chdir @template_dir do + Dir['**/*.js'].each do |source| + dest = out_dir + source + outfile = out_dir + "#{dest}.gz" + + debug_msg "Reading the original js file from %s" % dest + data = dest.read + + debug_msg "Writing gzipped file to %s" % outfile + + Zlib::GzipWriter.open(outfile) do |gz| + gz.mtime = File.mtime(dest) + gz.orig_name = dest.to_s + gz.write data + gz.close + end + end + end + end + + ## + # Adds classes and modules to the index + + def index_classes + debug_msg " generating class search index" + + documented = @classes.uniq.select do |klass| + klass.document_self_or_methods + end + + documented.each do |klass| + debug_msg " #{klass.full_name}" + record = klass.search_record + @index[:searchIndex] << search_string(record.shift) + @index[:longSearchIndex] << search_string(record.shift) + @index[:info] << record + end + end + + ## + # Adds methods to the index + + def index_methods + debug_msg " generating method search index" + + list = @classes.uniq.map do |klass| + klass.method_list + end.flatten.sort_by do |method| + [method.name, method.parent.full_name] + end + + list.each do |method| + debug_msg " #{method.full_name}" + record = method.search_record + @index[:searchIndex] << "#{search_string record.shift}()" + @index[:longSearchIndex] << "#{search_string record.shift}()" + @index[:info] << record + end + end + + ## + # Adds pages to the index + + def index_pages + debug_msg " generating pages search index" + + pages = @files.select do |file| + file.text? + end + + pages.each do |page| + debug_msg " #{page.page_name}" + record = page.search_record + @index[:searchIndex] << search_string(record.shift) + @index[:longSearchIndex] << '' + record.shift + @index[:info] << record + end + end + + ## + # The directory classes are written to + + def class_dir + @parent_generator.class_dir + end + + ## + # The directory files are written to + + def file_dir + @parent_generator.file_dir + end + + def reset files, classes # :nodoc: + @files = files + @classes = classes + + @index = { + :searchIndex => [], + :longSearchIndex => [], + :info => [] + } + end + + ## + # Removes whitespace and downcases +string+ + + def search_string string + string.downcase.gsub(/\s/, '') + end + +end + diff --git a/jni/ruby/lib/rdoc/generator/markup.rb b/jni/ruby/lib/rdoc/generator/markup.rb new file mode 100644 index 0000000..788e5a4 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/markup.rb @@ -0,0 +1,169 @@ +## +# Handle common RDoc::Markup tasks for various CodeObjects +# +# This module is loaded by generators. It allows RDoc's CodeObject tree to +# avoid loading generator code to improve startup time for +ri+. + +module RDoc::Generator::Markup + + ## + # Generates a relative URL from this object's path to +target_path+ + + def aref_to(target_path) + RDoc::Markup::ToHtml.gen_relative_url path, target_path + end + + ## + # Generates a relative URL from +from_path+ to this object's path + + def as_href(from_path) + RDoc::Markup::ToHtml.gen_relative_url from_path, path + end + + ## + # Handy wrapper for marking up this object's comment + + def description + markup @comment + end + + ## + # Creates an RDoc::Markup::ToHtmlCrossref formatter + + def formatter + return @formatter if defined? @formatter + + options = @store.rdoc.options + this = RDoc::Context === self ? self : @parent + + @formatter = RDoc::Markup::ToHtmlCrossref.new options, this.path, this + @formatter.code_object = self + @formatter + end + + ## + # Build a webcvs URL starting for the given +url+ with +full_path+ appended + # as the destination path. If +url+ contains '%s' +full_path+ will be + # will replace the %s using sprintf on the +url+. + + def cvs_url(url, full_path) + if /%s/ =~ url then + sprintf url, full_path + else + url + full_path + end + end + +end + +class RDoc::CodeObject + + include RDoc::Generator::Markup + +end + +class RDoc::MethodAttr + + @add_line_numbers = false + + class << self + ## + # Allows controlling whether #markup_code adds line numbers to + # the source code. + + attr_accessor :add_line_numbers + end + + ## + # Prepend +src+ with line numbers. Relies on the first line of a source + # code listing having: + # + # # File xxxxx, line dddd + # + # If it has this comment then line numbers are added to +src+ and the , + # line dddd portion of the comment is removed. + + def add_line_numbers(src) + return unless src.sub!(/\A(.*)(, line (\d+))/, '\1') + first = $3.to_i - 1 + last = first + src.count("\n") + size = last.to_s.length + + line = first + src.gsub!(/^/) do + res = if line == first then + " " * (size + 1) + else + "%2$*1$d " % [size, line] + end + + line += 1 + res + end + end + + ## + # Turns the method's token stream into HTML. + # + # Prepends line numbers if +add_line_numbers+ is true. + + def markup_code + return '' unless @token_stream + + src = RDoc::TokenStream.to_html @token_stream + + # dedent the source + indent = src.length + lines = src.lines.to_a + lines.shift if src =~ /\A.*#\ *File/i # remove '# File' comment + lines.each do |line| + if line =~ /^ *(?=\S)/ + n = $&.length + indent = n if n < indent + break if n == 0 + end + end + src.gsub!(/^#{' ' * indent}/, '') if indent > 0 + + add_line_numbers(src) if RDoc::MethodAttr.add_line_numbers + + src + end + +end + +class RDoc::ClassModule + + ## + # Handy wrapper for marking up this class or module's comment + + def description + markup @comment_location + end + +end + +class RDoc::Context::Section + + include RDoc::Generator::Markup + +end + +class RDoc::TopLevel + + ## + # Returns a URL for this source file on some web repository. Use the -W + # command line option to set. + + def cvs_url + url = @store.rdoc.options.webcvs + + if /%s/ =~ url then + url % @relative_name + else + url + @relative_name + end + end + +end + diff --git a/jni/ruby/lib/rdoc/generator/pot.rb b/jni/ruby/lib/rdoc/generator/pot.rb new file mode 100644 index 0000000..db6f3a0 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/pot.rb @@ -0,0 +1,97 @@ +## +# Generates a POT file. +# +# Here is a translator work flow with the generator. +# +# == Create .pot +# +# You create .pot file by pot formatter: +# +# % rdoc --format pot +# +# It generates doc/rdoc.pot. +# +# == Create .po +# +# You create .po file from doc/rdoc.pot. This operation is needed only +# the first time. This work flow assumes that you are a translator +# for Japanese. +# +# You create locale/ja/rdoc.po from doc/rdoc.pot. You can use msginit +# provided by GNU gettext or rmsginit provided by gettext gem. This +# work flow uses gettext gem because it is more portable than GNU +# gettext for Rubyists. Gettext gem is implemented by pure Ruby. +# +# % gem install gettext +# % mkdir -p locale/ja +# % rmsginit --input doc/rdoc.pot --output locale/ja/rdoc.po --locale ja +# +# Translate messages in .po +# +# You translate messages in .po by a PO file editor. po-mode.el exists +# for Emacs users. There are some GUI tools such as GTranslator. +# There are some Web services such as POEditor and Tansifex. You can +# edit by your favorite text editor because .po is a text file. +# Generate localized documentation +# +# You can generate localized documentation with locale/ja/rdoc.po: +# +# % rdoc --locale ja +# +# You can find documentation in Japanese in doc/. Yay! +# +# == Update translation +# +# You need to update translation when your application is added or +# modified messages. +# +# You can update .po by the following command lines: +# +# % rdoc --format pot +# % rmsgmerge --update locale/ja/rdoc.po doc/rdoc.pot +# +# You edit locale/ja/rdoc.po to translate new messages. + +class RDoc::Generator::POT + + RDoc::RDoc.add_generator self + + ## + # Description of this generator + + DESCRIPTION = 'creates .pot file' + + ## + # Set up a new .pot generator + + def initialize store, options #:not-new: + @options = options + @store = store + end + + ## + # Writes .pot to disk. + + def generate + po = extract_messages + pot_path = 'rdoc.pot' + File.open(pot_path, "w") do |pot| + pot.print(po.to_s) + end + end + + def class_dir + nil + end + + private + def extract_messages + extractor = MessageExtractor.new(@store) + extractor.extract + end + + autoload :MessageExtractor, 'rdoc/generator/pot/message_extractor' + autoload :PO, 'rdoc/generator/pot/po' + autoload :POEntry, 'rdoc/generator/pot/po_entry' + +end diff --git a/jni/ruby/lib/rdoc/generator/pot/message_extractor.rb b/jni/ruby/lib/rdoc/generator/pot/message_extractor.rb new file mode 100644 index 0000000..ceabc52 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/pot/message_extractor.rb @@ -0,0 +1,67 @@ +## +# Extracts message from RDoc::Store + +class RDoc::Generator::POT::MessageExtractor + + ## + # Creates a message extractor for +store+. + + def initialize store + @store = store + @po = RDoc::Generator::POT::PO.new + end + + ## + # Extracts messages from +store+, stores them into + # RDoc::Generator::POT::PO and returns it. + + def extract + @store.all_classes_and_modules.each do |klass| + extract_from_klass(klass) + end + @po + end + + private + + def extract_from_klass klass + extract_text(klass.comment_location, klass.full_name) + + klass.each_section do |section, constants, attributes| + extract_text(section.title ,"#{klass.full_name}: section title") + section.comments.each do |comment| + extract_text(comment, "#{klass.full_name}: #{section.title}") + end + end + + klass.each_constant do |constant| + extract_text(constant.comment, constant.full_name) + end + + klass.each_attribute do |attribute| + extract_text(attribute.comment, attribute.full_name) + end + + klass.each_method do |method| + extract_text(method.comment, method.full_name) + end + end + + def extract_text text, comment, location = nil + return if text.nil? + + options = { + :extracted_comment => comment, + :references => [location].compact, + } + i18n_text = RDoc::I18n::Text.new(text) + i18n_text.extract_messages do |part| + @po.add(entry(part[:paragraph], options)) + end + end + + def entry msgid, options + RDoc::Generator::POT::POEntry.new(msgid, options) + end + +end diff --git a/jni/ruby/lib/rdoc/generator/pot/po.rb b/jni/ruby/lib/rdoc/generator/pot/po.rb new file mode 100644 index 0000000..6a6b582 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/pot/po.rb @@ -0,0 +1,83 @@ +## +# Generates a PO format text + +class RDoc::Generator::POT::PO + + ## + # Creates an object that represents PO format. + + def initialize + @entries = {} + add_header + end + + ## + # Adds a PO entry to the PO. + + def add entry + existing_entry = @entries[entry.msgid] + if existing_entry + entry = existing_entry.merge(entry) + end + @entries[entry.msgid] = entry + end + + ## + # Returns PO format text for the PO. + + def to_s + po = '' + sort_entries.each do |entry| + po << "\n" unless po.empty? + po << entry.to_s + end + po + end + + private + + def add_header + add(header_entry) + end + + def header_entry + comment = <<-COMMENT +SOME DESCRIPTIVE TITLE. +Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +This file is distributed under the same license as the PACKAGE package. +FIRST AUTHOR , YEAR. + COMMENT + + content = <<-CONTENT +Project-Id-Version: PACKAGE VERSEION +Report-Msgid-Bugs-To: +PO-Revision-Date: YEAR-MO_DA HO:MI+ZONE +Last-Translator: FULL NAME +Language-Team: LANGUAGE +Language: +MIME-Version: 1.0 +Content-Type: text/plain; charset=CHARSET +Content-Transfer-Encoding: 8bit +Plural-Forms: nplurals=INTEGER; plural=EXPRESSION; + CONTENT + + options = { + :msgstr => content, + :translator_comment => comment, + :flags => ['fuzzy'], + } + RDoc::Generator::POT::POEntry.new('', options) + end + + def sort_entries + headers, messages = @entries.values.partition do |entry| + entry.msgid.empty? + end + # TODO: sort by location + sorted_messages = messages.sort_by do |entry| + entry.msgid + end + headers + sorted_messages + end + +end diff --git a/jni/ruby/lib/rdoc/generator/pot/po_entry.rb b/jni/ruby/lib/rdoc/generator/pot/po_entry.rb new file mode 100644 index 0000000..d4cef59 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/pot/po_entry.rb @@ -0,0 +1,140 @@ +## +# A PO entry in PO + +class RDoc::Generator::POT::POEntry + + # The msgid content + attr_reader :msgid + + # The msgstr content + attr_reader :msgstr + + # The comment content created by translator (PO editor) + attr_reader :translator_comment + + # The comment content extracted from source file + attr_reader :extracted_comment + + # The locations where the PO entry is extracted + attr_reader :references + + # The flags of the PO entry + attr_reader :flags + + ## + # Creates a PO entry for +msgid+. Other valus can be specified by + # +options+. + + def initialize msgid, options = {} + @msgid = msgid + @msgstr = options[:msgstr] || "" + @translator_comment = options[:translator_comment] + @extracted_comment = options[:extracted_comment] + @references = options[:references] || [] + @flags = options[:flags] || [] + end + + ## + # Returns the PO entry in PO format. + + def to_s + entry = '' + entry << format_translator_comment + entry << format_extracted_comment + entry << format_references + entry << format_flags + entry << <<-ENTRY +msgid #{format_message(@msgid)} +msgstr #{format_message(@msgstr)} + ENTRY + end + + ## + # Merges the PO entry with +other_entry+. + + def merge other_entry + options = { + :extracted_comment => merge_string(@extracted_comment, + other_entry.extracted_comment), + :translator_comment => merge_string(@translator_comment, + other_entry.translator_comment), + :references => merge_array(@references, + other_entry.references), + :flags => merge_array(@flags, + other_entry.flags), + } + self.class.new(@msgid, options) + end + + private + + def format_comment mark, comment + return '' unless comment + return '' if comment.empty? + + formatted_comment = '' + comment.each_line do |line| + formatted_comment << "#{mark} #{line}" + end + formatted_comment << "\n" unless formatted_comment.end_with?("\n") + formatted_comment + end + + def format_translator_comment + format_comment('#', @translator_comment) + end + + def format_extracted_comment + format_comment('#.', @extracted_comment) + end + + def format_references + return '' if @references.empty? + + formatted_references = '' + @references.sort.each do |file, line| + formatted_references << "\#: #{file}:#{line}\n" + end + formatted_references + end + + def format_flags + return '' if @flags.empty? + + formatted_flags = flags.join(",") + "\#, #{formatted_flags}\n" + end + + def format_message message + return "\"#{escape(message)}\"" unless message.include?("\n") + + formatted_message = '""' + message.each_line do |line| + formatted_message << "\n" + formatted_message << "\"#{escape(line)}\"" + end + formatted_message + end + + def escape string + string.gsub(/["\\\t\n]/) do |special_character| + case special_character + when "\t" + "\\t" + when "\n" + "\\n" + else + "\\#{special_character}" + end + end + end + + def merge_string string1, string2 + [string1, string2].compact.join("\n") + end + + def merge_array array1, array2 + (array1 + array2).uniq + end + +end diff --git a/jni/ruby/lib/rdoc/generator/ri.rb b/jni/ruby/lib/rdoc/generator/ri.rb new file mode 100644 index 0000000..b9c4141 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/ri.rb @@ -0,0 +1,30 @@ +## +# Generates ri data files + +class RDoc::Generator::RI + + RDoc::RDoc.add_generator self + + ## + # Description of this generator + + DESCRIPTION = 'creates ri data files' + + ## + # Set up a new ri generator + + def initialize store, options #:not-new: + @options = options + @store = store + @store.path = '.' + end + + ## + # Writes the parsed data store to disk for use by ri. + + def generate + @store.save + end + +end + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/.document b/jni/ruby/lib/rdoc/generator/template/darkfish/.document new file mode 100644 index 0000000..e69de29 diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_footer.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_footer.rhtml new file mode 100644 index 0000000..fe5822c --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_footer.rhtml @@ -0,0 +1,5 @@ + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_head.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_head.rhtml new file mode 100644 index 0000000..70f1c18 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_head.rhtml @@ -0,0 +1,19 @@ + + +<%= h @title %> + + + + + + + + +<% if @options.template_stylesheets.flatten.any? then %> +<% @options.template_stylesheets.flatten.each do |stylesheet| %> + +<% end %> +<% end %> + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml new file mode 100644 index 0000000..e889f80 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml @@ -0,0 +1,19 @@ +<% if !svninfo.empty? then %> + +<% end %> diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml new file mode 100644 index 0000000..fe54d83 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml @@ -0,0 +1,9 @@ + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml new file mode 100644 index 0000000..2bd8efe --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml @@ -0,0 +1,15 @@ +<% unless klass.extends.empty? then %> + +<% end %> diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml new file mode 100644 index 0000000..0ba1d2b --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml @@ -0,0 +1,9 @@ + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml new file mode 100644 index 0000000..d141098 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml @@ -0,0 +1,15 @@ +<% unless klass.includes.empty? then %> + +<% end %> diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml new file mode 100644 index 0000000..1285bfd --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml @@ -0,0 +1,15 @@ + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml new file mode 100644 index 0000000..45df08d --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml @@ -0,0 +1,12 @@ +<% unless klass.method_list.empty? then %> + + +<% end %> diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml new file mode 100644 index 0000000..d7f3308 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml @@ -0,0 +1,11 @@ + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml new file mode 100644 index 0000000..5f39825 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml @@ -0,0 +1,12 @@ +<% simple_files = @files.select { |f| f.text? } %> +<% unless simple_files.empty? then %> + +<% end %> diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml new file mode 100644 index 0000000..cc04852 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml @@ -0,0 +1,11 @@ +<% if klass.type == 'class' then %> + +<% end %> diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml new file mode 100644 index 0000000..9c49b31 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml @@ -0,0 +1,14 @@ + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml new file mode 100644 index 0000000..15ff78b --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml @@ -0,0 +1,11 @@ +<% unless klass.sections.length == 1 then %> + +<% end %> diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml new file mode 100644 index 0000000..b58e6b3 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml @@ -0,0 +1,18 @@ +<% comment = if current.respond_to? :comment_location then + current.comment_location + else + current.comment + end + table = current.parse(comment).table_of_contents + + if table.length > 1 then %> + +<% end %> diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/class.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/class.rhtml new file mode 100644 index 0000000..b497000 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/class.rhtml @@ -0,0 +1,174 @@ + + + +
+

+ <%= klass.type %> <%= klass.full_name %> +

+ +
+ <%= klass.description %> +
+ + <% klass.each_section do |section, constants, attributes| %> + <% constants = constants.select { |const| const.display? } %> + <% attributes = attributes.select { |attr| attr.display? } %> +
+ <% if section.title then %> +
+

+ <%= section.title %> +

+ + ↑ top + +
+ <% end %> + + <% if section.comment then %> +
+ <%= section.description %> +
+ <% end %> + + <% unless constants.empty? then %> +
+
+

Constants

+
+
+ <% constants.each do |const| %> +
<%= const.name %> + <% if const.comment then %> +
<%= const.description.strip %> + <% else %> +
(Not documented) + <% end %> + <% end %> +
+
+ <% end %> + + <% unless attributes.empty? then %> +
+
+

Attributes

+
+ + <% attributes.each do |attrib| %> +
+
+ <%= h attrib.name %>[<%= attrib.rw %>] +
+ +
+ <% if attrib.comment then %> + <%= attrib.description.strip %> + <% else %> +

(Not documented) + <% end %> +

+
+ <% end %> +
+ <% end %> + + <% klass.methods_by_type(section).each do |type, visibilities| + next if visibilities.empty? + visibilities.each do |visibility, methods| + next if methods.empty? %> +
+
+

<%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods

+
+ + <% methods.each do |method| %> +
"> + <% if method.call_seq then %> + <% method.call_seq.strip.split("\n").each_with_index do |call_seq, i| %> +
+ + <%= h(call_seq.strip. + gsub( /^\w+\./m, '')). + gsub(/(.*)[-=]>/, '\1→') %> + + <% if i == 0 and method.token_stream then %> + click to toggle source + <% end %> +
+ <% end %> + <% else %> +
+ <%= h method.name %><%= method.param_seq %> + <% if method.token_stream then %> + click to toggle source + <% end %> +
+ <% end %> + +
+ <% if method.comment then %> + <%= method.description.strip %> + <% else %> +

(Not documented) + <% end %> + <% if method.calls_super then %> +

+ Calls superclass method + <%= + method.superclass_method ? + method.formatter.link(method.superclass_method.full_name, method.superclass_method.full_name) : nil + %> +
+ <% end %> + + <% if method.token_stream then %> +
+
<%= method.markup_code %>
+
+ <% end %> +
+ + <% unless method.aliases.empty? then %> +
+ Also aliased as: <%= method.aliases.map do |aka| + if aka.parent then # HACK lib/rexml/encodings + %{#{h aka.name}} + else + h aka.name + end + end.join ", " %> +
+ <% end %> + + <% if method.is_alias_for then %> + + <% end %> +
+ + <% end %> +
+ <% end + end %> +
+<% end %> +
diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/css/fonts.css b/jni/ruby/lib/rdoc/generator/template/darkfish/css/fonts.css new file mode 100644 index 0000000..e9e7211 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/css/fonts.css @@ -0,0 +1,167 @@ +/* + * Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + * with Reserved Font Name "Source". All Rights Reserved. Source is a + * trademark of Adobe Systems Incorporated in the United States and/or other + * countries. + * + * This Font Software is licensed under the SIL Open Font License, Version + * 1.1. + * + * This license is copied below, and is also available with a FAQ at: + * http://scripts.sil.org/OFL + */ + +@font-face { + font-family: "Source Code Pro"; + font-style: normal; + font-weight: 400; + src: local("Source Code Pro"), + local("SourceCodePro-Regular"), + url("fonts/SourceCodePro-Regular.ttf") format("truetype"); +} + +@font-face { + font-family: "Source Code Pro"; + font-style: normal; + font-weight: 700; + src: local("Source Code Pro Bold"), + local("SourceCodePro-Bold"), + url("fonts/SourceCodePro-Bold.ttf") format("truetype"); +} + +/* + * Copyright (c) 2010, Łukasz Dziedzic (dziedzic@typoland.com), + * with Reserved Font Name Lato. + * + * This Font Software is licensed under the SIL Open Font License, Version + * 1.1. + * + * This license is copied below, and is also available with a FAQ at: + * http://scripts.sil.org/OFL + */ + +@font-face { + font-family: "Lato"; + font-style: normal; + font-weight: 300; + src: local("Lato Light"), + local("Lato-Light"), + url("fonts/Lato-Light.ttf") format("truetype"); +} + +@font-face { + font-family: "Lato"; + font-style: italic; + font-weight: 300; + src: local("Lato Light Italic"), + local("Lato-LightItalic"), + url("fonts/Lato-LightItalic.ttf") format("truetype"); +} + +@font-face { + font-family: "Lato"; + font-style: normal; + font-weight: 700; + src: local("Lato Regular"), + local("Lato-Regular"), + url("fonts/Lato-Regular.ttf") format("truetype"); +} + +@font-face { + font-family: "Lato"; + font-style: italic; + font-weight: 700; + src: local("Lato Italic"), + local("Lato-Italic"), + url("fonts/Lato-RegularItalic.ttf") format("truetype"); +} + +/* + * ----------------------------------------------------------- + * SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 + * ----------------------------------------------------------- + * + * PREAMBLE + * The goals of the Open Font License (OFL) are to stimulate worldwide + * development of collaborative font projects, to support the font creation + * efforts of academic and linguistic communities, and to provide a free and + * open framework in which fonts may be shared and improved in partnership + * with others. + * + * The OFL allows the licensed fonts to be used, studied, modified and + * redistributed freely as long as they are not sold by themselves. The + * fonts, including any derivative works, can be bundled, embedded, + * redistributed and/or sold with any software provided that any reserved + * names are not used by derivative works. The fonts and derivatives, + * however, cannot be released under any other type of license. The + * requirement for fonts to remain under this license does not apply + * to any document created using the fonts or their derivatives. + * + * DEFINITIONS + * "Font Software" refers to the set of files released by the Copyright + * Holder(s) under this license and clearly marked as such. This may + * include source files, build scripts and documentation. + * + * "Reserved Font Name" refers to any names specified as such after the + * copyright statement(s). + * + * "Original Version" refers to the collection of Font Software components as + * distributed by the Copyright Holder(s). + * + * "Modified Version" refers to any derivative made by adding to, deleting, + * or substituting -- in part or in whole -- any of the components of the + * Original Version, by changing formats or by porting the Font Software to a + * new environment. + * + * "Author" refers to any designer, engineer, programmer, technical + * writer or other person who contributed to the Font Software. + * + * PERMISSION & CONDITIONS + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of the Font Software, to use, study, copy, merge, embed, modify, + * redistribute, and sell modified and unmodified copies of the Font + * Software, subject to the following conditions: + * + * 1) Neither the Font Software nor any of its individual components, + * in Original or Modified Versions, may be sold by itself. + * + * 2) Original or Modified Versions of the Font Software may be bundled, + * redistributed and/or sold with any software, provided that each copy + * contains the above copyright notice and this license. These can be + * included either as stand-alone text files, human-readable headers or + * in the appropriate machine-readable metadata fields within text or + * binary files as long as those fields can be easily viewed by the user. + * + * 3) No Modified Version of the Font Software may use the Reserved Font + * Name(s) unless explicit written permission is granted by the corresponding + * Copyright Holder. This restriction only applies to the primary font name as + * presented to the users. + * + * 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + * Software shall not be used to promote, endorse or advertise any + * Modified Version, except to acknowledge the contribution(s) of the + * Copyright Holder(s) and the Author(s) or with their explicit written + * permission. + * + * 5) The Font Software, modified or unmodified, in part or in whole, + * must be distributed entirely under this license, and must not be + * distributed under any other license. The requirement for fonts to + * remain under this license does not apply to any document created + * using the Font Software. + * + * TERMINATION + * This license becomes null and void if any of the above conditions are + * not met. + * + * DISCLAIMER + * THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL + * DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM + * OTHER DEALINGS IN THE FONT SOFTWARE. + */ + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/css/rdoc.css b/jni/ruby/lib/rdoc/generator/template/darkfish/css/rdoc.css new file mode 100644 index 0000000..2f4dca7 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/css/rdoc.css @@ -0,0 +1,590 @@ +/* + * "Darkfish" Rdoc CSS + * $Id: rdoc.css 54 2009-01-27 01:09:48Z deveiant $ + * + * Author: Michael Granger + * + */ + +/* vim: ft=css et sw=2 ts=2 sts=2 */ +/* Base Green is: #6C8C22 */ + +* { padding: 0; margin: 0; } + +body { + background: #fafafa; + font-family: Lato, sans-serif; + font-weight: 300; +} + +h1 span, +h2 span, +h3 span, +h4 span, +h5 span, +h6 span { + position: relative; + + display: none; + padding-left: 1em; + line-height: 0; + vertical-align: baseline; + font-size: 10px; +} + +h1 span { top: -1.3em; } +h2 span { top: -1.2em; } +h3 span { top: -1.0em; } +h4 span { top: -0.8em; } +h5 span { top: -0.5em; } +h6 span { top: -0.5em; } + +h1:hover span, +h2:hover span, +h3:hover span, +h4:hover span, +h5:hover span, +h6:hover span { + display: inline; +} + +:link, +:visited { + color: #6C8C22; + text-decoration: none; +} + +:link:hover, +:visited:hover { + border-bottom: 1px dotted #6C8C22; +} + +code, +pre { + font-family: "Source Code Pro", Monaco, monospace; +} + +/* @group Generic Classes */ + +.initially-hidden { + display: none; +} + +#search-field { + width: 98%; + background: white; + border: none; + height: 1.5em; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + text-align: left; +} +#search-field:focus { + background: #f1edba; +} +#search-field:-moz-placeholder, +#search-field::-webkit-input-placeholder { + font-weight: bold; + color: #666; +} + +.missing-docs { + font-size: 120%; + background: white url(images/wrench_orange.png) no-repeat 4px center; + color: #ccc; + line-height: 2em; + border: 1px solid #d00; + opacity: 1; + padding-left: 20px; + text-indent: 24px; + letter-spacing: 3px; + font-weight: bold; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; +} + +.target-section { + border: 2px solid #dcce90; + border-left-width: 8px; + padding: 0 1em; + background: #fff3c2; +} + +/* @end */ + +/* @group Index Page, Standalone file pages */ +.table-of-contents ul { + margin: 1em; + list-style: none; +} + +.table-of-contents ul ul { + margin-top: 0.25em; +} + +.table-of-contents ul :link, +.table-of-contents ul :visited { + font-size: 16px; +} + +.table-of-contents li { + margin-bottom: 0.25em; +} + +.table-of-contents li .toc-toggle { + width: 16px; + height: 16px; + background: url(images/add.png) no-repeat; +} + +.table-of-contents li .toc-toggle.open { + background: url(images/delete.png) no-repeat; +} + +/* @end */ + +/* @group Top-Level Structure */ + +nav { + float: left; + width: 260px; + font-family: Helvetica, sans-serif; + font-size: 14px; +} + +main { + display: block; + margin: 0 2em 5em 260px; + padding-left: 20px; + min-width: 340px; + font-size: 16px; +} + +main h1, +main h2, +main h3, +main h4, +main h5, +main h6 { + font-family: Helvetica, sans-serif; +} + +.table-of-contents main { + margin-left: 2em; +} + +#validator-badges { + clear: both; + margin: 1em 1em 2em; + font-size: smaller; +} + +/* @end */ + +/* @group navigation */ +nav { + margin-bottom: 1em; +} + +nav .nav-section { + margin-top: 2em; + border-top: 2px solid #aaa; + font-size: 90%; + overflow: hidden; +} + +nav h2 { + margin: 0; + padding: 2px 8px 2px 8px; + background-color: #e8e8e8; + color: #555; + font-size: 125%; + text-align: center; +} + +nav h3, +#table-of-contents-navigation { + margin: 0; + padding: 2px 8px 2px 8px; + text-align: right; + background-color: #e8e8e8; + color: #555; +} + +nav ul, +nav dl, +nav p { + padding: 4px 8px 0; + list-style: none; +} + +#project-navigation .nav-section { + margin: 0; + border-top: 0; +} + +#home-section h2 { + text-align: center; +} + +#table-of-contents-navigation { + font-size: 1.2em; + font-weight: bold; + text-align: center; +} + +#search-section { + margin-top: 0; + border-top: 0; +} + +#search-field-wrapper { + border-top: 1px solid #aaa; + border-bottom: 1px solid #aaa; + padding: 3px 8px; + background-color: #e8e8e8; + color: #555; +} + +ul.link-list li { + white-space: nowrap; + line-height: 1.4em; +} + +ul.link-list .type { + font-size: 8px; + text-transform: uppercase; + color: white; + background: #969696; + padding: 2px 4px; + -webkit-border-radius: 5px; +} + +.calls-super { + background: url(images/arrow_up.png) no-repeat right center; +} + +/* @end */ + +/* @group Documentation Section */ +main { + color: #333; +} + +main > h1:first-child, +main > h2:first-child, +main > h3:first-child, +main > h4:first-child, +main > h5:first-child, +main > h6:first-child { + margin-top: 0px; +} + +main sup { + vertical-align: super; + font-size: 0.8em; +} + +/* The heading with the class name */ +main h1[class] { + margin-top: 0; + margin-bottom: 1em; + font-size: 2em; + color: #6C8C22; +} + +main h1 { + margin: 2em 0 0.5em; + font-size: 1.7em; +} + +main h2 { + margin: 2em 0 0.5em; + font-size: 1.5em; +} + +main h3 { + margin: 2em 0 0.5em; + font-size: 1.2em; +} + +main h4 { + margin: 2em 0 0.5em; + font-size: 1.1em; +} + +main h5 { + margin: 2em 0 0.5em; + font-size: 1em; +} + +main h6 { + margin: 2em 0 0.5em; + font-size: 1em; +} + +main p { + margin: 0 0 0.5em; + line-height: 1.4em; +} + +main pre { + margin: 1.2em 0.5em; + padding: 1em; + font-size: 0.8em; +} + +main hr { + margin: 1.5em 1em; + border: 2px solid #ddd; +} + +main blockquote { + margin: 0 2em 1.2em 1.2em; + padding-left: 0.5em; + border-left: 2px solid #ddd; +} + +main ol, +main ul { + margin: 1em 2em; +} + +main li > p { + margin-bottom: 0.5em; +} + +main dl { + margin: 1em 0.5em; +} + +main dt { + margin-bottom: 0.5em; + font-weight: bold; +} + +main dd { + margin: 0 1em 1em 0.5em; +} + +main header h2 { + margin-top: 2em; + border-width: 0; + border-top: 4px solid #bbb; + font-size: 130%; +} + +main header h3 { + margin: 2em 0 1.5em; + border-width: 0; + border-top: 3px solid #bbb; + font-size: 120%; +} + +.documentation-section-title { + position: relative; +} +.documentation-section-title .section-click-top { + position: absolute; + top: 6px; + left: 12px; + font-size: 10px; + color: #9b9877; + visibility: hidden; + padding-left: 0.5px; +} + +.documentation-section-title:hover .section-click-top { + visibility: visible; +} + +.constants-list > dl { + margin: 1em 0 2em; + border: 0; +} + +.constants-list > dl dt { + margin-bottom: 0.75em; + padding-left: 0; + font-family: "Source Code Pro", Monaco, monospace; + font-size: 110%; +} + +.constants-list > dl dt a { + color: inherit; +} + +.constants-list > dl dd { + margin: 0 0 2em 0; + padding: 0; + color: #666; +} + +.documentation-section h2 { + position: relative; +} + +.documentation-section h2 a { + position: absolute; + top: 8px; + right: 10px; + font-size: 12px; + color: #9b9877; + visibility: hidden; +} + +.documentation-section h2:hover a { + visibility: visible; +} + +/* @group Method Details */ + +main .method-source-code { + display: none; +} + +main .method-description .method-calls-super { + color: #333; + font-weight: bold; +} + +main .method-detail { + margin-bottom: 2.5em; + cursor: pointer; +} + +main .method-detail:target { + margin-left: -10px; + border-left: 10px solid #f1edba; +} + +main .method-heading { + position: relative; + font-family: "Source Code Pro", Monaco, monospace; + font-size: 110%; + font-weight: bold; + color: #333; +} +main .method-heading :link, +main .method-heading :visited { + color: inherit; +} +main .method-click-advice { + position: absolute; + top: 2px; + right: 5px; + font-size: 12px; + color: #9b9877; + visibility: hidden; + padding-right: 20px; + line-height: 20px; + background: url(images/zoom.png) no-repeat right top; +} +main .method-heading:hover .method-click-advice { + visibility: visible; +} + +main .method-alias .method-heading { + color: #666; +} + +main .method-description, +main .aliases { + margin-top: 0.75em; + color: #333; +} + +main .aliases { + padding-top: 4px; + font-style: italic; + cursor: default; +} +main .method-description ul { + margin-left: 1.5em; +} + +main #attribute-method-details .method-detail:hover { + background-color: transparent; + cursor: default; +} +main .attribute-access-type { + text-transform: uppercase; + padding: 0 1em; +} +/* @end */ + +/* @end */ + +/* @group Source Code */ + +pre { + margin: 0.5em 0; + border: 1px dashed #999; + padding: 0.5em; + background: #262626; + color: white; + overflow: auto; +} + +.ruby-constant { color: #7fffd4; background: transparent; } +.ruby-keyword { color: #00ffff; background: transparent; } +.ruby-ivar { color: #eedd82; background: transparent; } +.ruby-operator { color: #00ffee; background: transparent; } +.ruby-identifier { color: #ffdead; background: transparent; } +.ruby-node { color: #ffa07a; background: transparent; } +.ruby-comment { color: #dc0000; background: transparent; } +.ruby-regexp { color: #ffa07a; background: transparent; } +.ruby-value { color: #7fffd4; background: transparent; } + +/* @end */ + + +/* @group search results */ +#search-results { + font-family: Lato, sans-serif; + font-weight: 300; +} + +#search-results .search-match { + font-family: Helvetica, sans-serif; + font-weight: normal; +} + +#search-results .search-selected { + background: #e8e8e8; + border-bottom: 1px solid transparent; +} + +#search-results li { + list-style: none; + border-bottom: 1px solid #aaa; + margin-bottom: 0.5em; +} + +#search-results li:last-child { + border-bottom: none; + margin-bottom: 0; +} + +#search-results li p { + padding: 0; + margin: 0.5em; +} + +#search-results .search-namespace { + font-weight: bold; +} + +#search-results li em { + background: yellow; + font-style: normal; +} + +#search-results pre { + margin: 0.5em; + font-family: "Source Code Pro", Monaco, monospace; +} + +/* @end */ + diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf new file mode 100644 index 0000000..b49dd43 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf new file mode 100644 index 0000000..7959fef Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf new file mode 100644 index 0000000..839cd58 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf new file mode 100644 index 0000000..bababa0 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf new file mode 100644 index 0000000..61e3090 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf new file mode 100644 index 0000000..85686d9 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/add.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/add.png new file mode 100644 index 0000000..6332fef Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/add.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/arrow_up.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/arrow_up.png new file mode 100644 index 0000000..1ebb193 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/arrow_up.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/brick.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/brick.png new file mode 100644 index 0000000..7851cf3 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/brick.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/brick_link.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/brick_link.png new file mode 100644 index 0000000..9ebf013 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/brick_link.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/bug.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/bug.png new file mode 100644 index 0000000..2d5fb90 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/bug.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_black.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_black.png new file mode 100644 index 0000000..5761970 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_black.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png new file mode 100644 index 0000000..b47ce55 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png new file mode 100644 index 0000000..9ab4a89 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/date.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/date.png new file mode 100644 index 0000000..783c833 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/date.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/delete.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/delete.png new file mode 100644 index 0000000..08f2493 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/delete.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/find.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/find.png new file mode 100644 index 0000000..1547479 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/find.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif b/jni/ruby/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif new file mode 100644 index 0000000..82290f4 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png new file mode 100644 index 0000000..c6473b3 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/package.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/package.png new file mode 100644 index 0000000..da3c2a2 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/package.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/page_green.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/page_green.png new file mode 100644 index 0000000..de8e003 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/page_green.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/page_white_text.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/page_white_text.png new file mode 100644 index 0000000..813f712 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/page_white_text.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/page_white_width.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/page_white_width.png new file mode 100644 index 0000000..1eb8809 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/page_white_width.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/plugin.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/plugin.png new file mode 100644 index 0000000..6187b15 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/plugin.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/ruby.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/ruby.png new file mode 100644 index 0000000..f763a16 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/ruby.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/tag_blue.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/tag_blue.png new file mode 100644 index 0000000..3f02b5f Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/tag_blue.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/tag_green.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/tag_green.png new file mode 100644 index 0000000..83ec984 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/tag_green.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/transparent.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/transparent.png new file mode 100644 index 0000000..d665e17 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/transparent.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/wrench.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/wrench.png new file mode 100644 index 0000000..5c8213f Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/wrench.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/wrench_orange.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/wrench_orange.png new file mode 100644 index 0000000..565a933 Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/wrench_orange.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/images/zoom.png b/jni/ruby/lib/rdoc/generator/template/darkfish/images/zoom.png new file mode 100644 index 0000000..908612e Binary files /dev/null and b/jni/ruby/lib/rdoc/generator/template/darkfish/images/zoom.png differ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/index.rhtml b/jni/ruby/lib/rdoc/generator/template/darkfish/index.rhtml new file mode 100644 index 0000000..7d1c748 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/index.rhtml @@ -0,0 +1,23 @@ + + + +
+<% if @options.main_page and + main_page = @files.find { |f| f.full_name == @options.main_page } then %> +<%= main_page.description %> +<% else %> +

This is the API documentation for <%= @title %>. +<% end %> +

+ diff --git a/jni/ruby/lib/rdoc/generator/template/darkfish/js/darkfish.js b/jni/ruby/lib/rdoc/generator/template/darkfish/js/darkfish.js new file mode 100644 index 0000000..b789a65 --- /dev/null +++ b/jni/ruby/lib/rdoc/generator/template/darkfish/js/darkfish.js @@ -0,0 +1,161 @@ +/** + * + * Darkfish Page Functions + * $Id: darkfish.js 53 2009-01-07 02:52:03Z deveiant $ + * + * Author: Michael Granger + * + */ + +/* Provide console simulation for firebug-less environments */ +if (!("console" in window) || !("firebug" in console)) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", + "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; + + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +}; + + +/** + * Unwrap the first element that matches the given @expr@ from the targets and return them. + */ +$.fn.unwrap = function( expr ) { + return this.each( function() { + $(this).parents( expr ).eq( 0 ).after( this ).remove(); + }); +}; + + +function showSource( e ) { + var target = e.target; + var codeSections = $(target). + parents('.method-detail'). + find('.method-source-code'); + + $(target). + parents('.method-detail'). + find('.method-source-code'). + slideToggle(); +}; + +function hookSourceViews() { + $('.method-heading').click( showSource ); +}; + +function hookSearch() { + var input = $('#search-field').eq(0); + var result = $('#search-results').eq(0); + $(result).show(); + + var search_section = $('#search-section').get(0); + $(search_section).show(); + + var search = new Search(search_data, input, result); + + search.renderItem = function(result) { + var li = document.createElement('li'); + var html = ''; + + // TODO add relative path to