ffi-clang 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +12 -8
  3. data/README.md +3 -1
  4. data/ffi-clang.gemspec +1 -1
  5. data/lib/ffi/clang.rb +3 -1
  6. data/lib/ffi/clang/code_completion.rb +193 -0
  7. data/lib/ffi/clang/comment.rb +154 -11
  8. data/lib/ffi/clang/compilation_database.rb +125 -0
  9. data/lib/ffi/clang/cursor.rb +145 -9
  10. data/lib/ffi/clang/diagnostic.rb +36 -10
  11. data/lib/ffi/clang/file.rb +69 -0
  12. data/lib/ffi/clang/index.rb +9 -17
  13. data/lib/ffi/clang/lib.rb +25 -2
  14. data/lib/ffi/clang/lib/code_completion.rb +130 -0
  15. data/lib/ffi/clang/lib/comment.rb +73 -12
  16. data/lib/ffi/clang/lib/compilation_database.rb +58 -0
  17. data/lib/ffi/clang/lib/cursor.rb +78 -14
  18. data/lib/ffi/clang/lib/diagnostic.rb +32 -12
  19. data/lib/ffi/clang/lib/file.rb +15 -3
  20. data/lib/ffi/clang/lib/inclusions.rb +32 -0
  21. data/lib/ffi/clang/lib/source_location.rb +18 -0
  22. data/lib/ffi/clang/lib/source_range.rb +5 -0
  23. data/lib/ffi/clang/lib/token.rb +58 -0
  24. data/lib/ffi/clang/lib/translation_unit.rb +71 -1
  25. data/lib/ffi/clang/lib/type.rb +61 -3
  26. data/lib/ffi/clang/source_location.rb +102 -0
  27. data/lib/ffi/clang/source_range.rb +25 -4
  28. data/lib/ffi/clang/token.rb +95 -0
  29. data/lib/ffi/clang/translation_unit.rb +118 -2
  30. data/lib/ffi/clang/type.rb +61 -0
  31. data/lib/ffi/clang/unsaved_file.rb +16 -0
  32. data/lib/ffi/clang/utils.rb +38 -12
  33. data/lib/ffi/clang/version.rb +1 -1
  34. data/spec/clang/code_completion_spec.rb +181 -0
  35. data/spec/clang/comment_spec.rb +385 -12
  36. data/spec/clang/compilation_database_spec.rb +178 -0
  37. data/spec/clang/cursor_spec.rb +335 -12
  38. data/spec/clang/diagnostic_spec.rb +63 -4
  39. data/spec/clang/file_spec.rb +84 -0
  40. data/spec/clang/index_spec.rb +62 -5
  41. data/spec/clang/source_location_spec.rb +104 -4
  42. data/spec/clang/source_range_spec.rb +76 -0
  43. data/spec/clang/token_spec.rb +84 -0
  44. data/spec/clang/translation_unit_spec.rb +202 -5
  45. data/spec/clang/type_spec.rb +191 -0
  46. data/spec/clang/utils_spec.rb +2 -3
  47. data/spec/fixtures/a.c +3 -0
  48. data/spec/fixtures/compile_commands.json +17 -0
  49. data/spec/fixtures/completion.cxx +8 -0
  50. data/spec/fixtures/docs.c +1 -0
  51. data/spec/fixtures/docs.cc +1 -0
  52. data/spec/fixtures/docs.h +46 -3
  53. data/spec/fixtures/list.c +1 -0
  54. data/spec/fixtures/location1.c +7 -0
  55. data/spec/fixtures/simple.c +3 -0
  56. data/spec/fixtures/test.cxx +36 -0
  57. data/spec/spec_helper.rb +11 -0
  58. metadata +50 -21
