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,401 @@
|
|
|
1
|
+
#
|
|
2
|
+
# bitclust/methoddatabase.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/database'
|
|
11
|
+
require 'bitclust/libraryentry'
|
|
12
|
+
require 'bitclust/classentry'
|
|
13
|
+
require 'bitclust/methodentry'
|
|
14
|
+
require 'bitclust/docentry'
|
|
15
|
+
require 'bitclust/completion'
|
|
16
|
+
require 'bitclust/refsdatabase'
|
|
17
|
+
require 'bitclust/rrdparser'
|
|
18
|
+
require 'bitclust/exception'
|
|
19
|
+
require 'fileutils'
|
|
20
|
+
|
|
21
|
+
module BitClust
|
|
22
|
+
|
|
23
|
+
class MethodDatabase < Database
|
|
24
|
+
|
|
25
|
+
include Completion
|
|
26
|
+
|
|
27
|
+
def MethodDatabase.dummy(params = {})
|
|
28
|
+
db = super
|
|
29
|
+
db.refs = RefsDatabase.new
|
|
30
|
+
db
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def initialize(prefix)
|
|
34
|
+
super prefix
|
|
35
|
+
@librarymap = nil
|
|
36
|
+
@classmap = {}
|
|
37
|
+
@class_extent_loaded = false
|
|
38
|
+
@in_transaction = false
|
|
39
|
+
@dirty_libraries = {}
|
|
40
|
+
@dirty_classes = {}
|
|
41
|
+
@dirty_methods = {}
|
|
42
|
+
@refs = nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
attr_writer :refs
|
|
46
|
+
|
|
47
|
+
def init
|
|
48
|
+
FileUtils.rm_rf @prefix
|
|
49
|
+
FileUtils.mkdir_p @prefix
|
|
50
|
+
Dir.mkdir "#{@prefix}/library"
|
|
51
|
+
Dir.mkdir "#{@prefix}/class"
|
|
52
|
+
Dir.mkdir "#{@prefix}/method"
|
|
53
|
+
Dir.mkdir "#{@prefix}/doc"
|
|
54
|
+
FileUtils.touch "#{@prefix}/properties"
|
|
55
|
+
FileUtils.touch "#{@prefix}/refs"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
#
|
|
59
|
+
# Transaction
|
|
60
|
+
#
|
|
61
|
+
|
|
62
|
+
def commit
|
|
63
|
+
update_requires
|
|
64
|
+
update_sublibraries
|
|
65
|
+
# FIXME: many require loops in tk
|
|
66
|
+
#each_dirty_library do |lib|
|
|
67
|
+
# lib.check_link
|
|
68
|
+
#end
|
|
69
|
+
each_dirty_class do |c|
|
|
70
|
+
c.clear_cache
|
|
71
|
+
c.check_ancestor_type
|
|
72
|
+
end
|
|
73
|
+
each_dirty_class do |c|
|
|
74
|
+
c.check_ancestors_link
|
|
75
|
+
end
|
|
76
|
+
each_dirty_entry do |x|
|
|
77
|
+
x.save
|
|
78
|
+
end
|
|
79
|
+
clear_dirty
|
|
80
|
+
save_completion_index
|
|
81
|
+
copy_doc
|
|
82
|
+
make_refs
|
|
83
|
+
refs().save(realpath('refs'))
|
|
84
|
+
end
|
|
85
|
+
private :commit
|
|
86
|
+
|
|
87
|
+
def dirty?
|
|
88
|
+
not @dirty_libraries.empty? or
|
|
89
|
+
not @dirty_classes.empty? or
|
|
90
|
+
not @dirty_methods.empty?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def each_dirty_entry(&block)
|
|
94
|
+
(@dirty_libraries.keys +
|
|
95
|
+
@dirty_classes.keys +
|
|
96
|
+
@dirty_methods.keys).each(&block)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def dirty_library(lib)
|
|
100
|
+
@dirty_libraries[lib] = true
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def each_dirty_library(&block)
|
|
104
|
+
@dirty_libraries.each_key(&block)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def dirty_class(c)
|
|
108
|
+
@dirty_classes[c] = true
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def each_dirty_class(&block)
|
|
112
|
+
@dirty_classes.each_key(&block)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def dirty_method(m)
|
|
116
|
+
@dirty_methods[m] = true
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def each_dirty_method(&block)
|
|
120
|
+
@dirty_methods.each_key(&block)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def clear_dirty
|
|
124
|
+
@dirty_libraries.clear
|
|
125
|
+
@dirty_classes.clear
|
|
126
|
+
@dirty_methods.clear
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def update_requires
|
|
130
|
+
libraries.each{|lib|
|
|
131
|
+
lib.requires = lib.all_requires
|
|
132
|
+
}
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def update_sublibraries
|
|
136
|
+
libraries.each{|lib|
|
|
137
|
+
re = /\A#{lib.name}\//
|
|
138
|
+
libraries.each{|l|
|
|
139
|
+
lib.sublibrary(l) if re =~ l.name
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def update_by_stdlibtree(root)
|
|
145
|
+
@root = root
|
|
146
|
+
parse_LIBRARIES("#{root}/LIBRARIES", properties()).each do |libname|
|
|
147
|
+
update_by_file "#{root}/#{libname}.rd", libname
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def parse_LIBRARIES(path, properties)
|
|
152
|
+
fopen(path, 'r:UTF-8') {|f|
|
|
153
|
+
BitClust::Preprocessor.wrap(f, properties).map {|line| line.strip }
|
|
154
|
+
}
|
|
155
|
+
end
|
|
156
|
+
private :parse_LIBRARIES
|
|
157
|
+
|
|
158
|
+
def update_by_file(path, libname)
|
|
159
|
+
check_transaction
|
|
160
|
+
RRDParser.new(self).parse_file(path, libname, properties())
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def refs
|
|
164
|
+
@refs ||= RefsDatabase.load(realpath('refs'))
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def make_refs
|
|
168
|
+
[classes, libraries, methods, docs].each do |es|
|
|
169
|
+
es.each do |e|
|
|
170
|
+
refs().extract(e)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
refs
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def copy_doc
|
|
177
|
+
Dir.glob("#{@root}/../../doc/**/*.rd").each do |f|
|
|
178
|
+
if %r!\A#{Regexp.escape(@root)}/\.\./\.\./doc/([-\./\w]+)\.rd\z! =~ f
|
|
179
|
+
id = libname2id($1)
|
|
180
|
+
se = DocEntry.new(self, id)
|
|
181
|
+
s = Preprocessor.read(f, properties)
|
|
182
|
+
title, source = RRDParser.split_doc(s)
|
|
183
|
+
se.title = title
|
|
184
|
+
se.source = source
|
|
185
|
+
se.save
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
#
|
|
191
|
+
# Doc Entry
|
|
192
|
+
#
|
|
193
|
+
|
|
194
|
+
def docs
|
|
195
|
+
docmap().values
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def docmap
|
|
199
|
+
@docmap ||= load_extent(DocEntry)
|
|
200
|
+
end
|
|
201
|
+
private :docmap
|
|
202
|
+
|
|
203
|
+
def get_doc(name)
|
|
204
|
+
id = libname2id(name)
|
|
205
|
+
docmap()[id] ||= DocEntry.new(self, id)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def fetch_doc(name)
|
|
209
|
+
docmap()[libname2id(name)] or
|
|
210
|
+
raise DocNotFound, "doc not found: #{name.inspect}"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
#
|
|
214
|
+
# Library Entry
|
|
215
|
+
#
|
|
216
|
+
|
|
217
|
+
def libraries
|
|
218
|
+
librarymap().values
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def librarymap
|
|
222
|
+
@librarymap ||= load_extent(LibraryEntry)
|
|
223
|
+
end
|
|
224
|
+
private :librarymap
|
|
225
|
+
|
|
226
|
+
def get_library(name)
|
|
227
|
+
id = libname2id(name)
|
|
228
|
+
librarymap()[id] ||= LibraryEntry.new(self, id)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def fetch_library(name)
|
|
232
|
+
librarymap()[libname2id(name)] or
|
|
233
|
+
raise LibraryNotFound, "library not found: #{name.inspect}"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def fetch_library_id(id)
|
|
237
|
+
librarymap()[id] or
|
|
238
|
+
raise LibraryNotFound, "library not found: #{id.inspect}"
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def open_library(name, reopen = false)
|
|
242
|
+
check_transaction
|
|
243
|
+
map = librarymap()
|
|
244
|
+
id = libname2id(name)
|
|
245
|
+
if lib = map[id]
|
|
246
|
+
lib.clear unless reopen
|
|
247
|
+
else
|
|
248
|
+
lib = (map[id] ||= LibraryEntry.new(self, id))
|
|
249
|
+
end
|
|
250
|
+
dirty_library lib
|
|
251
|
+
lib
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
#
|
|
255
|
+
# Classe Entry
|
|
256
|
+
#
|
|
257
|
+
|
|
258
|
+
def classes
|
|
259
|
+
classmap().values
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def classmap
|
|
263
|
+
return @classmap if @class_extent_loaded
|
|
264
|
+
id_extent(ClassEntry).each do |id|
|
|
265
|
+
@classmap[id] ||= ClassEntry.new(self, id)
|
|
266
|
+
end
|
|
267
|
+
@class_extent_loaded = true
|
|
268
|
+
@classmap
|
|
269
|
+
end
|
|
270
|
+
private :classmap
|
|
271
|
+
|
|
272
|
+
# get a class entry if it exists, or create a new class entry object
|
|
273
|
+
# if it doesn't exist.
|
|
274
|
+
def get_class(name)
|
|
275
|
+
if id = intern_classname(name)
|
|
276
|
+
load_class(id) or
|
|
277
|
+
raise "must not happen: #{name.inspect}, #{id.inspect}"
|
|
278
|
+
else
|
|
279
|
+
id = classname2id(name)
|
|
280
|
+
@classmap[id] ||= ClassEntry.new(self, id)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
# This method does not work in transaction.
|
|
285
|
+
def fetch_class(name)
|
|
286
|
+
id = intern_classname(name) or
|
|
287
|
+
raise ClassNotFound, "class not found: #{name.inspect}"
|
|
288
|
+
load_class(id) or
|
|
289
|
+
raise "must not happen: #{name.inspect}, #{id.inspect}"
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def fetch_class_id(id)
|
|
293
|
+
load_class(id) or
|
|
294
|
+
raise ClassNotFound, "class not found: #{id.inspect}"
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def search_classes(pattern)
|
|
298
|
+
cs = _search_classes(pattern)
|
|
299
|
+
if cs.empty?
|
|
300
|
+
raise ClassNotFound, "no such class: #{pattern}"
|
|
301
|
+
end
|
|
302
|
+
cs
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def open_class(name)
|
|
306
|
+
check_transaction
|
|
307
|
+
id = classname2id(name)
|
|
308
|
+
if exist?("class/#{id}")
|
|
309
|
+
c = load_class(id)
|
|
310
|
+
c.clear
|
|
311
|
+
else
|
|
312
|
+
c = (@classmap[id] ||= ClassEntry.new(self, id))
|
|
313
|
+
end
|
|
314
|
+
yield c
|
|
315
|
+
dirty_class c
|
|
316
|
+
c
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def load_class(id)
|
|
320
|
+
@classmap[id] ||=
|
|
321
|
+
begin
|
|
322
|
+
return nil unless exist?("class/#{id}")
|
|
323
|
+
ClassEntry.new(self, id)
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
private :load_class
|
|
327
|
+
|
|
328
|
+
def load_extent(entry_class)
|
|
329
|
+
h = {}
|
|
330
|
+
id_extent(entry_class).each do |id|
|
|
331
|
+
h[id] = entry_class.new(self, id)
|
|
332
|
+
end
|
|
333
|
+
h
|
|
334
|
+
end
|
|
335
|
+
private :load_extent
|
|
336
|
+
|
|
337
|
+
def id_extent(entry_class)
|
|
338
|
+
entries(entry_class.type_id.to_s)
|
|
339
|
+
end
|
|
340
|
+
private :id_extent
|
|
341
|
+
|
|
342
|
+
#
|
|
343
|
+
# Method Entry
|
|
344
|
+
#
|
|
345
|
+
|
|
346
|
+
# FIXME: see kind
|
|
347
|
+
def open_method(id)
|
|
348
|
+
check_transaction
|
|
349
|
+
if m = id.klass.get_method(id)
|
|
350
|
+
m.clear
|
|
351
|
+
else
|
|
352
|
+
m = MethodEntry.new(self, id.idstring)
|
|
353
|
+
id.klass.add_method m
|
|
354
|
+
end
|
|
355
|
+
m.library = id.library
|
|
356
|
+
m.klass = id.klass
|
|
357
|
+
yield m
|
|
358
|
+
dirty_method m
|
|
359
|
+
m
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def methods
|
|
363
|
+
classes().map {|c| c.entries }.flatten
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
def get_method(spec)
|
|
367
|
+
get_class(spec.klass).get_method(spec)
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def fetch_methods(spec)
|
|
371
|
+
fetch_class(spec.klass).fetch_methods(spec)
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
def fetch_method(spec)
|
|
375
|
+
fetch_class(spec.klass).fetch_method(spec)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def search_method(pattern)
|
|
379
|
+
search_methods(pattern).first
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def search_methods(pattern)
|
|
383
|
+
result = _search_methods(pattern)
|
|
384
|
+
if result.fail?
|
|
385
|
+
if result.classes.empty?
|
|
386
|
+
loc = pattern.klass ? pattern.klass + '.' : ''
|
|
387
|
+
raise MethodNotFound, "no such method: #{loc}#{pattern.method}"
|
|
388
|
+
end
|
|
389
|
+
if result.classes.size <= 5
|
|
390
|
+
loc = result.classes.map {|c| c.label }.join(', ')
|
|
391
|
+
else
|
|
392
|
+
loc = "#{result.classes.size} classes"
|
|
393
|
+
end
|
|
394
|
+
raise MethodNotFound, "no such method in #{loc}: #{pattern.method}"
|
|
395
|
+
end
|
|
396
|
+
result
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
end
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#
|
|
2
|
+
# bitclust/methodentry.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 method, a constant, and a special variable.
|
|
16
|
+
class MethodEntry < Entry
|
|
17
|
+
|
|
18
|
+
def MethodEntry.type_id
|
|
19
|
+
:method
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize(db, id)
|
|
23
|
+
super db
|
|
24
|
+
@id = id
|
|
25
|
+
init_properties
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
attr_reader :id
|
|
29
|
+
|
|
30
|
+
def ==(other)
|
|
31
|
+
@id == other.id
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
alias eql? ==
|
|
35
|
+
|
|
36
|
+
def hash
|
|
37
|
+
@id.hash
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def <=>(other)
|
|
41
|
+
sort_key() <=> other.sort_key
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
KIND_NUM = {:defined => 0, :redefined => 1, :added => 2}
|
|
45
|
+
|
|
46
|
+
def sort_key
|
|
47
|
+
[label(), KIND_NUM[kind()]]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def name
|
|
51
|
+
methodid2mname(@id)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# typename = :singleton_method
|
|
55
|
+
# | :instance_method
|
|
56
|
+
# | :module_function
|
|
57
|
+
# | :constant
|
|
58
|
+
# | :special_variable
|
|
59
|
+
def typename
|
|
60
|
+
methodid2typename(@id)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
alias type typename
|
|
64
|
+
|
|
65
|
+
def typemark
|
|
66
|
+
methodid2typemark(@id)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def typechar
|
|
70
|
+
methodid2typechar(@id)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def type_label
|
|
74
|
+
case typemark()
|
|
75
|
+
when '.' then 'singleton method'
|
|
76
|
+
when '#' then 'instance method'
|
|
77
|
+
when '.#' then 'module function'
|
|
78
|
+
when '::' then 'constant'
|
|
79
|
+
when '$' then 'variable'
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def library
|
|
84
|
+
@library ||= @db.fetch_library_id(methodid2libid(@id))
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
attr_writer :library
|
|
88
|
+
|
|
89
|
+
def klass
|
|
90
|
+
@klass ||= @db.fetch_class_id(methodid2classid(@id))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
attr_writer :klass
|
|
94
|
+
|
|
95
|
+
persistent_properties {
|
|
96
|
+
property :names, '[String]'
|
|
97
|
+
property :visibility, 'Symbol' # :public | :private | :protected
|
|
98
|
+
property :kind, 'Symbol' # :defined | :added | :redefined
|
|
99
|
+
property :source, 'String'
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
def inspect
|
|
103
|
+
c, t, m, lib = methodid2specparts(@id)
|
|
104
|
+
"\#<method #{c}#{t}#{names().join(',')}>"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def spec
|
|
108
|
+
MethodSpec.new(*methodid2specparts(@id))
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def spec_string
|
|
112
|
+
methodid2specstring(@id)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def label
|
|
116
|
+
c, t, m, lib = methodid2specparts(@id)
|
|
117
|
+
"#{t == '$' ? '' : c}#{t}#{m}"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def short_label
|
|
121
|
+
c, t, m, lib = methodid2specparts(@id)
|
|
122
|
+
"#{t == '#' ? '' : t}#{m}"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def labels
|
|
126
|
+
c, t, m, lib = methodid2specparts(@id)
|
|
127
|
+
names().map {|name| "#{c}#{t}#{name}" }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def name?(name)
|
|
131
|
+
names().include?(name)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def name_match?(re)
|
|
135
|
+
names().any? {|n| re =~ n }
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def really_public?
|
|
139
|
+
visibility() == :public
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def public?
|
|
143
|
+
visibility() != :private
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def protected?
|
|
147
|
+
visibility() == :protected
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def private?
|
|
151
|
+
visibility() == :private
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def public_singleton_method?
|
|
155
|
+
singleton_method? and public?
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def private_singleton_method?
|
|
159
|
+
singleton_method? and private?
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def public_instance_method?
|
|
163
|
+
instance_method? and public?
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def private_instance_method?
|
|
167
|
+
instance_method? and public?
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def singleton_method?
|
|
171
|
+
t = typename()
|
|
172
|
+
t == :singleton_method or t == :module_function
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def instance_method?
|
|
176
|
+
t = typename()
|
|
177
|
+
t == :instance_method or t == :module_function
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def constant?
|
|
181
|
+
typename() == :constant
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def special_variable?
|
|
185
|
+
typename() == :special_variable
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def defined?
|
|
189
|
+
kind() == :defined
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def added?
|
|
193
|
+
kind() == :added
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def redefined?
|
|
197
|
+
kind() == :redefined
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
end
|