ffi-clang 0.13.0 → 0.14.0

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 (52) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/ext/rakefile.rb +2 -2
  4. data/lib/ffi/clang/clang_version.rb +7 -3
  5. data/lib/ffi/clang/code_completion.rb +121 -44
  6. data/lib/ffi/clang/comment.rb +164 -57
  7. data/lib/ffi/clang/compilation_database.rb +79 -25
  8. data/lib/ffi/clang/cursor.rb +395 -149
  9. data/lib/ffi/clang/diagnostic.rb +57 -23
  10. data/lib/ffi/clang/error.rb +12 -0
  11. data/lib/ffi/clang/file.rb +30 -11
  12. data/lib/ffi/clang/index.rb +37 -13
  13. data/lib/ffi/clang/lib/clang_version.rb +2 -2
  14. data/lib/ffi/clang/lib/code_completion.rb +15 -11
  15. data/lib/ffi/clang/lib/comment.rb +16 -14
  16. data/lib/ffi/clang/lib/compilation_database.rb +5 -5
  17. data/lib/ffi/clang/lib/cursor.rb +74 -56
  18. data/lib/ffi/clang/lib/diagnostic.rb +14 -14
  19. data/lib/ffi/clang/lib/file.rb +10 -6
  20. data/lib/ffi/clang/lib/inclusions.rb +3 -3
  21. data/lib/ffi/clang/lib/index.rb +7 -5
  22. data/lib/ffi/clang/lib/printing_policy.rb +36 -36
  23. data/lib/ffi/clang/lib/source_location.rb +9 -7
  24. data/lib/ffi/clang/lib/source_range.rb +5 -3
  25. data/lib/ffi/clang/lib/string.rb +9 -4
  26. data/lib/ffi/clang/lib/token.rb +17 -4
  27. data/lib/ffi/clang/lib/translation_unit.rb +17 -13
  28. data/lib/ffi/clang/lib/type.rb +19 -17
  29. data/lib/ffi/clang/lib.rb +35 -19
  30. data/lib/ffi/clang/platform.rb +25 -0
  31. data/lib/ffi/clang/printing_policy.rb +31 -18
  32. data/lib/ffi/clang/source_location.rb +119 -36
  33. data/lib/ffi/clang/source_range.rb +30 -12
  34. data/lib/ffi/clang/token.rb +48 -23
  35. data/lib/ffi/clang/translation_unit.rb +97 -33
  36. data/lib/ffi/clang/types/array.rb +15 -1
  37. data/lib/ffi/clang/types/elaborated.rb +19 -4
  38. data/lib/ffi/clang/types/function.rb +35 -10
  39. data/lib/ffi/clang/types/pointer.rb +23 -7
  40. data/lib/ffi/clang/types/record.rb +23 -8
  41. data/lib/ffi/clang/types/type.rb +80 -36
  42. data/lib/ffi/clang/types/type_def.rb +14 -2
  43. data/lib/ffi/clang/types/vector.rb +13 -1
  44. data/lib/ffi/clang/unsaved_file.rb +18 -8
  45. data/lib/ffi/clang/version.rb +4 -2
  46. data/lib/ffi/clang.rb +23 -45
  47. data/license.md +3 -2
  48. data/readme.md +12 -13
  49. data/releases.md +5 -0
  50. data.tar.gz.sig +0 -0
  51. metadata +10 -5
  52. metadata.gz.sig +0 -0
@@ -3,148 +3,231 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2010, by Jari Bakken.
5
5
  # Copyright, 2012, by Hal Brodigan.
6
- # Copyright, 2013-2022, by Samuel Williams.
6
+ # Copyright, 2013-2025, by Samuel Williams.
7
7
  # Copyright, 2013, by Garry Marshall.
8
8
  # Copyright, 2014, by Masahiro Sano.
9
9
  # Copyright, 2024, by Charlie Savage.
10
10
 
11
- require_relative 'lib/source_location'
12
- require_relative 'lib/file'
11
+ require_relative "lib/source_location"
12
+ require_relative "lib/file"
13
13
 
14
14
  module FFI
15
15
  module Clang
16
+ # Represents a location in source code.
17
+ # This base class provides common functionality for source locations,
18
+ # with specific subclasses for different types of location information.
16
19
  class SourceLocation
