bitclust-core 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +2907 -0
- data/Gemfile +7 -0
- data/README +21 -0
- data/Rakefile +20 -0
- data/bin/bitclust +14 -0
- data/bin/refe +36 -0
- data/bitclust-dev.gemspec +33 -0
- data/bitclust.gemspec +30 -0
- data/config.in +23 -0
- data/config.ru +48 -0
- data/config.ru.sample +31 -0
- data/data/bitclust/catalog/ja_JP.EUC-JP +78 -0
- data/data/bitclust/catalog/ja_JP.UTF-8 +78 -0
- data/data/bitclust/template.lillia/class +98 -0
- data/data/bitclust/template.lillia/class-index +28 -0
- data/data/bitclust/template.lillia/doc +48 -0
- data/data/bitclust/template.lillia/layout +19 -0
- data/data/bitclust/template.lillia/library +129 -0
- data/data/bitclust/template.lillia/library-index +32 -0
- data/data/bitclust/template.lillia/method +20 -0
- data/data/bitclust/template.lillia/rd_file +6 -0
- data/data/bitclust/template.offline/class +67 -0
- data/data/bitclust/template.offline/class-index +28 -0
- data/data/bitclust/template.offline/doc +13 -0
- data/data/bitclust/template.offline/function +22 -0
- data/data/bitclust/template.offline/function-index +24 -0
- data/data/bitclust/template.offline/layout +18 -0
- data/data/bitclust/template.offline/library +87 -0
- data/data/bitclust/template.offline/library-index +32 -0
- data/data/bitclust/template.offline/method +21 -0
- data/data/bitclust/template.offline/rd_file +6 -0
- data/data/bitclust/template/class +133 -0
- data/data/bitclust/template/class-index +30 -0
- data/data/bitclust/template/doc +14 -0
- data/data/bitclust/template/function +21 -0
- data/data/bitclust/template/function-index +25 -0
- data/data/bitclust/template/layout +19 -0
- data/data/bitclust/template/library +89 -0
- data/data/bitclust/template/library-index +35 -0
- data/data/bitclust/template/method +24 -0
- data/data/bitclust/template/opensearchdescription +10 -0
- data/data/bitclust/template/search +57 -0
- data/lib/bitclust.rb +9 -0
- data/lib/bitclust/app.rb +129 -0
- data/lib/bitclust/classentry.rb +425 -0
- data/lib/bitclust/compat.rb +39 -0
- data/lib/bitclust/completion.rb +531 -0
- data/lib/bitclust/crossrubyutils.rb +91 -0
- data/lib/bitclust/database.rb +181 -0
- data/lib/bitclust/docentry.rb +83 -0
- data/lib/bitclust/entry.rb +223 -0
- data/lib/bitclust/exception.rb +38 -0
- data/lib/bitclust/functiondatabase.rb +115 -0
- data/lib/bitclust/functionentry.rb +81 -0
- data/lib/bitclust/functionreferenceparser.rb +76 -0
- data/lib/bitclust/htmlutils.rb +80 -0
- data/lib/bitclust/interface.rb +87 -0
- data/lib/bitclust/libraryentry.rb +211 -0
- data/lib/bitclust/lineinput.rb +165 -0
- data/lib/bitclust/messagecatalog.rb +95 -0
- data/lib/bitclust/methoddatabase.rb +401 -0
- data/lib/bitclust/methodentry.rb +202 -0
- data/lib/bitclust/methodid.rb +209 -0
- data/lib/bitclust/methodsignature.rb +82 -0
- data/lib/bitclust/nameutils.rb +236 -0
- data/lib/bitclust/parseutils.rb +60 -0
- data/lib/bitclust/preprocessor.rb +273 -0
- data/lib/bitclust/rdcompiler.rb +507 -0
- data/lib/bitclust/refsdatabase.rb +66 -0
- data/lib/bitclust/requesthandler.rb +330 -0
- data/lib/bitclust/ridatabase.rb +349 -0
- data/lib/bitclust/rrdparser.rb +522 -0
- data/lib/bitclust/runner.rb +143 -0
- data/lib/bitclust/screen.rb +554 -0
- data/lib/bitclust/searcher.rb +518 -0
- data/lib/bitclust/server.rb +59 -0
- data/lib/bitclust/simplesearcher.rb +84 -0
- data/lib/bitclust/subcommand.rb +746 -0
- data/lib/bitclust/textutils.rb +51 -0
- data/lib/bitclust/version.rb +3 -0
- data/packer.rb +224 -0
- data/refe2.gemspec +29 -0
- data/server.exe +0 -0
- data/server.exy +159 -0
- data/server.rb +10 -0
- data/setup.rb +1596 -0
- data/standalone.rb +193 -0
- data/test/run_test.rb +15 -0
- data/test/test_bitclust.rb +81 -0
- data/test/test_entry.rb +39 -0
- data/test/test_functiondatabase.rb +55 -0
- data/test/test_libraryentry.rb +31 -0
- data/test/test_methoddatabase.rb +81 -0
- data/test/test_methodsignature.rb +14 -0
- data/test/test_nameutils.rb +324 -0
- data/test/test_preprocessor.rb +84 -0
- data/test/test_rdcompiler.rb +534 -0
- data/test/test_refsdatabase.rb +76 -0
- data/test/test_rrdparser.rb +26 -0
- data/test/test_runner.rb +102 -0
- data/test/test_simplesearcher.rb +48 -0
- data/theme/default/images/external.png +0 -0
- data/theme/default/rurema.png +0 -0
- data/theme/default/style.css +288 -0
- data/theme/default/test.css +254 -0
- data/theme/lillia/rurema.png +0 -0
- data/theme/lillia/style.css +331 -0
- data/theme/lillia/test.css +254 -0
- data/tools/bc-ancestors.rb +153 -0
- data/tools/bc-checkparams.rb +246 -0
- data/tools/bc-classes.rb +80 -0
- data/tools/bc-convert.rb +165 -0
- data/tools/bc-list.rb +63 -0
- data/tools/bc-methods.rb +171 -0
- data/tools/bc-preproc.rb +42 -0
- data/tools/bc-rdoc.rb +343 -0
- data/tools/bc-tochm.rb +301 -0
- data/tools/bc-tohtml.rb +125 -0
- data/tools/bc-tohtmlpackage.rb +241 -0
- data/tools/check-signature.rb +19 -0
- data/tools/forall-ruby.rb +20 -0
- data/tools/gencatalog.rb +69 -0
- data/tools/statrefm.rb +98 -0
- data/tools/stattodo.rb +150 -0
- data/tools/update-database.rb +146 -0
- data/view.cgi +6 -0
- metadata +222 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<% @title = _('Library Index') %>
|
|
2
|
+
<p>
|
|
3
|
+
<%= manual_home_link() %>
|
|
4
|
+
> <%= _("All Libraries") %>
|
|
5
|
+
</p>
|
|
6
|
+
<%= search_form() %>
|
|
7
|
+
|
|
8
|
+
<%
|
|
9
|
+
headline_init
|
|
10
|
+
%>
|
|
11
|
+
<%= headline(_("Library Index")) %>
|
|
12
|
+
<table class="entries libraries">
|
|
13
|
+
<%
|
|
14
|
+
headline_push
|
|
15
|
+
lib = @entries.detect {|lib| lib.id == '_builtin' }
|
|
16
|
+
%>
|
|
17
|
+
<tr>
|
|
18
|
+
<td class="signature"><%= library_link(lib.name, _('Builtin Library')) %></td>
|
|
19
|
+
<td class="description"><%= compile_rd(lib.synopsis_source) %></td>
|
|
20
|
+
</tr>
|
|
21
|
+
<%
|
|
22
|
+
@entries.each do |lib|
|
|
23
|
+
next if lib.id == '_builtin'
|
|
24
|
+
next if lib.is_sublibrary
|
|
25
|
+
%>
|
|
26
|
+
<tr>
|
|
27
|
+
<td class="signature"><%= library_link(lib.name) %></td>
|
|
28
|
+
<td class="description"><%= compile_rd(lib.synopsis_source) %></td>
|
|
29
|
+
</tr>
|
|
30
|
+
<%
|
|
31
|
+
end
|
|
32
|
+
headline_pop
|
|
33
|
+
%>
|
|
34
|
+
</table>
|
|
35
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<%
|
|
2
|
+
entry = @entries.sort.first
|
|
3
|
+
@title = "#{entry.type_label} #{entry.label}"
|
|
4
|
+
%>
|
|
5
|
+
<p>
|
|
6
|
+
<%= manual_home_link() %>
|
|
7
|
+
> <a href="<%= library_index_url() %>"><%= _('All Libraries') %></a>
|
|
8
|
+
> <%= friendly_library_link(entry.library.name) %>
|
|
9
|
+
> <%= class_link(entry.klass.name, _(entry.klass.type.to_s + ' %s', entry.klass.name)) %>
|
|
10
|
+
> <% if entry.typename == :special_variable %>$<% end %><%=h entry.name %>
|
|
11
|
+
<% unless entry.really_public? %>(<%= entry.visibility %>)<% end %>
|
|
12
|
+
</p>
|
|
13
|
+
<%= search_form() %>
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
<% headline_init %>
|
|
17
|
+
<%= headline("#{entry.type_label} #{entry.label}") %>
|
|
18
|
+
<% headline_push %>
|
|
19
|
+
<dl class="methodlist">
|
|
20
|
+
<% @entries.sort.each do |ent| %>
|
|
21
|
+
<%= compile_method(ent) %>
|
|
22
|
+
<% end %>
|
|
23
|
+
</dl>
|
|
24
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="<%=h encoding() %>"?>
|
|
2
|
+
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
|
|
3
|
+
xmlns:moz="http://www.mozilla.org/2006/browser/search/">
|
|
4
|
+
<ShortName><%= _('Ruby %s Reference Manual', ruby_version()) %></ShortName>
|
|
5
|
+
<Description><%= _('Ruby %s Reference Manual', ruby_version()) %></Description>
|
|
6
|
+
<Image height="16" width="16">data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%08%02%00%00%00%90%91h6%00%00%00%04gAMA%00%00%B1%8F%0B%FCa%05%00%00%00%06tRNS%00%FF%00%FF%00%FF7X%1B%7D%00%00%00TIDAT(%CFc%F8%0F%06%0C%C4%01%90J%88jc%E3U%10%84%A9%08Y%0AC%03P%08%03%19%C3d%D150%80%A5%D3PUC%B8%08%05%98%1A%D0%7C%F3%9FH%0D%98%8C%A1%A7%81%04O%93%10%AC%24G%1CiI%83%E4%C4w%86%10%80%A8%86j%20)y%03%00%B7%DF%E3P%F6%95%E2%F8%00%00%00%00IEND%AEB%60%82</Image>
|
|
7
|
+
<InputEncoding><%=h encoding() %></InputEncoding>
|
|
8
|
+
<Url type="text/html" method="get" template="<%=h search_full_url() %>?q={searchTerms}"/>
|
|
9
|
+
<moz:SearchForm><%=h search_full_url() %></moz:SearchForm>
|
|
10
|
+
</OpenSearchDescription>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<p>
|
|
2
|
+
<%= manual_home_link() %>
|
|
3
|
+
> <%=h _('Search Results') %>
|
|
4
|
+
</p>
|
|
5
|
+
<%
|
|
6
|
+
headline_init
|
|
7
|
+
%>
|
|
8
|
+
<%= headline(_('Search Results')) %>
|
|
9
|
+
<form method="get" action="" name="f">
|
|
10
|
+
<input value="<%=h @query %>" name="q" size="41">
|
|
11
|
+
<input value="<%= _('Search') %>" type="submit">
|
|
12
|
+
</form>
|
|
13
|
+
<p>
|
|
14
|
+
|
|
15
|
+
<table class="entries">
|
|
16
|
+
<tr>
|
|
17
|
+
<td></td>
|
|
18
|
+
<td style="text-align:right" nowrap="nowrap">
|
|
19
|
+
<%=h _('%d Results', @entries.size) %> <%=h '(%.3f sec)' % @elapsed_time %>
|
|
20
|
+
</td>
|
|
21
|
+
</tr>
|
|
22
|
+
<% unless @entries.empty? %>
|
|
23
|
+
<tr>
|
|
24
|
+
<th><%=h _('Entry') %></th>
|
|
25
|
+
<th colspan="2"><%=h _('Description') %></th>
|
|
26
|
+
</tr>
|
|
27
|
+
<% end %>
|
|
28
|
+
<%
|
|
29
|
+
headline_push
|
|
30
|
+
@entries.each do |e|
|
|
31
|
+
foreach_method_chunk(e.source) do |sigs, src| %>
|
|
32
|
+
<tr>
|
|
33
|
+
<% case e.type_id
|
|
34
|
+
when :method %>
|
|
35
|
+
<td class="signature"><%=
|
|
36
|
+
case e.type
|
|
37
|
+
when :special_variable
|
|
38
|
+
e.names.map {|name| method_link(e.spec_string, '$' + name) }
|
|
39
|
+
else
|
|
40
|
+
sigs.map {|sig|
|
|
41
|
+
method_link(e.spec_string,
|
|
42
|
+
e.klass.name + e.typemark + sig.to_s)
|
|
43
|
+
}
|
|
44
|
+
end.join("<br>\n") %></td>
|
|
45
|
+
<td class="description"><%= compile_rd(src) %></td>
|
|
46
|
+
<% when :class %>
|
|
47
|
+
<td class="signature"><%= class_link e.name %></td>
|
|
48
|
+
<td class="description"><%= compile_rd(src) %></td>
|
|
49
|
+
<% end %>
|
|
50
|
+
</tr>
|
|
51
|
+
<%
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
headline_pop
|
|
55
|
+
%>
|
|
56
|
+
</table>
|
|
57
|
+
|
data/lib/bitclust.rb
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require 'bitclust/requesthandler'
|
|
2
|
+
require 'bitclust/screen'
|
|
3
|
+
require 'bitclust/server'
|
|
4
|
+
require 'bitclust/searcher'
|
|
5
|
+
require 'bitclust/methoddatabase'
|
|
6
|
+
require 'bitclust/functiondatabase'
|
|
7
|
+
require 'bitclust/rrdparser'
|
|
8
|
+
require 'bitclust/exception'
|
|
9
|
+
require 'bitclust/version'
|
data/lib/bitclust/app.rb
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require 'bitclust'
|
|
2
|
+
require 'bitclust/interface'
|
|
3
|
+
|
|
4
|
+
module BitClust
|
|
5
|
+
|
|
6
|
+
class App
|
|
7
|
+
|
|
8
|
+
def initialize(options)
|
|
9
|
+
@options = options
|
|
10
|
+
dbpath = options[:dbpath]
|
|
11
|
+
baseurl = options[:baseurl] || ''
|
|
12
|
+
datadir = options[:datadir] || File.expand_path('../../data/bitclust', File.dirname(__FILE__))
|
|
13
|
+
encoding = options[:encoding] || 'utf-8'
|
|
14
|
+
viewpath = options[:viewpath]
|
|
15
|
+
capi = options[:capi]
|
|
16
|
+
if options[:rack]
|
|
17
|
+
request_handler_class = BitClust::RackRequestHandler
|
|
18
|
+
else
|
|
19
|
+
request_handler_class = BitClust::RequestHandler
|
|
20
|
+
end
|
|
21
|
+
@interfaces = {}
|
|
22
|
+
case dbpath
|
|
23
|
+
when String
|
|
24
|
+
dbpath = File.expand_path(dbpath)
|
|
25
|
+
db = BitClust::MethodDatabase.new(dbpath)
|
|
26
|
+
if capi
|
|
27
|
+
db = [db, BitClust::FunctionDatabase.new(dbpath)]
|
|
28
|
+
end
|
|
29
|
+
manager = BitClust::ScreenManager.new(
|
|
30
|
+
:base_url => baseurl,
|
|
31
|
+
:cgi_url => File.join(baseurl, viewpath),
|
|
32
|
+
:datadir => datadir,
|
|
33
|
+
:templatedir => options[:templatedir],
|
|
34
|
+
:theme => options[:theme],
|
|
35
|
+
:encoding => encoding
|
|
36
|
+
)
|
|
37
|
+
handler = request_handler_class.new(db, manager)
|
|
38
|
+
@interfaces[viewpath] = BitClust::Interface.new { handler }
|
|
39
|
+
when Array
|
|
40
|
+
dbpaths = dbpath
|
|
41
|
+
@versions = []
|
|
42
|
+
dbpaths.each do |dbpath|
|
|
43
|
+
next unless /db-([\d_]+)/ =~ dbpath
|
|
44
|
+
dbpath = File.expand_path(dbpath)
|
|
45
|
+
version = $1.tr("_", ".")
|
|
46
|
+
@versions << version
|
|
47
|
+
if viewpath
|
|
48
|
+
version_viewpath = File.join(version, viewpath)
|
|
49
|
+
else
|
|
50
|
+
version_viewpath = version
|
|
51
|
+
end
|
|
52
|
+
db = BitClust::MethodDatabase.new(dbpath)
|
|
53
|
+
if capi
|
|
54
|
+
db = [db, BitClust::FunctionDatabase.new(dbpath)]
|
|
55
|
+
end
|
|
56
|
+
manager = BitClust::ScreenManager.new(
|
|
57
|
+
:base_url => baseurl,
|
|
58
|
+
:cgi_url => File.join(baseurl, version_viewpath),
|
|
59
|
+
:datadir => datadir,
|
|
60
|
+
:templatedir => options[:templatedir],
|
|
61
|
+
:theme => options[:theme],
|
|
62
|
+
:encoding => encoding
|
|
63
|
+
)
|
|
64
|
+
handler = request_handler_class.new(db, manager)
|
|
65
|
+
@interfaces[version_viewpath] = BitClust::Interface.new { handler }
|
|
66
|
+
$bitclust_context_cache = nil # clear cache
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
attr_reader :interfaces, :versions
|
|
72
|
+
|
|
73
|
+
def index(req)
|
|
74
|
+
case
|
|
75
|
+
when @interfaces.size == 1 && viewpath = @options[:viewpath]
|
|
76
|
+
# Redirect from '/' to "#{viewpath}/"
|
|
77
|
+
@index = "<html><head><meta http-equiv='Refresh' content='0;URL=#{viewpath}'></head></html>"
|
|
78
|
+
when 1 < @interfaces.size
|
|
79
|
+
request_path = case
|
|
80
|
+
when req.respond_to?(:path_info)
|
|
81
|
+
req.path_info
|
|
82
|
+
when req.respond_to?(:path)
|
|
83
|
+
req.path_info
|
|
84
|
+
end
|
|
85
|
+
if @versions.any?{|version| %r|\A/?#{version}/?\z| =~ request_path }
|
|
86
|
+
viewpath = File.join(request_path, @options[:viewpath])
|
|
87
|
+
@index = "<html><head><meta http-equiv='Refresh' content='0;URL=#{viewpath}'></head></html>"
|
|
88
|
+
else
|
|
89
|
+
links = "<ul>"
|
|
90
|
+
@interfaces.keys.sort.each do |v|
|
|
91
|
+
if @options[:viewpath]
|
|
92
|
+
version = v.sub(@options[:viewpath], '')
|
|
93
|
+
else
|
|
94
|
+
version = v
|
|
95
|
+
end
|
|
96
|
+
url = v
|
|
97
|
+
links << %Q(<li><a href="#{url}/">#{version}</a></li>)
|
|
98
|
+
end
|
|
99
|
+
links << "</ul>"
|
|
100
|
+
if File.exist?("readme.html")
|
|
101
|
+
@index = File.read("readme.html").sub(%r!\./bitclust!, '').sub(/<!--links-->/) { links }
|
|
102
|
+
else
|
|
103
|
+
@index = "<html><head><title>bitclust</title></head><body>#{links}</body></html>"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def get_instance(server)
|
|
110
|
+
self
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def service(req, res)
|
|
114
|
+
unless %r|/#{File.basename(@options[:baseurl])}/?\z| =~ req.path
|
|
115
|
+
raise WEBrick::HTTPStatus::NotFound
|
|
116
|
+
end
|
|
117
|
+
res.body = index(req)
|
|
118
|
+
res['Content-Type'] = 'text/html; charset=utf-8'
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def call(env)
|
|
122
|
+
[
|
|
123
|
+
200,
|
|
124
|
+
{'Content-Type' => 'text/html; charset=utf-8'},
|
|
125
|
+
index(Rack::Request.new(env))
|
|
126
|
+
]
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
#
|
|
2
|
+
# bitclust/classentry.rb
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2006-2008 Minero Aoki
|
|
5
|
+
#
|
|
6
|
+
# This program is free software.
|
|
7
|
+
# You can distribute/modify this program under the Ruby License.
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
require 'bitclust/entry'
|
|
11
|
+
require 'bitclust/exception'
|
|
12
|
+
|
|
13
|
+
module BitClust
|
|
14
|
+
|
|
15
|
+
# Represents a class, a module and a singleton object.
|
|
16
|
+
class ClassEntry < Entry
|
|
17
|
+
|
|
18
|
+
include Enumerable
|
|
19
|
+
|
|
20
|
+
def ClassEntry.type_id
|
|
21
|
+
:class
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def initialize(db, id)
|
|
25
|
+
super db
|
|
26
|
+
@id = id
|
|
27
|
+
if saved?
|
|
28
|
+
@entries = nil
|
|
29
|
+
@ancestors_checked = true
|
|
30
|
+
@s_ancestors_checked = true
|
|
31
|
+
else
|
|
32
|
+
@entries = []
|
|
33
|
+
@ancestors_checked = false
|
|
34
|
+
@s_ancestors_checked = false
|
|
35
|
+
end
|
|
36
|
+
init_properties
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
attr_reader :id
|
|
40
|
+
|
|
41
|
+
def ==(other)
|
|
42
|
+
@id == other.id
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
alias eql? ==
|
|
46
|
+
|
|
47
|
+
def hash
|
|
48
|
+
@id.hash
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def <=>(other)
|
|
52
|
+
@id <=> other.id
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def name
|
|
56
|
+
classid2name(@id)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def name?(n)
|
|
60
|
+
name() == n
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Return the real class name
|
|
64
|
+
def realname
|
|
65
|
+
alias? ? aliasof.name : name
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def name_match?(re)
|
|
69
|
+
re =~ name()
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
alias label name
|
|
73
|
+
|
|
74
|
+
# FIXME: implement class alias
|
|
75
|
+
def labels
|
|
76
|
+
[label()]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
persistent_properties {
|
|
80
|
+
property :type, 'Symbol' # :class | :module | :object
|
|
81
|
+
property :superclass, 'ClassEntry'
|
|
82
|
+
property :included, '[ClassEntry]'
|
|
83
|
+
property :extended, '[ClassEntry]'
|
|
84
|
+
property :library, 'LibraryEntry'
|
|
85
|
+
property :aliases, '[ClassEntry]'
|
|
86
|
+
property :aliasof, 'ClassEntry'
|
|
87
|
+
property :source, 'String'
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
def save
|
|
91
|
+
super
|
|
92
|
+
save_index
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def inspect
|
|
96
|
+
"\#<#{type()} #{@id}>"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def dummy?
|
|
100
|
+
not type()
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def class?
|
|
104
|
+
type() == :class
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def module?
|
|
108
|
+
type() == :module
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def object?
|
|
112
|
+
type() == :object
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def alias?
|
|
116
|
+
!! aliasof()
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def include(m)
|
|
120
|
+
included().push m
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def extend(m)
|
|
124
|
+
extended().push m
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Add a alias +c+ to the alias list.
|
|
128
|
+
def alias(c)
|
|
129
|
+
aliases().push c
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def check_ancestor_type
|
|
133
|
+
s = superclass()
|
|
134
|
+
if s and not s.class? and not s.dummy?
|
|
135
|
+
raise InvalidAncestor, "#{name()} inherits #{s.name} but it is a #{s.type} (class expected)"
|
|
136
|
+
end
|
|
137
|
+
included().each do |c|
|
|
138
|
+
unless c.module? or c.dummy?
|
|
139
|
+
raise InvalidAncestor, "#{name()} includes #{c.name} but it is a #{c.type} (module expected)"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
extended().each do |c|
|
|
143
|
+
unless c.module? or c.dummy?
|
|
144
|
+
raise InvalidAncestor, "#{name()} extends #{c.name} but it is a #{c.type} (module expected)"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def check_ancestors_link(path = [])
|
|
150
|
+
return if @ancestors_checked
|
|
151
|
+
if path.include?(name())
|
|
152
|
+
raise InvalidLink, "ancestor link looped: #{path_string(path)}"
|
|
153
|
+
end
|
|
154
|
+
([superclass()] + included()).compact.each do |c|
|
|
155
|
+
path.push name()
|
|
156
|
+
c.check_ancestors_link path
|
|
157
|
+
path.pop
|
|
158
|
+
end
|
|
159
|
+
@ancestors_checked = true
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def check_singleton_ancestors_link(path = [])
|
|
163
|
+
return if @s_ancestors_checked
|
|
164
|
+
extended().each do |c|
|
|
165
|
+
path.push name()
|
|
166
|
+
c.check_singleton_ancestors_link path
|
|
167
|
+
path.pop
|
|
168
|
+
end
|
|
169
|
+
@s_ancestors_checked = true
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def ancestors
|
|
173
|
+
@ancestors ||=
|
|
174
|
+
[ self, included().map {|m| m.ancestors },
|
|
175
|
+
superclass() ? superclass().ancestors : [] ].flatten
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def included_modules
|
|
179
|
+
list = ancestors().select {|c| c.module? }
|
|
180
|
+
list.delete self
|
|
181
|
+
list
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def extended_modules
|
|
185
|
+
ancestors().select {|c| c.class? }.map {|c| c.extended }.flatten
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def entries(level = 0)
|
|
189
|
+
@entries ||= @db.entries("method/#{@id}")\
|
|
190
|
+
.map {|ent| MethodEntry.new(@db, "#{@id}/#{ent}") }
|
|
191
|
+
ret = @entries
|
|
192
|
+
ancestors[1..level].each{|c| ret += c.entries }
|
|
193
|
+
ret
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
alias methods entries
|
|
197
|
+
|
|
198
|
+
def each(&block)
|
|
199
|
+
entries().each(&block)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def add_method(m)
|
|
203
|
+
# FIXME: check duplication?
|
|
204
|
+
entries().push m
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
Parts = Struct.new(:singleton_methods, :private_singleton_methods,
|
|
208
|
+
:instance_methods, :private_instance_methods,
|
|
209
|
+
:module_functions,
|
|
210
|
+
:constants, :special_variables,
|
|
211
|
+
:added)
|
|
212
|
+
|
|
213
|
+
def partitioned_entries(level = 0)
|
|
214
|
+
s = []; spv = []
|
|
215
|
+
i = []; ipv = []
|
|
216
|
+
mf = []
|
|
217
|
+
c = []; v = []
|
|
218
|
+
added = []
|
|
219
|
+
entries(level).sort_by{|e| e.name}.each do |m|
|
|
220
|
+
case m.kind
|
|
221
|
+
when :defined, :redefined
|
|
222
|
+
case m.type
|
|
223
|
+
when :singleton_method
|
|
224
|
+
(m.public? ? s : spv).push m
|
|
225
|
+
when :instance_method
|
|
226
|
+
(m.public? ? i : ipv).push m
|
|
227
|
+
when :module_function
|
|
228
|
+
mf.push m
|
|
229
|
+
when :constant
|
|
230
|
+
c.push m
|
|
231
|
+
when :special_variable
|
|
232
|
+
v.push m
|
|
233
|
+
else
|
|
234
|
+
raise "must not happen: m.type=#{m.type.inspect} (#{m.inspect})"
|
|
235
|
+
end
|
|
236
|
+
when :added
|
|
237
|
+
added.push m
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
Parts.new(s,spv, i,ipv, mf, c, v, added)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def singleton_methods(level = 0)
|
|
244
|
+
# FIXME: inheritance
|
|
245
|
+
entries(level).select {|m| m.singleton_method? }.sort
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def public_singleton_methods(level = 0)
|
|
249
|
+
# FIXME: inheritance
|
|
250
|
+
entries(level).select {|m| m.public_singleton_method? }.sort
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def instance_methods(level = 0)
|
|
254
|
+
# FIXME: inheritance
|
|
255
|
+
entries(level).select {|m| m.instance_method? }.sort
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def private_singleton_methods(level = 0)
|
|
259
|
+
# FIXME: inheritance
|
|
260
|
+
entries(level).select {|m| m.private_singleton_method? }.sort
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def public_instance_methods(level = 0)
|
|
264
|
+
# FIXME: inheritance
|
|
265
|
+
entries(level).select {|m| m.public_instance_method? }.sort
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def private_instance_methods(level = 0)
|
|
269
|
+
# FIXME: inheritance
|
|
270
|
+
entries(level).select {|m| m.private_instance_method? }.sort
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
alias private_methods private_instance_methods
|
|
274
|
+
|
|
275
|
+
def constants(level = 0)
|
|
276
|
+
entries(level).select {|m| m.constant? }.sort
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def special_variables
|
|
280
|
+
entries().select {|m| m.special_variable? }.sort
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def singleton_method?(name, inherit = true)
|
|
284
|
+
if inherit
|
|
285
|
+
_smap().key?(name)
|
|
286
|
+
else
|
|
287
|
+
singleton_methods(false).detect {|m| m.name?(name) }
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def instance_method?(name, inherit = true)
|
|
292
|
+
if inherit
|
|
293
|
+
_imap().key?(name)
|
|
294
|
+
else
|
|
295
|
+
instance_methods(false).detect {|m| m.name?(name) }
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def constant?(name, inherit = true)
|
|
300
|
+
if inherit
|
|
301
|
+
ancestors().any? {|c| c.constant?(name, false) }
|
|
302
|
+
else
|
|
303
|
+
constants(false).detect {|m| m.name?(name) }
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def special_variable?(name)
|
|
308
|
+
special_variables().detect {|m| m.name?(name) }
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def get_methods(spec)
|
|
312
|
+
entries().select {|m| spec.match?(m) }
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def get_method(spec)
|
|
316
|
+
entries().detect {|m| spec.match?(m) }
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def fetch_methods(spec)
|
|
320
|
+
get_methods(spec) or
|
|
321
|
+
raise MethodNotFound, "no such method: #{spec}"
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def fetch_method(spec)
|
|
325
|
+
get_method(spec) or
|
|
326
|
+
raise MethodNotFound, "no such method: #{spec}"
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# internal use only
|
|
330
|
+
def match_entry(t, mname)
|
|
331
|
+
_index()[t + mname]
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def singleton_method_names
|
|
335
|
+
# should remove module functions?
|
|
336
|
+
_index().keys.select {|name| /\A\./ =~ name }.map {|name| name[1..-1] }
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def instance_method_names
|
|
340
|
+
_index().keys.select {|name| /\A\#/ =~ name }.map {|name| name[1..-1] }
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def constant_names
|
|
344
|
+
_index().keys.select {|name| /\A\:/ =~ name }.map {|name| name[1..-1] }
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def special_variable_names
|
|
348
|
+
special_variables().map {|m| m.names }.flatten
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def inherited_method_specs
|
|
352
|
+
cname = name()
|
|
353
|
+
_index().map {|mname, specstr| MethodSpec.parse(specstr) }\
|
|
354
|
+
.reject {|spec| spec.klass == cname }.uniq
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def clear_cache
|
|
358
|
+
@_smap = @_imap = @_cmap = nil
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# internal use only
|
|
362
|
+
def _smap
|
|
363
|
+
@_smap ||= makemap('s', extended_modules(), singleton_methods())
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# internal use only
|
|
367
|
+
def _imap
|
|
368
|
+
@_imap ||= makemap('i', included_modules(), instance_methods())
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# internal use only
|
|
372
|
+
def _cmap
|
|
373
|
+
@_cmap ||= makemap('c', included_modules(), constants())
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
private
|
|
377
|
+
|
|
378
|
+
def makemap(typechar, inherited_modules, ents)
|
|
379
|
+
if alias?
|
|
380
|
+
return aliasof().__send__("_#{typechar}map").dup
|
|
381
|
+
end
|
|
382
|
+
s = superclass()
|
|
383
|
+
map = s ? s.__send__("_#{typechar}map").dup : {}
|
|
384
|
+
inherited_modules.each do |mod|
|
|
385
|
+
map.update mod.__send__("_#{typechar == 'c' ? 'c' : 'i'}map")
|
|
386
|
+
end
|
|
387
|
+
defined, undefined = *ents.partition {|m| m.defined? }
|
|
388
|
+
(undefined + defined).each do |m|
|
|
389
|
+
m.names.each do |name|
|
|
390
|
+
map[name] = m.spec_string
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
map
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def save_index
|
|
397
|
+
@db.makepath "method/#{@id}"
|
|
398
|
+
@db.atomic_write_open("method/#{@id}/=index") {|f|
|
|
399
|
+
writemap _smap(), '.', f
|
|
400
|
+
writemap _imap(), '#', f
|
|
401
|
+
writemap _cmap(), ':', f
|
|
402
|
+
}
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def writemap(map, mark, f)
|
|
406
|
+
map.to_a.sort_by {|k,v| k }.each do |name, m|
|
|
407
|
+
f.puts "#{mark}#{name}\t#{m}"
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def _index
|
|
412
|
+
@_index ||=
|
|
413
|
+
begin
|
|
414
|
+
h = {}
|
|
415
|
+
@db.foreach_line("method/#{@id}/=index") do |line|
|
|
416
|
+
name, spec = line.split
|
|
417
|
+
h[name] = spec
|
|
418
|
+
end
|
|
419
|
+
h
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
end
|