@@ -0,0 +1,84 @@
1
+ # Copyright, 2014, by Masahiro Sano.
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'spec_helper'
22
+
23
+ describe Tokens do
24
+ let(:tu) { Index.new.parse_translation_unit(fixture_path("list.c")) }
25
+ let(:cursor) { tu.cursor }
26
+ let(:range) { find_first(cursor, :cursor_struct).extent }
27
+ let(:tokens) { tu.tokenize(range) }
28
+
29
+ it "can be obtained from a translation unit" do
30
+ expect(tokens).to be_kind_of(Tokens)
31
+ expect(tokens.size).to eq(13)
32
+ expect(tokens.tokens).to be_kind_of(Array)
33
+ expect(tokens.tokens.first).to be_kind_of(Token)
34
+ end
35
+
36
+ it "calls dispose_tokens on GC" do
37
+ tokens.autorelease = false
38
+ expect(Lib).to receive(:dispose_tokens).at_least(:once)
39
+ expect{tokens.free}.not_to raise_error
40
+ end
41
+
42
+ it "#each" do
43
+ spy = double(stub: nil)
44
+ expect(spy).to receive(:stub).exactly(tokens.size).times
45
+ tokens.each { spy.stub }
46
+ end
47
+
48
+ it "#cursors" do
49
+ expect(tokens.cursors).to be_kind_of(Array)
50
+ expect(tokens.cursors.size).to eq(tokens.size)
51
+ expect(tokens.cursors.first).to be_kind_of(Cursor)
52
+ end
53
+ end
54
+
55
+ describe Token do
56
+ let(:tu) { Index.new.parse_translation_unit(fixture_path("list.c")) }
57
+ let(:cursor) { tu.cursor }
58
+ let(:range) { find_first(cursor, :cursor_struct).extent }
59
+ let(:token) { tu.tokenize(range).first }
60
+
61
+ it "can be obtained from a translation unit" do
62
+ expect(token).to be_kind_of(Token)
63
+ end
64
+
65
+ it "#kind" do
66
+ expect(token.kind).to be_kind_of(Symbol)
67
+ expect(token.kind).to eq(:keyword)
68
+ end
69
+
70
+ it "#spelling" do
71
+ expect(token.spelling).to be_kind_of(String)
72
+ expect(token.spelling).to eq('struct')
73
+ end
74
+
75
+ it "#location" do
76
+ expect(token.location).to be_kind_of(SourceLocation)
77
+ expect(token.location.line).to eq(1)
78
+ end
79
+
80
+ it "#extent" do
81
+ expect(token.extent).to be_kind_of(SourceRange)
82
+ expect(token.extent.start.line).to eq(1)
83
+ end
84
+ end
@@ -1,19 +1,216 @@
1
+ # Copyright, 2014, by Masahiro Sano.
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
1
21
  require 'spec_helper'
2
22
 
3
23
  describe TranslationUnit do
4
- let(:tu) { Index.new.parse_translation_unit fixture_path("a.c") }
24
+ before :all do
25
+ FileUtils.mkdir_p TMP_DIR
26
+ end
27
+
28
+ after :all do
29
+ FileUtils.rm_rf TMP_DIR
30
+ end
31
+
32
+ let(:tu) { Index.new.parse_translation_unit fixture_path("a.c") }
5
33
 
6
34
  it "returns a list of diagnostics" do
7
35
  diags = tu.diagnostics
8
- diags.should be_kind_of(Array)
9
- diags.should_not be_empty
36
+ expect(diags).to be_kind_of(Array)
37
+ expect(diags).to_not be_empty
10
38
  end
11
39
 
12
40
  it "returns a list of diagnostics from an unsaved file" do
13
41
  file = UnsavedFile.new("a.c", File.read(fixture_path("a.c")))
14
42
  tu = Index.new.parse_translation_unit("a.c", nil,[file])
15
43
  diags = tu.diagnostics
