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
@@ -21,6 +21,6 @@
21
21
 
22
22
  module FFI
23
23
  module Clang
24
- VERSION = "0.2.0"
24
+ VERSION = "0.2.1"
25
25
  end
26
26
  end
@@ -0,0 +1,181 @@
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 CodeCompletion do
24
+ let(:filename) { fixture_path("completion.cxx") }
25
+ let(:tu) { Index.new.parse_translation_unit(filename) }
26
+ let(:line) { 7 }
27
+ let(:column) { 6 }
28
+ let(:results) { tu.code_complete(filename, line, column) }
29
+
30
+ describe "self.default_code_completion_options" do
31
+ let(:options) { FFI::Clang::CodeCompletion.default_code_completion_options }
32
+ it "returns a default set of code-completion options" do
33
+ expect(options).to be_kind_of(Hash)
34
+ options.keys.each { |key|
35
+ expect(FFI::Clang::Lib::CodeCompleteFlags.symbols).to include(key)
36
+ }
37
+ end
38
+ end
39
+
40
+ describe CodeCompletion::Results do
41
+ it "can be obtained from a translation unit" do
42
+ expect(results).to be_kind_of(CodeCompletion::Results)
43
+
44
+ # At least 40 results, depends on standard library implementation:
45
+ expect(results.size).to be >= 40
46
+
47
+ expect(results.results).to be_kind_of(Array)
48
+ expect(results.results.first).to be_kind_of(CodeCompletion::Result)
49
+ end
50
+
51
+ it "calls dispose_code_complete_results on GC" do
52
+ expect(Lib).to receive(:dispose_code_complete_results).at_least(:once)
53
+ expect{results.free}.not_to raise_error
54
+ end
55
+
56
+ it "#each" do
57
+ spy = double(stub: nil)
58
+ expect(spy).to receive(:stub).exactly(results.size).times
59
+ results.each { spy.stub }
60
+ end
61
+
62
+ it "#num_diagnostics" do
63
+ expect(results.num_diagnostics).to eq(2)
64
+ end
65
+
66
+ it "#diagnostic" do
67
+ expect(results.diagnostic(0)).to be_kind_of(Diagnostic)
68
+ end
69
+
70
+ it "#diagnostics" do
71
+ expect(results.diagnostics).to be_kind_of(Array)
72
+ expect(results.diagnostics.first).to be_kind_of(Diagnostic)
73
+ expect(results.diagnostics.size).to eq(results.num_diagnostics)
74
+ end
75
+
76
+ it "#contexts" do
77
+ expect(results.contexts).to be_kind_of(Hash)
78
+ results.contexts.keys.each { |key|
79
+ expect(FFI::Clang::Lib::CompletionContext.symbols).to include(key)
80
+ }
81
+ end
82
+
83
+ it "#container_usr" do
84
+ expect(results.container_usr).to be_kind_of(String)
85
+ expect(results.container_usr).to match(/std.+vector/)
86
+ end
87
+
88
+ it "#container_kind" do
89
+ expect(results.container_kind).to be_kind_of(Symbol)
90
+ expect(results.container_kind).to eq(:cursor_class_decl)
91
+ end
92
+
93
+ it "#incomplete?" do
94
+ expect(results.incomplete?).to be false
95
+ end
96
+
97
+ it "#objc_selector" do
98
+ #TODO
99
+ end
100
+
101
+ it "#sort!" do
102
+ results.sort!
103
+
104
+ # may be sorted with typed_text kind, first result will start with 'a'
105
+ expect(results.results.first.string.chunks.select{|x| x[:kind] == :typed_text}.first[:text]).to be =~ /^a/
106
+ end
107
+ end
108
+
109
+ describe CodeCompletion::Result do
110
+ let(:result) { results.results.first }
111
+ it "#string" do
112
+ expect(result.string).to be_kind_of(CodeCompletion::String)
113
+ end
114
+
115
+ it "#kind" do
116
+ expect(result.kind).to be_kind_of(Symbol)
117
+ end
118
+ end
119
+
120
+ describe CodeCompletion::String do
121
+ let(:str) { results.sort!; results.find{|x| x.string.chunk_text(1) == 'assign'}.string }
122
+
123
+ it "#num_chunks" do
124
+ expect(str.num_chunks).to be >= 5
125
+ end
126
+
127
+ it "#chunk_kind" do
128
+ expect(str.chunk_kind(0)).to eq(:result_type)
129
+ expect(str.chunk_kind(1)).to eq(:typed_text)
130
+ end
131
+
132
+ it "#chunk_text" do
133
+ expect(str.chunk_text(0)).to be =~ /void/
134
+ expect(str.chunk_text(1)).to eq('assign')
135
+ end
136
+
137
+ it "#chunk_completion" do
138
+ expect(str.chunk_completion(0)).to be_kind_of(CodeCompletion::String)
139
+ end
140
+
141
+ it "#chunks" do
142
+ expect(str.chunks).to be_kind_of(Array)
143
+ expect(str.chunks.first).to be_kind_of(Hash)
144
+ expect(str.chunks.size).to eq(str.num_chunks)
145
+ end
146
+
147
+ it "#priority" do
148
+ expect(str.priority).to be_kind_of(Integer)
149
+ end
150
+
151
+ it "#availability" do
152
+ expect(str.availability).to be_kind_of(Symbol)
153
+ expect(str.availability).to eq(:available)
154
+ end
155
+
156
+ it "#num_annotations" do
157
+ expect(str.num_annotations).to be_kind_of(Integer)
158
+ expect(str.num_annotations).to eq(0)
159
+ end
160
+
161
+ it "#annotation" do
162
+ expect(str.annotation(100)).to be_nil
163
+ # TODO: need tests for String which has annotation
164
+ end
165
+
166
+ it "#annotations" do
167
+ expect(str.annotations).to be_kind_of(Array)
168
+ # TODO: need tests for String which has annotation
169
+ end
170
+
171
+ it "#parent" do
172
+ expect(str.parent).to be_kind_of(String)
173
+ expect(str.parent).to be =~ /std.+vector/
174
+ end
175
+
176
+ it "#comment" do
177
+ expect(str.comment).to be_nil
178
+ # TODO: need tests for String which has real comment
179
+ end
180
+ end
181
+ end
@@ -22,7 +22,7 @@
22
22
  require 'spec_helper'
