rice 4.8.0 → 4.9.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/CMakePresets.json +77 -50
  4. data/FindRuby.cmake +1 -1
  5. data/bin/rice-doc.rb +2 -0
  6. data/include/rice/api.hpp +14 -1
  7. data/include/rice/rice.hpp +351 -132
  8. data/include/rice/stl.hpp +319 -256
  9. data/lib/rice/doc/config.rb +57 -57
  10. data/lib/rice/doc/cpp_reference.rb +158 -158
  11. data/lib/rice/doc/doxygen.rb +289 -289
  12. data/lib/rice/doc/mkdocs.rb +332 -332
  13. data/lib/rice/doc/rice.rb +48 -47
  14. data/lib/rice/doc/ruby.rb +26 -26
  15. data/lib/rice/native.rb +15 -15
  16. data/lib/rice/native_registry.rb +12 -17
  17. data/lib/rice/parameter.rb +5 -5
  18. data/lib/rice/rbs.rb +72 -72
  19. data/lib/rice/version.rb +1 -1
  20. data/lib/rubygems/builder.rb +9 -9
  21. data/lib/rubygems_plugin.rb +8 -8
  22. data/rice/Data_Type.ipp +12 -7
  23. data/rice/cpp_api/Class.hpp +5 -0
  24. data/rice/cpp_api/Class.ipp +5 -0
  25. data/rice/cpp_api/Object.hpp +6 -0
  26. data/rice/cpp_api/Object.ipp +5 -0
  27. data/rice/detail/Forwards.hpp +18 -0
  28. data/rice/detail/Forwards.ipp +60 -0
  29. data/rice/detail/Native.ipp +2 -4
  30. data/rice/detail/NativeAttributeGet.ipp +1 -1
  31. data/rice/detail/NativeAttributeSet.hpp +5 -3
  32. data/rice/detail/NativeAttributeSet.ipp +41 -33
  33. data/rice/detail/NativeMethod.ipp +25 -22
  34. data/rice/detail/NativeRegistry.hpp +4 -2
  35. data/rice/detail/NativeRegistry.ipp +42 -9
  36. data/rice/detail/Parameter.ipp +3 -4
  37. data/rice/detail/Type.ipp +4 -0
  38. data/rice/detail/Wrapper.hpp +17 -12
  39. data/rice/detail/Wrapper.ipp +95 -36
  40. data/rice/rice.hpp +3 -0
  41. data/rice/rice_api/NativeRegistry.ipp +14 -1
  42. data/rice/stl/exception.ipp +1 -1
  43. data/rice/stl/filesystem.ipp +1 -1
  44. data/rice/stl/map.ipp +13 -11
  45. data/rice/stl/multimap.ipp +13 -11
  46. data/rice/stl/pair.ipp +14 -8
  47. data/rice/stl/set.ipp +16 -16
  48. data/rice/stl/shared_ptr.hpp +16 -0
  49. data/rice/stl/shared_ptr.ipp +74 -37
  50. data/rice/stl/type_index.ipp +1 -1
  51. data/rice/stl/unique_ptr.hpp +9 -3
  52. data/rice/stl/unique_ptr.ipp +80 -124
  53. data/rice/stl/unordered_map.ipp +14 -12
  54. data/rice/stl/vector.ipp +67 -31
  55. data/test/test_Attribute.cpp +72 -0
  56. data/test/test_Callback.cpp +3 -0
  57. data/test/test_Inheritance.cpp +14 -14
  58. data/test/test_Keep_Alive_No_Wrapper.cpp +6 -2
  59. data/test/test_Stl_Map.cpp +46 -0
  60. data/test/test_Stl_Multimap.cpp +46 -0
  61. data/test/test_Stl_Set.cpp +34 -0
  62. data/test/test_Stl_SharedPtr.cpp +160 -45
  63. data/test/test_Stl_UniquePtr.cpp +48 -3
  64. data/test/test_Stl_Unordered_Map.cpp +46 -0
  65. data/test/test_Stl_Variant.cpp +10 -14
  66. data/test/test_Stl_Vector.cpp +140 -13
  67. data/test/test_Tracking.cpp +3 -0
  68. metadata +3 -1
@@ -1,336 +1,336 @@
1
1
  require 'fileutils'
2
2
 
3
3
  module Rice
