bitclust-core 1.2.6 → 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.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/README.md +65 -0
  4. data/Rakefile +32 -0
  5. data/data/bitclust/catalog/ja_JP.UTF-8 +19 -1
  6. data/data/bitclust/searchpage/index.html +90 -0
  7. data/data/bitclust/template/class +69 -8
  8. data/data/bitclust/template/function +2 -2
  9. data/data/bitclust/template/layout +11 -3
  10. data/data/bitclust/template/method +2 -2
  11. data/data/bitclust/template/search +1 -1
  12. data/data/bitclust/template.epub/class +22 -1
  13. data/data/bitclust/template.epub/function +2 -2
  14. data/data/bitclust/template.epub/layout +1 -3
  15. data/data/bitclust/template.epub/method +2 -2
  16. data/data/bitclust/template.lillia/class +26 -5
  17. data/data/bitclust/template.lillia/layout +1 -3
  18. data/data/bitclust/template.lillia/method +2 -2
  19. data/data/bitclust/template.offline/class +49 -5
  20. data/data/bitclust/template.offline/function +2 -2
  21. data/data/bitclust/template.offline/layout +27 -3
  22. data/data/bitclust/template.offline/method +2 -2
  23. data/lib/bitclust/app.rb +17 -17
  24. data/lib/bitclust/capi_converter.rb +20 -0
  25. data/lib/bitclust/classentry.rb +68 -17
  26. data/lib/bitclust/compat.rb +3 -2
  27. data/lib/bitclust/completion.rb +59 -27
  28. data/lib/bitclust/crossrubyutils.rb +9 -5
  29. data/lib/bitclust/database.rb +29 -8
  30. data/lib/bitclust/doc_converter.rb +63 -0
  31. data/lib/bitclust/docentry.rb +2 -1
  32. data/lib/bitclust/entity_splitter.rb +221 -0
  33. data/lib/bitclust/entry.rb +48 -7
  34. data/lib/bitclust/exception.rb +1 -0
  35. data/lib/bitclust/functiondatabase.rb +14 -1
  36. data/lib/bitclust/functionentry.rb +6 -1
  37. data/lib/bitclust/functionreferenceparser.rb +5 -4
  38. data/lib/bitclust/generators/epub.rb +11 -3
  39. data/lib/bitclust/htmlutils.rb +2 -1
  40. data/lib/bitclust/include_graph.rb +375 -0
  41. data/lib/bitclust/include_pruner.rb +144 -0
  42. data/lib/bitclust/interface.rb +2 -1
  43. data/lib/bitclust/libraryentry.rb +9 -7
  44. data/lib/bitclust/lineinput.rb +8 -5
  45. data/lib/bitclust/link_checker.rb +179 -0
  46. data/lib/bitclust/markdown_bridge.rb +186 -0
  47. data/lib/bitclust/markdown_orchestrator.rb +267 -0
  48. data/lib/bitclust/markdown_to_rrd.rb +824 -0
  49. data/lib/bitclust/markdown_tree.rb +217 -0
  50. data/lib/bitclust/mdcompiler.rb +883 -0
  51. data/lib/bitclust/mdparser.rb +347 -0
  52. data/lib/bitclust/messagecatalog.rb +4 -3
  53. data/lib/bitclust/method_since_calculator.rb +117 -0
  54. data/lib/bitclust/methoddatabase.rb +125 -14
  55. data/lib/bitclust/methodentry.rb +130 -7
  56. data/lib/bitclust/methodid.rb +13 -11
  57. data/lib/bitclust/methodsignature.rb +11 -4
  58. data/lib/bitclust/nameutils.rb +42 -22
  59. data/lib/bitclust/parseutils.rb +1 -0
  60. data/lib/bitclust/preprocessor.rb +70 -32
  61. data/lib/bitclust/progress_bar.rb +1 -0
  62. data/lib/bitclust/rdcompiler.rb +197 -96
  63. data/lib/bitclust/refsdatabase.rb +24 -8
  64. data/lib/bitclust/reloadable_request_handler.rb +72 -0
  65. data/lib/bitclust/requesthandler.rb +22 -16
  66. data/lib/bitclust/ridatabase.rb +11 -4
  67. data/lib/bitclust/rrd_to_markdown.rb +925 -0
  68. data/lib/bitclust/rrdparser.rb +197 -30
  69. data/lib/bitclust/runner.rb +18 -2
  70. data/lib/bitclust/screen.rb +81 -11
  71. data/lib/bitclust/search_index_generator.rb +288 -0
  72. data/lib/bitclust/searcher.rb +72 -22
  73. data/lib/bitclust/server.rb +6 -1
  74. data/lib/bitclust/silent_progress_bar.rb +1 -0
  75. data/lib/bitclust/simplesearcher.rb +25 -12
  76. data/lib/bitclust/subcommand.rb +8 -1
  77. data/lib/bitclust/subcommands/ancestors_command.rb +10 -2
  78. data/lib/bitclust/subcommands/checklink_command.rb +54 -0
  79. data/lib/bitclust/subcommands/chm_command.rb +16 -7
  80. data/lib/bitclust/subcommands/classes_command.rb +6 -0
  81. data/lib/bitclust/subcommands/epub_command.rb +1 -0
  82. data/lib/bitclust/subcommands/extract_command.rb +6 -0
  83. data/lib/bitclust/subcommands/htmlfile_command.rb +22 -7
  84. data/lib/bitclust/subcommands/init_command.rb +5 -1
  85. data/lib/bitclust/subcommands/list_command.rb +13 -4
  86. data/lib/bitclust/subcommands/lookup_command.rb +29 -9
  87. data/lib/bitclust/subcommands/methods_command.rb +11 -2
  88. data/lib/bitclust/subcommands/methodsince_command.rb +80 -0
  89. data/lib/bitclust/subcommands/preproc_command.rb +6 -0
  90. data/lib/bitclust/subcommands/property_command.rb +3 -1
  91. data/lib/bitclust/subcommands/query_command.rb +1 -0
  92. data/lib/bitclust/subcommands/searchpage_command.rb +102 -0
  93. data/lib/bitclust/subcommands/server_command.rb +16 -10
  94. data/lib/bitclust/subcommands/setup_command.rb +25 -10
  95. data/lib/bitclust/subcommands/statichtml_command.rb +132 -6
  96. data/lib/bitclust/subcommands/update_command.rb +111 -2
  97. data/lib/bitclust/syntax_highlighter.rb +52 -5
  98. data/lib/bitclust/textutils.rb +4 -3
  99. data/lib/bitclust/version.rb +2 -1
  100. data/lib/bitclust/version_badges.rb +90 -0
  101. data/lib/bitclust/whole_file_gate.rb +137 -0
  102. data/lib/bitclust.rb +1 -0
  103. data/test/test_app.rb +269 -0
  104. data/test/test_bitclust.rb +2 -0
  105. data/test/test_capi_converter.rb +91 -0
  106. data/test/test_class_screen.rb +413 -0
  107. data/test/test_copy_doc_md.rb +53 -0
  108. data/test/test_doc_converter.rb +78 -0
  109. data/test/test_entity_splitter.rb +231 -0
  110. data/test/test_entry.rb +207 -2
  111. data/test/test_eol_warning.rb +43 -0
  112. data/test/test_functionreferenceparser.rb +11 -0
  113. data/test/test_include_graph.rb +640 -0
  114. data/test/test_include_pruner.rb +133 -0
  115. data/test/test_link_checker.rb +114 -0
  116. data/test/test_lookup_command.rb +135 -0
  117. data/test/test_markdown_bridge.rb +217 -0
  118. data/test/test_markdown_orchestrator.rb +478 -0
  119. data/test/test_markdown_to_rrd.rb +757 -0
  120. data/test/test_markdown_tree.rb +369 -0
  121. data/test/test_mdcompiler.rb +1276 -0
  122. data/test/test_mdparser.rb +538 -0
  123. data/test/test_method_screen.rb +166 -0
  124. data/test/test_method_since_calculator.rb +290 -0
  125. data/test/test_methoddatabase.rb +16 -0
  126. data/test/test_methodentry.rb +328 -0
  127. data/test/test_methodsignature.rb +3 -1
  128. data/test/test_methodsince_command.rb +168 -0
  129. data/test/test_nameutils.rb +22 -0
  130. data/test/test_preprocessor.rb +215 -0
  131. data/test/test_rdcompiler.rb +429 -27
  132. data/test/test_refsdatabase.rb +32 -0
  133. data/test/test_rrd_to_markdown.rb +968 -0
  134. data/test/test_rrdparser.rb +295 -2
  135. data/test/test_run_ruby_wasm.rb +54 -0
  136. data/test/test_run_worker_prelude.rb +83 -0
  137. data/test/test_runner.rb +51 -0
  138. data/test/test_search_index_generator.rb +513 -0
  139. data/test/test_search_screen.rb +48 -0
  140. data/test/test_searcher.rb +153 -0
  141. data/test/test_searchpage_command.rb +167 -0
  142. data/test/test_simplesearcher.rb +28 -0
  143. data/test/test_statichtml_command.rb +204 -0
  144. data/test/test_syntax_highlighter.rb +60 -0
  145. data/test/test_whole_file_gate.rb +175 -0
  146. data/theme/default/js/NOTICE +42 -0
  147. data/theme/default/js/run-worker.js +111 -0
  148. data/theme/default/js/run.js +350 -0
  149. data/theme/default/js/search_controller.js +134 -0
  150. data/theme/default/js/search_init.js +176 -0
  151. data/theme/default/js/search_navigation.js +110 -0
  152. data/theme/default/js/search_page.js +202 -0
  153. data/theme/default/js/search_ranker.js +244 -0
  154. data/theme/default/script.js +91 -18
  155. data/theme/default/search.css +149 -0
  156. data/theme/default/style.css +193 -21
  157. data/theme/default/syntax-highlight.css +8 -0
  158. data/theme/lillia/style.css +45 -1
  159. metadata +178 -21
  160. data/README +0 -32
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  #
2
3
  # bitclust/methodentry.rb
