bitclust-core 1.6.0 → 1.7.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -0
  3. data/data/bitclust/catalog/ja_JP.UTF-8 +4 -2
  4. data/data/bitclust/template/function-index +1 -0
  5. data/data/bitclust/template/layout +1 -0
  6. data/data/bitclust/template.offline/function-index +1 -0
  7. data/data/bitclust/template.offline/layout +3 -0
  8. data/lib/bitclust/classentry.rb +1 -1
  9. data/lib/bitclust/docentry.rb +1 -1
  10. data/lib/bitclust/functionentry.rb +1 -1
  11. data/lib/bitclust/irb.rb +68 -0
  12. data/lib/bitclust/markdown_exporter.rb +311 -0
  13. data/lib/bitclust/mdcompiler.rb +15 -1
  14. data/lib/bitclust/mdparser.rb +42 -1
  15. data/lib/bitclust/methoddatabase.rb +4 -0
  16. data/lib/bitclust/methodentry.rb +24 -0
  17. data/lib/bitclust/methodsignature.rb +1 -1
  18. data/lib/bitclust/preprocessor.rb +4 -1
  19. data/lib/bitclust/rbs_overload_matcher.rb +179 -0
  20. data/lib/bitclust/rbs_sig_importer.rb +276 -0
  21. data/lib/bitclust/rbs_signatures.rb +125 -0
  22. data/lib/bitclust/rdcompiler.rb +12 -1
  23. data/lib/bitclust/runner.rb +2 -0
  24. data/lib/bitclust/screen.rb +4 -0
  25. data/lib/bitclust/search_index_generator.rb +28 -10
  26. data/lib/bitclust/searcher.rb +12 -2
  27. data/lib/bitclust/subcommands/rbssig_command.rb +99 -0
  28. data/lib/bitclust/subcommands/setup_command.rb +4 -1
  29. data/lib/bitclust/subcommands/statichtml_command.rb +59 -0
  30. data/lib/bitclust/version.rb +1 -1
  31. data/lib/bitclust-irb.rb +2 -0
  32. data/test/test_irb_plugin.rb +118 -0
  33. data/test/test_link_checker.rb +1 -1
  34. data/test/test_markdown_exporter.rb +260 -0
  35. data/test/test_mdcompiler.rb +47 -5
  36. data/test/test_mdparser.rb +219 -4
  37. data/test/test_methodentry.rb +111 -0
  38. data/test/test_methodsignature.rb +3 -1
  39. data/test/test_preprocessor.rb +26 -0
  40. data/test/test_rbs_overload_matcher.rb +170 -0
  41. data/test/test_rbs_sig_importer.rb +237 -0
  42. data/test/test_rbssig_command.rb +186 -0
  43. data/test/test_rdcompiler.rb +99 -1
  44. data/test/test_search_index_generator.rb +81 -0
  45. data/test/test_setup_command.rb +21 -0
  46. data/test/test_statichtml_command.rb +137 -0
  47. data/theme/default/js/run.js +14 -0
  48. data/theme/default/js/search_init.js +3 -1
  49. data/theme/default/js/search_page.js +7 -1
  50. data/theme/default/js/version_switcher.js +147 -0
  51. data/theme/default/search.css +21 -0
  52. data/theme/default/style.css +83 -7
  53. data/theme/lillia/style.css +26 -0
  54. metadata +35 -1
@@ -114,6 +114,9 @@ module BitClust
114
114
  key = e.values_at(:name, :full_name, :type, :path)
115
115
  entry = (merged[key] ||= e.merge(versions: []))
116
116
  entry[:versions] << version
117
+ # 説明文は「最新版か、収録されている最終版」のものを採用する。
118
+ # 昇順走査なので後勝ちで上書きすればよい
119
+ entry[:snippet] = e[:snippet] if e[:snippet]
117
120
  end
118
121
  end
119
122
  merged.values
@@ -126,14 +129,29 @@ module BitClust
126
129
 
127
130
  private
128
131
 
132
+ # 検索結果に添える説明文。meta description と同じ entry.description
133
+ # (最初の説明段落のプレーンテキスト)を使い、空なら nil(キー自体を
134
+ # 持たせない)。プレーンテキストのまま格納し、HTML エスケープは
135
+ # 表示側(search_init.js / search_page.js)で行う
136
+ def entry_snippet(entry)
137
+ desc = entry.description
138
+ desc unless desc.nil? || desc.empty?
139
+ end
140
+
141
+ def with_snippet(hash, entry)
142
+ snippet = entry_snippet(entry)
143
+ hash[:snippet] = snippet if snippet
144
+ hash
145
+ end
146
+
129
147
  def class_entries(db)
