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.
Files changed (127) hide show
  1. data/ChangeLog +2907 -0
  2. data/Gemfile +7 -0
  3. data/README +21 -0
  4. data/Rakefile +20 -0
  5. data/bin/bitclust +14 -0
  6. data/bin/refe +36 -0
  7. data/bitclust-dev.gemspec +33 -0
  8. data/bitclust.gemspec +30 -0
  9. data/config.in +23 -0
  10. data/config.ru +48 -0
  11. data/config.ru.sample +31 -0
  12. data/data/bitclust/catalog/ja_JP.EUC-JP +78 -0
  13. data/data/bitclust/catalog/ja_JP.UTF-8 +78 -0
  14. data/data/bitclust/template.lillia/class +98 -0
  15. data/data/bitclust/template.lillia/class-index +28 -0
  16. data/data/bitclust/template.lillia/doc +48 -0
  17. data/data/bitclust/template.lillia/layout +19 -0
  18. data/data/bitclust/template.lillia/library +129 -0
  19. data/data/bitclust/template.lillia/library-index +32 -0
  20. data/data/bitclust/template.lillia/method +20 -0
  21. data/data/bitclust/template.lillia/rd_file +6 -0
  22. data/data/bitclust/template.offline/class +67 -0
  23. data/data/bitclust/template.offline/class-index +28 -0
  24. data/data/bitclust/template.offline/doc +13 -0
  25. data/data/bitclust/template.offline/function +22 -0
  26. data/data/bitclust/template.offline/function-index +24 -0
  27. data/data/bitclust/template.offline/layout +18 -0
  28. data/data/bitclust/template.offline/library +87 -0
  29. data/data/bitclust/template.offline/library-index +32 -0
  30. data/data/bitclust/template.offline/method +21 -0
  31. data/data/bitclust/template.offline/rd_file +6 -0
  32. data/data/bitclust/template/class +133 -0
  33. data/data/bitclust/template/class-index +30 -0
  34. data/data/bitclust/template/doc +14 -0
  35. data/data/bitclust/template/function +21 -0
  36. data/data/bitclust/template/function-index +25 -0
  37. data/data/bitclust/template/layout +19 -0
  38. data/data/bitclust/template/library +89 -0
  39. data/data/bitclust/template/library-index +35 -0
  40. data/data/bitclust/template/method +24 -0
  41. data/data/bitclust/template/opensearchdescription +10 -0
  42. data/data/bitclust/template/search +57 -0
  43. data/lib/bitclust.rb +9 -0
  44. data/lib/bitclust/app.rb +129 -0
  45. data/lib/bitclust/classentry.rb +425 -0
  46. data/lib/bitclust/compat.rb +39 -0
  47. data/lib/bitclust/completion.rb +531 -0
  48. data/lib/bitclust/crossrubyutils.rb +91 -0
  49. data/lib/bitclust/database.rb +181 -0
  50. data/lib/bitclust/docentry.rb +83 -0
  51. data/lib/bitclust/entry.rb +223 -0
  52. data/lib/bitclust/exception.rb +38 -0
  53. data/lib/bitclust/functiondatabase.rb +115 -0
  54. data/lib/bitclust/functionentry.rb +81 -0
  55. data/lib/bitclust/functionreferenceparser.rb +76 -0
  56. data/lib/bitclust/htmlutils.rb +80 -0
  57. data/lib/bitclust/interface.rb +87 -0
  58. data/lib/bitclust/libraryentry.rb +211 -0
  59. data/lib/bitclust/lineinput.rb +165 -0
  60. data/lib/bitclust/messagecatalog.rb +95 -0
  61. data/lib/bitclust/methoddatabase.rb +401 -0
  62. data/lib/bitclust/methodentry.rb +202 -0
  63. data/lib/bitclust/methodid.rb +209 -0
  64. data/lib/bitclust/methodsignature.rb +82 -0
  65. data/lib/bitclust/nameutils.rb +236 -0
  66. data/lib/bitclust/parseutils.rb +60 -0
  67. data/lib/bitclust/preprocessor.rb +273 -0
  68. data/lib/bitclust/rdcompiler.rb +507 -0
  69. data/lib/bitclust/refsdatabase.rb +66 -0
  70. data/lib/bitclust/requesthandler.rb +330 -0
  71. data/lib/bitclust/ridatabase.rb +349 -0
  72. data/lib/bitclust/rrdparser.rb +522 -0
  73. data/lib/bitclust/runner.rb +143 -0
  74. data/lib/bitclust/screen.rb +554 -0
  75. data/lib/bitclust/searcher.rb +518 -0
  76. data/lib/bitclust/server.rb +59 -0
  77. data/lib/bitclust/simplesearcher.rb +84 -0
  78. data/lib/bitclust/subcommand.rb +746 -0
  79. data/lib/bitclust/textutils.rb +51 -0
  80. data/lib/bitclust/version.rb +3 -0
  81. data/packer.rb +224 -0
  82. data/refe2.gemspec +29 -0
  83. data/server.exe +0 -0
  84. data/server.exy +159 -0
  85. data/server.rb +10 -0
  86. data/setup.rb +1596 -0
  87. data/standalone.rb +193 -0
  88. data/test/run_test.rb +15 -0
  89. data/test/test_bitclust.rb +81 -0
  90. data/test/test_entry.rb +39 -0
  91. data/test/test_functiondatabase.rb +55 -0
  92. data/test/test_libraryentry.rb +31 -0
  93. data/test/test_methoddatabase.rb +81 -0
  94. data/test/test_methodsignature.rb +14 -0
  95. data/test/test_nameutils.rb +324 -0
  96. data/test/test_preprocessor.rb +84 -0
  97. data/test/test_rdcompiler.rb +534 -0
  98. data/test/test_refsdatabase.rb +76 -0
  99. data/test/test_rrdparser.rb +26 -0
  100. data/test/test_runner.rb +102 -0
  101. data/test/test_simplesearcher.rb +48 -0
  102. data/theme/default/images/external.png +0 -0
  103. data/theme/default/rurema.png +0 -0
  104. data/theme/default/style.css +288 -0
  105. data/theme/default/test.css +254 -0
  106. data/theme/lillia/rurema.png +0 -0
  107. data/theme/lillia/style.css +331 -0
  108. data/theme/lillia/test.css +254 -0
  109. data/tools/bc-ancestors.rb +153 -0
  110. data/tools/bc-checkparams.rb +246 -0
  111. data/tools/bc-classes.rb +80 -0
  112. data/tools/bc-convert.rb +165 -0
  113. data/tools/bc-list.rb +63 -0
  114. data/tools/bc-methods.rb +171 -0
  115. data/tools/bc-preproc.rb +42 -0
  116. data/tools/bc-rdoc.rb +343 -0
  117. data/tools/bc-tochm.rb +301 -0
  118. data/tools/bc-tohtml.rb +125 -0
  119. data/tools/bc-tohtmlpackage.rb +241 -0
  120. data/tools/check-signature.rb +19 -0
  121. data/tools/forall-ruby.rb +20 -0
  122. data/tools/gencatalog.rb +69 -0
  123. data/tools/statrefm.rb +98 -0
  124. data/tools/stattodo.rb +150 -0
  125. data/tools/update-database.rb +146 -0
  126. data/view.cgi +6 -0
  127. metadata +222 -0
@@ -0,0 +1,35 @@
1
+ <% @title = _('Library Index') %>
2
+ <p>
3
+ <%= manual_home_link() %>
4
+ &gt; <%= _("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
+ &gt; <a href="<%= library_index_url() %>"><%= _('All Libraries') %></a>
8
+ &gt; <%= friendly_library_link(entry.library.name) %>
9
+ &gt; <%= class_link(entry.klass.name, _(entry.klass.type.to_s + ' %s', entry.klass.name)) %>
10
+ &gt; <% 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
+ &gt; <%=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'
@@ -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