rdoc 4.0.0.preview2.1 → 4.0.0.rc.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rdoc might be problematic. Click here for more details.

Files changed (64) hide show
  1. checksums.yaml +6 -6
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CVE-2013-0256.rdoc +49 -0
  5. data/History.rdoc +33 -1
  6. data/Manifest.txt +3 -1
  7. data/Rakefile +2 -1
  8. data/lib/rdoc.rb +1 -1
  9. data/lib/rdoc/any_method.rb +2 -0
  10. data/lib/rdoc/attr.rb +2 -0
  11. data/lib/rdoc/class_module.rb +1 -0
  12. data/lib/rdoc/code_object.rb +7 -0
  13. data/lib/rdoc/cross_reference.rb +1 -1
  14. data/lib/rdoc/encoding.rb +3 -1
  15. data/lib/rdoc/generator/darkfish.rb +1 -1
  16. data/lib/rdoc/generator/template/darkfish/js/darkfish.js +9 -7
  17. data/lib/rdoc/generator/template/darkfish/rdoc.css +21 -0
  18. data/lib/rdoc/generator/template/json_index/.document +1 -0
  19. data/lib/rdoc/markup/attribute_manager.rb +5 -7
  20. data/lib/rdoc/markup/formatter.rb +75 -0
  21. data/lib/rdoc/markup/to_html.rb +9 -57
  22. data/lib/rdoc/markup/to_markdown.rb +55 -0
  23. data/lib/rdoc/parser.rb +35 -11
  24. data/lib/rdoc/parser/changelog.rb +9 -1
  25. data/lib/rdoc/parser/ruby.rb +23 -4
  26. data/lib/rdoc/rd/block_parser.rb +3 -2
  27. data/lib/rdoc/rd/block_parser.ry +3 -2
  28. data/lib/rdoc/rd/inline_parser.rb +1 -1
  29. data/lib/rdoc/rd/inline_parser.ry +1 -1
  30. data/lib/rdoc/ruby_lex.rb +20 -4
  31. data/lib/rdoc/ruby_token.rb +1 -0
  32. data/lib/rdoc/servlet.rb +25 -16
  33. data/lib/rdoc/store.rb +9 -4
  34. data/lib/rdoc/tom_doc.rb +1 -1
  35. data/lib/rdoc/top_level.rb +2 -1
  36. data/test/{test.ja.large.rdoc → test.ja.largedoc} +0 -0
  37. data/test/test_rdoc_any_method.rb +16 -7
  38. data/test/test_rdoc_attr.rb +4 -0
  39. data/test/test_rdoc_class_module.rb +2 -0
  40. data/test/test_rdoc_comment.rb +1 -1
  41. data/test/test_rdoc_constant.rb +4 -0
  42. data/test/test_rdoc_cross_reference.rb +15 -0
  43. data/test/test_rdoc_encoding.rb +1 -1
  44. data/test/test_rdoc_generator_markup.rb +4 -1
  45. data/test/test_rdoc_markup_formatter.rb +91 -0
  46. data/test/test_rdoc_markup_to_html.rb +52 -23
  47. data/test/test_rdoc_markup_to_markdown.rb +31 -0
  48. data/test/test_rdoc_options.rb +11 -0
  49. data/test/test_rdoc_parser.rb +50 -5
  50. data/test/test_rdoc_parser_c.rb +34 -11
  51. data/test/test_rdoc_parser_changelog.rb +32 -4
  52. data/test/test_rdoc_parser_markdown.rb +11 -5
  53. data/test/test_rdoc_parser_rd.rb +15 -5
  54. data/test/test_rdoc_parser_ruby.rb +23 -0
  55. data/test/test_rdoc_rd_block_parser.rb +141 -123
  56. data/test/test_rdoc_rd_inline_parser.rb +6 -1
  57. data/test/test_rdoc_rdoc.rb +5 -2
  58. data/test/test_rdoc_ruby_lex.rb +51 -5
  59. data/test/test_rdoc_servlet.rb +43 -5
  60. data/test/test_rdoc_store.rb +55 -4
  61. data/test/test_rdoc_tom_doc.rb +37 -0
  62. data/test/test_rdoc_top_level.rb +17 -1
  63. metadata +29 -34
  64. metadata.gz.sig +0 -0