3
4
  #
@@ -43,7 +44,8 @@ module BitClust
43
44
  sort_key() <=> other.sort_key
44
45
  end
45
46
 
46
- KIND_NUM = {:defined => 0, :redefined => 1, :added => 2}
47
+ KIND_NUM = {:defined => 0, :redefined => 1, :added => 2,
48
+ :undefined => 3, :nomethod => 4}
47
49
 
48
50
  def sort_key
49
51
  [label(), KIND_NUM[kind()]]
@@ -72,6 +74,14 @@ module BitClust
72
74
  methodid2typechar(@id)
73
75
  end
74
76
 
77
+ # bitclust#250: 表示専用の typemark。DB のバージョンが 4.0 以降なら
78
+ # module function の "." を "?." にする(それ以外の typemark は不変)。
79
+ # typemark 自体(識別子として使う方)は変えない -- URL・spec 文字列・
80
+ # refsdatabase のアンカーキー等はすべて typemark() 経由のまま
81
+ def display_typemark
82
+ NameUtils.display_typemark(typemark(), @db.propget('version'))
83
+ end
84
+
75
85
  def type_label
76
86
  case typemark()
77
87
  when '.' then 'singleton method'
@@ -79,6 +89,7 @@ module BitClust
79
89
  when '.#' then 'module function'
