ffi-clang 0.13.0 → 0.14.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 (52) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/ext/rakefile.rb +2 -2
  4. data/lib/ffi/clang/clang_version.rb +7 -3
  5. data/lib/ffi/clang/code_completion.rb +121 -44
  6. data/lib/ffi/clang/comment.rb +164 -57
  7. data/lib/ffi/clang/compilation_database.rb +79 -25
  8. data/lib/ffi/clang/cursor.rb +395 -149
  9. data/lib/ffi/clang/diagnostic.rb +57 -23
  10. data/lib/ffi/clang/error.rb +12 -0
  11. data/lib/ffi/clang/file.rb +30 -11
  12. data/lib/ffi/clang/index.rb +37 -13
  13. data/lib/ffi/clang/lib/clang_version.rb +2 -2
  14. data/lib/ffi/clang/lib/code_completion.rb +15 -11
  15. data/lib/ffi/clang/lib/comment.rb +16 -14
  16. data/lib/ffi/clang/lib/compilation_database.rb +5 -5
  17. data/lib/ffi/clang/lib/cursor.rb +74 -56
  18. data/lib/ffi/clang/lib/diagnostic.rb +14 -14
  19. data/lib/ffi/clang/lib/file.rb +10 -6
  20. data/lib/ffi/clang/lib/inclusions.rb +3 -3
  21. data/lib/ffi/clang/lib/index.rb +7 -5
  22. data/lib/ffi/clang/lib/printing_policy.rb +36 -36
  23. data/lib/ffi/clang/lib/source_location.rb +9 -7
  24. data/lib/ffi/clang/lib/source_range.rb +5 -3
  25. data/lib/ffi/clang/lib/string.rb +9 -4
  26. data/lib/ffi/clang/lib/token.rb +17 -4
  27. data/lib/ffi/clang/lib/translation_unit.rb +17 -13
  28. data/lib/ffi/clang/lib/type.rb +19 -17
  29. data/lib/ffi/clang/lib.rb +35 -19
  30. data/lib/ffi/clang/platform.rb +25 -0
  31. data/lib/ffi/clang/printing_policy.rb +31 -18
  32. data/lib/ffi/clang/source_location.rb +119 -36
  33. data/lib/ffi/clang/source_range.rb +30 -12
  34. data/lib/ffi/clang/token.rb +48 -23
  35. data/lib/ffi/clang/translation_unit.rb +97 -33
  36. data/lib/ffi/clang/types/array.rb +15 -1
  37. data/lib/ffi/clang/types/elaborated.rb +19 -4
  38. data/lib/ffi/clang/types/function.rb +35 -10
  39. data/lib/ffi/clang/types/pointer.rb +23 -7
  40. data/lib/ffi/clang/types/record.rb +23 -8
  41. data/lib/ffi/clang/types/type.rb +80 -36
  42. data/lib/ffi/clang/types/type_def.rb +14 -2
  43. data/lib/ffi/clang/types/vector.rb +13 -1
  44. data/lib/ffi/clang/unsaved_file.rb +18 -8
  45. data/lib/ffi/clang/version.rb +4 -2
  46. data/lib/ffi/clang.rb +23 -45
  47. data/license.md +3 -2
  48. data/readme.md +12 -13
  49. data/releases.md +5 -0
  50. data.tar.gz.sig +0 -0
  51. metadata +10 -5
  52. metadata.gz.sig +0 -0
@@ -2,20 +2,25 @@
2
2
 
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2013, by Carlos Martín Nieto.
5
- # Copyright, 2013-2022, by Samuel Williams.
5
+ # Copyright, 2013-2025, by Samuel Williams.
6
6
  # Copyright, 2014, by George Pimm.
7
7
  # Copyright, 2014, by Masahiro Sano.
8
8
 
9
- require_relative 'lib/cursor'
10
- require_relative 'lib/comment'
11
- require_relative 'source_location'
9
+ require_relative "lib/cursor"
10
+ require_relative "lib/comment"
11
+ require_relative "source_location"
12
12
 
13
13
  module FFI
14
14
  module Clang