@@ -18,6 +18,9 @@ class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc
18
18
  @headings[5] = ['##### ', '']
19
19
  @headings[6] = ['###### ', '']
20
20
 
21
+ add_special_RDOCLINK
22
+ add_special_TIDYLINK
23
+
21
24
  @hard_break = " \n"
22
25
  end
23
26
 
@@ -130,5 +133,57 @@ class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc
130
133
  @res << "\n" unless @res =~ /\n\z/
131
134
  end
132
135
 
136
+ ##
137
+ # Creates a Markdown-style URL from +url+ with +text+.
138
+
139
+ def gen_url url, text
140
+ scheme, url, = parse_url url
141
+
142
+ "[#{text.sub(%r{^#{scheme}:/*}i, '')}](#{url})"
143
+ end
144
+
145
+ ##
146
+ # Handles <tt>rdoc-</tt> type links for footnotes.
147
+
148
+ def handle_rdoc_link url
149
+ case url
150
+ when /\Ardoc-ref:/ then
151
+ $'
152
+ when /\Ardoc-label:footmark-(\d+)/ then
153
+ "[^#{$1}]:"
154
+ when /\Ardoc-label:foottext-(\d+)/ then
155
+ "[^#{$1}]"
156
+ when /\Ardoc-label:label-/ then
157
+ gen_url url, $'
158
+ when /\Ardoc-[a-z]+:/ then
159
+ $'
160
+ end
161
+ end
162
+
163
+ ##
164
+ # Converts the RDoc markup tidylink into a Markdown.style link.
165
+
166
+ def handle_special_TIDYLINK special
167
+ text = special.text
168
+
169
+ return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
170
+
171
+ label = $1
172
+ url = $2
173
+
174
+ if url =~ /^rdoc-label:foot/ then
175
+ handle_rdoc_link url
176
+ else
177
+ gen_url url, label
178
+ end
179
+ end
180
+
181
+ ##
182
+ # Converts the rdoc-...: links into a Markdown.style links.
183
+
184
+ def handle_special_RDOCLINK special
185
+ handle_rdoc_link special.text
186
+ end
187
+
133
188
  end
134
189
 
data/lib/rdoc/parser.rb CHANGED
@@ -45,6 +45,11 @@ class RDoc::Parser
45
45
 
46
46
  end
47
47
 
48
+ ##
49
+ # The name of the file being parsed
50
+
51
+ attr_reader :file_name
52
+
48
53
  ##
49
54
  # Alias an extension to another extension. After this call, files ending
50
55
  # "new_ext" will be parsed using the same parser as "old_ext"
@@ -53,7 +58,7 @@ class RDoc::Parser
53
58
  old_ext = old_ext.sub(/^\.(.*)/, '\1')
54
59
  new_ext = new_ext.sub(/^\.(.*)/, '\1')
55
60
 
56
- parser = can_parse "xxx.#{old_ext}"
61
+ parser = can_parse_by_name "xxx.#{old_ext}"
57
62
  return false unless parser
58
63
 
