ffi-clang 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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