20
+ # Get a null source location.
21
+ # @returns [ExpansionLocation] A null location that can be used for comparisons.
17
22
  def self.null_location
18
23
  ExpansionLocation.new Lib.get_null_location
19
24
  end
20
-
25
+
26
+ # @attribute [r] location
27
+ # @returns [FFI::Pointer] The underlying location pointer.
21
28
  attr_reader :location
29
+
30
+ # Create a new source location.
31
+ # @parameter location [FFI::Pointer] The low-level location handle.
22
32
  def initialize(location)
23
33
  @location = location
24
34
  end
25
-
35
+
36
+ # Check if this location is in a system header.
37
+ # @returns [Boolean] True if the location is in a system header file.
26
38
  def in_system_header?
27
39
  Lib.location_in_system_header(@location) != 0
28
40
  end
29
-
41
+
42
+ # Check if this location is from the main file.
43
+ # @returns [Boolean] True if the location is from the main translation unit file.
30
44
  def from_main_file?
31
45
  Lib.location_is_from_main_file(@location) != 0
32
46
  end
33
-
47
+
48
+ # Check if this location is null.
49
+ # @returns [Boolean] True if this is a null location.
34
50
  def null?
35
51
  Lib.equal_locations(@location, Lib.get_null_location) != 0
36
52
  end
37
-
53
+
54
+ # Compare this location with another for equality.
55
+ # @parameter other [SourceLocation] The other location to compare.
56
+ # @returns [Boolean] True if the locations are equal.
38
57
  def ==(other)
39
58
  Lib.equal_locations(@location, other.location) != 0
40
59
  end
41
60
  end
42
-
61
+
62
+ # Represents the expansion location of a macro.
63
+ # This provides the location where a macro was expanded, including file, line, column, and byte offset.
43
64
  class ExpansionLocation < SourceLocation
65
+ # @attribute [r] file
66
+ # @returns [String] The file path.
67
+ # @attribute [r] line
68
+ # @returns [Integer] The line number.
69
+ # @attribute [r] column
70
+ # @returns [Integer] The column number.
71
+ # @attribute [r] offset
72
+ # @returns [Integer] The byte offset in the file.
44
73
  attr_reader :file, :line, :column, :offset
45
-
74
+
75
+ # Create a new expansion location and extract its components.
76
+ # @parameter location [FFI::Pointer] The low-level location handle.
46
77
  def initialize(location)
47
78
  super(location)
48
-
79
+
49
80
  cxfile = MemoryPointer.new :pointer
50
81
  line = MemoryPointer.new :uint
51
82
  column = MemoryPointer.new :uint
52
83
  offset = MemoryPointer.new :uint
53
-
84
+
54
85
  Lib::get_expansion_location(@location, cxfile, line, column, offset)
55
-
86
+
56
87
  @file = Lib.extract_string Lib.get_file_name(cxfile.read_pointer)
57
88
  @line = line.get_uint(0)
58
89
  @column = column.get_uint(0)
59
90
  @offset = offset.get_uint(0)
60
91
  end
61
-
92
+
93
+ # Get a string representation of this location.
94
+ # @returns [String] The location in format "file:line:column:offset".
62
95
  def as_string
63
96
  "#{@file}:#{@line}:#{@column}:#{@offset}"
64
97
  end
65
-
98
+
99
+ # Get a detailed string representation.
100
+ # @returns [String] A string describing this expansion location.
66
101
  def to_s
67
102
  "ExpansionLocation <#{self.as_string}>"
68
103
  end
69
104
  end
70
-
105
+
106
+ # Represents a presumed location in source code.
107
+ # This is the location that appears to the user after macro expansion and #line directives.
71
108
  class PresumedLocation < SourceLocation
109
+ # @attribute [r] filename
110
+ # @returns [String] The presumed filename.
111
+ # @attribute [r] line
112
+ # @returns [Integer] The presumed line number.
113
+ # @attribute [r] column
114
+ # @returns [Integer] The presumed column number.
115
+ # @attribute [r] offset
116
+ # @returns [Integer] The presumed byte offset.
72
117
  attr_reader :filename, :line, :column, :offset