15
-
15
+ # Represents a documentation comment in parsed source code.
16
+ # This class provides access to structured documentation comments extracted from C/C++ source code.
17
+ # Comments can have different kinds (text, inline commands, HTML tags, block commands, etc.) and can be hierarchical.
16
18
  class Comment
17
19
  include Enumerable
18
-
20
+
21
+ # Build a comment instance from a low-level comment handle.
22
+ # @parameter comment [FFI::Pointer] The low-level comment handle.
23
+ # @returns [Comment] A comment instance of the appropriate subclass based on the comment kind.
19
24
  def self.build_from(comment)
20
25
  kind = Lib.comment_get_kind(comment)
21
26
  case kind
@@ -49,219 +54,321 @@ module FFI
49
54
  raise NotImplementedError, kind
50
55
  end
51
56
  end
52
-
57
+
58
+ # Get the text content of this comment.
59
+ # @returns [String] The text content, empty string for base Comment class.
53
60
  def text
54
61
  return ""
55
62
  end
56
-
63
+
64
+ # Create a new comment instance.
65
+ # @parameter comment [FFI::Pointer] The low-level comment handle.
57
66
  def initialize(comment)
58
67
  @comment = comment
59
68
  end
60
-
69
+
70
+ # Get the kind of this comment.
71
+ # @returns [Symbol] The comment kind (e.g., :comment_text, :comment_paragraph).
61
72
  def kind
62
73
  Lib.comment_get_kind(@comment)
63
74
  end
64
-
75
+
76
+ # Get the number of child comments.
77
+ # @returns [Integer] The number of child comments.
65
78
  def num_children
66
79
  Lib.comment_get_num_children(@comment)
67
80
  end
68
-
81
+
82
+ # Get a specific child comment by index.
83
+ # @parameter n [Integer] The child index (defaults to 0).
84
+ # @returns [Comment] The child comment at the specified index.
69
85
  def child(n = 0)
70
86
  Comment.build_from Lib.comment_get_child(@comment, n)
71
87
  end
72
-
88
+
89
+ # Get all child comments.
90
+ # @returns [Array<Comment>] An array of all child comments.
73
91
  def children
74
- num_children.times.map { |i| child(i) }
92
+ num_children.times.map {|i| child(i)}
75
93
  end
76
-
94
+
95
+ # Check if this comment is whitespace only.
96
+ # @returns [Boolean] True if the comment contains only whitespace.
77
97
  def whitespace?
78
98
  Lib.comment_is_whitespace(@comment) != 0
79
99
  end
80
-
100
+
101
+ # Check if this comment has a trailing newline.
102
+ # @returns [Boolean] True if the comment has a trailing newline.
81
103
  def has_trailing_newline?
82
104
  Lib.inline_content_comment_has_trailing_newline(@comment) != 0
83
105
  end
84
-
106
+
107
+ # Iterate over all child comments.
108
+ # @yields {|comment| ...} Yields each child comment.
109
+ # @parameter comment [Comment] The child comment.
85
110
  def each(&block)
86
111
  num_children.times.map do |i|
87
112
  block.call(child(i))
88
113
  end
89
114
  end
90
-
91
115
  end
92
-
116
+
117
+ # Represents an HTML tag in a documentation comment.
93
118
  class HTMLTagComment < Comment
119
+ # Get the name of the HTML tag.
120
+ # @returns [String] The HTML tag name.
94
121
  def name
95
122
  Lib.extract_string Lib.html_tag_comment_get_tag_name(@comment)
96
123
  end
97
124
  alias_method :tag, :name
98
-
125
+
126
+ # Get the text representation of this HTML tag.
127
+ # @returns [String] The HTML tag as a string.
99
128
  def text
100
129
  Lib.extract_string Lib.html_tag_comment_get_as_string(@comment)
101
130
  end
102
131
  end
103
-
132
+
133
+ # Represents an HTML start tag in a documentation comment.
104
134
  class HTMLStartTagComment < HTMLTagComment
135
+ # Check if this is a self-closing tag.
136
+ # @returns [Boolean] True if the tag is self-closing (e.g., <br/>).
105
137
  def self_closing?
106
138
  Lib.html_start_tag_comment_is_self_closing(@comment) != 0
