bitclust-core 1.6.1 → 1.8.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.
- checksums.yaml +4 -4
- data/Rakefile +1 -0
- data/data/bitclust/catalog/ja_JP.UTF-8 +4 -2
- data/data/bitclust/template/class-index +0 -1
- data/data/bitclust/template/function-index +1 -0
- data/data/bitclust/template/layout +1 -0
- data/data/bitclust/template.epub/class +5 -5
- data/data/bitclust/template.epub/class-index +0 -1
- data/data/bitclust/template.epub/contents +7 -4
- data/data/bitclust/template.epub/layout +4 -4
- data/data/bitclust/template.offline/class-index +0 -1
- data/data/bitclust/template.offline/function-index +1 -0
- data/data/bitclust/template.offline/layout +3 -0
- data/lib/bitclust/classentry.rb +1 -1
- data/lib/bitclust/docentry.rb +1 -1
- data/lib/bitclust/functionentry.rb +1 -1
- data/lib/bitclust/generators/epub.rb +69 -5
- data/lib/bitclust/irb.rb +74 -0
- data/lib/bitclust/markdown_bridge.rb +11 -6
- data/lib/bitclust/markdown_exporter.rb +311 -0
- data/lib/bitclust/markdown_tree.rb +118 -11
- data/lib/bitclust/mdcompiler.rb +15 -1
- data/lib/bitclust/mdparser.rb +42 -1
- data/lib/bitclust/methoddatabase.rb +17 -4
- data/lib/bitclust/methodentry.rb +24 -0
- data/lib/bitclust/methodsignature.rb +1 -1
- data/lib/bitclust/nameutils.rb +13 -0
- data/lib/bitclust/preprocessor.rb +4 -37
- data/lib/bitclust/rbs_overload_matcher.rb +179 -0
- data/lib/bitclust/rbs_sig_importer.rb +276 -0
- data/lib/bitclust/rbs_signatures.rb +125 -0
- data/lib/bitclust/rdcompiler.rb +12 -1
- data/lib/bitclust/remote.rb +405 -0
- data/lib/bitclust/runner.rb +7 -10
- data/lib/bitclust/screen.rb +6 -1
- data/lib/bitclust/search_index_generator.rb +28 -10
- data/lib/bitclust/searcher.rb +54 -25
- data/lib/bitclust/subcommands/chm_command.rb +1 -1
- data/lib/bitclust/subcommands/epub_command.rb +2 -2
- data/lib/bitclust/subcommands/extract_command.rb +7 -0
- data/lib/bitclust/subcommands/htmlfile_command.rb +7 -0
- data/lib/bitclust/subcommands/methods_command.rb +5 -28
- data/lib/bitclust/subcommands/query_command.rb +1 -0
- data/lib/bitclust/subcommands/rbssig_command.rb +99 -0
- data/lib/bitclust/subcommands/server_command.rb +21 -10
- data/lib/bitclust/subcommands/setup_command.rb +32 -11
- data/lib/bitclust/subcommands/statichtml_command.rb +59 -0
- data/lib/bitclust/syntax_highlighter.rb +65 -4
- data/lib/bitclust/user_dirs.rb +62 -0
- data/lib/bitclust/version.rb +1 -1
- data/lib/bitclust-irb.rb +2 -0
- data/test/test_chm_command.rb +22 -0
- data/test/test_epub_command.rb +60 -0
- data/test/test_epub_generator.rb +330 -0
- data/test/test_extract_command.rb +45 -0
- data/test/test_irb_plugin.rb +212 -0
- data/test/test_link_checker.rb +1 -1
- data/test/test_markdown_bridge.rb +35 -0
- data/test/test_markdown_exporter.rb +260 -0
- data/test/test_markdown_tree.rb +144 -0
- data/test/test_mdcompiler.rb +47 -5
- data/test/test_mdparser.rb +223 -4
- data/test/test_methodentry.rb +111 -0
- data/test/test_methods_command.rb +32 -0
- data/test/test_methodsignature.rb +3 -1
- data/test/test_opensearchdescription_screen.rb +39 -0
- data/test/test_preprocessor.rb +26 -0
- data/test/test_query_command.rb +30 -0
- data/test/test_rbs_overload_matcher.rb +170 -0
- data/test/test_rbs_sig_importer.rb +237 -0
- data/test/test_rbssig_command.rb +186 -0
- data/test/test_rdcompiler.rb +99 -1
- data/test/test_remote.rb +374 -0
- data/test/test_runner.rb +61 -1
- data/test/test_search_index_generator.rb +81 -0
- data/test/test_searcher.rb +63 -0
- data/test/test_server_command.rb +41 -0
- data/test/test_setup_command.rb +164 -0
- data/test/test_statichtml_command.rb +137 -0
- data/test/test_syntax_highlighter.rb +124 -0
- data/test/test_user_dirs.rb +62 -0
- data/theme/default/js/run.js +14 -0
- data/theme/default/js/search_init.js +3 -1
- data/theme/default/js/search_page.js +7 -1
- data/theme/default/js/version_switcher.js +147 -0
- data/theme/default/search.css +21 -0
- data/theme/default/style.css +83 -7
- data/theme/lillia/style.css +26 -0
- metadata +71 -2
- data/lib/bitclust/ridatabase.rb +0 -359
data/test/test_mdcompiler.rb
CHANGED
|
@@ -23,7 +23,7 @@ class TestMDCompiler < Test::Unit::TestCase
|
|
|
23
23
|
@rd = BitClust::RDCompiler.new(@u, 1, { :database => @db })
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def compile_method(compiler, src)
|
|
26
|
+
def compile_method(compiler, src, rbs_signature_overloads: nil)
|
|
27
27
|
method_entry = Object.new
|
|
28
28
|
mock(method_entry).source { src }
|
|
29
29
|
mock(method_entry).index_id.any_times { "dummy" }
|
|
@@ -32,6 +32,7 @@ class TestMDCompiler < Test::Unit::TestCase
|
|
|
32
32
|
mock(method_entry).names.any_times { [] }
|
|
33
33
|
mock(method_entry).since_map.any_times { {} }
|
|
34
34
|
mock(method_entry).until_map.any_times { {} }
|
|
35
|
+
mock(method_entry).rbs_signature_overloads.any_times { rbs_signature_overloads }
|
|
35
36
|
compiler.compile_method(method_entry)
|
|
36
37
|
end
|
|
37
38
|
|
|
@@ -58,6 +59,47 @@ class TestMDCompiler < Test::Unit::TestCase
|
|
|
58
59
|
|
|
59
60
|
# ---- メソッドエントリ ----
|
|
60
61
|
|
|
62
|
+
# RBS シグネチャ表示: MDCompiler も entry_chunk をオーバーライドしている
|
|
63
|
+
# ので、rd 経路と同じ位置(説明 <dd> の直前)に同じ <dt> が出ること
|
|
64
|
+
def test_rbs_signatures_dt_matches_rd_output
|
|
65
|
+
rd_src = "--- index(val) -> Integer\n\n説明\n"
|
|
66
|
+
overloads = [{'segments' => [['t', '() -> void']]}]
|
|
67
|
+
md_src = BitClust::RRDToMarkdown.convert(rd_src)
|
|
68
|
+
rd_html = compile_method(@rd, rd_src, rbs_signature_overloads: overloads)
|
|
69
|
+
md_html = compile_method(@md, md_src, rbs_signature_overloads: overloads)
|
|
70
|
+
assert_include md_html,
|
|
71
|
+
'<dt class="rbs-signature"><code>() → void</code></dt>'
|
|
72
|
+
assert_equal rd_html, md_html
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# チャンク振り分けは md 側のシグネチャ行(### def ...)でも rd と同じに
|
|
76
|
+
# 動くこと(MDCompiler は行を "--- " に正規化してから照合する)
|
|
77
|
+
def test_rbs_signatures_chunk_assignment_matches_rd_output
|
|
78
|
+
rd_src = <<~RD
|
|
79
|
+
--- index(sub) -> Integer | nil
|
|
80
|
+
|
|
81
|
+
文字列で探す。
|
|
82
|
+
|
|
83
|
+
--- index(pattern) {|s| ... } -> Integer | nil
|
|
84
|
+
|
|
85
|
+
ブロックで探す。
|
|
86
|
+
RD
|
|
87
|
+
overloads = [
|
|
88
|
+
{'segments' => [['t', '(String sub) -> Integer?']],
|
|
89
|
+
'params' => ['sub'], 'arity' => [1, 1]},
|
|
90
|
+
{'segments' => [['t', '(Regexp pattern) { (String) -> bool } -> Integer?']],
|
|
91
|
+
'params' => ['pattern'], 'arity' => [1, 1], 'block' => 'req'},
|
|
92
|
+
]
|
|
93
|
+
md_src = BitClust::RRDToMarkdown.convert(rd_src)
|
|
94
|
+
rd_html = compile_method(@rd, rd_src, rbs_signature_overloads: overloads)
|
|
95
|
+
md_html = compile_method(@md, md_src, rbs_signature_overloads: overloads)
|
|
96
|
+
assert_match(
|
|
97
|
+
%r!<code>index\(pattern\).*?</dt>\n<dt class="rbs-signature"><code>\(Regexp pattern\) \{ \(String\) → bool \} → Integer\?</code></dt>\n<dd!m,
|
|
98
|
+
md_html)
|
|
99
|
+
assert_equal 2, md_html.scan('rbs-signature').size
|
|
100
|
+
assert_equal rd_html, md_html
|
|
101
|
+
end
|
|
102
|
+
|
|
61
103
|
def test_method_signature_and_paragraph
|
|
62
104
|
assert_equivalent_method <<~RD
|
|
63
105
|
--- index(val) -> Integer
|
|
@@ -752,10 +794,10 @@ class TestMDCompiler < Test::Unit::TestCase
|
|
|
752
794
|
def test_gfm_table_alignment
|
|
753
795
|
md = "# T\n\n| a | b | c |\n|:--|:-:|--:|\n| 1 | 2 | 3 |\n"
|
|
754
796
|
html = gfm_compiler.compile(md)
|
|
755
|
-
assert_include html, '<th
|
|
756
|
-
assert_include html, '<th
|
|
757
|
-
assert_include html, '<th
|
|
758
|
-
assert_include html, '<td
|
|
797
|
+
assert_include html, '<th style="text-align:left">a</th>'
|
|
798
|
+
assert_include html, '<th style="text-align:center">b</th>'
|
|
799
|
+
assert_include html, '<th style="text-align:right">c</th>'
|
|
800
|
+
assert_include html, '<td style="text-align:right">3</td>'
|
|
759
801
|
end
|
|
760
802
|
|
|
761
803
|
def test_gfm_pipe_line_without_delimiter_is_paragraph
|
data/test/test_mdparser.rb
CHANGED
|
@@ -82,7 +82,7 @@ class TestMDParser < Test::Unit::TestCase
|
|
|
82
82
|
|
|
83
83
|
## Class Methods
|
|
84
84
|
|
|
85
|
-
### def new -> Comparable
|
|
85
|
+
### def Comparable.new -> Comparable
|
|
86
86
|
|
|
87
87
|
生成。
|
|
88
88
|
MD
|
|
@@ -181,7 +181,7 @@ class TestMDParser < Test::Unit::TestCase
|
|
|
181
181
|
end
|
|
182
182
|
|
|
183
183
|
def test_unsupported_signature_forms_are_rejected
|
|
184
|
-
# RBS 形式(MARKUP_SPEC §3.2
|
|
184
|
+
# RBS 形式(MARKUP_SPEC §3.2 で構想)は描画側
|
|
185
185
|
# (MethodSignature.parse)が受理できないため、パース時に拒否する
|
|
186
186
|
base = <<~MD
|
|
187
187
|
---
|
|
@@ -197,12 +197,83 @@ class TestMDParser < Test::Unit::TestCase
|
|
|
197
197
|
|
|
198
198
|
説明。
|
|
199
199
|
MD
|
|
200
|
-
['### def each: () { (untyped) -> void } -> self'
|
|
201
|
-
'### def self.new(size = 0) -> Foo'].each do |sig|
|
|
200
|
+
['### def each: () { (untyped) -> void } -> self'].each do |sig|
|
|
202
201
|
assert_raise(BitClust::ParseError, sig) { parse_md(base % sig) }
|
|
203
202
|
end
|
|
204
203
|
end
|
|
205
204
|
|
|
205
|
+
def test_self_and_class_name_prefixed_signatures
|
|
206
|
+
# クラスメソッドは `def self.name` / `def Klass.name` 形式でも書ける。
|
|
207
|
+
# どちらも singleton method として登録され、名前にプレフィクスは含まない
|
|
208
|
+
md = <<~MD
|
|
209
|
+
---
|
|
210
|
+
library: _builtin
|
|
211
|
+
---
|
|
212
|
+
# class Foo < Object
|
|
213
|
+
|
|
214
|
+
テスト。
|
|
215
|
+
|
|
216
|
+
## Class Methods
|
|
217
|
+
|
|
218
|
+
### def self.build(x) -> Foo
|
|
219
|
+
|
|
220
|
+
self. 形式。
|
|
221
|
+
|
|
222
|
+
### def Foo.create(x) -> Foo
|
|
223
|
+
|
|
224
|
+
Klass. 形式。
|
|
225
|
+
MD
|
|
226
|
+
_, lib = parse_md(md)
|
|
227
|
+
entries = lib.classes.first.entries
|
|
228
|
+
assert_equal [["build"], ["create"]], entries.map(&:names)
|
|
229
|
+
assert_equal [:singleton_method, :singleton_method], entries.map(&:type)
|
|
230
|
+
# source には書かれたままの md が入る
|
|
231
|
+
assert_include entries[0].source, "### def self.build(x) -> Foo"
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def test_main_prefixed_signature_on_object_page
|
|
235
|
+
# object main のページでは main. プレフィクスで特異メソッドを書ける
|
|
236
|
+
# (main は fatal・ARGF.class と同様に文法上クラス名として扱われる)
|
|
237
|
+
md = <<~MD
|
|
238
|
+
---
|
|
239
|
+
library: _builtin
|
|
240
|
+
---
|
|
241
|
+
# object main
|
|
242
|
+
|
|
243
|
+
テスト。
|
|
244
|
+
|
|
245
|
+
## Class Methods
|
|
246
|
+
|
|
247
|
+
### def main.include(*modules) -> self
|
|
248
|
+
|
|
249
|
+
main. 形式。
|
|
250
|
+
MD
|
|
251
|
+
_, lib = parse_md(md)
|
|
252
|
+
entries = lib.classes.first.entries
|
|
253
|
+
assert_equal [["include"]], entries.map(&:names)
|
|
254
|
+
assert_equal [:singleton_method], entries.map(&:type)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def test_self_prefixed_signature_in_instance_methods_section_is_rejected
|
|
258
|
+
# self. は singleton 確定なので Instance Methods セクションとは矛盾する
|
|
259
|
+
md = <<~MD
|
|
260
|
+
---
|
|
261
|
+
library: _builtin
|
|
262
|
+
---
|
|
263
|
+
# class Foo < Object
|
|
264
|
+
|
|
265
|
+
テスト。
|
|
266
|
+
|
|
267
|
+
## Instance Methods
|
|
268
|
+
|
|
269
|
+
### def self.bar -> nil
|
|
270
|
+
|
|
271
|
+
矛盾。
|
|
272
|
+
MD
|
|
273
|
+
error = assert_raise(BitClust::ParseError) { parse_md(md) }
|
|
274
|
+
assert_include error.message, "signature crash"
|
|
275
|
+
end
|
|
276
|
+
|
|
206
277
|
def test_library_file_with_category
|
|
207
278
|
md = <<~MD
|
|
208
279
|
---
|
|
@@ -341,6 +412,45 @@ class TestMDParser < Test::Unit::TestCase
|
|
|
341
412
|
end
|
|
342
413
|
end
|
|
343
414
|
|
|
415
|
+
def test_update_by_markdowntree_else_and_single_version_memberships
|
|
416
|
+
# bitclust#331: ゲート付き library リストの #@version V(単一版)と #@else。
|
|
417
|
+
# 3.2 だけ onlylib、それ以外は builtin に属する。版の比較は Gem::Version
|
|
418
|
+
# なので 3.2.0 の DB でも 3.2 と同じ版として扱う
|
|
419
|
+
require 'tmpdir'
|
|
420
|
+
Dir.mktmpdir do |root|
|
|
421
|
+
write = ->(rel, s) {
|
|
422
|
+
path = File.join(root, rel)
|
|
423
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
424
|
+
File.write(path, s)
|
|
425
|
+
}
|
|
426
|
+
write.call('builtin.md', "---\ntype: library\n---\nbuiltin。\n")
|
|
427
|
+
write.call('onlylib.md', "---\ntype: library\n---\nonlylib。\n")
|
|
428
|
+
write.call('onlylib/Shared.md', <<~'MD')
|
|
429
|
+
---
|
|
430
|
+
library:
|
|
431
|
+
#@version 3.2
|
|
432
|
+
- onlylib
|
|
433
|
+
#@else
|
|
434
|
+
- builtin
|
|
435
|
+
#@end
|
|
436
|
+
---
|
|
437
|
+
# class Shared < Object
|
|
438
|
+
|
|
439
|
+
共有クラス。
|
|
440
|
+
MD
|
|
441
|
+
|
|
442
|
+
classes = ->(version) {
|
|
443
|
+
db = BitClust::MethodDatabase.dummy("version" => version)
|
|
444
|
+
db.update_by_markdowntree(root)
|
|
445
|
+
%w[builtin onlylib].map { |lib| db.fetch_library(lib).classes.map(&:name) }
|
|
446
|
+
}
|
|
447
|
+
assert_equal [[], %w[Shared]], classes.call("3.2")
|
|
448
|
+
assert_equal [[], %w[Shared]], classes.call("3.2.0")
|
|
449
|
+
assert_equal [%w[Shared], []], classes.call("3.4")
|
|
450
|
+
assert_equal [%w[Shared], []], classes.call("3.0")
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
|
|
344
454
|
def test_update_by_markdowntree_parse_error_suggests_gem_update
|
|
345
455
|
# manual/ が新しい bitclust を必要とする記法を含むとき、古い gem では
|
|
346
456
|
# パースエラーになる。原因へたどり着けるよう gem 更新の案内を添える
|
|
@@ -570,4 +680,113 @@ class TestMDParser < Test::Unit::TestCase
|
|
|
570
680
|
assert_equal('2.0.0', entry.since_of('fuga'))
|
|
571
681
|
assert_equal('3.0', entry.since_of('fuga2'))
|
|
572
682
|
end
|
|
683
|
+
|
|
684
|
+
def test_entry_style_bare_def_in_singleton_section_is_rejected
|
|
685
|
+
# MARKUP_SPEC §3.1: 特異メソッドはプレフィクス必須(def 行だけで
|
|
686
|
+
# メソッド種別が分かるようにする)
|
|
687
|
+
md = <<~MD
|
|
688
|
+
---
|
|
689
|
+
library: _builtin
|
|
690
|
+
---
|
|
691
|
+
# class Foo < Object
|
|
692
|
+
|
|
693
|
+
テスト。
|
|
694
|
+
|
|
695
|
+
## Class Methods
|
|
696
|
+
|
|
697
|
+
### def build(x) -> Foo
|
|
698
|
+
|
|
699
|
+
プレフィクスなし。
|
|
700
|
+
MD
|
|
701
|
+
error = assert_raise(BitClust::ParseError) { parse_md(md) }
|
|
702
|
+
assert_include error.message, "singleton method entry must be written as `def Foo.name' or `def self.name'"
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
def test_entry_style_keyword_section_mismatch_is_rejected
|
|
706
|
+
# rurema/doctree#3291 型の分類間違い: キーワードとセクションの不一致
|
|
707
|
+
base = <<~MD
|
|
708
|
+
---
|
|
709
|
+
library: _builtin
|
|
710
|
+
---
|
|
711
|
+
# class Foo < Object
|
|
712
|
+
|
|
713
|
+
テスト。
|
|
714
|
+
|
|
715
|
+
## %s
|
|
716
|
+
|
|
717
|
+
### %s
|
|
718
|
+
|
|
719
|
+
不一致。
|
|
720
|
+
MD
|
|
721
|
+
[
|
|
722
|
+
# Class Methods 配下の const(#3291 の実例)
|
|
723
|
+
['Class Methods', 'const CURRENT -> Foo', "entry keyword `const' does not match this section (expected `def')"],
|
|
724
|
+
# Constants 配下の gvar
|
|
725
|
+
['Constants', 'gvar $foo -> Foo', "entry keyword `gvar' does not match this section (expected `const')"],
|
|
726
|
+
# Instance Methods 配下の const
|
|
727
|
+
['Instance Methods', 'const BAR -> Integer', "entry keyword `const' does not match this section (expected `def')"],
|
|
728
|
+
].each do |section, sig, message|
|
|
729
|
+
error = assert_raise(BitClust::ParseError, "#{section} / #{sig}") do
|
|
730
|
+
parse_md(base % [section, sig])
|
|
731
|
+
end
|
|
732
|
+
assert_include error.message, message
|
|
733
|
+
end
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
def test_entry_style_module_functions_require_keyword
|
|
737
|
+
md = <<~MD
|
|
738
|
+
---
|
|
739
|
+
library: _builtin
|
|
740
|
+
---
|
|
741
|
+
# module Foo
|
|
742
|
+
|
|
743
|
+
テスト。
|
|
744
|
+
|
|
745
|
+
## Module Functions
|
|
746
|
+
|
|
747
|
+
### def bar -> nil
|
|
748
|
+
|
|
749
|
+
module_function キーワードなし。
|
|
750
|
+
MD
|
|
751
|
+
error = assert_raise(BitClust::ParseError) { parse_md(md) }
|
|
752
|
+
assert_include error.message, "entry keyword `def' does not match this section (expected `module_function def')"
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
def test_entry_style_accepts_consistent_forms
|
|
756
|
+
md = <<~MD
|
|
757
|
+
---
|
|
758
|
+
library: _builtin
|
|
759
|
+
---
|
|
760
|
+
# class Foo < Object
|
|
761
|
+
|
|
762
|
+
テスト。
|
|
763
|
+
|
|
764
|
+
## Class Methods
|
|
765
|
+
|
|
766
|
+
### def Foo.build(x) -> Foo
|
|
767
|
+
|
|
768
|
+
Klass 形式。
|
|
769
|
+
|
|
770
|
+
### def self.create(x) -> Foo
|
|
771
|
+
|
|
772
|
+
self 形式。
|
|
773
|
+
|
|
774
|
+
## Instance Methods
|
|
775
|
+
|
|
776
|
+
### def each {|x| ... } -> self
|
|
777
|
+
|
|
778
|
+
素の def。
|
|
779
|
+
|
|
780
|
+
## Constants
|
|
781
|
+
|
|
782
|
+
### const BAR -> Integer
|
|
783
|
+
|
|
784
|
+
定数。
|
|
785
|
+
MD
|
|
786
|
+
_, lib = parse_md(md)
|
|
787
|
+
entries = lib.classes.first.entries
|
|
788
|
+
assert_equal [["build"], ["create"], ["each"], ["BAR"]], entries.map(&:names)
|
|
789
|
+
assert_equal [:singleton_method, :singleton_method, :instance_method, :constant],
|
|
790
|
+
entries.map(&:type)
|
|
791
|
+
end
|
|
573
792
|
end
|
data/test/test_methodentry.rb
CHANGED
|
@@ -3,6 +3,7 @@ require 'bitclust'
|
|
|
3
3
|
require 'bitclust/methoddatabase'
|
|
4
4
|
require 'tmpdir'
|
|
5
5
|
require 'fileutils'
|
|
6
|
+
require 'json'
|
|
6
7
|
|
|
7
8
|
class TestMethodEntryTitleLabels < Test::Unit::TestCase
|
|
8
9
|
def test_title_labels_matches_label_when_no_alias
|
|
@@ -326,3 +327,113 @@ class TestMethodEntrySinceUntil < Test::Unit::TestCase
|
|
|
326
327
|
File.write(path, lines.join)
|
|
327
328
|
end
|
|
328
329
|
end
|
|
330
|
+
|
|
331
|
+
# rbs_sig property(RBS シグネチャ表示)。オーバーロード配列
|
|
332
|
+
# ({"segments" => 行, "params"/"arity"/"block" => メタ情報} の配列)を
|
|
333
|
+
# {"overloads": [...]} の JSON 1 行で 'String' 型 property に格納する。
|
|
334
|
+
# JSON は改行を含まず、値中の '=' や ',' も property ファイル
|
|
335
|
+
# (key=value 1 行形式)で安全。
|
|
336
|
+
#
|
|
337
|
+
# テストリスト:
|
|
338
|
+
# [x] 既定は nil で rbs_signature_overloads も nil
|
|
339
|
+
# [x] JSON を入れて save → reload で round-trip する
|
|
340
|
+
# [x] 旧形式(セグメント行列そのものの配列)は segments だけの
|
|
341
|
+
# オーバーロード列に読み替える(#322 以前の DB)
|
|
342
|
+
# [x] property 行が無い古い DB でも nil(後方互換)
|
|
343
|
+
# [x] 空文字列(シグネチャ無しで save された値)も nil 扱い
|
|
344
|
+
# [x] 壊れた JSON は nil 扱い(描画を落とさない)
|
|
345
|
+
class TestMethodEntryRbsSig < Test::Unit::TestCase
|
|
346
|
+
OVERLOADS = [
|
|
347
|
+
{'segments' => [['t', '('], ['c', 'Integer'], ['t', ') -> '], ['c', 'String']],
|
|
348
|
+
'params' => ['base'], 'arity' => [1, 1]},
|
|
349
|
+
{'segments' => [['t', '() -> void']],
|
|
350
|
+
'params' => [], 'arity' => [0, 0], 'block' => 'req'},
|
|
351
|
+
]
|
|
352
|
+
|
|
353
|
+
def setup
|
|
354
|
+
@dir = Dir.mktmpdir
|
|
355
|
+
@db = BitClust::MethodDatabase.new(@dir)
|
|
356
|
+
@db.init
|
|
357
|
+
@db.transaction do
|
|
358
|
+
@db.propset('version', '4.0')
|
|
359
|
+
@db.propset('encoding', 'utf-8')
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def teardown
|
|
364
|
+
FileUtils.rm_rf(@dir)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
# 未保存エントリの String 型 property は "(uninitialized)" センチネル
|
|
368
|
+
# なので、rbs_sig そのものではなく overloads が nil であることを見る
|
|
369
|
+
def test_default_has_no_overloads
|
|
370
|
+
m = build_entry('sig')
|
|
371
|
+
assert_nil m.rbs_signature_overloads
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
def test_roundtrip
|
|
375
|
+
m = build_entry('sig')
|
|
376
|
+
m.rbs_sig = JSON.generate({'overloads' => OVERLOADS})
|
|
377
|
+
m.save
|
|
378
|
+
|
|
379
|
+
reloaded = reload_entry(m.id)
|
|
380
|
+
assert_equal(OVERLOADS, reloaded.rbs_signature_overloads)
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def test_old_array_format_is_read_as_segments_only
|
|
384
|
+
m = build_entry('sig')
|
|
385
|
+
m.rbs_sig = JSON.generate(OVERLOADS.map {|o| o['segments'] })
|
|
386
|
+
m.save
|
|
387
|
+
|
|
388
|
+
reloaded = reload_entry(m.id)
|
|
389
|
+
assert_equal(OVERLOADS.map {|o| {'segments' => o['segments']} },
|
|
390
|
+
reloaded.rbs_signature_overloads)
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
def test_missing_property_is_backward_compatible
|
|
394
|
+
m = build_entry('sig')
|
|
395
|
+
m.save
|
|
396
|
+
strip_property_line(m.id, 'rbs_sig')
|
|
397
|
+
|
|
398
|
+
reloaded = reload_entry(m.id)
|
|
399
|
+
assert_nil reloaded.rbs_sig
|
|
400
|
+
assert_nil reloaded.rbs_signature_overloads
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def test_saved_without_signature_is_treated_as_absent
|
|
404
|
+
m = build_entry('sig')
|
|
405
|
+
m.save
|
|
406
|
+
|
|
407
|
+
reloaded = reload_entry(m.id)
|
|
408
|
+
assert_nil reloaded.rbs_signature_overloads
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def test_broken_json_is_treated_as_absent
|
|
412
|
+
m = build_entry('sig')
|
|
413
|
+
m.rbs_sig = '{broken'
|
|
414
|
+
assert_nil m.rbs_signature_overloads
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
private
|
|
418
|
+
|
|
419
|
+
def build_entry(name)
|
|
420
|
+
id = BitClust::NameUtils.build_method_id('_builtin', 'Foo', :instance_method, name)
|
|
421
|
+
m = BitClust::MethodEntry.new(@db, id)
|
|
422
|
+
m.names = [name]
|
|
423
|
+
m.visibility = :public
|
|
424
|
+
m.kind = :defined
|
|
425
|
+
m.source = "説明\n"
|
|
426
|
+
m
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def reload_entry(id)
|
|
430
|
+
fresh_db = BitClust::MethodDatabase.new(@dir)
|
|
431
|
+
BitClust::MethodEntry.new(fresh_db, id)
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def strip_property_line(id, key)
|
|
435
|
+
path = File.join(@dir, BitClust::NameUtils.encodeid("method/#{id}"))
|
|
436
|
+
lines = File.readlines(path).reject {|l| l.start_with?("#{key}=") }
|
|
437
|
+
File.write(path, lines.join)
|
|
438
|
+
end
|
|
439
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'test/unit'
|
|
3
|
+
require 'bitclust'
|
|
4
|
+
require 'bitclust/subcommands/methods_command'
|
|
5
|
+
|
|
6
|
+
class TestMethodsCommand < Test::Unit::TestCase
|
|
7
|
+
def setup
|
|
8
|
+
@cmd = BitClust::Subcommands::MethodsCommand.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_needs_no_database
|
|
12
|
+
assert_false(@cmd.needs_database?)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_content_option_is_not_accepted
|
|
16
|
+
assert_raise(OptionParser::InvalidOption) do
|
|
17
|
+
@cmd.parse(['-c', 'Object'])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_ri_database_option_is_not_accepted
|
|
22
|
+
assert_raise(OptionParser::InvalidOption) do
|
|
23
|
+
@cmd.parse(['--ri-database=/tmp/ri', 'Object'])
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_diff_and_ruby_options_are_kept
|
|
28
|
+
assert_nothing_raised do
|
|
29
|
+
@cmd.parse(['--ruby=3.4.8', '--diff=refm/api/src/_builtin/Object', 'Object'])
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -6,7 +6,9 @@ class TestMethodSignature < Test::Unit::TestCase
|
|
|
6
6
|
data("special var" => ["$_ -> String | nil", "--- $_ -> String | nil"],
|
|
7
7
|
"backquote" => ["`command` -> String", "--- `(command) -> String"],
|
|
8
8
|
"aset" => ["self[key] = value", "--- []=(key, value)"],
|
|
9
|
-
"aset splat" => ["[]=(*idxary)", "--- []=(*idxary)"]
|
|
9
|
+
"aset splat" => ["[]=(*idxary)", "--- []=(*idxary)"],
|
|
10
|
+
"self prefix" => ["build(x) -> Foo", "--- self.build(x) -> Foo"],
|
|
11
|
+
"class prefix" => ["build(x) -> Foo", "--- Foo.build(x) -> Foo"])
|
|
10
12
|
def test_friendlyname(data)
|
|
11
13
|
friendly_string, method_signature = data
|
|
12
14
|
assert_equal(friendly_string, BitClust::MethodSignature.parse(method_signature).friendly_string)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'bitclust'
|
|
4
|
+
require 'bitclust/screen'
|
|
5
|
+
|
|
6
|
+
class TestOpenSearchDescriptionScreen < Test::Unit::TestCase
|
|
7
|
+
SRC = <<'HERE'
|
|
8
|
+
= class Foo
|
|
9
|
+
description
|
|
10
|
+
HERE
|
|
11
|
+
|
|
12
|
+
def screen
|
|
13
|
+
_lib, db = BitClust::RRDParser.parse(SRC, 'testlib', {'version' => '3.4'})
|
|
14
|
+
datadir = File.expand_path('../data/bitclust', __dir__)
|
|
15
|
+
manager = BitClust::ScreenManager.new(
|
|
16
|
+
:templatedir => "#{datadir}/template",
|
|
17
|
+
:catalogdir => "#{datadir}/catalog",
|
|
18
|
+
:encoding => 'utf-8',
|
|
19
|
+
:default_encoding => 'utf-8',
|
|
20
|
+
:base_url => '',
|
|
21
|
+
:cgi_url => '/view',
|
|
22
|
+
:target_version => '3.4'
|
|
23
|
+
)
|
|
24
|
+
manager.opensearchdescription_screen(URI.parse('http://example.com/view/opensearchdescription'),
|
|
25
|
+
:database => db)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_body_is_bare_xml_without_html_layout
|
|
29
|
+
body = screen.body
|
|
30
|
+
assert_match(/\A<\?xml/, body)
|
|
31
|
+
assert_not_include(body, '<html')
|
|
32
|
+
assert_match(%r{\A<\?xml[^>]*\?>\s*<OpenSearchDescription\b.*</OpenSearchDescription>\s*\z}m, body)
|
|
33
|
+
assert_include(body, 'http://example.com/view/search')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test_content_type_is_opensearch_xml
|
|
37
|
+
assert_equal 'application/opensearchdescription+xml; charset=utf-8', screen.content_type
|
|
38
|
+
end
|
|
39
|
+
end
|
data/test/test_preprocessor.rb
CHANGED
|
@@ -516,6 +516,32 @@ HERE
|
|
|
516
516
|
assert_equal "", process(src, '4.0')
|
|
517
517
|
end
|
|
518
518
|
|
|
519
|
+
def test_single_version
|
|
520
|
+
# 単一版のみの省略記法(#%if (version == "V") と同義)
|
|
521
|
+
src = gated('#%version 3.1')
|
|
522
|
+
assert_equal "out\n", process(src, '3.0')
|
|
523
|
+
assert_equal "in\n", process(src, '3.1')
|
|
524
|
+
assert_equal "out\n", process(src, '3.2')
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
def test_single_version_quoted
|
|
528
|
+
src = gated('#%version "3.1"')
|
|
529
|
+
assert_equal "in\n", process(src, '3.1')
|
|
530
|
+
assert_equal "out\n", process(src, '3.2')
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
def test_single_version_old_prefix
|
|
534
|
+
src = gated("\#@version 3.1")
|
|
535
|
+
assert_equal "in\n", process(src, '3.1')
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
def test_single_version_teeny
|
|
539
|
+
# 版名は文字列一致(teeny 付き版名は teeny まで一致したときのみ)
|
|
540
|
+
src = gated('#%version 2.7.0')
|
|
541
|
+
assert_equal "in\n", process(src, '2.7.0')
|
|
542
|
+
assert_equal "out\n", process(src, '2.7')
|
|
543
|
+
end
|
|
544
|
+
|
|
519
545
|
def test_two_dot_range_is_error
|
|
520
546
|
# .. (終端を含む Range)は誤解を招くため受け付けない(#285)
|
|
521
547
|
assert_raise(BitClust::ParseError) { process(gated('#%version 3.1..3.4'), '3.2') }
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'stringio'
|
|
3
|
+
require 'tmpdir'
|
|
4
|
+
require 'bitclust'
|
|
5
|
+
require 'bitclust/subcommands/query_command'
|
|
6
|
+
|
|
7
|
+
class TestQueryCommand < Test::Unit::TestCase
|
|
8
|
+
def run_query(script, capi: false)
|
|
9
|
+
Dir.mktmpdir do |dir|
|
|
10
|
+
cmd = BitClust::Subcommands::QueryCommand.new
|
|
11
|
+
cmd.parse([script])
|
|
12
|
+
out = StringIO.new
|
|
13
|
+
orig, $stdout = $stdout, out
|
|
14
|
+
begin
|
|
15
|
+
cmd.exec([script], {:prefix => dir, :capi => capi})
|
|
16
|
+
ensure
|
|
17
|
+
$stdout = orig
|
|
18
|
+
end
|
|
19
|
+
out.string
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_db_is_available_to_the_script
|
|
24
|
+
assert_equal %Q("BitClust::MethodDatabase"\n), run_query('@db.class.name')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_capi_uses_function_database
|
|
28
|
+
assert_equal %Q("BitClust::FunctionDatabase"\n), run_query('@db.class.name', capi: true)
|
|
29
|
+
end
|
|
30
|
+
end
|