16
- diags.should be_kind_of(Array)
17
- diags.should_not be_empty
44
+ expect(diags).to be_kind_of(Array)
45
+ expect(diags).to_not be_empty
46
+ end
47
+
48
+ it "calls dispose_translation_unit on GC" do
49
+ tu.autorelease = false
50
+ expect(Lib).to receive(:dispose_translation_unit).with(tu).once
51
+ expect{tu.free}.not_to raise_error
52
+ end
53
+
54
+ describe "#spelling" do
55
+ let (:spelling) { tu.spelling }
56
+
57
+ it "returns own filename" do
58
+ expect(spelling).to be_kind_of(String)
59
+ expect(spelling).to eq(fixture_path("a.c"))
60
+ end
61
+ end
62
+
63
+ describe "#file" do
64
+ let (:file) { tu.file(fixture_path("a.c")) }
65
+
66
+ it "returns File instance" do
67
+ expect(file).to be_kind_of(FFI::Clang::File)
68
+ end
69
+ end
70
+
71
+ describe "#location" do
72
+ let(:file) { tu.file(fixture_path("a.c")) }
73
+ let(:column) { 12 }
74
+ let(:location) { tu.location(file, 1, column) }
75
+
76
+ it "returns source location at a specific point" do
77
+ expect(location).to be_kind_of(SourceLocation)
78
+ expect(location.file).to eq(fixture_path("a.c"))
79
+ expect(location.line).to eq(1)
80
+ expect(location.column).to eq(column)
81
+ end
82
+ end
83
+
84
+ describe "#location_offset" do
85
+ let(:file) { tu.file(fixture_path("a.c")) }
86
+ let(:offset) { 10 }
87
+ let(:location) { tu.location_offset(file, offset) }
88
+
89
+ it "returns source location at a specific offset point" do
90
+ expect(location).to be_kind_of(SourceLocation)
91
+ expect(location.file).to eq(fixture_path("a.c"))
92
+ expect(location.column).to eq(offset+1)
93
+ end
94
+ end
95
+
96
+ describe "#cursor" do
97
+ let(:cursor) { tu.cursor }
98
+ let(:location) { tu.location(tu.file(fixture_path("a.c")), 1, 10) }
99
+ let(:cursor_with_loc) { tu.cursor(location) }
100
+
101
+ it "returns translation unit cursor if no arguments are specified" do
102
+ expect(cursor).to be_kind_of(Cursor)
103
+ expect(cursor.kind).to eq(:cursor_translation_unit)
104
+ end
105
+
106
+ it "returns a correspond cursor if a source location is passed" do
107
+ expect(cursor_with_loc).to be_kind_of(Cursor)
108
+ expect(cursor_with_loc.kind).to eq(:cursor_parm_decl)
109
+ end
110
+ end
111
+
112
+ describe "#self.default_editing_translation_unit_options" do
113
+ let (:opts) { FFI::Clang::TranslationUnit.default_editing_translation_unit_options }
114
+ it "returns hash with symbols of TranslationUnitFlags" do
115
+ expect(opts).to be_kind_of(Hash)
116
+ opts.keys.each { |key|
117
+ expect(FFI::Clang::Lib::TranslationUnitFlags.symbols).to include(key)
118
+ }
119
+ end
120
+ end
121
+
122
+ describe "#default_save_options" do
123
+ let (:opts) { tu.default_save_options }
124
+ it "returns hash with symbols of SaveTranslationUnitFlags" do
125
+ expect(opts).to be_kind_of(Hash)
126
+ opts.keys.each { |key|
127
+ expect(FFI::Clang::Lib::SaveTranslationUnitFlags.symbols).to include(key)
128
+ }
129
+ end
130
+ end
131
+
132
+ describe "#save" do
133
+ let (:filepath) { "#{TMP_DIR}/save_translation_unit" }
134
+ let (:may_not_exist_filepath) { "#{TMP_DIR}/not_writable_directory/save_translation_unit" }
135
+ it "saves translation unit as a file" do
136
+ expect{tu.save(filepath)}.not_to raise_error
137
+ expect(FileTest.exist?(filepath)).to be true
138
+ end
139
+
140
+ it "raises exception if save path is not writable" do
141
+ FileUtils.mkdir_p File.dirname(may_not_exist_filepath)
142
+ File.chmod(0444, File.dirname(may_not_exist_filepath))
143
+ expect{tu.save(may_not_exist_filepath)}.to raise_error
144
+ expect(FileTest.exist?(may_not_exist_filepath)).to be false
145
+ end
146
+ end
147
+
148
+ describe "#default_reparse_options" do
149
+ let (:opts) { tu.default_reparse_options }
150
+ it "returns hash with symbols of ReparseFlags" do
151
+ expect(opts).to be_kind_of(Hash)
152
+ opts.keys.each { |key|
153
+ expect(FFI::Clang::Lib::ReparseFlags.symbols).to include(key)
154
+ }
155
+ end
156
+ end
157
+
158
+ describe "#reparse" do
159
+ let (:path) { "#{TMP_DIR}/reparse_tmp.c" }
160
+ before :each do
161
+ FileUtils.touch path
162
+ @reparse_tu = Index.new.parse_translation_unit(path)
163
+ end
164
+ after :each do
165
+ FileUtils.rm path, :force => true
166
+ end
167
+
168
+ it "recretes translation unit" do
169
+ File::open(path, "w+") { |io|
170
+ io.write("int a;")
171
+ }
172
+ expect(find_first(@reparse_tu.cursor, :cursor_variable)).to be nil
173
+ expect{@reparse_tu.reparse}.not_to raise_error
174
+ expect(find_first(@reparse_tu.cursor, :cursor_variable).spelling).to eq("a")
175
+ end
176
+
177
+ it "raises exception if the file is not found when reparsing" do
178
+ FileUtils.rm path, :force => true
179
+ expect{@reparse_tu.reparse}.to raise_error
180
+ end
181
+ end
182
+
183
+ describe "#resource_usage" do
184
+ let (:ru) { tu.resource_usage }
185
+ it "returns ResourceUsage instance that represents memory usage of TU" do
186
+ expect(ru).to be_kind_of(TranslationUnit::ResourceUsage)
187
+ end
188
+ end
189
+
190
+ describe TranslationUnit::ResourceUsage do
191
+ let (:ru) { tu.resource_usage }
192
+ describe "#entries" do
193
+ let (:entries) { tu.resource_usage.entries }
194
+ it "returns array of CXTUResourceUsageEntry" do
195
+ expect(entries).to be_kind_of(Array)
196
+ expect(entries.first).to be_kind_of(Lib::CXTUResourceUsageEntry)
197
+ expect(entries.first[:kind]).to be_kind_of(Symbol)
198
+ expect(entries.first[:amount]).to be_kind_of(Integer)
199
+ end
200
+ end
201
+
202
+ describe "#self.name" do
203
+ let(:name) { FFI::Clang::TranslationUnit::ResourceUsage.name(:ast) }
204
+ it "returns the name of the memory category" do
205
+ expect(name).to be_kind_of(String)
206
+ end
207
+ end
208
+
209
+ describe "#self.release" do
210
+ it "releases data by calling 'clang_disposeCXTUResourceUsage'" do
211
+ ru.autorelease = false
212
+ expect{ ru.free }.not_to raise_error
213
+ end
214
+ end
18
215
  end