23
23
 
24
24
  describe Comment do
25
- let(:cursor) { Index.new.parse_translation_unit(fixture_path("docs.h")).cursor }
25
+ let(:cursor) { Index.new.parse_translation_unit(fixture_path("docs.cc")).cursor }
26
26
  let (:comment) { find_first(cursor, :cursor_function).comment }
27
27
 
28
28
  it "can be obtained from a cursor" do
@@ -56,7 +56,7 @@ describe Comment do
56
56
  end
57
57
 
58
58
  it "has working helpers" do
59
- comment.num_children.should equal(6)
59
+ comment.num_children.should equal(8)
60
60
 
61
61
  para = comment.child(1)
62
62
  para.text.should eq(" This is a longer explanation\n that spans multiple lines")
@@ -75,23 +75,396 @@ describe Comment do
75
75
  end
76
76
  end
77
77
 
78
- describe "understands blocks" do
79
- let (:block) { comment.child(5) }
78
+ describe "#whitespace?" do
79
+ it "checks the comment is whitespace" do
80
+ expect(comment.child.whitespace?).to be false
81
+ end
82
+ end
83
+
84
+ describe "#has_trailing_newline?" do
85
+ it "checks the content has a traling newline" do
86
+ expect(comment.child.has_trailing_newline?).to be false
87
+ end
88
+ end
89
+
90
+ context 'comment_null' do
91
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
92
+ child.kind == :cursor_function and child.spelling == 'no_comment_function' } }
93
+ let(:comment) { comment_cursor.comment }
94
+
95
+ it "is null comment" do
96
+ expect(comment).to be_kind_of(Comment)
97
+ expect(comment.kind).to eq(:comment_null)
98
+ expect(comment.text).to eq('')
99
+ end
100
+ end
101
+
102
+ context 'unknown comment type' do
103
+ let(:comment) { 'foobar' }
104
+ it "raises NotImplementedError" do
105
+ expect(Lib).to receive(:comment_get_kind).with(comment).and_return(:xxx_yyy_zzzz)
106
+ expect{Comment.build_from(comment)}.to raise_error(NotImplementedError)
107
+ end
108
+ end
109
+
110
+ describe HTMLStartTagComment do
111
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
112
+ child.kind == :cursor_function and child.spelling == 'b_function' } }
113
+ let(:comment) { comment_cursor.comment }
114
+ let(:paragraph) { comment_cursor.comment.child }
115
+ let(:html_start_tag_comments) { paragraph.children.select{|c| c.kind == :comment_html_start_tag} }
116
+
117
+ it "can be obtained from cursor" do
118
+ expect(comment).to be_kind_of(FullComment)
119
+ expect(comment.kind).to equal(:comment_full)
120
+ expect(paragraph).to be_kind_of(ParagraphComment)
121
+ expect(html_start_tag_comments.first).to be_kind_of(HTMLStartTagComment)
122
+ expect(html_start_tag_comments.size).to eq(2)
123
+ end
124
+
125
+ describe "#tag" do
126
+ it "returns HTML tag name" do
127
+ expect(html_start_tag_comments[0].tag).to eq('br')
128
+ expect(html_start_tag_comments[1].tag).to eq('a')
129
+ end
130
+
131
+ it "is alias method of #name" do
132
+ expect(html_start_tag_comments[0].name).to eq('br')
133
+ expect(html_start_tag_comments[1].name).to eq('a')
134
+ end
135
+ end
136
+
137
+ describe "#text" do
138
+ it "returns HTML tag as string", from_3_4: true do
139
+ expect(html_start_tag_comments[0].text.strip).to eq('<br/>')
140
+ expect(html_start_tag_comments[1].text.strip).to eq('<a href="http://example.org/">')
141
+ end
142
+
143
+ it "returuns empty string", upto_3_3: true do
144
+ expect(html_start_tag_comments[0].text.strip).to eq('')
145
+ expect(html_start_tag_comments[1].text.strip).to eq('')
146
+ end
147
+ end
148
+
149
+ describe "#self_closing?" do
150
+ it "checks the tag is self-closing" do
151
+ expect(html_start_tag_comments[0].self_closing?).to be true
152
+ expect(html_start_tag_comments[1].self_closing?).to be false
153
+ end
154
+ end
155
+
156
+ describe "#num_attrs" do
157
+ it "returns the number of attributes" do
158
+ expect(html_start_tag_comments[0].num_attrs).to eq(0)
159
+ expect(html_start_tag_comments[1].num_attrs).to eq(1)
160
+ end
161
+ end
162
+
163
+ describe "#attrs" do
164
+ it "returns attributes as Array of Hash" do
165
+ expect(html_start_tag_comments[0].attrs).to eq([])
166
+ expect(html_start_tag_comments[1].attrs).to eq([{name: 'href', value: 'http://example.org/'}])
167
+ end
168
+ end
169
+ end
170
+
171
+ describe HTMLEndTagComment do
172
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
173
+ child.kind == :cursor_function and child.spelling == 'b_function' } }
174
+ let(:comment) { comment_cursor.comment }
175
+ let(:paragraph) { comment_cursor.comment.child }
176
+ let(:html_end_tag_comment) { paragraph.children.select{|c| c.kind == :comment_html_end_tag}.first }
177
+
178
+ it "can be obtained from cursor" do
179
+ expect(comment).to be_kind_of(FullComment)
180
+ expect(comment.kind).to equal(:comment_full)
181
+ expect(paragraph).to be_kind_of(ParagraphComment)
182
+ expect(html_end_tag_comment).to be_kind_of(HTMLEndTagComment)
183
+ end
184
+
185
+ describe "#tag" do
186
+ it "returns HTML tag name" do
187
+ expect(html_end_tag_comment.tag).to eq('a')
188
+ end
189
+
190
+ it "is alias method of #name" do
191
+ expect(html_end_tag_comment.name).to eq('a')
192
+ end
193
+ end
194
+
195
+ describe "#text" do
196
+ it "returns HTML tag as string", from_3_4: true do
197
+ expect(html_end_tag_comment.text.strip).to eq('</a>')
198
+ end
199
+
200
+ it "returuns empty string", upto_3_3: true do
201
+ expect(html_end_tag_comment.text.strip).to eq('')
202
+ end
203
+ end
204
+ end
205
+
206
+ describe FullComment do
207
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
208
+ child.kind == :cursor_function and child.spelling == 'f_function' } }
209
+ let(:comment) { comment_cursor.comment }
210
+
211
+ it "can be obtained from cursor" do
212
+ expect(comment).to be_kind_of(FullComment)
213
+ expect(comment.kind).to equal(:comment_full)
214
+ end
215
+
216
+ describe "#to_html" do
217
+ it "converts a given full parsed comment to an HTML fragment", from_3_4: true do
218
+ expect(comment.to_html).to be_kind_of(String)
219
+ expect(comment.to_html).to eq('<p class="para-brief"> this is a function.</p>')
220
+ end
221
+
222
+ it "converts a given full parsed comment to an HTML fragment", upto_3_3: true do
223
+ expect(comment.to_html).to be_kind_of(String)
224
+ expect(comment.to_html).to eq('<p class="para-brief"> this is a function. </p>')
225
+ end
226
+ end
227
+
228
+ describe "#to_xml" do
229
+ it "converts a given full parsed comment to an XML document" do
230
+ expect(comment.to_xml).to be_kind_of(String)
231
+ end
232
+ end
233
+ end
234
+
235
+ describe BlockCommandComment do
236
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
237
+ child.kind == :cursor_function and child.spelling == 'f_function' } }
238
+ let(:comment) { comment_cursor.comment }
239
+ let(:block_cmd_comment) { comment.children.select{|c| c.kind == :comment_block_command}.first }
240
+
241
+ it "can be obtained from cursor" do
242
+ expect(comment).to be_kind_of(FullComment)
243
+ expect(comment.kind).to equal(:comment_full)
244
+ expect(block_cmd_comment).to be_kind_of(BlockCommandComment)
245
+ expect(block_cmd_comment.child).to be_kind_of(ParagraphComment)
246
+ end
247
+
248
+ describe "#name" do
249
+ it "returns the name of the block command" do
250
+ expect(block_cmd_comment.name).to eq("brief")
251
+ end
252
+ end
253
+
254
+ describe "#paragraph" do
255
+ it "returns the paragraph" do
256
+ expect(block_cmd_comment.paragraph).to be_kind_of(ParagraphComment)
257
+ end
258
+ end
259
+
260
+ describe "#num_args" do
261
+ it "returns the number of word-like arguments" do
262
+ expect(block_cmd_comment.num_args).to eq(0)
263
+ end
264
+ end
265
+
266
+ describe "#args" do
267
+ it "returns word-like arguments" do
268
+ expect(block_cmd_comment.args).to be_kind_of(Array)
269
+ expect(block_cmd_comment.args).to eq([])
270
+ end
271
+
272
+ #TODO: needs tests with comments which have arguments
273
+ end
274
+
275
+ describe "#text" do
276
+ it "returns readble text that includes children's comments" do
277
+ expect(block_cmd_comment.text).to be_kind_of(String)
278
+ expect(block_cmd_comment.text.strip).to eq('this is a function.')
279
+ end
280
+
281
+ it "is a alias method of #comment" do
282
+ expect(block_cmd_comment.comment).to eq(block_cmd_comment.text)
283
+ end
284
+ end
285
+ end
286
+
287
+ describe InlineCommandComment do
288
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
289
+ child.kind == :cursor_function and child.spelling == 'd_function' } }
290
+ let(:comment) { comment_cursor.comment }
291
+ let(:inline_command_comments) { comment.child.children.select{|c| c.kind == :comment_inline_command} }
292
+
293
+ it "can be obtained from cursor" do
294
+ expect(comment).to be_kind_of(FullComment)
295
+ expect(comment.kind).to equal(:comment_full)
296
+ expect(comment.child).to be_kind_of(ParagraphComment)
297
+ expect(inline_command_comments.size).to eq(2)
298
+ end
299
+
300
+ describe "#name" do
301
+ it "returns the name of the inline command" do
302
+ expect(inline_command_comments[0].name).to eq("em")
303
+ expect(inline_command_comments[1].name).to eq("b")
304
+ end
305
+ end
306
+
307
+ describe "#render_kind" do
308
+ it "returns the most appropriate rendering mode" do
309
+ expect(inline_command_comments[0].render_kind).to eq(:emphasized)
310
+ expect(inline_command_comments[1].render_kind).to eq(:bold)
311
+ end
312
+ end
313
+
314
+ describe "#num_args" do
315
+ it "returns number of command arguments" do
316
+ expect(inline_command_comments[0].num_args).to eq(1)
317
+ expect(inline_command_comments[1].num_args).to eq(1)
318
+ end
319
+ end
320
+
321
+ describe "#args" do
322
+ it "returns arguments as Array" do
323
+ expect(inline_command_comments[0].args).to eq(["foo"])
324
+ expect(inline_command_comments[1].args).to eq(["bar"])
325
+ end
326
+ end
327
+
328
+ describe "#text" do
329
+ it "returns readble text" do
330
+ expect(inline_command_comments[0].text.strip).to eq("foo")
331
+ expect(inline_command_comments[1].text.strip).to eq("bar")
332
+ end
333
+ end
334
+ end
335
+
336
+ describe VerbatimBlockCommandComment do
337
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
338
+ child.kind == :cursor_function and child.spelling == 'e_function' } }
339
+ let(:comment) { comment_cursor.comment }
340
+ let(:verb_block_cmd_comment) { comment.children.select{|c| c.kind == :comment_verbatim_block_command}.first }
341
+
342
+ it "can be obtained from cursor" do
343
+ expect(comment).to be_kind_of(FullComment)
344
+ expect(comment.kind).to equal(:comment_full)
345
+ expect(verb_block_cmd_comment).to be_kind_of(VerbatimBlockCommandComment)
346
+ end
347
+
348
+ describe "#text" do
349
+ it "returns readble text" do
350
+ expect(verb_block_cmd_comment.text).to eq(" foo bar\n baz")
351
+ end
352
+ end
353
+ end
354
+
355
+ describe VerbatimBlockLineComment do
356
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
357
+ child.kind == :cursor_function and child.spelling == 'e_function' } }
358
+ let(:comment) { comment_cursor.comment }
359
+ let(:verb_block_cmd_comment) { comment.children.select{|c| c.kind == :comment_verbatim_block_command}.first }
360
+ let(:verb_block_line_comments) { verb_block_cmd_comment.children }
361
+
362
+ it "can be obtained from cursor" do
363
+ expect(comment).to be_kind_of(FullComment)
364
+ expect(comment.kind).to equal(:comment_full)
365
+ expect(verb_block_cmd_comment).to be_kind_of(VerbatimBlockCommandComment)
366
+ expect(verb_block_line_comments.first).to be_kind_of(VerbatimBlockLineComment)
367
+ expect(verb_block_line_comments.size).to eq(2)
368
+ end
369
+
370
+ describe "#text" do
371
+ it "returns readble text" do
372
+ expect(verb_block_line_comments[0].text.strip).to eq("foo bar")
373
+ expect(verb_block_line_comments[1].text.strip).to eq("baz")
374
+ end
375
+ end
376
+ end
377
+
378
+ describe VerbatimLine do
379
+ # TODO: how to generate this comment?
380
+ end
381
+
382
+ describe ParamCommandComment do
383
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
384
+ child.kind == :cursor_function and child.spelling == 'a_function' } }
385
+ let(:comment) { comment_cursor.comment }
386
+ let(:param_cmd_comments) { comment.children.select{|c| c.kind == :comment_param_command} }
387
+
388
+ it "can be obtained from cursor" do
389
+ expect(comment).to be_kind_of(FullComment)
390
+ expect(comment.kind).to equal(:comment_full)
391
+ expect(param_cmd_comments.first).to be_kind_of(ParamCommandComment)
392
+ expect(param_cmd_comments.size).to eq(4)
393
+ end
394
+
395
+ describe "#text" do
396
+ it "returns readble text" do
397
+ expect(param_cmd_comments[0].text.strip).to eq("some input")
398
+ expect(param_cmd_comments[1].text.strip).to eq("some flags")
399
+ end
400
+ end
401
+
402
+ describe "#direction_explicit?" do
403
+ it "checks the direction is specified explicitly" do
404
+ expect(param_cmd_comments[0].direction_explicit?).to be true
405
+ expect(param_cmd_comments[3].direction_explicit?).to be false
406
+ end
407
+ end
408
+
409
+ describe "#direction" do
410
+ it "returns parameter passing direction" do
411
+ expect(param_cmd_comments[0].direction).to eq(:pass_direction_in)
412
+ expect(param_cmd_comments[1].direction).to eq(:pass_direction_out)
413
+ expect(param_cmd_comments[2].direction).to eq(:pass_direction_inout)
414
+ expect(param_cmd_comments[3].direction).to eq(:pass_direction_in)
415
+ end
416
+ end
417
+ end
418
+
419
+ describe TParamCommandComment do
420
+ let(:comment_cursor) { find_matching(cursor) { |child, parent|
421
+ child.kind == :cursor_function_template and child.spelling == 'c_function' } }
422
+ let(:comment) { comment_cursor.comment }
423
+ let(:tparam_cmd_comments) { comment.children.select{|c| c.kind == :comment_tparam_command} }
424
+
425
+ it "can be obtained from cursor" do
426
+ expect(comment).to be_kind_of(FullComment)
427
+ expect(comment.kind).to equal(:comment_full)
428
+ expect(tparam_cmd_comments.first).to be_kind_of(TParamCommandComment)
429
+ expect(tparam_cmd_comments.size).to eq(3)
430
+ end
431
+
432
+ describe "#text" do
433
+ it "returns readble text" do
434
+ expect(tparam_cmd_comments[0].text.strip).to eq("some type of foo")
435
+ expect(tparam_cmd_comments[1].text.strip).to eq("some type of bar")
436
+ end
437
+ end
80
438
 