73
-
118
+
119
+ # Create a new presumed location and extract its components.
120
+ # @parameter location [FFI::Pointer] The low-level location handle.
74
121
  def initialize(location)
75
122
  super(location)
76
-
123
+
77
124
  cxstring = MemoryPointer.new Lib::CXString
78
125
  line = MemoryPointer.new :uint
79
126
  column = MemoryPointer.new :uint
80
-
127
+
81
128
  Lib::get_presumed_location(@location, cxstring, line, column)
82
-
129
+
83
130
  @filename = Lib.extract_string cxstring
84
131
  @line = line.get_uint(0)
85
132
  @column = column.get_uint(0)
86
133
  end
87
-
134
+
135
+ # Get a string representation of this location.
136
+ # @returns [String] The location in format "filename:line:column".
88
137
  def as_string
89
138
  "#{@filename}:#{@line}:#{@column}"
90
139
  end
91
-
140
+
141
+ # Get a detailed string representation.
142
+ # @returns [String] A string describing this presumed location.
92
143
  def to_s
93
144
  "PresumedLocation <#{self.as_string}>"
94
145
  end
95
146
  end
96
-
147
+
148
+ # Represents the spelling location of a token in source code.
149
+ # This is the actual location where the token was written in the source file.
97
150
  class SpellingLocation < SourceLocation
151
+ # @attribute [r] file
152
+ # @returns [String] The file path.
153
+ # @attribute [r] line
154
+ # @returns [Integer] The line number.
155
+ # @attribute [r] column
156
+ # @returns [Integer] The column number.
157
+ # @attribute [r] offset
158
+ # @returns [Integer] The byte offset in the file.
98
159
  attr_reader :file, :line, :column, :offset
99
-
160
+
161
+ # Create a new spelling location and extract its components.
162
+ # @parameter location [FFI::Pointer] The low-level location handle.
100
163
  def initialize(location)
101
164
  super(location)
102
-
165
+
103
166
  cxfile = MemoryPointer.new :pointer
104
167
  line = MemoryPointer.new :uint
105
168
  column = MemoryPointer.new :uint
106
169
  offset = MemoryPointer.new :uint
107
-
170
+
108
171
  Lib::get_spelling_location(@location, cxfile, line, column, offset)
109
-
172
+
110
173
  @file = Lib.extract_string Lib.get_file_name(cxfile.read_pointer)
111
174
  @line = line.get_uint(0)
112
175
  @column = column.get_uint(0)
113
176
  @offset = offset.get_uint(0)
114
177
  end
115
-
178
+
179
+ # Get a string representation of this location.
180
+ # @returns [String] The location in format "file:line:column:offset".
116
181
  def as_string
117
182
  "#{@file}:#{@line}:#{@column}:#{@offset}"
118
183
  end
119
-
184
+
185
+ # Get a detailed string representation.
186
+ # @returns [String] A string describing this spelling location.
120
187
  def to_s
121
188
  "SpellingLocation <#{self.as_string}>"
122
189
  end
123
190
  end
124
-
191
+
192
+ # Represents a file location in source code.
193
+ # This provides the physical location in the file system where code appears.
125
194
  class FileLocation < SourceLocation
195
+ # @attribute [r] file
196
+ # @returns [String] The file path.
197
+ # @attribute [r] line
198
+ # @returns [Integer] The line number.
199
+ # @attribute [r] column
200
+ # @returns [Integer] The column number.
201
+ # @attribute [r] offset
202
+ # @returns [Integer] The byte offset in the file.
126
203
  attr_reader :file, :line, :column, :offset
127
-
204
+
205
+ # Create a new file location and extract its components.
206
+ # @parameter location [FFI::Pointer] The low-level location handle.
128
207
  def initialize(location)
129
208
  super(location)
130
-
209
+
131
210
  cxfile = MemoryPointer.new :pointer
132
211
  line = MemoryPointer.new :uint
133
212
  column = MemoryPointer.new :uint
134
213
  offset = MemoryPointer.new :uint
135
-
214
+
136
215
  Lib::get_file_location(@location, cxfile, line, column, offset)
137
-
216
+
138
217
  @file = Lib.extract_string Lib.get_file_name(cxfile.read_pointer)
