ghazel-ffi-clang 0.2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +21 -0
  5. data/Gemfile +4 -0
  6. data/README.md +74 -0
  7. data/Rakefile +12 -0
  8. data/ext/rakefile.rb +12 -0
  9. data/ext/teapot.rb +16 -0
  10. data/ffi-clang.gemspec +26 -0
  11. data/lib/ffi/clang.rb +54 -0
  12. data/lib/ffi/clang/comment.rb +278 -0
  13. data/lib/ffi/clang/cursor.rb +378 -0
  14. data/lib/ffi/clang/diagnostic.rb +113 -0
  15. data/lib/ffi/clang/file.rb +69 -0
  16. data/lib/ffi/clang/index.rb +71 -0
  17. data/lib/ffi/clang/lib.rb +73 -0
  18. data/lib/ffi/clang/lib/comment.rb +117 -0
  19. data/lib/ffi/clang/lib/cursor.rb +353 -0
  20. data/lib/ffi/clang/lib/diagnostic.rb +87 -0
  21. data/lib/ffi/clang/lib/file.rb +57 -0
  22. data/lib/ffi/clang/lib/index.rb +34 -0
  23. data/lib/ffi/clang/lib/source_location.rb +53 -0
  24. data/lib/ffi/clang/lib/source_range.rb +46 -0
  25. data/lib/ffi/clang/lib/string.rb +45 -0
  26. data/lib/ffi/clang/lib/token.rb +58 -0
  27. data/lib/ffi/clang/lib/translation_unit.rb +106 -0
  28. data/lib/ffi/clang/lib/type.rb +154 -0
  29. data/lib/ffi/clang/lib/utils.rb +29 -0
  30. data/lib/ffi/clang/source_location.rb +149 -0
  31. data/lib/ffi/clang/source_range.rb +61 -0
  32. data/lib/ffi/clang/token.rb +95 -0
  33. data/lib/ffi/clang/translation_unit.rb +142 -0
  34. data/lib/ffi/clang/type.rb +135 -0
  35. data/lib/ffi/clang/unsaved_file.rb +49 -0
  36. data/lib/ffi/clang/utils.rb +58 -0
  37. data/lib/ffi/clang/version.rb +26 -0
  38. data/spec/clang/comment_spec.rb +470 -0
  39. data/spec/clang/cursor_spec.rb +709 -0
  40. data/spec/clang/diagnostic_spec.rb +89 -0
  41. data/spec/clang/file_spec.rb +84 -0
  42. data/spec/clang/index_spec.rb +70 -0
  43. data/spec/clang/source_location_spec.rb +140 -0
  44. data/spec/clang/source_range_spec.rb +76 -0
  45. data/spec/clang/token_spec.rb +83 -0
  46. data/spec/clang/translation_unit_spec.rb +214 -0
  47. data/spec/clang/type_spec.rb +289 -0
  48. data/spec/clang/utils_spec.rb +61 -0
  49. data/spec/fixtures/a.c +7 -0
  50. data/spec/fixtures/canonical.c +5 -0
  51. data/spec/fixtures/docs.c +1 -0
  52. data/spec/fixtures/docs.cc +1 -0
  53. data/spec/fixtures/docs.h +54 -0
  54. data/spec/fixtures/list.c +11 -0
  55. data/spec/fixtures/location1.c +7 -0
  56. data/spec/fixtures/simple.c +3 -0
  57. data/spec/fixtures/test.cxx +62 -0
  58. data/spec/spec_helper.rb +64 -0
  59. metadata +180 -0