80
90
  when '::' then 'constant'
81
91
  when '$' then 'variable'
92
+ else raise "invalid typemark: #{typemark().inspect}"
82
93
  end
83
94
  end
84
95
 
@@ -96,10 +107,17 @@ module BitClust
96
107
 
97
108
  persistent_properties {
98
109
  property :names, '[String]'
99
- property :visibility, 'Symbol' # :public | :private | :protected
100
- property :kind, 'Symbol' # :defined | :added | :redefined
110
+ property :visibility, 'Symbol' ## :public | :private | :protected
111
+ property :kind, 'Symbol' ## :defined | :added | :redefined | :undefined | :nomethod
101
112
  property :source, 'String'
102
113
  property :source_location, 'Location'
114
+ # 名前別の since/until(bitclust#132)。トークンは
115
+ # "#{エンコード名}=#{バージョン}" の配列([String] 型を再利用)で、
116
+ # 生名の ',' '=' は encodename_url でエスケープ済みなので最後の '='
117
+ # がバージョンとの区切りになる(バージョン文字列には '=' も ',' も
118
+ # 現れない前提。fill_since/fill_until で検査する)
119
+ property :since_by_name, '[String]'
120
+ property :until_by_name, '[String]'
103
121
  }
104
122
 
105
123
  def inspect
