ghazel-ffi-clang 0.2.0.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 (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,83 @@
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
+ expect(Lib).to receive(:dispose_tokens).at_least(:once)
38
+ expect{tokens.free}.not_to raise_error
39
+ end
40
+
41
+ it "#each" do
42
+ spy = double(stub: nil)
43
+ expect(spy).to receive(:stub).exactly(tokens.size).times
44
+ tokens.each { spy.stub }
45
+ end
46
+
47
+ it "#cursors" do
48
+ expect(tokens.cursors).to be_kind_of(Array)
49
+ expect(tokens.cursors.size).to eq(tokens.size)
50
+ expect(tokens.cursors.first).to be_kind_of(Cursor)
51
+ end
52
+ end
53
+
54
+ describe Token do
55
+ let(:tu) { Index.new.parse_translation_unit(fixture_path("list.c")) }
56
+ let(:cursor) { tu.cursor }
57
+ let(:range) { find_first(cursor, :cursor_struct).extent }
58
+ let(:token) { tu.tokenize(range).first }
59
+
60
+ it "can be obtained from a translation unit" do
61
+ expect(token).to be_kind_of(Token)
62
+ end
63
+
64
+ it "#kind" do
65
+ expect(token.kind).to be_kind_of(Symbol)
66
+ expect(token.kind).to eq(:keyword)
67
+ end
68
+
69
+ it "#spelling" do
70
+ expect(token.spelling).to be_kind_of(String)
71
+ expect(token.spelling).to eq('struct')
72
+ end
73
+
74
+ it "#location" do
75
+ expect(token.location).to be_kind_of(SourceLocation)
76
+ expect(token.location.line).to eq(1)
77
+ end
78
+
79
+ it "#extent" do
80
+ expect(token.extent).to be_kind_of(SourceRange)
81
+ expect(token.extent.start.line).to eq(1)
82
+ end
83
+ end
@@ -0,0 +1,214 @@
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 TranslationUnit do
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") }
33
+
34
+ it "returns a list of diagnostics" do
35
+ diags = tu.diagnostics
36
+ expect(diags).to be_kind_of(Array)
37
+ expect(diags).to_not be_empty
38
+ end
39
+
40
+ it "returns a list of diagnostics from an unsaved file" do
41
+ file = UnsavedFile.new("a.c", File.read(fixture_path("a.c")))
42
+ tu = Index.new.parse_translation_unit("a.c", nil,[file])
43
+ diags = tu.diagnostics
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
+ expect(Lib).to receive(:dispose_translation_unit).with(tu)
50
+ expect{tu.free}.not_to raise_error
51
+ end
52
+
53
+ describe "#spelling" do
54
+ let (:spelling) { tu.spelling }
55
+
56
+ it "returns own filename" do
57
+ expect(spelling).to be_kind_of(String)
58
+ expect(spelling).to eq(fixture_path("a.c"))
59
+ end
60
+ end
61
+
62
+ describe "#file" do
63
+ let (:file) { tu.file(fixture_path("a.c")) }
64
+
65
+ it "returns File instance" do
66
+ expect(file).to be_kind_of(FFI::Clang::File)
67
+ end
68
+ end
69
+
70
+ describe "#location" do
71
+ let(:file) { tu.file(fixture_path("a.c")) }
72
+ let(:column) { 12 }
73
+ let(:location) { tu.location(file, 1, column) }
74
+
75
+ it "returns source location at a specific point" do
76
+ expect(location).to be_kind_of(SourceLocation)
77
+ expect(location.file).to eq(fixture_path("a.c"))
78
+ expect(location.line).to eq(1)
79
+ expect(location.column).to eq(column)
80
+ end
81
+ end
82
+
83
+ describe "#location_offset" do
84
+ let(:file) { tu.file(fixture_path("a.c")) }
85
+ let(:offset) { 10 }
86
+ let(:location) { tu.location_offset(file, offset) }
87
+
88
+ it "returns source location at a specific offset point" do
89
+ expect(location).to be_kind_of(SourceLocation)
90
+ expect(location.file).to eq(fixture_path("a.c"))
91
+ expect(location.column).to eq(offset+1)
92
+ end
93
+ end
94
+
95
+ describe "#cursor" do
96
+ let(:cursor) { tu.cursor }
97
+ let(:location) { tu.location(tu.file(fixture_path("a.c")), 1, 10) }
98
+ let(:cursor_with_loc) { tu.cursor(location) }
99
+
100
+ it "returns translation unit cursor if no arguments are specified" do
101
+ expect(cursor).to be_kind_of(Cursor)
102
+ expect(cursor.kind).to eq(:cursor_translation_unit)
103
+ end
104
+
105
+ it "returns a correspond cursor if a source location is passed" do
106
+ expect(cursor_with_loc).to be_kind_of(Cursor)
107
+ expect(cursor_with_loc.kind).to eq(:cursor_parm_decl)
108
+ end
109
+ end
110
+
111
+ describe "#self.default_editing_translation_unit_options" do
112
+ let (:opts) { FFI::Clang::TranslationUnit.default_editing_translation_unit_options }
113
+ it "returns hash with symbols of TranslationUnitFlags" do
114
+ expect(opts).to be_kind_of(Hash)
115
+ opts.keys.each { |key|
116
+ expect(FFI::Clang::Lib::TranslationUnitFlags.symbols).to include(key)
117
+ }
118
+ end
119
+ end
120
+
121
+ describe "#default_save_options" do
122
+ let (:opts) { tu.default_save_options }
123
+ it "returns hash with symbols of SaveTranslationUnitFlags" do
124
+ expect(opts).to be_kind_of(Hash)
125
+ opts.keys.each { |key|
126
+ expect(FFI::Clang::Lib::SaveTranslationUnitFlags.symbols).to include(key)
127
+ }
128
+ end
129
+ end
130
+
131
+ describe "#save" do
132
+ let (:filepath) { "#{TMP_DIR}/save_translation_unit" }
133
+ let (:may_not_exist_filepath) { "#{TMP_DIR}/not_writable_directory/save_translation_unit" }
134
+ it "saves translation unit as a file" do
135
+ expect{tu.save(filepath)}.not_to raise_error
136
+ expect(FileTest.exist?(filepath)).to be_true
137
+ end
138
+
139
+ it "raises exception if save path is not writable" do
140
+ FileUtils.mkdir_p File.dirname(may_not_exist_filepath)
141
+ File.chmod(0444, File.dirname(may_not_exist_filepath))
142
+ expect{tu.save(may_not_exist_filepath)}.to raise_error
143
+ expect(FileTest.exist?(may_not_exist_filepath)).to be_false
144
+ end
145
+ end
146
+
147
+ describe "#default_reparse_options" do
148
+ let (:opts) { tu.default_reparse_options }
149
+ it "returns hash with symbols of ReparseFlags" do
150
+ expect(opts).to be_kind_of(Hash)
151
+ opts.keys.each { |key|
152
+ expect(FFI::Clang::Lib::ReparseFlags.symbols).to include(key)
153
+ }
154
+ end
155
+ end
156
+
157
+ describe "#reparse" do
158
+ let (:path) { "#{TMP_DIR}/reparse_tmp.c" }
159
+ before :each do
160
+ FileUtils.touch path
161
+ @reparse_tu = Index.new.parse_translation_unit(path)
162
+ end
163
+ after :each do
164
+ FileUtils.rm path, :force => true
165
+ end
166
+
167
+ it "recretes translation unit" do
168
+ File::open(path, "w+") { |io|
169
+ io.write("int a;")
170
+ }
171
+ expect(find_first(@reparse_tu.cursor, :cursor_variable)).to be_false
172
+ expect{@reparse_tu.reparse}.not_to raise_error
173
+ expect(find_first(@reparse_tu.cursor, :cursor_variable).spelling).to eq("a")
174
+ end
175
+
176
+ it "raises exception if the file is not found when reparsing" do
177
+ FileUtils.rm path, :force => true
178
+ expect{@reparse_tu.reparse}.to raise_error
179
+ end
180
+ end
181
+
182
+ describe "#resource_usage" do
183
+ let (:ru) { tu.resource_usage }
184
+ it "returns ResourceUsage instance that represents memory usage of TU" do
185
+ expect(ru).to be_kind_of(TranslationUnit::ResourceUsage)
186
+ end
187
+ end
188
+
189
+ describe TranslationUnit::ResourceUsage do
190
+ let (:ru) { tu.resource_usage }
191
+ describe "#entries" do
192
+ let (:entries) { tu.resource_usage.entries }
193
+ it "returns array of CXTUResourceUsageEntry" do
194
+ expect(entries).to be_kind_of(Array)
195
+ expect(entries.first).to be_kind_of(Lib::CXTUResourceUsageEntry)
196
+ expect(entries.first[:kind]).to be_kind_of(Symbol)
197
+ expect(entries.first[:amount]).to be_kind_of(Integer)
198
+ end
199
+ end
200
+
201
+ describe "#self.name" do
202
+ let(:name) { FFI::Clang::TranslationUnit::ResourceUsage.name(:ast) }
203
+ it "returns the name of the memory category" do
204
+ expect(name).to be_kind_of(String)
205
+ end
206
+ end
207
+
208
+ describe "#self.release" do
209
+ it "releases data by calling 'clang_disposeCXTUResourceUsage'" do
210
+ expect{ ru.free }.not_to raise_error
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,289 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright, 2013, by Carlos Martín Nieto <cmn@dwim.me>
3
+ # Copyright, 2014, by Masahiro Sano.
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require 'spec_helper'
24
+
25
+ describe Type do
26
+ let(:cursor) { Index.new.parse_translation_unit(fixture_path("a.c")).cursor }
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 }
29
+ let(:type) { find_first(cursor, :cursor_function).type }
30
+
31
+ it "can tell us about the main function", from_3_3: true do
32
+ type.variadic?.should equal(false)
33
+
34
+ type.num_arg_types.should equal(2)
35
+ type.arg_type(0).spelling.should eq("int")
36
+ type.arg_type(1).spelling.should eq("const char *")
37
+ type.result_type.spelling.should eq("int")
38
+ end
39
+
40
+ describe '#kind_spelling' do
41
+ let(:kind_spelling_type) { find_matching(cursor_cxx) { |child, parent|
42
+ child.kind == :cursor_typedef_decl and child.spelling == 'const_int_ptr'}.type }
43
+
44
+ it 'returns type kind name with string' do
45
+ kind_spelling_type.kind_spelling.should eq 'Typedef'
46
+ end
47
+ end
48
+
49
+ describe '#canonical' do
50
+ let(:canonical_type) { find_matching(cursor_cxx) { |child, parent|
51
+ child.kind == :cursor_typedef_decl and child.spelling == 'const_int_ptr'
52
+ }.type.canonical }
53
+
54
+ it 'extracts typedef', upto_3_2: true do
55
+ expect(canonical_type).to be_kind_of(Type)
56
+ expect(canonical_type.kind).to be(:type_pointer)
57
+ end
58
+
59
+ it 'extracts typedef', from_3_3: true do
60
+ expect(canonical_type).to be_kind_of(Type)
61
+ expect(canonical_type.kind).to be(:type_pointer)
62
+ expect(canonical_type.spelling).to eq('const int *')
63
+ end
64
+ end
65
+
66
+ describe '#pointee' do
67
+ let(:pointee_type) { find_matching(cursor_cxx) { |child, parent|
68
+ child.kind == :cursor_typedef_decl and child.spelling == 'const_int_ptr'
69
+ }.type.canonical.pointee }
70
+
71
+ it 'gets pointee type of pointer, C++ reference', upto_3_2: true do
72
+ expect(pointee_type).to be_kind_of(Type)
73
+ expect(pointee_type.kind).to be(:type_int)
74
+ end
75
+
76
+ it 'gets pointee type of pointer, C++ reference', from_3_3: true do
77
+ expect(pointee_type).to be_kind_of(Type)
78
+ expect(pointee_type.kind).to be(:type_int)
79
+ expect(pointee_type.spelling).to eq('const int')
80
+ end
81
+ end
82
+
83
+ describe '#const_qualified?' do
84
+ let(:pointer_type) { find_matching(cursor_cxx) { |child, parent|
85
+ child.kind == :cursor_typedef_decl and child.spelling == 'const_int_ptr'
86
+ }.type.canonical }
87
+
88
+ let(:pointee_type) { find_matching(cursor_cxx) { |child, parent|
89
+ child.kind == :cursor_typedef_decl and child.spelling == 'const_int_ptr'
90
+ }.type.canonical.pointee }
91
+
92
+ it 'checks type is const qualified' do
93
+ pointee_type.const_qualified?.should equal true
94
+ end
95
+
96
+ it 'cannot check whether pointee type is const qualified' do
97
+ pointer_type.const_qualified?.should equal false
98
+ end
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
289
+ end