139
218
  @line = line.get_uint(0)
140
219
  @column = column.get_uint(0)
141
220
  @offset = offset.get_uint(0)
142
221
  end
143
-
222
+
223
+ # Get a string representation of this location.
224
+ # @returns [String] The location in format "file:line:column:offset".
144
225
  def as_string
145
226
  "#{@file}:#{@line}:#{@column}:#{@offset}"
146
227
  end
147
-
228
+
229
+ # Get a detailed string representation.
230
+ # @returns [String] A string describing this file location.
148
231
  def to_s
149
232
  "FileLocation <#{self.as_string}>"
150
233
  end
@@ -3,19 +3,25 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2010, by Jari Bakken.
5
5
  # Copyright, 2012, by Hal Brodigan.
6
- # Copyright, 2013-2022, by Samuel Williams.
6
+ # Copyright, 2013-2025, by Samuel Williams.
7
7
  # Copyright, 2013, by Garry Marshall.
8
8
  # Copyright, 2014, by Masahiro Sano.
9
9
 
10
- require_relative 'lib/source_range'
10
+ require_relative "lib/source_range"
11
11
 
12
12
  module FFI
13
13
  module Clang
14
+ # Represents a source range in a file.
14
15
  class SourceRange
16
+ # Get a null source range.
17
+ # @returns [SourceRange] A null source range.
15
18
  def self.null_range
16
19
  SourceRange.new Lib.get_null_range
17
20
  end
18
-
21
+
22
+ # Initialize a source range.
23
+ # @parameter range_or_begin_location [Lib::CXSourceRange | SourceLocation] Either a range structure or the beginning location.
24
+ # @parameter end_location [SourceLocation | Nil] The end location, or `nil` if first parameter is a range.
19
25
  def initialize(range_or_begin_location, end_location = nil)
20
26
  if end_location.nil?
21
27
  @range = range_or_begin_location
@@ -23,34 +29,46 @@ module FFI
23
29
  @range = Lib.get_range(range_or_begin_location.location, end_location.location)
24
30
  end
25
31
  end
26
-
32
+
33
+ # Get the start location of this range.
34
+ # @returns [ExpansionLocation] The start location.
27
35
  def start
28
36
  @start ||= ExpansionLocation.new(Lib.get_range_start @range)
29
37
  end
30
-
38
+
39
+ # Get the end location of this range.
40
+ # @returns [ExpansionLocation] The end location.
31
41
  def end
32
42
  @end ||= ExpansionLocation.new(Lib.get_range_end @range)
33
43
  end
34
-
35
- # The size, in bytes, of the source range.
44
+
45
+ # Get the size in bytes of the source range.
46
+ # @returns [Integer] The byte size.
36
47
  def bytesize
37
48
  self.end.offset - self.start.offset
38
49
  end
39
-
40
- # Read the part of the source file referred to by this source range.
50
+
51
+ # Read the text from the source file for this range.
52
+ # @returns [String] The source text.
41
53
  def text
42
54
  ::File.open(self.start.file, "r") do |file|
43
55
  file.seek(self.start.offset)
44
56
  return file.read(self.bytesize)
45
57
  end
46
58
  end
47
-
59
+
60
+ # Check if this range is null.
61
+ # @returns [Boolean] True if the range is null.
48
62
  def null?
49
63
  Lib.range_is_null(@range) != 0
50
64
  end
51
-
65
+
66
+ # @attribute [Lib::CXSourceRange] The underlying range structure.
52
67
  attr_reader :range
53
-
68
+
69
+ # Check if this range equals another range.
70
+ # @parameter other [SourceRange] The range to compare with.
71
+ # @returns [Boolean] True if the ranges are equal.
54
72
  def ==(other)
55
73
  Lib.equal_range(@range, other.range) != 0
56
74
  end
@@ -2,77 +2,102 @@
2
2
 
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2014, by Masahiro Sano.
5
- # Copyright, 2014-2022, by Samuel Williams.
5
+ # Copyright, 2014-2025, by Samuel Williams.
6
6
 
7
- require_relative 'lib/token'
8
- require_relative 'lib/cursor'
9
- require_relative 'source_location'
7
+ require_relative "lib/token"
8
+ require_relative "lib/cursor"
9
+ require_relative "source_location"
10
10
 