@@ -108,7 +126,8 @@ module BitClust
108
126
  end
109
127
 
110
128
  def spec
111
- MethodSpec.new(*methodid2specparts(@id))
129
+ c, t, m, lib = methodid2specparts(@id)
130
+ MethodSpec.new(c, t, m, lib)
112
131
  end
113
132
 
114
133
  def spec_string
@@ -120,11 +139,29 @@ module BitClust
120
139
  "#{t == '$' ? '' : c}#{t}#{m}"
121
140
  end
122
141
 
142
+ # bitclust#250: label の表示専用版(module function は 4.0 以降 "?." で
143
+ # 表示)。label 自身は refsdatabase.rb の [[a:...]] アンカーキーや
144
+ # `bitclust methods --diff` の突き合わせが literal ".#" 前提で使うので
145
+ # 変えない -- テンプレート側の実際の表示箇所だけがこちらを呼ぶ
146
+ def display_label
147
+ c, t, m, _lib = methodid2specparts(@id)
148
+ "#{t == '$' ? '' : c}#{display_typemark}#{m}"
149
+ end
150
+
123
151
  def short_label
124
152
  _c, t, m, _lib = methodid2specparts(@id)
125
153
  "#{t == '#' ? '' : t}#{m}"
126
154
  end
127
155
 
156
+ # bitclust#250: short_label の表示専用版。short_label 自身の唯一の
157
+ # 呼び出し元(htmlutils.rb の link_to_method)は display_short_label に
158
+ # 切り替え済みだが、short_label 自体は同じ理由(識別子的な使い方をする
159
+ # 将来のコードのため)で変えない
160
+ def display_short_label
161
+ _c, t, m, _lib = methodid2specparts(@id)
162
+ "#{t == '#' ? '' : display_typemark}#{m}"
163
+ end
164
+
128
165
  def index_id
129
166
  "#{methodid2typechar(@id)}_#{encodename_fs(name).gsub(/=/, '--')}".upcase
130
167
  end
@@ -134,10 +171,79 @@ module BitClust
134
171
  names().map {|name| "#{c}#{t}#{name}" }
135
172
  end
136
173
 
174
+ # Every name of this entry, formatted the same way as #label (i.e.
175
+ # without the redundant class prefix on special variables such as $!,
176
+ # unlike #labels). Used where all aliases of a method need to be listed
177
+ # together, e.g. the <title> of its page.
178
+ def title_labels
179
+ c, t, _m, _lib = methodid2specparts(@id)
180
+ names().map {|name| "#{t == '$' ? '' : c}#{t}#{name}" }
181
+ end
182
+
183
+ # bitclust#250: title_labels の表示専用版(<title> タグ・見出しで使う)
184
+ def display_title_labels
185
+ c, t, _m, _lib = methodid2specparts(@id)
186
+ names().map {|name| "#{t == '$' ? '' : c}#{display_typemark}#{name}" }
187
+ end
188
+
137
189
  def name?(name)
