Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require 'rubygems'
- require 'ffi'
- module Clang
- module Lib
- extend FFI::Library
- ffi_lib "clang"
- attach_function :create_index, :clang_createIndex, [:int, :int], :pointer
- attach_function :dispose_index, :clang_disposeIndex, [:pointer], :void
- attach_function :parse_translation_unit, :clang_parseTranslationUnit, [:pointer, :string, :pointer, :int, :pointer, :uint, :uint], :pointer
- attach_function :dispose_translation_unit, :clang_disposeTranslationUnit, [:pointer], :void
- attach_function :get_num_diagnostics, :clang_getNumDiagnostics, [:pointer], :uint
- attach_function :get_diagnostic, :clang_getDiagnostic, [:pointer, :uint], :pointer
- attach_function :dispose_diagnostic, :clang_disposeDiagnostic, [:pointer], :void
- attach_function :format_diagnostic, :clang_formatDiagnostic, [:pointer, :uint], :pointer
- attach_function :default_diagnostic_display_options, :clang_defaultDiagnosticDisplayOptions, [], :uint
- attach_function :get_c_string, :clang_getCString, [:pointer], :string
- attach_function :dispose_string, :clang_disposeString, [:pointer], :void
- attach_function :get_diagnostic_location, :clang_getDiagnosticLocation, [:pointer], :pointer
- attach_function :equal_locations, :clang_equalLocations, [:pointer, :pointer], :uint
- end
- class TranslationUnit
- def initialize(ptr)
- @ptr = FFI::AutoPointer.new(ptr, Lib.method(:dispose_translation_unit))
- end
- def diagnostics
- n = Lib.get_num_diagnostics(@ptr)
- 0.upto(n - 1).map do |idx|
- Diagnostic.new(Lib.get_diagnostic(@ptr, idx))
- end
- end
- end
- class Diagnostic
- def initialize(ptr)
- @ptr = FFI::AutoPointer.new(ptr, Lib.method(:dispose_diagnostic))
- end
- def format(opts = {})
- raise NotImplementedError, "#{self.class}#format options" unless opts.empty?
- cxstring = Lib.format_diagnostic(@ptr, Lib.default_diagnostic_display_options)
- result = Lib.get_c_string(cxstring)
- Lib.dispose_string(cxstring)
- result
- end
- def severity
- raise NotImplementedError
- end
- def source_location
- SourceLocation.new(Lib.get_diagnostic_location(@ptr))
- end
- def fixits
- raise NotImplementedError
- # unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag);
- # – CXString clang_getDiagnosticFixIt(CXDiagnostic Diag,
- # unsigned FixIt,
- # CXSourceRange *ReplacementRange);
- end
- def spelling
- raise NotImplementedError
- end
- end
- class SourceLocation
- def initialize(ptr)
- # no release? should we keep a reference to TU / diagnostic?
- @ptr = ptr
- end
- def ==(other)
- return unless other.kind_of? self.class
- Lib.equal_locations(@ptr, other.ptr) != 0
- end
- alias_method :eql?, :==
- protected
- def ptr
- @ptr
- end
- end
- class Index
- def initialize(opts = {})
- exclude_declarations_from_pch = opts[:exclude_declarations_from_pch] ? 1 : 0
- display_diagnostics = opts[:display_diagnostics] ? 1 : 0
- @ptr = FFI::AutoPointer.new Lib.create_index(exclude_declarations_from_pch, display_diagnostics),
- Lib.method(:dispose_index)
- end
- def parse_translation_unit(source_file, command_line_args = nil, opts = {})
- command_line_args = Array(command_line_args)
- args_pointer = FFI::MemoryPointer.new(:pointer)
- strings = command_line_args.map do |arg|
- FFI::MemoryPointer.from_string(arg.to_s)
- end
- args_pointer.put_array_of_pointer(strings) unless strings.empty?
- raise NotImplementedError, "options for #{self.class}#parse_translation_unit" unless opts.empty?
- tu = Lib.parse_translation_unit(@ptr, source_file, args_pointer, command_line_args.size, nil, 0, 0)
- raise "error parsing #{source_file.inspect}" if tu.nil? || tu.null?
- TranslationUnit.new tu
- end
- end
- end
Add Comment
Please, Sign In to add comment