130
148
  db.classes.sort.reject(&:dummy?).map do |c|
131
- {
149
+ with_snippet({
132
150
  name: c.name,
133
151
  full_name: c.name,
134
152
  type: c.type.to_s,
135
153
  path: "class/#{encode(c.name)}#{@suffix}",
136
- }
154
+ }, c)
137
155
  end
138
156
  end
139
157
 
@@ -162,11 +180,11 @@ module BitClust
162
180
  # sigil is the only thing distinguishing it, so keep it in +name+
163
181
  # too (not just +full_name+) or a "$;"-style query can't match it.
164
182
  name = full_name = tmark + mname
165
- result << { name: name, full_name: full_name, type: type, path: path }
183
+ result << with_snippet({ name: name, full_name: full_name, type: type, path: path }, entry)
166
184
  else
167
185
  name = mname
168
186
  full_name = cname + tmark + mname
169
- item = { name: name, full_name: full_name, type: type, path: path } #: entry
187
+ item = with_snippet({ name: name, full_name: full_name, type: type, path: path }, entry) #: entry
170
188
  if tmark.include?('.')
171
189
  # bitclust#279: singleton methods (".") and module functions
172
190
  # (".#"/"?.") keep a literal "." in full_name for display, but
@@ -185,12 +203,12 @@ module BitClust
185
203
 
186
204
  def library_entries(db)
187
205
  db.libraries.sort.map do |lib|
188
- {
206
+ with_snippet({
189
207
  name: lib.name,
190
208
  full_name: lib.name,
191
209
  type: 'library',
192
210
  path: "library/#{encode(lib.name)}#{@suffix}",
193
- }
211
+ }, lib)
194
212
  end
195
213
  end
196
214
 
@@ -201,12 +219,12 @@ module BitClust
201
219
  # Prose pages are identified by a Japanese title, so index the title
202
220
  # (for human queries) together with the slug (for identifier queries).
203
221
  label = (title && !title.empty? && title != slug) ? "#{title} (#{slug})" : slug
204
- {
222
+ with_snippet({
205
223
  name: label,
206
224
  full_name: label,
207
225
  type: 'document',
208
226
  path: "doc/#{encode(slug)}#{@suffix}",
209
- }
227
+ }, doc)
210
228
  end
211
229
  end
212
230
 
@@ -272,12 +290,12 @@ module BitClust
272
290
 
273
291
  def function_entries(fdb)
274
292
  fdb.functions.sort.map do |func|
275
- {
293
+ with_snippet({
276
294
  name: func.name,
277
295
  full_name: func.name,
278
296
  type: 'function',
279
297
  path: "function/#{func.name}#{@suffix}",
280
- }
298
+ }, func)
281
299
  end
282
300
  end
283
301
 
@@ -121,6 +121,14 @@ module BitClust
121
121
  @parser.help
122
122
  end
123
123
 
124
+ # irb プラグインなど組み込み利用向けの入口。argv のパターンを db から
125
+ # 検索し、結果を view(TerminalView)へ出力する。db が nil なら
126
+ # 既定の場所(~/.bitclust/config など)から探す
127
+ def run_query(db, argv, view)
128
+ @view = view
129
+ search_pattern db, argv
130
+ end
131
+
124
132
  private
125
133
 
126
134
  def server_mode_check(argv)
@@ -374,12 +382,14 @@ module BitClust
374
382
 
375
383
  class TerminalView
376
384
 
377
- def initialize(compiler, opts)
385
+ # io を省略すると出力先は呼び出し時点の $stdout(従来挙動)
386
+ def initialize(compiler, opts, io: nil)
378
387
  @compiler = compiler
379
388
  @describe_all = opts[:describe_all]
380
389
  @line = opts[:line]
381
390
  @encoding = opts[:encoding]
382
391
  @database = nil
392
+ @io = io
383
393
  end
384
394
 
385
395
  attr_accessor :database
@@ -546,7 +556,7 @@ module BitClust
546
556
  end
547
557
 
548
558
  def puts(*args)