138
190
  names().include?(name)
139
191
  end
140
192
 
193
+ # 名前別 since/until(bitclust#132)。名前ごとに別バージョンで
194
+ # 追加/削除されうる別名(例: alias)を区別して記録する
195
+
196
+ def since_of(name)
197
+ since_map[name]
198
+ end
199
+
200
+ def until_of(name)
201
+ until_map[name]
202
+ end
203
+
204
+ def since_map
205
+ decode_version_tokens(since_by_name)
206
+ end
207
+
208
+ def until_map
209
+ decode_version_tokens(until_by_name)
210
+ end
211
+
212
+ # name の since が未設定の場合のみ version を追加する。追加したら true、
213
+ # 既に値があって何もしなければ false を返す
214
+ def fill_since(name, version)
215
+ fill_version_token(:since_by_name, :since_of, name, version)
216
+ end
217
+
218
+ # fill_since の until 版
219
+ def fill_until(name, version)
220
+ fill_version_token(:until_by_name, :until_of, name, version)
221
+ end
222
+
223
+ private
224
+
225
+ def decode_version_tokens(tokens)
226
+ h = {} #: Hash[String, String]
227
+ tokens.each do |token|
228
+ i = token.rindex('=') or raise "must not happen: malformed version token #{token.inspect}"
229
+ raw_name = decodename_url(token[0...i] || raise)
230
+ h[raw_name] = token[(i + 1)..] || raise
231
+ end
232
+ h
233
+ end
234
+
235
+ def fill_version_token(prop, reader, name, version)
236
+ if version.include?('=') || version.include?(',')
237
+ raise ArgumentError, "version must not contain '=' or ',': #{version.inspect}"
238
+ end
239
+ return false if __send__(reader, name)
240
+ token = "#{encodename_url(name)}=#{version}"
241
+ __send__("#{prop}=", __send__(prop) + [token])
242
+ true
243
+ end
244
+
245
+ public
246
+
141
247
  def name_match?(re)
142
248
  names().any? {|n| re =~ n }
143
249
  end
@@ -147,7 +253,7 @@ module BitClust
147
253
  end
148
254
 
149
255
  def public?
150
- visibility() != :private
256
+ visibility() != :private && visibility() != :protected
151
257
  end
152
258
 
153
259
  def protected?
@@ -171,7 +277,11 @@ module BitClust
171
277
  end
172
278
 
173
279
  def private_instance_method?
174
- instance_method? and public?
280
+ instance_method? and private?
281
+ end
282
+
283
+ def protected_instance_method?
284
+ instance_method? and protected?
175
285
  end
176
286
 
177
287
  def singleton_method?
@@ -204,8 +314,21 @@ module BitClust
204
314
  kind() == :redefined
205
315
  end
206
316
 
317
+ def undefined?
318
+ kind() == :undefined
319
+ end
320
+
321
+ # 説明のためだけに記載されていて実際には定義されていないメソッド
322
+ # (ソースの @nomethod メタデータ行で指定する)
323
+ def nomethod?
324
+ kind() == :nomethod
325
+ end
326
+
207
327
  def description
208
- source.split(/\n\n+/, 3)[1]
328
+ paragraphs = source.split(/\n\n+/).drop(1)
329
+ # {: ...} 属性行や @param などのメタデータ段落は説明文として使わない
330
+ para = paragraphs.find {|p| !p.start_with?('@', '{:') } || paragraphs.first || ''
331
+ description_text(para)
209
332
  end
210
333
  end
211
334
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  #
2
3
  # bitclust/methodid.rb
3
4
  #
@@ -65,7 +66,8 @@ module BitClust
65
66
  class MethodSpec
66
67
 