@@ -0,0 +1,709 @@
1
+ # Copyright, 2010-2012 by Jari Bakken.
2
+ # Copyright, 2013, by Samuel G. D. Williams. <http://www.codeotaku.com>
3
+ # Copyright, 2013, by Garry C. Marshall. <http://www.meaningfulname.net>
4
+ # Copyright, 2014, by Masahiro Sano.
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+
24
+ require 'spec_helper'
25
+
26
+ describe Cursor do
27
+ let(:cursor) { Index.new.parse_translation_unit(fixture_path("list.c")).cursor }
28
+ let(:cursor_cxx) { Index.new.parse_translation_unit(fixture_path("test.cxx")).cursor }
29
+ let(:cursor_canon) { Index.new.parse_translation_unit(fixture_path("canonical.c")).cursor }
30
+ let(:cursor_pp) { Index.new.parse_translation_unit(fixture_path("docs.c"),[],[],{detailed_preprocessing_record: true}).cursor }
31
+
32
+ it "can be obtained from a translation unit" do
33
+ cursor.should be_kind_of(Cursor)
34
+ cursor.kind.should equal(:cursor_translation_unit)
35
+ cursor.null?.should equal(false)
36
+ cursor.translation_unit?.should equal(true)
37
+ end
38
+
39
+ it "returns the source location of the cursor" do
40
+ location = cursor.location
41
+ location.should be_kind_of(SourceLocation)
42
+ end
43
+
44
+ describe '#extent' do
45
+ let(:extent) { cursor.extent }
46
+ it "has an extent which is a SourceRange" do
47
+ expect(extent).to be_kind_of(SourceRange)
48
+ end
49
+
50
+ it 'has filename and posion at start point' do
51
+ expect(extent.start.file).to eq(fixture_path("list.c"))
52
+ expect(extent.start.line).to equal(1)
53
+ end
54
+
55
+ it 'has filename and posion at end point', from_3_4: true do
56
+ expect(extent.end.file).to eq(fixture_path("list.c"))
57
+ expect(extent.end.line).to equal(12)
58
+ end
59
+
60
+ it 'has filename and posion at end point', upto_3_3: true do
61
+ expect(extent.end.file).to eq(fixture_path("list.c"))
62
+ expect(extent.end.line).to equal(11)
63
+ end
64
+ end
65
+
66
+ it "returns the path of the translation unit for the translation unit cursor" do
67
+ cursor.display_name.should eq(fixture_path("list.c"))
68
+ cursor.spelling.should eq(fixture_path("list.c"))
69
+ end
70
+
71
+ it "allows us to visit its children" do
72
+ counter = 0
73
+ cursor.visit_children do |cursor, parent|
74
+ counter += 1
75
+ :recurse
76
+ end
77
+ counter.should_not equal(0)
78
+ end
79
+
80
+ describe "Null Cursor" do
81
+ it "can be a null cursor" do
82
+ Cursor.null_cursor.should be_kind_of(Cursor)
83
+ Cursor.null_cursor.kind.should equal(:cursor_invalid_file)
84
+ end
85
+
86
+ it "is null?" do
87
+ Cursor.null_cursor.null?.should equal(true)
88
+ end
89
+
90
+ it "is invalid?" do
91
+ Cursor.null_cursor.invalid?.should equal(true)
92
+ end
93
+
94
+ it "compares as equal to another null cursor instance" do
95
+ Cursor.null_cursor.should eq(Cursor.null_cursor)
96
+ end
97
+
98
+ it "should not equal a Translation Unit cursor" do
99
+ Cursor.null_cursor.should_not eq(cursor)
100
+ end
101
+ end
102
+
103
+ describe "Function Cursors" do
104
+ let (:func) { find_first(cursor, :cursor_function) }
105
+
106
+ it "is not invalid?" do
107
+ func.invalid?.should equal(false)
108
+ end
109
+
110
+ it "can find the first function declaration" do
111
+ func.should_not equal(nil)
112
+ func.kind.should equal(:cursor_function)
113
+ end
114
+
115
+ it "has an extent representing the bounds of the function" do
116
+ func.extent.should be_kind_of(SourceRange)
117
+ func.extent.start.line.should equal(5)
118
+ func.extent.end.line.should equal(5)
119
+ end
120
+
121
+ it "returns the name of the function" do
122
+ func.spelling.should eq("sum")
123
+ func.display_name.should eq("sum(union List *)")
124
+ end
125
+ end
126
+
127
+ describe "Struct Cursors" do
128
+ let (:struct) { find_first(cursor, :cursor_struct) }
129
+
130
+ it "can find the first struct" do
131
+ struct.should_not equal(nil)
132
+ struct.kind.should equal(:cursor_struct)
133
+ end
134
+
135
+ it "has an extent representing the bounds of the struct" do
136
+ struct.extent.start.line.should equal(1)
137
+ struct.extent.end.line.should equal(4)
138
+ end
139
+
140
+ it "returns the name of the struct" do
141
+ struct.spelling.should eq("List")
142
+ struct.display_name.should eq("List")
143
+ end
144
+
145
+ end
146
+
147
+ describe '#kind_spelling' do
148
+ let (:struct) { find_first(cursor, :cursor_struct) }
149
+
150
+ it "returns the spelling of the given kind" do
151
+ expect(struct.kind_spelling).to eq('StructDecl')
152
+ end
153
+ end
154
+
155
+ describe '#declaration?' do
156
+ let (:struct) { find_first(cursor, :cursor_struct) }
157
+
158
+ it "checks the cursor is declaration" do
159
+ expect(struct.declaration?).to be_true
160
+ end
161
+ end
162
+
163
+ describe '#reference?' do
164
+ let (:ref) { find_first(cursor, :cursor_type_ref) }
165
+
166
+ it "checks the cursor is reference" do
167
+ expect(ref.reference?).to be_true
168
+ end
169
+ end
170
+
171
+ describe '#expression?' do
172
+ let (:literal) { find_first(cursor, :cursor_integer_literal) }
173
+
174
+ it "checks the cursor is expression" do
175
+ expect(literal.expression?).to be_true
176
+ end
177
+ end
178
+
179
+ describe '#statement?' do
180
+ let (:return_stmt) { find_first(cursor, :cursor_return_stmt) }
181
+
182
+ it "checks the cursor is statement" do
183
+ expect(return_stmt.statement?).to be_true
184
+ end
185
+ end
186
+
187
+ describe '#attribute?' do
188
+ let (:attr) { find_first(cursor_cxx, :cursor_unexposed_attr) }
189
+
190
+ it "checks the cursor is attribute" do
191
+ expect(attr.attribute?).to be_true
192
+ end
193
+ end
194
+
195
+ describe '#public?' do
196
+ let(:public_cursor) { find_matching(cursor_cxx) { |child, parent|
197
+ child.kind == :cursor_field_decl and child.spelling == 'public_member_int' } }
198
+
199
+ it 'checks access control level is public', from_3_3: true do
200
+ expect(public_cursor.public?).to be_true
201
+ end
202
+
203
+ it 'returns false on clang 3.2', upto_3_2: true do
204
+ expect(public_cursor.public?).to be_false
205
+ end
206
+ end
207
+
208
+ describe '#private?' do
209
+ let(:private_cursor) { find_matching(cursor_cxx) { |child, parent|
210
+ child.kind == :cursor_field_decl and child.spelling == 'private_member_int' } }
211
+
212
+ it 'checks access control level is private', from_3_3: true do
213
+ expect(private_cursor.private?).to be_true
214
+ end
215
+
216
+ it 'returns false on clang 3.2', upto_3_2: true do
217
+ expect(private_cursor.private?).to be_false
218
+ end
219
+ end
220
+
221
+ describe '#protected?' do
222
+ let(:protected_cursor) { find_matching(cursor_cxx) { |child, parent|
223
+ child.kind == :cursor_field_decl and child.spelling == 'protected_member_int' } }
224
+
225
+ it 'checks access control level is protected', from_3_3: true do
226
+ expect(protected_cursor.protected?).to be_true
227
+ end
228
+
229
+ it 'returns false on clang 3.2', upto_3_2: true do
230
+ expect(protected_cursor.protected?).to be_false
231
+ end
232
+ end
233
+
234
+ describe '#preprocessing?' do
235
+ let (:pp) { find_first(cursor_pp, :cursor_macro_definition) }
236
+
237
+ it 'checks the cursor is preprocessing' do
238
+ expect(pp.preprocessing?).to be_true
239
+ end
240
+ end
241
+
242
+ describe '#unexposed?' do
243
+ let(:unexposed_cursor) { find_matching(cursor_cxx) { |child, parent|
244
+ child.kind == :cursor_unexposed_expr and child.spelling == 'func_overloaded' } }
245
+
246
+ it 'checks the cursor is unexposed' do
247
+ expect(unexposed_cursor.unexposed?).to be_true
248
+ end
249
+ end
250
+
251
+ describe '#virtual_base?' do
252
+ let(:virtual_base_cursor) { find_matching(cursor_cxx) { |child, parent|
253
+ child.kind == :cursor_cxx_base_specifier and parent.spelling == 'B' } }
254
+
255
+ it 'checks cursor is virtual base' do
256
+ virtual_base_cursor.virtual_base?.should equal true
257
+ end
258
+ end
259
+
260
+ describe '#virtual?' do
261
+ let(:virtual_cursor) { find_matching(cursor_cxx) { |child, parent|
262
+ child.kind == :cursor_cxx_method and child.spelling == 'func_a' } }
263
+
264
+ it 'checks member function is virtual' do
265
+ virtual_cursor.virtual?.should equal true
266
+ end
267
+ end
268
+
269
+ describe '#pure_virtual?', from_3_4: true do
270
+ let(:pure_virtual_cursor) { find_matching(cursor_cxx) { |child, parent|
271
+ child.kind == :cursor_cxx_method and
272
+ child.spelling == 'func_a' and parent.spelling == 'A' } }
273
+
274
+ it 'checks member function is purely virtual' do
275
+ pure_virtual_cursor.pure_virtual?.should equal true
276
+ end
277
+ end
278
+
279
+ describe '#static?' do
280
+ let(:static_method_cursor) { find_matching(cursor_cxx) { |child, parent|
281
+ child.kind == :cursor_cxx_method and child.spelling == 'func_b' } }
282
+
283
+ it 'checks cursor is static member function' do
284
+ static_method_cursor.static?.should equal true
285
+ end
286
+ end
287
+
288
+ describe '#enum_value' do
289
+ let(:enum_value_cursor) { find_matching(cursor_cxx) { |child, parent|
290
+ child.kind == :cursor_enum_constant_decl and child.spelling == 'EnumC' } }
291
+
292
+ it 'returns enum value' do
293
+ enum_value_cursor.enum_value.should equal 100
294
+ end
295
+ end
296
+
297
+ describe '#enum_unsigned_value' do
298
+ let(:enum_value_cursor) { find_matching(cursor_cxx) { |child, parent|
299
+ child.kind == :cursor_enum_constant_decl and child.spelling == 'EnumC' } }
300
+
301
+ it 'returns enum unsigned value' do
302
+ expect(enum_value_cursor.enum_unsigned_value).to eq(100)
303
+ end
304
+ end
305
+
306
+ describe '#dynamic_call?' do
307
+ let(:dynamic_call) { find_matching(cursor_cxx) { |child, parent|
308
+ child.kind == :cursor_call_expr and child.spelling == 'func_a' and
309
+ child.semantic_parent.spelling == 'f_dynamic_call' } }
310
+
311
+ it 'checks if the method call is dynamic' do
312
+ expect(dynamic_call.dynamic_call?).to be_true
313
+ end
314
+ end
315
+
316
+ describe '#specialized_template', from_3_3: true do # looks not working on 3.2
317
+ let(:cursor_function) { find_matching(cursor_cxx) { |child, parent|
318
+ child.kind == :cursor_function and child.spelling == 'func_overloaded' } }
319
+
320
+ it "returns a cursor that may represent a specialization or instantiation of a template" do
321
+ expect(cursor_function.specialized_template).to be_kind_of(Cursor)
322
+ expect(cursor_function.specialized_template.kind).to be(:cursor_function_template)
323
+ end
324
+ end
325
+
326
+ describe '#canonical' do
327
+ let (:structs) { find_all(cursor_canon, :cursor_struct) }
328
+
329
+ it "mathes 3 cursors" do
330
+ structs.size.should eq(3)
331
+ end
332
+
333
+ it "refers the first cursor as canonical one" do
334
+ structs[0].canonical.should eq(structs[0])
335
+ structs[1].canonical.should eq(structs[0])
336
+ structs[2].canonical.should eq(structs[0])
337
+ end
338
+ end
339
+
340
+ describe '#definition' do
341
+ let (:structs) { find_all(cursor_canon, :cursor_struct) }
342
+
343
+ it "mathes 3 cursors" do
344
+ structs.size.should eq(3)
345
+ end
346
+
347
+ it "refers the third cursor as definition one" do
348
+ structs[0].definition.should eq(structs[2])
349
+ structs[1].definition.should eq(structs[2])
350
+ structs[2].definition.should eq(structs[2])
351
+ end
352
+ end
353
+
354
+ describe '#template_kind', from_3_3: true do # looks not working on 3.2
355
+ let(:template) { find_matching(cursor_cxx) { |child, parent|
356
+ child.kind == :cursor_function_template and child.spelling == 'func_overloaded' } }
357
+
358
+ it "returns the cursor kind of the specializations would be generated" do
359
+ expect(template.template_kind).to be_kind_of(Symbol)
360
+ expect(template.template_kind).to be(:cursor_function)
361
+ end
362
+ end
363
+
364
+ describe '#access_specifier' do
365
+ let(:access_specifier_cursor) { find_matching(cursor_cxx) { |child, parent|
366
+ child.kind == :cursor_cxx_method and child.spelling == 'func_d' } }
367
+
368
+ it 'returns access specifier symbol', from_3_3: true do
369
+ access_specifier_cursor.access_specifier.should equal :private
370
+ end
371
+
372
+ it 'returns access specifier symbol(invalid, why?)', upto_3_2: true do
373
+ access_specifier_cursor.access_specifier.should equal :invalid
374
+ end
375
+ end
376
+
377
+ describe '#language' do
378
+ let(:c_language_cursor) { find_matching(cursor) { |c, p| c.kind == :cursor_struct } }
379
+ let(:cxx_language_cursor) { find_matching(cursor_cxx) { |c, p| c.kind == :cursor_struct } }
380
+
381
+ it 'returns :c if the cursor language is C' do
382
+ c_language_cursor.language.should equal :c
383
+ end
384
+
385
+ it 'returns :c_plus_plus if the cursor language is C++' do
386
+ cxx_language_cursor.language.should equal :c_plus_plus
387
+ end
388
+ end
389
+
390
+ describe '#translation_unit' do
391
+ let (:struct) { find_first(cursor, :cursor_struct) }
392
+
393
+ it "can find the first struct" do
394
+ struct.should_not equal(nil)
395
+ end
396
+
397
+ it "returns the translation unit that a cursor originated from" do
398
+ struct.translation_unit.should be_kind_of(TranslationUnit)
399
+ struct.translation_unit.spelling.should eq(fixture_path("list.c"))
400
+ end
401
+ end
402
+
403
+ describe '#linkage' do
404
+ let (:ref) { find_first(cursor, :cursor_type_ref) }
405
+ let (:func) { find_first(cursor, :cursor_function) }
406
+
407
+ it "returns :external if the cursor is non-static function" do
408
+ func.linkage.should equal :external
409
+ end
410
+
411
+ it "returns :invalid if the cursor does not have linkage" do
412
+ ref.linkage.should equal :invalid
413
+ end
414
+ end
415
+
416
+ describe '#semantic_parent' do
417
+ let(:parent) { find_matching(cursor_cxx) { |child, parent|
418
+ child.kind == :cursor_cxx_method and child.spelling == 'func_d' and parent.spelling != 'D' } }
419
+
420
+ it 'returns base class as semantic parent' do
421
+ parent.semantic_parent.spelling.should eq('D')
422
+ end
423
+ end
424
+
425
+ describe '#lexical_parent' do
426
+ let(:parent) { find_matching(cursor_cxx) { |child, parent|
427
+ child.kind == :cursor_cxx_method and child.spelling == 'func_d' and parent.spelling != 'D' } }
428
+
429
+ it 'returns translation unit as lexical parent' do
430
+ parent.lexical_parent.kind.should eq(:cursor_translation_unit)
431
+ end
432
+ end
433
+
434
+ describe '#included_file' do
435
+ #TODO
436
+ end
437
+
438
+ describe '#definition?' do
439
+ let (:struct) { find_all(cursor_canon, :cursor_struct).at(2) }
440
+
441
+ it "checks cursor is a definition" do
442
+ struct.definition?.should be_true
443
+ end
444
+ end
445
+
446
+ describe '#usr' do
447
+ let (:func) { find_first(cursor, :cursor_function) }
448
+
449
+ it "returns something in string" do
450
+ func.usr.should be_kind_of(String)
451
+ end
452
+ end
453
+
454
+ describe '#variadic?', from_3_3: true do
455
+ let(:func) { find_matching(cursor_cxx) { |child, parent|
456
+ child.kind == :cursor_function and child.spelling == 'f_variadic' } }
457
+
458
+ it "checks cursor is a variadic function" do
459
+ func.variadic?.should be_true
460
+ end
461
+ end
462
+
463
+ describe '#referenced' do
464
+ let(:struct) { find_matching(cursor_cxx) { |child, parent|
465
+ child.kind == :cursor_struct and child.spelling == 'A' } }
466
+ let(:ref) { find_matching(cursor_cxx) { |child, parent|
467
+ child.kind == :cursor_type_ref and child.spelling == 'struct A' } }
468
+
469
+ it "returns a cursor that this cursor references" do
470
+ ref.referenced.should eq(struct)
471
+ end
472
+
473
+ end
474
+
475
+ describe '#hash' do
476
+ let (:func) { find_first(cursor, :cursor_function) }
477
+
478
+ it "computes hash for the cursor" do
479
+ func.hash.should be_kind_of(Fixnum)
480
+ end
481
+ end
482
+
483
+ describe '#availability' do
484
+ let (:func) { find_first(cursor, :cursor_function) }
485
+
486
+ it "returns :available for the cursor availability" do
487
+ func.availability.should equal(:available)
488
+ end
489
+ end
490
+
491
+ describe '#type' do
492
+ let (:field) { find_first(cursor, :cursor_field_decl) }
493
+
494
+ it "returns type for the cursor" do
495
+ field.type.should be_kind_of(Type)
496
+ field.type.kind.should equal(:type_int)
497
+ end
498
+ end
499
+
500
+ describe '#underlying_type' do
501
+ let (:typedef) { find_first(cursor_cxx, :cursor_typedef_decl) }
502
+
503
+ it "returns type that the cursor type is underlying" do
504
+ typedef.underlying_type.should be_kind_of(Type)
505
+ typedef.underlying_type.kind.should equal(:type_pointer)
506
+ end
507
+ end
508
+
509
+ describe '#bitfield?', from_3_3: true do
510
+ let(:bitfield) { find_matching(cursor_cxx) { |child, parent|
511
+ child.kind == :cursor_field_decl and child.spelling == 'bit_field_a' } }
512
+ let(:non_bitfield) { find_matching(cursor_cxx) { |child, parent|
513
+ child.kind == :cursor_field_decl and child.spelling == 'non_bit_field_c' } }
514
+
515
+ it "returns true if the cursor is bitfield" do
516
+ expect(bitfield.bitfield?).to be_true
517
+ end
518
+
519
+ it "returns false if the cursor is not bitfield" do
520
+ expect(non_bitfield.bitfield?).to be_false
521
+ end
522
+ end
523
+
524
+ describe '#bitwidth', from_3_3: true do
525
+ let(:bitfield) { find_matching(cursor_cxx) { |child, parent|
526
+ child.kind == :cursor_field_decl and child.spelling == 'bit_field_a' } }
527
+ let(:non_bitfield) { find_matching(cursor_cxx) { |child, parent|
528
+ child.kind == :cursor_field_decl and child.spelling == 'non_bit_field_c' } }
529
+
530
+ it "returns the bit width of the bit field if the cursor is bitfield" do
531
+ expect(bitfield.bitwidth).to be_kind_of(Integer)
532
+ expect(bitfield.bitwidth).to eq(2)
533
+ end
534
+
535
+ it "returns -1 if the cursor is not bitfield" do
536
+ expect(non_bitfield.bitwidth).to eq(-1)
537
+ end
538
+ end
539
+
540
+ describe '#enum_decl_integer_type' do
541
+ let(:enum) { find_matching(cursor_cxx) { |child, parent|
542
+ child.kind == :cursor_enum_decl and child.spelling == 'normal_enum' } }
543
+
544
+ it "returns the integer type of the enum declaration" do
545
+ expect(enum.enum_decl_integer_type).to be_kind_of(Type)
546
+ expect(enum.enum_decl_integer_type.kind).to be(:type_uint)
547
+ end
548
+ end
549
+
550
+ describe '#platform_availability' do
551
+ let(:func) { find_matching(cursor_cxx) { |child, parent|
552
+ child.kind == :cursor_function and child.spelling == 'availability_func'} }
553
+ let(:availability) { func.platform_availability }
554
+
555
+ it "returns the availability of the entity as Hash" do
556
+ expect(availability).to be_kind_of(Hash)
557
+ expect(availability[:always_deprecated]).to be_kind_of(Integer)
558
+ expect(availability[:always_unavailable]).to be_kind_of(Integer)
559
+ expect(availability[:deprecated_message]).to be_kind_of(String)
560
+ expect(availability[:unavailable_message]).to be_kind_of(String)
561
+ expect(availability[:availability]).to be_kind_of(Array)
562
+ end
563
+ end
564
+
565
+ describe '#overriddens' do
566
+ let(:override_cursor) { find_matching(cursor_cxx) { |child, parent|
567
+ child.kind == :cursor_cxx_method and
568
+ child.spelling == 'func_a' and parent.spelling == 'D' } }
569
+
570
+ it "returns the set of methods which are overridden by this cursor method" do
571
+ expect(override_cursor.overriddens).to be_kind_of(Array)
572
+ expect(override_cursor.overriddens.size).to eq(2)
573
+ expect(override_cursor.overriddens.map{|cur| cur.semantic_parent.spelling}).to eq(["B", "C"])
574
+ end
575
+ end
576
+
577
+ describe '#overloaded_decl' do
578
+ let(:overloaded) { find_matching(cursor_cxx) { |child, parent|
579
+ child.kind == :cursor_overloaded_decl_ref and child.spelling == 'func_overloaded' } }
580
+
581
+ it "returns a cursor for one of the overloaded declarations" do
582
+ expect(overloaded.overloaded_decl(0)).to be_kind_of(Cursor)
583
+ expect(overloaded.overloaded_decl(0).kind).to be(:cursor_function_template)
584
+ expect(overloaded.overloaded_decl(0).spelling).to eq('func_overloaded')
585
+ end
586
+ end
587
+
588
+ describe '#num_overloaded_decls' do
589
+ let(:overloaded) { find_matching(cursor_cxx) { |child, parent|
590
+ child.kind == :cursor_overloaded_decl_ref and child.spelling == 'func_overloaded' } }
591
+
592
+ it "returns the number of overloaded declarations" do
593
+ expect(overloaded.num_overloaded_decls).to be_kind_of(Integer)
594
+ expect(overloaded.num_overloaded_decls).to be(2)
595
+ end
596
+ end
597
+
598
+ describe '#objc_type_encoding' do
599
+ #TODO
600
+ end
601
+
602
+ describe '#argument' do
603
+ let(:func) { find_matching(cursor_cxx) { |child, parent|
604
+ child.kind == :cursor_function and child.spelling == 'f_non_variadic' } }
605
+
606
+ it "returns the argument cursor of the function" do
607
+ expect(func.argument(0)).to be_kind_of(Cursor)
608
+ expect(func.argument(0).spelling).to eq('a')
609
+ end
610
+ end
611
+
612
+ describe '#num_arguments' do
613
+ let(:cursor_cxx) { Index.new.parse_translation_unit(fixture_path("test.cxx")).cursor }
614
+ let(:func) { find_matching(cursor_cxx) { |child, parent|
615
+ child.kind == :cursor_function and child.spelling == 'f_non_variadic' } }
616
+
617
+ it "returns the number of non-variadic arguments" do
618
+ expect(func.num_arguments).to be_kind_of(Integer)
619
+ expect(func.num_arguments).to be(3)
620
+ end
621
+ end
622
+
623
+ describe '#result_type' do
624
+ let(:func) { find_matching(cursor_cxx) { |child, parent|
625
+ child.kind == :cursor_function and child.spelling == 'f_non_variadic' } }
626
+
627
+ it "result the result type of the function" do
628
+ expect(func.result_type).to be_kind_of(Type)
629
+ expect(func.result_type.kind).to be(:type_void)
630
+ end
631
+ end
632
+
633
+ describe '#raw_comment_text' do
634
+ let(:func) { find_matching(cursor_pp) { |child, parent|
635
+ child.kind == :cursor_function and child.spelling == 'a_function' } }
636
+
637
+ it "checks the cursor is declaration" do
638
+ expect(func.raw_comment_text).to be_kind_of(String)
639
+ expect(func.raw_comment_text).not_to be_empty
640
+ end
641
+ end
642
+
643
+ describe '#comment' do
644
+ let(:func) { find_matching(cursor_pp) { |child, parent|
645
+ child.kind == :cursor_function and child.spelling == 'a_function' } }
646
+
647
+ it "checks the cursor is declaration" do
648
+ expect(func.comment).to be_kind_of(Comment)
649
+ end
650
+ end
651
+
652
+ describe '#included_file' do
653
+ let (:inclusion) { find_first(cursor_pp, :cursor_inclusion_directive) }
654
+
655
+ it 'returns the file that is included by the given inclusion directive cursor' do
656
+ expect(inclusion.included_file).to be_kind_of(FFI::Clang::File)
657
+ expect(File.basename(inclusion.included_file.name)).to eq("docs.h")
658
+ end
659
+ end
660
+
661
+ describe Cursor::PlatformAvailability do
662
+ let(:func) { find_matching(cursor_cxx) { |child, parent|
663
+ child.kind == :cursor_function and child.spelling == 'availability_func'} }
664
+ let(:availability) { func.platform_availability[:availability].first }
665
+
666
+ it "can be obtained by Cursor#platform_availability" do
667
+ expect(availability).to be_kind_of(Cursor::PlatformAvailability)
668
+ end
669
+
670
+ describe "#platform" do
671
+ it "returns availability information for the platform" do
672
+ expect(availability.platform).to be_kind_of(String)
673
+ end
674
+ end
675
+
676
+ describe "#introduced" do
677
+ it "returns the version number in which this entity was introduced" do
678
+ expect(availability.introduced).to be_kind_of(Lib::CXVersion)
679
+ expect(availability.introduced.to_s).to eq("10.4.1")
680
+ end
681
+ end
682
+
683
+ describe "#deprecated" do
684
+ it "returns the version number in which this entity was deprecated" do
685
+ expect(availability.deprecated).to be_kind_of(Lib::CXVersion)
686
+ expect(availability.deprecated.to_s).to eq("10.6")
687
+ end
688
+ end
689
+
690
+ describe "#obsoleted" do
691
+ it "returns the version number in which this entity was obsoleted" do
692
+ expect(availability.obsoleted).to be_kind_of(Lib::CXVersion)
693
+ expect(availability.obsoleted.to_s).to eq("10.7")
694
+ end
695
+ end
696
+
697
+ describe "#unavailable" do
698
+ it "returns whether the entity is unavailable on this platform" do
699
+ expect(availability.unavailable).to be_false
700
+ end
701
+ end
702
+
703
+ describe "#message" do
704
+ it "returns an optional message to provide to a user of this API" do
705
+ expect(availability.message).to be_kind_of(String)
706
+ end
707
+ end
708
+ end
709
+ end