bitclust-core 1.3.0 → 1.6.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/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 +124 -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 +538 -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,231 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
|
|
5
|
+
require 'bitclust/entity_splitter'
|
|
6
|
+
require 'bitclust/include_graph'
|
|
7
|
+
|
|
8
|
+
# EntitySplitter: マルチエンティティ RD をエンティティ単位に分割する(O3)。
|
|
9
|
+
# 2段階:
|
|
10
|
+
# 1. resolve_header_gates — スコープ定数(常に真/偽)の版ゲートのうち、最初の内容行が
|
|
11
|
+
# エンティティ H1 のブロックを解決する(活きている枝を残しゲートを外す)。
|
|
12
|
+
# 版で改名されたエンティティ(thread/Mutex, Net::HTTPURITooLong 等)の H1 ペアが
|
|
13
|
+
# スコープ内の単一 H1 に収束し、旧名は活き枝の alias 行として残る。
|
|
14
|
+
# 2. segments — 深さ0の H1(またはスコープ内ゲート付き H1 ブロック)を境界に分割。
|
|
15
|
+
# セグメント間の内容は直前のエンティティに帰属。連結すると入力に一致する。
|
|
16
|
+
#
|
|
17
|
+
# テストリスト:
|
|
18
|
+
# [x] resolve: 常真 since + #@else 改名ペア → 活き枝のみ(thread/Mutex パターン)
|
|
19
|
+
# [x] resolve: 常偽 until + #@else → else 枝のみ
|
|
20
|
+
# [x] resolve: 常真ゲートがエンティティ全体を包む(else なし)→ unwrap(EarlyHints パターン)
|
|
21
|
+
# [x] resolve: 常偽ゲートがエンティティ全体を包む(else なし)→ ブロックごと除去
|
|
22
|
+
# [x] resolve: スコープ内ゲート(since 3.2 等)→ 据え置き
|
|
23
|
+
# [x] resolve: 散文を包むゲート(最初の内容行が H1 でない)→ 据え置き
|
|
24
|
+
# [x] resolve: ブロック内にネストした #@ があっても対応を取る
|
|
25
|
+
# [x] resolve: 活き枝に複数エンティティがあってもそのまま残す(base64 パターン)
|
|
26
|
+
# [x] segments: 裸 H1 で分割、内容は直前エンティティへ、連結=入力
|
|
27
|
+
# [x] segments: スコープ内ゲート付き H1 ブロックは丸ごと1セグメント
|
|
28
|
+
# [x] segments: #@samplecode 内の「= class」風の行は境界にしない
|
|
29
|
+
# [x] segments: 先頭に H1 以外の内容がある場合は nil
|
|
30
|
+
# [x] entity_filename: :: → __、. は保持
|
|
31
|
+
class TestEntitySplitter < Test::Unit::TestCase
|
|
32
|
+
def scope
|
|
33
|
+
BitClust::IncludeGraph::Scope.new("3.0", "4.2")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def resolve(src)
|
|
37
|
+
BitClust::EntitySplitter.resolve_header_gates(src, scope)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def segments(src)
|
|
41
|
+
BitClust::EntitySplitter.segments(src)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# ---- resolve_header_gates ----
|
|
45
|
+
|
|
46
|
+
def test_resolve_renamed_entity_keeps_active_branch
|
|
47
|
+
# thread/Mutex: #@since 2.3.0(常真)で改名された H1 ペア
|
|
48
|
+
src = <<~RRD
|
|
49
|
+
\#@since 2.3.0
|
|
50
|
+
= class Thread::Mutex < Object
|
|
51
|
+
alias Mutex
|
|
52
|
+
\#@else
|
|
53
|
+
= class Mutex < Object
|
|
54
|
+
\#@end
|
|
55
|
+
|
|
56
|
+
本文。
|
|
57
|
+
RRD
|
|
58
|
+
expected = <<~RRD
|
|
59
|
+
= class Thread::Mutex < Object
|
|
60
|
+
alias Mutex
|
|
61
|
+
|
|
62
|
+
本文。
|
|
63
|
+
RRD
|
|
64
|
+
assert_equal expected, resolve(src)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def test_resolve_never_until_with_else_keeps_else_branch
|
|
68
|
+
src = "\#@until 2.3.0\n= class Old < Object\n\#@else\n= class New < Object\n\#@end\n本文。\n"
|
|
69
|
+
assert_equal "= class New < Object\n本文。\n", resolve(src)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_resolve_unwraps_wholly_gated_entity
|
|
73
|
+
# Net::HTTPEarlyHints: #@since 2.6.0(常真)がエンティティ全体を包む
|
|
74
|
+
src = "= class A < B\n\n\#@since 2.6.0\n= class C < D\n説明。\n\#@end\n\n= class E < F\n"
|
|
75
|
+
assert_equal "= class A < B\n\n= class C < D\n説明。\n\n= class E < F\n", resolve(src)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_resolve_drops_never_gated_entity
|
|
79
|
+
src = "= class A < B\n\n\#@until 2.4.0\n= class Dead < B\n説明。\n\#@end\n\n= class E < F\n"
|
|
80
|
+
assert_equal "= class A < B\n\n= class E < F\n", resolve(src)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def test_resolve_keeps_in_scope_gate
|
|
84
|
+
src = "\#@since 3.2\n= class New < Object\n説明。\n\#@end\n"
|
|
85
|
+
assert_equal src, resolve(src)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_resolve_keeps_prose_gates
|
|
89
|
+
src = "= class A < B\n\#@since 2.3.0\n新しい説明。\n\#@else\n古い説明。\n\#@end\n"
|
|
90
|
+
assert_equal src, resolve(src)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_resolve_provably_true_if_gate_with_entities
|
|
94
|
+
# digest.rd: #@if(version >= "1.8.6")(常真)がエンティティ構造ごと包む
|
|
95
|
+
src = "\#@if(version >= \"1.8.6\")\n= class A < Object\n\n= class B < A\ninclude I\n\#@else\n= class B < Object\n\#@end\n共通。\n"
|
|
96
|
+
assert_equal "= class A < Object\n\n= class B < A\ninclude I\n共通。\n", resolve(src)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_resolve_constant_gate_containing_h1_after_prose
|
|
100
|
+
# syslog.rd: 常真ゲートが散文の後にエンティティ H1 を含む
|
|
101
|
+
src = "= module C\n\n\#@since 2.0.0\n散文。\n= module D\nD。\n\#@end\n"
|
|
102
|
+
assert_equal "= module C\n\n散文。\n= module D\nD。\n", resolve(src)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def test_resolve_keeps_relation_only_constant_gate
|
|
106
|
+
# H1 を含まない定数ゲート(gated relations)は front matter の #@ 表現に任せる
|
|
107
|
+
src = "= module C\n\#@since 2.0.0\ninclude X\n\#@end\n"
|
|
108
|
+
assert_equal src, resolve(src)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_resolve_ignores_h1_like_lines_inside_samplecode
|
|
112
|
+
src = "\#@since 2.0.0\n散文。\n\#@samplecode\n= class Fake < Object\n\#@end\n\#@end\n"
|
|
113
|
+
assert_equal src, resolve(src)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def test_resolve_handles_quoted_version
|
|
117
|
+
# Preprocessor は #@since "1.8.5" のクォート形式も受理する(_builtin/Process に実在)
|
|
118
|
+
src = "\#@since \"1.8.5\"\n= class A < B\n本文。\n\#@end\n"
|
|
119
|
+
assert_equal "= class A < B\n本文。\n", resolve(src)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def test_resolve_handles_nested_blocks
|
|
123
|
+
src = <<~RRD
|
|
124
|
+
\#@since 1.9.1
|
|
125
|
+
= class A < B
|
|
126
|
+
\#@since 2.0.0
|
|
127
|
+
版分岐の説明。
|
|
128
|
+
\#@end
|
|
129
|
+
\#@end
|
|
130
|
+
RRD
|
|
131
|
+
expected = <<~RRD
|
|
132
|
+
= class A < B
|
|
133
|
+
\#@since 2.0.0
|
|
134
|
+
版分岐の説明。
|
|
135
|
+
\#@end
|
|
136
|
+
RRD
|
|
137
|
+
assert_equal expected, resolve(src)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def test_resolve_keeps_multi_entity_active_branch
|
|
141
|
+
# base64/Base64: 常真ゲートの枝に複数エンティティ
|
|
142
|
+
src = "\#@since 1.9.1\n= module Base64\n\n= reopen Kernel\n\#@else\n= module Base64\n\#@end\n"
|
|
143
|
+
assert_equal "= module Base64\n\n= reopen Kernel\n", resolve(src)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# ---- segments ----
|
|
147
|
+
|
|
148
|
+
def test_segments_split_at_bare_h1
|
|
149
|
+
src = "= class A < Object\ninclude Foo\n\nA の説明。\n\n= class B < Object\nB の説明。\n"
|
|
150
|
+
segs = segments(src)
|
|
151
|
+
assert_equal ["A", "B"], segs.map(&:first)
|
|
152
|
+
assert_equal "= class A < Object\ninclude Foo\n\nA の説明。\n\n", segs[0][1]
|
|
153
|
+
assert_equal "= class B < Object\nB の説明。\n", segs[1][1]
|
|
154
|
+
assert_equal src, segs.map(&:last).join
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_segments_in_scope_gated_block_is_one_segment
|
|
158
|
+
src = "= class A < Object\n\n\#@since 3.2\n= class New < Object\n説明。\n\#@end\n"
|
|
159
|
+
segs = segments(src)
|
|
160
|
+
assert_equal ["A", "New"], segs.map(&:first)
|
|
161
|
+
assert_equal "\#@since 3.2\n= class New < Object\n説明。\n\#@end\n", segs[1][1]
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def test_segments_partial_gate_around_h1_is_not_a_boundary
|
|
165
|
+
# syslog の旧構造: H1 と見出しだけがゲートされ、定数群はゲートの外にある。
|
|
166
|
+
# 単独ファイル化するとゲートが偽の版で自立パースできない
|
|
167
|
+
# (旧世界では直前エンティティに付く)ので分割境界にしない
|
|
168
|
+
src = "= class A < Object\n\n" \
|
|
169
|
+
"\#@since 2.0.0\n= module B\n説明。\n== Constants\n\#@end\n" \
|
|
170
|
+
"--- CONST -> Integer\n"
|
|
171
|
+
segs = segments(src)
|
|
172
|
+
assert_equal ["A"], segs.map(&:first)
|
|
173
|
+
assert_equal src, segs[0][1]
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def test_segments_gated_boundary_allows_trailing_blanks
|
|
177
|
+
src = "= class A < Object\n\n" \
|
|
178
|
+
"\#@since 3.2\n= class New < Object\n説明。\n\#@end\n\n"
|
|
179
|
+
segs = segments(src)
|
|
180
|
+
assert_equal ["A", "New"], segs.map(&:first)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def test_segments_ignores_h1_like_lines_in_samplecode
|
|
184
|
+
src = "= class A < Object\n\#@samplecode\n= class B < Object\n\#@end\n"
|
|
185
|
+
segs = segments(src)
|
|
186
|
+
assert_equal ["A"], segs.map(&:first)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def test_segments_leading_content_becomes_base_segment
|
|
190
|
+
# ライブラリファイルのインライン・エンティティ: 先頭のライブラリ概要部は
|
|
191
|
+
# name=nil のベースセグメントになる
|
|
192
|
+
src = "category Cat\n\n概要。\n\n= class A < Object\nA の説明。\n"
|
|
193
|
+
segs = segments(src)
|
|
194
|
+
assert_equal [nil, "A"], segs.map(&:first)
|
|
195
|
+
assert_equal "category Cat\n\n概要。\n\n", segs[0][1]
|
|
196
|
+
assert_equal src, segs.map(&:last).join
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def test_segments_single_entity
|
|
200
|
+
src = "= class A < Object\n説明。\n"
|
|
201
|
+
assert_equal [["A", src]], segments(src)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# ---- header_relations? ----
|
|
205
|
+
|
|
206
|
+
def test_header_relations_detects_relation_after_h1
|
|
207
|
+
assert_true BitClust::EntitySplitter.header_relations?(
|
|
208
|
+
"= class A < Object\ninclude Foo\n\n説明。\n")
|
|
209
|
+
assert_true BitClust::EntitySplitter.header_relations?(
|
|
210
|
+
"= class A < Object\n\n説明。\n\n= class B < Object\nalias C\n")
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def test_header_relations_ignores_body_and_samplecode
|
|
214
|
+
# 本文到達後の include 風の行(コード例等)は数えない
|
|
215
|
+
assert_false BitClust::EntitySplitter.header_relations?(
|
|
216
|
+
"= module Math\n\n説明。\n\n\#@samplecode\ninclude Math\n\#@end\n")
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def test_header_relations_counts_gated_relations
|
|
220
|
+
assert_true BitClust::EntitySplitter.header_relations?(
|
|
221
|
+
"= class A < Object\n\#@since 2.6.0\nalias B\n\#@end\n\n説明。\n")
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# ---- entity_filename ----
|
|
225
|
+
|
|
226
|
+
def test_entity_filename
|
|
227
|
+
assert_equal "Net__HTTPOK", BitClust::EntitySplitter.entity_filename("Net::HTTPOK")
|
|
228
|
+
assert_equal "ARGF.class", BitClust::EntitySplitter.entity_filename("ARGF.class")
|
|
229
|
+
assert_equal "Time", BitClust::EntitySplitter.entity_filename("Time")
|
|
230
|
+
end
|
|
231
|
+
end
|
data/test/test_entry.rb
CHANGED
|
@@ -11,11 +11,11 @@ alias HogeHogeHoge
|
|
|
11
11
|
--- hoge
|
|
12
12
|
hoge
|
|
13
13
|
--- fuga
|
|
14
|
-
|
|
14
|
+
{: undef}
|
|
15
15
|
fuga
|
|
16
16
|
== Instance Methods
|
|
17
17
|
--- fugafuga
|
|
18
|
-
|
|
18
|
+
{: undef}
|
|
19
19
|
fugafuga
|
|
20
20
|
= class Bar < Hoge
|
|
21
21
|
== Class Methods
|
|
@@ -62,5 +62,210 @@ HERE
|
|
|
62
62
|
assert('Exception', @lib.fetch_class("Err").superclass.name)
|
|
63
63
|
assert('Exception', @lib.fetch_class("ErrErr").superclass.name)
|
|
64
64
|
end
|
|
65
|
+
|
|
66
|
+
def test_instance_method?
|
|
67
|
+
bar = @lib.fetch_class("Bar")
|
|
68
|
+
assert(bar.instance_method?('fugafuga'))
|
|
69
|
+
assert(!bar.instance_method?('fugafuga', false))
|
|
70
|
+
hoge = @lib.fetch_class("Hoge")
|
|
71
|
+
assert(hoge.instance_method?('fugafuga'))
|
|
72
|
+
assert(hoge.instance_method?('fugafuga', false))
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class TestEntryDescription < Test::Unit::TestCase
|
|
77
|
+
def parse_class(class_source)
|
|
78
|
+
lib, = BitClust::RRDParser.parse(class_source, 'hoge')
|
|
79
|
+
lib.fetch_class('Hoge')
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_description_truncates_newline_between_non_ascii
|
|
83
|
+
klass = parse_class(<<HERE)
|
|
84
|
+
= class Hoge
|
|
85
|
+
これは1行目で
|
|
86
|
+
あとに続きます。
|
|
87
|
+
|
|
88
|
+
以降の段落は含まれません。
|
|
89
|
+
HERE
|
|
90
|
+
assert_equal('これは1行目であとに続きます。', klass.description)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_description_truncates_consecutive_newlines_between_non_ascii
|
|
94
|
+
klass = parse_class(<<HERE)
|
|
95
|
+
= class Hoge
|
|
96
|
+
あい
|
|
97
|
+
うえ
|
|
98
|
+
おか。
|
|
99
|
+
HERE
|
|
100
|
+
assert_equal('あいうえおか。', klass.description)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def test_description_converts_newline_to_space_around_ascii
|
|
104
|
+
klass = parse_class(<<HERE)
|
|
105
|
+
= class Hoge
|
|
106
|
+
first line
|
|
107
|
+
second line
|
|
108
|
+
HERE
|
|
109
|
+
assert_equal('first line second line', klass.description)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def test_description_replaces_bracket_link_with_plain_text
|
|
113
|
+
klass = parse_class(<<HERE)
|
|
114
|
+
= class Hoge
|
|
115
|
+
自身の hostname を文字列で返します。また、[[m:URI::Generic#host]] が設
|
|
116
|
+
定されていない場合は [[c:Array]] を返します。
|
|
117
|
+
HERE
|
|
118
|
+
assert_equal('自身の hostname を文字列で返します。また、URI::Generic#host が設定されていない場合は Array を返します。',
|
|
119
|
+
klass.description)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def test_description_replaces_indexer_bracket_link
|
|
123
|
+
klass = parse_class(<<HERE)
|
|
124
|
+
= class Hoge
|
|
125
|
+
[[m:String#[] ]] を参照。
|
|
126
|
+
HERE
|
|
127
|
+
assert_equal('String#[] を参照。', klass.description)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_method_description_is_plain_text
|
|
131
|
+
klass = parse_class(<<HERE)
|
|
132
|
+
= class Hoge
|
|
133
|
+
== Instance Methods
|
|
134
|
+
--- fuga
|
|
135
|
+
|
|
136
|
+
[[c:Array]] を日本語で
|
|
137
|
+
返します。
|
|
138
|
+
|
|
139
|
+
次の段落。
|
|
140
|
+
HERE
|
|
141
|
+
method = klass.entries.detect {|m| m.name == 'fuga' }
|
|
142
|
+
assert_equal('Array を日本語で返します。', method.description)
|
|
143
|
+
end
|
|
65
144
|
end
|
|
66
145
|
|
|
146
|
+
class TestEntryNomethod < Test::Unit::TestCase
|
|
147
|
+
def parse_class(class_source)
|
|
148
|
+
lib, = BitClust::RRDParser.parse(class_source, 'hoge')
|
|
149
|
+
lib.fetch_class('Hoge')
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def test_nomethod_is_partitioned_separately
|
|
153
|
+
klass = parse_class(<<HERE)
|
|
154
|
+
= class Hoge
|
|
155
|
+
== Instance Methods
|
|
156
|
+
--- fuga
|
|
157
|
+
{: nomethod}
|
|
158
|
+
|
|
159
|
+
説明のためのエントリです。
|
|
160
|
+
HERE
|
|
161
|
+
parts = klass.partitioned_entries
|
|
162
|
+
assert_equal(['fuga'], parts.nomethod.map(&:name))
|
|
163
|
+
assert_equal([], parts.instance_methods.map(&:name))
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def test_redefined_is_partitioned_separately
|
|
167
|
+
klass = parse_class(<<HERE)
|
|
168
|
+
= class Hoge
|
|
169
|
+
== Instance Methods
|
|
170
|
+
--- bar
|
|
171
|
+
|
|
172
|
+
説明です。
|
|
173
|
+
|
|
174
|
+
= redefine Hoge
|
|
175
|
+
== Instance Methods
|
|
176
|
+
--- baz
|
|
177
|
+
|
|
178
|
+
再定義の説明です。
|
|
179
|
+
HERE
|
|
180
|
+
parts = klass.partitioned_entries
|
|
181
|
+
assert_equal(['baz'], parts.redefined.map(&:name))
|
|
182
|
+
assert_equal(['bar'], parts.instance_methods.map(&:name))
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def test_description_skips_leading_metadata_paragraph
|
|
186
|
+
klass = parse_class(<<HERE)
|
|
187
|
+
= class Hoge
|
|
188
|
+
== Instance Methods
|
|
189
|
+
--- fuga
|
|
190
|
+
{: nomethod}
|
|
191
|
+
|
|
192
|
+
説明のためのエントリです。
|
|
193
|
+
HERE
|
|
194
|
+
method = klass.entries.detect {|m| m.name == 'fuga' }
|
|
195
|
+
assert_equal('説明のためのエントリです。', method.description)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def test_description_is_empty_when_only_metadata
|
|
199
|
+
klass = parse_class(<<HERE)
|
|
200
|
+
= class Hoge
|
|
201
|
+
== Instance Methods
|
|
202
|
+
--- fuga
|
|
203
|
+
{: undef}
|
|
204
|
+
HERE
|
|
205
|
+
method = klass.entries.detect {|m| m.name == 'fuga' }
|
|
206
|
+
assert_equal('', method.description)
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
class TestClassEntryDynamicallyIncludedEntries < Test::Unit::TestCase
|
|
211
|
+
SRC = <<'HERE'
|
|
212
|
+
= module DynMod
|
|
213
|
+
dyn module
|
|
214
|
+
== Instance Methods
|
|
215
|
+
--- dyn_method
|
|
216
|
+
dyn method
|
|
217
|
+
== Private Instance Methods
|
|
218
|
+
--- hidden_dyn_method
|
|
219
|
+
hidden dyn method
|
|
220
|
+
= class Host < Object
|
|
221
|
+
host class
|
|
222
|
+
== Instance Methods
|
|
223
|
+
--- host_method
|
|
224
|
+
host method
|
|
225
|
+
= reopen Host
|
|
226
|
+
include DynMod
|
|
227
|
+
HERE
|
|
228
|
+
|
|
229
|
+
def setup
|
|
230
|
+
@lib, = BitClust::RRDParser.parse(SRC, 'dynlib')
|
|
231
|
+
@host = @lib.fetch_class('Host')
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def test_returns_public_instance_methods_of_dynamically_included_modules
|
|
235
|
+
assert_equal(['dyn_method'], @host.dynamically_included_entries.map(&:name))
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def test_excludes_private_instance_methods_of_the_dynamically_included_module
|
|
239
|
+
names = @host.dynamically_included_entries.map(&:name)
|
|
240
|
+
assert_not_include(names, 'hidden_dyn_method')
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def test_entries_keep_their_originating_module_and_library
|
|
244
|
+
entry = @host.dynamically_included_entries.first
|
|
245
|
+
assert_equal('DynMod', entry.klass.name)
|
|
246
|
+
assert_equal('dynlib', entry.library.name)
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def test_does_not_affect_ancestors
|
|
250
|
+
# dynamic include must not change the MRO/ancestors chain.
|
|
251
|
+
assert_equal(['Host', 'Object'], @host.ancestors.map(&:name))
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def test_does_not_affect_entries_or_partitioned_entries
|
|
255
|
+
assert_not_include(@host.entries.map(&:name), 'dyn_method')
|
|
256
|
+
parts = @host.partitioned_entries
|
|
257
|
+
assert_not_include(parts.instance_methods.map(&:name), 'dyn_method')
|
|
258
|
+
assert_not_include(parts.added.map(&:name), 'dyn_method')
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def test_is_empty_when_class_has_no_dynamic_include
|
|
262
|
+
plain, = BitClust::RRDParser.parse(<<'PLAIN', 'dynlib')
|
|
263
|
+
= class Plain < Object
|
|
264
|
+
plain class
|
|
265
|
+
== Instance Methods
|
|
266
|
+
--- plain_method
|
|
267
|
+
plain method
|
|
268
|
+
PLAIN
|
|
269
|
+
assert_equal([], plain.fetch_class('Plain').dynamically_included_entries)
|
|
270
|
+
end
|
|
271
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'bitclust'
|
|
3
|
+
require 'bitclust/screen'
|
|
4
|
+
|
|
5
|
+
class TestEOLWarning < Test::Unit::TestCase
|
|
6
|
+
SRC = <<'HERE'
|
|
7
|
+
= class Hoge
|
|
8
|
+
hoge class
|
|
9
|
+
== Instance Methods
|
|
10
|
+
--- foo
|
|
11
|
+
foo method
|
|
12
|
+
HERE
|
|
13
|
+
|
|
14
|
+
BANNER_TEXT = 'このマニュアルは既にメンテナンスが終了したバージョンの Ruby を対象としています。'
|
|
15
|
+
LATEST_URL = 'https://docs.ruby-lang.org/ja/latest/'
|
|
16
|
+
|
|
17
|
+
def render(manager_options)
|
|
18
|
+
lib, = BitClust::RRDParser.parse(SRC, 'testlib')
|
|
19
|
+
datadir = File.expand_path('../data/bitclust', __dir__)
|
|
20
|
+
manager = BitClust::ScreenManager.new({
|
|
21
|
+
:templatedir => "#{datadir}/template.offline",
|
|
22
|
+
:catalogdir => "#{datadir}/catalog",
|
|
23
|
+
:encoding => 'utf-8',
|
|
24
|
+
:default_encoding => 'utf-8',
|
|
25
|
+
:base_url => '',
|
|
26
|
+
:target_version => '3.0'
|
|
27
|
+
}.merge(manager_options))
|
|
28
|
+
db = BitClust::MethodDatabase.dummy('version' => '3.0')
|
|
29
|
+
manager.class_screen(lib.fetch_class('Hoge'), :database => db).body
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_eol_warning_banner_is_shown_when_enabled
|
|
33
|
+
html = render(:eol_warning => true)
|
|
34
|
+
assert_include(html, BANNER_TEXT)
|
|
35
|
+
assert_include(html, LATEST_URL)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_eol_warning_banner_is_hidden_by_default
|
|
39
|
+
html = render({})
|
|
40
|
+
assert_not_include(html, BANNER_TEXT)
|
|
41
|
+
assert_not_include(html, LATEST_URL)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -48,4 +48,15 @@ HERE
|
|
|
48
48
|
assert_equal data[:expected], result.collect(&:source)
|
|
49
49
|
}
|
|
50
50
|
end
|
|
51
|
+
|
|
52
|
+
# source_location points at the file only; the line number is no longer
|
|
53
|
+
# recorded (it would only churn the generated diffs).
|
|
54
|
+
def test_source_location_has_no_line_number
|
|
55
|
+
@db.transaction {
|
|
56
|
+
result = @parser.parse_file(@path, "test.c", {"version" => "2.6.0"})
|
|
57
|
+
location = result.first.source_location
|
|
58
|
+
assert_equal @path, location.file
|
|
59
|
+
assert_nil location.line
|
|
60
|
+
}
|
|
61
|
+
end
|
|
51
62
|
end
|