11
11
  module FFI
12
12
  module Clang
13
+ # Represents a collection of tokens from a source range.
13
14
  class Tokens < AutoPointer
14
15
  include Enumerable
15
-
16
+
17
+ # @attribute [Integer] The number of tokens.
16
18
  attr_reader :size
19
+
20
+ # @attribute [Array(Token)] The array of tokens.
17
21
  attr_reader :tokens
18
-
22
+
23
+ # Initialize a token collection.
24
+ # @parameter pointer [FFI::Pointer] The tokens pointer.
25
+ # @parameter token_size [Integer] The number of tokens.
26
+ # @parameter translation_unit [TranslationUnit] The parent translation unit.
19
27
  def initialize(pointer, token_size, translation_unit)
20
28
  ptr = Lib::TokensPointer.new(pointer,token_size, translation_unit)
21
29
  super ptr
22
-
30
+
23
31
  @translation_unit = translation_unit
24
32
  @size = token_size
25
-
33
+
26
34
  @tokens = []
27
35
  cur_ptr = pointer
28
- token_size.times {
29
- @tokens << Token.new(cur_ptr, translation_unit)
30
- cur_ptr += Lib::CXToken.size
36
+ token_size.times {@tokens << Token.new(cur_ptr, translation_unit)
37
+ cur_ptr += Lib::CXToken.size
31
38
  }
32
39
  end
33
-
40
+
41
+ # Release the tokens pointer.
42
+ # @parameter pointer [Lib::TokensPointer] The tokens pointer to release.
34
43
  def self.release(pointer)
35
44
  Lib.dispose_tokens(pointer.translation_unit, pointer, pointer.token_size)
36
45
  end
37
-
46
+
47
+ # Iterate over each token.
48
+ # @yields {|token| ...} Each token in the collection.
49
+ # @parameter token [Token] The token.
38
50
  def each(&block)
39
51
  @tokens.each do |token|
40
52
  block.call(token)
41
53
  end
42
54
  end
43
-
55
+
56
+ # Get cursors corresponding to each token.
57
+ # @returns [Array(Cursor)] Array of cursors for each token.
44
58
  def cursors
45
59
  ptr = MemoryPointer.new(Lib::CXCursor, @size)
46
60
  Lib.annotate_tokens(@translation_unit, self, @size, ptr)
47
-
61
+
48
62
  cur_ptr = ptr
49
63
  arr = []
50
- @size.times {
51
- arr << Cursor.new(cur_ptr, @translation_unit)
52
- cur_ptr += Lib::CXCursor.size
64
+ @size.times {arr << Cursor.new(cur_ptr, @translation_unit)
65
+ cur_ptr += Lib::CXCursor.size
53
66
  }
54
67
  arr
55
68
  end
56
69
  end
57
-
70
+
71
+ # Represents a single token in the source code.
58
72
  class Token
73
+ # Initialize a token.
74
+ # @parameter token [FFI::Pointer] The token pointer.
75
+ # @parameter translation_unit [TranslationUnit] The parent translation unit.
59
76
  def initialize(token, translation_unit)
60
77
  @token = token
61
78
  @translation_unit = translation_unit
62
79
  end
63
-
80
+
81
+ # Get the kind of this token.
82
+ # @returns [Symbol] The token kind.
64
83
  def kind
65
84
  Lib.get_token_kind(@token)
66
85
  end
67
-
86
+
87
+ # Get the spelling (text) of this token.
88
+ # @returns [String] The token spelling.
68
89
  def spelling
69
90
  Lib.extract_string Lib.get_token_spelliing(@translation_unit, @token)
70
91
  end
71
-
92
+
93
+ # Get the location of this token.
94
+ # @returns [ExpansionLocation] The token location.
72
95
  def location
73
96
  ExpansionLocation.new Lib.get_token_location(@translation_unit, @token)
74
97
  end
75
-
98
+
99
+ # Get the extent (source range) of this token.
100
+ # @returns [SourceRange] The token extent.
76
101
  def extent
77
102
  SourceRange.new Lib.get_token_extent(@translation_unit, @token)
78
103
  end