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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/ext/rakefile.rb +2 -2
- data/lib/ffi/clang/clang_version.rb +7 -3
- data/lib/ffi/clang/code_completion.rb +121 -44
- data/lib/ffi/clang/comment.rb +164 -57
- data/lib/ffi/clang/compilation_database.rb +79 -25
- data/lib/ffi/clang/cursor.rb +395 -149
- data/lib/ffi/clang/diagnostic.rb +57 -23
- data/lib/ffi/clang/error.rb +12 -0
- data/lib/ffi/clang/file.rb +30 -11
- data/lib/ffi/clang/index.rb +37 -13
- data/lib/ffi/clang/lib/clang_version.rb +2 -2
- data/lib/ffi/clang/lib/code_completion.rb +15 -11
- data/lib/ffi/clang/lib/comment.rb +16 -14
- data/lib/ffi/clang/lib/compilation_database.rb +5 -5
- data/lib/ffi/clang/lib/cursor.rb +74 -56
- data/lib/ffi/clang/lib/diagnostic.rb +14 -14
- data/lib/ffi/clang/lib/file.rb +10 -6
- data/lib/ffi/clang/lib/inclusions.rb +3 -3
- data/lib/ffi/clang/lib/index.rb +7 -5
- data/lib/ffi/clang/lib/printing_policy.rb +36 -36
- data/lib/ffi/clang/lib/source_location.rb +9 -7
- data/lib/ffi/clang/lib/source_range.rb +5 -3
- data/lib/ffi/clang/lib/string.rb +9 -4
- data/lib/ffi/clang/lib/token.rb +17 -4
- data/lib/ffi/clang/lib/translation_unit.rb +17 -13
- data/lib/ffi/clang/lib/type.rb +19 -17
- data/lib/ffi/clang/lib.rb +35 -19
- data/lib/ffi/clang/platform.rb +25 -0
- data/lib/ffi/clang/printing_policy.rb +31 -18
- data/lib/ffi/clang/source_location.rb +119 -36
- data/lib/ffi/clang/source_range.rb +30 -12
- data/lib/ffi/clang/token.rb +48 -23
- data/lib/ffi/clang/translation_unit.rb +97 -33
- data/lib/ffi/clang/types/array.rb +15 -1
- data/lib/ffi/clang/types/elaborated.rb +19 -4
- data/lib/ffi/clang/types/function.rb +35 -10
- data/lib/ffi/clang/types/pointer.rb +23 -7
- data/lib/ffi/clang/types/record.rb +23 -8
- data/lib/ffi/clang/types/type.rb +80 -36
- data/lib/ffi/clang/types/type_def.rb +14 -2
- data/lib/ffi/clang/types/vector.rb +13 -1
- data/lib/ffi/clang/unsaved_file.rb +18 -8
- data/lib/ffi/clang/version.rb +4 -2
- data/lib/ffi/clang.rb +23 -45
- data/license.md +3 -2
- data/readme.md +12 -13
- data/releases.md +5 -0
- data.tar.gz.sig +0 -0
- metadata +10 -5
- metadata.gz.sig +0 -0
data/lib/ffi/clang/cursor.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Released under the MIT License.
|
|
4
4
|
# Copyright, 2013, by Garry Marshall.
|
|
5
|
-
# Copyright, 2013-
|
|
5
|
+
# Copyright, 2013-2025, by Samuel Williams.
|
|
6
6
|
# Copyright, 2013, by Carlos Martín Nieto.
|
|
7
7
|
# Copyright, 2013, by Dave Wilkinson.
|
|
8
8
|
# Copyright, 2013, by Takeshi Watanabe.
|
|
@@ -11,139 +11,216 @@
|
|
|
11
11
|
# Copyright, 2014, by Niklas Therning.
|
|
12
12
|
# Copyright, 2019, by Michael Metivier.
|
|
13
13
|
# Copyright, 2022, by Motonori Iwamuro.
|
|
14
|
-
# Copyright, 2023-
|
|
14
|
+
# Copyright, 2023-2025, by Charlie Savage.
|
|
15
15
|
|
|
16
|
-
require_relative
|
|
17
|
-
require_relative
|
|
16
|
+
require_relative "lib/cursor"
|
|
17
|
+
require_relative "lib/code_completion"
|
|
18
18
|
|
|
19
|
-
require_relative
|
|
20
|
-
require_relative
|
|
21
|
-
require_relative
|
|
22
|
-
require_relative
|
|
19
|
+
require_relative "printing_policy"
|
|
20
|
+
require_relative "source_location"
|
|
21
|
+
require_relative "source_range"
|
|
22
|
+
require_relative "comment"
|
|
23
23
|
|
|
24
24
|
module FFI
|
|
25
25
|
module Clang
|
|
26
|
+
# Represents a cursor in the abstract syntax tree (AST).
|
|
26
27
|
class Cursor
|
|
27
28
|
include Enumerable
|
|
28
|
-
|
|
29
|
+
|
|
30
|
+
# @attribute [FFI::Lib::CXCursor] The underlying libclang cursor structure.
|
|
29
31
|
attr_reader :cursor
|
|
32
|
+
|
|
33
|
+
# @attribute [TranslationUnit] The translation unit this cursor belongs to.
|
|
30
34
|
attr_reader :translation_unit
|
|
31
|
-
|
|
35
|
+
|
|
36
|
+
# Get a null cursor.
|
|
37
|
+
# @returns [Cursor] A null cursor instance.
|
|
32
38
|
def self.null_cursor
|
|
33
39
|
Cursor.new Lib.get_null_cursor, nil
|
|
34
40
|
end
|
|
35
|
-
|
|
36
|
-
#
|
|
41
|
+
|
|
42
|
+
# Get the spelling of a cursor kind.
|
|
43
|
+
# @parameter kind [Symbol] The cursor kind.
|
|
44
|
+
# @returns [String] The string representation of the cursor kind.
|
|
37
45
|
def self.kind_spelling(kind)
|
|
38
46
|
Lib.extract_string Lib.get_cursor_kind_spelling(kind)
|
|
39
47
|
end
|
|
40
|
-
|
|
48
|
+
|
|
49
|
+
# Initialize a cursor with a libclang cursor structure.
|
|
50
|
+
# @parameter cxcursor [Lib::CXCursor] The libclang cursor.
|
|
51
|
+
# @parameter translation_unit [TranslationUnit] The parent translation unit.
|
|
41
52
|
def initialize(cxcursor, translation_unit)
|
|
42
53
|
@cursor = cxcursor
|
|
43
54
|
@translation_unit = translation_unit
|
|
44
55
|
end
|
|
45
|
-
|
|
56
|
+
|
|
57
|
+
# Check if this cursor is null.
|
|
58
|
+
# @returns [Boolean] True if the cursor is null.
|
|
46
59
|
def null?
|
|
47
60
|
Lib.cursor_is_null(@cursor) != 0
|
|
48
61
|
end
|
|
49
|
-
|
|
62
|
+
|
|
63
|
+
# Get the raw comment text associated with this cursor.
|
|
64
|
+
# @returns [String] The raw comment text.
|
|
50
65
|
def raw_comment_text
|
|
51
66
|
Lib.extract_string Lib.cursor_get_raw_comment_text(@cursor)
|
|
52
67
|
end
|
|
53
|
-
|
|
68
|
+
|
|
69
|
+
# Get the parsed comment associated with this cursor.
|
|
70
|
+
# @returns [Comment] The parsed comment structure.
|
|
54
71
|
def comment
|
|
55
72
|
Comment.build_from Lib.cursor_get_parsed_comment(@cursor)
|
|
56
73
|
end
|
|
57
|
-
|
|
74
|
+
|
|
75
|
+
# Get the source range of the comment.
|
|
76
|
+
# @returns [SourceRange] The comment source range.
|
|
58
77
|
def comment_range
|
|
59
78
|
SourceRange.new(Lib.cursor_get_comment_range(@cursor))
|
|
60
79
|
end
|
|
61
|
-
|
|
80
|
+
|
|
81
|
+
# Get the code completion string for this cursor.
|
|
82
|
+
# @returns [CodeCompletion::String] The completion string.
|
|
62
83
|
def completion
|
|
63
84
|
CodeCompletion::String.new Lib.get_cursor_completion_string(@cursor)
|
|
64
85
|
end
|
|
65
|
-
|
|
86
|
+
|
|
87
|
+
# Check if this cursor is anonymous.
|
|
88
|
+
# @returns [Boolean] True if the cursor is anonymous.
|
|
66
89
|
def anonymous?
|
|
67
90
|
Lib.cursor_is_anonymous(@cursor) != 0
|
|
68
91
|
end
|
|
69
|
-
|
|
92
|
+
|
|
93
|
+
# Check if this cursor is an anonymous record declaration.
|
|
94
|
+
# @returns [Boolean] True if it's an anonymous record declaration.
|
|
70
95
|
def anonymous_record_declaration?
|
|
71
96
|
Lib.cursor_is_anonymous_record_decl(@cursor) != 0
|
|
72
97
|
end
|
|
73
|
-
|
|
98
|
+
|
|
99
|
+
# Check if this cursor is a declaration.
|
|
100
|
+
# @returns [Boolean] True if it's a declaration.
|
|
74
101
|
def declaration?
|
|
75
102
|
Lib.is_declaration(kind) != 0
|
|
76
103
|
end
|
|
77
|
-
|
|
104
|
+
|
|
105
|
+
# Check if this cursor is a reference.
|
|
106
|
+
# @returns [Boolean] True if it's a reference.
|
|
78
107
|
def reference?
|
|
79
108
|
Lib.is_reference(kind) != 0
|
|
80
109
|
end
|
|
81
|
-
|
|
110
|
+
|
|
111
|
+
# Check if this cursor is an expression.
|
|
112
|
+
# @returns [Boolean] True if it's an expression.
|
|
82
113
|
def expression?
|
|
83
114
|
Lib.is_expression(kind) != 0
|
|
84
115
|
end
|
|
85
|
-
|
|
116
|
+
|
|
117
|
+
# Check if this cursor is a statement.
|
|
118
|
+
# @returns [Boolean] True if it's a statement.
|
|
86
119
|
def statement?
|
|
87
120
|
Lib.is_statement(kind) != 0
|
|
88
121
|
end
|
|
89
|
-
|
|
122
|
+
|
|
123
|
+
# Check if this cursor is an attribute.
|
|
124
|
+
# @returns [Boolean] True if it's an attribute.
|
|
90
125
|
def attribute?
|
|
91
126
|
Lib.is_attribute(kind) != 0
|
|
92
127
|
end
|
|
93
|
-
|
|
128
|
+
|
|
129
|
+
# Check if this cursor has public access.
|
|
130
|
+
# @returns [Boolean] True if the cursor is public.
|
|
94
131
|
def public?
|
|
95
132
|
Lib.cxx_get_access_specifier(@cursor) == :public
|
|
96
133
|
end
|
|
97
|
-
|
|
134
|
+
|
|
135
|
+
# Check if this cursor has private access.
|
|
136
|
+
# @returns [Boolean] True if the cursor is private.
|
|
98
137
|
def private?
|
|
99
138
|
Lib.cxx_get_access_specifier(@cursor) == :private
|
|
100
139
|
end
|
|
101
|
-
|
|
140
|
+
|
|
141
|
+
# Check if this cursor has protected access.
|
|
142
|
+
# @returns [Boolean] True if the cursor is protected.
|
|
102
143
|
def protected?
|
|
103
144
|
Lib.cxx_get_access_specifier(@cursor) == :protected
|
|
104
145
|
end
|
|
105
|
-
|
|
146
|
+
|
|
147
|
+
# Check if this cursor is invalid.
|
|
148
|
+
# @returns [Boolean] True if the cursor is invalid.
|
|
106
149
|
def invalid?
|
|
107
150
|
Lib.is_invalid(kind) != 0
|
|
108
151
|
end
|
|
109
|
-
|
|
152
|
+
|
|
153
|
+
# Check if this cursor is a translation unit.
|
|
154
|
+
# @returns [Boolean] True if it's a translation unit.
|
|
110
155
|
def translation_unit?
|
|
111
156
|
Lib.is_translation_unit(kind) != 0
|
|
112
157
|
end
|
|
113
|
-
|
|
158
|
+
|
|
159
|
+
# Check if this cursor is a preprocessing directive.
|
|
160
|
+
# @returns [Boolean] True if it's a preprocessing directive.
|
|
114
161
|
def preprocessing?
|
|
115
162
|
Lib.is_preprocessing(kind) != 0
|
|
116
163
|
end
|
|
117
|
-
|
|
164
|
+
|
|
165
|
+
# Check if this cursor is unexposed.
|
|
166
|
+
# @returns [Boolean] True if the cursor is unexposed.
|
|
118
167
|
def unexposed?
|
|
119
168
|
Lib.is_unexposed(kind) != 0
|
|
120
169
|
end
|
|
121
|
-
|
|
170
|
+
|
|
171
|
+
# Get the expansion location of this cursor.
|
|
172
|
+
# @returns [ExpansionLocation] The expansion location.
|
|
122
173
|
def expansion_location
|
|
123
174
|
ExpansionLocation.new(Lib.get_cursor_location(@cursor))
|
|
124
175
|
end
|
|
125
176
|
alias :location :expansion_location
|
|
126
|
-
|
|
177
|
+
|
|
178
|
+
# Get the presumed location of this cursor.
|
|
179
|
+
# @returns [PresumedLocation] The presumed location.
|
|
127
180
|
def presumed_location
|
|
128
181
|
PresumedLocation.new(Lib.get_cursor_location(@cursor))
|
|
129
182
|
end
|
|
130
|
-
|
|
183
|
+
|
|
184
|
+
# Get the spelling location of this cursor.
|
|
185
|
+
# @returns [SpellingLocation] The spelling location.
|
|
131
186
|
def spelling_location
|
|
132
187
|
SpellingLocation.new(Lib.get_cursor_location(@cursor))
|
|
133
188
|
end
|
|
134
|
-
|
|
189
|
+
|
|
190
|
+
# Get the file location of this cursor.
|
|
191
|
+
# @returns [FileLocation] The file location.
|
|
135
192
|
def file_location
|
|
136
193
|
FileLocation.new(Lib.get_cursor_location(@cursor))
|
|
137
194
|
end
|
|
138
|
-
|
|
195
|
+
|
|
196
|
+
# Get the source extent of this cursor.
|
|
197
|
+
# @returns [SourceRange] The source extent.
|
|
139
198
|
def extent
|
|
140
199
|
SourceRange.new(Lib.get_cursor_extent(@cursor))
|
|
141
200
|
end
|
|
142
|
-
|
|
201
|
+
|
|
202
|
+
# Get the display name of this cursor.
|
|
203
|
+
# @returns [String] The display name.
|
|
143
204
|
def display_name
|
|
144
205
|
Lib.extract_string Lib.get_cursor_display_name(@cursor)
|
|
145
206
|
end
|
|
146
|
-
|
|
207
|
+
|
|
208
|
+
# Get the qualified display name including parent scope.
|
|
209
|
+
# @returns [String | Nil] The qualified display name, or `nil` for translation units.
|
|
210
|
+
# @raises [ArgumentError] If the semantic parent is invalid.
|
|
211
|
+
def qualified_display_name
|
|
212
|
+
if self.kind != :cursor_translation_unit
|
|
213
|
+
if self.semantic_parent.kind == :cursor_invalid_file
|
|
214
|
+
raise(ArgumentError, "Invalid semantic parent: #{self}")
|
|
215
|
+
end
|
|
216
|
+
result = self.semantic_parent.qualified_display_name
|
|
217
|
+
result ? "#{result}::#{self.display_name}" : self.display_name
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Get the fully qualified name of this cursor.
|
|
222
|
+
# @returns [String | Nil] The qualified name, or `nil` for translation units.
|
|
223
|
+
# @raises [ArgumentError] If the semantic parent is invalid.
|
|
147
224
|
def qualified_name
|
|
148
225
|
if self.kind != :cursor_translation_unit
|
|
149
226
|
if self.semantic_parent.kind == :cursor_invalid_file
|
|
@@ -153,96 +230,142 @@ module FFI
|
|
|
153
230
|
result ? "#{result}::#{self.spelling}" : self.spelling
|
|
154
231
|
end
|
|
155
232
|
end
|
|
156
|
-
|
|
233
|
+
|
|
234
|
+
# Get the spelling (name) of this cursor.
|
|
235
|
+
# @returns [String] The cursor spelling.
|
|
157
236
|
def spelling
|
|
158
237
|
Lib.extract_string Lib.get_cursor_spelling(@cursor)
|
|
159
238
|
end
|
|
160
|
-
|
|
239
|
+
|
|
240
|
+
# Get the printing policy for this cursor.
|
|
241
|
+
# @returns [PrintingPolicy] The printing policy.
|
|
161
242
|
def printing_policy
|
|
162
243
|
PrintingPolicy.new(cursor)
|
|
163
244
|
end
|
|
164
|
-
|
|
245
|
+
|
|
246
|
+
# Get the Unified Symbol Resolution (USR) for this cursor.
|
|
247
|
+
# @returns [String] The USR string.
|
|
165
248
|
def usr
|
|
166
249
|
Lib.extract_string Lib.get_cursor_usr(@cursor)
|
|
167
250
|
end
|
|
168
|
-
|
|
251
|
+
|
|
252
|
+
# Get the kind of this cursor.
|
|
253
|
+
# @returns [Symbol | Nil] The cursor kind.
|
|
169
254
|
def kind
|
|
170
255
|
@cursor ? @cursor[:kind] : nil
|
|
171
256
|
end
|
|
172
|
-
|
|
257
|
+
|
|
258
|
+
# Get the spelling of the cursor kind.
|
|
259
|
+
# @returns [String] The cursor kind spelling.
|
|
173
260
|
def kind_spelling
|
|
174
261
|
Cursor.kind_spelling @cursor[:kind]
|
|
175
262
|
end
|
|
176
|
-
|
|
263
|
+
|
|
264
|
+
# Get the type of this cursor.
|
|
265
|
+
# @returns [Types::Type] The cursor type.
|
|
177
266
|
def type
|
|
178
267
|
Types::Type.create Lib.get_cursor_type(@cursor), @translation_unit
|
|
179
268
|
end
|
|
180
|
-
|
|
269
|
+
|
|
270
|
+
# Get the result type for a function cursor.
|
|
271
|
+
# @returns [Types::Type] The result type.
|
|
181
272
|
def result_type
|
|
182
273
|
Types::Type.create Lib.get_cursor_result_type(@cursor), @translation_unit
|
|
183
274
|
end
|
|
184
|
-
|
|
275
|
+
|
|
276
|
+
# Get the underlying type for a typedef cursor.
|
|
277
|
+
# @returns [Types::Type] The underlying type.
|
|
185
278
|
def underlying_type
|
|
186
279
|
Types::Type.create Lib.get_typedef_decl_underlying_type(@cursor), @translation_unit
|
|
187
280
|
end
|
|
188
|
-
|
|
281
|
+
|
|
282
|
+
# Check if this cursor is a virtual base class.
|
|
283
|
+
# @returns [Boolean] True if it's a virtual base.
|
|
189
284
|
def virtual_base?
|
|
190
285
|
Lib.is_virtual_base(@cursor) != 0
|
|
191
286
|
end
|
|
192
|
-
|
|
287
|
+
|
|
288
|
+
# Check if this cursor is a dynamic call.
|
|
289
|
+
# @returns [Boolean] True if it's a dynamic call.
|
|
193
290
|
def dynamic_call?
|
|
194
291
|
Lib.is_dynamic_call(@cursor) != 0
|
|
195
292
|
end
|
|
196
|
-
|
|
293
|
+
|
|
294
|
+
# Check if this cursor is variadic.
|
|
295
|
+
# @returns [Boolean] True if the cursor is variadic.
|
|
197
296
|
def variadic?
|
|
198
297
|
Lib.is_variadic(@cursor) != 0
|
|
199
298
|
end
|
|
200
|
-
|
|
299
|
+
|
|
300
|
+
# Check if this cursor is a definition.
|
|
301
|
+
# @returns [Boolean] True if the cursor is a definition.
|
|
201
302
|
def definition?
|
|
202
303
|
Lib.is_definition(@cursor) != 0
|
|
203
304
|
end
|
|
204
|
-
|
|
305
|
+
|
|
306
|
+
# Check if this is a static method.
|
|
307
|
+
# @returns [Boolean] True if the method is static.
|
|
205
308
|
def static?
|
|
206
309
|
Lib.cxx_method_is_static(@cursor) != 0
|
|
207
310
|
end
|
|
208
|
-
|
|
311
|
+
|
|
312
|
+
# Check if this is a virtual method.
|
|
313
|
+
# @returns [Boolean] True if the method is virtual.
|
|
209
314
|
def virtual?
|
|
210
315
|
Lib.cxx_method_is_virtual(@cursor) != 0
|
|
211
316
|
end
|
|
212
|
-
|
|
317
|
+
|
|
318
|
+
# Check if this is a pure virtual method.
|
|
319
|
+
# @returns [Boolean] True if the method is pure virtual.
|
|
213
320
|
def pure_virtual?
|
|
214
321
|
Lib.cxx_method_is_pure_virtual(@cursor) != 0
|
|
215
322
|
end
|
|
216
|
-
|
|
323
|
+
|
|
324
|
+
# Get the value of an enum constant.
|
|
325
|
+
# @returns [Integer] The enum value.
|
|
217
326
|
def enum_value
|
|
218
327
|
Lib.get_enum_value @cursor
|
|
219
328
|
end
|
|
220
|
-
|
|
329
|
+
|
|
330
|
+
# Get the unsigned value of an enum constant.
|
|
331
|
+
# @returns [Integer] The unsigned enum value.
|
|
221
332
|
def enum_unsigned_value
|
|
222
333
|
Lib.get_enum_unsigned_value @cursor
|
|
223
334
|
end
|
|
224
|
-
|
|
335
|
+
|
|
336
|
+
# Get the integer type of an enum declaration.
|
|
337
|
+
# @returns [Types::Type] The enum's underlying integer type.
|
|
225
338
|
def enum_type
|
|
226
339
|
Types::Type.create Lib.get_enum_decl_integer_type(@cursor), @translation_unit
|
|
227
340
|
end
|
|
228
|
-
|
|
341
|
+
|
|
342
|
+
# Get the template that this cursor specializes.
|
|
343
|
+
# @returns [Cursor] The specialized template cursor.
|
|
229
344
|
def specialized_template
|
|
230
345
|
Cursor.new Lib.get_specialized_cursor_template(@cursor), @translation_unit
|
|
231
346
|
end
|
|
232
|
-
|
|
347
|
+
|
|
348
|
+
# Get the canonical cursor for this cursor.
|
|
349
|
+
# @returns [Cursor] The canonical cursor.
|
|
233
350
|
def canonical
|
|
234
351
|
Cursor.new Lib.get_canonical_cursor(@cursor), @translation_unit
|
|
235
352
|
end
|
|
236
|
-
|
|
353
|
+
|
|
354
|
+
# Get the definition cursor for this cursor.
|
|
355
|
+
# @returns [Cursor] The definition cursor.
|
|
237
356
|
def definition
|
|
238
357
|
Cursor.new Lib.get_cursor_definition(@cursor), @translation_unit
|
|
239
358
|
end
|
|
240
|
-
|
|
359
|
+
|
|
360
|
+
# Check if this is an opaque declaration without a definition.
|
|
361
|
+
# @returns [Boolean] True if it's an opaque declaration.
|
|
241
362
|
def opaque_declaration?
|
|
242
363
|
# Is this a declaration that does not have a definition in the translation unit
|
|
243
364
|
self.declaration? && !self.definition? && self.definition.invalid?
|
|
244
365
|
end
|
|
245
|
-
|
|
366
|
+
|
|
367
|
+
# Check if this is a forward declaration.
|
|
368
|
+
# @returns [Boolean] True if it's a forward declaration.
|
|
246
369
|
def forward_declaration?
|
|
247
370
|
# Is this a forward declaration for a definition contained in the same translation_unit?
|
|
248
371
|
# https://joshpeterson.github.io/identifying-a-forward-declaration-with-libclang
|
|
@@ -252,77 +375,109 @@ module FFI
|
|
|
252
375
|
# !self.definition? && self.definition
|
|
253
376
|
self.declaration? && !self.eql?(self.definition) && !self.definition.invalid?
|
|
254
377
|
end
|
|
255
|
-
|
|
378
|
+
|
|
379
|
+
# Get the cursor referenced by this cursor.
|
|
380
|
+
# @returns [Cursor] The referenced cursor.
|
|
256
381
|
def referenced
|
|
257
382
|
Cursor.new Lib.get_cursor_referenced(@cursor), @translation_unit
|
|
258
383
|
end
|
|
259
|
-
|
|
384
|
+
|
|
385
|
+
# Get the semantic parent of this cursor.
|
|
386
|
+
# @returns [Cursor] The semantic parent cursor.
|
|
260
387
|
def semantic_parent
|
|
261
388
|
Cursor.new Lib.get_cursor_semantic_parent(@cursor), @translation_unit
|
|
262
389
|
end
|
|
263
|
-
|
|
390
|
+
|
|
391
|
+
# Get the lexical parent of this cursor.
|
|
392
|
+
# @returns [Cursor] The lexical parent cursor.
|
|
264
393
|
def lexical_parent
|
|
265
394
|
Cursor.new Lib.get_cursor_lexical_parent(@cursor), @translation_unit
|
|
266
395
|
end
|
|
267
|
-
|
|
396
|
+
|
|
397
|
+
# Get the template cursor kind.
|
|
398
|
+
# @returns [Symbol] The template cursor kind.
|
|
268
399
|
def template_kind
|
|
269
400
|
Lib.get_template_cursor_kind @cursor
|
|
270
401
|
end
|
|
271
|
-
|
|
402
|
+
|
|
403
|
+
# Get the C++ access specifier.
|
|
404
|
+
# @returns [Symbol] The access specifier (`:public`, `:private`, or `:protected`).
|
|
272
405
|
def access_specifier
|
|
273
406
|
Lib.get_cxx_access_specifier @cursor
|
|
274
407
|
end
|
|
275
|
-
|
|
408
|
+
|
|
409
|
+
# Get the programming language of this cursor.
|
|
410
|
+
# @returns [Symbol] The language symbol.
|
|
276
411
|
def language
|
|
277
412
|
Lib.get_language @cursor
|
|
278
413
|
end
|
|
279
|
-
|
|
414
|
+
|
|
415
|
+
# Get the number of arguments for this cursor.
|
|
416
|
+
# @returns [Integer] The number of arguments.
|
|
280
417
|
def num_args
|
|
281
418
|
Lib.get_num_args @cursor
|
|
282
419
|
end
|
|
283
|
-
|
|
420
|
+
|
|
421
|
+
# Iterate over child cursors.
|
|
422
|
+
# @parameter recurse [Boolean] Whether to recurse into children by default.
|
|
423
|
+
# @yields {|cursor, parent| ...} Each child cursor with its parent.
|
|
424
|
+
# @parameter cursor [Cursor] The child cursor.
|
|
425
|
+
# @parameter parent [Cursor] The parent cursor.
|
|
426
|
+
# @returns [Enumerator] If no block is given.
|
|
284
427
|
def each(recurse = true, &block)
|
|
285
428
|
return to_enum(:each, recurse) unless block_given?
|
|
286
|
-
|
|
429
|
+
|
|
287
430
|
adapter = Proc.new do |cxcursor, parent_cursor, unused|
|
|
288
431
|
# Call the block and capture the result. This lets advanced users
|
|
289
432
|
# modify the recursion on a case by case basis if needed
|
|
290
433
|
result = block.call Cursor.new(cxcursor, @translation_unit), Cursor.new(parent_cursor, @translation_unit)
|
|
291
434
|
case result
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
435
|
+
when :continue
|
|
436
|
+
:continue
|
|
437
|
+
when :recurse
|
|
438
|
+
:recurse
|
|
439
|
+
else
|
|
440
|
+
recurse ? :recurse : :continue
|
|
298
441
|
end
|
|
299
442
|
end
|
|
300
|
-
|
|
443
|
+
|
|
301
444
|
Lib.visit_children(@cursor, adapter, nil)
|
|
302
445
|
end
|
|
303
|
-
|
|
446
|
+
|
|
447
|
+
# Visit only direct children without recursing.
|
|
448
|
+
# @yields {|cursor, parent| ...} Each direct child cursor.
|
|
449
|
+
# @parameter cursor [Cursor] The child cursor.
|
|
450
|
+
# @parameter parent [Cursor] The parent cursor.
|
|
304
451
|
def visit_children(&block)
|
|
305
452
|
each(false, &block)
|
|
306
453
|
end
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
454
|
+
|
|
455
|
+
# Find ancestors of this cursor by kind.
|
|
456
|
+
# @parameter kinds [Array(Symbol)] The cursor kinds to search for.
|
|
457
|
+
# @returns [Array(Cursor)] Array of ancestor cursors matching the kinds.
|
|
458
|
+
def ancestors_by_kind(*kinds)
|
|
459
|
+
result = Array.new
|
|
460
|
+
|
|
461
|
+
parent = self
|
|
462
|
+
while parent != self.semantic_parent
|
|
463
|
+
parent = self.semantic_parent
|
|
464
|
+
if kinds.include?(parent.kind)
|
|
465
|
+
result << parent
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
result
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
# Find child cursors by kind.
|
|
472
|
+
# @parameter recurse [Boolean | Nil] Whether to recurse into children.
|
|
473
|
+
# @parameter kinds [Array(Symbol)] The cursor kinds to search for.
|
|
474
|
+
# @returns [Array(Cursor)] Array of matching cursors.
|
|
475
|
+
# @raises [RuntimeError] If recurse parameter is not nil or boolean.
|
|
321
476
|
def find_by_kind(recurse, *kinds)
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
477
|
+
unless (recurse == nil || recurse == true || recurse == false)
|
|
478
|
+
raise("Recurse parameter must be nil or a boolean value. Value was: #{recurse}")
|
|
479
|
+
end
|
|
480
|
+
|
|
326
481
|
result = Array.new
|
|
327
482
|
self.each(recurse) do |child, parent|
|
|
328
483
|
if kinds.include?(child.kind)
|
|
@@ -331,55 +486,70 @@ module FFI
|
|
|
331
486
|
end
|
|
332
487
|
result
|
|
333
488
|
end
|
|
334
|
-
|
|
489
|
+
|
|
490
|
+
# Find all references to this cursor in a file.
|
|
491
|
+
# @parameter file [String | Nil] The file path, or `nil` to use the translation unit file.
|
|
492
|
+
# @yields {|cursor, range| ...} Each reference with its cursor and source range.
|
|
493
|
+
# @parameter cursor [Cursor] The reference cursor.
|
|
494
|
+
# @parameter range [SourceRange] The source range of the reference.
|
|
335
495
|
def find_references_in_file(file = nil, &block)
|
|
336
496
|
file ||= Lib.extract_string Lib.get_translation_unit_spelling(@translation_unit)
|
|
337
|
-
|
|
497
|
+
|
|
338
498
|
visit_adapter = Proc.new do |unused, cxcursor, cxsource_range|
|
|
339
499
|
block.call Cursor.new(cxcursor, @translation_unit), SourceRange.new(cxsource_range)
|
|
340
500
|
end
|
|
341
501
|
visitor = FFI::Clang::Lib::CXCursorAndRangeVisitor.new
|
|
342
502
|
visitor[:visit] = visit_adapter
|
|
343
|
-
|
|
503
|
+
|
|
344
504
|
Lib.find_references_in_file(@cursor, Lib.get_file(@translation_unit, file), visitor)
|
|
345
505
|
end
|
|
346
|
-
|
|
506
|
+
|
|
507
|
+
# Get the linkage of this cursor.
|
|
508
|
+
# @returns [Symbol] The linkage kind.
|
|
347
509
|
def linkage
|
|
348
510
|
Lib.get_cursor_linkage(@cursor)
|
|
349
511
|
end
|
|
350
|
-
|
|
512
|
+
|
|
513
|
+
# Get the exception specification type for this cursor.
|
|
514
|
+
# @returns [Symbol] The exception specification type.
|
|
351
515
|
def exception_specification
|
|
352
516
|
Lib.get_cursor_exception_specification_type(@cursor)
|
|
353
517
|
end
|
|
354
|
-
|
|
518
|
+
|
|
519
|
+
# Get the availability of this cursor.
|
|
520
|
+
# @returns [Symbol] The availability status.
|
|
355
521
|
def availability
|
|
356
522
|
Lib.get_cursor_availability(@cursor)
|
|
357
523
|
end
|
|
358
|
-
|
|
524
|
+
|
|
525
|
+
# Get the file included by this cursor.
|
|
526
|
+
# @returns [File] The included file.
|
|
359
527
|
def included_file
|
|
360
528
|
File.new Lib.get_included_file(@cursor), @translation_unit
|
|
361
529
|
end
|
|
362
|
-
|
|
530
|
+
|
|
531
|
+
# Get platform availability information for this cursor.
|
|
532
|
+
# @parameter max_availability_size [Integer] Maximum number of platforms to query.
|
|
533
|
+
# @returns [Hash] Platform availability information.
|
|
363
534
|
def platform_availability(max_availability_size = 4)
|
|
364
535
|
availability_ptr = FFI::MemoryPointer.new(Lib::CXPlatformAvailability, max_availability_size)
|
|
365
536
|
always_deprecated_ptr = FFI::MemoryPointer.new :int
|
|
366
537
|
always_unavailable_ptr = FFI::MemoryPointer.new :int
|
|
367
538
|
deprecated_message_ptr = FFI::MemoryPointer.new Lib::CXString
|
|
368
539
|
unavailable_message_ptr = FFI::MemoryPointer.new Lib::CXString
|
|
369
|
-
|
|
540
|
+
|
|
370
541
|
actual_availability_size = Lib.get_cursor_platform_availability(
|
|
371
542
|
@cursor,
|
|
372
543
|
always_deprecated_ptr, deprecated_message_ptr,
|
|
373
544
|
always_unavailable_ptr, unavailable_message_ptr,
|
|
374
545
|
availability_ptr, max_availability_size)
|
|
375
|
-
|
|
546
|
+
|
|
376
547
|
availability = []
|
|
377
548
|
cur_ptr = availability_ptr
|
|
378
|
-
[actual_availability_size, max_availability_size].min.times {
|
|
379
|
-
|
|
380
|
-
cur_ptr += Lib::CXPlatformAvailability.size
|
|
549
|
+
[actual_availability_size, max_availability_size].min.times {availability << PlatformAvailability.new(cur_ptr)
|
|
550
|
+
cur_ptr += Lib::CXPlatformAvailability.size
|
|
381
551
|
}
|
|
382
|
-
|
|
552
|
+
|
|
383
553
|
# return as Hash
|
|
384
554
|
{
|
|
385
555
|
always_deprecated: always_deprecated_ptr.get_int(0),
|
|
@@ -389,64 +559,91 @@ module FFI
|
|
|
389
559
|
availability: availability
|
|
390
560
|
}
|
|
391
561
|
end
|
|
392
|
-
|
|
562
|
+
|
|
563
|
+
# Get all cursors that this cursor overrides.
|
|
564
|
+
# @returns [Array(Cursor)] Array of overridden cursors.
|
|
393
565
|
def overriddens
|
|
394
566
|
cursor_ptr = FFI::MemoryPointer.new :pointer
|
|
395
567
|
num_ptr = FFI::MemoryPointer.new :uint
|
|
396
568
|
Lib.get_overridden_cursors(@cursor, cursor_ptr, num_ptr)
|
|
397
569
|
num = num_ptr.get_uint(0)
|
|
398
570
|
cur_ptr = cursor_ptr.get_pointer(0)
|
|
399
|
-
|
|
571
|
+
|
|
400
572
|
overriddens = []
|
|
401
|
-
num.times {
|
|
402
|
-
|
|
403
|
-
cur_ptr += Lib::CXCursor.size
|
|
573
|
+
num.times {overriddens << Cursor.new(cur_ptr, @translation_unit)
|
|
574
|
+
cur_ptr += Lib::CXCursor.size
|
|
404
575
|
}
|
|
405
576
|
Lib.dispose_overridden_cursors(cursor_ptr.get_pointer(0)) if num != 0
|
|
406
577
|
overriddens
|
|
407
578
|
end
|
|
408
|
-
|
|
579
|
+
|
|
580
|
+
# Check if this cursor represents a bitfield.
|
|
581
|
+
# @returns [Boolean] True if it's a bitfield.
|
|
409
582
|
def bitfield?
|
|
410
583
|
Lib.is_bit_field(@cursor) != 0
|
|
411
584
|
end
|
|
412
|
-
|
|
585
|
+
|
|
586
|
+
# Get the bit width of a bitfield.
|
|
587
|
+
# @returns [Integer] The bitfield width.
|
|
413
588
|
def bitwidth
|
|
414
589
|
Lib.get_field_decl_bit_width(@cursor)
|
|
415
590
|
end
|
|
416
|
-
|
|
591
|
+
|
|
592
|
+
# Get an overloaded declaration by index.
|
|
593
|
+
# @parameter i [Integer] The index of the overloaded declaration.
|
|
594
|
+
# @returns [Cursor] The overloaded declaration cursor.
|
|
417
595
|
def overloaded_decl(i)
|
|
418
596
|
Cursor.new Lib.get_overloaded_decl(@cursor, i), @translation_unit
|
|
419
597
|
end
|
|
420
|
-
|
|
598
|
+
|
|
599
|
+
# Get the number of overloaded declarations.
|
|
600
|
+
# @returns [Integer] The number of overloaded declarations.
|
|
421
601
|
def num_overloaded_decls
|
|
422
602
|
Lib.get_num_overloaded_decls(@cursor)
|
|
423
603
|
end
|
|
424
|
-
|
|
604
|
+
|
|
605
|
+
# Get the Objective-C type encoding.
|
|
606
|
+
# @returns [String] The Objective-C type encoding.
|
|
425
607
|
def objc_type_encoding
|
|
426
608
|
Lib.extract_string Lib.get_decl_objc_type_encoding(@cursor)
|
|
427
609
|
end
|
|
428
|
-
|
|
610
|
+
|
|
611
|
+
# Get a function or method argument by index.
|
|
612
|
+
# @parameter i [Integer] The argument index.
|
|
613
|
+
# @returns [Cursor] The argument cursor.
|
|
429
614
|
def argument(i)
|
|
430
615
|
Cursor.new Lib.cursor_get_argument(@cursor, i), @translation_unit
|
|
431
616
|
end
|
|
432
|
-
|
|
617
|
+
|
|
618
|
+
# Get the number of arguments.
|
|
619
|
+
# @returns [Integer] The number of arguments.
|
|
433
620
|
def num_arguments
|
|
434
621
|
Lib.cursor_get_num_arguments(@cursor)
|
|
435
622
|
end
|
|
436
|
-
|
|
623
|
+
|
|
624
|
+
# Check if this cursor equals another cursor.
|
|
625
|
+
# @parameter other [Cursor] The cursor to compare with.
|
|
626
|
+
# @returns [Boolean] True if the cursors are equal.
|
|
437
627
|
def eql?(other)
|
|
438
628
|
Lib.are_equal(@cursor, other.cursor) != 0
|
|
439
629
|
end
|
|
440
630
|
alias == eql?
|
|
441
|
-
|
|
631
|
+
|
|
632
|
+
# Get the hash code for this cursor.
|
|
633
|
+
# @returns [Integer] The hash code.
|
|
442
634
|
def hash
|
|
443
635
|
Lib.get_cursor_hash(@cursor)
|
|
444
636
|
end
|
|
445
|
-
|
|
637
|
+
|
|
638
|
+
# Get a string representation of this cursor.
|
|
639
|
+
# @returns [String] The cursor string representation.
|
|
446
640
|
def to_s
|
|
447
641
|
"Cursor <#{self.kind.to_s.gsub(/^cursor_/, '')}: #{self.spelling}>"
|
|
448
642
|
end
|
|
449
|
-
|
|
643
|
+
|
|
644
|
+
# Find all references to this cursor.
|
|
645
|
+
# @parameter file [String | Nil] The file to search in, or `nil` for the translation unit file.
|
|
646
|
+
# @returns [Array(Cursor)] Array of reference cursors.
|
|
450
647
|
def references(file = nil)
|
|
451
648
|
refs = []
|
|
452
649
|
self.find_references_in_file(file) do |cursor, unused|
|
|
@@ -455,95 +652,144 @@ module FFI
|
|
|
455
652
|
end
|
|
456
653
|
refs
|
|
457
654
|
end
|
|
458
|
-
|
|
655
|
+
|
|
656
|
+
# Check if this is a converting constructor.
|
|
657
|
+
# @returns [Boolean] True if it's a converting constructor.
|
|
459
658
|
def converting_constructor?
|
|
460
659
|
Lib.is_converting_constructor(@cursor) != 0
|
|
461
660
|
end
|
|
462
|
-
|
|
661
|
+
|
|
662
|
+
# Check if this is a copy constructor.
|
|
663
|
+
# @returns [Boolean] True if it's a copy constructor.
|
|
463
664
|
def copy_constructor?
|
|
464
665
|
Lib.is_copy_constructor(@cursor) != 0
|
|
465
666
|
end
|
|
466
|
-
|
|
667
|
+
|
|
668
|
+
# Check if this is a default constructor.
|
|
669
|
+
# @returns [Boolean] True if it's a default constructor.
|
|
467
670
|
def default_constructor?
|
|
468
671
|
Lib.is_default_constructor(@cursor) != 0
|
|
469
672
|
end
|
|
470
|
-
|
|
673
|
+
|
|
674
|
+
# Check if this is a move constructor.
|
|
675
|
+
# @returns [Boolean] True if it's a move constructor.
|
|
471
676
|
def move_constructor?
|
|
472
677
|
Lib.is_move_constructor(@cursor) != 0
|
|
473
678
|
end
|
|
474
|
-
|
|
679
|
+
|
|
680
|
+
# Check if this cursor is mutable.
|
|
681
|
+
# @returns [Boolean] True if it's mutable.
|
|
475
682
|
def mutable?
|
|
476
683
|
Lib.is_mutable(@cursor) != 0
|
|
477
684
|
end
|
|
478
|
-
|
|
685
|
+
|
|
686
|
+
# Check if this cursor is defaulted.
|
|
687
|
+
# @returns [Boolean] True if it's defaulted.
|
|
479
688
|
def defaulted?
|
|
480
689
|
Lib.is_defaulted(@cursor) != 0
|
|
481
690
|
end
|
|
482
|
-
|
|
691
|
+
|
|
692
|
+
# Check if this cursor is deleted.
|
|
693
|
+
# @returns [Boolean] True if it's deleted.
|
|
483
694
|
def deleted?
|
|
484
695
|
Lib.is_deleted(@cursor) != 0
|
|
485
696
|
end
|
|
486
|
-
|
|
697
|
+
|
|
698
|
+
# Check if this is a copy assignment operator.
|
|
699
|
+
# @returns [Boolean] True if it's a copy assignment operator.
|
|
487
700
|
def copy_assignment_operator?
|
|
488
701
|
Lib.is_copy_assignment_operator(@cursor) != 0
|
|
489
702
|
end
|
|
490
|
-
|
|
703
|
+
|
|
704
|
+
# Check if this is a move assignment operator.
|
|
705
|
+
# @returns [Boolean] True if it's a move assignment operator.
|
|
491
706
|
def move_assignment_operator?
|
|
492
707
|
Lib.is_move_assignment_operator(@cursor) != 0
|
|
493
708
|
end
|
|
494
|
-
|
|
709
|
+
|
|
710
|
+
# Check if this cursor is explicit.
|
|
711
|
+
# @returns [Boolean] True if it's explicit.
|
|
495
712
|
def explicit?
|
|
496
713
|
Lib.is_explicit(@cursor) != 0
|
|
497
714
|
end
|
|
498
|
-
|
|
715
|
+
|
|
716
|
+
# Check if this cursor is abstract.
|
|
717
|
+
# @returns [Boolean] True if it's abstract.
|
|
499
718
|
def abstract?
|
|
500
719
|
Lib.is_abstract(@cursor) != 0
|
|
501
720
|
end
|
|
502
|
-
|
|
721
|
+
|
|
722
|
+
# Check if this is a scoped enum.
|
|
723
|
+
# @returns [Boolean] True if it's a scoped enum.
|
|
503
724
|
def enum_scoped?
|
|
504
725
|
Lib.is_enum_scoped(@cursor) != 0
|
|
505
726
|
end
|
|
506
|
-
|
|
727
|
+
|
|
728
|
+
# Check if this cursor is const-qualified.
|
|
729
|
+
# @returns [Boolean] True if it's const.
|
|
507
730
|
def const?
|
|
508
731
|
Lib.is_const(@cursor) != 0
|
|
509
732
|
end
|
|
510
|
-
|
|
733
|
+
|
|
734
|
+
# Represents platform availability information for a cursor.
|
|
511
735
|
class PlatformAvailability < AutoPointer
|
|
736
|
+
# Initialize platform availability from a memory pointer.
|
|
737
|
+
# @parameter memory_pointer [FFI::MemoryPointer] The memory pointer.
|
|
512
738
|
def initialize(memory_pointer)
|
|
513
739
|
pointer = FFI::Pointer.new(memory_pointer)
|
|
514
740
|
super(pointer)
|
|
515
|
-
|
|
741
|
+
|
|
516
742
|
# I'm not sure this is safe.
|
|
517
743
|
# Keep a reference to CXPlatformAvailability itself allocated by MemoryPointer.
|
|
518
744
|
@memory_pointer = memory_pointer
|
|
519
745
|
@platform_availability = Lib::CXPlatformAvailability.new(memory_pointer)
|
|
520
746
|
end
|
|
521
|
-
|
|
747
|
+
|
|
748
|
+
# Release the platform availability pointer.
|
|
749
|
+
# @parameter pointer [FFI::Pointer] The pointer to release.
|
|
522
750
|
def self.release(pointer)
|
|
523
751
|
# Memory allocated by get_cursor_platform_availability is managed by AutoPointer.
|
|
524
752
|
Lib.dispose_platform_availability(Lib::CXPlatformAvailability.new(pointer))
|
|
525
753
|
end
|
|
526
|
-
|
|
754
|
+
|
|
755
|
+
# Get the platform name.
|
|
756
|
+
# @returns [String] The platform name.
|
|
527
757
|
def platform
|
|
528
758
|
Lib.get_string @platform_availability[:platform]
|
|
529
759
|
end
|
|
530
|
-
|
|
760
|
+
|
|
761
|
+
# Get the platform name.
|
|
762
|
+
# @returns [String] The platform name.
|
|
763
|
+
def platform
|
|
764
|
+
Lib.get_string @platform_availability[:platform]
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
# Get the version where the feature was introduced.
|
|
768
|
+
# @returns [Lib::CXVersion] The introduced version.
|
|
531
769
|
def introduced
|
|
532
770
|
@platform_availability[:introduced]
|
|
533
771
|
end
|
|
534
|
-
|
|
772
|
+
|
|
773
|
+
# Get the version where the feature was deprecated.
|
|
774
|
+
# @returns [Lib::CXVersion] The deprecated version.
|
|
535
775
|
def deprecated
|
|
536
776
|
@platform_availability[:deprecated]
|
|
537
777
|
end
|
|
538
|
-
|
|
778
|
+
|
|
779
|
+
# Get the version where the feature was obsoleted.
|
|
780
|
+
# @returns [Lib::CXVersion] The obsoleted version.
|
|
539
781
|
def obsoleted
|
|
540
782
|
@platform_availability[:obsoleted]
|
|
541
783
|
end
|
|
542
|
-
|
|
784
|
+
|
|
785
|
+
# Check if the feature is unavailable.
|
|
786
|
+
# @returns [Boolean] True if unavailable.
|
|
543
787
|
def unavailable
|
|
544
788
|
@platform_availability[:unavailable] != 0
|
|
545
789
|
end
|
|
546
|
-
|
|
790
|
+
|
|
791
|
+
# Get the availability message.
|
|
792
|
+
# @returns [String] The availability message.
|
|
547
793
|
def message
|
|
548
794
|
Lib.get_string @platform_availability[:message]
|
|
549
795
|
end
|