549
- super(*args.collect {|arg| convert(arg)})
559
+ (@io || $stdout).puts(*args.collect {|arg| convert(arg)})
550
560
  end
551
561
 
552
562
  def convert(string)
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # bitclust/subcommands/rbssig_command.rb
4
+ #
5
+ # RBS 型シグネチャを DB のメソッドエントリに書き込む(rbs_sig property):
6
+ #
7
+ # bitclust rbssig --sig-root=RBS_CHECKOUT <dbpath>
8
+ # bitclust rbssig --sig-dir=DIR [--sig-dir=DIR ...] <dbpath>
9
+ #
10
+ # DB 構築(update)後・statichtml 前に実行する(methodsince と同じ位置)。
11
+ # --sig-root には対象 Ruby バージョンに同梱される rbs のチェックアウト
12
+ # (core/ と stdlib/ を含む)を渡す。表示は 4.0 以降のドキュメント専用
13
+ # なので、DB の version が 4.0 未満ならエラーにする。
14
+
15
+ require 'bitclust'
16
+ require 'bitclust/subcommand'
17
+ require 'bitclust/rbs_sig_importer'
18
+ require 'tmpdir'
19
+ require 'fileutils'
20
+
21
+ module BitClust
22
+ module Subcommands
23
+ class RbssigCommand < Subcommand
24
+ MINIMUM_VERSION = Gem::Version.new('4.0')
25
+
26
+ def initialize
27
+ super
28
+ @sig_root = nil
29
+ @sig_dirs = []
30
+ @dry_run = false
31
+ @parser.banner = "Usage: #{File.basename($0, '.*')} rbssig [options] <dbpath>"
32
+ @parser.on('--sig-root=PATH', 'ruby/rbs checkout containing core/ and stdlib/.') {|path|
33
+ @sig_root = path
34
+ }
35
+ @parser.on('--sig-dir=PATH', 'Directory of extra .rbs files (repeatable).') {|path|
36
+ @sig_dirs.push path
37
+ }
38
+ @parser.on('--dry-run', 'Compute and print stats without saving.') {
39
+ @dry_run = true
40
+ }
41
+ end
42
+
43
+ # DB パスは位置引数で受けるのでグローバル --database は不要
44
+ def needs_database?
45
+ false
46
+ end
47
+
48
+ def exec(argv, options)
49
+ error('no --sig-root or --sig-dir given') if @sig_root.nil? && @sig_dirs.empty?
50
+ error("wrong number of arguments (#{argv.size} for 1)") unless argv.size == 1
51
+ path = argv.first
52
+ version = check_version(path)
53
+
54
+ sig_root = @sig_root
55
+ importer = RbsSigImporter.new(
56
+ core_root: sig_root && File.join(sig_root, 'core'),
57
+ repository_root: sig_root && File.join(sig_root, 'stdlib'),
58
+ sig_dirs: @sig_dirs)
59
+ stats =
60
+ if @dry_run
61
+ apply_dry_run(importer, path)
62
+ else
63
+ importer.apply(MethodDatabase.new(path))
64
+ end
65
+ puts "#{File.basename(path)} (version #{version}): " \
66
+ "entries_updated=#{stats[:entries_updated]} sigs_matched=#{stats[:sigs_matched]} " \
67
+ "methods_missed=#{stats[:methods_missed]}"
68
+ end
69
+
70
+ private
71
+
72
+ # RBS シグネチャ表示は 4.0 以降のドキュメント専用。比較は
73
+ # display_typemark(nameutils.rb)と同じく Gem::Version で行う
74
+ # (文字列比較だと "10.0" が "4.0" より小さく見える)
75
+ def check_version(path)
76
+ version = MethodDatabase.new(path).propget('version') or
77
+ error("#{path}: no version property (not a bitclust database?)")
78
+ begin
79
+ if Gem::Version.new(version) < MINIMUM_VERSION
80
+ error("#{path}: version #{version} is before 4.0; RBS signatures are only for 4.0+ databases")
81
+ end
82
+ rescue ArgumentError
83
+ error("#{path}: malformed version property: #{version.inspect}")
84
+ end
85
+ version
86
+ end
87
+
88
+ # --dry-run: 実 DB には書き込まず、複製に apply した統計だけを見せる
89
+ # (methodsince の apply_dry_run と同じ手口)
90
+ def apply_dry_run(importer, path)
91
+ Dir.mktmpdir do |tmp|
92
+ copy = File.join(tmp, 'db')
93
+ FileUtils.cp_r(path, copy)
94
+ importer.apply(MethodDatabase.new(copy))
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -20,7 +20,10 @@ module BitClust
20
20
  @prepare = nil
