lib/ffi/clang/translation_unit.rb in ffi-clang-0.2.0 vs lib/ffi/clang/translation_unit.rb in ffi-clang-0.2.1

- old
+ new

@@ -1,7 +1,8 @@ # Copyright, 2010-2012 by Jari Bakken. # Copyright, 2013, by Samuel G. D. Williams. <http://www.codeotaku.com> +# Copyright, 2014, by Masahiro Sano. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell @@ -18,11 +19,14 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. require 'ffi/clang/lib/translation_unit' +require 'ffi/clang/lib/inclusions' require 'ffi/clang/cursor' +require 'ffi/clang/file' +require 'ffi/clang/token' module FFI module Clang class TranslationUnit < AutoPointer def initialize(pointer, index) @@ -32,19 +36,131 @@ def self.release(pointer) Lib.dispose_translation_unit(pointer) end + def self.default_editing_translation_unit_options + bitmask = Lib.default_editing_translation_unit_options + Lib.opts_from Lib::TranslationUnitFlags, bitmask + end + + def default_save_options + bitmask = Lib.default_save_options(self) + Lib.opts_from Lib::SaveTranslationUnitFlags, bitmask + end + + def save(filename, opts = {}) + ret = Lib.save_translation_unit(self, filename, 0) + sym = Lib::SaveError[ret] + raise Error, "unknown return values: #{ret} #{sym.inspect}" unless sym + raise Error, "save error: #{sym.inspect}, filename: #{filename}" if sym != :none + end + + def default_reparse_options + bitmask = Lib.default_save_options(self) + Lib.opts_from Lib::ReparseFlags, bitmask + end + + def reparse(unsaved = [], opts = {}) + unsaved_files = UnsavedFile.unsaved_pointer_from(unsaved) + if Lib.reparse_translation_unit(self, unsaved.size, unsaved_files, 0) != 0 + raise Error, "reparse error" + end + end + def diagnostics n = Lib.get_num_diagnostics(self) n.times.map do |i| Diagnostic.new(self, Lib.get_diagnostic(self, i)) end end - def cursor - Cursor.new(Lib.get_translation_unit_cursor(self), self) + def cursor(location = nil) + if location.nil? + Cursor.new Lib.get_translation_unit_cursor(self), self + else + Cursor.new Lib.get_cursor(self, location.location), self + end + end + + def location(file, line, column) + ExpansionLocation.new Lib.get_location(self, file, line, column) + end + + def location_offset(file, offset) + ExpansionLocation.new Lib.get_location_offset(self, file, offset) + end + + def file(file_name) + File.new(Lib.get_file(self, file_name), self) + end + + def spelling + Lib.get_translation_unit_spelling(self) + end + + def resource_usage + FFI::Clang::TranslationUnit::ResourceUsage.new Lib.resource_usage(self) + end + + def tokenize(range) + token_ptr = MemoryPointer.new :pointer + uint_ptr = MemoryPointer.new :uint + Lib.tokenize(self, range.range, token_ptr, uint_ptr) + Tokens.new(token_ptr.get_pointer(0), uint_ptr.get_uint(0), self) + end + + def code_complete(source_file, line, column, unsaved = [], opts = nil) + opts = CodeCompletion.default_code_completion_options if opts.nil? + unsaved_files = UnsavedFile.unsaved_pointer_from(unsaved) + option_bitmask = Lib.bitmask_from(Lib::CodeCompleteFlags, opts) + ptr = Lib.code_complete_at(self, source_file, line, column, unsaved_files, unsaved.length, option_bitmask) + CodeCompletion::Results.new ptr, self + end + + def inclusions(&block) + adapter = Proc.new do |included_file, inclusion_stack, include_len, unused| + file = Lib.extract_string Lib.get_file_name(included_file) + cur_ptr = inclusion_stack + inclusions = [] + include_len.times { + inclusions << SourceLocation.new(Lib::CXSourceLocation.new(cur_ptr)) + cur_ptr += Lib::CXSourceLocation.size + } + block.call file, inclusions + end + + Lib.get_inclusions(self, adapter, nil) + end + + class ResourceUsage < AutoPointer + def initialize(resource_usage) + # CXResourceUsage is returned by value and should be freed explicitly. + # Get FFI::pointer of the data so that the data is handled by AutoPointer. + pointer = FFI::Pointer.new(resource_usage.to_ptr) + super(pointer) + @resource_usage = resource_usage + end + + def self.release(pointer) + # clang_disposeCXTUResourceUsage requires value type, so create it by pointer + Lib.dispose_resource_usage(Lib::CXTUResourceUsage.new(pointer)) + end + + def self.name(kind) + Lib.resource_usage_name(kind) + end + + def entries + ary = [] + ptr = @resource_usage[:entries] + @resource_usage[:numEntries].times { + ary << Lib::CXTUResourceUsageEntry.new(ptr) + ptr += Lib::CXTUResourceUsageEntry.size + } + ary + end end end end end