59
64
  RDoc::Parser.parsers.unshift [/\.#{new_ext}$/, parser]
@@ -72,14 +77,14 @@ class RDoc::Parser
72
77
 
73
78
  have_encoding = s.respond_to? :encoding
74
79
 
75
- if have_encoding then
76
- return false if s.encoding != Encoding::ASCII_8BIT and s.valid_encoding?
77
- end
78
-
79
80
  return true if s[0, 2] == Marshal.dump('')[0, 2] or s.index("\x00")
80
81
 
81
82
  if have_encoding then
82
- s.force_encoding Encoding.default_external
83
+ mode = "r"
84
+ s.sub!(/\A#!.*\n/, '') # assume shebang line isn't longer than 1024.
85
+ encoding = s[/^\s*\#\s*(?:-\*-\s*)?(?:en)?coding:\s*([^\s;]+?)(?:-\*-|[\s;])/, 1]
86
+ mode = "r:#{encoding}" if encoding
87
+ s = File.open(file, mode) {|f| f.gets(nil, 1024)}
83
88
 
84
89
  not s.valid_encoding?
85
90
  else
@@ -126,23 +131,36 @@ class RDoc::Parser
126
131
  zip_signature == "PK\x03\x04" or
127
132
  zip_signature == "PK\x05\x06" or
128
133
  zip_signature == "PK\x07\x08"
134
+ rescue
135
+ false
129
136
  end
130
137
 
131
138
  ##
132
139
  # Return a parser that can handle a particular extension
133
140
 
134
- def self.can_parse(file_name)
135
- parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }.last
141
+ def self.can_parse file_name
142
+ parser = can_parse_by_name file_name
136
143
 
137
144
  # HACK Selenium hides a jar file using a .txt extension
138
145
  return if parser == RDoc::Parser::Simple and zip? file_name
139
146
 
147
+ parser
148
+ end
149
+
150
+ ##
151
+ # Returns a parser that can handle the extension for +file_name+. This does
152
+ # not depend upon the file being readable.
153
+
154
+ def self.can_parse_by_name file_name
155
+ _, parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }
156
+
140
157
  # The default parser must not parse binary files
141
158
  ext_name = File.extname file_name
142
159
  return parser if ext_name.empty?
160
+
143
161
  if parser == RDoc::Parser::Simple and ext_name !~ /txt|rdoc/ then
144
162
  case check_modeline file_name
145
- when 'rdoc' then # continue
163
+ when nil, 'rdoc' then # continue
146
164
  else return nil
147
165
  end
148
166
  end
@@ -168,6 +186,8 @@ class RDoc::Parser
168
186
  type = $1
169
187
  end
170
188
 
189
+ return nil if /coding:/i =~ type
190
+
171
191
  type.downcase
172
192
  rescue ArgumentError # invalid byte sequence, etc.
173
193
  end
@@ -182,21 +202,25 @@ class RDoc::Parser
182
202
  parser = use_markup content
183
203
 
184
204
  unless parser then
205
+ parse_name = file_name
206
+
185
207
  # If no extension, look for shebang
186
208
  if file_name !~ /\.\w+$/ && content =~ %r{\A#!(.+)} then
187
209
  shebang = $1
188
210
  case shebang
189
211
  when %r{env\s+ruby}, %r{/ruby}
190
- file_name = "dummy.rb"
212
+ parse_name = 'dummy.rb'
191
213
  end
192
214
  end
193
215
 
194
- parser = can_parse file_name
216
+ parser = can_parse parse_name
195
217
  end
196
218
 
197
219
  return unless parser
198
220
 
199
221
  parser.new top_level, file_name, content, options, stats
222
+ rescue SystemCallError
223
+ nil
200
224
  end
201
225
 
202
226
  ##
@@ -102,7 +102,12 @@ class RDoc::Parser::ChangeLog < RDoc::Parser
102
102
 
103
103
  def group_entries entries
104
104
  entries.group_by do |title, _|
105
- Time.parse(title).strftime "%Y-%m-%d"
105
+ begin
106
+ Time.parse(title).strftime '%Y-%m-%d'
107
+ rescue NoMethodError, ArgumentError
108
+ time, = title.split ' ', 2
109
+ Time.parse(time).strftime '%Y-%m-%d'
110
+ end
106
111
  end
107
112
  end
108
113
 
@@ -139,6 +144,9 @@ class RDoc::Parser::ChangeLog < RDoc::Parser
139
144
  time = Time.parse entry_name
140
145
  # HACK Ruby 1.8 does not raise ArgumentError for Time.parse "Other"
141
146
  entry_name = nil unless entry_name =~ /#{time.year}/
147
+ rescue NoMethodError
148
+ time, = entry_name.split ' ', 2
149
+ time = Time.parse time
142
150
  rescue ArgumentError
143
151
  entry_name = nil
144
152
  end
@@ -1116,6 +1116,18 @@ class RDoc::Parser::Ruby < RDoc::Parser
1116
1116
  name = name_t2.name
1117
1117
  prev_container = container
1118
1118
  container = container.find_module_named(name_t.name)
1119
+
1120
+ unless container then
1121
+ constant = prev_container.constants.find do |const|
1122
+ const.name == name_t.name
1123
+ end
1124
+
1125
+ if constant then
1126
+ parse_method_dummy prev_container
1127
+ return
1128
+ end
1129
+ end
1130
+
1119
1131
  unless container then
1120
1132
  added_container = true
1121
1133
  obj = name_t.name.split("::").inject(Object) do |state, item|
@@ -1138,10 +1150,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
1138
1150
  container.record_location @top_level
1139
1151
  end
1140
1152
  when TkIDENTIFIER, TkIVAR, TkGVAR then
1141
- dummy = RDoc::Context.new
1142
- dummy.parent = container
1143
- dummy.store = container.store
1144
- skip_method dummy
1153
+ parse_method_dummy container
1145
1154
  return
1146
1155
  when TkTRUE, TkFALSE, TkNIL then
1147
1156
  klass_name = "#{name_t.name.capitalize}Class"
@@ -1228,6 +1237,16 @@ class RDoc::Parser::Ruby < RDoc::Parser
1228
1237
  @stats.add_method meth
1229
1238
  end
1230
1239
 
1240
+ ##
1241
+ # Parses a method that needs to be ignored.
1242
+
1243
+ def parse_method_dummy container
1244
+ dummy = RDoc::Context.new
1245
+ dummy.parent = container
1246
+ dummy.store = container.store
1247
+ skip_method dummy
1248
+ end
1249
+
1231
1250
  ##
1232
1251
  # Extracts +yield+ parameters from +method+
1233
1252
 
@@ -394,11 +394,12 @@ end
394
394
  # Adds footnote +content+ to the document
395
395
 
396
396
  def add_footnote content
397
- index = @footnotes.length + 1
397
+ index = @footnotes.length / 2 + 1
398
398
 
399
399
  footmark_link = "{^#{index}}[rdoc-label:footmark-#{index}:foottext-#{index}]"
400
400
 
401
- @footnotes << RDoc::Markup::Paragraph.new(footmark_link, *content)
401
+ @footnotes << RDoc::Markup::Paragraph.new(footmark_link, ' ', *content)
402
+ @footnotes << RDoc::Markup::BlankLine.new
402
403
 
403
404
  index
404
405
  end
@@ -607,11 +607,12 @@ end
607
607
  # Adds footnote +content+ to the document
608
608
 
609
609
  def add_footnote content
610
- index = @footnotes.length + 1
610
+ index = @footnotes.length / 2 + 1
611
611
 
612
612
  footmark_link = "{^#{index}}[rdoc-label:footmark-#{index}:foottext-#{index}]"
613
613
 
614
- @footnotes << RDoc::Markup::Paragraph.new(footmark_link, *content)
614
+ @footnotes << RDoc::Markup::Paragraph.new(footmark_link, ' ', *content)
615
+ @footnotes << RDoc::Markup::BlankLine.new
615
616
 
616
617
  index
617
618
  end
@@ -1104,7 +1104,7 @@ def _reduce_101(val, _values, result)
1104
1104
  end
1105
1105
 
1106
1106
  def _reduce_102(val, _values, result)
1107
- result = "<tt>#{val[1]}</tt>"
1107
+ result = inline "<tt>#{val[1]}</tt>", val[1]
1108
1108
 
1109
1109
  result
1110
1110
  end
@@ -293,7 +293,7 @@ class InlineParser
293
293
  ;
294
294
 
295
295
  verb : VERB_OPEN verb_strings VERB_CLOSE {
296
- result = "<tt>#{val[1]}</tt>"
296
+ result = inline "<tt>#{val[1]}</tt>", val[1]
297
297
  }
298
298
  ;
299
299
 
data/lib/rdoc/ruby_lex.rb CHANGED
@@ -982,12 +982,13 @@ class RDoc::RubyLex
982
982
  indent = true
983
983
  end
984
984
  if /['"`]/ =~ ch
985
- lt = ch
985
+ user_quote = lt = ch
986
986
  quoted = ""
987
987
  while (c = getc) && c != lt
988
988
  quoted.concat c
989
989
  end
990
990
  else
991
+ user_quote = nil
991
992
  lt = '"'
992
993
  quoted = ch.dup
993
994
  while (c = getc) && c =~ /\w/
@@ -1007,8 +1008,17 @@ class RDoc::RubyLex
1007
1008
  end
1008
1009
  end
1009
1010
 
1011
+ output_heredoc = reserve.join =~ /\A\r?\n\z/
1012
+
1013
+ if output_heredoc then
1014
+ doc = '<<'
1015
+ doc << '-' if indent
1016
+ doc << "#{user_quote}#{quoted}#{user_quote}\n"
1017
+ else
1018
+ doc = '"'
1019
+ end
1020
+
1010
1021
  @here_header = false
1011
- doc = '"'
1012
1022
  while l = gets
1013
1023
  l = l.sub(/(:?\r)?\n\z/, "\n")
1014
1024
  if (indent ? l.strip : l.chomp) == quoted
@@ -1016,7 +1026,12 @@ class RDoc::RubyLex
1016
1026
  end
1017
1027
  doc << l
1018
1028
  end
1019
- doc << '"'
1029
+
1030
+ if output_heredoc then
1031
+ doc << l.chomp
1032
+ else
1033
+ doc << '"'
1034
+ end
1020
1035
 
1021
1036
  @here_header = true
1022
1037
  @here_readed.concat reserve
@@ -1024,9 +1039,10 @@ class RDoc::RubyLex
1024
1039
  ungetc ch
1025
1040
  end
1026
1041
 
1042
+ token_class = output_heredoc ? RDoc::RubyLex::TkHEREDOC : Ltype2Token[lt]
1027
1043
  @ltype = ltback
1028
1044
  @lex_state = EXPR_END
1029
- Token(Ltype2Token[lt], doc)
1045
+ Token(token_class, doc)
1030
1046
  end
1031
1047
 
1032
1048
  def identify_quotation
@@ -331,6 +331,7 @@ module RDoc::RubyToken
331
331
  [:TkINTEGER, TkVal],
332
332
  [:TkFLOAT, TkVal],
333
333
  [:TkSTRING, TkVal],
334
+ [:TkHEREDOC, TkVal],
334
335
  [:TkXSTRING, TkVal],
335
336
  [:TkREGEXP, TkVal],
336
337
  [:TkSYMBOL, TkVal],
data/lib/rdoc/servlet.rb CHANGED
@@ -326,21 +326,25 @@ version. If you're viewing Ruby's documentation, include the version of ruby.
326
326
 
327
327
  search_index << name
328
328
 
329
- comment = case type
330
- when :gem
331
- gemspec = path.gsub(%r%/doc/([^/]*?)/ri$%,
332
- '/specifications/\1.gemspec')
333
-
334
- spec = Gem::Specification.load gemspec
335
-
336
- spec.summary
337
- when :system then
338
- 'Documentation for the Ruby standard library'
339
- when :site then
340
- 'Documentation for non-gem libraries'
341
- when :home then
342
- 'Documentation from your home directory'
343
- end
329
+ case type
330
+ when :gem
331
+ gemspec = path.gsub(%r%/doc/([^/]*?)/ri$%,
332
+ '/specifications/\1.gemspec')
333
+
334
+ spec = Gem::Specification.load gemspec
335
+
336
+ path = spec.full_name
337
+ comment = spec.summary
338
+ when :system then
339
+ path = 'ruby'
340
+ comment = 'Documentation for the Ruby standard library'
341
+ when :site then
342
+ path = 'site'
343
+ comment = 'Documentation for non-gem libraries'
344
+ when :home then
345
+ path = 'home'
346
+ comment = 'Documentation from your home directory'
347
+ end
344
348
 
345
349
  info << [name, '', path, '', comment]
346
350
  end
@@ -387,8 +391,12 @@ version. If you're viewing Ruby's documentation, include the version of ruby.
387
391
 
388
392
  def store_for source_name
389
393
  case source_name
394
+ when 'home' then
395
+ RDoc::Store.new RDoc::RI::Paths.home_dir, :home
390
396
  when 'ruby' then
391
397
  RDoc::Store.new RDoc::RI::Paths.system_dir, :system
398
+ when 'site' then
399
+ RDoc::Store.new RDoc::RI::Paths.site_dir, :site
392
400
  else
393
401
  ri_dir, type = ri_paths.find do |dir, dir_type|
394
402
  next unless dir_type == :gem
@@ -396,7 +404,8 @@ version. If you're viewing Ruby's documentation, include the version of ruby.
396
404
  source_name == dir[%r%/([^/]*)/ri$%, 1]
397
405
  end
398
406
 
399
- raise "could not find ri documentation for #{source_name}" unless
407
+ raise RDoc::Error,
408
+ "could not find ri documentation for #{source_name}" unless
400
409
  ri_dir
401
410
 
402
411
  RDoc::Store.new ri_dir, type
data/lib/rdoc/store.rb CHANGED
@@ -354,6 +354,9 @@ class RDoc::Store
354
354
  loaded_mod = load_class_data name
355
355
 
356
356
  file = loaded_mod.in_files.first
357
+
358
+ return unless file # legacy data source
359
+
357
360
  file.store = self
358
361
 
359
362
  mod = file.add_module RDoc::NormalModule, name
@@ -816,13 +819,13 @@ class RDoc::Store
816
819
  @cache[:ancestors][full_name] ||= []
817
820
  @cache[:ancestors][full_name].concat ancestors
818
821
 
819
- attributes = klass.attributes.map do |attribute|
822
+ attribute_definitions = klass.attributes.map do |attribute|
820
823
  "#{attribute.definition} #{attribute.name}"
821
824
  end
822
825
 
823
- unless attributes.empty? then
826
+ unless attribute_definitions.empty? then
824
827
  @cache[:attributes][full_name] ||= []
825
- @cache[:attributes][full_name].concat attributes
828
+ @cache[:attributes][full_name].concat attribute_definitions
826
829
  end
827
830
 
828
831
  to_delete = []
@@ -836,13 +839,15 @@ class RDoc::Store
836
839
 
837
840
  class_methods = class_methods. map { |method| method.name }
838
841
  instance_methods = instance_methods.map { |method| method.name }
842
+ attribute_names = klass.attributes.map { |attr| attr.name }
839
843
 
840
844
  old = @cache[:class_methods][full_name] - class_methods
841
845
  to_delete.concat old.map { |method|
842
846
  method_file full_name, "#{full_name}::#{method}"
843
847
  }
844
848
 
845
- old = @cache[:instance_methods][full_name] - instance_methods
849
+ old = @cache[:instance_methods][full_name] -
850
+ instance_methods - attribute_names
846
851
  to_delete.concat old.map { |method|
847
852
  method_file full_name, "#{full_name}##{method}"
848
853
  }