bitclust-core 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|