bitclust-core 1.3.0 → 1.6.1
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.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/README.md +65 -0
- data/Rakefile +32 -0
- data/data/bitclust/catalog/ja_JP.UTF-8 +19 -1
- data/data/bitclust/searchpage/index.html +90 -0
- data/data/bitclust/template/class +69 -8
- data/data/bitclust/template/function +2 -2
- data/data/bitclust/template/layout +11 -3
- data/data/bitclust/template/method +2 -2
- data/data/bitclust/template/search +1 -1
- data/data/bitclust/template.epub/class +22 -1
- data/data/bitclust/template.epub/function +2 -2
- data/data/bitclust/template.epub/layout +1 -3
- data/data/bitclust/template.epub/method +2 -2
- data/data/bitclust/template.lillia/class +26 -5
- data/data/bitclust/template.lillia/layout +1 -3
- data/data/bitclust/template.lillia/method +2 -2
- data/data/bitclust/template.offline/class +48 -4
- data/data/bitclust/template.offline/function +2 -2
- data/data/bitclust/template.offline/layout +27 -3
- data/data/bitclust/template.offline/method +2 -2
- data/lib/bitclust/app.rb +16 -17
- data/lib/bitclust/capi_converter.rb +20 -0
- data/lib/bitclust/classentry.rb +67 -17
- data/lib/bitclust/compat.rb +2 -2
- data/lib/bitclust/completion.rb +58 -27
- data/lib/bitclust/crossrubyutils.rb +8 -5
- data/lib/bitclust/database.rb +28 -8
- data/lib/bitclust/doc_converter.rb +63 -0
- data/lib/bitclust/docentry.rb +1 -1
- data/lib/bitclust/entity_splitter.rb +221 -0
- data/lib/bitclust/entry.rb +47 -7
- data/lib/bitclust/functiondatabase.rb +13 -1
- data/lib/bitclust/functionentry.rb +5 -1
- data/lib/bitclust/functionreferenceparser.rb +4 -4
- data/lib/bitclust/generators/epub.rb +10 -3
- data/lib/bitclust/htmlutils.rb +1 -1
- data/lib/bitclust/include_graph.rb +375 -0
- data/lib/bitclust/include_pruner.rb +144 -0
- data/lib/bitclust/interface.rb +1 -1
- data/lib/bitclust/libraryentry.rb +8 -7
- data/lib/bitclust/lineinput.rb +7 -5
- data/lib/bitclust/link_checker.rb +179 -0
- data/lib/bitclust/markdown_bridge.rb +186 -0
- data/lib/bitclust/markdown_orchestrator.rb +267 -0
- data/lib/bitclust/markdown_to_rrd.rb +824 -0
- data/lib/bitclust/markdown_tree.rb +217 -0
- data/lib/bitclust/mdcompiler.rb +883 -0
- data/lib/bitclust/mdparser.rb +347 -0
- data/lib/bitclust/messagecatalog.rb +3 -3
- data/lib/bitclust/method_since_calculator.rb +117 -0
- data/lib/bitclust/methoddatabase.rb +128 -14
- data/lib/bitclust/methodentry.rb +125 -7
- data/lib/bitclust/methodid.rb +12 -11
- data/lib/bitclust/methodsignature.rb +10 -4
- data/lib/bitclust/nameutils.rb +41 -22
- data/lib/bitclust/preprocessor.rb +66 -29
- data/lib/bitclust/rdcompiler.rb +195 -95
- data/lib/bitclust/refsdatabase.rb +23 -8
- data/lib/bitclust/reloadable_request_handler.rb +72 -0
- data/lib/bitclust/requesthandler.rb +21 -16
- data/lib/bitclust/ridatabase.rb +10 -4
- data/lib/bitclust/rrd_to_markdown.rb +925 -0
- data/lib/bitclust/rrdparser.rb +196 -30
- data/lib/bitclust/runner.rb +17 -2
- data/lib/bitclust/screen.rb +80 -11
- data/lib/bitclust/search_index_generator.rb +288 -0
- data/lib/bitclust/searcher.rb +69 -20
- data/lib/bitclust/simplesearcher.rb +24 -12
- data/lib/bitclust/subcommand.rb +7 -1
- data/lib/bitclust/subcommands/ancestors_command.rb +9 -2
- data/lib/bitclust/subcommands/checklink_command.rb +54 -0
- data/lib/bitclust/subcommands/chm_command.rb +15 -7
- data/lib/bitclust/subcommands/classes_command.rb +5 -0
- data/lib/bitclust/subcommands/extract_command.rb +5 -0
- data/lib/bitclust/subcommands/htmlfile_command.rb +21 -7
- data/lib/bitclust/subcommands/init_command.rb +4 -1
- data/lib/bitclust/subcommands/list_command.rb +12 -4
- data/lib/bitclust/subcommands/lookup_command.rb +28 -9
- data/lib/bitclust/subcommands/methods_command.rb +10 -2
- data/lib/bitclust/subcommands/methodsince_command.rb +80 -0
- data/lib/bitclust/subcommands/preproc_command.rb +5 -0
- data/lib/bitclust/subcommands/property_command.rb +2 -1
- data/lib/bitclust/subcommands/searchpage_command.rb +102 -0
- data/lib/bitclust/subcommands/server_command.rb +10 -8
- data/lib/bitclust/subcommands/setup_command.rb +24 -10
- data/lib/bitclust/subcommands/statichtml_command.rb +129 -6
- data/lib/bitclust/subcommands/update_command.rb +110 -2
- data/lib/bitclust/syntax_highlighter.rb +48 -4
- data/lib/bitclust/textutils.rb +3 -3
- data/lib/bitclust/version.rb +1 -1
- data/lib/bitclust/version_badges.rb +90 -0
- data/lib/bitclust/whole_file_gate.rb +137 -0
- data/test/test_app.rb +269 -0
- data/test/test_bitclust.rb +2 -0
- data/test/test_capi_converter.rb +91 -0
- data/test/test_class_screen.rb +413 -0
- data/test/test_copy_doc_md.rb +53 -0
- data/test/test_doc_converter.rb +78 -0
- data/test/test_entity_splitter.rb +231 -0
- data/test/test_entry.rb +207 -2
- data/test/test_eol_warning.rb +43 -0
- data/test/test_functionreferenceparser.rb +11 -0
- data/test/test_include_graph.rb +640 -0
- data/test/test_include_pruner.rb +133 -0
- data/test/test_link_checker.rb +114 -0
- data/test/test_lookup_command.rb +135 -0
- data/test/test_markdown_bridge.rb +217 -0
- data/test/test_markdown_orchestrator.rb +478 -0
- data/test/test_markdown_to_rrd.rb +757 -0
- data/test/test_markdown_tree.rb +369 -0
- data/test/test_mdcompiler.rb +1276 -0
- data/test/test_mdparser.rb +573 -0
- data/test/test_method_screen.rb +166 -0
- data/test/test_method_since_calculator.rb +290 -0
- data/test/test_methoddatabase.rb +16 -0
- data/test/test_methodentry.rb +328 -0
- data/test/test_methodsignature.rb +3 -1
- data/test/test_methodsince_command.rb +168 -0
- data/test/test_nameutils.rb +22 -0
- data/test/test_preprocessor.rb +215 -0
- data/test/test_rdcompiler.rb +401 -30
- data/test/test_refsdatabase.rb +32 -0
- data/test/test_rrd_to_markdown.rb +968 -0
- data/test/test_rrdparser.rb +295 -2
- data/test/test_run_ruby_wasm.rb +54 -0
- data/test/test_run_worker_prelude.rb +83 -0
- data/test/test_runner.rb +51 -0
- data/test/test_search_index_generator.rb +513 -0
- data/test/test_search_screen.rb +48 -0
- data/test/test_searcher.rb +132 -0
- data/test/test_searchpage_command.rb +167 -0
- data/test/test_simplesearcher.rb +28 -0
- data/test/test_statichtml_command.rb +204 -0
- data/test/test_syntax_highlighter.rb +60 -0
- data/test/test_whole_file_gate.rb +175 -0
- data/theme/default/js/NOTICE +42 -0
- data/theme/default/js/run-worker.js +111 -0
- data/theme/default/js/run.js +350 -0
- data/theme/default/js/search_controller.js +134 -0
- data/theme/default/js/search_init.js +176 -0
- data/theme/default/js/search_navigation.js +110 -0
- data/theme/default/js/search_page.js +202 -0
- data/theme/default/js/search_ranker.js +244 -0
- data/theme/default/script.js +91 -18
- data/theme/default/search.css +149 -0
- data/theme/default/style.css +193 -21
- data/theme/default/syntax-highlight.css +8 -0
- data/theme/lillia/style.css +45 -1
- metadata +161 -20
- data/README +0 -32
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'bitclust'
|
|
3
|
+
require 'bitclust/methoddatabase'
|
|
4
|
+
require 'tmpdir'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
class TestMethodEntryTitleLabels < Test::Unit::TestCase
|
|
8
|
+
def test_title_labels_matches_label_when_no_alias
|
|
9
|
+
lib, db = BitClust::RRDParser.parse(<<HERE, 'dummy')
|
|
10
|
+
= class Enumerable2
|
|
11
|
+
== Instance Methods
|
|
12
|
+
--- select -> Array
|
|
13
|
+
|
|
14
|
+
説明のためのエントリ
|
|
15
|
+
HERE
|
|
16
|
+
_ = lib
|
|
17
|
+
m = db.get_method(BitClust::MethodSpec.parse('Enumerable2#select'))
|
|
18
|
+
assert_equal(['Enumerable2#select'], m.title_labels)
|
|
19
|
+
assert_equal(m.label, m.title_labels.join(', '))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_title_labels_lists_every_alias
|
|
23
|
+
lib, db = BitClust::RRDParser.parse(<<HERE, 'dummy')
|
|
24
|
+
= class Enumerable2
|
|
25
|
+
== Instance Methods
|
|
26
|
+
--- collect -> Array
|
|
27
|
+
--- map -> Array
|
|
28
|
+
|
|
29
|
+
説明のためのエントリ
|
|
30
|
+
HERE
|
|
31
|
+
_ = lib
|
|
32
|
+
m = db.get_method(BitClust::MethodSpec.parse('Enumerable2#collect'))
|
|
33
|
+
assert_equal(['Enumerable2#collect', 'Enumerable2#map'], m.title_labels)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# #label omits the class prefix for special variables (e.g. "$;", not
|
|
37
|
+
# "Kernel$;"); #title_labels must keep that convention for every alias,
|
|
38
|
+
# unlike #labels which always includes the prefix.
|
|
39
|
+
def test_title_labels_omits_class_prefix_for_special_variables
|
|
40
|
+
lib, db = BitClust::RRDParser.parse(<<HERE, 'dummy')
|
|
41
|
+
= module Kernel
|
|
42
|
+
description
|
|
43
|
+
== Special Variables
|
|
44
|
+
--- $;
|
|
45
|
+
--- $FIELD_SEPARATOR
|
|
46
|
+
|
|
47
|
+
区切り文字。
|
|
48
|
+
HERE
|
|
49
|
+
_ = lib
|
|
50
|
+
m = db.get_method(BitClust::MethodSpec.parse('Kernel$;'))
|
|
51
|
+
assert_equal('$;', m.label)
|
|
52
|
+
assert_equal(['$;', '$FIELD_SEPARATOR'], m.title_labels)
|
|
53
|
+
assert_equal(['Kernel$;', 'Kernel$FIELD_SEPARATOR'], m.labels)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_title_labels_matches_label_for_single_special_variable
|
|
57
|
+
lib, db = BitClust::RRDParser.parse(<<HERE, 'dummy')
|
|
58
|
+
= module Kernel
|
|
59
|
+
description
|
|
60
|
+
== Special Variables
|
|
61
|
+
--- $stdout -> IO
|
|
62
|
+
|
|
63
|
+
標準出力。
|
|
64
|
+
HERE
|
|
65
|
+
_ = lib
|
|
66
|
+
m = db.get_method(BitClust::MethodSpec.parse('Kernel$stdout'))
|
|
67
|
+
assert_equal(['$stdout'], m.title_labels)
|
|
68
|
+
assert_equal(m.label, m.title_labels.join(', '))
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# bitclust#250: Ruby 4.0 以降のドキュメントでは module function の表記を
|
|
73
|
+
# 独自の「.#」から「?.」に変える(表示のみ。識別子は変えない)。
|
|
74
|
+
#
|
|
75
|
+
# label/short_label/labels/title_labels 自身は refsdatabase.rb の
|
|
76
|
+
# [[a:...]] アンカー解決キー(labels)や `bitclust methods --diff` の
|
|
77
|
+
# expand_mf マッチング(labels)が literal ".#" を前提にしているため、
|
|
78
|
+
# 一切変更しない。表示用には display_label/display_short_label/
|
|
79
|
+
# display_title_labels/display_typemark を新設し、テンプレート側の
|
|
80
|
+
# 実際の表示箇所だけがそちらを呼ぶようにする。
|
|
81
|
+
class TestMethodEntryDisplayTypemark < Test::Unit::TestCase
|
|
82
|
+
SRC = <<HERE
|
|
83
|
+
= module Kernel
|
|
84
|
+
description
|
|
85
|
+
== Module Functions
|
|
86
|
+
--- mf
|
|
87
|
+
--- mf2
|
|
88
|
+
|
|
89
|
+
説明
|
|
90
|
+
|
|
91
|
+
== Instance Methods
|
|
92
|
+
--- im
|
|
93
|
+
|
|
94
|
+
説明
|
|
95
|
+
|
|
96
|
+
== Special Variables
|
|
97
|
+
--- $stdout -> IO
|
|
98
|
+
|
|
99
|
+
標準出力。
|
|
100
|
+
HERE
|
|
101
|
+
|
|
102
|
+
def build(version)
|
|
103
|
+
_lib, db = BitClust::RRDParser.parse(SRC, 'testlib', {'version' => version})
|
|
104
|
+
db
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def test_module_function_display_stays_dot_hash_before_4_0
|
|
108
|
+
db = build('3.4')
|
|
109
|
+
m = db.get_method(BitClust::MethodSpec.parse('Kernel.#mf'))
|
|
110
|
+
assert_equal('.#', m.display_typemark)
|
|
111
|
+
assert_equal('Kernel.#mf', m.display_label)
|
|
112
|
+
assert_equal('.#mf', m.display_short_label)
|
|
113
|
+
assert_equal(['Kernel.#mf', 'Kernel.#mf2'], m.display_title_labels)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def test_module_function_display_switches_to_question_dot_at_4_0
|
|
117
|
+
db = build('4.0')
|
|
118
|
+
m = db.get_method(BitClust::MethodSpec.parse('Kernel.#mf'))
|
|
119
|
+
assert_equal('?.', m.display_typemark)
|
|
120
|
+
assert_equal('Kernel?.mf', m.display_label)
|
|
121
|
+
assert_equal('?.mf', m.display_short_label)
|
|
122
|
+
assert_equal(['Kernel?.mf', 'Kernel?.mf2'], m.display_title_labels)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# 識別子として使われる label/labels/short_label/title_labels は、
|
|
126
|
+
# 表示版とは無関係に version が 4.0 以降でも従来どおり ".#" のまま
|
|
127
|
+
def test_identity_methods_are_unaffected_by_version
|
|
128
|
+
db = build('4.0')
|
|
129
|
+
m = db.get_method(BitClust::MethodSpec.parse('Kernel.#mf'))
|
|
130
|
+
assert_equal('.#', m.typemark)
|
|
131
|
+
assert_equal('Kernel.#mf', m.label)
|
|
132
|
+
assert_equal('.#mf', m.short_label)
|
|
133
|
+
assert_equal(['Kernel.#mf', 'Kernel.#mf2'], m.title_labels)
|
|
134
|
+
assert_equal(['Kernel.#mf', 'Kernel.#mf2'], m.labels)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def test_instance_method_and_special_variable_display_are_unaffected_by_version
|
|
138
|
+
db = build('4.0')
|
|
139
|
+
im = db.get_method(BitClust::MethodSpec.parse('Kernel#im'))
|
|
140
|
+
assert_equal('#', im.display_typemark)
|
|
141
|
+
assert_equal('Kernel#im', im.display_label)
|
|
142
|
+
assert_equal('im', im.display_short_label)
|
|
143
|
+
|
|
144
|
+
sv = db.get_method(BitClust::MethodSpec.parse('Kernel$stdout'))
|
|
145
|
+
assert_equal('$', sv.display_typemark)
|
|
146
|
+
assert_equal('$stdout', sv.display_label)
|
|
147
|
+
assert_equal('$stdout', sv.display_short_label)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# meta description(コンパイラを通さない表示テキスト)内の module function
|
|
152
|
+
# 参照 [[m:Kernel.#mf2]] のラベルも、可視ページの bracket_link と同様に
|
|
153
|
+
# DB バージョン 4.0 以降では "?." で表示する(bitclust#282/#283 の続き。
|
|
154
|
+
# 従来この経路だけ ".#" のまま残っていた)
|
|
155
|
+
class TestMethodEntryDescriptionQdot < Test::Unit::TestCase
|
|
156
|
+
SRC = <<HERE
|
|
157
|
+
= module Kernel
|
|
158
|
+
|
|
159
|
+
== Module Functions
|
|
160
|
+
|
|
161
|
+
--- mf
|
|
162
|
+
|
|
163
|
+
[[m:Kernel.#mf2]] を参照してください。
|
|
164
|
+
|
|
165
|
+
--- mf2
|
|
166
|
+
|
|
167
|
+
説明。
|
|
168
|
+
HERE
|
|
169
|
+
|
|
170
|
+
def description(version)
|
|
171
|
+
_lib, db = BitClust::RRDParser.parse(SRC, 'testlib', {'version' => version})
|
|
172
|
+
db.get_method(BitClust::MethodSpec.parse('Kernel.#mf')).description
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def test_meta_description_keeps_dot_hash_before_4_0
|
|
176
|
+
assert_equal('Kernel.#mf2 を参照してください。', description('3.4'))
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def test_meta_description_uses_question_dot_at_4_0
|
|
180
|
+
assert_equal('Kernel?.mf2 を参照してください。', description('4.0'))
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# メソッド名別の since/until (bitclust#132 P1)。
|
|
185
|
+
#
|
|
186
|
+
# テストリスト:
|
|
187
|
+
# [x] 新規エントリの since_map/until_map は空、since_of/until_of は nil
|
|
188
|
+
# [x] fill_since は初回のみ追加して true を返す。既に値があれば false で上書きしない
|
|
189
|
+
# [x] fill_until も同様
|
|
190
|
+
# [x] fill_since/fill_until は version に '=' や ',' を含むと ArgumentError
|
|
191
|
+
# [x] 実ディスク DB への保存→別インスタンスで再読込しても since_of/until_of が一致
|
|
192
|
+
# [x] 名前に '=' を含む("==", "foo=")・',' を含む("," )・"-@" が
|
|
193
|
+
# エンコード/デコードを経て正しく往復する
|
|
194
|
+
# [x] since_by_name/until_by_name のキー自体がプロパティファイルに無い
|
|
195
|
+
# (旧DB)場合も落ちずに空配列として読める(Entry の '[String]' デシリアライザの
|
|
196
|
+
# nil 安全化)
|
|
197
|
+
class TestMethodEntrySinceUntil < Test::Unit::TestCase
|
|
198
|
+
def setup
|
|
199
|
+
@dir = Dir.mktmpdir
|
|
200
|
+
@db = BitClust::MethodDatabase.new(@dir)
|
|
201
|
+
@db.init
|
|
202
|
+
@db.transaction do
|
|
203
|
+
@db.propset('version', '2.0')
|
|
204
|
+
@db.propset('encoding', 'utf-8')
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def teardown
|
|
209
|
+
FileUtils.rm_rf(@dir)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def test_defaults_are_empty
|
|
213
|
+
m = build_entry('marker')
|
|
214
|
+
assert_equal({}, m.since_map)
|
|
215
|
+
assert_equal({}, m.until_map)
|
|
216
|
+
assert_nil m.since_of('marker')
|
|
217
|
+
assert_nil m.until_of('marker')
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def test_fill_since_adds_once
|
|
221
|
+
m = build_entry('marker')
|
|
222
|
+
assert_equal(true, m.fill_since('marker', '2.0'))
|
|
223
|
+
assert_equal('2.0', m.since_of('marker'))
|
|
224
|
+
# 既に値があるので上書きされず false
|
|
225
|
+
assert_equal(false, m.fill_since('marker', '3.0'))
|
|
226
|
+
assert_equal('2.0', m.since_of('marker'))
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def test_fill_until_adds_once
|
|
230
|
+
m = build_entry('marker')
|
|
231
|
+
assert_equal(true, m.fill_until('marker', '3.0'))
|
|
232
|
+
assert_equal('3.0', m.until_of('marker'))
|
|
233
|
+
assert_equal(false, m.fill_until('marker', '4.0'))
|
|
234
|
+
assert_equal('3.0', m.until_of('marker'))
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def test_fill_since_rejects_version_with_equal_or_comma
|
|
238
|
+
m = build_entry('marker')
|
|
239
|
+
assert_raise(ArgumentError) { m.fill_since('marker', '2.0=1') }
|
|
240
|
+
assert_raise(ArgumentError) { m.fill_since('marker', '2.0,1') }
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def test_fill_until_rejects_version_with_equal_or_comma
|
|
244
|
+
m = build_entry('marker')
|
|
245
|
+
assert_raise(ArgumentError) { m.fill_until('marker', '2.0=1') }
|
|
246
|
+
assert_raise(ArgumentError) { m.fill_until('marker', '2.0,1') }
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def test_roundtrip_through_disk
|
|
250
|
+
m = build_entry('marker')
|
|
251
|
+
m.fill_since('marker', '2.0')
|
|
252
|
+
m.fill_until('marker', '3.0')
|
|
253
|
+
m.save
|
|
254
|
+
|
|
255
|
+
reloaded = reload_entry(m.id)
|
|
256
|
+
assert_equal('2.0', reloaded.since_of('marker'))
|
|
257
|
+
assert_equal('3.0', reloaded.until_of('marker'))
|
|
258
|
+
assert_equal({'marker' => '2.0'}, reloaded.since_map)
|
|
259
|
+
assert_equal({'marker' => '3.0'}, reloaded.until_map)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def test_roundtrip_names_with_special_characters
|
|
263
|
+
[ '==', 'foo=', '-@', ',' ].each do |name|
|
|
264
|
+
m = build_entry(name)
|
|
265
|
+
m.fill_since(name, '2.0')
|
|
266
|
+
m.save
|
|
267
|
+
|
|
268
|
+
reloaded = reload_entry(m.id)
|
|
269
|
+
assert_equal('2.0', reloaded.since_of(name),
|
|
270
|
+
"since_of(#{name.inspect}) should round-trip")
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def test_multiple_names_share_one_entry
|
|
275
|
+
m = build_entry_with_names(['-@', 'dedup'])
|
|
276
|
+
m.fill_since('-@', '2.0')
|
|
277
|
+
m.fill_since('dedup', '3.0')
|
|
278
|
+
m.save
|
|
279
|
+
|
|
280
|
+
reloaded = reload_entry(m.id)
|
|
281
|
+
assert_equal('2.0', reloaded.since_of('-@'))
|
|
282
|
+
assert_equal('3.0', reloaded.since_of('dedup'))
|
|
283
|
+
assert_equal({'-@' => '2.0', 'dedup' => '3.0'}, reloaded.since_map)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def test_missing_since_by_name_key_is_backward_compatible
|
|
287
|
+
m = build_entry('old_method')
|
|
288
|
+
m.save
|
|
289
|
+
strip_property_line(m.id, 'since_by_name')
|
|
290
|
+
strip_property_line(m.id, 'until_by_name')
|
|
291
|
+
|
|
292
|
+
reloaded = reload_entry(m.id)
|
|
293
|
+
assert_equal([], reloaded.since_by_name)
|
|
294
|
+
assert_equal([], reloaded.until_by_name)
|
|
295
|
+
assert_nil reloaded.since_of('old_method')
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
private
|
|
299
|
+
|
|
300
|
+
def build_entry(name)
|
|
301
|
+
build_entry_with_names([name])
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def build_entry_with_names(names)
|
|
305
|
+
id = BitClust::NameUtils.build_method_id('_builtin', 'Foo', :instance_method, names.first)
|
|
306
|
+
m = BitClust::MethodEntry.new(@db, id)
|
|
307
|
+
m.names = names
|
|
308
|
+
m.visibility = :public
|
|
309
|
+
m.kind = :defined
|
|
310
|
+
m.source = "説明\n"
|
|
311
|
+
m
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def reload_entry(id)
|
|
315
|
+
fresh_db = BitClust::MethodDatabase.new(@dir)
|
|
316
|
+
BitClust::MethodEntry.new(fresh_db, id)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def property_file_path(id)
|
|
320
|
+
File.join(@dir, BitClust::NameUtils.encodeid("method/#{id}"))
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def strip_property_line(id, key)
|
|
324
|
+
path = property_file_path(id)
|
|
325
|
+
lines = File.readlines(path).reject {|l| l.start_with?("#{key}=") }
|
|
326
|
+
File.write(path, lines.join)
|
|
327
|
+
end
|
|
328
|
+
end
|
|
@@ -4,7 +4,9 @@ require 'bitclust/methodsignature'
|
|
|
4
4
|
class TestMethodSignature < Test::Unit::TestCase
|
|
5
5
|
|
|
6
6
|
data("special var" => ["$_ -> String | nil", "--- $_ -> String | nil"],
|
|
7
|
-
"backquote" => ["`command` -> String", "--- `(command) -> String"]
|
|
7
|
+
"backquote" => ["`command` -> String", "--- `(command) -> String"],
|
|
8
|
+
"aset" => ["self[key] = value", "--- []=(key, value)"],
|
|
9
|
+
"aset splat" => ["[]=(*idxary)", "--- []=(*idxary)"])
|
|
8
10
|
def test_friendlyname(data)
|
|
9
11
|
friendly_string, method_signature = data
|
|
10
12
|
assert_equal(friendly_string, BitClust::MethodSignature.parse(method_signature).friendly_string)
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'test/unit'
|
|
3
|
+
require 'bitclust'
|
|
4
|
+
require 'bitclust/methoddatabase'
|
|
5
|
+
require 'bitclust/subcommands/methodsince_command'
|
|
6
|
+
require 'stringio'
|
|
7
|
+
require 'tmpdir'
|
|
8
|
+
require 'fileutils'
|
|
9
|
+
|
|
10
|
+
# methodsince サブコマンド(bitclust#132 P2)。
|
|
11
|
+
#
|
|
12
|
+
# テストリスト:
|
|
13
|
+
# [x] グローバル --database 不要(needs_database? が false)
|
|
14
|
+
# [x] --update が無いとエラー
|
|
15
|
+
# [x] ラダー DB を走査して --update 対象に since/until が書き込まれる
|
|
16
|
+
# (フロアのメソッドには付かず、ゲート付きメソッドには付く)
|
|
17
|
+
# [x] 統計行が "basename (version V): entries_updated=.. since_filled=..
|
|
18
|
+
# until_filled=.. floor_skipped=.." の形式で出力される
|
|
19
|
+
# [x] --update は複数指定でき、対象ごとに統計行が出力される
|
|
20
|
+
# [x] --update に無い位置引数の DB はラダーには参加するが書き込まれない
|
|
21
|
+
# [x] --dry-run は統計を表示するだけで実DBファイルには一切書き込まない
|
|
22
|
+
# [x] Runner に登録されている(bitclust methodsince として呼べる)
|
|
23
|
+
class TestMethodsinceCommand < Test::Unit::TestCase
|
|
24
|
+
def setup
|
|
25
|
+
@tmpdir = "methodsince_test_tmp"
|
|
26
|
+
FileUtils.rm_rf(@tmpdir)
|
|
27
|
+
@db10 = build_db('1.0', <<~'RD')
|
|
28
|
+
description
|
|
29
|
+
|
|
30
|
+
= class Foo < Object
|
|
31
|
+
== Instance Methods
|
|
32
|
+
--- old
|
|
33
|
+
|
|
34
|
+
説明
|
|
35
|
+
RD
|
|
36
|
+
@db20 = build_db('2.0', <<~'RD')
|
|
37
|
+
description
|
|
38
|
+
|
|
39
|
+
= class Foo < Object
|
|
40
|
+
== Instance Methods
|
|
41
|
+
--- old
|
|
42
|
+
|
|
43
|
+
説明
|
|
44
|
+
|
|
45
|
+
#@since 2.0
|
|
46
|
+
--- newone
|
|
47
|
+
|
|
48
|
+
説明
|
|
49
|
+
#@end
|
|
50
|
+
RD
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def teardown
|
|
54
|
+
FileUtils.rm_rf(@tmpdir)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def build_db(version, builtin_rd)
|
|
58
|
+
root = "#{@tmpdir}/tree-#{version}/refm/api/src"
|
|
59
|
+
FileUtils.mkdir_p("#{root}/_builtin")
|
|
60
|
+
File.write("#{root}/LIBRARIES", "_builtin\n")
|
|
61
|
+
File.write("#{root}/_builtin.rd", builtin_rd)
|
|
62
|
+
prefix = "#{@tmpdir}/db-#{version}"
|
|
63
|
+
db = BitClust::MethodDatabase.new(prefix)
|
|
64
|
+
db.init
|
|
65
|
+
db.transaction do
|
|
66
|
+
db.propset('version', version)
|
|
67
|
+
db.propset('encoding', 'utf-8')
|
|
68
|
+
end
|
|
69
|
+
db.transaction do
|
|
70
|
+
db.update_by_stdlibtree(root)
|
|
71
|
+
end
|
|
72
|
+
prefix
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def run_command(argv)
|
|
76
|
+
cmd = BitClust::Subcommands::MethodsinceCommand.new
|
|
77
|
+
cmd.parse(argv)
|
|
78
|
+
out = StringIO.new
|
|
79
|
+
orig_stdout = $stdout
|
|
80
|
+
$stdout = out
|
|
81
|
+
begin
|
|
82
|
+
cmd.exec(argv, { prefix: nil, capi: false })
|
|
83
|
+
ensure
|
|
84
|
+
$stdout = orig_stdout
|
|
85
|
+
end
|
|
86
|
+
out.string
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def find_entry(prefix, name)
|
|
90
|
+
db = BitClust::MethodDatabase.new(prefix)
|
|
91
|
+
db.get_class('Foo').entries.find {|m| m.name?(name) }
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_needs_no_global_database_option
|
|
95
|
+
cmd = BitClust::Subcommands::MethodsinceCommand.new
|
|
96
|
+
assert_false cmd.needs_database?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_no_update_is_an_error
|
|
100
|
+
cmd = BitClust::Subcommands::MethodsinceCommand.new
|
|
101
|
+
argv = [@db10, @db20]
|
|
102
|
+
cmd.parse(argv)
|
|
103
|
+
assert_raise(SystemExit) do
|
|
104
|
+
capture_stderr { cmd.exec(argv, { prefix: nil, capi: false }) }
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def test_fills_since_into_update_target
|
|
109
|
+
run_command([@db10, "--update=#{@db20}"])
|
|
110
|
+
assert_nil find_entry(@db20, 'old').since_of('old')
|
|
111
|
+
assert_equal '2.0', find_entry(@db20, 'newone').since_of('newone')
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_prints_one_stats_line_per_target
|
|
115
|
+
out = run_command([@db10, "--update=#{@db20}"])
|
|
116
|
+
assert_match(
|
|
117
|
+
/\Adb-2\.0 \(version 2\.0\): entries_updated=\d+ since_filled=\d+ until_filled=\d+ floor_skipped=\d+\n\z/,
|
|
118
|
+
out)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_multiple_update_targets_each_get_a_stats_line
|
|
122
|
+
out = run_command(["--update=#{@db10}", "--update=#{@db20}"])
|
|
123
|
+
lines = out.lines
|
|
124
|
+
assert_equal 2, lines.size
|
|
125
|
+
assert_match(/\Adb-1\.0 /, lines[0])
|
|
126
|
+
assert_match(/\Adb-2\.0 /, lines[1])
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_positional_ladder_db_is_not_written_to
|
|
130
|
+
before = File.read(property_file_path(@db10, 'old'))
|
|
131
|
+
run_command([@db10, "--update=#{@db20}"])
|
|
132
|
+
after = File.read(property_file_path(@db10, 'old'))
|
|
133
|
+
assert_equal before, after
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def test_dry_run_leaves_real_database_untouched
|
|
137
|
+
run_command([@db10, "--update=#{@db20}", '--dry-run'])
|
|
138
|
+
assert_nil find_entry(@db20, 'newone').since_of('newone')
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_dry_run_still_prints_computed_stats
|
|
142
|
+
out = run_command([@db10, "--update=#{@db20}", '--dry-run'])
|
|
143
|
+
assert_match(/since_filled=1\b/, out)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def test_registered_in_runner
|
|
147
|
+
require 'bitclust/runner'
|
|
148
|
+
runner = BitClust::Runner.new
|
|
149
|
+
runner.prepare
|
|
150
|
+
subcommands = runner.instance_variable_get(:@subcommands)
|
|
151
|
+
assert_kind_of(BitClust::Subcommands::MethodsinceCommand, subcommands['methodsince'])
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
private
|
|
155
|
+
|
|
156
|
+
def property_file_path(prefix, name)
|
|
157
|
+
id = BitClust::NameUtils.build_method_id('_builtin', 'Foo', :instance_method, name)
|
|
158
|
+
File.join(prefix, BitClust::NameUtils.encodeid("method/#{id}"))
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def capture_stderr
|
|
162
|
+
orig = $stderr
|
|
163
|
+
$stderr = StringIO.new
|
|
164
|
+
yield
|
|
165
|
+
ensure
|
|
166
|
+
$stderr = orig
|
|
167
|
+
end
|
|
168
|
+
end
|
data/test/test_nameutils.rb
CHANGED
|
@@ -306,6 +306,28 @@ class TestNameUtils < Test::Unit::TestCase
|
|
|
306
306
|
assert_equal(expected, typemark2char(target))
|
|
307
307
|
end
|
|
308
308
|
|
|
309
|
+
# bitclust#250: Ruby 4.0 以降のドキュメントでは module function の表記を
|
|
310
|
+
# 独自の「.#」から「?.」に変える。表示だけの変換であり、識別子(typemark
|
|
311
|
+
# そのもの・typemark2char 等)は一切変えないので、対象は '.#' のみ。
|
|
312
|
+
# バージョン比較は文字列比較ではなく Gem::Version で行う(例: "10.0" を
|
|
313
|
+
# 文字列比較すると "4.0" より小さく見えてしまう)。
|
|
314
|
+
data("module function before 4.0 stays as-is" => ['.#', '.#', '3.4'],
|
|
315
|
+
"module function at exactly 4.0 switches" => ['?.', '.#', '4.0'],
|
|
316
|
+
"module function after 4.0 switches" => ['?.', '.#', '4.1'],
|
|
317
|
+
"module function 4.0.0 counts as 4.0" => ['?.', '.#', '4.0.0'],
|
|
318
|
+
"module function double-digit major (10.0)" => ['?.', '.#', '10.0'],
|
|
319
|
+
"module function just under 4.0 stays as-is" => ['.#', '.#', '3.99'],
|
|
320
|
+
"module function with nil version stays as-is" => ['.#', '.#', nil],
|
|
321
|
+
"module function with empty version stays" => ['.#', '.#', ''],
|
|
322
|
+
"singleton method mark is never rewritten" => ['.', '.', '4.0'],
|
|
323
|
+
"instance method mark is never rewritten" => ['#', '#', '4.0'],
|
|
324
|
+
"constant mark is never rewritten" => ['::', '::', '4.0'],
|
|
325
|
+
"special variable mark is never rewritten" => ['$', '$', '4.0'])
|
|
326
|
+
def test_display_typemark(data)
|
|
327
|
+
expected, mark, version = data
|
|
328
|
+
assert_equal(expected, display_typemark(mark, version))
|
|
329
|
+
end
|
|
330
|
+
|
|
309
331
|
data("s" => [".", "s"],
|
|
310
332
|
"i" => ["#", "i"],
|
|
311
333
|
"m" => [".#", "m"],
|