rdoc 2.0.0
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.
- data/History.txt +13 -0
- data/Manifest.txt +61 -0
- data/README.txt +34 -0
- data/Rakefile +10 -0
- data/bin/rdoc +22 -0
- data/bin/ri +6 -0
- data/lib/rdoc.rb +277 -0
- data/lib/rdoc/code_objects.rb +776 -0
- data/lib/rdoc/diagram.rb +338 -0
- data/lib/rdoc/dot.rb +249 -0
- data/lib/rdoc/generator.rb +1048 -0
- data/lib/rdoc/generator/chm.rb +113 -0
- data/lib/rdoc/generator/chm/chm.rb +98 -0
- data/lib/rdoc/generator/html.rb +370 -0
- data/lib/rdoc/generator/html/hefss.rb +414 -0
- data/lib/rdoc/generator/html/html.rb +704 -0
- data/lib/rdoc/generator/html/kilmer.rb +418 -0
- data/lib/rdoc/generator/html/one_page_html.rb +121 -0
- data/lib/rdoc/generator/ri.rb +229 -0
- data/lib/rdoc/generator/xml.rb +120 -0
- data/lib/rdoc/generator/xml/rdf.rb +113 -0
- data/lib/rdoc/generator/xml/xml.rb +111 -0
- data/lib/rdoc/markup.rb +473 -0
- data/lib/rdoc/markup/attribute_manager.rb +274 -0
- data/lib/rdoc/markup/formatter.rb +14 -0
- data/lib/rdoc/markup/fragments.rb +337 -0
- data/lib/rdoc/markup/inline.rb +101 -0
- data/lib/rdoc/markup/lines.rb +152 -0
- data/lib/rdoc/markup/preprocess.rb +71 -0
- data/lib/rdoc/markup/to_flow.rb +185 -0
- data/lib/rdoc/markup/to_html.rb +353 -0
- data/lib/rdoc/markup/to_html_crossref.rb +86 -0
- data/lib/rdoc/markup/to_latex.rb +328 -0
- data/lib/rdoc/markup/to_test.rb +50 -0
- data/lib/rdoc/options.rb +616 -0
- data/lib/rdoc/parsers/parse_c.rb +775 -0
- data/lib/rdoc/parsers/parse_f95.rb +1841 -0
- data/lib/rdoc/parsers/parse_rb.rb +2584 -0
- data/lib/rdoc/parsers/parse_simple.rb +40 -0
- data/lib/rdoc/parsers/parserfactory.rb +99 -0
- data/lib/rdoc/rdoc.rb +277 -0
- data/lib/rdoc/ri.rb +4 -0
- data/lib/rdoc/ri/cache.rb +188 -0
- data/lib/rdoc/ri/descriptions.rb +150 -0
- data/lib/rdoc/ri/display.rb +274 -0
- data/lib/rdoc/ri/driver.rb +452 -0
- data/lib/rdoc/ri/formatter.rb +616 -0
- data/lib/rdoc/ri/paths.rb +102 -0
- data/lib/rdoc/ri/reader.rb +106 -0
- data/lib/rdoc/ri/util.rb +81 -0
- data/lib/rdoc/ri/writer.rb +68 -0
- data/lib/rdoc/stats.rb +25 -0
- data/lib/rdoc/template.rb +64 -0
- data/lib/rdoc/tokenstream.rb +33 -0
- data/test/test_rdoc_c_parser.rb +261 -0
- data/test/test_rdoc_markup.rb +613 -0
- data/test/test_rdoc_markup_attribute_manager.rb +224 -0
- data/test/test_rdoc_ri_attribute_formatter.rb +42 -0
- data/test/test_rdoc_ri_default_display.rb +295 -0
- data/test/test_rdoc_ri_formatter.rb +318 -0
- data/test/test_rdoc_ri_overstrike_formatter.rb +69 -0
- metadata +134 -0
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'rdoc/ri'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Encapsulate all the strangeness to do with finding out where to find RDoc
|
5
|
+
# files
|
6
|
+
#
|
7
|
+
# We basically deal with three directories:
|
8
|
+
#
|
9
|
+
# 1. The 'system' documentation directory, which holds the documentation
|
10
|
+
# distributed with Ruby, and which is managed by the Ruby install process
|
11
|
+
# 2. The 'site' directory, which contains site-wide documentation added
|
12
|
+
# locally.
|
13
|
+
# 3. The 'user' documentation directory, stored under the user's own home
|
14
|
+
# directory.
|
15
|
+
#
|
16
|
+
# There's contention about all this, but for now:
|
17
|
+
#
|
18
|
+
# system:: $datadir/ri/<ver>/system/...
|
19
|
+
# site:: $datadir/ri/<ver>/site/...
|
20
|
+
# user:: ~/.rdoc
|
21
|
+
|
22
|
+
module RDoc::RI::Paths
|
23
|
+
|
24
|
+
#:stopdoc:
|
25
|
+
require 'rbconfig'
|
26
|
+
|
27
|
+
DOC_DIR = "doc/rdoc"
|
28
|
+
|
29
|
+
version = RbConfig::CONFIG['ruby_version']
|
30
|
+
|
31
|
+
base = File.join(RbConfig::CONFIG['datadir'], "ri", version)
|
32
|
+
SYSDIR = File.join(base, "system")
|
33
|
+
SITEDIR = File.join(base, "site")
|
34
|
+
homedir = ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH']
|
35
|
+
|
36
|
+
if homedir then
|
37
|
+
HOMEDIR = File.join(homedir, ".rdoc")
|
38
|
+
else
|
39
|
+
HOMEDIR = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# This is the search path for 'ri'
|
43
|
+
PATH = [ SYSDIR, SITEDIR, HOMEDIR ].find_all {|p| p && File.directory?(p)}
|
44
|
+
|
45
|
+
begin
|
46
|
+
require 'rubygems' unless defined?(Gem) and defined?(Gem::Enable) and
|
47
|
+
Gem::Enable
|
48
|
+
|
49
|
+
# HACK dup'd from Gem.latest_partials and friends
|
50
|
+
all_paths = []
|
51
|
+
|
52
|
+
all_paths = Gem.path.map do |dir|
|
53
|
+
Dir[File.join(dir, 'doc', '*', 'ri')]
|
54
|
+
end.flatten
|
55
|
+
|
56
|
+
ri_paths = {}
|
57
|
+
|
58
|
+
all_paths.each do |dir|
|
59
|
+
base = File.basename File.dirname(dir)
|
60
|
+
if base =~ /(.*)-((\d+\.)*\d+)/ then
|
61
|
+
name, version = $1, $2
|
62
|
+
ver = Gem::Version.new version
|
63
|
+
if ri_paths[name].nil? or ver > ri_paths[name][0] then
|
64
|
+
ri_paths[name] = [ver, dir]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
GEMDIRS = ri_paths.map { |k,v| v.last }.sort
|
70
|
+
GEMDIRS.each { |dir| PATH << dir }
|
71
|
+
rescue LoadError
|
72
|
+
GEMDIRS = []
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the selected documentation directories as an Array, or PATH if no
|
76
|
+
# overriding directories were given.
|
77
|
+
|
78
|
+
def self.path(use_system, use_site, use_home, use_gems, *extra_dirs)
|
79
|
+
path = raw_path(use_system, use_site, use_home, use_gems, *extra_dirs)
|
80
|
+
return path.select { |directory| File.directory? directory }
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the selected documentation directories including nonexistent
|
84
|
+
# directories. Used to print out what paths were searched if no ri was
|
85
|
+
# found.
|
86
|
+
|
87
|
+
def self.raw_path(use_system, use_site, use_home, use_gems, *extra_dirs)
|
88
|
+
return PATH unless use_system or use_site or use_home or use_gems or
|
89
|
+
not extra_dirs.empty?
|
90
|
+
|
91
|
+
path = []
|
92
|
+
path << extra_dirs unless extra_dirs.empty?
|
93
|
+
path << SYSDIR if use_system
|
94
|
+
path << SITEDIR if use_site
|
95
|
+
path << HOMEDIR if use_home
|
96
|
+
path << GEMDIRS if use_gems
|
97
|
+
|
98
|
+
return path.flatten.compact
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'rdoc/ri'
|
2
|
+
require 'rdoc/ri/descriptions'
|
3
|
+
require 'rdoc/ri/writer'
|
4
|
+
require 'rdoc/markup/to_flow'
|
5
|
+
|
6
|
+
class RDoc::RI::Reader
|
7
|
+
|
8
|
+
def initialize(ri_cache)
|
9
|
+
@cache = ri_cache
|
10
|
+
end
|
11
|
+
|
12
|
+
def top_level_namespace
|
13
|
+
[ @cache.toplevel ]
|
14
|
+
end
|
15
|
+
|
16
|
+
def lookup_namespace_in(target, namespaces)
|
17
|
+
result = []
|
18
|
+
for n in namespaces
|
19
|
+
result.concat(n.contained_modules_matching(target))
|
20
|
+
end
|
21
|
+
result
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_class_by_name(full_name)
|
25
|
+
names = full_name.split(/::/)
|
26
|
+
ns = @cache.toplevel
|
27
|
+
for name in names
|
28
|
+
ns = ns.contained_class_named(name)
|
29
|
+
return nil if ns.nil?
|
30
|
+
end
|
31
|
+
get_class(ns)
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_methods(name, is_class_method, namespaces)
|
35
|
+
result = []
|
36
|
+
namespaces.each do |ns|
|
37
|
+
result.concat ns.methods_matching(name, is_class_method)
|
38
|
+
end
|
39
|
+
result
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Return the MethodDescription for a given MethodEntry by deserializing the
|
44
|
+
# YAML
|
45
|
+
|
46
|
+
def get_method(method_entry)
|
47
|
+
path = method_entry.path_name
|
48
|
+
File.open(path) { |f| RI::Description.deserialize(f) }
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Return a class description
|
53
|
+
|
54
|
+
def get_class(class_entry)
|
55
|
+
result = nil
|
56
|
+
for path in class_entry.path_names
|
57
|
+
path = RiWriter.class_desc_path(path, class_entry)
|
58
|
+
desc = File.open(path) {|f| RI::Description.deserialize(f) }
|
59
|
+
if result
|
60
|
+
result.merge_in(desc)
|
61
|
+
else
|
62
|
+
result = desc
|
63
|
+
end
|
64
|
+
end
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Return the names of all classes and modules
|
70
|
+
|
71
|
+
def full_class_names
|
72
|
+
res = []
|
73
|
+
find_classes_in(res, @cache.toplevel)
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Return a list of all classes, modules, and methods
|
78
|
+
|
79
|
+
def all_names
|
80
|
+
res = []
|
81
|
+
find_names_in(res, @cache.toplevel)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def find_classes_in(res, klass)
|
87
|
+
classes = klass.classes_and_modules
|
88
|
+
for c in classes
|
89
|
+
res << c.full_name
|
90
|
+
find_classes_in(res, c)
|
91
|
+
end
|
92
|
+
res
|
93
|
+
end
|
94
|
+
|
95
|
+
def find_names_in(res, klass)
|
96
|
+
classes = klass.classes_and_modules
|
97
|
+
for c in classes
|
98
|
+
res << c.full_name
|
99
|
+
res.concat c.all_method_names
|
100
|
+
find_names_in(res, c)
|
101
|
+
end
|
102
|
+
res
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
data/lib/rdoc/ri/util.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'rdoc/ri'
|
2
|
+
|
3
|
+
class RDoc::RI::Error < RuntimeError; end
|
4
|
+
|
5
|
+
##
|
6
|
+
# Break argument into its constituent class or module names, an
|
7
|
+
# optional method type, and a method name
|
8
|
+
|
9
|
+
class RDoc::RI::NameDescriptor
|
10
|
+
|
11
|
+
attr_reader :class_names
|
12
|
+
attr_reader :method_name
|
13
|
+
|
14
|
+
##
|
15
|
+
# true and false have the obvious meaning. nil means we don't care
|
16
|
+
|
17
|
+
attr_reader :is_class_method
|
18
|
+
|
19
|
+
##
|
20
|
+
# +arg+ may be
|
21
|
+
#
|
22
|
+
# 1. A class or module name (optionally qualified with other class or module
|
23
|
+
# names (Kernel, File::Stat etc)
|
24
|
+
# 2. A method name
|
25
|
+
# 3. A method name qualified by a optionally fully qualified class or module
|
26
|
+
# name
|
27
|
+
#
|
28
|
+
# We're fairly casual about delimiters: folks can say Kernel::puts,
|
29
|
+
# Kernel.puts, or Kernel\#puts for example. There's one exception: if you
|
30
|
+
# say IO::read, we look for a class method, but if you say IO.read, we look
|
31
|
+
# for an instance method
|
32
|
+
|
33
|
+
def initialize(arg)
|
34
|
+
@class_names = []
|
35
|
+
separator = nil
|
36
|
+
|
37
|
+
tokens = arg.split(/(\.|::|#)/)
|
38
|
+
|
39
|
+
# Skip leading '::', '#' or '.', but remember it might
|
40
|
+
# be a method name qualifier
|
41
|
+
separator = tokens.shift if tokens[0] =~ /^(\.|::|#)/
|
42
|
+
|
43
|
+
# Skip leading '::', but remember we potentially have an inst
|
44
|
+
|
45
|
+
# leading stuff must be class names
|
46
|
+
|
47
|
+
while tokens[0] =~ /^[A-Z]/
|
48
|
+
@class_names << tokens.shift
|
49
|
+
unless tokens.empty?
|
50
|
+
separator = tokens.shift
|
51
|
+
break unless separator == "::"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Now must have a single token, the method name, or an empty array
|
56
|
+
unless tokens.empty?
|
57
|
+
@method_name = tokens.shift
|
58
|
+
# We may now have a trailing !, ?, or = to roll into
|
59
|
+
# the method name
|
60
|
+
if !tokens.empty? && tokens[0] =~ /^[!?=]$/
|
61
|
+
@method_name << tokens.shift
|
62
|
+
end
|
63
|
+
|
64
|
+
if @method_name =~ /::|\.|#/ or !tokens.empty?
|
65
|
+
raise RDoc::RI::Error.new("Bad argument: #{arg}")
|
66
|
+
end
|
67
|
+
if separator && separator != '.'
|
68
|
+
@is_class_method = separator == "::"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Return the full class name (with '::' between the components) or "" if
|
74
|
+
# there's no class name
|
75
|
+
|
76
|
+
def full_class_name
|
77
|
+
@class_names.join("::")
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'rdoc/ri'
|
3
|
+
|
4
|
+
class RDoc::RI::Writer
|
5
|
+
|
6
|
+
def self.class_desc_path(dir, class_desc)
|
7
|
+
File.join(dir, "cdesc-" + class_desc.name + ".yaml")
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Convert a name from internal form (containing punctuation) to an external
|
12
|
+
# form (where punctuation is replaced by %xx)
|
13
|
+
|
14
|
+
def self.internal_to_external(name)
|
15
|
+
if ''.respond_to? :ord then
|
16
|
+
name.gsub(/\W/) { "%%%02x" % $&[0].ord }
|
17
|
+
else
|
18
|
+
name.gsub(/\W/) { "%%%02x" % $&[0] }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# And the reverse operation
|
24
|
+
|
25
|
+
def self.external_to_internal(name)
|
26
|
+
name.gsub(/%([0-9a-f]{2,2})/) { $1.to_i(16).chr }
|
27
|
+
end
|
28
|
+
|
29
|
+
def initialize(base_dir)
|
30
|
+
@base_dir = base_dir
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove_class(class_desc)
|
34
|
+
FileUtils.rm_rf(path_to_dir(class_desc.full_name))
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_class(class_desc)
|
38
|
+
dir = path_to_dir(class_desc.full_name)
|
39
|
+
FileUtils.mkdir_p(dir)
|
40
|
+
class_file_name = self.class.class_desc_path(dir, class_desc)
|
41
|
+
File.open(class_file_name, "w") do |f|
|
42
|
+
f.write(class_desc.serialize)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_method(class_desc, method_desc)
|
47
|
+
dir = path_to_dir(class_desc.full_name)
|
48
|
+
file_name = self.class.internal_to_external(method_desc.name)
|
49
|
+
meth_file_name = File.join(dir, file_name)
|
50
|
+
if method_desc.is_singleton
|
51
|
+
meth_file_name += "-c.yaml"
|
52
|
+
else
|
53
|
+
meth_file_name += "-i.yaml"
|
54
|
+
end
|
55
|
+
|
56
|
+
File.open(meth_file_name, "w") do |f|
|
57
|
+
f.write(method_desc.serialize)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def path_to_dir(class_name)
|
64
|
+
File.join(@base_dir, *class_name.split('::'))
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
data/lib/rdoc/stats.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rdoc'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Simple stats collector
|
5
|
+
|
6
|
+
class RDoc::Stats
|
7
|
+
|
8
|
+
attr_accessor :num_files, :num_classes, :num_modules, :num_methods
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@num_files = @num_classes = @num_modules = @num_methods = 0
|
12
|
+
@start = Time.now
|
13
|
+
end
|
14
|
+
|
15
|
+
def print
|
16
|
+
puts "Files: #@num_files"
|
17
|
+
puts "Classes: #@num_classes"
|
18
|
+
puts "Modules: #@num_modules"
|
19
|
+
puts "Methods: #@num_methods"
|
20
|
+
puts "Elapsed: " + sprintf("%0.3fs", Time.now - @start)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module RDoc; end
|
4
|
+
|
5
|
+
##
|
6
|
+
# An ERb wrapper that allows nesting of one ERb template inside another.
|
7
|
+
#
|
8
|
+
# This TemplatePage operates similarly to RDoc 1.x's TemplatePage, but uses
|
9
|
+
# ERb instead of a custom template language.
|
10
|
+
#
|
11
|
+
# Converting from a RDoc 1.x template to an RDoc 2.x template is fairly easy.
|
12
|
+
#
|
13
|
+
# * %blah% becomes <%= values["blah"] %>
|
14
|
+
# * !INCLUDE! becomes <%= template_include %>
|
15
|
+
# * HREF:aref:name becomes <%= href values["aref"], values["name"] %>
|
16
|
+
# * IF:blah becomes <% if values["blah"] then %>
|
17
|
+
# * IFNOT:blah becomes <% unless values["blah"] then %>
|
18
|
+
# * ENDIF:blah becomes <% end %>
|
19
|
+
# * START:blah becomes <% values["blah"].each do |blah| %>
|
20
|
+
# * END:blah becomes <% end %>
|
21
|
+
#
|
22
|
+
# To make nested loops easier to convert, start by converting START statements
|
23
|
+
# to:
|
24
|
+
#
|
25
|
+
# <% values["blah"].each do |blah| $stderr.puts blah.keys %>
|
26
|
+
#
|
27
|
+
# So you can see what is being used inside which loop.
|
28
|
+
|
29
|
+
class RDoc::TemplatePage
|
30
|
+
|
31
|
+
##
|
32
|
+
# Create a new TemplatePage that will use +templates+.
|
33
|
+
|
34
|
+
def initialize(*templates)
|
35
|
+
@templates = templates
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Returns "<a href=\"#{ref}\">#{name}</a>"
|
40
|
+
|
41
|
+
def href(ref, name)
|
42
|
+
if ref then
|
43
|
+
"<a href=\"#{ref}\">#{name}</a>"
|
44
|
+
else
|
45
|
+
name
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Process the template using +values+, writing the result to +io+.
|
51
|
+
|
52
|
+
def write_html_on(io, values)
|
53
|
+
b = binding
|
54
|
+
template_include = ""
|
55
|
+
|
56
|
+
@templates.reverse_each do |template|
|
57
|
+
template_include = ERB.new(template).result b
|
58
|
+
end
|
59
|
+
|
60
|
+
io.write template_include
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|