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,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