diff options
Diffstat (limited to 'lib/rdoc')
102 files changed, 2278 insertions, 1379 deletions
diff --git a/lib/rdoc/alias.rb b/lib/rdoc/alias.rb index 858e053049..446cf9ccb4 100644 --- a/lib/rdoc/alias.rb +++ b/lib/rdoc/alias.rb @@ -109,4 +109,3 @@ class RDoc::Alias < RDoc::CodeObject end end - diff --git a/lib/rdoc/anon_class.rb b/lib/rdoc/anon_class.rb index d02a38c2cf..3c2f0e1877 100644 --- a/lib/rdoc/anon_class.rb +++ b/lib/rdoc/anon_class.rb @@ -8,4 +8,3 @@ class RDoc::AnonClass < RDoc::ClassModule end - diff --git a/lib/rdoc/any_method.rb b/lib/rdoc/any_method.rb index 0b7dd717ab..465c4a4fb2 100644 --- a/lib/rdoc/any_method.rb +++ b/lib/rdoc/any_method.rb @@ -116,6 +116,13 @@ class RDoc::AnyMethod < RDoc::MethodAttr end ## + # Whether the method has a call-seq. + + def has_call_seq? + !!(@call_seq || is_alias_for&._call_seq) + end + + ## # Loads is_alias_for from the internal name. Returns nil if the alias # cannot be found. @@ -297,6 +304,14 @@ class RDoc::AnyMethod < RDoc::MethodAttr end ## + # Whether to skip the method description, true for methods that have + # aliases with a call-seq that doesn't include the method name. + + def skip_description? + has_call_seq? && call_seq.nil? && !!(is_alias_for || !aliases.empty?) + end + + ## # Sets the store for this method and its referenced code objects. def store= store @@ -350,12 +365,12 @@ class RDoc::AnyMethod < RDoc::MethodAttr ignore << is_alias_for.name ignore.concat is_alias_for.aliases.map(&:name) end - ignore.map! { |n| n =~ /\A\[/ ? n[0, 1] : n} + ignore.map! { |n| n =~ /\A\[/ ? /\[.*\]/ : n} ignore.delete(method_name) ignore = Regexp.union(ignore) matching = entries.reject do |entry| - entry =~ /^\w*\.?#{ignore}/ or + entry =~ /^\w*\.?#{ignore}[$\(\s]/ or entry =~ /\s#{ignore}\s/ end diff --git a/lib/rdoc/attr.rb b/lib/rdoc/attr.rb index f780b3b976..a403235933 100644 --- a/lib/rdoc/attr.rb +++ b/lib/rdoc/attr.rb @@ -173,4 +173,3 @@ class RDoc::Attr < RDoc::MethodAttr end end - diff --git a/lib/rdoc/class_module.rb b/lib/rdoc/class_module.rb index 7609080fbf..c69e14b5e4 100644 --- a/lib/rdoc/class_module.rb +++ b/lib/rdoc/class_module.rb @@ -799,4 +799,3 @@ class RDoc::ClassModule < RDoc::Context end end - diff --git a/lib/rdoc/comment.rb b/lib/rdoc/comment.rb index 9e90999eac..04ec226436 100644 --- a/lib/rdoc/comment.rb +++ b/lib/rdoc/comment.rb @@ -6,8 +6,8 @@ # Each comment may have a different markup format set by #format=. By default # 'rdoc' is used. The :markup: directive tells RDoc which format to use. # -# See RDoc::Markup@Other+directives for instructions on adding an alternate -# format. +# See RDoc::MarkupReference@Directive+for+Specifying+RDoc+Source+Format. + class RDoc::Comment @@ -97,42 +97,26 @@ class RDoc::Comment # comment. The difficulty is to make sure not to match lines starting # with ARGF at the same indent, but that are after the first description # paragraph. - if @text =~ /^\s*:?call-seq:(.*?(?:\S).*?)^\s*$/m then + if /^(?<S> ((?!\n)\s)*+ (?# whitespaces except newline)) + :?call-seq: + (?<B> \g<S>(?<N>\n|\z) (?# trailing spaces))? + (?<seq> + (\g<S>(?!\w)\S.*\g<N>)* + (?> + (?<H> \g<S>\w+ (?# ' # ARGF' in the example above)) + .*\g<N>)? + (\g<S>\S.*\g<N> (?# other non-blank line))*+ + (\g<B>+(\k<H>.*\g<N> (?# ARGF.to_a lines))++)*+ + ) + (?m:^\s*$|\z) + /x =~ @text + seq = $~[:seq] + all_start, all_stop = $~.offset(0) - seq_start, seq_stop = $~.offset(1) - - # we get the following lines that start with the leading word at the - # same indent, even if they have blank lines before - if $1 =~ /(^\s*\n)+^(\s*\w+)/m then - leading = $2 # ' * ARGF' in the example above - re = %r% - \A( - (^\s*\n)+ - (^#{Regexp.escape leading}.*?\n)+ - )+ - ^\s*$ - %xm - - if @text[seq_stop..-1] =~ re then - all_stop = seq_stop + $~.offset(0).last - seq_stop = seq_stop + $~.offset(1).last - end - end - - seq = @text[seq_start..seq_stop] - seq.gsub!(/^\s*(\S|\n)/m, '\1') @text.slice! all_start...all_stop - method.call_seq = seq.chomp - - else - regexp = /^\s*:?call-seq:(.*?)(^\s*$|\z)/m - if regexp =~ @text then - @text = @text.sub(regexp, '') - seq = $1 - seq.gsub!(/^\s*/, '') - method.call_seq = seq - end + seq.gsub!(/^\s*/, '') + method.call_seq = seq end method @@ -149,12 +133,7 @@ class RDoc::Comment # HACK dubious def encode! encoding - # TODO: Remove this condition after Ruby 2.2 EOL - if RUBY_VERSION < '2.3.0' - @text = @text.force_encoding encoding - else - @text = String.new @text, encoding: encoding - end + @text = String.new @text, encoding: encoding self end diff --git a/lib/rdoc/constant.rb b/lib/rdoc/constant.rb index 0c3d7505a1..12b8be775c 100644 --- a/lib/rdoc/constant.rb +++ b/lib/rdoc/constant.rb @@ -184,4 +184,3 @@ class RDoc::Constant < RDoc::CodeObject end end - diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb index c6edfb473c..c688d562c3 100644 --- a/lib/rdoc/context.rb +++ b/lib/rdoc/context.rb @@ -710,7 +710,7 @@ class RDoc::Context < RDoc::CodeObject # This method exists to make it easy to work with Context subclasses that # aren't part of RDoc. - def each_ancestor # :nodoc: + def each_ancestor(&_) # :nodoc: end ## diff --git a/lib/rdoc/context/section.rb b/lib/rdoc/context/section.rb index c316efe99f..aecd4e0213 100644 --- a/lib/rdoc/context/section.rb +++ b/lib/rdoc/context/section.rb @@ -231,4 +231,3 @@ class RDoc::Context::Section end end - diff --git a/lib/rdoc/cross_reference.rb b/lib/rdoc/cross_reference.rb index 319bbc02ac..4e011219e8 100644 --- a/lib/rdoc/cross_reference.rb +++ b/lib/rdoc/cross_reference.rb @@ -131,6 +131,9 @@ class RDoc::CrossReference @seen = {} end + ## + # Returns a method reference to +name+. + def resolve_method name ref = nil @@ -223,4 +226,3 @@ class RDoc::CrossReference end end - diff --git a/lib/rdoc/encoding.rb b/lib/rdoc/encoding.rb index cf60badd24..67e190f782 100644 --- a/lib/rdoc/encoding.rb +++ b/lib/rdoc/encoding.rb @@ -86,17 +86,6 @@ module RDoc::Encoding nil end - def self.remove_frozen_string_literal string - string =~ /\A(?:#!.*\n)?(.*\n)/ - first_line = $1 - - if first_line =~ /\A# +frozen[-_]string[-_]literal[=:].+$/i - string = string.sub first_line, '' - end - - string - end - ## # Detects the encoding of +string+ based on the magic comment @@ -124,12 +113,7 @@ module RDoc::Encoding if text.kind_of? RDoc::Comment text.encode! encoding else - # TODO: Remove this condition after Ruby 2.2 EOL - if RUBY_VERSION < '2.3.0' - text.force_encoding encoding - else - String.new text, encoding: encoding - end + String.new text, encoding: encoding end end diff --git a/lib/rdoc/erb_partial.rb b/lib/rdoc/erb_partial.rb index d6e3f41b7e..043d763db1 100644 --- a/lib/rdoc/erb_partial.rb +++ b/lib/rdoc/erb_partial.rb @@ -16,4 +16,3 @@ class RDoc::ERBPartial < ERB end end - diff --git a/lib/rdoc/erbio.rb b/lib/rdoc/erbio.rb index 0d5f96e133..0f98eaedee 100644 --- a/lib/rdoc/erbio.rb +++ b/lib/rdoc/erbio.rb @@ -20,12 +20,8 @@ class RDoc::ERBIO < ERB ## # Defaults +eoutvar+ to 'io', otherwise is identical to ERB's initialize - def initialize str, safe_level = nil, legacy_trim_mode = nil, legacy_eoutvar = 'io', trim_mode: nil, eoutvar: 'io' - if RUBY_VERSION >= '2.6' - super(str, trim_mode: trim_mode, eoutvar: eoutvar) - else - super(str, safe_level, legacy_trim_mode, legacy_eoutvar) - end + def initialize str, trim_mode: nil, eoutvar: 'io' + super(str, trim_mode: trim_mode, eoutvar: eoutvar) end ## @@ -39,4 +35,3 @@ class RDoc::ERBIO < ERB end end - diff --git a/lib/rdoc/extend.rb b/lib/rdoc/extend.rb index e1b182902e..7d57433de6 100644 --- a/lib/rdoc/extend.rb +++ b/lib/rdoc/extend.rb @@ -7,4 +7,3 @@ class RDoc::Extend < RDoc::Mixin end - diff --git a/lib/rdoc/generator/darkfish.rb b/lib/rdoc/generator/darkfish.rb index 60e0265e8c..1b408a6f8e 100644 --- a/lib/rdoc/generator/darkfish.rb +++ b/lib/rdoc/generator/darkfish.rb @@ -610,7 +610,7 @@ class RDoc::Generator::Darkfish @classes = @store.all_classes_and_modules.sort @files = @store.all_files.sort - @methods = @classes.map { |m| m.method_list }.flatten.sort + @methods = @classes.flat_map { |m| m.method_list }.sort @modsort = get_sorted_module_list @classes end @@ -778,11 +778,7 @@ class RDoc::Generator::Darkfish erbout = "_erbout_#{file_var}" end - if RUBY_VERSION >= '2.6' - template = klass.new template, trim_mode: '-', eoutvar: erbout - else - template = klass.new template, nil, '-', erbout - end + template = klass.new template, trim_mode: '-', eoutvar: erbout @template_cache[file] = template template end diff --git a/lib/rdoc/generator/json_index.rb b/lib/rdoc/generator/json_index.rb index 3a1000033d..c454910d5c 100644 --- a/lib/rdoc/generator/json_index.rb +++ b/lib/rdoc/generator/json_index.rb @@ -230,9 +230,9 @@ class RDoc::Generator::JsonIndex def index_methods debug_msg " generating method search index" - list = @classes.uniq.map do |klass| + list = @classes.uniq.flat_map do |klass| klass.method_list - end.flatten.sort_by do |method| + end.sort_by do |method| [method.name, method.parent.full_name] end diff --git a/lib/rdoc/generator/markup.rb b/lib/rdoc/generator/markup.rb index 41e132450d..76b7d458aa 100644 --- a/lib/rdoc/generator/markup.rb +++ b/lib/rdoc/generator/markup.rb @@ -109,7 +109,7 @@ class RDoc::MethodAttr lines.shift if src =~ /\A.*#\ *File/i # remove '# File' comment lines.each do |line| if line =~ /^ *(?=\S)/ - n = $&.length + n = $~.end(0) indent = n if n < indent break if n == 0 end @@ -157,4 +157,3 @@ class RDoc::TopLevel end end - diff --git a/lib/rdoc/generator/pot.rb b/lib/rdoc/generator/pot.rb index bee1133b07..b0b7c07179 100644 --- a/lib/rdoc/generator/pot.rb +++ b/lib/rdoc/generator/pot.rb @@ -81,6 +81,7 @@ class RDoc::Generator::POT end end + # :nodoc: def class_dir nil end diff --git a/lib/rdoc/generator/ri.rb b/lib/rdoc/generator/ri.rb index 0eef1d03f5..1c2f018f97 100644 --- a/lib/rdoc/generator/ri.rb +++ b/lib/rdoc/generator/ri.rb @@ -28,4 +28,3 @@ class RDoc::Generator::RI end end - diff --git a/lib/rdoc/generator/template/darkfish/_head.rhtml b/lib/rdoc/generator/template/darkfish/_head.rhtml index 4f331245c3..d5aed3e9ef 100644 --- a/lib/rdoc/generator/template/darkfish/_head.rhtml +++ b/lib/rdoc/generator/template/darkfish/_head.rhtml @@ -3,18 +3,18 @@ <title><%= h @title %></title> <script type="text/javascript"> - var rdoc_rel_prefix = "<%= asset_rel_prefix %>/"; - var index_rel_prefix = "<%= rel_prefix %>/"; + var rdoc_rel_prefix = "<%= h asset_rel_prefix %>/"; + var index_rel_prefix = "<%= h rel_prefix %>/"; </script> -<script src="<%= asset_rel_prefix %>/js/navigation.js" defer></script> -<script src="<%= asset_rel_prefix %>/js/search.js" defer></script> -<script src="<%= asset_rel_prefix %>/js/search_index.js" defer></script> -<script src="<%= asset_rel_prefix %>/js/searcher.js" defer></script> -<script src="<%= asset_rel_prefix %>/js/darkfish.js" defer></script> +<script src="<%= h asset_rel_prefix %>/js/navigation.js" defer></script> +<script src="<%= h asset_rel_prefix %>/js/search.js" defer></script> +<script src="<%= h asset_rel_prefix %>/js/search_index.js" defer></script> +<script src="<%= h asset_rel_prefix %>/js/searcher.js" defer></script> +<script src="<%= h asset_rel_prefix %>/js/darkfish.js" defer></script> -<link href="<%= asset_rel_prefix %>/css/fonts.css" rel="stylesheet"> -<link href="<%= asset_rel_prefix %>/css/rdoc.css" rel="stylesheet"> +<link href="<%= h asset_rel_prefix %>/css/fonts.css" rel="stylesheet"> +<link href="<%= h asset_rel_prefix %>/css/rdoc.css" rel="stylesheet"> <%- @options.template_stylesheets.each do |stylesheet| -%> -<link href="<%= asset_rel_prefix %>/<%= File.basename stylesheet %>" rel="stylesheet"> +<link href="<%= h asset_rel_prefix %>/<%= File.basename stylesheet %>" rel="stylesheet"> <%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml index 0ed683ca14..3f68f0c0dc 100644 --- a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +++ b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml @@ -12,18 +12,18 @@ <%- end.each do |n, files| -%> <%- f = files.shift -%> <%- if files.empty? -%> - <li><a href="<%= rel_prefix %>/<%= f.path %>"><%= h f.page_name %></a> + <li><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h f.page_name %></a> <%- next -%> <%- end -%> <li><details<% if dir == n %> open<% end %>><summary><% if n == f.page_name - %><a href="<%= rel_prefix %>/<%= f.path %>"><%= h n %></a><% + %><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h n %></a><% else %><%= h n %><% files.unshift(f) end %></summary> <ul class="link-list"> <%- files.each do |f| -%> - <li><a href="<%= rel_prefix %>/<%= f.path %>"><%= h f.page_name %></a> + <li><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h f.page_name %></a> <%- end -%> </ul></details> <%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml index 9c49b31376..afc7f7b88d 100644 --- a/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +++ b/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml @@ -3,7 +3,7 @@ <div id="search-field-wrapper"> <input id="search-field" role="combobox" aria-label="Search" aria-autocomplete="list" aria-controls="search-results" - type="text" name="search" placeholder="Search" spellcheck="false" + type="text" name="search" placeholder="Search (/) for a class, method, ..." spellcheck="false" title="Type to search, Up and Down to navigate, Enter to load"> </div> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml index bf70819f64..b1e047b5f7 100644 --- a/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +++ b/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml @@ -3,16 +3,37 @@ else current.comment end - table = current.parse(comment).table_of_contents + table = current.parse(comment).table_of_contents.dup if table.length > 1 then %> <div class="nav-section"> <h3>Table of Contents</h3> + <%- display_link = proc do |heading| -%> + <a href="#<%= heading.label current %>"><%= heading.plain_html %></a> + <%- end -%> + + <%- list_siblings = proc do -%> + <%- level = table.first&.level -%> + <%- while table.first && table.first.level >= level -%> + <%- heading = table.shift -%> + <%- if table.first.nil? || table.first.level <= heading.level -%> + <li><% display_link.call heading -%> + <%- else -%> + <li> + <details open> + <summary><%- display_link.call heading -%></summary> + <ul class="link-list" role="directory"> + <% list_siblings.call %> + </ul> + </details> + </li> + <%- end -%> + <%- end -%> + <%- end -%> + <ul class="link-list" role="directory"> -<%- table.each do |heading| -%> - <li><a href="#<%= heading.label current %>"><%= heading.plain_html %></a> -<%- end -%> + <% list_siblings.call %> </ul> </div> <%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/class.rhtml b/lib/rdoc/generator/template/darkfish/class.rhtml index 5d7b6a1b80..d6510336df 100644 --- a/lib/rdoc/generator/template/darkfish/class.rhtml +++ b/lib/rdoc/generator/template/darkfish/class.rhtml @@ -98,29 +98,36 @@ <%- methods.each do |method| -%> <div id="<%= method.aref %>" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>"> - <%- if (call_seq = method.call_seq) then -%> - <%- call_seq.strip.split("\n").each_with_index do |call_seq, i| -%> - <div class="method-heading"> - <span class="method-callseq"> - <%= h(call_seq.strip. - gsub( /^\w+\./m, '')). - gsub(/(.*)[-=]>/, '\1→') %> - </span> - <%- if i == 0 and method.token_stream then -%> - <span class="method-click-advice">click to toggle source</span> - <%- end -%> - </div> - <%- end -%> - <%- else -%> - <div class="method-heading"> - <span class="method-name"><%= h method.name %></span><span - class="method-args"><%= h method.param_seq %></span> - <%- if method.token_stream then -%> - <span class="method-click-advice">click to toggle source</span> + <div class="method-header"> + <%- if (call_seq = method.call_seq) then -%> + <%- call_seq.strip.split("\n").each_with_index do |call_seq, i| -%> + <div class="method-heading"> + <span class="method-callseq"> + <%= h(call_seq.strip. + gsub( /^\w+\./m, '')). + gsub(/(.*)[-=]>/, '\1→') %> + </span> + <%- if i == 0 and method.token_stream then -%> + <span class="method-click-advice">click to toggle source</span> + <%- end -%> + </div> + <%- end -%> + <%- elsif method.has_call_seq? then -%> + <div class="method-heading"> + <span class="method-name"><%= h method.name %></span> + </div> + <%- else -%> + <div class="method-heading"> + <span class="method-name"><%= h method.name %></span><span + class="method-args"><%= h method.param_seq %></span> + <%- if method.token_stream then -%> + <span class="method-click-advice">click to toggle source</span> + <%- end -%> + </div> <%- end -%> </div> - <%- end -%> + <%- unless method.skip_description? then -%> <div class="method-description"> <%- if method.comment then -%> <%= method.description.strip %> @@ -143,6 +150,7 @@ </div> <%- end -%> </div> + <%- end -%> <%- unless method.aliases.empty? then -%> <div class="aliases"> diff --git a/lib/rdoc/generator/template/darkfish/css/rdoc.css b/lib/rdoc/generator/template/darkfish/css/rdoc.css index 1be815f503..2cc55e03b1 100644 --- a/lib/rdoc/generator/template/darkfish/css/rdoc.css +++ b/lib/rdoc/generator/template/darkfish/css/rdoc.css @@ -17,6 +17,14 @@ body { background: #fafafa; font-family: Lato, sans-serif; font-weight: 300; + + /* Layout */ + display: grid; + grid-template-columns: auto 1fr; +} + +body > :last-child { + grid-column: 1 / 3; } h1 span, @@ -79,6 +87,17 @@ pre { border-radius: 0.2em; } +em { + text-decoration-color: rgba(52, 48, 64, 0.25); + text-decoration-line: underline; + text-decoration-style: dotted; +} + +strong, +em { + background-color: rgba(158, 178, 255, 0.1); +} + table { margin: 0; border-spacing: 0; @@ -181,21 +200,25 @@ table tr:nth-child(even) td { /* @group Top-Level Structure */ nav { - float: left; - width: 260px; font-family: Helvetica, sans-serif; font-size: 14px; border-right: 1px solid #ccc; position: sticky; top: 0; overflow: auto; + + /* Layout */ + width: 260px; /* fallback */ + width: max(50px, 20vw); + min-width: 50px; + max-width: 80vw; height: calc(100vh - 100px); /* reduce the footer height */ + resize: horizontal; } main { display: block; - margin: 0 2em 5em 260px; - padding-left: 20px; + margin: 1em; min-width: 340px; font-size: 16px; } @@ -214,7 +237,6 @@ main h6 { } #validator-badges { - clear: both; margin: 1em 1em 2em; font-size: smaller; } @@ -309,23 +331,26 @@ dl.note-list dt { background: url(../images/arrow_up.png) no-repeat right center; } -.nav-section details summary { +.nav-section details > summary { display: block; } -.nav-section details summary::-webkit-details-marker { +.nav-section details > summary::-webkit-details-marker { display: none; } -.nav-section details summary:before { +.nav-section details > summary::before { content: ""; } -.nav-section details summary:after { - content: " \25B6"; /* BLACK RIGHT-POINTING TRIANGLE */ +.nav-section details > summary::after { + content: "\25B6"; /* BLACK RIGHT-POINTING TRIANGLE */ + font-size: 0.8em; + margin-left: 0.4em; } -.nav-section details[open] > summary:after { - content: " \25BD"; /* WHITE DOWN-POINTING TRIANGLE */ + +.nav-section details[open] > summary::after { + content: "\25BD"; /* WHITE DOWN-POINTING TRIANGLE */ } /* @end */ @@ -553,7 +578,7 @@ main .method-click-advice { line-height: 20px; background: url(../images/zoom.png) no-repeat right top; } -main .method-heading:hover .method-click-advice { +main .method-header:hover .method-click-advice { visibility: visible; } diff --git a/lib/rdoc/generator/template/darkfish/index.rhtml b/lib/rdoc/generator/template/darkfish/index.rhtml index 13fa3dcc7f..423e225b68 100644 --- a/lib/rdoc/generator/template/darkfish/index.rhtml +++ b/lib/rdoc/generator/template/darkfish/index.rhtml @@ -17,6 +17,6 @@ main_page = @files.find { |f| f.full_name == @options.main_page } then %> <%= main_page.description %> <%- else -%> -<p>This is the API documentation for <%= @title %>. +<p>This is the API documentation for <%= h @title %>. <%- end -%> </main> diff --git a/lib/rdoc/generator/template/darkfish/js/darkfish.js b/lib/rdoc/generator/template/darkfish/js/darkfish.js index 111bbf8eb9..19a85c54e1 100644 --- a/lib/rdoc/generator/template/darkfish/js/darkfish.js +++ b/lib/rdoc/generator/template/darkfish/js/darkfish.js @@ -54,7 +54,7 @@ function hookSearch() { var html = ''; // TODO add relative path to <script> per-page - html += '<p class="search-match"><a href="' + index_rel_prefix + result.path + '">' + this.hlt(result.title); + html += '<p class="search-match"><a href="' + index_rel_prefix + this.escapeHTML(result.path) + '">' + this.hlt(result.title); if (result.params) html += '<span class="params">' + result.params + '</span>'; html += '</a>'; @@ -78,7 +78,20 @@ function hookSearch() { search.scrollIntoView = search.scrollInWindow; }; +function hookFocus() { + document.addEventListener("keydown", (event) => { + if (document.activeElement.tagName === 'INPUT') { + return; + } + if (event.key === "/") { + event.preventDefault(); + document.querySelector('#search-field').focus(); + } + }); +} + document.addEventListener('DOMContentLoaded', function() { hookSourceViews(); hookSearch(); + hookFocus(); }); diff --git a/lib/rdoc/generator/template/darkfish/js/search.js b/lib/rdoc/generator/template/darkfish/js/search.js index b558ca5b4f..d3cded1d57 100644 --- a/lib/rdoc/generator/template/darkfish/js/search.js +++ b/lib/rdoc/generator/template/darkfish/js/search.js @@ -15,9 +15,9 @@ Search.prototype = Object.assign({}, Navigation, new function() { this.init = function() { var _this = this; var observer = function(e) { - switch(e.keyCode) { - case 38: // Event.KEY_UP - case 40: // Event.KEY_DOWN + switch(e.key) { + case 'ArrowUp': + case 'ArrowDown': return; } _this.search(_this.input.value); @@ -101,7 +101,7 @@ Search.prototype = Object.assign({}, Navigation, new function() { } this.escapeHTML = function(html) { - return html.replace(/[&<>]/g, function(c) { + return html.replace(/[&<>"`']/g, function(c) { return '&#' + c.charCodeAt(0) + ';'; }); } diff --git a/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml b/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml index 303d7016cc..54a376c9e5 100644 --- a/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +++ b/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml @@ -8,14 +8,14 @@ <ul> <%- simple_files.sort.each do |file| -%> <li class="file"> - <a href="<%= file.path %>"><%= h file.page_name %></a> + <a href="<%= h file.path %>"><%= h file.page_name %></a> <% # HACK table_of_contents should not exist on Document table = file.parse(file.comment).table_of_contents unless table.empty? then %> <ul> <%- table.each do |heading| -%> - <li><a href="<%= file.path %>#<%= heading.aref %>"><%= heading.plain_html %></a> + <li><a href="<%= h file.path %>#<%= heading.aref %>"><%= heading.plain_html %></a> <%- end -%> </ul> <%- end -%> @@ -36,8 +36,9 @@ unless table.empty? then %> <ul> <%- table.each do |item| -%> - <li><a href="<%= klass.path %>#<%= item.aref %>"><%= item.plain_html %></a> -<%- end -%> +<%- label = item.respond_to?(:label) ? item.label(klass) : item.aref -%> + <li><a href="<%= klass.path %>#<%= label %>"><%= item.plain_html %></a> +<%- end -%> </ul> <%- end -%> </li> @@ -46,9 +47,9 @@ <h2 id="methods">Methods</h2> <ul> -<%- @store.all_classes_and_modules.map do |mod| +<%- @store.all_classes_and_modules.flat_map do |mod| mod.method_list - end.flatten.sort.each do |method| %> + end.sort.each do |method| %> <li class="method"> <a href="<%= method.path %>"><%= h method.pretty_name %></a> — diff --git a/lib/rdoc/generator/template/json_index/js/navigation.js b/lib/rdoc/generator/template/json_index/js/navigation.js index dfad74b1ae..137e3a0038 100644 --- a/lib/rdoc/generator/template/json_index/js/navigation.js +++ b/lib/rdoc/generator/template/json_index/js/navigation.js @@ -23,24 +23,24 @@ Navigation = new function() { this.onkeydown = function(e) { if (!this.navigationActive) return; - switch(e.keyCode) { - case 37: //Event.KEY_LEFT: + switch(e.key) { + case 'ArrowLeft': if (this.moveLeft()) e.preventDefault(); break; - case 38: //Event.KEY_UP: - if (e.keyCode == 38 || e.ctrlKey) { + case 'ArrowUp': + if (e.key == 'ArrowUp' || e.ctrlKey) { if (this.moveUp()) e.preventDefault(); } break; - case 39: //Event.KEY_RIGHT: + case 'ArrowRight': if (this.moveRight()) e.preventDefault(); break; - case 40: //Event.KEY_DOWN: - if (e.keyCode == 40 || e.ctrlKey) { + case 'ArrowDown': + if (e.key == 'ArrowDown' || e.ctrlKey) { if (this.moveDown()) e.preventDefault(); } break; - case 13: //Event.KEY_RETURN: + case 'Enter': if (this.current) e.preventDefault(); this.select(this.current); break; diff --git a/lib/rdoc/ghost_method.rb b/lib/rdoc/ghost_method.rb index 2488feb9d7..25f951e35e 100644 --- a/lib/rdoc/ghost_method.rb +++ b/lib/rdoc/ghost_method.rb @@ -4,4 +4,3 @@ class RDoc::GhostMethod < RDoc::AnyMethod end - diff --git a/lib/rdoc/include.rb b/lib/rdoc/include.rb index b3ad610649..c3e0d45e47 100644 --- a/lib/rdoc/include.rb +++ b/lib/rdoc/include.rb @@ -7,4 +7,3 @@ class RDoc::Include < RDoc::Mixin end - diff --git a/lib/rdoc/known_classes.rb b/lib/rdoc/known_classes.rb index 4d7f4aa995..3e8752bbde 100644 --- a/lib/rdoc/known_classes.rb +++ b/lib/rdoc/known_classes.rb @@ -25,6 +25,7 @@ module RDoc "rb_cObject" => "Object", "rb_cProc" => "Proc", "rb_cRange" => "Range", + "rb_cRefinement" => "Refinement", "rb_cRegexp" => "Regexp", "rb_cRubyVM" => "RubyVM", "rb_cSocket" => "Socket", @@ -35,7 +36,7 @@ module RDoc "rb_cTime" => "Time", "rb_cTrueClass" => "TrueClass", - "rb_eArgError" => "ArgError", + "rb_eArgError" => "ArgumentError", "rb_eEOFError" => "EOFError", "rb_eException" => "Exception", "rb_eFatal" => "fatal", @@ -45,8 +46,8 @@ module RDoc "rb_eInterrupt" => "Interrupt", "rb_eLoadError" => "LoadError", "rb_eNameError" => "NameError", - "rb_eNoMemError" => "NoMemError", - "rb_eNotImpError" => "NotImpError", + "rb_eNoMemError" => "NoMemoryError", + "rb_eNotImpError" => "NotImplementedError", "rb_eRangeError" => "RangeError", "rb_eRuntimeError" => "RuntimeError", "rb_eScriptError" => "ScriptError", @@ -57,7 +58,7 @@ module RDoc "rb_eSystemCallError" => "SystemCallError", "rb_eSystemExit" => "SystemExit", "rb_eTypeError" => "TypeError", - "rb_eZeroDivError" => "ZeroDivError", + "rb_eZeroDivError" => "ZeroDivisionError", "rb_mComparable" => "Comparable", "rb_mEnumerable" => "Enumerable", diff --git a/lib/rdoc/markdown.rb b/lib/rdoc/markdown.rb index 25a7217d3c..5c72a5f224 100644 --- a/lib/rdoc/markdown.rb +++ b/lib/rdoc/markdown.rb @@ -175,7 +175,7 @@ # [dingus]: http://daringfireball.net/projects/markdown/dingus # [GFM]: https://github.github.com/gfm/ # [pegmarkdown]: https://github.com/jgm/peg-markdown -# [PHPE]: http://michelf.com/projects/php-markdown/extra/#def-list +# [PHPE]: https://michelf.ca/projects/php-markdown/extra/#def-list # [syntax]: http://daringfireball.net/projects/markdown/syntax #-- # Last updated to jgm/peg-markdown commit 8f8fc22ef0 @@ -209,45 +209,75 @@ class RDoc::Markdown attr_accessor :result, :pos def current_column(target=pos) - if c = string.rindex("\n", target-1) - return target - c - 1 + if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1) + return target - c + elsif c = string.rindex("\n", target) + return target - c end target + 1 end + def position_line_offsets + unless @position_line_offsets + @position_line_offsets = [] + total = 0 + string.each_line do |line| + total += line.size + @position_line_offsets << total + end + end + @position_line_offsets + end + if [].respond_to? :bsearch_index def current_line(target=pos) - unless @line_offsets - @line_offsets = [] - total = 0 - string.each_line do |line| - total += line.size - @line_offsets << total - end + if line = position_line_offsets.bsearch_index {|x| x > target } + return line + 1 end - - @line_offsets.bsearch_index {|x| x >= target } + 1 || -1 + raise "Target position #{target} is outside of string" end else def current_line(target=pos) - cur_offset = 0 - cur_line = 0 - - string.each_line do |line| - cur_line += 1 - cur_offset += line.size - return cur_line if cur_offset >= target + if line = position_line_offsets.index {|x| x > target } + return line + 1 end - -1 + raise "Target position #{target} is outside of string" end end + def current_character(target=pos) + if target < 0 || target >= string.size + raise "Target position #{target} is outside of string" + end + string[target, 1] + end + + KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) + + def current_pos_info(target=pos) + l = current_line target + c = current_column target + ln = get_line(l-1) + chr = string[target,1] + KpegPosInfo.new(target, l, c, ln, chr) + end + def lines - lines = [] - string.each_line { |l| lines << l } - lines + string.lines + end + + def get_line(no) + loff = position_line_offsets + if no < 0 + raise "Line No is out of range: #{no} < 0" + elsif no >= loff.size + raise "Line No is out of range: #{no} >= #{loff.size}" + end + lend = loff[no]-1 + lstart = no > 0 ? loff[no-1] : 0 + string[lstart..lend] end @@ -261,6 +291,7 @@ class RDoc::Markdown @string = string @string_size = string ? string.size : 0 @pos = pos + @position_line_offsets = nil end def show_pos @@ -285,30 +316,22 @@ class RDoc::Markdown end def failure_caret - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - - line = lines[l-1] - "#{line}\n#{' ' * (c - 1)}^" + p = current_pos_info @failing_rule_offset + "#{p.line.chomp}\n#{' ' * (p.col - 1)}^" end def failure_character - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - lines[l-1][c-1, 1] + current_character @failing_rule_offset end def failure_oneline - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - - char = lines[l-1][c-1, 1] + p = current_pos_info @failing_rule_offset if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] - "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'" + "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'" else - "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'" + "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'" end end @@ -321,10 +344,9 @@ class RDoc::Markdown def show_error(io=STDOUT) error_pos = @failing_rule_offset - line_no = current_line(error_pos) - col_no = current_column(error_pos) + p = current_pos_info(error_pos) - io.puts "On line #{line_no}, column #{col_no}:" + io.puts "On line #{p.lno}, column #{p.col}:" if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] @@ -333,10 +355,9 @@ class RDoc::Markdown io.puts "Failed to match rule '#{@failed_rule}'" end - io.puts "Got: #{string[error_pos,1].inspect}" - line = lines[line_no-1] - io.puts "=> #{line}" - io.print(" " * (col_no + 3)) + io.puts "Got: #{p.char.inspect}" + io.puts "=> #{p.line}" + io.print(" " * (p.col + 2)) io.puts "^" end @@ -445,6 +466,7 @@ class RDoc::Markdown end def apply_with_args(rule, *args) + @result = nil memo_key = [rule, args] if m = @memoizations[memo_key][@pos] @pos = m.pos @@ -478,6 +500,7 @@ class RDoc::Markdown end def apply(rule) + @result = nil if m = @memoizations[rule][@pos] @pos = m.pos if !m.set @@ -811,7 +834,7 @@ class RDoc::Markdown @note_order.each_with_index do |ref, index| label = index + 1 - note = @footnotes[ref] + note = @footnotes[ref] or raise ParseError, "footnote [^#{ref}] not found" link = "{^#{label}}[rdoc-label:footmark-#{label}:foottext-#{label}] " note.parts.unshift link @@ -15533,7 +15556,7 @@ class RDoc::Markdown return _tmp end - # RawNoteBlock = @StartList:a (!@BlankLine OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a } + # RawNoteBlock = @StartList:a (!@BlankLine !RawNoteReference OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a } def _RawNoteBlock _save = self.pos @@ -15556,6 +15579,14 @@ class RDoc::Markdown self.pos = _save2 break end + _save4 = self.pos + _tmp = apply(:_RawNoteReference) + _tmp = _tmp ? nil : true + self.pos = _save4 + unless _tmp + self.pos = _save2 + break + end _tmp = apply(:_OptionallyIndentedLine) l = @result unless _tmp @@ -15573,26 +15604,34 @@ class RDoc::Markdown if _tmp while true - _save4 = self.pos + _save5 = self.pos while true # sequence - _save5 = self.pos + _save6 = self.pos _tmp = _BlankLine() _tmp = _tmp ? nil : true - self.pos = _save5 + self.pos = _save6 unless _tmp - self.pos = _save4 + self.pos = _save5 + break + end + _save7 = self.pos + _tmp = apply(:_RawNoteReference) + _tmp = _tmp ? nil : true + self.pos = _save7 + unless _tmp + self.pos = _save5 break end _tmp = apply(:_OptionallyIndentedLine) l = @result unless _tmp - self.pos = _save4 + self.pos = _save5 break end @result = begin; a << l ; end _tmp = true unless _tmp - self.pos = _save4 + self.pos = _save5 end break end # end sequence @@ -15894,7 +15933,7 @@ class RDoc::Markdown return _tmp end - # Table = &{ github? } TableRow:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) } + # Table = &{ github? } TableHead:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) } def _Table _save = self.pos @@ -15906,7 +15945,7 @@ class RDoc::Markdown self.pos = _save break end - _tmp = apply(:_TableRow) + _tmp = apply(:_TableHead) header = @result unless _tmp self.pos = _save @@ -15950,18 +15989,18 @@ class RDoc::Markdown return _tmp end - # TableRow = TableItem+:row "|" @Newline { row } - def _TableRow + # TableHead = TableItem2+:items "|"? @Newline { items } + def _TableHead _save = self.pos while true # sequence _save1 = self.pos _ary = [] - _tmp = apply(:_TableItem) + _tmp = apply(:_TableItem2) if _tmp _ary << @result while true - _tmp = apply(:_TableItem) + _tmp = apply(:_TableItem2) _ary << @result if _tmp break unless _tmp end @@ -15970,13 +16009,18 @@ class RDoc::Markdown else self.pos = _save1 end - row = @result + items = @result unless _tmp self.pos = _save break end + _save2 = self.pos _tmp = match_string("|") unless _tmp + _tmp = true + self.pos = _save2 + end + unless _tmp self.pos = _save break end @@ -15985,7 +16029,7 @@ class RDoc::Markdown self.pos = _save break end - @result = begin; row ; end + @result = begin; items ; end _tmp = true unless _tmp self.pos = _save @@ -15993,90 +16037,92 @@ class RDoc::Markdown break end # end sequence - set_failed_rule :_TableRow unless _tmp + set_failed_rule :_TableHead unless _tmp return _tmp end - # TableItem = "|" < (!"|" !@Newline .)+ > { text.strip } - def _TableItem + # TableRow = ((TableItem:item1 TableItem2*:items { [item1, *items] }):row | TableItem2+:row) "|"? @Newline { row } + def _TableRow _save = self.pos while true # sequence - _tmp = match_string("|") - unless _tmp - self.pos = _save - break - end - _text_start = self.pos + _save1 = self.pos + while true # choice - _save2 = self.pos - while true # sequence - _save3 = self.pos - _tmp = match_string("|") - _tmp = _tmp ? nil : true - self.pos = _save3 - unless _tmp - self.pos = _save2 + _save2 = self.pos + while true # sequence + _tmp = apply(:_TableItem) + item1 = @result + unless _tmp + self.pos = _save2 + break + end + _ary = [] + while true + _tmp = apply(:_TableItem2) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + items = @result + unless _tmp + self.pos = _save2 + break + end + @result = begin; [item1, *items] ; end + _tmp = true + unless _tmp + self.pos = _save2 + end break - end + end # end sequence + + row = @result + break if _tmp + self.pos = _save1 _save4 = self.pos - _tmp = _Newline() - _tmp = _tmp ? nil : true - self.pos = _save4 - unless _tmp - self.pos = _save2 - break - end - _tmp = get_byte - unless _tmp - self.pos = _save2 + _ary = [] + _tmp = apply(:_TableItem2) + if _tmp + _ary << @result + while true + _tmp = apply(:_TableItem2) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + else + self.pos = _save4 end + row = @result + break if _tmp + self.pos = _save1 break - end # end sequence - - if _tmp - while true - - _save5 = self.pos - while true # sequence - _save6 = self.pos - _tmp = match_string("|") - _tmp = _tmp ? nil : true - self.pos = _save6 - unless _tmp - self.pos = _save5 - break - end - _save7 = self.pos - _tmp = _Newline() - _tmp = _tmp ? nil : true - self.pos = _save7 - unless _tmp - self.pos = _save5 - break - end - _tmp = get_byte - unless _tmp - self.pos = _save5 - end - break - end # end sequence + end # end choice - break unless _tmp - end + unless _tmp + self.pos = _save + break + end + _save5 = self.pos + _tmp = match_string("|") + unless _tmp _tmp = true - else - self.pos = _save1 + self.pos = _save5 end - if _tmp - text = get_text(_text_start) + unless _tmp + self.pos = _save + break end + _tmp = _Newline() unless _tmp self.pos = _save break end - @result = begin; text.strip ; end + @result = begin; row ; end _tmp = true unless _tmp self.pos = _save @@ -16084,46 +16130,46 @@ class RDoc::Markdown break end # end sequence - set_failed_rule :_TableItem unless _tmp + set_failed_rule :_TableRow unless _tmp return _tmp end - # TableLine = TableColumn+:line "|" @Newline { line } - def _TableLine + # TableItem2 = "|" TableItem + def _TableItem2 _save = self.pos while true # sequence - _save1 = self.pos - _ary = [] - _tmp = apply(:_TableColumn) - if _tmp - _ary << @result - while true - _tmp = apply(:_TableColumn) - _ary << @result if _tmp - break unless _tmp - end - _tmp = true - @result = _ary - else - self.pos = _save1 - end - line = @result + _tmp = match_string("|") unless _tmp self.pos = _save break end - _tmp = match_string("|") + _tmp = apply(:_TableItem) unless _tmp self.pos = _save - break end - _tmp = _Newline() + break + end # end sequence + + set_failed_rule :_TableItem2 unless _tmp + return _tmp + end + + # TableItem = < /(?:\\.|[^|\n])+/ > { text.strip.gsub(/\\(.)/, '\1') } + def _TableItem + + _save = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\G(?-mix:(?:\\.|[^|\n])+)/) + if _tmp + text = get_text(_text_start) + end unless _tmp self.pos = _save break end - @result = begin; line ; end + @result = begin; text.strip.gsub(/\\(.)/, '\1') ; end _tmp = true unless _tmp self.pos = _save @@ -16131,80 +16177,136 @@ class RDoc::Markdown break end # end sequence - set_failed_rule :_TableLine unless _tmp + set_failed_rule :_TableItem unless _tmp return _tmp end - # TableColumn = "|" < ("-"+ ":"? | ":" "-"*) > { text.start_with?(":") ? :left : text.end_with?(":") ? :right : nil } - def _TableColumn + # TableLine = ((TableAlign:align1 TableAlign2*:aligns {[align1, *aligns] }):line | TableAlign2+:line) "|"? @Newline { line } + def _TableLine _save = self.pos while true # sequence - _tmp = match_string("|") - unless _tmp - self.pos = _save - break - end - _text_start = self.pos _save1 = self.pos while true # choice _save2 = self.pos while true # sequence - _save3 = self.pos - _tmp = match_string("-") - if _tmp - while true - _tmp = match_string("-") - break unless _tmp - end - _tmp = true - else - self.pos = _save3 - end + _tmp = apply(:_TableAlign) + align1 = @result unless _tmp self.pos = _save2 break end - _save4 = self.pos - _tmp = match_string(":") + _ary = [] + while true + _tmp = apply(:_TableAlign2) + _ary << @result if _tmp + break unless _tmp + end + _tmp = true + @result = _ary + aligns = @result unless _tmp - _tmp = true - self.pos = _save4 + self.pos = _save2 + break end + @result = begin; [align1, *aligns] ; end + _tmp = true unless _tmp self.pos = _save2 end break end # end sequence + line = @result break if _tmp self.pos = _save1 - - _save5 = self.pos - while true # sequence - _tmp = match_string(":") - unless _tmp - self.pos = _save5 - break - end + _save4 = self.pos + _ary = [] + _tmp = apply(:_TableAlign2) + if _tmp + _ary << @result while true - _tmp = match_string("-") + _tmp = apply(:_TableAlign2) + _ary << @result if _tmp break unless _tmp end _tmp = true - unless _tmp - self.pos = _save5 - end - break - end # end sequence - + @result = _ary + else + self.pos = _save4 + end + line = @result break if _tmp self.pos = _save1 break end # end choice + unless _tmp + self.pos = _save + break + end + _save5 = self.pos + _tmp = match_string("|") + unless _tmp + _tmp = true + self.pos = _save5 + end + unless _tmp + self.pos = _save + break + end + _tmp = _Newline() + unless _tmp + self.pos = _save + break + end + @result = begin; line ; end + _tmp = true + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_TableLine unless _tmp + return _tmp + end + + # TableAlign2 = "|" @Sp TableAlign + def _TableAlign2 + + _save = self.pos + while true # sequence + _tmp = match_string("|") + unless _tmp + self.pos = _save + break + end + _tmp = _Sp() + unless _tmp + self.pos = _save + break + end + _tmp = apply(:_TableAlign) + unless _tmp + self.pos = _save + end + break + end # end sequence + + set_failed_rule :_TableAlign2 unless _tmp + return _tmp + end + + # TableAlign = < /:?-+:?/ > @Sp { text.start_with?(":") ? (text.end_with?(":") ? :center : :left) : (text.end_with?(":") ? :right : nil) } + def _TableAlign + + _save = self.pos + while true # sequence + _text_start = self.pos + _tmp = scan(/\G(?-mix::?-+:?)/) if _tmp text = get_text(_text_start) end @@ -16212,8 +16314,15 @@ class RDoc::Markdown self.pos = _save break end - @result = begin; text.start_with?(":") ? :left : - text.end_with?(":") ? :right : nil + _tmp = _Sp() + unless _tmp + self.pos = _save + break + end + @result = begin; + text.start_with?(":") ? + (text.end_with?(":") ? :center : :left) : + (text.end_with?(":") ? :right : nil) ; end _tmp = true unless _tmp @@ -16222,7 +16331,7 @@ class RDoc::Markdown break end # end sequence - set_failed_rule :_TableColumn unless _tmp + set_failed_rule :_TableAlign unless _tmp return _tmp end @@ -16336,12 +16445,12 @@ class RDoc::Markdown return _tmp end - # DefinitionListLabel = StrChunk:label @Sp @Newline { label } + # DefinitionListLabel = Inline:label @Sp @Newline { label } def _DefinitionListLabel _save = self.pos while true # sequence - _tmp = apply(:_StrChunk) + _tmp = apply(:_Inline) label = @result unless _tmp self.pos = _save @@ -16656,16 +16765,19 @@ class RDoc::Markdown Rules[:_Note] = rule_info("Note", "&{ notes? } @NonindentSpace RawNoteReference:ref \":\" @Sp @StartList:a RawNoteBlock:i { a.concat i } (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil }") Rules[:_InlineNote] = rule_info("InlineNote", "&{ notes? } \"^[\" @StartList:a (!\"]\" Inline:l { a << l })+ \"]\" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }") Rules[:_Notes] = rule_info("Notes", "(Note | SkipBlock)*") - Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "@StartList:a (!@BlankLine OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }") + Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "@StartList:a (!@BlankLine !RawNoteReference OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }") Rules[:_CodeFence] = rule_info("CodeFence", "&{ github? } Ticks3 (@Sp StrChunk:format)? Spnl < ((!\"`\" Nonspacechar)+ | !Ticks3 /`+/ | Spacechar | @Newline)+ > Ticks3 @Sp @Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format.instance_of?(String) verbatim }") - Rules[:_Table] = rule_info("Table", "&{ github? } TableRow:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) }") - Rules[:_TableRow] = rule_info("TableRow", "TableItem+:row \"|\" @Newline { row }") - Rules[:_TableItem] = rule_info("TableItem", "\"|\" < (!\"|\" !@Newline .)+ > { text.strip }") - Rules[:_TableLine] = rule_info("TableLine", "TableColumn+:line \"|\" @Newline { line }") - Rules[:_TableColumn] = rule_info("TableColumn", "\"|\" < (\"-\"+ \":\"? | \":\" \"-\"*) > { text.start_with?(\":\") ? :left : text.end_with?(\":\") ? :right : nil }") + Rules[:_Table] = rule_info("Table", "&{ github? } TableHead:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) }") + Rules[:_TableHead] = rule_info("TableHead", "TableItem2+:items \"|\"? @Newline { items }") + Rules[:_TableRow] = rule_info("TableRow", "((TableItem:item1 TableItem2*:items { [item1, *items] }):row | TableItem2+:row) \"|\"? @Newline { row }") + Rules[:_TableItem2] = rule_info("TableItem2", "\"|\" TableItem") + Rules[:_TableItem] = rule_info("TableItem", "< /(?:\\\\.|[^|\\n])+/ > { text.strip.gsub(/\\\\(.)/, '\\1') }") + Rules[:_TableLine] = rule_info("TableLine", "((TableAlign:align1 TableAlign2*:aligns {[align1, *aligns] }):line | TableAlign2+:line) \"|\"? @Newline { line }") + Rules[:_TableAlign2] = rule_info("TableAlign2", "\"|\" @Sp TableAlign") + Rules[:_TableAlign] = rule_info("TableAlign", "< /:?-+:?/ > @Sp { text.start_with?(\":\") ? (text.end_with?(\":\") ? :center : :left) : (text.end_with?(\":\") ? :right : nil) }") Rules[:_DefinitionList] = rule_info("DefinitionList", "&{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }") Rules[:_DefinitionListItem] = rule_info("DefinitionListItem", "DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }") - Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "StrChunk:label @Sp @Newline { label }") + Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "Inline:label @Sp @Newline { label }") Rules[:_DefinitionListDefinition] = rule_info("DefinitionListDefinition", "@NonindentSpace \":\" @Space Inlines:a @BlankLine+ { paragraph a }") # :startdoc: end diff --git a/lib/rdoc/markdown/entities.rb b/lib/rdoc/markdown/entities.rb index d2cf610293..265c2eb3f3 100644 --- a/lib/rdoc/markdown/entities.rb +++ b/lib/rdoc/markdown/entities.rb @@ -2129,4 +2129,3 @@ RDoc::Markdown::HTML_ENTITIES = { "zwj" => [0x0200D], "zwnj" => [0x0200C], } - diff --git a/lib/rdoc/markdown/literals.rb b/lib/rdoc/markdown/literals.rb index 4c36672de7..c5c15d3100 100644 --- a/lib/rdoc/markdown/literals.rb +++ b/lib/rdoc/markdown/literals.rb @@ -3,7 +3,6 @@ # :markup: markdown ## -#-- # This set of literals is for Ruby 1.9 regular expressions and gives full # unicode support. # @@ -39,45 +38,75 @@ class RDoc::Markdown::Literals attr_accessor :result, :pos def current_column(target=pos) - if c = string.rindex("\n", target-1) - return target - c - 1 + if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1) + return target - c + elsif c = string.rindex("\n", target) + return target - c end target + 1 end + def position_line_offsets + unless @position_line_offsets + @position_line_offsets = [] + total = 0 + string.each_line do |line| + total += line.size + @position_line_offsets << total + end + end + @position_line_offsets + end + if [].respond_to? :bsearch_index def current_line(target=pos) - unless @line_offsets - @line_offsets = [] - total = 0 - string.each_line do |line| - total += line.size - @line_offsets << total - end + if line = position_line_offsets.bsearch_index {|x| x > target } + return line + 1 end - - @line_offsets.bsearch_index {|x| x >= target } + 1 || -1 + raise "Target position #{target} is outside of string" end else def current_line(target=pos) - cur_offset = 0 - cur_line = 0 - - string.each_line do |line| - cur_line += 1 - cur_offset += line.size - return cur_line if cur_offset >= target + if line = position_line_offsets.index {|x| x > target } + return line + 1 end - -1 + raise "Target position #{target} is outside of string" + end + end + + def current_character(target=pos) + if target < 0 || target >= string.size + raise "Target position #{target} is outside of string" end + string[target, 1] + end + + KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char) + + def current_pos_info(target=pos) + l = current_line target + c = current_column target + ln = get_line(l-1) + chr = string[target,1] + KpegPosInfo.new(target, l, c, ln, chr) end def lines - lines = [] - string.each_line { |l| lines << l } - lines + string.lines + end + + def get_line(no) + loff = position_line_offsets + if no < 0 + raise "Line No is out of range: #{no} < 0" + elsif no >= loff.size + raise "Line No is out of range: #{no} >= #{loff.size}" + end + lend = loff[no]-1 + lstart = no > 0 ? loff[no-1] : 0 + string[lstart..lend] end @@ -91,6 +120,7 @@ class RDoc::Markdown::Literals @string = string @string_size = string ? string.size : 0 @pos = pos + @position_line_offsets = nil end def show_pos @@ -115,30 +145,22 @@ class RDoc::Markdown::Literals end def failure_caret - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - - line = lines[l-1] - "#{line}\n#{' ' * (c - 1)}^" + p = current_pos_info @failing_rule_offset + "#{p.line.chomp}\n#{' ' * (p.col - 1)}^" end def failure_character - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - lines[l-1][c-1, 1] + current_character @failing_rule_offset end def failure_oneline - l = current_line @failing_rule_offset - c = current_column @failing_rule_offset - - char = lines[l-1][c-1, 1] + p = current_pos_info @failing_rule_offset if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] - "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'" + "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'" else - "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'" + "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'" end end @@ -151,10 +173,9 @@ class RDoc::Markdown::Literals def show_error(io=STDOUT) error_pos = @failing_rule_offset - line_no = current_line(error_pos) - col_no = current_column(error_pos) + p = current_pos_info(error_pos) - io.puts "On line #{line_no}, column #{col_no}:" + io.puts "On line #{p.lno}, column #{p.col}:" if @failed_rule.kind_of? Symbol info = self.class::Rules[@failed_rule] @@ -163,10 +184,9 @@ class RDoc::Markdown::Literals io.puts "Failed to match rule '#{@failed_rule}'" end - io.puts "Got: #{string[error_pos,1].inspect}" - line = lines[line_no-1] - io.puts "=> #{line}" - io.print(" " * (col_no + 3)) + io.puts "Got: #{p.char.inspect}" + io.puts "=> #{p.line}" + io.print(" " * (p.col + 2)) io.puts "^" end @@ -275,6 +295,7 @@ class RDoc::Markdown::Literals end def apply_with_args(rule, *args) + @result = nil memo_key = [rule, args] if m = @memoizations[memo_key][@pos] @pos = m.pos @@ -308,6 +329,7 @@ class RDoc::Markdown::Literals end def apply(rule) + @result = nil if m = @memoizations[rule][@pos] @pos = m.pos if !m.set diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb index f7aa02fd9f..6e93030965 100644 --- a/lib/rdoc/markup.rb +++ b/lib/rdoc/markup.rb @@ -97,638 +97,7 @@ # # = \RDoc Markup Reference # -# == Block Markup -# -# === Paragraphs and Verbatim -# -# The markup engine looks for a document's natural left margin. This is -# used as the initial margin for the document. -# -# Consecutive lines starting at this margin are considered to be a -# paragraph. Empty lines separate paragraphs. -# -# Any line that starts to the right of the current margin is treated -# as verbatim text. This is useful for code listings: -# -# 3.times { puts "Ruby" } -# -# In verbatim text, two or more blank lines are collapsed into one, -# and trailing blank lines are removed: -# -# This is the first line -# -# -# This is the second non-blank line, -# after 2 blank lines in the source markup. -# -# -# There were two trailing blank lines right above this paragraph, that -# have been removed. In addition, the verbatim text has been shifted -# left, so the amount of indentation of verbatim text is unimportant. -# -# For HTML output RDoc makes a small effort to determine if a verbatim section -# contains Ruby source code. If so, the verbatim block will be marked up as -# HTML. Triggers include "def", "class", "module", "require", the "hash -# rocket"# (=>) or a block call with a parameter. -# -# === Headers -# -# A line starting with an equal sign (=) is treated as a -# heading. Level one headings have one equals sign, level two headings -# have two, and so on until level six, which is the maximum -# (seven hyphens or more result in a level six heading). -# -# For example, the above header was obtained with: -# -# === Headers -# -# In HTML output headers have an id matching their name. The above example's -# HTML is: -# -# <h3 id="label-Headers">Headers</h3> -# -# If a heading is inside a method body the id will be prefixed with the -# method's id. If the above header where in the documentation for a method -# such as: -# -# ## -# # This method does fun things -# # -# # = Example -# # -# # Example of fun things goes here ... -# -# def do_fun_things -# end -# -# The header's id would be: -# -# <h1 id="method-i-do_fun_things-label-Example">Example</h1> -# -# The label can be linked-to using <tt>SomeClass@Headers</tt>. See -# {Links}[rdoc-ref:RDoc::Markup@Links] for further details. -# -# === Rules -# -# A line starting with three or more hyphens (at the current indent) -# generates a horizontal rule. -# -# --- -# -# produces: -# -# --- -# -# === Simple Lists -# -# If a paragraph starts with a "*", "-", "<digit>." or "<letter>.", -# then it is taken to be the start of a list. The margin is increased to be -# the first non-space following the list start flag. Subsequent lines -# should be indented to this new margin until the list ends. For example: -# -# * this is a list with three paragraphs in -# the first item. This is the first paragraph. -# -# And this is the second paragraph. -# -# 1. This is an indented, numbered list. -# 2. This is the second item in that list -# -# This is the third conventional paragraph in the -# first list item. -# -# * This is the second item in the original list -# -# produces: -# -# * this is a list with three paragraphs in -# the first item. This is the first paragraph. -# -# And this is the second paragraph. -# -# 1. This is an indented, numbered list. -# 2. This is the second item in that list -# -# This is the third conventional paragraph in the -# first list item. -# -# * This is the second item in the original list -# -# === Labeled Lists -# -# You can also construct labeled lists, sometimes called description -# or definition lists. Do this by putting the label in square brackets -# and indenting the list body: -# -# [cat] a small furry mammal -# that seems to sleep a lot -# -# [ant] a little insect that is known -# to enjoy picnics -# -# produces: -# -# [cat] a small furry mammal -# that seems to sleep a lot -# -# [ant] a little insect that is known -# to enjoy picnics -# -# If you want the list bodies to line up to the left of the labels, -# use two colons: -# -# cat:: a small furry mammal -# that seems to sleep a lot -# -# ant:: a little insect that is known -# to enjoy picnics -# -# produces: -# -# cat:: a small furry mammal -# that seems to sleep a lot -# -# ant:: a little insect that is known -# to enjoy picnics -# -# Notice that blank lines right after the label are ignored in labeled lists: -# -# [one] -# -# definition 1 -# -# [two] -# -# definition 2 -# -# produces the same output as -# -# [one] definition 1 -# [two] definition 2 -# -# -# === Lists and Verbatim -# -# If you want to introduce a verbatim section right after a list, it has to be -# less indented than the list item bodies, but more indented than the list -# label, letter, digit or bullet. For instance: -# -# * point 1 -# -# * point 2, first paragraph -# -# point 2, second paragraph -# verbatim text inside point 2 -# point 2, third paragraph -# verbatim text outside of the list (the list is therefore closed) -# regular paragraph after the list -# -# produces: -# -# * point 1 -# -# * point 2, first paragraph -# -# point 2, second paragraph -# verbatim text inside point 2 -# point 2, third paragraph -# verbatim text outside of the list (the list is therefore closed) -# regular paragraph after the list -# -# == Text Markup -# -# === Bold, Italic, Typewriter Text -# -# You can use markup within text (except verbatim) to change the -# appearance of parts of that text. Out of the box, RDoc::Markup -# supports word-based and general markup. -# -# Word-based markup uses flag characters around individual words: -# -# <tt>\*_word_\*</tt>:: displays _word_ in a *bold* font -# <tt>\__word_\_</tt>:: displays _word_ in an _emphasized_ font -# <tt>\+_word_\+</tt>:: displays _word_ in a +code+ font -# -# General markup affects text between a start delimiter and an end -# delimiter. Not surprisingly, these delimiters look like HTML markup. -# -# <tt>\<b>_text_</b></tt>:: displays _text_ in a *bold* font -# <tt>\<em>_text_</em></tt>:: displays _text_ in an _emphasized_ font -# (alternate tag: <tt>\<i></tt>) -# <tt>\<tt>_text_\</tt></tt>:: displays _text_ in a +code+ font -# (alternate tag: <tt>\<code></tt>) -# -# Unlike conventional Wiki markup, general markup can cross line -# boundaries. You can turn off the interpretation of markup by -# preceding the first character with a backslash (see <i>Escaping -# Text Markup</i>, below). -# -# === Links -# -# Links to starting with +http:+, +https:+, +mailto:+, +ftp:+ or +www.+ -# are recognized. An HTTP url that references an external image is converted -# into an inline image element. -# -# Classes and methods will be automatically linked to their definition. For -# example, <tt>RDoc::Markup</tt> will link to this documentation. By default -# methods will only be automatically linked if they contain an <tt>_</tt> (all -# methods can be automatically linked through the <tt>--hyperlink-all</tt> -# command line option). -# -# Single-word methods can be linked by using the <tt>#</tt> character for -# instance methods or <tt>::</tt> for class methods. For example, -# <tt>#convert</tt> links to #convert. A class or method may be combined like -# <tt>RDoc::Markup#convert</tt>. -# -# A heading inside the documentation can be linked by following the class -# or method by an <tt>@</tt> then the heading name. -# <tt>RDoc::Markup@Links</tt> will link to this section like this: -# RDoc::Markup@Links. Spaces in headings with multiple words must be escaped -# with <tt>+</tt> like <tt>RDoc::Markup@Escaping+Text+Markup</tt>. -# Punctuation and other special characters must be escaped like CGI.escape. -# -# The <tt>@</tt> can also be used to link to sections. If a section and a -# heading share the same name the section is preferred for the link. -# -# Links can also be of the form <tt>label[url]</tt>, in which case +label+ is -# used in the displayed text, and +url+ is used as the target. If +label+ -# contains multiple words, put it in braces: <tt>{multi word label}[url]</tt>. -# The +url+ may be an +http:+-type link or a cross-reference to a class, -# module or method with a label. -# -# Links with the <code>rdoc-image:</code> scheme will create an image tag for -# HTML output. Only fully-qualified URLs are supported. -# -# Links with the <tt>rdoc-ref:</tt> scheme will link to the referenced class, -# module, method, file, etc. If the referenced item is does not exist -# no link will be generated and <tt>rdoc-ref:</tt> will be removed from the -# resulting text. -# -# Links starting with <tt>rdoc-label:label_name</tt> will link to the -# +label_name+. You can create a label for the current link (for -# bidirectional links) by supplying a name for the current link like -# <tt>rdoc-label:label-other:label-mine</tt>. -# -# Links starting with +link:+ refer to local files whose path is relative to -# the <tt>--op</tt> directory. Use <tt>rdoc-ref:</tt> instead of -# <tt>link:</tt> to link to files generated by RDoc as the link target may -# be different across RDoc generators. -# -# Example links: -# -# https://github.com/ruby/rdoc -# mailto:user@example.com -# {RDoc Documentation}[http://rdoc.rubyforge.org] -# {RDoc Markup}[rdoc-ref:RDoc::Markup] -# -# === Escaping Text Markup -# -# Text markup can be escaped with a backslash, as in \<tt>, which was obtained -# with <tt>\\<tt></tt>. Except in verbatim sections and between \<tt> tags, -# to produce a backslash you have to double it unless it is followed by a -# space, tab or newline. Otherwise, the HTML formatter will discard it, as it -# is used to escape potential links: -# -# * The \ must be doubled if not followed by white space: \\. -# * But not in \<tt> tags: in a Regexp, <tt>\S</tt> matches non-space. -# * This is a link to {ruby-lang}[https://www.ruby-lang.org]. -# * This is not a link, however: \{ruby-lang.org}[https://www.ruby-lang.org]. -# * This will not be linked to \RDoc::RDoc#document -# -# generates: -# -# * The \ must be doubled if not followed by white space: \\. -# * But not in \<tt> tags: in a Regexp, <tt>\S</tt> matches non-space. -# * This is a link to {ruby-lang}[https://www.ruby-lang.org] -# * This is not a link, however: \{ruby-lang.org}[https://www.ruby-lang.org] -# * This will not be linked to \RDoc::RDoc#document -# -# Inside \<tt> tags, more precisely, leading backslashes are removed only if -# followed by a markup character (<tt><*_+</tt>), a backslash, or a known link -# reference (a known class or method). So in the example above, the backslash -# of <tt>\S</tt> would be removed if there was a class or module named +S+ in -# the current context. -# -# This behavior is inherited from RDoc version 1, and has been kept for -# compatibility with existing RDoc documentation. -# -# === Conversion of characters -# -# HTML will convert two/three dashes to an em-dash. Other common characters are -# converted as well: -# -# em-dash:: -- or --- -# ellipsis:: ... -# -# single quotes:: 'text' or `text' -# double quotes:: "text" or ``text'' -# -# copyright:: (c) -# registered trademark:: (r) -# -# produces: -# -# em-dash:: -- or --- -# ellipsis:: ... -# -# single quotes:: 'text' or `text' -# double quotes:: "text" or ``text'' -# -# copyright:: (c) -# registered trademark:: (r) -# -# -# == Documenting Source Code -# -# Comment blocks can be written fairly naturally, either using <tt>#</tt> on -# successive lines of the comment, or by including the comment in -# a <tt>=begin</tt>/<tt>=end</tt> block. If you use the latter form, -# the <tt>=begin</tt> line _must_ be flagged with an +rdoc+ tag: -# -# =begin rdoc -# Documentation to be processed by RDoc. -# -# ... -# =end -# -# RDoc stops processing comments if it finds a comment line starting -# with <tt>--</tt> right after the <tt>#</tt> character (otherwise, -# it will be treated as a rule if it has three dashes or more). -# This can be used to separate external from internal comments, -# or to stop a comment being associated with a method, class, or module. -# Commenting can be turned back on with a line that starts with <tt>++</tt>. -# -# ## -# # Extract the age and calculate the date-of-birth. -# #-- -# # FIXME: fails if the birthday falls on February 29th -# #++ -# # The DOB is returned as a Time object. -# -# def get_dob(person) -# # ... -# end -# -# Names of classes, files, and any method names containing an underscore or -# preceded by a hash character are automatically linked from comment text to -# their description. This linking works inside the current class or module, -# and with ancestor methods (in included modules or in the superclass). -# -# Method parameter lists are extracted and displayed with the method -# description. If a method calls +yield+, then the parameters passed to yield -# will also be displayed: -# -# def fred -# ... -# yield line, address -# -# This will get documented as: -# -# fred() { |line, address| ... } -# -# You can override this using a comment containing ':yields: ...' immediately -# after the method definition -# -# def fred # :yields: index, position -# # ... -# -# yield line, address -# -# which will get documented as -# -# fred() { |index, position| ... } -# -# +:yields:+ is an example of a documentation directive. These appear -# immediately after the start of the document element they are modifying. -# -# RDoc automatically cross-references words with underscores or camel-case. -# To suppress cross-references, prefix the word with a \ character. To -# include special characters like "<tt>\n</tt>", you'll need to use -# two \ characters in normal text, but only one in \<tt> text: -# -# "\\n" or "<tt>\n</tt>" -# -# produces: -# -# "\\n" or "<tt>\n</tt>" -# -# == Directives -# -# Directives are keywords surrounded by ":" characters. -# -# === Controlling what is documented -# -# [+:nodoc:+ / <tt>:nodoc: all</tt>] -# This directive prevents documentation for the element from -# being generated. For classes and modules, methods, aliases, -# constants, and attributes directly within the affected class or -# module also will be omitted. By default, though, modules and -# classes within that class or module _will_ be documented. This is -# turned off by adding the +all+ modifier. -# -# module MyModule # :nodoc: -# class Input -# end -# end -# -# module OtherModule # :nodoc: all -# class Output -# end -# end -# -# In the above code, only class <tt>MyModule::Input</tt> will be documented. -# -# The +:nodoc:+ directive, like +:enddoc:+, +:stopdoc:+ and +:startdoc:+ -# presented below, is local to the current file: if you do not want to -# document a module that appears in several files, specify +:nodoc:+ on each -# appearance, at least once per file. -# -# [+:stopdoc:+ / +:startdoc:+] -# Stop and start adding new documentation elements to the current container. -# For example, if a class has a number of constants that you don't want to -# document, put a +:stopdoc:+ before the first, and a +:startdoc:+ after the -# last. If you don't specify a +:startdoc:+ by the end of the container, -# disables documentation for the rest of the current file. -# -# [+:doc:+] -# Forces a method or attribute to be documented even if it wouldn't be -# otherwise. Useful if, for example, you want to include documentation of a -# particular private method. -# -# [+:enddoc:+] -# Document nothing further at the current level: directives +:startdoc:+ and -# +:doc:+ that appear after this will not be honored for the current container -# (file, class or module), in the current file. -# -# [+:notnew:+ / +:not_new:+ / +:not-new:+ ] -# Only applicable to the +initialize+ instance method. Normally RDoc -# assumes that the documentation and parameters for +initialize+ are -# actually for the +new+ method, and so fakes out a +new+ for the class. -# The +:notnew:+ directive stops this. Remember that +initialize+ is private, -# so you won't see the documentation unless you use the +-a+ command line -# option. -# -# === Method arguments -# -# [+:arg:+ or +:args:+ _parameters_] -# Overrides the default argument handling with exactly these parameters. -# -# ## -# # :args: a, b -# -# def some_method(*a) -# end -# -# [+:yield:+ or +:yields:+ _parameters_] -# Overrides the default yield discovery with these parameters. -# -# ## -# # :yields: key, value -# -# def each_thing &block -# @things.each(&block) -# end -# -# [+:call-seq:+] -# Lines up to the next blank line or lines with a common prefix in the -# comment are treated as the method's calling sequence, overriding the -# default parsing of method parameters and yield arguments. -# -# Multiple lines may be used. -# -# # :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 -# # -# # The remaining lines are documentation ... -# -# === Sections -# -# Sections allow you to group methods in a class into sensible containers. If -# you use the sections 'Public', 'Internal' and 'Deprecated' (the three -# allowed method statuses from TomDoc) the sections will be displayed in that -# order placing the most useful methods at the top. Otherwise, sections will -# be displayed in alphabetical order. -# -# [+:category:+ _section_] -# Adds this item to the named +section+ overriding the current section. Use -# this to group methods by section in RDoc output while maintaining a -# sensible ordering (like alphabetical). -# -# # :category: Utility Methods -# # -# # CGI escapes +text+ -# -# def convert_string text -# CGI.escapeHTML text -# end -# -# An empty category will place the item in the default category: -# -# # :category: -# # -# # This method is in the default category -# -# def some_method -# # ... -# end -# -# Unlike the :section: directive, :category: is not sticky. The category -# only applies to the item immediately following the comment. -# -# Use the :section: directive to provide introductory text for a section of -# documentation. -# -# [+:section:+ _title_] -# Provides section introductory text in RDoc output. The title following -# +:section:+ is used as the section name and the remainder of the comment -# containing the section is used as introductory text. A section's comment -# block must be separated from following comment blocks. Use an empty title -# to switch to the default section. -# -# The :section: directive is sticky, so subsequent methods, aliases, -# attributes, and classes will be contained in this section until the -# section is changed. The :category: directive will override the :section: -# directive. -# -# A :section: comment block may have one or more lines before the :section: -# directive. These will be removed, and any identical lines at the end of -# the block are also removed. This allows you to add visual cues to the -# section. -# -# Example: -# -# # ---------------------------------------- -# # :section: My Section -# # This is the section that I wrote. -# # See it glisten in the noon-day sun. -# # ---------------------------------------- -# -# ## -# # Comment for some_method -# -# def some_method -# # ... -# end -# -# === Other directives -# -# [+:markup:+ _type_] -# Overrides the default markup type for this comment with the specified -# markup type. For Ruby files, if the first comment contains this directive -# it is applied automatically to all comments in the file. -# -# Unless you are converting between markup formats you should use a -# <code>.rdoc_options</code> file to specify the default documentation -# format for your entire project. See RDoc::Options@Saved+Options for -# instructions. -# -# At the top of a file the +:markup:+ directive applies to the entire file: -# -# # coding: UTF-8 -# # :markup: TomDoc -# -# # TomDoc comment here ... -# -# class MyClass -# # ... -# -# For just one comment: -# -# # ... -# end -# -# # :markup: RDoc -# # -# # This is a comment in RDoc markup format ... -# -# def some_method -# # ... -# -# See Markup@CONTRIBUTING for instructions on adding a new markup format. -# -# [+:include:+ _filename_] -# Include the contents of the named file at this point. This directive -# must appear alone on one line, possibly preceded by spaces. In this -# position, it can be escaped with a \ in front of the first colon. -# -# The file will be searched for in the directories listed by the +--include+ -# option, or in the current directory by default. The contents of the file -# will be shifted to have the same indentation as the ':' at the start of -# the +:include:+ directive. -# -# [+:title:+ _text_] -# Sets the title for the document. Equivalent to the <tt>--title</tt> -# command line parameter. (The command line parameter overrides any :title: -# directive in the source). -# -# [+:main:+ _name_] -# Equivalent to the <tt>--main</tt> command line parameter. +# See RDoc::MarkupReference. # #-- # Original Author:: Dave Thomas, dave@pragmaticprogrammer.com diff --git a/lib/rdoc/markup/attr_changer.rb b/lib/rdoc/markup/attr_changer.rb index 4c4bc6479e..e5ba470bb6 100644 --- a/lib/rdoc/markup/attr_changer.rb +++ b/lib/rdoc/markup/attr_changer.rb @@ -20,4 +20,3 @@ class RDoc::Markup::AttrChanger end end - diff --git a/lib/rdoc/markup/attr_span.rb b/lib/rdoc/markup/attr_span.rb index 20ef11cd6d..f1fabf1c3b 100644 --- a/lib/rdoc/markup/attr_span.rb +++ b/lib/rdoc/markup/attr_span.rb @@ -33,4 +33,3 @@ class RDoc::Markup::AttrSpan end end - diff --git a/lib/rdoc/markup/attribute_manager.rb b/lib/rdoc/markup/attribute_manager.rb index 6ef5af8856..f6eb06da95 100644 --- a/lib/rdoc/markup/attribute_manager.rb +++ b/lib/rdoc/markup/attribute_manager.rb @@ -1,8 +1,19 @@ # frozen_string_literal: true + ## # Manages changes of attributes in a block of text class RDoc::Markup::AttributeManager + unless ::MatchData.method_defined?(:match_length) + using ::Module.new { + refine(::MatchData) { + def match_length(nth) # :nodoc: + b, e = offset(nth) + e - b if b + end + } + } + end ## # The NUL character @@ -127,6 +138,7 @@ class RDoc::Markup::AttributeManager res end + # :nodoc: def exclusive?(attr) (attr & @exclusive_bitmap) != 0 end @@ -144,6 +156,7 @@ class RDoc::Markup::AttributeManager convert_attrs_word_pair_map(str, attrs, exclusive) end + # :nodoc: def convert_attrs_matching_word_pairs(str, attrs, exclusive) # first do matching ones tags = @matching_word_pairs.select { |start, bitmap| @@ -153,29 +166,32 @@ class RDoc::Markup::AttributeManager tags = "[#{tags.join("")}](?!#{PROTECT_ATTR})" all_tags = "[#{@matching_word_pairs.keys.join("")}](?!#{PROTECT_ATTR})" - re = /(^|\W|#{all_tags})(#{tags})(\2*[#\\]?[\w:#{PROTECT_ATTR}.\/\[\]-]+?\S?)\2(?!\2)(#{all_tags}|\W|$)/ + re = /(?:^|\W|#{all_tags})\K(#{tags})(\1*[#\\]?[\w:#{PROTECT_ATTR}.\/\[\]-]+?\S?)\1(?!\1)(?=#{all_tags}|\W|$)/ 1 while str.gsub!(re) { |orig| - attr = @matching_word_pairs[$2] - attr_updated = attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr) - if attr_updated - $1 + NULL * $2.length + $3 + NULL * $2.length + $4 + a, w = (m = $~).values_at(1, 2) + attr = @matching_word_pairs[a] + if attrs.set_attrs(m.begin(2), w.length, attr) + a = NULL * a.length else - $1 + NON_PRINTING_START + $2 + NON_PRINTING_END + $3 + NON_PRINTING_START + $2 + NON_PRINTING_END + $4 + a = NON_PRINTING_START + a + NON_PRINTING_END end + a + w + a } str.delete!(NON_PRINTING_START + NON_PRINTING_END) end + # :nodoc: def convert_attrs_word_pair_map(str, attrs, exclusive) # then non-matching unless @word_pair_map.empty? then @word_pair_map.each do |regexp, attr| next unless exclusive == exclusive?(attr) 1 while str.gsub!(regexp) { |orig| - updated = attrs.set_attrs($`.length + $1.length, $2.length, attr) + w = (m = ($~))[2] + updated = attrs.set_attrs(m.begin(2), w.length, attr) if updated - NULL * $1.length + $2 + NULL * $3.length + NULL * m.match_length(1) + w + NULL * m.match_length(3) else orig end @@ -194,9 +210,9 @@ class RDoc::Markup::AttributeManager 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) { |orig| attr = @html_tags[$1.downcase] - html_length = $1.length + 2 + html_length = $~.match_length(1) + 2 # "<>".length seq = NULL * html_length - attrs.set_attrs($`.length + html_length, $2.length, attr) + attrs.set_attrs($~.begin(2), $~.match_length(2), attr) seq + $2 + seq + NULL } end @@ -387,4 +403,3 @@ class RDoc::Markup::AttributeManager end end - diff --git a/lib/rdoc/markup/attributes.rb b/lib/rdoc/markup/attributes.rb index ce014ce928..d9d18b3059 100644 --- a/lib/rdoc/markup/attributes.rb +++ b/lib/rdoc/markup/attributes.rb @@ -68,4 +68,3 @@ class RDoc::Markup::Attributes end end - diff --git a/lib/rdoc/markup/blank_line.rb b/lib/rdoc/markup/blank_line.rb index 3129ab5e7f..f63ae9479c 100644 --- a/lib/rdoc/markup/blank_line.rb +++ b/lib/rdoc/markup/blank_line.rb @@ -25,4 +25,3 @@ class RDoc::Markup::BlankLine end end - diff --git a/lib/rdoc/markup/block_quote.rb b/lib/rdoc/markup/block_quote.rb index 7a4b3e36b0..d9fcbf213c 100644 --- a/lib/rdoc/markup/block_quote.rb +++ b/lib/rdoc/markup/block_quote.rb @@ -12,4 +12,3 @@ class RDoc::Markup::BlockQuote < RDoc::Markup::Raw end end - diff --git a/lib/rdoc/markup/document.rb b/lib/rdoc/markup/document.rb index f3a5de1fc3..94cf6a3666 100644 --- a/lib/rdoc/markup/document.rb +++ b/lib/rdoc/markup/document.rb @@ -162,4 +162,3 @@ class RDoc::Markup::Document end end - diff --git a/lib/rdoc/markup/formatter.rb b/lib/rdoc/markup/formatter.rb index 2bac76e838..9daffaabb8 100644 --- a/lib/rdoc/markup/formatter.rb +++ b/lib/rdoc/markup/formatter.rb @@ -90,7 +90,7 @@ class RDoc::Markup::Formatter def add_regexp_handling_TIDYLINK @markup.add_regexp_handling(/(?: - \{.*?\} | # multi-word label + \{[^{}]*\} | # multi-word label \b[^\s{}]+? # single-word label ) @@ -263,4 +263,3 @@ class RDoc::Markup::Formatter end end - diff --git a/lib/rdoc/markup/hard_break.rb b/lib/rdoc/markup/hard_break.rb index 046068d5c2..de1819c903 100644 --- a/lib/rdoc/markup/hard_break.rb +++ b/lib/rdoc/markup/hard_break.rb @@ -29,4 +29,3 @@ class RDoc::Markup::HardBreak end end - diff --git a/lib/rdoc/markup/heading.rb b/lib/rdoc/markup/heading.rb index 93a3a52000..02476e5226 100644 --- a/lib/rdoc/markup/heading.rb +++ b/lib/rdoc/markup/heading.rb @@ -76,4 +76,3 @@ RDoc::Markup::Heading = end end - diff --git a/lib/rdoc/markup/include.rb b/lib/rdoc/markup/include.rb index ad7c4a9640..2bf63526b2 100644 --- a/lib/rdoc/markup/include.rb +++ b/lib/rdoc/markup/include.rb @@ -40,4 +40,3 @@ class RDoc::Markup::Include end end - diff --git a/lib/rdoc/markup/indented_paragraph.rb b/lib/rdoc/markup/indented_paragraph.rb index d42b2e52b8..992cd7cf81 100644 --- a/lib/rdoc/markup/indented_paragraph.rb +++ b/lib/rdoc/markup/indented_paragraph.rb @@ -45,4 +45,3 @@ class RDoc::Markup::IndentedParagraph < RDoc::Markup::Raw end end - diff --git a/lib/rdoc/markup/list.rb b/lib/rdoc/markup/list.rb index 05c3609202..112b7a1a86 100644 --- a/lib/rdoc/markup/list.rb +++ b/lib/rdoc/markup/list.rb @@ -99,4 +99,3 @@ class RDoc::Markup::List end end - diff --git a/lib/rdoc/markup/list_item.rb b/lib/rdoc/markup/list_item.rb index d22554ee73..0b8326a69f 100644 --- a/lib/rdoc/markup/list_item.rb +++ b/lib/rdoc/markup/list_item.rb @@ -97,4 +97,3 @@ class RDoc::Markup::ListItem end end - diff --git a/lib/rdoc/markup/paragraph.rb b/lib/rdoc/markup/paragraph.rb index a2e45ef009..21dfda007a 100644 --- a/lib/rdoc/markup/paragraph.rb +++ b/lib/rdoc/markup/paragraph.rb @@ -26,4 +26,3 @@ class RDoc::Markup::Paragraph < RDoc::Markup::Raw end end - diff --git a/lib/rdoc/markup/parser.rb b/lib/rdoc/markup/parser.rb index 1b54a519d1..9c77048591 100644 --- a/lib/rdoc/markup/parser.rb +++ b/lib/rdoc/markup/parser.rb @@ -218,7 +218,7 @@ class RDoc::Markup::Parser break if peek_token.first == :BREAK - data << ' ' if skip :NEWLINE + data << ' ' if skip :NEWLINE and /#{SPACE_SEPARATED_LETTER_CLASS}\z/o.match?(data) else unget break @@ -287,6 +287,12 @@ class RDoc::Markup::Parser line << ' ' * indent when :BREAK, :TEXT then line << data + when :BLOCKQUOTE then + line << '>>>' + peek_type, _, peek_column = peek_token + if peek_type != :NEWLINE and peek_column + line << ' ' * (peek_column - column - 3) + end else # *LIST_TOKENS list_marker = case type when :BULLET then data @@ -372,11 +378,8 @@ class RDoc::Markup::Parser unget parse_text parent, indent when :BLOCKQUOTE then - type, _, column = get - if type == :NEWLINE - type, _, column = get - end - unget if type + nil while (type, = get; type) and type != :NEWLINE + _, _, column, = peek_token bq = RDoc::Markup::BlockQuote.new p :blockquote_start => [data, column] if @debug parse bq, column @@ -417,6 +420,8 @@ class RDoc::Markup::Parser # A simple wrapper of StringScanner that is aware of the current column and lineno class MyStringScanner + # :stopdoc: + def initialize(input) @line = @column = 0 @s = StringScanner.new input @@ -453,6 +458,8 @@ class RDoc::Markup::Parser def [](i) @s[i] end + + #:startdoc: end ## @@ -544,7 +551,10 @@ class RDoc::Markup::Parser [:NOTE, @s[1], *pos] # >>> followed by end of line => :BLOCKQUOTE when @s.scan(/>>> *(\w+)?$/) then - [:BLOCKQUOTE, @s[1], *pos] + if word = @s[1] + @s.unscan(word) + end + [:BLOCKQUOTE, word, *pos] # anything else: :TEXT else @s.scan(/(.*?)( )?\r?$/) diff --git a/lib/rdoc/markup/raw.rb b/lib/rdoc/markup/raw.rb index 85e2c8b825..a7c1c210a6 100644 --- a/lib/rdoc/markup/raw.rb +++ b/lib/rdoc/markup/raw.rb @@ -67,4 +67,3 @@ class RDoc::Markup::Raw end end - diff --git a/lib/rdoc/markup/regexp_handling.rb b/lib/rdoc/markup/regexp_handling.rb index 6ed868c2c1..c471fe73c7 100644 --- a/lib/rdoc/markup/regexp_handling.rb +++ b/lib/rdoc/markup/regexp_handling.rb @@ -38,4 +38,3 @@ class RDoc::Markup::RegexpHandling end end - diff --git a/lib/rdoc/markup/rule.rb b/lib/rdoc/markup/rule.rb index 38c1dc7f56..448148d6d1 100644 --- a/lib/rdoc/markup/rule.rb +++ b/lib/rdoc/markup/rule.rb @@ -18,4 +18,3 @@ class RDoc::Markup::Rule < Struct.new :weight end end - diff --git a/lib/rdoc/markup/table.rb b/lib/rdoc/markup/table.rb index 7bcb10aff3..27a20f073a 100644 --- a/lib/rdoc/markup/table.rb +++ b/lib/rdoc/markup/table.rb @@ -3,12 +3,21 @@ # A section of table class RDoc::Markup::Table - attr_accessor :header, :align, :body + # headers of each column + attr_accessor :header + # alignments of each column + attr_accessor :align + + # body texts of each column + attr_accessor :body + + # Creates new instance def initialize header, align, body @header, @align, @body = header, align, body end + # :stopdoc: def == other self.class == other.class and @header == other.header and @@ -20,7 +29,7 @@ class RDoc::Markup::Table visitor.accept_table @header, @body, @align end - def pretty_print q # :nodoc: + def pretty_print q q.group 2, '[Table: ', ']' do q.group 2, '[Head: ', ']' do q.seplist @header.zip(@align) do |text, align| diff --git a/lib/rdoc/markup/to_ansi.rb b/lib/rdoc/markup/to_ansi.rb index 6cc3b70e93..c3eacab21a 100644 --- a/lib/rdoc/markup/to_ansi.rb +++ b/lib/rdoc/markup/to_ansi.rb @@ -91,4 +91,3 @@ class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc end end - diff --git a/lib/rdoc/markup/to_bs.rb b/lib/rdoc/markup/to_bs.rb index f9b86487db..afd9d6e981 100644 --- a/lib/rdoc/markup/to_bs.rb +++ b/lib/rdoc/markup/to_bs.rb @@ -41,6 +41,31 @@ class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc end ## + # Prepares the visitor for consuming +list_item+ + + def accept_list_item_start list_item + type = @list_type.last + + case type + when :NOTE, :LABEL then + bullets = Array(list_item.label).map do |label| + attributes(label).strip + end.join "\n" + + bullets << ":\n" unless bullets.empty? + + @prefix = ' ' * @indent + @indent += 2 + @prefix << bullets + (' ' * @indent) + else + bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.' + @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1) + width = bullet.length + 1 + @indent += width + end + end + + ## # Turns on or off regexp handling for +convert_string+ def annotate tag diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb index 2bfabc8942..91cadf9d16 100644 --- a/lib/rdoc/markup/to_html.rb +++ b/lib/rdoc/markup/to_html.rb @@ -61,6 +61,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter # # These methods are used by regexp handling markup added by RDoc::Markup#add_regexp_handling. + # :nodoc: URL_CHARACTERS_REGEXP_STR = /[A-Za-z0-9\-._~:\/\?#\[\]@!$&'\(\)*+,;%=]/.source ## @@ -84,7 +85,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter def handle_RDOCLINK url # :nodoc: case url when /^rdoc-ref:/ - $' + CGI.escapeHTML($') when /^rdoc-label:/ text = $' @@ -95,13 +96,11 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter else text end - gen_url url, text + gen_url CGI.escapeHTML(url), CGI.escapeHTML(text) when /^rdoc-image:/ - "<img src=\"#{$'}\">" - else - url =~ /\Ardoc-[a-z]+:/ - - $' + %[<img src=\"#{CGI.escapeHTML($')}\">] + when /\Ardoc-[a-z]+:/ + CGI.escapeHTML($') end end @@ -125,7 +124,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter # Reference to a local file relative to the output directory. def handle_regexp_HYPERLINK(target) - url = target.text + url = CGI.escapeHTML(target.text) gen_url url, url end @@ -154,9 +153,13 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter text =~ /^\{(.*)\}\[(.*?)\]$/ or text =~ /^(\S+)\[(.*?)\]$/ label = $1 - url = $2 + url = CGI.escapeHTML($2) - label = handle_RDOCLINK label if /^rdoc-image:/ =~ label + if /^rdoc-image:/ =~ label + label = handle_RDOCLINK(label) + else + label = CGI.escapeHTML(label) + end gen_url url, label end @@ -200,7 +203,9 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter def accept_paragraph paragraph @res << "\n<p>" text = paragraph.text @hard_break - text = text.gsub(/\r?\n/, ' ') + text = text.gsub(/(#{SPACE_SEPARATED_LETTER_CLASS})?\K\r?\n(?=(?(1)(#{SPACE_SEPARATED_LETTER_CLASS})?))/o) { + defined?($2) && ' ' + } @res << to_html(text) @res << "</p>\n" end @@ -324,7 +329,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter header.zip(aligns) do |text, align| @res << '<th' @res << ' align="' << align << '"' if align - @res << '>' << CGI.escapeHTML(text) << "</th>\n" + @res << '>' << to_html(text) << "</th>\n" end @res << "</tr>\n</thead>\n<tbody>\n" body.each do |row| @@ -332,7 +337,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter row.zip(aligns) do |text, align| @res << '<td' @res << ' align="' << align << '"' if align - @res << '>' << CGI.escapeHTML(text) << "</td>\n" + @res << '>' << to_html(text) << "</td>\n" end @res << "</tr>\n" end @@ -428,7 +433,9 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter def parseable? text verbose, $VERBOSE = $VERBOSE, nil - eval("BEGIN {return true}\n#{text}") + catch(:valid) do + eval("BEGIN { throw :valid, true }\n#{text}") + end rescue SyntaxError false ensure @@ -443,4 +450,3 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter end end - diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb index a9fd09df41..9b5de62fd6 100644 --- a/lib/rdoc/markup/to_html_crossref.rb +++ b/lib/rdoc/markup/to_html_crossref.rb @@ -42,6 +42,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml @cross_reference = RDoc::CrossReference.new @context end + # :nodoc: def init_link_notation_regexp_handlings add_regexp_handling_RDOCLINK @@ -62,8 +63,8 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml name = name[1..-1] unless @show_hash if name[0, 1] == '#' - if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])@/ - text ||= "#{CGI.unescape $'} at <code>#{$1}</code>" + if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/ + text ||= [CGI.unescape($'), (" at <code>#{$1}</code>" if $~.begin(1))].join("") code = false else text ||= name @@ -138,39 +139,37 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml # Creates an HTML link to +name+ with the given +text+. def link name, text, code = true - if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])@/ + if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/ name = $1 label = $' end - ref = @cross_reference.resolve name, text + ref = @cross_reference.resolve name, text if name case ref when String then ref else - path = ref.as_href @from_path + path = ref ? ref.as_href(@from_path) : +"" if code and RDoc::CodeObject === ref and !(RDoc::TopLevel === ref) text = "<code>#{CGI.escapeHTML text}</code>" end - if path =~ /#/ then - path << "-label-#{label}" - elsif ref.sections and - ref.sections.any? { |section| label == section.title } then - path << "##{label}" - else - if ref.respond_to?(:aref) + if label + if path =~ /#/ + path << "-label-#{label}" + elsif ref&.sections&.any? { |section| label == section.title } + path << "##{label}" + elsif ref.respond_to?(:aref) path << "##{ref.aref}-label-#{label}" else path << "#label-#{label}" end - end if label + end "<a href=\"#{path}\">#{text}</a>" end end end - diff --git a/lib/rdoc/markup/to_html_snippet.rb b/lib/rdoc/markup/to_html_snippet.rb index 4eb36592b7..f471395a3a 100644 --- a/lib/rdoc/markup/to_html_snippet.rb +++ b/lib/rdoc/markup/to_html_snippet.rb @@ -66,6 +66,9 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml alias accept_rule ignore + ## + # Adds +paragraph+ to the output + def accept_paragraph paragraph para = @in_list_entry.last || "<p>" @@ -282,4 +285,3 @@ class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml end end - diff --git a/lib/rdoc/markup/to_joined_paragraph.rb b/lib/rdoc/markup/to_joined_paragraph.rb index 46e07c94ad..31cbe0853c 100644 --- a/lib/rdoc/markup/to_joined_paragraph.rb +++ b/lib/rdoc/markup/to_joined_paragraph.rb @@ -25,9 +25,9 @@ class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter def accept_paragraph paragraph parts = paragraph.parts.chunk do |part| String === part - end.map do |string, chunk| + end.flat_map do |string, chunk| string ? chunk.join.rstrip : chunk - end.flatten + end paragraph.parts.replace parts end @@ -44,4 +44,3 @@ class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter alias accept_table ignore end - diff --git a/lib/rdoc/markup/to_label.rb b/lib/rdoc/markup/to_label.rb index aa1dbcf2a1..cf808364e9 100644 --- a/lib/rdoc/markup/to_label.rb +++ b/lib/rdoc/markup/to_label.rb @@ -72,4 +72,3 @@ class RDoc::Markup::ToLabel < RDoc::Markup::Formatter alias start_accepting ignore end - diff --git a/lib/rdoc/markup/to_markdown.rb b/lib/rdoc/markup/to_markdown.rb index 3ee48becb0..b915fab60b 100644 --- a/lib/rdoc/markup/to_markdown.rb +++ b/lib/rdoc/markup/to_markdown.rb @@ -45,8 +45,6 @@ class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc # Finishes consumption of `list` def accept_list_end list - @res << "\n" - super end @@ -60,6 +58,8 @@ class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc when :NOTE, :LABEL then use_prefix + @res << "\n" + 4 else @list_index[-1] = @list_index.last.succ @@ -81,11 +81,11 @@ class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc attributes(label).strip end.join "\n" - bullets << "\n:" + bullets << "\n" unless bullets.empty? @prefix = ' ' * @indent @indent += 4 - @prefix << bullets + (' ' * (@indent - 1)) + @prefix << bullets << ":" << (' ' * (@indent - 1)) else bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.' @prefix = (' ' * @indent) + bullet.ljust(4) @@ -189,4 +189,3 @@ class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc end end - diff --git a/lib/rdoc/markup/to_rdoc.rb b/lib/rdoc/markup/to_rdoc.rb index 3cdf4fd08b..88234f5096 100644 --- a/lib/rdoc/markup/to_rdoc.rb +++ b/lib/rdoc/markup/to_rdoc.rb @@ -145,11 +145,19 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter case type when :NOTE, :LABEL then - bullets = Array(list_item.label).map do |label| + stripped_labels = Array(list_item.label).map do |label| attributes(label).strip - end.join "\n" + end + + bullets = case type + when :NOTE + stripped_labels.map { |b| "#{b}::" } + when :LABEL + stripped_labels.map { |b| "[#{b}]" } + end - bullets << ":\n" unless bullets.empty? + bullets = bullets.join("\n") + bullets << "\n" unless stripped_labels.empty? @prefix = ' ' * @indent @indent += 2 @@ -330,33 +338,15 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter text_len = 20 if text_len < 20 - re = /^(.{0,#{text_len}})[ \n]/ next_prefix = ' ' * @indent prefix = @prefix || next_prefix @prefix = nil - @res << prefix - - while text.length > text_len - if text =~ re then - @res << $1 - text.slice!(0, $&.length) - else - @res << text.slice!(0, text_len) - end - - @res << "\n" << next_prefix - end - - if text.empty? then - @res.pop - @res.pop - else - @res << text - @res << "\n" + text.scan(/\G(?:([^ \n]{#{text_len}})(?=[^ \n])|(.{1,#{text_len}})(?:[ \n]|\z))/) do + @res << prefix << ($1 || $2) << "\n" + prefix = next_prefix end end end - diff --git a/lib/rdoc/markup/to_table_of_contents.rb b/lib/rdoc/markup/to_table_of_contents.rb index eb8e8faa16..e5b8225ba3 100644 --- a/lib/rdoc/markup/to_table_of_contents.rb +++ b/lib/rdoc/markup/to_table_of_contents.rb @@ -86,4 +86,3 @@ class RDoc::Markup::ToTableOfContents < RDoc::Markup::Formatter # :startdoc: end - diff --git a/lib/rdoc/markup/to_test.rb b/lib/rdoc/markup/to_test.rb index 61d3cffaf0..30113da561 100644 --- a/lib/rdoc/markup/to_test.rb +++ b/lib/rdoc/markup/to_test.rb @@ -67,4 +67,3 @@ class RDoc::Markup::ToTest < RDoc::Markup::Formatter # :startdoc: end - diff --git a/lib/rdoc/markup/to_tt_only.rb b/lib/rdoc/markup/to_tt_only.rb index 9235d33f04..9ac14ed235 100644 --- a/lib/rdoc/markup/to_tt_only.rb +++ b/lib/rdoc/markup/to_tt_only.rb @@ -118,4 +118,3 @@ class RDoc::Markup::ToTtOnly < RDoc::Markup::Formatter end end - diff --git a/lib/rdoc/markup/verbatim.rb b/lib/rdoc/markup/verbatim.rb index 7f1bc29a09..f51c2cfa14 100644 --- a/lib/rdoc/markup/verbatim.rb +++ b/lib/rdoc/markup/verbatim.rb @@ -81,4 +81,3 @@ class RDoc::Markup::Verbatim < RDoc::Markup::Raw end end - diff --git a/lib/rdoc/meta_method.rb b/lib/rdoc/meta_method.rb index 7927a9ce9c..8c95a0f78c 100644 --- a/lib/rdoc/meta_method.rb +++ b/lib/rdoc/meta_method.rb @@ -4,4 +4,3 @@ class RDoc::MetaMethod < RDoc::AnyMethod end - diff --git a/lib/rdoc/method_attr.rb b/lib/rdoc/method_attr.rb index aae3c47e85..61ddb32f46 100644 --- a/lib/rdoc/method_attr.rb +++ b/lib/rdoc/method_attr.rb @@ -416,4 +416,3 @@ class RDoc::MethodAttr < RDoc::CodeObject end end - diff --git a/lib/rdoc/mixin.rb b/lib/rdoc/mixin.rb index 379d7cc526..fa8faefc15 100644 --- a/lib/rdoc/mixin.rb +++ b/lib/rdoc/mixin.rb @@ -118,4 +118,3 @@ class RDoc::Mixin < RDoc::CodeObject end end - diff --git a/lib/rdoc/normal_class.rb b/lib/rdoc/normal_class.rb index 68dfa7d4a3..aa340b5d15 100644 --- a/lib/rdoc/normal_class.rb +++ b/lib/rdoc/normal_class.rb @@ -90,4 +90,3 @@ class RDoc::NormalClass < RDoc::ClassModule end end - diff --git a/lib/rdoc/normal_module.rb b/lib/rdoc/normal_module.rb index edf29f8f1c..498ec4dde2 100644 --- a/lib/rdoc/normal_module.rb +++ b/lib/rdoc/normal_module.rb @@ -71,4 +71,3 @@ class RDoc::NormalModule < RDoc::ClassModule end end - diff --git a/lib/rdoc/options.rb b/lib/rdoc/options.rb index 55994c9dcc..7518e6cc54 100644 --- a/lib/rdoc/options.rb +++ b/lib/rdoc/options.rb @@ -105,6 +105,7 @@ class RDoc::Options generator_name generator_options generators + locale op_dir page_dir option_parser @@ -339,6 +340,10 @@ class RDoc::Options attr_reader :visibility + ## + # Indicates if files of test suites should be skipped + attr_accessor :skip_tests + def initialize loaded_options = nil # :nodoc: init_ivars override loaded_options if loaded_options @@ -386,6 +391,7 @@ class RDoc::Options @write_options = false @encoding = Encoding::UTF_8 @charset = @encoding.name + @skip_tests = true end def init_with map # :nodoc: @@ -560,9 +566,10 @@ class RDoc::Options @op_dir ||= 'doc' - @rdoc_include << "." if @rdoc_include.empty? root = @root.to_s - @rdoc_include << root unless @rdoc_include.include?(root) + if @rdoc_include.empty? || !@rdoc_include.include?(root) + @rdoc_include << root + end @exclude = self.exclude @@ -778,6 +785,13 @@ Usage: #{opt.program_name} [options] [names...] opt.separator nil + opt.on("--no-skipping-tests", nil, + "Don't skip generating documentation for test and spec files") do |value| + @skip_tests = false + end + + opt.separator nil + opt.on("--extension=NEW=OLD", "-E", "Treat files ending with .new as if they", "ended with .old. Using '-E cgi=rb' will", diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb index 7006265b63..425105effa 100644 --- a/lib/rdoc/parser.rb +++ b/lib/rdoc/parser.rb @@ -125,9 +125,11 @@ class RDoc::Parser return parser if ext_name.empty? if parser == RDoc::Parser::Simple and ext_name !~ /txt|rdoc/ then - case check_modeline file_name + case mode = check_modeline(file_name) when nil, 'rdoc' then # continue - else return nil + else + RDoc::Parser.parsers.find { |_, p| return p if mode.casecmp?(p.name[/\w+\z/]) } + return nil end end @@ -266,6 +268,23 @@ class RDoc::Parser autoload :RubyTools, "#{__dir__}/parser/ruby_tools" autoload :Text, "#{__dir__}/parser/text" + ## + # Normalizes tabs in +body+ + + def handle_tab_width(body) + if /\t/ =~ body + tab_width = @options.tab_width + body.split(/\n/).map do |line| + 1 while line.gsub!(/\t+/) do + b, e = $~.offset(0) + ' ' * (tab_width * (e-b) - b % tab_width) + end + line + end.join "\n" + else + body + end + end end # simple must come first in order to show up last in the parsers list diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb index b1bbf22f16..f8f238fd74 100644 --- a/lib/rdoc/parser/c.rb +++ b/lib/rdoc/parser/c.rb @@ -122,6 +122,11 @@ class RDoc::Parser::C < RDoc::Parser include RDoc::Text + # :stopdoc: + BOOL_ARG_PATTERN = /\s*+\b([01]|Q?(?:true|false)|TRUE|FALSE)\b\s*/ + TRUE_VALUES = ['1', 'TRUE', 'true', 'Qtrue'].freeze + # :startdoc: + ## # Maps C variable names to names of Ruby classes or modules @@ -259,18 +264,18 @@ class RDoc::Parser::C < RDoc::Parser @content.scan(/rb_attr\s*\( \s*(\w+), \s*([\w"()]+), - \s*([01]), - \s*([01]), - \s*\w+\);/xm) do |var_name, attr_name, read, write| + #{BOOL_ARG_PATTERN}, + #{BOOL_ARG_PATTERN}, + \s*\w+\);/xmo) do |var_name, attr_name, read, write| handle_attr var_name, attr_name, read, write end @content.scan(%r%rb_define_attr\( \s*([\w\.]+), \s*"([^"]+)", - \s*(\d+), - \s*(\d+)\s*\); - %xm) do |var_name, attr_name, read, write| + #{BOOL_ARG_PATTERN}, + #{BOOL_ARG_PATTERN}\); + %xmo) do |var_name, attr_name, read, write| handle_attr var_name, attr_name, read, write end end @@ -367,12 +372,20 @@ class RDoc::Parser::C < RDoc::Parser next end + var_name = $~[:var_name] type = $~[:module] ? :module : :class class_name = $~[:class_name] parent_name = $~[:parent_name] || $~[:path] under = $~[:under] + attributes = $~[:attributes] - handle_class_module($~[:var_name], type, class_name, parent_name, under) + handle_class_module(var_name, type, class_name, parent_name, under) + if attributes and !parent_name # rb_struct_define *not* without_accessor + true_flag = 'Qtrue' + attributes.scan(/"\K\w+(?=")/) do |attr_name| + handle_attr var_name, attr_name, true_flag, true_flag + end + end end end @@ -562,19 +575,18 @@ class RDoc::Parser::C < RDoc::Parser table = {} file_content.scan(%r{ ((?>/\*.*?\*/\s*)?) - ((?:(?:\w+)\s+)? - (?:intern\s+)?VALUE\s+(\w+) - \s*(?:\([^)]*\))(?:[^\);]|$)) + ((?:\w+\s+){0,2} VALUE\s+(\w+) + \s*(?:\([^\)]*\))(?:[^\);]|$)) | ((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+(\w+)\s+(\w+)) | ^\s*\#\s*define\s+(\w+)\s+(\w+) }xm) do case - when $1 - table[$3] = [:func_def, $1, $2, $~.offset(2)] if !table[$3] || table[$3][0] != :func_def - when $4 - table[$6] = [:macro_def, $4, $5, $~.offset(5), $7] if !table[$6] || table[$6][0] == :macro_alias - when $8 - table[$8] ||= [:macro_alias, $9] + when name = $3 + table[name] = [:func_def, $1, $2, $~.offset(2)] if !(t = table[name]) || t[0] != :func_def + when name = $6 + table[name] = [:macro_def, $4, $5, $~.offset(5), $7] if !(t = table[name]) || t[0] == :macro_alias + when name = $8 + table[name] ||= [:macro_alias, $9] end end table @@ -715,7 +727,7 @@ class RDoc::Parser::C < RDoc::Parser ((?>/\*.*?\*/\s+)) (static\s+)? void\s+ - Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xmi then + Init(?:VM)?_(?i:#{class_name})\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xm then comment = $1.sub(%r%Document-(?:class|module):\s+#{class_name}%, '') elsif @content =~ %r%Document-(?:class|module):\s+#{class_name}\s*? (?:<\s+[:,\w]+)?\n((?>.*?\*/))%xm then @@ -744,17 +756,27 @@ class RDoc::Parser::C < RDoc::Parser def gen_const_table file_content table = {} @content.scan(%r{ - ((?>^\s*/\*.*?\*/\s+)) - rb_define_(\w+)\((?:\s*(?:\w+),)?\s* - "(\w+)"\s*, + (?<doc>(?>^\s*/\*.*?\*/\s+)) + rb_define_(?<type>\w+)\(\s*(?:\w+),\s* + "(?<name>\w+)"\s*, + .*?\)\s*; + | (?<doc>(?>^\s*/\*.*?\*/\s+)) + rb_file_(?<type>const)\(\s* + "(?<name>\w+)"\s*, .*?\)\s*; + | (?<doc>(?>^\s*/\*.*?\*/\s+)) + rb_curses_define_(?<type>const)\(\s* + (?<name>\w+) + \s*\)\s*; | Document-(?:const|global|variable):\s - ((?:\w+::)*\w+) - \s*?\n((?>.*?\*/)) + (?<name>(?:\w+::)*\w+) + \s*?\n(?<doc>(?>.*?\*/)) }mxi) do - case - when $1 then table[[$2, $3]] = $1 - when $4 then table[$4] = "/*\n" + $5 + name, doc, type = $~.values_at(:name, :doc, :type) + if type + table[[type, name]] = doc + else + table[name] = "/*\n" + doc end end table @@ -815,8 +837,8 @@ class RDoc::Parser::C < RDoc::Parser def handle_attr(var_name, attr_name, read, write) rw = '' - rw += 'R' if '1' == read - rw += 'W' if '1' == write + rw += 'R' if TRUE_VALUES.include?(read) + rw += 'W' if TRUE_VALUES.include?(write) class_name = @known_classes[var_name] @@ -926,14 +948,13 @@ class RDoc::Parser::C < RDoc::Parser # "/* definition: comment */" form. The literal ':' and '\' characters # can be escaped with a backslash. if type.downcase == 'const' then - no_match, new_definition, new_comment = comment.text.split(/(\A.*):/) + if /\A(.+?)?:(?!\S)/ =~ comment.text + new_definition, new_comment = $1, $' - if no_match and no_match.empty? then - if new_definition.empty? then # Default to literal C definition + if !new_definition # Default to literal C definition new_definition = definition else - new_definition = new_definition.gsub("\:", ":") - new_definition = new_definition.gsub("\\", '\\') + new_definition = new_definition.gsub(/\\([\\:])/, '\1') end new_definition.sub!(/\A(\s+)/, '') @@ -1045,23 +1066,6 @@ class RDoc::Parser::C < RDoc::Parser end ## - # Normalizes tabs in +body+ - - def handle_tab_width(body) - if /\t/ =~ body - tab_width = @options.tab_width - body.split(/\n/).map do |line| - 1 while line.gsub!(/\t+/) do - ' ' * (tab_width * $&.length - $`.length % tab_width) - end && $~ - line - end.join "\n" - else - body - end - end - - ## # Loads the variable map with the given +name+ from the RDoc::Store, if # present. @@ -1221,6 +1225,9 @@ class RDoc::Parser::C < RDoc::Parser @top_level end + ## + # Creates a RDoc::Comment instance. + def new_comment text = nil, location = nil, language = nil RDoc::Comment.new(text, location, language).tap do |comment| comment.format = @markup diff --git a/lib/rdoc/parser/changelog.rb b/lib/rdoc/parser/changelog.rb index 9245d49376..a046241870 100644 --- a/lib/rdoc/parser/changelog.rb +++ b/lib/rdoc/parser/changelog.rb @@ -216,12 +216,22 @@ class RDoc::Parser::ChangeLog < RDoc::Parser @top_level end + ## + # The extension for Git commit log + module Git + ## + # Parses auxiliary info. Currentry `base-url` to expand + # references is effective. + def parse_info(info) /^\s*base-url\s*=\s*(.*\S)/ =~ info @base_url = $1 end + ## + # Parses the entries in the Git commit logs + def parse_entries entries = [] @@ -244,6 +254,11 @@ class RDoc::Parser::ChangeLog < RDoc::Parser entries end + ## + # Returns a list of ChangeLog entries as + # RDoc::Parser::ChangeLog::Git::LogEntry list for the given + # +entries+. + def create_entries entries # git log entries have no strictly itemized style like the old # style, just assume Markdown. @@ -332,4 +347,3 @@ class RDoc::Parser::ChangeLog < RDoc::Parser end end end - diff --git a/lib/rdoc/parser/markdown.rb b/lib/rdoc/parser/markdown.rb index 9ff478f872..3c316227b9 100644 --- a/lib/rdoc/parser/markdown.rb +++ b/lib/rdoc/parser/markdown.rb @@ -20,5 +20,3 @@ class RDoc::Parser::Markdown < RDoc::Parser end end - - diff --git a/lib/rdoc/parser/rd.rb b/lib/rdoc/parser/rd.rb index 25f5711731..19e47e549d 100644 --- a/lib/rdoc/parser/rd.rb +++ b/lib/rdoc/parser/rd.rb @@ -20,4 +20,3 @@ class RDoc::Parser::RD < RDoc::Parser end end - diff --git a/lib/rdoc/parser/ripper_state_lex.rb b/lib/rdoc/parser/ripper_state_lex.rb index 5492f08726..f6cefd0305 100644 --- a/lib/rdoc/parser/ripper_state_lex.rb +++ b/lib/rdoc/parser/ripper_state_lex.rb @@ -1,7 +1,12 @@ # frozen_string_literal: true require 'ripper' +## +# Wrapper for Ripper lex states + class RDoc::Parser::RipperStateLex + # :stopdoc: + # TODO: Remove this constants after Ruby 2.4 EOL RIPPER_HAS_LEX_STATE = Ripper::Filter.method_defined?(:state) @@ -368,7 +373,7 @@ class RDoc::Parser::RipperStateLex private def get_symbol_tk(tk) is_symbol = true symbol_tk = Token.new(tk.line_no, tk.char_no, :on_symbol) - if ":'" == tk[:text] or ':"' == tk[:text] + if ":'" == tk[:text] or ':"' == tk[:text] or tk[:text].start_with?('%s') tk1 = get_string_tk(tk) symbol_tk[:text] = tk1[:text] symbol_tk[:state] = tk1[:state] @@ -565,6 +570,9 @@ class RDoc::Parser::RipperStateLex tk end + # :startdoc: + + # New lexer for +code+. def initialize(code) @buf = [] @heredoc_queue = [] @@ -572,6 +580,7 @@ class RDoc::Parser::RipperStateLex @tokens = @inner_lex.parse([]) end + # Returns tokens parsed from +code+. def self.parse(code) lex = self.new(code) tokens = [] @@ -584,6 +593,7 @@ class RDoc::Parser::RipperStateLex tokens end + # Returns +true+ if lex state will be +END+ after +token+. def self.end?(token) (token[:state] & EXPR_END) end diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb index 3c5f79632c..85f1cd0391 100644 --- a/lib/rdoc/parser/ruby.rb +++ b/lib/rdoc/parser/ruby.rb @@ -8,6 +8,9 @@ # by Keiju ISHITSUKA (Nippon Rational Inc.) # +require 'ripper' +require_relative 'ripper_state_lex' + ## # Extracts code elements from a source file returning a TopLevel object # containing the constituent file elements. @@ -138,9 +141,6 @@ # Note that by default, the :method: directive will be ignored if there is a # standard rdocable item following it. -require 'ripper' -require_relative 'ripper_state_lex' - class RDoc::Parser::Ruby < RDoc::Parser parse_files_matching(/\.rbw?$/) @@ -164,15 +164,7 @@ class RDoc::Parser::Ruby < RDoc::Parser def initialize(top_level, file_name, content, options, stats) super - if /\t/ =~ content then - tab_width = @options.tab_width - content = content.split(/\n/).map do |line| - 1 while line.gsub!(/\t+/) { - ' ' * (tab_width*$&.length - $`.length % tab_width) - } && $~ - line - end.join("\n") - end + content = handle_tab_width(content) @size = 0 @token_listeners = nil @@ -188,6 +180,9 @@ class RDoc::Parser::Ruby < RDoc::Parser reset end + ## + # Return +true+ if +tk+ is a newline. + def tk_nl?(tk) :on_nl == tk[:kind] or :on_ignored_nl == tk[:kind] end @@ -794,8 +789,10 @@ class RDoc::Parser::Ruby < RDoc::Parser al.line = line_no read_documentation_modifiers al, RDoc::ATTR_MODIFIERS - context.add_alias al - @stats.add_alias al + if al.document_self or not @track_visibility + context.add_alias al + @stats.add_alias al + end al end @@ -1458,6 +1455,12 @@ class RDoc::Parser::Ruby < RDoc::Parser meth = RDoc::AnyMethod.new get_tkread, name look_for_directives_in meth, comment meth.singleton = single == SINGLE ? true : singleton + if singleton + # `current_line_visibility' is useless because it works against + # the normal method named as same as the singleton method, after + # the latter was defined. Of course these are different things. + container.current_line_visibility = :public + end record_location meth meth.line = line_no @@ -1781,6 +1784,7 @@ class RDoc::Parser::Ruby < RDoc::Parser nest = 1 save_visibility = container.visibility + container.visibility = :public unless current_method non_comment_seen = true @@ -2142,7 +2146,7 @@ class RDoc::Parser::Ruby < RDoc::Parser if :on_nl == tk[:kind] or (:on_kw == tk[:kind] && 'def' == tk[:text]) then return elsif :on_comment == tk[:kind] or :on_embdoc == tk[:kind] then - return unless tk[:text] =~ /\s*:?([\w-]+):\s*(.*)/ + return unless tk[:text] =~ /:?\b([\w-]+):\s*(.*)/ directive = $1.downcase diff --git a/lib/rdoc/parser/ruby_tools.rb b/lib/rdoc/parser/ruby_tools.rb index 681d7166ce..40ea517c4d 100644 --- a/lib/rdoc/parser/ruby_tools.rb +++ b/lib/rdoc/parser/ruby_tools.rb @@ -163,5 +163,3 @@ module RDoc::Parser::RubyTools end end - - diff --git a/lib/rdoc/parser/text.rb b/lib/rdoc/parser/text.rb index 01de0cc595..5095d8cc64 100644 --- a/lib/rdoc/parser/text.rb +++ b/lib/rdoc/parser/text.rb @@ -9,4 +9,3 @@ module RDoc::Parser::Text end - diff --git a/lib/rdoc/rd/block_parser.rb b/lib/rdoc/rd/block_parser.rb index eb7d46925b..527147d91d 100644 --- a/lib/rdoc/rd/block_parser.rb +++ b/lib/rdoc/rd/block_parser.rb @@ -1,11 +1,659 @@ # frozen_string_literal: true # # DO NOT MODIFY!!!! -# This file is automatically generated by Racc 1.6.0 -# from Racc grammar file "". +# This file is automatically generated by Racc 1.7.3 +# from Racc grammar file "block_parser.ry". # -require 'racc/parser.rb' +###### racc/parser.rb begin +unless $".find {|p| p.end_with?('/racc/parser.rb')} +$".push "#{__dir__}/racc/parser.rb" +#-- +# Copyright (c) 1999-2006 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. +# +# As a special exception, when this code is copied by Racc +# into a Racc output file, you may use that output file +# without restriction. +#++ + +unless $".find {|p| p.end_with?('/racc/info.rb')} +$".push "#{__dir__}/racc/info.rb" + +module Racc + VERSION = '1.7.3' + Version = VERSION + Copyright = 'Copyright (c) 1999-2006 Minero Aoki' +end + +end + + +unless defined?(NotImplementedError) + NotImplementedError = NotImplementError # :nodoc: +end + +module Racc + class ParseError < StandardError; end +end +unless defined?(::ParseError) + ParseError = Racc::ParseError # :nodoc: +end + +# Racc is a LALR(1) parser generator. +# It is written in Ruby itself, and generates Ruby programs. +# +# == Command-line Reference +# +# racc [-o<var>filename</var>] [--output-file=<var>filename</var>] +# [-e<var>rubypath</var>] [--executable=<var>rubypath</var>] +# [-v] [--verbose] +# [-O<var>filename</var>] [--log-file=<var>filename</var>] +# [-g] [--debug] +# [-E] [--embedded] +# [-l] [--no-line-convert] +# [-c] [--line-convert-all] +# [-a] [--no-omit-actions] +# [-C] [--check-only] +# [-S] [--output-status] +# [--version] [--copyright] [--help] <var>grammarfile</var> +# +# [+grammarfile+] +# Racc grammar file. Any extension is permitted. +# [-o+outfile+, --output-file=+outfile+] +# A filename for output. default is <+filename+>.tab.rb +# [-O+filename+, --log-file=+filename+] +# Place logging output in file +filename+. +# Default log file name is <+filename+>.output. +# [-e+rubypath+, --executable=+rubypath+] +# output executable file(mode 755). where +path+ is the Ruby interpreter. +# [-v, --verbose] +# verbose mode. create +filename+.output file, like yacc's y.output file. +# [-g, --debug] +# add debug code to parser class. To display debugging information, +# use this '-g' option and set @yydebug true in parser class. +# [-E, --embedded] +# Output parser which doesn't need runtime files (racc/parser.rb). +# [-F, --frozen] +# Output parser which declares frozen_string_literals: true +# [-C, --check-only] +# Check syntax of racc grammar file and quit. +# [-S, --output-status] +# Print messages time to time while compiling. +# [-l, --no-line-convert] +# turns off line number converting. +# [-c, --line-convert-all] +# Convert line number of actions, inner, header and footer. +# [-a, --no-omit-actions] +# Call all actions, even if an action is empty. +# [--version] +# print Racc version and quit. +# [--copyright] +# Print copyright and quit. +# [--help] +# Print usage and quit. +# +# == Generating Parser Using Racc +# +# To compile Racc grammar file, simply type: +# +# $ racc parse.y +# +# This creates Ruby script file "parse.tab.y". The -o option can change the output filename. +# +# == Writing A Racc Grammar File +# +# If you want your own parser, you have to write a grammar file. +# A grammar file contains the name of your parser class, grammar for the parser, +# user code, and anything else. +# When writing a grammar file, yacc's knowledge is helpful. +# If you have not used yacc before, Racc is not too difficult. +# +# Here's an example Racc grammar file. +# +# class Calcparser +# rule +# target: exp { print val[0] } +# +# exp: exp '+' exp +# | exp '*' exp +# | '(' exp ')' +# | NUMBER +# end +# +# Racc grammar files resemble yacc files. +# But (of course), this is Ruby code. +# yacc's $$ is the 'result', $0, $1... is +# an array called 'val', and $-1, $-2... is an array called '_values'. +# +# See the {Grammar File Reference}[rdoc-ref:lib/racc/rdoc/grammar.en.rdoc] for +# more information on grammar files. +# +# == Parser +# +# Then you must prepare the parse entry method. There are two types of +# parse methods in Racc, Racc::Parser#do_parse and Racc::Parser#yyparse +# +# Racc::Parser#do_parse is simple. +# +# It's yyparse() of yacc, and Racc::Parser#next_token is yylex(). +# This method must returns an array like [TOKENSYMBOL, ITS_VALUE]. +# EOF is [false, false]. +# (TOKENSYMBOL is a Ruby symbol (taken from String#intern) by default. +# If you want to change this, see the grammar reference. +# +# Racc::Parser#yyparse is little complicated, but useful. +# It does not use Racc::Parser#next_token, instead it gets tokens from any iterator. +# +# For example, <code>yyparse(obj, :scan)</code> causes +# calling +obj#scan+, and you can return tokens by yielding them from +obj#scan+. +# +# == Debugging +# +# When debugging, "-v" or/and the "-g" option is helpful. +# +# "-v" creates verbose log file (.output). +# "-g" creates a "Verbose Parser". +# Verbose Parser prints the internal status when parsing. +# But it's _not_ automatic. +# You must use -g option and set +@yydebug+ to +true+ in order to get output. +# -g option only creates the verbose parser. +# +# === Racc reported syntax error. +# +# Isn't there too many "end"? +# grammar of racc file is changed in v0.10. +# +# Racc does not use '%' mark, while yacc uses huge number of '%' marks.. +# +# === Racc reported "XXXX conflicts". +# +# Try "racc -v xxxx.y". +# It causes producing racc's internal log file, xxxx.output. +# +# === Generated parsers does not work correctly +# +# Try "racc -g xxxx.y". +# This command let racc generate "debugging parser". +# Then set @yydebug=true in your parser. +# It produces a working log of your parser. +# +# == Re-distributing Racc runtime +# +# A parser, which is created by Racc, requires the Racc runtime module; +# racc/parser.rb. +# +# Ruby 1.8.x comes with Racc runtime module, +# you need NOT distribute Racc runtime files. +# +# If you want to include the Racc runtime module with your parser. +# This can be done by using '-E' option: +# +# $ racc -E -omyparser.rb myparser.y +# +# This command creates myparser.rb which `includes' Racc runtime. +# Only you must do is to distribute your parser file (myparser.rb). +# +# Note: parser.rb is ruby license, but your parser is not. +# Your own parser is completely yours. +module Racc + + unless defined?(Racc_No_Extensions) + Racc_No_Extensions = false # :nodoc: + end + + class Parser + + Racc_Runtime_Version = ::Racc::VERSION + Racc_Runtime_Core_Version_R = ::Racc::VERSION + + begin + if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby' + require 'jruby' + require 'racc/cparse-jruby.jar' + com.headius.racc.Cparse.new.load(JRuby.runtime, false) + else + require 'racc/cparse' + end + + unless new.respond_to?(:_racc_do_parse_c, true) + raise LoadError, 'old cparse.so' + end + if Racc_No_Extensions + raise LoadError, 'selecting ruby version of racc runtime core' + end + + Racc_Main_Parsing_Routine = :_racc_do_parse_c # :nodoc: + Racc_YY_Parse_Method = :_racc_yyparse_c # :nodoc: + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C # :nodoc: + Racc_Runtime_Type = 'c' # :nodoc: + rescue LoadError + Racc_Main_Parsing_Routine = :_racc_do_parse_rb + Racc_YY_Parse_Method = :_racc_yyparse_rb + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R + Racc_Runtime_Type = 'ruby' + end + + def Parser.racc_runtime_type # :nodoc: + Racc_Runtime_Type + end + + def _racc_setup + @yydebug = false unless self.class::Racc_debug_parser + @yydebug = false unless defined?(@yydebug) + if @yydebug + @racc_debug_out = $stderr unless defined?(@racc_debug_out) + @racc_debug_out ||= $stderr + end + arg = self.class::Racc_arg + arg[13] = true if arg.size < 14 + arg + end + + def _racc_init_sysvars + @racc_state = [0] + @racc_tstack = [] + @racc_vstack = [] + + @racc_t = nil + @racc_val = nil + + @racc_read_next = true + + @racc_user_yyerror = false + @racc_error_status = 0 + end + + # The entry point of the parser. This method is used with #next_token. + # If Racc wants to get token (and its value), calls next_token. + # + # Example: + # def parse + # @q = [[1,1], + # [2,2], + # [3,3], + # [false, '$']] + # do_parse + # end + # + # def next_token + # @q.shift + # end + class_eval <<~RUBY, __FILE__, __LINE__ + 1 + def do_parse + #{Racc_Main_Parsing_Routine}(_racc_setup(), false) + end + RUBY + + # The method to fetch next token. + # If you use #do_parse method, you must implement #next_token. + # + # The format of return value is [TOKEN_SYMBOL, VALUE]. + # +token-symbol+ is represented by Ruby's symbol by default, e.g. :IDENT + # for 'IDENT'. ";" (String) for ';'. + # + # The final symbol (End of file) must be false. + def next_token + raise NotImplementedError, "#{self.class}\#next_token is not defined" + end + + def _racc_do_parse_rb(arg, in_debug) + action_table, action_check, action_default, action_pointer, + _, _, _, _, + _, _, token_table, * = arg + + _racc_init_sysvars + tok = act = i = nil + + catch(:racc_end_parse) { + while true + if i = action_pointer[@racc_state[-1]] + if @racc_read_next + if @racc_t != 0 # not EOF + tok, @racc_val = next_token() + unless tok # EOF + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token + end + racc_read_token(@racc_t, tok, @racc_val) if @yydebug + @racc_read_next = false + end + end + i += @racc_t + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + else + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; + end + end + } + end + + # Another entry point for the parser. + # If you use this method, you must implement RECEIVER#METHOD_ID method. + # + # RECEIVER#METHOD_ID is a method to get next token. + # It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE]. + class_eval <<~RUBY, __FILE__, __LINE__ + 1 + def yyparse(recv, mid) + #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), false) + end + RUBY + + def _racc_yyparse_rb(recv, mid, arg, c_debug) + action_table, action_check, action_default, action_pointer, + _, _, _, _, + _, _, token_table, * = arg + + _racc_init_sysvars + + catch(:racc_end_parse) { + until i = action_pointer[@racc_state[-1]] + while act = _racc_evalact(action_default[@racc_state[-1]], arg) + ; + end + end + recv.__send__(mid) do |tok, val| + unless tok + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token + end + @racc_val = val + @racc_read_next = false + + i += @racc_t + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; + end + + while !(i = action_pointer[@racc_state[-1]]) || + ! @racc_read_next || + @racc_t == 0 # $ + unless i and i += @racc_t and + i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; + end + end + end + } + end + + ### + ### common + ### + + def _racc_evalact(act, arg) + action_table, action_check, _, action_pointer, + _, _, _, _, + _, _, _, shift_n, + reduce_n, * = arg + nerr = 0 # tmp + + if act > 0 and act < shift_n + # + # shift + # + if @racc_error_status > 0 + @racc_error_status -= 1 unless @racc_t <= 1 # error token or EOF + end + @racc_vstack.push @racc_val + @racc_state.push act + @racc_read_next = true + if @yydebug + @racc_tstack.push @racc_t + racc_shift @racc_t, @racc_tstack, @racc_vstack + end + + elsif act < 0 and act > -reduce_n + # + # reduce + # + code = catch(:racc_jump) { + @racc_state.push _racc_do_reduce(arg, act) + false + } + if code + case code + when 1 # yyerror + @racc_user_yyerror = true # user_yyerror + return -reduce_n + when 2 # yyaccept + return shift_n + else + raise '[Racc Bug] unknown jump code' + end + end + + elsif act == shift_n + # + # accept + # + racc_accept if @yydebug + throw :racc_end_parse, @racc_vstack[0] + + elsif act == -reduce_n + # + # error + # + case @racc_error_status + when 0 + unless arg[21] # user_yyerror + nerr += 1 + on_error @racc_t, @racc_val, @racc_vstack + end + when 3 + if @racc_t == 0 # is $ + # We're at EOF, and another error occurred immediately after + # attempting auto-recovery + throw :racc_end_parse, nil + end + @racc_read_next = true + end + @racc_user_yyerror = false + @racc_error_status = 3 + while true + if i = action_pointer[@racc_state[-1]] + i += 1 # error token + if i >= 0 and + (act = action_table[i]) and + action_check[i] == @racc_state[-1] + break + end + end + throw :racc_end_parse, nil if @racc_state.size <= 1 + @racc_state.pop + @racc_vstack.pop + if @yydebug + @racc_tstack.pop + racc_e_pop @racc_state, @racc_tstack, @racc_vstack + end + end + return act + + else + raise "[Racc Bug] unknown action #{act.inspect}" + end + + racc_next_state(@racc_state[-1], @racc_state) if @yydebug + + nil + end + + def _racc_do_reduce(arg, act) + _, _, _, _, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, _, _, + _, use_result, * = arg + + state = @racc_state + vstack = @racc_vstack + tstack = @racc_tstack + + i = act * -3 + len = reduce_table[i] + reduce_to = reduce_table[i+1] + method_id = reduce_table[i+2] + void_array = [] + + tmp_t = tstack[-len, len] if @yydebug + tmp_v = vstack[-len, len] + tstack[-len, len] = void_array if @yydebug + vstack[-len, len] = void_array + state[-len, len] = void_array + + # tstack must be updated AFTER method call + if use_result + vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0]) + else + vstack.push __send__(method_id, tmp_v, vstack) + end + tstack.push reduce_to + + racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug + + k1 = reduce_to - nt_base + if i = goto_pointer[k1] + i += state[-1] + if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 + return curstate + end + end + goto_default[k1] + end + + # This method is called when a parse error is found. + # + # ERROR_TOKEN_ID is an internal ID of token which caused error. + # You can get string representation of this ID by calling + # #token_to_str. + # + # ERROR_VALUE is a value of error token. + # + # value_stack is a stack of symbol values. + # DO NOT MODIFY this object. + # + # This method raises ParseError by default. + # + # If this method returns, parsers enter "error recovering mode". + def on_error(t, val, vstack) + raise ParseError, sprintf("parse error on value %s (%s)", + val.inspect, token_to_str(t) || '?') + end + + # Enter error recovering mode. + # This method does not call #on_error. + def yyerror + throw :racc_jump, 1 + end + + # Exit parser. + # Return value is +Symbol_Value_Stack[0]+. + def yyaccept + throw :racc_jump, 2 + end + + # Leave error recovering mode. + def yyerrok + @racc_error_status = 0 + end + + # For debugging output + def racc_read_token(t, tok, val) + @racc_debug_out.print 'read ' + @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') ' + @racc_debug_out.puts val.inspect + @racc_debug_out.puts + end + + def racc_shift(tok, tstack, vstack) + @racc_debug_out.puts "shift #{racc_token2str tok}" + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_reduce(toks, sim, tstack, vstack) + out = @racc_debug_out + out.print 'reduce ' + if toks.empty? + out.print ' <none>' + else + toks.each {|t| out.print ' ', racc_token2str(t) } + end + out.puts " --> #{racc_token2str(sim)}" + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_accept + @racc_debug_out.puts 'accept' + @racc_debug_out.puts + end + + def racc_e_pop(state, tstack, vstack) + @racc_debug_out.puts 'error recovering mode: pop token' + racc_print_states state + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_next_state(curstate, state) + @racc_debug_out.puts "goto #{curstate}" + racc_print_states state + @racc_debug_out.puts + end + + def racc_print_stacks(t, v) + out = @racc_debug_out + out.print ' [' + t.each_index do |i| + out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')' + end + out.puts ' ]' + end + + def racc_print_states(s) + out = @racc_debug_out + out.print ' [' + s.each {|st| out.print ' ', st } + out.puts ' ]' + end + + def racc_token2str(tok) + self.class::Racc_token_to_s_table[tok] or + raise "[Racc Bug] can't convert token #{tok} to string" + end + + # Convert internal ID of token symbol to the string. + def token_to_str(t) + self.class::Racc_token_to_s_table[t] + end + + end + +end + +end +###### racc/parser.rb end class RDoc::RD @@ -18,8 +666,6 @@ class BlockParser < Racc::Parser # :stopdoc: -TMPFILE = ["rdtmp", $$, 0] - MARK_TO_LEVEL = { '=' => 1, '==' => 2, @@ -129,15 +775,19 @@ def next_token # :nodoc: # non-RD part begin when /^=begin\s+(\w+)/ part = $1 +=begin # not imported to RDoc if @in_part # if in non-RD part @part_content.push(line) else @in_part = part if @tree.filter[part] # if filter exists # p "BEGIN_PART: #{@in_part}" # DEBUG end +=end + @in_part = part # non-RD part end - when /^=end/ + when /^=end(?:$|[\s\0\C-d\C-z])/ if @in_part # if in non-RD part +=begin # not imported to RDoc # p "END_PART: #{@in_part}" # DEBUG # make Part-in object part = RDoc::RD::Part.new(@part_content.join(""), @tree, "r") @@ -148,20 +798,22 @@ def next_token # :nodoc: if @tree.filter[@in_part].mode == :rd # if output is RD formatted subtree = parse_subtree(part_out.to_a) else # if output is target formatted - basename = TMPFILE.join('.') - TMPFILE[-1] += 1 - tmpfile = open(@tree.tmp_dir + "/" + basename + ".#{@in_part}", "w") - tmpfile.print(part_out) - tmpfile.close + basename = Tempfile.create(["rdtmp", ".#{@in_part}"], @tree.tmp_dir) do |tmpfile| + tmpfile.print(part_out) + File.basename(tmpfile.path) + end subtree = parse_subtree(["=begin\n", "<<< #{basename}\n", "=end\n"]) end @in_part = nil return [:SUBTREE, subtree] +=end end else +=begin # not imported to RDoc if @in_part # if in non-RD part @part_content.push(line) end +=end end end @@ -356,7 +1008,7 @@ def get_included(file) file_name = File.join dir, file if File.exist? file_name then - included = IO.readlines file_name + included = File.readlines file_name break end end @@ -620,6 +1272,7 @@ Racc_arg = [ racc_shift_n, racc_reduce_n, racc_use_result_var ] +Ractor.make_shareable(Racc_arg) if defined?(Ractor) Racc_token_to_s_table = [ "$end", @@ -670,6 +1323,7 @@ Racc_token_to_s_table = [ "blocks_in_list", "block_in_list", "whitelines2" ] +Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor) Racc_debug_parser = false diff --git a/lib/rdoc/rd/inline.rb b/lib/rdoc/rd/inline.rb index e5cb545728..77d88b2860 100644 --- a/lib/rdoc/rd/inline.rb +++ b/lib/rdoc/rd/inline.rb @@ -69,4 +69,3 @@ class RDoc::RD::Inline alias to_s rdoc # :nodoc: end - diff --git a/lib/rdoc/rd/inline_parser.rb b/lib/rdoc/rd/inline_parser.rb index c1da35a109..adacf64d5b 100644 --- a/lib/rdoc/rd/inline_parser.rb +++ b/lib/rdoc/rd/inline_parser.rb @@ -1,11 +1,659 @@ # frozen_string_literal: true # # DO NOT MODIFY!!!! -# This file is automatically generated by Racc 1.6.0 -# from Racc grammar file "". +# This file is automatically generated by Racc 1.7.3 +# from Racc grammar file "inline_parser.ry". # -require 'racc/parser.rb' +###### racc/parser.rb begin +unless $".find {|p| p.end_with?('/racc/parser.rb')} +$".push "#{__dir__}/racc/parser.rb" +#-- +# Copyright (c) 1999-2006 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. +# +# As a special exception, when this code is copied by Racc +# into a Racc output file, you may use that output file +# without restriction. +#++ + +unless $".find {|p| p.end_with?('/racc/info.rb')} +$".push "#{__dir__}/racc/info.rb" + +module Racc + VERSION = '1.7.3' + Version = VERSION + Copyright = 'Copyright (c) 1999-2006 Minero Aoki' +end + +end + + +unless defined?(NotImplementedError) + NotImplementedError = NotImplementError # :nodoc: +end + +module Racc + class ParseError < StandardError; end +end +unless defined?(::ParseError) + ParseError = Racc::ParseError # :nodoc: +end + +# Racc is a LALR(1) parser generator. +# It is written in Ruby itself, and generates Ruby programs. +# +# == Command-line Reference +# +# racc [-o<var>filename</var>] [--output-file=<var>filename</var>] +# [-e<var>rubypath</var>] [--executable=<var>rubypath</var>] +# [-v] [--verbose] +# [-O<var>filename</var>] [--log-file=<var>filename</var>] +# [-g] [--debug] +# [-E] [--embedded] +# [-l] [--no-line-convert] +# [-c] [--line-convert-all] +# [-a] [--no-omit-actions] +# [-C] [--check-only] +# [-S] [--output-status] +# [--version] [--copyright] [--help] <var>grammarfile</var> +# +# [+grammarfile+] +# Racc grammar file. Any extension is permitted. +# [-o+outfile+, --output-file=+outfile+] +# A filename for output. default is <+filename+>.tab.rb +# [-O+filename+, --log-file=+filename+] +# Place logging output in file +filename+. +# Default log file name is <+filename+>.output. +# [-e+rubypath+, --executable=+rubypath+] +# output executable file(mode 755). where +path+ is the Ruby interpreter. +# [-v, --verbose] +# verbose mode. create +filename+.output file, like yacc's y.output file. +# [-g, --debug] +# add debug code to parser class. To display debugging information, +# use this '-g' option and set @yydebug true in parser class. +# [-E, --embedded] +# Output parser which doesn't need runtime files (racc/parser.rb). +# [-F, --frozen] +# Output parser which declares frozen_string_literals: true +# [-C, --check-only] +# Check syntax of racc grammar file and quit. +# [-S, --output-status] +# Print messages time to time while compiling. +# [-l, --no-line-convert] +# turns off line number converting. +# [-c, --line-convert-all] +# Convert line number of actions, inner, header and footer. +# [-a, --no-omit-actions] +# Call all actions, even if an action is empty. +# [--version] +# print Racc version and quit. +# [--copyright] +# Print copyright and quit. +# [--help] +# Print usage and quit. +# +# == Generating Parser Using Racc +# +# To compile Racc grammar file, simply type: +# +# $ racc parse.y +# +# This creates Ruby script file "parse.tab.y". The -o option can change the output filename. +# +# == Writing A Racc Grammar File +# +# If you want your own parser, you have to write a grammar file. +# A grammar file contains the name of your parser class, grammar for the parser, +# user code, and anything else. +# When writing a grammar file, yacc's knowledge is helpful. +# If you have not used yacc before, Racc is not too difficult. +# +# Here's an example Racc grammar file. +# +# class Calcparser +# rule +# target: exp { print val[0] } +# +# exp: exp '+' exp +# | exp '*' exp +# | '(' exp ')' +# | NUMBER +# end +# +# Racc grammar files resemble yacc files. +# But (of course), this is Ruby code. +# yacc's $$ is the 'result', $0, $1... is +# an array called 'val', and $-1, $-2... is an array called '_values'. +# +# See the {Grammar File Reference}[rdoc-ref:lib/racc/rdoc/grammar.en.rdoc] for +# more information on grammar files. +# +# == Parser +# +# Then you must prepare the parse entry method. There are two types of +# parse methods in Racc, Racc::Parser#do_parse and Racc::Parser#yyparse +# +# Racc::Parser#do_parse is simple. +# +# It's yyparse() of yacc, and Racc::Parser#next_token is yylex(). +# This method must returns an array like [TOKENSYMBOL, ITS_VALUE]. +# EOF is [false, false]. +# (TOKENSYMBOL is a Ruby symbol (taken from String#intern) by default. +# If you want to change this, see the grammar reference. +# +# Racc::Parser#yyparse is little complicated, but useful. +# It does not use Racc::Parser#next_token, instead it gets tokens from any iterator. +# +# For example, <code>yyparse(obj, :scan)</code> causes +# calling +obj#scan+, and you can return tokens by yielding them from +obj#scan+. +# +# == Debugging +# +# When debugging, "-v" or/and the "-g" option is helpful. +# +# "-v" creates verbose log file (.output). +# "-g" creates a "Verbose Parser". +# Verbose Parser prints the internal status when parsing. +# But it's _not_ automatic. +# You must use -g option and set +@yydebug+ to +true+ in order to get output. +# -g option only creates the verbose parser. +# +# === Racc reported syntax error. +# +# Isn't there too many "end"? +# grammar of racc file is changed in v0.10. +# +# Racc does not use '%' mark, while yacc uses huge number of '%' marks.. +# +# === Racc reported "XXXX conflicts". +# +# Try "racc -v xxxx.y". +# It causes producing racc's internal log file, xxxx.output. +# +# === Generated parsers does not work correctly +# +# Try "racc -g xxxx.y". +# This command let racc generate "debugging parser". +# Then set @yydebug=true in your parser. +# It produces a working log of your parser. +# +# == Re-distributing Racc runtime +# +# A parser, which is created by Racc, requires the Racc runtime module; +# racc/parser.rb. +# +# Ruby 1.8.x comes with Racc runtime module, +# you need NOT distribute Racc runtime files. +# +# If you want to include the Racc runtime module with your parser. +# This can be done by using '-E' option: +# +# $ racc -E -omyparser.rb myparser.y +# +# This command creates myparser.rb which `includes' Racc runtime. +# Only you must do is to distribute your parser file (myparser.rb). +# +# Note: parser.rb is ruby license, but your parser is not. +# Your own parser is completely yours. +module Racc + + unless defined?(Racc_No_Extensions) + Racc_No_Extensions = false # :nodoc: + end + + class Parser + + Racc_Runtime_Version = ::Racc::VERSION + Racc_Runtime_Core_Version_R = ::Racc::VERSION + + begin + if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby' + require 'jruby' + require 'racc/cparse-jruby.jar' + com.headius.racc.Cparse.new.load(JRuby.runtime, false) + else + require 'racc/cparse' + end + + unless new.respond_to?(:_racc_do_parse_c, true) + raise LoadError, 'old cparse.so' + end + if Racc_No_Extensions + raise LoadError, 'selecting ruby version of racc runtime core' + end + + Racc_Main_Parsing_Routine = :_racc_do_parse_c # :nodoc: + Racc_YY_Parse_Method = :_racc_yyparse_c # :nodoc: + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C # :nodoc: + Racc_Runtime_Type = 'c' # :nodoc: + rescue LoadError + Racc_Main_Parsing_Routine = :_racc_do_parse_rb + Racc_YY_Parse_Method = :_racc_yyparse_rb + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R + Racc_Runtime_Type = 'ruby' + end + + def Parser.racc_runtime_type # :nodoc: + Racc_Runtime_Type + end + + def _racc_setup + @yydebug = false unless self.class::Racc_debug_parser + @yydebug = false unless defined?(@yydebug) + if @yydebug + @racc_debug_out = $stderr unless defined?(@racc_debug_out) + @racc_debug_out ||= $stderr + end + arg = self.class::Racc_arg + arg[13] = true if arg.size < 14 + arg + end + + def _racc_init_sysvars + @racc_state = [0] + @racc_tstack = [] + @racc_vstack = [] + + @racc_t = nil + @racc_val = nil + + @racc_read_next = true + + @racc_user_yyerror = false + @racc_error_status = 0 + end + + # The entry point of the parser. This method is used with #next_token. + # If Racc wants to get token (and its value), calls next_token. + # + # Example: + # def parse + # @q = [[1,1], + # [2,2], + # [3,3], + # [false, '$']] + # do_parse + # end + # + # def next_token + # @q.shift + # end + class_eval <<~RUBY, __FILE__, __LINE__ + 1 + def do_parse + #{Racc_Main_Parsing_Routine}(_racc_setup(), false) + end + RUBY + + # The method to fetch next token. + # If you use #do_parse method, you must implement #next_token. + # + # The format of return value is [TOKEN_SYMBOL, VALUE]. + # +token-symbol+ is represented by Ruby's symbol by default, e.g. :IDENT + # for 'IDENT'. ";" (String) for ';'. + # + # The final symbol (End of file) must be false. + def next_token + raise NotImplementedError, "#{self.class}\#next_token is not defined" + end + + def _racc_do_parse_rb(arg, in_debug) + action_table, action_check, action_default, action_pointer, + _, _, _, _, + _, _, token_table, * = arg + + _racc_init_sysvars + tok = act = i = nil + + catch(:racc_end_parse) { + while true + if i = action_pointer[@racc_state[-1]] + if @racc_read_next + if @racc_t != 0 # not EOF + tok, @racc_val = next_token() + unless tok # EOF + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token + end + racc_read_token(@racc_t, tok, @racc_val) if @yydebug + @racc_read_next = false + end + end + i += @racc_t + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + else + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; + end + end + } + end + + # Another entry point for the parser. + # If you use this method, you must implement RECEIVER#METHOD_ID method. + # + # RECEIVER#METHOD_ID is a method to get next token. + # It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE]. + class_eval <<~RUBY, __FILE__, __LINE__ + 1 + def yyparse(recv, mid) + #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), false) + end + RUBY + + def _racc_yyparse_rb(recv, mid, arg, c_debug) + action_table, action_check, action_default, action_pointer, + _, _, _, _, + _, _, token_table, * = arg + + _racc_init_sysvars + + catch(:racc_end_parse) { + until i = action_pointer[@racc_state[-1]] + while act = _racc_evalact(action_default[@racc_state[-1]], arg) + ; + end + end + recv.__send__(mid) do |tok, val| + unless tok + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token + end + @racc_val = val + @racc_read_next = false + + i += @racc_t + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; + end + + while !(i = action_pointer[@racc_state[-1]]) || + ! @racc_read_next || + @racc_t == 0 # $ + unless i and i += @racc_t and + i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; + end + end + end + } + end + + ### + ### common + ### + + def _racc_evalact(act, arg) + action_table, action_check, _, action_pointer, + _, _, _, _, + _, _, _, shift_n, + reduce_n, * = arg + nerr = 0 # tmp + + if act > 0 and act < shift_n + # + # shift + # + if @racc_error_status > 0 + @racc_error_status -= 1 unless @racc_t <= 1 # error token or EOF + end + @racc_vstack.push @racc_val + @racc_state.push act + @racc_read_next = true + if @yydebug + @racc_tstack.push @racc_t + racc_shift @racc_t, @racc_tstack, @racc_vstack + end + + elsif act < 0 and act > -reduce_n + # + # reduce + # + code = catch(:racc_jump) { + @racc_state.push _racc_do_reduce(arg, act) + false + } + if code + case code + when 1 # yyerror + @racc_user_yyerror = true # user_yyerror + return -reduce_n + when 2 # yyaccept + return shift_n + else + raise '[Racc Bug] unknown jump code' + end + end + + elsif act == shift_n + # + # accept + # + racc_accept if @yydebug + throw :racc_end_parse, @racc_vstack[0] + + elsif act == -reduce_n + # + # error + # + case @racc_error_status + when 0 + unless arg[21] # user_yyerror + nerr += 1 + on_error @racc_t, @racc_val, @racc_vstack + end + when 3 + if @racc_t == 0 # is $ + # We're at EOF, and another error occurred immediately after + # attempting auto-recovery + throw :racc_end_parse, nil + end + @racc_read_next = true + end + @racc_user_yyerror = false + @racc_error_status = 3 + while true + if i = action_pointer[@racc_state[-1]] + i += 1 # error token + if i >= 0 and + (act = action_table[i]) and + action_check[i] == @racc_state[-1] + break + end + end + throw :racc_end_parse, nil if @racc_state.size <= 1 + @racc_state.pop + @racc_vstack.pop + if @yydebug + @racc_tstack.pop + racc_e_pop @racc_state, @racc_tstack, @racc_vstack + end + end + return act + + else + raise "[Racc Bug] unknown action #{act.inspect}" + end + + racc_next_state(@racc_state[-1], @racc_state) if @yydebug + + nil + end + + def _racc_do_reduce(arg, act) + _, _, _, _, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, _, _, + _, use_result, * = arg + + state = @racc_state + vstack = @racc_vstack + tstack = @racc_tstack + + i = act * -3 + len = reduce_table[i] + reduce_to = reduce_table[i+1] + method_id = reduce_table[i+2] + void_array = [] + + tmp_t = tstack[-len, len] if @yydebug + tmp_v = vstack[-len, len] + tstack[-len, len] = void_array if @yydebug + vstack[-len, len] = void_array + state[-len, len] = void_array + + # tstack must be updated AFTER method call + if use_result + vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0]) + else + vstack.push __send__(method_id, tmp_v, vstack) + end + tstack.push reduce_to + + racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug + + k1 = reduce_to - nt_base + if i = goto_pointer[k1] + i += state[-1] + if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 + return curstate + end + end + goto_default[k1] + end + + # This method is called when a parse error is found. + # + # ERROR_TOKEN_ID is an internal ID of token which caused error. + # You can get string representation of this ID by calling + # #token_to_str. + # + # ERROR_VALUE is a value of error token. + # + # value_stack is a stack of symbol values. + # DO NOT MODIFY this object. + # + # This method raises ParseError by default. + # + # If this method returns, parsers enter "error recovering mode". + def on_error(t, val, vstack) + raise ParseError, sprintf("parse error on value %s (%s)", + val.inspect, token_to_str(t) || '?') + end + + # Enter error recovering mode. + # This method does not call #on_error. + def yyerror + throw :racc_jump, 1 + end + + # Exit parser. + # Return value is +Symbol_Value_Stack[0]+. + def yyaccept + throw :racc_jump, 2 + end + + # Leave error recovering mode. + def yyerrok + @racc_error_status = 0 + end + + # For debugging output + def racc_read_token(t, tok, val) + @racc_debug_out.print 'read ' + @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') ' + @racc_debug_out.puts val.inspect + @racc_debug_out.puts + end + + def racc_shift(tok, tstack, vstack) + @racc_debug_out.puts "shift #{racc_token2str tok}" + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_reduce(toks, sim, tstack, vstack) + out = @racc_debug_out + out.print 'reduce ' + if toks.empty? + out.print ' <none>' + else + toks.each {|t| out.print ' ', racc_token2str(t) } + end + out.puts " --> #{racc_token2str(sim)}" + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_accept + @racc_debug_out.puts 'accept' + @racc_debug_out.puts + end + + def racc_e_pop(state, tstack, vstack) + @racc_debug_out.puts 'error recovering mode: pop token' + racc_print_states state + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_next_state(curstate, state) + @racc_debug_out.puts "goto #{curstate}" + racc_print_states state + @racc_debug_out.puts + end + + def racc_print_stacks(t, v) + out = @racc_debug_out + out.print ' [' + t.each_index do |i| + out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')' + end + out.puts ' ]' + end + + def racc_print_states(s) + out = @racc_debug_out + out.print ' [' + s.each {|st| out.print ' ', st } + out.puts ' ]' + end + + def racc_token2str(tok) + self.class::Racc_token_to_s_table[tok] or + raise "[Racc Bug] can't convert token #{tok} to string" + end + + # Convert internal ID of token symbol to the string. + def token_to_str(t) + self.class::Racc_token_to_s_table[t] + end + + end + +end + +end +###### racc/parser.rb end require 'strscan' @@ -652,6 +1300,7 @@ Racc_arg = [ racc_shift_n, racc_reduce_n, racc_use_result_var ] +Ractor.make_shareable(Racc_arg) if defined?(Ractor) Racc_token_to_s_table = [ "$end", @@ -723,6 +1372,7 @@ Racc_token_to_s_table = [ "normal_strings", "verb_string", "verb_normal_string" ] +Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor) Racc_debug_parser = false diff --git a/lib/rdoc/rdoc.gemspec b/lib/rdoc/rdoc.gemspec index 525a15fcde..93a281c8ae 100644 --- a/lib/rdoc/rdoc.gemspec +++ b/lib/rdoc/rdoc.gemspec @@ -28,6 +28,10 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat s.homepage = "https://ruby.github.io/rdoc" s.licenses = ["Ruby"] + s.metadata["homepage_uri"] = s.homepage + s.metadata["source_code_uri"] = "https://github.com/ruby/rdoc" + s.metadata["changelog_uri"] = "#{s.metadata["source_code_uri"]}/releases" + s.bindir = "exe" s.executables = ["rdoc", "ri"] s.require_paths = ["lib"] @@ -38,16 +42,12 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat "CVE-2013-0256.rdoc", "ExampleMarkdown.md", "ExampleRDoc.rdoc", - "Gemfile", "History.rdoc", "LEGAL.rdoc", "LICENSE.rdoc", "README.rdoc", "RI.rdoc", - "Rakefile", "TODO.rdoc", - "bin/console", - "bin/setup", "exe/rdoc", "exe/ri", "lib/rdoc.rb", @@ -223,26 +223,14 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat "lib/rdoc/top_level.rb", "lib/rdoc/version.rb", "man/ri.1", - "rdoc.gemspec", ] # files from .gitignore s.files << "lib/rdoc/rd/block_parser.rb" << "lib/rdoc/rd/inline_parser.rb" << "lib/rdoc/markdown.rb" << "lib/rdoc/markdown/literals.rb" s.rdoc_options = ["--main", "README.rdoc"] - s.extra_rdoc_files += %w[ - CVE-2013-0256.rdoc - CONTRIBUTING.rdoc - ExampleMarkdown.md - ExampleRDoc.rdoc - History.rdoc - LEGAL.rdoc - LICENSE.rdoc - README.rdoc - RI.rdoc - TODO.rdoc - ] + s.extra_rdoc_files += s.files.grep(%r[\A[^\/]+\.(?:rdoc|md)\z]) - s.required_ruby_version = Gem::Requirement.new(">= 2.5.0") + s.required_ruby_version = Gem::Requirement.new(">= 2.6.0") s.required_rubygems_version = Gem::Requirement.new(">= 2.2") s.add_dependency 'psych', '>= 4.0.0' diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb index 400f9b5bc3..2da6d9b575 100644 --- a/lib/rdoc/rdoc.rb +++ b/lib/rdoc/rdoc.rb @@ -36,6 +36,17 @@ class RDoc::RDoc GENERATORS = {} ## + # List of directory names always skipped + + UNCONDITIONALLY_SKIPPED_DIRECTORIES = %w[CVS .svn .git].freeze + + ## + # List of directory names skipped if test suites should be skipped + + TEST_SUITE_DIRECTORY_NAMES = %w[spec test].freeze + + + ## # Generator instance used for creating output attr_accessor :generator @@ -108,7 +119,7 @@ class RDoc::RDoc # +files+. def gather_files files - files = ["."] if files.empty? + files = [@options.root.to_s] if files.empty? file_list = normalized_file_list files, true, @options.exclude @@ -280,7 +291,10 @@ option) file_list[rel_file_name] = mtime end when "directory" then - next if rel_file_name == "CVS" || rel_file_name == ".svn" + next if UNCONDITIONALLY_SKIPPED_DIRECTORIES.include?(rel_file_name) + + basename = File.basename(rel_file_name) + next if options.skip_tests && TEST_SUITE_DIRECTORY_NAMES.include?(basename) created_rid = File.join rel_file_name, "created.rid" next if File.file? created_rid @@ -415,9 +429,7 @@ The internal error was: files.reject do |file, *| file =~ /\.(?:class|eps|erb|scpt\.txt|svg|ttf|yml)$/i or (file =~ /tags$/i and - File.open(file, 'rb') { |io| - io.read(100) =~ /\A(\f\n[^,]+,\d+$|!_TAG_)/ - }) + /\A(\f\n[^,]+,\d+$|!_TAG_)/.match?(File.binread(file, 100))) end end diff --git a/lib/rdoc/require.rb b/lib/rdoc/require.rb index 91f9c24e5d..05e26b84b0 100644 --- a/lib/rdoc/require.rb +++ b/lib/rdoc/require.rb @@ -49,4 +49,3 @@ class RDoc::Require < RDoc::CodeObject end end - diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb index edd2a703e7..64783dc163 100644 --- a/lib/rdoc/ri/driver.rb +++ b/lib/rdoc/ri/driver.rb @@ -1,17 +1,6 @@ # frozen_string_literal: true -require 'abbrev' require 'optparse' -begin - require 'readline' -rescue LoadError -end - -begin - require 'win32console' -rescue LoadError -end - require_relative '../../rdoc' require_relative 'formatter' # For RubyGems backwards compatibility @@ -45,9 +34,9 @@ class RDoc::RI::Driver class NotFoundError < Error - def initialize(klass, suggestions = nil) # :nodoc: + def initialize(klass, suggestion_proc = nil) # :nodoc: @klass = klass - @suggestions = suggestions + @suggestion_proc = suggestion_proc end ## @@ -59,8 +48,9 @@ class RDoc::RI::Driver def message # :nodoc: str = "Nothing known about #{@klass}" - if @suggestions and !@suggestions.empty? - str += "\nDid you mean? #{@suggestions.join("\n ")}" + suggestions = @suggestion_proc&.call + if suggestions and !suggestions.empty? + str += "\nDid you mean? #{suggestions.join("\n ")}" end str end @@ -431,9 +421,6 @@ or the PAGER environment variable. @use_stdout = options[:use_stdout] @show_all = options[:show_all] @width = options[:width] - - # pager process for jruby - @jruby_pager_process = nil end ## @@ -962,8 +949,8 @@ or the PAGER environment variable. ary = class_names.grep(Regexp.new("\\A#{klass.gsub(/(?=::|\z)/, '[^:]*')}\\z")) if ary.length != 1 && ary.first != klass if check_did_you_mean - suggestions = DidYouMean::SpellChecker.new(dictionary: class_names).correct(klass) - raise NotFoundError.new(klass, suggestions) + suggestion_proc = -> { DidYouMean::SpellChecker.new(dictionary: class_names).correct(klass) } + raise NotFoundError.new(klass, suggestion_proc) else raise NotFoundError, klass end @@ -1050,36 +1037,6 @@ or the PAGER environment variable. end ## - # Finds the given +pager+ for jruby. Returns an IO if +pager+ was found. - # - # Returns false if +pager+ does not exist. - # - # Returns nil if the jruby JVM doesn't support ProcessBuilder redirection - # (1.6 and older). - - def find_pager_jruby pager - require 'java' - require 'shellwords' - - return nil unless java.lang.ProcessBuilder.constants.include? :Redirect - - pager = Shellwords.split pager - - pb = java.lang.ProcessBuilder.new(*pager) - pb = pb.redirect_output java.lang.ProcessBuilder::Redirect::INHERIT - - @jruby_pager_process = pb.start - - input = @jruby_pager_process.output_stream - - io = input.to_io - io.sync = true - io - rescue java.io.IOException - false - end - - ## # Finds a store that matches +name+ which can be the name of a gem, "ruby", # "home" or "site". # @@ -1118,6 +1075,10 @@ or the PAGER environment variable. def interactive puts "\nEnter the method name you want to look up." + begin + require 'readline' + rescue LoadError + end if defined? Readline then Readline.completion_proc = method :complete puts "You can use tab to autocomplete." @@ -1127,7 +1088,7 @@ or the PAGER environment variable. loop do name = if defined? Readline then - Readline.readline ">> " + Readline.readline ">> ", true else print ">> " $stdin.gets @@ -1147,17 +1108,6 @@ or the PAGER environment variable. end ## - # Is +file+ in ENV['PATH']? - - def in_path? file - return true if file =~ %r%\A/% and File.exist? file - - ENV['PATH'].split(File::PATH_SEPARATOR).any? do |path| - File.exist? File.join(path, file) - end - end - - ## # Lists classes known to ri starting with +names+. If +names+ is empty all # known classes are shown. @@ -1288,8 +1238,8 @@ or the PAGER environment variable. methods.push(*store.instance_methods[klass]) if [:instance, :both].include? types end methods = methods.uniq - suggestions = DidYouMean::SpellChecker.new(dictionary: methods).correct(method_name) - raise NotFoundError.new(name, suggestions) + suggestion_proc = -> { DidYouMean::SpellChecker.new(dictionary: methods).correct(method_name) } + raise NotFoundError.new(name, suggestion_proc) else raise NotFoundError, name end @@ -1351,7 +1301,6 @@ or the PAGER environment variable. yield pager ensure pager.close - @jruby_pager_process.wait_for if @jruby_pager_process end else yield $stdout @@ -1519,27 +1468,14 @@ or the PAGER environment variable. def setup_pager return if @use_stdout - jruby = RUBY_ENGINE == 'jruby' - pagers = [ENV['RI_PAGER'], ENV['PAGER'], 'pager', 'less', 'more'] + require 'shellwords' pagers.compact.uniq.each do |pager| - next unless pager - - pager_cmd = pager.split(' ').first - - next unless in_path? pager_cmd - - if jruby then - case io = find_pager_jruby(pager) - when nil then break - when false then next - else io - end - else - io = IO.popen(pager, 'w') rescue next - end + pager = Shellwords.split(pager) + next if pager.empty? + io = IO.popen(pager, 'w') rescue next next if $? and $?.pid == io.pid and $?.exited? # pager didn't work @paging = true diff --git a/lib/rdoc/ri/store.rb b/lib/rdoc/ri/store.rb index 9f4b03734a..96742e7ae3 100644 --- a/lib/rdoc/ri/store.rb +++ b/lib/rdoc/ri/store.rb @@ -4,4 +4,3 @@ module RDoc::RI Store = RDoc::Store # :nodoc: end - diff --git a/lib/rdoc/single_class.rb b/lib/rdoc/single_class.rb index 860f06a6e5..dd16529648 100644 --- a/lib/rdoc/single_class.rb +++ b/lib/rdoc/single_class.rb @@ -28,4 +28,3 @@ class RDoc::SingleClass < RDoc::ClassModule end end end - diff --git a/lib/rdoc/stats/quiet.rb b/lib/rdoc/stats/quiet.rb index bc4161b2d4..9c98ea5f86 100644 --- a/lib/rdoc/stats/quiet.rb +++ b/lib/rdoc/stats/quiet.rb @@ -57,4 +57,3 @@ class RDoc::Stats::Quiet def done_adding(*) end end - diff --git a/lib/rdoc/stats/verbose.rb b/lib/rdoc/stats/verbose.rb index 6ace8937a2..7090d561f8 100644 --- a/lib/rdoc/stats/verbose.rb +++ b/lib/rdoc/stats/verbose.rb @@ -42,5 +42,3 @@ class RDoc::Stats::Verbose < RDoc::Stats::Normal end end - - diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb index 9fc540d317..cd27d47dd1 100644 --- a/lib/rdoc/store.rb +++ b/lib/rdoc/store.rb @@ -197,6 +197,9 @@ class RDoc::Store top_level end + ## + # Sets the parser of +absolute_name+, unless it from a source code file. + def update_parser_of_file(absolute_name, parser) if top_level = @files_hash[absolute_name] then @text_files_hash[absolute_name] = top_level if top_level.text? @@ -556,9 +559,7 @@ class RDoc::Store def load_cache #orig_enc = @encoding - File.open cache_path, 'rb' do |io| - @cache = Marshal.load io - end + @cache = marshal_load(cache_path) load_enc = @cache[:encoding] @@ -615,9 +616,7 @@ class RDoc::Store def load_class_data klass_name file = class_file klass_name - File.open file, 'rb' do |io| - Marshal.load io - end + marshal_load(file) rescue Errno::ENOENT => e error = MissingFileError.new(self, file, klass_name) error.set_backtrace e.backtrace @@ -630,14 +629,10 @@ class RDoc::Store def load_method klass_name, method_name file = method_file klass_name, method_name - File.open file, 'rb' do |io| - obj = Marshal.load io - obj.store = self - obj.parent = - find_class_or_module(klass_name) || load_class(klass_name) unless - obj.parent - obj - end + obj = marshal_load(file) + obj.store = self + obj.parent ||= find_class_or_module(klass_name) || load_class(klass_name) + obj rescue Errno::ENOENT => e error = MissingFileError.new(self, file, klass_name + method_name) error.set_backtrace e.backtrace @@ -650,11 +645,9 @@ class RDoc::Store def load_page page_name file = page_file page_name - File.open file, 'rb' do |io| - obj = Marshal.load io - obj.store = self - obj - end + obj = marshal_load(file) + obj.store = self + obj rescue Errno::ENOENT => e error = MissingFileError.new(self, file, page_name) error.set_backtrace e.backtrace @@ -976,4 +969,21 @@ class RDoc::Store @unique_modules end + private + def marshal_load(file) + File.open(file, 'rb') {|io| Marshal.load(io, MarshalFilter)} + end + + MarshalFilter = proc do |obj| + case obj + when true, false, nil, Array, Class, Encoding, Hash, Integer, String, Symbol, RDoc::Text + else + unless obj.class.name.start_with?("RDoc::") + raise TypeError, "not permitted class: #{obj.class.name}" + end + end + obj + end + private_constant :MarshalFilter + end diff --git a/lib/rdoc/task.rb b/lib/rdoc/task.rb index 8ea2d0588c..eb584c9d2a 100644 --- a/lib/rdoc/task.rb +++ b/lib/rdoc/task.rb @@ -50,6 +50,9 @@ require 'rake/tasklib' # [rerdoc] # Rebuild the rdoc files from scratch, even if they are not out of date. # +# [rdoc:coverage] +# Print RDoc coverage report for all rdoc files. +# # Simple Example: # # require 'rdoc/task' @@ -90,8 +93,8 @@ require 'rake/tasklib' # RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean", # :rerdoc => "rdoc:force") # -# This will create the tasks <tt>:rdoc</tt>, <tt>:rdoc:clean</tt> and -# <tt>:rdoc:force</tt>. +# This will create the tasks <tt>:rdoc</tt>, <tt>:rdoc:clean</tt>, +# <tt>:rdoc:force</tt>, and <tt>:rdoc:coverage</tt>. class RDoc::Task < Rake::TaskLib @@ -248,6 +251,18 @@ class RDoc::Task < Rake::TaskLib RDoc::RDoc.new.document args end + namespace rdoc_task_name do + desc coverage_task_description + task coverage_task_name do + @before_running_rdoc.call if @before_running_rdoc + opts = option_list << "-C" + args = opts + @rdoc_files + + $stderr.puts "rdoc #{args.join ' '}" if Rake.application.options.trace + RDoc::RDoc.new.document args + end + end + self end @@ -288,6 +303,13 @@ class RDoc::Task < Rake::TaskLib "Rebuild RDoc HTML files" end + ## + # Task description for the coverage task or its renamed description + + def coverage_task_description + "Print RDoc coverage report" + end + private def rdoc_target @@ -315,6 +337,10 @@ class RDoc::Task < Rake::TaskLib end end + def coverage_task_name + "coverage" + end + end # :stopdoc: diff --git a/lib/rdoc/text.rb b/lib/rdoc/text.rb index 0bc4aba428..9804f81abe 100644 --- a/lib/rdoc/text.rb +++ b/lib/rdoc/text.rb @@ -10,6 +10,10 @@ require 'strscan' module RDoc::Text + ## + # The language for this text. This affects stripping comments + # markers. + attr_accessor :language ## @@ -309,4 +313,10 @@ module RDoc::Text res.join.strip end + ## + # Character class to be separated by a space when concatenating + # lines. + + SPACE_SEPARATED_LETTER_CLASS = /[\p{Nd}\p{Lc}\p{Pc}]|[!-~&&\W]/ + end diff --git a/lib/rdoc/token_stream.rb b/lib/rdoc/token_stream.rb index f428e2400c..19ca7ed248 100644 --- a/lib/rdoc/token_stream.rb +++ b/lib/rdoc/token_stream.rb @@ -112,8 +112,7 @@ module RDoc::TokenStream # Returns a string representation of the token stream def tokens_to_s - token_stream.compact.map { |token| token[:text] }.join '' + (token_stream or return '').compact.map { |token| token[:text] }.join '' end end - diff --git a/lib/rdoc/top_level.rb b/lib/rdoc/top_level.rb index b8b6110bb2..3864f66431 100644 --- a/lib/rdoc/top_level.rb +++ b/lib/rdoc/top_level.rb @@ -52,6 +52,9 @@ class RDoc::TopLevel < RDoc::Context @classes_or_modules = [] end + ## + # Sets the parser for this toplevel context, also the store. + def parser=(val) @parser = val @store.update_parser_of_file(absolute_name, val) if @store @@ -286,4 +289,3 @@ class RDoc::TopLevel < RDoc::Context end end - diff --git a/lib/rdoc/version.rb b/lib/rdoc/version.rb index 2c52a6b87b..87842d9847 100644 --- a/lib/rdoc/version.rb +++ b/lib/rdoc/version.rb @@ -5,6 +5,6 @@ module RDoc ## # RDoc version you are using - VERSION = '6.4.0' + VERSION = '6.6.3.1' end |