ffi-clang 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +12 -8
  3. data/README.md +3 -1
  4. data/ffi-clang.gemspec +1 -1
  5. data/lib/ffi/clang.rb +3 -1
  6. data/lib/ffi/clang/code_completion.rb +193 -0
  7. data/lib/ffi/clang/comment.rb +154 -11
  8. data/lib/ffi/clang/compilation_database.rb +125 -0
  9. data/lib/ffi/clang/cursor.rb +145 -9
  10. data/lib/ffi/clang/diagnostic.rb +36 -10
  11. data/lib/ffi/clang/file.rb +69 -0
  12. data/lib/ffi/clang/index.rb +9 -17
  13. data/lib/ffi/clang/lib.rb +25 -2
  14. data/lib/ffi/clang/lib/code_completion.rb +130 -0
  15. data/lib/ffi/clang/lib/comment.rb +73 -12
  16. data/lib/ffi/clang/lib/compilation_database.rb +58 -0
  17. data/lib/ffi/clang/lib/cursor.rb +78 -14
  18. data/lib/ffi/clang/lib/diagnostic.rb +32 -12
  19. data/lib/ffi/clang/lib/file.rb +15 -3
  20. data/lib/ffi/clang/lib/inclusions.rb +32 -0
  21. data/lib/ffi/clang/lib/source_location.rb +18 -0
  22. data/lib/ffi/clang/lib/source_range.rb +5 -0
  23. data/lib/ffi/clang/lib/token.rb +58 -0
  24. data/lib/ffi/clang/lib/translation_unit.rb +71 -1
  25. data/lib/ffi/clang/lib/type.rb +61 -3
  26. data/lib/ffi/clang/source_location.rb +102 -0
  27. data/lib/ffi/clang/source_range.rb +25 -4
  28. data/lib/ffi/clang/token.rb +95 -0
  29. data/lib/ffi/clang/translation_unit.rb +118 -2
  30. data/lib/ffi/clang/type.rb +61 -0
  31. data/lib/ffi/clang/unsaved_file.rb +16 -0
  32. data/lib/ffi/clang/utils.rb +38 -12
  33. data/lib/ffi/clang/version.rb +1 -1
  34. data/spec/clang/code_completion_spec.rb +181 -0
  35. data/spec/clang/comment_spec.rb +385 -12
  36. data/spec/clang/compilation_database_spec.rb +178 -0
  37. data/spec/clang/cursor_spec.rb +335 -12
  38. data/spec/clang/diagnostic_spec.rb +63 -4
  39. data/spec/clang/file_spec.rb +84 -0
  40. data/spec/clang/index_spec.rb +62 -5
  41. data/spec/clang/source_location_spec.rb +104 -4
  42. data/spec/clang/source_range_spec.rb +76 -0
  43. data/spec/clang/token_spec.rb +84 -0
  44. data/spec/clang/translation_unit_spec.rb +202 -5
  45. data/spec/clang/type_spec.rb +191 -0
  46. data/spec/clang/utils_spec.rb +2 -3
  47. data/spec/fixtures/a.c +3 -0
  48. data/spec/fixtures/compile_commands.json +17 -0
  49. data/spec/fixtures/completion.cxx +8 -0
  50. data/spec/fixtures/docs.c +1 -0
  51. data/spec/fixtures/docs.cc +1 -0
  52. data/spec/fixtures/docs.h +46 -3
  53. data/spec/fixtures/list.c +1 -0
  54. data/spec/fixtures/location1.c +7 -0
  55. data/spec/fixtures/simple.c +3 -0
  56. data/spec/fixtures/test.cxx +36 -0
  57. data/spec/spec_helper.rb +11 -0
  58. metadata +50 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0711385ae78d16e56e06a6bb827a08951c1128dd
4
- data.tar.gz: 5eb03fd538e2949c1063a07c071ab778e000b7cb
3
+ metadata.gz: ba2f1301bc825e8bb4bfe80ebe60ed2e2b20945a
4
+ data.tar.gz: 4d33834e8851dfcf646cb934dfd5a0921f5d81e8
5
5
  SHA512:
