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,573 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
require 'stringio'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
require 'bitclust/mdparser'
|
|
7
|
+
require 'bitclust/rrdparser'
|
|
8
|
+
require 'bitclust/methoddatabase'
|
|
9
|
+
|
|
10
|
+
# MDParser: Markdown ソースを直接パースして DB エントリを作る(フェーズ3 M3)。
|
|
11
|
+
# 構造(クラス・エントリ・関係)は同等 rd の RRDParser と一致し、
|
|
12
|
+
# source には md 断片がそのまま入る。
|
|
13
|
+
class TestMDParser < Test::Unit::TestCase
|
|
14
|
+
PARAMS = { "version" => "3.4" }
|
|
15
|
+
|
|
16
|
+
def parse_md(md, libname = "_builtin")
|
|
17
|
+
db = BitClust::MethodDatabase.dummy(PARAMS)
|
|
18
|
+
lib = BitClust::MDParser.new(db).parse(StringIO.new(md), libname, PARAMS)
|
|
19
|
+
[db, lib]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def parse_rd(rd, libname = "_builtin")
|
|
23
|
+
db = BitClust::MethodDatabase.dummy(PARAMS)
|
|
24
|
+
lib = BitClust::RRDParser.new(db).parse(StringIO.new(rd), libname, PARAMS)
|
|
25
|
+
[db, lib]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_class_with_include_and_method
|
|
29
|
+
md = <<~MD
|
|
30
|
+
---
|
|
31
|
+
library: _builtin
|
|
32
|
+
include:
|
|
33
|
+
- Enumerable
|
|
34
|
+
---
|
|
35
|
+
# class Array < Object
|
|
36
|
+
|
|
37
|
+
配列クラス。
|
|
38
|
+
|
|
39
|
+
## Instance Methods
|
|
40
|
+
|
|
41
|
+
### def index(val) -> Integer
|
|
42
|
+
|
|
43
|
+
説明。
|
|
44
|
+
MD
|
|
45
|
+
rd = <<~RD
|
|
46
|
+
= class Array < Object
|
|
47
|
+
include Enumerable
|
|
48
|
+
|
|
49
|
+
配列クラス。
|
|
50
|
+
|
|
51
|
+
== Instance Methods
|
|
52
|
+
|
|
53
|
+
--- index(val) -> Integer
|
|
54
|
+
|
|
55
|
+
説明。
|
|
56
|
+
RD
|
|
57
|
+
_, mlib = parse_md(md)
|
|
58
|
+
_, rlib = parse_rd(rd)
|
|
59
|
+
|
|
60
|
+
mc = mlib.classes.first
|
|
61
|
+
rc = rlib.classes.first
|
|
62
|
+
assert_equal rc.name, mc.name
|
|
63
|
+
assert_equal rc.type, mc.type
|
|
64
|
+
assert_equal rc.superclass&.name, mc.superclass&.name
|
|
65
|
+
assert_equal rc.included.map(&:name), mc.included.map(&:name)
|
|
66
|
+
assert_equal rc.entries.map(&:names), mc.entries.map(&:names)
|
|
67
|
+
assert_equal rc.entries.first.type, mc.entries.first.type
|
|
68
|
+
|
|
69
|
+
# source は md のまま
|
|
70
|
+
assert_equal "配列クラス。", mc.source
|
|
71
|
+
assert_equal "### def index(val) -> Integer\n\n説明。\n", mc.entries.first.source
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_module_and_class_methods_section
|
|
75
|
+
md = <<~MD
|
|
76
|
+
---
|
|
77
|
+
library: _builtin
|
|
78
|
+
---
|
|
79
|
+
# module Comparable
|
|
80
|
+
|
|
81
|
+
比較演算モジュール。
|
|
82
|
+
|
|
83
|
+
## Class Methods
|
|
84
|
+
|
|
85
|
+
### def new -> Comparable
|
|
86
|
+
|
|
87
|
+
生成。
|
|
88
|
+
MD
|
|
89
|
+
_, lib = parse_md(md)
|
|
90
|
+
c = lib.classes.first
|
|
91
|
+
assert_equal "Comparable", c.name
|
|
92
|
+
assert_equal :module, c.type
|
|
93
|
+
assert_equal :singleton_method, c.entries.first.type
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def test_constants_section_with_const_keyword
|
|
97
|
+
md = <<~MD
|
|
98
|
+
---
|
|
99
|
+
library: _builtin
|
|
100
|
+
---
|
|
101
|
+
# class Float < Numeric
|
|
102
|
+
|
|
103
|
+
浮動小数点数。
|
|
104
|
+
|
|
105
|
+
## Constants
|
|
106
|
+
|
|
107
|
+
### const DIG -> Integer
|
|
108
|
+
|
|
109
|
+
桁数。
|
|
110
|
+
MD
|
|
111
|
+
_, lib = parse_md(md)
|
|
112
|
+
e = lib.classes.first.entries.first
|
|
113
|
+
assert_equal :constant, e.type
|
|
114
|
+
assert_equal ["DIG"], e.names
|
|
115
|
+
assert_equal "### const DIG -> Integer\n\n桁数。\n", e.source
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def test_reopen_with_dynamic_include_across_files
|
|
119
|
+
# ライブラリはファイル単位で組み立てる(module 定義とreopen が別ファイル、
|
|
120
|
+
# 同じ libname で順にパースすると同一 Library に合流する)
|
|
121
|
+
module_md = <<~MD
|
|
122
|
+
---
|
|
123
|
+
library: mylib
|
|
124
|
+
---
|
|
125
|
+
# module MyModule
|
|
126
|
+
|
|
127
|
+
モジュール。
|
|
128
|
+
MD
|
|
129
|
+
reopen_md = <<~MD
|
|
130
|
+
---
|
|
131
|
+
library: mylib
|
|
132
|
+
include:
|
|
133
|
+
- MyModule
|
|
134
|
+
---
|
|
135
|
+
# reopen Object
|
|
136
|
+
MD
|
|
137
|
+
db = BitClust::MethodDatabase.dummy(PARAMS)
|
|
138
|
+
BitClust::MDParser.new(db).parse(StringIO.new(module_md), "mylib", PARAMS)
|
|
139
|
+
BitClust::MDParser.new(db).parse(StringIO.new(reopen_md), "mylib", PARAMS)
|
|
140
|
+
assert_equal ["MyModule"], db.get_class("Object").dynamically_included.map(&:name)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def test_gvar_signature
|
|
144
|
+
md = <<~MD
|
|
145
|
+
---
|
|
146
|
+
library: _builtin
|
|
147
|
+
---
|
|
148
|
+
# module Kernel
|
|
149
|
+
|
|
150
|
+
カーネル。
|
|
151
|
+
|
|
152
|
+
## Special Variables
|
|
153
|
+
|
|
154
|
+
### gvar $stdin -> IO
|
|
155
|
+
|
|
156
|
+
標準入力。
|
|
157
|
+
MD
|
|
158
|
+
_, lib = parse_md(md)
|
|
159
|
+
e = lib.classes.first.entries.first
|
|
160
|
+
assert_equal :special_variable, e.type
|
|
161
|
+
assert_equal "### gvar $stdin -> IO\n\n標準入力。\n", e.source
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def test_relations_require_single_entity
|
|
165
|
+
# 案B: 関係(include 等)を持つファイルは単一エンティティでなければならない
|
|
166
|
+
md = <<~MD
|
|
167
|
+
---
|
|
168
|
+
library: _builtin
|
|
169
|
+
include:
|
|
170
|
+
- Enumerable
|
|
171
|
+
---
|
|
172
|
+
# class Foo < Object
|
|
173
|
+
|
|
174
|
+
ふー。
|
|
175
|
+
|
|
176
|
+
# class Bar < Object
|
|
177
|
+
|
|
178
|
+
ばー。
|
|
179
|
+
MD
|
|
180
|
+
assert_raise(BitClust::ParseError) { parse_md(md) }
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def test_unsupported_signature_forms_are_rejected
|
|
184
|
+
# RBS 形式(MARKUP_SPEC §3.2 で構想)と self. プレフィクスは描画側
|
|
185
|
+
# (MethodSignature.parse)が受理できないため、パース時に拒否する
|
|
186
|
+
base = <<~MD
|
|
187
|
+
---
|
|
188
|
+
library: _builtin
|
|
189
|
+
---
|
|
190
|
+
# class Foo < Object
|
|
191
|
+
|
|
192
|
+
テスト。
|
|
193
|
+
|
|
194
|
+
## Instance Methods
|
|
195
|
+
|
|
196
|
+
%s
|
|
197
|
+
|
|
198
|
+
説明。
|
|
199
|
+
MD
|
|
200
|
+
['### def each: () { (untyped) -> void } -> self',
|
|
201
|
+
'### def self.new(size = 0) -> Foo'].each do |sig|
|
|
202
|
+
assert_raise(BitClust::ParseError, sig) { parse_md(base % sig) }
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def test_library_file_with_category
|
|
207
|
+
md = <<~MD
|
|
208
|
+
---
|
|
209
|
+
type: library
|
|
210
|
+
category: FileFormat
|
|
211
|
+
---
|
|
212
|
+
CSV を扱うライブラリです。
|
|
213
|
+
MD
|
|
214
|
+
_, lib = parse_md(md, "csv")
|
|
215
|
+
assert_equal "FileFormat", lib.category
|
|
216
|
+
assert_equal "CSV を扱うライブラリです。", lib.source
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def test_since_directive_in_body
|
|
220
|
+
md = <<~MD
|
|
221
|
+
---
|
|
222
|
+
library: _builtin
|
|
223
|
+
---
|
|
224
|
+
# class Array < Object
|
|
225
|
+
|
|
226
|
+
配列。
|
|
227
|
+
|
|
228
|
+
## Instance Methods
|
|
229
|
+
|
|
230
|
+
\#@since 3.4
|
|
231
|
+
### def newmethod -> nil
|
|
232
|
+
|
|
233
|
+
新しい。
|
|
234
|
+
\#@end
|
|
235
|
+
MD
|
|
236
|
+
_, lib = parse_md(md)
|
|
237
|
+
assert_equal [["newmethod"]], lib.classes.first.entries.map(&:names)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def test_update_by_markdowntree
|
|
241
|
+
# MarkdownTree 駆動の組み立て: lib ファイル → メンバー(reopen 後置)、
|
|
242
|
+
# 版ゲート外のライブラリ/メンバーはスキップ
|
|
243
|
+
require 'tmpdir'
|
|
244
|
+
Dir.mktmpdir do |root|
|
|
245
|
+
write = ->(rel, s) {
|
|
246
|
+
path = File.join(root, rel)
|
|
247
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
248
|
+
File.write(path, s)
|
|
249
|
+
}
|
|
250
|
+
write.call('mylib.md', <<~MD)
|
|
251
|
+
---
|
|
252
|
+
type: library
|
|
253
|
+
category: Text
|
|
254
|
+
---
|
|
255
|
+
mylib の説明。
|
|
256
|
+
MD
|
|
257
|
+
write.call('mylib/MyModule.md', <<~MD)
|
|
258
|
+
---
|
|
259
|
+
library: mylib
|
|
260
|
+
---
|
|
261
|
+
# module MyModule
|
|
262
|
+
|
|
263
|
+
モジュール。
|
|
264
|
+
MD
|
|
265
|
+
# 辞書順で module より先に来る reopen ファイル(後置されることを確認)
|
|
266
|
+
write.call('mylib/Kernel.md', <<~MD)
|
|
267
|
+
---
|
|
268
|
+
library: mylib
|
|
269
|
+
include:
|
|
270
|
+
- MyModule
|
|
271
|
+
---
|
|
272
|
+
# reopen Object
|
|
273
|
+
MD
|
|
274
|
+
write.call('mylib/Gone.md', <<~MD)
|
|
275
|
+
---
|
|
276
|
+
library: mylib
|
|
277
|
+
until: "3.0"
|
|
278
|
+
---
|
|
279
|
+
# class Gone < Object
|
|
280
|
+
|
|
281
|
+
3.0 で消えた。
|
|
282
|
+
MD
|
|
283
|
+
write.call('oldlib.md', <<~MD)
|
|
284
|
+
---
|
|
285
|
+
type: library
|
|
286
|
+
until: "2.0"
|
|
287
|
+
---
|
|
288
|
+
古いライブラリ。
|
|
289
|
+
MD
|
|
290
|
+
|
|
291
|
+
db = BitClust::MethodDatabase.dummy(PARAMS)
|
|
292
|
+
db.update_by_markdowntree(root)
|
|
293
|
+
|
|
294
|
+
assert_equal ["mylib"], db.libraries.map(&:name)
|
|
295
|
+
lib = db.fetch_library("mylib")
|
|
296
|
+
assert_equal "Text", lib.category
|
|
297
|
+
assert_equal "mylib の説明。", lib.source
|
|
298
|
+
# reopen はメソッド定義が無い限り lib.classes に載らない(rd と同じ)
|
|
299
|
+
assert_equal %w[MyModule], lib.classes.map(&:name).sort
|
|
300
|
+
assert_equal ["MyModule"], db.get_class("Object").dynamically_included.map(&:name)
|
|
301
|
+
# source_location は md の実パス
|
|
302
|
+
assert_equal "#{root}/mylib.md", lib.source_location.file
|
|
303
|
+
assert_equal "#{root}/mylib/MyModule.md", db.get_class("MyModule").source_location.file
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def test_update_by_markdowntree_gated_memberships
|
|
308
|
+
# 多重所属(ゲート付き library リスト): 版によって所属ライブラリが変わる。
|
|
309
|
+
# 3.4 では builtin のみ、3.0 では builtin と oldlib の両方に属する
|
|
310
|
+
require 'tmpdir'
|
|
311
|
+
Dir.mktmpdir do |root|
|
|
312
|
+
write = ->(rel, s) {
|
|
313
|
+
path = File.join(root, rel)
|
|
314
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
315
|
+
File.write(path, s)
|
|
316
|
+
}
|
|
317
|
+
write.call('builtin.md', "---\ntype: library\n---\nbuiltin。\n")
|
|
318
|
+
write.call('oldlib.md', "---\ntype: library\n---\noldlib。\n")
|
|
319
|
+
write.call('oldlib/Shared.md', <<~'MD')
|
|
320
|
+
---
|
|
321
|
+
library:
|
|
322
|
+
- builtin
|
|
323
|
+
#@until 3.2
|
|
324
|
+
- oldlib
|
|
325
|
+
#@end
|
|
326
|
+
---
|
|
327
|
+
# class Shared < Object
|
|
328
|
+
|
|
329
|
+
共有クラス。
|
|
330
|
+
MD
|
|
331
|
+
|
|
332
|
+
db34 = BitClust::MethodDatabase.dummy("version" => "3.4")
|
|
333
|
+
db34.update_by_markdowntree(root)
|
|
334
|
+
assert_equal %w[Shared], db34.fetch_library("builtin").classes.map(&:name)
|
|
335
|
+
assert_equal [], db34.fetch_library("oldlib").classes.map(&:name)
|
|
336
|
+
|
|
337
|
+
db30 = BitClust::MethodDatabase.dummy("version" => "3.0")
|
|
338
|
+
db30.update_by_markdowntree(root)
|
|
339
|
+
assert_equal %w[Shared], db30.fetch_library("builtin").classes.map(&:name)
|
|
340
|
+
assert_equal %w[Shared], db30.fetch_library("oldlib").classes.map(&:name)
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def test_update_by_markdowntree_parse_error_suggests_gem_update
|
|
345
|
+
# manual/ が新しい bitclust を必要とする記法を含むとき、古い gem では
|
|
346
|
+
# パースエラーになる。原因へたどり着けるよう gem 更新の案内を添える
|
|
347
|
+
require 'tmpdir'
|
|
348
|
+
Dir.mktmpdir do |root|
|
|
349
|
+
write = ->(rel, s) {
|
|
350
|
+
path = File.join(root, rel)
|
|
351
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
352
|
+
File.write(path, s)
|
|
353
|
+
}
|
|
354
|
+
write.call('mylib.md', "---\ntype: library\n---\nmylib。\n")
|
|
355
|
+
write.call('mylib/Foo.md', <<~MD)
|
|
356
|
+
---
|
|
357
|
+
library: mylib
|
|
358
|
+
---
|
|
359
|
+
# class Foo < Object
|
|
360
|
+
|
|
361
|
+
クラス。
|
|
362
|
+
|
|
363
|
+
## Instance Methods
|
|
364
|
+
|
|
365
|
+
### def bar: (Integer) -> String
|
|
366
|
+
|
|
367
|
+
RBS 形式のシグネチャ(未対応)。
|
|
368
|
+
MD
|
|
369
|
+
|
|
370
|
+
db = BitClust::MethodDatabase.dummy(PARAMS)
|
|
371
|
+
error = assert_raise(BitClust::ParseError) do
|
|
372
|
+
db.update_by_markdowntree(root)
|
|
373
|
+
end
|
|
374
|
+
assert_include error.message, "unsupported method signature"
|
|
375
|
+
assert_include error.message, "bitclust の gem を更新すると解決するかもしれません"
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def test_copy_doc_md_keeps_relative_location
|
|
380
|
+
# Windows CI 対応: doc エントリの source_location は md_root と同じ形
|
|
381
|
+
# (相対で渡せば相対 manual/doc/...)で格納する。絶対パス化すると
|
|
382
|
+
# Windows のドライブレター(D:)のコロンで Location の
|
|
383
|
+
# デシリアライズ(file:line 分割)が壊れる
|
|
384
|
+
require 'tmpdir'
|
|
385
|
+
Dir.mktmpdir do |root|
|
|
386
|
+
write = ->(rel, s) {
|
|
387
|
+
path = File.join(root, rel)
|
|
388
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
389
|
+
File.write(path, s)
|
|
390
|
+
}
|
|
391
|
+
write.call('manual/api/mylib.md', <<~MD)
|
|
392
|
+
---
|
|
393
|
+
type: library
|
|
394
|
+
category: Text
|
|
395
|
+
---
|
|
396
|
+
mylib の説明。
|
|
397
|
+
MD
|
|
398
|
+
write.call('manual/doc/help.md', "= ヘルプ\n\n本文。\n")
|
|
399
|
+
write.call('manual/doc/parts.md', "\#@include(included)\n")
|
|
400
|
+
write.call('manual/doc/included.md', "= 部品\n\n部品本文。\n")
|
|
401
|
+
|
|
402
|
+
db = BitClust::MethodDatabase.new(File.join(root, 'db'))
|
|
403
|
+
db.init
|
|
404
|
+
db.transaction {
|
|
405
|
+
db.propset 'version', '3.4'
|
|
406
|
+
db.propset 'encoding', 'utf-8'
|
|
407
|
+
}
|
|
408
|
+
Dir.chdir(root) do
|
|
409
|
+
db.transaction {
|
|
410
|
+
db.update_by_markdowntree('manual/api')
|
|
411
|
+
}
|
|
412
|
+
end
|
|
413
|
+
doc_ids = db.docs.map(&:name).sort
|
|
414
|
+
assert_equal %w[help parts], doc_ids # include 参照先はページにしない
|
|
415
|
+
assert_equal 'manual/doc/help.md',
|
|
416
|
+
db.docs.find { |d| d.name == 'help' }.source_location.file.to_s
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
def test_location_deserialize_drops_line
|
|
421
|
+
# source_location の永続化はファイルのみ(行番号は生成物の diff を安定させる
|
|
422
|
+
# ため落とす。master b1d81d7 のポリシー)。旧形式の file:line も
|
|
423
|
+
# 後方互換で file だけを読む。Windows で壊れないよう doc の格納パスは
|
|
424
|
+
# 相対に保つ(copy_doc_md 側の慣例)
|
|
425
|
+
db = BitClust::MethodDatabase.dummy(PARAMS)
|
|
426
|
+
e = BitClust::DocEntry.new(db, 'x')
|
|
427
|
+
e.__send__(:_set_properties,
|
|
428
|
+
{ 'source_location' => 'manual/doc/help.md:12' })
|
|
429
|
+
loc = e.instance_variable_get(:@source_location)
|
|
430
|
+
assert_equal 'manual/doc/help.md', loc.file
|
|
431
|
+
assert_nil loc.line
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def test_function_parser
|
|
435
|
+
# capi: キーワード無しの ### 全行がシグネチャ。source は本文のみ(md のまま)
|
|
436
|
+
require 'bitclust/functiondatabase'
|
|
437
|
+
md = <<~MD
|
|
438
|
+
### VALUE rb_ary_new()
|
|
439
|
+
|
|
440
|
+
空の Ruby の配列を作成し返します。
|
|
441
|
+
|
|
442
|
+
```
|
|
443
|
+
VALUE ary = rb_ary_new();
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### static int rb_ary_size(VALUE ary)
|
|
447
|
+
|
|
448
|
+
内部関数です。
|
|
449
|
+
MD
|
|
450
|
+
db = BitClust::FunctionDatabase.dummy(PARAMS)
|
|
451
|
+
io = StringIO.new(md)
|
|
452
|
+
def io.path = "array.c.md"
|
|
453
|
+
BitClust::MDFunctionParser.new(db).parse(io, "array.c", PARAMS)
|
|
454
|
+
funcs = db.functions.sort_by(&:name)
|
|
455
|
+
assert_equal %w[rb_ary_new rb_ary_size], funcs.map(&:name)
|
|
456
|
+
f = funcs.first
|
|
457
|
+
assert_equal "array.c", f.filename
|
|
458
|
+
assert_equal "VALUE", f.type
|
|
459
|
+
# body はヘッダ直後の空行込み(レガシー FunctionReferenceParser と同じ)
|
|
460
|
+
assert_equal "\n空の Ruby の配列を作成し返します。\n\n```\nVALUE ary = rb_ary_new();\n```\n\n",
|
|
461
|
+
f.source
|
|
462
|
+
assert funcs.last.private
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def test_multi_entity_bundle_without_relations
|
|
466
|
+
md = <<~MD
|
|
467
|
+
---
|
|
468
|
+
library: _builtin
|
|
469
|
+
---
|
|
470
|
+
# class Errno::EPERM < SystemCallError
|
|
471
|
+
|
|
472
|
+
EPERM。
|
|
473
|
+
|
|
474
|
+
# class Errno::ENOENT < SystemCallError
|
|
475
|
+
|
|
476
|
+
ENOENT。
|
|
477
|
+
MD
|
|
478
|
+
_, lib = parse_md(md)
|
|
479
|
+
assert_equal %w[Errno::EPERM Errno::ENOENT], lib.classes.map(&:name)
|
|
480
|
+
end
|
|
481
|
+
def test_method_attribute_list_sets_kind
|
|
482
|
+
md = <<~MD
|
|
483
|
+
---
|
|
484
|
+
library: _builtin
|
|
485
|
+
---
|
|
486
|
+
# class Hoge
|
|
487
|
+
|
|
488
|
+
クラスの説明。
|
|
489
|
+
|
|
490
|
+
## Instance Methods
|
|
491
|
+
|
|
492
|
+
### def fuga -> nil
|
|
493
|
+
{: nomethod}
|
|
494
|
+
|
|
495
|
+
説明のためのエントリです。
|
|
496
|
+
|
|
497
|
+
### def piyo -> nil
|
|
498
|
+
{: undef}
|
|
499
|
+
MD
|
|
500
|
+
db, = parse_md(md)
|
|
501
|
+
assert_equal(:nomethod, db.get_method(BitClust::MethodSpec.parse('Hoge#fuga')).kind)
|
|
502
|
+
assert_equal(:undefined, db.get_method(BitClust::MethodSpec.parse('Hoge#piyo')).kind)
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def test_method_attribute_on_every_alias_signature
|
|
506
|
+
md = <<~MD
|
|
507
|
+
---
|
|
508
|
+
library: _builtin
|
|
509
|
+
---
|
|
510
|
+
# class Hoge
|
|
511
|
+
|
|
512
|
+
クラスの説明。
|
|
513
|
+
|
|
514
|
+
## Instance Methods
|
|
515
|
+
|
|
516
|
+
### def fuga -> nil
|
|
517
|
+
{: nomethod}
|
|
518
|
+
### def fuga2 -> nil
|
|
519
|
+
{: nomethod}
|
|
520
|
+
|
|
521
|
+
説明のためのエントリです。
|
|
522
|
+
MD
|
|
523
|
+
db, = parse_md(md)
|
|
524
|
+
fuga = db.get_method(BitClust::MethodSpec.parse('Hoge#fuga'))
|
|
525
|
+
assert_equal(:nomethod, fuga.kind)
|
|
526
|
+
assert_equal(['fuga', 'fuga2'], fuga.names)
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def test_method_attribute_since_is_recorded
|
|
530
|
+
md = <<~MD
|
|
531
|
+
---
|
|
532
|
+
library: _builtin
|
|
533
|
+
---
|
|
534
|
+
# class Hoge
|
|
535
|
+
|
|
536
|
+
クラスの説明。
|
|
537
|
+
|
|
538
|
+
## Instance Methods
|
|
539
|
+
|
|
540
|
+
### def fuga -> nil
|
|
541
|
+
{: since="3.1"}
|
|
542
|
+
|
|
543
|
+
説明のためのエントリです。
|
|
544
|
+
MD
|
|
545
|
+
db, = parse_md(md)
|
|
546
|
+
entry = db.get_method(BitClust::MethodSpec.parse('Hoge#fuga'))
|
|
547
|
+
assert_equal('3.1', entry.since_of('fuga'))
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
def test_method_attribute_since_differs_per_alias_signature
|
|
551
|
+
md = <<~MD
|
|
552
|
+
---
|
|
553
|
+
library: _builtin
|
|
554
|
+
---
|
|
555
|
+
# class Hoge
|
|
556
|
+
|
|
557
|
+
クラスの説明。
|
|
558
|
+
|
|
559
|
+
## Instance Methods
|
|
560
|
+
|
|
561
|
+
### def fuga -> nil
|
|
562
|
+
{: since="2.0.0"}
|
|
563
|
+
### def fuga2 -> nil
|
|
564
|
+
{: since="3.0"}
|
|
565
|
+
|
|
566
|
+
説明のためのエントリです。
|
|
567
|
+
MD
|
|
568
|
+
db, = parse_md(md)
|
|
569
|
+
entry = db.get_method(BitClust::MethodSpec.parse('Hoge#fuga'))
|
|
570
|
+
assert_equal('2.0.0', entry.since_of('fuga'))
|
|
571
|
+
assert_equal('3.0', entry.since_of('fuga2'))
|
|
572
|
+
end
|
|
573
|
+
end
|