19
216
  end
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # Copyright, 2013, by Carlos Martín Nieto <cmn@dwim.me>
3
+ # Copyright, 2014, by Masahiro Sano.
3
4
  #
4
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
5
6
  # of this software and associated documentation files (the "Software"), to deal
@@ -24,6 +25,7 @@ require 'spec_helper'
24
25
  describe Type do
25
26
  let(:cursor) { Index.new.parse_translation_unit(fixture_path("a.c")).cursor }
26
27
  let(:cursor_cxx) { Index.new.parse_translation_unit(fixture_path("test.cxx")).cursor }
28
+ let(:cursor_list) { Index.new.parse_translation_unit(fixture_path("list.c")).cursor }
27
29
  let(:type) { find_first(cursor, :cursor_function).type }
28
30
 
29
31
  it "can tell us about the main function", from_3_3: true do
@@ -95,4 +97,193 @@ describe Type do
95
97
  pointer_type.const_qualified?.should equal false
96
98
  end
97
99
  end
100
+
101
+ describe '#volatile_qualified?' do
102
+ let(:pointer_type) { find_matching(cursor) { |child, parent|
103
+ child.kind == :cursor_variable and child.spelling == 'volatile_int_ptr'
104
+ }.type }
105
+
106
+ it 'checks type is volatile qualified' do
107
+ expect(pointer_type.volatile_qualified?).to be true
108
+ end
109
+ end
110
+
111
+ describe '#restrict_qualified?' do
112
+ let(:pointer_type) { find_matching(cursor) { |child, parent|
113
+ child.kind == :cursor_variable and child.spelling == 'restrict_int_ptr'
114
+ }.type }
115
+
116
+ it 'checks type is restrict qualified' do
117
+ expect(pointer_type.restrict_qualified?).to be true
118
+ end
119
+ end
120
+
121
+ describe '#element_type' do
122
+ let(:array_type) { find_matching(cursor_cxx) { |child, parent|
123
+ child.kind == :cursor_variable and child.spelling == 'int_array'
124
+ }.type }
125
+
126
+ it 'returns the element type of the array type' do
127
+ expect(array_type.element_type).to be_kind_of(Type)
128
+ expect(array_type.element_type.kind).to eq(:type_int)
129
+ end
130
+ end
131
+
132
+ describe '#num_elements' do
133
+ let(:array_type) { find_matching(cursor_cxx) { |child, parent|
134
+ child.kind == :cursor_variable and child.spelling == 'int_array'
135
+ }.type }
136
+
137
+ it 'returns the number of elements of the array' do
138
+ expect(array_type.num_elements).to eq(8)
139
+ end
140
+ end
141
+
142
+ describe '#array_element_type' do
143
+ let(:array_type) { find_matching(cursor_cxx) { |child, parent|
144
+ child.kind == :cursor_variable and child.spelling == 'int_array'
145
+ }.type }
146
+
147
+ it 'returns the array element type of the array type' do
148
+ expect(array_type.array_element_type).to be_kind_of(Type)
149
+ expect(array_type.array_element_type.kind).to eq(:type_int)
150
+ end
151
+ end
152
+
153
+ describe '#array_size' do
154
+ let(:array_type) { find_matching(cursor_cxx) { |child, parent|
155
+ child.kind == :cursor_variable and child.spelling == 'int_array'
156
+ }.type }
157
+
158
+ it 'returns the number of elements of the array' do
159
+ expect(array_type.array_size).to eq(8)
160
+ end
161
+ end
162
+
163
+ describe '#alignof', from_3_3: true do
164
+ let(:array_type) { find_matching(cursor_cxx) { |child, parent|
165
+ child.kind == :cursor_variable and child.spelling == 'int_array'
166
+ }.type }
167
+
168
+ it 'returns the alignment of the type in bytes' do
169
+ expect(array_type.alignof).to be_kind_of(Integer)
170
+ expect(array_type.alignof).to be > 0
171
+ end
172
+ end
173
+
174
+ describe '#sizeof', from_3_3: true do
175
+ let(:array_type) { find_matching(cursor_cxx) { |child, parent|
176
+ child.kind == :cursor_variable and child.spelling == 'int_array'
177
+ }.type }
178
+
179
+ it 'returns the size of the type in bytes' do
180
+ expect(array_type.sizeof).to be_kind_of(Integer)
181
+ expect(array_type.sizeof).to be(32)
182
+ end
183
+ end
184
+
185
+ describe '#offsetof', from_3_3: true do
186
+ let(:struct) { find_matching(cursor_list) { |child, parent|
187
+ child.kind == :cursor_struct and child.spelling == 'List'
188
+ }.type }
189
+
190
+ it 'returns the offset of a field in a record of the type in bits' do
191
+ expect(struct.offsetof('Next')).to be_kind_of(Integer)
192
+ expect(struct.offsetof('Next')).to be(64)
193
+ end
194
+ end
195
+
196
+ describe '#ref_qualifier', from_3_4: true do
197
+ let(:lvalue) { find_matching(cursor_cxx) { |child, parent|
198
+ child.kind == :cursor_cxx_method and child.spelling == 'func_lvalue_ref'
199
+ }.type }
200
+ let(:rvalue) { find_matching(cursor_cxx) { |child, parent|
201
+ child.kind == :cursor_cxx_method and child.spelling == 'func_rvalue_ref'
202
+ }.type }
203
+ let(:none) { find_matching(cursor_cxx) { |child, parent|
204
+ child.kind == :cursor_cxx_method and child.spelling == 'func_none'
205
+ }.type }
206
+
207
+ it 'returns :ref_qualifier_lvalue the type is ref-qualified with lvalue' do
208
+ expect(lvalue.ref_qualifier).to be(:ref_qualifier_lvalue)
209
+ end
210
+
211
+ it 'returns :ref_qualifier_rvalue the type is ref-qualified with rvalue' do
212
+ expect(rvalue.ref_qualifier).to be(:ref_qualifier_rvalue)
213
+ end
214
+
215
+ it 'returns :ref_qualifier_none the type is not ref-qualified' do
216
+ expect(none.ref_qualifier).to be(:ref_qualifier_none)
217
+ end
218
+ end
219
+
220
+ describe '#pod?' do
221
+ let(:struct) { find_matching(cursor_list) { |child, parent|
222
+ child.kind == :cursor_struct and child.spelling == 'List'
223
+ }.type }
224
+
225
+ it 'returns true if the type is a POD type' do
226
+ expect(struct.pod?).to be true
227
+ end
228
+ end
229
+
230
+ describe '#class_type', from_3_4: true do
231
+ let(:member_pointer) { find_matching(cursor_cxx) { |child, parent|
232
+ child.kind == :cursor_variable and child.spelling == 'member_pointer'
233
+ }.type }
234
+
235
+ it 'returns the class type of the member pointer type' do
236
+ expect(member_pointer.class_type).to be_kind_of(Type)
237
+ expect(member_pointer.class_type.kind).to be(:type_record)
238
+ expect(member_pointer.class_type.spelling).to eq('A')
239
+ end
240
+ end
241
+
242
+ describe '#declaration' do
243
+ let(:struct_ref) { find_matching(cursor_cxx) { |child, parent|
244
+ child.kind == :cursor_type_ref and child.spelling == 'struct D'
245
+ }.type }
246
+ let(:struct_decl) { find_matching(cursor_cxx) { |child, parent|
247
+ child.kind == :cursor_struct and child.spelling == 'D'
248
+ } }
249
+ let(:no_decl) { find_first(cursor_cxx, :cursor_cxx_method).type }
250
+
251
+ it 'returns the class type of the member pointer type' do
252
+ expect(struct_ref.declaration).to be_kind_of(Cursor)
253
+ expect(struct_ref.declaration.kind).to be(:cursor_struct)
254
+ expect(struct_ref.declaration).to eq(struct_decl)
255
+ end
256
+
257
+ it 'returns :cursor_no_decl_found if the type has no declaration' do
258
+ expect(no_decl.declaration).to be_kind_of(Cursor)
259
+ expect(no_decl.declaration.kind).to be(:cursor_no_decl_found)
260
+ end
261
+ end
262
+
263
+ describe '#calling_conv' do
264
+ let(:function) { find_matching(cursor_cxx) { |child, parent|
265
+ child.kind == :cursor_function and child.spelling == 'f_variadic'
266
+ }.type }
267
+
268
+ it 'returns the calling convention associated with the function type', from_3_4: true do
269
+ expect(function.calling_conv).to be(:calling_conv_c)
270
+ end
271
+
272
+ it 'returns the calling convention associated with the function type', upto_3_3: true do
273
+ expect(function.calling_conv).to be(:calling_conv_default)
274
+ end
275
+ end
276
+
277
+ describe '#==' do
278
+ let(:type_decl) { find_matching(cursor_cxx) { |child, parent|
279
+ child.kind == :cursor_field_decl and child.spelling == 'int_member_a'
280
+ }.type }
281
+ let(:type_ref) { find_matching(cursor_cxx) { |child, parent|
282
+ child.kind == :cursor_decl_ref_expr and child.spelling == 'int_member_a'
283
+ }.type }
284
+
285
+ it 'checks if two types represent the same type' do
286
+ expect(type_decl == type_ref).to be true
287
+ end
288
+ end
98
289
  end