107
139
  end
108
-
140
+
141
+ # Get the number of attributes on this tag.
142
+ # @returns [Integer] The number of attributes.
109
143
  def num_attrs
110
144
  Lib.html_start_tag_comment_get_num_attrs(@comment)
111
145
  end
112
-
146
+
147
+ # Get all attributes on this tag.
148
+ # @returns [Array<Hash>] An array of hashes with :name and :value keys.
113
149
  def attrs
114
- num_attrs.times.map { |i|
150
+ num_attrs.times.map {|i|
115
151
  {
116
152
  name: Lib.extract_string(Lib.html_start_tag_comment_get_attr_name(@comment, i)),
117
- value: Lib.extract_string(Lib.html_start_tag_comment_get_attr_value(@comment, i)),
153
+ value: Lib.extract_string(Lib.html_start_tag_comment_get_attr_value(@comment, i)),
118
154
  }
119
- }
155
+ }
120
156
  end
121
157
  end
122
-
158
+
159
+ # Represents an HTML end tag in a documentation comment.
123
160
  class HTMLEndTagComment < HTMLTagComment
124
161
  end
125
-
162
+
163
+ # Represents a paragraph comment containing text and inline content.
126
164
  class ParagraphComment < Comment
165
+ # Get the text content by joining all child text with newlines.
166
+ # @returns [String] The paragraph text content.
127
167
  def text
128
168
  self.map(&:text).join("\n")
129
169
  end
130
170
  end
131
-
171
+
172
+ # Represents a plain text comment.
132
173
  class TextComment < Comment
174
+ # Get the text content of this comment.
175
+ # @returns [String] The text content.
133
176
  def text
134
177
  Lib.extract_string Lib.text_comment_get_text(@comment)
135
178
  end
136
179
  end
137
-
180
+
181
+ # Represents an inline command comment (e.g., \c, \p).
138
182
  class InlineCommandComment < Comment
183
+ # Get the command name.
184
+ # @returns [String] The inline command name (e.g., "c", "p").
139
185
  def name
140
186
  Lib.extract_string Lib.inline_command_comment_get_command_name(@comment)
141
187
  end
142
-
188
+
189
+ # Get the render kind for this inline command.
190
+ # @returns [Symbol] The render kind.
143
191
  def render_kind
144
192
  Lib.inline_command_comment_get_render_kind(@comment)
145
193
  end
146
-
194
+
195
+ # Get the number of arguments to this command.
196
+ # @returns [Integer] The number of arguments.
147
197
  def num_args
148
198
  Lib.inline_command_comment_get_num_args(@comment)
149
199
  end
150
-
200
+
201
+ # Get all arguments to this command.
202
+ # @returns [Array<String>] An array of argument strings.
151
203
  def args