6
- metadata.gz: 95fe823fc29639734c09302303b96c92a50060c0a5ac09adc9936f3d7b37ade0d90a6bf878eaf4bf4415f5a22f20807e086de7b0e8a242bd00cfa2f12edbde73
7
- data.tar.gz: 54e2bfa618b2eeff3b0920ea731f9e3391179c761fce11c1a86ede8f1b40894d0770a3ece965942680ab4f0985e61501b1bb9d903a08d761d46eda0de010aece
6
+ metadata.gz: 93f851368ed6a50978407ab7227511d7a20fd12716cb6413615ab00b015867b384c8c3b8eb7e1921a3ddb2b95321202282dafc8a854459342f9243c4e66774ef
7
+ data.tar.gz: 365b47a6501012f6498fdbc3c9754ca4b9a2226edd5853f4084b93ac552c97a82a9c440d0fce1eb6e6f00bdd9115d144b265a78973971feb8e6cb49f85ac3d41
@@ -8,11 +8,15 @@ env:
8
8
  - LLVM_VERSION=3.4
9
9
  - LLVM_VERSION=3.5
10
10
  install:
11
- - sudo add-apt-repository --yes ppa:h-rayflood/llvm
12
- - sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
13
- - sudo add-apt-repository --yes 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise main'
14
- - wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
15
- - sudo apt-get -qq update
16
- - sudo apt-get -qq install libclang-${LLVM_VERSION}-dev
17
- - export LD_LIBRARY_PATH=/usr/lib/llvm-${LLVM_VERSION}/lib/
18
- - bundle install
11
+ - sudo add-apt-repository --yes ppa:h-rayflood/llvm
12
+ - sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
13
+ - sudo add-apt-repository --yes 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise main'
14
+ - wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
15
+ - sudo apt-get -qq update
16
+ - sudo apt-get -qq install libclang-${LLVM_VERSION}-dev clang-${LLVM_VERSION}
17
+ - export LD_LIBRARY_PATH=/usr/lib/llvm-${LLVM_VERSION}/lib/
18
+ - export PATH=/usr/lib/llvm-${LLVM_VERSION}/bin:$PATH
19
+ - bundle install
20
+ matrix:
21
+ allow_failures:
22
+ - env: LLVM_VERSION=3.5
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
1
  # FFI::Clang
2
2
 
3
- A light weight wrapper for Ruby exposing libclang.
3
+ A light weight wrapper for Ruby exposing [libclang][1].
4
4
 