81
- it 'is BlockCommandComment' do
82
- expect(block).to be_kind_of(BlockCommandComment)
439
+ describe "#name" do
440
+ it "returns template parameter name" do
441
+ expect(tparam_cmd_comments[0].name).to eq("T1")
442
+ expect(tparam_cmd_comments[1].name).to eq("T2")
443
+ expect(tparam_cmd_comments[2].name).to eq("T3")
444
+ end
83
445
  end
84
446
 
85
- it 'has name' do
86
- expect(block.name).to eq("return")
447
+ describe "#valid_position?" do
448
+ it "checks this parameter has valid position" do
449
+ expect(tparam_cmd_comments[0].valid_position?).to be true
450
+ end
87
451
  end
88
452
 
89
- it 'has comment', from_3_4: true do
90
- expect(block.comment).to eq(" a random value")
453
+ describe "#depth" do
454
+ it "returns nesting depth of this parameter" do
455
+ expect(tparam_cmd_comments[0].depth).to eq(1)
456
+ expect(tparam_cmd_comments[1].depth).to eq(2)
457
+ expect(tparam_cmd_comments[2].depth).to eq(1)
458
+ end
91
459
  end
92
460
 
93
- it 'has comment', upto_3_3: true do
94
- expect(block.comment).to eq(" a random value\n ")
461
+ describe "#index" do
462
+ it "returns index of the parameter at the given nesting depth" do
463
+ expect(tparam_cmd_comments[0].index(0)).to eq(0)
464
+ expect(tparam_cmd_comments[1].index(0)).to eq(1)
465
+ expect(tparam_cmd_comments[1].index(1)).to eq(0)
466
+ expect(tparam_cmd_comments[2].index(0)).to eq(1)
467
+ end
95
468
  end
96
469
  end
97
470
  end