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,522 @@
|
|
|
1
|
+
#
|
|
2
|
+
# bitclust/rrdparser.rb
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2006-2007 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/compat'
|
|
11
|
+
require 'bitclust/preprocessor'
|
|
12
|
+
require 'bitclust/methodid'
|
|
13
|
+
require 'bitclust/lineinput'
|
|
14
|
+
require 'bitclust/parseutils'
|
|
15
|
+
require 'bitclust/nameutils'
|
|
16
|
+
require 'bitclust/exception'
|
|
17
|
+
require 'bitclust/methoddatabase'
|
|
18
|
+
|
|
19
|
+
module BitClust
|
|
20
|
+
|
|
21
|
+
class RRDParser
|
|
22
|
+
|
|
23
|
+
include NameUtils
|
|
24
|
+
include ParseUtils
|
|
25
|
+
|
|
26
|
+
def RRDParser.parse_stdlib_file(path, params = {"version" => "1.9.0"})
|
|
27
|
+
parser = new(MethodDatabase.dummy(params))
|
|
28
|
+
parser.parse_file(path, libname(path), params)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def RRDParser.parse(s, lib, params = {"version" => "1.9.0"})
|
|
32
|
+
parser = new(MethodDatabase.dummy(params))
|
|
33
|
+
if s.respond_to?(:to_io)
|
|
34
|
+
io = s.to_io
|
|
35
|
+
elsif s.respond_to?(:to_str)
|
|
36
|
+
s1 = s.to_str
|
|
37
|
+
require 'stringio'
|
|
38
|
+
io = StringIO.new(s1)
|
|
39
|
+
else
|
|
40
|
+
io = s
|
|
41
|
+
end
|
|
42
|
+
l = parser.parse(io, lib, params)
|
|
43
|
+
return l, parser.db
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def RRDParser.split_doc(source)
|
|
47
|
+
if m = /^=(\[a:.*?\])?( +(.*)|([^=].*))\r?\n/.match(source)
|
|
48
|
+
title = $3 || $4
|
|
49
|
+
s = m.post_match
|
|
50
|
+
return title, s
|
|
51
|
+
end
|
|
52
|
+
return ["", source]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def RRDParser.libname(path)
|
|
56
|
+
case path
|
|
57
|
+
when %r<(\A|/)_builtin/>
|
|
58
|
+
'_builtin'
|
|
59
|
+
else
|
|
60
|
+
path.sub(%r<\A(.*/)?src/>, '').sub(/\.rd(\.off)?\z/, '')
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
private_class_method :libname
|
|
64
|
+
|
|
65
|
+
def initialize(db)
|
|
66
|
+
@db = db
|
|
67
|
+
end
|
|
68
|
+
attr_reader :db
|
|
69
|
+
|
|
70
|
+
def parse_file(path, libname, params = {})
|
|
71
|
+
fopen(path, 'r:UTF-8') {|f|
|
|
72
|
+
return parse(f, libname, params)
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def parse(f, libname, params = {})
|
|
77
|
+
@context = Context.new(@db, libname)
|
|
78
|
+
f = LineInput.new(Preprocessor.wrap(f, params))
|
|
79
|
+
do_parse f
|
|
80
|
+
@context.library
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def do_parse(f)
|
|
86
|
+
f.skip_blank_lines
|
|
87
|
+
f.while_match(/\Arequire\s/) do |line|
|
|
88
|
+
@context.require line.split[1]
|
|
89
|
+
end
|
|
90
|
+
f.skip_blank_lines
|
|
91
|
+
f.while_match(/\Asublibrary\s/) do |line|
|
|
92
|
+
@context.sublibrary line.split[1]
|
|
93
|
+
end
|
|
94
|
+
f.skip_blank_lines
|
|
95
|
+
@context.library.source = f.break(/\A==?[^=]|\A---/).join('').rstrip
|
|
96
|
+
read_classes f
|
|
97
|
+
if line = f.gets # error
|
|
98
|
+
case line
|
|
99
|
+
when /\A==[^=]/
|
|
100
|
+
parse_error "met level-2 header in library document; maybe you forgot level-1 header", line
|
|
101
|
+
when /\A---/
|
|
102
|
+
parse_error "met bare method entry in library document; maybe you forgot reopen/redefine level-1 header", line
|
|
103
|
+
else
|
|
104
|
+
parse_error "unexpected line in library document", line
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def read_classes(f)
|
|
110
|
+
f.while_match(/\A=[^=]/) do |line|
|
|
111
|
+
type, name, superclass = *parse_level1_header(line)
|
|
112
|
+
case type
|
|
113
|
+
when 'class'
|
|
114
|
+
@context.define_class name, (superclass || 'Object')
|
|
115
|
+
read_class_body f
|
|
116
|
+
when 'module'
|
|
117
|
+
parse_error "superclass given for module", line if superclass
|
|
118
|
+
@context.define_module name
|
|
119
|
+
read_class_body f
|
|
120
|
+
when 'object'
|
|
121
|
+
if superclass
|
|
122
|
+
# FIXME
|
|
123
|
+
tty_warn "#{line.location}: singleton object class not implemented yet"
|
|
124
|
+
end
|
|
125
|
+
@context.define_object name
|
|
126
|
+
read_object_body f
|
|
127
|
+
when 'reopen'
|
|
128
|
+
@context.reopen_class name
|
|
129
|
+
read_reopen_body f
|
|
130
|
+
when 'redefine'
|
|
131
|
+
@context.redefine_class name
|
|
132
|
+
read_reopen_body f
|
|
133
|
+
else
|
|
134
|
+
parse_error "wrong level-1 header", line
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def parse_level1_header(line)
|
|
140
|
+
m = /\A(\S+)\s*([^\s<]+)(?:\s*<\s*(\S+))?\z/.match(line.sub(/\A=/, '').strip)
|
|
141
|
+
unless m
|
|
142
|
+
parse_error "level-1 header syntax error", line
|
|
143
|
+
end
|
|
144
|
+
return m[1], isconst(m[2], line), isconst(m[3], line)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def isconst(name, line)
|
|
148
|
+
return nil unless name
|
|
149
|
+
unless /\A#{CLASS_PATH_RE}\z/o =~ name
|
|
150
|
+
raise ParseError, "#{line.location}: not a constant: #{name.inspect}"
|
|
151
|
+
end
|
|
152
|
+
name
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def read_class_body(f)
|
|
156
|
+
f.skip_blank_lines
|
|
157
|
+
read_aliases f
|
|
158
|
+
f.skip_blank_lines
|
|
159
|
+
read_extends f
|
|
160
|
+
read_includes f
|
|
161
|
+
f.skip_blank_lines
|
|
162
|
+
@context.klass.source = f.break(/\A==?[^=]|\A---/).join('').rstrip
|
|
163
|
+
read_level2_blocks f
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def read_reopen_body(f)
|
|
167
|
+
f.skip_blank_lines
|
|
168
|
+
read_extends f, true
|
|
169
|
+
read_includes f, true
|
|
170
|
+
f.skip_blank_lines
|
|
171
|
+
read_level2_blocks f
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def read_object_body(f)
|
|
175
|
+
f.skip_blank_lines
|
|
176
|
+
read_aliases f
|
|
177
|
+
f.skip_blank_lines
|
|
178
|
+
read_extends f
|
|
179
|
+
f.skip_blank_lines
|
|
180
|
+
@context.klass.source = f.break(/\A=|\A---/).join('').rstrip
|
|
181
|
+
@context.visibility = :public
|
|
182
|
+
@context.type = :singleton_method
|
|
183
|
+
read_entries f
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def read_aliases(f)
|
|
187
|
+
f.while_match(/\Aalias\s/) do |line|
|
|
188
|
+
@context.alias line.split[1]
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def read_includes(f, reopen = false)
|
|
193
|
+
f.while_match(/\Ainclude\s/) do |line|
|
|
194
|
+
tty_warn "#{line.location}: dynamic include is not implemented yet" if reopen
|
|
195
|
+
@context.include line.split[1] unless reopen # FIXME
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def read_extends(f, reopen = false)
|
|
200
|
+
f.while_match(/\Aextend\s/) do |line|
|
|
201
|
+
tty_warn "#{line.location}: dynamic extend is not implemented yet" if reopen
|
|
202
|
+
@context.extend line.split[1] unless reopen # FIXME
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def tty_warn(msg)
|
|
207
|
+
$stderr.puts msg if $stderr.tty?
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def read_level2_blocks(f)
|
|
211
|
+
read_entries f
|
|
212
|
+
f.skip_blank_lines
|
|
213
|
+
f.while_match(/\A==[^=]/) do |line|
|
|
214
|
+
case line.sub(/\A==/, '').strip
|
|
215
|
+
when /\A((?:public|private|protected)\s+)?(?:(class|singleton|instance)\s+)?methods?\z/i
|
|
216
|
+
@context.visibility = ($1 || 'public').downcase.intern
|
|
217
|
+
t = ($2 || 'instance').downcase.sub(/class/, 'singleton')
|
|
218
|
+
@context.type = "#{t}_method".intern
|
|
219
|
+
when /\AModule\s+Functions?\z/i
|
|
220
|
+
@context.module_function
|
|
221
|
+
when /\AConstants?\z/i
|
|
222
|
+
@context.constant
|
|
223
|
+
when /\ASpecial\s+Variables?\z/i
|
|
224
|
+
@context.special_variable
|
|
225
|
+
else
|
|
226
|
+
parse_error "unknown level-2 header", line
|
|
227
|
+
end
|
|
228
|
+
read_entries f
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def read_entries(f)
|
|
233
|
+
concat_aliases(read_chunks(f)).each do |chunk|
|
|
234
|
+
@context.define_method chunk
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def concat_aliases(chunks)
|
|
239
|
+
return [] if chunks.empty?
|
|
240
|
+
result = [chunks.shift]
|
|
241
|
+
chunks.each do |chunk|
|
|
242
|
+
if result.last.alias?(chunk)
|
|
243
|
+
result.last.unify chunk
|
|
244
|
+
else
|
|
245
|
+
result.push chunk
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
result
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def read_chunks(f)
|
|
252
|
+
f.skip_blank_lines
|
|
253
|
+
result = []
|
|
254
|
+
f.while_match(/\A---/) do |line|
|
|
255
|
+
f.ungets line
|
|
256
|
+
result.push read_chunk(f)
|
|
257
|
+
end
|
|
258
|
+
result
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def read_chunk(f)
|
|
262
|
+
header = f.span(/\A---/)
|
|
263
|
+
body = f.break(/\A(?:---|={1,2}[^=])/)
|
|
264
|
+
src = (header + body).join('')
|
|
265
|
+
src.location = header[0].location
|
|
266
|
+
sigs = header.map {|line| method_signature(line) }
|
|
267
|
+
mainsig = check_chunk_signatures(sigs, header[0])
|
|
268
|
+
names = sigs.map {|s| s.name }.uniq.sort
|
|
269
|
+
Chunk.new(mainsig, names, src)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def check_chunk_signatures(sigs, line)
|
|
273
|
+
cxt = @context.signature
|
|
274
|
+
if cxt and cxt.fully_qualified?
|
|
275
|
+
if bad = sigs.detect {|sig| not cxt.compatible?(sig) }
|
|
276
|
+
parse_error "signature crash: `#{cxt}' given by level-1/2 header but method entry has a signature `#{bad}'; remove level-1/2 header or modify method entry", line
|
|
277
|
+
end
|
|
278
|
+
cxt
|
|
279
|
+
else
|
|
280
|
+
sig = sigs[0]
|
|
281
|
+
unless sig.fully_qualified?
|
|
282
|
+
if not cxt
|
|
283
|
+
parse_error "missing class and type; give full signature for method entry", line
|
|
284
|
+
elsif not cxt.type
|
|
285
|
+
parse_error "missing type: write level-2 header", line
|
|
286
|
+
elsif not cxt.klass
|
|
287
|
+
raise "must not happen: type given but class not exist: context=#{cxt}, entry=#{sig}"
|
|
288
|
+
else
|
|
289
|
+
raise "must not happen: context=#{cxt}, entry=#{sig}"
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
if cxt
|
|
293
|
+
unless sig.compatible?(cxt)
|
|
294
|
+
parse_error "signature crash: #{cxt} given by level-1/2 but method entry has a signature #{sig}; remove level-1/2 header or modify method entry", line
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
unless sigs.all? {|s| sig.same_type?(s) }
|
|
298
|
+
parse_error "alias entries have different class/type", line
|
|
299
|
+
end
|
|
300
|
+
sig
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
SIGNATURE = /\A---\s*(?:(#{CLASS_PATH_RE})(#{TYPEMARK_RE}))?(#{METHOD_NAME_RE})/
|
|
305
|
+
GVAR = /\A---\s*(#{GVAR_RE})/
|
|
306
|
+
|
|
307
|
+
def method_signature(line)
|
|
308
|
+
case
|
|
309
|
+
when m = SIGNATURE.match(line)
|
|
310
|
+
Signature.new(*m.captures)
|
|
311
|
+
when m = GVAR.match(line)
|
|
312
|
+
Signature.new(nil, '$', m[1][1..-1])
|
|
313
|
+
else
|
|
314
|
+
parse_error "wrong method signature", line
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
class Context
|
|
319
|
+
include NameUtils
|
|
320
|
+
|
|
321
|
+
def initialize(db, libname)
|
|
322
|
+
@db = db
|
|
323
|
+
#@library = @db.open_library(libname)
|
|
324
|
+
@library = @db.open_library(libname, true) # FIXME: always reopen
|
|
325
|
+
@klass = nil
|
|
326
|
+
@type = nil
|
|
327
|
+
@visibility = nil
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
attr_reader :library
|
|
331
|
+
attr_reader :klass
|
|
332
|
+
attr_accessor :type
|
|
333
|
+
attr_accessor :visibility
|
|
334
|
+
|
|
335
|
+
def require(libname)
|
|
336
|
+
@library.require @db.get_library(libname)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def sublibrary(libname)
|
|
340
|
+
@library.sublibrary @db.get_library(libname)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def define_class(name, supername)
|
|
344
|
+
if @db.properties['version'] >= "1.9.0"
|
|
345
|
+
top = 'BasicObject'
|
|
346
|
+
else
|
|
347
|
+
top = 'Object'
|
|
348
|
+
end
|
|
349
|
+
superclass = (name == top ? nil : @db.get_class(supername))
|
|
350
|
+
register_class :class, name, superclass
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def define_module(name)
|
|
354
|
+
register_class :module, name, nil
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def define_object(name)
|
|
358
|
+
register_class :object, name, nil
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def register_class(type, name, superclass)
|
|
362
|
+
@klass = @db.open_class(name) {|c|
|
|
363
|
+
c.type = type
|
|
364
|
+
c.superclass = superclass
|
|
365
|
+
c.library = @library
|
|
366
|
+
@library.add_class c
|
|
367
|
+
}
|
|
368
|
+
@kind = :defined
|
|
369
|
+
clear_scope
|
|
370
|
+
end
|
|
371
|
+
private :register_class
|
|
372
|
+
|
|
373
|
+
def clear_scope
|
|
374
|
+
@type = nil
|
|
375
|
+
@visibility = nil
|
|
376
|
+
end
|
|
377
|
+
private :clear_scope
|
|
378
|
+
|
|
379
|
+
def reopen_class(name)
|
|
380
|
+
@kind = :added
|
|
381
|
+
@klass = name ? @db.get_class(name) : nil
|
|
382
|
+
clear_scope
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def redefine_class(name)
|
|
386
|
+
@kind = :redefined
|
|
387
|
+
@klass = name ? @db.get_class(name) : nil
|
|
388
|
+
clear_scope
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
def include(name)
|
|
392
|
+
@klass.include @db.get_class(name)
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def extend(name)
|
|
396
|
+
@klass.extend @db.get_class(name)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# Add a alias +name+ to the alias list.
|
|
400
|
+
def alias(name)
|
|
401
|
+
@db.open_class(name) do |c|
|
|
402
|
+
c.type = @klass.type
|
|
403
|
+
c.library = @library
|
|
404
|
+
c.aliasof = @klass
|
|
405
|
+
c.source = "Alias of [[c:#{@klass.name}]]\n"
|
|
406
|
+
@library.add_class c
|
|
407
|
+
@klass.alias c
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def module_function
|
|
412
|
+
@type = :module_function
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def constant
|
|
416
|
+
@type = :constant
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
def special_variable
|
|
420
|
+
unless @klass and @klass.name == 'Kernel'
|
|
421
|
+
raise "must not happen: type=special_variable but class!=Kernel"
|
|
422
|
+
end
|
|
423
|
+
@type = :special_variable
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def signature
|
|
427
|
+
return nil unless @klass
|
|
428
|
+
Signature.new(@klass.name, @type ? typename2mark(@type) : nil, nil)
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def define_method(chunk)
|
|
432
|
+
id = method_id(chunk)
|
|
433
|
+
@db.open_method(id) {|m|
|
|
434
|
+
m.names = chunk.names.sort
|
|
435
|
+
m.kind = @kind
|
|
436
|
+
m.visibility = @visibility || :public
|
|
437
|
+
m.source = chunk.source
|
|
438
|
+
case @kind
|
|
439
|
+
when :added, :redefined
|
|
440
|
+
@library.add_method m
|
|
441
|
+
end
|
|
442
|
+
}
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
def method_id(chunk)
|
|
446
|
+
id = MethodID.new
|
|
447
|
+
id.library = @library
|
|
448
|
+
id.klass = chunk.signature.klass ? @db.get_class(chunk.signature.klass) : @klass
|
|
449
|
+
id.type = chunk.signature.typename || @type
|
|
450
|
+
id.name = chunk.names.sort.first
|
|
451
|
+
id
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
class Chunk
|
|
456
|
+
def initialize(signature, names, source)
|
|
457
|
+
@signature = signature
|
|
458
|
+
@names = names
|
|
459
|
+
@source = source
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
attr_reader :signature
|
|
463
|
+
attr_reader :names
|
|
464
|
+
attr_reader :source
|
|
465
|
+
|
|
466
|
+
def inspect
|
|
467
|
+
"\#<Chunk #{@signature.klass}#{@signature.type}#{@names.join(',')} #{@source.location}>"
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
def alias?(other)
|
|
471
|
+
@signature.compatible?(other.signature) and
|
|
472
|
+
not (@names & other.names).empty?
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
def unify(other)
|
|
476
|
+
@names |= other.names
|
|
477
|
+
@source << other.source
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
class Signature
|
|
482
|
+
include NameUtils
|
|
483
|
+
|
|
484
|
+
def initialize(c, t, m)
|
|
485
|
+
@klass = c # String
|
|
486
|
+
@type = t
|
|
487
|
+
@name = m
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
attr_reader :klass
|
|
491
|
+
attr_reader :type
|
|
492
|
+
attr_reader :name
|
|
493
|
+
|
|
494
|
+
def inspect
|
|
495
|
+
"\#<signature #{to_s()}>"
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
def to_s
|
|
499
|
+
"#{@klass || '_'}#{@type || ' _ '}#{@name}"
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
def typename
|
|
503
|
+
typemark2name(@type)
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
def same_type?(other)
|
|
507
|
+
@klass == other.klass and @type == other.type
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
def compatible?(other)
|
|
511
|
+
(not @klass or not other.klass or @klass == other.klass) and
|
|
512
|
+
(not @type or not other.type or @type == other.type)
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
def fully_qualified?
|
|
516
|
+
(@klass and @type) ? true : false
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
end
|