Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

- Added libclang.dll support(experimental).

  • Loading branch information...
commit 2bcf80dfbd3f8853ef7a267548d6e5c9436522c4 1 parent f479ade
@Shougo authored
View
107 autoload/neocomplcache/sources/clang_complete.vim
@@ -23,13 +23,48 @@
" - Add snippets on Pattern and OVERLOAD (is it possible?)
"
+" Variables initialize.
+if !exists('g:neocomplcache_clang_complete_use_library')
+ let g:neocomplcache_clang_complete_use_library = 0
+endif
+if !exists('g:neocomplcache_clang_complete_macros')
+ let g:neocomplcache_clang_complete_macros = 0
+endif
+if !exists('g:neocomplcache_clang_complete_patterns')
+ let g:neocomplcache_clang_complete_patterns = 0
+endif
+if !exists('g:neocomplcache_clang_complete_user_options')
+ let g:neocomplcache_clang_complete_user_options = ''
+endif
+
let s:source = {
\ 'name': 'clang_complete',
\ 'kind': 'ftplugin',
\ 'filetypes': { 'c': 1, 'cpp': 1, 'objc': 1, 'objcpp': 1 },
\ }
-function s:ClangCompleteInit()
+" Store plugin path, as this is available only when sourcing the file,
+" not during a function call.
+let s:plugin_path = escape(expand('<sfile>:p:h'), '\')
+
+function! s:init_ClangCompletePython()
+ python import sys
+
+ if exists('g:neocomplcache_clang_complete_library_path')
+ " Load the library from the given library path.
+ execute 'python sys.argv = ["' . escape(g:neocomplcache_clang_complete_library_path, '\') . '"]'
+ else
+ " By setting argv[0] to '' force the python bindings to load the library
+ " from the normal system search path.
+ python sys.argv[0] = ''
+ endif
+
+ execute 'python sys.path = ["' . s:plugin_path . '/clang_complete"] + sys.path'
+ execute 'pyfile ' . s:plugin_path . '/clang_complete/libclang.py'
+ python initClangComplete(vim.eval('g:neocomplcache_clang_complete_lib_flags'))
+endfunction
+
+function! s:init_ClangComplete()
let b:should_overload = 0
let l:local_conf = findfile('.clang_complete', '.;')
@@ -82,6 +117,29 @@ function s:ClangCompleteInit()
if expand('%:e') =~ 'h*'
let b:clang_parameters .= '-header'
endif
+
+ let g:neocomplcache_clang_complete_lib_flags = 0
+ if g:neocomplcache_clang_complete_macros
+ let b:clang_parameters .= ' -code-completion-macros'
+ let g:neocomplcache_clang_complete_lib_flags = 1
+ endif
+ if g:neocomplcache_clang_complete_patterns
+ let b:clang_parameters .= ' -code-completion-patterns'
+ let g:clang_complete_lib_flags += 2
+ endif
+
+ " Load the python bindings of libclang.
+ if g:neocomplcache_clang_complete_use_library
+ if has('python')
+ call s:init_ClangCompletePython()
+ else
+ echoe 'clang_complete: No python support available.'
+ echoe 'Cannot use clang library, using executable'
+ echoe 'Compile vim with python support to use libclang'
+ let g:neocomplcache_clang_complete_use_library = 0
+ return
+ endif
+ endif
endfunction
function! s:get_kind(proto)
@@ -103,9 +161,9 @@ function! s:get_kind(proto)
endfunction
function! s:source.initialize()
- au neocomplcache FileType c,cpp,objc,objcpp call s:ClangCompleteInit()
+ autocmd neocomplcache FileType c,cpp,objc,objcpp call s:init_ClangComplete()
if &l:filetype == 'c' || &l:filetype == 'cpp' || &l:filetype == 'objc' || &l:filetype == 'objcpp'
- call s:ClangCompleteInit()
+ call s:init_ClangComplete()
endif
call neocomplcache#set_completion_length('clang_complete', 0)
@@ -188,26 +246,17 @@ function! s:source.get_complete_words(cur_keyword_pos, cur_keyword_str)
return []
endif
- let l:buf = getline(1, '$')
- let l:tempfile = expand('%:p:h') . '/' . localtime() . expand('%:t')
- if neocomplcache#is_win()
- let l:tempfile = substitute(l:tempfile, '\\', '/', 'g')
+ if g:neocomplcache_clang_complete_use_library
+ python vim.command('let l:clang_output = ' + str(getCurrentCompletions(vim.eval('a:cur_keyword_str'), vim.eval('a:cur_keyword_pos+1'))))
+ " echomsg string(l:clang_output)
+ else
+ let l:clang_output = s:complete_from_clang_binary(a:cur_keyword_pos)
endif
- call writefile(l:buf, l:tempfile)
- let l:escaped_tempfile = shellescape(l:tempfile)
-
- let l:command = b:clang_exec . ' -cc1 -fsyntax-only'
- \ . ' -fno-caret-diagnostics -fdiagnostics-print-source-range-info'
- \ . ' -code-completion-at='
- \ . l:escaped_tempfile . ":" . line('.') . ":" . (a:cur_keyword_pos+1)
- \ . ' ' . l:escaped_tempfile
- \ . ' ' . b:clang_parameters . ' ' . b:clang_user_options . ' -o -'
- let l:clang_output = split(neocomplcache#system(l:command), '\n')
- call delete(l:tempfile)
if v:shell_error
call s:ClangQuickFix(l:clang_output)
return []
endif
+
if l:clang_output == []
return []
endif
@@ -268,6 +317,28 @@ function! s:source.get_complete_words(cur_keyword_pos, cur_keyword_str)
return l:list
endfunction
+function! s:complete_from_clang_binary(cur_keyword_pos)
+ let l:buf = getline(1, '$')
+ let l:tempfile = expand('%:p:h') . '/' . localtime() . expand('%:t')
+ if neocomplcache#is_win()
+ let l:tempfile = substitute(l:tempfile, '\\', '/', 'g')
+ endif
+ call writefile(l:buf, l:tempfile)
+ let l:escaped_tempfile = shellescape(l:tempfile)
+
+ let l:command = b:clang_exec . ' -cc1 -fsyntax-only'
+ \ . ' -fno-caret-diagnostics -fdiagnostics-print-source-range-info'
+ \ . ' -code-completion-at='
+ \ . l:escaped_tempfile . ":" . line('.') . ":" . (a:cur_keyword_pos+1)
+ \ . ' ' . l:escaped_tempfile
+ \ . ' ' . b:clang_parameters . ' ' . b:clang_user_options . ' ' . g:neocomplcache_clang_complete_user_options
+ let l:clang_output = split(neocomplcache#system(l:command), '\n')
+
+ call delete(l:tempfile)
+
+ return l:clang_output
+endfunction
+
function! neocomplcache#sources#clang_complete#define()
return s:source
endfunction
View
24 autoload/neocomplcache/sources/clang_complete/clang/__init__.py
@@ -0,0 +1,24 @@
+#===- __init__.py - Clang Python Bindings --------------------*- python -*--===#
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+r"""
+Clang Library Bindings
+======================
+
+This package provides access to the Clang compiler and libraries.
+
+The available modules are:
+
+ cindex
+
+ Bindings for the Clang indexing library.
+"""
+
+__all__ = ['cindex']
+
View
BIN  autoload/neocomplcache/sources/clang_complete/clang/__init__.pyc
Binary file not shown
View
1,237 autoload/neocomplcache/sources/clang_complete/clang/cindex.py
@@ -0,0 +1,1237 @@
+#===- cindex.py - Python Indexing Library Bindings -----------*- python -*--===#
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+r"""
+Clang Indexing Library Bindings
+===============================
+
+This module provides an interface to the Clang indexing library. It is a
+low-level interface to the indexing library which attempts to match the Clang
+API directly while also being "pythonic". Notable differences from the C API
+are:
+
+ * string results are returned as Python strings, not CXString objects.
+
+ * null cursors are translated to None.
+
+ * access to child cursors is done via iteration, not visitation.
+
+The major indexing objects are:
+
+ Index
+
+ The top-level object which manages some global library state.
+
+ TranslationUnit
+
+ High-level object encapsulating the AST for a single translation unit. These
+ can be loaded from .ast files or parsed on the fly.
+
+ Cursor
+
+ Generic object for representing a node in the AST.
+
+ SourceRange, SourceLocation, and File
+
+ Objects representing information about the input source.
+
+Most object information is exposed using properties, when the underlying API
+call is efficient.
+"""
+
+# TODO
+# ====
+#
+# o API support for invalid translation units. Currently we can't even get the
+# diagnostics on failure because they refer to locations in an object that
+# will have been invalidated.
+#
+# o fix memory management issues (currently client must hold on to index and
+# translation unit, or risk crashes).
+#
+# o expose code completion APIs.
+#
+# o cleanup ctypes wrapping, would be nice to separate the ctypes details more
+# clearly, and hide from the external interface (i.e., help(cindex)).
+#
+# o implement additional SourceLocation, SourceRange, and File methods.
+
+import sys
+import vim
+from ctypes import *
+
+def get_cindex_library():
+ # FIXME: It's probably not the case that the library is actually found in
+ # this location. We need a better system of identifying and loading the
+ # CIndex library. It could be on path or elsewhere, or versioned, etc.
+ import platform
+ name = platform.system()
+ path = sys.argv[0]
+ if path != '':
+ path += '/'
+ if name == 'Darwin':
+ path += 'clang.dylib'
+ elif name == 'Windows':
+ path += 'clang.dll'
+ else:
+ path += 'clang.so'
+ return cdll.LoadLibrary(path)
+
+# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
+# object. This is a problem, because it means that from_parameter will see an
+# integer and pass the wrong value on platforms where int != void*. Work around
+# this by marshalling object arguments as void**.
+c_object_p = POINTER(c_void_p)
+
+lib = get_cindex_library()
+
+### Structures and Utility Classes ###
+
+class _CXString(Structure):
+ """Helper for transforming CXString results."""
+
+ _fields_ = [("spelling", c_char_p), ("free", c_int)]
+
+ def __del__(self):
+ _CXString_dispose(self)
+
+ @staticmethod
+ def from_result(res, fn, args):
+ assert isinstance(res, _CXString)
+ return _CXString_getCString(res)
+
+class SourceLocation(Structure):
+ """
+ A SourceLocation represents a particular location within a source file.
+ """
+ _fields_ = [("ptr_data", c_void_p * 2), ("int_data", c_uint)]
+ _data = None
+
+ def _get_instantiation(self):
+ if self._data is None:
+ f, l, c, o = c_object_p(), c_uint(), c_uint(), c_uint()
+ SourceLocation_loc(self, byref(f), byref(l), byref(c), byref(o))
+ if f:
+ f = File(f)
+ else:
+ f = None
+ self._data = (f, int(l.value), int(c.value), int(c.value))
+ return self._data
+
+ @property
+ def file(self):
+ """Get the file represented by this source location."""
+ return self._get_instantiation()[0]
+
+ @property
+ def line(self):
+ """Get the line represented by this source location."""
+ return self._get_instantiation()[1]
+
+ @property
+ def column(self):
+ """Get the column represented by this source location."""
+ return self._get_instantiation()[2]
+
+ @property
+ def offset(self):
+ """Get the file offset represented by this source location."""
+ return self._get_instantiation()[3]
+
+ def __repr__(self):
+ if self.file:
+ filename = self.file.name
+ else:
+ filename = None
+ return "<SourceLocation file %r, line %r, column %r>" % (
+ filename, self.line, self.column)
+
+class SourceRange(Structure):
+ """
+ A SourceRange describes a range of source locations within the source
+ code.
+ """
+ _fields_ = [
+ ("ptr_data", c_void_p * 2),
+ ("begin_int_data", c_uint),
+ ("end_int_data", c_uint)]
+
+ # FIXME: Eliminate this and make normal constructor? Requires hiding ctypes
+ # object.
+ @staticmethod
+ def from_locations(start, end):
+ return SourceRange_getRange(start, end)
+
+ @property
+ def start(self):
+ """
+ Return a SourceLocation representing the first character within a
+ source range.
+ """
+ return SourceRange_start(self)
+
+ @property
+ def end(self):
+ """
+ Return a SourceLocation representing the last character within a
+ source range.
+ """
+ return SourceRange_end(self)
+
+ def __repr__(self):
+ return "<SourceRange start %r, end %r>" % (self.start, self.end)
+
+class Diagnostic(object):
+ """
+ A Diagnostic is a single instance of a Clang diagnostic. It includes the
+ diagnostic severity, the message, the location the diagnostic occurred, as
+ well as additional source ranges and associated fix-it hints.
+ """
+
+ Ignored = 0
+ Note = 1
+ Warning = 2
+ Error = 3
+ Fatal = 4
+
+ def __init__(self, ptr):
+ self.ptr = ptr
+
+ def __del__(self):
+ _clang_disposeDiagnostic(self)
+
+ @property
+ def severity(self):
+ return _clang_getDiagnosticSeverity(self)
+
+ @property
+ def location(self):
+ return _clang_getDiagnosticLocation(self)
+
+ @property
+ def spelling(self):
+ return _clang_getDiagnosticSpelling(self)
+
+ @property
+ def ranges(self):
+ class RangeIterator:
+ def __init__(self, diag):
+ self.diag = diag
+
+ def __len__(self):
+ return int(_clang_getDiagnosticNumRanges(self.diag))
+
+ def __getitem__(self, key):
+ if (key >= len(self)):
+ raise IndexError
+ return _clang_getDiagnosticRange(self.diag, key)
+
+ return RangeIterator(self)
+
+ @property
+ def fixits(self):
+ class FixItIterator:
+ def __init__(self, diag):
+ self.diag = diag
+
+ def __len__(self):
+ return int(_clang_getDiagnosticNumFixIts(self.diag))
+
+ def __getitem__(self, key):
+ range = SourceRange()
+ value = _clang_getDiagnosticFixIt(self.diag, key, byref(range))
+ if len(value) == 0:
+ raise IndexError
+
+ return FixIt(range, value)
+
+ return FixItIterator(self)
+
+ def __repr__(self):
+ return "<Diagnostic severity %r, location %r, spelling %r>" % (
+ self.severity, self.location, self.spelling)
+
+ def from_param(self):
+ return self.ptr
+
+class FixIt(object):
+ """
+ A FixIt represents a transformation to be applied to the source to
+ "fix-it". The fix-it shouldbe applied by replacing the given source range
+ with the given value.
+ """
+
+ def __init__(self, range, value):
+ self.range = range
+ self.value = value
+
+ def __repr__(self):
+ return "<FixIt range %r, value %r>" % (self.range, self.value)
+
+### Cursor Kinds ###
+
+class CursorKind(object):
+ """
+ A CursorKind describes the kind of entity that a cursor points to.
+ """
+
+ # The unique kind objects, indexed by id.
+ _kinds = []
+ _name_map = None
+
+ def __init__(self, value):
+ if value >= len(CursorKind._kinds):
+ CursorKind._kinds += [None] * (value - len(CursorKind._kinds) + 1)
+ if CursorKind._kinds[value] is not None:
+ raise ValueError,'CursorKind already loaded'
+ self.value = value
+ CursorKind._kinds[value] = self
+ CursorKind._name_map = None
+
+ def from_param(self):
+ return self.value
+
+ @property
+ def name(self):
+ """Get the enumeration name of this cursor kind."""
+ if self._name_map is None:
+ self._name_map = {}
+ for key,value in CursorKind.__dict__.items():
+ if isinstance(value,CursorKind):
+ self._name_map[value] = key
+ return self._name_map[self]
+
+ @staticmethod
+ def from_id(id):
+ if id >= len(CursorKind._kinds) or CursorKind._kinds[id] is None:
+ raise ValueError,'Unknown cursor kind'
+ return CursorKind._kinds[id]
+
+ @staticmethod
+ def get_all_kinds():
+ """Return all CursorKind enumeration instances."""
+ return filter(None, CursorKind._kinds)
+
+ def is_declaration(self):
+ """Test if this is a declaration kind."""
+ return CursorKind_is_decl(self)
+
+ def is_reference(self):
+ """Test if this is a reference kind."""
+ return CursorKind_is_ref(self)
+
+ def is_expression(self):
+ """Test if this is an expression kind."""
+ return CursorKind_is_expr(self)
+
+ def is_statement(self):
+ """Test if this is a statement kind."""
+ return CursorKind_is_stmt(self)
+
+ def is_invalid(self):
+ """Test if this is an invalid kind."""
+ return CursorKind_is_inv(self)
+
+ def __repr__(self):
+ return 'CursorKind.%s' % (self.name,)
+
+# FIXME: Is there a nicer way to expose this enumeration? We could potentially
+# represent the nested structure, or even build a class hierarchy. The main
+# things we want for sure are (a) simple external access to kinds, (b) a place
+# to hang a description and name, (c) easy to keep in sync with Index.h.
+
+###
+# Declaration Kinds
+
+# A declaration whose specific kind is not exposed via this interface.
+#
+# Unexposed declarations have the same operations as any other kind of
+# declaration; one can extract their location information, spelling, find their
+# definitions, etc. However, the specific kind of the declaration is not
+# reported.
+CursorKind.UNEXPOSED_DECL = CursorKind(1)
+
+# A C or C++ struct.
+CursorKind.STRUCT_DECL = CursorKind(2)
+
+# A C or C++ union.
+CursorKind.UNION_DECL = CursorKind(3)
+
+# A C++ class.
+CursorKind.CLASS_DECL = CursorKind(4)
+
+# An enumeration.
+CursorKind.ENUM_DECL = CursorKind(5)
+
+# A field (in C) or non-static data member (in C++) in a struct, union, or C++
+# class.
+CursorKind.FIELD_DECL = CursorKind(6)
+
+# An enumerator constant.
+CursorKind.ENUM_CONSTANT_DECL = CursorKind(7)
+
+# A function.
+CursorKind.FUNCTION_DECL = CursorKind(8)
+
+# A variable.
+CursorKind.VAR_DECL = CursorKind(9)
+
+# A function or method parameter.
+CursorKind.PARM_DECL = CursorKind(10)
+
+# An Objective-C @interface.
+CursorKind.OBJC_INTERFACE_DECL = CursorKind(11)
+
+# An Objective-C @interface for a category.
+CursorKind.OBJC_CATEGORY_DECL = CursorKind(12)
+
+# An Objective-C @protocol declaration.
+CursorKind.OBJC_PROTOCOL_DECL = CursorKind(13)
+
+# An Objective-C @property declaration.
+CursorKind.OBJC_PROPERTY_DECL = CursorKind(14)
+
+# An Objective-C instance variable.
+CursorKind.OBJC_IVAR_DECL = CursorKind(15)
+
+# An Objective-C instance method.
+CursorKind.OBJC_INSTANCE_METHOD_DECL = CursorKind(16)
+
+# An Objective-C class method.
+CursorKind.OBJC_CLASS_METHOD_DECL = CursorKind(17)
+
+# An Objective-C @implementation.
+CursorKind.OBJC_IMPLEMENTATION_DECL = CursorKind(18)
+
+# An Objective-C @implementation for a category.
+CursorKind.OBJC_CATEGORY_IMPL_DECL = CursorKind(19)
+
+# A typedef.
+CursorKind.TYPEDEF_DECL = CursorKind(20)
+
+###
+# Reference Kinds
+
+CursorKind.OBJC_SUPER_CLASS_REF = CursorKind(40)
+CursorKind.OBJC_PROTOCOL_REF = CursorKind(41)
+CursorKind.OBJC_CLASS_REF = CursorKind(42)
+
+# A reference to a type declaration.
+#
+# A type reference occurs anywhere where a type is named but not
+# declared. For example, given:
+# typedef unsigned size_type;
+# size_type size;
+#
+# The typedef is a declaration of size_type (CXCursor_TypedefDecl),
+# while the type of the variable "size" is referenced. The cursor
+# referenced by the type of size is the typedef for size_type.
+CursorKind.TYPE_REF = CursorKind(43)
+
+###
+# Invalid/Error Kinds
+
+CursorKind.INVALID_FILE = CursorKind(70)
+CursorKind.NO_DECL_FOUND = CursorKind(71)
+CursorKind.NOT_IMPLEMENTED = CursorKind(72)
+
+###
+# Expression Kinds
+
+# An expression whose specific kind is not exposed via this interface.
+#
+# Unexposed expressions have the same operations as any other kind of
+# expression; one can extract their location information, spelling, children,
+# etc. However, the specific kind of the expression is not reported.
+CursorKind.UNEXPOSED_EXPR = CursorKind(100)
+
+# An expression that refers to some value declaration, such as a function,
+# varible, or enumerator.
+CursorKind.DECL_REF_EXPR = CursorKind(101)
+
+# An expression that refers to a member of a struct, union, class, Objective-C
+# class, etc.
+CursorKind.MEMBER_REF_EXPR = CursorKind(102)
+
+# An expression that calls a function.
+CursorKind.CALL_EXPR = CursorKind(103)
+
+# An expression that sends a message to an Objective-C object or class.
+CursorKind.OBJC_MESSAGE_EXPR = CursorKind(104)
+
+# A statement whose specific kind is not exposed via this interface.
+#
+# Unexposed statements have the same operations as any other kind of statement;
+# one can extract their location information, spelling, children, etc. However,
+# the specific kind of the statement is not reported.
+CursorKind.UNEXPOSED_STMT = CursorKind(200)
+
+###
+# Other Kinds
+
+# Cursor that represents the translation unit itself.
+#
+# The translation unit cursor exists primarily to act as the root cursor for
+# traversing the contents of a translation unit.
+CursorKind.TRANSLATION_UNIT = CursorKind(300)
+
+### Cursors ###
+
+class Cursor(Structure):
+ """
+ The Cursor class represents a reference to an element within the AST. It
+ acts as a kind of iterator.
+ """
+ _fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)]
+
+ def __eq__(self, other):
+ return Cursor_eq(self, other)
+
+ def __ne__(self, other):
+ return not Cursor_eq(self, other)
+
+ def is_definition(self):
+ """
+ Returns true if the declaration pointed at by the cursor is also a
+ definition of that entity.
+ """
+ return Cursor_is_def(self)
+
+ def get_definition(self):
+ """
+ If the cursor is a reference to a declaration or a declaration of
+ some entity, return a cursor that points to the definition of that
+ entity.
+ """
+ # TODO: Should probably check that this is either a reference or
+ # declaration prior to issuing the lookup.
+ return Cursor_def(self)
+
+ def get_usr(self):
+ """Return the Unified Symbol Resultion (USR) for the entity referenced
+ by the given cursor (or None).
+
+ A Unified Symbol Resolution (USR) is a string that identifies a
+ particular entity (function, class, variable, etc.) within a
+ program. USRs can be compared across translation units to determine,
+ e.g., when references in one translation refer to an entity defined in
+ another translation unit."""
+ return Cursor_usr(self)
+
+ @property
+ def kind(self):
+ """Return the kind of this cursor."""
+ return CursorKind.from_id(self._kind_id)
+
+ @property
+ def spelling(self):
+ """Return the spelling of the entity pointed at by the cursor."""
+ if not self.kind.is_declaration():
+ # FIXME: clang_getCursorSpelling should be fixed to not assert on
+ # this, for consistency with clang_getCursorUSR.
+ return None
+ return Cursor_spelling(self)
+
+ @property
+ def location(self):
+ """
+ Return the source location (the starting character) of the entity
+ pointed at by the cursor.
+ """
+ return Cursor_loc(self)
+
+ @property
+ def extent(self):
+ """
+ Return the source range (the range of text) occupied by the entity
+ pointed at by the cursor.
+ """
+ return Cursor_extent(self)
+
+ def get_children(self):
+ """Return an iterator for accessing the children of this cursor."""
+
+ # FIXME: Expose iteration from CIndex, PR6125.
+ def visitor(child, parent, children):
+ # FIXME: Document this assertion in API.
+ # FIXME: There should just be an isNull method.
+ assert child != Cursor_null()
+ children.append(child)
+ return 1 # continue
+ children = []
+ Cursor_visit(self, Cursor_visit_callback(visitor), children)
+ return iter(children)
+
+ @staticmethod
+ def from_result(res, fn, args):
+ assert isinstance(res, Cursor)
+ # FIXME: There should just be an isNull method.
+ if res == Cursor_null():
+ return None
+ return res
+
+## CIndex Objects ##
+
+# CIndex objects (derived from ClangObject) are essentially lightweight
+# wrappers attached to some underlying object, which is exposed via CIndex as
+# a void*.
+
+class ClangObject(object):
+ """
+ A helper for Clang objects. This class helps act as an intermediary for
+ the ctypes library and the Clang CIndex library.
+ """
+ def __init__(self, obj):
+ assert isinstance(obj, c_object_p) and obj
+ self.obj = self._as_parameter_ = obj
+
+ def from_param(self):
+ return self._as_parameter_
+
+
+class _CXUnsavedFile(Structure):
+ """Helper for passing unsaved file arguments."""
+ _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)]
+
+## Diagnostic Conversion ##
+
+_clang_getNumDiagnostics = lib.clang_getNumDiagnostics
+_clang_getNumDiagnostics.argtypes = [c_object_p]
+_clang_getNumDiagnostics.restype = c_uint
+
+_clang_getDiagnostic = lib.clang_getDiagnostic
+_clang_getDiagnostic.argtypes = [c_object_p, c_uint]
+_clang_getDiagnostic.restype = c_object_p
+
+_clang_disposeDiagnostic = lib.clang_disposeDiagnostic
+_clang_disposeDiagnostic.argtypes = [Diagnostic]
+
+_clang_getDiagnosticSeverity = lib.clang_getDiagnosticSeverity
+_clang_getDiagnosticSeverity.argtypes = [Diagnostic]
+_clang_getDiagnosticSeverity.restype = c_int
+
+_clang_getDiagnosticLocation = lib.clang_getDiagnosticLocation
+_clang_getDiagnosticLocation.argtypes = [Diagnostic]
+_clang_getDiagnosticLocation.restype = SourceLocation
+
+_clang_getDiagnosticSpelling = lib.clang_getDiagnosticSpelling
+_clang_getDiagnosticSpelling.argtypes = [Diagnostic]
+_clang_getDiagnosticSpelling.restype = _CXString
+_clang_getDiagnosticSpelling.errcheck = _CXString.from_result
+
+_clang_getDiagnosticNumRanges = lib.clang_getDiagnosticNumRanges
+_clang_getDiagnosticNumRanges.argtypes = [Diagnostic]
+_clang_getDiagnosticNumRanges.restype = c_uint
+
+_clang_getDiagnosticRange = lib.clang_getDiagnosticRange
+_clang_getDiagnosticRange.argtypes = [Diagnostic, c_uint]
+_clang_getDiagnosticRange.restype = SourceRange
+
+_clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts
+_clang_getDiagnosticNumFixIts.argtypes = [Diagnostic]
+_clang_getDiagnosticNumFixIts.restype = c_uint
+
+_clang_getDiagnosticFixIt = lib.clang_getDiagnosticFixIt
+_clang_getDiagnosticFixIt.argtypes = [Diagnostic, c_uint, POINTER(SourceRange)]
+_clang_getDiagnosticFixIt.restype = _CXString
+_clang_getDiagnosticFixIt.errcheck = _CXString.from_result
+
+###
+
+class CompletionChunk:
+ class Kind:
+ def __init__(self, name):
+ self.name = name
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return "<ChunkKind: %s>" % self
+
+ def __init__(self, completionString, key):
+ self.cs = completionString
+ self.key = key
+
+ def __repr__(self):
+ return "{'" + self.spelling + "', " + str(self.kind) + "}"
+
+ @property
+ def spelling(self):
+ return _clang_getCompletionChunkText(self.cs, self.key).spelling
+
+ @property
+ def kind(self):
+ res = _clang_getCompletionChunkKind(self.cs, self.key)
+ return completionChunkKindMap[res]
+
+ @property
+ def string(self):
+ res = _clang_getCompletionChunkCompletionString(self.cs, self.key)
+
+ if (res):
+ return CompletionString(res)
+ else:
+ None
+
+ def isKindOptional(self):
+ return self.kind == completionChunkKindMap[0]
+
+ def isKindTypedText(self):
+ return self.kind == completionChunkKindMap[1]
+
+ def isKindPlaceHolder(self):
+ return self.kind == completionChunkKindMap[3]
+
+ def isKindInformative(self):
+ return self.kind == completionChunkKindMap[4]
+
+ def isKindResultType(self):
+ return self.kind == completionChunkKindMap[15]
+
+completionChunkKindMap = {
+ 0: CompletionChunk.Kind("Optional"),
+ 1: CompletionChunk.Kind("TypedText"),
+ 2: CompletionChunk.Kind("Text"),
+ 3: CompletionChunk.Kind("Placeholder"),
+ 4: CompletionChunk.Kind("Informative"),
+ 5: CompletionChunk.Kind("CurrentParameter"),
+ 6: CompletionChunk.Kind("LeftParen"),
+ 7: CompletionChunk.Kind("RightParen"),
+ 8: CompletionChunk.Kind("LeftBracket"),
+ 9: CompletionChunk.Kind("RightBracket"),
+ 10: CompletionChunk.Kind("LeftBrace"),
+ 11: CompletionChunk.Kind("RightBrace"),
+ 12: CompletionChunk.Kind("LeftAngle"),
+ 13: CompletionChunk.Kind("RightAngle"),
+ 14: CompletionChunk.Kind("Comma"),
+ 15: CompletionChunk.Kind("ResultType"),
+ 16: CompletionChunk.Kind("Colon"),
+ 17: CompletionChunk.Kind("SemiColon"),
+ 18: CompletionChunk.Kind("Equal"),
+ 19: CompletionChunk.Kind("HorizontalSpace"),
+ 20: CompletionChunk.Kind("VerticalSpace")}
+
+class CompletionString(ClangObject):
+ class Availability:
+ def __init__(self, name):
+ self.name = name
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return "<Availability: %s>" % self
+
+ def __len__(self):
+ return _clang_getNumCompletionChunks(self.obj)
+
+ def __getitem__(self, key):
+ if len(self) <= key:
+ raise IndexError
+ return CompletionChunk(self.obj, key)
+
+ @property
+ def priority(self):
+ return _clang_getCompletionPriority(self.obj)
+
+ @property
+ def availability(self):
+ res = _clang_getCompletionAvailability(self.obj)
+ return availabilityKinds[res]
+
+ def __repr__(self):
+ return " | ".join([str(a) for a in self]) \
+ + " || Priority: " + str(self.priority) \
+ + " || Availability: " + str(self.availability)
+
+availabilityKinds = {
+ 0: CompletionChunk.Kind("Available"),
+ 1: CompletionChunk.Kind("Deprecated"),
+ 2: CompletionChunk.Kind("NotAvailable")}
+
+class CodeCompletionResult(Structure):
+ _fields_ = [('cursorKind', c_int), ('completionString', c_object_p)]
+
+ def __repr__(self):
+ return str(CompletionString(self.completionString))
+
+ @property
+ def string(self):
+ return CompletionString(self.completionString)
+
+class CCRStructure(Structure):
+ _fields_ = [('results', POINTER(CodeCompletionResult)),
+ ('numResults', c_int)]
+
+ def __len__(self):
+ return self.numResults
+
+ def __getitem__(self, key):
+ if len(self) <= key:
+ raise IndexError
+
+ return self.results[key]
+
+class CodeCompletionResults(ClangObject):
+ def __init__(self, ptr):
+ assert isinstance(ptr, POINTER(CCRStructure)) and ptr
+ self.ptr = self._as_parameter_ = ptr
+
+ def from_param(self):
+ return self._as_parameter_
+
+ def __del__(self):
+ CodeCompletionResults_dispose(self)
+
+ @property
+ def results(self):
+ return self.ptr.contents
+
+ @property
+ def diagnostics(self):
+ class DiagnosticsItr:
+ def __init__(self, ccr):
+ self.ccr= ccr
+
+ def __len__(self):
+ return int(_clang_codeCompleteGetNumDiagnostics(self.ccr))
+
+ def __getitem__(self, key):
+ return _clang_codeCompleteGetDiagnostic(self.ccr, key)
+
+ return DiagnosticsItr(self)
+
+class TranslationUnit(ClangObject):
+ """
+ The TranslationUnit class represents a source code translation unit and
+ provides read-only access to its top-level declarations.
+ """
+
+ # enum CXTranslationUnit_Flags
+ Nothing = 0x0
+ DetailedPreprocessingRecord = 0x01
+ Incomplete = 0x02
+ PrecompiledPreamble = 0x04
+ CacheCompletionResults = 0x08
+ CXXPrecompiledPreamble = 0x10
+ CXXChainedPCH = 0x20
+
+ def __init__(self, ptr):
+ ClangObject.__init__(self, ptr)
+
+ def __del__(self):
+ TranslationUnit_dispose(self)
+
+ @property
+ def cursor(self):
+ """Retrieve the cursor that represents the given translation unit."""
+ return TranslationUnit_cursor(self)
+
+ @property
+ def spelling(self):
+ """Get the original translation unit source file name."""
+ return TranslationUnit_spelling(self)
+
+ def get_includes(self):
+ """
+ Return an iterable sequence of FileInclusion objects that describe the
+ sequence of inclusions in a translation unit. The first object in
+ this sequence is always the input file. Note that this method will not
+ recursively iterate over header files included through precompiled
+ headers.
+ """
+ def visitor(fobj, lptr, depth, includes):
+ loc = lptr.contents
+ includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
+
+ # Automatically adapt CIndex/ctype pointers to python objects
+ includes = []
+ TranslationUnit_includes(self,
+ TranslationUnit_includes_callback(visitor),
+ includes)
+ return iter(includes)
+
+ @property
+ def diagnostics(self):
+ """
+ Return an iterable (and indexable) object containing the diagnostics.
+ """
+ class DiagIterator:
+ def __init__(self, tu):
+ self.tu = tu
+
+ def __len__(self):
+ return int(_clang_getNumDiagnostics(self.tu))
+
+ def __getitem__(self, key):
+ diag = _clang_getDiagnostic(self.tu, key)
+ if not diag:
+ raise IndexError
+ return Diagnostic(diag)
+
+ return DiagIterator(self)
+
+ def reparse(self, unsaved_files = [], options = Nothing):
+ """
+ Reparse an already parsed translation unit.
+
+ In-memory contents for files can be provided by passing a list of pairs
+ as unsaved_files, the first items should be the filenames to be mapped
+ and the second should be the contents to be substituted for the
+ file. The contents may be passed as strings or file objects.
+ """
+ unsaved_files_array = 0
+ if len(unsaved_files):
+ unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
+ for i,(name,value) in enumerate(unsaved_files):
+ if not isinstance(value, str):
+ # FIXME: It would be great to support an efficient version
+ # of this, one day.
+ value = value.read()
+ print value
+ if not isinstance(value, str):
+ raise TypeError,'Unexpected unsaved file contents.'
+ unsaved_files_array[i].name = name
+ unsaved_files_array[i].contents = value
+ unsaved_files_array[i].length = len(value)
+ ptr = TranslationUnit_reparse(self, len(unsaved_files),
+ unsaved_files_array,
+ options)
+ def codeComplete(self, path, line, column, unsaved_files = [], options = 0):
+ """
+ Code complete in this translation unit.
+
+ In-memory contents for files can be provided by passing a list of pairs
+ as unsaved_files, the first items should be the filenames to be mapped
+ and the second should be the contents to be substituted for the
+ file. The contents may be passed as strings or file objects.
+ """
+ unsaved_files_array = 0
+ if len(unsaved_files):
+ unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
+ for i,(name,value) in enumerate(unsaved_files):
+ if not isinstance(value, str):
+ # FIXME: It would be great to support an efficient version
+ # of this, one day.
+ value = value.read()
+ print value
+ if not isinstance(value, str):
+ raise TypeError,'Unexpected unsaved file contents.'
+ unsaved_files_array[i].name = name
+ unsaved_files_array[i].contents = value
+ unsaved_files_array[i].length = len(value)
+ ptr = TranslationUnit_codeComplete(self, path,
+ line, column,
+ unsaved_files_array,
+ len(unsaved_files),
+ options)
+ if ptr:
+ return CodeCompletionResults(ptr)
+
+ return None
+
+class Index(ClangObject):
+ """
+ The Index type provides the primary interface to the Clang CIndex library,
+ primarily by providing an interface for reading and parsing translation
+ units.
+ """
+
+ @staticmethod
+ def create(excludeDecls=False):
+ """
+ Create a new Index.
+ Parameters:
+ excludeDecls -- Exclude local declarations from translation units.
+ """
+ return Index(Index_create(excludeDecls, 0))
+
+ def __del__(self):
+ Index_dispose(self)
+
+ def read(self, path):
+ """Load the translation unit from the given AST file."""
+ ptr = TranslationUnit_read(self, path)
+ if ptr:
+ return TranslationUnit(ptr)
+ return None
+
+ def parse(self, path, args = [], unsaved_files = [], options = TranslationUnit.Nothing):
+ """
+ Load the translation unit from the given source code file by running
+ clang and generating the AST before loading. Additional command line
+ parameters can be passed to clang via the args parameter.
+
+ In-memory contents for files can be provided by passing a list of pairs
+ to as unsaved_files, the first item should be the filenames to be mapped
+ and the second should be the contents to be substituted for the
+ file. The contents may be passed as strings or file objects.
+ """
+ arg_array = 0
+ if len(args):
+ arg_array = (c_char_p * len(args))(* args)
+ unsaved_files_array = 0
+ if len(unsaved_files):
+ unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
+ for i,(name,value) in enumerate(unsaved_files):
+ if not isinstance(value, str):
+ # FIXME: It would be great to support an efficient version
+ # of this, one day.
+ value = value.read()
+ print value
+ if not isinstance(value, str):
+ raise TypeError,'Unexpected unsaved file contents.'
+ unsaved_files_array[i].name = name
+ unsaved_files_array[i].contents = value
+ unsaved_files_array[i].length = len(value)
+ ptr = TranslationUnit_parse(self, path, arg_array, len(args),
+ unsaved_files_array, len(unsaved_files),
+ options)
+ if ptr:
+ return TranslationUnit(ptr)
+ return None
+
+class File(ClangObject):
+ """
+ The File class represents a particular source file that is part of a
+ translation unit.
+ """
+
+ @property
+ def name(self):
+ """Return the complete file and path name of the file."""
+ return File_name(self)
+
+ @property
+ def time(self):
+ """Return the last modification time of the file."""
+ return File_time(self)
+
+class FileInclusion(object):
+ """
+ The FileInclusion class represents the inclusion of one source file by
+ another via a '#include' directive or as the input file for the translation
+ unit. This class provides information about the included file, the including
+ file, the location of the '#include' directive and the depth of the included
+ file in the stack. Note that the input file has depth 0.
+ """
+
+ def __init__(self, src, tgt, loc, depth):
+ self.source = src
+ self.include = tgt
+ self.location = loc
+ self.depth = depth
+
+ @property
+ def is_input_file(self):
+ """True if the included file is the input file."""
+ return self.depth == 0
+
+# Additional Functions and Types
+
+# String Functions
+_CXString_dispose = lib.clang_disposeString
+_CXString_dispose.argtypes = [_CXString]
+
+_CXString_getCString = lib.clang_getCString
+_CXString_getCString.argtypes = [_CXString]
+_CXString_getCString.restype = c_char_p
+
+# Source Location Functions
+SourceLocation_loc = lib.clang_getInstantiationLocation
+SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p),
+ POINTER(c_uint), POINTER(c_uint),
+ POINTER(c_uint)]
+
+# Source Range Functions
+SourceRange_getRange = lib.clang_getRange
+SourceRange_getRange.argtypes = [SourceLocation, SourceLocation]
+SourceRange_getRange.restype = SourceRange
+
+SourceRange_start = lib.clang_getRangeStart
+SourceRange_start.argtypes = [SourceRange]
+SourceRange_start.restype = SourceLocation
+
+SourceRange_end = lib.clang_getRangeEnd
+SourceRange_end.argtypes = [SourceRange]
+SourceRange_end.restype = SourceLocation
+
+# CursorKind Functions
+CursorKind_is_decl = lib.clang_isDeclaration
+CursorKind_is_decl.argtypes = [CursorKind]
+CursorKind_is_decl.restype = bool
+
+CursorKind_is_ref = lib.clang_isReference
+CursorKind_is_ref.argtypes = [CursorKind]
+CursorKind_is_ref.restype = bool
+
+CursorKind_is_expr = lib.clang_isExpression
+CursorKind_is_expr.argtypes = [CursorKind]
+CursorKind_is_expr.restype = bool
+
+CursorKind_is_stmt = lib.clang_isStatement
+CursorKind_is_stmt.argtypes = [CursorKind]
+CursorKind_is_stmt.restype = bool
+
+CursorKind_is_inv = lib.clang_isInvalid
+CursorKind_is_inv.argtypes = [CursorKind]
+CursorKind_is_inv.restype = bool
+
+# Cursor Functions
+# TODO: Implement this function
+Cursor_get = lib.clang_getCursor
+Cursor_get.argtypes = [TranslationUnit, SourceLocation]
+Cursor_get.restype = Cursor
+
+Cursor_null = lib.clang_getNullCursor
+Cursor_null.restype = Cursor
+
+Cursor_usr = lib.clang_getCursorUSR
+Cursor_usr.argtypes = [Cursor]
+Cursor_usr.restype = _CXString
+Cursor_usr.errcheck = _CXString.from_result
+
+Cursor_is_def = lib.clang_isCursorDefinition
+Cursor_is_def.argtypes = [Cursor]
+Cursor_is_def.restype = bool
+
+Cursor_def = lib.clang_getCursorDefinition
+Cursor_def.argtypes = [Cursor]
+Cursor_def.restype = Cursor
+Cursor_def.errcheck = Cursor.from_result
+
+Cursor_eq = lib.clang_equalCursors
+Cursor_eq.argtypes = [Cursor, Cursor]
+Cursor_eq.restype = c_uint
+
+Cursor_spelling = lib.clang_getCursorSpelling
+Cursor_spelling.argtypes = [Cursor]
+Cursor_spelling.restype = _CXString
+Cursor_spelling.errcheck = _CXString.from_result
+
+Cursor_loc = lib.clang_getCursorLocation
+Cursor_loc.argtypes = [Cursor]
+Cursor_loc.restype = SourceLocation
+
+Cursor_extent = lib.clang_getCursorExtent
+Cursor_extent.argtypes = [Cursor]
+Cursor_extent.restype = SourceRange
+
+Cursor_ref = lib.clang_getCursorReferenced
+Cursor_ref.argtypes = [Cursor]
+Cursor_ref.restype = Cursor
+Cursor_ref.errcheck = Cursor.from_result
+
+Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
+Cursor_visit = lib.clang_visitChildren
+Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
+Cursor_visit.restype = c_uint
+
+# Index Functions
+Index_create = lib.clang_createIndex
+Index_create.argtypes = [c_int, c_int]
+Index_create.restype = c_object_p
+
+Index_dispose = lib.clang_disposeIndex
+Index_dispose.argtypes = [Index]
+
+# Translation Unit Functions
+TranslationUnit_read = lib.clang_createTranslationUnit
+TranslationUnit_read.argtypes = [Index, c_char_p]
+TranslationUnit_read.restype = c_object_p
+
+TranslationUnit_parse = lib.clang_parseTranslationUnit
+TranslationUnit_parse.argtypes = [Index, c_char_p, c_void_p,
+ c_int, c_void_p, c_int, c_int]
+TranslationUnit_parse.restype = c_object_p
+
+TranslationUnit_reparse = lib.clang_reparseTranslationUnit
+TranslationUnit_reparse.argtypes = [TranslationUnit, c_int, c_void_p, c_int]
+TranslationUnit_reparse.restype = c_int
+
+TranslationUnit_codeComplete = lib.clang_codeCompleteAt
+TranslationUnit_codeComplete.argtypes = [TranslationUnit, c_char_p, c_int,
+ c_int, c_void_p, c_int, c_int]
+TranslationUnit_codeComplete.restype = POINTER(CCRStructure)
+
+TranslationUnit_cursor = lib.clang_getTranslationUnitCursor
+TranslationUnit_cursor.argtypes = [TranslationUnit]
+TranslationUnit_cursor.restype = Cursor
+TranslationUnit_cursor.errcheck = Cursor.from_result
+
+TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling
+TranslationUnit_spelling.argtypes = [TranslationUnit]
+TranslationUnit_spelling.restype = _CXString
+TranslationUnit_spelling.errcheck = _CXString.from_result
+
+TranslationUnit_dispose = lib.clang_disposeTranslationUnit
+TranslationUnit_dispose.argtypes = [TranslationUnit]
+
+TranslationUnit_includes_callback = CFUNCTYPE(None,
+ c_object_p,
+ POINTER(SourceLocation),
+ c_uint, py_object)
+TranslationUnit_includes = lib.clang_getInclusions
+TranslationUnit_includes.argtypes = [TranslationUnit,
+ TranslationUnit_includes_callback,
+ py_object]
+
+# File Functions
+File_name = lib.clang_getFileName
+File_name.argtypes = [File]
+File_name.restype = c_char_p
+
+File_time = lib.clang_getFileTime
+File_time.argtypes = [File]
+File_time.restype = c_uint
+
+# Code completion
+
+CodeCompletionResults_dispose = lib.clang_disposeCodeCompleteResults
+CodeCompletionResults_dispose.argtypes = [CodeCompletionResults]
+
+_clang_codeCompleteGetNumDiagnostics = lib.clang_codeCompleteGetNumDiagnostics
+_clang_codeCompleteGetNumDiagnostics.argtypes = [CodeCompletionResults]
+_clang_codeCompleteGetNumDiagnostics.restype = c_int
+
+_clang_codeCompleteGetDiagnostic = lib.clang_codeCompleteGetDiagnostic
+_clang_codeCompleteGetDiagnostic.argtypes = [CodeCompletionResults, c_int]
+_clang_codeCompleteGetDiagnostic.restype = Diagnostic
+
+_clang_getCompletionChunkText = lib.clang_getCompletionChunkText
+_clang_getCompletionChunkText.argtypes = [c_void_p, c_int]
+_clang_getCompletionChunkText.restype = _CXString
+
+_clang_getCompletionChunkKind = lib.clang_getCompletionChunkKind
+_clang_getCompletionChunkKind.argtypes = [c_void_p, c_int]
+_clang_getCompletionChunkKind.restype = c_int
+
+_clang_getCompletionChunkCompletionString = lib.clang_getCompletionChunkCompletionString
+_clang_getCompletionChunkCompletionString.argtypes = [c_void_p, c_int]
+_clang_getCompletionChunkCompletionString.restype = c_object_p
+
+_clang_getNumCompletionChunks = lib.clang_getNumCompletionChunks
+_clang_getNumCompletionChunks.argtypes = [c_void_p]
+_clang_getNumCompletionChunks.restype = c_int
+
+_clang_getCompletionAvailability = lib.clang_getCompletionAvailability
+_clang_getCompletionAvailability.argtypes = [c_void_p]
+_clang_getCompletionAvailability.restype = c_int
+
+_clang_getCompletionPriority = lib.clang_getCompletionPriority
+_clang_getCompletionPriority.argtypes = [c_void_p]
+_clang_getCompletionPriority.restype = c_int
+
+
+###
+
+__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind',
+ 'Diagnostic', 'FixIt', 'CodeCompletionResults', 'SourceRange',
+ 'SourceLocation', 'File']
View
BIN  autoload/neocomplcache/sources/clang_complete/clang/cindex.pyc
Binary file not shown
View
366 autoload/neocomplcache/sources/clang_complete/libclang.py
@@ -0,0 +1,366 @@
+# Copyright (c) 2010, 2011, Xavier Deguillard
+# All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Xavier Deguillard nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL XAVIER DEGUILLARD BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Original routine is from clang_complete.
+# https://github.com/Rip-Rip/clang_complete
+
+from clang.cindex import *
+import vim
+import time
+import re
+import threading
+
+def initClangComplete(clang_complete_flags):
+ global index
+ index = Index.create()
+ global translationUnits
+ translationUnits = dict()
+ global complete_flags
+ complete_flags = int(clang_complete_flags)
+
+# Get a tuple (fileName, fileContent) for the file opened in the current
+# vim buffer. The fileContent contains the unsafed buffer content.
+def getCurrentFile():
+ file = "\n".join(vim.eval("getline(1, '$')"))
+ return (vim.current.buffer.name, file)
+
+def getCurrentTranslationUnit(update = False):
+ userOptionsGlobal = splitOptions(vim.eval("g:neocomplcache_clang_complete_user_options"))
+ userOptionsLocal = splitOptions(vim.eval("b:clang_user_options"))
+ args = userOptionsGlobal + userOptionsLocal
+
+ currentFile = getCurrentFile()
+ fileName = vim.current.buffer.name
+
+ if fileName in translationUnits:
+ tu = translationUnits[fileName]
+ if update:
+ if debug:
+ start = time.time()
+ tu.reparse([currentFile])
+ if debug:
+ elapsed = (time.time() - start)
+ print "LibClang - Reparsing: " + str(elapsed)
+ return tu
+
+ if debug:
+ start = time.time()
+ flags = TranslationUnit.PrecompiledPreamble | TranslationUnit.CXXPrecompiledPreamble # | TranslationUnit.CacheCompletionResults
+ tu = index.parse(fileName, args, [currentFile], flags)
+ if debug:
+ elapsed = (time.time() - start)
+ print "LibClang - First parse: " + str(elapsed)
+
+ if tu == None:
+ print "Cannot parse this source file. The following arguments " \
+ + "are used for clang: " + " ".join(args)
+ return None
+
+ translationUnits[fileName] = tu
+
+ # Reparse to initialize the PCH cache even for auto completion
+ # This should be done by index.parse(), however it is not.
+ # So we need to reparse ourselves.
+ if debug:
+ start = time.time()
+ tu.reparse([currentFile])
+ if debug:
+ elapsed = (time.time() - start)
+ print "LibClang - First reparse (generate PCH cache): " + str(elapsed)
+ return tu
+
+def splitOptions(options):
+ optsList = []
+ opt = ""
+ quoted = False
+
+ for char in options:
+ if char == ' ' and not quoted:
+ if opt != "":
+ optsList += [opt]
+ opt = ""
+ continue
+ elif char == '"':
+ quoted = not quoted
+ opt += char
+
+ if opt != "":
+ optsList += [opt]
+ return optsList
+
+def getQuickFix(diagnostic):
+ # Some diagnostics have no file, e.g. "too many errors emitted, stopping now"
+ if diagnostic.location.file:
+ filename = diagnostic.location.file.name
+ else:
+ filename = ""
+
+ if diagnostic.severity == diagnostic.Warning:
+ type = 'W'
+ elif diagnostic.severity == diagnostic.Error:
+ type = 'E'
+ else:
+ return None
+
+ return dict({ 'bufnr' : int(vim.eval("bufnr('" + filename + "', 1)")),
+ 'lnum' : diagnostic.location.line,
+ 'col' : diagnostic.location.column,
+ 'text' : diagnostic.spelling,
+ 'type' : type})
+
+def getQuickFixList(tu):
+ return filter (None, map (getQuickFix, tu.diagnostics))
+
+def highlightRange(range, hlGroup):
+ pattern = '/\%' + str(range.start.line) + 'l' + '\%' \
+ + str(range.start.column) + 'c' + '.*' \
+ + '\%' + str(range.end.column) + 'c/'
+ command = "exe 'syntax match' . ' " + hlGroup + ' ' + pattern + "'"
+ vim.command(command)
+
+def highlightDiagnostic(diagnostic):
+ if diagnostic.severity == diagnostic.Warning:
+ hlGroup = 'SpellLocal'
+ elif diagnostic.severity == diagnostic.Error:
+ hlGroup = 'SpellBad'
+ else:
+ return
+
+ pattern = '/\%' + str(diagnostic.location.line) + 'l\%' \
+ + str(diagnostic.location.column) + 'c./'
+ command = "exe 'syntax match' . ' " + hlGroup + ' ' + pattern + "'"
+ vim.command(command)
+
+ # Use this wired kind of iterator as the python clang libraries
+ # have a bug in the range iterator that stops us to use:
+ #
+ # | for range in diagnostic.ranges
+ #
+ for i in range(len(diagnostic.ranges)):
+ highlightRange(diagnostic.ranges[i], hlGroup)
+
+def highlightDiagnostics(tu):
+ map (highlightDiagnostic, tu.diagnostics)
+
+def highlightCurrentDiagnostics():
+ if vim.current.buffer.name in translationUnits:
+ highlightDiagnostics(translationUnits[vim.current.buffer.name])
+
+def getCurrentQuickFixList():
+ if vim.current.buffer.name in translationUnits:
+ return getQuickFixList(translationUnits[vim.current.buffer.name])
+ return []
+
+def updateCurrentDiagnostics():
+ global debug
+ # debug = int(vim.eval("g:clang_debug")) == 1
+ debug = 0
+ getCurrentTranslationUnit(update = True)
+
+def getCurrentCompletionResults(line, column):
+ tu = getCurrentTranslationUnit()
+ currentFile = getCurrentFile()
+ if debug:
+ start = time.time()
+ cr = tu.codeComplete(vim.current.buffer.name, line, column, [currentFile],
+ complete_flags)
+ if debug:
+ elapsed = (time.time() - start)
+ print "LibClang - Code completion time: " + str(elapsed)
+ return cr
+
+def completeCurrentAt(line, column):
+ print "\n".join(map(str, getCurrentCompletionResults().results))
+
+def formatChunkForWord(chunk):
+ return chunk.spelling
+
+def formatResult(result):
+ completion = dict()
+
+ abbr = getAbbr(result.string)
+ info = filter(lambda x: not x.isKindInformative(), result.string)
+ word = filter(lambda x: not x.isKindResultType(), info)
+ returnValue = filter(lambda x: x.isKindResultType(), info)
+
+ if len(returnValue) > 0:
+ returnStr = returnValue[0].spelling + " "
+ else:
+ returnStr = ""
+
+ info = returnStr + "".join(map(lambda x: x.spelling, word))
+ word = abbr
+
+ completion['word'] = word
+ completion['abbr'] = abbr
+ completion['menu'] = info
+ completion['info'] = info
+ completion['dup'] = 1
+
+ # Replace the number that represents a specific kind with a better
+ # textual representation.
+ completion['kind'] = kinds[result.cursorKind]
+
+ return completion
+
+
+def getCurrentCompletions(base, column):
+ global debug
+ # debug = int(vim.eval("g:clang_debug")) == 1
+ debug = 0
+ # priority = vim.eval("g:clang_sort_algo") == 'priority'
+ priority = 'priority'
+ line = int(vim.eval("line('.')"))
+
+ cr = getCurrentCompletionResults(line, column)
+ if cr is None:
+ return []
+
+ regexp = re.compile("^" + base)
+ filteredResult = filter(lambda x: regexp.match(getAbbr(x.string)), cr.results)
+
+ getPriority = lambda x: x.string.priority
+ getAbbrevation = lambda x: getAbbr(x.string).lower()
+ if priority:
+ key = getPriority
+ else:
+ key = getAbbrevation
+ sortedResult = sorted(filteredResult, None, key)
+ return map(formatResult, sortedResult)
+
+def getAbbr(strings):
+ tmplst = filter(lambda x: x.isKindTypedText(), strings)
+ if len(tmplst) == 0:
+ return ""
+ else:
+ return tmplst[0].spelling
+
+kinds = dict({ \
+# Declarations \
+ 1 : 't', # CXCursor_UnexposedDecl (A declaration whose specific kind is not \
+ # exposed via this interface) \
+ 2 : 't', # CXCursor_StructDecl (A C or C++ struct) \
+ 3 : 't', # CXCursor_UnionDecl (A C or C++ union) \
+ 4 : 't', # CXCursor_ClassDecl (A C++ class) \
+ 5 : 't', # CXCursor_EnumDecl (An enumeration) \
+ 6 : 'm', # CXCursor_FieldDecl (A field (in C) or non-static data member \
+ # (in C++) in a struct, union, or C++ class) \
+ 7 : 'e', # CXCursor_EnumConstantDecl (An enumerator constant) \
+ 8 : 'f', # CXCursor_FunctionDecl (A function) \
+ 9 : 'v', # CXCursor_VarDecl (A variable) \
+10 : 'a', # CXCursor_ParmDecl (A function or method parameter) \
+11 : '11', # CXCursor_ObjCInterfaceDecl (An Objective-C @interface) \
+12 : '12', # CXCursor_ObjCCategoryDecl (An Objective-C @interface for a \
+ # category) \
+13 : '13', # CXCursor_ObjCProtocolDecl (An Objective-C @protocol declaration) \
+14 : '14', # CXCursor_ObjCPropertyDecl (An Objective-C @property declaration) \
+15 : '15', # CXCursor_ObjCIvarDecl (An Objective-C instance variable) \
+16 : '16', # CXCursor_ObjCInstanceMethodDecl (An Objective-C instance method) \
+17 : '17', # CXCursor_ObjCClassMethodDecl (An Objective-C class method) \
+18 : '18', # CXCursor_ObjCImplementationDec (An Objective-C @implementation) \
+19 : '19', # CXCursor_ObjCCategoryImplDecll (An Objective-C @implementation \
+ # for a category) \
+20 : 't', # CXCursor_TypedefDecl (A typedef) \
+21 : 'f', # CXCursor_CXXMethod (A C++ class method) \
+22 : 'n', # CXCursor_Namespace (A C++ namespace) \
+23 : '23', # CXCursor_LinkageSpec (A linkage specification, e.g. 'extern "C"') \
+24 : '+', # CXCursor_Constructor (A C++ constructor) \
+25 : '~', # CXCursor_Destructor (A C++ destructor) \
+26 : '26', # CXCursor_ConversionFunction (A C++ conversion function) \
+27 : 'a', # CXCursor_TemplateTypeParameter (A C++ template type parameter) \
+28 : 'a', # CXCursor_NonTypeTemplateParameter (A C++ non-type template \
+ # parameter) \
+29 : 'a', # CXCursor_TemplateTemplateParameter (A C++ template template \
+ # parameter) \
+30 : 'f', # CXCursor_FunctionTemplate (A C++ function template) \
+31 : 'p', # CXCursor_ClassTemplate (A C++ class template) \
+32 : '32', # CXCursor_ClassTemplatePartialSpecialization (A C++ class template \
+ # partial specialization) \
+33 : 'n', # CXCursor_NamespaceAlias (A C++ namespace alias declaration) \
+34 : '34', # CXCursor_UsingDirective (A C++ using directive) \
+35 : '35', # CXCursor_UsingDeclaration (A using declaration) \
+ \
+# References \
+40 : '40', # CXCursor_ObjCSuperClassRef \
+41 : '41', # CXCursor_ObjCProtocolRef \
+42 : '42', # CXCursor_ObjCClassRef \
+43 : '43', # CXCursor_TypeRef \
+44 : '44', # CXCursor_CXXBaseSpecifier \
+45 : '45', # CXCursor_TemplateRef (A reference to a class template, function \
+ # template, template template parameter, or class template partial \
+ # specialization) \
+46 : '46', # CXCursor_NamespaceRef (A reference to a namespace or namespace \
+ # alias) \
+47 : '47', # CXCursor_MemberRef (A reference to a member of a struct, union, \
+ # or class that occurs in some non-expression context, e.g., a \
+ # designated initializer) \
+48 : '48', # CXCursor_LabelRef (A reference to a labeled statement) \
+49 : '49', # CXCursor_OverloadedDeclRef (A reference to a set of overloaded \
+ # functions or function templates that has not yet been resolved to \
+ # a specific function or function template) \
+ \
+# Error conditions \
+#70 : '70', # CXCursor_FirstInvalid \
+70 : '70', # CXCursor_InvalidFile \
+71 : '71', # CXCursor_NoDeclFound \
+72 : 'u', # CXCursor_NotImplemented \
+73 : '73', # CXCursor_InvalidCode \
+ \
+# Expressions \
+100 : '100', # CXCursor_UnexposedExpr (An expression whose specific kind is \
+ # not exposed via this interface) \
+101 : '101', # CXCursor_DeclRefExpr (An expression that refers to some value \
+ # declaration, such as a function, varible, or enumerator) \
+102 : '102', # CXCursor_MemberRefExpr (An expression that refers to a member \
+ # of a struct, union, class, Objective-C class, etc) \
+103 : '103', # CXCursor_CallExpr (An expression that calls a function) \
+104 : '104', # CXCursor_ObjCMessageExpr (An expression that sends a message \
+ # to an Objective-C object or class) \
+105 : '105', # CXCursor_BlockExpr (An expression that represents a block \
+ # literal) \
+ \
+# Statements \
+200 : '200', # CXCursor_UnexposedStmt (A statement whose specific kind is not \
+ # exposed via this interface) \
+201 : '201', # CXCursor_LabelStmt (A labelled statement in a function) \
+ \
+# Translation unit \
+300 : '300', # CXCursor_TranslationUnit (Cursor that represents the \
+ # translation unit itself) \
+ \
+# Attributes \
+400 : '400', # CXCursor_UnexposedAttr (An attribute whose specific kind is \
+ # not exposed via this interface) \
+401 : '401', # CXCursor_IBActionAttr \
+402 : '402', # CXCursor_IBOutletAttr \
+403 : '403', # CXCursor_IBOutletCollectionAttr \
+ \
+# Preprocessing \
+500 : '500', # CXCursor_PreprocessingDirective \
+501 : 'd', # CXCursor_MacroDefinition \
+502 : '502', # CXCursor_MacroInstantiation \
+503 : '503' # CXCursor_InclusionDirective \
+})
+
+# vim: set ts=2 sts=2 sw=2 expandtab :
Please sign in to comment.
Something went wrong with that request. Please try again.