ffi-clang

FORK: Ruby FFI bindings for my custom patched clang 8.0.
git clone https://git.neptards.moe/neptards/ffi-clang.git
Log | Files | Refs | README

translation_unit.rb (5493B)


      1 # Copyright, 2010-2012 by Jari Bakken.
      2 # Copyright, 2013, by Samuel G. D. Williams. <http://www.codeotaku.com>
      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_relative 'lib/translation_unit'
     24 require_relative 'lib/inclusions'
     25 require_relative 'cursor'
     26 require_relative 'file'
     27 require_relative 'token'
     28 
     29 module FFI
     30 	module Clang
     31 		class TranslationUnit < AutoPointer
     32 			def initialize(pointer, index)
     33 				super pointer
     34 				@index = index
     35 			end
     36 
     37 			def self.release(pointer)
     38 				Lib.dispose_translation_unit(pointer)
     39 			end
     40 
     41 			def self.default_editing_translation_unit_options
     42 				bitmask = Lib.default_editing_translation_unit_options
     43 				Lib.opts_from Lib::TranslationUnitFlags, bitmask
     44 			end
     45 
     46 			def default_save_options
     47 				bitmask = Lib.default_save_options(self)
     48 				Lib.opts_from Lib::SaveTranslationUnitFlags, bitmask
     49 			end
     50 
     51 			def save(filename, opts = {})
     52 				ret = Lib.save_translation_unit(self, filename, 0)
     53 				sym = Lib::SaveError[ret]
     54 				raise Error, "unknown return values: #{ret} #{sym.inspect}" unless sym
     55 				raise Error, "save error: #{sym.inspect}, filename: #{filename}" if sym != :none
     56 			end
     57 
     58 			def default_reparse_options
     59 				bitmask = Lib.default_save_options(self)
     60 				Lib.opts_from Lib::ReparseFlags, bitmask
     61 			end
     62 
     63 			def reparse(unsaved = [], opts = {})
     64 				unsaved_files = UnsavedFile.unsaved_pointer_from(unsaved)
     65 				if Lib.reparse_translation_unit(self, unsaved.size, unsaved_files, 0) != 0
     66 					raise Error, "reparse error"
     67 				end
     68 			end
     69 
     70 			def diagnostics
     71 				n = Lib.get_num_diagnostics(self)
     72 			
     73 				n.times.map do |i|
     74 					Diagnostic.new(self, Lib.get_diagnostic(self, i))
     75 				end
     76 			end
     77 
     78 			def cursor(location = nil)
     79 				if location.nil?
     80 					Cursor.new Lib.get_translation_unit_cursor(self), self
     81 				else
     82 					Cursor.new Lib.get_cursor(self, location.location), self
     83 				end
     84 			end
     85 
     86 			def location(file, line, column)
     87 				ExpansionLocation.new Lib.get_location(self, file, line, column)
     88 			end
     89 
     90 			def location_offset(file, offset)
     91 				ExpansionLocation.new Lib.get_location_offset(self, file, offset)
     92 			end
     93 
     94 			def file(file_name = nil)
     95 				if file_name.nil?
     96 					File.new(Lib.get_file(self, spelling), self)
     97 				else
     98 					File.new(Lib.get_file(self, file_name), self)
     99 				end
    100 			end
    101 
    102 			def spelling
    103 				Lib.extract_string Lib.get_translation_unit_spelling(self)
    104 			end
    105 
    106 			def resource_usage
    107 				FFI::Clang::TranslationUnit::ResourceUsage.new Lib.resource_usage(self)
    108 			end
    109 
    110 			def tokenize(range)
    111 				token_ptr = MemoryPointer.new :pointer
    112 				uint_ptr = MemoryPointer.new :uint
    113 				Lib.tokenize(self, range.range, token_ptr, uint_ptr)
    114 				Tokens.new(token_ptr.get_pointer(0), uint_ptr.get_uint(0), self)
    115 			end
    116 
    117 			def code_complete(source_file, line, column, unsaved = [], opts = nil)
    118 				opts = CodeCompletion.default_code_completion_options if opts.nil?
    119 				unsaved_files = UnsavedFile.unsaved_pointer_from(unsaved)
    120 				option_bitmask = Lib.bitmask_from(Lib::CodeCompleteFlags, opts)
    121 				ptr = Lib.code_complete_at(self, source_file, line, column, unsaved_files, unsaved.length, option_bitmask)
    122 				CodeCompletion::Results.new ptr, self
    123 			end
    124 
    125 			def inclusions(&block)
    126 				adapter = Proc.new do |included_file, inclusion_stack, include_len, unused|
    127 					file = Lib.extract_string Lib.get_file_name(included_file)
    128 					cur_ptr = inclusion_stack
    129 					inclusions = []
    130 					include_len.times {
    131 						inclusions << SourceLocation.new(Lib::CXSourceLocation.new(cur_ptr))
    132 						cur_ptr += Lib::CXSourceLocation.size
    133 					}
    134 					block.call file, inclusions
    135 				end
    136 				
    137 				Lib.get_inclusions(self, adapter, nil)
    138 			end
    139 
    140 			class ResourceUsage < AutoPointer
    141 				def initialize(resource_usage)
    142 					# CXResourceUsage is returned by value and should be freed explicitly.
    143 					# Get FFI::pointer of the data so that the data is handled by AutoPointer.
    144 					pointer = FFI::Pointer.new(resource_usage.to_ptr)
    145 					super(pointer)
    146 					@resource_usage = resource_usage
    147 				end
    148 
    149 				def self.release(pointer)
    150 					# clang_disposeCXTUResourceUsage requires value type, so create it by pointer
    151 					Lib.dispose_resource_usage(Lib::CXTUResourceUsage.new(pointer))
    152 				end
    153 
    154 				def self.name(kind)
    155 					Lib.resource_usage_name(kind)
    156 				end
    157 
    158 				def entries
    159 					ary = []
    160 					ptr = @resource_usage[:entries]
    161 					@resource_usage[:numEntries].times {
    162 						ary << Lib::CXTUResourceUsageEntry.new(ptr)
    163 						ptr += Lib::CXTUResourceUsageEntry.size
    164 					}
    165 					ary
    166 				end
    167 			end
    168 		end
    169 	end
    170 end