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