4
- module Doc
5
- class Mkdocs
6
- ESCAPE_METHODS = {'*' => '\*',
7
- '+' => '\+',
8
- '-' => '\-',
9
- '.' => '\.',
10
- '!' => '\!',
11
- '|' => '\|',
12
- '[]' => '\[\]',
13
- '[]=' => '\[\]='}
14
-
15
- attr_reader :klasses, :output
16
-
17
- def initialize(klasses, doc_resolvers, output)
18
- @klasses = klasses
19
- @doc_resolvers = doc_resolvers
20
- @output = output
21
- end
22
-
23
- def generate
24
- FileUtils.mkdir_p(@output)
25
-
26
- klasses.sort_by(&:name).each.with_index do |klass, i|
27
- STDOUT << klass.name << " (" << i << "/" << klasses.count << ")" << "\n"
28
- if klass.instance_of?(Module)
29
- write_module(klass)
30
- elsif klass.cpp_class.match(/^enum/i)
31
- write_enum(klass)
32
- elsif klass.cpp_class.match(/^union/i)
33
- write_union(klass)
34
- else
35
- write_class(klass)
36
- end
37
- end
38
-
39
- create_indexes
40
- end
41
-
42
- def create_indexes
43
- # Find all directories (including output root)
44
- directories = Dir.glob(File.join(@output, '**', '*')).select { |f| File.directory?(f) }
45
- directories.unshift(@output)
46
-
47
- directories.each do |dir|
48
- entries = []
49
- has_index = File.exist?(File.join(dir, 'index.md'))
50
-
51
- # Get all .md files in this directory (excluding index.md)
52
- Dir.glob(File.join(dir, '*.md')).each do |file|
53
- basename = File.basename(file)
54
- entries << basename unless basename == 'index.md'
55
- end
56
-
57
- # Get all subdirectories
58
- Dir.glob(File.join(dir, '*')).each do |path|
59
- if File.directory?(path)
60
- entries << File.basename(path)
61
- end
62
- end
63
-
64
- # Sort alphabetically
65
- entries.sort!
66
-
67
- # Prepend index.md if it exists
68
- entries.unshift('index.md') if has_index
69
-
70
- pages_path = File.join(dir, '.pages')
71
- File.open(pages_path, 'w') do |file|
72
- file << "nav:\n"
73
- entries.each do |entry|
74
- file << " - #{entry}\n"
75
- end
76
- end
77
- end
78
- end
79
-
80
- def output_path(klass)
81
- parts = klass.name.split("::")
82
- path = if klass.instance_of?(Module)
83
- File.join(@output, *parts[0..-1], "index.md")
84
- else
85
- File.join(@output, *parts[0..-2], "#{parts.last}.md")
86
- end
87
-
88
- unless Dir.exist?(File.dirname(path))
89
- FileUtils.mkdir_p((File.dirname(path)))
90
- end
91
- path
92
- end
93
-
94
- def resolver(klass)
95
- parts = klass.name.split("::")
96
- key = if parts.length == 1 && !klass.instance_of?(Module)
97
- nil
98
- else
99
- parts.first
100
- end
101
-
102
- @doc_resolvers[key]
103
- end
104
-
105
- def class_sig(klass)
106
- klass_name = klass.name.split("::").last
107
-
108
- url = resolver(klass)&.class_url(klass)
109
- if url
110
- "#[#{klass_name}](#{url})"
111
- else
112
- "##{klass_name}"
113
- end
114
- end
115
-
116
- def enum_sig(klass)
117
- klass_name = klass.name.split("::").last
118
- url = resolver(klass)&.enum_url(klass)
119
- if url
120
- "#[#{klass_name} Enum](#{url})"
121
- else
122
- "##{klass_name} Enum"
123
- end
124
- end
125
-
126
- def enum_value_sig(klass, value)
127
- url = resolver(klass)&.enum_value_url(klass, value)
128
-
129
- if url
130
- "[#{value}](#{url})"
131
- else
132
- "#{value}"
133
- end
134
- end
135
-
136
- def union_sig(klass)
137
- klass_name = klass.name.split("::").last
138
- url = resolver(klass)&.union_url(klass)
139
- if url
140
- "#[#{klass_name} Union](#{url})"
141
- else
142
- "##{klass_name} Union"
143
- end
144
- end
145
-
146
- def method_sigs(klass, native_methods, method_sig)
147
- native_methods.map do |native_method|
148
- method_sig(klass, native_method, method_sig)
149
- end.join("\n\n")
150
- end
151
-
152
- def type_url(klass)
153
- resolver = resolver(klass)
154
-
155
- if klass.instance_of?(Module)
156
- resolver&.module_url(klass)
157
- elsif !klass.respond_to?(:cpp_class)
158
- resolver&.class_url(klass)
159
- elsif klass.cpp_class.match(/^enum/i)
160
- resolver&.enum_url(klass)
161
- elsif klass.cpp_class.match(/^union/i)
162
- resolver&.union_url(klass)
163
- else
164
- resolver&.class_url(klass)
165
- end
166
- end
167
-
168
- def parameters_sig(klass, native)
169
- native.parameters.map do |parameter|
170
- url = type_url(parameter.klass)
171
- if url
172
- "#{parameter.arg.name}: [#{parameter.klass}](#{url})"
173
- else
174
- "#{parameter.arg.name}: #{parameter.klass}"
175
- end
176
- end.join(", ")
177
- end
178
-
179
- def return_sig(klass, native)
180
- url = type_url(native.return_klass)
181
- if url
182
- "[#{native.return_klass}](#{url})"
183
- else
184
- "#{native.return_klass}"
185
- end
186
- end
187
-
188
- def constructor_sig(klass, native)
189
- url = resolver(klass)&.method_url(klass, native)
190
-
191
- if url
192
- "[initialize](#{url})(#{parameters_sig(klass, native)})"
193
- else
194
- "initialize(#{parameters_sig(klass, native)})"
195
- end
196
- end
197
-
198
- def method_sig(klass, native, singleton)
199
- url = if singleton
200
- resolver(klass)&.singleton_method_url(klass, native)
201
- else
202
- resolver(klass)&.method_url(klass, native)
203
- end
204
-
205
- name = ESCAPE_METHODS[native.name] || native.name
206
-
207
- parameters_string = if native.parameters.empty?
208
- ""
209
- else
210
- "(#{parameters_sig(klass, native)})"
211
- end
212
-
213
- if url
214
- "[#{name}](#{url})#{parameters_string} -> #{return_sig(klass, native)}"
215
- else
216
- "#{name}#{parameters_string} -> #{return_sig(klass, native)}"
217
- end
218
- end
219
-
220
- def attribute_sig(klass, native_attributes)
221
- attr_type = if native_attributes.size == 2
222
- "read/write"
223
- elsif native_attributes.first.kind == NativeKind::AttributeReader
224
- "read"
225
- else
226
- "write"
227
- end
228
-
229
- native_attribute = native_attributes.first
230
-
231
- attribute_resolver = resolver(klass)
232
- attribute_url = attribute_resolver&.attribute_url(klass, native_attribute)
233
-
234
- type_url = type_url(native_attribute.return_klass)
235
-
236
- if attribute_url
237
- "[#{native_attribute.name}](#{attribute_url}): [#{native_attribute.return_klass}](#{type_url}) (#{attr_type})"
238
- else
239
- "#{native_attribute.name}: [#{native_attribute.return_klass}](#{type_url}) (#{attr_type})"
240
- end
241
- end
242
-
243
- def write_module(a_module)
244
- native_singleton_functions = Registries.instance.natives.native_functions(a_module.singleton_class).sort.group_by(&:name)
245
- return if native_singleton_functions.empty?
246
-
247
- path = output_path(a_module)
248
- File.open(path, 'w') do |file|
249
- file << "#" << a_module.name << "\n"
250
- file << "## Singleton Methods" << "\n"
251
- native_singleton_functions.each do |name, natives|
252
- file << method_sigs(a_module, natives, false) << "\n\n"
253
- end
254
- file << "\n"
255
- end
256
- end
257
-
258
- def write_class(klass)
259
- native_attributes = Registries.instance.natives.native_attributes(klass).sort.group_by(&:name)
260
- native_singleton_functions = Registries.instance.natives.native_functions(klass.singleton_class).sort.group_by(&:name)
261
- native_methods = Registries.instance.natives.native_methods(klass).sort.group_by(&:name)
262
-
263
- path = output_path(klass)
264
- File.open(path, 'w') do |file|
265
- file << class_sig(klass) << "\n"
266
-
267
- # Singleton methods
268
- unless native_singleton_functions.empty?
269
- file << "## Singleton Methods" << "\n"
270
- native_singleton_functions.each do |name, natives|
271
- file << method_sigs(klass, natives, true) << "\n\n"
272
- end
273
- file << "\n"
274
- end
275
-
276
- # Constructors
277
- constructors = native_methods.delete("initialize")
278
- if constructors
279
- file << "## Constructors" << "\n"
280
- constructors.each do |constructor|
281
- file << constructor_sig(klass, constructor) << "\n\n"
282
- end
283
- file << "\n"
284
- end
285
-
286
- # Attributes
287
- unless native_attributes.empty?
288
- file << "## Attributes" << "\n"
289
- native_attributes.each do |name, natives|
290
- file << attribute_sig(klass, natives) << "\n\n"
291
- end
292
- file << "\n"
293
- end
294
-
295
- # Instance methods
296
- unless native_methods.empty?
297
- file << "## Methods" << "\n"
298
- native_methods.each do |name, natives|
299
- file << method_sigs(klass, natives, false) << "\n\n"
300
- end
301
- file << "\n"
302
- end
303
- end
304
- end
305
-
306
- def write_enum(klass)
307
- path = output_path(klass)
308
- File.open(path, 'w') do |file|
309
- file << enum_sig(klass) << "\n"
310
- file << "## Values" << "\n"
311
- klass.values.each do |value|
312
- file << "* " << enum_value_sig(klass, value) << "\n"
313
- end
314
- end
315
- end
316
-
317
- def write_union(klass)
318
- native_attributes = Registries.instance.natives.native_attributes(klass).sort.group_by(&:name)
319
-
320
- path = output_path(klass)
321
- File.open(path, 'w') do |file|
322
- file << union_sig(klass) << "\n"
323
-
324
- # Attributes
325
- unless native_attributes.empty?
326
- file << "## Attributes" << "\n"
327
- native_attributes.each do |name, natives|
328
- file << attribute_sig(klass, natives) << "\n\n"
329
- end
330
- file << "\n"
331
- end
332
- end
333
- end
334
- end
335
- end
4
+ module Doc
5
+ class Mkdocs
6
+ ESCAPE_METHODS = {'*' => '\*',
7
+ '+' => '\+',
8
+ '-' => '\-',
9
+ '.' => '\.',
10
+ '!' => '\!',
11
+ '|' => '\|',
12
+ '[]' => '\[\]',
13
+ '[]=' => '\[\]='}
14
+
15
+ attr_reader :klasses, :output
16
+
17
+ def initialize(klasses, doc_resolvers, output)
18
+ @klasses = klasses
19
+ @doc_resolvers = doc_resolvers
20
+ @output = output
21
+ end
22
+
23
+ def generate
24
+ FileUtils.mkdir_p(@output)
25
+
26
+ klasses.sort_by(&:name).each.with_index do |klass, i|
27
+ STDOUT << klass.name << " (" << i << "/" << klasses.count << ")" << "\n"
28
+ if klass.instance_of?(Module)
29
+ write_module(klass)
30
+ elsif klass.cpp_class.match(/^enum/i)
31
+ write_enum(klass)
32
+ elsif klass.cpp_class.match(/^union/i)
33
+ write_union(klass)
34
+ else
35
+ write_class(klass)
36
+ end
37
+ end
38
+
39
+ create_indexes
40
+ end
41
+
42
+ def create_indexes
43
+ # Find all directories (including output root)
44
+ directories = Dir.glob(File.join(@output, '**', '*')).select { |f| File.directory?(f) }
45
+ directories.unshift(@output)
46
+
47
+ directories.each do |dir|
48
+ entries = []
49
+ has_index = File.exist?(File.join(dir, 'index.md'))
50
+
51
+ # Get all .md files in this directory (excluding index.md)
52
+ Dir.glob(File.join(dir, '*.md')).each do |file|
53
+ basename = File.basename(file)
54
+ entries << basename unless basename == 'index.md'
55
+ end
56
+
57
+ # Get all subdirectories
58
+ Dir.glob(File.join(dir, '*')).each do |path|
59
+ if File.directory?(path)
60
+ entries << File.basename(path)
61
+ end
62
+ end
63
+
64
+ # Sort alphabetically
65
+ entries.sort!
66
+
67
+ # Prepend index.md if it exists
68
+ entries.unshift('index.md') if has_index
69
+
70
+ pages_path = File.join(dir, '.pages')
71
+ File.open(pages_path, 'w') do |file|
72
+ file << "nav:\n"
73
+ entries.each do |entry|
74
+ file << " - #{entry}\n"
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ def output_path(klass)
81
+ parts = klass.name.split("::")
82
+ path = if klass.instance_of?(Module)
83
+ File.join(@output, *parts[0..-1], "index.md")
84
+ else
85
+ File.join(@output, *parts[0..-2], "#{parts.last}.md")
86
+ end
87
+
88
+ unless Dir.exist?(File.dirname(path))
89
+ FileUtils.mkdir_p((File.dirname(path)))
90
+ end
91
+ path
92
+ end
93
+
94
+ def resolver(klass)
95
+ parts = klass.name.split("::")
96
+ key = if parts.length == 1 && !klass.instance_of?(Module)
97
+ nil
98
+ else
99
+ parts.first
100
+ end
101
+
102
+ @doc_resolvers[key]
103
+ end
104
+
105
+ def class_sig(klass)
106
+ klass_name = klass.name.split("::").last
107
+
108
+ url = resolver(klass)&.class_url(klass)
109
+ if url
110
+ "#[#{klass_name}](#{url})"
111
+ else
112
+ "##{klass_name}"
113
+ end
114
+ end
115
+
116
+ def enum_sig(klass)
117
+ klass_name = klass.name.split("::").last
118
+ url = resolver(klass)&.enum_url(klass)
119
+ if url
120
+ "#[#{klass_name} Enum](#{url})"
121
+ else
122
+ "##{klass_name} Enum"
123
+ end
124
+ end
125
+
126
+ def enum_value_sig(klass, value)
127
+ url = resolver(klass)&.enum_value_url(klass, value)
128
+
129
+ if url
130
+ "[#{value}](#{url})"
131
+ else
132
+ "#{value}"
133
+ end
134
+ end
135
+
136
+ def union_sig(klass)
137
+ klass_name = klass.name.split("::").last
138
+ url = resolver(klass)&.union_url(klass)
139
+ if url
140
+ "#[#{klass_name} Union](#{url})"
141
+ else
142
+ "##{klass_name} Union"
143
+ end
144
+ end
145
+
146
+ def method_sigs(klass, native_methods, method_sig)
147
+ native_methods.map do |native_method|
148
+ method_sig(klass, native_method, method_sig)
149
+ end.join("\n\n")
150
+ end
151
+
152
+ def type_url(klass)
153
+ resolver = resolver(klass)
154
+
155
+ if klass.instance_of?(Module)
156
+ resolver&.module_url(klass)
157
+ elsif !klass.respond_to?(:cpp_class)
158
+ resolver&.class_url(klass)
159
+ elsif klass.cpp_class.match(/^enum/i)
160
+ resolver&.enum_url(klass)
161
+ elsif klass.cpp_class.match(/^union/i)
162
+ resolver&.union_url(klass)
163
+ else
164
+ resolver&.class_url(klass)
165
+ end
166
+ end
167
+
168
+ def parameters_sig(klass, native)
169
+ native.parameters.map do |parameter|
170
+ url = type_url(parameter.klass)
171
+ if url
172
+ "#{parameter.arg.name}: [#{parameter.klass}](#{url})"
173
+ else
174
+ "#{parameter.arg.name}: #{parameter.klass}"
175
+ end
176
+ end.join(", ")
177
+ end
178
+
179
+ def return_sig(klass, native)
180
+ url = type_url(native.return_klass)
181
+ if url
182
+ "[#{native.return_klass}](#{url})"
183
+ else
184
+ "#{native.return_klass}"
185
+ end
186
+ end
187
+
188
+ def constructor_sig(klass, native)
189
+ url = resolver(klass)&.method_url(klass, native)
190
+
191
+ if url
192
+ "[initialize](#{url})(#{parameters_sig(klass, native)})"
193
+ else
194
+ "initialize(#{parameters_sig(klass, native)})"
195
+ end
196
+ end
197
+
198
+ def method_sig(klass, native, singleton)
199
+ url = if singleton
200
+ resolver(klass)&.singleton_method_url(klass, native)
201
+ else
202
+ resolver(klass)&.method_url(klass, native)
203
+ end
204
+
205
+ name = ESCAPE_METHODS[native.name] || native.name
206
+
207
+ parameters_string = if native.parameters.empty?
208
+ ""
209
+ else
210
+ "(#{parameters_sig(klass, native)})"
211
+ end
212
+
213
+ if url
214
+ "[#{name}](#{url})#{parameters_string} -> #{return_sig(klass, native)}"
215
+ else
216
+ "#{name}#{parameters_string} -> #{return_sig(klass, native)}"
217
+ end
218
+ end
219
+
220
+ def attribute_sig(klass, native_attributes)
221
+ attr_type = if native_attributes.size == 2
222
+ "read/write"
223
+ elsif native_attributes.first.kind == NativeKind::AttributeReader
224
+ "read"
225
+ else
226
+ "write"
227
+ end
228
+
229
+ native_attribute = native_attributes.first
230
+
231
+ attribute_resolver = resolver(klass)
232
+ attribute_url = attribute_resolver&.attribute_url(klass, native_attribute)
233
+
234
+ type_url = type_url(native_attribute.return_klass)
235
+
236
+ if attribute_url
237
+ "[#{native_attribute.name}](#{attribute_url}): [#{native_attribute.return_klass}](#{type_url}) (#{attr_type})"
238
+ else
239
+ "#{native_attribute.name}: [#{native_attribute.return_klass}](#{type_url}) (#{attr_type})"
240
+ end
241
+ end
242
+
243
+ def write_module(a_module)
244
+ native_singleton_functions = Registries.instance.natives.native_functions(a_module.singleton_class).sort.group_by(&:name)
245
+ return if native_singleton_functions.empty?
246
+
247
+ path = output_path(a_module)
248
+ File.open(path, 'w') do |file|
249
+ file << "#" << a_module.name << "\n"
250
+ file << "## Singleton Methods" << "\n"
251
+ native_singleton_functions.each do |name, natives|
252
+ file << method_sigs(a_module, natives, false) << "\n\n"
253
+ end
254
+ file << "\n"
255
+ end
256
+ end
257
+
258
+ def write_class(klass)
259
+ native_attributes = Registries.instance.natives.native_attributes(klass).sort.group_by(&:name)
260
+ native_singleton_functions = Registries.instance.natives.native_functions(klass.singleton_class).sort.group_by(&:name)
261
+ native_methods = Registries.instance.natives.native_methods(klass).sort.group_by(&:name)
262
+
263
+ path = output_path(klass)
264
+ File.open(path, 'w') do |file|
265
+ file << class_sig(klass) << "\n"
266
+
267
+ # Singleton methods
268
+ unless native_singleton_functions.empty?
269
+ file << "## Singleton Methods" << "\n"
270
+ native_singleton_functions.each do |name, natives|
271
+ file << method_sigs(klass, natives, true) << "\n\n"
272
+ end
273
+ file << "\n"
274
+ end
275
+
276
+ # Constructors
277
+ constructors = native_methods.delete("initialize")
278
+ if constructors
279
+ file << "## Constructors" << "\n"
280
+ constructors.each do |constructor|
281
+ file << constructor_sig(klass, constructor) << "\n\n"
282
+ end
283
+ file << "\n"
284
+ end
285
+
286
+ # Attributes
287
+ unless native_attributes.empty?
288
+ file << "## Attributes" << "\n"
289
+ native_attributes.each do |name, natives|
290
+ file << attribute_sig(klass, natives) << "\n\n"
291
+ end
292
+ file << "\n"
293
+ end
294
+
295
+ # Instance methods
296
+ unless native_methods.empty?
297
+ file << "## Methods" << "\n"
298
+ native_methods.each do |name, natives|
299
+ file << method_sigs(klass, natives, false) << "\n\n"
300
+ end
301
+ file << "\n"
302
+ end
303
+ end
304
+ end
305
+
306
+ def write_enum(klass)
307
+ path = output_path(klass)
308
+ File.open(path, 'w') do |file|
309
+ file << enum_sig(klass) << "\n"
310
+ file << "## Values" << "\n"
311
+ klass.values.each do |value|
312
+ file << "* " << enum_value_sig(klass, value) << "\n"
313
+ end
314
+ end
315
+ end
316
+
317
+ def write_union(klass)
318
+ native_attributes = Registries.instance.natives.native_attributes(klass).sort.group_by(&:name)
319
+
320
+ path = output_path(klass)
321
+ File.open(path, 'w') do |file|
322
+ file << union_sig(klass) << "\n"
323
+
324
+ # Attributes
325
+ unless native_attributes.empty?
326
+ file << "## Attributes" << "\n"
327
+ native_attributes.each do |name, natives|
328
+ file << attribute_sig(klass, natives) << "\n\n"
329
+ end
330
+ file << "\n"
331
+ end
332
+ end
333
+ end
334
+ end
335
+ end
336
336
  end