152
- num_args.times.map { |i|
204
+ num_args.times.map {|i|
153
205
  Lib.extract_string Lib.inline_command_comment_get_arg_text(@comment, i)
154
206
  }
155
207
  end
156
-
208
+
209
+ # Get the text by joining all arguments.
210
+ # @returns [String] The joined argument text.
157
211
  def text
158
212
  args.join
159
213
  end
160
214
  end
161
-
215
+
216
+ # Represents a block command comment (e.g., \brief, \return).
162
217
  class BlockCommandComment < Comment
218
+ # Get the command name.
219
+ # @returns [String] The block command name (e.g., "brief", "return").
163
220
  def name
164
221
  Lib.extract_string Lib.block_command_comment_get_command_name(@comment)
165
222
  end
166
-
223
+
224
+ # Get the paragraph comment associated with this block command.
225
+ # @returns [Comment] The paragraph comment.
167
226
  def paragraph
168
227
  Comment.build_from Lib.block_command_comment_get_paragraph(@comment)
169
228
  end
170
-
229
+
230
+ # Get the text content from the paragraph.
231
+ # @returns [String] The text content.
171
232
  def text
172
233
  self.paragraph.text
173
234
  end
174
235
  alias_method :comment, :text
175
-
236
+
237
+ # Get the number of arguments to this command.
238
+ # @returns [Integer] The number of arguments.
176
239
  def num_args
177
240
  Lib.block_command_comment_get_num_args(@comment)
178
241
  end
179
-
242
+
243
+ # Get all arguments to this command.
244
+ # @returns [Array<String>] An array of argument strings.
180
245
  def args
181
- num_args.times.map { |i|
246
+ num_args.times.map {|i|
182
247
  Lib.extract_string Lib.block_command_comment_get_arg_text(@comment, i)
183
248
  }
184
249
  end
185
250
  end
186
-
251
+
252
+ # Represents a parameter documentation command (e.g., \param, \arg).
187
253
  class ParamCommandComment < Comment
254
+ # Get the parameter name being documented.
255
+ # @returns [String] The parameter name.
188
256
  def name
189
257
  Lib.extract_string Lib.param_command_comment_get_param_name(@comment)
190
258
  end
191
-
259
+
260
+ # Get the documentation text for this parameter.
261
+ # @returns [String] The parameter documentation text.
192
262
  def text
193
263
  self.map(&:text).join("")
194
264
  end
195
-
265
+
196
266
  alias_method :comment, :text
197
-
267
+
268
+ # Check if the parameter index is valid.
269
+ # @returns [Boolean] True if the parameter index is valid.
198
270
  def valid_index?
199
271
  Lib.param_command_comment_is_param_index_valid(@comment) != 0
200
272
  end
201
-
273
+
274
+ # Get the parameter index in the function signature.
275
+ # @returns [Integer] The zero-based parameter index.
202
276
  def index
203
277
  Lib.param_command_comment_get_param_index(@comment)
204
278
  end
205
-
279
+
280
+ # Check if the parameter direction is explicitly specified.
281
+ # @returns [Boolean] True if the direction is explicit (e.g., [in], [out]).
206
282
  def direction_explicit?
207
283
  Lib.param_command_comment_is_direction_explicit(@comment) != 0
208
284
  end
209
-
285
+
286
+ # Get the parameter direction.
287
+ # @returns [Symbol] The direction (:in, :out, or :in_out).
210
288
  def direction
211
289
  Lib.param_command_comment_get_direction(@comment)
212
290
  end
213
291
  end
214
-
292
+
293
+ # Represents a template parameter documentation command (e.g., \tparam).
215
294
  class TParamCommandComment < Comment
295
+ # Get the documentation text for this template parameter.
296
+ # @returns [String] The template parameter documentation text.
216
297
  def text
217
298
  self.child.text
218
299
  end
219
300
  alias_method :comment, :text
220
-
301
+
302
+ # Get the template parameter name being documented.
303
+ # @returns [String] The template parameter name.
221
304
  def name
222
305
  Lib.extract_string Lib.tparam_command_comment_get_param_name(@comment)
223
306
  end
224
-
307
+
308
+ # Check if the parameter position is valid.
309
+ # @returns [Boolean] True if the position is valid in the template parameter list.
225
310
  def valid_position?
226
311
  Lib.tparam_command_comment_is_param_position_valid(@comment) != 0
227
312
  end
228
-
313
+
314
+ # Get the nesting depth of this template parameter.
315
+ # @returns [Integer] The nesting depth.
229
316
  def depth
230
317
  Lib.tparam_command_comment_get_depth(@comment)
231
318
  end
232
-
319
+
320
+ # Get the index of this template parameter at the specified depth.
321
+ # @parameter depth [Integer] The nesting depth (defaults to 0).
322
+ # @returns [Integer] The index at the specified depth.
233
323
  def index(depth = 0)
234
324
  Lib.tparam_command_comment_get_index(@comment, depth)
235
325
  end
236
326
  end
237
-
327
+
328
+ # Represents a verbatim block command comment (e.g., \code, \verbatim).
238
329
  class VerbatimBlockCommandComment < Comment
330
+ # Get the text by joining all child lines with newlines.
331
+ # @returns [String] The verbatim block text.
239
332
  def text
240
333
  children.map(&:text).join("\n")
241
334
  end
242
335
  end
243
-
336
+
337
+ # Represents a line within a verbatim block comment.
244
338
  class VerbatimBlockLineComment < Comment
339
+ # Get the text of this line.
340
+ # @returns [String] The line text.
245
341
  def text
246
342
  Lib.extract_string Lib.verbatim_block_line_comment_get_text(@comment)
247
343
  end
248
344
  end
249
-
345
+
346
+ # Represents a verbatim line comment (e.g., \code on a single line).
250
347
  class VerbatimLine < Comment
348
+ # Get the text of this verbatim line.
349
+ # @returns [String] The verbatim line text.
251
350
  def text
252
351
  Lib.extract_string Lib.verbatim_line_comment_get_text(@comment)
253
352
  end
254
353
  end
255
-
354
+
355
+ # Represents a complete documentation comment with all its components.
356
+ # This is the top-level comment structure that can be converted to HTML or XML.
256
357
  class FullComment < Comment
358
+ # Convert this documentation comment to HTML.
359
+ # @returns [String] The HTML representation of the comment.
257
360
  def to_html
258
361
  Lib.extract_string Lib.full_comment_get_as_html(@comment)
259
362
  end
260
-
363
+
364
+ # Convert this documentation comment to XML.
365
+ # @returns [String] The XML representation of the comment.
261
366
  def to_xml
262
367
  Lib.extract_string Lib.full_comment_get_as_xml(@comment)
263
368
  end
264
369
 
370
+ # Get the text by collecting and joining all child text.
371
+ # @returns [String] The combined text content with newlines.
265
372
  def text
266
373
  self.children.collect{|child| child.text.strip}.join("\n")
267
374
  end
@@ -2,15 +2,20 @@
2
2
 
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2014, by Masahiro Sano.
5
- # Copyright, 2014-2022, by Samuel Williams.
5
+ # Copyright, 2014-2025, by Samuel Williams.
6
6
 
7
- require_relative 'lib/compilation_database'
7
+ require_relative "lib/compilation_database"
8
8
 
9
9
  module FFI
10
10
  module Clang
11
+ # Represents a compilation database for a project.
11
12
  class CompilationDatabase < AutoPointer
13
+ # Represents an error loading the compilation database.
12
14
  class DatabaseLoadError < FFI::Clang::Error; end
13
-
15
+
16
+ # Initialize a compilation database from a directory.
17
+ # @parameter dirpath [String] The directory path containing the compilation database.
18
+ # @raises [DatabaseLoadError] If the database cannot be loaded.
14
19
  def initialize(dirpath)
15
20
  uint_ptr = MemoryPointer.new :uint
16
21
  cdb_ptr = Lib.compilation_database_from_directory(dirpath, uint_ptr)
@@ -20,88 +25,137 @@ module FFI
20
25
  end
21
26
  super cdb_ptr
22
27
  end
23
-
28
+
29
+ # Release the compilation database pointer.
30
+ # @parameter pointer [FFI::Pointer] The pointer to release.
24
31
  def self.release(pointer)
25
32
  Lib.compilation_database_dispose(pointer)
26
33
  end
27
-
34
+
35
+ # Get compile commands for a specific file.
36
+ # @parameter filename [String] The filename to get commands for.
37
+ # @returns [CompileCommands] The compile commands for the file.
28
38
  def compile_commands(filename)
29
39
  CompileCommands.new Lib.compilation_database_get_compile_commands(self, filename), self
30
40
  end
31
-
41
+
42
+ # Get all compile commands in the database.
43
+ # @returns [CompileCommands] All compile commands.
32
44
  def all_compile_commands
33
45
  CompileCommands.new Lib.compilation_database_get_all_compile_commands(self), self
34
46
  end
35
-
47
+
48
+ # Represents a collection of compile commands.
36
49
  class CompileCommands < AutoPointer
37
50
  include Enumerable
38
-
51
+
52
+ # Initialize compile commands.
53
+ # @parameter pointer [FFI::Pointer] The commands pointer.
54
+ # @parameter database [CompilationDatabase] The parent database.
39
55
  def initialize(pointer, database)
40
56
  super pointer
41
57
  @database = database
42
58
  end
43
-
59
+
60
+ # Release the compile commands pointer.
61
+ # @parameter pointer [FFI::Pointer] The pointer to release.
44
62
  def self.release(pointer)
45
63
  Lib.compile_commands_dispose(pointer)
46
64
  end
47
-
65
+
66
+ # Get the number of compile commands.
67
+ # @returns [Integer] The number of commands.
48
68
  def size
49
69
  Lib.compile_commands_get_size(self)
50
70
  end
51
-
71
+
72
+ # Get a compile command by index.
73
+ # @parameter i [Integer] The command index.
74
+ # @returns [CompileCommand] The compile command.
52
75
  def command(i)
53
76
  CompileCommand.new Lib.compile_commands_get_command(self, i)
54
77
  end
55
-
78
+
79
+ # Get all compile commands.
80
+ # @returns [Array(CompileCommand)] Array of compile commands.
56
81
  def commands
57
- size.times.map { |i| command(i) }
82
+ size.times.map {|i| command(i)}
58
83
  end
59
-
84
+
85
+ # Iterate over each compile command.
86
+ # @yields {|command| ...} Each compile command.
87
+ # @parameter command [CompileCommand] The compile command.
60
88
  def each(&block)
61
89
  size.times.map do |i|
62
90
  block.call(command(i))
63
91
  end
64
92
  end
65
93
  end
66
-
94
+
95
+ # Represents a single compile command.
67
96
  class CompileCommand
97
+ # Initialize a compile command.
98
+ # @parameter pointer [FFI::Pointer] The command pointer.
68
99
  def initialize(pointer)
69
100
  @pointer = pointer
70
101
  end
71
-
102
+
103
+ # Get the working directory for the command.
104
+ # @returns [String] The directory path.
72
105
  def directory
73
106
  Lib.extract_string Lib.compile_command_get_directory(@pointer)
74
107
  end
75
-
108
+
109
+ # Get the number of arguments.
110
+ # @returns [Integer] The number of arguments.
76
111
  def num_args
77
112
  Lib.compile_command_get_num_args(@pointer)
78
113
  end
79
-
114
+
115
+ # Get an argument by index.
116
+ # @parameter i [Integer] The argument index.
117
+ # @returns [String] The argument.
80
118
  def arg(i)
81
119
  Lib.extract_string Lib.compile_command_get_arg(@pointer, i)
82
120
  end
83
-
121
+
122
+ # Get all arguments.
123
+ # @returns [Array(String)] Array of arguments.
84
124
  def args
85
- num_args.times.map { |i| arg(i) }
125
+ num_args.times.map {|i| arg(i)}
86
126
  end
87
-
127
+
128
+ # Get the number of mapped sources.
129
+ # @returns [Integer] The number of mapped sources.
130
+ # @raises [NotImplementedError] This method is not yet implemented.
88
131
  def num_mapped_sources
89
132
  raise NotImplementedError
90
133
  # Lib.compile_command_get_num_mapped_sources(@pointer)
91
134
  end
92
-
135
+
136
+ # Get a mapped source path by index.
137
+ # @parameter i [Integer] The source index.
138
+ # @returns [String] The mapped source path.
139
+ # @raises [NotImplementedError] This method is not yet implemented.
93
140
  def mapped_source_path(i)
94
141
  raise NotImplementedError
95
142
  # Lib.extract_string Lib.compile_command_get_mapped_source_path(@pointer, i)
96
143
  end
97
-
144
+
145
+ # Get mapped source content by index.
146
+ # @parameter i [Integer] The source index.
147
+ # @returns [String] The mapped source content.
148
+ # @raises [NotImplementedError] This method is not yet implemented.
98
149
  def mapped_source_content(i)
99
150
  raise NotImplementedError
100
151
  # Lib.extract_string Lib.compile_command_get_mapped_source_content(@pointer, i)
101
152
  end
102
-
153
+
154
+ # Get all mapped sources.
155
+ # @returns [Array(Hash)] Array of hashes with `:path` and `:content` keys.
156
+ # @raises [NotImplementedError] This method is not yet implemented.
103
157
  def mapped_sources
104
- num_mapped_sources.times.map { |i|
158
+ num_mapped_sources.times.map {|i|
105
159
  {path: mapped_source_path(i), content: mapped_source_content(i)}
106
160
  }
107
161
  end