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,166 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'bitclust'
|
|
3
|
+
require 'bitclust/screen'
|
|
4
|
+
|
|
5
|
+
# Covers data/bitclust/template.offline, used by `bitclust statichtml` (the
|
|
6
|
+
# production docs.ruby-lang.org build) and `bitclust chm`.
|
|
7
|
+
#
|
|
8
|
+
# NOTE: only one templatedir is exercised here on purpose. Screen#run_template
|
|
9
|
+
# caches the compiled ERB template methods on the *class* (MethodScreen),
|
|
10
|
+
# keyed only by method name (e.g. "method_template"), regardless of which
|
|
11
|
+
# @template_repository the instance was built with. So constructing
|
|
12
|
+
# MethodScreen from two different templatedirs (e.g. this one and
|
|
13
|
+
# data/bitclust/template) within the same process is unreliable: whichever
|
|
14
|
+
# templatedir's ERB gets compiled first "wins" for every MethodScreen built
|
|
15
|
+
# afterwards, in every test file, for the rest of the run. This is a
|
|
16
|
+
# pre-existing quirk of Screen, not something introduced here.
|
|
17
|
+
#
|
|
18
|
+
# data/bitclust/template, data/bitclust/template.lillia and
|
|
19
|
+
# data/bitclust/template.epub were hand-verified (each in its own process,
|
|
20
|
+
# not committed as an automated test here) to build @title the same way as
|
|
21
|
+
# template.offline below, just keeping their pre-existing
|
|
22
|
+
# "#{entry.type_label} #{entry.label}" prefix -- i.e. the fix is
|
|
23
|
+
# entry.label -> entry.title_labels.join(', ') in all four `method`
|
|
24
|
+
# templates, so the CHM (template) and EPUB (template.epub) screens get the
|
|
25
|
+
# same alias listing.
|
|
26
|
+
class TestMethodScreenTitle < Test::Unit::TestCase
|
|
27
|
+
SRC = <<'HERE'
|
|
28
|
+
= class Enumerable2 < Object
|
|
29
|
+
enumerable class
|
|
30
|
+
== Instance Methods
|
|
31
|
+
--- collect -> Array
|
|
32
|
+
--- map -> Array
|
|
33
|
+
|
|
34
|
+
説明のためのエントリ
|
|
35
|
+
|
|
36
|
+
--- select -> Array
|
|
37
|
+
|
|
38
|
+
説明2
|
|
39
|
+
HERE
|
|
40
|
+
|
|
41
|
+
def setup
|
|
42
|
+
@lib, @db = BitClust::RRDParser.parse(SRC, 'testlib')
|
|
43
|
+
datadir = File.expand_path('../data/bitclust', __dir__)
|
|
44
|
+
@manager = BitClust::ScreenManager.new(
|
|
45
|
+
:templatedir => "#{datadir}/template.offline",
|
|
46
|
+
:catalogdir => "#{datadir}/catalog",
|
|
47
|
+
:encoding => 'utf-8',
|
|
48
|
+
:default_encoding => 'utf-8',
|
|
49
|
+
:base_url => '',
|
|
50
|
+
:target_version => '3.4'
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def method_html(spec)
|
|
55
|
+
entry = @db.get_method(BitClust::MethodSpec.parse(spec))
|
|
56
|
+
@manager.method_screen([entry], :database => @db).body
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def title_of(html)
|
|
60
|
+
html[/<title>(.*?) \(Ruby/, 1]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# template.offline's <title> has never included the "instance method"
|
|
64
|
+
# type_label prefix (only entry.label); the alias fix must keep that
|
|
65
|
+
# pre-existing convention and just expand the single name to every alias.
|
|
66
|
+
def test_title_lists_every_alias
|
|
67
|
+
assert_equal('Enumerable2#collect, Enumerable2#map',
|
|
68
|
+
title_of(method_html('Enumerable2#collect')))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Both aliases are the very same entry, so they share one page/title
|
|
72
|
+
# regardless of which alias URL was requested.
|
|
73
|
+
def test_title_is_the_same_regardless_of_which_alias_was_requested
|
|
74
|
+
assert_equal(method_html('Enumerable2#collect'), method_html('Enumerable2#map'))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# A method without any alias renders exactly as before: only its own name.
|
|
78
|
+
def test_title_is_unchanged_for_a_method_without_aliases
|
|
79
|
+
html = method_html('Enumerable2#select')
|
|
80
|
+
assert_equal('Enumerable2#select', title_of(html))
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Only the <title> tag changes; the on-page h1 headline keeps showing only
|
|
84
|
+
# the entry's own (alphabetically-first) name, as before.
|
|
85
|
+
def test_h1_headline_is_not_affected
|
|
86
|
+
html = method_html('Enumerable2#collect')
|
|
87
|
+
assert_match(%r{<h1>instance method Enumerable2\#collect</h1>}, html)
|
|
88
|
+
assert_not_match(/<h1>[^<]*Enumerable2#map/, html)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# bitclust#132 P3: since/until バージョンバッジが method ページ(template.offline、
|
|
93
|
+
# statichtml/chm が使う経路)の <dt> に実際に描画されることのエンドツーエンド確認
|
|
94
|
+
class TestMethodScreenVersionBadges < Test::Unit::TestCase
|
|
95
|
+
SRC = <<'HERE'
|
|
96
|
+
= class Enumerable2 < Object
|
|
97
|
+
enumerable class
|
|
98
|
+
== Instance Methods
|
|
99
|
+
--- select -> Array
|
|
100
|
+
|
|
101
|
+
説明
|
|
102
|
+
HERE
|
|
103
|
+
|
|
104
|
+
def setup
|
|
105
|
+
@lib, @db = BitClust::RRDParser.parse(SRC, 'testlib')
|
|
106
|
+
datadir = File.expand_path('../data/bitclust', __dir__)
|
|
107
|
+
@manager = BitClust::ScreenManager.new(
|
|
108
|
+
:templatedir => "#{datadir}/template.offline",
|
|
109
|
+
:catalogdir => "#{datadir}/catalog",
|
|
110
|
+
:encoding => 'utf-8',
|
|
111
|
+
:default_encoding => 'utf-8',
|
|
112
|
+
:base_url => '',
|
|
113
|
+
:target_version => '3.4'
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def test_since_badge_is_rendered_after_fill_since
|
|
118
|
+
entry = @db.get_method(BitClust::MethodSpec.parse('Enumerable2#select'))
|
|
119
|
+
entry.fill_since('select', '3.2')
|
|
120
|
+
html = @manager.method_screen([entry], :database => @db).body
|
|
121
|
+
assert_include(html, '<span class="method-since-badge">Ruby 3.2 から</span>')
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# bitclust#250: Ruby 4.0 以降のドキュメントでは module function の表記を
|
|
126
|
+
# 独自の「.#」から「?.」に変える(表示のみ、識別子は変えない)。この
|
|
127
|
+
# メソッドページの見出し・<title> がまさに issue に挙がっている
|
|
128
|
+
# 「module function Kernel.#open」の例そのもの
|
|
129
|
+
class TestMethodScreenModuleFunctionDisplay < Test::Unit::TestCase
|
|
130
|
+
SRC = <<'HERE'
|
|
131
|
+
= module Kernel
|
|
132
|
+
description
|
|
133
|
+
== Module Functions
|
|
134
|
+
--- mf
|
|
135
|
+
|
|
136
|
+
説明
|
|
137
|
+
HERE
|
|
138
|
+
|
|
139
|
+
def render(version)
|
|
140
|
+
_lib, db = BitClust::RRDParser.parse(SRC, 'testlib', {'version' => version})
|
|
141
|
+
entry = db.get_method(BitClust::MethodSpec.parse('Kernel.#mf'))
|
|
142
|
+
datadir = File.expand_path('../data/bitclust', __dir__)
|
|
143
|
+
manager = BitClust::ScreenManager.new(
|
|
144
|
+
:templatedir => "#{datadir}/template.offline",
|
|
145
|
+
:catalogdir => "#{datadir}/catalog",
|
|
146
|
+
:encoding => 'utf-8',
|
|
147
|
+
:default_encoding => 'utf-8',
|
|
148
|
+
:base_url => '',
|
|
149
|
+
:target_version => version
|
|
150
|
+
)
|
|
151
|
+
manager.method_screen([entry], :database => db).body
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def test_headline_and_title_show_dot_hash_before_4_0
|
|
155
|
+
html = render('3.4')
|
|
156
|
+
assert_match(%r{<h1>module function Kernel\.#mf</h1>}, html)
|
|
157
|
+
assert_include(html, '<title>Kernel.#mf')
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def test_headline_and_title_switch_to_question_dot_at_4_0
|
|
161
|
+
html = render('4.0')
|
|
162
|
+
assert_match(%r{<h1>module function Kernel\?\.mf</h1>}, html)
|
|
163
|
+
assert_include(html, '<title>Kernel?.mf')
|
|
164
|
+
assert_not_include(html, 'Kernel.#mf')
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'test/unit'
|
|
3
|
+
require 'bitclust'
|
|
4
|
+
require 'bitclust/methoddatabase'
|
|
5
|
+
require 'bitclust/method_since_calculator'
|
|
6
|
+
require 'tmpdir'
|
|
7
|
+
require 'fileutils'
|
|
8
|
+
|
|
9
|
+
# メソッド名別 since/until の算出(bitclust#132 P2)。
|
|
10
|
+
#
|
|
11
|
+
# テストリスト:
|
|
12
|
+
# [x] フロア(ラダー最古版から存在)のメソッドは since も until も付かない
|
|
13
|
+
# [x] #@since ゲート付きメソッドは、追加された版以降の対象すべてで
|
|
14
|
+
# since が付く
|
|
15
|
+
# [x] 別名グループ: シグネチャごとに異なるゲートを持てば名前ごとに
|
|
16
|
+
# 別の since になる(-@ は 2.0.0、dedup は 3.0)。ゲートが効いて
|
|
17
|
+
# いない版の対象ではその別名自体が存在しない
|
|
18
|
+
# [x] #@until ゲート付きメソッドは、消える1つ前の版の対象で until が付き、
|
|
19
|
+
# 消えた後の対象にはエントリ自体が存在しない
|
|
20
|
+
# [x] インスタンスメソッドとシンゲルトンメソッドは同名でも別キー
|
|
21
|
+
# [x] kind=:undefined のエントリは走査で無視される: {: undef} → 実メソッド化
|
|
22
|
+
# したものは実メソッド化した版が since になり、逆に undef 化は削除扱いで
|
|
23
|
+
# 前の版の対象に until が付く
|
|
24
|
+
# [x] kind=:undefined のエントリには適用でも書き込まない
|
|
25
|
+
# [x] ラダーに同じバージョンが重複していれば .new で UserError
|
|
26
|
+
# [x] apply は冪等: 2回目は floor_skipped 以外すべて0
|
|
27
|
+
# [x] 既に値がある名前は上書きしない(著者値が算出値より優先)
|
|
28
|
+
# [x] 対象DBのバージョンがラダーに無ければ apply は UserError
|
|
29
|
+
# [x] 統合: `{: since="X"}` 属性行(#132 P4)でパース時に記録された値は
|
|
30
|
+
# 算出結果で上書きされない(RD ソース上の明示注記が算出値より優先)
|
|
31
|
+
class TestMethodSinceCalculator < Test::Unit::TestCase
|
|
32
|
+
RD = <<~'RD'
|
|
33
|
+
description
|
|
34
|
+
|
|
35
|
+
= class MSCTest
|
|
36
|
+
== Instance Methods
|
|
37
|
+
--- old_timer
|
|
38
|
+
|
|
39
|
+
説明
|
|
40
|
+
|
|
41
|
+
#@since 2.0.0
|
|
42
|
+
--- newmeth
|
|
43
|
+
|
|
44
|
+
説明
|
|
45
|
+
#@end
|
|
46
|
+
|
|
47
|
+
#@since 3.0
|
|
48
|
+
--- overridden
|
|
49
|
+
{: since="2.5"}
|
|
50
|
+
|
|
51
|
+
説明
|
|
52
|
+
#@end
|
|
53
|
+
|
|
54
|
+
#@since 2.0.0
|
|
55
|
+
--- suppressed
|
|
56
|
+
{: since=""}
|
|
57
|
+
|
|
58
|
+
説明
|
|
59
|
+
#@end
|
|
60
|
+
|
|
61
|
+
#@since 2.0.0
|
|
62
|
+
--- -@
|
|
63
|
+
#@since 3.0
|
|
64
|
+
--- dedup
|
|
65
|
+
#@end
|
|
66
|
+
|
|
67
|
+
説明
|
|
68
|
+
#@end
|
|
69
|
+
|
|
70
|
+
#@until 3.0
|
|
71
|
+
--- legacy
|
|
72
|
+
|
|
73
|
+
説明
|
|
74
|
+
#@end
|
|
75
|
+
|
|
76
|
+
--- undefmeth
|
|
77
|
+
{: undef}
|
|
78
|
+
|
|
79
|
+
説明
|
|
80
|
+
|
|
81
|
+
--- undef_then_real
|
|
82
|
+
#@until 2.0.0
|
|
83
|
+
{: undef}
|
|
84
|
+
#@end
|
|
85
|
+
|
|
86
|
+
説明
|
|
87
|
+
|
|
88
|
+
#@since 2.0.0
|
|
89
|
+
--- real_then_undef
|
|
90
|
+
#@since 3.0
|
|
91
|
+
{: undef}
|
|
92
|
+
#@end
|
|
93
|
+
|
|
94
|
+
説明
|
|
95
|
+
#@end
|
|
96
|
+
|
|
97
|
+
--- marker
|
|
98
|
+
|
|
99
|
+
説明
|
|
100
|
+
|
|
101
|
+
== Singleton Methods
|
|
102
|
+
#@since 2.0.0
|
|
103
|
+
--- marker
|
|
104
|
+
|
|
105
|
+
説明
|
|
106
|
+
#@end
|
|
107
|
+
RD
|
|
108
|
+
|
|
109
|
+
LADDER_VERSIONS = %w[1.8.7 2.0.0 3.0]
|
|
110
|
+
|
|
111
|
+
def setup
|
|
112
|
+
@tmpdir = Dir.mktmpdir
|
|
113
|
+
@paths = {}
|
|
114
|
+
LADDER_VERSIONS.each {|v| build_db(v) }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def teardown
|
|
118
|
+
FileUtils.rm_rf(@tmpdir)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_floor_method_has_no_since_or_until
|
|
122
|
+
run_calculator('2.0.0')
|
|
123
|
+
run_calculator('3.0')
|
|
124
|
+
assert_nil find_entry('2.0.0', 'i', 'old_timer').since_of('old_timer')
|
|
125
|
+
assert_nil find_entry('2.0.0', 'i', 'old_timer').until_of('old_timer')
|
|
126
|
+
assert_nil find_entry('3.0', 'i', 'old_timer').since_of('old_timer')
|
|
127
|
+
assert_nil find_entry('3.0', 'i', 'old_timer').until_of('old_timer')
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_since_gated_method_gets_since_in_every_later_target
|
|
131
|
+
run_calculator('2.0.0')
|
|
132
|
+
run_calculator('3.0')
|
|
133
|
+
assert_equal '2.0.0', find_entry('2.0.0', 'i', 'newmeth').since_of('newmeth')
|
|
134
|
+
assert_equal '2.0.0', find_entry('3.0', 'i', 'newmeth').since_of('newmeth')
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def test_alias_group_since_is_split_by_name
|
|
138
|
+
run_calculator('2.0.0')
|
|
139
|
+
run_calculator('3.0')
|
|
140
|
+
|
|
141
|
+
at_2_0_0 = find_entry('2.0.0', 'i', '-@')
|
|
142
|
+
assert_equal ['-@'], at_2_0_0.names
|
|
143
|
+
assert_equal '2.0.0', at_2_0_0.since_of('-@')
|
|
144
|
+
|
|
145
|
+
at_3_0 = find_entry('3.0', 'i', '-@')
|
|
146
|
+
assert_equal ['-@', 'dedup'], at_3_0.names.sort
|
|
147
|
+
assert_equal '2.0.0', at_3_0.since_of('-@')
|
|
148
|
+
assert_equal '3.0', at_3_0.since_of('dedup')
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def test_until_gated_method
|
|
152
|
+
run_calculator('2.0.0')
|
|
153
|
+
assert_equal '3.0', find_entry('2.0.0', 'i', 'legacy').until_of('legacy')
|
|
154
|
+
assert_nil find_entry('3.0', 'i', 'legacy')
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_singleton_and_instance_method_are_distinct_keys
|
|
158
|
+
run_calculator('2.0.0')
|
|
159
|
+
assert_nil find_entry('2.0.0', 'i', 'marker').since_of('marker')
|
|
160
|
+
assert_equal '2.0.0', find_entry('2.0.0', 's', 'marker').since_of('marker')
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def test_undefined_entries_are_ignored_in_scan
|
|
164
|
+
run_calculator('3.0')
|
|
165
|
+
# 全版 {: undef} の undefmeth は presence ゼロ → 何も書かれない
|
|
166
|
+
e = find_entry('3.0', 'i', 'undefmeth')
|
|
167
|
+
assert_equal :undefined, e.kind
|
|
168
|
+
assert_nil e.since_of('undefmeth')
|
|
169
|
+
assert_nil e.until_of('undefmeth')
|
|
170
|
+
# 1.8.7 では {: undef}(存在しない印)なので presence に数えず、実メソッド化
|
|
171
|
+
# した 2.0.0 が since になる(scan がフィルタしなければ floor 扱いで nil)
|
|
172
|
+
assert_equal '2.0.0',
|
|
173
|
+
find_entry('3.0', 'i', 'undef_then_real').since_of('undef_then_real')
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def test_undefined_entries_are_ignored_in_apply
|
|
177
|
+
run_calculator('2.0.0')
|
|
178
|
+
run_calculator('3.0')
|
|
179
|
+
# 3.0 で undef 化 → presence は 2.0.0 のみ。2.0.0 の対象では削除扱いで
|
|
180
|
+
# until が付く
|
|
181
|
+
at_2_0_0 = find_entry('2.0.0', 'i', 'real_then_undef')
|
|
182
|
+
assert_equal '2.0.0', at_2_0_0.since_of('real_then_undef')
|
|
183
|
+
assert_equal '3.0', at_2_0_0.until_of('real_then_undef')
|
|
184
|
+
# 3.0 の :undefined エントリ自体には(算出値があっても)書き込まない
|
|
185
|
+
at_3_0 = find_entry('3.0', 'i', 'real_then_undef')
|
|
186
|
+
assert_equal :undefined, at_3_0.kind
|
|
187
|
+
assert_nil at_3_0.since_of('real_then_undef')
|
|
188
|
+
assert_nil at_3_0.until_of('real_then_undef')
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def test_duplicate_version_in_ladder_raises
|
|
192
|
+
dbs = ladder_dbs + [fresh_db('2.0.0')]
|
|
193
|
+
assert_raise(BitClust::UserError) { BitClust::MethodSinceCalculator.new(dbs) }
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def test_apply_is_idempotent
|
|
197
|
+
calc = BitClust::MethodSinceCalculator.new(ladder_dbs)
|
|
198
|
+
calc.scan
|
|
199
|
+
first_stats = calc.apply(fresh_db('2.0.0'))
|
|
200
|
+
second_stats = calc.apply(fresh_db('2.0.0'))
|
|
201
|
+
|
|
202
|
+
assert_operator first_stats[:since_filled], :>, 0
|
|
203
|
+
assert_equal 0, second_stats[:since_filled]
|
|
204
|
+
assert_equal 0, second_stats[:until_filled]
|
|
205
|
+
assert_equal 0, second_stats[:entries_updated]
|
|
206
|
+
assert_equal first_stats[:floor_skipped], second_stats[:floor_skipped]
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def test_author_value_takes_precedence_over_computed_value
|
|
210
|
+
pre = fresh_db('3.0')
|
|
211
|
+
entry = pre.get_class('MSCTest').entries.find {|m| m.typechar == 'i' && m.name?('newmeth') } or raise
|
|
212
|
+
entry.fill_since('newmeth', '1.9.9')
|
|
213
|
+
entry.save
|
|
214
|
+
|
|
215
|
+
calc = BitClust::MethodSinceCalculator.new(ladder_dbs)
|
|
216
|
+
calc.scan
|
|
217
|
+
calc.apply(fresh_db('3.0'))
|
|
218
|
+
|
|
219
|
+
assert_equal '1.9.9', find_entry('3.0', 'i', 'newmeth').since_of('newmeth')
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def test_author_since_attribute_parsed_from_source_survives_apply
|
|
223
|
+
# overridden は #@since 3.0 でゲートされているのでラダー上は 3.0 と算出
|
|
224
|
+
# されるが、RD ソースの {: since="2.5"} がパース時点(update_by_stdlibtree)
|
|
225
|
+
# で既に記録されているため、apply(fill_since は未設定時のみ書く)では
|
|
226
|
+
# 上書きされずそのまま残る
|
|
227
|
+
run_calculator('2.0.0')
|
|
228
|
+
run_calculator('3.0')
|
|
229
|
+
|
|
230
|
+
assert_nil find_entry('2.0.0', 'i', 'overridden')
|
|
231
|
+
assert_equal '2.5', find_entry('3.0', 'i', 'overridden').since_of('overridden')
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def test_explicit_empty_since_suppresses_computed_value
|
|
235
|
+
# suppressed は #@since 2.0.0 ゲートによりラダー上は 2.0.0 と算出されるが、
|
|
236
|
+
# {: since=""}(明示的に不明=バッジ非表示)がパース時に記録されているため
|
|
237
|
+
# apply は上書きしない(bitclust#132: ドキュメント追加がメソッド追加より
|
|
238
|
+
# 遅れて算出が誤る場合の抑止)
|
|
239
|
+
run_calculator('3.0')
|
|
240
|
+
assert_equal '', find_entry('3.0', 'i', 'suppressed').since_of('suppressed')
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def test_apply_rejects_target_whose_version_is_not_in_ladder
|
|
244
|
+
build_db('4.0')
|
|
245
|
+
calc = BitClust::MethodSinceCalculator.new(ladder_dbs)
|
|
246
|
+
calc.scan
|
|
247
|
+
assert_raise(BitClust::UserError) { calc.apply(fresh_db('4.0')) }
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
private
|
|
251
|
+
|
|
252
|
+
def build_db(version)
|
|
253
|
+
root = "#{@tmpdir}/tree-#{version}/refm/api/src"
|
|
254
|
+
FileUtils.mkdir_p("#{root}/_builtin")
|
|
255
|
+
File.write("#{root}/LIBRARIES", "_builtin\n")
|
|
256
|
+
File.write("#{root}/_builtin.rd", RD)
|
|
257
|
+
prefix = "#{@tmpdir}/db-#{version}"
|
|
258
|
+
db = BitClust::MethodDatabase.new(prefix)
|
|
259
|
+
db.init
|
|
260
|
+
db.transaction do
|
|
261
|
+
db.propset('version', version)
|
|
262
|
+
db.propset('encoding', 'utf-8')
|
|
263
|
+
end
|
|
264
|
+
db.transaction do
|
|
265
|
+
db.update_by_stdlibtree(root)
|
|
266
|
+
end
|
|
267
|
+
@paths[version] = prefix
|
|
268
|
+
prefix
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def fresh_db(version)
|
|
272
|
+
BitClust::MethodDatabase.new(@paths[version] || raise("no such db: #{version}"))
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def ladder_dbs
|
|
276
|
+
LADDER_VERSIONS.map {|v| fresh_db(v) }
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def run_calculator(target_version)
|
|
280
|
+
calc = BitClust::MethodSinceCalculator.new(ladder_dbs)
|
|
281
|
+
calc.scan
|
|
282
|
+
calc.apply(fresh_db(target_version))
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def find_entry(version, typechar, name)
|
|
286
|
+
fresh_db(version).get_class('MSCTest').entries.find {|m|
|
|
287
|
+
m.typechar == typechar && m.name?(name)
|
|
288
|
+
}
|
|
289
|
+
end
|
|
290
|
+
end
|
data/test/test_methoddatabase.rb
CHANGED
|
@@ -57,6 +57,22 @@ class TestMethodDatabase < Test::Unit::TestCase
|
|
|
57
57
|
@db.get_class("B").dynamically_included.map{|m| m.name})
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# source_location must be stored without a line number so that regenerating
|
|
61
|
+
# the database does not churn the persisted entries (and the generated HTML).
|
|
62
|
+
def test_source_location_serialized_without_line_number
|
|
63
|
+
entry = @db.search_methods(BitClust::MethodNamePattern.new(nil, nil, 'at_exit')).records.first.entry
|
|
64
|
+
entry.source_location = BitClust::Location.new('refm/api/src/_builtin/Kernel', 42)
|
|
65
|
+
assert_equal('refm/api/src/_builtin/Kernel', entry._get_properties['source_location'])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_source_location_roundtrip_drops_line_number
|
|
69
|
+
entry = @db.search_methods(BitClust::MethodNamePattern.new(nil, nil, 'at_exit')).records.first.entry
|
|
70
|
+
entry.source_location = BitClust::Location.new('refm/api/src/_builtin/Kernel', 42)
|
|
71
|
+
entry._set_properties(entry._get_properties)
|
|
72
|
+
assert_equal('refm/api/src/_builtin/Kernel', entry.source_location.file)
|
|
73
|
+
assert_nil(entry.source_location.line)
|
|
74
|
+
end
|
|
75
|
+
|
|
60
76
|
private
|
|
61
77
|
def setup_files
|
|
62
78
|
FileUtils.mkdir_p("#{@root}/_builtin")
|