From 1c279a7d2753949c725754e1302f791b76358114 Mon Sep 17 00:00:00 2001 From: drbrain Date: Tue, 27 Nov 2012 04:28:14 +0000 Subject: * lib/rdoc*: Updated to RDoc 4.0 (pre-release) * bin/rdoc: ditto * test/rdoc: ditto * NEWS: Updated with RDoc 4.0 information git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37889 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- .../Amps and angle encoding.text | 21 + test/rdoc/MarkdownTest_1.0.3/Auto links.text | 13 + .../rdoc/MarkdownTest_1.0.3/Backslash escapes.text | 120 ++ .../Blockquotes with code blocks.text | 11 + test/rdoc/MarkdownTest_1.0.3/Code Blocks.text | 14 + test/rdoc/MarkdownTest_1.0.3/Code Spans.text | 6 + ...rd-wrapped paragraphs with list-like lines.text | 8 + test/rdoc/MarkdownTest_1.0.3/Horizontal rules.text | 67 + .../MarkdownTest_1.0.3/Inline HTML (Advanced).text | 15 + .../MarkdownTest_1.0.3/Inline HTML (Simple).text | 69 + .../MarkdownTest_1.0.3/Inline HTML comments.text | 13 + .../MarkdownTest_1.0.3/Links, inline style.text | 12 + .../MarkdownTest_1.0.3/Links, reference style.text | 71 + .../Links, shortcut references.text | 20 + .../Literal quotes in titles.text | 7 + .../Markdown Documentation - Basics.text | 306 ++++ .../Markdown Documentation - Syntax.text | 888 +++++++++ .../MarkdownTest_1.0.3/Nested blockquotes.text | 5 + .../Ordered and unordered lists.text | 131 ++ .../MarkdownTest_1.0.3/Strong and em together.text | 7 + test/rdoc/MarkdownTest_1.0.3/Tabs.text | 21 + test/rdoc/MarkdownTest_1.0.3/Tidyness.text | 5 + test/rdoc/test.ja.large.rdoc | 3 + test/rdoc/test.ja.largedoc | 3 - test/rdoc/test_attribute_manager.rb | 66 +- test/rdoc/test_rdoc_any_method.rb | 134 +- test/rdoc/test_rdoc_attr.rb | 85 +- test/rdoc/test_rdoc_class_module.rb | 855 ++++++++- test/rdoc/test_rdoc_code_object.rb | 35 +- test/rdoc/test_rdoc_comment.rb | 504 ++++++ test/rdoc/test_rdoc_constant.rb | 132 ++ test/rdoc/test_rdoc_context.rb | 230 ++- test/rdoc/test_rdoc_context_section.rb | 123 +- test/rdoc/test_rdoc_cross_reference.rb | 28 +- test/rdoc/test_rdoc_encoding.rb | 27 +- test/rdoc/test_rdoc_extend.rb | 94 + test/rdoc/test_rdoc_generator_darkfish.rb | 110 +- test/rdoc/test_rdoc_generator_json_index.rb | 275 +++ test/rdoc/test_rdoc_generator_markup.rb | 56 + test/rdoc/test_rdoc_generator_ri.rb | 39 +- test/rdoc/test_rdoc_include.rb | 12 + test/rdoc/test_rdoc_markdown.rb | 977 ++++++++++ test/rdoc/test_rdoc_markdown_test.rb | 1891 ++++++++++++++++++++ test/rdoc/test_rdoc_markup.rb | 16 +- test/rdoc/test_rdoc_markup_attribute_manager.rb | 17 +- test/rdoc/test_rdoc_markup_attributes.rb | 39 + test/rdoc/test_rdoc_markup_document.rb | 55 +- test/rdoc/test_rdoc_markup_formatter.rb | 29 +- test/rdoc/test_rdoc_markup_hard_break.rb | 31 + test/rdoc/test_rdoc_markup_heading.rb | 20 + test/rdoc/test_rdoc_markup_include.rb | 19 + test/rdoc/test_rdoc_markup_indented_paragraph.rb | 23 +- test/rdoc/test_rdoc_markup_paragraph.rb | 23 +- test/rdoc/test_rdoc_markup_parser.rb | 381 +++- test/rdoc/test_rdoc_markup_pre_process.rb | 69 +- test/rdoc/test_rdoc_markup_raw.rb | 14 +- test/rdoc/test_rdoc_markup_to_ansi.rb | 49 +- test/rdoc/test_rdoc_markup_to_bs.rb | 33 +- test/rdoc/test_rdoc_markup_to_html.rb | 259 ++- test/rdoc/test_rdoc_markup_to_html_crossref.rb | 142 +- test/rdoc/test_rdoc_markup_to_html_snippet.rb | 710 ++++++++ test/rdoc/test_rdoc_markup_to_joined_paragraph.rb | 32 + test/rdoc/test_rdoc_markup_to_label.rb | 112 ++ test/rdoc/test_rdoc_markup_to_markdown.rb | 352 ++++ test/rdoc/test_rdoc_markup_to_rdoc.rb | 48 +- test/rdoc/test_rdoc_markup_to_table_of_contents.rb | 95 + test/rdoc/test_rdoc_markup_to_tt_only.rb | 25 +- test/rdoc/test_rdoc_markup_verbatim.rb | 29 + test/rdoc/test_rdoc_method_attr.rb | 35 +- test/rdoc/test_rdoc_normal_class.rb | 29 +- test/rdoc/test_rdoc_normal_module.rb | 2 +- test/rdoc/test_rdoc_options.rb | 232 ++- test/rdoc/test_rdoc_parser.rb | 121 +- test/rdoc/test_rdoc_parser_c.rb | 377 ++-- test/rdoc/test_rdoc_parser_markdown.rb | 55 + test/rdoc/test_rdoc_parser_rd.rb | 52 + test/rdoc/test_rdoc_parser_ruby.rb | 1152 ++++++++---- test/rdoc/test_rdoc_parser_simple.rb | 54 +- test/rdoc/test_rdoc_rd.rb | 30 + test/rdoc/test_rdoc_rd_block_parser.rb | 523 ++++++ test/rdoc/test_rdoc_rd_inline.rb | 63 + test/rdoc/test_rdoc_rd_inline_parser.rb | 173 ++ test/rdoc/test_rdoc_rdoc.rb | 203 ++- test/rdoc/test_rdoc_ri_driver.rb | 489 ++++- test/rdoc/test_rdoc_ri_paths.rb | 150 +- test/rdoc/test_rdoc_ri_store.rb | 473 ----- test/rdoc/test_rdoc_ruby_lex.rb | 222 ++- test/rdoc/test_rdoc_ruby_token.rb | 19 + test/rdoc/test_rdoc_rubygems_hook.rb | 7 +- test/rdoc/test_rdoc_servlet.rb | 408 +++++ test/rdoc/test_rdoc_stats.rb | 352 ++-- test/rdoc/test_rdoc_store.rb | 824 +++++++++ test/rdoc/test_rdoc_task.rb | 17 +- test/rdoc/test_rdoc_text.rb | 193 +- test/rdoc/test_rdoc_token_stream.rb | 42 + test/rdoc/test_rdoc_tom_doc.rb | 455 +++++ test/rdoc/test_rdoc_top_level.rb | 227 +-- test/rdoc/xref_test_case.rb | 24 +- 98 files changed, 15139 insertions(+), 1995 deletions(-) create mode 100644 test/rdoc/MarkdownTest_1.0.3/Amps and angle encoding.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Auto links.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Backslash escapes.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Blockquotes with code blocks.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Code Blocks.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Code Spans.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Hard-wrapped paragraphs with list-like lines.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Horizontal rules.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Inline HTML (Advanced).text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Inline HTML (Simple).text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Inline HTML comments.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Links, inline style.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Links, reference style.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Links, shortcut references.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Literal quotes in titles.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Basics.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Nested blockquotes.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Ordered and unordered lists.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Strong and em together.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Tabs.text create mode 100644 test/rdoc/MarkdownTest_1.0.3/Tidyness.text create mode 100644 test/rdoc/test.ja.large.rdoc delete mode 100644 test/rdoc/test.ja.largedoc create mode 100644 test/rdoc/test_rdoc_comment.rb create mode 100644 test/rdoc/test_rdoc_extend.rb create mode 100644 test/rdoc/test_rdoc_generator_json_index.rb create mode 100644 test/rdoc/test_rdoc_generator_markup.rb create mode 100644 test/rdoc/test_rdoc_markdown.rb create mode 100644 test/rdoc/test_rdoc_markdown_test.rb create mode 100644 test/rdoc/test_rdoc_markup_attributes.rb create mode 100644 test/rdoc/test_rdoc_markup_hard_break.rb create mode 100644 test/rdoc/test_rdoc_markup_heading.rb create mode 100644 test/rdoc/test_rdoc_markup_include.rb create mode 100644 test/rdoc/test_rdoc_markup_to_html_snippet.rb create mode 100644 test/rdoc/test_rdoc_markup_to_joined_paragraph.rb create mode 100644 test/rdoc/test_rdoc_markup_to_label.rb create mode 100644 test/rdoc/test_rdoc_markup_to_markdown.rb create mode 100644 test/rdoc/test_rdoc_markup_to_table_of_contents.rb create mode 100644 test/rdoc/test_rdoc_markup_verbatim.rb create mode 100644 test/rdoc/test_rdoc_parser_markdown.rb create mode 100644 test/rdoc/test_rdoc_parser_rd.rb create mode 100644 test/rdoc/test_rdoc_rd.rb create mode 100644 test/rdoc/test_rdoc_rd_block_parser.rb create mode 100644 test/rdoc/test_rdoc_rd_inline.rb create mode 100644 test/rdoc/test_rdoc_rd_inline_parser.rb delete mode 100644 test/rdoc/test_rdoc_ri_store.rb create mode 100644 test/rdoc/test_rdoc_ruby_token.rb create mode 100644 test/rdoc/test_rdoc_servlet.rb create mode 100644 test/rdoc/test_rdoc_store.rb create mode 100644 test/rdoc/test_rdoc_token_stream.rb create mode 100644 test/rdoc/test_rdoc_tom_doc.rb (limited to 'test/rdoc') diff --git a/test/rdoc/MarkdownTest_1.0.3/Amps and angle encoding.text b/test/rdoc/MarkdownTest_1.0.3/Amps and angle encoding.text new file mode 100644 index 0000000000..0e9527f931 --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Amps and angle encoding.text @@ -0,0 +1,21 @@ +AT&T has an ampersand in their name. + +AT&T is another way to write it. + +This & that. + +4 < 5. + +6 > 5. + +Here's a [link] [1] with an ampersand in the URL. + +Here's a link with an amersand in the link text: [AT&T] [2]. + +Here's an inline [link](/script?foo=1&bar=2). + +Here's an inline [link](). + + +[1]: http://example.com/?foo=1&bar=2 +[2]: http://att.com/ "AT&T" \ No newline at end of file diff --git a/test/rdoc/MarkdownTest_1.0.3/Auto links.text b/test/rdoc/MarkdownTest_1.0.3/Auto links.text new file mode 100644 index 0000000000..abbc48869d --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Auto links.text @@ -0,0 +1,13 @@ +Link: . + +With an ampersand: + +* In a list? +* +* It should. + +> Blockquoted: + +Auto-links should not occur here: `` + + or here: \ No newline at end of file diff --git a/test/rdoc/MarkdownTest_1.0.3/Backslash escapes.text b/test/rdoc/MarkdownTest_1.0.3/Backslash escapes.text new file mode 100644 index 0000000000..5b014cb33d --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Backslash escapes.text @@ -0,0 +1,120 @@ +These should all get escaped: + +Backslash: \\ + +Backtick: \` + +Asterisk: \* + +Underscore: \_ + +Left brace: \{ + +Right brace: \} + +Left bracket: \[ + +Right bracket: \] + +Left paren: \( + +Right paren: \) + +Greater-than: \> + +Hash: \# + +Period: \. + +Bang: \! + +Plus: \+ + +Minus: \- + + + +These should not, because they occur within a code block: + + Backslash: \\ + + Backtick: \` + + Asterisk: \* + + Underscore: \_ + + Left brace: \{ + + Right brace: \} + + Left bracket: \[ + + Right bracket: \] + + Left paren: \( + + Right paren: \) + + Greater-than: \> + + Hash: \# + + Period: \. + + Bang: \! + + Plus: \+ + + Minus: \- + + +Nor should these, which occur in code spans: + +Backslash: `\\` + +Backtick: `` \` `` + +Asterisk: `\*` + +Underscore: `\_` + +Left brace: `\{` + +Right brace: `\}` + +Left bracket: `\[` + +Right bracket: `\]` + +Left paren: `\(` + +Right paren: `\)` + +Greater-than: `\>` + +Hash: `\#` + +Period: `\.` + +Bang: `\!` + +Plus: `\+` + +Minus: `\-` + + +These should get escaped, even though they're matching pairs for +other Markdown constructs: + +\*asterisks\* + +\_underscores\_ + +\`backticks\` + +This is a code span with a literal backslash-backtick sequence: `` \` `` + +This is a tag with unescaped backticks bar. + +This is a tag with backslashes bar. diff --git a/test/rdoc/MarkdownTest_1.0.3/Blockquotes with code blocks.text b/test/rdoc/MarkdownTest_1.0.3/Blockquotes with code blocks.text new file mode 100644 index 0000000000..c31d171049 --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Blockquotes with code blocks.text @@ -0,0 +1,11 @@ +> Example: +> +> sub status { +> print "working"; +> } +> +> Or: +> +> sub status { +> return "working"; +> } diff --git a/test/rdoc/MarkdownTest_1.0.3/Code Blocks.text b/test/rdoc/MarkdownTest_1.0.3/Code Blocks.text new file mode 100644 index 0000000000..b54b09285a --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Code Blocks.text @@ -0,0 +1,14 @@ + code block on the first line + +Regular text. + + code block indented by spaces + +Regular text. + + the lines in this block + all contain trailing spaces + +Regular Text. + + code block on the last line \ No newline at end of file diff --git a/test/rdoc/MarkdownTest_1.0.3/Code Spans.text b/test/rdoc/MarkdownTest_1.0.3/Code Spans.text new file mode 100644 index 0000000000..750a1973df --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Code Spans.text @@ -0,0 +1,6 @@ +`` + +Fix for backticks within HTML tag: like this + +Here's how you put `` `backticks` `` in a code span. + diff --git a/test/rdoc/MarkdownTest_1.0.3/Hard-wrapped paragraphs with list-like lines.text b/test/rdoc/MarkdownTest_1.0.3/Hard-wrapped paragraphs with list-like lines.text new file mode 100644 index 0000000000..f8a5b27bf4 --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Hard-wrapped paragraphs with list-like lines.text @@ -0,0 +1,8 @@ +In Markdown 1.0.0 and earlier. Version +8. This line turns into a list item. +Because a hard-wrapped line in the +middle of a paragraph looked like a +list item. + +Here's one with a bullet. +* criminey. diff --git a/test/rdoc/MarkdownTest_1.0.3/Horizontal rules.text b/test/rdoc/MarkdownTest_1.0.3/Horizontal rules.text new file mode 100644 index 0000000000..1594bda27b --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Horizontal rules.text @@ -0,0 +1,67 @@ +Dashes: + +--- + + --- + + --- + + --- + + --- + +- - - + + - - - + + - - - + + - - - + + - - - + + +Asterisks: + +*** + + *** + + *** + + *** + + *** + +* * * + + * * * + + * * * + + * * * + + * * * + + +Underscores: + +___ + + ___ + + ___ + + ___ + + ___ + +_ _ _ + + _ _ _ + + _ _ _ + + _ _ _ + + _ _ _ diff --git a/test/rdoc/MarkdownTest_1.0.3/Inline HTML (Advanced).text b/test/rdoc/MarkdownTest_1.0.3/Inline HTML (Advanced).text new file mode 100644 index 0000000000..86b7206d2a --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Inline HTML (Advanced).text @@ -0,0 +1,15 @@ +Simple block on one line: + +
foo
+ +And nested without indentation: + +
+
+
+foo +
+
+
+
bar
+
diff --git a/test/rdoc/MarkdownTest_1.0.3/Inline HTML (Simple).text b/test/rdoc/MarkdownTest_1.0.3/Inline HTML (Simple).text new file mode 100644 index 0000000000..14aa2dc272 --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Inline HTML (Simple).text @@ -0,0 +1,69 @@ +Here's a simple block: + +
+ foo +
+ +This should be a code block, though: + +
+ foo +
+ +As should this: + +
foo
+ +Now, nested: + +
+
+
+ foo +
+
+
+ +This should just be an HTML comment: + + + +Multiline: + + + +Code block: + + + +Just plain comment, with trailing spaces on the line: + + + +Code: + +
+ +Hr's: + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ diff --git a/test/rdoc/MarkdownTest_1.0.3/Inline HTML comments.text b/test/rdoc/MarkdownTest_1.0.3/Inline HTML comments.text new file mode 100644 index 0000000000..41d830d038 --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Inline HTML comments.text @@ -0,0 +1,13 @@ +Paragraph one. + + + + + +Paragraph two. + + + +The end. diff --git a/test/rdoc/MarkdownTest_1.0.3/Links, inline style.text b/test/rdoc/MarkdownTest_1.0.3/Links, inline style.text new file mode 100644 index 0000000000..09017a90c7 --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Links, inline style.text @@ -0,0 +1,12 @@ +Just a [URL](/url/). + +[URL and title](/url/ "title"). + +[URL and title](/url/ "title preceded by two spaces"). + +[URL and title](/url/ "title preceded by a tab"). + +[URL and title](/url/ "title has spaces afterward" ). + + +[Empty](). diff --git a/test/rdoc/MarkdownTest_1.0.3/Links, reference style.text b/test/rdoc/MarkdownTest_1.0.3/Links, reference style.text new file mode 100644 index 0000000000..341ec88e3d --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Links, reference style.text @@ -0,0 +1,71 @@ +Foo [bar] [1]. + +Foo [bar][1]. + +Foo [bar] +[1]. + +[1]: /url/ "Title" + + +With [embedded [brackets]] [b]. + + +Indented [once][]. + +Indented [twice][]. + +Indented [thrice][]. + +Indented [four][] times. + + [once]: /url + + [twice]: /url + + [thrice]: /url + + [four]: /url + + +[b]: /url/ + +* * * + +[this] [this] should work + +So should [this][this]. + +And [this] []. + +And [this][]. + +And [this]. + +But not [that] []. + +Nor [that][]. + +Nor [that]. + +[Something in brackets like [this][] should work] + +[Same with [this].] + +In this case, [this](/somethingelse/) points to something else. + +Backslashing should suppress \[this] and [this\]. + +[this]: foo + + +* * * + +Here's one where the [link +breaks] across lines. + +Here's another where the [link +breaks] across lines, but with a line-ending space. + + +[link breaks]: /url/ diff --git a/test/rdoc/MarkdownTest_1.0.3/Links, shortcut references.text b/test/rdoc/MarkdownTest_1.0.3/Links, shortcut references.text new file mode 100644 index 0000000000..8c44c98fee --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Links, shortcut references.text @@ -0,0 +1,20 @@ +This is the [simple case]. + +[simple case]: /simple + + + +This one has a [line +break]. + +This one has a [line +break] with a line-ending space. + +[line break]: /foo + + +[this] [that] and the [other] + +[this]: /this +[that]: /that +[other]: /other diff --git a/test/rdoc/MarkdownTest_1.0.3/Literal quotes in titles.text b/test/rdoc/MarkdownTest_1.0.3/Literal quotes in titles.text new file mode 100644 index 0000000000..29d0e4235b --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Literal quotes in titles.text @@ -0,0 +1,7 @@ +Foo [bar][]. + +Foo [bar](/url/ "Title with "quotes" inside"). + + + [bar]: /url/ "Title with "quotes" inside" + diff --git a/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Basics.text b/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Basics.text new file mode 100644 index 0000000000..486055ca7f --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Basics.text @@ -0,0 +1,306 @@ +Markdown: Basics +================ + + + + +Getting the Gist of Markdown's Formatting Syntax +------------------------------------------------ + +This page offers a brief overview of what it's like to use Markdown. +The [syntax page] [s] provides complete, detailed documentation for +every feature, but Markdown should be very easy to pick up simply by +looking at a few examples of it in action. The examples on this page +are written in a before/after style, showing example syntax and the +HTML output produced by Markdown. + +It's also helpful to simply try Markdown out; the [Dingus] [d] is a +web application that allows you type your own Markdown-formatted text +and translate it to XHTML. + +**Note:** This document is itself written using Markdown; you +can [see the source for it by adding '.text' to the URL] [src]. + + [s]: /projects/markdown/syntax "Markdown Syntax" + [d]: /projects/markdown/dingus "Markdown Dingus" + [src]: /projects/markdown/basics.text + + +## Paragraphs, Headers, Blockquotes ## + +A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks like a +blank line -- a line containing nothing spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs. + +Markdown offers two styles of headers: *Setext* and *atx*. +Setext-style headers for `

` and `

` are created by +"underlining" with equal signs (`=`) and hyphens (`-`), respectively. +To create an atx-style header, you put 1-6 hash marks (`#`) at the +beginning of the line -- the number of hashes equals the resulting +HTML header level. + +Blockquotes are indicated using email-style '`>`' angle brackets. + +Markdown: + + A First Level Header + ==================== + + A Second Level Header + --------------------- + + Now is the time for all good men to come to + the aid of their country. This is just a + regular paragraph. + + The quick brown fox jumped over the lazy + dog's back. + + ### Header 3 + + > This is a blockquote. + > + > This is the second paragraph in the blockquote. + > + > ## This is an H2 in a blockquote + + +Output: + +

A First Level Header

+ +

A Second Level Header

+ +

Now is the time for all good men to come to + the aid of their country. This is just a + regular paragraph.

+ +

The quick brown fox jumped over the lazy + dog's back.

+ +

Header 3

+ +
+

This is a blockquote.

+ +

This is the second paragraph in the blockquote.

+ +

This is an H2 in a blockquote

+
+ + + +### Phrase Emphasis ### + +Markdown uses asterisks and underscores to indicate spans of emphasis. + +Markdown: + + Some of these words *are emphasized*. + Some of these words _are emphasized also_. + + Use two asterisks for **strong emphasis**. + Or, if you prefer, __use two underscores instead__. + +Output: + +

Some of these words are emphasized. + Some of these words are emphasized also.

+ +

Use two asterisks for strong emphasis. + Or, if you prefer, use two underscores instead.

+ + + +## Lists ## + +Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`, +`+`, and `-`) as list markers. These three markers are +interchangable; this: + + * Candy. + * Gum. + * Booze. + +this: + + + Candy. + + Gum. + + Booze. + +and this: + + - Candy. + - Gum. + - Booze. + +all produce the same output: + +
    +
  • Candy.
  • +
  • Gum.
  • +
  • Booze.
  • +
+ +Ordered (numbered) lists use regular numbers, followed by periods, as +list markers: + + 1. Red + 2. Green + 3. Blue + +Output: + +
    +
  1. Red
  2. +
  3. Green
  4. +
  5. Blue
  6. +
+ +If you put blank lines between items, you'll get `

` tags for the +list item text. You can create multi-paragraph list items by indenting +the paragraphs by 4 spaces or 1 tab: + + * A list item. + + With multiple paragraphs. + + * Another item in the list. + +Output: + +

    +
  • A list item.

    +

    With multiple paragraphs.

  • +
  • Another item in the list.

  • +
+ + + +### Links ### + +Markdown supports two styles for creating links: *inline* and +*reference*. With both styles, you use square brackets to delimit the +text you want to turn into a link. + +Inline-style links use parentheses immediately after the link text. +For example: + + This is an [example link](http://example.com/). + +Output: + +

This is an + example link.

+ +Optionally, you may include a title attribute in the parentheses: + + This is an [example link](http://example.com/ "With a Title"). + +Output: + +

This is an + example link.

+ +Reference-style links allow you to refer to your links by names, which +you define elsewhere in your document: + + I get 10 times more traffic from [Google][1] than from + [Yahoo][2] or [MSN][3]. + + [1]: http://google.com/ "Google" + [2]: http://search.yahoo.com/ "Yahoo Search" + [3]: http://search.msn.com/ "MSN Search" + +Output: + +

I get 10 times more traffic from Google than from Yahoo or MSN.

+ +The title attribute is optional. Link names may contain letters, +numbers and spaces, but are *not* case sensitive: + + I start my morning with a cup of coffee and + [The New York Times][NY Times]. + + [ny times]: http://www.nytimes.com/ + +Output: + +

I start my morning with a cup of coffee and + The New York Times.

+ + +### Images ### + +Image syntax is very much like link syntax. + +Inline (titles are optional): + + ![alt text](/path/to/img.jpg "Title") + +Reference-style: + + ![alt text][id] + + [id]: /path/to/img.jpg "Title" + +Both of the above examples produce the same output: + + alt text + + + +### Code ### + +In a regular paragraph, you can create code span by wrapping text in +backtick quotes. Any ampersands (`&`) and angle brackets (`<` or +`>`) will automatically be translated into HTML entities. This makes +it easy to use Markdown to write about HTML example code: + + I strongly recommend against using any `` tags. + + I wish SmartyPants used named entities like `—` + instead of decimal-encoded entites like `—`. + +Output: + +

I strongly recommend against using any + <blink> tags.

+ +

I wish SmartyPants used named entities like + &mdash; instead of decimal-encoded + entites like &#8212;.

+ + +To specify an entire block of pre-formatted code, indent every line of +the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`, +and `>` characters will be escaped automatically. + +Markdown: + + If you want your page to validate under XHTML 1.0 Strict, + you've got to put paragraph tags in your blockquotes: + +
+

For example.

+
+ +Output: + +

If you want your page to validate under XHTML 1.0 Strict, + you've got to put paragraph tags in your blockquotes:

+ +
<blockquote>
+        <p>For example.</p>
+    </blockquote>
+    
diff --git a/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text b/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text new file mode 100644 index 0000000000..57360a16c8 --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text @@ -0,0 +1,888 @@ +Markdown: Syntax +================ + + + + +* [Overview](#overview) + * [Philosophy](#philosophy) + * [Inline HTML](#html) + * [Automatic Escaping for Special Characters](#autoescape) +* [Block Elements](#block) + * [Paragraphs and Line Breaks](#p) + * [Headers](#header) + * [Blockquotes](#blockquote) + * [Lists](#list) + * [Code Blocks](#precode) + * [Horizontal Rules](#hr) +* [Span Elements](#span) + * [Links](#link) + * [Emphasis](#em) + * [Code](#code) + * [Images](#img) +* [Miscellaneous](#misc) + * [Backslash Escapes](#backslash) + * [Automatic Links](#autolink) + + +**Note:** This document is itself written using Markdown; you +can [see the source for it by adding '.text' to the URL][src]. + + [src]: /projects/markdown/syntax.text + +* * * + +

Overview

+ +

Philosophy

+ +Markdown is intended to be as easy-to-read and easy-to-write as is feasible. + +Readability, however, is emphasized above all else. A Markdown-formatted +document should be publishable as-is, as plain text, without looking +like it's been marked up with tags or formatting instructions. While +Markdown's syntax has been influenced by several existing text-to-HTML +filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4], +[Grutatext] [5], and [EtText] [6] -- the single biggest source of +inspiration for Markdown's syntax is the format of plain text email. + + [1]: http://docutils.sourceforge.net/mirror/setext.html + [2]: http://www.aaronsw.com/2002/atx/ + [3]: http://textism.com/tools/textile/ + [4]: http://docutils.sourceforge.net/rst.html + [5]: http://www.triptico.com/software/grutatxt.html + [6]: http://ettext.taint.org/doc/ + +To this end, Markdown's syntax is comprised entirely of punctuation +characters, which punctuation characters have been carefully chosen so +as to look like what they mean. E.g., asterisks around a word actually +look like \*emphasis\*. Markdown lists look like, well, lists. Even +blockquotes look like quoted passages of text, assuming you've ever +used email. + + + +

Inline HTML

+ +Markdown's syntax is intended for one purpose: to be used as a +format for *writing* for the web. + +Markdown is not a replacement for HTML, or even close to it. Its +syntax is very small, corresponding only to a very small subset of +HTML tags. The idea is *not* to create a syntax that makes it easier +to insert HTML tags. In my opinion, HTML tags are already easy to +insert. The idea for Markdown is to make it easy to read, write, and +edit prose. HTML is a *publishing* format; Markdown is a *writing* +format. Thus, Markdown's formatting syntax only addresses issues that +can be conveyed in plain text. + +For any markup that is not covered by Markdown's syntax, you simply +use HTML itself. There's no need to preface it or delimit it to +indicate that you're switching from Markdown to HTML; you just use +the tags. + +The only restrictions are that block-level HTML elements -- e.g. `
`, +``, `
`, `

`, etc. -- must be separated from surrounding +content by blank lines, and the start and end tags of the block should +not be indented with tabs or spaces. Markdown is smart enough not +to add extra (unwanted) `

` tags around HTML block-level tags. + +For example, to add an HTML table to a Markdown article: + + This is a regular paragraph. + +

+ + + +
Foo
+ + This is another regular paragraph. + +Note that Markdown formatting syntax is not processed within block-level +HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an +HTML block. + +Span-level HTML tags -- e.g. ``, ``, or `` -- can be +used anywhere in a Markdown paragraph, list item, or header. If you +want, you can even use HTML tags instead of Markdown formatting; e.g. if +you'd prefer to use HTML `` or `` tags instead of Markdown's +link or image syntax, go right ahead. + +Unlike block-level HTML tags, Markdown syntax *is* processed within +span-level tags. + + +

Automatic Escaping for Special Characters

+ +In HTML, there are two characters that demand special treatment: `<` +and `&`. Left angle brackets are used to start tags; ampersands are +used to denote HTML entities. If you want to use them as literal +characters, you must escape them as entities, e.g. `<`, and +`&`. + +Ampersands in particular are bedeviling for web writers. If you want to +write about 'AT&T', you need to write '`AT&T`'. You even need to +escape ampersands within URLs. Thus, if you want to link to: + + http://images.google.com/images?num=30&q=larry+bird + +you need to encode the URL as: + + http://images.google.com/images?num=30&q=larry+bird + +in your anchor tag `href` attribute. Needless to say, this is easy to +forget, and is probably the single most common source of HTML validation +errors in otherwise well-marked-up web sites. + +Markdown allows you to use these characters naturally, taking care of +all the necessary escaping for you. If you use an ampersand as part of +an HTML entity, it remains unchanged; otherwise it will be translated +into `&`. + +So, if you want to include a copyright symbol in your article, you can write: + + © + +and Markdown will leave it alone. But if you write: + + AT&T + +Markdown will translate it to: + + AT&T + +Similarly, because Markdown supports [inline HTML](#html), if you use +angle brackets as delimiters for HTML tags, Markdown will treat them as +such. But if you write: + + 4 < 5 + +Markdown will translate it to: + + 4 < 5 + +However, inside Markdown code spans and blocks, angle brackets and +ampersands are *always* encoded automatically. This makes it easy to use +Markdown to write about HTML code. (As opposed to raw HTML, which is a +terrible format for writing about HTML syntax, because every single `<` +and `&` in your example code needs to be escaped.) + + +* * * + + +

Block Elements

+ + +

Paragraphs and Line Breaks

+ +A paragraph is simply one or more consecutive lines of text, separated +by one or more blank lines. (A blank line is any line that looks like a +blank line -- a line containing nothing but spaces or tabs is considered +blank.) Normal paragraphs should not be intended with spaces or tabs. + +The implication of the "one or more consecutive lines of text" rule is +that Markdown supports "hard-wrapped" text paragraphs. This differs +significantly from most other text-to-HTML formatters (including Movable +Type's "Convert Line Breaks" option) which translate every line break +character in a paragraph into a `
` tag. + +When you *do* want to insert a `
` break tag using Markdown, you +end a line with two or more spaces, then type return. + +Yes, this takes a tad more effort to create a `
`, but a simplistic +"every line break is a `
`" rule wouldn't work for Markdown. +Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l] +work best -- and look better -- when you format them with hard breaks. + + [bq]: #blockquote + [l]: #list + + + + + +Markdown supports two styles of headers, [Setext] [1] and [atx] [2]. + +Setext-style headers are "underlined" using equal signs (for first-level +headers) and dashes (for second-level headers). For example: + + This is an H1 + ============= + + This is an H2 + ------------- + +Any number of underlining `=`'s or `-`'s will work. + +Atx-style headers use 1-6 hash characters at the start of the line, +corresponding to header levels 1-6. For example: + + # This is an H1 + + ## This is an H2 + + ###### This is an H6 + +Optionally, you may "close" atx-style headers. This is purely +cosmetic -- you can use this if you think it looks better. The +closing hashes don't even need to match the number of hashes +used to open the header. (The number of opening hashes +determines the header level.) : + + # This is an H1 # + + ## This is an H2 ## + + ### This is an H3 ###### + + +

Blockquotes

+ +Markdown uses email-style `>` characters for blockquoting. If you're +familiar with quoting passages of text in an email message, then you +know how to create a blockquote in Markdown. It looks best if you hard +wrap the text and put a `>` before every line: + + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + > + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + > id sem consectetuer libero luctus adipiscing. + +Markdown allows you to be lazy and only put the `>` before the first +line of a hard-wrapped paragraph: + + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + id sem consectetuer libero luctus adipiscing. + +Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by +adding additional levels of `>`: + + > This is the first level of quoting. + > + > > This is nested blockquote. + > + > Back to the first level. + +Blockquotes can contain other Markdown elements, including headers, lists, +and code blocks: + + > ## This is a header. + > + > 1. This is the first list item. + > 2. This is the second list item. + > + > Here's some example code: + > + > return shell_exec("echo $input | $markdown_script"); + +Any decent text editor should make email-style quoting easy. For +example, with BBEdit, you can make a selection and choose Increase +Quote Level from the Text menu. + + +

Lists

+ +Markdown supports ordered (numbered) and unordered (bulleted) lists. + +Unordered lists use asterisks, pluses, and hyphens -- interchangably +-- as list markers: + + * Red + * Green + * Blue + +is equivalent to: + + + Red + + Green + + Blue + +and: + + - Red + - Green + - Blue + +Ordered lists use numbers followed by periods: + + 1. Bird + 2. McHale + 3. Parish + +It's important to note that the actual numbers you use to mark the +list have no effect on the HTML output Markdown produces. The HTML +Markdown produces from the above list is: + +
    +
  1. Bird
  2. +
  3. McHale
  4. +
  5. Parish
  6. +
+ +If you instead wrote the list in Markdown like this: + + 1. Bird + 1. McHale + 1. Parish + +or even: + + 3. Bird + 1. McHale + 8. Parish + +you'd get the exact same HTML output. The point is, if you want to, +you can use ordinal numbers in your ordered Markdown lists, so that +the numbers in your source match the numbers in your published HTML. +But if you want to be lazy, you don't have to. + +If you do use lazy list numbering, however, you should still start the +list with the number 1. At some point in the future, Markdown may support +starting ordered lists at an arbitrary number. + +List markers typically start at the left margin, but may be indented by +up to three spaces. List markers must be followed by one or more spaces +or a tab. + +To make lists look nice, you can wrap items with hanging indents: + + * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, + viverra nec, fringilla in, laoreet vitae, risus. + * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. + Suspendisse id sem consectetuer libero luctus adipiscing. + +But if you want to be lazy, you don't have to: + + * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. + Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, + viverra nec, fringilla in, laoreet vitae, risus. + * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. + Suspendisse id sem consectetuer libero luctus adipiscing. + +If list items are separated by blank lines, Markdown will wrap the +items in `

` tags in the HTML output. For example, this input: + + * Bird + * Magic + +will turn into: + +

    +
  • Bird
  • +
  • Magic
  • +
+ +But this: + + * Bird + + * Magic + +will turn into: + +
    +
  • Bird

  • +
  • Magic

  • +
+ +List items may consist of multiple paragraphs. Each subsequent +paragraph in a list item must be intended by either 4 spaces +or one tab: + + 1. This is a list item with two paragraphs. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. Aliquam hendrerit + mi posuere lectus. + + Vestibulum enim wisi, viverra nec, fringilla in, laoreet + vitae, risus. Donec sit amet nisl. Aliquam semper ipsum + sit amet velit. + + 2. Suspendisse id sem consectetuer libero luctus adipiscing. + +It looks nice if you indent every line of the subsequent +paragraphs, but here again, Markdown will allow you to be +lazy: + + * This is a list item with two paragraphs. + + This is the second paragraph in the list item. You're + only required to indent the first line. Lorem ipsum dolor + sit amet, consectetuer adipiscing elit. + + * Another item in the same list. + +To put a blockquote within a list item, the blockquote's `>` +delimiters need to be indented: + + * A list item with a blockquote: + + > This is a blockquote + > inside a list item. + +To put a code block within a list item, the code block needs +to be indented *twice* -- 8 spaces or two tabs: + + * A list item with a code block: + + + + +It's worth noting that it's possible to trigger an ordered list by +accident, by writing something like this: + + 1986. What a great season. + +In other words, a *number-period-space* sequence at the beginning of a +line. To avoid this, you can backslash-escape the period: + + 1986\. What a great season. + + + +

Code Blocks

+ +Pre-formatted code blocks are used for writing about programming or +markup source code. Rather than forming normal paragraphs, the lines +of a code block are interpreted literally. Markdown wraps a code block +in both `
` and `` tags.
+
+To produce a code block in Markdown, simply indent every line of the
+block by at least 4 spaces or 1 tab. For example, given this input:
+
+    This is a normal paragraph:
+
+        This is a code block.
+
+Markdown will generate:
+
+    

This is a normal paragraph:

+ +
This is a code block.
+    
+ +One level of indentation -- 4 spaces or 1 tab -- is removed from each +line of the code block. For example, this: + + Here is an example of AppleScript: + + tell application "Foo" + beep + end tell + +will turn into: + +

Here is an example of AppleScript:

+ +
tell application "Foo"
+        beep
+    end tell
+    
+ +A code block continues until it reaches a line that is not indented +(or the end of the article). + +Within a code block, ampersands (`&`) and angle brackets (`<` and `>`) +are automatically converted into HTML entities. This makes it very +easy to include example HTML source code using Markdown -- just paste +it and indent it, and Markdown will handle the hassle of encoding the +ampersands and angle brackets. For example, this: + + + +will turn into: + +
<div class="footer">
+        &copy; 2004 Foo Corporation
+    </div>
+    
+ +Regular Markdown syntax is not processed within code blocks. E.g., +asterisks are just literal asterisks within a code block. This means +it's also easy to use Markdown to write about Markdown's own syntax. + + + +

Horizontal Rules

+ +You can produce a horizontal rule tag (`
`) by placing three or +more hyphens, asterisks, or underscores on a line by themselves. If you +wish, you may use spaces between the hyphens or asterisks. Each of the +following lines will produce a horizontal rule: + + * * * + + *** + + ***** + + - - - + + --------------------------------------- + + _ _ _ + + +* * * + +

Span Elements

+ + + +Markdown supports two style of links: *inline* and *reference*. + +In both styles, the link text is delimited by [square brackets]. + +To create an inline link, use a set of regular parentheses immediately +after the link text's closing square bracket. Inside the parentheses, +put the URL where you want the link to point, along with an *optional* +title for the link, surrounded in quotes. For example: + + This is [an example](http://example.com/ "Title") inline link. + + [This link](http://example.net/) has no title attribute. + +Will produce: + +

This is + an example inline link.

+ +

This link has no + title attribute.

+ +If you're referring to a local resource on the same server, you can +use relative paths: + + See my [About](/about/) page for details. + +Reference-style links use a second set of square brackets, inside +which you place a label of your choosing to identify the link: + + This is [an example][id] reference-style link. + +You can optionally use a space to separate the sets of brackets: + + This is [an example] [id] reference-style link. + +Then, anywhere in the document, you define your link label like this, +on a line by itself: + + [id]: http://example.com/ "Optional Title Here" + +That is: + +* Square brackets containing the link identifier (optionally + indented from the left margin using up to three spaces); +* followed by a colon; +* followed by one or more spaces (or tabs); +* followed by the URL for the link; +* optionally followed by a title attribute for the link, enclosed + in double or single quotes. + +The link URL may, optionally, be surrounded by angle brackets: + + [id]: "Optional Title Here" + +You can put the title attribute on the next line and use extra spaces +or tabs for padding, which tends to look better with longer URLs: + + [id]: http://example.com/longish/path/to/resource/here + "Optional Title Here" + +Link definitions are only used for creating links during Markdown +processing, and are stripped from your document in the HTML output. + +Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links: + + [link text][a] + [link text][A] + +are equivalent. + +The *implicit link name* shortcut allows you to omit the name of the +link, in which case the link text itself is used as the name. +Just use an empty set of square brackets -- e.g., to link the word +"Google" to the google.com web site, you could simply write: + + [Google][] + +And then define the link: + + [Google]: http://google.com/ + +Because link names may contain spaces, this shortcut even works for +multiple words in the link text: + + Visit [Daring Fireball][] for more information. + +And then define the link: + + [Daring Fireball]: http://daringfireball.net/ + +Link definitions can be placed anywhere in your Markdown document. I +tend to put them immediately after each paragraph in which they're +used, but if you want, you can put them all at the end of your +document, sort of like footnotes. + +Here's an example of reference links in action: + + I get 10 times more traffic from [Google] [1] than from + [Yahoo] [2] or [MSN] [3]. + + [1]: http://google.com/ "Google" + [2]: http://search.yahoo.com/ "Yahoo Search" + [3]: http://search.msn.com/ "MSN Search" + +Using the implicit link name shortcut, you could instead write: + + I get 10 times more traffic from [Google][] than from + [Yahoo][] or [MSN][]. + + [google]: http://google.com/ "Google" + [yahoo]: http://search.yahoo.com/ "Yahoo Search" + [msn]: http://search.msn.com/ "MSN Search" + +Both of the above examples will produce the following HTML output: + +

I get 10 times more traffic from Google than from + Yahoo + or MSN.

+ +For comparison, here is the same paragraph written using +Markdown's inline link style: + + I get 10 times more traffic from [Google](http://google.com/ "Google") + than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or + [MSN](http://search.msn.com/ "MSN Search"). + +The point of reference-style links is not that they're easier to +write. The point is that with reference-style links, your document +source is vastly more readable. Compare the above examples: using +reference-style links, the paragraph itself is only 81 characters +long; with inline-style links, it's 176 characters; and as raw HTML, +it's 234 characters. In the raw HTML, there's more markup than there +is text. + +With Markdown's reference-style links, a source document much more +closely resembles the final output, as rendered in a browser. By +allowing you to move the markup-related metadata out of the paragraph, +you can add links without interrupting the narrative flow of your +prose. + + +

Emphasis

+ +Markdown treats asterisks (`*`) and underscores (`_`) as indicators of +emphasis. Text wrapped with one `*` or `_` will be wrapped with an +HTML `` tag; double `*`'s or `_`'s will be wrapped with an HTML +`` tag. E.g., this input: + + *single asterisks* + + _single underscores_ + + **double asterisks** + + __double underscores__ + +will produce: + + single asterisks + + single underscores + + double asterisks + + double underscores + +You can use whichever style you prefer; the lone restriction is that +the same character must be used to open and close an emphasis span. + +Emphasis can be used in the middle of a word: + + un*fucking*believable + +But if you surround an `*` or `_` with spaces, it'll be treated as a +literal asterisk or underscore. + +To produce a literal asterisk or underscore at a position where it +would otherwise be used as an emphasis delimiter, you can backslash +escape it: + + \*this text is surrounded by literal asterisks\* + + + +

Code

+ +To indicate a span of code, wrap it with backtick quotes (`` ` ``). +Unlike a pre-formatted code block, a code span indicates code within a +normal paragraph. For example: + + Use the `printf()` function. + +will produce: + +

Use the printf() function.

+ +To include a literal backtick character within a code span, you can use +multiple backticks as the opening and closing delimiters: + + ``There is a literal backtick (`) here.`` + +which will produce this: + +

There is a literal backtick (`) here.

+ +The backtick delimiters surrounding a code span may include spaces -- +one after the opening, one before the closing. This allows you to place +literal backtick characters at the beginning or end of a code span: + + A single backtick in a code span: `` ` `` + + A backtick-delimited string in a code span: `` `foo` `` + +will produce: + +

A single backtick in a code span: `

+ +

A backtick-delimited string in a code span: `foo`

+ +With a code span, ampersands and angle brackets are encoded as HTML +entities automatically, which makes it easy to include example HTML +tags. Markdown will turn this: + + Please don't use any `` tags. + +into: + +

Please don't use any <blink> tags.

+ +You can write this: + + `—` is the decimal-encoded equivalent of `—`. + +to produce: + +

&#8212; is the decimal-encoded + equivalent of &mdash;.

+ + + +

Images

+ +Admittedly, it's fairly difficult to devise a "natural" syntax for +placing images into a plain text document format. + +Markdown uses an image syntax that is intended to resemble the syntax +for links, allowing for two styles: *inline* and *reference*. + +Inline image syntax looks like this: + + ![Alt text](/path/to/img.jpg) + + ![Alt text](/path/to/img.jpg "Optional title") + +That is: + +* An exclamation mark: `!`; +* followed by a set of square brackets, containing the `alt` + attribute text for the image; +* followed by a set of parentheses, containing the URL or path to + the image, and an optional `title` attribute enclosed in double + or single quotes. + +Reference-style image syntax looks like this: + + ![Alt text][id] + +Where "id" is the name of a defined image reference. Image references +are defined using syntax identical to link references: + + [id]: url/to/image "Optional title attribute" + +As of this writing, Markdown has no syntax for specifying the +dimensions of an image; if this is important to you, you can simply +use regular HTML `` tags. + + +* * * + + +

Miscellaneous

+ + + +Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this: + + + +Markdown will turn this into: + + http://example.com/ + +Automatic links for email addresses work similarly, except that +Markdown will also perform a bit of randomized decimal and hex +entity-encoding to help obscure your address from address-harvesting +spambots. For example, Markdown will turn this: + + + +into something like this: + + address@exa + mple.com + +which will render in a browser as a clickable link to "address@example.com". + +(This sort of entity-encoding trick will indeed fool many, if not +most, address-harvesting bots, but it definitely won't fool all of +them. It's better than nothing, but an address published in this way +will probably eventually start receiving spam.) + + + +

Backslash Escapes

+ +Markdown allows you to use backslash escapes to generate literal +characters which would otherwise have special meaning in Markdown's +formatting syntax. For example, if you wanted to surround a word with +literal asterisks (instead of an HTML `` tag), you can backslashes +before the asterisks, like this: + + \*literal asterisks\* + +Markdown provides backslash escapes for the following characters: + + \ backslash + ` backtick + * asterisk + _ underscore + {} curly braces + [] square brackets + () parentheses + # hash mark + + plus sign + - minus sign (hyphen) + . dot + ! exclamation mark + diff --git a/test/rdoc/MarkdownTest_1.0.3/Nested blockquotes.text b/test/rdoc/MarkdownTest_1.0.3/Nested blockquotes.text new file mode 100644 index 0000000000..ed3c624ffb --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Nested blockquotes.text @@ -0,0 +1,5 @@ +> foo +> +> > bar +> +> foo diff --git a/test/rdoc/MarkdownTest_1.0.3/Ordered and unordered lists.text b/test/rdoc/MarkdownTest_1.0.3/Ordered and unordered lists.text new file mode 100644 index 0000000000..7f3b49777f --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Ordered and unordered lists.text @@ -0,0 +1,131 @@ +## Unordered + +Asterisks tight: + +* asterisk 1 +* asterisk 2 +* asterisk 3 + + +Asterisks loose: + +* asterisk 1 + +* asterisk 2 + +* asterisk 3 + +* * * + +Pluses tight: + ++ Plus 1 ++ Plus 2 ++ Plus 3 + + +Pluses loose: + ++ Plus 1 + ++ Plus 2 + ++ Plus 3 + +* * * + + +Minuses tight: + +- Minus 1 +- Minus 2 +- Minus 3 + + +Minuses loose: + +- Minus 1 + +- Minus 2 + +- Minus 3 + + +## Ordered + +Tight: + +1. First +2. Second +3. Third + +and: + +1. One +2. Two +3. Three + + +Loose using tabs: + +1. First + +2. Second + +3. Third + +and using spaces: + +1. One + +2. Two + +3. Three + +Multiple paragraphs: + +1. Item 1, graf one. + + Item 2. graf two. The quick brown fox jumped over the lazy dog's + back. + +2. Item 2. + +3. Item 3. + + + +## Nested + +* Tab + * Tab + * Tab + +Here's another: + +1. First +2. Second: + * Fee + * Fie + * Foe +3. Third + +Same thing but with paragraphs: + +1. First + +2. Second: + * Fee + * Fie + * Foe + +3. Third + + +This was an error in Markdown 1.0.1: + +* this + + * sub + + that diff --git a/test/rdoc/MarkdownTest_1.0.3/Strong and em together.text b/test/rdoc/MarkdownTest_1.0.3/Strong and em together.text new file mode 100644 index 0000000000..95ee690dbe --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Strong and em together.text @@ -0,0 +1,7 @@ +***This is strong and em.*** + +So is ***this*** word. + +___This is strong and em.___ + +So is ___this___ word. diff --git a/test/rdoc/MarkdownTest_1.0.3/Tabs.text b/test/rdoc/MarkdownTest_1.0.3/Tabs.text new file mode 100644 index 0000000000..589d1136e1 --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Tabs.text @@ -0,0 +1,21 @@ ++ this is a list item + indented with tabs + ++ this is a list item + indented with spaces + +Code: + + this code block is indented by one tab + +And: + + this code block is indented by two tabs + +And: + + + this is an example list item + indented with tabs + + + this is an example list item + indented with spaces diff --git a/test/rdoc/MarkdownTest_1.0.3/Tidyness.text b/test/rdoc/MarkdownTest_1.0.3/Tidyness.text new file mode 100644 index 0000000000..5f18b8da21 --- /dev/null +++ b/test/rdoc/MarkdownTest_1.0.3/Tidyness.text @@ -0,0 +1,5 @@ +> A list within a blockquote: +> +> * asterisk 1 +> * asterisk 2 +> * asterisk 3 diff --git a/test/rdoc/test.ja.large.rdoc b/test/rdoc/test.ja.large.rdoc new file mode 100644 index 0000000000..a9c6c4691c --- /dev/null +++ b/test/rdoc/test.ja.large.rdoc @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + 吾輩(わがはい)は猫である。名前はまだ無い。 + どこで生れたかとんと見当(けんとう)がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪(どうあく)な種族であったそうだ。この書生というのは時々我々を捕(つかま)えて煮(に)て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌(てのひら)に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始(みはじめ)であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶(やかん)だ。その後(ご)猫にもだいぶ逢(あ)ったがこんな片輪(かたわ)には一度も出会(でく)わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙(けむり)を吹く。どうも咽(む)せぽくて実に弱った。これが人間の飲む煙草(たばこ)というものである事はようやくこの頃知った。 diff --git a/test/rdoc/test.ja.largedoc b/test/rdoc/test.ja.largedoc deleted file mode 100644 index a9c6c4691c..0000000000 --- a/test/rdoc/test.ja.largedoc +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- - 吾輩(わがはい)は猫である。名前はまだ無い。 - どこで生れたかとんと見当(けんとう)がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪(どうあく)な種族であったそうだ。この書生というのは時々我々を捕(つかま)えて煮(に)て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌(てのひら)に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始(みはじめ)であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶(やかん)だ。その後(ご)猫にもだいぶ逢(あ)ったがこんな片輪(かたわ)には一度も出会(でく)わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙(けむり)を吹く。どうも咽(む)せぽくて実に弱った。これが人間の飲む煙草(たばこ)というものである事はようやくこの頃知った。 diff --git a/test/rdoc/test_attribute_manager.rb b/test/rdoc/test_attribute_manager.rb index 25e8ca5e04..8832a5d515 100644 --- a/test/rdoc/test_attribute_manager.rb +++ b/test/rdoc/test_attribute_manager.rb @@ -1,27 +1,26 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc' -require 'rdoc/markup' -require 'rdoc/markup/formatter' -require 'rdoc/markup/attribute_manager' +require 'rdoc/test_case' -class TestAttributeManager < MiniTest::Unit::TestCase # HACK fix test name +class TestAttributeManager < RDoc::TestCase # HACK fix test name def setup + super + + @options = RDoc::Options.new + @am = RDoc::Markup::AttributeManager.new @klass = RDoc::Markup::AttributeManager - @formatter = RDoc::Markup::Formatter.new + @formatter = RDoc::Markup::Formatter.new @options @formatter.add_tag :BOLD, '', '' @formatter.add_tag :EM, '', '' - @formatter.add_tag :TT, '', '' + @formatter.add_tag :TT, '', '' end def test_convert_attrs_ignores_code - assert_equal 'foo __send__ bar', output('foo __send__ bar') + assert_equal 'foo __send__ bar', output('foo __send__ bar') end def test_convert_attrs_ignores_tt - assert_equal 'foo __send__ bar', output('foo __send__ bar') + assert_equal 'foo __send__ bar', output('foo __send__ bar') end def test_convert_attrs_preserves_double @@ -30,7 +29,7 @@ class TestAttributeManager < MiniTest::Unit::TestCase # HACK fix test name end def test_convert_attrs_does_not_ignore_after_tt - assert_equal 'the IF:key directive', output('the IF:_key_ directive') + assert_equal 'the IF:key directive', output('the IF:_key_ directive') end def test_initial_word_pairs @@ -73,38 +72,39 @@ class TestAttributeManager < MiniTest::Unit::TestCase # HACK fix test name end def test_add_special - @am.add_special("WikiWord", :WIKIWORD) + @am.add_special "WikiWord", :WIKIWORD specials = @am.special - assert_equal(1,specials.size) - assert(specials.has_key?("WikiWord")) + + assert_equal 1, specials.size + assert specials.assoc "WikiWord" end def test_escapes - assert_equal 'text', output('text') - assert_equal 'text', output('\\text') - assert_equal '', output('\\') - assert_equal '', output('\\') - assert_equal '\\', output('\\\\') - assert_equal 'text', output('*text*') - assert_equal '*text*', output('\\*text*') - assert_equal '\\', output('\\') - assert_equal '\\text', output('\\text') - assert_equal '\\\\text', output('\\\\text') - assert_equal 'text \\ text', output('text \\ text') - - assert_equal 'and \\s matches space', + assert_equal 'text', output('text') + assert_equal 'text', output('\\text') + assert_equal '', output('\\') + assert_equal '', output('\\') + assert_equal '\\', output('\\\\') + assert_equal 'text', output('*text*') + assert_equal '*text*', output('\\*text*') + assert_equal '\\', output('\\') + assert_equal '\\text', output('\\text') + assert_equal '\\\\text', output('\\\\text') + assert_equal 'text \\ text', output('text \\ text') + + assert_equal 'and \\s matches space', output('and \\s matches space') - assert_equal 'use text for code', + assert_equal 'use text for code', output('use \\text for code') - assert_equal 'use text for code', + assert_equal 'use text for code', output('use \\text\\ for code') assert_equal 'use text for code', output('use \\\\text for code') - assert_equal 'use text for code', + assert_equal 'use text for code', output('use \\text for code') - assert_equal 'use +text+ for code', + assert_equal 'use +text+ for code', output('use \\+text+ for code') - assert_equal 'use text for code', + assert_equal 'use text for code', output('use \\+text+ for code') assert_equal 'illegal not changed', output('illegal not changed') diff --git a/test/rdoc/test_rdoc_any_method.rb b/test/rdoc/test_rdoc_any_method.rb index c0feccef95..abf749c4c9 100644 --- a/test/rdoc/test_rdoc_any_method.rb +++ b/test/rdoc/test_rdoc_any_method.rb @@ -1,8 +1,6 @@ require File.expand_path '../xref_test_case', __FILE__ -require 'rdoc/code_objects' -require 'rdoc/generator/markup' -class RDocAnyMethodTest < XrefTestCase +class TestRDocAnyMethod < XrefTestCase def test_aref m = RDoc::AnyMethod.new nil, 'method?' @@ -47,34 +45,12 @@ method(a, b) { |c, d| ... } def test_markup_code tokens = [ RDoc::RubyToken::TkCONSTANT. new(0, 0, 0, 'CONSTANT'), - RDoc::RubyToken::TkDEF. new(0, 0, 0, 'KW'), - RDoc::RubyToken::TkIVAR. new(0, 0, 0, 'IVAR'), - RDoc::RubyToken::TkOp. new(0, 0, 0, 'Op'), - RDoc::RubyToken::TkId. new(0, 0, 0, 'Id'), - RDoc::RubyToken::TkNode. new(0, 0, 0, 'Node'), - RDoc::RubyToken::TkCOMMENT. new(0, 0, 0, 'COMMENT'), - RDoc::RubyToken::TkREGEXP. new(0, 0, 0, 'REGEXP'), - RDoc::RubyToken::TkSTRING. new(0, 0, 0, 'STRING'), - RDoc::RubyToken::TkVal. new(0, 0, 0, 'Val'), - RDoc::RubyToken::TkBACKSLASH.new(0, 0, 0, '\\'), ] @c2_a.collect_tokens @c2_a.add_tokens(*tokens) - expected = [ - 'CONSTANT', - 'KW', - 'IVAR', - 'Op', - 'Id', - 'Node', - 'COMMENT', - 'REGEXP', - 'STRING', - 'Val', - '\\' - ].join + expected = 'CONSTANT' assert_equal expected, @c2_a.markup_code end @@ -84,7 +60,9 @@ method(a, b) { |c, d| ... } end def test_marshal_dump - top_level = RDoc::TopLevel.new 'file.rb' + @store.path = Dir.tmpdir + top_level = @store.add_file 'file.rb' + m = RDoc::AnyMethod.new nil, 'method' m.block_params = 'some_block' m.call_seq = 'call_seq' @@ -92,20 +70,23 @@ method(a, b) { |c, d| ... } m.params = 'param' m.record_location top_level - cm = RDoc::ClassModule.new 'Klass' + cm = top_level.add_class RDoc::ClassModule, 'Klass' cm.add_method m + section = cm.sections.first + al = RDoc::Alias.new nil, 'method', 'aliased', 'alias comment' al_m = m.add_alias al, cm loaded = Marshal.load Marshal.dump m + loaded.store = @store comment = RDoc::Markup::Document.new( RDoc::Markup::Paragraph.new('this is a comment')) assert_equal m, loaded - assert_equal [al_m], loaded.aliases + assert_equal [al_m.name], loaded.aliases.map { |alas| alas.name } assert_equal 'some_block', loaded.block_params assert_equal 'call_seq', loaded.call_seq assert_equal comment, loaded.comment @@ -115,6 +96,8 @@ method(a, b) { |c, d| ... } assert_equal 'param', loaded.params assert_equal nil, loaded.singleton # defaults to nil assert_equal :public, loaded.visibility + assert_equal cm, loaded.parent + assert_equal section, loaded.section end def test_marshal_load @@ -138,28 +121,37 @@ method(a, b) { |c, d| ... } end def test_marshal_load_version_0 + @store.path = Dir.tmpdir + top_level = @store.add_file 'file.rb' + m = RDoc::AnyMethod.new nil, 'method' - cm = RDoc::ClassModule.new 'Klass' + + cm = top_level.add_class RDoc::ClassModule, 'Klass' cm.add_method m + + section = cm.sections.first + al = RDoc::Alias.new nil, 'method', 'aliased', 'alias comment' al_m = m.add_alias al, cm - loaded = Marshal.load "\x04\bU:\x14RDoc::AnyMethod[\x0Fi\x00I" \ - "\"\vmethod\x06:\x06EF\"\x11Klass#method0:\vpublic" \ - "o:\eRDoc::Markup::Document\x06:\v@parts[\x06" \ - "o:\x1CRDoc::Markup::Paragraph\x06;\t[\x06I" \ - "\"\x16this is a comment\x06;\x06FI" \ - "\"\rcall_seq\x06;\x06FI\"\x0Fsome_block\x06;\x06F" \ - "[\x06[\aI\"\faliased\x06;\x06Fo;\b\x06;\t[\x06" \ - "o;\n\x06;\t[\x06I\"\x12alias comment\x06;\x06FI" \ + loaded = Marshal.load "\x04\bU:\x14RDoc::AnyMethod[\x0Fi\x00I" + + "\"\vmethod\x06:\x06EF\"\x11Klass#method0:\vpublic" + + "o:\eRDoc::Markup::Document\x06:\v@parts[\x06" + + "o:\x1CRDoc::Markup::Paragraph\x06;\t[\x06I" + + "\"\x16this is a comment\x06;\x06FI" + + "\"\rcall_seq\x06;\x06FI\"\x0Fsome_block\x06;\x06F" + + "[\x06[\aI\"\faliased\x06;\x06Fo;\b\x06;\t[\x06" + + "o;\n\x06;\t[\x06I\"\x12alias comment\x06;\x06FI" + "\"\nparam\x06;\x06F" + loaded.store = @store + comment = RDoc::Markup::Document.new( RDoc::Markup::Paragraph.new('this is a comment')) assert_equal m, loaded - assert_equal [al_m], loaded.aliases + assert_equal [al_m.name], loaded.aliases.map { |alas| alas.name } assert_equal 'some_block', loaded.block_params assert_equal 'call_seq', loaded.call_seq assert_equal comment, loaded.comment @@ -169,6 +161,8 @@ method(a, b) { |c, d| ... } assert_equal nil, loaded.singleton # defaults to nil assert_equal :public, loaded.visibility assert_equal nil, loaded.file + assert_equal cm, loaded.parent + assert_equal section, loaded.section end def test_name @@ -200,6 +194,15 @@ method(a, b) { |c, d| ... } assert_equal %w[a b c d], m.param_list end + def test_param_list_default + m = RDoc::AnyMethod.new nil, 'method' + m.parent = @c1 + + m.params = '(b = default)' + + assert_equal %w[b], m.param_list + end + def test_param_list_params m = RDoc::AnyMethod.new nil, 'method' m.parent = @c1 @@ -259,5 +262,58 @@ method(a, b) { |c, d| ... } assert_equal 'C1', @c1.method_list.last.parent_name end + def test_store_equals + loaded = Marshal.load Marshal.dump(@c1.method_list.last) + + loaded.store = @store + + assert_equal @store, loaded.file.store + end + + def test_superclass_method + m3 = RDoc::AnyMethod.new '', 'no_super' + + m2 = RDoc::AnyMethod.new '', 'supers' + m2.calls_super = true + + m1 = RDoc::AnyMethod.new '', 'supers' + + c1 = RDoc::NormalClass.new 'Outer' + c1.store = @store + c1.add_method m1 + + c2 = RDoc::NormalClass.new 'Inner', c1 + c2.store = @store + c2.add_method m2 + c2.add_method m3 + + assert_nil m3.superclass_method, + 'no superclass method for no_super' + + assert_equal m1, m2.superclass_method, + 'superclass method missing for supers' + end + + def test_superclass_method_multilevel + m2 = RDoc::AnyMethod.new '', 'supers' + m2.calls_super = true + + m1 = RDoc::AnyMethod.new '', 'supers' + + c1 = RDoc::NormalClass.new 'Outer' + c1.store = @store + c1.add_method m1 + + c2 = RDoc::NormalClass.new 'Middle', c1 + c2.store = @store + + c3 = RDoc::NormalClass.new 'Inner', c2 + c3.store = @store + c3.add_method m2 + + assert_equal m1, m2.superclass_method, + 'superclass method missing for supers' + end + end diff --git a/test/rdoc/test_rdoc_attr.rb b/test/rdoc/test_rdoc_attr.rb index b69d8c6499..92ff1b9856 100644 --- a/test/rdoc/test_rdoc_attr.rb +++ b/test/rdoc/test_rdoc_attr.rb @@ -1,10 +1,10 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/rdoc' +require 'rdoc/test_case' -class TestRDocAttr < MiniTest::Unit::TestCase +class TestRDocAttr < RDoc::TestCase def setup + super + @a = RDoc::Attr.new nil, 'attr', 'RW', '' end @@ -43,15 +43,18 @@ class TestRDocAttr < MiniTest::Unit::TestCase end def test_marshal_dump - tl = RDoc::TopLevel.new 'file.rb' + tl = @store.add_file 'file.rb' @a.comment = 'this is a comment' @a.record_location tl - cm = RDoc::ClassModule.new 'Klass' + cm = tl.add_class RDoc::NormalClass, 'Klass' cm.add_attribute @a + section = cm.sections.first + loaded = Marshal.load Marshal.dump @a + loaded.store = @store assert_equal @a, loaded @@ -65,31 +68,58 @@ class TestRDocAttr < MiniTest::Unit::TestCase assert_equal 'RW', loaded.rw assert_equal false, loaded.singleton assert_equal :public, loaded.visibility + assert_equal tl, loaded.file + assert_equal cm, loaded.parent + assert_equal section, loaded.section + end + + def test_marshal_dump_singleton + tl = @store.add_file 'file.rb' + + @a.comment = 'this is a comment' + @a.record_location tl + + cm = tl.add_class RDoc::NormalClass, 'Klass' + cm.add_attribute @a + + section = cm.sections.first @a.rw = 'R' @a.singleton = true @a.visibility = :protected loaded = Marshal.load Marshal.dump @a + loaded.store = @store assert_equal @a, loaded + comment = RDoc::Markup::Document.new( + RDoc::Markup::Paragraph.new('this is a comment')) + assert_equal comment, loaded.comment assert_equal 'Klass::attr', loaded.full_name assert_equal 'attr', loaded.name assert_equal 'R', loaded.rw assert_equal true, loaded.singleton assert_equal :protected, loaded.visibility + assert_equal tl, loaded.file + assert_equal cm, loaded.parent + assert_equal section, loaded.section end def test_marshal_load_version_1 - data = "\x04\bU:\x0FRDoc::Attr[\fi\x06I\"\tattr\x06:\x06EF" \ - "\"\x0FKlass#attrI\"\aRW\x06;\x06F:\vpublic" \ - "o:\eRDoc::Markup::Document\x06:\v@parts[\x06" \ - "o:\x1CRDoc::Markup::Paragraph\x06;\t[\x06I" \ + tl = @store.add_file 'file.rb' + cm = tl.add_class RDoc::NormalClass, 'Klass' + section = cm.sections.first + + data = "\x04\bU:\x0FRDoc::Attr[\fi\x06I\"\tattr\x06:\x06EF" + + "\"\x0FKlass#attrI\"\aRW\x06;\x06F:\vpublic" + + "o:\eRDoc::Markup::Document\x06:\v@parts[\x06" + + "o:\x1CRDoc::Markup::Paragraph\x06;\t[\x06I" + "\"\x16this is a comment\x06;\x06FF" loaded = Marshal.load data + loaded.store = @store comment = RDoc::Markup::Document.new( RDoc::Markup::Paragraph.new('this is a comment')) @@ -101,7 +131,40 @@ class TestRDocAttr < MiniTest::Unit::TestCase assert_equal false, loaded.singleton assert_equal :public, loaded.visibility - assert_equal nil, loaded.file # version 2 + # version 2 + assert_nil loaded.file + + # version 3 + assert_equal cm, loaded.parent + assert_equal section, loaded.section + end + + def test_marshal_load_version_2 + tl = @store.add_file 'file.rb' + cm = tl.add_class RDoc::NormalClass, 'Klass' + section = cm.sections.first + + loaded = Marshal.load "\x04\bU:\x0FRDoc::Attr[\ri\aI\"\tattr\x06" + + ":\x06ETI\"\x0FKlass#attr\x06;\x06TI\"\aRW\x06" + + ";\x06T:\vpublico:\eRDoc::Markup::Document\a" + + ":\v@parts[\x06o:\x1CRDoc::Markup::Paragraph\x06;" + + "\t[\x06I\"\x16this is a comment\x06;\x06T:\n" + + "@file0FI\"\ffile.rb\x06;\x06T" + loaded.store = @store + + comment = doc(para('this is a comment')) + + assert_equal comment, loaded.comment + assert_equal 'Klass#attr', loaded.full_name + assert_equal 'attr', loaded.name + assert_equal 'RW', loaded.rw + assert_equal false, loaded.singleton + assert_equal :public, loaded.visibility + assert_equal tl, loaded.file + + # version 3 + assert_equal cm, loaded.parent + assert_equal section, loaded.section end def test_params diff --git a/test/rdoc/test_rdoc_class_module.rb b/test/rdoc/test_rdoc_class_module.rb index 7d32a91580..a6aa1e9472 100644 --- a/test/rdoc/test_rdoc_class_module.rb +++ b/test/rdoc/test_rdoc_class_module.rb @@ -1,14 +1,7 @@ -require 'pp' require File.expand_path '../xref_test_case', __FILE__ class TestRDocClassModule < XrefTestCase - def setup - super - - @RM = RDoc::Markup - end - def mu_pp obj s = '' s = PP.pp obj, s @@ -17,9 +10,9 @@ class TestRDocClassModule < XrefTestCase end def test_add_comment - tl1 = RDoc::TopLevel.new 'one.rb' - tl2 = RDoc::TopLevel.new 'two.rb' - tl3 = RDoc::TopLevel.new 'three.rb' + tl1 = @store.add_file 'one.rb' + tl2 = @store.add_file 'two.rb' + tl3 = @store.add_file 'three.rb' cm = RDoc::ClassModule.new 'Klass' cm.add_comment '# comment 1', tl1 @@ -40,8 +33,16 @@ class TestRDocClassModule < XrefTestCase assert_equal "comment 1\n---\ncomment 2\n---\n* comment 3", cm.comment end + def test_add_comment_comment + cm = RDoc::ClassModule.new 'Klass' + + cm.add_comment comment('comment'), @top_level + + assert_equal 'comment', cm.comment.text + end + def test_add_comment_stopdoc - tl = RDoc::TopLevel.new 'file.rb' + tl = @store.add_file 'file.rb' cm = RDoc::ClassModule.new 'Klass' cm.stop_doc @@ -52,7 +53,7 @@ class TestRDocClassModule < XrefTestCase end def test_ancestors - assert_equal [@parent], @child.ancestors + assert_equal [@parent, "Object"], @child.ancestors end def test_comment_equals @@ -70,14 +71,41 @@ class TestRDocClassModule < XrefTestCase assert_equal "comment 1\n---\ncomment 2\n---\n* comment 3", cm.comment end + def test_comment_equals_comment + cm = RDoc::ClassModule.new 'Klass' + + cm.comment = comment 'comment' + + assert_equal 'comment', cm.comment.text + end + + def test_docuent_self_or_methods + assert @c1.document_self_or_methods + + @c1.document_self = false + + assert @c1.document_self_or_methods + + @c1_m.document_self = false + + assert @c1.document_self_or_methods + + @c1__m.document_self = false + + refute @c1.document_self_or_methods + end + def test_each_ancestor - ancestors = [] + assert_equal [@parent], @child.each_ancestor.to_a + end - @child.each_ancestor do |mod| - ancestors << mod - end + def test_each_ancestor_cycle + m_incl = RDoc::Include.new 'M', nil + + m = @top_level.add_module RDoc::NormalModule, 'M' + m.add_include m_incl - assert_equal [@parent], ancestors + assert_empty m.each_ancestor.to_a end # handle making a short module alias of yourself @@ -89,7 +117,7 @@ class TestRDocClassModule < XrefTestCase end def test_from_module_comment - tl = RDoc::TopLevel.new 'file.rb' + tl = @store.add_file 'file.rb' klass = tl.add_class RDoc::NormalModule, 'Klass' klass.add_comment 'really a class', tl @@ -99,7 +127,8 @@ class TestRDocClassModule < XrefTestCase end def test_marshal_dump - tl = RDoc::TopLevel.new 'file.rb' + @store.path = Dir.tmpdir + tl = @store.add_file 'file.rb' ns = tl.add_module RDoc::NormalModule, 'Namespace' @@ -120,20 +149,32 @@ class TestRDocClassModule < XrefTestCase i1 = RDoc::Include.new 'I1', '' i1.record_location tl + e1 = RDoc::Extend.new 'E1', '' + e1.record_location tl + + section_comment = RDoc::Comment.new('section comment') + section_comment.location = tl + + assert_equal 1, cm.sections.length, 'sanity, default section only' + s0 = cm.sections.first + s1 = cm.add_section 'section', section_comment + cm.add_attribute a1 cm.add_attribute a2 cm.add_method m1 cm.add_constant c1 cm.add_include i1 + cm.add_extend e1 cm.add_comment 'this is a comment', tl loaded = Marshal.load Marshal.dump cm + loaded.store = @store assert_equal cm, loaded inner = RDoc::Markup::Document.new( RDoc::Markup::Paragraph.new('this is a comment')) - inner.file = tl.absolute_name + inner.file = tl comment = RDoc::Markup::Document.new inner @@ -142,9 +183,15 @@ class TestRDocClassModule < XrefTestCase assert_equal [c1], loaded.constants assert_equal 'Namespace::Klass', loaded.full_name assert_equal [i1], loaded.includes + assert_equal [e1], loaded.extends assert_equal [m1], loaded.method_list assert_equal 'Klass', loaded.name assert_equal 'Super', loaded.superclass + assert_equal [tl], loaded.in_files + assert_equal 'Namespace', loaded.parent.name + + expected = { nil => s0, 'section' => s1 } + assert_equal expected, loaded.sections_hash assert_equal tl, loaded.attributes.first.file @@ -152,11 +199,13 @@ class TestRDocClassModule < XrefTestCase assert_equal tl, loaded.includes.first.file + assert_equal tl, loaded.extends.first.file + assert_equal tl, loaded.method_list.first.file end def test_marshal_load_version_0 - tl = RDoc::TopLevel.new 'file.rb' + tl = @store.add_file 'file.rb' ns = tl.add_module RDoc::NormalModule, 'Namespace' cm = ns.add_class RDoc::NormalClass, 'Klass', 'Super' @@ -165,25 +214,29 @@ class TestRDocClassModule < XrefTestCase c = RDoc::Constant.new('C1', nil, '') i = RDoc::Include.new('I1', '') + s0 = cm.sections.first + cm.add_attribute a cm.add_method m cm.add_constant c cm.add_include i cm.add_comment 'this is a comment', tl - loaded = Marshal.load "\x04\bU:\x16RDoc::NormalClass[\x0Ei\x00\"\nKlass" \ - "\"\x15Namespace::KlassI\"\nSuper\x06:\x06EF" \ - "o:\eRDoc::Markup::Document\x06:\v@parts[\x06" \ - "o:\x1CRDoc::Markup::Paragraph\x06;\b[\x06I" \ - "\"\x16this is a comment\x06;\x06F[\x06[\aI" \ - "\"\aa1\x06;\x06FI\"\aRW\x06;\x06F[\x06[\aI" \ - "\"\aC1\x06;\x06Fo;\a\x06;\b[\x00[\x06[\aI" \ - "\"\aI1\x06;\x06Fo;\a\x06;\b[\x00[\a[\aI" \ - "\"\nclass\x06;\x06F[\b[\a:\vpublic[\x00[\a" \ - ":\x0Eprotected[\x00[\a:\fprivate[\x00[\aI" \ - "\"\rinstance\x06;\x06F[\b[\a;\n[\x06I" \ + loaded = Marshal.load "\x04\bU:\x16RDoc::NormalClass[\x0Ei\x00\"\nKlass" + + "\"\x15Namespace::KlassI\"\nSuper\x06:\x06EF" + + "o:\eRDoc::Markup::Document\x06:\v@parts[\x06" + + "o:\x1CRDoc::Markup::Paragraph\x06;\b[\x06I" + + "\"\x16this is a comment\x06;\x06F[\x06[\aI" + + "\"\aa1\x06;\x06FI\"\aRW\x06;\x06F[\x06[\aI" + + "\"\aC1\x06;\x06Fo;\a\x06;\b[\x00[\x06[\aI" + + "\"\aI1\x06;\x06Fo;\a\x06;\b[\x00[\a[\aI" + + "\"\nclass\x06;\x06F[\b[\a:\vpublic[\x00[\a" + + ":\x0Eprotected[\x00[\a:\fprivate[\x00[\aI" + + "\"\rinstance\x06;\x06F[\b[\a;\n[\x06I" + "\"\am1\x06;\x06F[\a;\v[\x00[\a;\f[\x00" + loaded.store = @store + assert_equal cm, loaded comment = RDoc::Markup::Document.new( @@ -197,12 +250,300 @@ class TestRDocClassModule < XrefTestCase assert_equal [m], loaded.method_list assert_equal 'Klass', loaded.name assert_equal 'Super', loaded.superclass - assert_equal nil, loaded.file + assert_nil loaded.file + assert_empty loaded.in_files + assert_nil loaded.parent + assert loaded.current_section + + expected = { nil => s0 } + assert_equal expected, loaded.sections_hash + end + + def test_marshal_load_version_1 + tl = @store.add_file 'file.rb' + + ns = tl.add_module RDoc::NormalModule, 'Namespace' + + cm = ns.add_class RDoc::NormalClass, 'Klass', 'Super' + cm.record_location tl + + a1 = RDoc::Attr.new nil, 'a1', 'RW', '' + a1.record_location tl + a2 = RDoc::Attr.new nil, 'a2', 'RW', '', true + a2.record_location tl + + m1 = RDoc::AnyMethod.new nil, 'm1' + m1.record_location tl + + c1 = RDoc::Constant.new 'C1', nil, '' + c1.record_location tl + + i1 = RDoc::Include.new 'I1', '' + i1.record_location tl + + s0 = cm.sections.first + + cm.add_attribute a1 + cm.add_attribute a2 + cm.add_method m1 + cm.add_constant c1 + cm.add_include i1 + cm.add_comment 'this is a comment', tl + + loaded = Marshal.load "\x04\bU:\x16RDoc::NormalClass[\x0Ei\x06I\"\nKlass" + + "\x06:\x06EFI\"\x15Namespace::Klass\x06;\x06FI" + + "\"\nSuper\x06;\x06Fo:\eRDoc::Markup::Document\a" + + ":\v@parts[\x06o;\a\a;\b[\x06o" + + ":\x1CRDoc::Markup::Paragraph\x06;\b" + + "[\x06I\"\x16this is a comment\x06;\x06F" + + ":\n@fileI\"\ffile.rb\x06;\x06F;\n0[\a[\nI" + + "\"\aa2\x06;\x06FI\"\aRW\x06;\x06F:\vpublicT@\x11" + + "[\nI\"\aa1\x06;\x06FI\"\aRW\x06;\x06F;\vF@\x11" + + "[\x06[\bI\"\aC1\x06;\x06Fo;\a\a;\b[\x00;\n0@\x11" + + "[\x06[\bI\"\aI1\x06;\x06Fo;\a\a;\b[\x00;\n0@\x11" + + "[\a[\aI\"\nclass\x06;\x06F[\b[\a;\v[\x00" + + "[\a:\x0Eprotected[\x00[\a:\fprivate[\x00[\aI" + + "\"\rinstance\x06;\x06F[\b[\a;\v[\x06[\aI" + + "\"\am1\x06;\x06F@\x11[\a;\f[\x00[\a;\r[\x00" + + loaded.store = @store + + assert_equal cm, loaded + + inner = RDoc::Markup::Document.new( + RDoc::Markup::Paragraph.new('this is a comment')) + inner.file = tl + + comment = RDoc::Markup::Document.new inner + + assert_equal [a2, a1], loaded.attributes.sort + assert_equal comment, loaded.comment + assert_equal [c1], loaded.constants + assert_equal 'Namespace::Klass', loaded.full_name + assert_equal [i1], loaded.includes + assert_empty loaded.extends + assert_equal [m1], loaded.method_list + assert_equal 'Klass', loaded.name + assert_equal 'Super', loaded.superclass + assert_empty loaded.in_files + assert_nil loaded.parent + assert loaded.current_section + + assert_equal tl, loaded.attributes.first.file + assert_equal tl, loaded.constants.first.file + assert_equal tl, loaded.includes.first.file + assert_equal tl, loaded.method_list.first.file + + expected = { nil => s0 } + assert_equal expected, loaded.sections_hash + end + + def test_marshal_load_version_2 + tl = @store.add_file 'file.rb' + + ns = tl.add_module RDoc::NormalModule, 'Namespace' + + cm = ns.add_class RDoc::NormalClass, 'Klass', 'Super' + cm.record_location tl + + a1 = RDoc::Attr.new nil, 'a1', 'RW', '' + a1.record_location tl + a2 = RDoc::Attr.new nil, 'a2', 'RW', '', true + a2.record_location tl + + m1 = RDoc::AnyMethod.new nil, 'm1' + m1.record_location tl + + c1 = RDoc::Constant.new 'C1', nil, '' + c1.record_location tl + + i1 = RDoc::Include.new 'I1', '' + i1.record_location tl + + e1 = RDoc::Extend.new 'E1', '' + e1.record_location tl + + s0 = cm.sections.first + + cm.add_attribute a1 + cm.add_attribute a2 + cm.add_method m1 + cm.add_constant c1 + cm.add_include i1 + cm.add_extend e1 + cm.add_comment 'this is a comment', tl + + loaded = Marshal.load "\x04\bU:\x16RDoc::NormalClass[\x0Fi\aI\"\nKlass" + + "\x06:\x06EFI\"\x15Namespace::Klass\x06;\x06FI" + + "\"\nSuper\x06;\x06Fo:\eRDoc::Markup::Document\a" + + ":\v@parts[\x06o;\a\a;\b[\x06o" + + ":\x1CRDoc::Markup::Paragraph\x06;\b" + + "[\x06I\"\x16this is a comment\x06;\x06F" + + ":\n@fileI\"\ffile.rb\x06;\x06F;\n0[\a[\nI" + + "\"\aa2\x06;\x06FI\"\aRW\x06;\x06F:\vpublicT@\x11" + + "[\nI\"\aa1\x06;\x06FI\"\aRW\x06;\x06F;\vF@\x11" + + "[\x06[\bI\"\aC1\x06;\x06Fo;\a\a;\b[\x00;\n0@\x11" + + "[\x06[\bI\"\aI1\x06;\x06Fo;\a\a;\b[\x00;\n0@\x11" + + "[\a[\aI\"\nclass\x06;\x06F[\b[\a;\v[\x00" + + "[\a:\x0Eprotected[\x00[\a:\fprivate[\x00[\aI" + + "\"\rinstance\x06;\x06F[\b[\a;\v[\x06[\aI" + + "\"\am1\x06;\x06F@\x11[\a;\f[\x00[\a;\r[\x00" + + "[\x06[\bI\"\aE1\x06;\x06Fo;\a\a;\b[\x00;\n0@\x11" + + loaded.store = @store + + assert_equal cm, loaded + + inner = RDoc::Markup::Document.new( + RDoc::Markup::Paragraph.new('this is a comment')) + inner.file = tl + + comment = RDoc::Markup::Document.new inner + + assert_equal [a2, a1], loaded.attributes.sort + assert_equal comment, loaded.comment + assert_equal [c1], loaded.constants + assert_equal 'Namespace::Klass', loaded.full_name + assert_equal [i1], loaded.includes + assert_equal [e1], loaded.extends + assert_equal [m1], loaded.method_list + assert_equal 'Klass', loaded.name + assert_equal 'Super', loaded.superclass + assert_empty loaded.in_files + assert_nil loaded.parent + assert loaded.current_section + + assert_equal tl, loaded.attributes. first.file + assert_equal tl, loaded.constants. first.file + assert_equal tl, loaded.includes. first.file + assert_equal tl, loaded.extends. first.file + assert_equal tl, loaded.method_list.first.file + + expected = { nil => s0 } + assert_equal expected, loaded.sections_hash + end + + def test_marshal_load_version_3 + tl = @store.add_file 'file.rb' + + ns = tl.add_module RDoc::NormalModule, 'Namespace' + + cm = ns.add_class RDoc::NormalClass, 'Klass', 'Super' + cm.record_location tl + + a1 = RDoc::Attr.new nil, 'a1', 'RW', '' + a1.record_location tl + a2 = RDoc::Attr.new nil, 'a2', 'RW', '', true + a2.record_location tl + + m1 = RDoc::AnyMethod.new nil, 'm1' + m1.record_location tl + + c1 = RDoc::Constant.new 'C1', nil, '' + c1.record_location tl + + i1 = RDoc::Include.new 'I1', '' + i1.record_location tl + + e1 = RDoc::Extend.new 'E1', '' + e1.record_location tl + + section_comment = RDoc::Comment.new('section comment') + section_comment.location = tl + + assert_equal 1, cm.sections.length, 'sanity, default section only' + s0 = cm.sections.first + s1 = cm.add_section 'section', section_comment + + cm.add_attribute a1 + cm.add_attribute a2 + cm.add_method m1 + cm.add_constant c1 + cm.add_include i1 + cm.add_extend e1 + cm.add_comment 'this is a comment', tl + + loaded = Marshal.load "\x04\bU:\x16RDoc::NormalClass[\x13i\bI\"\nKlass" + + "\x06:\x06ETI\"\x15Namespace::Klass\x06;\x06TI" + + "\"\nSuper\x06;\x06To:\eRDoc::Markup::Document\a" + + ":\v@parts[\x06o;\a\a;\b[\x06o" + + ":\x1CRDoc::Markup::Paragraph\x06;\b[\x06I" + + "\"\x16this is a comment\x06;\x06T:\n@fileI" + + "\"\ffile.rb\x06;\x06T;\n0[\a[\nI\"\aa2\x06;" + + "\x06TI\"\aRW\x06;\x06T:\vpublicT@\x11[\nI" + + "\"\aa1\x06;\x06TI\"\aRW\x06;\x06T;\vF@\x11" + + "[\x06U:\x13RDoc::Constant[\x0Fi\x00I\"\aC1\x06" + + ";\x06TI\"\x19Namespace::Klass::C1\x06;\x06T00o" + + ";\a\a;\b[\x00;\n0@\x11@\ac\x16RDoc::NormalClass0" + + "[\x06[\bI\"\aI1\x06;\x06To;\a\a;\b[\x00;\n0@\x11" + + "[\a[\aI\"\nclass\x06;\x06T[\b[\a;\v[\x00[\a" + + ":\x0Eprotected[\x00[\a:\fprivate[\x00[\aI" + + "\"\rinstance\x06;\x06T[\b[\a;\v[\x06[\aI" + + "\"\am1\x06;\x06T@\x11[\a;\r[\x00[\a;\x0E[\x00" + + "[\x06[\bI\"\aE1\x06;\x06To;\a\a;\b[\x00;\n0@\x11" + + "[\aU:\eRDoc::Context::Section[\bi\x000o;\a\a;\b" + + "[\x00;\n0U;\x0F[\bi\x00I\"\fsection\x06;\x06To" + + ";\a\a;\b[\x06o;\a\a;\b[\x06o;\t\x06;\b[\x06I" + + "\"\x14section comment\x06;\x06T;\n@\x11;\n0" + + "[\x06@\x11I\"\x0ENamespace\x06" + + ";\x06Tc\x17RDoc::NormalModule" + + loaded.store = @store + + assert_equal cm, loaded + + inner = RDoc::Markup::Document.new( + RDoc::Markup::Paragraph.new('this is a comment')) + inner.file = tl + + comment = RDoc::Markup::Document.new inner + + assert_equal [a2, a1], loaded.attributes.sort + assert_equal comment, loaded.comment + assert_equal [c1], loaded.constants + assert_equal 'Namespace::Klass', loaded.full_name + assert_equal [i1], loaded.includes + assert_equal [e1], loaded.extends + assert_equal [m1], loaded.method_list + assert_equal 'Klass', loaded.name + assert_equal 'Super', loaded.superclass + assert_equal 'Namespace', loaded.parent.name + assert loaded.current_section + + expected = { + nil => s0, + 'section' => s1, + } + + assert_equal expected, loaded.sections_hash + assert_equal [tl], loaded.in_files + + assert_equal tl, loaded.attributes. first.file + assert_equal tl, loaded.constants. first.file + assert_equal tl, loaded.includes. first.file + assert_equal tl, loaded.extends. first.file + assert_equal tl, loaded.method_list.first.file + end + + def test_merge + tl = @store.add_file 'one.rb' + p1 = tl.add_class RDoc::NormalClass, 'Parent' + c1 = p1.add_class RDoc::NormalClass, 'Klass' + + c2 = RDoc::NormalClass.new 'Klass' + + c2.merge c1 + + assert_equal 'Parent', c1.parent_name, 'original parent name' + assert_equal 'Parent', c2.parent_name, 'merged parent name' + + assert c1.current_section, 'original current_section' + assert c2.current_section, 'merged current_section' end def test_merge_attributes - tl1 = RDoc::TopLevel.new 'one.rb' - tl2 = RDoc::TopLevel.new 'two.rb' + tl1 = @store.add_file 'one.rb' + tl2 = @store.add_file 'two.rb' cm1 = RDoc::ClassModule.new 'Klass' @@ -237,7 +578,7 @@ class TestRDocClassModule < XrefTestCase end def test_merge_attributes_version_0 - tl1 = RDoc::TopLevel.new 'one.rb' + tl1 = @store.add_file 'one.rb' cm1 = RDoc::ClassModule.new 'Klass' @@ -270,7 +611,7 @@ class TestRDocClassModule < XrefTestCase end def test_merge_collections_drop - tl = RDoc::TopLevel.new 'file' + tl = @store.add_file 'file' cm1 = RDoc::ClassModule.new 'C' cm1.record_location tl @@ -297,17 +638,21 @@ class TestRDocClassModule < XrefTestCase end def test_merge_comment - tl1 = RDoc::TopLevel.new 'one.rb' - tl2 = RDoc::TopLevel.new 'two.rb' + tl1 = @store.add_file 'one.rb' + tl2 = @store.add_file 'two.rb' - cm1 = RDoc::ClassModule.new 'Klass' + cm1 = tl1.add_class RDoc::ClassModule, 'Klass' cm1.add_comment 'klass 1', tl1 + cm1.record_location tl1 - cm2 = RDoc::ClassModule.new 'Klass' + cm2 = tl1.add_class RDoc::NormalClass, 'Klass' cm2.add_comment 'klass 2', tl2 cm2.add_comment 'klass 3', tl1 + cm2.record_location tl1 + cm2.record_location tl2 cm2 = Marshal.load Marshal.dump cm2 + cm2.store = @store cm1.merge cm2 @@ -322,7 +667,7 @@ class TestRDocClassModule < XrefTestCase end def test_merge_comment_version_0 - tl = RDoc::TopLevel.new 'file.rb' + tl = @store.add_file 'file.rb' cm1 = RDoc::ClassModule.new 'Klass' cm1.add_comment 'klass 1', tl @@ -347,17 +692,19 @@ class TestRDocClassModule < XrefTestCase end def test_merge_constants - tl1 = RDoc::TopLevel.new 'one.rb' - tl2 = RDoc::TopLevel.new 'two.rb' + tl1 = @store.add_file 'one.rb' + tl2 = @store.add_file 'two.rb' - cm1 = RDoc::ClassModule.new 'Klass' + cm1 = tl1.add_class RDoc::ClassModule, 'Klass' const = cm1.add_constant RDoc::Constant.new('C1', nil, 'one') const.record_location tl1 const = cm1.add_constant RDoc::Constant.new('C3', nil, 'one') const.record_location tl1 - cm2 = RDoc::ClassModule.new 'Klass' + store = RDoc::Store.new + tl = store.add_file 'one.rb' + cm2 = tl.add_class RDoc::ClassModule, 'Klass' cm2.instance_variable_set :@comment, @RM::Document.new const = cm2.add_constant RDoc::Constant.new('C2', nil, 'two') @@ -381,16 +728,18 @@ class TestRDocClassModule < XrefTestCase end def test_merge_constants_version_0 - tl1 = RDoc::TopLevel.new 'one.rb' + tl1 = @store.add_file 'one.rb' - cm1 = RDoc::ClassModule.new 'Klass' + cm1 = tl1.add_class RDoc::ClassModule, 'Klass' const = cm1.add_constant RDoc::Constant.new('C1', nil, 'one') const.record_location tl1 const = cm1.add_constant RDoc::Constant.new('C3', nil, 'one') const.record_location tl1 - cm2 = RDoc::ClassModule.new 'Klass' + store = RDoc::Store.new + tl = store.add_file 'one.rb' + cm2 = tl.add_class RDoc::ClassModule, 'Klass' cm2.instance_variable_set :@comment, @RM::Document.new const = cm2.add_constant RDoc::Constant.new('C2', nil, 'two') @@ -411,18 +760,55 @@ class TestRDocClassModule < XrefTestCase assert_equal expected, cm1.constants.sort end + def test_merge_extends + tl1 = @store.add_file 'one.rb' + cm1 = tl1.add_class RDoc::ClassModule, 'Klass' + + ext = cm1.add_extend RDoc::Extend.new('I1', 'one') + ext.record_location tl1 + ext = cm1.add_extend RDoc::Extend.new('I3', 'one') + ext.record_location tl1 + + tl2 = @store.add_file 'two.rb' + tl2.store = RDoc::Store.new + + cm2 = tl2.add_class RDoc::ClassModule, 'Klass' + cm2.instance_variable_set :@comment, @RM::Document.new + + ext = cm2.add_extend RDoc::Extend.new('I2', 'two') + ext.record_location tl2 + ext = cm2.add_extend RDoc::Extend.new('I3', 'one') + ext.record_location tl1 + ext = cm2.add_extend RDoc::Extend.new('I4', 'one') + ext.record_location tl1 + + cm1.merge cm2 + + expected = [ + RDoc::Extend.new('I2', 'two'), + RDoc::Extend.new('I3', 'one'), + RDoc::Extend.new('I4', 'one'), + ] + + expected.each do |a| a.parent = cm1 end + + assert_equal expected, cm1.extends.sort + end + def test_merge_includes - tl1 = RDoc::TopLevel.new 'one.rb' - tl2 = RDoc::TopLevel.new 'two.rb' + tl1 = @store.add_file 'one.rb' - cm1 = RDoc::ClassModule.new 'Klass' + cm1 = tl1.add_class RDoc::ClassModule, 'Klass' incl = cm1.add_include RDoc::Include.new('I1', 'one') incl.record_location tl1 incl = cm1.add_include RDoc::Include.new('I3', 'one') incl.record_location tl1 - cm2 = RDoc::ClassModule.new 'Klass' + tl2 = @store.add_file 'two.rb' + tl2.store = RDoc::Store.new + + cm2 = tl2.add_class RDoc::ClassModule, 'Klass' cm2.instance_variable_set :@comment, @RM::Document.new incl = cm2.add_include RDoc::Include.new('I2', 'two') @@ -446,16 +832,19 @@ class TestRDocClassModule < XrefTestCase end def test_merge_includes_version_0 - tl1 = RDoc::TopLevel.new 'one.rb' + tl1 = @store.add_file 'one.rb' - cm1 = RDoc::ClassModule.new 'Klass' + cm1 = tl1.add_class RDoc::ClassModule, 'Klass' incl = cm1.add_include RDoc::Include.new('I1', 'one') incl.record_location tl1 incl = cm1.add_include RDoc::Include.new('I3', 'one') incl.record_location tl1 - cm2 = RDoc::ClassModule.new 'Klass' + tl2 = @store.add_file 'one.rb' + tl2.store = RDoc::Store.new + + cm2 = tl2.add_class RDoc::ClassModule, 'Klass' cm2.instance_variable_set :@comment, @RM::Document.new incl = cm2.add_include RDoc::Include.new('I2', 'two') @@ -477,10 +866,10 @@ class TestRDocClassModule < XrefTestCase end def test_merge_methods - tl1 = RDoc::TopLevel.new 'one.rb' - tl2 = RDoc::TopLevel.new 'two.rb' + tl1 = @store.add_file 'one.rb' + tl2 = @store.add_file 'two.rb' - cm1 = RDoc::ClassModule.new 'Klass' + cm1 = tl1.add_class RDoc::NormalClass, 'Klass' meth = cm1.add_method RDoc::AnyMethod.new(nil, 'm1') meth.record_location tl1 @@ -488,6 +877,7 @@ class TestRDocClassModule < XrefTestCase meth.record_location tl1 cm2 = RDoc::ClassModule.new 'Klass' + cm2.store = @store cm2.instance_variable_set :@comment, @RM::Document.new meth = cm2.add_method RDoc::AnyMethod.new(nil, 'm2') @@ -511,9 +901,9 @@ class TestRDocClassModule < XrefTestCase end def test_merge_methods_version_0 - tl1 = RDoc::TopLevel.new 'one.rb' + tl1 = @store.add_file 'one.rb' - cm1 = RDoc::ClassModule.new 'Klass' + cm1 = tl1.add_class RDoc::NormalClass, 'Klass' meth = cm1.add_method RDoc::AnyMethod.new(nil, 'm1') meth.record_location tl1 @@ -521,6 +911,7 @@ class TestRDocClassModule < XrefTestCase meth.record_location tl1 cm2 = RDoc::ClassModule.new 'Klass' + cm2.store = @store cm2.instance_variable_set :@comment, @RM::Document.new meth = cm2.add_method RDoc::AnyMethod.new(nil, 'm2') @@ -541,49 +932,176 @@ class TestRDocClassModule < XrefTestCase assert_equal expected, cm1.method_list.sort end + def test_merge_sections + store1 = @store + + tl1_1 = store1.add_file 'one.rb' + + cm1 = tl1_1.add_class RDoc::ClassModule, 'Klass' + cm1.record_location tl1_1 + + s1_0 = cm1.sections.first + s1_1 = cm1.add_section 'section 1', comment('comment 1', tl1_1) + cm1.add_section 'section 2', comment('comment 2 a', tl1_1) + cm1.add_section 'section 4', comment('comment 4 a', tl1_1) + + store2 = RDoc::Store.new + tl2_1 = store2.add_file 'one.rb' + tl2_2 = store2.add_file 'two.rb' + + cm2 = tl2_1.add_class RDoc::ClassModule, 'Klass' + cm2.record_location tl2_1 + cm2.record_location tl2_2 + + cm2.sections.first + s2_2 = cm2.add_section 'section 2', comment('comment 2 b', tl2_1) + s2_3 = cm2.add_section 'section 3', comment('comment 3', tl2_2) + cm2.add_section 'section 4', comment('comment 4 b', tl2_2) + + cm1.merge cm2 + + expected = [ + s1_0, + s1_1, + s2_2, + s2_3, + RDoc::Context::Section.new(cm1, 'section 4', nil) + ] + + merged_sections = cm1.sections.sort_by do |s| + s.title || '' + end + + assert_equal expected, merged_sections + + assert_equal [comment('comment 2 b', tl2_1)], + cm1.sections_hash['section 2'].comments + + expected_s4_comments = [ + comment('comment 4 a', tl2_1), + comment('comment 4 b', tl2_2), + ] + + assert_equal expected_s4_comments, cm1.sections_hash['section 4'].comments + end + + def test_merge_sections_overlap + store1 = @store + + tl1_1 = store1.add_file 'one.rb' + tl1_3 = store1.add_file 'three.rb' + + cm1 = tl1_1.add_class RDoc::ClassModule, 'Klass' + cm1.record_location tl1_1 + + cm1.add_section 'section', comment('comment 1 a', tl1_1) + cm1.add_section 'section', comment('comment 3', tl1_3) + + store2 = RDoc::Store.new + tl2_1 = store2.add_file 'one.rb' + tl2_2 = store2.add_file 'two.rb' + tl2_3 = store2.add_file 'three.rb' + + cm2 = tl2_1.add_class RDoc::ClassModule, 'Klass' + cm2.record_location tl2_1 + cm2.record_location tl2_2 + + s2_0 = cm2.sections.first + s2_1 = cm2.add_section 'section', comment('comment 1 b', tl1_1) + cm2.add_section 'section', comment('comment 2', tl2_2) + + cm1.merge_sections cm2 + + expected = [ + s2_0, + s2_1, + ] + + merged_sections = cm1.sections.sort_by do |s| + s.title || '' + end + + assert_equal expected, merged_sections + + expected = [ + comment('comment 1 b', tl2_1), + comment('comment 3', tl2_3), + comment('comment 2', tl2_2), + ] + + comments = cm1.sections_hash['section'].comments + + assert_equal expected, comments.sort_by { |c| c.file.name } + end + def test_parse - tl1 = RDoc::TopLevel.new 'one.rb' - tl2 = RDoc::TopLevel.new 'two.rb' + tl1 = @store.add_file 'one.rb' + tl2 = @store.add_file 'two.rb' cm = RDoc::ClassModule.new 'Klass' cm.add_comment 'comment 1', tl1 cm.add_comment 'comment 2', tl2 doc1 = @RM::Document.new @RM::Paragraph.new 'comment 1' - doc1.file = tl1.absolute_name + doc1.file = tl1 doc2 = @RM::Document.new @RM::Paragraph.new 'comment 2' - doc2.file = tl2.absolute_name + doc2.file = tl2 expected = @RM::Document.new doc1, doc2 assert_equal expected, cm.parse(cm.comment_location) end - def test_parse_comment_location - tl1 = RDoc::TopLevel.new 'one.rb' - tl2 = RDoc::TopLevel.new 'two.rb' + def test_parse_comment + tl1 = @store.add_file 'one.rb' + + cm = RDoc::ClassModule.new 'Klass' + cm.comment = comment 'comment 1', tl1 + + doc = @RM::Document.new @RM::Paragraph.new 'comment 1' + doc.file = tl1 + + assert_equal doc, cm.parse(cm.comment) + end + + def test_parse_comment_format + tl1 = @store.add_file 'one.rb' cm = RDoc::ClassModule.new 'Klass' + cm.comment = comment 'comment ((*1*))', tl1 + cm.comment.format = 'rd' + + doc = @RM::Document.new @RM::Paragraph.new 'comment 1' + doc.file = tl1 + + assert_equal doc, cm.parse(cm.comment) + end + + def test_parse_comment_location + tl1 = @store.add_file 'one.rb' + tl2 = @store.add_file 'two.rb' + + cm = tl1.add_class RDoc::NormalClass, 'Klass' cm.add_comment 'comment 1', tl1 cm.add_comment 'comment 2', tl2 cm = Marshal.load Marshal.dump cm doc1 = @RM::Document.new @RM::Paragraph.new 'comment 1' - doc1.file = tl1.absolute_name + doc1.file = tl1 doc2 = @RM::Document.new @RM::Paragraph.new 'comment 2' - doc2.file = tl2.absolute_name + doc2.file = tl2 assert_same cm.comment_location, cm.parse(cm.comment_location) end def test_remove_nodoc_children - parent = RDoc::ClassModule.new 'A' + parent = @top_level.add_class RDoc::ClassModule, 'A' parent.modules_hash.replace 'B' => true, 'C' => true - RDoc::TopLevel.all_modules_hash.replace 'A::B' => true + @store.modules_hash.replace 'A::B' => true parent.classes_hash.replace 'D' => true, 'E' => true - RDoc::TopLevel.all_classes_hash.replace 'A::D' => true + @store.classes_hash.replace 'A::D' => true parent.remove_nodoc_children @@ -591,6 +1109,83 @@ class TestRDocClassModule < XrefTestCase assert_equal %w[D], parent.classes_hash.keys end + def test_search_record + @c2_c3.add_comment 'This is a comment.', @xref_data + + expected = [ + 'C3', + 'C2::C3', + 'C2::C3', + '', + 'C2/C3.html', + '', + "

This is a comment.\n" + ] + + assert_equal expected, @c2_c3.search_record + end + + def test_search_record_merged + @c2_c3.add_comment 'comment A', @store.add_file('a.rb') + @c2_c3.add_comment 'comment B', @store.add_file('b.rb') + + expected = [ + 'C3', + 'C2::C3', + 'C2::C3', + '', + 'C2/C3.html', + '', + "

comment A\n

comment B\n" + ] + + assert_equal expected, @c2_c3.search_record + end + + def test_store_equals + # version 2 + loaded = Marshal.load "\x04\bU:\x16RDoc::NormalClass[\x0Fi\aI\"\nKlass" + + "\x06:\x06EFI\"\x15Namespace::Klass\x06;\x06FI" + + "\"\nSuper\x06;\x06Fo:\eRDoc::Markup::Document\a" + + ":\v@parts[\x06o;\a\a;\b[\x06o" + + ":\x1CRDoc::Markup::Paragraph\x06;\b" + + "[\x06I\"\x16this is a comment\x06;\x06F" + + ":\n@fileI\"\ffile.rb\x06;\x06F;\n0[\a[\nI" + + "\"\aa2\x06;\x06FI\"\aRW\x06;\x06F:\vpublicT@\x11" + + "[\nI\"\aa1\x06;\x06FI\"\aRW\x06;\x06F;\vF@\x11" + + "[\x06[\bI\"\aC1\x06;\x06Fo;\a\a;\b[\x00;\n0@\x11" + + "[\x06[\bI\"\aI1\x06;\x06Fo;\a\a;\b[\x00;\n0@\x11" + + "[\a[\aI\"\nclass\x06;\x06F[\b[\a;\v[\x00" + + "[\a:\x0Eprotected[\x00[\a:\fprivate[\x00[\aI" + + "\"\rinstance\x06;\x06F[\b[\a;\v[\x06[\aI" + + "\"\am1\x06;\x06F@\x11[\a;\f[\x00[\a;\r[\x00" + + "[\x06[\bI\"\aE1\x06;\x06Fo;\a\a;\b[\x00;\n0@\x11" + + loaded.store = @store + + assert_same @store, loaded.store + + a = loaded.attributes.first + assert_same @store, a.store + assert_same @store, a.file.store + + c = loaded.constants.first + assert_same @store, c.store + assert_same @store, c.file.store + + i = loaded.includes.first + assert_same @store, i.store + assert_same @store, i.file.store + + e = loaded.extends.first + assert_same @store, e.store + assert_same @store, e.file.store + + m = loaded.method_list.first + assert_same @store, m.store + assert_same @store, m.file.store + end + def test_superclass assert_equal @c3_h1, @c3_h2.superclass end @@ -668,6 +1263,30 @@ class TestRDocClassModule < XrefTestCase assert_equal 'O1::A1', o1_a1_m.full_name end + def test_update_aliases_reparent_root + store = RDoc::Store.new + + top_level = store.add_file 'file.rb' + + klass = top_level.add_class RDoc::NormalClass, 'Klass' + object = top_level.add_class RDoc::NormalClass, 'Object' + + const = RDoc::Constant.new 'A', nil, '' + const.record_location top_level + const.is_alias_for = klass + + top_level.add_module_alias klass, 'A', top_level + + object.add_constant const + + object.update_aliases + + assert_equal %w[A Klass Object], store.classes_hash.keys.sort + + assert_equal 'A', store.classes_hash['A'].full_name + assert_equal 'Klass', store.classes_hash['Klass'].full_name + end + def test_update_includes a = RDoc::Include.new 'M1', nil b = RDoc::Include.new 'M2', nil @@ -681,16 +1300,30 @@ class TestRDocClassModule < XrefTestCase @m1_m2.document_self = nil assert @m1_m2.remove_from_documentation? - assert RDoc::TopLevel.all_modules_hash.key? @m1_m2.full_name - refute RDoc::TopLevel.all_modules_hash[@m1_m2.full_name].nil? - RDoc::TopLevel.remove_nodoc RDoc::TopLevel.all_modules_hash - refute RDoc::TopLevel.all_modules_hash.key? @m1_m2.full_name + assert @store.modules_hash.key? @m1_m2.full_name + refute @store.modules_hash[@m1_m2.full_name].nil? + + @store.remove_nodoc @store.modules_hash + refute @store.modules_hash.key? @m1_m2.full_name @c1.update_includes assert_equal [a, c], @c1.includes end + def test_update_includes_trim + a = RDoc::Include.new 'D::M', nil + b = RDoc::Include.new 'D::M', nil + + @c1.add_include a + @c1.add_include b + @c1.ancestors # cache included modules + + @c1.update_includes + + assert_equal [a], @c1.includes + end + def test_update_includes_with_colons a = RDoc::Include.new 'M1', nil b = RDoc::Include.new 'M1::M2', nil @@ -704,15 +1337,75 @@ class TestRDocClassModule < XrefTestCase @m1_m2.document_self = nil assert @m1_m2.remove_from_documentation? - assert RDoc::TopLevel.all_modules_hash.key? @m1_m2.full_name - refute RDoc::TopLevel.all_modules_hash[@m1_m2.full_name].nil? - RDoc::TopLevel.remove_nodoc RDoc::TopLevel.all_modules_hash - refute RDoc::TopLevel.all_modules_hash.key? @m1_m2.full_name + assert @store.modules_hash.key? @m1_m2.full_name + refute @store.modules_hash[@m1_m2.full_name].nil? + @store.remove_nodoc @store.modules_hash + refute @store.modules_hash.key? @m1_m2.full_name @c1.update_includes assert_equal [a, c], @c1.includes end + def test_update_extends + a = RDoc::Extend.new 'M1', nil + b = RDoc::Extend.new 'M2', nil + c = RDoc::Extend.new 'C', nil + + @c1.add_extend a + @c1.add_extend b + @c1.add_extend c + @c1.each_extend do |extend| extend.module end # cache extended modules + + @m1_m2.document_self = nil + assert @m1_m2.remove_from_documentation? + + assert @store.modules_hash.key? @m1_m2.full_name + refute @store.modules_hash[@m1_m2.full_name].nil? + @store.remove_nodoc @store.modules_hash + refute @store.modules_hash.key? @m1_m2.full_name + + @c1.update_extends + + assert_equal [a, c], @c1.extends + end + + def test_update_extends_trim + a = RDoc::Extend.new 'D::M', nil + b = RDoc::Extend.new 'D::M', nil + + @c1.add_extend a + @c1.add_extend b + @c1.each_extend do |extend| extend.module end # cache extended modules + + @c1.update_extends + + assert_equal [a], @c1.extends + end + + def test_update_extends_with_colons + a = RDoc::Extend.new 'M1', nil + b = RDoc::Extend.new 'M1::M2', nil + c = RDoc::Extend.new 'C', nil + + @c1.add_extend a + @c1.add_extend b + @c1.add_extend c + @c1.each_extend do |extend| extend.module end # cache extended modules + + @m1_m2.document_self = nil + assert @m1_m2.remove_from_documentation? + + assert @store.modules_hash.key? @m1_m2.full_name + refute @store.modules_hash[@m1_m2.full_name].nil? + + @store.remove_nodoc @store.modules_hash + refute @store.modules_hash.key? @m1_m2.full_name + + @c1.update_extends + + assert_equal [a, c], @c1.extends + end + end diff --git a/test/rdoc/test_rdoc_code_object.rb b/test/rdoc/test_rdoc_code_object.rb index c7a37488cc..ef8a5df713 100644 --- a/test/rdoc/test_rdoc_code_object.rb +++ b/test/rdoc/test_rdoc_code_object.rb @@ -1,9 +1,6 @@ # coding: US-ASCII -require 'rubygems' -require 'minitest/autorun' require File.expand_path '../xref_test_case', __FILE__ -require 'rdoc/code_object' class TestRDocCodeObject < XrefTestCase @@ -32,6 +29,16 @@ class TestRDocCodeObject < XrefTestCase assert_equal 'I am a comment', @co.comment end + def test_comment_equals_comment + @co.comment = comment '' + + assert_equal '', @co.comment.text + + @co.comment = comment 'I am a comment' + + assert_equal 'I am a comment', @co.comment.text + end + def test_comment_equals_document doc = RDoc::Markup::Document.new @co.comment = doc @@ -167,7 +174,7 @@ class TestRDocCodeObject < XrefTestCase def test_file_name assert_equal nil, @co.file_name - @co.record_location RDoc::TopLevel.new 'lib/file.rb' + @co.record_location @store.add_file 'lib/file.rb' assert_equal 'lib/file.rb', @co.file_name end @@ -256,6 +263,26 @@ class TestRDocCodeObject < XrefTestCase refute @co.ignored? end + def test_section + parent = RDoc::Context.new + section = parent.sections.first + + @co.parent = parent + @co.instance_variable_set :@section, section + + assert_equal section, @co.section + + @co.instance_variable_set :@section, nil + @co.instance_variable_set :@section_title, nil + + assert_equal section, @co.section + + @co.instance_variable_set :@section, nil + @co.instance_variable_set :@section_title, 'new title' + + assert_equal 'new title', @co.section.title + end + def test_start_doc @co.document_self = false @co.document_children = false diff --git a/test/rdoc/test_rdoc_comment.rb b/test/rdoc/test_rdoc_comment.rb new file mode 100644 index 0000000000..1afc94c251 --- /dev/null +++ b/test/rdoc/test_rdoc_comment.rb @@ -0,0 +1,504 @@ +# coding: us-ascii + +require 'rdoc/test_case' + +class TestRDocComment < RDoc::TestCase + + def setup + super + + @top_level = @store.add_file 'file.rb' + @comment = RDoc::Comment.new + @comment.location = @top_level + @comment.text = 'this is a comment' + end + + def test_empty_eh + refute_empty @comment + + @comment = '' + + assert_empty @comment + end + + def test_equals2 + assert_equal @comment, @comment.dup + + c2 = @comment.dup + c2.text = nil + + refute_equal @comment, c2 + + c3 = @comment.dup + c3.location = nil + + refute_equal @comment, c3 + end + + def test_extract_call_seq + m = RDoc::AnyMethod.new nil, 'm' + + comment = RDoc::Comment.new <<-COMMENT, @top_level +call-seq: + bla => true or false + +moar comment + COMMENT + + comment.extract_call_seq m + + assert_equal "bla => true or false\n", m.call_seq + end + + def test_extract_call_seq_blank + m = RDoc::AnyMethod.new nil, 'm' + + comment = RDoc::Comment.new <<-COMMENT, @top_level +call-seq: + bla => true or false + + COMMENT + + comment.extract_call_seq m + + assert_equal "bla => true or false\n", m.call_seq + end + + def test_extract_call_seq_commented + m = RDoc::AnyMethod.new nil, 'm' + + comment = RDoc::Comment.new <<-COMMENT, @top_level +# call-seq: +# bla => true or false +# +# moar comment + COMMENT + + comment.extract_call_seq m + + assert_equal nil, m.call_seq + end + + def test_extract_call_seq_no_blank + m = RDoc::AnyMethod.new nil, 'm' + + comment = RDoc::Comment.new <<-COMMENT, @top_level +call-seq: + bla => true or false + COMMENT + + comment.extract_call_seq m + + assert_equal "bla => true or false\n", m.call_seq + end + + def test_extract_call_seq_undent + m = RDoc::AnyMethod.new nil, 'm' + + comment = RDoc::Comment.new <<-COMMENT, @top_level +call-seq: + bla => true or false +moar comment + COMMENT + + comment.extract_call_seq m + + assert_equal "bla => true or false\nmoar comment\n", m.call_seq + end + + def test_extract_call_seq_c + comment = RDoc::Comment.new <<-COMMENT +call-seq: + commercial() -> Date
+ commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8]
+ commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] + +If no arguments are given: +* ruby 1.8: returns a +Date+ for 1582-10-15 (the Day of Calendar Reform in + Italy) +* ruby 1.9: returns a +Date+ for julian day 0 + +Otherwise, returns a +Date+ for the commercial week year, commercial week, +and commercial week day given. Ignores the 4th argument. + COMMENT + + method_obj = RDoc::AnyMethod.new nil, 'blah' + + comment.extract_call_seq method_obj + + expected = <<-CALL_SEQ.chomp +commercial() -> Date
+commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8]
+commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] + + CALL_SEQ + + assert_equal expected, method_obj.call_seq + end + + def test_extract_call_seq_c_no_blank + comment = RDoc::Comment.new <<-COMMENT +call-seq: + commercial() -> Date
+ commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8]
+ commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] + COMMENT + + method_obj = RDoc::AnyMethod.new nil, 'blah' + + comment.extract_call_seq method_obj + + expected = <<-CALL_SEQ.chomp +commercial() -> Date
+commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8]
+commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] + + CALL_SEQ + + assert_equal expected, method_obj.call_seq + end + + def test_extract_call_seq_c_separator + comment = RDoc::Comment.new <<-'COMMENT' +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 + +Reads +ARGF+'s current file in its entirety, returning an +Array+ of its +lines, one line per element. Lines are assumed to be separated by _sep_. + + lines = ARGF.readlines + lines[0] #=> "This is line one\n" + + COMMENT + + method_obj = RDoc::AnyMethod.new nil, 'blah' + + comment.extract_call_seq method_obj + + expected = <<-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 + CALL_SEQ + + assert_equal expected, method_obj.call_seq + + expected = <<-'COMMENT' + +Reads +ARGF+'s current file in its entirety, returning an +Array+ of its +lines, one line per element. Lines are assumed to be separated by _sep_. + + lines = ARGF.readlines + lines[0] #=> "This is line one\n" + + COMMENT + + assert_equal expected, comment.text + end + + def test_force_encoding + skip "Encoding not implemented" unless Object.const_defined? :Encoding + + @comment.force_encoding Encoding::UTF_8 + + assert_equal Encoding::UTF_8, @comment.text.encoding + end + + def test_format + assert_equal 'rdoc', @comment.format + end + + def test_format_equals + c = comment 'content' + document = c.parse + + c.format = RDoc::RD + + assert_equal RDoc::RD, c.format + refute_same document, c.parse + end + + def test_initialize_copy + copy = @comment.dup + + refute_same @comment.text, copy.text + assert_same @comment.location, copy.location + end + + def test_location + assert_equal @top_level, @comment.location + end + + def test_normalize + @comment.text = <<-TEXT + # comment + TEXT + + assert_same @comment, @comment.normalize + + assert_equal 'comment', @comment.text + end + + def test_normalize_twice + @comment.text = <<-TEXT + # comment + TEXT + + @comment.normalize + + text = @comment.text + + @comment.normalize + + assert_same text, @comment.text, 'normalize not cached' + end + + def test_normalize_document + @comment.text = nil + @comment.document = @RM::Document.new + + assert_same @comment, @comment.normalize + + assert_nil @comment.text + end + + def test_normalize_eh + refute @comment.normalized? + + @comment.normalize + + assert @comment.normalized? + end + + def test_text + assert_equal 'this is a comment', @comment.text + end + + def test_text_equals + @comment.text = 'other' + + assert_equal 'other', @comment.text + refute @comment.normalized? + end + + def test_text_equals_no_text + c = RDoc::Comment.new nil, @top_level + c.document = @RM::Document.new + + e = assert_raises RDoc::Error do + c.text = 'other' + end + + assert_equal 'replacing document-only comment is not allowed', e.message + end + + def test_text_equals_parsed + document = @comment.parse + + @comment.text = 'other' + + refute_equal document, @comment.parse + end + + def test_tomdoc_eh + refute @comment.tomdoc? + + @comment.format = 'tomdoc' + + assert @comment.tomdoc? + end + + def test_parse + parsed = @comment.parse + + expected = @RM::Document.new( + @RM::Paragraph.new('this is a comment')) + + expected.file = @top_level + + assert_equal expected, parsed + assert_same parsed, @comment.parse + end + + def test_parse_rd + c = comment 'it ((*works*))' + c.format = 'rd' + + expected = + @RM::Document.new( + @RM::Paragraph.new('it works')) + expected.file = @top_level + + assert_equal expected, c.parse + end + + def test_remove_private_encoding + skip "Encoding not implemented" unless Object.const_defined? :Encoding + + comment = RDoc::Comment.new <<-EOS, @top_level +# This is text +#-- +# this is private + EOS + + comment.force_encoding Encoding::IBM437 + + comment.remove_private + + assert_equal Encoding::IBM437, comment.text.encoding + end + + def test_remove_private_hash + @comment.text = <<-TEXT +#-- +# private +#++ +# public + TEXT + + @comment.remove_private + + assert_equal "# public\n", @comment.text + end + + def test_remove_private_hash_trail + comment = RDoc::Comment.new <<-EOS, @top_level +# This is text +#-- +# this is private + EOS + + expected = RDoc::Comment.new <<-EOS, @top_level +# This is text + EOS + + comment.remove_private + + assert_equal expected, comment + end + + def test_remove_private_long + comment = RDoc::Comment.new <<-EOS, @top_level +#----- +#++ +# this is text +#----- + EOS + + expected = RDoc::Comment.new <<-EOS, @top_level +# this is text + EOS + + comment.remove_private + + assert_equal expected, comment + end + + def test_remove_private_rule + comment = RDoc::Comment.new <<-EOS, @top_level +# This is text with a rule: +# --- +# this is also text + EOS + + expected = comment.dup + + comment.remove_private + + assert_equal expected, comment + end + + def test_remove_private_star + @comment.text = <<-TEXT +/* + *-- + * private + *++ + * public + */ + TEXT + + @comment.remove_private + + assert_equal "/*\n * public\n */\n", @comment.text + end + + def test_remove_private_star2 + @comment.text = <<-TEXT +/*-- + * private + *++ + * public + */ + TEXT + + @comment.remove_private + + assert_equal "/*--\n * private\n *++\n * public\n */\n", @comment.text + end + + def test_remove_private_toggle + comment = RDoc::Comment.new <<-EOS, @top_level +# This is text +#-- +# this is private +#++ +# This is text again. + EOS + + expected = RDoc::Comment.new <<-EOS, @top_level +# This is text +# This is text again. + EOS + + comment.remove_private + + assert_equal expected, comment + end + + def test_remove_private_toggle_encoding + skip "Encoding not implemented" unless Object.const_defined? :Encoding + + comment = RDoc::Comment.new <<-EOS, @top_level +# This is text +#-- +# this is private +#++ +# This is text again. + EOS + + comment.force_encoding Encoding::IBM437 + + comment.remove_private + + assert_equal Encoding::IBM437, comment.text.encoding + end + + def test_remove_private_toggle_encoding_ruby_bug? + skip "Encoding not implemented" unless Object.const_defined? :Encoding + + comment = RDoc::Comment.new <<-EOS, @top_level +#-- +# this is private +#++ +# This is text again. + EOS + + comment.force_encoding Encoding::IBM437 + + comment.remove_private + + assert_equal Encoding::IBM437, comment.text.encoding + end + +end + diff --git a/test/rdoc/test_rdoc_constant.rb b/test/rdoc/test_rdoc_constant.rb index b915f5cc7a..1a2e43a6e4 100644 --- a/test/rdoc/test_rdoc_constant.rb +++ b/test/rdoc/test_rdoc_constant.rb @@ -8,6 +8,138 @@ class TestRDocConstant < XrefTestCase @const = @c1.constants.first end + def test_full_name + assert_equal 'C1::CONST', @const.full_name + end + + def test_is_alias_for + top_level = @store.add_file 'file.rb' + + c = RDoc::Constant.new 'CONST', nil, 'comment' + top_level.add_constant c + + assert_nil c.is_alias_for + + c.is_alias_for = 'C1' + + assert_equal @c1, c.is_alias_for + + c.is_alias_for = 'unknown' + + assert_equal 'unknown', c.is_alias_for + end + + def test_marshal_dump + top_level = @store.add_file 'file.rb' + + c = RDoc::Constant.new 'CONST', nil, 'this is a comment' + c.record_location top_level + + aliased = top_level.add_class RDoc::NormalClass, 'Aliased' + c.is_alias_for = aliased + + cm = top_level.add_class RDoc::NormalClass, 'Klass' + cm.add_constant c + + section = cm.sections.first + + loaded = Marshal.load Marshal.dump c + loaded.store = @store + + comment = doc(para('this is a comment')) + + assert_equal c, loaded + + assert_equal aliased, loaded.is_alias_for + assert_equal comment, loaded.comment + assert_equal top_level, loaded.file + assert_equal 'Klass::CONST', loaded.full_name + assert_equal 'CONST', loaded.name + assert_nil loaded.visibility + assert_equal cm, loaded.parent + assert_equal section, loaded.section + end + + def test_marshal_load + top_level = @store.add_file 'file.rb' + + c = RDoc::Constant.new 'CONST', nil, 'this is a comment' + c.record_location top_level + + cm = top_level.add_class RDoc::NormalClass, 'Klass' + cm.add_constant c + + section = cm.sections.first + + loaded = Marshal.load Marshal.dump c + loaded.store = @store + + comment = doc(para('this is a comment')) + + assert_equal c, loaded + + assert_nil loaded.is_alias_for + assert_equal comment, loaded.comment + assert_equal top_level, loaded.file + assert_equal 'Klass::CONST', loaded.full_name + assert_equal 'CONST', loaded.name + assert_nil loaded.visibility + assert_equal cm, loaded.parent + assert_equal section, loaded.section + end + + def test_marshal_load_version_0 + top_level = @store.add_file 'file.rb' + + aliased = top_level.add_class RDoc::NormalClass, 'Aliased' + cm = top_level.add_class RDoc::NormalClass, 'Klass' + section = cm.sections.first + + loaded = Marshal.load "\x04\bU:\x13RDoc::Constant[\x0Fi\x00I" + + "\"\nCONST\x06:\x06ETI\"\x11Klass::CONST\x06" + + ";\x06T0I\"\fAliased\x06;\x06To" + + ":\eRDoc::Markup::Document\a:\v@parts[\x06o" + + ":\x1CRDoc::Markup::Paragraph\x06;\b[\x06I" + + "\"\x16this is a comment\x06;\x06T:\n@file0I" + + "\"\ffile.rb\x06;\x06TI\"\nKlass\x06" + + ";\x06Tc\x16RDoc::NormalClass0" + + loaded.store = @store + + comment = doc(para('this is a comment')) + + assert_equal aliased, loaded.is_alias_for + assert_equal comment, loaded.comment + assert_equal top_level, loaded.file + assert_equal 'Klass::CONST', loaded.full_name + assert_equal 'CONST', loaded.name + assert_nil loaded.visibility + assert_equal cm, loaded.parent + assert_equal section, loaded.section + end + + def test_marshal_round_trip + top_level = @store.add_file 'file.rb' + + c = RDoc::Constant.new 'CONST', nil, 'this is a comment' + c.record_location top_level + c.is_alias_for = 'Unknown' + + cm = top_level.add_class RDoc::NormalClass, 'Klass' + cm.add_constant c + + section = cm.sections.first + + loaded = Marshal.load Marshal.dump c + loaded.store = @store + + reloaded = Marshal.load Marshal.dump loaded + reloaded.store = @store + + assert_equal section, reloaded.section + assert_equal 'Unknown', reloaded.is_alias_for + end + def test_path assert_equal 'C1.html#CONST', @const.path end diff --git a/test/rdoc/test_rdoc_context.rb b/test/rdoc/test_rdoc_context.rb index 2fb8ef7bb7..bd0baaa725 100644 --- a/test/rdoc/test_rdoc_context.rb +++ b/test/rdoc/test_rdoc_context.rb @@ -1,5 +1,3 @@ -require 'rubygems' -require 'minitest/autorun' require File.expand_path '../xref_test_case', __FILE__ class TestRDocContext < XrefTestCase @@ -8,6 +6,10 @@ class TestRDocContext < XrefTestCase super @context = RDoc::Context.new + @context.store = @store + + @enumerator = # 1.8 vs 1.9 + Object.const_defined?(:Enumerator) ? Enumerator : Enumerable::Enumerator end def test_initialize @@ -40,7 +42,7 @@ class TestRDocContext < XrefTestCase end def test_add_alias_method_attr - top_level = RDoc::TopLevel.new 'file.rb' + top_level = @store.add_file 'file.rb' attr = RDoc::Attr.new nil, 'old_name', 'R', '' @@ -60,7 +62,7 @@ class TestRDocContext < XrefTestCase end def test_add_alias_method - top_level = RDoc::TopLevel.new 'file.rb' + top_level = @store.add_file 'file.rb' meth = RDoc::AnyMethod.new nil, 'old_name' meth.singleton = false @@ -103,7 +105,7 @@ class TestRDocContext < XrefTestCase @c1.add_class RDoc::NormalClass, 'Klass', 'Object' assert_includes @c1.classes.map { |k| k.full_name }, 'C1::Klass' - assert_includes RDoc::TopLevel.classes.map { |k| k.full_name }, 'C1::Klass' + assert_includes @store.all_classes.map { |k| k.full_name }, 'C1::Klass' end def test_add_class_basic_object @@ -142,7 +144,7 @@ class TestRDocContext < XrefTestCase @c1.add_class RDoc::NormalClass, 'Klass', 'Object' assert_includes @c1.classes.map { |k| k.full_name }, 'C1::Klass' - assert_includes RDoc::TopLevel.classes.map { |k| k.full_name }, 'C1::Klass' + assert_includes @store.all_classes.map { |k| k.full_name }, 'C1::Klass' end def test_add_class_superclass @@ -163,9 +165,9 @@ class TestRDocContext < XrefTestCase refute_includes @c1.modules.map { |k| k.full_name }, 'C1::Klass', 'c1 modules' - assert_includes RDoc::TopLevel.classes.map { |k| k.full_name }, 'C1::Klass', + assert_includes @store.all_classes.map { |k| k.full_name }, 'C1::Klass', 'TopLevel classes' - refute_includes RDoc::TopLevel.modules.map { |k| k.full_name }, 'C1::Klass', + refute_includes @store.all_modules.map { |k| k.full_name }, 'C1::Klass', 'TopLevel modules' end @@ -176,6 +178,13 @@ class TestRDocContext < XrefTestCase assert_equal [const], @context.constants end + def test_add_extend + ext = RDoc::Extend.new 'Name', 'comment' + @context.add_extend ext + + assert_equal [ext], @context.extends + end + def test_add_include incl = RDoc::Include.new 'Name', 'comment' @context.add_include incl @@ -183,16 +192,6 @@ class TestRDocContext < XrefTestCase assert_equal [incl], @context.includes end - def test_add_include_twice - incl1 = RDoc::Include.new 'Name', 'comment' - @context.add_include incl1 - - incl2 = RDoc::Include.new 'Name', 'comment' - @context.add_include incl2 - - assert_equal [incl1], @context.includes - end - def test_add_method meth = RDoc::AnyMethod.new nil, 'old_name' meth.visibility = nil @@ -217,6 +216,34 @@ class TestRDocContext < XrefTestCase assert_equal %w[old_name new_name], @context.method_list.map { |m| m.name } end + def test_add_method_duplicate + @store.rdoc.options.verbosity = 2 + + meth1 = RDoc::AnyMethod.new nil, 'name' + meth1.record_location @store.add_file 'first.rb' + meth1.visibility = nil + meth1.comment = comment 'first' + + @context.add_method meth1 + + meth2 = RDoc::AnyMethod.new nil, 'name' + meth2.record_location @store.add_file 'second.rb' + meth2.comment = comment 'second' + + _, err = capture_io do + @context.add_method meth2 + end + + expected = 'Duplicate method (unknown)#name in file second.rb, ' \ + 'previously in file first.rb' + + assert_equal expected, err.chomp + + method = @context.method_list.first + + assert_equal 'first', method.comment.text + end + def test_add_module @c1.add_module RDoc::NormalModule, 'Mod' @@ -224,18 +251,35 @@ class TestRDocContext < XrefTestCase end def test_add_module_alias - tl = RDoc::TopLevel.new 'file.rb' + tl = @store.add_file 'file.rb' c3_c4 = @c2.add_module_alias @c2_c3, 'C4', tl - c4 = @c2.find_module_named('C4') - alias_constant = @c2.constants.first - assert_equal c4, c3_c4 + assert_equal 'C2::C4', c3_c4.full_name assert_equal tl, alias_constant.file end + def test_add_module_alias_top_level + store = RDoc::Store.new + + top_level = store.add_file 'file.rb' + + klass = top_level.add_class RDoc::NormalClass, 'Klass' + klass.comment = 'klass comment' + + object = top_level.add_class RDoc::NormalClass, 'Object' + + top_level.add_module_alias klass, 'A', top_level + + refute_empty object.constants + + constant = object.constants.first + + assert_equal 'klass comment', constant.comment + end + def test_add_module_class k = @c1.add_class RDoc::NormalClass, 'Klass', nil m = @c1.add_module RDoc::NormalModule, 'Klass' @@ -255,18 +299,20 @@ class TestRDocContext < XrefTestCase def test_add_section default_section = @context.sections.first - @context.add_section nil, '# comment' + @context.add_section nil, comment('comment', @top_level) assert_equal 1, @context.sections.length - assert_equal '# comment', @context.sections.first.comment + assert_equal [comment("comment", @top_level)], + @context.sections.first.comments - @context.add_section nil, '# new comment' + @context.add_section nil, comment('new comment', @top_level) assert_equal 1, @context.sections.length - assert_equal "# comment\n# ---\n# new comment", - @context.sections.first.comment + assert_equal [comment('comment', @top_level), + comment('new comment', @top_level)], + @context.sections.first.comments - @context.add_section 'other', '' + @context.add_section 'other', comment('', @top_level) assert_equal 2, @context.sections.length @@ -275,6 +321,23 @@ class TestRDocContext < XrefTestCase assert_equal default_section, @context.current_section end + def test_add_section_no_comment + default_section = @context.sections.first + + @context.add_section nil + + assert_equal 1, @context.sections.length + + @context.add_section 'other' + + assert_equal 2, @context.sections.length + + new_section = @context.sections.find { |section| section.title == 'other' } + + assert new_section + assert_equal default_section, @context.current_section + end + def test_add_to incl = RDoc::Include.new 'Name', 'comment' arr = [] @@ -288,7 +351,8 @@ class TestRDocContext < XrefTestCase def test_add_to_temporary_section incl = RDoc::Include.new 'Name', 'comment' arr = [] - section = @context.add_section 'temporary', '' + section = + @context.add_section 'temporary', RDoc::Comment.new('', @top_level) @context.temporary_section = section @context.add_to arr, incl @@ -316,19 +380,30 @@ class TestRDocContext < XrefTestCase refute_includes arr, incl end + def bench_add_include + cm = RDoc::ClassModule.new 'Klass' + + assert_performance_linear 0.9 do |count| + count.times do |i| + cm.add_include RDoc::Include.new("N::M#{i}", nil) + end + end + end + def test_child_name assert_equal 'C1::C1', @c1.child_name('C1') end def test_classes assert_equal %w[C2::C3], @c2.classes.map { |k| k.full_name } - assert_equal %w[C3::H1 C3::H2], @c3.classes.map { |k| k.full_name } + assert_equal %w[C3::H1 C3::H2], @c3.classes.map { |k| k.full_name }.sort end def test_current_section default_section = @context.current_section - new_section = @context.add_section 'other', '' + new_section = + @context.add_section 'other', RDoc::Comment.new('', @top_level) @context.temporary_section = new_section assert_equal new_section, @context.current_section @@ -338,7 +413,7 @@ class TestRDocContext < XrefTestCase def test_defined_in_eh assert @c1.defined_in?(@c1.top_level) - refute @c1.defined_in?(RDoc::TopLevel.new('name.rb')) + refute @c1.defined_in?(@store.add_file('name.rb')) end def test_equals2 @@ -347,6 +422,10 @@ class TestRDocContext < XrefTestCase refute_equal @c2_c3, @c3 end + def test_each_method_enumerator + assert_kind_of @enumerator, @c1.each_method + end + def test_each_section sects = [] consts = [] @@ -375,6 +454,10 @@ class TestRDocContext < XrefTestCase assert_equal expected_attrs, attrs end + def test_each_section_enumerator + assert_kind_of @enumerator, @c1.each_section + end + def test_find_attribute_named assert_equal nil, @c1.find_attribute_named('none') assert_equal 'R', @c1.find_attribute_named('attr').rw @@ -448,6 +531,16 @@ class TestRDocContext < XrefTestCase assert_equal @c1__m, @c1.find_symbol('::m') end + def test_find_symbol_module + assert_nil @m1_m2.find_symbol_module 'N' + assert_nil @m1_m2.find_symbol_module 'M2::M1' + + @m1_m2.parent = nil # loaded from legacy ri store + + assert_nil @m1_m2.find_symbol_module 'N' + assert_nil @m1_m2.find_symbol_module 'M2::M1' + end + def test_fully_documented_eh context = RDoc::Context.new @@ -650,14 +743,51 @@ class TestRDocContext < XrefTestCase assert_equal [@pub, @prot, @priv], methods end + def test_section_contents + default = @context.sections.first + @context.add_method RDoc::AnyMethod.new(nil, 'm1') + + b = @context.add_section 'B' + m = @context.add_method RDoc::AnyMethod.new(nil, 'm2') + m.section = b + + assert_equal [default, b], @context.section_contents + end + + def test_section_contents_no_default + @context = RDoc::Context.new + b = @context.add_section 'B' + m = @context.add_method RDoc::AnyMethod.new(nil, 'm') + m.section = b + + assert_equal [b], @context.section_contents + end + + def test_section_contents_only_default + @context = RDoc::Context.new + + @context.add_method RDoc::AnyMethod.new(nil, 'm') + + assert_empty @context.section_contents + end + + def test_section_contents_unused + @context = RDoc::Context.new + + @context.add_method RDoc::AnyMethod.new(nil, 'm') + @context.add_section 'B' + + assert_empty @context.section_contents + end + def test_set_current_section default_section = @context.sections.first - @context.set_current_section nil, '' + @context.set_current_section nil, RDoc::Comment.new('', @top_level) assert_equal default_section, @context.current_section - @context.set_current_section 'other', '' + @context.set_current_section 'other', RDoc::Comment.new('', @top_level) new_section = @context.sections.find { |section| section != default_section @@ -666,6 +796,38 @@ class TestRDocContext < XrefTestCase assert_equal new_section, @context.current_section end + def test_sort_sections + c = RDoc::Context.new + c.add_section 'C' + c.add_section 'A' + c.add_section 'B' + + titles = c.sort_sections.map { |section| section.title } + + assert_equal [nil, 'A', 'B', 'C'], titles + end + + def test_sort_sections_tomdoc + c = RDoc::Context.new + c.add_section 'Public' + c.add_section 'Internal' + c.add_section 'Deprecated' + + titles = c.sort_sections.map { |section| section.title } + + assert_equal [nil, 'Public', 'Internal', 'Deprecated'], titles + end + + def test_sort_sections_tomdoc_missing + c = RDoc::Context.new + c.add_section 'Internal' + c.add_section 'Public' + + titles = c.sort_sections.map { |section| section.title } + + assert_equal [nil, 'Public', 'Internal'], titles + end + def util_visibilities @pub = RDoc::AnyMethod.new nil, 'pub' @prot = RDoc::AnyMethod.new nil, 'prot' diff --git a/test/rdoc/test_rdoc_context_section.rb b/test/rdoc/test_rdoc_context_section.rb index d37a4d222e..716d3ae6bb 100644 --- a/test/rdoc/test_rdoc_context_section.rb +++ b/test/rdoc/test_rdoc_context_section.rb @@ -1,14 +1,49 @@ -require 'rubygems' -require 'cgi' -require 'minitest/autorun' -require 'rdoc' -require 'rdoc/code_objects' +require 'rdoc/test_case' -class TestRDocContextSection < MiniTest::Unit::TestCase +class TestRDocContextSection < RDoc::TestCase def setup + super + + @top_level = @store.add_file 'file.rb' + + @klass = @top_level.add_class RDoc::NormalClass, 'Object' + @S = RDoc::Context::Section - @s = @S.new nil, 'section', '# comment' + @s = @S.new @klass, 'section', comment('# comment', @top_level) + end + + def mu_pp obj + s = '' + s = PP.pp obj, s + s.force_encoding Encoding.default_external if defined? Encoding + s.chomp + end + + def test_add_comment + file1 = @store.add_file 'file1.rb' + + klass = file1.add_class RDoc::NormalClass, 'Klass' + + c1 = RDoc::Comment.new "# :section: section\n", file1 + c2 = RDoc::Comment.new "# hello\n", file1 + c3 = RDoc::Comment.new "# world\n", file1 + + s = @S.new klass, 'section', c1 + + assert_empty s.comments + + s.add_comment nil + + assert_empty s.comments + + s.add_comment c2 + + assert_equal [c2], s.comments + + s.add_comment c3 + + assert_equal [c2, c3], s.comments end def test_aref @@ -19,27 +54,75 @@ class TestRDocContextSection < MiniTest::Unit::TestCase assert_equal 'one+two', @S.new(nil, 'one two', nil).aref end - def test_comment_equals - @s.comment = "# :section: section\n" + def test_extract_comment + assert_equal '', @s.extract_comment(comment('')).text + assert_equal '', @s.extract_comment(comment("# :section: b\n")).text + assert_equal '# c', @s.extract_comment(comment("# :section: b\n# c")).text + assert_equal '# c', + @s.extract_comment(comment("# a\n# :section: b\n# c")).text + end + + def test_marshal_dump + loaded = Marshal.load Marshal.dump @s - assert_equal "# comment", @s.comment + expected = RDoc::Comment.new('comment', @top_level).parse + expected = doc(expected) - @s.comment = "# :section: section\n# other" + assert_equal 'section', loaded.title + assert_equal expected, loaded.comments + assert_nil loaded.parent, 'parent is set manually' + end - assert_equal "# comment\n# ---\n# other", @s.comment + def test_marshal_dump_no_comment + s = @S.new @klass, 'section', comment('') - s = @S.new nil, nil, nil + loaded = Marshal.load Marshal.dump s + + assert_equal 'section', loaded.title + assert_empty loaded.comments + assert_nil loaded.parent, 'parent is set manually' + end - s.comment = "# :section:\n# other" + def test_marshal_load_version_0 + loaded = Marshal.load "\x04\bU:\eRDoc::Context::Section" + + "[\bi\x00I\"\fsection\x06:\x06EFo" + + ":\eRDoc::Markup::Document\a:\v@parts" + + "[\x06o;\a\a;\b[\x06o" + + ":\x1CRDoc::Markup::Paragraph\x06;\b" + + "[\x06I\"\fcomment\x06;\x06F:\n@fileI" + + "\"\ffile.rb\x06;\x06F;\n0" - assert_equal "# other", s.comment + expected = doc RDoc::Comment.new('comment', @top_level).parse + + assert_equal 'section', loaded.title + assert_equal expected, loaded.comments + assert_nil loaded.parent, 'parent is set manually' end - def test_extract_comment - assert_equal '', @s.extract_comment('') - assert_equal '', @s.extract_comment("# :section: b\n") - assert_equal '# c', @s.extract_comment("# :section: b\n# c") - assert_equal '# c', @s.extract_comment("# a\n# :section: b\n# c") + def test_remove_comment_array + other = @store.add_file 'other.rb' + + other_comment = comment('bogus', other) + + @s.add_comment other_comment + + @s.remove_comment comment('bogus', @top_level) + + assert_equal [other_comment], @s.comments + end + + def test_remove_comment_document + other = @store.add_file 'other.rb' + + other_comment = comment('bogus', other) + + @s.add_comment other_comment + + loaded = Marshal.load Marshal.dump @s + + loaded.remove_comment comment('bogus', @top_level) + + assert_equal doc(other_comment.parse), loaded.comments end def test_sequence diff --git a/test/rdoc/test_rdoc_cross_reference.rb b/test/rdoc/test_rdoc_cross_reference.rb index 06062ba125..45afd80d31 100644 --- a/test/rdoc/test_rdoc_cross_reference.rb +++ b/test/rdoc/test_rdoc_cross_reference.rb @@ -1,5 +1,3 @@ -require 'rubygems' -require 'minitest/autorun' require File.expand_path '../xref_test_case', __FILE__ class TestRDocCrossReference < XrefTestCase @@ -95,7 +93,7 @@ class TestRDocCrossReference < XrefTestCase end def test_resolve_file - assert_ref @xref_data, 'xref_data.rb' + refute_ref 'xref_data.rb' end def test_resolve_method @@ -131,6 +129,30 @@ class TestRDocCrossReference < XrefTestCase assert_ref @c2_c3_m, '::C2::C3#m(*)' end + def test_resolve_page + page = @store.add_file 'README.txt' + page.parser = RDoc::Parser::Simple + + assert_ref page, 'README' + end + + def test_resolve_percent + i_percent = RDoc::AnyMethod.new nil, '%' + i_percent.singleton = false + @c1.add_method i_percent + + c_percent = RDoc::AnyMethod.new nil, '%' + c_percent.singleton = true + @c1.add_method c_percent + + assert_ref i_percent, '%' + assert_ref i_percent, '#%' + assert_ref c_percent, '::%' + + assert_ref i_percent, 'C1#%' + assert_ref c_percent, 'C1::%' + end + def test_resolve_no_ref assert_equal '', @xref.resolve('', '') diff --git a/test/rdoc/test_rdoc_encoding.rb b/test/rdoc/test_rdoc_encoding.rb index b5ffd7714c..d43bc2e244 100644 --- a/test/rdoc/test_rdoc_encoding.rb +++ b/test/rdoc/test_rdoc_encoding.rb @@ -1,15 +1,12 @@ # coding: US-ASCII -require 'rubygems' -require 'minitest/autorun' -require 'rdoc' -require 'rdoc/encoding' +require 'rdoc/test_case' -require 'tempfile' - -class TestRDocEncoding < MiniTest::Unit::TestCase +class TestRDocEncoding < RDoc::TestCase def setup + super + @tempfile = Tempfile.new 'test_rdoc_encoding' end @@ -100,6 +97,22 @@ class TestRDocEncoding < MiniTest::Unit::TestCase assert_equal Encoding::UTF_8, content.encoding end + def test_class_read_file_encoding_invalid + skip "Encoding not implemented" unless Object.const_defined? :Encoding + + @tempfile.write "# coding: ascii\nM\xE4r" + @tempfile.flush + + contents = :junk + _, err = capture_io do + contents = RDoc::Encoding.read_file @tempfile.path, Encoding::UTF_8 + end + + assert_equal "unable to convert \"\\xE4\" on US-ASCII for #{@tempfile.path}, skipping\n", err + + assert_nil contents + end + def test_class_read_file_encoding_with_signature skip "Encoding not implemented" unless defined? ::Encoding diff --git a/test/rdoc/test_rdoc_extend.rb b/test/rdoc/test_rdoc_extend.rb new file mode 100644 index 0000000000..149931549d --- /dev/null +++ b/test/rdoc/test_rdoc_extend.rb @@ -0,0 +1,94 @@ +require File.expand_path '../xref_test_case', __FILE__ + +class TestRDocExtend < XrefTestCase + + def setup + super + + @ext = RDoc::Extend.new 'M1', 'comment' + @ext.parent = @m1 + @ext.store = @store + end + + def test_module + assert_equal @m1, @ext.module + assert_equal 'Unknown', RDoc::Extend.new('Unknown', 'comment').module + end + + def test_module_extended + m1 = @xref_data.add_module RDoc::NormalModule, 'Mod1' + m1.add_module RDoc::NormalModule, 'Mod3' + m1_m2 = m1.add_module RDoc::NormalModule, 'Mod2' + m1_m2_m3 = m1_m2.add_module RDoc::NormalModule, 'Mod3' + m1_m2_m3.add_module RDoc::NormalModule, 'Mod4' + m1_m2.add_module RDoc::NormalModule, 'Mod4' + m1_m2_k0 = m1_m2.add_class RDoc::NormalClass, 'Klass0' + m1_m2_k0_m4 = m1_m2_k0.add_module RDoc::NormalModule, 'Mod4' + m1_m2_k0_m4.add_module RDoc::NormalModule, 'Mod6' + m1_m2_k0.add_module RDoc::NormalModule, 'Mod5' + + e0_m4 = RDoc::Extend.new 'Mod4', nil + e0_m5 = RDoc::Extend.new 'Mod5', nil + e0_m6 = RDoc::Extend.new 'Mod6', nil + e0_m1 = RDoc::Extend.new 'Mod1', nil + e0_m2 = RDoc::Extend.new 'Mod2', nil + e0_m3 = RDoc::Extend.new 'Mod3', nil + + m1_m2_k0.add_extend e0_m4 + m1_m2_k0.add_extend e0_m5 + m1_m2_k0.add_extend e0_m6 + m1_m2_k0.add_extend e0_m1 + m1_m2_k0.add_extend e0_m2 + m1_m2_k0.add_extend e0_m3 + + assert_equal [e0_m4, e0_m5, e0_m6, e0_m1, e0_m2, e0_m3], m1_m2_k0.extends + assert_equal ['Object'], m1_m2_k0.ancestors + + m1_k1 = m1.add_class RDoc::NormalClass, 'Klass1' + + e1_m1 = RDoc::Extend.new 'Mod1', nil + e1_m2 = RDoc::Extend.new 'Mod2', nil + e1_m3 = RDoc::Extend.new 'Mod3', nil + e1_m4 = RDoc::Extend.new 'Mod4', nil + e1_k0_m4 = RDoc::Extend.new 'Klass0::Mod4', nil + + m1_k1.add_extend e1_m1 + m1_k1.add_extend e1_m2 + m1_k1.add_extend e1_m3 + m1_k1.add_extend e1_m4 + m1_k1.add_extend e1_k0_m4 + + assert_equal [e1_m1, e1_m2, e1_m3, e1_m4, e1_k0_m4], m1_k1.extends + assert_equal ['Object'], m1_k1.ancestors + + m1_k2 = m1.add_class RDoc::NormalClass, 'Klass2' + + e2_m1 = RDoc::Extend.new 'Mod1', nil + e2_m2 = RDoc::Extend.new 'Mod2', nil + e2_m3 = RDoc::Extend.new 'Mod3', nil + e2_k0_m4 = RDoc::Extend.new 'Klass0::Mod4', nil + + m1_k2.add_extend e2_m1 + m1_k2.add_extend e2_m3 + m1_k2.add_extend e2_m2 + m1_k2.add_extend e2_k0_m4 + + assert_equal [e2_m1, e2_m3, e2_m2, e2_k0_m4], m1_k2.extends + assert_equal ['Object'], m1_k2.ancestors + + m1_k3 = m1.add_class RDoc::NormalClass, 'Klass3' + + e3_m1 = RDoc::Extend.new 'Mod1', nil + e3_m2 = RDoc::Extend.new 'Mod2', nil + e3_m4 = RDoc::Extend.new 'Mod4', nil + + m1_k3.add_extend e3_m1 + m1_k3.add_extend e3_m2 + m1_k3.add_extend e3_m4 + + assert_equal [e3_m1, e3_m2, e3_m4], m1_k3.extends + assert_equal ['Object'], m1_k3.ancestors + end + +end + diff --git a/test/rdoc/test_rdoc_generator_darkfish.rb b/test/rdoc/test_rdoc_generator_darkfish.rb index faea1ae34a..d1c2f66665 100644 --- a/test/rdoc/test_rdoc_generator_darkfish.rb +++ b/test/rdoc/test_rdoc_generator_darkfish.rb @@ -1,16 +1,12 @@ -require 'minitest/autorun' -require 'rdoc/rdoc' -require 'rdoc/generator/darkfish' -require 'tmpdir' -require 'fileutils' +require 'rdoc/test_case' -class TestRDocGeneratorDarkfish < MiniTest::Unit::TestCase +class TestRDocGeneratorDarkfish < RDoc::TestCase def setup - @pwd = Dir.pwd + super + @lib_dir = "#{@pwd}/lib" $LOAD_PATH.unshift @lib_dir # ensure we load from this RDoc - RDoc::TopLevel.reset @options = RDoc::Options.new @options.option_parser = OptionParser.new @@ -22,22 +18,27 @@ class TestRDocGeneratorDarkfish < MiniTest::Unit::TestCase @options.generator = RDoc::Generator::Darkfish $LOAD_PATH.each do |path| - darkfish_dir = File.join path, 'rdoc/generator/template/darkfish' + darkfish_dir = File.join path, 'rdoc/generator/template/darkfish/' next unless File.directory? darkfish_dir @options.template_dir = darkfish_dir break end - rd = RDoc::RDoc.new - rd.options = @options - RDoc::RDoc.current = rd + @rdoc.options = @options + + @g = @options.generator.new @store, @options + @rdoc.generator = @g + + @top_level = @store.add_file 'file.rb' + @top_level.parser = RDoc::Parser::Ruby + @klass = @top_level.add_class RDoc::NormalClass, 'Klass' - @g = @options.generator.new @options + @alias_constant = RDoc::Constant.new 'A', nil, '' + @alias_constant.record_location @top_level - rd.generator = @g + @top_level.add_constant @alias_constant - @top_level = RDoc::TopLevel.new 'file.rb' - @klass = @top_level.add_class RDoc::NormalClass, 'Object' + @klass.add_module_alias @klass, 'A', @top_level @meth = RDoc::AnyMethod.new nil, 'method' @meth_bang = RDoc::AnyMethod.new nil, 'method!' @@ -49,9 +50,16 @@ class TestRDocGeneratorDarkfish < MiniTest::Unit::TestCase @ignored = @top_level.add_class RDoc::NormalClass, 'Ignored' @ignored.ignore + + @store.complete :private + + @object = @store.find_class_or_module 'Object' + @klass_alias = @store.find_class_or_module 'Klass::A' end def teardown + super + $LOAD_PATH.shift Dir.chdir @pwd FileUtils.rm_rf @tmpdir @@ -65,15 +73,23 @@ class TestRDocGeneratorDarkfish < MiniTest::Unit::TestCase refute File.exist?(path), "#{path} exists" end + def mu_pp obj + s = '' + s = PP.pp obj, s + s = s.force_encoding Encoding.default_external if defined? Encoding + s.chomp + end + def test_generate - top_level = RDoc::TopLevel.new 'file.rb' + top_level = @store.add_file 'file.rb' top_level.add_class @klass.class, @klass.name - @g.generate [top_level] + @g.generate assert_file 'index.html' assert_file 'Object.html' - assert_file 'file_rb.html' + assert_file 'table_of_contents.html' + assert_file 'js/search_index.js' encoding = if Object.const_defined? :Encoding then Regexp.escape Encoding.default_external.name @@ -85,37 +101,73 @@ class TestRDocGeneratorDarkfish < MiniTest::Unit::TestCase File.read('index.html')) assert_match(/ { + :searchIndex => %w[c d meth() meth() page], + :longSearchIndex => %w[c c::d c#meth() c::d#meth()], + :info => [ + @klass.search_record[2..-1], + @nest_klass.search_record[2..-1], + @meth.search_record[2..-1], + @nest_meth.search_record[2..-1], + @page.search_record[2..-1], + ], + }, + } + + expected[:index][:longSearchIndex] << '' + + assert_equal expected, index + end + + def test_class_dir + assert_equal @darkfish.class_dir, @g.class_dir + end + + def test_file_dir + assert_equal @darkfish.file_dir, @g.file_dir + end + + def test_generate + @g.generate + + assert_file 'js/searcher.js' + assert_file 'js/navigation.js' + assert_file 'js/search_index.js' + + json = File.read 'js/search_index.js' + + json =~ /\Avar search_data = / + + assignment = $& + index = $' + + refute_empty assignment + + index = JSON.parse index + + info = [ + @klass.search_record[2..-1], + @nest_klass.search_record[2..-1], + @meth.search_record[2..-1], + @nest_meth.search_record[2..-1], + @page.search_record[2..-1], + ] + + expected = { + 'index' => { + 'searchIndex' => [ + 'c', + 'd', + 'meth()', + 'meth()', + 'page', + ], + 'longSearchIndex' => [ + 'c', + 'c::d', + 'c#meth()', + 'c::d#meth()', + '', + ], + 'info' => info, + }, + } + + assert_equal expected, index + end + + def test_generate_utf_8 + skip "Encoding not implemented" unless Object.const_defined? :Encoding + + text = "5\xB0" + text.force_encoding Encoding::ISO_8859_1 + @klass.add_comment comment(text), @top_level + + @g.generate + + json = File.read 'js/search_index.js' + json.force_encoding Encoding::UTF_8 + + json =~ /\Avar search_data = / + + index = $' + + index = JSON.parse index + + klass_record = @klass.search_record[2..-1] + klass_record[-1] = "

5\xc2\xb0\n" + klass_record.last.force_encoding Encoding::UTF_8 + + info = [ + klass_record, + @nest_klass.search_record[2..-1], + @meth.search_record[2..-1], + @nest_meth.search_record[2..-1], + @page.search_record[2..-1], + ] + + expected = { + 'index' => { + 'searchIndex' => [ + 'c', + 'd', + 'meth()', + 'meth()', + 'page', + ], + 'longSearchIndex' => [ + 'c', + 'c::d', + 'c#meth()', + 'c::d#meth()', + '', + ], + 'info' => info, + }, + } + + assert_equal expected, index + end + + def test_index_classes + @g.reset @top_levels, @klasses + + @g.index_classes + + expected = { + :searchIndex => %w[c d], + :longSearchIndex => %w[c c::d], + :info => [ + @klass.search_record[2..-1], + @nest_klass.search_record[2..-1], + ], + } + + assert_equal expected, @g.index + end + + def test_index_classes_nodoc + @klass.document_self = false + @nest_klass.document_self = false + @meth.document_self = false + @nest_meth.document_self = false + + @g.reset @top_levels, @klasses + + @g.index_classes + + expected = { + :searchIndex => [], + :longSearchIndex => [], + :info => [], + } + + assert_equal expected, @g.index + end + + def test_index_methods + @g.reset @top_levels, @klasses + + @g.index_methods + + expected = { + :searchIndex => %w[meth() meth()], + :longSearchIndex => %w[c#meth() c::d#meth()], + :info => [ + @meth.search_record[2..-1], + @nest_meth.search_record[2..-1], + ], + } + + assert_equal expected, @g.index + end + + def test_index_pages + @g.reset @top_levels, @klasses + + @g.index_pages + + expected = { + :searchIndex => %w[page], + :longSearchIndex => [''], + :info => [@page.search_record[2..-1]], + } + + assert_equal expected, @g.index + end + + def test_search_string + assert_equal 'cd', @g.search_string('C d') + end + +end + diff --git a/test/rdoc/test_rdoc_generator_markup.rb b/test/rdoc/test_rdoc_generator_markup.rb new file mode 100644 index 0000000000..1b44085283 --- /dev/null +++ b/test/rdoc/test_rdoc_generator_markup.rb @@ -0,0 +1,56 @@ +require 'rdoc/test_case' + +class TestRDocGeneratorMarkup < RDoc::TestCase + + include RDoc::Text + include RDoc::Generator::Markup + + attr_reader :store + + def setup + super + + @options = RDoc::Options.new + @rdoc.options = @options + + @parent = self + @path = '/index.html' + @symbols = {} + end + + def test_aref_to + assert_equal 'Foo/Bar.html', aref_to('Foo/Bar.html') + end + + def test_as_href + assert_equal '../index.html', as_href('Foo/Bar.html') + end + + def test_cvs_url + assert_equal 'http://example/this_page', + cvs_url('http://example/', 'this_page') + + assert_equal 'http://example/?page=this_page&foo=bar', + cvs_url('http://example/?page=%s&foo=bar', 'this_page') + end + + def test_description + @comment = '= Hello' + + assert_equal "\n

Hello

\n", description + end + + def test_formatter + assert_kind_of RDoc::Markup::ToHtmlCrossref, formatter + refute formatter.show_hash + assert_same self, formatter.context + end + + attr_reader :path + + def find_symbol name + @symbols[name] + end + +end + diff --git a/test/rdoc/test_rdoc_generator_ri.rb b/test/rdoc/test_rdoc_generator_ri.rb index 2be006843c..a2bcec534d 100644 --- a/test/rdoc/test_rdoc_generator_ri.rb +++ b/test/rdoc/test_rdoc_generator_ri.rb @@ -1,26 +1,22 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/rdoc' -require 'rdoc/generator/ri' -require 'tmpdir' -require 'fileutils' +require 'rdoc/test_case' -class TestRDocGeneratorRI < MiniTest::Unit::TestCase +class TestRDocGeneratorRI < RDoc::TestCase def setup - @options = RDoc::Options.new - @options.encoding = Encoding::UTF_8 if Object.const_defined? :Encoding + super - @pwd = Dir.pwd - RDoc::TopLevel.reset + @options = RDoc::Options.new + if Object.const_defined? :Encoding then + @options.encoding = Encoding::UTF_8 + @store.encoding = Encoding::UTF_8 + end @tmpdir = File.join Dir.tmpdir, "test_rdoc_generator_ri_#{$$}" FileUtils.mkdir_p @tmpdir - Dir.chdir @tmpdir - @g = RDoc::Generator::RI.new @options + @g = RDoc::Generator::RI.new @store, @options - @top_level = RDoc::TopLevel.new 'file.rb' + @top_level = @store.add_file 'file.rb' @klass = @top_level.add_class RDoc::NormalClass, 'Object' @meth = RDoc::AnyMethod.new nil, 'method' @@ -35,9 +31,13 @@ class TestRDocGeneratorRI < MiniTest::Unit::TestCase @klass.add_method @meth @klass.add_method @meth_bang @klass.add_attribute @attr + + Dir.chdir @tmpdir end def teardown + super + Dir.chdir @pwd FileUtils.rm_rf @tmpdir end @@ -51,7 +51,7 @@ class TestRDocGeneratorRI < MiniTest::Unit::TestCase end def test_generate - @g.generate nil + @g.generate assert_file File.join(@tmpdir, 'cache.ri') @@ -70,16 +70,15 @@ class TestRDocGeneratorRI < MiniTest::Unit::TestCase end def test_generate_dry_run - @options.dry_run = true - @g = RDoc::Generator::RI.new @options + @store.dry_run = true + @g = RDoc::Generator::RI.new @store, @options - top_level = RDoc::TopLevel.new 'file.rb' + top_level = @store.add_file 'file.rb' top_level.add_class @klass.class, @klass.name - @g.generate nil + @g.generate refute_file File.join(@tmpdir, 'cache.ri') - refute_file File.join(@tmpdir, 'Object') end diff --git a/test/rdoc/test_rdoc_include.rb b/test/rdoc/test_rdoc_include.rb index 71eaf9abf8..464a698018 100644 --- a/test/rdoc/test_rdoc_include.rb +++ b/test/rdoc/test_rdoc_include.rb @@ -7,6 +7,8 @@ class TestRDocInclude < XrefTestCase @inc = RDoc::Include.new 'M1', 'comment' @inc.parent = @m1 + @inc.record_location @top_level + @inc.store = @store end def test_module @@ -92,5 +94,15 @@ class TestRDocInclude < XrefTestCase assert_equal [m1_m2_m4, m1_m2, m1, 'Object'], m1_k3.ancestors end + def test_store_equals + incl = RDoc::Include.new 'M', nil + incl.record_location RDoc::TopLevel.new @top_level.name + + incl.store = @store + + assert_same @top_level, incl.file + assert_same @store, incl.file.store + end + end diff --git a/test/rdoc/test_rdoc_markdown.rb b/test/rdoc/test_rdoc_markdown.rb new file mode 100644 index 0000000000..f3eb22227c --- /dev/null +++ b/test/rdoc/test_rdoc_markdown.rb @@ -0,0 +1,977 @@ +# coding: UTF-8 + +require 'rubygems' +require 'minitest/autorun' +require 'pp' + +require 'rdoc' +require 'rdoc/markup/block_quote' +require 'rdoc/markdown' + +class TestRDocMarkdown < RDoc::TestCase + + def setup + @RM = RDoc::Markup + + @parser = RDoc::Markdown.new + end + + def mu_pp obj + s = '' + s = PP.pp obj, s + s.force_encoding Encoding.default_external if defined? Encoding + s.chomp + end + + def test_class_parse + doc = RDoc::Markdown.parse "hello\n\nworld" + + expected = doc(para("hello"), para("world")) + + assert_equal expected, doc + end + + def test_emphasis + assert_equal '_word_', @parser.emphasis('word') + assert_equal 'two words', @parser.emphasis('two words') + assert_equal '*bold*', @parser.emphasis('*bold*') + end + + def test_parse_auto_link_email + doc = parse "Autolink: " + + expected = doc(para("Autolink: mailto:nobody-0+_./!%~$@example")) + + assert_equal expected, doc + end + + def test_parse_auto_link_url + doc = parse "Autolink: " + + expected = doc(para("Autolink: http://example")) + + assert_equal expected, doc + end + + def test_parse_block_quote + doc = parse <<-BLOCK_QUOTE +> this is +> a block quote + BLOCK_QUOTE + + expected = + doc( + block( + para("this is\na block quote"))) + + assert_equal expected, doc + end + + def test_parse_block_quote_continue + doc = parse <<-BLOCK_QUOTE +> this is +a block quote + BLOCK_QUOTE + + expected = + doc( + block( + para("this is\na block quote"))) + + assert_equal expected, doc + end + + def test_parse_block_quote_list + doc = parse <<-BLOCK_QUOTE +> text +> +> * one +> * two + BLOCK_QUOTE + + expected = + doc( + block( + para("text"), + list(:BULLET, + item(nil, para("one")), + item(nil, para("two"))))) + + assert_equal expected, doc + end + + def test_parse_block_quote_newline + doc = parse <<-BLOCK_QUOTE +> this is +a block quote + + BLOCK_QUOTE + + expected = + doc( + block( + para("this is\na block quote"))) + + assert_equal expected, doc + end + + def test_parse_block_quote_separate + doc = parse <<-BLOCK_QUOTE +> this is +a block quote + +> that continues + BLOCK_QUOTE + + expected = + doc( + block( + para("this is\na block quote"), + para("that continues"))) + + assert_equal expected, doc + end + + def test_parse_char_entity + doc = parse 'π &nn;' + + expected = doc(para('π &nn;')) + + assert_equal expected, doc + end + + def test_parse_code + doc = parse "Code: `text`" + + expected = doc(para("Code: text")) + + assert_equal expected, doc + end + + def test_parse_code_github + doc = parse <<-MD +Example: + +``` +code goes here +``` + MD + + expected = + doc( + para("Example:"), + verb("code goes here\n")) + + assert_equal expected, doc + end + + def test_parse_code_github_format + doc = parse <<-MD +Example: + +``` ruby +code goes here +``` + MD + + code = verb("code goes here\n") + code.format = :ruby + + expected = + doc( + para("Example:"), + code) + + assert_equal expected, doc + end + + def test_parse_definition_list + doc = parse <<-MD +one +: This is a definition + +two +: This is another definition + MD + + expected = doc( + list(:NOTE, + item(%w[one], para("This is a definition")), + item(%w[two], para("This is another definition")))) + + assert_equal expected, doc + end + + def test_parse_definition_list_indents + doc = parse <<-MD +zero +: Indented zero characters + +one + : Indented one characters + +two + : Indented two characters + +three + : Indented three characters + +four + : Indented four characters + + MD + + expected = doc( + list(:NOTE, + item(%w[zero], para("Indented zero characters")), + item(%w[one], para("Indented one characters")), + item(%w[two], para("Indented two characters")), + item(%w[three], para("Indented three characters"))), + para("four\n : Indented four characters")) + + assert_equal expected, doc + end + + def test_parse_definition_list_multi_description + doc = parse <<-MD +label +: This is a definition + +: This is another definition + MD + + expected = doc( + list(:NOTE, + item(%w[label], para("This is a definition")), + item(nil, para("This is another definition")))) + + assert_equal expected, doc + end + + def test_parse_definition_list_multi_label + doc = parse <<-MD +one +two +: This is a definition + MD + + expected = doc( + list(:NOTE, + item(%w[one two], para("This is a definition")))) + + assert_equal expected, doc + end + + def test_parse_definition_list_multi_line + doc = parse <<-MD +one +: This is a definition +that extends to two lines + +two +: This is another definition +that also extends to two lines + MD + + expected = doc( + list(:NOTE, + item(%w[one], + para("This is a definition\nthat extends to two lines")), + item(%w[two], + para("This is another definition\nthat also extends to two lines")))) + + assert_equal expected, doc + end + + def test_parse_definition_list_no + @parser.definition_lists = false + + doc = parse <<-MD +one +: This is a definition + +two +: This is another definition + MD + + expected = doc( + para("one\n: This is a definition"), + para("two\n: This is another definition")) + + assert_equal expected, doc + end + + def test_parse_entity_dec + doc = parse "Entity: A" + + expected = doc(para("Entity: A")) + + assert_equal expected, doc + end + + def test_parse_entity_hex + doc = parse "Entity: A" + + expected = doc(para("Entity: A")) + + assert_equal expected, doc + end + + def test_parse_entity_named + doc = parse "Entity: π" + + expected = doc(para("Entity: π")) + + assert_equal expected, doc + end + + def test_parse_emphasis_star + doc = parse "it *works*\n" + + expected = @RM::Document.new( + @RM::Paragraph.new("it _works_")) + + assert_equal expected, doc + end + + def test_parse_emphasis_underscore + doc = parse "it _works_\n" + + expected = + doc( + para("it _works_")) + + assert_equal expected, doc + end + + def test_parse_emphasis_underscore_embedded + doc = parse "foo_bar bar_baz\n" + + expected = + doc( + para("foo_bar bar_baz")) + + assert_equal expected, doc + end + + def test_parse_emphasis_underscore_in_word + doc = parse "it foo_bar_baz\n" + + expected = + doc( + para("it foo_bar_baz")) + + assert_equal expected, doc + end + + def test_parse_escape + assert_equal doc(para("Backtick: `")), parse("Backtick: \\`") + + assert_equal doc(para("Backslash: \\")), parse("Backslash: \\\\") + + assert_equal doc(para("Colon: :")), parse("Colon: \\:") + end + + def test_parse_heading_atx + doc = parse "# heading\n" + + expected = @RM::Document.new( + @RM::Heading.new(1, "heading")) + + assert_equal expected, doc + end + + def test_parse_heading_setext_dash + doc = parse <<-MD +heading +--- + MD + + expected = @RM::Document.new( + @RM::Heading.new(2, "heading")) + + assert_equal expected, doc + end + + def test_parse_heading_setext_equals + doc = parse <<-MD +heading +=== + MD + + expected = @RM::Document.new( + @RM::Heading.new(1, "heading")) + + assert_equal expected, doc + end + + def test_parse_html + @parser.html = true + + doc = parse "
Links here
\n" + + expected = doc( + @RM::Raw.new("
Links here
")) + + assert_equal expected, doc + end + + def test_parse_html_hr + @parser.html = true + + doc = parse "
\n" + + expected = doc(raw("
")) + + assert_equal expected, doc + end + + def test_parse_html_no_html + @parser.html = false + + doc = parse "
Links here
\n" + + expected = doc() + + assert_equal expected, doc + end + + def test_parse_image + doc = parse "image ![alt text](path/to/image.jpg)" + + expected = doc(para("image {alt text}[path/to/image.jpg]")) + + assert_equal expected, doc + end + + def test_parse_line_break + doc = parse "Some text \nwith extra lines" + + expected = doc( + para("Some text", hard_break, "with extra lines")) + + assert_equal expected, doc + end + + def test_parse_link_reference_id + doc = parse <<-MD +This is [an example][id] reference-style link. + +[id]: http://example.com "Optional Title Here" + MD + + expected = doc( + para("This is {an example}[http://example.com] reference-style link.")) + + assert_equal expected, doc + end + + def test_parse_link_reference_id_adjacent + doc = parse <<-MD +[this] [this] should work + +[this]: example + MD + + expected = doc( + para("{this}[example] should work")) + + assert_equal expected, doc + end + + def test_parse_link_reference_id_eof + doc = parse <<-MD.chomp +This is [an example][id] reference-style link. + +[id]: http://example.com "Optional Title Here" + MD + + expected = doc( + para("This is {an example}[http://example.com] reference-style link.")) + + assert_equal expected, doc + end + + def test_parse_link_reference_id_many + doc = parse <<-MD +This is [an example][id] reference-style link. + +And [another][id]. + +[id]: http://example.com "Optional Title Here" + MD + + expected = doc( + para("This is {an example}[http://example.com] reference-style link."), + para("And {another}[http://example.com].")) + + assert_equal expected, doc + end + + def test_parse_link_reference_implicit + doc = parse <<-MD +This is [an example][] reference-style link. + +[an example]: http://example.com "Optional Title Here" + MD + + expected = doc( + para("This is {an example}[http://example.com] reference-style link.")) + + assert_equal expected, doc + end + + def test_parse_list_bullet + doc = parse <<-MD +* one +* two + MD + + expected = doc( + list(:BULLET, + item(nil, para("one")), + item(nil, para("two")))) + + assert_equal expected, doc + end + + def test_parse_list_bullet_auto_link + doc = parse <<-MD +* + MD + + expected = doc( + list(:BULLET, + item(nil, para("http://example/")))) + + assert_equal expected, doc + end + + def test_parse_list_bullet_continue + doc = parse <<-MD +* one + +* two + MD + + expected = doc( + list(:BULLET, + item(nil, para("one")), + item(nil, para("two")))) + + assert_equal expected, doc + end + + def test_parse_list_bullet_multiline + doc = parse <<-MD +* one + two + MD + + expected = doc( + list(:BULLET, + item(nil, para("one\n two")))) + + assert_equal expected, doc + end + + def test_parse_list_bullet_nest + doc = parse <<-MD +* outer + * inner + MD + + expected = doc( + list(:BULLET, + item(nil, + para("outer"), + list(:BULLET, + item(nil, + para("inner")))))) + + assert_equal expected, doc + end + + def test_parse_list_bullet_nest_loose + doc = parse <<-MD +* outer + + * inner + MD + + expected = doc( + list(:BULLET, + item(nil, + para("outer"), + list(:BULLET, + item(nil, para("inner")))))) + + assert_equal expected, doc + end + + def test_parse_list_bullet_nest_continue + doc = parse <<-MD +* outer + * inner + continue inner +* outer 2 + MD + + expected = doc( + list(:BULLET, + item(nil, + para("outer"), + list(:BULLET, + item(nil, + para("inner\n continue inner")))), + item(nil, + para("outer 2")))) + + assert_equal expected, doc + end + + def test_parse_list_number + doc = parse <<-MD +1. one +1. two + MD + + expected = doc( + list(:NUMBER, + item(nil, para("one")), + item(nil, para("two")))) + + assert_equal expected, doc + end + + def test_parse_list_number_continue + doc = parse <<-MD +1. one + +1. two + MD + + expected = doc( + list(:NUMBER, + item(nil, para("one")), + item(nil, para("two")))) + + assert_equal expected, doc + end + + def test_parse_note + @parser.notes = true + + doc = parse <<-MD +Some text.[^1] + +[^1]: With a footnote + MD + + expected = doc( + para("Some text.{*1}[rdoc-label:foottext-1:footmark-1]"), + @RM::Rule.new(1), + para("{^1}[rdoc-label:footmark-1:foottext-1] With a footnote")) + + assert_equal expected, doc + end + + def test_parse_note_indent + @parser.notes = true + + doc = parse <<-MD +Some text.[^1] + +[^1]: With a footnote + + more + MD + + expected = doc( + para("Some text.{*1}[rdoc-label:foottext-1:footmark-1]"), + rule(1), + para("{^1}[rdoc-label:footmark-1:foottext-1] With a footnote\n\nmore")) + + assert_equal expected, doc + end + + def test_parse_note_inline + @parser.notes = true + + doc = parse <<-MD +Some text. ^[With a footnote] + MD + + expected = doc( + para("Some text. {*1}[rdoc-label:foottext-1:footmark-1]"), + @RM::Rule.new(1), + para("{^1}[rdoc-label:footmark-1:foottext-1] With a footnote")) + + assert_equal expected, doc + end + + def test_parse_note_no_notes + @parser.notes = false + + assert_raises RuntimeError do # TODO use a real error + parse "Some text.[^1]" + end + end + + def test_parse_note_multiple + @parser.notes = true + + doc = parse <<-MD +Some text[^1] +with inline notes^[like this] +and an extra note.[^2] + +[^1]: With a footnote + +[^2]: Which should be numbered correctly + MD + + expected = doc( + para("Some text{*1}[rdoc-label:foottext-1:footmark-1]\n" + + "with inline notes{*2}[rdoc-label:foottext-2:footmark-2]\n" + + "and an extra note.{*3}[rdoc-label:foottext-3:footmark-3]"), + + rule(1), + + para("{^1}[rdoc-label:footmark-1:foottext-1] With a footnote"), + para("{^2}[rdoc-label:footmark-2:foottext-2] like this"), + para("{^3}[rdoc-label:footmark-3:foottext-3] " + + "Which should be numbered correctly")) + + assert_equal expected, doc + end + + def test_parse_paragraph + doc = parse "it worked\n" + + expected = doc(para("it worked")) + + assert_equal expected, doc + end + + def test_parse_paragraph_break_on_newline + @parser.break_on_newline = true + + doc = parse "one\ntwo\n" + + expected = doc(para("one", hard_break, "two")) + + assert_equal expected, doc + + doc = parse "one \ntwo\nthree\n" + + expected = doc(para("one", hard_break, "two", hard_break, "three")) + + assert_equal expected, doc + end + + def test_parse_paragraph_stars + doc = parse "it worked ****\n" + + expected = @RM::Document.new( + @RM::Paragraph.new("it worked ****")) + + assert_equal expected, doc + end + + def test_parse_paragraph_html + @parser.html = true + + doc = parse "
Links here
" + + expected = doc(raw("
Links here
")) + + assert_equal expected, doc + end + + def test_parse_paragraph_html_no_html + @parser.html = false + + doc = parse "
Links here
" + + expected = doc() + + assert_equal expected, doc + end + + def test_parse_paragraph_indent_one + doc = parse <<-MD + text + MD + + expected = doc(para("text")) + + assert_equal expected, doc + end + + def test_parse_paragraph_indent_two + doc = parse <<-MD + text + MD + + expected = doc(para("text")) + + assert_equal expected, doc + end + + def test_parse_paragraph_indent_three + doc = parse <<-MD + text + MD + + expected = doc(para("text")) + + assert_equal expected, doc + end + + def test_parse_paragraph_multiline + doc = parse "one\ntwo" + + expected = doc(para("one\ntwo")) + + assert_equal expected, doc + end + + def test_parse_paragraph_two + doc = parse "one\n\ntwo" + + expected = @RM::Document.new( + @RM::Paragraph.new("one"), + @RM::Paragraph.new("two")) + + assert_equal expected, doc + end + + def test_parse_plain + doc = parse "it worked" + + expected = @RM::Document.new( + @RM::Paragraph.new("it worked")) + + assert_equal expected, doc + end + + def test_parse_reference_link_embedded_bracket + doc = parse "With [embedded [brackets]] [b].\n\n[b]: /url/\n" + + expected = + doc( + para("With {embedded [brackets]}[/url/].")) + + assert_equal expected, doc + end + + def test_parse_rule_dash + doc = parse "- - -\n\n" + + expected = @RM::Document.new(@RM::Rule.new(1)) + + assert_equal expected, doc + end + + def test_parse_rule_underscore + doc = parse "_ _ _\n\n" + + expected = @RM::Document.new(@RM::Rule.new(1)) + + assert_equal expected, doc + end + + def test_parse_rule_star + doc = parse "* * *\n\n" + + expected = @RM::Document.new(@RM::Rule.new(1)) + + assert_equal expected, doc + end + + def test_parse_strong_star + doc = parse "it **works**\n" + + expected = @RM::Document.new( + @RM::Paragraph.new("it *works*")) + + assert_equal expected, doc + end + + def test_parse_strong_underscore + doc = parse "it __works__\n" + + expected = @RM::Document.new( + @RM::Paragraph.new("it *works*")) + + assert_equal expected, doc + end + + def test_parse_strong_emphasis_star + doc = parse "it ***works***\n" + + expected = @RM::Document.new( + @RM::Paragraph.new("it _works_")) + + assert_equal expected, doc + end + + def test_parse_strong_emphasis_underscore + doc = parse "it ___works___\n" + + expected = @RM::Document.new( + @RM::Paragraph.new("it _works_")) + + assert_equal expected, doc + end + + def test_parse_style + @parser.css = true + + doc = parse "\n" + + expected = doc( + @RM::Raw.new("")) + + assert_equal expected, doc + end + + def test_parse_style_disabled + doc = parse "\n" + + expected = doc() + + assert_equal expected, doc + end + + def test_parse_verbatim + doc = parse <<-MD + text + MD + + expected = doc(verb("text\n")) + + assert_equal expected, doc + end + + def test_parse_verbatim_eof + doc = parse " text" + + expected = doc(verb("text\n")) + + assert_equal expected, doc + end + + def test_strong + assert_equal '*word*', @parser.strong('word') + assert_equal 'two words', @parser.strong('two words') + assert_equal '_emphasis_', @parser.strong('_emphasis_') + end + + def parse text + @parser.parse text + end + +end + diff --git a/test/rdoc/test_rdoc_markdown_test.rb b/test/rdoc/test_rdoc_markdown_test.rb new file mode 100644 index 0000000000..7dfe727ef5 --- /dev/null +++ b/test/rdoc/test_rdoc_markdown_test.rb @@ -0,0 +1,1891 @@ +require 'rubygems' +require 'minitest/autorun' +require 'pp' + +require 'rdoc' +require 'rdoc/markdown' + +class TestRDocMarkdownTest < RDoc::TestCase + + MARKDOWN_TEST_PATH = File.expand_path '../MarkdownTest_1.0.3/', __FILE__ + + def setup + super + + @parser = RDoc::Markdown.new + end + + def mu_pp obj + s = '' + s = PP.pp obj, s + s.force_encoding Encoding.default_external if defined? Encoding + s.chomp + end + + def test_amps_and_angle_encoding + input = File.read "#{MARKDOWN_TEST_PATH}/Amps and angle encoding.text" + + doc = @parser.parse input + + expected = + doc( + para("AT&T has an ampersand in their name."), + para("AT&T is another way to write it."), + para("This & that."), + para("4 < 5."), + para("6 > 5."), + para("Here's a {link}[http://example.com/?foo=1&bar=2] with " + + "an ampersand in the URL."), + para("Here's a link with an amersand in the link text: " + + "{AT&T}[http://att.com/]."), + para("Here's an inline {link}[/script?foo=1&bar=2]."), + para("Here's an inline {link}[/script?foo=1&bar=2].")) + + assert_equal expected, doc + end + + def test_auto_links + input = File.read "#{MARKDOWN_TEST_PATH}/Auto links.text" + + doc = @parser.parse input + + # TODO verify rdoc auto-links too + expected = + doc( + para("Link: http://example.com/."), + para("With an ampersand: http://example.com/?foo=1&bar=2"), + list(:BULLET, + item(nil, para("In a list?")), + item(nil, para("http://example.com/")), + item(nil, para("It should."))), + block( + para("Blockquoted: http://example.com/")), + para("Auto-links should not occur here: " + + ""), + verb("or here: \n")) + + assert_equal expected, doc + end + + def test_backslash_escapes + input = File.read "#{MARKDOWN_TEST_PATH}/Backslash escapes.text" + + doc = @parser.parse input + + expected = + doc( + para("These should all get escaped:"), + + para("Backslash: \\"), + para("Backtick: `"), + para("Asterisk: *"), + para("Underscore: _"), + para("Left brace: {"), + para("Right brace: }"), + para("Left bracket: ["), + para("Right bracket: ]"), + para("Left paren: ("), + para("Right paren: )"), + para("Greater-than: >"), + para("Hash: #"), + para("Period: ."), + para("Bang: !"), + para("Plus: +"), + para("Minus: -"), + + para("These should not, because they occur within a code block:"), + + verb("Backslash: \\\\\n", + "\n", + "Backtick: \\`\n", + "\n", + "Asterisk: \\*\n", + "\n", + "Underscore: \\_\n", + "\n", + "Left brace: \\{\n", + "\n", + "Right brace: \\}\n", + "\n", + "Left bracket: \\[\n", + "\n", + "Right bracket: \\]\n", + "\n", + "Left paren: \\(\n", + "\n", + "Right paren: \\)\n", + "\n", + "Greater-than: \\>\n", + "\n", + "Hash: \\#\n", + "\n", + "Period: \\.\n", + "\n", + "Bang: \\!\n", + "\n", + "Plus: \\+\n", + "\n", + "Minus: \\-\n"), + + para("Nor should these, which occur in code spans:"), + + para("Backslash: \\\\"), + para("Backtick: \\`"), + para("Asterisk: \\*"), + para("Underscore: \\_"), + para("Left brace: \\{"), + para("Right brace: \\}"), + para("Left bracket: \\["), + para("Right bracket: \\]"), + para("Left paren: \\("), + para("Right paren: \\)"), + para("Greater-than: \\>"), + para("Hash: \\#"), + para("Period: \\."), + para("Bang: \\!"), + para("Plus: \\+"), + para("Minus: \\-"), + + para("These should get escaped, even though they're matching pairs for\n" + + "other Markdown constructs:"), + + para("\*asterisks\*"), + para("\_underscores\_"), + para("`backticks`"), + + para("This is a code span with a literal backslash-backtick " + + "sequence: \\`"), + + para("This is a tag with unescaped backticks " + + "bar."), + + para("This is a tag with backslashes " + + "bar.")) + + assert_equal expected, doc + end + + def test_blockquotes_with_code_blocks + input = File.read "#{MARKDOWN_TEST_PATH}/Blockquotes with code blocks.text" + + doc = @parser.parse input + + expected = + doc( + block( + para("Example:"), + verb("sub status {\n", + " print \"working\";\n", + "}\n"), + para("Or:"), + verb("sub status {\n", + " return \"working\";\n", + "}\n"))) + + assert_equal expected, doc + end + + def test_code_blocks + input = File.read "#{MARKDOWN_TEST_PATH}/Code Blocks.text" + + doc = @parser.parse input + + expected = + doc( + verb("code block on the first line\n"), + para("Regular text."), + + verb("code block indented by spaces\n"), + para("Regular text."), + + verb("the lines in this block \n", + "all contain trailing spaces \n"), + para("Regular Text."), + + verb("code block on the last line\n")) + + assert_equal expected, doc + end + + def test_code_spans + input = File.read "#{MARKDOWN_TEST_PATH}/Code Spans.text" + + doc = @parser.parse input + + expected = doc( + para(" content of attribute \">"), + para("Fix for backticks within HTML tag: " + + "like this"), + para("Here's how you put `backticks` in a code span.")) + + assert_equal expected, doc + end + + def test_hard_wrapped_paragraphs_with_list_like_lines + input = File.read "#{MARKDOWN_TEST_PATH}/Hard-wrapped paragraphs with list-like lines.text" + + doc = @parser.parse input + + expected = + doc( + para("In Markdown 1.0.0 and earlier. Version\n" + + "8. This line turns into a list item.\n" + + "Because a hard-wrapped line in the\n" + + "middle of a paragraph looked like a\n" + + "list item."), + para("Here's one with a bullet.\n" + + "* criminey.")) + + assert_equal expected, doc + end + + def test_horizontal_rules + input = File.read "#{MARKDOWN_TEST_PATH}/Horizontal rules.text" + + doc = @parser.parse input + + expected = + doc( + para("Dashes:"), + + rule(1), + rule(1), + rule(1), + rule(1), + verb("---\n"), + + rule(1), + rule(1), + rule(1), + rule(1), + verb("- - -\n"), + + para("Asterisks:"), + + rule(1), + rule(1), + rule(1), + rule(1), + verb("***\n"), + + rule(1), + rule(1), + rule(1), + rule(1), + verb("* * *\n"), + + para("Underscores:"), + + rule(1), + rule(1), + rule(1), + rule(1), + verb("___\n"), + + rule(1), + rule(1), + rule(1), + rule(1), + verb("_ _ _\n")) + + assert_equal expected, doc + end + + def test_inline_html_advanced + input = File.read "#{MARKDOWN_TEST_PATH}/Inline HTML (Advanced).text" + + @parser.html = true + + doc = @parser.parse input + + expected = + doc( + para("Simple block on one line:"), + raw("
foo
"), + para("And nested without indentation:"), + raw(<<-RAW.chomp)) +
+
+
+foo +
+
+
+
bar
+
+ RAW + + assert_equal expected, doc + end + + def test_inline_html_simple + input = File.read "#{MARKDOWN_TEST_PATH}/Inline HTML (Simple).text" + + @parser.html = true + + doc = @parser.parse input + + expected = + doc( + para("Here's a simple block:"), + raw("
\n\tfoo\n
"), + + para("This should be a code block, though:"), + verb("
\n", + "\tfoo\n", + "
\n"), + + para("As should this:"), + verb("
foo
\n"), + + para("Now, nested:"), + raw("
\n\t
\n\t\t
\n\t\t\tfoo\n" + + "\t\t
\n\t
\n
"), + + para("This should just be an HTML comment:"), + raw(""), + + para("Multiline:"), + raw(""), + + para("Code block:"), + verb("\n"), + + para("Just plain comment, with trailing spaces on the line:"), + raw(""), + + para("Code:"), + verb("
\n"), + + para("Hr's:"), + raw("
"), + raw("
"), + raw("
"), + + raw("
"), + raw("
"), + raw("
"), + + raw("
"), + raw("
"), + raw("
")) + + assert_equal expected, doc + end + + def test_inline_html_comments + input = File.read "#{MARKDOWN_TEST_PATH}/Inline HTML comments.text" + + doc = @parser.parse input + + expected = + doc( + para("Paragraph one."), + + raw(""), + + raw(""), + + para("Paragraph two."), + + raw(""), + + para("The end.")) + + assert_equal expected, doc + end + + def test_links_inline_style + input = File.read "#{MARKDOWN_TEST_PATH}/Links, inline style.text" + + doc = @parser.parse input + + expected = + doc( + para("Just a {URL}[/url/]."), + para("{URL and title}[/url/]."), + para("{URL and title}[/url/]."), + para("{URL and title}[/url/]."), + para("{URL and title}[/url/]."), + para("{Empty}[].")) + + assert_equal expected, doc + end + + def test_links_reference_style + input = File.read "#{MARKDOWN_TEST_PATH}/Links, reference style.text" + + doc = @parser.parse input + + expected = + doc( + para("Foo {bar}[/url/]."), + para("Foo {bar}[/url/]."), + para("Foo {bar}[/url/]."), + + para("With {embedded [brackets]}[/url/]."), + + para("Indented {once}[/url]."), + para("Indented {twice}[/url]."), + para("Indented {thrice}[/url]."), + para("Indented [four][] times."), + + verb("[four]: /url\n"), + + rule(1), + + para("{this}[foo] should work"), + para("So should {this}[foo]."), + para("And {this}[foo]."), + para("And {this}[foo]."), + para("And {this}[foo]."), + + para("But not [that] []."), + para("Nor [that][]."), + para("Nor [that]."), + + para("[Something in brackets like {this}[foo] should work]"), + para("[Same with {this}[foo].]"), + + para("In this case, {this}[/somethingelse/] points to something else."), + para("Backslashing should suppress [this] and [this]."), + + rule(1), + + para("Here's one where the {link breaks}[/url/] across lines."), + para("Here's another where the {link breaks}[/url/] across lines, " + + "but with a line-ending space.")) + + assert_equal expected, doc + end + + def test_links_shortcut_references + input = File.read "#{MARKDOWN_TEST_PATH}/Links, shortcut references.text" + + doc = @parser.parse input + + expected = + doc( + para("This is the {simple case}[/simple]."), + para("This one has a {line break}[/foo]."), + para("This one has a {line break}[/foo] with a line-ending space."), + para("{this}[/that] and the {other}[/other]")) + + assert_equal expected, doc + end + + def test_literal_quotes_in_titles + input = File.read "#{MARKDOWN_TEST_PATH}/Literal quotes in titles.text" + + doc = @parser.parse input + + # TODO support title attribute + expected = + doc( + para("Foo {bar}[/url/]."), + para("Foo {bar}[/url/].")) + + assert_equal expected, doc + end + + def test_markdown_documentation_basics + input = File.read "#{MARKDOWN_TEST_PATH}/Markdown Documentation - Basics.text" + + doc = @parser.parse input + + expected = + doc( + head(1, "Markdown: Basics"), + + raw(<<-RAW.chomp), + + RAW + + head(2, "Getting the Gist of Markdown's Formatting Syntax"), + + para("This page offers a brief overview of what it's like to use Markdown.\n" + + "The {syntax page}[/projects/markdown/syntax] provides complete, detailed documentation for\n" + + "every feature, but Markdown should be very easy to pick up simply by\n" + + "looking at a few examples of it in action. The examples on this page\n" + + "are written in a before/after style, showing example syntax and the\n" + + "HTML output produced by Markdown."), + + para("It's also helpful to simply try Markdown out; the {Dingus}[/projects/markdown/dingus] is a\n" + + "web application that allows you type your own Markdown-formatted text\n" + + "and translate it to XHTML."), + + para("Note: This document is itself written using Markdown; you\n" + + "can {see the source for it by adding '.text' to the URL}[/projects/markdown/basics.text]."), + + head(2, "Paragraphs, Headers, Blockquotes"), + + para("A paragraph is simply one or more consecutive lines of text, separated\n" + + "by one or more blank lines. (A blank line is any line that looks like a\n" + + "blank line -- a line containing nothing spaces or tabs is considered\n" + + "blank.) Normal paragraphs should not be intended with spaces or tabs."), + + para("Markdown offers two styles of headers: _Setext_ and _atx_.\n" + + "Setext-style headers for

and

are created by\n" + + "\"underlining\" with equal signs (=) and hyphens (-), respectively.\n" + + "To create an atx-style header, you put 1-6 hash marks (#) at the\n" + + "beginning of the line -- the number of hashes equals the resulting\n" + + "HTML header level."), + + para("Blockquotes are indicated using email-style '>' angle brackets."), + + para("Markdown:"), + + verb("A First Level Header\n", + "====================\n", + "\n", + "A Second Level Header\n", + "---------------------\n", + "\n", + "Now is the time for all good men to come to\n", + "the aid of their country. This is just a\n", + "regular paragraph.\n", + "\n", + "The quick brown fox jumped over the lazy\n", + "dog's back.\n", + "\n", + "### Header 3\n", + "\n", + "> This is a blockquote.\n", + "> \n", + "> This is the second paragraph in the blockquote.\n", + ">\n", + "> ## This is an H2 in a blockquote\n"), + + para("Output:"), + + verb("

A First Level Header

\n", + "\n", + "

A Second Level Header

\n", + "\n", + "

Now is the time for all good men to come to\n", + "the aid of their country. This is just a\n", + "regular paragraph.

\n", + "\n", + "

The quick brown fox jumped over the lazy\n", + "dog's back.

\n", + "\n", + "

Header 3

\n", + "\n", + "
\n", + "

This is a blockquote.

\n", + "\n", + "

This is the second paragraph in the blockquote.

\n", + "\n", + "

This is an H2 in a blockquote

\n", + "
\n"), + + head(3, "Phrase Emphasis"), + para("Markdown uses asterisks and underscores to indicate spans of emphasis."), + + para("Markdown:"), + + verb("Some of these words *are emphasized*.\n", + "Some of these words _are emphasized also_.\n", + "\n", + "Use two asterisks for **strong emphasis**.\n", + "Or, if you prefer, __use two underscores instead__.\n"), + + para("Output:"), + + verb("

Some of these words are emphasized.\n", + "Some of these words are emphasized also.

\n", + "\n", + "

Use two asterisks for strong emphasis.\n", + "Or, if you prefer, use two underscores instead.

\n"), + + head(2, "Lists"), + + para("Unordered (bulleted) lists use asterisks, pluses, and hyphens (*,\n" + + "+, and -) as list markers. These three markers are\n" + + "interchangable; this:"), + + verb("* Candy.\n", + "* Gum.\n", + "* Booze.\n"), + + para("this:"), + + verb("+ Candy.\n", + "+ Gum.\n", + "+ Booze.\n"), + + para("and this:"), + + verb("- Candy.\n", + "- Gum.\n", + "- Booze.\n"), + + para("all produce the same output:"), + + verb("
    \n", + "
  • Candy.
  • \n", + "
  • Gum.
  • \n", + "
  • Booze.
  • \n", + "
\n"), + + para("Ordered (numbered) lists use regular numbers, followed by periods, as\n" + + "list markers:"), + + verb("1. Red\n", + "2. Green\n", + "3. Blue\n"), + + para("Output:"), + + verb("
    \n", + "
  1. Red
  2. \n", + "
  3. Green
  4. \n", + "
  5. Blue
  6. \n", + "
\n"), + + para("If you put blank lines between items, you'll get

tags for the\n" + + "list item text. You can create multi-paragraph list items by indenting\n" + + "the paragraphs by 4 spaces or 1 tab:"), + + verb("* A list item.\n", + "\n", + " With multiple paragraphs.\n", + "\n", + "* Another item in the list.\n"), + + para("Output:"), + + verb("

    \n", + "
  • A list item.

    \n", + "

    With multiple paragraphs.

  • \n", + "
  • Another item in the list.

  • \n", + "
\n"), + + head(3, "Links"), + + para("Markdown supports two styles for creating links: _inline_ and\n" + + "_reference_. With both styles, you use square brackets to delimit the\n" + + "text you want to turn into a link."), + + para("Inline-style links use parentheses immediately after the link text.\n" + + "For example:"), + + verb("This is an [example link](http://example.com/).\n"), + + para("Output:"), + + verb("

This is an \n", + "example link.

\n"), + + para("Optionally, you may include a title attribute in the parentheses:"), + + verb("This is an [example link](http://example.com/ \"With a Title\").\n"), + + para("Output:"), + + verb("

This is an \n", + "example link.

\n"), + + para("Reference-style links allow you to refer to your links by names, which\n" + + "you define elsewhere in your document:"), + + verb("I get 10 times more traffic from [Google][1] than from\n", + "[Yahoo][2] or [MSN][3].\n", + "\n", + "[1]: http://google.com/ \"Google\"\n", + "[2]: http://search.yahoo.com/ \"Yahoo Search\"\n", + "[3]: http://search.msn.com/ \"MSN Search\"\n"), + + para("Output:"), + + verb("

I get 10 times more traffic from Google than from Yahoo or MSN.

\n"), + + para("The title attribute is optional. Link names may contain letters,\n" + + "numbers and spaces, but are _not_ case sensitive:"), + + verb("I start my morning with a cup of coffee and\n", + "[The New York Times][NY Times].\n", + "\n", + "[ny times]: http://www.nytimes.com/\n"), + + para("Output:"), + + verb("

I start my morning with a cup of coffee and\n", + "The New York Times.

\n"), + + head(3, "Images"), + + para("Image syntax is very much like link syntax."), + + para("Inline (titles are optional):"), + + verb("![alt text](/path/to/img.jpg \"Title\")\n"), + + para("Reference-style:"), + + verb("![alt text][id]\n", + "\n", + "[id]: /path/to/img.jpg \"Title\"\n"), + + para("Both of the above examples produce the same output:"), + + verb("\"alt\n"), + + head(3, "Code"), + + para("In a regular paragraph, you can create code span by wrapping text in\n" + + "backtick quotes. Any ampersands (&) and angle brackets (< or\n" + + ">) will automatically be translated into HTML entities. This makes\n" + + "it easy to use Markdown to write about HTML example code:"), + + verb( + "I strongly recommend against using any `` tags.\n", + "\n", + "I wish SmartyPants used named entities like `—`\n", + "instead of decimal-encoded entites like `—`.\n"), + + para("Output:"), + + verb("

I strongly recommend against using any\n", + "<blink> tags.

\n", + "\n", + "

I wish SmartyPants used named entities like\n", + "&mdash; instead of decimal-encoded\n", + "entites like &#8212;.

\n"), + + para("To specify an entire block of pre-formatted code, indent every line of\n" + + "the block by 4 spaces or 1 tab. Just like with code spans, &, <,\n" + + "and > characters will be escaped automatically."), + + para("Markdown:"), + + verb("If you want your page to validate under XHTML 1.0 Strict,\n", + "you've got to put paragraph tags in your blockquotes:\n", + "\n", + "
\n", + "

For example.

\n", + "
\n"), + + para("Output:"), + + verb("

If you want your page to validate under XHTML 1.0 Strict,\n", + "you've got to put paragraph tags in your blockquotes:

\n", + "\n", + "
<blockquote>\n",
+             "    <p>For example.</p>\n",
+             "</blockquote>\n",
+             "
\n")) + + assert_equal expected, doc + end + + def test_markdown_documentation_syntax + input = File.read "#{MARKDOWN_TEST_PATH}/Markdown Documentation - Syntax.text" + + doc = @parser.parse input + + expected = + doc( + head(1, "Markdown: Syntax"), + + raw(<<-RAW.chomp), + + RAW + + list(:BULLET, + item(nil, + para("{Overview}[#overview]"), + list(:BULLET, + item(nil, + para("{Philosophy}[#philosophy]")), + item(nil, + para("{Inline HTML}[#html]")), + item(nil, + para("{Automatic Escaping for Special Characters}[#autoescape]")))), + item(nil, + para("{Block Elements}[#block]"), + list(:BULLET, + item(nil, + para("{Paragraphs and Line Breaks}[#p]")), + item(nil, + para("{Headers}[#header]")), + item(nil, + para("{Blockquotes}[#blockquote]")), + item(nil, + para("{Lists}[#list]")), + item(nil, + para("{Code Blocks}[#precode]")), + item(nil, + para("{Horizontal Rules}[#hr]")))), + item(nil, + para("{Span Elements}[#span]"), + list(:BULLET, + item(nil, + para("{Links}[#link]")), + item(nil, + para("{Emphasis}[#em]")), + item(nil, + para("{Code}[#code]")), + item(nil, + para("{Images}[#img]")))), + item(nil, + para("{Miscellaneous}[#misc]"), + list(:BULLET, + item(nil, + para("{Backslash Escapes}[#backslash]")), + item(nil, + para("{Automatic Links}[#autolink]"))))), + + para("Note: This document is itself written using Markdown; you\n" + + "can {see the source for it by adding '.text' to the URL}[/projects/markdown/syntax.text]."), + + rule(1), + + raw("

Overview

"), + + raw("

Philosophy

"), + + para("Markdown is intended to be as easy-to-read and easy-to-write as is feasible."), + + para("Readability, however, is emphasized above all else. A Markdown-formatted\n" + + "document should be publishable as-is, as plain text, without looking\n" + + "like it's been marked up with tags or formatting instructions. While\n" + + "Markdown's syntax has been influenced by several existing text-to-HTML\n" + + "filters -- including {Setext}[http://docutils.sourceforge.net/mirror/setext.html], {atx}[http://www.aaronsw.com/2002/atx/], {Textile}[http://textism.com/tools/textile/], {reStructuredText}[http://docutils.sourceforge.net/rst.html],\n" + + "{Grutatext}[http://www.triptico.com/software/grutatxt.html], and {EtText}[http://ettext.taint.org/doc/] -- the single biggest source of\n" + + "inspiration for Markdown's syntax is the format of plain text email."), + + para("To this end, Markdown's syntax is comprised entirely of punctuation\n" + + "characters, which punctuation characters have been carefully chosen so\n" + + "as to look like what they mean. E.g., asterisks around a word actually\n" + + "look like \*emphasis\*. Markdown lists look like, well, lists. Even\n" + + "blockquotes look like quoted passages of text, assuming you've ever\n" + + "used email."), + + raw("

Inline HTML

"), + + para("Markdown's syntax is intended for one purpose: to be used as a\n" + + "format for _writing_ for the web."), + + para("Markdown is not a replacement for HTML, or even close to it. Its\n" + + "syntax is very small, corresponding only to a very small subset of\n" + + "HTML tags. The idea is _not_ to create a syntax that makes it easier\n" + + "to insert HTML tags. In my opinion, HTML tags are already easy to\n" + + "insert. The idea for Markdown is to make it easy to read, write, and\n" + + "edit prose. HTML is a _publishing_ format; Markdown is a _writing_\n" + + "format. Thus, Markdown's formatting syntax only addresses issues that\n" + + "can be conveyed in plain text."), + + para("For any markup that is not covered by Markdown's syntax, you simply\n" + + "use HTML itself. There's no need to preface it or delimit it to\n" + + "indicate that you're switching from Markdown to HTML; you just use\n" + + "the tags."), + + para("The only restrictions are that block-level HTML elements -- e.g.
,\n" + + ",
, 

, etc. -- must be separated from surrounding\n" + + "content by blank lines, and the start and end tags of the block should\n" + + "not be indented with tabs or spaces. Markdown is smart enough not\n" + + "to add extra (unwanted)

tags around HTML block-level tags."), + + para("For example, to add an HTML table to a Markdown article:"), + + verb("This is a regular paragraph.\n", + "\n", + "

\n", + " \n", + " \n", + " \n", + "
Foo
\n", + "\n", + "This is another regular paragraph.\n"), + + para("Note that Markdown formatting syntax is not processed within block-level\n" + + "HTML tags. E.g., you can't use Markdown-style *emphasis* inside an\n" + + "HTML block."), + + para("Span-level HTML tags -- e.g. , , or -- can be\n" + + "used anywhere in a Markdown paragraph, list item, or header. If you\n" + + "want, you can even use HTML tags instead of Markdown formatting; e.g. if\n" + + "you'd prefer to use HTML or tags instead of Markdown's\n" + + "link or image syntax, go right ahead."), + + para("Unlike block-level HTML tags, Markdown syntax _is_ processed within\n" + + "span-level tags."), + + raw("

Automatic Escaping for Special Characters

"), + + para("In HTML, there are two characters that demand special treatment: <\n" + + "and &. Left angle brackets are used to start tags; ampersands are\n" + + "used to denote HTML entities. If you want to use them as literal\n" + + "characters, you must escape them as entities, e.g. <, and\n" + + "&."), + + para("Ampersands in particular are bedeviling for web writers. If you want to\n" + + "write about 'AT&T', you need to write 'AT&T'. You even need to\n" + + "escape ampersands within URLs. Thus, if you want to link to:"), + + verb("http://images.google.com/images?num=30&q=larry+bird\n"), + + para("you need to encode the URL as:"), + + verb("http://images.google.com/images?num=30&q=larry+bird\n"), + + para("in your anchor tag href attribute. Needless to say, this is easy to\n" + + "forget, and is probably the single most common source of HTML validation\n" + + "errors in otherwise well-marked-up web sites."), + + para("Markdown allows you to use these characters naturally, taking care of\n" + + "all the necessary escaping for you. If you use an ampersand as part of\n" + + "an HTML entity, it remains unchanged; otherwise it will be translated\n" + + "into &."), + + para("So, if you want to include a copyright symbol in your article, you can write:"), + + verb("©\n"), + + para("and Markdown will leave it alone. But if you write:"), + + verb("AT&T\n"), + + para("Markdown will translate it to:"), + + verb("AT&T\n"), + + para("Similarly, because Markdown supports {inline HTML}[#html], if you use\n" + + "angle brackets as delimiters for HTML tags, Markdown will treat them as\n" + + "such. But if you write:"), + + verb("4 < 5\n"), + + para("Markdown will translate it to:"), + + verb("4 < 5\n"), + + para("However, inside Markdown code spans and blocks, angle brackets and\n" + + "ampersands are _always_ encoded automatically. This makes it easy to use\n" + + "Markdown to write about HTML code. (As opposed to raw HTML, which is a\n" + + "terrible format for writing about HTML syntax, because every single <\n" + + "and & in your example code needs to be escaped.)"), + + rule(1), + + raw("

Block Elements

"), + + raw("

Paragraphs and Line Breaks

"), + + para("A paragraph is simply one or more consecutive lines of text, separated\n" + + "by one or more blank lines. (A blank line is any line that looks like a\n" + + "blank line -- a line containing nothing but spaces or tabs is considered\n" + + "blank.) Normal paragraphs should not be intended with spaces or tabs."), + + para("The implication of the \"one or more consecutive lines of text\" rule is\n" + + "that Markdown supports \"hard-wrapped\" text paragraphs. This differs\n" + + "significantly from most other text-to-HTML formatters (including Movable\n" + + "Type's \"Convert Line Breaks\" option) which translate every line break\n" + + "character in a paragraph into a
tag."), + + para("When you _do_ want to insert a
break tag using Markdown, you\n" + + "end a line with two or more spaces, then type return."), + + para("Yes, this takes a tad more effort to create a
, but a simplistic\n" + + "\"every line break is a
\" rule wouldn't work for Markdown.\n" + + "Markdown's email-style {blockquoting}[#blockquote] and multi-paragraph {list items}[#list]\n" + + "work best -- and look better -- when you format them with hard breaks."), + + raw("

Headers

"), + + para("Markdown supports two styles of headers, {Setext}[http://docutils.sourceforge.net/mirror/setext.html] and {atx}[http://www.aaronsw.com/2002/atx/]."), + + para("Setext-style headers are \"underlined\" using equal signs (for first-level\n" + + "headers) and dashes (for second-level headers). For example:"), + + verb("This is an H1\n", + "=============\n", + "\n", + "This is an H2\n", + "-------------\n"), + + para("Any number of underlining ='s or -'s will work."), + + para("Atx-style headers use 1-6 hash characters at the start of the line,\n" + + "corresponding to header levels 1-6. For example:"), + + verb("# This is an H1\n", + "\n", + "## This is an H2\n", + "\n", + "###### This is an H6\n"), + + para("Optionally, you may \"close\" atx-style headers. This is purely\n" + + "cosmetic -- you can use this if you think it looks better. The\n" + + "closing hashes don't even need to match the number of hashes\n" + + "used to open the header. (The number of opening hashes\n" + + "determines the header level.) :"), + + verb("# This is an H1 #\n", + "\n", + "## This is an H2 ##\n", + "\n", + "### This is an H3 ######\n"), + + raw("

Blockquotes

"), + + para( + "Markdown uses email-style > characters for blockquoting. If you're\n" + + "familiar with quoting passages of text in an email message, then you\n" + + "know how to create a blockquote in Markdown. It looks best if you hard\n" + + "wrap the text and put a > before every line:"), + + verb("> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\n", + "> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\n", + "> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n", + "> \n", + "> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\n", + "> id sem consectetuer libero luctus adipiscing.\n"), + + para("Markdown allows you to be lazy and only put the > before the first\n" + + "line of a hard-wrapped paragraph:"), + + verb("> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,\n", + "consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.\n", + "Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.\n", + "\n", + "> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse\n", + "id sem consectetuer libero luctus adipiscing.\n"), + + para("Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by\n" + + "adding additional levels of >:"), + + verb("> This is the first level of quoting.\n", + ">\n", + "> > This is nested blockquote.\n", + ">\n", + "> Back to the first level.\n"), + + para("Blockquotes can contain other Markdown elements, including headers, lists,\n" + + "and code blocks:"), + + verb("> ## This is a header.\n", + "> \n", + "> 1. This is the first list item.\n", + "> 2. This is the second list item.\n", + "> \n", + "> Here's some example code:\n", + "> \n", + "> return shell_exec(\"echo $input | $markdown_script\");\n"), + + para("Any decent text editor should make email-style quoting easy. For\n" + + "example, with BBEdit, you can make a selection and choose Increase\n" + + "Quote Level from the Text menu."), + + raw("

Lists

"), + + para("Markdown supports ordered (numbered) and unordered (bulleted) lists."), + + para("Unordered lists use asterisks, pluses, and hyphens -- interchangably\n" + + "-- as list markers:"), + + verb("* Red\n", + "* Green\n", + "* Blue\n"), + + para("is equivalent to:"), + + verb("+ Red\n", + "+ Green\n", + "+ Blue\n"), + + para("and:"), + + verb("- Red\n", + "- Green\n", + "- Blue\n"), + + para("Ordered lists use numbers followed by periods:"), + + verb("1. Bird\n", + "2. McHale\n", + "3. Parish\n"), + + para("It's important to note that the actual numbers you use to mark the\n" + + "list have no effect on the HTML output Markdown produces. The HTML\n" + + "Markdown produces from the above list is:"), + + verb("
    \n", + "
  1. Bird
  2. \n", + "
  3. McHale
  4. \n", + "
  5. Parish
  6. \n", + "
\n"), + + para("If you instead wrote the list in Markdown like this:"), + + verb("1. Bird\n", + "1. McHale\n", + "1. Parish\n"), + + para("or even:"), + + verb("3. Bird\n", + "1. McHale\n", + "8. Parish\n"), + + para("you'd get the exact same HTML output. The point is, if you want to,\n" + + "you can use ordinal numbers in your ordered Markdown lists, so that\n" + + "the numbers in your source match the numbers in your published HTML.\n" + + "But if you want to be lazy, you don't have to."), + + para("If you do use lazy list numbering, however, you should still start the\n" + + "list with the number 1. At some point in the future, Markdown may support\n" + + "starting ordered lists at an arbitrary number."), + + para("List markers typically start at the left margin, but may be indented by\n" + + "up to three spaces. List markers must be followed by one or more spaces\n" + + "or a tab."), + + para("To make lists look nice, you can wrap items with hanging indents:"), + + verb("* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n", + " Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\n", + " viverra nec, fringilla in, laoreet vitae, risus.\n", + "* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\n", + " Suspendisse id sem consectetuer libero luctus adipiscing.\n"), + + para("But if you want to be lazy, you don't have to:"), + + verb("* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\n", + "Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,\n", + "viverra nec, fringilla in, laoreet vitae, risus.\n", + "* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.\n", + "Suspendisse id sem consectetuer libero luctus adipiscing.\n"), + + para("If list items are separated by blank lines, Markdown will wrap the\n" + + "items in

tags in the HTML output. For example, this input:"), + + verb("* Bird\n", + "* Magic\n"), + + para("will turn into:"), + + verb("

    \n", + "
  • Bird
  • \n", + "
  • Magic
  • \n", + "
\n"), + + para("But this:"), + + verb("* Bird\n", + "\n", + "* Magic\n"), + + para("will turn into:"), + + verb("
    \n", + "
  • Bird

  • \n", + "
  • Magic

  • \n", + "
\n"), + + para("List items may consist of multiple paragraphs. Each subsequent\n" + + "paragraph in a list item must be intended by either 4 spaces\n" + + "or one tab:"), + + verb("1. This is a list item with two paragraphs. Lorem ipsum dolor\n", + " sit amet, consectetuer adipiscing elit. Aliquam hendrerit\n", + " mi posuere lectus.\n", + "\n", + " Vestibulum enim wisi, viverra nec, fringilla in, laoreet\n", + " vitae, risus. Donec sit amet nisl. Aliquam semper ipsum\n", + " sit amet velit.\n", + "\n", + "2. Suspendisse id sem consectetuer libero luctus adipiscing.\n"), + + para("It looks nice if you indent every line of the subsequent\n" + + "paragraphs, but here again, Markdown will allow you to be\n" + + "lazy:"), + + verb("* This is a list item with two paragraphs.\n", + "\n", + " This is the second paragraph in the list item. You're\n", + "only required to indent the first line. Lorem ipsum dolor\n", + "sit amet, consectetuer adipiscing elit.\n", + "\n", + "* Another item in the same list.\n"), + + para("To put a blockquote within a list item, the blockquote's >\n" + + "delimiters need to be indented:"), + + verb("* A list item with a blockquote:\n", + "\n", + " > This is a blockquote\n", + " > inside a list item.\n"), + + para( + "To put a code block within a list item, the code block needs\n" + + "to be indented _twice_ -- 8 spaces or two tabs:"), + + verb("* A list item with a code block:\n", + "\n", + " \n"), + + para("It's worth noting that it's possible to trigger an ordered list by\n" + + "accident, by writing something like this:"), + + verb("1986. What a great season.\n"), + + para("In other words, a number-period-space sequence at the beginning of a\n" + + "line. To avoid this, you can backslash-escape the period:"), + + verb("1986\\. What a great season.\n"), + + raw("

Code Blocks

"), + + para("Pre-formatted code blocks are used for writing about programming or\n" + + "markup source code. Rather than forming normal paragraphs, the lines\n" + + "of a code block are interpreted literally. Markdown wraps a code block\n" + + "in both
 and  tags."),
+
+        para("To produce a code block in Markdown, simply indent every line of the\n" +
+             "block by at least 4 spaces or 1 tab. For example, given this input:"),
+
+        verb("This is a normal paragraph:\n",
+             "\n",
+             "    This is a code block.\n"),
+
+        para("Markdown will generate:"),
+
+        verb("

This is a normal paragraph:

\n", + "\n", + "
This is a code block.\n",
+             "
\n"), + + para("One level of indentation -- 4 spaces or 1 tab -- is removed from each\n" + + "line of the code block. For example, this:"), + + verb("Here is an example of AppleScript:\n", + "\n", + " tell application \"Foo\"\n", + " beep\n", + " end tell\n"), + + para("will turn into:"), + + verb("

Here is an example of AppleScript:

\n", + "\n", + "
tell application \"Foo\"\n",
+             "    beep\n",
+             "end tell\n",
+             "
\n"), + + para("A code block continues until it reaches a line that is not indented\n" + + "(or the end of the article)."), + + para("Within a code block, ampersands (&) and angle brackets (< and >)\n" + + "are automatically converted into HTML entities. This makes it very\n" + + "easy to include example HTML source code using Markdown -- just paste\n" + + "it and indent it, and Markdown will handle the hassle of encoding the\n" + + "ampersands and angle brackets. For example, this:"), + + verb("
\n", + " © 2004 Foo Corporation\n", + "
\n"), + + para("will turn into:"), + + verb("
<div class=\"footer\">\n",
+             "    &copy; 2004 Foo Corporation\n",
+             "</div>\n",
+             "
\n"), + + para("Regular Markdown syntax is not processed within code blocks. E.g.,\n" + + "asterisks are just literal asterisks within a code block. This means\n" + + "it's also easy to use Markdown to write about Markdown's own syntax."), + + raw("

Horizontal Rules

"), + + para("You can produce a horizontal rule tag (
) by placing three or\n" + + "more hyphens, asterisks, or underscores on a line by themselves. If you\n" + + "wish, you may use spaces between the hyphens or asterisks. Each of the\n" + + "following lines will produce a horizontal rule:"), + + verb("* * *\n", + "\n", + "***\n", + "\n", + "*****\n", + "\n", + "- - -\n", + "\n", + "---------------------------------------\n", + "\n", + "_ _ _\n"), + + rule(1), + + raw("

Span Elements

"), + + raw("

Links

"), + + para("Markdown supports two style of links: _inline_ and _reference_."), + + para("In both styles, the link text is delimited by [square brackets]."), + + para("To create an inline link, use a set of regular parentheses immediately\n" + + "after the link text's closing square bracket. Inside the parentheses,\n" + + "put the URL where you want the link to point, along with an _optional_\n" + + "title for the link, surrounded in quotes. For example:"), + + verb("This is [an example](http://example.com/ \"Title\") inline link.\n", + "\n", + "[This link](http://example.net/) has no title attribute.\n"), + + para("Will produce:"), + + verb("

This is \n", + "an example inline link.

\n", + "\n", + "

This link has no\n", + "title attribute.

\n"), + + para("If you're referring to a local resource on the same server, you can\n" + + "use relative paths:"), + + verb("See my [About](/about/) page for details.\n"), + + para("Reference-style links use a second set of square brackets, inside\n" + + "which you place a label of your choosing to identify the link:"), + + verb("This is [an example][id] reference-style link.\n"), + + para("You can optionally use a space to separate the sets of brackets:"), + + verb("This is [an example] [id] reference-style link.\n"), + + para("Then, anywhere in the document, you define your link label like this,\n" + + "on a line by itself:"), + + verb("[id]: http://example.com/ \"Optional Title Here\"\n"), + + para("That is:"), + + list(:BULLET, + item(nil, + para("Square brackets containing the link identifier (optionally\n" + + "indented from the left margin using up to three spaces);")), + item(nil, + para("followed by a colon;")), + item(nil, + para("followed by one or more spaces (or tabs);")), + item(nil, + para("followed by the URL for the link;")), + item(nil, + para("optionally followed by a title attribute for the link, enclosed\n" + + "in double or single quotes."))), + + para("The link URL may, optionally, be surrounded by angle brackets:"), + + verb("[id]: \"Optional Title Here\"\n"), + + para("You can put the title attribute on the next line and use extra spaces\n" + + "or tabs for padding, which tends to look better with longer URLs:"), + + verb("[id]: http://example.com/longish/path/to/resource/here\n", + " \"Optional Title Here\"\n"), + + para("Link definitions are only used for creating links during Markdown\n" + + "processing, and are stripped from your document in the HTML output."), + + para("Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are _not_ case sensitive. E.g. these two links:"), + + verb("[link text][a]\n", + "[link text][A]\n"), + + para("are equivalent."), + + para("The implicit link name shortcut allows you to omit the name of the\n" + + "link, in which case the link text itself is used as the name.\n" + + "Just use an empty set of square brackets -- e.g., to link the word\n" + + "\"Google\" to the google.com web site, you could simply write:"), + + verb("[Google][]\n"), + + para("And then define the link:"), + + verb("[Google]: http://google.com/\n"), + + para("Because link names may contain spaces, this shortcut even works for\n" + + "multiple words in the link text:"), + + + verb("Visit [Daring Fireball][] for more information.\n"), + + para("And then define the link:"), + + verb("[Daring Fireball]: http://daringfireball.net/\n"), + + para("Link definitions can be placed anywhere in your Markdown document. I\n" + + "tend to put them immediately after each paragraph in which they're\n" + + "used, but if you want, you can put them all at the end of your\n" + + "document, sort of like footnotes."), + + para("Here's an example of reference links in action:"), + + verb("I get 10 times more traffic from [Google] [1] than from\n", + "[Yahoo] [2] or [MSN] [3].\n", + "\n", + " [1]: http://google.com/ \"Google\"\n", + " [2]: http://search.yahoo.com/ \"Yahoo Search\"\n", + " [3]: http://search.msn.com/ \"MSN Search\"\n"), + + para("Using the implicit link name shortcut, you could instead write:"), + + verb("I get 10 times more traffic from [Google][] than from\n", + "[Yahoo][] or [MSN][].\n", + "\n", + " [google]: http://google.com/ \"Google\"\n", + " [yahoo]: http://search.yahoo.com/ \"Yahoo Search\"\n", + " [msn]: http://search.msn.com/ \"MSN Search\"\n"), + + para("Both of the above examples will produce the following HTML output:"), + + verb("

I get 10 times more traffic from Google than from\n", + "Yahoo\n", + "or MSN.

\n"), + + para("For comparison, here is the same paragraph written using\n" + + "Markdown's inline link style:"), + + verb("I get 10 times more traffic from [Google](http://google.com/ \"Google\")\n", + "than from [Yahoo](http://search.yahoo.com/ \"Yahoo Search\") or\n", + "[MSN](http://search.msn.com/ \"MSN Search\").\n"), + + para("The point of reference-style links is not that they're easier to\n" + + "write. The point is that with reference-style links, your document\n" + + "source is vastly more readable. Compare the above examples: using\n" + + "reference-style links, the paragraph itself is only 81 characters\n" + + "long; with inline-style links, it's 176 characters; and as raw HTML,\n" + + "it's 234 characters. In the raw HTML, there's more markup than there\n" + + "is text."), + + para("With Markdown's reference-style links, a source document much more\n" + + "closely resembles the final output, as rendered in a browser. By\n" + + "allowing you to move the markup-related metadata out of the paragraph,\n" + + "you can add links without interrupting the narrative flow of your\n" + + "prose."), + + raw("

Emphasis

"), + + para("Markdown treats asterisks (*) and underscores (_) as indicators of\n" + + "emphasis. Text wrapped with one * or _ will be wrapped with an\n" + + "HTML tag; double *'s or _'s will be wrapped with an HTML\n" + + " tag. E.g., this input:"), + + verb("*single asterisks*\n", + "\n", + "_single underscores_\n", + "\n", + "**double asterisks**\n", + "\n", + "__double underscores__\n"), + + para("will produce:"), + + verb("single asterisks\n", + "\n", + "single underscores\n", + "\n", + "double asterisks\n", + "\n", + "double underscores\n"), + + para("You can use whichever style you prefer; the lone restriction is that\n" + + "the same character must be used to open and close an emphasis span."), + + para("Emphasis can be used in the middle of a word:"), + + verb("un*fucking*believable\n"), + + para("But if you surround an * or _ with spaces, it'll be treated as a\n" + + "literal asterisk or underscore."), + + para("To produce a literal asterisk or underscore at a position where it\n" + + "would otherwise be used as an emphasis delimiter, you can backslash\n" + + "escape it:"), + + verb("\\*this text is surrounded by literal asterisks\\*\n"), + + raw("

Code

"), + + para("To indicate a span of code, wrap it with backtick quotes (`).\n" + + "Unlike a pre-formatted code block, a code span indicates code within a\n" + + "normal paragraph. For example:"), + + verb("Use the `printf()` function.\n"), + + para("will produce:"), + + verb("

Use the printf() function.

\n"), + + para("To include a literal backtick character within a code span, you can use\n" + + "multiple backticks as the opening and closing delimiters:"), + + verb("``There is a literal backtick (`) here.``\n"), + + para("which will produce this:"), + + verb("

There is a literal backtick (`) here.

\n"), + + para("The backtick delimiters surrounding a code span may include spaces --\n" + + "one after the opening, one before the closing. This allows you to place\n" + + "literal backtick characters at the beginning or end of a code span:"), + + verb("A single backtick in a code span: `` ` ``\n", + "\n", + "A backtick-delimited string in a code span: `` `foo` ``\n"), + + para("will produce:"), + + verb("

A single backtick in a code span: `

\n", + "\n", + "

A backtick-delimited string in a code span: `foo`

\n"), + + para("With a code span, ampersands and angle brackets are encoded as HTML\n" + + "entities automatically, which makes it easy to include example HTML\n" + + "tags. Markdown will turn this:"), + + verb("Please don't use any `` tags.\n"), + + para("into:"), + + verb("

Please don't use any <blink> tags.

\n"), + + para("You can write this:"), + + verb("`—` is the decimal-encoded equivalent of `—`.\n"), + + para("to produce:"), + + verb( "

&#8212; is the decimal-encoded\n", + "equivalent of &mdash;.

\n"), + + raw("

Images

"), + + para("Admittedly, it's fairly difficult to devise a \"natural\" syntax for\n" + + "placing images into a plain text document format."), + + para("Markdown uses an image syntax that is intended to resemble the syntax\n" + + "for links, allowing for two styles: _inline_ and _reference_."), + + para("Inline image syntax looks like this:"), + + verb("![Alt text](/path/to/img.jpg)\n", + "\n", + "![Alt text](/path/to/img.jpg \"Optional title\")\n"), + + para("That is:"), + + list(:BULLET, + item(nil, + para("An exclamation mark: !;")), + item(nil, + para("followed by a set of square brackets, containing the alt\n" + + "attribute text for the image;")), + item(nil, + para("followed by a set of parentheses, containing the URL or path to\n" + + "the image, and an optional title attribute enclosed in double\n" + + "or single quotes."))), + + para("Reference-style image syntax looks like this:"), + + verb("![Alt text][id]\n"), + + para("Where \"id\" is the name of a defined image reference. Image references\n" + + "are defined using syntax identical to link references:"), + + verb("[id]: url/to/image \"Optional title attribute\"\n"), + + para("As of this writing, Markdown has no syntax for specifying the\n" + + "dimensions of an image; if this is important to you, you can simply\n" + + "use regular HTML tags."), + + rule(1), + + raw("

Miscellaneous

"), + + raw("

Automatic Links

"), + + para("Markdown supports a shortcut style for creating \"automatic\" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:"), + + verb("\n"), + + para("Markdown will turn this into:"), + + verb("http://example.com/\n"), + + para("Automatic links for email addresses work similarly, except that\n" + + "Markdown will also perform a bit of randomized decimal and hex\n" + + "entity-encoding to help obscure your address from address-harvesting\n" + + "spambots. For example, Markdown will turn this:"), + + verb("\n"), + + para("into something like this:"), + + verb("address@exa\n", + "mple.com\n"), + + para("which will render in a browser as a clickable link to \"address@example.com\"."), + + para("(This sort of entity-encoding trick will indeed fool many, if not\n" + + "most, address-harvesting bots, but it definitely won't fool all of\n" + + "them. It's better than nothing, but an address published in this way\n" + + "will probably eventually start receiving spam.)"), + + raw("

Backslash Escapes

"), + + para("Markdown allows you to use backslash escapes to generate literal\n" + + "characters which would otherwise have special meaning in Markdown's\n" + + "formatting syntax. For example, if you wanted to surround a word with\n" + + "literal asterisks (instead of an HTML tag), you can backslashes\n" + + "before the asterisks, like this:"), + + verb("\\*literal asterisks\\*\n"), + + para("Markdown provides backslash escapes for the following characters:"), + + verb("\\ backslash\n", + "` backtick\n", + "* asterisk\n", + "_ underscore\n", + "{} curly braces\n", + "[] square brackets\n", + "() parentheses\n", + "# hash mark\n", + "+ plus sign\n", + "- minus sign (hyphen)\n", + ". dot\n", + "! exclamation mark\n")) + + assert_equal expected, doc + end + + def test_nested_blockquotes + input = File.read "#{MARKDOWN_TEST_PATH}/Nested blockquotes.text" + + doc = @parser.parse input + + expected = + doc( + block( + para("foo"), + block( + para("bar")), + para("foo"))) + + assert_equal expected, doc + end + + def test_ordered_and_unordered_lists + input = File.read "#{MARKDOWN_TEST_PATH}/Ordered and unordered lists.text" + + doc = @parser.parse input + + expected = + doc( + head(2, 'Unordered'), + + para('Asterisks tight:'), + list(:BULLET, + item(nil, para("asterisk 1")), + item(nil, para("asterisk 2")), + item(nil, para("asterisk 3"))), + para('Asterisks loose:'), + list(:BULLET, + item(nil, para("asterisk 1")), + item(nil, para("asterisk 2")), + item(nil, para("asterisk 3"))), + + rule(1), + + para("Pluses tight:"), + list(:BULLET, + item(nil, para("Plus 1")), + item(nil, para("Plus 2")), + item(nil, para("Plus 3"))), + para("Pluses loose:"), + list(:BULLET, + item(nil, para("Plus 1")), + item(nil, para("Plus 2")), + item(nil, para("Plus 3"))), + + rule(1), + + para("Minuses tight:"), + list(:BULLET, + item(nil, para("Minus 1")), + item(nil, para("Minus 2")), + item(nil, para("Minus 3"))), + para("Minuses loose:"), + list(:BULLET, + item(nil, para("Minus 1")), + item(nil, para("Minus 2")), + item(nil, para("Minus 3"))), + + head(2, "Ordered"), + + para("Tight:"), + list(:NUMBER, + item(nil, para("First")), + item(nil, para("Second")), + item(nil, para("Third"))), + para("and:"), + list(:NUMBER, + item(nil, para("One")), + item(nil, para("Two")), + item(nil, para("Three"))), + + para("Loose using tabs:"), + list(:NUMBER, + item(nil, para("First")), + item(nil, para("Second")), + item(nil, para("Third"))), + para("and using spaces:"), + list(:NUMBER, + item(nil, para("One")), + item(nil, para("Two")), + item(nil, para("Three"))), + + para("Multiple paragraphs:"), + list(:NUMBER, + item(nil, + para("Item 1, graf one."), + para("Item 2. graf two. The quick brown fox " + + "jumped over the lazy dog's\nback.")), + item(nil, para("Item 2.")), + item(nil, para("Item 3."))), + + head(2, "Nested"), + list(:BULLET, + item(nil, + para("Tab"), + list(:BULLET, + item(nil, + para("Tab"), + list(:BULLET, + item(nil, + para("Tab"))))))), + + para("Here's another:"), + list(:NUMBER, + item(nil, para("First")), + item(nil, para("Second:"), + list(:BULLET, + item(nil, para("Fee")), + item(nil, para("Fie")), + item(nil, para("Foe")))), + item(nil, para("Third"))), + + para("Same thing but with paragraphs:"), + list(:NUMBER, + item(nil, para("First")), + item(nil, para("Second:"), + list(:BULLET, + item(nil, para("Fee")), + item(nil, para("Fie")), + item(nil, para("Foe")))), + item(nil, para("Third"))), + + para("This was an error in Markdown 1.0.1:"), + list(:BULLET, + item(nil, + para("this"), + list(:BULLET, + item(nil, para("sub"))), + para("that")))) + + assert_equal expected, doc + end + + def test_strong_and_em_together + input = File.read "#{MARKDOWN_TEST_PATH}/Strong and em together.text" + + doc = @parser.parse input + + expected = + doc( + para("This is strong and em."), + para("So is _this_ word."), + para("This is strong and em."), + para("So is _this_ word.")) + + assert_equal expected, doc + end + + def test_tabs + input = File.read "#{MARKDOWN_TEST_PATH}/Tabs.text" + + doc = @parser.parse input + + expected = + doc( + list(:BULLET, + item(nil, + para("this is a list item\nindented with tabs")), + item(nil, + para("this is a list item\nindented with spaces"))), + + para("Code:"), + + verb("this code block is indented by one tab\n"), + + para("And:"), + + verb("\tthis code block is indented by two tabs\n"), + + para("And:"), + + verb( + "+\tthis is an example list item\n", + "\tindented with tabs\n", + "\n", + "+ this is an example list item\n", + " indented with spaces\n")) + + assert_equal expected, doc + end + + def test_tidyness + input = File.read "#{MARKDOWN_TEST_PATH}/Tidyness.text" + + doc = @parser.parse input + + expected = + doc( + block( + para("A list within a blockquote:"), + list(:BULLET, + item(nil, para("asterisk 1")), + item(nil, para("asterisk 2")), + item(nil, para("asterisk 3"))))) + + assert_equal expected, doc + end + +end + diff --git a/test/rdoc/test_rdoc_markup.rb b/test/rdoc/test_rdoc_markup.rb index ae6c11e7da..5c28a2c6e6 100644 --- a/test/rdoc/test_rdoc_markup.rb +++ b/test/rdoc/test_rdoc_markup.rb @@ -1,9 +1,13 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/markup' -require 'rdoc/markup/to_test' +require 'rdoc/test_case' -class TestRDocMarkup < MiniTest::Unit::TestCase +class TestRDocMarkup < RDoc::TestCase + + def test_class_parse + expected = @RM::Document.new( + @RM::Paragraph.new('hello')) + + assert_equal expected, RDoc::Markup.parse('hello') + end def test_convert str = <<-STR @@ -44,7 +48,7 @@ the time m = RDoc::Markup.new m.add_word_pair '{', '}', :STRIKE - tt = RDoc::Markup::ToTest.new m + tt = RDoc::Markup::ToTest.new nil, m tt.add_tag :STRIKE, 'STRIKE ', ' STRIKE' out = m.convert str, tt diff --git a/test/rdoc/test_rdoc_markup_attribute_manager.rb b/test/rdoc/test_rdoc_markup_attribute_manager.rb index b65457fc7e..36edea3f73 100644 --- a/test/rdoc/test_rdoc_markup_attribute_manager.rb +++ b/test/rdoc/test_rdoc_markup_attribute_manager.rb @@ -1,13 +1,10 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc' -require 'rdoc/markup' -require 'rdoc/markup/inline' -require 'rdoc/markup/to_html_crossref' +require 'rdoc/test_case' -class TestRDocMarkupAttributeManager < MiniTest::Unit::TestCase +class TestRDocMarkupAttributeManager < RDoc::TestCase def setup + super + @am = RDoc::Markup::AttributeManager.new @bold_on = @am.changed_attribute_by_name([], [:BOLD]) @@ -32,8 +29,8 @@ class TestRDocMarkupAttributeManager < MiniTest::Unit::TestCase end def crossref(text) - crossref_bitmap = RDoc::Markup::Attribute.bitmap_for(:_SPECIAL_) | - RDoc::Markup::Attribute.bitmap_for(:CROSSREF) + crossref_bitmap = @am.attributes.bitmap_for(:_SPECIAL_) | + @am.attributes.bitmap_for(:CROSSREF) [ @am.changed_attribute_by_name([], [:CROSSREF, :_SPECIAL_]), RDoc::Markup::Special.new(crossref_bitmap, text), @@ -212,7 +209,7 @@ class TestRDocMarkupAttributeManager < MiniTest::Unit::TestCase end def test_special - @am.add_special(RDoc::Markup::ToHtmlCrossref::CROSSREF_REGEXP, :CROSSREF) + @am.add_special(RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF) # # The apostrophes in "cats'" and "dogs'" suppress the flagging of these diff --git a/test/rdoc/test_rdoc_markup_attributes.rb b/test/rdoc/test_rdoc_markup_attributes.rb new file mode 100644 index 0000000000..636e0cca68 --- /dev/null +++ b/test/rdoc/test_rdoc_markup_attributes.rb @@ -0,0 +1,39 @@ +require 'rdoc/test_case' + +class TestRDocMarkupAttributes < RDoc::TestCase + + def setup + super + + @as = RDoc::Markup::Attributes.new + end + + def test_bitmap_for + assert_equal 2, @as.bitmap_for('two') + assert_equal 2, @as.bitmap_for('two') + assert_equal 4, @as.bitmap_for('three') + end + + def test_as_string + @as.bitmap_for 'two' + @as.bitmap_for 'three' + + assert_equal 'none', @as.as_string(0) + assert_equal '_SPECIAL_', @as.as_string(1) + assert_equal 'two', @as.as_string(2) + assert_equal '_SPECIAL_,two', @as.as_string(3) + end + + def test_each_name_of + @as.bitmap_for 'two' + @as.bitmap_for 'three' + + assert_equal %w[], @as.each_name_of(0).to_a + assert_equal %w[], @as.each_name_of(1).to_a + assert_equal %w[two], @as.each_name_of(2).to_a + assert_equal %w[three], @as.each_name_of(4).to_a + assert_equal %w[two three], @as.each_name_of(6).to_a + end + +end + diff --git a/test/rdoc/test_rdoc_markup_document.rb b/test/rdoc/test_rdoc_markup_document.rb index 9eea019ae4..564434dfe6 100644 --- a/test/rdoc/test_rdoc_markup_document.rb +++ b/test/rdoc/test_rdoc_markup_document.rb @@ -1,12 +1,10 @@ -require 'pp' -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/markup' +require 'rdoc/test_case' -class TestRDocMarkupDocument < MiniTest::Unit::TestCase +class TestRDocMarkupDocument < RDoc::TestCase def setup - @RM = RDoc::Markup + super + @d = @RM::Document.new end @@ -47,6 +45,21 @@ class TestRDocMarkupDocument < MiniTest::Unit::TestCase end end + def test_concat + @d.concat [@RM::BlankLine.new, @RM::BlankLine.new] + + refute_empty @d + end + + def test_each + a = @RM::Document.new + b = @RM::Document.new(@RM::Paragraph.new('hi')) + + @d.push a, b + + assert_equal [a, b], @d.map { |sub_doc| sub_doc } + end + def test_empty_eh assert_empty @d @@ -82,6 +95,18 @@ class TestRDocMarkupDocument < MiniTest::Unit::TestCase assert_equal @d, d2 end + def test_file_equals + @d.file = 'file.rb' + + assert_equal 'file.rb', @d.file + end + + def test_file_equals_top_level + @d.file = @store.add_file 'file.rb' + + assert_equal 'file.rb', @d.file + end + def test_lt2 @d << @RM::BlankLine.new @@ -148,5 +173,23 @@ class TestRDocMarkupDocument < MiniTest::Unit::TestCase refute_empty @d end + def test_table_of_contents + doc = @RM::Document.new( + @RM::Heading.new(1, 'A'), + @RM::Paragraph.new('B'), + @RM::Heading.new(2, 'C'), + @RM::Paragraph.new('D'), + @RM::Heading.new(1, 'E'), + @RM::Paragraph.new('F')) + + expected = [ + @RM::Heading.new(1, 'A'), + @RM::Heading.new(2, 'C'), + @RM::Heading.new(1, 'E'), + ] + + assert_equal expected, doc.table_of_contents + end + end diff --git a/test/rdoc/test_rdoc_markup_formatter.rb b/test/rdoc/test_rdoc_markup_formatter.rb index 73e75e2aa1..9512babce3 100644 --- a/test/rdoc/test_rdoc_markup_formatter.rb +++ b/test/rdoc/test_rdoc_markup_formatter.rb @@ -1,17 +1,13 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc' -require 'rdoc/markup' -require 'rdoc/markup/formatter' +require 'rdoc/test_case' -class TestRDocMarkupFormatter < MiniTest::Unit::TestCase +class TestRDocMarkupFormatter < RDoc::TestCase class ToTest < RDoc::Markup::Formatter def initialize markup - super + super nil, markup - add_tag :TT, '', '' + add_tag :TT, '', '' end def accept_paragraph paragraph @@ -37,20 +33,25 @@ class TestRDocMarkupFormatter < MiniTest::Unit::TestCase end def setup - @markup = RDoc::Markup.new + super + + @markup = @RM.new @markup.add_special(/[A-Z]+/, :CAPS) + @attribute_manager = @markup.attribute_manager + @attributes = @attribute_manager.attributes + @to = ToTest.new @markup - @caps = RDoc::Markup::Attribute.bitmap_for :CAPS - @special = RDoc::Markup::Attribute.bitmap_for :_SPECIAL_ - @tt = RDoc::Markup::Attribute.bitmap_for :TT + @caps = @attributes.bitmap_for :CAPS + @special = @attributes.bitmap_for :_SPECIAL_ + @tt = @attributes.bitmap_for :TT end def test_convert_tt_special - converted = @to.convert 'AAA' + converted = @to.convert 'AAA' - assert_equal 'AAA', converted + assert_equal 'AAA', converted end end diff --git a/test/rdoc/test_rdoc_markup_hard_break.rb b/test/rdoc/test_rdoc_markup_hard_break.rb new file mode 100644 index 0000000000..b9f7873160 --- /dev/null +++ b/test/rdoc/test_rdoc_markup_hard_break.rb @@ -0,0 +1,31 @@ +require 'rdoc/test_case' + +class TestRDocMarkupHardBreak < RDoc::TestCase + + def setup + super + + @hb = RDoc::Markup::HardBreak.new + end + + def test_accept + visitor = Object.new + + def visitor.accept_hard_break(obj) @obj = obj end + def visitor.obj() @obj end + + @hb.accept visitor + + assert_same @hb, visitor.obj + end + + def test_equals2 + other = RDoc::Markup::HardBreak.new + + assert_equal @hb, other + + refute_equal @hb, Object.new + end + +end + diff --git a/test/rdoc/test_rdoc_markup_heading.rb b/test/rdoc/test_rdoc_markup_heading.rb new file mode 100644 index 0000000000..eef051a64e --- /dev/null +++ b/test/rdoc/test_rdoc_markup_heading.rb @@ -0,0 +1,20 @@ +require 'rdoc/test_case' + +class TestRDocMarkupHeading < RDoc::TestCase + + def setup + super + + @h = RDoc::Markup::Heading.new 1, 'Hello *Friend*!' + end + + def test_aref + assert_equal 'label-Hello+Friend%21', @h.aref + end + + def test_plain_html + assert_equal 'Hello Friend!', @h.plain_html + end + +end + diff --git a/test/rdoc/test_rdoc_markup_include.rb b/test/rdoc/test_rdoc_markup_include.rb new file mode 100644 index 0000000000..37a5b320e9 --- /dev/null +++ b/test/rdoc/test_rdoc_markup_include.rb @@ -0,0 +1,19 @@ +require 'rdoc/test_case' + +class TestRDocMarkupInclude < RDoc::TestCase + + def setup + super + + @include = @RM::Include.new 'file', [Dir.tmpdir] + end + + def test_equals2 + assert_equal @include, @RM::Include.new('file', [Dir.tmpdir]) + refute_equal @include, @RM::Include.new('file', %w[.]) + refute_equal @include, @RM::Include.new('other', [Dir.tmpdir]) + refute_equal @include, Object.new + end + +end + diff --git a/test/rdoc/test_rdoc_markup_indented_paragraph.rb b/test/rdoc/test_rdoc_markup_indented_paragraph.rb index e3e2b630e1..d8dd795e5b 100644 --- a/test/rdoc/test_rdoc_markup_indented_paragraph.rb +++ b/test/rdoc/test_rdoc_markup_indented_paragraph.rb @@ -1,11 +1,10 @@ -require 'pp' -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/markup' +require 'rdoc/test_case' -class TestRDocMarkupIndentedParagraph < MiniTest::Unit::TestCase +class TestRDocMarkupIndentedParagraph < RDoc::TestCase def setup + super + @IP = RDoc::Markup::IndentedParagraph end @@ -36,5 +35,19 @@ class TestRDocMarkupIndentedParagraph < MiniTest::Unit::TestCase refute_equal one, two end + def test_text + paragraph = @IP.new(2, 'hello', ' world') + + assert_equal 'hello world', paragraph.text + end + + def test_text_break + paragraph = @IP.new(2, 'hello', hard_break, 'world') + + assert_equal 'helloworld', paragraph.text + + assert_equal "hello\n world", paragraph.text("\n") + end + end diff --git a/test/rdoc/test_rdoc_markup_paragraph.rb b/test/rdoc/test_rdoc_markup_paragraph.rb index 6ae1ad9a84..8de1c3cff5 100644 --- a/test/rdoc/test_rdoc_markup_paragraph.rb +++ b/test/rdoc/test_rdoc_markup_paragraph.rb @@ -1,9 +1,6 @@ -require 'pp' -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/markup' +require 'rdoc/test_case' -class TestRDocMarkupParagraph < MiniTest::Unit::TestCase +class TestRDocMarkupParagraph < RDoc::TestCase def test_accept visitor = Object.new @@ -14,7 +11,21 @@ class TestRDocMarkupParagraph < MiniTest::Unit::TestCase paragraph.accept visitor - assert_equal paragraph, visitor.obj + assert_same paragraph, visitor.obj + end + + def test_text + paragraph = para('hello', ' world') + + assert_equal 'hello world', paragraph.text + end + + def test_text_break + paragraph = para('hello', hard_break, 'world') + + assert_equal 'helloworld', paragraph.text + + assert_equal "hello\nworld", paragraph.text("\n") end end diff --git a/test/rdoc/test_rdoc_markup_parser.rb b/test/rdoc/test_rdoc_markup_parser.rb index e214c4defc..45f911acd1 100644 --- a/test/rdoc/test_rdoc_markup_parser.rb +++ b/test/rdoc/test_rdoc_markup_parser.rb @@ -1,14 +1,12 @@ # coding: utf-8 -require 'pp' -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/markup' +require 'rdoc/test_case' -class TestRDocMarkupParser < MiniTest::Unit::TestCase +class TestRDocMarkupParser < RDoc::TestCase def setup - @RM = RDoc::Markup + super + @RMP = @RM::Parser end @@ -30,6 +28,19 @@ class TestRDocMarkupParser < MiniTest::Unit::TestCase assert_equal @RM::Heading.new(3, 'heading three'), parser.build_heading(3) end + def test_char_pos + parser = @RMP.new + s = parser.setup_scanner 'cät' + + s.scan(/\S+/) + + if Object.const_defined? :Encoding then + assert_equal 3, parser.char_pos(s.pos) + else + assert_equal 4, parser.char_pos(s.pos) + end + end + def test_get parser = util_parser @@ -148,13 +159,11 @@ the time STR expected = [ - @RM::List.new(:BULLET, *[ - @RM::ListItem.new(nil, - @RM::Paragraph.new('l1', 'l1+')), - @RM::ListItem.new(nil, - @RM::Paragraph.new('l2')), - ]), - ] + list(:BULLET, + item(nil, + para('l1 ', 'l1+')), + item(nil, + para('l2')))] assert_equal expected, @RMP.parse(str).parts end @@ -191,16 +200,16 @@ the time STR expected = [ - @RM::List.new(:BULLET, *[ - @RM::ListItem.new(nil, - @RM::Paragraph.new('l1'), - @RM::List.new(:BULLET, *[ - @RM::ListItem.new(nil, - @RM::Paragraph.new('l1.1', 'text'), - @RM::Verbatim.new("code\n", " code\n"), - @RM::Paragraph.new('text'))])), - @RM::ListItem.new(nil, - @RM::Paragraph.new('l2'))])] + list(:BULLET, + item(nil, + para('l1'), + list(:BULLET, + item(nil, + para('l1.1 ', 'text'), + verb("code\n", " code\n"), + para('text')))), + item(nil, + para('l2')))] assert_equal expected, @RMP.parse(str).parts end @@ -326,11 +335,11 @@ the time STR expected = [ - @RM::List.new(:LABEL, *[ - @RM::ListItem.new('one', - @RM::Paragraph.new('item one')), - @RM::ListItem.new('two', - @RM::Paragraph.new('item two'))])] + list(:LABEL, + item(%w[one], + para('item one')), + item(%w[two], + para('item two')))] assert_equal expected, @RMP.parse(str).parts end @@ -343,19 +352,33 @@ the time STR expected = [ - @RM::List.new(:LABEL, *[ - @RM::ListItem.new('cat', - @RM::Paragraph.new('l1'), - @RM::List.new(:BULLET, *[ - @RM::ListItem.new(nil, - @RM::Paragraph.new('l1.1'))])), - @RM::ListItem.new('dog', - @RM::Paragraph.new('l2'))])] + list(:LABEL, + item(%w[cat], + para('l1'), + list(:BULLET, + item(nil, + para('l1.1')))), + item(%w[dog], + para('l2')))] + + assert_equal expected, @RMP.parse(str).parts + end + + def test_parse_label_multi_label + str = <<-STR +[one] +[two] some description + STR + + expected = [ + list(:LABEL, + item(%w[one two], + para('some description')))] assert_equal expected, @RMP.parse(str).parts end - def test_parse_label_multiline + def test_parse_label_multi_line str = <<-STR [cat] l1 continuation @@ -363,11 +386,11 @@ the time STR expected = [ - @RM::List.new(:LABEL, *[ - @RM::ListItem.new('cat', - @RM::Paragraph.new('l1', 'continuation')), - @RM::ListItem.new('dog', - @RM::Paragraph.new('l2'))])] + list(:LABEL, + item(%w[cat], + para('l1 ', 'continuation')), + item(%w[dog], + para('l2')))] assert_equal expected, @RMP.parse(str).parts end @@ -381,12 +404,11 @@ the time STR expected = [ - @RM::List.new(:LABEL, *[ - @RM::ListItem.new('one', - @RM::Paragraph.new('item one')), - @RM::ListItem.new('two', - @RM::Paragraph.new('item two')), - ])] + list(:LABEL, + item(%w[one], + para('item one')), + item(%w[two], + para('item two')))] assert_equal expected, @RMP.parse(str).parts end @@ -443,6 +465,17 @@ a. 新しい機能 assert_equal expected, @RMP.parse(str).parts end + def test_parse_line_break + str = "now is\nthe time \nfor all" + + expected = [ + para('now is ', 'the time'), + blank_line, + para('for all')] + + assert_equal expected, @RMP.parse(str).parts + end + def test_parse_list_list_1 str = <<-STR 10. para 1 @@ -456,16 +489,16 @@ a. 新しい機能 STR expected = [ - @RM::List.new(:NUMBER, *[ - @RM::ListItem.new(nil, *[ - @RM::Paragraph.new('para 1'), - @RM::BlankLine.new, - @RM::List.new(:LABEL, *[ - @RM::ListItem.new('label 1', *[ - @RM::Paragraph.new('para 1.1'), - @RM::BlankLine.new, - @RM::Verbatim.new("code\n"), - @RM::Paragraph.new('para 1.2')])])])])] + list(:NUMBER, + item(nil, + para('para 1'), + blank_line, + list(:LABEL, + item(%w[label\ 1], + para('para 1.1'), + blank_line, + verb("code\n"), + para('para 1.2')))))] assert_equal expected, @RMP.parse(str).parts end @@ -479,15 +512,15 @@ a. 新しい機能 STR expected = [ - @RM::List.new(:NUMBER, *[ - @RM::ListItem.new(nil, *[ - @RM::Paragraph.new('para'), - @RM::BlankLine.new, - @RM::List.new(:NOTE, *[ - @RM::ListItem.new('label 1', - @RM::Paragraph.new('text 1')), - @RM::ListItem.new('label 2', - @RM::Paragraph.new('text 2'))])])])] + list(:NUMBER, + item(nil, + para('para'), + blank_line, + list(:NOTE, + item(%w[label\ 1], + para('text 1')), + item(%w[label\ 2], + para('text 2')))))] assert_equal expected, @RMP.parse(str).parts end @@ -546,11 +579,11 @@ two:: item two STR expected = [ - @RM::List.new(:NOTE, *[ - @RM::ListItem.new('one', - @RM::Paragraph.new('item one')), - @RM::ListItem.new('two', - @RM::Paragraph.new('item two'))])] + list(:NOTE, + item(%w[one], + para('item one')), + item(%w[two], + para('item two')))] assert_equal expected, @RMP.parse(str).parts end @@ -562,11 +595,9 @@ two:: STR expected = [ - @RM::List.new(:NOTE, *[ - @RM::ListItem.new('one', - @RM::BlankLine.new), - @RM::ListItem.new('two', - @RM::BlankLine.new)])] + list(:NOTE, + item(%w[one two], + blank_line))] assert_equal expected, @RMP.parse(str).parts end @@ -577,11 +608,11 @@ one:: two:: STR expected = [ - @RM::List.new(:NOTE, *[ - @RM::ListItem.new('one', - @RM::List.new(:NOTE, *[ - @RM::ListItem.new('two', - @RM::BlankLine.new)]))])] + list(:NOTE, + item(%w[one], + list(:NOTE, + item(%w[two], + blank_line))))] assert_equal expected, @RMP.parse(str).parts end @@ -594,14 +625,14 @@ one:: two:: STR expected = [ - @RM::List.new(:NUMBER, *[ - @RM::ListItem.new(nil, - @RM::Paragraph.new('l1'), - @RM::List.new(:BULLET, *[ - @RM::ListItem.new(nil, - @RM::Paragraph.new('l1.1'))])), - @RM::ListItem.new(nil, - @RM::Paragraph.new('l2'))])] + list(:NUMBER, + item(nil, + para('l1'), + list(:BULLET, + item(nil, + para('l1.1')))), + item(nil, + para('l2')))] assert_equal expected, @RMP.parse(str).parts end @@ -623,7 +654,7 @@ for all good men def test_parse_paragraph_multiline str = "now is the time\nfor all good men" - expected = @RM::Paragraph.new 'now is the time for all good men' + expected = @RM::Paragraph.new 'now is the time ', 'for all good men' assert_equal [expected], @RMP.parse(str).parts end @@ -1185,6 +1216,38 @@ the time assert_equal expected, @RMP.tokenize(str) end + def test_tokenize_label_newline + str = <<-STR +[cat] + l1 + STR + + expected = [ + [:LABEL, 'cat', 0, 0], + [:NEWLINE, "\n", 5, 0], + [:TEXT, 'l1', 2, 1], + [:NEWLINE, "\n", 4, 1], + ] + + assert_equal expected, @RMP.tokenize(str) + end + + def test_tokenize_label_newline_windows + str = <<-STR +[cat]\r + l1\r + STR + + expected = [ + [:LABEL, 'cat', 0, 0], + [:NEWLINE, "\n", 6, 0], + [:TEXT, 'l1', 2, 1], + [:NEWLINE, "\n", 5, 1], + ] + + assert_equal expected, @RMP.tokenize(str) + end + def test_tokenize_lalpha str = <<-STR a. l1 @@ -1203,6 +1266,53 @@ b. l1.1 assert_equal expected, @RMP.tokenize(str) end + def test_tokenize_line_break + str = "now is\nthe time \nfor all\n" + + expected = [ + [:TEXT, 'now is', 0, 0], + [:NEWLINE, "\n", 6, 0], + [:TEXT, 'the time', 0, 1], + [:BREAK, " ", 8, 1], + [:NEWLINE, "\n", 10, 1], + [:TEXT, 'for all', 0, 2], + [:NEWLINE, "\n", 7, 2], + ] + + assert_equal expected, @RMP.tokenize(str) + end + + def test_tokenize_line_break_long + str = "now is\nthe time \nfor all\n" + + expected = [ + [:TEXT, 'now is', 0, 0], + [:NEWLINE, "\n", 6, 0], + [:TEXT, 'the time ', 0, 1], + [:BREAK, ' ', 9, 1], + [:NEWLINE, "\n", 11, 1], + [:TEXT, 'for all', 0, 2], + [:NEWLINE, "\n", 7, 2], + ] + + assert_equal expected, @RMP.tokenize(str) + end + + def test_tokenize_line_break_no_short + str = "now is\nthe time \nfor all\n" + + expected = [ + [:TEXT, 'now is', 0, 0], + [:NEWLINE, "\n", 6, 0], + [:TEXT, 'the time ', 0, 1], + [:NEWLINE, "\n", 9, 1], + [:TEXT, 'for all', 0, 2], + [:NEWLINE, "\n", 7, 2], + ] + + assert_equal expected, @RMP.tokenize(str) + end + def test_tokenize_note str = <<-STR cat:: l1 @@ -1237,6 +1347,64 @@ dog:: assert_equal expected, @RMP.tokenize(str) end + def test_tokenize_note_newline + str = <<-STR +cat:: + l1 + STR + + expected = [ + [:NOTE, 'cat', 0, 0], + [:NEWLINE, "\n", 5, 0], + [:TEXT, 'l1', 2, 1], + [:NEWLINE, "\n", 4, 1], + ] + + assert_equal expected, @RMP.tokenize(str) + end + + def test_tokenize_note_utf_8 + skip 'Encoding not implemented' unless Object.const_defined? :Encoding + + str = <<-STR +cät:: l1a + l1b +døg:: l2a + l2b + STR + + expected = [ + [:NOTE, 'cät', 0, 0], + [:TEXT, 'l1a', 6, 0], + [:NEWLINE, "\n", 9, 0], + [:TEXT, 'l1b', 6, 1], + [:NEWLINE, "\n", 9, 1], + [:NOTE, 'døg', 0, 2], + [:TEXT, 'l2a', 6, 2], + [:NEWLINE, "\n", 9, 2], + [:TEXT, 'l2b', 6, 3], + [:NEWLINE, "\n", 9, 3], + ] + + assert_equal expected, @RMP.tokenize(str) + end + + def test_tokenize_note_newline_windows + str = <<-STR +cat::\r + l1\r + STR + + expected = [ + [:NOTE, 'cat', 0, 0], + [:NEWLINE, "\n", 6, 0], + [:TEXT, 'l1', 2, 1], + [:NEWLINE, "\n", 5, 1], + ] + + assert_equal expected, @RMP.tokenize(str) + end + def test_tokenize_note_not str = <<-STR Cat::Dog @@ -1363,6 +1531,24 @@ for all assert_equal expected, @RMP.tokenize(str) end + def test_tokenize_rule_windows + str = <<-STR +---\r + +--- blah ---\r + STR + + expected = [ + [:RULE, 1, 0, 0], + [:NEWLINE, "\n", 4, 0], + [:NEWLINE, "\n", 0, 1], + [:TEXT, "--- blah ---", 0, 2], + [:NEWLINE, "\n", 13, 2], + ] + + assert_equal expected, @RMP.tokenize(str) + end + def test_tokenize_ualpha str = <<-STR A. l1 @@ -1438,6 +1624,19 @@ Example heading: assert_equal expected, @RMP.tokenize(str) end + def test_token_pos + parser = @RMP.new + s = parser.setup_scanner 'cät' + + s.scan(/\S+/) + + if Object.const_defined? :Encoding then + assert_equal [3, 0], parser.token_pos(s.pos) + else + assert_equal [4, 0], parser.token_pos(s.pos) + end + end + # HACK move to Verbatim test case def test_verbatim_normalize v = @RM::Verbatim.new "foo\n", "\n", "\n", "bar\n" diff --git a/test/rdoc/test_rdoc_markup_pre_process.rb b/test/rdoc/test_rdoc_markup_pre_process.rb index 34867c8c6b..3a991a6397 100644 --- a/test/rdoc/test_rdoc_markup_pre_process.rb +++ b/test/rdoc/test_rdoc_markup_pre_process.rb @@ -1,16 +1,11 @@ # coding: utf-8 -require 'tempfile' -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/markup/pre_process' -require 'rdoc/code_objects' -require 'rdoc/options' +require 'rdoc/test_case' -class TestRDocMarkupPreProcess < MiniTest::Unit::TestCase +class TestRDocMarkupPreProcess < RDoc::TestCase def setup - RDoc::Markup::PreProcess.registered.clear + super @tempfile = Tempfile.new 'test_rdoc_markup_pre_process' @file_name = File.basename @tempfile.path @@ -20,11 +15,23 @@ class TestRDocMarkupPreProcess < MiniTest::Unit::TestCase end def teardown - RDoc::Markup::PreProcess.registered.clear + super @tempfile.close end + def test_class_register + RDoc::Markup::PreProcess.register 'for_test' do raise 'fail' end + + assert_equal %w[for_test], RDoc::Markup::PreProcess.registered.keys + end + + def test_class_post_process + RDoc::Markup::PreProcess.post_process do end + + assert_equal 1, RDoc::Markup::PreProcess.post_processors.length + end + def test_include_file @tempfile.write <<-INCLUDE # -*- mode: rdoc; coding: utf-8; fill-column: 74; -*- @@ -73,6 +80,50 @@ contents of a string. assert_equal "#\n", text end + def test_handle_comment + text = "# :main: M\n" + c = comment text + + out = @pp.handle c + + assert_same out, text + assert_equal "#\n", text + end + + def test_handle_markup + c = comment ':markup: rd' + + @pp.handle c + + assert_equal 'rd', c.format + end + + def test_handle_markup_empty + c = comment ':markup:' + + @pp.handle c + + assert_equal 'rdoc', c.format + end + + def test_handle_post_process + cd = RDoc::CodeObject.new + + RDoc::Markup::PreProcess.post_process do |text, code_object| + code_object.metadata[:stuff] = text + + :junk + end + + text = "# a b c\n" + + out = @pp.handle text, cd + + assert_same out, text + assert_equal "# a b c\n", text + assert_equal "# a b c\n", cd.metadata[:stuff] + end + def test_handle_unregistered text = "# :x: y\n" out = @pp.handle text diff --git a/test/rdoc/test_rdoc_markup_raw.rb b/test/rdoc/test_rdoc_markup_raw.rb index 4e57b7df39..16cc60e3a8 100644 --- a/test/rdoc/test_rdoc_markup_raw.rb +++ b/test/rdoc/test_rdoc_markup_raw.rb @@ -1,12 +1,10 @@ -require 'pp' -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/markup' +require 'rdoc/test_case' -class TestRDocMarkupRaw < MiniTest::Unit::TestCase +class TestRDocMarkupRaw < RDoc::TestCase def setup - @RM = RDoc::Markup + super + @p = @RM::Raw.new end @@ -23,5 +21,9 @@ class TestRDocMarkupRaw < MiniTest::Unit::TestCase assert_equal @RM::Raw.new('hi', 'there'), @p end + def test_pretty_print + assert_equal '[raw: ]', mu_pp(@p) + end + end diff --git a/test/rdoc/test_rdoc_markup_to_ansi.rb b/test/rdoc/test_rdoc_markup_to_ansi.rb index f60d1999c2..5afaf94350 100644 --- a/test/rdoc/test_rdoc_markup_to_ansi.rb +++ b/test/rdoc/test_rdoc_markup_to_ansi.rb @@ -1,7 +1,4 @@ -require 'rubygems' -require 'rdoc/markup/text_formatter_test_case' -require 'rdoc/markup/to_ansi' -require 'minitest/autorun' +require 'rdoc/test_case' class TestRDocMarkupToAnsi < RDoc::Markup::TextFormatterTestCase @@ -18,6 +15,10 @@ class TestRDocMarkupToAnsi < RDoc::Markup::TextFormatterTestCase assert_equal "\e[0m\n", @to.res.join end + def accept_block_quote + assert_equal "\e[0m> quote\n", @to.res.join + end + def accept_document assert_equal "\e[0mhello\n", @to.res.join end @@ -67,7 +68,7 @@ class TestRDocMarkupToAnsi < RDoc::Markup::TextFormatterTestCase end def accept_list_item_end_label - assert_equal "\e[0m", @to.res.join + assert_equal "\e[0mcat:\n", @to.res.join assert_equal 0, @to.indent, 'indent' end @@ -77,7 +78,7 @@ class TestRDocMarkupToAnsi < RDoc::Markup::TextFormatterTestCase end def accept_list_item_end_note - assert_equal "\e[0m", @to.res.join + assert_equal "\e[0mcat:\n", @to.res.join assert_equal 0, @to.indent, 'indent' end @@ -245,10 +246,28 @@ class TestRDocMarkupToAnsi < RDoc::Markup::TextFormatterTestCase @to.res.join end + def accept_list_item_start_note_multi_description + assert_equal "\e[0mlabel:\n description one\n\n description two\n\n", + @to.res.join + end + + def accept_list_item_start_note_multi_label + assert_equal "\e[0mone\ntwo:\n two headers\n\n", + @to.res.join + end + def accept_paragraph_b assert_equal "\e[0mreg \e[1mbold words\e[m reg\n", @to.end_accepting end + def accept_paragraph_br + assert_equal "\e[0mone\ntwo\n", @to.end_accepting + end + + def accept_paragraph_break + assert_equal "\e[0mhello\nworld\n", @to.end_accepting + end + def accept_paragraph_i assert_equal "\e[0mreg \e[4mitalic words\e[m reg\n", @to.end_accepting end @@ -328,5 +347,23 @@ words words words words assert_equal expected, @to.end_accepting end + # functional test + def test_convert_list_note + note_list = <<-NOTE_LIST +foo :: +bar :: + hi + NOTE_LIST + + expected = <<-EXPECTED +\e[0mfoo +bar: + hi + + EXPECTED + + assert_equal expected, @to.convert(note_list) + end + end diff --git a/test/rdoc/test_rdoc_markup_to_bs.rb b/test/rdoc/test_rdoc_markup_to_bs.rb index 35a9266b5d..f2e6352b69 100644 --- a/test/rdoc/test_rdoc_markup_to_bs.rb +++ b/test/rdoc/test_rdoc_markup_to_bs.rb @@ -1,7 +1,4 @@ -require 'rubygems' -require 'rdoc/markup/text_formatter_test_case' -require 'rdoc/markup/to_bs' -require 'minitest/autorun' +require 'rdoc/test_case' class TestRDocMarkupToBs < RDoc::Markup::TextFormatterTestCase @@ -18,6 +15,10 @@ class TestRDocMarkupToBs < RDoc::Markup::TextFormatterTestCase assert_equal "\n", @to.res.join end + def accept_block_quote + assert_equal "> quote\n", @to.res.join + end + def accept_document assert_equal "hello\n", @to.res.join end @@ -68,7 +69,7 @@ class TestRDocMarkupToBs < RDoc::Markup::TextFormatterTestCase end def accept_list_item_end_label - assert_equal "\n", @to.res.join + assert_equal "cat:\n", @to.res.join assert_equal 0, @to.indent, 'indent' end @@ -78,7 +79,7 @@ class TestRDocMarkupToBs < RDoc::Markup::TextFormatterTestCase end def accept_list_item_end_note - assert_equal "\n", @to.res.join + assert_equal "cat:\n", @to.res.join assert_equal 0, @to.indent, 'indent' end @@ -252,12 +253,32 @@ class TestRDocMarkupToBs < RDoc::Markup::TextFormatterTestCase assert_equal "teletype:\n teletype description\n\n", @to.res.join end + def accept_list_item_start_note_multi_description + assert_equal "label:\n description one\n\n description two\n\n", + @to.res.join + end + + def accept_list_item_start_note_multi_label + assert_equal "one\ntwo:\n two headers\n\n", @to.res.join + end + def accept_paragraph_b skip "No String#chars, upgrade your ruby" unless ''.respond_to? :chars assert_equal "reg b\bbo\bol\bld\bd \b w\bwo\bor\brd\bds\bs reg\n", @to.end_accepting end + def accept_paragraph_br + skip "No String#chars, upgrade your ruby" unless ''.respond_to? :chars + assert_equal "one\ntwo\n", @to.end_accepting + end + + def accept_paragraph_break + skip "No String#chars, upgrade your ruby" unless ''.respond_to? :chars + assert_equal "hello\nworld\n", + @to.end_accepting + end + def accept_paragraph_i skip "No String#chars, upgrade your ruby" unless ''.respond_to? :chars assert_equal "reg _\bi_\bt_\ba_\bl_\bi_\bc_\b _\bw_\bo_\br_\bd_\bs reg\n", diff --git a/test/rdoc/test_rdoc_markup_to_html.rb b/test/rdoc/test_rdoc_markup_to_html.rb index 2cb16e88ae..cb444a531f 100644 --- a/test/rdoc/test_rdoc_markup_to_html.rb +++ b/test/rdoc/test_rdoc_markup_to_html.rb @@ -1,7 +1,4 @@ -require 'rubygems' -require 'rdoc/markup/formatter_test_case' -require 'rdoc/markup/to_html' -require 'minitest/autorun' +require 'rdoc/test_case' class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase @@ -10,7 +7,7 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase def setup super - @to = RDoc::Markup::ToHtml.new + @to = RDoc::Markup::ToHtml.new @options end def test_class_gen_relative_url @@ -30,36 +27,41 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase assert_empty @to.res.join end + def accept_block_quote + assert_equal "\n
\n

quote

\n
\n", @to.res.join + end + def accept_document assert_equal "\n

hello

\n", @to.res.join end def accept_heading - assert_equal "\n
Hello
\n", @to.res.join + assert_equal "\n
Hello
\n", @to.res.join end def accept_heading_1 - assert_equal "\n

Hello

\n", @to.res.join + assert_equal "\n

Hello

\n", @to.res.join end def accept_heading_2 - assert_equal "\n

Hello

\n", @to.res.join + assert_equal "\n

Hello

\n", @to.res.join end def accept_heading_3 - assert_equal "\n

Hello

\n", @to.res.join + assert_equal "\n

Hello

\n", @to.res.join end def accept_heading_4 - assert_equal "\n

Hello

\n", @to.res.join + assert_equal "\n

Hello

\n", @to.res.join end def accept_heading_b - assert_equal "\n

Hello

\n", @to.res.join + assert_equal "\n

Hello

\n", + @to.res.join end def accept_heading_suppressed_crossref - assert_equal "\n

Hello

\n", @to.res.join + assert_equal "\n

Hello

\n", @to.res.join end def accept_list_end_bullet @@ -73,14 +75,14 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase assert_equal [], @to.list assert_equal [], @to.in_list_entry - assert_equal "
\n", @to.res.join + assert_equal "
\n", @to.res.join end def accept_list_end_lalpha assert_equal [], @to.list assert_equal [], @to.in_list_entry - assert_equal "
    \n", @to.res.join + assert_equal "
      \n", @to.res.join end def accept_list_end_number @@ -94,14 +96,14 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase assert_equal [], @to.list assert_equal [], @to.in_list_entry - assert_equal "
      \n", @to.res.join + assert_equal "
      \n", @to.res.join end def accept_list_end_ualpha assert_equal [], @to.list assert_equal [], @to.in_list_entry - assert_equal "
        \n", @to.res.join + assert_equal "
          \n", @to.res.join end def accept_list_item_end_bullet @@ -117,7 +119,7 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase end def accept_list_item_end_note - assert_equal %w[], @to.in_list_entry + assert_equal %w[], @to.in_list_entry end def accept_list_item_end_number @@ -133,24 +135,49 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase end def accept_list_item_start_label - assert_equal "
          cat
          \n
          ", @to.res.join + assert_equal "
          cat\n
          ", @to.res.join end def accept_list_item_start_lalpha - assert_equal "
          1. ", @to.res.join + assert_equal "
            1. ", @to.res.join end def accept_list_item_start_note - assert_equal "\n

              cat

              ", + assert_equal "
              cat\n
              ", @to.res.join end def accept_list_item_start_note_2 expected = <<-EXPECTED - -

              teletype

              +
              teletype +

              teletype description

              -
              +
              + EXPECTED + + assert_equal expected, @to.res.join + end + + def accept_list_item_start_note_multi_description + expected = <<-EXPECTED +
              label +
              +

              description one

              +
              +

              description two

              +
              + EXPECTED + + assert_equal expected, @to.res.join + end + + def accept_list_item_start_note_multi_label + expected = <<-EXPECTED +
              one +
              two +
              +

              two headers

              +
              EXPECTED assert_equal expected, @to.res.join @@ -161,7 +188,7 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase end def accept_list_item_start_ualpha - assert_equal "
              1. ", @to.res.join + assert_equal "
                1. ", @to.res.join end def accept_list_start_bullet @@ -175,21 +202,21 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase assert_equal [:LABEL], @to.list assert_equal [false], @to.in_list_entry - assert_equal '
                  ', @to.res.join + assert_equal '
                  ', @to.res.join end def accept_list_start_lalpha assert_equal [:LALPHA], @to.list assert_equal [false], @to.in_list_entry - assert_equal "
                    ", @to.res.join + assert_equal "
                      ", @to.res.join end def accept_list_start_note assert_equal [:NOTE], @to.list assert_equal [false], @to.in_list_entry - assert_equal "", @to.res.join + assert_equal "
                      ", @to.res.join end def accept_list_start_number @@ -203,7 +230,7 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase assert_equal [:UALPHA], @to.list assert_equal [false], @to.in_list_entry - assert_equal "
                        ", @to.res.join + assert_equal "
                          ", @to.res.join end def accept_paragraph @@ -211,7 +238,15 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase end def accept_paragraph_b - assert_equal "\n

                          reg bold words reg

                          \n", @to.res.join + assert_equal "\n

                          reg bold words reg

                          \n", @to.res.join + end + + def accept_paragraph_br + assert_equal "\n

                          one
                          two

                          \n", @to.res.join + end + + def accept_paragraph_break + assert_equal "\n

                          hello
                          \nworld

                          \n", @to.res.join end def accept_paragraph_i @@ -219,11 +254,11 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase end def accept_paragraph_plus - assert_equal "\n

                          reg teletype reg

                          \n", @to.res.join + assert_equal "\n

                          reg teletype reg

                          \n", @to.res.join end def accept_paragraph_star - assert_equal "\n

                          reg bold reg

                          \n", @to.res.join + assert_equal "\n

                          reg bold reg

                          \n", @to.res.join end def accept_paragraph_underscore @@ -297,20 +332,155 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase assert_equal expected, @to.end_accepting end + def test_accept_heading_7 + @to.start_accepting + + @to.accept_heading @RM::Heading.new(7, 'Hello') + + assert_equal "\n
                          Hello
                          \n", @to.res.join + end + + def test_accept_heading_aref_class + @to.code_object = RDoc::NormalClass.new 'Foo' + @to.start_accepting + + @to.accept_heading @RM::Heading.new(1, 'Hello') + + assert_equal "\n

                          Hello

                          \n", + @to.res.join + end + + def test_accept_heading_aref_method + @to.code_object = RDoc::AnyMethod.new nil, 'foo' + @to.start_accepting + + @to.accept_heading @RM::Heading.new(1, 'Hello') + + assert_equal "\n

                          Hello

                          \n", + @to.res.join + end + + def test_accept_verbatim_parseable + verb = @RM::Verbatim.new("class C\n", "end\n") + + @to.start_accepting + @to.accept_verbatim verb + + expected = <<-EXPECTED + +
                          class C
                          +end
                          +
                          + EXPECTED + + assert_equal expected, @to.res.join + end + + def test_accept_verbatim_parseable_error + verb = @RM::Verbatim.new("a % 09 # => blah\n") + + @to.start_accepting + @to.accept_verbatim verb + + inner = CGI.escapeHTML "a % 09 # => blah" + + expected = <<-EXPECTED + +
                          #{inner}
                          +
                          + EXPECTED + + assert_equal expected, @to.res.join + end + + def test_accept_verbatim_ruby + verb = @RM::Verbatim.new("1 + 1\n") + verb.format = :ruby + + @to.start_accepting + @to.accept_verbatim verb + + expected = <<-EXPECTED + +
                          1 + 1
                          +
                          + EXPECTED + + assert_equal expected, @to.res.join + end + def test_convert_string assert_equal '<>', @to.convert_string('<>') end + def test_convert_HYPERLINK_irc + result = @to.convert 'irc://irc.freenode.net/#ruby-lang' + + assert_equal "\n

                          irc.freenode.net/#ruby-lang

                          \n", result + end + + def test_convert_RDOCLINK_label_label + result = @to.convert 'rdoc-label:label-One' + + assert_equal "\n

                          One

                          \n", result + end + + def test_convert_RDOCLINK_label_foottext + result = @to.convert 'rdoc-label:foottext-1' + + assert_equal "\n

                          *1

                          \n", result + end + + def test_convert_RDOCLINK_label_footmark + result = @to.convert 'rdoc-label:footmark-1' + + assert_equal "\n

                          ^1

                          \n", result + end + + def test_convert_RDOCLINK_ref + result = @to.convert 'rdoc-ref:C' + + assert_equal "\n

                          C

                          \n", result + end + + def test_convert_TIDYLINK_footnote + result = @to.convert 'text{*1}[rdoc-label:foottext-1:footmark-1]' + + assert_equal "\n

                          text*1

                          \n", result + end + + def test_convert_TIDYLINK_rdoc_label + result = @to.convert '{foo}[rdoc-label:foottext-1]' + + assert_equal "\n

                          foo

                          \n", result + end + + def test_convert_TIDYLINK_irc + result = @to.convert '{ruby-lang}[irc://irc.freenode.net/#ruby-lang]' + + assert_equal "\n

                          ruby-lang

                          \n", result + end + def test_gen_url assert_equal 'example', @to.gen_url('link:example', 'example') end - def test_gem_url_image_url + def test_gen_url_rdoc_label + assert_equal 'example', + @to.gen_url('rdoc-label:foottext-1', 'example') + end + + def test_gen_url_rdoc_label_id + assert_equal 'example', + @to.gen_url('rdoc-label:foottext-1:footmark-1', 'example') + end + + def test_gen_url_image_url assert_equal '', @to.gen_url('http://example.com/image.png', 'ignored') end - def test_gem_url_ssl_image_url + def test_gen_url_ssl_image_url assert_equal '', @to.gen_url('https://example.com/image.png', 'ignored') end @@ -322,6 +492,14 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase assert_equal 'README.txt', link end + def test_handle_special_HYPERLINK_irc + special = RDoc::Markup::Special.new 0, 'irc://irc.freenode.net/#ruby-lang' + + link = @to.handle_special_HYPERLINK special + + assert_equal 'irc.freenode.net/#ruby-lang', link + end + def test_list_verbatim_2 str = "* one\n verb1\n verb2\n* two\n" @@ -339,8 +517,21 @@ verb2 assert_equal expected, @m.convert(str, @to) end + def test_parseable_eh + assert @to.parseable?('def x() end'), 'def' + assert @to.parseable?('class C end'), 'class' + assert @to.parseable?('module M end'), 'module' + assert @to.parseable?('a # => blah'), '=>' + assert @to.parseable?('x { |y| ... }'), '{ |x|' + assert @to.parseable?('x do |y| ... end'), 'do |x|' + refute @to.parseable?('* 1'), '* 1' + refute @to.parseable?('# only a comment'), '# only a comment' + refute @to.parseable?('<% require "foo" %>'), 'ERB' + refute @to.parseable?('class="foo"'), 'HTML class' + end + def test_to_html - assert_equal "\n

                          --

                          \n", util_format("--") + assert_equal "\n

                          --

                          \n", util_format("--") end def util_format text diff --git a/test/rdoc/test_rdoc_markup_to_html_crossref.rb b/test/rdoc/test_rdoc_markup_to_html_crossref.rb index 4f122512ac..27a60120f4 100644 --- a/test/rdoc/test_rdoc_markup_to_html_crossref.rb +++ b/test/rdoc/test_rdoc_markup_to_html_crossref.rb @@ -1,8 +1,3 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/rdoc' -require 'rdoc/code_objects' -require 'rdoc/markup/to_html_crossref' require File.expand_path '../xref_test_case', __FILE__ class TestRDocMarkupToHtmlCrossref < XrefTestCase @@ -10,25 +5,93 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase def setup super - @to = RDoc::Markup::ToHtmlCrossref.new 'index.html', @c1, true + @options.hyperlink_all = true + + @to = RDoc::Markup::ToHtmlCrossref.new @options, 'index.html', @c1 end def test_convert_CROSSREF result = @to.convert 'C1' - assert_equal "\n

                          C1

                          \n", result + assert_equal para("C1"), result + end + + def test_convert_CROSSREF_label + result = @to.convert 'C1@foo' + assert_equal para("foo at C1"), result + + result = @to.convert 'C1#m@foo' + assert_equal para("foo at C1#m"), + result end - def test_convert_HYPERLINK_rdoc_ref + def test_convert_CROSSREF_label_period + result = @to.convert 'C1@foo.' + assert_equal para("foo at C1."), result + end + + def test_convert_CROSSREF_label_space + result = @to.convert 'C1@foo+bar' + assert_equal para("foo bar at C1"), + result + end + + def test_convert_RDOCLINK_rdoc_ref result = @to.convert 'rdoc-ref:C1' - assert_equal "\n

                          C1

                          \n", result + assert_equal para("C1"), result + end + + def test_convert_RDOCLINK_rdoc_ref_method + result = @to.convert 'rdoc-ref:C1#m' + + assert_equal para("#m"), result end - def test_convert_TIDYLINK_rdoc_ref - result = @to.convert '{foo}[rdoc-ref:C1]' + def test_convert_RDOCLINK_rdoc_ref_method_label + result = @to.convert 'rdoc-ref:C1#m@foo' + + assert_equal para("foo at C1#m"), + result, 'rdoc-ref:C1#m@foo' + end + + def test_convert_RDOCLINK_rdoc_ref_method_percent + m = @c1.add_method RDoc::AnyMethod.new nil, '%' + m.singleton = false + + result = @to.convert 'rdoc-ref:C1#%' + + assert_equal para("#%"), result + + m.singleton = true + + result = @to.convert 'rdoc-ref:C1::%' + + assert_equal para("::%"), result + end + + def test_convert_RDOCLINK_rdoc_ref_method_percent_label + m = @c1.add_method RDoc::AnyMethod.new nil, '%' + m.singleton = false + + result = @to.convert 'rdoc-ref:C1#%@f' + + assert_equal para("f at C1#%"), + result + + m.singleton = true + + result = @to.convert 'rdoc-ref:C1::%@f' - assert_equal "\n

                          foo

                          \n", result + assert_equal para("f at C1::%"), + result + end + + def test_convert_RDOCLINK_rdoc_ref_label + result = @to.convert 'rdoc-ref:C1@foo' + + assert_equal para("foo at C1"), result, + 'rdoc-ref:C1@foo' end def test_gen_url @@ -43,6 +106,11 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase assert_equal "C2::C3", SPECIAL('C2::C3') end + def test_handle_special_CROSSREF_label + assert_equal "foo at C1#m", + SPECIAL('C1#m@foo') + end + def test_handle_special_CROSSREF_show_hash_false @to.show_hash = false @@ -51,8 +119,10 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase end def test_handle_special_HYPERLINK_rdoc - RDoc::TopLevel.new 'README.txt' - @to = RDoc::Markup::ToHtmlCrossref.new 'C2.html', @c2, true + readme = @store.add_file 'README.txt' + readme.parser = RDoc::Parser::Simple + + @to = RDoc::Markup::ToHtmlCrossref.new @options, 'C2.html', @c2 link = @to.handle_special_HYPERLINK hyper 'C2::C3' @@ -68,8 +138,10 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase end def test_handle_special_TIDYLINK_rdoc - RDoc::TopLevel.new 'README.txt' - @to = RDoc::Markup::ToHtmlCrossref.new 'C2.html', @c2, true + readme = @store.add_file 'README.txt' + readme.parser = RDoc::Parser::Simple + + @to = RDoc::Markup::ToHtmlCrossref.new @options, 'C2.html', @c2 link = @to.handle_special_TIDYLINK tidy 'C2::C3' @@ -79,15 +151,51 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase assert_equal 'tidy', link + link = @to.handle_special_TIDYLINK tidy 'C1#m' + + assert_equal 'tidy', link + link = @to.handle_special_TIDYLINK tidy 'README.txt' assert_equal 'tidy', link end + def test_handle_special_TIDYLINK_label + link = @to.handle_special_TIDYLINK tidy 'C1#m@foo' + + assert_equal "tidy", + link, 'C1#m@foo' + end + + def test_to_html_CROSSREF_email + @options.hyperlink_all = false + + @to = RDoc::Markup::ToHtmlCrossref.new @options, 'index.html', @c1 + + result = @to.to_html 'first.last@example.com' + + assert_equal 'first.last@example.com', result + end + + def test_to_html_CROSSREF_email_hyperlink_all + result = @to.to_html 'first.last@example.com' + + assert_equal 'first.last@example.com', result + end + def test_link assert_equal 'n', @to.link('n', 'n') - assert_equal 'm', @to.link('m', 'm') + assert_equal '::m', @to.link('m', 'm') + end + + def test_link_class_method_full + assert_equal 'Parent.m', + @to.link('Parent::m', 'Parent::m') + end + + def para text + "\n

                          #{text}

                          \n" end def SPECIAL text diff --git a/test/rdoc/test_rdoc_markup_to_html_snippet.rb b/test/rdoc/test_rdoc_markup_to_html_snippet.rb new file mode 100644 index 0000000000..065b2edbc8 --- /dev/null +++ b/test/rdoc/test_rdoc_markup_to_html_snippet.rb @@ -0,0 +1,710 @@ +require 'rdoc/test_case' + +class TestRDocMarkupToHtmlSnippet < RDoc::Markup::FormatterTestCase + + add_visitor_tests + + def setup + super + + @to = RDoc::Markup::ToHtmlSnippet.new @options, 100, 100 + @ellipsis = @to.to_html '...' + end + + def accept_blank_line + assert_empty @to.res.join + end + + def accept_block_quote + assert_equal "\n

                          quote\n

                          \n", @to.res.join + + assert_equal 5, @to.characters + end + + def accept_document + assert_equal "

                          hello\n", @to.res.join + assert_equal 5, @to.characters + end + + def accept_heading + assert_equal "

                          Hello\n", @to.res.join + assert_equal 5, @to.characters + end + + def accept_heading_1 + assert_equal "

                          Hello\n", @to.res.join + assert_equal 5, @to.characters + end + + def accept_heading_2 + assert_equal "

                          Hello\n", @to.res.join + assert_equal 5, @to.characters + end + + def accept_heading_3 + assert_equal "

                          Hello\n", @to.res.join + assert_equal 5, @to.characters + end + + def accept_heading_4 + assert_equal "

                          Hello\n", @to.res.join + assert_equal 5, @to.characters + end + + def accept_heading_b + assert_equal "

                          Hello\n", + @to.res.join + assert_equal 5, @to.characters + end + + def accept_heading_suppressed_crossref + assert_equal "

                          Hello\n", @to.res.join + assert_equal 5, @to.characters + end + + def accept_list_end_bullet + assert_equal [], @to.list + assert_equal [], @to.in_list_entry + + assert_equal "\n", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_end_label + assert_equal [], @to.list + assert_equal [], @to.in_list_entry + + assert_equal "\n", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_end_lalpha + assert_equal [], @to.list + assert_equal [], @to.in_list_entry + + assert_equal "\n", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_end_number + assert_equal [], @to.list + assert_equal [], @to.in_list_entry + + assert_equal "\n", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_end_note + assert_equal [], @to.list + assert_equal [], @to.in_list_entry + + assert_equal "\n", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_end_ualpha + assert_equal [], @to.list + assert_equal [], @to.in_list_entry + + assert_equal "\n", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_item_end_bullet + assert_equal [''], @to.in_list_entry + assert_equal 0, @to.characters + end + + def accept_list_item_end_label + assert_equal [''], @to.in_list_entry + assert_equal 4, @to.characters + end + + def accept_list_item_end_lalpha + assert_equal [''], @to.in_list_entry + assert_equal 0, @to.characters + end + + def accept_list_item_end_note + assert_equal [''], @to.in_list_entry + assert_equal 4, @to.characters + end + + def accept_list_item_end_number + assert_equal [''], @to.in_list_entry + assert_equal 0, @to.characters + end + + def accept_list_item_end_ualpha + assert_equal [''], @to.in_list_entry + assert_equal 0, @to.characters + end + + def accept_list_item_start_bullet + assert_equal "

                          ", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_item_start_label + assert_equal "

                          cat — ", @to.res.join + assert_equal 4, @to.characters + end + + def accept_list_item_start_lalpha + assert_equal "

                          ", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_item_start_note + assert_equal "

                          cat — ", + @to.res.join + assert_equal 4, @to.characters + end + + def accept_list_item_start_note_2 + expected = <<-EXPECTED +

                          teletype — teletype description + + EXPECTED + + assert_equal expected, @to.res.join + assert_equal 29, @to.characters + end + + def accept_list_item_start_note_multi_description + expected = <<-EXPECTED +

                          label — description one +

                          description two + + EXPECTED + + assert_equal expected, @to.res.join + assert_equal 37, @to.characters + end + + def accept_list_item_start_note_multi_label + expected = <<-EXPECTED +

                          one, two — two headers + + EXPECTED + + assert_equal expected, @to.res.join + assert_equal 18, @to.characters + end + + def accept_list_item_start_number + assert_equal "

                          ", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_item_start_ualpha + assert_equal "

                          ", @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_start_bullet + assert_equal [:BULLET], @to.list + assert_equal [''], @to.in_list_entry + + assert_equal '', @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_start_label + assert_equal [:LABEL], @to.list + assert_equal [''], @to.in_list_entry + + assert_equal '', @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_start_lalpha + assert_equal [:LALPHA], @to.list + assert_equal [''], @to.in_list_entry + + assert_equal '', @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_start_note + assert_equal [:NOTE], @to.list + assert_equal [''], @to.in_list_entry + + assert_equal '', @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_start_number + assert_equal [:NUMBER], @to.list + assert_equal [''], @to.in_list_entry + + assert_equal '', @to.res.join + assert_equal 0, @to.characters + end + + def accept_list_start_ualpha + assert_equal [:UALPHA], @to.list + assert_equal [''], @to.in_list_entry + + assert_equal '', @to.res.join + assert_equal 0, @to.characters + end + + def accept_paragraph + assert_equal "

                          hi\n", @to.res.join + + assert_equal 2, @to.characters + end + + def accept_paragraph_b + assert_equal "

                          reg bold words reg\n", @to.res.join + + assert_equal 18, @to.characters + end + + def accept_paragraph_br + assert_equal "

                          one
                          two\n", @to.res.join + + assert_equal 6, @to.characters + end + + def accept_paragraph_break + assert_equal "

                          hello
                          \nworld\n", @to.res.join + + assert_equal 11, @to.characters + end + + def accept_paragraph_i + assert_equal "

                          reg italic words reg\n", @to.res.join + + assert_equal 20, @to.characters + end + + def accept_paragraph_plus + assert_equal "

                          reg teletype reg\n", @to.res.join + + assert_equal 16, @to.characters + end + + def accept_paragraph_star + assert_equal "

                          reg bold reg\n", @to.res.join + + assert_equal 12, @to.characters + end + + def accept_paragraph_underscore + assert_equal "

                          reg italic reg\n", @to.res.join + + assert_equal 14, @to.characters + end + + def accept_raw + assert_equal '', @to.res.join + assert_equal 0, @to.characters + end + + def accept_rule + assert_empty @to.res + assert_equal 0, @to.characters + end + + def accept_verbatim + assert_equal "\n

                          hi\n  world
                          \n", @to.res.join + assert_equal 10, @to.characters + end + + def end_accepting + assert_equal 'hi', @to.res.join + end + + def start_accepting + assert_equal [], @to.res + assert_equal [], @to.in_list_entry + assert_equal [], @to.list + assert_equal 0, @to.characters + end + + def list_nested + expected = <<-EXPECTED +

                          l1 +

                          l1.1 + +

                          l2 + + EXPECTED + + assert_equal expected, @to.res.join + assert_equal 8, @to.characters + end + + def list_verbatim + expected = <<-EXPECTED +

                          list stuff + +

                          * list
                          +  with
                          +
                          +  second
                          +
                          +  1. indented
                          +  2. numbered
                          +
                          +  third
                          +
                          +* second
                          + + EXPECTED + + assert_equal expected, @to.end_accepting + assert_equal 81, @to.characters + end + + def test_accept_heading_7 + @to.start_accepting + + @to.accept_heading @RM::Heading.new(7, 'Hello') + + assert_equal "

                          Hello\n", @to.res.join + assert_equal 5, @to.characters + end + + def test_accept_heading_aref_class + @to.code_object = RDoc::NormalClass.new 'Foo' + @to.start_accepting + + @to.accept_heading @RM::Heading.new(1, 'Hello') + + assert_equal "

                          Hello\n", + @to.res.join + assert_equal 5, @to.characters + end + + def test_accept_heading_aref_method + @to.code_object = RDoc::AnyMethod.new nil, 'foo' + @to.start_accepting + + @to.accept_heading @RM::Heading.new(1, 'Hello') + + assert_equal "

                          Hello\n", + @to.res.join + assert_equal 5, @to.characters + end + + def test_accept_verbatim_ruby + options = RDoc::Options.new + rdoc = RDoc::RDoc.new + rdoc.options = options + RDoc::RDoc.current = rdoc + + verb = @RM::Verbatim.new("class C\n", "end\n") + + @to.start_accepting + @to.accept_verbatim verb + + expected = <<-EXPECTED + +

                          class C
                          +end
                          +
                          + EXPECTED + + assert_equal expected, @to.res.join + assert_equal 11, @to.characters + end + + def test_accept_verbatim_ruby_error + options = RDoc::Options.new + rdoc = RDoc::RDoc.new + rdoc.options = options + RDoc::RDoc.current = rdoc + + verb = @RM::Verbatim.new("a % 09 # => blah\n") + + @to.start_accepting + @to.accept_verbatim verb + + inner = CGI.escapeHTML "a % 09 # => blah" + + expected = <<-EXPECTED + +
                          #{inner}
                          +
                          + EXPECTED + + assert_equal expected, @to.res.join + assert_equal 16, @to.characters + end + + def test_add_paragraph + @to = RDoc::Markup::ToHtmlSnippet.new @options, 0, 3 + assert_throws :done do + @to.add_paragraph + @to.add_paragraph + @to.add_paragraph + end + + assert_equal 3, @to.paragraphs + end + + def test_convert_limit + rdoc = <<-RDOC += Hello + +This is some text, it *will* be cut off after 100 characters and an ellipsis +must follow + +So there you have it + RDOC + + expected = <<-EXPECTED +

                          Hello +

                          This is some text, it will be cut off after 100 characters +and an ellipsis must follow +

                          So there you #{@ellipsis} + EXPECTED + + actual = @to.convert rdoc + + assert_equal expected, actual + assert_equal 111, @to.characters, 'snippet character length' + end + + def test_convert_limit_2 + rdoc = <<-RDOC +Outputs formatted RI data for the class or method +name+. + +Returns true if +name+ was found, false if it was not an alternative could +be guessed, raises an error if +name+ couldn't be guessed. + RDOC + + expected = <<-EXPECTED +

                          Outputs formatted RI data for the class or method name. +

                          Returns true if name was found, false if it was #{@ellipsis} + EXPECTED + + actual = @to.convert rdoc + + assert_equal expected, actual + assert_equal 159, @to.characters, 'snippet character length' + end + + def test_convert_limit_paragraphs + @to = RDoc::Markup::ToHtmlSnippet.new @options, 100, 3 + + rdoc = <<-RDOC += \RDoc - Ruby Documentation System + +* {RDoc Project Page}[https://github.com/rdoc/rdoc/] +* {RDoc Documentation}[http://docs.seattlerb.org/rdoc] +* {RDoc Bug Tracker}[https://github.com/rdoc/rdoc/issues] + +== DESCRIPTION: + +RDoc produces HTML and command-line documentation for Ruby projects. RDoc +includes the +rdoc+ and +ri+ tools for generating and displaying online +documentation. + +See RDoc for a description of RDoc's markup and basic use. + RDOC + + expected = <<-EXPECTED +

                          RDoc - Ruby Documentation System +

                          RDoc Project Page +

                          RDoc Documentation + EXPECTED + + actual = @to.convert rdoc + + assert_equal expected, actual + assert_equal 67, @to.characters + end + + def test_convert_limit_in_tag + @to = RDoc::Markup::ToHtmlSnippet.new @options, 4 + rdoc = "* ab *c* d\n" + + expected = "

                          ab c #{@ellipsis}\n\n" + + actual = @to.convert rdoc + + assert_equal 4, @to.characters + assert_equal expected, actual + end + + def test_convert_limit_verbatim + rdoc = <<-RDOC += Hello There + +This is some text, it *will* be cut off after 100 characters + + This one is cut off in this verbatim section + RDOC + + expected = <<-EXPECTED +

                          Hello There +

                          This is some text, it will be cut off after 100 characters + +

                          This one is cut off in this verbatim ...
                          + EXPECTED + + actual = @to.convert rdoc + + assert_equal expected, actual + assert_equal 113, @to.characters + end + + def test_convert_limit_verbatim_2 + rdoc = <<-RDOC +Extracts the class, selector and method name parts from +name+ like +Foo::Bar#baz. + +NOTE: Given Foo::Bar, Bar is considered a class even though it may be a + method + RDOC + + expected = <<-EXPECTED +

                          Extracts the class, selector and method name parts from name +like Foo::Bar#baz. +

                          NOTE: Given Foo::Bar, #{@ellipsis} + EXPECTED + + actual = @to.convert rdoc + + assert_equal expected, actual + assert_equal 101, @to.characters + end + + def test_convert_limit_verbatim_multiline + rdoc = <<-RDOC +Look for directives in a normal comment block: + + # :stopdoc: + # Don't display comment from this point forward + +This routine modifies its +comment+ parameter. + RDOC + + inner = CGI.escapeHTML "# Don't display comment from this point forward" + expected = <<-EXPECTED +

                          Look for directives in a normal comment block: + +

                          # :stopdoc:
                          +#{inner}
                          + EXPECTED + + actual = @to.convert rdoc + + assert_equal expected, actual + assert_equal 105, @to.characters + end + + def test_convert_limit_over + @to = RDoc::Markup::ToHtmlSnippet.new @options, 4 + rdoc = "* text\n" * 2 + + expected = "

                          text\n" + expected.chomp! + expected << " #{@ellipsis}\n" + + actual = @to.convert rdoc + + assert_equal 4, @to.characters + assert_equal expected, actual + end + + def test_convert_string + assert_equal '<>', @to.convert_string('<>') + end + + def test_convert_RDOCLINK_label_label + result = @to.convert 'rdoc-label:label-One' + + assert_equal "

                          One\n", result + assert_equal 3, @to.characters + end + + def test_convert_RDOCLINK_label_foottext + result = @to.convert 'rdoc-label:foottext-1' + + assert_equal "

                          *1\n", result + assert_equal 2, @to.characters + end + + def test_convert_RDOCLINK_label_footmark + result = @to.convert 'rdoc-label:footmark-1' + + assert_equal "

                          ^1\n", result + assert_equal 2, @to.characters + end + + def test_convert_RDOCLINK_ref + result = @to.convert 'rdoc-ref:C' + + assert_equal "

                          C\n", result + assert_equal 1, @to.characters + end + + def test_convert_TIDYLINK_rdoc_label + result = @to.convert '{foo}[rdoc-label:foottext-1]' + + assert_equal "

                          foo\n", result + assert_equal 3, @to.characters + end + + def test_handle_special_HYPERLINK_link + special = RDoc::Markup::Special.new 0, 'link:README.txt' + + link = @to.handle_special_HYPERLINK special + + assert_equal 'README.txt', link + end + + def test_list_verbatim_2 + str = "* one\n verb1\n verb2\n* two\n" + + expected = <<-EXPECTED +

                          one + +

                          verb1
                          +verb2
                          +

                          two + + EXPECTED + + assert_equal expected, @m.convert(str, @to) + assert_equal 17, @to.characters + end + + def test_on_tags + on = RDoc::Markup::AttrChanger.new 2, 0 + + @to.on_tags [], on + + assert_equal 2, @to.mask + end + + def test_off_tags + on = RDoc::Markup::AttrChanger.new 2, 0 + off = RDoc::Markup::AttrChanger.new 0, 2 + + @to.on_tags [], on + @to.off_tags [], off + + assert_equal 0, @to.mask + end + + def test_to_html + assert_equal "

                          --\n", util_format("--") + assert_equal 2, @to.characters + end + + def util_format text + paragraph = RDoc::Markup::Paragraph.new text + + @to.start_accepting + @to.accept_paragraph paragraph + @to.end_accepting + end + +end + diff --git a/test/rdoc/test_rdoc_markup_to_joined_paragraph.rb b/test/rdoc/test_rdoc_markup_to_joined_paragraph.rb new file mode 100644 index 0000000000..148edb1772 --- /dev/null +++ b/test/rdoc/test_rdoc_markup_to_joined_paragraph.rb @@ -0,0 +1,32 @@ +require 'rdoc/test_case' + +class TestRDocMarkupToJoinedParagraph < RDoc::TestCase + + def setup + super + + @to = RDoc::Markup::ToJoinedParagraph.new + end + + def test_accept_paragraph + parsed = para('hello', ' ', 'world') + + @to.accept_paragraph parsed + + expected = para('hello world') + + assert_equal expected, parsed + end + + def test_accept_paragraph_break + parsed = para('hello', ' ', 'world', hard_break, 'everyone') + + @to.accept_paragraph parsed + + expected = para('hello world', hard_break, 'everyone') + + assert_equal expected, parsed + end + +end + diff --git a/test/rdoc/test_rdoc_markup_to_label.rb b/test/rdoc/test_rdoc_markup_to_label.rb new file mode 100644 index 0000000000..5fb358bee3 --- /dev/null +++ b/test/rdoc/test_rdoc_markup_to_label.rb @@ -0,0 +1,112 @@ +require 'rdoc/test_case' + +class TestRDocMarkupToLabel < RDoc::Markup::FormatterTestCase + + add_visitor_tests + + def setup + super + + @to = RDoc::Markup::ToLabel.new + end + + def empty + assert_empty @to.res + end + + def end_accepting + assert_equal %w[hi], @to.res + end + + alias accept_blank_line empty + alias accept_block_quote empty + alias accept_document empty + alias accept_heading empty + alias accept_heading_1 empty + alias accept_heading_2 empty + alias accept_heading_3 empty + alias accept_heading_4 empty + alias accept_heading_b empty + alias accept_heading_suppressed_crossref empty + alias accept_list_end_bullet empty + alias accept_list_end_label empty + alias accept_list_end_lalpha empty + alias accept_list_end_note empty + alias accept_list_end_number empty + alias accept_list_end_ualpha empty + alias accept_list_item_end_bullet empty + alias accept_list_item_end_label empty + alias accept_list_item_end_lalpha empty + alias accept_list_item_end_note empty + alias accept_list_item_end_number empty + alias accept_list_item_end_ualpha empty + alias accept_list_item_start_bullet empty + alias accept_list_item_start_label empty + alias accept_list_item_start_lalpha empty + alias accept_list_item_start_note empty + alias accept_list_item_start_note_2 empty + alias accept_list_item_start_note_multi_description empty + alias accept_list_item_start_note_multi_label empty + alias accept_list_item_start_number empty + alias accept_list_item_start_ualpha empty + alias accept_list_start_bullet empty + alias accept_list_start_label empty + alias accept_list_start_lalpha empty + alias accept_list_start_note empty + alias accept_list_start_number empty + alias accept_list_start_ualpha empty + alias accept_paragraph empty + alias accept_paragraph_b empty + alias accept_paragraph_br empty + alias accept_paragraph_break empty + alias accept_paragraph_i empty + alias accept_paragraph_plus empty + alias accept_paragraph_star empty + alias accept_paragraph_underscore empty + alias accept_raw empty + alias accept_rule empty + alias accept_verbatim empty + alias list_nested empty + alias list_verbatim empty + alias start_accepting empty + + def test_convert_bold + assert_equal 'bold', @to.convert('bold') + assert_equal 'bold', @to.convert('*bold*') + end + + def test_convert_crossref + assert_equal 'SomeClass', @to.convert('SomeClass') + assert_equal 'SomeClass', @to.convert('\\SomeClass') + + assert_equal 'some_method', @to.convert('some_method') + assert_equal 'some_method', @to.convert('\\some_method') + + assert_equal '%23some_method', @to.convert('#some_method') + assert_equal '%23some_method', @to.convert('\\#some_method') + end + + def test_convert_em + assert_equal 'em', @to.convert('em') + assert_equal 'em', @to.convert('*em*') + end + + def test_convert_em_dash # for HTML conversion + assert_equal '--', @to.convert('--') + end + + def test_convert_escape + assert_equal 'a+%3E+b', @to.convert('a > b') + end + + def test_convert_tidylink + assert_equal 'text', @to.convert('{text}[stuff]') + assert_equal 'text', @to.convert('text[stuff]') + end + + def test_convert_tt + assert_equal 'tt', @to.convert('tt') + end + +end + diff --git a/test/rdoc/test_rdoc_markup_to_markdown.rb b/test/rdoc/test_rdoc_markup_to_markdown.rb new file mode 100644 index 0000000000..56f84b41db --- /dev/null +++ b/test/rdoc/test_rdoc_markup_to_markdown.rb @@ -0,0 +1,352 @@ +require 'rdoc/test_case' + +class TestRDocMarkupToMarkdown < RDoc::Markup::TextFormatterTestCase + + add_visitor_tests + add_text_tests + + def setup + super + + @to = RDoc::Markup::ToMarkdown.new + end + + def accept_blank_line + assert_equal "\n", @to.res.join + end + + def accept_block_quote + assert_equal "> quote\n", @to.res.join + end + + def accept_document + assert_equal "hello\n", @to.res.join + end + + def accept_heading + assert_equal "##### Hello\n", @to.res.join + end + + def accept_list_end_bullet + assert_empty @to.list_index + assert_empty @to.list_type + assert_empty @to.list_width + end + + def accept_list_end_label + assert_empty @to.list_index + assert_empty @to.list_type + assert_empty @to.list_width + end + + def accept_list_end_lalpha + assert_empty @to.list_index + assert_empty @to.list_type + assert_empty @to.list_width + end + + def accept_list_end_note + assert_empty @to.list_index + assert_empty @to.list_type + assert_empty @to.list_width + end + + def accept_list_end_number + assert_empty @to.list_index + assert_empty @to.list_type + assert_empty @to.list_width + end + + def accept_list_end_ualpha + assert_empty @to.list_index + assert_empty @to.list_type + assert_empty @to.list_width + end + + def accept_list_item_end_bullet + assert_equal 0, @to.indent, 'indent' + end + + def accept_list_item_end_label + assert_equal "cat\n: ", @to.res.join + assert_equal 0, @to.indent, 'indent' + end + + def accept_list_item_end_lalpha + assert_equal 0, @to.indent, 'indent' + assert_equal 2, @to.list_index.last + end + + def accept_list_item_end_note + assert_equal "cat\n: ", @to.res.join + assert_equal 0, @to.indent, 'indent' + end + + def accept_list_item_end_number + assert_equal 0, @to.indent, 'indent' + assert_equal 2, @to.list_index.last + end + + def accept_list_item_end_ualpha + assert_equal 0, @to.indent, 'indent' + assert_equal 2, @to.list_index.last + end + + def accept_list_item_start_bullet + assert_equal [""], @to.res + assert_equal '* ', @to.prefix + end + + def accept_list_item_start_label + assert_equal [""], @to.res + assert_equal "cat\n: ", @to.prefix + + assert_equal 4, @to.indent + end + + def accept_list_item_start_lalpha + assert_equal [""], @to.res + assert_equal '1. ', @to.prefix + + assert_equal 1, @to.list_index.last + assert_equal 4, @to.indent + end + + def accept_list_item_start_note + assert_equal [""], @to.res + assert_equal "cat\n: ", @to.prefix + + assert_equal 4, @to.indent + end + + def accept_list_item_start_number + assert_equal [""], @to.res + assert_equal '1. ', @to.prefix + + assert_equal 1, @to.list_index.last + assert_equal 4, @to.indent + end + + def accept_list_item_start_ualpha + assert_equal [""], @to.res + assert_equal '1. ', @to.prefix + + assert_equal 1, @to.list_index.last + assert_equal 4, @to.indent + end + + def accept_list_start_bullet + assert_equal "", @to.res.join + assert_equal [nil], @to.list_index + assert_equal [:BULLET], @to.list_type + assert_equal [4], @to.list_width + end + + def accept_list_start_label + assert_equal "", @to.res.join + assert_equal [nil], @to.list_index + assert_equal [:LABEL], @to.list_type + assert_equal [4], @to.list_width + end + + def accept_list_start_lalpha + assert_equal "", @to.res.join + assert_equal [1], @to.list_index + assert_equal [:LALPHA], @to.list_type + assert_equal [4], @to.list_width + end + + def accept_list_start_note + assert_equal "", @to.res.join + assert_equal [nil], @to.list_index + assert_equal [:NOTE], @to.list_type + assert_equal [4], @to.list_width + end + + def accept_list_start_number + assert_equal "", @to.res.join + assert_equal [1], @to.list_index + assert_equal [:NUMBER], @to.list_type + assert_equal [4], @to.list_width + end + + def accept_list_start_ualpha + assert_equal "", @to.res.join + assert_equal [1], @to.list_index + assert_equal [:UALPHA], @to.list_type + assert_equal [4], @to.list_width + end + + def accept_paragraph + assert_equal "hi\n", @to.res.join + end + + def accept_raw + raw = <<-RAW.rstrip +

                      +
                      NameCount +
                      a1 +
                      b2 +
                      + RAW + + assert_equal raw, @to.res.join + end + + def accept_rule + assert_equal "---\n", @to.res.join + end + + def accept_verbatim + assert_equal " hi\n world\n\n", @to.res.join + end + + def end_accepting + assert_equal "hi", @to.end_accepting + end + + def start_accepting + assert_equal 0, @to.indent + assert_equal [""], @to.res + assert_empty @to.list_index + assert_empty @to.list_type + assert_empty @to.list_width + end + + def accept_heading_1 + assert_equal "# Hello\n", @to.end_accepting + end + + def accept_heading_2 + assert_equal "## Hello\n", @to.end_accepting + end + + def accept_heading_3 + assert_equal "### Hello\n", @to.end_accepting + end + + def accept_heading_4 + assert_equal "#### Hello\n", @to.end_accepting + end + + def accept_heading_indent + assert_equal " # Hello\n", @to.end_accepting + end + + def accept_heading_b + assert_equal "# **Hello**\n", @to.end_accepting + end + + def accept_heading_suppressed_crossref + assert_equal "# Hello\n", @to.end_accepting + end + + def accept_list_item_start_note_2 + assert_equal "`teletype`\n: teletype description\n\n", @to.res.join + end + + def accept_list_item_start_note_multi_description + assert_equal "label\n: description one\n\n: description two\n\n", + @to.res.join + end + + def accept_list_item_start_note_multi_label + assert_equal "one\ntwo\n: two headers\n\n", @to.res.join + end + + def accept_paragraph_b + assert_equal "reg **bold words** reg\n", @to.end_accepting + end + + def accept_paragraph_br + assert_equal "one \ntwo\n", @to.end_accepting + end + + def accept_paragraph_break + assert_equal "hello \nworld\n", @to.end_accepting + end + + def accept_paragraph_i + assert_equal "reg *italic words* reg\n", @to.end_accepting + end + + def accept_paragraph_indent + expected = <<-EXPECTED + words words words words words words words words words words words words + words words words words words words words words words words words words + words words words words words words + EXPECTED + + assert_equal expected, @to.end_accepting + end + + def accept_paragraph_plus + assert_equal "reg `teletype` reg\n", @to.end_accepting + end + + def accept_paragraph_star + assert_equal "reg **bold** reg\n", @to.end_accepting + end + + def accept_paragraph_underscore + assert_equal "reg *italic* reg\n", @to.end_accepting + end + + def accept_paragraph_wrap + expected = <<-EXPECTED +words words words words words words words words words words words words words +words words words words words words words words words words words words words +words words words words + EXPECTED + + assert_equal expected, @to.end_accepting + end + + def accept_rule_indent + assert_equal " ---\n", @to.end_accepting + end + + def accept_verbatim_indent + assert_equal " hi\n world\n\n", @to.end_accepting + end + + def accept_verbatim_big_indent + assert_equal " hi\n world\n\n", @to.end_accepting + end + + def list_nested + expected = <<-EXPECTED +* l1 + * l1.1 + +* l2 + + EXPECTED + + assert_equal expected, @to.end_accepting + end + + def list_verbatim + expected = <<-EXPECTED # HACK overblown +* list stuff + + * list + with + + second + + 1. indented + 2. numbered + + third + + * second + + + EXPECTED + + assert_equal expected, @to.end_accepting + end + +end + diff --git a/test/rdoc/test_rdoc_markup_to_rdoc.rb b/test/rdoc/test_rdoc_markup_to_rdoc.rb index 06cae078c6..4b60d0133e 100644 --- a/test/rdoc/test_rdoc_markup_to_rdoc.rb +++ b/test/rdoc/test_rdoc_markup_to_rdoc.rb @@ -1,7 +1,4 @@ -require 'rubygems' -require 'rdoc/markup/text_formatter_test_case' -require 'rdoc/markup/to_rdoc' -require 'minitest/autorun' +require 'rdoc/test_case' class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase @@ -18,6 +15,10 @@ class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase assert_equal "\n", @to.res.join end + def accept_block_quote + assert_equal "> quote\n", @to.res.join + end + def accept_document assert_equal "hello\n", @to.res.join end @@ -67,7 +68,7 @@ class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase end def accept_list_item_end_label - assert_equal "\n", @to.res.join + assert_equal "cat:\n", @to.res.join assert_equal 0, @to.indent, 'indent' end @@ -77,7 +78,7 @@ class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase end def accept_list_item_end_note - assert_equal "\n", @to.res.join + assert_equal "cat:\n", @to.res.join assert_equal 0, @to.indent, 'indent' end @@ -244,10 +245,27 @@ class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase assert_equal "teletype:\n teletype description\n\n", @to.res.join end + def accept_list_item_start_note_multi_description + assert_equal "label:\n description one\n\n description two\n\n", + @to.res.join + end + + def accept_list_item_start_note_multi_label + assert_equal "one\ntwo:\n two headers\n\n", @to.res.join + end + def accept_paragraph_b assert_equal "reg bold words reg\n", @to.end_accepting end + def accept_paragraph_br + assert_equal "one\ntwo\n", @to.end_accepting + end + + def accept_paragraph_break + assert_equal "hello\nworld\n", @to.end_accepting + end + def accept_paragraph_i assert_equal "reg italic words reg\n", @to.end_accepting end @@ -327,6 +345,24 @@ words words words words assert_equal expected, @to.end_accepting end + # functional test + def test_convert_list_note + note_list = <<-NOTE_LIST +foo :: +bar :: + hi + NOTE_LIST + + expected = <<-EXPECTED +foo +bar: + hi + + EXPECTED + + assert_equal expected, @to.convert(note_list) + end + def test_accept_indented_paragraph ip = RDoc::Markup::IndentedParagraph.new 2, 'cats are cool' diff --git a/test/rdoc/test_rdoc_markup_to_table_of_contents.rb b/test/rdoc/test_rdoc_markup_to_table_of_contents.rb new file mode 100644 index 0000000000..fd0be746d8 --- /dev/null +++ b/test/rdoc/test_rdoc_markup_to_table_of_contents.rb @@ -0,0 +1,95 @@ +require 'rdoc/test_case' + +class TestRDocMarkupToTableOfContents < RDoc::Markup::FormatterTestCase + + add_visitor_tests + + def setup + super + + @to = RDoc::Markup::ToTableOfContents.new + end + + def end_accepting + assert_equal %w[hi], @to.res + end + + def empty + assert_empty @to.res + end + + def accept_heading + assert_equal [@RM::Heading.new(5, 'Hello')], @to.res + end + + def accept_heading_1 + assert_equal [@RM::Heading.new(1, 'Hello')], @to.res + end + + def accept_heading_2 + assert_equal [@RM::Heading.new(2, 'Hello')], @to.res + end + + def accept_heading_3 + assert_equal [@RM::Heading.new(3, 'Hello')], @to.res + end + + def accept_heading_4 + assert_equal [@RM::Heading.new(4, 'Hello')], @to.res + end + + def accept_heading_b + assert_equal [@RM::Heading.new(1, '*Hello*')], @to.res + end + + def accept_heading_suppressed_crossref + assert_equal [@RM::Heading.new(1, '\\Hello')], @to.res + end + + alias accept_blank_line empty + alias accept_block_quote empty + alias accept_document empty + alias accept_list_end_bullet empty + alias accept_list_end_label empty + alias accept_list_end_lalpha empty + alias accept_list_end_note empty + alias accept_list_end_number empty + alias accept_list_end_ualpha empty + alias accept_list_item_end_bullet empty + alias accept_list_item_end_label empty + alias accept_list_item_end_lalpha empty + alias accept_list_item_end_note empty + alias accept_list_item_end_number empty + alias accept_list_item_end_ualpha empty + alias accept_list_item_start_bullet empty + alias accept_list_item_start_label empty + alias accept_list_item_start_lalpha empty + alias accept_list_item_start_note empty + alias accept_list_item_start_note_2 empty + alias accept_list_item_start_note_multi_description empty + alias accept_list_item_start_note_multi_label empty + alias accept_list_item_start_number empty + alias accept_list_item_start_ualpha empty + alias accept_list_start_bullet empty + alias accept_list_start_label empty + alias accept_list_start_lalpha empty + alias accept_list_start_note empty + alias accept_list_start_number empty + alias accept_list_start_ualpha empty + alias accept_paragraph empty + alias accept_paragraph_b empty + alias accept_paragraph_br empty + alias accept_paragraph_break empty + alias accept_paragraph_i empty + alias accept_paragraph_plus empty + alias accept_paragraph_star empty + alias accept_paragraph_underscore empty + alias accept_raw empty + alias accept_rule empty + alias accept_verbatim empty + alias list_nested empty + alias list_verbatim empty + alias start_accepting empty + +end + diff --git a/test/rdoc/test_rdoc_markup_to_tt_only.rb b/test/rdoc/test_rdoc_markup_to_tt_only.rb index f5bb662897..2e950dd1b0 100644 --- a/test/rdoc/test_rdoc_markup_to_tt_only.rb +++ b/test/rdoc/test_rdoc_markup_to_tt_only.rb @@ -1,7 +1,4 @@ -require 'rubygems' -require 'rdoc/markup/formatter_test_case' -require 'rdoc/markup/to_tt_only' -require 'minitest/autorun' +require 'rdoc/test_case' class TestRDocMarkupToTtOnly < RDoc::Markup::FormatterTestCase @@ -17,6 +14,10 @@ class TestRDocMarkupToTtOnly < RDoc::Markup::FormatterTestCase assert_empty @to.end_accepting end + def accept_block_quote + assert_empty @to.end_accepting + end + def accept_document assert_equal [], @to.res end @@ -125,6 +126,10 @@ class TestRDocMarkupToTtOnly < RDoc::Markup::FormatterTestCase assert_empty @to.end_accepting end + def accept_paragraph_break + assert_empty @to.end_accepting + end + def accept_raw assert_empty @to.end_accepting end @@ -177,10 +182,22 @@ class TestRDocMarkupToTtOnly < RDoc::Markup::FormatterTestCase assert_equal [nil, 'teletype', nil], @to.res end + def accept_list_item_start_note_multi_description + assert_empty @to.res + end + + def accept_list_item_start_note_multi_label + assert_empty @to.res + end + def accept_paragraph_b assert_empty @to.end_accepting end + def accept_paragraph_br + assert_empty @to.end_accepting + end + def accept_paragraph_i assert_empty @to.end_accepting end diff --git a/test/rdoc/test_rdoc_markup_verbatim.rb b/test/rdoc/test_rdoc_markup_verbatim.rb new file mode 100644 index 0000000000..781d52849a --- /dev/null +++ b/test/rdoc/test_rdoc_markup_verbatim.rb @@ -0,0 +1,29 @@ +require 'rdoc/test_case' + +class TestRDocMarkupVerbatim < RDoc::TestCase + + def test_equals2 + v1 = verb('1 + 1') + v2 = verb('1 + 1') + v3 = verb('1 + 2') + v4 = verb('1 + 1') + v4.format = :ruby + + assert_equal v1, v2 + + refute_equal v1, v3 + refute_equal v1, v4 + end + + def test_ruby_eh + verbatim = RDoc::Markup::Verbatim.new + + refute verbatim.ruby? + + verbatim.format = :ruby + + assert verbatim.ruby? + end + +end + diff --git a/test/rdoc/test_rdoc_method_attr.rb b/test/rdoc/test_rdoc_method_attr.rb index 007a3f6b35..8fff038289 100644 --- a/test/rdoc/test_rdoc_method_attr.rb +++ b/test/rdoc/test_rdoc_method_attr.rb @@ -111,12 +111,45 @@ class TestRDocMethodAttr < XrefTestCase assert_nil @m1_m.find_method_or_attribute 'm' end + def test_full_name + assert_equal 'C1#m', @c1_m.full_name + assert_equal 'C1::m', @c1__m.full_name + end + + def test_output_name + assert_equal '#m', @c1_m.output_name(@c1) + assert_equal '::m', @c1__m.output_name(@c1) + + assert_equal 'C1#m', @c1_m.output_name(@c2) + assert_equal 'C1.m', @c1__m.output_name(@c2) + end + + def test_search_record + @c1_m.comment = 'This is a comment.' + + expected = [ + 'm', + 'C1#m', + 'm', + 'C1', + 'C1.html#method-i-m', + '(foo)', + "

                      This is a comment.\n", + ] + + assert_equal expected, @c1_m.search_record + end + + def test_equals2 + assert_equal @c1_m, @c1_m + refute_equal @c1_m, @parent_m + end + def test_to_s assert_equal 'RDoc::AnyMethod: C1#m', @c1_m.to_s assert_equal 'RDoc::AnyMethod: C2#b', @c2_b.to_s assert_equal 'RDoc::AnyMethod: C1::m', @c1__m.to_s end - end diff --git a/test/rdoc/test_rdoc_normal_class.rb b/test/rdoc/test_rdoc_normal_class.rb index bd0d67e19c..f3c7890d59 100644 --- a/test/rdoc/test_rdoc_normal_class.rb +++ b/test/rdoc/test_rdoc_normal_class.rb @@ -2,15 +2,34 @@ require File.expand_path '../xref_test_case', __FILE__ class TestRDocNormalClass < XrefTestCase - def test_ancestors_class - top_level = RDoc::TopLevel.new 'file.rb' - klass = top_level.add_class RDoc::NormalClass, 'Klass' + def test_ancestors + klass = @top_level.add_class RDoc::NormalClass, 'Klass' incl = RDoc::Include.new 'Incl', '' - sub_klass = klass.add_class RDoc::NormalClass, 'SubClass', 'Klass' + sub_klass = @top_level.add_class RDoc::NormalClass, 'SubClass' + sub_klass.superclass = klass sub_klass.add_include incl - assert_equal [incl.name, klass], sub_klass.ancestors + assert_equal [incl.name, klass, 'Object'], sub_klass.ancestors + end + + def test_ancestors_multilevel + c1 = @top_level.add_class RDoc::NormalClass, 'Outer' + c2 = @top_level.add_class RDoc::NormalClass, 'Middle', c1 + c3 = @top_level.add_class RDoc::NormalClass, 'Inner', c2 + + assert_equal [c2, c1, 'Object'], c3.ancestors + end + + def test_direct_ancestors + incl = RDoc::Include.new 'Incl', '' + + c1 = @top_level.add_class RDoc::NormalClass, 'Outer' + c2 = @top_level.add_class RDoc::NormalClass, 'Middle', c1 + c3 = @top_level.add_class RDoc::NormalClass, 'Inner', c2 + c3.add_include incl + + assert_equal [incl.name, c2], c3.direct_ancestors end def test_definition diff --git a/test/rdoc/test_rdoc_normal_module.rb b/test/rdoc/test_rdoc_normal_module.rb index 975bf911fe..120f56a284 100644 --- a/test/rdoc/test_rdoc_normal_module.rb +++ b/test/rdoc/test_rdoc_normal_module.rb @@ -9,7 +9,7 @@ class TestRDocNormalModule < XrefTestCase end def test_ancestors_module - top_level = RDoc::TopLevel.new 'file.rb' + top_level = @store.add_file 'file.rb' mod = top_level.add_module RDoc::NormalModule, 'Mod' incl = RDoc::Include.new 'Incl', '' diff --git a/test/rdoc/test_rdoc_options.rb b/test/rdoc/test_rdoc_options.rb index 2f74f45b45..ddd9cb83ae 100644 --- a/test/rdoc/test_rdoc_options.rb +++ b/test/rdoc/test_rdoc_options.rb @@ -1,56 +1,130 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/options' +require 'rdoc/test_case' -require 'fileutils' -require 'tmpdir' - -class TestRDocOptions < MiniTest::Unit::TestCase +class TestRDocOptions < RDoc::TestCase def setup + super + @options = RDoc::Options.new @generators = RDoc::RDoc::GENERATORS.dup end def teardown + super + RDoc::RDoc::GENERATORS.replace @generators end + def mu_pp obj + s = '' + s = PP.pp obj, s + s = s.force_encoding Encoding.default_external if defined? Encoding + s.chomp + end + def test_check_files skip "assumes UNIX permission model" if /mswin|mingw/ =~ RUBY_PLATFORM + out, err = capture_io do - Dir.mktmpdir do |dir| - Dir.chdir dir do - FileUtils.touch 'unreadable' - FileUtils.chmod 0, 'unreadable' + temp_dir do + FileUtils.touch 'unreadable' + FileUtils.chmod 0, 'unreadable' - @options.files = %w[nonexistent unreadable] + @options.files = %w[nonexistent unreadable] - @options.check_files - end + @options.check_files end end assert_empty @options.files - assert_equal '', out + assert_empty out + assert_empty err + end - expected = <<-EXPECTED -file 'nonexistent' not found -file 'unreadable' not readable - EXPECTED + def test_check_files_warn + @options.verbosity = 2 - assert_equal expected, err + out, err = capture_io do + @options.files = %w[nonexistent] + + @options.check_files + end + + assert_empty out + assert_equal "file 'nonexistent' not found\n", err + assert_empty @options.files end def test_dry_run_default refute @options.dry_run end + def test_encode_with + coder = {} + class << coder; alias add []=; end + + @options.encode_with coder + + encoding = Object.const_defined?(:Encoding) ? 'UTF-8' : nil + + expected = { + 'charset' => 'UTF-8', + 'encoding' => encoding, + 'exclude' => [], + 'hyperlink_all' => false, + 'line_numbers' => false, + 'main_page' => nil, + 'markup' => 'rdoc', + 'rdoc_include' => [], + 'show_hash' => false, + 'static_path' => [], + 'tab_width' => 8, + 'title' => nil, + 'visibility' => :protected, + 'webcvs' => nil, + } + + assert_equal expected, coder + end + + def test_encode_with_trim_paths + subdir = nil + coder = {} + class << coder; alias add []=; end + + temp_dir do |dir| + FileUtils.mkdir 'project' + FileUtils.mkdir 'dir' + FileUtils.touch 'file' + + Dir.chdir 'project' do + subdir = File.expand_path 'subdir' + FileUtils.mkdir 'subdir' + @options.parse %w[ + --copy subdir + --copy ../file + --copy ../ + --copy / + --include subdir + --include ../dir + --include ../ + --include / + ] + + @options.encode_with coder + end + end + + assert_equal [subdir], coder['rdoc_include'] + + assert_equal [subdir], coder['static_path'] + end + def test_encoding_default skip "Encoding not implemented" unless Object.const_defined? :Encoding - assert_equal Encoding.default_external, @options.encoding + assert_equal Encoding::UTF_8, @options.encoding end def test_generator_descriptions @@ -67,6 +141,63 @@ file 'unreadable' not readable assert_equal expected, @options.generator_descriptions end + def test_init_with_encoding + skip "Encoding not implemented" unless Object.const_defined? :Encoding + RDoc.load_yaml + + @options.encoding = Encoding::IBM437 + + options = YAML.load YAML.dump @options + + assert_equal Encoding::IBM437, options.encoding + end + + def test_init_with_trim_paths + RDoc.load_yaml + + yaml = <<-YAML +--- !ruby/object:RDoc::Options +static_path: +- /etc +rdoc_include: +- /etc + YAML + + options = YAML.load yaml + + assert_empty options.rdoc_include + assert_empty options.static_path + end + + def test_parse_copy_files_file_relative + file = File.basename __FILE__ + expected = File.expand_path __FILE__ + + Dir.chdir File.expand_path('..', __FILE__) do + @options.parse %W[--copy-files #{file}] + + assert_equal [expected], @options.static_path + end + end + + def test_parse_copy_files_file_absolute + @options.parse %W[--copy-files #{File.expand_path __FILE__}] + + assert_equal [File.expand_path(__FILE__)], @options.static_path + end + + def test_parse_copy_files_directory_relative + @options.parse %w[--copy-files .] + + assert_equal [@pwd], @options.static_path + end + + def test_parse_copy_files_directory_absolute + @options.parse %w[--copy-files /] + + assert_equal ['/'], @options.static_path + end + def test_parse_coverage @options.parse %w[--dcov] @@ -286,6 +417,17 @@ file 'unreadable' not readable assert_equal 'MAIN', @options.main_page end + def test_parse_markup + out, err = capture_io do + @options.parse %w[--markup tomdoc] + end + + assert_empty out + assert_empty err + + assert_equal 'tomdoc', @options.markup + end + def test_parse_template out, err = capture_io do @options.parse %w[--template darkfish] @@ -337,13 +479,21 @@ file 'unreadable' not readable $LOAD_PATH.replace orig_LOAD_PATH end - def test_parse_extension_alias - out, err = capture_io do - @options.parse %w[--extension foobar=rdoc] - end + def test_parse_write_options + tmpdir = File.join Dir.tmpdir, "test_rdoc_options_#{$$}" + FileUtils.mkdir_p tmpdir - assert_empty out - assert_empty err + Dir.chdir tmpdir do + e = assert_raises SystemExit do + @options.parse %w[--write-options] + end + + assert_equal 0, e.status + + assert File.exist? '.rdoc_options' + end + ensure + FileUtils.rm_rf tmpdir end def test_setup_generator @@ -397,5 +547,33 @@ file 'unreadable' not readable refute @options.update_output_dir end + def test_warn + out, err = capture_io do + @options.warn "warnings off" + end + + assert_empty out + assert_empty err + + @options.verbosity = 2 + + out, err = capture_io do + @options.warn "warnings on" + end + + assert_empty out + assert_equal "warnings on\n", err + end + + def test_write_options + temp_dir do |dir| + @options.write_options + + assert File.exist? '.rdoc_options' + + assert_equal @options, YAML.load(File.read('.rdoc_options')) + end + end + end diff --git a/test/rdoc/test_rdoc_parser.rb b/test/rdoc/test_rdoc_parser.rb index c323efeac3..35a797063a 100644 --- a/test/rdoc/test_rdoc_parser.rb +++ b/test/rdoc/test_rdoc_parser.rb @@ -1,14 +1,16 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/parser' -require 'rdoc/parser/ruby' -require 'tmpdir' +require 'rdoc/test_case' -class TestRDocParser < MiniTest::Unit::TestCase +class TestRDocParser < RDoc::TestCase def setup + super + @RP = RDoc::Parser @binary_dat = File.expand_path '../binary.dat', __FILE__ + + @fn = 'file.rb' + @top_level = RDoc::TopLevel.new @fn + @options = RDoc::Options.new end def test_class_binary_eh_marshal @@ -29,11 +31,8 @@ class TestRDocParser < MiniTest::Unit::TestCase end def test_class_binary_large_japanese_rdoc - extenc, Encoding.default_external = Encoding.default_external, Encoding::US_ASCII - file_name = File.expand_path '../test.ja.largedoc', __FILE__ + file_name = File.expand_path '../test.ja.large.rdoc', __FILE__ assert !@RP.binary?(file_name) - ensure - Encoding.default_external = extenc end def test_class_binary_japanese_rdoc @@ -60,13 +59,18 @@ class TestRDocParser < MiniTest::Unit::TestCase readme_file_name = File.expand_path '../README', __FILE__ assert_equal @RP::Simple, @RP.can_parse(readme_file_name) + end - jtest_largerdoc_file_name = File.expand_path '../test.ja.largedoc', __FILE__ - assert_nil @RP.can_parse(jtest_largerdoc_file_name) - - @RP.alias_extension("rdoc", "largedoc") - assert_equal @RP::Simple, @RP.can_parse(jtest_largerdoc_file_name) + def test_class_can_parse_forbidden + Tempfile.open 'forbidden' do |io| + begin + File.chmod 0000, io.path + assert_nil @RP.can_parse io.path + ensure + File.chmod 0400, io.path + end + end end ## @@ -89,5 +93,92 @@ class TestRDocParser < MiniTest::Unit::TestCase assert_nil @RP.for(nil, @binary_dat, nil, nil, nil) end + def test_class_for_markup + content = <<-CONTENT +# coding: utf-8 markup: rd + CONTENT + + parser = @RP.for @top_level, __FILE__, content, @options, nil + + assert_kind_of @RP::RD, parser + end + + def test_class_use_markup + content = <<-CONTENT +# coding: utf-8 markup: rd + CONTENT + + parser = @RP.use_markup content + + assert_equal @RP::RD, parser + end + + def test_class_use_markup_markdown + content = <<-CONTENT +# coding: utf-8 markup: markdown + CONTENT + + parser = @RP.use_markup content + + assert_equal @RP::Ruby, parser + end + + def test_class_use_markup_modeline + content = <<-CONTENT +# -*- coding: utf-8 -*- +# markup: rd + CONTENT + + parser = @RP.use_markup content + + assert_equal @RP::RD, parser + end + + def test_class_use_markup_modeline_shebang + content = <<-CONTENT +#!/bin/sh +/* -*- coding: utf-8 -*- + * markup: rd + */ + CONTENT + + parser = @RP.use_markup content + + assert_equal @RP::RD, parser + end + + def test_class_use_markup_shebang + content = <<-CONTENT +#!/usr/bin/env ruby +# coding: utf-8 markup: rd + CONTENT + + parser = @RP.use_markup content + + assert_equal @RP::RD, parser + end + + def test_class_use_markup_tomdoc + content = <<-CONTENT +# coding: utf-8 markup: tomdoc + CONTENT + + parser = @RP.use_markup content + + assert_equal @RP::Ruby, parser + end + + def test_class_use_markup_none + parser = @RP.use_markup '' + + assert_nil parser + end + + def test_initialize + @RP.new @top_level, @fn, '', @options, nil + + assert_equal @RP, @top_level.parser + end + end diff --git a/test/rdoc/test_rdoc_parser_c.rb b/test/rdoc/test_rdoc_parser_c.rb index 438eeee2ab..4e5e6ab1a2 100644 --- a/test/rdoc/test_rdoc_parser_c.rb +++ b/test/rdoc/test_rdoc_parser_c.rb @@ -1,9 +1,4 @@ -require 'stringio' -require 'tempfile' -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/options' -require 'rdoc/parser/c' +require 'rdoc/test_case' =begin TODO: test call-seq parsing @@ -51,22 +46,24 @@ class RDoc::Parser::C public :do_classes, :do_constants end -class TestRDocParserC < MiniTest::Unit::TestCase +class TestRDocParserC < RDoc::TestCase def setup + super + @tempfile = Tempfile.new self.class.name filename = @tempfile.path - @top_level = RDoc::TopLevel.new filename + @top_level = @store.add_file filename @fn = filename @options = RDoc::Options.new - @stats = RDoc::Stats.new 0 - - RDoc::Parser::C.reset - RDoc::TopLevel.reset + @options.verbosity = 2 + @stats = RDoc::Stats.new @store, 0 end def teardown + super + @tempfile.close end @@ -116,18 +113,18 @@ void Init_Blah(void) { accessor = attrs.shift assert_equal 'accessor', accessor.name assert_equal 'RW', accessor.rw - assert_equal 'This is an accessor', accessor.comment + assert_equal 'This is an accessor', accessor.comment.text assert_equal @top_level, accessor.file reader = attrs.shift assert_equal 'reader', reader.name assert_equal 'R', reader.rw - assert_equal 'This is a reader', reader.comment + assert_equal 'This is a reader', reader.comment.text writer = attrs.shift assert_equal 'writer', writer.name assert_equal 'W', writer.rw - assert_equal 'This is a writer', writer.comment + assert_equal 'This is a writer', writer.comment.text end def test_do_attr_rb_define_attr @@ -150,7 +147,7 @@ void Init_Blah(void) { accessor = attrs.shift assert_equal 'accessor', accessor.name assert_equal 'RW', accessor.rw - assert_equal 'This is an accessor', accessor.comment + assert_equal 'This is an accessor', accessor.comment.text assert_equal @top_level, accessor.file end @@ -211,7 +208,7 @@ void Init_Blah(void) { assert_equal 'bleh', methods.last.name assert methods.last.singleton assert_equal 'blah', methods.last.is_alias_for.name - assert_equal 'This should show up as an alias', methods.last.comment + assert_equal 'This should show up as an alias', methods.last.comment.text end def test_do_classes_boot_class @@ -223,7 +220,7 @@ VALUE cFoo = boot_defclass("Foo", rb_cObject); EOF klass = util_get_class content, 'cFoo' - assert_equal "this is the Foo boot class", klass.comment + assert_equal "this is the Foo boot class", klass.comment.text assert_equal 'Object', klass.superclass end @@ -236,7 +233,7 @@ VALUE cFoo = boot_defclass("Foo", 0); EOF klass = util_get_class content, 'cFoo' - assert_equal "this is the Foo boot class", klass.comment + assert_equal "this is the Foo boot class", klass.comment.text assert_equal nil, klass.superclass end @@ -251,7 +248,7 @@ void Init_Blah(void) { refute util_get_class(content, 'cDate') end - assert_equal "Enclosing class/module \"cDate\" for alias b a not known\n", + assert_equal "Enclosing class or module \"cDate\" for alias b a is not known\n", err end @@ -264,7 +261,21 @@ VALUE cFoo = rb_define_class("Foo", rb_cObject); EOF klass = util_get_class content, 'cFoo' - assert_equal "this is the Foo class", klass.comment + assert_equal "this is the Foo class", klass.comment.text + end + + def test_do_classes_struct + content = <<-EOF +/* Document-class: Foo + * this is the Foo class + */ +VALUE cFoo = rb_struct_define_without_accessor( + "Foo", rb_cObject, foo_alloc, + "some", "various", "fields", NULL); + EOF + + klass = util_get_class content, 'cFoo' + assert_equal "this is the Foo class", klass.comment.text end def test_do_classes_class_under @@ -277,7 +288,7 @@ VALUE cFoo = rb_define_class_under(rb_mKernel, "Foo", rb_cObject); klass = util_get_class content, 'cFoo' assert_equal 'Kernel::Foo', klass.full_name - assert_equal "this is the Foo class under Kernel", klass.comment + assert_equal "this is the Foo class under Kernel", klass.comment.text end def test_do_classes_class_under_rb_path2class @@ -292,7 +303,7 @@ VALUE cFoo = rb_define_class_under(rb_mKernel, "Foo", rb_path2class("A::B")); assert_equal 'Kernel::Foo', klass.full_name assert_equal 'A::B', klass.superclass - assert_equal 'this is Kernel::Foo < A::B', klass.comment + assert_equal 'this is Kernel::Foo < A::B', klass.comment.text end def test_do_classes_singleton @@ -315,7 +326,7 @@ VALUE mFoo = rb_define_module("Foo"); EOF klass = util_get_class content, 'mFoo' - assert_equal "this is the Foo module", klass.comment + assert_equal "this is the Foo module", klass.comment.text end def test_do_classes_module_under @@ -327,7 +338,7 @@ VALUE mFoo = rb_define_module_under(rb_mKernel, "Foo"); EOF klass = util_get_class content, 'mFoo' - assert_equal "this is the Foo module under Kernel", klass.comment + assert_equal "this is the Foo module under Kernel", klass.comment.text end def test_do_constants @@ -377,6 +388,12 @@ void Init_foo(){ */ rb_define_const(cFoo, "MULTILINE_NOT_EMPTY", INT2FIX(1)); + /* + * Multiline comment goes here because this comment spans multiple lines. + * 1: However, the value extraction should only happen for the first line + */ + rb_define_const(cFoo, "MULTILINE_COLON_ON_SECOND_LINE", INT2FIX(1)); + } EOF @@ -393,7 +410,7 @@ void Init_foo(){ assert_equal @top_level, constants.first.file - constants = constants.map { |c| [c.name, c.value, c.comment] } + constants = constants.map { |c| [c.name, c.value, c.comment.text] } assert_equal ['PERFECT', '300', 'The highest possible score in bowling '], constants.shift @@ -426,6 +443,13 @@ Multiline comment goes here because this comment spans multiple lines. assert_equal ['MULTILINE_VALUE', '1', comment], constants.shift assert_equal ['MULTILINE_NOT_EMPTY', 'INT2FIX(1)', comment], constants.shift + comment = <<-EOF.chomp +Multiline comment goes here because this comment spans multiple lines. +1: However, the value extraction should only happen for the first line + EOF + assert_equal ['MULTILINE_COLON_ON_SECOND_LINE', 'INT2FIX(1)', comment], + constants.shift + assert constants.empty?, constants.inspect end @@ -445,6 +469,7 @@ void Init_curses(){ @parser = util_parser content + @parser.do_modules @parser.do_classes @parser.do_constants @@ -455,7 +480,40 @@ void Init_curses(){ assert_equal 'COLOR_BLACK', constants.first.name assert_equal 'UINT2NUM(COLOR_BLACK)', constants.first.value - assert_equal 'Value of the color black', constants.first.comment + assert_equal 'Value of the color black', constants.first.comment.text + end + + def test_do_constants_file + content = <<-EOF +void Init_File(void) { + rb_cFile = rb_define_class("File", rb_cIO); + rb_mFConst = rb_define_module_under(rb_cFile, "Constants"); + rb_include_module(rb_cIO, rb_mFConst); + + /* Document-const: LOCK_SH + * + * Shared lock + */ + rb_file_const("LOCK_SH", INT2FIX(LOCK_SH)); +} + EOF + + @parser = util_parser content + + @parser.do_modules + @parser.do_classes + @parser.do_constants + + klass = @parser.classes['rb_mFConst'] + + constants = klass.constants + refute_empty klass.constants + + constant = constants.first + + assert_equal 'LOCK_SH', constant.name + assert_equal 'INT2FIX(LOCK_SH)', constant.value + assert_equal 'Shared lock', constant.comment.text end def test_do_includes @@ -472,7 +530,7 @@ Init_foo() { incl = klass.includes.first assert_equal 'Inc', incl.name - assert_equal '', incl.comment + assert_equal '', incl.comment.text assert_equal @top_level, incl.file end @@ -563,12 +621,63 @@ void Init_Blah(void) { assert methods.first.singleton end + def test_do_missing + parser = util_parser + + klass_a = @top_level.add_class RDoc::ClassModule, 'A' + parser.classes['a'] = klass_a + + parser.enclosure_dependencies['c'] << 'b' + parser.enclosure_dependencies['b'] << 'a' + parser.enclosure_dependencies['d'] << 'a' + + parser.missing_dependencies['d'] = ['d', :class, 'D', 'Object', 'a'] + parser.missing_dependencies['c'] = ['c', :class, 'C', 'Object', 'b'] + parser.missing_dependencies['b'] = ['b', :class, 'B', 'Object', 'a'] + + parser.do_missing + + assert_equal %w[A A::B A::B::C A::D], + @store.all_classes_and_modules.map { |m| m.full_name }.sort + end + + def test_do_missing_cycle + parser = util_parser + + klass_a = @top_level.add_class RDoc::ClassModule, 'A' + parser.classes['a'] = klass_a + + parser.enclosure_dependencies['c'] << 'b' + parser.enclosure_dependencies['b'] << 'a' + + parser.missing_dependencies['c'] = ['c', :class, 'C', 'Object', 'b'] + parser.missing_dependencies['b'] = ['b', :class, 'B', 'Object', 'a'] + + parser.enclosure_dependencies['y'] << 'z' + parser.enclosure_dependencies['z'] << 'y' + + parser.missing_dependencies['y'] = ['y', :class, 'Y', 'Object', 'z'] + parser.missing_dependencies['z'] = ['z', :class, 'Z', 'Object', 'y'] + + _, err = capture_io do + parser.do_missing + end + + expected = 'Unable to create class Y (y), class Z (z) ' + + 'due to a cyclic class or module creation' + + assert_equal expected, err.chomp + + assert_equal %w[A A::B A::B::C], + @store.all_classes_and_modules.map { |m| m.full_name }.sort + end + def test_find_alias_comment - parser = util_parser '' + parser = util_parser comment = parser.find_alias_comment 'C', '[]', 'index' - assert_equal '', comment + assert_equal '', comment.text parser = util_parser <<-C /* @@ -580,27 +689,28 @@ rb_define_alias(C, "[]", "index"); comment = parser.find_alias_comment 'C', '[]', 'index' - assert_equal "/*\n * comment\n */\n\n", comment + assert_equal "/*\n * comment\n */\n\n", comment.text end - def test_find_class_comment_include + def test_find_class_comment @options.rdoc_include << File.dirname(__FILE__) content = <<-EOF /* - * a comment for class Foo - * - * :include: test.txt + * Comment 1 */ -void -Init_Foo(void) { - VALUE foo = rb_define_class("Foo", rb_cObject); -} +foo = rb_define_class("MyClassName1", rb_cObject); + +/* + * Comment 2 + */ +bar = rb_define_class("MyClassName2", rb_cObject); EOF - klass = util_get_class content, 'foo' + util_get_class content - assert_equal "a comment for class Foo\n\ntest file", klass.comment + assert_equal "Comment 1", @parser.classes['foo'].comment.text + assert_equal "Comment 2", @parser.classes['bar'].comment.text end def test_find_class_comment_init @@ -616,7 +726,7 @@ Init_Foo(void) { klass = util_get_class content, 'foo' - assert_equal "a comment for class Foo", klass.comment + assert_equal "a comment for class Foo", klass.comment.text end def test_find_class_comment_define_class @@ -629,7 +739,7 @@ VALUE foo = rb_define_class("Foo", rb_cObject); klass = util_get_class content, 'foo' - assert_equal "a comment for class Foo", klass.comment + assert_equal "a comment for class Foo", klass.comment.text end def test_find_class_comment_define_class_Init_Foo @@ -648,7 +758,7 @@ Init_Foo(void) { klass = util_get_class content, 'foo' - assert_equal "a comment for class Foo on Init", klass.comment + assert_equal "a comment for class Foo on Init", klass.comment.text end def test_find_class_comment_define_class_Init_Foo_no_void @@ -667,7 +777,7 @@ Init_Foo() { klass = util_get_class content, 'foo' - assert_equal "a comment for class Foo on Init", klass.comment + assert_equal "a comment for class Foo on Init", klass.comment.text end def test_find_class_comment_define_class_bogus_comment @@ -687,7 +797,42 @@ Init_Foo(void) { klass = util_get_class content, 'foo' - assert_equal '', klass.comment + assert_equal '', klass.comment.text + end + + def test_find_class_comment_define_class_under + content = <<-EOF +/* + * a comment for class Foo + */ +VALUE foo = rb_define_class_under(rb_cObject, "Foo", rb_cObject); + EOF + + klass = util_get_class content, 'foo' + + assert_equal "a comment for class Foo", klass.comment.text + end + + def test_find_class_comment_define_class_under_Init + content = <<-EOF +/* + * a comment for class Foo on Init + */ +void +Init_Foo(void) { + /* + * a comment for class Foo on rb_define_class + */ + VALUE foo = rb_define_class_under(rb_cObject, "Foo", rb_cObject); +} + EOF + + klass = util_get_class content, 'foo' + + # the inner comment is used since Object::Foo is not necessarily the same + # thing as "Foo" for Init_ + assert_equal "a comment for class Foo on rb_define_class", + klass.comment.text end def test_find_const_comment_rb_define @@ -702,7 +847,7 @@ rb_define_const(cFoo, "CONST", value); comment = parser.find_const_comment 'const', 'CONST' - assert_equal "/*\n * A comment\n */\n", comment + assert_equal "/*\n * A comment\n */\n", comment.text end def test_find_const_comment_document_const @@ -718,7 +863,7 @@ rb_define_const(cFoo, "CONST", value); comment = parser.find_const_comment nil, 'CONST' - assert_equal " *\n * A comment\n */", comment + assert_equal "/*\n *\n * A comment\n */", comment.text end def test_find_const_comment_document_const_full_name @@ -734,7 +879,7 @@ rb_define_const(cFoo, "CONST", value); comment = parser.find_const_comment nil, 'CONST', 'Foo' - assert_equal " *\n * A comment\n */", comment + assert_equal "/*\n *\n * A comment\n */", comment.text end def test_find_body @@ -759,7 +904,7 @@ Init_Foo(void) { assert_equal 'my_method', other_function.name assert_equal "a comment for other_function", - other_function.comment + other_function.comment.text assert_equal '()', other_function.params code = other_function.token_stream.first.text @@ -832,7 +977,7 @@ Init_Foo(void) { other_function = klass.method_list.first assert_equal 'my_method', other_function.name - assert_equal 'a comment for rb_other_function', other_function.comment + assert_equal 'a comment for rb_other_function', other_function.comment.text assert_equal '()', other_function.params assert_equal 118, other_function.offset assert_equal 8, other_function.line @@ -866,7 +1011,7 @@ Init_Foo(void) { other_function = klass.method_list.first assert_equal 'my_method', other_function.name - assert_equal 'a comment for other_function', other_function.comment + assert_equal 'a comment for other_function', other_function.comment.text assert_equal '()', other_function.params assert_equal 39, other_function.offset assert_equal 4, other_function.line @@ -904,11 +1049,11 @@ Init_Foo(void) { bar = methods.first assert_equal 'Foo#bar', bar.full_name - assert_equal "a comment for bar", bar.comment + assert_equal "a comment for bar", bar.comment.text baz = methods.last assert_equal 'Foo#baz', baz.full_name - assert_equal "a comment for bar", baz.comment + assert_equal "a comment for bar", baz.comment.text end def test_find_body_document_method_equals @@ -938,7 +1083,7 @@ Init_zlib() { bar = methods.first assert_equal 'Zlib::GzipWriter#mtime=', bar.full_name - assert_equal 'A comment', bar.comment + assert_equal 'A comment', bar.comment.text end def test_find_body_document_method_same @@ -979,73 +1124,37 @@ Init_Foo(void) { s_bar = methods.first assert_equal 'Foo::bar', s_bar.full_name - assert_equal "a comment for Foo::bar", s_bar.comment + assert_equal "a comment for Foo::bar", s_bar.comment.text bar = methods.last assert_equal 'Foo#bar', bar.full_name - assert_equal "a comment for Foo#bar", bar.comment + assert_equal "a comment for Foo#bar", bar.comment.text end def test_find_modifiers_call_seq - comment = <<-COMMENT -/* call-seq: - * commercial() -> Date
                      - * commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8]
                      - * commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] - * - * If no arguments are given: - * * ruby 1.8: returns a +Date+ for 1582-10-15 (the Day of Calendar Reform in - * Italy) - * * ruby 1.9: returns a +Date+ for julian day 0 - * - * Otherwise, returns a +Date+ for the commercial week year, commercial week, - * and commercial week day given. Ignores the 4th argument. - */ - - COMMENT - - parser = util_parser '' - method_obj = RDoc::AnyMethod.new nil, 'blah' - - parser.find_modifiers comment, method_obj + comment = RDoc::Comment.new <<-COMMENT +call-seq: + commercial() -> Date
                      - expected = <<-CALL_SEQ.chomp -commercial() -> Date
                      -commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8]
                      -commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] - - CALL_SEQ - - assert_equal expected, method_obj.call_seq - end - - def test_find_modifiers_call_seq_no_blank - comment = <<-COMMENT -/* call-seq: - * commercial() -> Date
                      - * commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8]
                      - * commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] - */ +If no arguments are given: COMMENT - parser = util_parser '' + parser = util_parser method_obj = RDoc::AnyMethod.new nil, 'blah' parser.find_modifiers comment, method_obj expected = <<-CALL_SEQ.chomp commercial() -> Date
                      -commercial(cwyear, cweek=41, cwday=5, sg=nil) -> Date [ruby 1.8]
                      -commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] - + CALL_SEQ assert_equal expected, method_obj.call_seq end def test_find_modifiers_nodoc - comment = <<-COMMENT + comment = RDoc::Comment.new <<-COMMENT /* :nodoc: * * Blah @@ -1053,7 +1162,7 @@ commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] COMMENT - parser = util_parser '' + parser = util_parser method_obj = RDoc::AnyMethod.new nil, 'blah' parser.find_modifiers comment, method_obj @@ -1062,7 +1171,7 @@ commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] end def test_find_modifiers_yields - comment = <<-COMMENT + comment = RDoc::Comment.new <<-COMMENT /* :yields: a, b * * Blah @@ -1070,22 +1179,14 @@ commercial(cwyear, cweek=1, cwday=1, sg=nil) -> Date [ruby 1.9] COMMENT - parser = util_parser '' + parser = util_parser method_obj = RDoc::AnyMethod.new nil, 'blah' parser.find_modifiers comment, method_obj assert_equal 'a, b', method_obj.block_params - expected = <<-EXPECTED -/* - * - * Blah - */ - - EXPECTED - - assert_equal expected, comment + assert_equal "\n\nBlah", comment.text end def test_handle_method_args_minus_1 @@ -1206,14 +1307,14 @@ void Init_Blah(void) { end def test_look_for_directives_in - parser = util_parser '' + parser = util_parser - comment = "# :markup: not_rdoc\n" + comment = RDoc::Comment.new "# :other: not_handled\n" parser.look_for_directives_in @top_level, comment - assert_equal "# :markup: not_rdoc\n", comment - assert_equal 'not_rdoc', @top_level.metadata['markup'] + assert_equal "# :other: not_handled\n", comment.text + assert_equal 'not_handled', @top_level.metadata['other'] end def test_define_method @@ -1240,7 +1341,7 @@ Init_IO(void) { klass = util_get_class content, 'rb_cIO' read_method = klass.method_list.first assert_equal "read", read_method.name - assert_equal "Method Comment! ", read_method.comment + assert_equal "Method Comment! ", read_method.comment.text assert_equal "rb_io_s_read", read_method.c_function assert read_method.singleton end @@ -1271,7 +1372,7 @@ Init_IO(void) { klass = util_get_class content, 'rb_cIO' read_method = klass.method_list.first assert_equal "read", read_method.name - assert_equal "Method Comment! ", read_method.comment + assert_equal "Method Comment! ", read_method.comment.text assert_equal "rb_io_s_read", read_method.c_function assert read_method.singleton end @@ -1301,7 +1402,7 @@ Init_IO(void) { read_method = klass.method_list.first assert_equal 'IO#read', read_method.full_name assert_equal :private, read_method.visibility - assert_equal "Method Comment! ", read_method.comment + assert_equal "Method Comment! ", read_method.comment.text end def test_define_method_private_singleton @@ -1329,7 +1430,7 @@ Init_IO(void) { klass = util_get_class content, 'rb_cIO' read_method = klass.method_list.first assert_equal "read", read_method.name - assert_equal "Method Comment! ", read_method.comment + assert_equal "Method Comment! ", read_method.comment.text assert_equal :private, read_method.visibility assert read_method.singleton end @@ -1359,12 +1460,12 @@ Init_IO(void) { klass = util_get_class content, 'rb_cIO' read_method = klass.method_list.first assert_equal "read", read_method.name - assert_equal "Method Comment! ", read_method.comment + assert_equal "Method Comment! ", read_method.comment.text assert read_method.singleton end def test_rb_scan_args - parser = util_parser '' + parser = util_parser assert_equal '(p1)', parser.rb_scan_args('rb_scan_args(a, b, "1",)') @@ -1422,13 +1523,39 @@ Init_IO(void) { parser.rb_scan_args('rb_scan_args(a, b, "*:&",)') end - def util_get_class(content, name) + def test_scan_order_dependent + parser = util_parser <<-C +void a(void) { + mA = rb_define_module("A"); +} + +void b(void) { + cB = rb_define_class_under(mA, "B", rb_cObject); +} + +void c(void) { + mC = rb_define_module_under(cB, "C"); +} + +void d(void) { + mD = rb_define_class_under(mC, "D"); +} + C + + parser.scan + + assert_equal %w[A A::B A::B::C], + @store.all_classes_and_modules.map { |m| m.full_name }.sort + end + + def util_get_class content, name = nil @parser = util_parser content @parser.scan - @parser.classes[name] + + @parser.classes[name] if name end - def util_parser(content) + def util_parser content = '' RDoc::Parser::C.new @top_level, @fn, content, @options, @stats end diff --git a/test/rdoc/test_rdoc_parser_markdown.rb b/test/rdoc/test_rdoc_parser_markdown.rb new file mode 100644 index 0000000000..df0e04d5c1 --- /dev/null +++ b/test/rdoc/test_rdoc_parser_markdown.rb @@ -0,0 +1,55 @@ +require 'rdoc/test_case' + +class TestRDocParserMarkdown < RDoc::TestCase + + def setup + super + + @RP = RDoc::Parser + + @tempfile = Tempfile.new self.class.name + filename = @tempfile.path + + @top_level = @store.add_file filename + @fn = filename + @options = RDoc::Options.new + @stats = RDoc::Stats.new @store, 0 + end + + def teardown + super + + @tempfile.close + end + + def test_file + assert_kind_of RDoc::Parser::Text, util_parser('') + end + + def test_class_can_parse + assert_equal @RP::Markdown, @RP.can_parse('foo.md') + assert_equal @RP::Markdown, @RP.can_parse('foo.md.ja') + + assert_equal @RP::Markdown, @RP.can_parse('foo.markdown') + assert_equal @RP::Markdown, @RP.can_parse('foo.markdown.ja') + end + + def test_scan + parser = util_parser 'it *really* works' + + expected = + @RM::Document.new( + @RM::Paragraph.new('it _really_ works')) + expected.file = @top_level + + parser.scan + + assert_equal expected, @top_level.comment.parse + end + + def util_parser content + RDoc::Parser::Markdown.new @top_level, @fn, content, @options, @stats + end + +end + diff --git a/test/rdoc/test_rdoc_parser_rd.rb b/test/rdoc/test_rdoc_parser_rd.rb new file mode 100644 index 0000000000..b94280f497 --- /dev/null +++ b/test/rdoc/test_rdoc_parser_rd.rb @@ -0,0 +1,52 @@ +require 'rdoc/test_case' + +class TestRDocParserRd < RDoc::TestCase + + def setup + super + + @RP = RDoc::Parser + + @tempfile = Tempfile.new self.class.name + filename = @tempfile.path + + @top_level = @store.add_file filename + @fn = filename + @options = RDoc::Options.new + @stats = RDoc::Stats.new @store, 0 + end + + def teardown + super + + @tempfile.close + end + + def test_file + assert_kind_of RDoc::Parser::Text, util_parser('') + end + + def test_class_can_parse + assert_equal @RP::RD, @RP.can_parse('foo.rd') + assert_equal @RP::RD, @RP.can_parse('foo.rd.ja') + end + + def test_scan + parser = util_parser 'it ((*really*)) works' + + expected = + @RM::Document.new( + @RM::Paragraph.new('it really works')) + expected.file = @top_level + + parser.scan + + assert_equal expected, @top_level.comment.parse + end + + def util_parser content + RDoc::Parser::RD.new @top_level, @fn, content, @options, @stats + end + +end + diff --git a/test/rdoc/test_rdoc_parser_ruby.rb b/test/rdoc/test_rdoc_parser_ruby.rb index 6086b3ec13..b25a36301e 100644 --- a/test/rdoc/test_rdoc_parser_ruby.rb +++ b/test/rdoc/test_rdoc_parser_ruby.rb @@ -1,17 +1,12 @@ # coding: utf-8 -require 'stringio' -require 'tempfile' -require 'rubygems' -require 'minitest/autorun' +require 'rdoc/test_case' -require 'rdoc/options' -require 'rdoc/parser/ruby' -require 'rdoc/stats' - -class TestRDocParserRuby < MiniTest::Unit::TestCase +class TestRDocParserRuby < RDoc::TestCase def setup + super + @tempfile = Tempfile.new self.class.name @filename = @tempfile.path @@ -19,19 +14,32 @@ class TestRDocParserRuby < MiniTest::Unit::TestCase @tempfile2 = Tempfile.new self.class.name @filename2 = @tempfile2.path - util_top_level + @top_level = @store.add_file @filename + @top_level2 = @store.add_file @filename2 + @options = RDoc::Options.new @options.quiet = true @options.option_parser = OptionParser.new - @stats = RDoc::Stats.new 0 + @comment = RDoc::Comment.new '', @top_level + + @stats = RDoc::Stats.new @store, 0 end def teardown + super + @tempfile.close @tempfile2.close end + def mu_pp obj + s = '' + s = PP.pp obj, s + s = s.force_encoding(Encoding.default_external) if defined? Encoding + s.chomp + end + def test_collect_first_comment p = util_parser <<-CONTENT # first @@ -42,7 +50,7 @@ class C; end comment = p.collect_first_comment - assert_equal "# first\n", comment + assert_equal RDoc::Comment.new("# first\n", @top_level), comment end def test_collect_first_comment_encoding @@ -59,67 +67,46 @@ class C; end comment = p.collect_first_comment - assert_equal Encoding::CP852, comment.encoding + assert_equal Encoding::CP852, comment.text.encoding end - def test_extract_call_seq - m = RDoc::AnyMethod.new nil, 'm' - p = util_parser '' + def test_get_class_or_module + ctxt = RDoc::Context.new + ctxt.store = @store - comment = <<-COMMENT - # call-seq: - # bla => true or false - # - # moar comment - COMMENT + cont, name_t, given_name = util_parser('A') .get_class_or_module ctxt - p.extract_call_seq comment, m + assert_equal ctxt, cont + assert_equal 'A', name_t.text + assert_equal 'A', given_name - assert_equal "bla => true or false\n", m.call_seq - end + cont, name_t, given_name = util_parser('A::B') .get_class_or_module ctxt - def test_extract_call_seq_blank - m = RDoc::AnyMethod.new nil, 'm' - p = util_parser '' + assert_equal @store.find_module_named('A'), cont + assert_equal 'B', name_t.text + assert_equal 'A::B', given_name - comment = <<-COMMENT - # call-seq: - # bla => true or false - # - COMMENT + cont, name_t, given_name = util_parser('A:: B').get_class_or_module ctxt - p.extract_call_seq comment, m + assert_equal @store.find_module_named('A'), cont + assert_equal 'B', name_t.text + assert_equal 'A::B', given_name - assert_equal "bla => true or false\n", m.call_seq - end - - def test_extract_call_seq_no_blank - m = RDoc::AnyMethod.new nil, 'm' - p = util_parser '' - - comment = <<-COMMENT - # call-seq: - # bla => true or false - COMMENT - - p.extract_call_seq comment, m - - assert_equal "bla => true or false\n", m.call_seq + assert_raises NoMethodError do + util_parser("A::\nB").get_class_or_module ctxt + end end - def test_extract_call_seq_undent - m = RDoc::AnyMethod.new nil, 'm' - p = util_parser '' + def test_get_class_specification + assert_equal 'A', util_parser('A') .get_class_specification + assert_equal 'A::B', util_parser('A::B').get_class_specification + assert_equal '::A', util_parser('::A').get_class_specification - comment = <<-COMMENT - # call-seq: - # bla => true or false - # moar comment - COMMENT + assert_equal 'self', util_parser('self').get_class_specification - p.extract_call_seq comment, m + assert_equal '', util_parser('').get_class_specification - assert_equal "bla => true or false\nmoar comment\n", m.call_seq + assert_equal '', util_parser('$g').get_class_specification end def test_get_symbol_or_name @@ -149,159 +136,32 @@ class C; end def test_look_for_directives_in_attr util_parser "" - comment = "# :attr: my_attr\n" + comment = RDoc::Comment.new "# :attr: my_attr\n", @top_level @parser.look_for_directives_in @top_level, comment - assert_equal "# :attr: my_attr\n", comment + assert_equal "# :attr: my_attr\n", comment.text - comment = "# :attr_reader: my_method\n" + comment = RDoc::Comment.new "# :attr_reader: my_method\n", @top_level @parser.look_for_directives_in @top_level, comment - assert_equal "# :attr_reader: my_method\n", comment + assert_equal "# :attr_reader: my_method\n", comment.text - comment = "# :attr_writer: my_method\n" + comment = RDoc::Comment.new "# :attr_writer: my_method\n", @top_level @parser.look_for_directives_in @top_level, comment - assert_equal "# :attr_writer: my_method\n", comment - end - - def test_remove_private_comments - util_parser '' - - comment = <<-EOS -# This is text -#-- -# this is private - EOS - - expected = <<-EOS -# This is text - EOS - - @parser.remove_private_comments(comment) - - assert_equal expected, comment - end - - def test_remove_private_comments_encoding - skip "Encoding not implemented" unless Object.const_defined? :Encoding - - util_parser '' - - comment = <<-EOS -# This is text -#-- -# this is private - EOS - comment.force_encoding Encoding::IBM437 - - @parser.remove_private_comments comment - - assert_equal Encoding::IBM437, comment.encoding - end - - def test_remove_private_comments_long - util_parser '' - - comment = <<-EOS -#----- -#++ -# this is text -#----- - EOS - - expected = <<-EOS -# this is text - EOS - - @parser.remove_private_comments(comment) - - assert_equal expected, comment - end - - def test_remove_private_comments_rule - util_parser '' - - comment = <<-EOS -# This is text with a rule: -# --- -# this is also text - EOS - - expected = comment.dup - - @parser.remove_private_comments(comment) - - assert_equal expected, comment - end - - def test_remove_private_comments_toggle - util_parser '' - - comment = <<-EOS -# This is text -#-- -# this is private -#++ -# This is text again. - EOS - - expected = <<-EOS -# This is text -# This is text again. - EOS - - @parser.remove_private_comments(comment) - - assert_equal expected, comment - end - - def test_remove_private_comments_toggle_encoding - skip "Encoding not implemented" unless Object.const_defined? :Encoding - - util_parser '' - - comment = <<-EOS -# This is text -#-- -# this is private -#++ -# This is text again. - EOS - - comment.force_encoding Encoding::IBM437 - - @parser.remove_private_comments comment - - assert_equal Encoding::IBM437, comment.encoding - end - - def test_remove_private_comments_toggle_encoding_ruby_bug? - skip "Encoding not implemented" unless Object.const_defined? :Encoding - - util_parser '' - - comment = <<-EOS -#-- -# this is private -#++ -# This is text again. - EOS - - comment.force_encoding Encoding::IBM437 - - @parser.remove_private_comments comment - - assert_equal Encoding::IBM437, comment.encoding + assert_equal "# :attr_writer: my_method\n", comment.text end def test_look_for_directives_in_commented util_parser "" - comment = "# how to make a section:\n# # :section: new section\n" + comment = RDoc::Comment.new <<-COMMENT, @top_level +# how to make a section: +# # :section: new section + COMMENT @parser.look_for_directives_in @top_level, comment @@ -310,43 +170,48 @@ class C; end assert_equal nil, section.comment assert_equal "# how to make a section:\n# # :section: new section\n", - comment + comment.text end def test_look_for_directives_in_method util_parser "" - comment = "# :method: my_method\n" + comment = RDoc::Comment.new "# :method: my_method\n", @top_level @parser.look_for_directives_in @top_level, comment - assert_equal "# :method: my_method\n", comment + assert_equal "# :method: my_method\n", comment.text - comment = "# :singleton-method: my_method\n" + comment = RDoc::Comment.new "# :singleton-method: my_method\n", @top_level @parser.look_for_directives_in @top_level, comment - assert_equal "# :singleton-method: my_method\n", comment + assert_equal "# :singleton-method: my_method\n", comment.text end def test_look_for_directives_in_section util_parser "" - comment = "# :section: new section\n# woo stuff\n" + comment = RDoc::Comment.new <<-COMMENT, @top_level +# :section: new section +# woo stuff + COMMENT @parser.look_for_directives_in @top_level, comment section = @top_level.current_section assert_equal 'new section', section.title - assert_equal "# woo stuff\n", section.comment + assert_equal [comment("# woo stuff\n", @top_level)], section.comments - assert_equal '', comment + assert_empty comment end def test_look_for_directives_in_unhandled util_parser "" - @parser.look_for_directives_in @top_level, "# :unhandled: blah\n" + comment = RDoc::Comment.new "# :unhandled: blah\n", @top_level + + @parser.look_for_directives_in @top_level, comment assert_equal 'blah', @top_level.metadata['unhandled'] end @@ -420,7 +285,7 @@ class C; end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# my attr\n" + comment = RDoc::Comment.new "##\n# my attr\n", @top_level util_parser "attr :foo, :bar" @@ -432,7 +297,7 @@ class C; end foo = klass.attributes.first assert_equal 'foo', foo.name - assert_equal 'my attr', foo.comment + assert_equal 'my attr', foo.comment.text assert_equal @top_level, foo.file assert_equal 0, foo.offset assert_equal 1, foo.line @@ -443,7 +308,7 @@ class C; end klass.parent = @top_level klass.stop_doc - comment = "##\n# my attr\n" + comment = RDoc::Comment.new "##\n# my attr\n", @top_level util_parser "attr :foo, :bar" @@ -458,7 +323,7 @@ class C; end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# my attr\n" + comment = RDoc::Comment.new "##\n# my attr\n", @top_level util_parser "attr_accessor :foo, :bar" @@ -471,7 +336,7 @@ class C; end foo = klass.attributes.first assert_equal 'foo', foo.name assert_equal 'RW', foo.rw - assert_equal 'my attr', foo.comment + assert_equal 'my attr', foo.comment.text assert_equal @top_level, foo.file assert_equal 0, foo.offset assert_equal 1, foo.line @@ -479,14 +344,14 @@ class C; end bar = klass.attributes.last assert_equal 'bar', bar.name assert_equal 'RW', bar.rw - assert_equal 'my attr', bar.comment + assert_equal 'my attr', bar.comment.text end def test_parse_attr_accessor_nodoc klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# my attr\n" + comment = RDoc::Comment.new "##\n# my attr\n", @top_level util_parser "attr_accessor :foo, :bar # :nodoc:" @@ -502,7 +367,7 @@ class C; end klass.parent = @top_level klass.stop_doc - comment = "##\n# my attr\n" + comment = RDoc::Comment.new "##\n# my attr\n", @top_level util_parser "attr_accessor :foo, :bar" @@ -517,7 +382,7 @@ class C; end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# my attr\n" + comment = RDoc::Comment.new "##\n# my attr\n", @top_level util_parser "attr_writer :foo, :bar" @@ -530,20 +395,20 @@ class C; end foo = klass.attributes.first assert_equal 'foo', foo.name assert_equal 'W', foo.rw - assert_equal "my attr", foo.comment + assert_equal "my attr", foo.comment.text assert_equal @top_level, foo.file bar = klass.attributes.last assert_equal 'bar', bar.name assert_equal 'W', bar.rw - assert_equal "my attr", bar.comment + assert_equal "my attr", bar.comment.text end def test_parse_meta_attr klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :attr: \n# my method\n" + comment = RDoc::Comment.new "##\n# :attr: \n# my method\n", @top_level util_parser "add_my_method :foo, :bar" @@ -555,7 +420,7 @@ class C; end foo = klass.attributes.first assert_equal 'foo', foo.name assert_equal 'RW', foo.rw - assert_equal "my method", foo.comment + assert_equal "my method", foo.comment.text assert_equal @top_level, foo.file end @@ -563,7 +428,8 @@ class C; end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :attr_accessor: \n# my method\n" + comment = + RDoc::Comment.new "##\n# :attr_accessor: \n# my method\n", @top_level util_parser "add_my_method :foo, :bar" @@ -575,7 +441,7 @@ class C; end foo = klass.attributes.first assert_equal 'foo', foo.name assert_equal 'RW', foo.rw - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end @@ -583,7 +449,7 @@ class C; end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :attr: foo\n# my method\n" + comment = RDoc::Comment.new "##\n# :attr: foo\n# my method\n", @top_level util_parser "add_my_method :foo, :bar" @@ -595,7 +461,7 @@ class C; end foo = klass.attributes.first assert_equal 'foo', foo.name assert_equal 'RW', foo.rw - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end @@ -603,7 +469,8 @@ class C; end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :attr_reader: \n# my method\n" + comment = + RDoc::Comment.new "##\n# :attr_reader: \n# my method\n", @top_level util_parser "add_my_method :foo, :bar" @@ -614,7 +481,7 @@ class C; end foo = klass.attributes.first assert_equal 'foo', foo.name assert_equal 'R', foo.rw - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end @@ -623,7 +490,7 @@ class C; end klass.parent = @top_level klass.stop_doc - comment = "##\n# :attr: \n# my method\n" + comment = RDoc::Comment.new "##\n# :attr: \n# my method\n", @top_level util_parser "add_my_method :foo, :bar" @@ -638,7 +505,8 @@ class C; end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :attr_writer: \n# my method\n" + comment = + RDoc::Comment.new "##\n# :attr_writer: \n# my method\n", @top_level util_parser "add_my_method :foo, :bar" @@ -649,12 +517,12 @@ class C; end foo = klass.attributes.first assert_equal 'foo', foo.name assert_equal 'W', foo.rw - assert_equal "my method", foo.comment + assert_equal "my method", foo.comment.text assert_equal @top_level, foo.file end def test_parse_class - comment = "##\n# my class\n" + comment = RDoc::Comment.new "##\n# my class\n", @top_level util_parser "class Foo\nend" @@ -664,7 +532,7 @@ class C; end foo = @top_level.classes.first assert_equal 'Foo', foo.full_name - assert_equal 'my class', foo.comment + assert_equal 'my class', foo.comment.text assert_equal [@top_level], foo.in_files assert_equal 0, foo.offset assert_equal 1, foo.line @@ -681,7 +549,7 @@ end tk = @parser.get_tk - @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = @top_level.classes.first assert_equal 'Foo', foo.full_name @@ -712,7 +580,7 @@ end tk = @parser.get_tk - @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = @top_level.classes.first assert_equal 'Foo', foo.full_name @@ -721,7 +589,7 @@ end end def test_parse_class_nodoc - comment = "##\n# my class\n" + comment = RDoc::Comment.new "##\n# my class\n", @top_level util_parser "class Foo # :nodoc:\nend" @@ -737,10 +605,23 @@ end assert_equal 1, foo.line end + def test_parse_class_single_root + comment = RDoc::Comment.new "##\n# my class\n", @top_level + + util_parser "class << ::Foo\nend" + + tk = @parser.get_tk + + @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment + + foo = @store.all_modules.first + assert_equal 'Foo', foo.full_name + end + def test_parse_class_stopdoc @top_level.stop_doc - comment = "##\n# my class\n" + comment = RDoc::Comment.new "##\n# my class\n", @top_level util_parser "class Foo\nend" @@ -772,7 +653,7 @@ end tk = @parser.get_tk - @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = @top_level.classes.first assert_equal 'Foo', foo.full_name @@ -794,7 +675,7 @@ end tk = @parser.get_tk - @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment const_fail_meta = @top_level.classes.first assert_equal 'ConstFailMeta', const_fail_meta.full_name @@ -803,21 +684,20 @@ end end def test_parse_class_nested_superclass - util_top_level foo = @top_level.add_module RDoc::NormalModule, 'Foo' util_parser "class Bar < Super\nend" tk = @parser.get_tk - @parser.parse_class foo, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_class foo, RDoc::Parser::Ruby::NORMAL, tk, @comment bar = foo.classes.first assert_equal 'Super', bar.superclass end def test_parse_module - comment = "##\n# my module\n" + comment = RDoc::Comment.new "##\n# my module\n", @top_level util_parser "module Foo\nend" @@ -827,13 +707,13 @@ end foo = @top_level.modules.first assert_equal 'Foo', foo.full_name - assert_equal 'my module', foo.comment + assert_equal 'my module', foo.comment.text end def test_parse_module_nodoc @top_level.stop_doc - comment = "##\n# my module\n" + comment = RDoc::Comment.new "##\n# my module\n", @top_level util_parser "module Foo # :nodoc:\nend" @@ -849,7 +729,7 @@ end def test_parse_module_stopdoc @top_level.stop_doc - comment = "##\n# my module\n" + comment = RDoc::Comment.new "##\n# my module\n", @top_level util_parser "module Foo\nend" @@ -859,7 +739,7 @@ end foo = @top_level.modules.first assert_equal 'Foo', foo.full_name - assert_equal 'my module', foo.comment + assert_empty foo.comment end def test_parse_class_colon3 @@ -872,9 +752,24 @@ end util_parser code - @parser.parse_class @top_level, false, @parser.get_tk, '' + @parser.parse_class @top_level, false, @parser.get_tk, @comment + + assert_equal %w[A B], @store.all_classes.map { |c| c.full_name }.sort + end + + def test_parse_class_colon3_self_reference + code = <<-CODE +class A::B + class ::A + end +end + CODE + + util_parser code + + @parser.parse_class @top_level, false, @parser.get_tk, @comment - assert_equal %w[A B], RDoc::TopLevel.classes.map { |c| c.full_name } + assert_equal %w[A A::B], @store.all_classes.map { |c| c.full_name }.sort end def test_parse_class_single @@ -891,23 +786,44 @@ end util_parser code - @parser.parse_class @top_level, false, @parser.get_tk, '' + @parser.parse_class @top_level, false, @parser.get_tk, @comment + + assert_equal %w[A], @store.all_classes.map { |c| c.full_name } - assert_equal %w[A], RDoc::TopLevel.classes.map { |c| c.full_name } - assert_equal %w[A::B A::d], RDoc::TopLevel.modules.map { |c| c.full_name } + modules = @store.all_modules.sort_by { |c| c.full_name } + assert_equal %w[A::B A::d], modules.map { |c| c.full_name } - b = RDoc::TopLevel.modules.first + b = modules.first assert_equal 10, b.offset assert_equal 2, b.line # make sure method/alias was not added to enclosing class/module - a = RDoc::TopLevel.all_classes_hash['A'] + a = @store.classes_hash['A'] assert_empty a.method_list # make sure non-constant-named module will be removed from documentation - d = RDoc::TopLevel.all_modules_hash['A::d'] + d = @store.modules_hash['A::d'] assert d.remove_from_documentation? + end + def test_parse_class_single_gvar + code = <<-CODE +class << $g + def m + end +end + CODE + + util_parser code + + @parser.parse_class @top_level, false, @parser.get_tk, '' + + assert_empty @store.all_classes + mod = @store.all_modules.first + + refute mod.document_self + + assert_empty mod.method_list end # TODO this is really a Context#add_class test @@ -925,13 +841,16 @@ end util_parser code - @parser.parse_module @top_level, false, @parser.get_tk, '' + @parser.parse_module @top_level, false, @parser.get_tk, @comment + + assert_equal %w[A], + @store.all_modules.map { |c| c.full_name } + assert_equal %w[A::B A::C A::Object], + @store.all_classes.map { |c| c.full_name }.sort - assert_equal %w[A], RDoc::TopLevel.modules.map { |c| c.full_name } - assert_equal %w[A::B A::C A::Object], RDoc::TopLevel.classes.map { |c| c.full_name }.sort - assert_equal 'Object', RDoc::TopLevel.classes_hash['A::B'].superclass - assert_equal 'Object', RDoc::TopLevel.classes_hash['A::Object'].superclass - assert_equal 'A::Object', RDoc::TopLevel.classes_hash['A::C'].superclass.full_name + assert_equal 'Object', @store.classes_hash['A::B'].superclass + assert_equal 'Object', @store.classes_hash['A::Object'].superclass + assert_equal 'A::Object', @store.classes_hash['A::C'].superclass.full_name end def test_parse_class_mistaken_for_module @@ -954,7 +873,7 @@ end @parser.scan - assert_equal %w[Foo::Baz], RDoc::TopLevel.modules_hash.keys + assert_equal %w[Foo::Baz], @store.modules_hash.keys assert_empty @top_level.modules foo = @top_level.classes.first @@ -968,9 +887,9 @@ end end def test_parse_class_definition_encountered_after_class_reference - # The code below is not strictly legal Ruby (Foo must have been defined - # before Foo.bar is encountered), but RDoc might encounter Foo.bar before - # Foo if they live in different files. + # The code below is not legal Ruby (Foo must have been defined before + # Foo.bar is encountered), but RDoc might encounter Foo.bar before Foo if + # they live in different files. code = <<-EOF def Foo.bar @@ -984,9 +903,8 @@ end @parser.scan - assert_empty RDoc::TopLevel.modules_hash - # HACK why does it fail? - #assert_empty @top_level.modules + assert_empty @store.modules_hash + assert_empty @store.all_modules foo = @top_level.classes.first assert_equal 'Foo', foo.full_name @@ -997,13 +915,14 @@ end end def test_parse_module_relative_to_top_level_namespace - comment = <<-EOF + comment = RDoc::Comment.new <<-EOF, @top_level # # Weirdly named module # EOF - code = comment + <<-EOF + code = <<-EOF +#{comment.text} module ::Foo class Helper end @@ -1015,7 +934,7 @@ EOF foo = @top_level.modules.first assert_equal 'Foo', foo.full_name - assert_equal 'Weirdly named module', foo.comment + assert_equal 'Weirdly named module', foo.comment.text helper = foo.classes.first assert_equal 'Foo::Helper', helper.full_name @@ -1025,7 +944,7 @@ EOF klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :attr: foo\n# my attr\n" + comment = RDoc::Comment.new "##\n# :attr: foo\n# my attr\n", @top_level util_parser "\n" @@ -1036,7 +955,7 @@ EOF foo = klass.attributes.first assert_equal 'foo', foo.name assert_equal 'RW', foo.rw - assert_equal 'my attr', foo.comment + assert_equal 'my attr', foo.comment.text assert_equal @top_level, foo.file assert_equal 0, foo.offset assert_equal 1, foo.line @@ -1058,7 +977,7 @@ EOF klass.parent = @top_level klass.stop_doc - comment = "##\n# :attr: foo\n# my attr\n" + comment = RDoc::Comment.new "##\n# :attr: foo\n# my attr\n", @top_level util_parser "\n" @@ -1073,7 +992,7 @@ EOF klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :method: foo\n# my method\n" + comment = RDoc::Comment.new "##\n# :method: foo\n# my method\n", @top_level util_parser "\n" @@ -1083,7 +1002,7 @@ EOF foo = klass.method_list.first assert_equal 'foo', foo.name - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file assert_equal 0, foo.offset assert_equal 1, foo.line @@ -1106,9 +1025,10 @@ EOF assert_equal klass.current_section, foo.section stream = [ - tk(:COMMENT, 1, 1, nil, "# File #{@top_level.absolute_name}, line 1"), + tk(:COMMENT, 0, 1, 1, nil, + "# File #{@top_level.absolute_name}, line 1"), RDoc::Parser::Ruby::NEWLINE_TOKEN, - tk(:SPACE, 1, 1, nil, ''), + tk(:SPACE, 0, 1, 1, nil, ''), ] assert_equal stream, foo.token_stream @@ -1119,7 +1039,7 @@ EOF klass.parent = @top_level klass.stop_doc - comment = "##\n# :method: foo\n# my method\n" + comment = RDoc::Comment.new "##\n# :method: foo\n# my method\n", @top_level util_parser "\n" @@ -1131,15 +1051,13 @@ EOF end def test_parse_constant - util_top_level - klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "A = v" tk = @parser.get_tk - @parser.parse_constant klass, tk, '' + @parser.parse_constant klass, tk, @comment foo = klass.constants.first @@ -1150,52 +1068,47 @@ EOF end def test_parse_constant_attrasgn - util_top_level - klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "A[k] = v" tk = @parser.get_tk - @parser.parse_constant klass, tk, '' + @parser.parse_constant klass, tk, @comment assert klass.constants.empty? end def test_parse_constant_alias - util_top_level klass = @top_level.add_class RDoc::NormalClass, 'Foo' - cB = klass.add_class RDoc::NormalClass, 'B' + klass.add_class RDoc::NormalClass, 'B' util_parser "A = B" tk = @parser.get_tk - @parser.parse_constant klass, tk, '' + @parser.parse_constant klass, tk, @comment - assert_equal cB, klass.find_module_named('A') + assert_equal 'Foo::A', klass.find_module_named('A').full_name end def test_parse_constant_alias_same_name foo = @top_level.add_class RDoc::NormalClass, 'Foo' - top_bar = @top_level.add_class RDoc::NormalClass, 'Bar' + @top_level.add_class RDoc::NormalClass, 'Bar' bar = foo.add_class RDoc::NormalClass, 'Bar' - assert RDoc::TopLevel.find_class_or_module('::Bar') + assert @store.find_class_or_module('::Bar') util_parser "A = ::Bar" tk = @parser.get_tk - @parser.parse_constant foo, tk, '' + @parser.parse_constant foo, tk, @comment - assert_equal top_bar, bar.find_module_named('A') + assert_equal 'A', bar.find_module_named('A').full_name end def test_parse_constant_stopdoc - util_top_level - klass = @top_level.add_class RDoc::NormalClass, 'Foo' klass.stop_doc @@ -1203,7 +1116,7 @@ EOF tk = @parser.get_tk - @parser.parse_constant klass, tk, '' + @parser.parse_constant klass, tk, @comment assert_empty klass.constants end @@ -1212,7 +1125,7 @@ EOF klass = RDoc::NormalClass.new 'C' klass.parent = @top_level - comment = "# my include\n" + comment = RDoc::Comment.new "# my include\n", @top_level util_parser "include I" @@ -1224,15 +1137,35 @@ EOF incl = klass.includes.first assert_equal 'I', incl.name - assert_equal 'my include', incl.comment + assert_equal 'my include', incl.comment.text assert_equal @top_level, incl.file end + def test_parse_extend + klass = RDoc::NormalClass.new 'C' + klass.parent = @top_level + + comment = RDoc::Comment.new "# my extend\n", @top_level + + util_parser "extend I" + + @parser.get_tk # extend + + @parser.parse_extend klass, comment + + assert_equal 1, klass.extends.length + + ext = klass.extends.first + assert_equal 'I', ext.name + assert_equal 'my extend', ext.comment.text + assert_equal @top_level, ext.file + end + def test_parse_meta_method klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# my method\n" + comment = RDoc::Comment.new "##\n# my method\n", @top_level util_parser "add_my_method :foo, :bar\nadd_my_method :baz" @@ -1242,7 +1175,7 @@ EOF foo = klass.method_list.first assert_equal 'foo', foo.name - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file assert_equal 0, foo.offset assert_equal 1, foo.line @@ -1265,16 +1198,17 @@ EOF assert_equal klass.current_section, foo.section stream = [ - tk(:COMMENT, 1, 1, nil, "# File #{@top_level.absolute_name}, line 1"), + tk(:COMMENT, 0, 1, 1, nil, + "# File #{@top_level.absolute_name}, line 1"), RDoc::Parser::Ruby::NEWLINE_TOKEN, - tk(:SPACE, 1, 1, nil, ''), - tk(:IDENTIFIER, 1, 0, 'add_my_method', 'add_my_method'), - tk(:SPACE, 1, 13, nil, ' '), - tk(:SYMBOL, 1, 14, nil, ':foo'), - tk(:COMMA, 1, 18, nil, ','), - tk(:SPACE, 1, 19, nil, ' '), - tk(:SYMBOL, 1, 20, nil, ':bar'), - tk(:NL, 1, 24, nil, "\n"), + tk(:SPACE, 0, 1, 1, nil, ''), + tk(:IDENTIFIER, 0, 1, 0, 'add_my_method', 'add_my_method'), + tk(:SPACE, 0, 1, 13, nil, ' '), + tk(:SYMBOL, 0, 1, 14, nil, ':foo'), + tk(:COMMA, 0, 1, 18, nil, ','), + tk(:SPACE, 0, 1, 19, nil, ' '), + tk(:SYMBOL, 0, 1, 20, nil, ':bar'), + tk(:NL, 0, 1, 24, nil, "\n"), ] assert_equal stream, foo.token_stream @@ -1284,7 +1218,7 @@ EOF klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# my method\n" + comment = RDoc::Comment.new "##\n# my method\n", @top_level content = <<-CONTENT inline(:my_method) do |*args| @@ -1298,14 +1232,31 @@ end @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment - assert_nil @parser.get_tk + assert_equal tk(:NL, 0, 3, 3, 3, "\n"), @parser.get_tk + end + + def test_parse_meta_method_define_method + klass = RDoc::NormalClass.new 'Foo' + comment = RDoc::Comment.new "##\n# my method\n", @top_level + + util_parser "define_method :foo do end" + + tk = @parser.get_tk + + @parser.parse_meta_method klass, RDoc::Parser::Ruby::NORMAL, tk, comment + + foo = klass.method_list.first + assert_equal 'foo', foo.name + assert_equal 'my method', foo.comment.text + assert_equal @top_level, foo.file end def test_parse_meta_method_name klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :method: woo_hoo!\n# my method\n" + comment = + RDoc::Comment.new "##\n# :method: woo_hoo!\n# my method\n", @top_level util_parser "add_my_method :foo, :bar\nadd_my_method :baz" @@ -1315,7 +1266,7 @@ end foo = klass.method_list.first assert_equal 'woo_hoo!', foo.name - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end @@ -1323,7 +1274,8 @@ end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :singleton-method:\n# my method\n" + comment = + RDoc::Comment.new "##\n# :singleton-method:\n# my method\n", @top_level util_parser "add_my_method :foo, :bar\nadd_my_method :baz" @@ -1334,7 +1286,7 @@ end foo = klass.method_list.first assert_equal 'foo', foo.name assert_equal true, foo.singleton, 'singleton method' - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end @@ -1342,7 +1294,9 @@ end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# :singleton-method: woo_hoo!\n# my method\n" + comment = + RDoc::Comment.new "##\n# :singleton-method: woo_hoo!\n# my method\n", + @top_level util_parser "add_my_method :foo, :bar\nadd_my_method :baz" @@ -1353,13 +1307,13 @@ end foo = klass.method_list.first assert_equal 'woo_hoo!', foo.name assert_equal true, foo.singleton, 'singleton method' - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end def test_parse_meta_method_string_name klass = RDoc::NormalClass.new 'Foo' - comment = "##\n# my method\n" + comment = RDoc::Comment.new "##\n# my method\n", @top_level util_parser "add_my_method 'foo'" @@ -1369,7 +1323,7 @@ end foo = klass.method_list.first assert_equal 'foo', foo.name - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end @@ -1378,7 +1332,7 @@ end klass.parent = @top_level klass.stop_doc - comment = "##\n# my method\n" + comment = RDoc::Comment.new "##\n# my method\n", @top_level util_parser "add_my_method :foo, :bar\nadd_my_method :baz" @@ -1391,7 +1345,7 @@ end def test_parse_meta_method_unknown klass = RDoc::NormalClass.new 'Foo' - comment = "##\n# my method\n" + comment = RDoc::Comment.new "##\n# my method\n", @top_level util_parser "add_my_method ('foo')" @@ -1401,7 +1355,7 @@ end foo = klass.method_list.first assert_equal 'unknown', foo.name - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file end @@ -1409,7 +1363,7 @@ end klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level - comment = "##\n# my method\n" + comment = RDoc::Comment.new "##\n# my method\n", @top_level util_parser "def foo() :bar end" @@ -1419,7 +1373,7 @@ end foo = klass.method_list.first assert_equal 'foo', foo.name - assert_equal 'my method', foo.comment + assert_equal 'my method', foo.comment.text assert_equal @top_level, foo.file assert_equal 0, foo.offset assert_equal 1, foo.line @@ -1442,19 +1396,20 @@ end assert_equal klass.current_section, foo.section stream = [ - tk(:COMMENT, 1, 1, nil, "# File #{@top_level.absolute_name}, line 1"), + tk(:COMMENT, 0, 1, 1, nil, + "# File #{@top_level.absolute_name}, line 1"), RDoc::Parser::Ruby::NEWLINE_TOKEN, - tk(:SPACE, 1, 1, nil, ''), - tk(:DEF, 1, 0, 'def', 'def'), - tk(:SPACE, 1, 3, nil, ' '), - tk(:IDENTIFIER, 1, 4, 'foo', 'foo'), - tk(:LPAREN, 1, 7, nil, '('), - tk(:RPAREN, 1, 8, nil, ')'), - tk(:SPACE, 1, 9, nil, ' '), - tk(:COLON, 1, 10, nil, ':'), - tk(:IDENTIFIER, 1, 11, 'bar', 'bar'), - tk(:SPACE, 1, 14, nil, ' '), - tk(:END, 1, 15, 'end', 'end'), + tk(:SPACE, 0, 1, 1, nil, ''), + tk(:DEF, 0, 1, 0, 'def', 'def'), + tk(:SPACE, 3, 1, 3, nil, ' '), + tk(:IDENTIFIER, 4, 1, 4, 'foo', 'foo'), + tk(:LPAREN, 7, 1, 7, nil, '('), + tk(:RPAREN, 8, 1, 8, nil, ')'), + tk(:SPACE, 9, 1, 9, nil, ' '), + tk(:COLON, 10, 1, 10, nil, ':'), + tk(:IDENTIFIER, 11, 1, 11, 'bar', 'bar'), + tk(:SPACE, 14, 1, 14, nil, ' '), + tk(:END, 15, 1, 15, 'end', 'end'), ] assert_equal stream, foo.token_stream @@ -1468,19 +1423,34 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment assert klass.aliases.empty? end + def test_parse_method_ampersand + klass = RDoc::NormalClass.new 'Foo' + klass.parent = @top_level + + util_parser "def self.&\nend" + + tk = @parser.get_tk + + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment + + ampersand = klass.method_list.first + assert_equal '&', ampersand.name + assert ampersand.singleton + end + def test_parse_method_false util_parser "def false.foo() :bar end" tk = @parser.get_tk - @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment - klass = RDoc::TopLevel.find_class_named 'FalseClass' + klass = @store.find_class_named 'FalseClass' foo = klass.method_list.first assert_equal 'foo', foo.name @@ -1494,9 +1464,9 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment - assert klass.method_list.empty? + assert_empty klass.method_list end def test_parse_method_gvar @@ -1504,11 +1474,27 @@ end tk = @parser.get_tk - @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment assert @top_level.method_list.empty? end + def test_parse_method_gvar_insane + util_parser "def $stdout.foo() class << $other; end; end" + + tk = @parser.get_tk + + @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment + + assert @top_level.method_list.empty? + + assert_empty @store.all_classes + + assert_equal 1, @store.all_modules.length + + refute @store.all_modules.first.document_self + end + def test_parse_method_internal_gvar klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level @@ -1517,7 +1503,7 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment assert_equal 1, klass.method_list.length end @@ -1530,7 +1516,7 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment assert_equal 1, klass.method_list.length end @@ -1543,7 +1529,7 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment assert_equal 1, klass.method_list.length end @@ -1553,9 +1539,9 @@ end tk = @parser.get_tk - @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment - klass = RDoc::TopLevel.find_class_named 'NilClass' + klass = @store.find_class_named 'NilClass' foo = klass.method_list.first assert_equal 'foo', foo.name @@ -1569,7 +1555,7 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = klass.method_list.first assert_equal '(arg1, arg2 = {})', foo.params @@ -1584,7 +1570,7 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = klass.method_list.first assert_equal '(arg1, arg2)', foo.params @@ -1598,18 +1584,33 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = klass.method_list.first assert_equal '(arg1, arg2, arg3)', foo.params end + def test_parse_method_star + klass = RDoc::NormalClass.new 'Foo' + klass.parent = @top_level + + util_parser "def self.*\nend" + + tk = @parser.get_tk + + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment + + ampersand = klass.method_list.first + assert_equal '*', ampersand.name + assert ampersand.singleton + end + def test_parse_method_stopdoc klass = RDoc::NormalClass.new 'Foo' klass.parent = @top_level klass.stop_doc - comment = "##\n# my method\n" + comment = RDoc::Comment.new "##\n# my method\n", @top_level util_parser "def foo() :bar end" @@ -1627,9 +1628,9 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment - object = RDoc::TopLevel.find_class_named 'Object' + object = @store.find_class_named 'Object' foo = object.method_list.first assert_equal 'Object#foo', foo.full_name @@ -1643,9 +1644,9 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment - object = RDoc::TopLevel.find_class_named 'Object' + object = @store.find_class_named 'Object' foo = object.method_list.first assert_equal 'Object::foo', foo.full_name @@ -1656,9 +1657,9 @@ end tk = @parser.get_tk - @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment - klass = RDoc::TopLevel.find_class_named 'TrueClass' + klass = @store.find_class_named 'TrueClass' foo = klass.method_list.first assert_equal 'foo', foo.name @@ -1677,7 +1678,7 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment omega = klass.method_list.first assert_equal "def \317\211", omega.text @@ -1695,7 +1696,7 @@ module Foo end CODE - @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, '' + @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil foo = @top_level.modules.first assert_equal 'Foo', foo.full_name, 'module Foo' @@ -1706,18 +1707,44 @@ end end def test_parse_statements_class_nested - comment = "##\n# my method\n" + comment = RDoc::Comment.new "##\n# my method\n", @top_level - util_parser "module Foo\n#{comment}class Bar\nend\nend" + util_parser "module Foo\n#{comment.text}class Bar\nend\nend" - @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, '' + @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL foo = @top_level.modules.first assert_equal 'Foo', foo.full_name, 'module Foo' bar = foo.classes.first assert_equal 'Foo::Bar', bar.full_name, 'class Foo::Bar' - assert_equal 'my method', bar.comment + assert_equal 'my method', bar.comment.text + end + + def test_parse_statements_def_percent_string_pound + util_parser "class C\ndef a\n%r{#}\nend\ndef b() end\nend" + + @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL + + x = @top_level.classes.first + + assert_equal 2, x.method_list.length + a = x.method_list.first + + expected = [ + tk(:COMMENT, 0, 2, 1, nil, "# File #{@filename}, line 2"), + tk(:NL, 0, 0, 0, nil, "\n"), + tk(:SPACE, 0, 1, 1, nil, ''), + tk(:DEF, 8, 2, 0, 'def', 'def'), + tk(:SPACE, 11, 2, 3, nil, ' '), + tk(:IDENTIFIER, 12, 2, 4, 'a', 'a'), + tk(:NL, 13, 2, 5, nil, "\n"), + tk(:DREGEXP, 14, 3, 0, nil, '%r{#}'), + tk(:NL, 19, 3, 5, nil, "\n"), + tk(:END, 20, 4, 0, 'end', 'end'), + ] + + assert_equal expected, a.token_stream end def test_parse_statements_encoding @@ -1738,8 +1765,8 @@ end foo = @top_level.classes.first.method_list.first assert_equal 'foo', foo.name - assert_equal 'this is my method', foo.comment - assert_equal Encoding::CP852, foo.comment.encoding + assert_equal 'this is my method', foo.comment.text + assert_equal Encoding::CP852, foo.comment.text.encoding end def test_parse_statements_identifier_meta_method @@ -1822,8 +1849,25 @@ EOF assert_equal 'unknown', @top_level.classes.first.external_aliases[0].old_name end - def test_parse_statements_identifier_constant + def test_parse_statements_identifier_args + comment = "##\n# :args: x\n# :method: b\n# my method\n" + + util_parser "module M\n#{comment}def_delegator :a, :b, :b\nend" + @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL + + m = @top_level.modules.first + assert_equal 'M', m.full_name + + b = m.method_list.first + assert_equal 'M#b', b.full_name + assert_equal 'x', b.params + assert_equal 'my method', b.comment.text + + assert_nil m.params, 'Module parameter not removed' + end + + def test_parse_statements_identifier_constant sixth_constant = <<-EOF Class.new do rule :file do @@ -1934,6 +1978,24 @@ EOF assert_equal 'RW', foo.rw end + def test_parse_statements_identifier_define_method + util_parser <<-RUBY +class C + ## + # :method: a + define_method :a do end + ## + # :method: b + define_method :b do end +end + RUBY + + @parser.parse_statements @top_level + c = @top_level.classes.first + + assert_equal %w[a b], c.method_list.map { |m| m.name } + end + def test_parse_statements_identifier_include content = "class Foo\ninclude Bar\nend" @@ -1991,10 +2053,10 @@ end @parser.parse_statements @top_level - date, date_time = @top_level.classes + date, date_time = @top_level.classes.sort_by { |c| c.full_name } date_now = date.method_list.first - date_time_now = date_time.method_list.first + date_time_now = date_time.method_list.sort_by { |m| m.full_name }.first assert_equal :private, date_now.visibility assert_equal :public, date_time_now.visibility @@ -2016,10 +2078,11 @@ end @parser.parse_statements @top_level - date, date_time = @top_level.classes + # TODO sort classes by default + date, date_time = @top_level.classes.sort_by { |c| c.full_name } date_now = date.method_list.first - date_time_now = date_time.method_list.first + date_time_now = date_time.method_list.sort_by { |m| m.full_name }.first assert_equal :public, date_now.visibility, date_now.full_name assert_equal :private, date_time_now.visibility, date_time_now.full_name @@ -2035,9 +2098,25 @@ end assert_equal 1, @top_level.requires.length end - def test_parse_statements_stopdoc_TkALIAS - util_top_level + def test_parse_statements_identifier_yields + comment = "##\n# :yields: x\n# :method: b\n# my method\n" + + util_parser "module M\n#{comment}def_delegator :a, :b, :b\nend" + + @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL + + m = @top_level.modules.first + assert_equal 'M', m.full_name + + b = m.method_list.first + assert_equal 'M#b', b.full_name + assert_equal 'x', b.block_params + assert_equal 'my method', b.comment.text + + assert_nil m.params, 'Module parameter not removed' + end + def test_parse_statements_stopdoc_TkALIAS klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\nalias old new" @@ -2049,8 +2128,6 @@ end end def test_parse_statements_stopdoc_TkIDENTIFIER_alias_method - util_top_level - klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\nalias_method :old :new" @@ -2062,8 +2139,6 @@ end end def test_parse_statements_stopdoc_TkIDENTIFIER_metaprogrammed - util_top_level - klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\n# attr :meta" @@ -2075,8 +2150,6 @@ end end def test_parse_statements_stopdoc_TkCONSTANT - util_top_level - klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\nA = v" @@ -2087,8 +2160,6 @@ end end def test_parse_statements_stopdoc_TkDEF - util_top_level - klass = @top_level.add_class RDoc::NormalClass, 'Foo' util_parser "\n# :stopdoc:\ndef m\n end" @@ -2098,6 +2169,25 @@ end assert_empty klass.method_list end + def test_parse_statements_super + m = RDoc::AnyMethod.new '', 'm' + util_parser 'super' + + @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, m + + assert m.calls_super + end + + def test_parse_statements_super_no_method + content = "super" + + util_parser content + + @parser.parse_statements @top_level + + assert_nil @parser.get_tk + end + def test_parse_statements_while_begin util_parser <<-RUBY class A @@ -2220,12 +2310,104 @@ end tk = @parser.get_tk - @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, '' + @parser.parse_method klass, RDoc::Parser::Ruby::NORMAL, tk, @comment foo = klass.method_list.first assert_equal 'nth(i)', foo.block_params end + def test_read_directive + parser = util_parser '# :category: test' + + directive, value = parser.read_directive %w[category] + + assert_equal 'category', directive + assert_equal 'test', value + + assert_kind_of RDoc::RubyToken::TkNL, parser.get_tk + end + + def test_read_directive_allow + parser = util_parser '# :category: test' + + directive = parser.read_directive [] + + assert_nil directive + + assert_kind_of RDoc::RubyToken::TkNL, parser.get_tk + end + + def test_read_directive_empty + parser = util_parser '# test' + + directive = parser.read_directive %w[category] + + assert_nil directive + + assert_kind_of RDoc::RubyToken::TkNL, parser.get_tk + end + + def test_read_directive_no_comment + parser = util_parser '' + + directive = parser.read_directive %w[category] + + assert_nil directive + + assert_kind_of RDoc::RubyToken::TkNL, parser.get_tk + end + + def test_read_directive_one_liner + parser = util_parser '; end # :category: test' + + directive, value = parser.read_directive %w[category] + + assert_equal 'category', directive + assert_equal 'test', value + + assert_kind_of RDoc::RubyToken::TkSEMICOLON, parser.get_tk + end + + def test_read_documentation_modifiers + c = RDoc::Context.new + + parser = util_parser '# :category: test' + + parser.read_documentation_modifiers c, %w[category] + + assert_equal 'test', c.current_section.title + end + + def test_read_documentation_modifiers_notnew + m = RDoc::AnyMethod.new nil, 'initialize' + + parser = util_parser '# :notnew: test' + + parser.read_documentation_modifiers m, %w[notnew] + + assert m.dont_rename_initialize + end + + def test_read_documentation_modifiers_not_dash_new + m = RDoc::AnyMethod.new nil, 'initialize' + + parser = util_parser '# :not-new: test' + + parser.read_documentation_modifiers m, %w[not-new] + + assert m.dont_rename_initialize + end + + def test_read_documentation_modifiers_not_new + m = RDoc::AnyMethod.new nil, 'initialize' + + parser = util_parser '# :not_new: test' + + parser.read_documentation_modifiers m, %w[not_new] + + assert m.dont_rename_initialize + end + def test_sanity_integer util_parser '1' assert_equal '1', @parser.get_tk.text @@ -2255,7 +2437,7 @@ end def test_sanity_interpolation_curly util_parser '%{ #{} }' - assert_equal '%{ #{} }', @parser.get_tk.text + assert_equal '%Q{ #{} }', @parser.get_tk.text assert_equal RDoc::RubyToken::TkNL, @parser.get_tk.class end @@ -2312,11 +2494,11 @@ end foo = @top_level.classes.first - assert_equal 'Foo comment', foo.comment + assert_equal 'Foo comment', foo.comment.text m = foo.method_list.first - assert_equal 'm comment', m.comment + assert_equal 'm comment', m.comment.text end def test_scan_block_comment_nested # Issue #41 @@ -2338,12 +2520,12 @@ end foo = @top_level.modules.first assert_equal 'Foo', foo.full_name - assert_equal 'findmeindoc', foo.comment + assert_equal 'findmeindoc', foo.comment.text bar = foo.classes.first assert_equal 'Foo::Bar', bar.full_name - assert_equal '', bar.comment + assert_equal '', bar.comment.text end def test_scan_block_comment_notflush @@ -2386,11 +2568,46 @@ end foo = @top_level.classes.first assert_equal "= DESCRIPTION\n\nThis is a simple test class\n\n= RUMPUS\n\nIs a silly word", - foo.comment + foo.comment.text m = foo.method_list.first - assert_equal 'A nice girl', m.comment + assert_equal 'A nice girl', m.comment.text + end + + def test_scan_constant_nodoc + content = <<-CONTENT # newline is after M is important +module M + + C = v # :nodoc: +end + CONTENT + + util_parser content + + @parser.scan + + c = @top_level.modules.first.constants.first + + assert c.documented? + end + + def test_scan_constant_nodoc_block + content = <<-CONTENT # newline is after M is important +module M + + C = v do # :nodoc: + end +end + CONTENT + + util_parser content + + @parser.scan + + c = @top_level.modules.first.constants.first + + assert c.documented? end def test_scan_meta_method_block @@ -2415,6 +2632,157 @@ class C assert_equal 2, @top_level.classes.first.method_list.length end + def test_scan_markup_override + content = <<-CONTENT +# *awesome* +class C + # :markup: rd + # ((*radical*)) + def m + end +end + CONTENT + + util_parser content + + @parser.scan + + c = @top_level.classes.first + + assert_equal 'rdoc', c.comment.format + + assert_equal 'rd', c.method_list.first.comment.format + end + + def test_scan_markup_first_comment + content = <<-CONTENT +# :markup: rd + +# ((*awesome*)) +class C + # ((*radical*)) + def m + end +end + CONTENT + + util_parser content + + @parser.scan + + c = @top_level.classes.first + + assert_equal 'rd', c.comment.format + + assert_equal 'rd', c.method_list.first.comment.format + end + + def test_scan_tomdoc_meta + util_parser <<-RUBY +# :markup: tomdoc + +class C + + # Signature + # + # find_by_[_and_...](args) + # + # field - A field name. + +end + + RUBY + + @parser.scan + + c = @top_level.classes.first + + m = c.method_list.first + + assert_equal "find_by_[_and_...]", m.name + assert_equal "find_by_[_and_...](args)\n", m.call_seq + + expected = + doc( + head(3, 'Signature'), + list(:NOTE, + item(%w[field], + para('A field name.')))) + expected.file = @top_level + + assert_equal expected, m.comment.parse + end + + def test_scan_stopdoc + util_parser <<-RUBY +class C + # :stopdoc: + class Hidden + end +end + RUBY + + @parser.scan + + c = @top_level.classes.first + + hidden = c.classes.first + + refute hidden.document_self + assert hidden.ignored? + end + + def test_scan_stopdoc_class_alias + util_parser <<-RUBY +# :stopdoc: +module A + B = C +end + RUBY + + @parser.scan + + assert_empty @store.all_classes + + assert_equal 1, @store.all_modules.length + m = @store.all_modules.first + + assert m.ignored? + end + + def test_scan_stopdoc_nested + util_parser <<-RUBY +# :stopdoc: +class A::B +end + RUBY + + @parser.scan + + a = @store.modules_hash['A'] + a_b = @store.classes_hash['A::B'] + + refute a.document_self, 'A is inside stopdoc' + assert a.ignored?, 'A is inside stopdoc' + + refute a_b.document_self, 'A::B is inside stopdoc' + assert a_b.ignored?, 'A::B is inside stopdoc' + end + + def test_scan_struct_self_brackets + util_parser <<-RUBY +class C < M.m + def self.[] + end +end + RUBY + + @parser.scan + + c = @store.find_class_named 'C' + assert_equal %w[C::[]], c.method_list.map { |m| m.full_name } + end + def test_stopdoc_after_comment util_parser <<-EOS module Bar @@ -2433,21 +2801,21 @@ class C foo = @top_level.modules.first.modules.first assert_equal 'Foo', foo.name - assert_equal 'hello', foo.comment + assert_equal 'hello', foo.comment.text baz = @top_level.modules.first.classes.first assert_equal 'Baz', baz.name - assert_equal 'there', baz.comment + assert_equal 'there', baz.comment.text end - def tk(klass, line, char, name, text) + def tk klass, scan, line, char, name, text klass = RDoc::RubyToken.const_get "Tk#{klass.to_s.upcase}" token = if klass.instance_method(:initialize).arity == 3 then - raise ArgumentError, "name not used for #{klass}" unless name.nil? - klass.new nil, line, char + raise ArgumentError, "name not used for #{klass}" if name + klass.new scan, line, char else - klass.new nil, line, char, name + klass.new scan, line, char, name end token.set_text text @@ -2467,11 +2835,5 @@ class C second_file_content, @options, @stats end - def util_top_level - RDoc::TopLevel.reset - @top_level = RDoc::TopLevel.new @filename - @top_level2 = RDoc::TopLevel.new @filename2 - end - end diff --git a/test/rdoc/test_rdoc_parser_simple.rb b/test/rdoc/test_rdoc_parser_simple.rb index 8cedfaa2fc..356ea07504 100644 --- a/test/rdoc/test_rdoc_parser_simple.rb +++ b/test/rdoc/test_rdoc_parser_simple.rb @@ -1,24 +1,22 @@ -require 'tempfile' -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/options' -require 'rdoc/parser' +require 'rdoc/test_case' -class TestRDocParserSimple < MiniTest::Unit::TestCase +class TestRDocParserSimple < RDoc::TestCase def setup + super + @tempfile = Tempfile.new self.class.name filename = @tempfile.path - @top_level = RDoc::TopLevel.new filename + @top_level = @store.add_file filename @fn = filename @options = RDoc::Options.new - @stats = RDoc::Stats.new 0 - - RDoc::TopLevel.reset + @stats = RDoc::Stats.new @store, 0 end def teardown + super + @tempfile.close end @@ -45,7 +43,7 @@ Regular expressions (regexps) are patterns which describe the contents of a string. TEXT - assert_equal expected, @top_level.comment + assert_equal expected, @top_level.comment.text end # RDoc stops processing comments if it finds a comment line CONTAINING @@ -74,21 +72,39 @@ contents of a string. # # --- def test_remove_private_comments - parser = util_parser '' - text = "foo\n\n--\nbar\n++\n\nbaz\n" + parser = util_parser "foo\n\n--\nbar\n++\n\nbaz\n" + + parser.scan - expected = "foo\n\n\n\nbaz\n" + expected = "foo\n\n\nbaz" - assert_equal expected, parser.remove_private_comments(text) + assert_equal expected, @top_level.comment.text + end + + def test_remove_private_comments_rule + parser = util_parser "foo\n---\nbar" + + parser.scan + + expected = "foo\n---\nbar" + + assert_equal expected, @top_level.comment.text end def test_remove_private_comments_star - parser = util_parser '' + parser = util_parser "* foo\n* bar\n" + + parser.scan - text = "* foo\n* bar\n" - expected = text.dup + assert_equal "* foo\n* bar", @top_level.comment.text + end + + def test_scan + parser = util_parser 'it *really* works' + + parser.scan - assert_equal expected, parser.remove_private_comments(text) + assert_equal 'it *really* works', @top_level.comment.text end def util_parser(content) diff --git a/test/rdoc/test_rdoc_rd.rb b/test/rdoc/test_rdoc_rd.rb new file mode 100644 index 0000000000..d917a63661 --- /dev/null +++ b/test/rdoc/test_rdoc_rd.rb @@ -0,0 +1,30 @@ +require 'rdoc/test_case' + +class TestRDocRd < RDoc::TestCase + + def test_class_parse + expected = + @RM::Document.new( + @RM::Paragraph.new('hello')) + + assert_equal expected, RDoc::RD.parse("hello") + end + + def test_class_parse_begin_end + expected = + @RM::Document.new( + @RM::Paragraph.new('hello')) + + assert_equal expected, RDoc::RD.parse("=begin\nhello\n=end\n") + end + + def test_class_parse_newline + expected = + @RM::Document.new( + @RM::Paragraph.new('hello')) + + assert_equal expected, RDoc::RD.parse("hello\n") + end + +end + diff --git a/test/rdoc/test_rdoc_rd_block_parser.rb b/test/rdoc/test_rdoc_rd_block_parser.rb new file mode 100644 index 0000000000..541c26fd89 --- /dev/null +++ b/test/rdoc/test_rdoc_rd_block_parser.rb @@ -0,0 +1,523 @@ +require 'rdoc/test_case' + +class TestRDocRdBlockParser < RDoc::TestCase + + def setup + super + + @block_parser = RDoc::RD::BlockParser.new + end + + def mu_pp(obj) + s = "" + s = PP.pp obj, s + s = s.force_encoding(Encoding.default_external) if defined? Encoding + s.chomp + end + + def test_parse_desclist + list = <<-LIST +:one + desc one +:two + desc two + LIST + + expected = + doc( + @RM::List.new(:NOTE, + @RM::ListItem.new("one", @RM::Paragraph.new("desc one")), + @RM::ListItem.new("two", @RM::Paragraph.new("desc two")))) + + assert_equal expected, parse(list) + end + + def test_parse_enumlist + list = <<-LIST +(1) one +(1) two + LIST + + expected = + doc( + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, @RM::Paragraph.new("one")), + @RM::ListItem.new(nil, @RM::Paragraph.new("two")))) + + assert_equal expected, parse(list) + end + + def test_parse_enumlist_paragraphs + list = <<-LIST +(1) one + + two + LIST + + expected = + doc( + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, + @RM::Paragraph.new("one"), + @RM::Paragraph.new("two")))) + + assert_equal expected, parse(list) + end + + def test_parse_enumlist_multiline + list = <<-LIST +(1) one + two + LIST + + contents = "one\n two" # 1.8 vs 1.9 + + expected = + doc( + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, @RM::Paragraph.new(*contents)))) + + assert_equal expected, parse(list) + end + + def test_parse_enumlist_verbatim + list = <<-LIST +(1) item + verbatim + LIST + + expected = + doc( + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, + @RM::Paragraph.new("item"), + @RM::Verbatim.new("verbatim\n")))) + + assert_equal expected, parse(list) + end + + def test_parse_enumlist_verbatim_continue + list = <<-LIST +(1) one + verbatim + two + LIST + + expected = + doc( + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, + @RM::Paragraph.new("one"), + @RM::Verbatim.new("verbatim\n"), + @RM::Paragraph.new("two")))) + + assert_equal expected, parse(list) + end + + def test_parse_footnote + expected = + doc( + @RM::Paragraph.new("{*1}[rdoc-label:foottext-1:footmark-1]"), + @RM::Rule.new(1), + @RM::Paragraph.new("{^1}[rdoc-label:footmark-1:foottext-1]", "text")) + + assert_equal expected, parse("((-text-))") + end + + def test_parse_include + @block_parser.include_path = [Dir.tmpdir] + + expected = doc(@RM::Include.new("parse_include", [Dir.tmpdir])) + + assert_equal expected, parse("<<< parse_include") + end + + def test_parse_include_subtree + @block_parser.include_path = [Dir.tmpdir] + + expected = + doc( + @RM::BlankLine.new, + @RM::Paragraph.new("include worked"), + @RM::BlankLine.new, + @RM::BlankLine.new) + + Tempfile.open %w[parse_include .rd] do |io| + io.puts "=begin\ninclude ((*worked*))\n=end" + io.flush + + str = <<-STR +<<< #{File.basename io.path} + STR + + assert_equal expected, parse(str) + end + end + + def test_parse_heading + assert_equal doc(@RM::Heading.new(1, "H")), parse("= H") + assert_equal doc(@RM::Heading.new(2, "H")), parse("== H") + assert_equal doc(@RM::Heading.new(3, "H")), parse("=== H") + assert_equal doc(@RM::Heading.new(4, "H")), parse("==== H") + assert_equal doc(@RM::Heading.new(5, "H")), parse("+ H") + assert_equal doc(@RM::Heading.new(6, "H")), parse("++ H") + end + + def test_parse_itemlist + list = <<-LIST +* one +* two + LIST + + expected = + doc( + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, @RM::Paragraph.new("one")), + @RM::ListItem.new(nil, @RM::Paragraph.new("two")))) + + assert_equal expected, parse(list) + end + + def test_parse_itemlist_multiline + list = <<-LIST +* one + two + LIST + + contents = "one\n two" # 1.8 vs 1.9 + + expected = + doc( + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, @RM::Paragraph.new(*contents)))) + + assert_equal expected, parse(list) + end + + def test_parse_itemlist_nest + list = <<-LIST +* one + * inner +* two + LIST + + expected = + doc( + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, + @RM::Paragraph.new("one"), + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, @RM::Paragraph.new("inner")))), + @RM::ListItem.new(nil, + @RM::Paragraph.new("two")))) + + assert_equal expected, parse(list) + end + + def test_parse_itemlist_paragraphs + list = <<-LIST +* one + + two + LIST + + expected = + doc( + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, + @RM::Paragraph.new("one"), + @RM::Paragraph.new("two")))) + + assert_equal expected, parse(list) + end + + def test_parse_itemlist_verbatim + list = <<-LIST +* item + verbatim + LIST + + expected = + doc( + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, + @RM::Paragraph.new("item"), + @RM::Verbatim.new("verbatim\n")))) + + assert_equal expected, parse(list) + end + + def test_parse_itemlist_verbatim_continue + list = <<-LIST +* one + verbatim + two + LIST + + expected = + doc( + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, + @RM::Paragraph.new("one"), + @RM::Verbatim.new("verbatim\n"), + @RM::Paragraph.new("two")))) + + assert_equal expected, parse(list) + end + + def test_parse_lists + list = <<-LIST +(1) one +(1) two +* three +* four +(1) five +(1) six + LIST + + expected = + doc( + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, @RM::Paragraph.new("one")), + @RM::ListItem.new(nil, @RM::Paragraph.new("two"))), + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, @RM::Paragraph.new("three")), + @RM::ListItem.new(nil, @RM::Paragraph.new("four"))), + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, @RM::Paragraph.new("five")), + @RM::ListItem.new(nil, @RM::Paragraph.new("six")))) + + assert_equal expected, parse(list) + end + + def test_parse_lists_nest + list = <<-LIST +(1) one +(1) two + * three + * four +(1) five +(1) six + LIST + + expected = + doc( + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, @RM::Paragraph.new("one")), + @RM::ListItem.new(nil, + @RM::Paragraph.new("two"), + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, @RM::Paragraph.new("three")), + @RM::ListItem.new(nil, @RM::Paragraph.new("four")))), + @RM::ListItem.new(nil, @RM::Paragraph.new("five")), + @RM::ListItem.new(nil, @RM::Paragraph.new("six")))) + + assert_equal expected, parse(list) + end + + def test_parse_lists_nest_verbatim + list = <<-LIST +(1) one +(1) two + * three + * four + verbatim +(1) five +(1) six + LIST + + expected = + doc( + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, @RM::Paragraph.new("one")), + @RM::ListItem.new(nil, + @RM::Paragraph.new("two"), + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, @RM::Paragraph.new("three")), + @RM::ListItem.new(nil, @RM::Paragraph.new("four"))), + @RM::Verbatim.new("verbatim\n")), + @RM::ListItem.new(nil, @RM::Paragraph.new("five")), + @RM::ListItem.new(nil, @RM::Paragraph.new("six")))) + + assert_equal expected, parse(list) + end + + def test_parse_lists_nest_verbatim2 + list = <<-LIST +(1) one +(1) two + * three + * four + verbatim +(1) five +(1) six + LIST + + expected = + doc( + @RM::List.new(:NUMBER, + @RM::ListItem.new(nil, @RM::Paragraph.new("one")), + @RM::ListItem.new(nil, + @RM::Paragraph.new("two"), + @RM::List.new(:BULLET, + @RM::ListItem.new(nil, @RM::Paragraph.new("three")), + @RM::ListItem.new(nil, @RM::Paragraph.new("four"))), + @RM::Verbatim.new("verbatim\n")), + @RM::ListItem.new(nil, @RM::Paragraph.new("five")), + @RM::ListItem.new(nil, @RM::Paragraph.new("six")))) + + assert_equal expected, parse(list) + end + + def test_parse_methodlist + list = <<-LIST +--- Array#each {|i| ... } + yield block for each item. +--- Array#index(val) + return index of first item which equals with val. if it hasn't + same item, return nil. + LIST + + expected = + doc( + @RM::List.new(:LABEL, + @RM::ListItem.new( + "Array#each {|i| ... }", + @RM::Paragraph.new("yield block for each item.")), + @RM::ListItem.new( + "Array#index(val)", + @RM::Paragraph.new("return index of first item which equals with val. if it hasn't same item, return nil.")))) + + assert_equal expected, parse(list) + end + + def test_parse_methodlist_empty + list = <<-LIST +--- A#b + + LIST + + expected = + doc( + @RM::List.new(:LABEL, + @RM::ListItem.new("A#b"))) + + assert_equal expected, parse(list) + end + + def test_parse_methodlist_paragraph + list = <<-LIST +--- A#b + + one + LIST + + expected = + doc( + @RM::List.new(:LABEL, + @RM::ListItem.new( + "A#b", + @RM::Paragraph.new("one")))) + + assert_equal expected, parse(list) + end + + def test_parse_methodlist_paragraph2 + list = <<-LIST.chomp +--- A#b + + one +two + LIST + + expected = + doc( + @RM::List.new(:LABEL, + @RM::ListItem.new( + "A#b", + @RM::Paragraph.new("one"))), + @RM::Paragraph.new("two")) + + assert_equal expected, parse(list) + end + + def test_parse_methodlist_paragraph_verbatim + list = <<-LIST.chomp +--- A#b + + text + verbatim + LIST + + expected = + doc( + @RM::List.new(:LABEL, + @RM::ListItem.new( + "A#b", + @RM::Paragraph.new("text"), + @RM::Verbatim.new("verbatim\n")))) + + assert_equal expected, parse(list) + end + + def test_parse_verbatim + assert_equal doc(@RM::Verbatim.new("verbatim\n")), parse(" verbatim") + end + + def test_parse_verbatim_blankline + expected = doc(@RM::Verbatim.new("one\n", "\n", "two\n")) + + verbatim = <<-VERBATIM + one + + two + VERBATIM + + assert_equal expected, parse(verbatim) + end + + def test_parse_verbatim_indent + expected = doc(@RM::Verbatim.new("one\n", " two\n")) + + verbatim = <<-VERBATIM + one + two + VERBATIM + + assert_equal expected, parse(verbatim) + end + + def test_parse_verbatim_multi + expected = doc(@RM::Verbatim.new("one\n", "two\n")) + + verbatim = <<-VERBATIM + one + two + VERBATIM + + assert_equal expected, parse(verbatim) + end + + def test_parse_textblock + assert_equal doc(@RM::Paragraph.new("text")), parse("text") + end + + def test_parse_textblock_multi + expected = doc(@RM::Paragraph.new("one two")) + + assert_equal expected, parse("one\ntwo") + end + + def parse text + text = ["=begin", text, "=end"].join "\n" + + doc = @block_parser.parse text.lines.to_a + + assert_equal @RM::BlankLine.new, doc.parts.shift, "=begin blankline" + assert_equal @RM::BlankLine.new, doc.parts.pop, "=end blankline" + + doc + end + +end + diff --git a/test/rdoc/test_rdoc_rd_inline.rb b/test/rdoc/test_rdoc_rd_inline.rb new file mode 100644 index 0000000000..d601ecca1a --- /dev/null +++ b/test/rdoc/test_rdoc_rd_inline.rb @@ -0,0 +1,63 @@ +require 'rdoc/test_case' + +class TestRDocRdInline < RDoc::TestCase + + def setup + super + + @inline = RDoc::RD::Inline.new '+text+', 'text' + end + + def test_class_new + inline = RDoc::RD::Inline.new @inline + + refute_equal inline.rdoc, inline.reference + end + + def test_initialize + inline = RDoc::RD::Inline.new 'text' + + assert_equal inline.rdoc, inline.reference + refute_same inline.rdoc, inline.reference + end + + def test_initialize_inline + inline = RDoc::RD::Inline.new @inline + + assert_equal '+text+', inline.rdoc + assert_equal 'text', inline.reference + end + + def test_append_inline + out = @inline.append @inline + + assert_same @inline, out + + assert_equal '+text++text+', @inline.rdoc + assert_equal 'texttext', @inline.reference + end + + def test_append_string + @inline.append ' more' + + assert_equal '+text+ more', @inline.rdoc + assert_equal 'text more', @inline.reference + end + + def test_equals2 + assert_equal @inline, RDoc::RD::Inline.new('+text+', 'text') + refute_equal @inline, RDoc::RD::Inline.new('+text+', 'other') + refute_equal @inline, RDoc::RD::Inline.new('+other+', 'text') + refute_equal @inline, Object.new + end + + def test_inspect + assert_equal '(inline: +text+)', @inline.inspect + end + + def test_to_s + assert_equal '+text+', @inline.to_s + end + +end + diff --git a/test/rdoc/test_rdoc_rd_inline_parser.rb b/test/rdoc/test_rdoc_rd_inline_parser.rb new file mode 100644 index 0000000000..6b6c00f886 --- /dev/null +++ b/test/rdoc/test_rdoc_rd_inline_parser.rb @@ -0,0 +1,173 @@ +require 'rdoc/test_case' + +class TestRDocRdInlineParser < RDoc::TestCase + + def setup + super + + @block_parser = RDoc::RD::BlockParser.new + @block_parser.instance_variable_set :@i, 0 + @inline_parser = RDoc::RD::InlineParser.new @block_parser + end + + def test_parse + assert_equal 'regular emphasis', parse('regular ((*emphasis*))') + end + + def test_parse_code + assert_equal 'text', parse('(({text}))') + end + + def test_parse_em + assert_equal 'text', parse('((*text*))') + end + + def test_parse_footnote + assert_equal '{*1}[rdoc-label:foottext-1:footmark-1]', parse('((-text-))') + + expected = [ + @RM::Paragraph.new('{^1}[rdoc-label:footmark-1:foottext-1]', 'text') + ] + + assert_equal expected, @block_parser.footnotes + end + + def test_parse_index + assert_equal 'text', parse('((:text:))') + + assert_includes @block_parser.labels, 'text' + end + + def test_parse_kbd + assert_equal 'text', parse('((%text%))') + end + + def test_parse_multiple + assert_equal 'one two', parse('((*one*)) ((*two*))') + end + + def test_parse_newline + assert_equal "one\ntwo", parse("one\ntwo") + end + + def test_parse_quote + assert_equal 'one " two', parse('one " two') + end + + def test_parse_ref + assert_equal '{text}[rdoc-label:text]', parse('(())') + end + + def test_parse_ref_em + assert_equal '{text}[rdoc-label:text]', parse('((<((*text*))>))') + end + + def test_parse_ref_filename_quote + assert_equal '{RD/foo}[rdoc-label:RD/foo]', parse('(())') + end + + def test_parse_ref_filename + assert_equal '{RD}[rdoc-label:RD/]', parse('(())') + end + + def test_parse_ref_quote + assert_equal '{text \\"}[rdoc-label:text \\"]', parse('(())') + end + + def test_parse_ref_quote_content + assert_equal '{text}[rdoc-label:text]', + parse('((<"((*text*))">))') + end + + def test_parse_ref_quote_content_multi + assert_equal '{one two}[rdoc-label:one two]', + parse('((<"((*one*)) ((*two*))">))') + end + + def test_parse_ref_substitute + assert_equal '{text}[rdoc-label:thing]', parse('(())') + end + + def test_parse_ref_substitute_element_quote + assert_equal '{text}[rdoc-label:"RD"]', + parse('(())') + end + + def test_parse_ref_substitute_filename + assert_equal '{text}[rdoc-label:RD/]', parse('(())') + end + + def test_parse_ref_substitute_filename_label + assert_equal '{text}[rdoc-label:RD/label]', + parse('(())') + end + + def test_parse_ref_substitute_filename_quote + assert_equal '{text}[rdoc-label:"RD"/]', parse('(())') + end + + def test_parse_ref_substitute_multi_content + assert_equal '{one two}[rdoc-label:thing]', + parse('((<((*one*)) two|thing>))') + end + + def test_parse_ref_substitute_multi_content2 + assert_equal '{one \\" two}[rdoc-label:thing]', + parse('((<((*one*)) \" two|thing>))') + end + + def test_parse_ref_substitute_multi_content3 + assert_equal '{one \\" two}[rdoc-label:thing]', + parse('((<((*one*)) \" ((*two*))|thing>))') + end + + def test_parse_ref_substitute_quote + assert_equal '{one | two}[rdoc-label:thing]', + parse('((<"one | two"|thing>))') + end + + def test_parse_ref_substitute_quote_content + assert_equal '{text}[rdoc-label:thing]', + parse('((<"((*text*))"|thing>))') + end + + def test_parse_ref_substitute_url + assert_equal '{text}[http://example]', + parse('(())') + end + + def test_parse_ref_url + assert_equal '{http://example}[http://example]', + parse('(())') + end + + def test_parse_var + assert_equal '+text+', parse('((|text|))') + end + + def test_parse_verb + assert_equal 'text', parse("(('text'))") + end + + def test_parse_verb_backslash + assert_equal "(('text'))", parse("(('(('text\\'))'))") + end + + def test_parse_verb_backslash_backslash + assert_equal 'text \\', parse("(('text \\\\'))") + end + + def test_parse_verb_backslash_quote + assert_equal 'text "', parse("(('text \\\"'))") + end + + def test_parse_verb_multiple + assert_equal '((*text*))', parse("(('((*text*))'))") + end + + def parse text + @inline_parser.parse text + end + +end + diff --git a/test/rdoc/test_rdoc_rdoc.rb b/test/rdoc/test_rdoc_rdoc.rb index aedccc9dbf..fd6b3f81e4 100644 --- a/test/rdoc/test_rdoc_rdoc.rb +++ b/test/rdoc/test_rdoc_rdoc.rb @@ -1,47 +1,107 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/rdoc' +require 'rdoc/test_case' -require 'fileutils' -require 'tempfile' -require 'tmpdir' - -class TestRDocRDoc < MiniTest::Unit::TestCase +class TestRDocRDoc < RDoc::TestCase def setup - RDoc::TopLevel.reset + super @rdoc = RDoc::RDoc.new @rdoc.options = RDoc::Options.new - @stats = RDoc::Stats.new 0, 0 + @stats = RDoc::Stats.new @store, 0, 0 @rdoc.instance_variable_set :@stats, @stats end - def test_class_reset - tl = RDoc::TopLevel.new 'file.rb' - tl.add_class RDoc::NormalClass, 'C' - tl.add_class RDoc::NormalModule, 'M' + def test_document # functional test + options = RDoc::Options.new + options.files = [File.expand_path('../xref_data.rb')] + options.setup_generator 'ri' + options.main_page = 'MAIN_PAGE.rdoc' + options.title = 'title' - c = RDoc::Parser::C - enclosure_classes = c.send :class_variable_get, :@@enclosure_classes - enclosure_classes['A'] = 'B' - known_bodies = c.send :class_variable_get, :@@known_bodies - known_bodies['A'] = 'B' + rdoc = RDoc::RDoc.new - RDoc::RDoc.reset + temp_dir do + capture_io do + rdoc.document options + end - assert_empty RDoc::TopLevel.all_classes_hash - assert_empty RDoc::TopLevel.all_files_hash - assert_empty RDoc::TopLevel.all_modules_hash + assert File.directory? 'doc' + assert_equal rdoc, rdoc.store.rdoc + end - assert_empty c.send :class_variable_get, :@@enclosure_classes - assert_empty c.send :class_variable_get, :@@known_bodies + store = rdoc.store + + assert_equal 'MAIN_PAGE.rdoc', store.main + assert_equal 'title', store.title end def test_gather_files - file = File.expand_path __FILE__ - assert_equal [file], @rdoc.gather_files([file, file]) + a = File.expand_path __FILE__ + b = File.expand_path '../test_rdoc_text.rb', __FILE__ + + assert_equal [a, b], @rdoc.gather_files([b, a, b]) + end + + def test_handle_pipe + $stdin = StringIO.new "hello" + + out, = capture_io do + @rdoc.handle_pipe + end + + assert_equal "\n

                      hello

                      \n", out + ensure + $stdin = STDIN + end + + def test_handle_pipe_rd + $stdin = StringIO.new "=begin\nhello\n=end" + + @rdoc.options.markup = 'rd' + + out, = capture_io do + @rdoc.handle_pipe + end + + assert_equal "\n

                      hello

                      \n", out + ensure + $stdin = STDIN + end + + def test_load_options + temp_dir do + options = RDoc::Options.new + options.markup = 'tomdoc' + options.write_options + + options = @rdoc.load_options + + assert_equal 'tomdoc', options.markup + end + end + + def test_load_options_invalid + temp_dir do + open '.rdoc_options', 'w' do |io| + io.write "a: !ruby.yaml.org,2002:str |\nfoo" + end + + e = assert_raises RDoc::Error do + @rdoc.load_options + end + + options_file = File.expand_path '.rdoc_options' + assert_equal "#{options_file} is not a valid rdoc options file", e.message + end + end + + def load_options_no_file + temp_dir do + options = @rdoc.load_options + + assert_kind_of RDoc::Options, options + end end def test_normalized_file_list @@ -62,9 +122,29 @@ class TestRDocRDoc < MiniTest::Unit::TestCase assert_empty files end + def test_normalized_file_list_non_file_directory + skip '/dev/stdin is not a character special' unless + File.chardev? '/dev/stdin' + + files = nil + + out, err = capture_io do + files = @rdoc.normalized_file_list %w[/dev/stdin] + end + + files = files.map { |file| File.expand_path file } + + assert_empty files + + assert_empty out + assert_match %r%^rdoc can't parse%, err + assert_match %r%/dev/stdin$%, err + end + def test_parse_file_encoding skip "Encoding not implemented" unless Object.const_defined? :Encoding @rdoc.options.encoding = Encoding::ISO_8859_1 + @rdoc.store = RDoc::Store.new Tempfile.open 'test.txt' do |io| io.write 'hi' @@ -76,6 +156,31 @@ class TestRDocRDoc < MiniTest::Unit::TestCase end end + def test_parse_file_forbidden + @rdoc.store = RDoc::Store.new + + Tempfile.open 'test.txt' do |io| + io.write 'hi' + io.rewind + + File.chmod 0000, io.path + + begin + top_level = :bug + + _, err = capture_io do + top_level = @rdoc.parse_file io.path + end + + assert_match "Unable to read #{io.path},", err + + assert_nil top_level + ensure + File.chmod 0400, io.path + end + end + end + def test_remove_unparseable file_list = %w[ blah.class @@ -89,9 +194,35 @@ class TestRDocRDoc < MiniTest::Unit::TestCase assert_empty @rdoc.remove_unparseable file_list end - def test_setup_output_dir - skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir + def test_remove_unparseable_tags_emacs + temp_dir do + open 'TAGS', 'w' do |io| # emacs + io.write "\f\nlib/foo.rb,43\n" + end + + file_list = %w[ + TAGS + ] + + assert_empty @rdoc.remove_unparseable file_list + end + end + def test_remove_unparseable_tags_vim + temp_dir do + open 'TAGS', 'w' do |io| # emacs + io.write "!_TAG_" + end + + file_list = %w[ + TAGS + ] + + assert_empty @rdoc.remove_unparseable file_list + end + end + + def test_setup_output_dir Dir.mktmpdir {|d| path = File.join d, 'testdir' @@ -105,8 +236,6 @@ class TestRDocRDoc < MiniTest::Unit::TestCase end def test_setup_output_dir_dry_run - skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir - @rdoc.options.dry_run = true Dir.mktmpdir do |d| @@ -119,8 +248,6 @@ class TestRDocRDoc < MiniTest::Unit::TestCase end def test_setup_output_dir_exists - skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir - Dir.mktmpdir {|path| open @rdoc.output_flag_file(path), 'w' do |io| io.puts Time.at 0 @@ -135,8 +262,6 @@ class TestRDocRDoc < MiniTest::Unit::TestCase end def test_setup_output_dir_exists_empty_created_rid - skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir - Dir.mktmpdir {|path| open @rdoc.output_flag_file(path), 'w' do end @@ -162,8 +287,6 @@ class TestRDocRDoc < MiniTest::Unit::TestCase end def test_setup_output_dir_exists_not_rdoc - skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir - Dir.mktmpdir do |dir| e = assert_raises RDoc::Error do @rdoc.setup_output_dir dir, false @@ -174,8 +297,6 @@ class TestRDocRDoc < MiniTest::Unit::TestCase end def test_update_output_dir - skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir - Dir.mktmpdir do |d| @rdoc.update_output_dir d, Time.now, {} @@ -184,8 +305,6 @@ class TestRDocRDoc < MiniTest::Unit::TestCase end def test_update_output_dir_dont - skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir - Dir.mktmpdir do |d| @rdoc.options.update_output_dir = false @rdoc.update_output_dir d, Time.now, {} @@ -195,8 +314,6 @@ class TestRDocRDoc < MiniTest::Unit::TestCase end def test_update_output_dir_dry_run - skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir - Dir.mktmpdir do |d| @rdoc.options.dry_run = true @rdoc.update_output_dir d, Time.now, {} diff --git a/test/rdoc/test_rdoc_ri_driver.rb b/test/rdoc/test_rdoc_ri_driver.rb index e219993e57..8fb91c5e1c 100644 --- a/test/rdoc/test_rdoc_ri_driver.rb +++ b/test/rdoc/test_rdoc_ri_driver.rb @@ -1,16 +1,9 @@ -require 'pp' -require 'rubygems' -require 'minitest/autorun' -require 'tmpdir' -require 'fileutils' -require 'stringio' -require 'rdoc/ri/driver' -require 'rdoc/rdoc' +require 'rdoc/test_case' -class TestRDocRIDriver < MiniTest::Unit::TestCase +class TestRDocRIDriver < RDoc::TestCase def setup - @RM = RDoc::Markup + super @tmpdir = File.join Dir.tmpdir, "test_rdoc_ri_driver_#{$$}" @home_ri = File.join @tmpdir, 'dot_ri' @@ -23,14 +16,22 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase ENV['HOME'] = @tmpdir ENV.delete 'RI' - @options = RDoc::RI::Driver.process_args [] - @options[:home] = @tmpdir + @options = RDoc::RI::Driver.default_options + @options[:use_system] = false + @options[:use_site] = false + @options[:use_home] = false + @options[:use_gems] = false + + @options[:home] = @tmpdir @options[:use_stdout] = true - @options[:formatter] = @RM::ToRdoc + @options[:formatter] = @RM::ToRdoc + @driver = RDoc::RI::Driver.new @options end def teardown + super + ENV['HOME'] = @orig_home ENV['RI'] = @orig_ri FileUtils.rm_rf @tmpdir @@ -56,7 +57,7 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase util_store out, = capture_io do - RDoc::RI::Driver.dump @store.cache_path + RDoc::RI::Driver.dump @store1.cache_path end assert_match %r%:class_methods%, out @@ -85,8 +86,8 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase expected = @RM::Document.new( @RM::Rule.new(1), @RM::Paragraph.new('Also found in:'), - @RM::Verbatim.new("ruby core\n", - "~/.ri\n")) + @RM::Verbatim.new("ruby core", "\n", + "~/.rdoc", "\n")) assert_equal expected, out end @@ -107,26 +108,44 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase def test_add_from util_store - @store.type = :system + @store1.type = :system out = @RM::Document.new - @driver.add_from out, @store + @driver.add_from out, @store1 expected = @RM::Document.new @RM::Paragraph.new("(from ruby core)") assert_equal expected, out end - def test_add_includes_empty + def test_add_extends + util_store + out = @RM::Document.new - @driver.add_includes out, [] + @driver.add_extends out, [[[@cFooExt], @store1]] + + expected = @RM::Document.new( + @RM::Rule.new(1), + @RM::Heading.new(1, "Extended by:"), + @RM::Paragraph.new("Ext (from #{@store1.friendly_path})"), + @RM::BlankLine.new, + @RM::Paragraph.new("Extend thingy"), + @RM::BlankLine.new) + + assert_equal expected, out + end + + def test_add_extension_modules_empty + out = @RM::Document.new + + @driver.add_extension_modules out, 'Includes', [] assert_empty out end - def test_add_includes_many + def test_add_extension_modules_many util_store out = @RM::Document.new @@ -134,23 +153,23 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase enum = RDoc::Include.new 'Enumerable', nil @cFoo.add_include enum - @driver.add_includes out, [[[@cFooInc, enum], @store]] + @driver.add_extension_modules out, 'Includes', [[[@cFooInc, enum], @store1]] expected = @RM::Document.new( @RM::Rule.new(1), @RM::Heading.new(1, "Includes:"), - @RM::Paragraph.new("(from #{@store.friendly_path})"), + @RM::Paragraph.new("(from #{@store1.friendly_path})"), @RM::BlankLine.new, @RM::Paragraph.new("Inc"), @RM::BlankLine.new, @RM::Paragraph.new("Include thingy"), @RM::BlankLine.new, - @RM::Verbatim.new("Enumerable\n")) + @RM::Verbatim.new("Enumerable", "\n")) assert_equal expected, out end - def test_add_includes_many_no_doc + def test_add_extension_modules_many_no_doc util_store out = @RM::Document.new @@ -159,29 +178,29 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase @cFoo.add_include enum @cFooInc.instance_variable_set :@comment, '' - @driver.add_includes out, [[[@cFooInc, enum], @store]] + @driver.add_extension_modules out, 'Includes', [[[@cFooInc, enum], @store1]] expected = @RM::Document.new( @RM::Rule.new(1), @RM::Heading.new(1, "Includes:"), - @RM::Paragraph.new("(from #{@store.friendly_path})"), - @RM::Verbatim.new("Inc\n", - "Enumerable\n")) + @RM::Paragraph.new("(from #{@store1.friendly_path})"), + @RM::Verbatim.new("Inc", "\n", + "Enumerable", "\n")) assert_equal expected, out end - def test_add_includes_one + def test_add_extension_modules_one util_store out = @RM::Document.new - @driver.add_includes out, [[[@cFooInc], @store]] + @driver.add_extension_modules out, 'Includes', [[[@cFooInc], @store1]] expected = @RM::Document.new( @RM::Rule.new(1), @RM::Heading.new(1, "Includes:"), - @RM::Paragraph.new("Inc (from #{@store.friendly_path})"), + @RM::Paragraph.new("Inc (from #{@store1.friendly_path})"), @RM::BlankLine.new, @RM::Paragraph.new("Include thingy"), @RM::BlankLine.new) @@ -189,6 +208,137 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase assert_equal expected, out end + def test_add_includes + util_store + + out = @RM::Document.new + + @driver.add_includes out, [[[@cFooInc], @store1]] + + expected = @RM::Document.new( + @RM::Rule.new(1), + @RM::Heading.new(1, "Includes:"), + @RM::Paragraph.new("Inc (from #{@store1.friendly_path})"), + @RM::BlankLine.new, + @RM::Paragraph.new("Include thingy"), + @RM::BlankLine.new) + + assert_equal expected, out + end + + def test_add_method + util_store + + out = doc + + @driver.add_method out, 'Foo::Bar#blah' + + expected = + doc( + head(1, 'Foo::Bar#blah'), + blank_line, + para('(from ~/.rdoc)'), + head(3, 'Implementation from Bar'), + rule(1), + verb("blah(5) => 5\n", + "blah(6) => 6\n"), + rule(1), + blank_line, + blank_line) + + assert_equal expected, out + end + + def test_add_method_attribute + util_store + + out = doc + + @driver.add_method out, 'Foo::Bar#attr' + + expected = + doc( + head(1, 'Foo::Bar#attr'), + blank_line, + para('(from ~/.rdoc)'), + rule(1), + blank_line, + blank_line) + + assert_equal expected, out + end + + def test_add_method_inherited + util_multi_store + + out = doc + + @driver.add_method out, 'Bar#inherit' + + expected = + doc( + head(1, 'Bar#inherit'), + blank_line, + para('(from ~/.rdoc)'), + head(3, 'Implementation from Foo'), + rule(1), + blank_line, + blank_line) + + assert_equal expected, out + end + + def test_add_method_overriden + util_multi_store + + out = doc + + @driver.add_method out, 'Bar#override' + + expected = + doc( + head(1, 'Bar#override'), + blank_line, + para("(from #{@store2.path})"), + rule(1), + blank_line, + para('must be displayed'), + blank_line, + blank_line) + + assert_equal expected, out + end + + def test_add_method_documentation + util_store + + out = doc() + + missing = RDoc::AnyMethod.new nil, 'missing' + @cFoo.add_method missing + + @driver.add_method_documentation out, @cFoo + + expected = + doc( + head(1, 'Foo#inherit'), + blank_line, + para('(from ~/.rdoc)'), + rule(1), + blank_line, + blank_line, + head(1, 'Foo#override'), + blank_line, + para('(from ~/.rdoc)'), + rule(1), + blank_line, + para('must not be displayed in Bar#override'), + blank_line, + blank_line) + + assert_equal expected, out + end + def test_add_method_list out = @RM::Document.new @@ -241,35 +391,48 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase expected = { 'Ambiguous' => [@store1, @store2], 'Bar' => [@store2], - 'Foo' => [@store1], + 'Ext' => [@store1], + 'Foo' => [@store1, @store2], 'Foo::Bar' => [@store1], 'Foo::Baz' => [@store1, @store2], 'Inc' => [@store1], } - assert_equal expected, @driver.classes + classes = @driver.classes + + assert_equal expected.keys.sort, classes.keys.sort + + expected.each do |klass, stores| + assert_equal stores, classes[klass].sort_by { |store| store.path }, + "mismatch for #{klass}" + end end def test_class_document util_store - tl1 = RDoc::TopLevel.new 'one.rb' - tl2 = RDoc::TopLevel.new 'two.rb' + tl1 = @store1.add_file 'one.rb' + tl2 = @store1.add_file 'two.rb' @cFoo.add_comment 'one', tl1 @cFoo.add_comment 'two', tl2 - @store.save_class @cFoo + + @store1.save_class @cFoo found = [ - [@store, @store.load_class(@cFoo.full_name)] + [@store1, @store1.load_class(@cFoo.full_name)] ] - out = @driver.class_document @cFoo.full_name, found, [], [] + extends = [[[@cFooExt], @store1]] + includes = [[[@cFooInc], @store1]] + + out = @driver.class_document @cFoo.full_name, found, [], includes, extends expected = @RM::Document.new @driver.add_class expected, 'Foo', [] - @driver.add_includes expected, [] - @driver.add_from expected, @store + @driver.add_includes expected, includes + @driver.add_extends expected, extends + @driver.add_from expected, @store1 expected << @RM::Rule.new(1) doc = @RM::Document.new(@RM::Paragraph.new('one')) @@ -375,6 +538,32 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase assert_match %r%^ attr_accessor attr%, out assert_equal 1, out.scan(/-\n/).length + + refute_match %r%Foo::Bar#blah%, out + end + + def test_display_class_all + util_store + + @driver.show_all = true + + out, = capture_io do + @driver.display_class 'Foo::Bar' + end + + assert_match %r%^= Foo::Bar%, out + assert_match %r%^\(from%, out + + assert_match %r%^= Class methods:%, out + assert_match %r%^ new%, out + assert_match %r%^= Instance methods:%, out + assert_match %r%^ blah%, out + assert_match %r%^= Attributes:%, out + assert_match %r%^ attr_accessor attr%, out + + assert_equal 6, out.scan(/-\n/).length + + assert_match %r%Foo::Bar#blah%, out end def test_display_class_ambiguous @@ -421,6 +610,14 @@ class TestRDocRIDriver < MiniTest::Unit::TestCase assert_match %r%^= Inc$%, out end + def test_display_class_page + out, = capture_io do + @driver.display_class 'ruby:README' + end + + assert_empty out + end + def test_display_method util_store @@ -509,6 +706,68 @@ Foo::Bar#bother assert_match %r%things.*stuff%, out end + def test_display_page + util_store + + out, = capture_io do + @driver.display_page 'home:README.rdoc' + end + + assert_match %r%= README%, out + end + + def test_display_page_add_extension + util_store + + out, = capture_io do + @driver.display_page 'home:README' + end + + assert_match %r%= README%, out + end + + def test_display_page_ambiguous + util_store + + other = @store1.add_file 'README.md' + other.parser = RDoc::Parser::Simple + other.comment = + doc( + head(1, 'README.md'), + para('This is the other README')) + + @store1.save_page other + + out, = capture_io do + @driver.display_page 'home:README' + end + + assert_match %r%= README pages in ~/\.rdoc%, out + assert_match %r%README\.rdoc%, out + assert_match %r%README\.md%, out + end + + def test_display_page_list + util_store + + other = @store1.add_file 'OTHER.rdoc' + other.parser = RDoc::Parser::Simple + other.comment = + doc( + head(1, 'OTHER'), + para('This is OTHER')) + + @store1.save_page other + + out, = capture_io do + @driver.display_page_list @store1 + end + + assert_match %r%= Pages in ~/\.rdoc%, out + assert_match %r%README\.rdoc%, out + assert_match %r%OTHER\.rdoc%, out + end + def test_expand_class util_store @@ -532,6 +791,17 @@ Foo::Bar#bother end assert_equal 'Z', e.name + + @driver.stores << RDoc::Store.new(nil, :system) + + assert_equal 'ruby:README', @driver.expand_name('ruby:README') + assert_equal 'ruby:', @driver.expand_name('ruby:') + + e = assert_raises RDoc::RI::Driver::NotFoundError do + @driver.expand_name 'nonexistent_gem:' + end + + assert_equal 'nonexistent_gem', e.name end def test_find_methods @@ -544,7 +814,7 @@ Foo::Bar#bother end expected = [ - [@store, 'Foo::Bar', 'Foo::Bar', :both, nil], + [@store1, 'Foo::Bar', 'Foo::Bar', :both, nil], ] assert_equal expected, items @@ -560,11 +830,12 @@ Foo::Bar#bother end expected = [ - [@store, 'Ambiguous', 'Ambiguous', :both, 'blah'], - [@store, 'Foo', 'Foo', :both, 'blah'], - [@store, 'Foo::Bar', 'Foo::Bar', :both, 'blah'], - [@store, 'Foo::Baz', 'Foo::Baz', :both, 'blah'], - [@store, 'Inc', 'Inc', :both, 'blah'], + [@store1, 'Ambiguous', 'Ambiguous', :both, 'blah'], + [@store1, 'Ext', 'Ext', :both, 'blah'], + [@store1, 'Foo', 'Foo', :both, 'blah'], + [@store1, 'Foo::Bar', 'Foo::Bar', :both, 'blah'], + [@store1, 'Foo::Baz', 'Foo::Baz', :both, 'blah'], + [@store1, 'Inc', 'Inc', :both, 'blah'], ] assert_equal expected, items @@ -596,6 +867,21 @@ Foo::Bar#bother assert_equal found, sorted end + def test_find_store + @driver.stores << RDoc::Store.new(nil, :system) + @driver.stores << RDoc::Store.new('doc/gem-1.0/ri', :gem) + + assert_equal 'ruby', @driver.find_store('ruby') + assert_equal 'gem-1.0', @driver.find_store('gem-1.0') + assert_equal 'gem-1.0', @driver.find_store('gem') + + e = assert_raises RDoc::RI::Driver::NotFoundError do + @driver.find_store 'nonexistent' + end + + assert_equal 'nonexistent', e.name + end + def test_formatter tty = Object.new def tty.tty?() true; end @@ -609,20 +895,21 @@ Foo::Bar#bother driver.instance_variable_set :@paging, true assert_instance_of @RM::ToBs, driver.formatter(StringIO.new) - - driver.instance_variable_set :@formatter_klass, @RM::ToHtml - - assert_instance_of @RM::ToHtml, driver.formatter(tty) end def test_in_path_eh path = ENV['PATH'] - refute @driver.in_path?('/nonexistent') + test_path = File.expand_path '..', __FILE__ + + temp_dir do |dir| + nonexistent = File.join dir, 'nonexistent' + refute @driver.in_path?(nonexistent) - ENV['PATH'] = File.expand_path '..', __FILE__ + ENV['PATH'] = test_path - assert @driver.in_path?(File.basename(__FILE__)) + assert @driver.in_path?(File.basename(__FILE__)) + end ensure ENV['PATH'] = path end @@ -658,7 +945,7 @@ Foo::Bar#bother @driver.list_known_classes end - assert_equal "Ambiguous\nFoo\nFoo::Bar\nFoo::Baz\nInc\n", out + assert_equal "Ambiguous\nExt\nFoo\nFoo::Bar\nFoo::Baz\nInc\n", out end def test_list_known_classes_name @@ -700,15 +987,15 @@ Foo::Bar#bother index = RDoc::AnyMethod.new nil, '[]' index.record_location @top_level @cFoo.add_method index - @store.save_method @cFoo, index + @store1.save_method @cFoo, index c_index = RDoc::AnyMethod.new nil, '[]' c_index.singleton = true c_index.record_location @top_level @cFoo.add_method c_index - @store.save_method @cFoo, c_index + @store1.save_method @cFoo, c_index - @store.save_cache + @store1.save_cache assert_equal %w[Foo#[]], @driver.list_methods_matching('Foo#[]') assert_equal %w[Foo::[]], @driver.list_methods_matching('Foo::[]') @@ -717,7 +1004,7 @@ Foo::Bar#bother def test_load_method util_store - method = @driver.load_method(@store, :instance_methods, 'Foo', '#', + method = @driver.load_method(@store1, :instance_methods, 'Foo', '#', 'inherit') assert_equal @inherit, method @@ -735,11 +1022,11 @@ Foo::Bar#bother def test_load_methods_matching util_store - expected = [[@store, [@inherit]]] + expected = [[@store1, [@inherit]]] assert_equal expected, @driver.load_methods_matching('Foo#inherit') - expected = [[@store, [@blah]]] + expected = [[@store1, [@blah]]] assert_equal expected, @driver.load_methods_matching('.blah') @@ -768,6 +1055,18 @@ Foo::Bar#bother refute @driver.paging? end + def test_page_in_presence_of_child_status + skip 'this test hangs on travis-ci.org' if ENV['CI'] + @driver.use_stdout = false + + with_dummy_pager do + @driver.page do |io| + refute_equal $stdout, io + assert @driver.paging? + end + end + end + def test_page_stdout @driver.use_stdout = true @@ -798,6 +1097,20 @@ Foo::Bar#bother assert_equal 'foo', meth, '::foo method' end + def test_parse_name_page + klass, type, meth = @driver.parse_name 'ruby:README' + + assert_equal 'ruby', klass, 'ruby project' + assert_equal ':', type, 'ruby type' + assert_equal 'README', meth, 'ruby page' + + klass, type, meth = @driver.parse_name 'ruby:' + + assert_equal 'ruby', klass, 'ruby project' + assert_equal ':', type, 'ruby type' + assert_equal nil, meth, 'ruby page' + end + def test_parse_name_single_class klass, type, meth = @driver.parse_name 'Foo' @@ -958,13 +1271,11 @@ Foo::Bar#bother def util_multi_store util_store - @store1 = @store - - @top_level = RDoc::TopLevel.new 'file.rb' - @home_ri2 = "#{@home_ri}2" @store2 = RDoc::RI::Store.new @home_ri2 + @top_level = @store2.add_file 'file.rb' + # as if seen in a namespace like class Ambiguous::Other @mAmbiguous = @top_level.add_module RDoc::NormalModule, 'Ambiguous' @@ -980,29 +1291,31 @@ Foo::Bar#bother @override.comment = 'must be displayed' @override.record_location @top_level - @store2.save_class @mAmbiguous - @store2.save_class @cBar - @store2.save_class @cFoo_Baz - - @store2.save_method @cBar, @override - @store2.save_method @cBar, @baz - - @store2.save_cache + @store2.save @driver.stores = [@store1, @store2] - - RDoc::RDoc.reset end def util_store - @store = RDoc::RI::Store.new @home_ri + @store1 = RDoc::RI::Store.new @home_ri, :home - @top_level = RDoc::TopLevel.new 'file.rb' + @top_level = @store1.add_file 'file.rb' + + @readme = @store1.add_file 'README.rdoc' + @readme.parser = RDoc::Parser::Simple + @readme.comment = + doc( + head(1, 'README'), + para('This is a README')) @cFoo = @top_level.add_class RDoc::NormalClass, 'Foo' + @mExt = @top_level.add_module RDoc::NormalModule, 'Ext' @mInc = @top_level.add_module RDoc::NormalModule, 'Inc' @cAmbiguous = @top_level.add_class RDoc::NormalClass, 'Ambiguous' + doc = @RM::Document.new @RM::Paragraph.new('Extend thingy') + @cFooExt = @cFoo.add_extend RDoc::Extend.new('Ext', doc) + @cFooExt.record_location @top_level doc = @RM::Document.new @RM::Paragraph.new('Include thingy') @cFooInc = @cFoo.add_include RDoc::Include.new('Inc', doc) @cFooInc.record_location @top_level @@ -1033,28 +1346,12 @@ Foo::Bar#bother # overriden by Bar in multi_store @overriden = @cFoo.add_method RDoc::AnyMethod.new(nil, 'override') - @overriden.comment = 'must not be displayed' + @overriden.comment = 'must not be displayed in Bar#override' @overriden.record_location @top_level - @store.save_class @cFoo - @store.save_class @cFoo_Bar - @store.save_class @cFoo_Baz - @store.save_class @mInc - @store.save_class @cAmbiguous - - @store.save_method @cFoo_Bar, @blah - @store.save_method @cFoo_Bar, @bother - @store.save_method @cFoo_Bar, @new - @store.save_method @cFoo_Bar, @attr - - @store.save_method @cFoo, @inherit - @store.save_method @cFoo, @overriden - - @store.save_cache - - @driver.stores = [@store] + @store1.save - RDoc::RDoc.reset + @driver.stores = [@store1] end end diff --git a/test/rdoc/test_rdoc_ri_paths.rb b/test/rdoc/test_rdoc_ri_paths.rb index e6f33d7d5e..0ef80345bb 100644 --- a/test/rdoc/test_rdoc_ri_paths.rb +++ b/test/rdoc/test_rdoc_ri_paths.rb @@ -1,42 +1,154 @@ -require 'rubygems' -require 'minitest/autorun' -require 'tmpdir' -require 'fileutils' -require 'rdoc/ri/paths' +require 'rdoc/test_case' -class TestRDocRIPaths < MiniTest::Unit::TestCase +class TestRDocRIPaths < RDoc::TestCase def setup - RDoc::RI::Paths.instance_variable_set :@gemdirs, %w[/nonexistent/gemdir] + super + + @orig_gem_path = Gem.path + + @tempdir = File.join Dir.tmpdir, "test_rdoc_ri_paths_#{$$}" + Gem.use_paths @tempdir + Gem.ensure_gem_subdirectories @tempdir + + specs = [ + @rake_10 = Gem::Specification.new('rake', '10.0.1'), + @rdoc_4_0 = Gem::Specification.new('rdoc', '4.0'), + @rdoc_3_12 = Gem::Specification.new('rdoc', '3.12'), + @nodoc = Gem::Specification.new('nodoc', '1.0'), + ] + + specs.each do |spec| + spec.loaded_from = File.join @tempdir, spec.spec_file + + open spec.spec_file, 'w' do |file| + file.write spec.to_ruby_for_cache + end + + FileUtils.mkdir_p File.join(spec.doc_dir, 'ri') unless + spec.name == 'nodoc' + end + + Gem::Specification.reset + Gem::Specification.all = specs end def teardown - RDoc::RI::Paths.instance_variable_set :@gemdirs, nil + super + + Gem.use_paths(*@orig_gem_path) + Gem::Specification.reset + FileUtils.rm_rf @tempdir + end + + def test_class_each + enum = RDoc::RI::Paths.each true, true, true, :all + + path = enum.map { |dir,| dir } + + assert_equal RDoc::RI::Paths.system_dir, path.shift + assert_equal RDoc::RI::Paths.site_dir, path.shift + assert_equal RDoc::RI::Paths.home_dir, path.shift + assert_equal File.join(@nodoc.doc_dir, 'ri'), path.shift + assert_equal File.join(@rake_10.doc_dir, 'ri'), path.shift + assert_equal File.join(@rdoc_4_0.doc_dir, 'ri'), path.shift + assert_equal File.join(@rdoc_3_12.doc_dir, 'ri'), path.shift + assert_empty path + end + + def test_class_gemdirs_latest + Dir.chdir @tempdir do + gemdirs = RDoc::RI::Paths.gemdirs :latest + + expected = [ + File.join(@rake_10.doc_dir, 'ri'), + File.join(@rdoc_4_0.doc_dir, 'ri'), + ] + + assert_equal expected, gemdirs + end + end + + def test_class_gemdirs_legacy + Dir.chdir @tempdir do + gemdirs = RDoc::RI::Paths.gemdirs true + + expected = [ + File.join(@rake_10.doc_dir, 'ri'), + File.join(@rdoc_4_0.doc_dir, 'ri'), + ] + + assert_equal expected, gemdirs + end + end + + def test_class_gemdirs_all + Dir.chdir @tempdir do + gemdirs = RDoc::RI::Paths.gemdirs :all + + expected = [ + File.join(@nodoc.doc_dir, 'ri'), + File.join(@rake_10.doc_dir, 'ri'), + File.join(@rdoc_4_0.doc_dir, 'ri'), + File.join(@rdoc_3_12.doc_dir, 'ri'), + ] + + assert_equal expected, gemdirs + end + end + + def test_class_gem_dir + dir = RDoc::RI::Paths.gem_dir 'rake', '10.0.1' + + expected = File.join @rake_10.doc_dir, 'ri' + + assert_equal expected, dir + end + + def test_class_home_dir + dir = RDoc::RI::Paths.home_dir + + assert_equal RDoc::RI::Paths::HOMEDIR, dir end def test_class_path_nonexistent - path = RDoc::RI::Paths.path true, true, true, true, '/nonexistent' + temp_dir do |dir| + nonexistent = File.join dir, 'nonexistent' + dir = RDoc::RI::Paths.path true, true, true, true, nonexistent - refute_includes path, '/nonexistent' + refute_includes dir, nonexistent + end end def test_class_raw_path path = RDoc::RI::Paths.raw_path true, true, true, true - assert_equal RDoc::RI::Paths::SYSDIR, path.shift - assert_equal RDoc::RI::Paths::SITEDIR, path.shift - assert_equal RDoc::RI::Paths::HOMEDIR, path.shift - assert_equal '/nonexistent/gemdir', path.shift + assert_equal RDoc::RI::Paths.system_dir, path.shift + assert_equal RDoc::RI::Paths.site_dir, path.shift + assert_equal RDoc::RI::Paths.home_dir, path.shift + assert_equal File.join(@rake_10.doc_dir, 'ri'), path.shift end def test_class_raw_path_extra_dirs path = RDoc::RI::Paths.raw_path true, true, true, true, '/nonexistent' - assert_equal '/nonexistent', path.shift - assert_equal RDoc::RI::Paths::SYSDIR, path.shift - assert_equal RDoc::RI::Paths::SITEDIR, path.shift - assert_equal RDoc::RI::Paths::HOMEDIR, path.shift - assert_equal '/nonexistent/gemdir', path.shift + assert_equal '/nonexistent', path.shift + assert_equal RDoc::RI::Paths.system_dir, path.shift + assert_equal RDoc::RI::Paths.site_dir, path.shift + assert_equal RDoc::RI::Paths.home_dir, path.shift + assert_equal File.join(@rake_10.doc_dir, 'ri'), path.shift + end + + def test_class_site_dir + dir = RDoc::RI::Paths.site_dir + + assert_equal File.join(RDoc::RI::Paths::BASE, 'site'), dir + end + + def test_class_system_dir + dir = RDoc::RI::Paths.system_dir + + assert_equal File.join(RDoc::RI::Paths::BASE, 'system'), dir end end diff --git a/test/rdoc/test_rdoc_ri_store.rb b/test/rdoc/test_rdoc_ri_store.rb deleted file mode 100644 index 23e441b633..0000000000 --- a/test/rdoc/test_rdoc_ri_store.rb +++ /dev/null @@ -1,473 +0,0 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/rdoc' -require 'rdoc/ri' -require 'rdoc/markup' -require 'tmpdir' -require 'fileutils' -require 'pp' - -class TestRDocRIStore < MiniTest::Unit::TestCase - - OBJECT_ANCESTORS = defined?(::BasicObject) ? %w[BasicObject] : [] - - def setup - RDoc::TopLevel.reset - - @tmpdir = File.join Dir.tmpdir, "test_rdoc_ri_store_#{$$}" - @s = RDoc::RI::Store.new @tmpdir - - @top_level = RDoc::TopLevel.new 'file.rb' - - @klass = @top_level.add_class RDoc::NormalClass, 'Object' - @klass.add_comment 'original', @top_level - - @cmeth = RDoc::AnyMethod.new nil, 'cmethod' - @cmeth.singleton = true - @cmeth.record_location @top_level - - @meth = RDoc::AnyMethod.new nil, 'method' - @meth.record_location @top_level - - @meth_bang = RDoc::AnyMethod.new nil, 'method!' - @meth_bang.record_location @top_level - - @attr = RDoc::Attr.new nil, 'attr', 'RW', '' - @attr.record_location @top_level - - @klass.add_method @cmeth - @klass.add_method @meth - @klass.add_method @meth_bang - @klass.add_attribute @attr - - @nest_klass = @klass.add_class RDoc::NormalClass, 'SubClass' - @nest_meth = RDoc::AnyMethod.new nil, 'method' - @nest_meth.record_location @top_level - - @nest_incl = RDoc::Include.new 'Incl', '' - @nest_incl.record_location @top_level - - @nest_klass.add_method @nest_meth - @nest_klass.add_include @nest_incl - - @RM = RDoc::Markup - end - - def teardown - FileUtils.rm_rf @tmpdir - end - - def mu_pp obj - s = '' - s = PP.pp obj, s - s.force_encoding Encoding.default_external if defined? Encoding - s.chomp - end - - def assert_cache imethods, cmethods, attrs, modules, ancestors = {} - imethods ||= { 'Object' => %w[method method!] } - cmethods ||= { 'Object' => %w[cmethod] } - attrs ||= { 'Object' => ['attr_accessor attr'] } - - # this is sort-of a hack - @s.clean_cache_collection ancestors - - expected = { - :ancestors => ancestors, - :attributes => attrs, - :class_methods => cmethods, - :encoding => nil, - :instance_methods => imethods, - :modules => modules, - } - - @s.save_cache - - assert_equal expected, @s.cache - end - - def assert_directory path - assert File.directory?(path), "#{path} is not a directory" - end - - def assert_file path - assert File.file?(path), "#{path} is not a file" - end - - def refute_file path - refute File.exist?(path), "#{path} exists" - end - - def test_attributes - @s.cache[:attributes]['Object'] = %w[attr] - - expected = { 'Object' => %w[attr] } - - assert_equal expected, @s.attributes - end - - def test_class_file - assert_equal File.join(@tmpdir, 'Object', 'cdesc-Object.ri'), - @s.class_file('Object') - assert_equal File.join(@tmpdir, 'Object', 'SubClass', 'cdesc-SubClass.ri'), - @s.class_file('Object::SubClass') - end - - def test_class_methods - @s.cache[:class_methods]['Object'] = %w[method] - - expected = { 'Object' => %w[method] } - - assert_equal expected, @s.class_methods - end - - def test_class_path - assert_equal File.join(@tmpdir, 'Object'), @s.class_path('Object') - assert_equal File.join(@tmpdir, 'Object', 'SubClass'), - @s.class_path('Object::SubClass') - end - - def test_dry_run - refute @s.dry_run - - @s.dry_run = true - - assert @s.dry_run - end - - def test_friendly_path - @s.path = @tmpdir - @s.type = nil - assert_equal @s.path, @s.friendly_path - - @s.type = :extra - assert_equal @s.path, @s.friendly_path - - @s.type = :system - assert_equal "ruby core", @s.friendly_path - - @s.type = :site - assert_equal "ruby site", @s.friendly_path - - @s.type = :home - assert_equal "~/.ri", @s.friendly_path - - @s.type = :gem - @s.path = "#{@tmpdir}/gem_repository/doc/gem_name-1.0/ri" - assert_equal "gem gem_name-1.0", @s.friendly_path - end - - def test_instance_methods - @s.cache[:instance_methods]['Object'] = %w[method] - - expected = { 'Object' => %w[method] } - - assert_equal expected, @s.instance_methods - end - - def test_load_cache - cache = { - :encoding => :encoding_value, - :methods => %w[Object#method], - :modules => %w[Object], - } - - Dir.mkdir @tmpdir - - open File.join(@tmpdir, 'cache.ri'), 'wb' do |io| - Marshal.dump cache, io - end - - @s.load_cache - - assert_equal cache, @s.cache - - assert_equal :encoding_value, @s.encoding - end - - def test_load_cache_encoding_differs - skip "Encoding not implemented" unless Object.const_defined? :Encoding - - cache = { - :encoding => Encoding::ISO_8859_1, - :methods => %w[Object#method], - :modules => %w[Object], - } - - Dir.mkdir @tmpdir - - open File.join(@tmpdir, 'cache.ri'), 'wb' do |io| - Marshal.dump cache, io - end - - @s.encoding = Encoding::UTF_8 - - @s.load_cache - - assert_equal cache, @s.cache - - assert_equal Encoding::UTF_8, @s.encoding - end - - def test_load_cache_no_cache - cache = { - :ancestors => {}, - :attributes => {}, - :class_methods => {}, - :encoding => nil, - :instance_methods => {}, - :modules => [], - } - - @s.load_cache - - assert_equal cache, @s.cache - end - - def test_load_class - @s.save_class @klass - - assert_equal @klass, @s.load_class('Object') - end - - def test_load_method_bang - @s.save_method @klass, @meth_bang - - meth = @s.load_method('Object', '#method!') - assert_equal @meth_bang, meth - end - - def test_method_file - assert_equal File.join(@tmpdir, 'Object', 'method-i.ri'), - @s.method_file('Object', 'Object#method') - - assert_equal File.join(@tmpdir, 'Object', 'method%21-i.ri'), - @s.method_file('Object', 'Object#method!') - - assert_equal File.join(@tmpdir, 'Object', 'SubClass', 'method%21-i.ri'), - @s.method_file('Object::SubClass', 'Object::SubClass#method!') - - assert_equal File.join(@tmpdir, 'Object', 'method-c.ri'), - @s.method_file('Object', 'Object::method') - end - - def test_save_cache - @s.save_class @klass - @s.save_method @klass, @meth - @s.save_method @klass, @cmeth - @s.save_class @nest_klass - @s.encoding = :encoding_value - - @s.save_cache - - assert_file File.join(@tmpdir, 'cache.ri') - - expected = { - :attributes => { 'Object' => ['attr_accessor attr'] }, - :class_methods => { 'Object' => %w[cmethod] }, - :instance_methods => { - 'Object' => %w[method method!], - 'Object::SubClass' => %w[method], - }, - :modules => %w[Object Object::SubClass], - :ancestors => { - 'Object::SubClass' => %w[Incl Object], - }, - :encoding => :encoding_value, - } - - expected[:ancestors]['Object'] = %w[BasicObject] if defined?(::BasicObject) - - open File.join(@tmpdir, 'cache.ri'), 'rb' do |io| - cache = Marshal.load io.read - - assert_equal expected, cache - end - end - - def test_save_cache_dry_run - @s.dry_run = true - - @s.save_class @klass - @s.save_method @klass, @meth - @s.save_method @klass, @cmeth - @s.save_class @nest_klass - - @s.save_cache - - refute_file File.join(@tmpdir, 'cache.ri') - end - - def test_save_cache_duplicate_methods - @s.save_method @klass, @meth - @s.save_method @klass, @meth - - @s.save_cache - - assert_cache({ 'Object' => %w[method] }, {}, {}, []) - end - - def test_save_class - @s.save_class @klass - - assert_directory File.join(@tmpdir, 'Object') - assert_file File.join(@tmpdir, 'Object', 'cdesc-Object.ri') - - assert_cache nil, nil, nil, %w[Object], 'Object' => OBJECT_ANCESTORS - - assert_equal @klass, @s.load_class('Object') - end - - def test_save_class_basic_object - @klass.instance_variable_set :@superclass, nil - - @s.save_class @klass - - assert_directory File.join(@tmpdir, 'Object') - assert_file File.join(@tmpdir, 'Object', 'cdesc-Object.ri') - - assert_cache(nil, nil, nil, %w[Object]) - - assert_equal @klass, @s.load_class('Object') - end - - def test_save_class_delete - # save original - @s.save_class @klass - @s.save_method @klass, @meth - @s.save_method @klass, @meth_bang - @s.save_method @klass, @cmeth - @s.save_cache - - klass = RDoc::NormalClass.new 'Object' - - meth = klass.add_method RDoc::AnyMethod.new(nil, 'replace') - meth.record_location @top_level - - # load original, save newly updated class - @s = RDoc::RI::Store.new @tmpdir - @s.load_cache - @s.save_class klass - @s.save_cache - - # load from disk again - @s = RDoc::RI::Store.new @tmpdir - @s.load_cache - - @s.load_class 'Object' - - assert_cache({ 'Object' => %w[replace] }, {}, - { 'Object' => %w[attr_accessor\ attr] }, %w[Object], - 'Object' => OBJECT_ANCESTORS) - - refute File.exist? @s.method_file(@klass.full_name, @meth.full_name) - refute File.exist? @s.method_file(@klass.full_name, @meth_bang.full_name) - refute File.exist? @s.method_file(@klass.full_name, @cmeth.full_name) - end - - def test_save_class_dry_run - @s.dry_run = true - - @s.save_class @klass - - refute_file File.join(@tmpdir, 'Object') - refute_file File.join(@tmpdir, 'Object', 'cdesc-Object.ri') - end - - def test_save_class_merge - @s.save_class @klass - - klass = RDoc::NormalClass.new 'Object' - klass.add_comment 'new comment', @top_level - - s = RDoc::RI::Store.new @tmpdir - s.save_class klass - - s = RDoc::RI::Store.new @tmpdir - - inner = @RM::Document.new @RM::Paragraph.new 'new comment' - inner.file = @top_level.absolute_name - - document = @RM::Document.new inner - - assert_equal document, s.load_class('Object').comment - end - - # This is a functional test - def test_save_class_merge_constant - tl = RDoc::TopLevel.new 'file.rb' - klass = RDoc::NormalClass.new 'C' - klass.add_comment 'comment', tl - - const = klass.add_constant RDoc::Constant.new('CONST', nil, nil) - const.record_location tl - - @s.save_class klass - - RDoc::RDoc.reset - - klass2 = RDoc::NormalClass.new 'C' - klass2.record_location tl - - s = RDoc::RI::Store.new @tmpdir - s.save_class klass2 - - s = RDoc::RI::Store.new @tmpdir - - result = s.load_class 'C' - - assert_empty result.constants - end - - def test_save_class_methods - @s.save_class @klass - - assert_directory File.join(@tmpdir, 'Object') - assert_file File.join(@tmpdir, 'Object', 'cdesc-Object.ri') - - assert_cache nil, nil, nil, %w[Object], 'Object' => OBJECT_ANCESTORS - - assert_equal @klass, @s.load_class('Object') - end - - def test_save_class_nested - @s.save_class @nest_klass - - assert_directory File.join(@tmpdir, 'Object', 'SubClass') - assert_file File.join(@tmpdir, 'Object', 'SubClass', 'cdesc-SubClass.ri') - - assert_cache({ 'Object::SubClass' => %w[method] }, {}, {}, - %w[Object::SubClass], 'Object::SubClass' => %w[Incl Object]) - end - - def test_save_method - @s.save_method @klass, @meth - - assert_directory File.join(@tmpdir, 'Object') - assert_file File.join(@tmpdir, 'Object', 'method-i.ri') - - assert_cache({ 'Object' => %w[method] }, {}, {}, []) - - assert_equal @meth, @s.load_method('Object', '#method') - end - - def test_save_method_dry_run - @s.dry_run = true - - @s.save_method @klass, @meth - - refute_file File.join(@tmpdir, 'Object') - refute_file File.join(@tmpdir, 'Object', 'method-i.ri') - end - - def test_save_method_nested - @s.save_method @nest_klass, @nest_meth - - assert_directory File.join(@tmpdir, 'Object', 'SubClass') - assert_file File.join(@tmpdir, 'Object', 'SubClass', 'method-i.ri') - - assert_cache({ 'Object::SubClass' => %w[method] }, {}, {}, []) - end - -end - diff --git a/test/rdoc/test_rdoc_ruby_lex.rb b/test/rdoc/test_rdoc_ruby_lex.rb index 4398f4119f..1dc11e95a3 100644 --- a/test/rdoc/test_rdoc_ruby_lex.rb +++ b/test/rdoc/test_rdoc_ruby_lex.rb @@ -1,9 +1,219 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/rdoc' -require 'rdoc/ruby_lex' +require 'rdoc/test_case' + +class TestRDocRubyLex < RDoc::TestCase + + def setup + @TK = RDoc::RubyToken + end + + def mu_pp obj + s = '' + s = PP.pp obj, s + s = s.force_encoding(Encoding.default_external) if defined? Encoding + s.chomp + end + + def test_class_tokenize + tokens = RDoc::RubyLex.tokenize "def x() end", nil + + expected = [ + @TK::TkDEF .new( 0, 1, 0, "def"), + @TK::TkSPACE .new( 3, 1, 3, " "), + @TK::TkIDENTIFIER.new( 4, 1, 4, "x"), + @TK::TkLPAREN .new( 5, 1, 5, "("), + @TK::TkRPAREN .new( 6, 1, 6, ")"), + @TK::TkSPACE .new( 7, 1, 7, " "), + @TK::TkEND .new( 8, 1, 8, "end"), + @TK::TkNL .new(11, 1, 11, "\n"), + ] + + assert_equal expected, tokens + end + + def test_class_tokenize___END__ + tokens = RDoc::RubyLex.tokenize '__END__', nil + + expected = [ + @TK::TkEND_OF_SCRIPT.new(0, 1, 0, '__END__'), + @TK::TkNL .new(7, 1, 7, "\n"), + ] + + assert_equal expected, tokens + end + + def test_class_tokenize_character_literal + tokens = RDoc::RubyLex.tokenize "?\\", nil + + expected = [ + @TK::TkSTRING.new( 0, 1, 0, "\\"), + @TK::TkNL .new( 2, 1, 2, "\n"), + ] + + assert_equal expected, tokens + end + + def test_class_tokenize_def_heredoc + tokens = RDoc::RubyLex.tokenize <<-'RUBY', nil +def x + <= Gem::Version.new('1.9') + @a = quick_spec 'a' @rdoc = RDoc::RubygemsHook.new @a @@ -195,5 +198,5 @@ class TestRDocRubygemsHook < Gem::TestCase FileUtils.chmod 0755, @a.doc_dir end -end if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.9') +end diff --git a/test/rdoc/test_rdoc_servlet.rb b/test/rdoc/test_rdoc_servlet.rb new file mode 100644 index 0000000000..0234d33077 --- /dev/null +++ b/test/rdoc/test_rdoc_servlet.rb @@ -0,0 +1,408 @@ +require 'rdoc/test_case' +class TestRDocServlet < RDoc::TestCase + + def setup + super + + @orig_gem_path = Gem.path + + @tempdir = File.join Dir.tmpdir, "test_rdoc_servlet_#{$$}" + Gem.use_paths @tempdir + Gem.ensure_gem_subdirectories @tempdir + + @spec = Gem::Specification.new 'spec', '1.0' + @spec.loaded_from = File.join @tempdir, @spec.spec_file + + Gem::Specification.reset + Gem::Specification.all = [@spec] + + server = {} + def server.mount(*) end + + @stores = {} + @cache = Hash.new { |hash, store| hash[store] = {} } + + @s = RDoc::Servlet.new server, @stores, @cache + + @req = WEBrick::HTTPRequest.new :Logger => nil + @res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0' + + def @req.path= path + instance_variable_set :@path, path + end + + @req.instance_variable_set :@header, Hash.new { |h, k| h[k] = [] } + + @base = File.join @tempdir, 'base' + @system_dir = File.join @tempdir, 'base', 'system' + + @orig_base = RDoc::RI::Paths::BASE + RDoc::RI::Paths::BASE.replace @base + @orig_ri_path_homedir = RDoc::RI::Paths::HOMEDIR + RDoc::RI::Paths::HOMEDIR.replace File.join @tempdir, 'home' + + RDoc::RI::Paths.instance_variable_set \ + :@gemdirs, %w[/nonexistent/gems/example-1.0/ri] + end + + def teardown + super + + Gem.use_paths(*@orig_gem_path) + Gem::Specification.reset + + FileUtils.rm_rf @tempdir + + RDoc::RI::Paths::BASE.replace @orig_base + RDoc::RI::Paths::HOMEDIR.replace @orig_ri_path_homedir + RDoc::RI::Paths.instance_variable_set :@gemdirs, nil + end + + def test_asset + temp_dir do + now = Time.now + + open 'rdoc.css', 'w' do |io| io.write 'h1 { color: red }' end + File.utime now, now, 'rdoc.css' + + @s.asset_dirs[:darkfish] = '.' + + @req.path = 'rdoc.css' + + @s.asset :darkfish, @req, @res + + assert_equal 'h1 { color: red }', @res.body + assert_equal 'text/css', @res.content_type + assert_equal now.httpdate, @res['last-modified'] + end + end + + def test_do_GET + touch_system_cache_path + + @req.path = '/ruby/Missing.html' + + @s.do_GET @req, @res + + assert_equal 404, @res.status + end + + def test_do_GET_asset_darkfish + temp_dir do + FileUtils.touch 'rdoc.css' + + @s.asset_dirs[:darkfish] = '.' + + @req.path = '/rdoc.css' + + @s.do_GET @req, @res + + assert_equal 'text/css', @res.content_type + end + end + + def test_do_GET_asset_json_index + temp_dir do + FileUtils.mkdir 'js' + FileUtils.touch 'js/navigation.js' + + @s.asset_dirs[:json_index] = '.' + + @req.path = '/js/navigation.js' + + @s.do_GET @req, @res + + assert_equal 'application/javascript', @res.content_type + end + end + + def test_do_GET_error + touch_system_cache_path + + def @req.path() raise 'no' end + + @s.do_GET @req, @res + + assert_equal 500, @res.status + end + + def test_do_GET_not_modified + touch_system_cache_path + @req.header['if-modified-since'] = [(Time.now + 10).httpdate] + @req.path = '/ruby/Missing.html' + + assert_raises WEBrick::HTTPStatus::NotModified do + @s.do_GET @req, @res + end + end + + def test_do_GET_root + touch_system_cache_path + + @req.path = '/' + + @s.do_GET @req, @res + + assert_equal 'text/html', @res.content_type + assert_match %r%Local RDoc Documentation%, @res.body + end + + def test_do_GET_root_search + touch_system_cache_path + + @req.path = '/js/search_index.js' + + @s.do_GET @req, @res + + assert_equal 'application/javascript', @res.content_type + end + + def test_documentation_page_class + store = RDoc::Store.new + + generator = @s.generator_for store + + file = store.add_file 'file.rb' + klass = file.add_class RDoc::NormalClass, 'Klass' + klass.add_class RDoc::NormalClass, 'Sub' + + @s.documentation_page store, generator, 'Klass::Sub.html', @req, @res + + assert_match %r%class Klass::Sub - %, @res.body + assert_match %r%%, @res.body + end + + def test_documentation_page_not_found + store = RDoc::Store.new + + generator = @s.generator_for store + + @req.path = '/ruby/Missing.html' + + @s.documentation_page store, generator, 'Missing.html', @req, @res + + assert_equal 404, @res.status + end + + def test_documentation_page_page + store = RDoc::Store.new + + generator = @s.generator_for store + + readme = store.add_file 'README.rdoc' + readme.parser = RDoc::Parser::Simple + + @s.documentation_page store, generator, 'README_rdoc.html', @req, @res + + assert_match %r%README - %, @res.body + assert_match %r%%, @res.body + end + + def test_documentation_source + store, path = @s.documentation_source '/ruby/Object.html' + + assert_equal @system_dir, store.path + + assert_equal 'Object.html', path + end + + def test_documentation_source_cached + cached_store = RDoc::Store.new + + @stores['ruby'] = cached_store + + store, path = @s.documentation_source '/ruby/Object.html' + + assert_same cached_store, store + + assert_equal 'Object.html', path + end + + def test_error + e = RuntimeError.new 'foo' + e.set_backtrace caller + + @s.error e, @req, @res + + assert_equal 'text/html', @res.content_type + assert_equal 500, @res.status + assert_match %r%Error%, @res.body + end + + def test_generator_for + store = RDoc::Store.new + store.main = 'MAIN_PAGE.rdoc' + store.title = 'Title' + + generator = @s.generator_for store + + refute generator.file_output + + assert_equal '..', generator.asset_rel_path + + assert_equal 'MAIN_PAGE.rdoc', @s.options.main_page + assert_equal 'Title', @s.options.title + + assert_kind_of RDoc::RDoc, store.rdoc + assert_same generator, store.rdoc.generator + end + + def test_if_modified_since + temp_dir do + now = Time.now + File.utime now, now, '.' + + @s.if_modified_since @req, @res, '.' + + assert_equal now.to_i, Time.parse(@res['last-modified']).to_i + end + end + + def test_if_modified_since_not_modified + temp_dir do + now = Time.now + File.utime now, now, '.' + + @req.header['if-modified-since'] = [(now + 10).httpdate] + + assert_raises WEBrick::HTTPStatus::NotModified do + @s.if_modified_since @req, @res, '.' + end + + assert_equal now.to_i, Time.parse(@res['last-modified']).to_i + end + end + + def test_installed_docs + touch_system_cache_path + + expected = [ + ['Ruby Documentation', 'ruby/', true, :system, + @system_dir], + ['Site Documentation', 'site/', false, :site, + File.join(@base, 'site')], + ['Home Documentation', 'home/', false, :home, + RDoc::RI::Paths::HOMEDIR], + ['spec-1.0', 'spec-1.0/', false, :gem, + File.join(@spec.doc_dir, 'ri')], + ] + + assert_equal expected, @s.installed_docs + end + + def test_not_found + generator = @s.generator_for RDoc::Store.new + + @req.path = '/ruby/Missing.html' + + @s.not_found generator, @req, @res + + assert_equal 404, @res.status + assert_match %r%<title>Not Found%, @res.body + assert_match %r%/ruby/Missing\.html%, @res.body + end + + def test_ri_paths + paths = @s.ri_paths + + expected = [ + [@system_dir, :system], + [File.join(@base, 'site'), :site], + [RDoc::RI::Paths::HOMEDIR, :home], + [File.join(@spec.doc_dir, 'ri'), :gem], + ] + + assert_equal expected, paths.to_a + end + + def test_root + @s.root @req, @res + + assert_equal 'text/html', @res.content_type + assert_match %r%Local RDoc Documentation%, @res.body + end + + def test_root_search + touch_system_cache_path + + @s.root_search @req, @res + + assert_equal 'application/javascript', @res.content_type + + @res.body =~ /\{.*\}/ + + index = JSON.parse $& + + expected = { + 'index' => { + 'searchIndex' => %w[ + Ruby\ Documentation + ], + 'longSearchIndex' => %w[ + Ruby\ Documentation + ], + 'info' => [ + ['Ruby Documentation', '', @system_dir, '', + 'Documentation for the Ruby standard library'], + ], + } + } + + assert_equal expected, index + end + + def test_show_documentation_index + touch_system_cache_path + + @req.path = '/ruby' + + @s.show_documentation @req, @res + + assert_equal 'text/html', @res.content_type + assert_match %r%Standard Library Documentation%, @res.body + end + + def test_show_documentation_table_of_contents + touch_system_cache_path + + @req.path = '/ruby/table_of_contents.html' + + @s.show_documentation @req, @res + + assert_equal 'text/html', @res.content_type + assert_match %r%<title>Table of Contents - Standard Library Documentation%, + @res.body + end + + def test_show_documentation_page + touch_system_cache_path + + @req.path = '/ruby/Missing.html' + + @s.show_documentation @req, @res + + assert_equal 404, @res.status + end + + def test_show_documentation_search_index + touch_system_cache_path + + @req.path = '/ruby/js/search_index.js' + + @s.show_documentation @req, @res + + assert_equal 'application/javascript', @res.content_type + assert_match %r%\Avar search_data =%, @res.body + end + + def touch_system_cache_path + store = RDoc::Store.new @system_dir + store.title = 'Standard Library Documentation' + + FileUtils.mkdir_p File.dirname store.cache_path + + store.save + end + +end + diff --git a/test/rdoc/test_rdoc_stats.rb b/test/rdoc/test_rdoc_stats.rb index 0bf08334da..5073e53b7e 100644 --- a/test/rdoc/test_rdoc_stats.rb +++ b/test/rdoc/test_rdoc_stats.rb @@ -1,29 +1,46 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/stats' -require 'rdoc/code_objects' -require 'rdoc/markup' -require 'rdoc/parser' +require 'rdoc/test_case' -class TestRDocStats < MiniTest::Unit::TestCase +class TestRDocStats < RDoc::TestCase def setup - RDoc::TopLevel.reset + super - @s = RDoc::Stats.new 0 + @s = RDoc::Stats.new @store, 0 + + @tl = @store.add_file 'file.rb' + @tl.parser = RDoc::Parser::Ruby + end + + def test_doc_stats + c = RDoc::CodeObject.new + + assert_equal [1, 1], @s.doc_stats([c]) + end + + def test_doc_stats_documented + c = RDoc::CodeObject.new + c.comment = comment 'x' + + assert_equal [1, 0], @s.doc_stats([c]) + end + + def test_doc_stats_display_eh + c = RDoc::CodeObject.new + c.ignore + + assert_equal [0, 0], @s.doc_stats([c]) end def test_report_attr - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl - c.add_comment 'C', tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl a = RDoc::Attr.new nil, 'a', 'RW', nil - a.record_location tl + a.record_location @tl c.add_attribute a - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report @@ -40,33 +57,46 @@ end end def test_report_attr_documented - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl - c.add_comment 'C', tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl a = RDoc::Attr.new nil, 'a', 'RW', 'a' - a.record_location tl + a.record_location @tl c.add_attribute a - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report assert_equal @s.great_job, report end + def test_report_attr_line + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl + + a = RDoc::Attr.new nil, 'a', 'RW', nil + a.record_location @tl + a.line = 3 + c.add_attribute a + + @store.complete :public + + assert_match '# in file file.rb:3', @s.report + end + def test_report_constant - tl = RDoc::TopLevel.new 'file.rb' - m = tl.add_module RDoc::NormalModule, 'M' - m.record_location tl - m.add_comment 'M', tl + m = @tl.add_module RDoc::NormalModule, 'M' + m.record_location @tl + m.add_comment 'M', @tl c = RDoc::Constant.new 'C', nil, nil - c.record_location tl + c.record_location @tl m.add_constant c - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report @@ -84,18 +114,17 @@ end end def test_report_constant_alias - tl = RDoc::TopLevel.new 'file.rb' - mod = tl.add_module RDoc::NormalModule, 'M' + mod = @tl.add_module RDoc::NormalModule, 'M' - c = tl.add_class RDoc::NormalClass, 'C' + c = @tl.add_class RDoc::NormalClass, 'C' mod.add_constant c ca = RDoc::Constant.new 'CA', nil, nil ca.is_alias_for = c - tl.add_constant ca + @tl.add_constant ca - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report @@ -105,33 +134,46 @@ end end def test_report_constant_documented - tl = RDoc::TopLevel.new 'file.rb' - m = tl.add_module RDoc::NormalModule, 'M' - m.record_location tl + m = @tl.add_module RDoc::NormalModule, 'M' + m.record_location @tl m.comment = 'M' c = RDoc::Constant.new 'C', nil, 'C' - c.record_location tl + c.record_location @tl m.add_constant c - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report assert_equal @s.great_job, report end + def test_report_constant_line + m = @tl.add_module RDoc::NormalModule, 'M' + m.record_location @tl + m.add_comment 'M', @tl + + c = RDoc::Constant.new 'C', nil, nil + c.record_location @tl + c.line = 5 + m.add_constant c + + @store.complete :public + + assert_match '# in file file.rb:5', @s.report + end + def test_report_class - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl m = RDoc::AnyMethod.new nil, 'm' - m.record_location tl + m.record_location @tl c.add_method m m.comment = 'm' - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report @@ -148,18 +190,31 @@ end assert_equal expected, report end + def test_report_skip_object + c = @tl.add_class RDoc::NormalClass, 'Object' + c.record_location @tl + + m = RDoc::AnyMethod.new nil, 'm' + m.record_location @tl + c.add_method m + m.comment = 'm' + + @store.complete :public + + refute_match %r%^class Object$%, @s.report + end + def test_report_class_documented - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl - c.add_comment 'C', tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl m = RDoc::AnyMethod.new nil, 'm' - m.record_location tl + m.record_location @tl c.add_method m m.comment = 'm' - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report @@ -167,25 +222,24 @@ end end def test_report_class_documented_level_1 - tl = RDoc::TopLevel.new 'file.rb' - c1 = tl.add_class RDoc::NormalClass, 'C1' - c1.record_location tl - c1.add_comment 'C1', tl + c1 = @tl.add_class RDoc::NormalClass, 'C1' + c1.record_location @tl + c1.add_comment 'C1', @tl m1 = RDoc::AnyMethod.new nil, 'm1' - m1.record_location tl + m1.record_location @tl c1.add_method m1 m1.comment = 'm1' - c2 = tl.add_class RDoc::NormalClass, 'C2' - c2.record_location tl + c2 = @tl.add_class RDoc::NormalClass, 'C2' + c2.record_location @tl m2 = RDoc::AnyMethod.new nil, 'm2' - m2.record_location tl + m2.record_location @tl c2.add_method m2 m2.comment = 'm2' - RDoc::TopLevel.complete :public + @store.complete :public @s.coverage_level = 1 @@ -206,10 +260,9 @@ end end def test_report_class_empty - tl = RDoc::TopLevel.new 'file.rb' - tl.add_class RDoc::NormalClass, 'C' + @tl.add_class RDoc::NormalClass, 'C' - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report @@ -225,15 +278,14 @@ The following items are not documented: end def test_report_class_empty_2 - tl = RDoc::TopLevel.new 'file.rb' - c1 = tl.add_class RDoc::NormalClass, 'C1' - c1.record_location tl + c1 = @tl.add_class RDoc::NormalClass, 'C1' + c1.record_location @tl - c2 = tl.add_class RDoc::NormalClass, 'C2' - c2.record_location tl - c2.add_comment 'C2', tl + c2 = @tl.add_class RDoc::NormalClass, 'C2' + c2.record_location @tl + c2.add_comment 'C2', @tl - RDoc::TopLevel.complete :public + @store.complete :public @s.coverage_level = 1 report = @s.report @@ -253,16 +305,15 @@ end end def test_report_class_method_documented - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl m = RDoc::AnyMethod.new nil, 'm' - m.record_location tl + m.record_location @tl c.add_method m m.comment = 'm' - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report @@ -279,8 +330,19 @@ end assert_equal expected, report end + def test_report_class_module_ignore + c = @tl.add_class RDoc::NormalClass, 'C' + c.ignore + + @store.complete :public + + report = @s.report_class_module c + + assert_nil report + end + def test_report_empty - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report @@ -288,21 +350,20 @@ end end def test_report_method - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl - c.add_comment 'C', tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl m1 = RDoc::AnyMethod.new nil, 'm1' - m1.record_location tl + m1.record_location @tl c.add_method m1 m2 = RDoc::AnyMethod.new nil, 'm2' - m2.record_location tl + m2.record_location @tl c.add_method m2 m2.comment = 'm2' - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report @@ -314,6 +375,40 @@ class C # is documented # in file file.rb def m1; end +end + EXPECTED + + assert_equal expected, report + end + + def test_report_method_class + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl + + m1 = RDoc::AnyMethod.new nil, 'm1' + m1.record_location @tl + m1.singleton = true + c.add_method m1 + + m2 = RDoc::AnyMethod.new nil, 'm2' + m2.record_location @tl + m2.singleton = true + c.add_method m2 + m2.comment = 'm2' + + @store.complete :public + + report = @s.report + + expected = <<-EXPECTED +The following items are not documented: + +class C # is documented + + # in file file.rb + def self.m1; end + end EXPECTED @@ -321,41 +416,54 @@ end end def test_report_method_documented - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl - c.add_comment 'C', tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl m = RDoc::AnyMethod.new nil, 'm' - m.record_location tl + m.record_location @tl c.add_method m m.comment = 'm' - RDoc::TopLevel.complete :public + @store.complete :public report = @s.report assert_equal @s.great_job, report end + def test_report_method_line + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl + + m1 = RDoc::AnyMethod.new nil, 'm1' + m1.record_location @tl + m1.line = 4 + c.add_method m1 + + @store.complete :public + + assert_match '# in file file.rb:4', @s.report + end + def test_report_method_parameters - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl - c.add_comment 'C', tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl m1 = RDoc::AnyMethod.new nil, 'm1' - m1.record_location tl + m1.record_location @tl m1.params = '(p1, p2)' m1.comment = 'Stuff with +p1+' c.add_method m1 m2 = RDoc::AnyMethod.new nil, 'm2' - m2.record_location tl + m2.record_location @tl c.add_method m2 m2.comment = 'm2' - RDoc::TopLevel.complete :public + @store.complete :public @s.coverage_level = 1 report = @s.report @@ -376,18 +484,18 @@ end end def test_report_method_parameters_documented - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl - c.add_comment 'C', tl + @tl.parser = RDoc::Parser::Ruby + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl m = RDoc::AnyMethod.new nil, 'm' - m.record_location tl + m.record_location @tl m.params = '(p1)' m.comment = 'Stuff with +p1+' c.add_method m - RDoc::TopLevel.complete :public + @store.complete :public @s.coverage_level = 1 report = @s.report @@ -396,13 +504,12 @@ end end def test_report_method_parameters_yield - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl - c.add_comment 'C', tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl m = RDoc::AnyMethod.new nil, 'm' - m.record_location tl + m.record_location @tl m.call_seq = <<-SEQ m(a) { |c| ... } m(a, b) { |c, d| ... } @@ -410,7 +517,7 @@ m(a, b) { |c, d| ... } m.comment = 'Stuff with +a+, yields +c+ for you to do stuff with' c.add_method m - RDoc::TopLevel.complete :public + @store.complete :public @s.coverage_level = 1 report = @s.report @@ -431,26 +538,25 @@ end end def test_summary - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl - m = tl.add_module RDoc::NormalModule, 'M' - m.record_location tl + m = @tl.add_module RDoc::NormalModule, 'M' + m.record_location @tl a = RDoc::Attr.new nil, 'a', 'RW', nil - a.record_location tl + a.record_location @tl c.add_attribute a c_c = RDoc::Constant.new 'C', nil, nil - c_c.record_location tl + c_c.record_location @tl c.add_constant c_c m = RDoc::AnyMethod.new nil, 'm' - m.record_location tl + m.record_location @tl c.add_method m - RDoc::TopLevel.complete :public + @store.complete :public summary = @s.summary summary.sub!(/Elapsed:.*/, '') @@ -473,11 +579,10 @@ Total: 5 (5 undocumented) end def test_summary_level_false - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl - RDoc::TopLevel.complete :public + @store.complete :public @s.coverage_level = false @@ -502,18 +607,17 @@ Total: 1 (1 undocumented) end def test_summary_level_1 - tl = RDoc::TopLevel.new 'file.rb' - c = tl.add_class RDoc::NormalClass, 'C' - c.record_location tl - c.add_comment 'C', tl + c = @tl.add_class RDoc::NormalClass, 'C' + c.record_location @tl + c.add_comment 'C', @tl m = RDoc::AnyMethod.new nil, 'm' - m.record_location tl + m.record_location @tl m.params = '(p1, p2)' m.comment = 'Stuff with +p1+' c.add_method m - RDoc::TopLevel.complete :public + @store.complete :public @s.coverage_level = 1 @s.report diff --git a/test/rdoc/test_rdoc_store.rb b/test/rdoc/test_rdoc_store.rb new file mode 100644 index 0000000000..1b87ca6036 --- /dev/null +++ b/test/rdoc/test_rdoc_store.rb @@ -0,0 +1,824 @@ +require File.expand_path '../xref_test_case', __FILE__ + +class TestRDocStore < XrefTestCase + + OBJECT_ANCESTORS = defined?(::BasicObject) ? %w[BasicObject] : [] + + def setup + super + + @tmpdir = File.join Dir.tmpdir, "test_rdoc_ri_store_#{$$}" + @s = RDoc::RI::Store.new @tmpdir + + @top_level = @s.add_file 'file.rb' + + @page = @s.add_file 'README.txt' + @page.parser = RDoc::Parser::Simple + @page.comment = RDoc::Comment.new 'This is a page', @page + + @klass = @top_level.add_class RDoc::NormalClass, 'Object' + @klass.add_comment 'original', @top_level + + @cmeth = RDoc::AnyMethod.new nil, 'cmethod' + @cmeth.singleton = true + @cmeth.record_location @top_level + + @meth_comment = RDoc::Comment.new 'method comment' + @meth_comment.location = @top_level + + @meth = RDoc::AnyMethod.new nil, 'method' + @meth.record_location @top_level + @meth.comment = @meth_comment + + @meth_bang = RDoc::AnyMethod.new nil, 'method!' + @meth_bang.record_location @top_level + + @meth_bang_alias = RDoc::Alias.new nil, 'method!', 'method_bang', '' + @meth_bang_alias.record_location @top_level + + @meth_bang.add_alias @meth_bang_alias, @klass + + @attr_comment = RDoc::Comment.new 'attribute comment' + @attr_comment.location = @top_level + + @attr = RDoc::Attr.new nil, 'attr', 'RW', '' + @attr.record_location @top_level + @attr.comment = @attr_comment + + @klass.add_method @cmeth + @klass.add_method @meth + @klass.add_method @meth_bang + @klass.add_attribute @attr + + @nest_klass = @klass.add_class RDoc::NormalClass, 'SubClass' + @nest_meth = RDoc::AnyMethod.new nil, 'method' + @nest_meth.record_location @top_level + + @nest_incl = RDoc::Include.new 'Incl', '' + @nest_incl.record_location @top_level + + @nest_klass.add_method @nest_meth + @nest_klass.add_include @nest_incl + + @mod = @top_level.add_module RDoc::NormalModule, 'Mod' + @mod.record_location @top_level + end + + def teardown + super + + FileUtils.rm_rf @tmpdir + end + + def mu_pp obj + s = '' + s = PP.pp obj, s + s.force_encoding Encoding.default_external if defined? Encoding + s.chomp + end + + def assert_cache imethods, cmethods, attrs, modules, + ancestors = {}, pages = [], main = nil, title = nil + imethods ||= { 'Object' => %w[method method! method_bang] } + cmethods ||= { 'Object' => %w[cmethod] } + attrs ||= { 'Object' => ['attr_accessor attr'] } + + # this is sort-of a hack + @s.clean_cache_collection ancestors + + expected = { + :ancestors => ancestors, + :attributes => attrs, + :class_methods => cmethods, + :encoding => nil, + :instance_methods => imethods, + :modules => modules, + :pages => pages, + :main => main, + :title => title, + } + + @s.save_cache + + assert_equal expected, @s.cache + end + + def assert_directory path + assert File.directory?(path), "#{path} is not a directory" + end + + def assert_file path + assert File.file?(path), "#{path} is not a file" + end + + def refute_file path + refute File.exist?(path), "#{path} exists" + end + + def test_add_file + top_level = @store.add_file 'file.rb' + + assert_kind_of RDoc::TopLevel, top_level + assert_equal @store, top_level.store + assert_equal 'file.rb', top_level.name + assert_includes @store.all_files, top_level + + assert_same top_level, @store.add_file('file.rb') + refute_same top_level, @store.add_file('other.rb') + end + + def test_all_classes_and_modules + expected = %w[ + C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 + Child + M1 M1::M2 + Parent + ] + + assert_equal expected, + @store.all_classes_and_modules.map { |m| m.full_name }.sort + end + + def test_all_files + assert_equal %w[xref_data.rb], + @store.all_files.map { |m| m.full_name }.sort + end + + def test_all_modules + assert_equal %w[M1 M1::M2], + @store.all_modules.map { |m| m.full_name }.sort + end + + def test_attributes + @s.cache[:attributes]['Object'] = %w[attr] + + expected = { 'Object' => %w[attr] } + + assert_equal expected, @s.attributes + end + + def test_class_file + assert_equal File.join(@tmpdir, 'Object', 'cdesc-Object.ri'), + @s.class_file('Object') + assert_equal File.join(@tmpdir, 'Object', 'SubClass', 'cdesc-SubClass.ri'), + @s.class_file('Object::SubClass') + end + + def test_class_methods + @s.cache[:class_methods]['Object'] = %w[method] + + expected = { 'Object' => %w[method] } + + assert_equal expected, @s.class_methods + end + + def test_class_path + assert_equal File.join(@tmpdir, 'Object'), @s.class_path('Object') + assert_equal File.join(@tmpdir, 'Object', 'SubClass'), + @s.class_path('Object::SubClass') + end + + def test_classes + expected = %w[ + C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 + Child + Parent + ] + + assert_equal expected, @store.all_classes.map { |m| m.full_name }.sort + end + + def test_complete + @c2.add_module_alias @c2_c3, 'A1', @top_level + + @store.complete :public + + a1 = @xref_data.find_class_or_module 'C2::A1' + + assert_equal 'C2::A1', a1.full_name + refute_empty a1.aliases + end + + def test_find_class_named + assert_equal @c1, @store.find_class_named('C1') + + assert_equal @c2_c3, @store.find_class_named('C2::C3') + end + + def test_find_class_named_from + assert_equal @c5_c1, @store.find_class_named_from('C1', 'C5') + + assert_equal @c1, @store.find_class_named_from('C1', 'C4') + end + + def test_find_class_or_module + assert_equal @m1, @store.find_class_or_module('M1') + assert_equal @c1, @store.find_class_or_module('C1') + + assert_equal @m1, @store.find_class_or_module('::M1') + assert_equal @c1, @store.find_class_or_module('::C1') + end + + def test_find_file_named + assert_equal @xref_data, @store.find_file_named(@file_name) + end + + def test_find_module_named + assert_equal @m1, @store.find_module_named('M1') + assert_equal @m1_m2, @store.find_module_named('M1::M2') + end + + def test_find_text_page + page = @store.add_file 'PAGE.txt' + page.parser = RDoc::Parser::Simple + + assert_nil @store.find_text_page 'no such page' + + assert_equal page, @store.find_text_page('PAGE.txt') + end + + def test_friendly_path + @s.path = @tmpdir + @s.type = nil + assert_equal @s.path, @s.friendly_path + + @s.type = :extra + assert_equal @s.path, @s.friendly_path + + @s.type = :system + assert_equal "ruby core", @s.friendly_path + + @s.type = :site + assert_equal "ruby site", @s.friendly_path + + @s.type = :home + assert_equal "~/.rdoc", @s.friendly_path + + @s.type = :gem + @s.path = "#{@tmpdir}/gem_repository/doc/gem_name-1.0/ri" + assert_equal "gem gem_name-1.0", @s.friendly_path + end + + def test_dry_run + refute @s.dry_run + + @s.dry_run = true + + assert @s.dry_run + end + + def test_instance_methods + @s.cache[:instance_methods]['Object'] = %w[method] + + expected = { 'Object' => %w[method] } + + assert_equal expected, @s.instance_methods + end + + def test_load_all + FileUtils.mkdir_p @tmpdir + + @s.save + + s = RDoc::Store.new @tmpdir + + s.load_all + + assert_equal [@klass, @nest_klass], s.all_classes.sort + assert_equal [@mod], s.all_modules.sort + assert_equal [@page, @top_level], s.all_files.sort + + methods = s.all_classes_and_modules.map do |mod| + mod.method_list + end.flatten.sort + + _meth_bang_alias = RDoc::AnyMethod.new nil, 'method_bang' + _meth_bang_alias.parent = @klass + + assert_equal [@meth, @meth_bang, _meth_bang_alias, @nest_meth, @cmeth], + methods.sort_by { |m| m.full_name } + + method = methods.find { |m| m == @meth } + assert_equal @meth_comment.parse, method.comment + + assert_equal @klass, methods.last.parent + + attributes = s.all_classes_and_modules.map do |mod| + mod.attributes + end.flatten.sort + + assert_equal [@attr], attributes + + assert_equal @attr_comment.parse, attributes.first.comment + end + + def test_load_cache + cache = { + :encoding => :encoding_value, + :methods => { "Object" => %w[Object#method] }, + :main => @page.full_name, + :modules => %w[Object], + :pages => [], + } + + Dir.mkdir @tmpdir + + open File.join(@tmpdir, 'cache.ri'), 'wb' do |io| + Marshal.dump cache, io + end + + @s.load_cache + + assert_equal cache, @s.cache + + assert_equal :encoding_value, @s.encoding + assert_equal 'README.txt', @s.main + end + + def test_load_cache_encoding_differs + skip "Encoding not implemented" unless Object.const_defined? :Encoding + + cache = { + :encoding => Encoding::ISO_8859_1, + :main => nil, + :methods => { "Object" => %w[Object#method] }, + :modules => %w[Object], + :pages => [], + } + + Dir.mkdir @tmpdir + + open File.join(@tmpdir, 'cache.ri'), 'wb' do |io| + Marshal.dump cache, io + end + + @s.encoding = Encoding::UTF_8 + + @s.load_cache + + assert_equal cache, @s.cache + + assert_equal Encoding::UTF_8, @s.encoding + end + + def test_load_cache_no_cache + cache = { + :ancestors => {}, + :attributes => {}, + :class_methods => {}, + :encoding => nil, + :instance_methods => {}, + :main => nil, + :modules => [], + :pages => [], + :title => nil, + } + + @s.load_cache + + assert_equal cache, @s.cache + end + + def test_load_cache_legacy + cache = { + :ancestors => {}, + :attributes => {}, + :class_methods => {}, + :encoding => :encoding_value, + :instance_methods => { "Object" => %w[Object#method] }, + :modules => %w[Object], + # no :pages + # no :main + } + + Dir.mkdir @tmpdir + + open File.join(@tmpdir, 'cache.ri'), 'wb' do |io| + Marshal.dump cache, io + end + + @s.load_cache + + expected = { + :ancestors => {}, + :attributes => {}, + :class_methods => {}, + :encoding => :encoding_value, + :instance_methods => { "Object" => %w[Object#method] }, + :main => nil, + :modules => %w[Object], + :pages => [], + } + + assert_equal expected, @s.cache + + assert_equal :encoding_value, @s.encoding + assert_nil @s.main + end + + def test_load_class + @s.save_class @klass + @s.classes_hash.clear + + assert_equal @klass, @s.load_class('Object') + + assert_includes @s.classes_hash, 'Object' + end + + def test_load_method + @s.save_method @klass, @meth_bang + + meth = @s.load_method('Object', '#method!') + assert_equal @meth_bang, meth + assert_equal @klass, meth.parent + assert_equal @s, meth.store + end + + def test_load_method_legacy + @s.save_method @klass, @meth + + file = @s.method_file @klass.full_name, @meth.full_name + + open file, 'wb' do |io| + io.write "\x04\bU:\x14RDoc::AnyMethod[\x0Fi\x00I" + + "\"\vmethod\x06:\x06EF\"\x11Klass#method0:\vpublic" + + "o:\eRDoc::Markup::Document\x06:\v@parts[\x06" + + "o:\x1CRDoc::Markup::Paragraph\x06;\t[\x06I" + + "\"\x16this is a comment\x06;\x06FI" + + "\"\rcall_seq\x06;\x06FI\"\x0Fsome_block\x06;\x06F" + + "[\x06[\aI\"\faliased\x06;\x06Fo;\b\x06;\t[\x06" + + "o;\n\x06;\t[\x06I\"\x12alias comment\x06;\x06FI" + + "\"\nparam\x06;\x06F" + end + + meth = @s.load_method('Object', '#method') + assert_equal 'Klass#method', meth.full_name + assert_equal @klass, meth.parent + assert_equal @s, meth.store + end + + def test_load_page + @s.save_page @page + + assert_equal @page, @s.load_page('README.txt') + end + + def test_main + assert_equal nil, @s.main + + @s.main = 'README.txt' + + assert_equal 'README.txt', @s.main + end + + def test_method_file + assert_equal File.join(@tmpdir, 'Object', 'method-i.ri'), + @s.method_file('Object', 'Object#method') + + assert_equal File.join(@tmpdir, 'Object', 'method%21-i.ri'), + @s.method_file('Object', 'Object#method!') + + assert_equal File.join(@tmpdir, 'Object', 'SubClass', 'method%21-i.ri'), + @s.method_file('Object::SubClass', 'Object::SubClass#method!') + + assert_equal File.join(@tmpdir, 'Object', 'method-c.ri'), + @s.method_file('Object', 'Object::method') + end + + def test_module_names + @s.save_class @klass + + assert_equal %w[Object], @s.module_names + end + + def test_page + page = @store.add_file 'PAGE.txt' + page.parser = RDoc::Parser::Simple + + assert_nil @store.page 'no such page' + + assert_equal page, @store.page('PAGE') + end + + def test_save + FileUtils.mkdir_p @tmpdir + + @s.save + + assert_directory File.join(@tmpdir, 'Object') + + assert_file File.join(@tmpdir, 'Object', 'cdesc-Object.ri') + assert_file File.join(@tmpdir, 'Object', 'method-i.ri') + assert_file File.join(@tmpdir, 'page-README_txt.ri') + + assert_file File.join(@tmpdir, 'cache.ri') + + expected = { + :ancestors => { + 'Object::SubClass' => %w[Incl Object], + }, + :attributes => { 'Object' => ['attr_accessor attr'] }, + :class_methods => { 'Object' => %w[cmethod] }, + :instance_methods => { + 'Object' => %w[attr method method! method_bang], + 'Object::SubClass' => %w[method], + }, + :main => nil, + :modules => %w[Mod Object Object::SubClass], + :encoding => nil, + :pages => %w[README.txt], + :title => nil, + } + + expected[:ancestors]['Object'] = %w[BasicObject] if defined?(::BasicObject) + + open File.join(@tmpdir, 'cache.ri'), 'rb' do |io| + cache = Marshal.load io.read + + assert_equal expected, cache + end + end + + def test_save_cache + @s.save_class @klass + @s.save_method @klass, @meth + @s.save_method @klass, @cmeth + @s.save_class @nest_klass + @s.save_page @page + @s.encoding = :encoding_value + @s.main = @page.full_name + @s.title = 'title' + + @s.save_cache + + assert_file File.join(@tmpdir, 'cache.ri') + + expected = { + :ancestors => { + 'Object::SubClass' => %w[Incl Object], + }, + :attributes => { 'Object' => ['attr_accessor attr'] }, + :class_methods => { 'Object' => %w[cmethod] }, + :instance_methods => { + 'Object' => %w[method method! method_bang], + 'Object::SubClass' => %w[method], + }, + :main => @page.full_name, + :modules => %w[Object Object::SubClass], + :encoding => :encoding_value, + :pages => %w[README.txt], + :title => 'title', + } + + expected[:ancestors]['Object'] = %w[BasicObject] if defined?(::BasicObject) + + open File.join(@tmpdir, 'cache.ri'), 'rb' do |io| + cache = Marshal.load io.read + + assert_equal expected, cache + end + end + + def test_save_cache_dry_run + @s.dry_run = true + + @s.save_class @klass + @s.save_method @klass, @meth + @s.save_method @klass, @cmeth + @s.save_class @nest_klass + + @s.save_cache + + refute_file File.join(@tmpdir, 'cache.ri') + end + + def test_save_cache_duplicate_methods + @s.save_method @klass, @meth + @s.save_method @klass, @meth + + @s.save_cache + + assert_cache({ 'Object' => %w[method] }, {}, {}, []) + end + + def test_save_cache_duplicate_pages + @s.save_page @page + @s.save_page @page + + @s.save_cache + + assert_cache({}, {}, {}, [], {}, %w[README.txt]) + end + + def test_save_class + @s.save_class @klass + + assert_directory File.join(@tmpdir, 'Object') + assert_file File.join(@tmpdir, 'Object', 'cdesc-Object.ri') + + assert_cache nil, nil, nil, %w[Object], 'Object' => OBJECT_ANCESTORS + + assert_equal @klass, @s.load_class('Object') + end + + def test_save_class_basic_object + @klass.instance_variable_set :@superclass, nil + + @s.save_class @klass + + assert_directory File.join(@tmpdir, 'Object') + assert_file File.join(@tmpdir, 'Object', 'cdesc-Object.ri') + + assert_cache(nil, nil, nil, %w[Object]) + + assert_equal @klass, @s.load_class('Object') + end + + def test_save_class_delete + # save original + @s.save_class @klass + @s.save_method @klass, @meth + @s.save_method @klass, @meth_bang + @s.save_method @klass, @cmeth + @s.save_cache + + klass = RDoc::NormalClass.new 'Object' + + meth = klass.add_method RDoc::AnyMethod.new(nil, 'replace') + meth.record_location @top_level + + # load original, save newly updated class + @s = RDoc::RI::Store.new @tmpdir + @s.load_cache + @s.save_class klass + @s.save_cache + + # load from disk again + @s = RDoc::RI::Store.new @tmpdir + @s.load_cache + + @s.load_class 'Object' + + assert_cache({ 'Object' => %w[replace] }, {}, + { 'Object' => %w[attr_accessor\ attr] }, %w[Object], + 'Object' => OBJECT_ANCESTORS) + + refute File.exist? @s.method_file(@klass.full_name, @meth.full_name) + refute File.exist? @s.method_file(@klass.full_name, @meth_bang.full_name) + refute File.exist? @s.method_file(@klass.full_name, @cmeth.full_name) + end + + def test_save_class_dry_run + @s.dry_run = true + + @s.save_class @klass + + refute_file File.join(@tmpdir, 'Object') + refute_file File.join(@tmpdir, 'Object', 'cdesc-Object.ri') + end + + def test_save_class_merge + @s.save_class @klass + + klass = RDoc::NormalClass.new 'Object' + klass.add_comment 'new comment', @top_level + + s = RDoc::RI::Store.new @tmpdir + s.save_class klass + + s = RDoc::RI::Store.new @tmpdir + + inner = @RM::Document.new @RM::Paragraph.new 'new comment' + inner.file = @top_level + + document = @RM::Document.new inner + + assert_equal document, s.load_class('Object').comment + end + + # This is a functional test + def test_save_class_merge_constant + store = RDoc::Store.new + tl = store.add_file 'file.rb' + + klass = tl.add_class RDoc::NormalClass, 'C' + klass.add_comment 'comment', tl + + const = klass.add_constant RDoc::Constant.new('CONST', nil, nil) + const.record_location tl + + @s.save_class klass + + # separate parse run, independent store + store = RDoc::Store.new + tl = store.add_file 'file.rb' + klass2 = tl.add_class RDoc::NormalClass, 'C' + klass2.record_location tl + + s = RDoc::RI::Store.new @tmpdir + s.save_class klass2 + + # separate `ri` run, independent store + s = RDoc::RI::Store.new @tmpdir + + result = s.load_class 'C' + + assert_empty result.constants + end + + def test_save_class_methods + @s.save_class @klass + + assert_directory File.join(@tmpdir, 'Object') + assert_file File.join(@tmpdir, 'Object', 'cdesc-Object.ri') + + assert_cache nil, nil, nil, %w[Object], 'Object' => OBJECT_ANCESTORS + + assert_equal @klass, @s.load_class('Object') + end + + def test_save_class_nested + @s.save_class @nest_klass + + assert_directory File.join(@tmpdir, 'Object', 'SubClass') + assert_file File.join(@tmpdir, 'Object', 'SubClass', 'cdesc-SubClass.ri') + + assert_cache({ 'Object::SubClass' => %w[method] }, {}, {}, + %w[Object::SubClass], 'Object::SubClass' => %w[Incl Object]) + end + + def test_save_method + @s.save_method @klass, @meth + + assert_directory File.join(@tmpdir, 'Object') + assert_file File.join(@tmpdir, 'Object', 'method-i.ri') + + assert_cache({ 'Object' => %w[method] }, {}, {}, []) + + assert_equal @meth, @s.load_method('Object', '#method') + end + + def test_save_method_dry_run + @s.dry_run = true + + @s.save_method @klass, @meth + + refute_file File.join(@tmpdir, 'Object') + refute_file File.join(@tmpdir, 'Object', 'method-i.ri') + end + + def test_save_method_nested + @s.save_method @nest_klass, @nest_meth + + assert_directory File.join(@tmpdir, 'Object', 'SubClass') + assert_file File.join(@tmpdir, 'Object', 'SubClass', 'method-i.ri') + + assert_cache({ 'Object::SubClass' => %w[method] }, {}, {}, []) + end + + def test_save_page + @s.save_page @page + + assert_file File.join(@tmpdir, 'page-README_txt.ri') + + assert_cache({}, {}, {}, [], {}, %w[README.txt]) + end + + def test_save_page_file + @s.save_page @top_level + + refute_file File.join(@tmpdir, 'page-file_rb.ri') + end + + def test_source + @s.path = @tmpdir + @s.type = nil + assert_equal @s.path, @s.source + + @s.type = :extra + assert_equal @s.path, @s.source + + @s.type = :system + assert_equal "ruby", @s.source + + @s.type = :site + assert_equal "site", @s.source + + @s.type = :home + assert_equal "home", @s.source + + @s.type = :gem + @s.path = "#{@tmpdir}/gem_repository/doc/gem_name-1.0/ri" + assert_equal "gem_name-1.0", @s.source + end + + def test_title + assert_equal nil, @s.title + + @s.title = 'rdoc' + + assert_equal 'rdoc', @s.title + end + +end + diff --git a/test/rdoc/test_rdoc_task.rb b/test/rdoc/test_rdoc_task.rb index c17a5c8b38..dce02bc9b7 100644 --- a/test/rdoc/test_rdoc_task.rb +++ b/test/rdoc/test_rdoc_task.rb @@ -1,10 +1,11 @@ -require 'rubygems' -require 'minitest/autorun' -require 'rdoc/task' +require 'rdoc/test_case' +require 'rake' -class TestRDocTask < MiniTest::Unit::TestCase +class TestRDocTask < RDoc::TestCase def setup + super + Rake::Task.clear @t = RDoc::Task.new @@ -32,6 +33,14 @@ class TestRDocTask < MiniTest::Unit::TestCase end end + def test_markup_option + rdoc_task = RDoc::Task.new do |rd| + rd.markup = "tomdoc" + end + + assert_equal %w[-o html --markup tomdoc], rdoc_task.option_list + end + def test_tasks_creation RDoc::Task.new assert Rake::Task[:rdoc] diff --git a/test/rdoc/test_rdoc_text.rb b/test/rdoc/test_rdoc_text.rb index e11c995e59..47eb4de906 100644 --- a/test/rdoc/test_rdoc_text.rb +++ b/test/rdoc/test_rdoc_text.rb @@ -1,16 +1,26 @@ # coding: utf-8 -require 'rubygems' -require 'minitest/autorun' -require 'rdoc' -require 'rdoc/text' -require 'rdoc/markup' -require 'rdoc/markup/formatter' +require 'rdoc/test_case' -class TestRDocText < MiniTest::Unit::TestCase +class TestRDocText < RDoc::TestCase include RDoc::Text + def setup + super + + @options = RDoc::Options.new + + @top_level = @store.add_file 'file.rb' + end + + def mu_pp obj + s = '' + s = PP.pp obj, s + s = s.force_encoding Encoding.default_external if defined? Encoding + s.chomp + end + def test_self_encode_fallback skip "Encoding not implemented" unless Object.const_defined? :Encoding @@ -110,13 +120,19 @@ The comments associated with assert_equal Encoding::US_ASCII, result.encoding end - def test_markup - def formatter() RDoc::Markup::ToHtml.new end + def test_markup_string + out = markup('hi').gsub("\n", '') - assert_equal "<p>hi</p>", markup('hi').gsub("\n", '') + assert_equal '<p>hi</p>', out end - def test_normalize_comment + def test_markup_comment + out = markup(comment('hi')).gsub("\n", '') + + assert_equal '<p>hi</p>', out + end + + def test_normalize_comment_hash text = <<-TEXT ## # we don't worry too much. @@ -127,6 +143,42 @@ The comments associated with expected = <<-EXPECTED.rstrip we don't worry too much. +The comments associated with + EXPECTED + + assert_equal expected, normalize_comment(text) + end + + def test_normalize_comment_stars_single_space + text = <<-TEXT +/* + * we don't worry too much. + * + * The comments associated with + */ + TEXT + + expected = <<-EXPECTED.rstrip +we don't worry too much. + +The comments associated with + EXPECTED + + assert_equal expected, normalize_comment(text) + end + + def test_normalize_comment_stars_single_double_space + text = <<-TEXT +/* + * we don't worry too much. + * + * The comments associated with + */ + TEXT + + expected = <<-EXPECTED.rstrip +we don't worry too much. + The comments associated with EXPECTED @@ -137,6 +189,17 @@ The comments associated with assert_kind_of RDoc::Markup::Document, parse('hi') end + def test_parse_comment + expected = RDoc::Markup::Document.new + expected.file = @top_level + + c = comment '' + parsed = parse c + + assert_equal expected, parsed + assert_same parsed, parse(c) + end + def test_parse_document assert_equal RDoc::Markup::Document.new, parse(RDoc::Markup::Document.new) end @@ -149,10 +212,92 @@ The comments associated with assert_equal RDoc::Markup::Document.new, parse("#\n") end + def test_parse_format_markdown + expected = + @RM::Document.new( + @RM::Paragraph.new('it _works_')) + + parsed = parse 'it *works*', 'markdown' + + assert_equal expected, parsed + end + + def test_parse_format_rd + expected = + @RM::Document.new( + @RM::Paragraph.new('it <em>works</em>')) + + parsed = parse 'it ((*works*))', 'rd' + + assert_equal expected, parsed + end + + def test_parse_format_tomdoc + code = verb('1 + 1') + code.format = :ruby + + expected = + doc( + para('It does a thing'), + blank_line, + head(3, 'Examples'), + blank_line, + code) + + text = <<-TOMDOC +It does a thing + +Examples + + 1 + 1 + TOMDOC + + parsed = parse text, 'tomdoc' + + assert_equal expected, parsed + end + def test_parse_newline assert_equal RDoc::Markup::Document.new, parse("\n") end +# def test_snippet +# text = <<-TEXT +#This is one-hundred characters or more of text in a single paragraph. This +#paragraph will be cut off some point after the one-hundredth character. +# TEXT +# +# expected = text.gsub(/\r?\n/, ' ').sub(/ some point.*/, '') +# +# assert_equal expected, snippet(text) +# end +# +# def test_snippet_comment +# c = comment 'This is a comment' +# +# assert_equal 'This is a comment', snippet(c) +# end +# +# def test_snippet_no_space +# text = <<-TEXT.strip +#This is one-hundred characters or more of text in a single paragraph. This +#paragraph will not be cut +# TEXT +# +# expected = <<-EXPECTED.strip.gsub(/\r?\n/, ' ') +#This is one-hundred characters or more of text in a single paragraph. This +#paragraph will not be cut +# EXPECTED +# +# assert_equal expected, snippet(text) +# end +# +# def test_snippet_short +# text = 'This is a comment' +# +# assert_equal text.dup, snippet(text) +# end + def test_strip_hashes text = <<-TEXT ## @@ -309,6 +454,24 @@ The comments associated with assert_equal Encoding::BINARY, result.encoding end + def test_strip_stars_no_stars + text = <<-TEXT +* we don't worry too much. + +The comments associated with + + TEXT + + expected = <<-EXPECTED +* we don't worry too much. + +The comments associated with + + EXPECTED + + assert_equal expected, strip_stars(text) + end + def test_to_html_apostrophe assert_equal '‘a', to_html("'a") assert_equal 'a’', to_html("a'") @@ -320,6 +483,10 @@ The comments associated with assert_equal 'S', to_html('\\S') end + def test_to_html_br + assert_equal '<br>', to_html('<br>') + end + def test_to_html_copyright assert_equal '©', to_html('(c)') end @@ -393,5 +560,9 @@ The comments associated with assert_equal "mismatched <tt> tag\n", err end + def formatter() + RDoc::Markup::ToHtml.new @options + end + end diff --git a/test/rdoc/test_rdoc_token_stream.rb b/test/rdoc/test_rdoc_token_stream.rb new file mode 100644 index 0000000000..3c1a225c25 --- /dev/null +++ b/test/rdoc/test_rdoc_token_stream.rb @@ -0,0 +1,42 @@ +require 'rdoc/test_case' + +class TestRDocTokenStream < RDoc::TestCase + + def test_class_to_html + tokens = [ + RDoc::RubyToken::TkCONSTANT. new(0, 0, 0, 'CONSTANT'), + RDoc::RubyToken::TkDEF. new(0, 0, 0, 'KW'), + RDoc::RubyToken::TkIVAR. new(0, 0, 0, 'IVAR'), + RDoc::RubyToken::TkOp. new(0, 0, 0, 'Op'), + RDoc::RubyToken::TkId. new(0, 0, 0, 'Id'), + RDoc::RubyToken::TkNode. new(0, 0, 0, 'Node'), + RDoc::RubyToken::TkCOMMENT. new(0, 0, 0, 'COMMENT'), + RDoc::RubyToken::TkREGEXP. new(0, 0, 0, 'REGEXP'), + RDoc::RubyToken::TkSTRING. new(0, 0, 0, 'STRING'), + RDoc::RubyToken::TkVal. new(0, 0, 0, 'Val'), + RDoc::RubyToken::TkBACKSLASH.new(0, 0, 0, '\\'), + ] + + expected = [ + '<span class="ruby-constant">CONSTANT</span>', + '<span class="ruby-keyword">KW</span>', + '<span class="ruby-ivar">IVAR</span>', + '<span class="ruby-operator">Op</span>', + '<span class="ruby-identifier">Id</span>', + '<span class="ruby-node">Node</span>', + '<span class="ruby-comment">COMMENT</span>', + '<span class="ruby-regexp">REGEXP</span>', + '<span class="ruby-string">STRING</span>', + '<span class="ruby-value">Val</span>', + '\\' + ].join + + assert_equal expected, RDoc::TokenStream.to_html(tokens) + end + + def test_class_to_html_empty + assert_equal '', RDoc::TokenStream.to_html([]) + end + +end + diff --git a/test/rdoc/test_rdoc_tom_doc.rb b/test/rdoc/test_rdoc_tom_doc.rb new file mode 100644 index 0000000000..08f30d1e53 --- /dev/null +++ b/test/rdoc/test_rdoc_tom_doc.rb @@ -0,0 +1,455 @@ +require 'rdoc/test_case' + +class TestRDocTomDoc < RDoc::TestCase + + def setup + super + + @top_level = @store.add_file 'file.rb' + + @TD = RDoc::TomDoc + @td = @TD.new + end + + def mu_pp obj + s = '' + s = PP.pp obj, s + s = s.force_encoding Encoding.default_external if defined? Encoding + s.chomp + end + + def test_class_add_post_processor + RDoc::TomDoc.add_post_processor + + pp = RDoc::Markup::PreProcess.new __FILE__, [] + + text = "# Public: Do some stuff\n" + + comment = RDoc::Comment.new text, nil + comment.format = 'tomdoc' + + parent = RDoc::Context.new + + pp.handle comment, parent + + method = parent.add_method RDoc::AnyMethod.new(nil, 'm') + + assert_equal 'Public', method.section.title + assert_equal "# Do some stuff\n", comment.text + end + + def test_class_signature + c = comment <<-COMMENT +Signature + + method_<here>(args) + +here - something + COMMENT + c.format = 'tomdoc' + + signature = @TD.signature c + + assert_equal "method_<here>(args)\n", signature + end + + def test_class_signature_no_space + c = comment <<-COMMENT +Signature + method_<here>(args) + +here - something + COMMENT + c.format = 'tomdoc' + + signature = @TD.signature c + + assert_equal "method_<here>(args)\n", signature + + expected = + doc( + head(3, 'Signature'), + list(:NOTE, + item(%w[here], + para('something')))) + expected.file = @top_level + + assert_equal expected, c.parse + end + + def test_class_signature_none + c = comment '' + c.format = 'tomdoc' + + assert_nil @TD.signature c + end + + def test_class_rdoc + c = comment <<-COMMENT +=== Signature + + method_<here>(args) + +here - something + COMMENT + c.format = 'rdoc' + + signature = @TD.signature c + + assert_nil signature + end + + def test_class_signature_two_space + c = comment <<-COMMENT +Signature + + + method_<here>(args) + +here - something + COMMENT + c.format = 'tomdoc' + + signature = @TD.signature c + + assert_equal "method_<here>(args)\n", signature + + expected = + doc( + head(3, 'Signature'), + list(:NOTE, + item(%w[here], + para('something')))) + expected.file = @top_level + + assert_equal expected, c.parse + end + + def test_parse_paragraph + text = "Public: Do some stuff\n" + + expected = + @RM::Document.new( + @RM::Paragraph.new('Do some stuff')) + + assert_equal expected, @TD.parse(text) + end + + def test_parse_arguments + text = <<-TEXT +Create new Arg object. + +name - name of argument +description - arguments description + TEXT + + expected = + doc( + para('Create new Arg object.'), + blank_line, + list(:NOTE, + item(%w[name], + para('name of argument')), + item(%w[description], + para('arguments description')))) + + assert_equal expected, @TD.parse(text) + end + + def test_parse_arguments_multiline + text = <<-TEXT +Do some stuff + +foo - A comment goes here + and is more than one line + TEXT + + expected = + doc( + para('Do some stuff'), + blank_line, + list(:NOTE, + item(%w[foo], + para('A comment goes here', 'and is more than one line')))) + + assert_equal expected, @TD.parse(text) + end + + def test_parse_arguments_nested + text = <<-TEXT +Do some stuff + +foo - A comment goes here + :bar - bar documentation + TEXT + + expected = + doc( + para('Do some stuff'), + blank_line, + list(:NOTE, + item(%w[foo], + para('A comment goes here'), + list(:NOTE, + item(%w[:bar], + para('bar documentation')))))) + + assert_equal expected, @TD.parse(text) + end + + def test_parse_examples + text = <<-TEXT +Do some stuff + +Examples + + 1 + 1 + TEXT + + code = verb("1 + 1\n") + code.format = :ruby + + expected = + doc( + para('Do some stuff'), + blank_line, + head(3, 'Examples'), + blank_line, + code) + + document = @TD.parse(text) + assert_equal expected, document + assert document.parts.last.ruby? + end + + def test_parse_examples_signature + text = <<-TEXT +Do some stuff + +Examples + + 1 + 1 + +Signature + + foo(args) + TEXT + + code1 = verb("1 + 1\n") + code1.format = :ruby + + code2 = verb("foo(args)\n") + + expected = + doc( + para('Do some stuff'), + blank_line, + head(3, 'Examples'), + blank_line, + code1, + head(3, 'Signature'), + blank_line, + code2) + + document = @TD.parse text + + assert_equal expected, document + end + + def test_parse_returns + text = <<-TEXT +Do some stuff + +Returns a thing + TEXT + + expected = + @RM::Document.new( + @RM::Paragraph.new('Do some stuff'), + @RM::BlankLine.new, + @RM::Paragraph.new('Returns a thing')) + + assert_equal expected, @TD.parse(text) + end + + def test_parse_returns_multiline + text = <<-TEXT +Do some stuff + +Returns a thing + that is multiline + TEXT + + expected = + @RM::Document.new( + @RM::Paragraph.new('Do some stuff'), + @RM::BlankLine.new, + @RM::Paragraph.new('Returns a thing', 'that is multiline')) + + assert_equal expected, @TD.parse(text) + end + + def test_parse_signature + text = <<-TEXT +Do some stuff + +Signature + + some_method(args) + TEXT + + expected = + @RM::Document.new( + @RM::Paragraph.new('Do some stuff'), + @RM::BlankLine.new, + @RM::Heading.new(3, 'Signature'), + @RM::BlankLine.new, + @RM::Verbatim.new("some_method(args)\n")) + + assert_equal expected, @TD.parse(text) + end + + def test_tokenize_paragraph + @td.tokenize "Public: Do some stuff\n" + + expected = [ + [:TEXT, "Do some stuff", 0, 0], + [:NEWLINE, "\n", 13, 0], + ] + + assert_equal expected, @td.tokens + end + + def test_tokenize_arguments + @td.tokenize <<-TEXT +Create new Arg object. + +name - name of argument +description - arguments description + TEXT + + expected = [ + [:TEXT, "Create new Arg object.", 0, 0], + [:NEWLINE, "\n", 22, 0], + [:NEWLINE, "\n", 0, 1], + [:NOTE, "name", 0, 2], + [:TEXT, "name of argument", 14, 2], + [:NEWLINE, "\n", 30, 2], + [:NOTE, "description", 0, 3], + [:TEXT, "arguments description", 14, 3], + [:NEWLINE, "\n", 35, 3], + ] + + assert_equal expected, @td.tokens + end + + def test_tokenize_arguments_multiline + @td.tokenize <<-TEXT +Do some stuff + +foo - A comment goes here + and is more than one line + TEXT + + expected = [ + [:TEXT, "Do some stuff", 0, 0], + [:NEWLINE, "\n", 13, 0], + [:NEWLINE, "\n", 0, 1], + [:NOTE, "foo", 0, 2], + [:TEXT, "A comment goes here", 6, 2], + [:NEWLINE, "\n", 25, 2], + [:TEXT, "and is more than one line", 2, 3], + [:NEWLINE, "\n", 27, 3], + ] + + assert_equal expected, @td.tokens + end + + def test_tokenize_arguments_nested + @td.tokenize <<-TEXT +Do some stuff + +foo - A comment goes here + :bar - bar documentation + TEXT + + expected = [ + [:TEXT, "Do some stuff", 0, 0], + [:NEWLINE, "\n", 13, 0], + [:NEWLINE, "\n", 0, 1], + [:NOTE, "foo", 0, 2], + [:TEXT, "A comment goes here", 6, 2], + [:NEWLINE, "\n", 25, 2], + [:NOTE, ":bar", 6, 3], + [:TEXT, "bar documentation", 13, 3], + [:NEWLINE, "\n", 30, 3], + ] + + assert_equal expected, @td.tokens + end + + def test_tokenize_examples + @td.tokenize <<-TEXT +Do some stuff + +Examples + + 1 + 1 + TEXT + + expected = [ + [:TEXT, "Do some stuff", 0, 0], + [:NEWLINE, "\n", 13, 0], + [:NEWLINE, "\n", 0, 1], + [:HEADER, 3, 0, 2], + [:TEXT, "Examples", 0, 2], + [:NEWLINE, "\n", 8, 2], + [:NEWLINE, "\n", 0, 3], + [:TEXT, "1 + 1", 2, 4], + [:NEWLINE, "\n", 7, 4], + ] + + assert_equal expected, @td.tokens + end + + def test_tokenize_returns + @td.tokenize <<-TEXT +Do some stuff + +Returns a thing + TEXT + + expected = [ + [:TEXT, "Do some stuff", 0, 0], + [:NEWLINE, "\n", 13, 0], + [:NEWLINE, "\n", 0, 1], + [:TEXT, "Returns a thing", 0, 2], + [:NEWLINE, "\n", 15, 2], + ] + + assert_equal expected, @td.tokens + end + + def test_tokenize_returns_multiline + @td.tokenize <<-TEXT +Do some stuff + +Returns a thing + that is multiline + TEXT + + expected = [ + [:TEXT, "Do some stuff", 0, 0], + [:NEWLINE, "\n", 13, 0], + [:NEWLINE, "\n", 0, 1], + [:TEXT, "Returns a thing", 0, 2], + [:NEWLINE, "\n", 15, 2], + [:TEXT, "that is multiline", 2, 3], + [:NEWLINE, "\n", 19, 3], + ] + + assert_equal expected, @td.tokens + end + +end + diff --git a/test/rdoc/test_rdoc_top_level.rb b/test/rdoc/test_rdoc_top_level.rb index 9e68bc4bdd..61f4362d09 100644 --- a/test/rdoc/test_rdoc_top_level.rb +++ b/test/rdoc/test_rdoc_top_level.rb @@ -1,5 +1,3 @@ -require 'rubygems' -require 'minitest/autorun' require File.expand_path '../xref_test_case', __FILE__ class TestRDocTopLevel < XrefTestCase @@ -7,102 +5,15 @@ class TestRDocTopLevel < XrefTestCase def setup super - @top_level = RDoc::TopLevel.new 'path/top_level.rb' - end - - def test_class_all_classes_and_modules - expected = %w[ - C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 - Child - M1 M1::M2 - Parent - ] - - assert_equal expected, - RDoc::TopLevel.all_classes_and_modules.map { |m| m.full_name }.sort - end - - def test_class_classes - expected = %w[ - C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 - Child Parent - ] - - assert_equal expected, RDoc::TopLevel.classes.map { |m| m.full_name }.sort - end - - def test_class_complete - @c2.add_module_alias @c2_c3, 'A1', @top_level - - RDoc::TopLevel.complete :public - - a1 = @xref_data.find_class_or_module 'C2::A1' - - assert_equal 'C2::A1', a1.full_name - refute_empty a1.aliases - end - - def test_class_files - assert_equal %w[path/top_level.rb xref_data.rb], - RDoc::TopLevel.files.map { |m| m.full_name }.sort - end - - def test_class_find_class_named - assert_equal @c1, RDoc::TopLevel.find_class_named('C1') - - assert_equal @c2_c3, RDoc::TopLevel.find_class_named('C2::C3') - end - - def test_class_find_class_named_from - assert_equal @c5_c1, RDoc::TopLevel.find_class_named_from('C1', 'C5') - - assert_equal @c1, RDoc::TopLevel.find_class_named_from('C1', 'C4') - end - - def test_class_find_class_or_module - assert_equal @m1, RDoc::TopLevel.find_class_or_module('M1') - assert_equal @c1, RDoc::TopLevel.find_class_or_module('C1') - - assert_equal @m1, RDoc::TopLevel.find_class_or_module('::M1') - assert_equal @c1, RDoc::TopLevel.find_class_or_module('::C1') - end - - def test_class_find_file_named - assert_equal @xref_data, RDoc::TopLevel.find_file_named(@file_name) - end - - def test_class_find_module_named - assert_equal @m1, RDoc::TopLevel.find_module_named('M1') - assert_equal @m1_m2, RDoc::TopLevel.find_module_named('M1::M2') - end - - def test_class_modules - assert_equal %w[M1 M1::M2], - RDoc::TopLevel.modules.map { |m| m.full_name }.sort - end - - def test_class_new - tl1 = RDoc::TopLevel.new 'file.rb' - tl2 = RDoc::TopLevel.new 'file.rb' - tl3 = RDoc::TopLevel.new 'other.rb' - - assert_same tl1, tl2 - refute_same tl1, tl3 - end - - def test_class_reset - RDoc::TopLevel.reset - - assert_empty RDoc::TopLevel.classes - assert_empty RDoc::TopLevel.modules - assert_empty RDoc::TopLevel.files + @top_level = @store.add_file 'path/top_level.rb' + @top_level.parser = RDoc::Parser::Ruby end def test_add_alias a = RDoc::Alias.new nil, 'old', 'new', nil @top_level.add_alias a - object = RDoc::TopLevel.find_class_named 'Object' + object = @store.find_class_named 'Object' expected = { '#old' => [a] } assert_equal expected, object.unmatched_alias_lists assert_includes object.in_files, @top_level @@ -114,7 +25,7 @@ class TestRDocTopLevel < XrefTestCase a = RDoc::Alias.new nil, 'old', 'new', nil @top_level.add_alias a - object = RDoc::TopLevel.find_class_named('Object') + object = @store.find_class_named('Object') assert_empty object.unmatched_alias_lists assert_includes object.in_files, @top_level end @@ -123,7 +34,7 @@ class TestRDocTopLevel < XrefTestCase const = RDoc::Constant.new 'C', nil, nil @top_level.add_constant const - object = RDoc::TopLevel.find_class_named 'Object' + object = @store.find_class_named 'Object' assert_equal [const], object.constants assert_includes object.in_files, @top_level end @@ -134,7 +45,7 @@ class TestRDocTopLevel < XrefTestCase const = RDoc::Constant.new 'C', nil, nil @top_level.add_constant const - object = RDoc::TopLevel.find_class_named 'Object' + object = @store.find_class_named 'Object' assert_empty object.constants assert_includes object.in_files, @top_level end @@ -143,7 +54,7 @@ class TestRDocTopLevel < XrefTestCase include = RDoc::Include.new 'C', nil @top_level.add_include include - object = RDoc::TopLevel.find_class_named 'Object' + object = @store.find_class_named 'Object' assert_equal [include], object.includes assert_includes object.in_files, @top_level end @@ -154,7 +65,7 @@ class TestRDocTopLevel < XrefTestCase include = RDoc::Include.new 'C', nil @top_level.add_include include - object = RDoc::TopLevel.find_class_named('Object') + object = @store.find_class_named('Object') assert_empty object.includes assert_includes object.in_files, @top_level end @@ -163,7 +74,7 @@ class TestRDocTopLevel < XrefTestCase method = RDoc::AnyMethod.new nil, 'm' @top_level.add_method method - object = RDoc::TopLevel.find_class_named 'Object' + object = @store.find_class_named 'Object' assert_equal [method], object.method_list assert_includes object.in_files, @top_level end @@ -174,7 +85,7 @@ class TestRDocTopLevel < XrefTestCase method = RDoc::AnyMethod.new nil, 'm' @top_level.add_method method - object = RDoc::TopLevel.find_class_named('Object') + object = @store.find_class_named('Object') assert_empty object.method_list assert_includes object.in_files, @top_level end @@ -183,9 +94,18 @@ class TestRDocTopLevel < XrefTestCase assert_equal 'top_level.rb', @top_level.base_name end + def test_display_eh + refute @top_level.display? + + page = @store.add_file 'README.txt' + page.parser = RDoc::Parser::Simple + + assert page.display? + end + def test_eql_eh - top_level2 = RDoc::TopLevel.new 'path/top_level.rb' - other_level = RDoc::TopLevel.new 'path/other_level.rb' + top_level2 = @store.add_file 'path/top_level.rb' + other_level = @store.add_file 'path/other_level.rb' assert_operator @top_level, :eql?, top_level2 @@ -193,8 +113,8 @@ class TestRDocTopLevel < XrefTestCase end def test_equals2 - top_level2 = RDoc::TopLevel.new 'path/top_level.rb' - other_level = RDoc::TopLevel.new 'path/other_level.rb' + top_level2 = @store.add_file 'path/top_level.rb' + other_level = @store.add_file 'path/other_level.rb' assert_equal @top_level, top_level2 @@ -213,8 +133,8 @@ class TestRDocTopLevel < XrefTestCase end def test_hash - tl2 = RDoc::TopLevel.new 'path/top_level.rb' - tl3 = RDoc::TopLevel.new 'other/top_level.rb' + tl2 = @store.add_file 'path/top_level.rb' + tl3 = @store.add_file 'other/top_level.rb' assert_equal @top_level.hash, tl2.hash refute_equal @top_level.hash, tl3.hash @@ -232,9 +152,106 @@ class TestRDocTopLevel < XrefTestCase assert_equal 0, @top_level.last_modified end + def test_marshal_dump + page = @store.add_file 'README.txt' + page.parser = RDoc::Parser::Simple + page.comment = RDoc::Comment.new 'This is a page', page + + loaded = Marshal.load Marshal.dump page + + comment = RDoc::Markup::Document.new( + RDoc::Markup::Paragraph.new('This is a page')) + comment.file = loaded + + assert_equal page, loaded + + assert_equal 'README.txt', loaded.absolute_name + assert_equal 'README.txt', loaded.relative_name + + assert_equal RDoc::Parser::Simple, loaded.parser + + assert_equal comment, loaded.comment + end + + def test_marshal_load_version_0 + loaded = Marshal.load "\x04\bU:\x13RDoc::TopLevel" + + "[\ti\x00I\"\x0FREADME.txt\x06:\x06EF" + + "c\x19RDoc::Parser::Simple" + + "o:\eRDoc::Markup::Document\a:\v@parts" + + "[\x06o:\x1CRDoc::Markup::Paragraph\x06;\b" + + "[\x06I\"\x13This is a page\x06;\x06F:\n@file@\a" + + comment = RDoc::Markup::Document.new( + RDoc::Markup::Paragraph.new('This is a page')) + comment.file = loaded + + assert_equal 'README.txt', loaded.absolute_name + assert_equal 'README.txt', loaded.relative_name + + assert_equal RDoc::Parser::Simple, loaded.parser + + assert_equal comment, loaded.comment + end + def test_name assert_equal 'top_level.rb', @top_level.name end + def test_page_name + assert_equal 'top_level', @top_level.page_name + + tl = @store.add_file 'README.ja.rdoc' + + assert_equal 'README.ja', tl.page_name + + tl = @store.add_file 'Rakefile' + + assert_equal 'Rakefile', tl.page_name + end + + def test_search_record + assert_nil @xref_data.search_record + end + + def test_search_record_page + page = @store.add_file 'README.txt' + page.parser = RDoc::Parser::Simple + page.comment = 'This is a comment.' + + expected = [ + 'README', + '', + 'README', + '', + 'README_txt.html', + '', + "<p>This is a comment.\n", + ] + + assert_equal expected, page.search_record + end + + def test_text_eh + refute @xref_data.text? + + rd = @store.add_file 'rd_format.rd' + rd.parser = RDoc::Parser::RD + + assert rd.text? + + simple = @store.add_file 'simple.txt' + simple.parser = RDoc::Parser::Simple + + assert simple.text? + end + + def test_text_eh_no_parser + refute @xref_data.text? + + rd = @store.add_file 'rd_format.rd' + + refute rd.text? + end + end diff --git a/test/rdoc/xref_test_case.rb b/test/rdoc/xref_test_case.rb index a001700d3b..29021a301c 100644 --- a/test/rdoc/xref_test_case.rb +++ b/test/rdoc/xref_test_case.rb @@ -1,26 +1,21 @@ ENV['RDOC_TEST'] = 'yes' -require 'rubygems' -require 'minitest/autorun' require 'rdoc' -require 'rdoc/stats' -require 'rdoc/options' -require 'rdoc/code_objects' -require 'rdoc/parser/ruby' require File.expand_path '../xref_data', __FILE__ -class XrefTestCase < MiniTest::Unit::TestCase +class XrefTestCase < RDoc::TestCase def setup - RDoc::TopLevel.reset - - @file_name = 'xref_data.rb' - @xref_data = RDoc::TopLevel.new @file_name + super @options = RDoc::Options.new @options.quiet = true - stats = RDoc::Stats.new 0 + @file_name = 'xref_data.rb' + @xref_data = @store.add_file @file_name + @top_level = @xref_data + + stats = RDoc::Stats.new @store, 0 parser = RDoc::Parser::Ruby.new @xref_data, @file_name, XREF_DATA, @options, stats @@ -30,9 +25,8 @@ class XrefTestCase < MiniTest::Unit::TestCase generator = Object.new def generator.class_dir() nil end def generator.file_dir() nil end - rdoc = RDoc::RDoc.new - RDoc::RDoc.current = rdoc - rdoc.generator = generator + @rdoc.options = @options + @rdoc.generator = generator @c1 = @xref_data.find_module_named 'C1' @c1_m = @c1.method_list.last # C1#m -- cgit v1.2.3