67
68
  def MethodSpec.parse(str)
68
- new(*NameUtils.split_method_spec(str))
69
+ c, t, m = NameUtils.split_method_spec(str)
70
+ new(c, t, m)
69
71
  end
70
72
 
71
73
  def initialize(c, t, m, library = nil)
@@ -88,8 +90,13 @@ module BitClust
88
90
  "#{@klass}#{@type}#{@method}"
89
91
  end
90
92
 
91
- def display_name
92
- @type == '$' ? "$#{@method}" : to_s()
93
+ # version はドキュメント対象の Ruby バージョン(DB の version プロパティ)。
94
+ # 指定すると module function typemark を表示用に畳む
95
+ # (4.0 以降は "?."。NameUtils#display_typemark と同じ規則)
96
+ def display_name(version = nil)
97
+ return "$#{@method}" if @type == '$'
98
+ return "#{@klass}#{NameUtils.display_typemark(_ = @type, version)}#{@method}" if version
99
+ to_s()
93
100
  end
94
101
 
95
102
  def ==(other)
@@ -181,15 +188,10 @@ module BitClust
181
188
  private :tesc
182
189
 
183
190
  def match?(m)
184
- (not @library or m.library.name?(@library)) and
185
- (not @klass or m.klass.name?(@klass)) and
191
+ (not @library or m.library.name?(@library || raise)) and
192
+ (not @klass or m.klass.name?(@klass || raise)) and
186
193
  (not @type or m.typemark == @type) and
187
- (not @method or m.name?(@method))
188
- end
189
-
190
- def select_classes(cs)
191
- return cs unless @klass
192
- expand_ic(cs, @klass, @crecache)
194
+ (not @method or m.name?(@method || raise))
193
195
  end
194
196
 
195
197
  def empty?
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  #
2
3
  # bitclust/methodsignature.rb
3
4
  #
@@ -32,7 +33,7 @@ module BitClust
32
33
  m = METHOD_SIGNATURE_RE.match(line) or
33
34
  raise ParseError, %Q(unknown signature format: "#{line.strip}")
34
35
  method, gvar, params, block, type = m.captures
35
- new(method || gvar, params && params.strip, block && block.strip, type && type.strip)
36
+ new(method || gvar || raise, params && params.strip, block && block.strip, type && type.strip)
36
37
  end
37
38
 
38
39
  def initialize(name, params, block, type)
@@ -63,9 +64,15 @@ module BitClust
63
64
  when "[]" # aref
64
65
  "self[#{@params}]" + (@type ? " -> #{@type}" : "")
65
66
  when "[]=" # aset
66
- params = @params.split(',')
67
- val = params.pop
68
- "self[#{params.join(',').strip}] = #{val.strip}"
67
+ params = @params&.split(',')
68
+ if params && params.size >= 2
69
+ val = params.pop || raise
70
+ "self[#{params.join(',').strip}] = #{val.strip}"
71
+ else
72
+ # Signatures like []=(*idxary) in historic documents cannot be
73
+ # shaped into "self[...] = ..."; show the raw signature instead
74
+ to_s()
75
+ end
69
76
  when "`" # `command`
70
77
  "`#{@params}`" + (@type ? " -> #{@type}" : "")
71
78
  when /\A\W/ # binary operator
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  #
2
3
  # bitclust/nameutils.rb
3
4
  #
@@ -58,51 +59,55 @@ module BitClust
58
59
  def split_method_spec(spec)
59
60
  case spec
60
61
  when /\AKernel\$/
