bitclust-core 0.5.0

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