5
5
  [![Build Status](https://secure.travis-ci.org/ioquatix/ffi-clang.png)](http://travis-ci.org/ioquatix/ffi-clang)
6
6
  [![Code Climate](https://codeclimate.com/github/ioquatix/ffi-clang.png)](https://codeclimate.com/github/ioquatix/ffi-clang)
7
7
 
8
+ [1]: http://llvm.org/devmtg/2010-11/Gregor-libclang.pdf
9
+
8
10
  ## Installation
9
11
 
10
12
  Add this line to your application's Gemfile:
@@ -21,6 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "ffi"
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rspec", "~> 3.0.0"
24
25
  spec.add_development_dependency "rake"
25
- spec.add_development_dependency "rspec"
26
26
  end
@@ -51,4 +51,6 @@ require 'ffi/clang/cursor'
51
51
  require 'ffi/clang/source_location'
52
52
  require 'ffi/clang/source_range'
53
53
  require 'ffi/clang/unsaved_file'
54
-
54
+ require 'ffi/clang/token'
55
+ require 'ffi/clang/code_completion'
56
+ require 'ffi/clang/compilation_database'
@@ -0,0 +1,193 @@
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 'ffi/clang/lib/code_completion'
22
+
23
+ module FFI
24
+ module Clang
25
+ class CodeCompletion
26
+ def self.default_code_completion_options
27
+ Lib.opts_from Lib::CodeCompleteFlags, Lib.default_code_completion_options
28
+ end
29
+
30
+ class Results < FFI::AutoPointer
31
+ include Enumerable
32
+
33
+ attr_reader :size
34
+ attr_reader :results
35
+
36
+ def initialize(code_complete_results, translation_unit)
37
+ super code_complete_results.pointer
38
+ @translation_unit = translation_unit
39
+ @code_complete_results = code_complete_results
40
+ initialize_results
41
+ end
42
+
43
+ def self.release(pointer)
44
+ Lib.dispose_code_complete_results(pointer)
45
+ end
46
+
47
+ def each(&block)
48
+ @results.each do |token|
49
+ block.call(token)
50
+ end
51
+ end
52
+
53
+ def num_diagnostics
54
+ Lib.get_code_complete_get_num_diagnostics(@code_complete_results)
55
+ end
56
+
57
+ def diagnostic(i)
58
+ Diagnostic.new(@translation_unit, Lib.get_code_complete_get_diagnostic(@code_complete_results, i))
59
+ end
60
+
61
+ def diagnostics
62
+ num_diagnostics.times.map { |i|
63
+ Diagnostic.new(@translation_unit, Lib.get_code_complete_get_diagnostic(@code_complete_results, i))
64
+ }
65
+ end
66
+
67
+ def contexts
68
+ Lib.opts_from Lib::CompletionContext, Lib.get_code_complete_get_contexts(@code_complete_results)
69
+ end
70
+
71
+ def container_usr
72
+ Lib.extract_string Lib.get_code_complete_get_container_usr(@code_complete_results)
73
+ end
74
+
75
+ def container_kind
76
+ is_incomplete = MemoryPointer.new :uint
77
+ Lib.get_code_complete_get_container_kind(@code_complete_results, is_incomplete)
78
+ end
79
+
80
+ def incomplete?
81
+ is_incomplete = MemoryPointer.new :uint
82
+ Lib.get_code_complete_get_container_kind(@code_complete_results, is_incomplete)
83
+ is_incomplete.read_uint != 0
84
+ end
85
+
86
+ def objc_selector
87
+ Lib.extract_string Lib.get_code_complete_get_objc_selector(@code_complete_results)
88
+ end
89
+
90
+ def sort!
91
+ Lib.sort_code_completion_results(@code_complete_results[:results], @code_complete_results[:num])
92
+ initialize_results
93
+ end
94
+
95
+ def inspect
96
+ @results.inspect
97
+ end
98
+
99
+ private
100
+
101
+ def initialize_results
102
+ @size = @code_complete_results[:num]
103
+ cur_ptr = @code_complete_results[:results]
104
+ @results = []
105
+ @size.times {
106
+ @results << Result.new(Lib::CXCompletionResult.new(cur_ptr))
107
+ cur_ptr += Lib::CXCompletionResult.size
108
+ }
109
+ end
110
+ end
111
+
112
+ class Result
113
+ def initialize(result)
114
+ @result = result
115
+ end
116
+
117
+ def kind
118
+ @result[:kind]
119
+ end
120
+
121
+ def string
122
+ CodeCompletion::String.new @result[:string]
123
+ end
124
+
125
+ def inspect
126
+ "<#{kind.inspect} = #{string.inspect}>"
127
+ end
128
+ end
129
+
130
+ class String
131
+ def initialize(ptr)
132
+ @pointer = ptr
133
+ end
134
+
135
+ def chunk_kind(i)
136
+ Lib.get_completion_chunk_kind(@pointer, i)
137
+ end
138
+
139
+ def chunk_text(i)
140
+ Lib.extract_string Lib.get_completion_text(@pointer, i)
141
+ end
142
+
143
+ def chunk_completion(i)
144
+ CodeCompletion::String.new Lib.get_completion_chunk_completion_string(@pointer, i)
145
+ end
146
+
147
+ def num_chunks
148
+ Lib.get_num_completion_chunks(@pointer)
149
+ end
150
+
151
+ def chunks
152
+ num_chunks.times.map { |i|
153
+ { kind: chunk_kind(i), text: chunk_text(i), completion: chunk_completion(i) }
154
+ }
155
+ end
156
+
157
+ def priority
158
+ Lib.get_completion_priority(@pointer)
159
+ end
160
+
161
+ def availability
162
+ Lib.get_completion_availability(@pointer)
163
+ end
164
+
165
+ def num_annotations
166
+ Lib.get_completion_num_annotations(@pointer)
167
+ end
168
+
169
+ def annotation(i)
170
+ Lib.extract_string Lib.get_completion_annotation(@pointer, i)
171
+ end
172
+
173
+ def annotations
174
+ num_annotations.times.map { |i|
175
+ Lib.extract_string Lib.get_completion_annotation(@pointer, i)
176
+ }
177
+ end
178
+
179
+ def parent
180
+ Lib.extract_string Lib.get_completion_parent(@pointer, nil)
181
+ end
182
+
183
+ def comment
184
+ Lib.extract_string Lib.get_completion_brief_comment(@pointer)
185
+ end
186
+
187
+ def inspect
188
+ chunks.inspect
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -32,23 +32,41 @@ module FFI
32
32
  def self.build_from(comment)
33
33
  kind = Lib.comment_get_kind(comment)
34
34
  case kind
35
- when :comment_full
36
- FullComment.new comment
37
- when :comment_paragraph
38
- ParagraphComment.new comment
35
+ when :comment_null
36
+ Comment.new comment
39
37
  when :comment_text
40
38
  TextComment.new comment
39
+ when :comment_inline_command
40
+ InlineCommandComment.new comment
41
+ when :comment_html_start_tag
42
+ HTMLStartTagComment.new comment
43
+ when :comment_html_end_tag
44
+ HTMLEndTagComment.new comment
45
+ when :comment_paragraph
46
+ ParagraphComment.new comment
41
47
  when :comment_block_command
42
48
  BlockCommandComment.new comment
43
49
  when :comment_param_command
44
50
  ParamCommandComment.new comment
45
- when :comment_null
46
- Comment.new comment
51
+ when :comment_tparam_command
52
+ TParamCommandComment.new comment
53
+ when :comment_verbatim_block_command
54
+ VerbatimBlockCommandComment.new comment
55
+ when :comment_verbatim_block_line
56
+ VerbatimBlockLineComment.new comment
57
+ when :comment_verbatim_line
58
+ VerbatimLine.new comment
59
+ when :comment_full
60
+ FullComment.new comment
47
61
  else
48
62
  raise NotImplementedError, kind
49
63
  end
50
64
  end
51
65
 
66
+ def text
67
+ return ""
68
+ end
69
+
52
70
  def initialize(comment)
53
71
  @comment = comment
54
72
  end
@@ -65,14 +83,59 @@ module FFI
65
83
  Comment.build_from Lib.comment_get_child(@comment, n)
66
84
  end
67
85
 
86
+ def children
87
+ num_children.times.map { |i| child(i) }
88
+ end
89
+
90
+ def whitespace?
91
+ Lib.comment_is_whitespace(@comment) != 0
92
+ end
93
+
94
+ def has_trailing_newline?
95
+ Lib.inline_content_comment_has_trailing_newline(@comment) != 0
96
+ end
97
+
68
98
  def each(&block)
69
- (0..num_children-1).map do |i|
99
+ num_children.times.map do |i|
70
100
  block.call(child(i))
71
101
  end
72
102
  end
73
103
 
74
104
  end
75
105
 
106
+ class HTMLTagComment < Comment
107
+ def name
108
+ Lib.extract_string Lib.html_tag_comment_get_tag_name(@comment)
109
+ end
110
+ alias_method :tag, :name
111
+
112
+ def text
113
+ Lib.extract_string Lib.html_tag_comment_get_as_string(@comment)
114
+ end
115
+ end
116
+
117
+ class HTMLStartTagComment < HTMLTagComment
118
+ def self_closing?
119
+ Lib.html_start_tag_comment_is_self_closing(@comment) != 0
120
+ end
121
+
122
+ def num_attrs
123
+ Lib.html_start_tag_comment_get_num_attrs(@comment)
124
+ end
125
+
126
+ def attrs
127
+ num_attrs.times.map { |i|
128
+ {
129
+ name: Lib.extract_string(Lib.html_start_tag_comment_get_attr_name(@comment, i)),
130
+ value: Lib.extract_string(Lib.html_start_tag_comment_get_attr_value(@comment, i)),
131
+ }
132
+ }
133
+ end
134
+ end
135
+
136
+ class HTMLEndTagComment < HTMLTagComment
137
+ end
138
+
76
139
  class ParagraphComment < Comment
77
140
  def text
78
141
  self.map(&:text).join("\n")
@@ -85,6 +148,30 @@ module FFI
85
148
  end
86
149
  end
87
150
 
151
+ class InlineCommandComment < Comment
152
+ def name
153
+ Lib.extract_string Lib.inline_command_comment_get_command_name(@comment)
154
+ end
155
+
156
+ def render_kind
157
+ Lib.inline_command_comment_get_render_kind(@comment)
158
+ end
159
+
160
+ def num_args
161
+ Lib.inline_command_comment_get_num_args(@comment)
162
+ end
163
+
164
+ def args
165
+ num_args.times.map { |i|
166
+ Lib.extract_string Lib.inline_command_comment_get_arg_text(@comment, i)
167
+ }
168
+ end
169
+
170
+ def text
171
+ args.join
172
+ end
173
+ end
174
+
88
175
  class BlockCommandComment < Comment
89
176
  def name
90
177
  Lib.extract_string Lib.block_command_comment_get_command_name(@comment)
@@ -94,13 +181,20 @@ module FFI
94
181
  Comment.build_from Lib.block_command_comment_get_paragraph(@comment)
95
182
  end
96
183
 
97
- def comment
184
+ def text
98
185
  self.paragraph.text
99
186
  end
187
+ alias_method :comment, :text
100
188
 
101
189
  def num_args
102
190
  Lib.block_command_comment_get_num_args(@comment)
103
191
  end
192
+
193
+ def args
194
+ num_args.times.map { |i|
195
+ Lib.extract_string Lib.block_command_comment_get_arg_text(@comment, i)
196
+ }
197
+ end
104
198
  end
105
199
 
106
200
  class ParamCommandComment < Comment
@@ -108,9 +202,10 @@ module FFI
108
202
  Lib.extract_string Lib.param_command_comment_get_param_name(@comment)
109
203
  end
110
204
 
111
- def comment
112
- self.child.text
205
+ def text
206
+ self.map(&:text).join("")
113
207
  end
208
+ alias_method :comment, :text
114
209
 
115
210
  def valid_index?
116
211
  Lib.param_command_comment_is_param_index_valid(@comment) != 0
@@ -119,6 +214,55 @@ module FFI
119
214
  def index
120
215
  Lib.param_command_comment_get_param_index(@comment)
121
216
  end
217
+
218
+ def direction_explicit?
219
+ Lib.param_command_comment_is_direction_explicit(@comment) != 0
220
+ end
221
+
222
+ def direction
223
+ Lib.param_command_comment_get_direction(@comment)
224
+ end
225
+ end
226
+
227
+ class TParamCommandComment < Comment
228
+ def text
229
+ self.child.text
230
+ end
231
+ alias_method :comment, :text
232
+
233
+ def name
234
+ Lib.extract_string Lib.tparam_command_comment_get_param_name(@comment)
235
+ end
236
+
237
+ def valid_position?
238
+ Lib.tparam_command_comment_is_param_position_valid(@comment) != 0
239
+ end
240
+
241
+ def depth
242
+ Lib.tparam_command_comment_get_depth(@comment)
243
+ end
244
+
245
+ def index(depth = 0)
246
+ Lib.tparam_command_comment_get_index(@comment, depth)
247
+ end
248
+ end
249
+
250
+ class VerbatimBlockCommandComment < Comment
251
+ def text
252
+ children.map(&:text).join("\n")
253
+ end
254
+ end
255
+
256
+ class VerbatimBlockLineComment < Comment
257
+ def text
258
+ Lib.extract_string Lib.verbatim_block_line_comment_get_text(@comment)
259
+ end
260
+ end
261
+
262
+ class VerbatimLine < Comment
263
+ def text
264
+ Lib.extract_string Lib.verbatim_line_comment_get_text(@comment)
265
+ end
122
266
  end
123
267
 
124
268
  class FullComment < Comment
@@ -130,6 +274,5 @@ module FFI
130
274
  Lib.extract_string Lib.full_comment_get_as_xml(@comment)
131
275
  end
132
276
  end
133
-
134
277
  end
135
278
  end