21
21
  @cleanup = nil
22
22
  @purge = nil
23
- @versions = ["3.3.0", "3.4.0", "4.0.0"]
23
+ # teeny は付けない。#%if (version == "V") や #%version V の等値ゲートは
24
+ # 文字列一致なので、teeny 付きの版名で DB を作ると doctree CI・
25
+ # 生成済みドキュメントとゲートの判定がずれる
26
+ @versions = ["3.3", "3.4", "4.0"]
24
27
  @update = true
25
28
  @parser.banner = "Usage: #{File.basename($0, '.*')} setup [options]"
26
29
  @parser.on('--prepare', 'Prepare config file and checkout repository. Do not create database.') {
@@ -13,6 +13,7 @@ require 'bitclust/subcommand'
13
13
  require 'bitclust/progress_bar'
14
14
  require 'bitclust/silent_progress_bar'
15
15
  require 'bitclust/search_index_generator'
16
+ require 'bitclust/markdown_exporter'
16
17
 
17
18
  module BitClust
18
19
  module Subcommands
@@ -125,6 +126,7 @@ module BitClust
125
126
  @run_ruby_wasm = nil
126
127
  @sitemap_baseurl = nil
127
128
  @sitemap_paths = []
129
+ @markdown_output = false
128
130
  @parser.banner = "Usage: #{File.basename($0, '.*')} statichtml [options]"
129
131
  @parser.on('-o', '--outputdir=PATH', 'Output directory') do |path|
130
132
  begin
@@ -170,6 +172,9 @@ module BitClust
170
172
  @parser.on('--sitemap-baseurl=URL', 'Generate sitemap.xml under the output directory, with <loc> built from this base URL (e.g. https://docs.ruby-lang.org/ja/3.4/). Omit to skip sitemap.xml generation (default)') do |url|
171
173
  @sitemap_baseurl = url
172
174
  end
175
+ @parser.on('--markdown-output', 'Also write each page as Markdown (.md next to the .html), assembled from the preprocessed Markdown sources. Ignored for databases not created from a Markdown tree') do
176
+ @markdown_output = true
177
+ end
173
178
  @parser.on('--no-stop-on-syntax-error', 'Do not stop on syntax error') do |boolean|
174
179
  @stop_on_syntax_error = boolean
175
180
  end
@@ -185,8 +190,10 @@ module BitClust
185
190
  db = MethodDatabase.new(prefix.to_s)
186
191
  fdb = FunctionDatabase.new(prefix.to_s)
187
192
  manager = ScreenManager.new(@manager_config)
193
+ @markdown_exporter = MarkdownExporter.new(@urlmapper, @suffix) if @markdown_output
188
194
 
189
195
  db.transaction do
196
+ warn_markdown_output_skipped(db, "the method database")
190
197
  methods = {} #: Hash[String, Array[MethodEntry]]
191
198
  db.methods.each_with_index do |entry, i|
192
199
  next if entry.undefined?
@@ -203,6 +210,7 @@ module BitClust
203
210
  end
204
211
 
205
212
  fdb.transaction do
213
+ warn_markdown_output_skipped(fdb, "the function database")
206
214
  create_html_entries("capi", fdb.functions, manager, fdb)
207
215
  end
208
216
 
@@ -234,6 +242,7 @@ module BitClust
234
242
  FileUtils.cp(@manager_config[:themedir] + "script.js",
235
243
  @outputdir.to_s, :verbose => @verbose, :preserve => true)
236
244
  copy_run_ruby_wasm_script if @run_ruby_wasm
245
+ copy_version_switcher_script
237
246
  FileUtils.cp(@manager_config[:themedir] + @manager_config[:favicon_url],
238
247
  @outputdir.to_s, :verbose => @verbose, :preserve => true)
239
248
  Dir.mktmpdir do |tmpdir|
@@ -412,6 +421,19 @@ HERE
412
421
  end
413
422
  end
414
423
 
424
+ # Copy the version-switcher script. A themedir without it is
425
+ # tolerated: warn and skip instead of aborting the whole build.
426
+ def copy_version_switcher_script
427
+ src = @manager_config[:themedir] + "js" + "version_switcher.js"
428
+ unless src.file?
429
+ $stderr.puts "warning: #{src} not found; version switcher script not copied"
430
+ return
431
+ end
432
+ jsdir = @outputdir + "js"
433
+ FileUtils.mkdir_p(jsdir) unless jsdir.directory?
434
+ FileUtils.cp(src.to_s, jsdir.to_s, :verbose => @verbose, :preserve => true)
435
+ end
436
+
415
437
  def create_html_file(entry, manager, outputdir, db)
416
438
  e = entry.is_a?(Array) ? entry.sort.first : entry
417
439
  case e.type_id
@@ -419,6 +441,7 @@ HERE
419
441
  @urlmapper.bitclust_html_base = '..'
420
442
  path = outputdir + e.type_id.to_s + html_filename(encodename_package(e.name), @suffix)
421
443
  create_html_file_p(entry, manager, path, db)
444
+ create_markdown_file_p(e, path, db)
422
445
  when :function
423
446
  create_html_function_file(entry, manager, outputdir, db)
424
447
  else
@@ -435,6 +458,11 @@ HERE
435
458
  path = outputdir + e.type_id.to_s + encodename_package(e.klass.name) +
436
459
  e.typechar + html_filename(encodename_package(name), @suffix)
437
460
  create_html_file_p(entries, manager, path, db)
461
+ if markdown_export?(db)
462
+ create_file(markdown_path(path),
463
+ @markdown_exporter.method_page(method_name, entries.sort),
464
+ :verbose => @verbose)
465
+ end
438
466
  end
439
467
 
440
468
  def create_html_function_file(entry, manager, outputdir, db)
@@ -442,6 +470,7 @@ HERE
442
470
  @urlmapper.bitclust_html_base = '..'
443
471
  path = outputdir + entry.type_id.to_s + html_filename(entry.name, @suffix)
444
472
  create_html_file_p(entry, manager, path, db)
473
+ create_markdown_file_p(entry, path, db)
445
474
  end
446
475
 
447
476
  def create_html_file_p(entry, manager, path, db)
@@ -453,6 +482,36 @@ HERE
453
482
  record_sitemap_path(path)
454
483
  end
455
484
 
485
+ # --markdown-output は Markdown ツリー由来の DB でのみ有効。
486
+ # ソースが md でない(凍結版 RD など)DB では何も出力しない
487
+ def markdown_export?(db)
488
+ @markdown_output && db.properties['source_format'] == 'markdown'
489
+ end
490
+
491
+ def warn_markdown_output_skipped(db, label)
492
+ return if !@markdown_output || db.properties['source_format'] == 'markdown'
493
+ $stderr.puts "warning: --markdown-output is ignored for #{label}: it was not created from a Markdown tree"
494
+ end
495
+
496
+ def create_markdown_file_p(entry, html_path, db)
497
+ return unless markdown_export?(db)
498
+ content =
499
+ case entry.type_id
500
+ when :library then @markdown_exporter.library_page(_ = entry)
501
+ when :class then @markdown_exporter.class_page(_ = entry)
502
+ when :doc then @markdown_exporter.doc_page(_ = entry)
503
+ when :function then @markdown_exporter.function_page(_ = entry)
504
+ else return
505
+ end
506
+ create_file(markdown_path(html_path), content, :verbose => @verbose)
507
+ end
508
+
509
+ def markdown_path(html_path)
510
+ s = html_path.to_s
511
+ s = s.end_with?(@suffix) ? s[0, s.length - @suffix.length].to_s : s
512
+ Pathname.new("#{s}.md")
513
+ end
514
+
456
515
  def create_file(path, str, options = {})
457
516
  verbose = options[:verbose]
458
517
  $stderr.print("creating #{path} ...") if verbose
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module BitClust
3
- VERSION = "1.6.0"
3
+ VERSION = "1.7.0"
4
4
  end
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require 'bitclust/irb'
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+ require 'test/unit'
3
+ require 'tmpdir'
4
+ require 'fileutils'
5
+ require 'stringio'
6
+ require 'bitclust'
7
+ require 'bitclust/methoddatabase'
8
+ require 'bitclust/searcher'
9
+
10
+ # bitclust-irb gem の irb コマンド(refe)。
11
+ #
12
+ # テストリスト:
13
+ # [x] TerminalView が io: に出力する(既定は従来どおり $stdout)
14
+ # [x] Irb.lookup がメソッドを検索して整形結果を io へ書く
15
+ # [x] Irb.lookup がクラスも引ける
16
+ # [x] 空のパターンは使い方を表示して例外にしない
17
+ # [x] 見つからないパターンはメッセージを io へ書いて例外にしない
18
+ # [x] require で IRB::Command::Base のサブクラスとして登録される
19
+ class TestBitClustIrbPlugin < Test::Unit::TestCase
20
+ FOO_MD = <<~'MD'
21
+ ---
22
+ library: foo
23
+ ---
24
+ # class Foo < Object
25
+
26
+ クラスの説明。
27
+
28
+ ## Instance Methods
29
+
30
+ ### def bar -> nil
31
+
32
+ bar の説明。
33
+ MD
34
+
35
+ def build_markdown_db(dir)
36
+ api = File.join(dir, 'manual', 'api')
37
+ FileUtils.mkdir_p(File.join(api, 'foo'))
38
+ File.write(File.join(api, 'foo.md'), "---\ntype: library\n---\nfoo ライブラリ。\n")
39
+ File.write(File.join(api, 'foo', 'Foo.md'), FOO_MD)
40
+ prefix = File.join(dir, 'db')
41
+ db = BitClust::MethodDatabase.new(prefix)
42
+ db.init
43
+ db.transaction do
44
+ db.propset('version', '3.4')
45
+ db.propset('encoding', 'utf-8')
46
+ end
47
+ db.transaction do
48
+ db.update_by_markdowntree(api)
49
+ end
50
+ BitClust::MethodDatabase.new(prefix)
51
+ end
52
+
53
+ def with_db(&block)
54
+ Dir.mktmpdir do |dir|
55
+ yield build_markdown_db(dir)
56
+ end
57
+ end
58
+
59
+ def test_terminal_view_writes_to_given_io
60
+ out = StringIO.new
61
+ view = BitClust::TerminalView.new(BitClust::Plain.new, {}, io: out)
62
+ view.send(:puts, 'hello')
63
+ assert_equal("hello\n", out.string)
64
+ end
65
+
66
+ def test_lookup_method
67
+ require 'bitclust/irb'
68
+ with_db do |db|
69
+ out = StringIO.new
70
+ BitClust::Irb.lookup('Foo#bar', db: db, io: out)
71
+ assert_match(/Foo#bar/, out.string)
72
+ assert_match(/bar の説明。/, out.string)
73
+ end
74
+ end
75
+
76
+ def test_lookup_class
77
+ require 'bitclust/irb'
78
+ with_db do |db|
79
+ out = StringIO.new
80
+ BitClust::Irb.lookup('Foo', db: db, io: out)
81
+ assert_match(/class Foo < Object/, out.string)
82
+ assert_match(/クラスの説明。/, out.string)
83
+ end
84
+ end
85
+
86
+ def test_lookup_empty_pattern_shows_usage
87
+ require 'bitclust/irb'
88
+ with_db do |db|
89
+ out = StringIO.new
90
+ assert_nothing_raised do
91
+ BitClust::Irb.lookup('', db: db, io: out)
92
+ end
93
+ assert_match(/refe/, out.string)
94
+ end
95
+ end
96
+
97
+ def test_lookup_not_found_reports_instead_of_raising
98
+ require 'bitclust/irb'
99
+ with_db do |db|
100
+ out = StringIO.new
101
+ assert_nothing_raised do
102
+ BitClust::Irb.lookup('NoSuchClass#no_such_method', db: db, io: out)
103
+ end
104
+ assert_match(/no such method/, out.string)
105
+ end
106
+ end
107
+
108
+ def test_command_is_registered_for_irb
109
+ begin
110
+ require 'irb/command'
111
+ rescue LoadError
112
+ omit 'irb >= 1.13 is not available'
113
+ end
114
+ require 'bitclust/irb'
115
+ assert(BitClust::Irb::RefeCommand < ::IRB::Command::Base)
116
+ assert_match(/るりま|リファレンス/, BitClust::Irb::RefeCommand.description)
117
+ end
118
+ end
@@ -38,7 +38,7 @@ class TestLinkChecker < Test::Unit::TestCase
38
38
 
39
39
  ## Class Methods
40
40
 
41
- ### def baz -> nil
41
+ ### def Foo.baz -> nil
42
42
 
43
43
  baz です。
44
44