61
- return 'Kernel', '$', $'
62
+ return ['Kernel', '$', $' || raise]
62
63
  else
63
64
  m = /\A(#{CLASS_PATH_RE})(#{TYPEMARK_RE})(#{METHOD_NAME_RE})\z/o.match(spec) or
64
65
  raise ArgumentError, "wrong method spec: #{spec.inspect}"
65
- return *m.captures
66
+ cname = m[1] || raise
67
+ # @type var tmark: NameUtils::typemark
68
+ tmark = _ = m[2] || raise
69
+ mname = m[3] || raise
70
+ return [cname, tmark, mname]
66
71
  end
67
72
  end
68
73
 
69
74
  def methodid2specstring(id)
70
- c, t, m, _lib = *split_method_id(id)
75
+ c, t, m, _lib = split_method_id(id)
71
76
  classid2name(c) + typechar2mark(t) + decodename_url(m)
72
77
  end
73
78
 
74
79
  def methodid2specparts(id)
75
- c, t, m, lib = *split_method_id(id)
76
- return classid2name(c), typechar2mark(t), decodename_url(m), libid2name(lib)
80
+ c, t, m, lib = split_method_id(id)
81
+ [classid2name(c), typechar2mark(t), decodename_url(m), libid2name(lib)]
77
82
  end
78
83
 
79
84
  def methodid2libid(id)
80
- _c, _t, _m, lib = *split_method_id(id)
85
+ _c, _t, _m, lib = split_method_id(id)
81
86
  lib
82
87
  end
83
88
 
84
89
  def methodid2classid(id)
85
- c, _t, _m, _lib = *split_method_id(id)
90
+ c, _t, _m, _lib = split_method_id(id)
86
91
  c
87
92
  end
88
93
 
89
94
  def methodid2typechar(id)
90
- _c, t, _m, _lib = *split_method_id(id)
95
+ _c, t, _m, _lib = split_method_id(id)
91
96
  t
92
97
  end
93
98
 
94
99
  def methodid2typename(id)
95
- _c, t, _m, _lib = *split_method_id(id)
100
+ _c, t, _m, _lib = split_method_id(id)
96
101
  typechar2name(t)
97
102
  end
98
103
 
99
104
  def methodid2typemark(id)
100
- _c, t, _m, _lib = *split_method_id(id)
105
+ _c, t, _m, _lib = split_method_id(id)
101
106
  typechar2mark(t)
102
107
  end
103
108
 
104
109
  def methodid2mname(id)
105
- _c, _t, m, _lib = *split_method_id(id)
110
+ _c, _t, m, _lib = split_method_id(id)
106
111
  decodename_url(m)
107
112
  end
108
113
 
@@ -120,13 +125,13 @@ module BitClust
120
125
  "#{cid}/#{typename2char(t)}.#{encodename_url(name)}.#{libid}"
121
126
  end
122
127
 
123
- @@split_method_id = {}
128
+ @@split_method_id = {} #: Hash[String, untyped]
124
129
 
125
130
  # private module function
126
131
  def split_method_id(id)
127
132
  @@split_method_id[id] ||= begin
128
133
  c, rest = id.split("/")
129
- [c, *rest.split(%r<[/\.]>, 3)]
134
+ [c, *rest&.split(%r<[/\.]>, 3)]
130
135
  end
131
136
  end
132
137
 
@@ -141,7 +146,7 @@ module BitClust
141
146
  MARK_TO_NAME = NAME_TO_MARK.invert
142
147
 
143
148
  def typename?(n)
144
- NAME_TO_MARK.key?(n)
149
+ NAME_TO_MARK.key?(_ = n)
145
150
  end
146
151
 
147
152
  def typename2mark(name)
@@ -165,7 +170,7 @@ module BitClust
165
170
  CHAR_TO_NAME = NAME_TO_CHAR.invert
166
171
 
167
172
  def typechar?(c)
168
- CHAR_TO_NAME.key?(c)
173
+ CHAR_TO_NAME.key?(_ = c)
169
174
  end
170
175
 
171
176
  def typename2char(name)
@@ -189,7 +194,7 @@ module BitClust
189
194
  CHAR_TO_MARK = MARK_TO_CHAR.invert
190
195
 
191
196
  def typemark?(m)
192
- MARK_TO_CHAR.key?(m)
197
+ MARK_TO_CHAR.key?(_ = m)
193
198
  end
194
199
 
195
200
  def typechar2mark(char)
@@ -202,24 +207,39 @@ module BitClust
202
207
  raise "must not happen: #{mark.inspect}"
203
208
  end
204
209
 
210
+ # bitclust#250: Ruby 4.0 以降のドキュメントでは module function の表記を
211
+ # るりま独自の ".#" から "?." に変える(表示のみ。ソース側は既に "?."
212
+ # 記法に対応済みで、内部的には従来どおり ".#" に変換される)。
213
+ #
214
+ # これは見た目だけの変換であり、method id・URL・spec 文字列など識別子と
215
+ # して使う ".#" 自体は一切変えない。typemark が '.#' 以外、または version
216
+ # が不明(nil/空)な場合はそのまま返す。バージョン比較は文字列比較では
217
+ # なく Gem::Version で行う("10.0" を文字列比較すると "4.0" より小さく
218
+ # 見えてしまうため)。
219
+ def display_typemark(mark, version)
220
+ return mark unless mark == '.#'
221
+ return mark unless version && !version.empty?
222
+ Gem::Version.new(version) >= Gem::Version.new('4.0') ? '?.' : mark
223
+ end
224
+
205
225
  def functionname?(n)
206
226
  /\A\w+\z/ =~ n ? true : false
207
227
  end
208
228
 
209
229
  # string -> case-sensitive ID
210
230
  def encodename_url(str)
211
- str.gsub(/[^A-Za-z0-9_]/n) {|ch| sprintf('=%02x', ch[0].ord) }
231
+ str.gsub(/[^A-Za-z0-9_]/n) {|ch| sprintf('=%02x', (ch[0] || raise).ord) }
212
232
  end
213
233
 
214
234
  # case-sensitive ID -> string
215
235
  def decodename_url(str)
216
- str.gsub(/=[\da-h]{2}/ni) {|s| s[1,2].hex.chr }
236
+ str.gsub(/=[\da-h]{2}/ni) {|s| (s[1,2] || raise).hex.chr }
217
237
  end
218
238
 
219
239
  # string -> encoded string in a rdoc way
220
240
  def encodename_rdocurl(str)
221
241
  str = str.gsub(/[^A-Za-z0-9_.]/n) {|ch|
222
- sprintf('-%02X', ch[0].ord)
242
+ sprintf('-%02X', (ch[0] || raise).ord)
223
243
  }
224
244
  str.sub(/\A-/, '')
225
245
  end
@@ -231,18 +251,18 @@ module BitClust
231
251
 
232
252
  # encoded string -> case-sensitive ID (decode only [A-Z])
233
253
  def decodeid(str)
234
- str.gsub(/-[a-z]/ni) {|s| s[1,1].upcase }
254
+ str.gsub(/-[a-z]/ni) {|s| (s[1,1] || raise).upcase }
235
255
  end
236
256
 
237
257
  def encodename_fs(str)
238
258
  str.gsub(/[^a-z0-9_]/n) {|ch|
239
- (/[A-Z]/n =~ ch) ? "-#{ch}" : sprintf('=%02x', ch[0].ord)
259
+ (/[A-Z]/n =~ ch) ? "-#{ch}" : sprintf('=%02x', (ch[0] || raise).ord)
240
260
  }.downcase
241
261
  end
242
262
 
243
263
  def decodename_fs(str)
244
264
  str.gsub(/=[\da-h]{2}|-[a-z]/ni) {|s|
245
- (/\A-/ =~ s) ? s[1,1].upcase : s[1,2].hex.chr
265
+ (/\A-/ =~ s) ? (s[1,1] || raise).upcase : (s[1,2] || raise).hex.chr
246
266
  }
247
267
  end
248
268
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  #
2
3
  # bitclust/parseutils.rb
3
4
  #