diff options
author | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
commit | 056abd2059c65a3e908193aeae16fad98017437c (patch) | |
tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /bindings/python/clang/cindex.py | |
parent | cc73504950eb7b5dff2dded9bedd67bc36d64641 (diff) | |
download | FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz |
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'bindings/python/clang/cindex.py')
-rw-r--r-- | bindings/python/clang/cindex.py | 1330 |
1 files changed, 820 insertions, 510 deletions
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index fc0a2a1..5e162c0 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -67,26 +67,12 @@ import collections import clang.enumerations -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() - if name == 'Darwin': - return cdll.LoadLibrary('libclang.dylib') - elif name == 'Windows': - return cdll.LoadLibrary('libclang.dll') - else: - return cdll.LoadLibrary('libclang.so') - # 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() callbacks = {} ### Exception Classes ### @@ -133,18 +119,43 @@ class TranslationUnitSaveError(Exception): ### Structures and Utility Classes ### +class CachedProperty(object): + """Decorator that lazy-loads the value of a property. + + The first time the property is accessed, the original property function is + executed. The value it returns is set as the new value of that instance's + property, replacing the original method. + """ + + def __init__(self, wrapped): + self.wrapped = wrapped + try: + self.__doc__ = wrapped.__doc__ + except: + pass + + def __get__(self, instance, instance_type=None): + if instance is None: + return self + + value = self.wrapped(instance) + setattr(instance, self.wrapped.__name__, value) + + return value + + class _CXString(Structure): """Helper for transforming CXString results.""" _fields_ = [("spelling", c_char_p), ("free", c_int)] def __del__(self): - lib.clang_disposeString(self) + conf.lib.clang_disposeString(self) @staticmethod def from_result(res, fn, args): assert isinstance(res, _CXString) - return lib.clang_getCString(res) + return conf.lib.clang_getCString(res) class SourceLocation(Structure): """ @@ -156,7 +167,7 @@ class SourceLocation(Structure): def _get_instantiation(self): if self._data is None: f, l, c, o = c_object_p(), c_uint(), c_uint(), c_uint() - lib.clang_getInstantiationLocation(self, byref(f), byref(l), + conf.lib.clang_getInstantiationLocation(self, byref(f), byref(l), byref(c), byref(o)) if f: f = File(f) @@ -171,7 +182,7 @@ class SourceLocation(Structure): Retrieve the source location associated with a given file/line/column in a particular translation unit. """ - return lib.clang_getLocation(tu, file, line, column) + return conf.lib.clang_getLocation(tu, file, line, column) @staticmethod def from_offset(tu, file, offset): @@ -181,7 +192,7 @@ class SourceLocation(Structure): file -- File instance to obtain offset from offset -- Integer character offset within file """ - return lib.clang_getLocationForOffset(tu, file, offset) + return conf.lib.clang_getLocationForOffset(tu, file, offset) @property def file(self): @@ -204,7 +215,7 @@ class SourceLocation(Structure): return self._get_instantiation()[3] def __eq__(self, other): - return lib.clang_equalLocations(self, other) + return conf.lib.clang_equalLocations(self, other) def __ne__(self, other): return not self.__eq__(other) @@ -231,7 +242,7 @@ class SourceRange(Structure): # object. @staticmethod def from_locations(start, end): - return lib.clang_getRange(start, end) + return conf.lib.clang_getRange(start, end) @property def start(self): @@ -239,7 +250,7 @@ class SourceRange(Structure): Return a SourceLocation representing the first character within a source range. """ - return lib.clang_getRangeStart(self) + return conf.lib.clang_getRangeStart(self) @property def end(self): @@ -247,10 +258,10 @@ class SourceRange(Structure): Return a SourceLocation representing the last character within a source range. """ - return lib.clang_getRangeEnd(self) + return conf.lib.clang_getRangeEnd(self) def __eq__(self, other): - return lib.clang_equalRanges(self, other) + return conf.lib.clang_equalRanges(self, other) def __ne__(self, other): return not self.__eq__(other) @@ -275,19 +286,19 @@ class Diagnostic(object): self.ptr = ptr def __del__(self): - lib.clang_disposeDiagnostic(self) + conf.lib.clang_disposeDiagnostic(self) @property def severity(self): - return lib.clang_getDiagnosticSeverity(self) + return conf.lib.clang_getDiagnosticSeverity(self) @property def location(self): - return lib.clang_getDiagnosticLocation(self) + return conf.lib.clang_getDiagnosticLocation(self) @property def spelling(self): - return lib.clang_getDiagnosticSpelling(self) + return conf.lib.clang_getDiagnosticSpelling(self) @property def ranges(self): @@ -296,12 +307,12 @@ class Diagnostic(object): self.diag = diag def __len__(self): - return int(lib.clang_getDiagnosticNumRanges(self.diag)) + return int(conf.lib.clang_getDiagnosticNumRanges(self.diag)) def __getitem__(self, key): if (key >= len(self)): raise IndexError - return lib.clang_getDiagnosticRange(self.diag, key) + return conf.lib.clang_getDiagnosticRange(self.diag, key) return RangeIterator(self) @@ -312,11 +323,11 @@ class Diagnostic(object): self.diag = diag def __len__(self): - return int(lib.clang_getDiagnosticNumFixIts(self.diag)) + return int(conf.lib.clang_getDiagnosticNumFixIts(self.diag)) def __getitem__(self, key): range = SourceRange() - value = lib.clang_getDiagnosticFixIt(self.diag, key, + value = conf.lib.clang_getDiagnosticFixIt(self.diag, key, byref(range)) if len(value) == 0: raise IndexError @@ -328,25 +339,25 @@ class Diagnostic(object): @property def category_number(self): """The category number for this diagnostic.""" - return lib.clang_getDiagnosticCategory(self) + return conf.lib.clang_getDiagnosticCategory(self) @property def category_name(self): """The string name of the category for this diagnostic.""" - return lib.clang_getDiagnosticCategoryName(self.category_number) + return conf.lib.clang_getDiagnosticCategoryName(self.category_number) @property def option(self): """The command-line option that enables this diagnostic.""" - return lib.clang_getDiagnosticOption(self, None) + return conf.lib.clang_getDiagnosticOption(self, None) @property def disable_option(self): """The command-line option that disables this diagnostic.""" disable = _CXString() - lib.clang_getDiagnosticOption(self, byref(disable)) + conf.lib.clang_getDiagnosticOption(self, byref(disable)) - return lib.clang_getCString(disable) + return conf.lib.clang_getCString(disable) def __repr__(self): return "<Diagnostic severity %r, location %r, spelling %r>" % ( @@ -389,7 +400,7 @@ class TokenGroup(object): self._count = count def __del__(self): - lib.clang_disposeTokens(self._tu, self._memory, self._count) + conf.lib.clang_disposeTokens(self._tu, self._memory, self._count) @staticmethod def get_tokens(tu, extent): @@ -401,7 +412,7 @@ class TokenGroup(object): tokens_memory = POINTER(Token)() tokens_count = c_uint() - lib.clang_tokenize(tu, extent, byref(tokens_memory), + conf.lib.clang_tokenize(tu, extent, byref(tokens_memory), byref(tokens_count)) count = int(tokens_count.value) @@ -507,39 +518,39 @@ class CursorKind(object): def is_declaration(self): """Test if this is a declaration kind.""" - return lib.clang_isDeclaration(self) + return conf.lib.clang_isDeclaration(self) def is_reference(self): """Test if this is a reference kind.""" - return lib.clang_isReference(self) + return conf.lib.clang_isReference(self) def is_expression(self): """Test if this is an expression kind.""" - return lib.clang_isExpression(self) + return conf.lib.clang_isExpression(self) def is_statement(self): """Test if this is a statement kind.""" - return lib.clang_isStatement(self) + return conf.lib.clang_isStatement(self) def is_attribute(self): """Test if this is an attribute kind.""" - return lib.clang_isAttribute(self) + return conf.lib.clang_isAttribute(self) def is_invalid(self): """Test if this is an invalid kind.""" - return lib.clang_isInvalid(self) + return conf.lib.clang_isInvalid(self) def is_translation_unit(self): """Test if this is a translation unit kind.""" - return lib.clang_isTranslationUnit(self) + return conf.lib.clang_isTranslationUnit(self) def is_preprocessing(self): """Test if this is a preprocessing kind.""" - return lib.clang_isPreprocessing(self) + return conf.lib.clang_isPreprocessing(self) def is_unexposed(self): """Test if this is an unexposed kind.""" - return lib.clang_isUnexposed(self) + return conf.lib.clang_isUnexposed(self) def __repr__(self): return 'CursorKind.%s' % (self.name,) @@ -643,7 +654,7 @@ CursorKind.TEMPLATE_TYPE_PARAMETER = CursorKind(27) CursorKind.TEMPLATE_NON_TYPE_PARAMETER = CursorKind(28) # A C++ template template parameter. -CursorKind.TEMPLATE_TEMPLATE_PARAMTER = CursorKind(29) +CursorKind.TEMPLATE_TEMPLATE_PARAMETER = CursorKind(29) # A C++ function template. CursorKind.FUNCTION_TEMPLATE = CursorKind(30) @@ -1038,13 +1049,13 @@ class Cursor(Structure): def from_location(tu, location): # We store a reference to the TU in the instance so the TU won't get # collected before the cursor. - cursor = lib.clang_getCursor(tu, location) + cursor = conf.lib.clang_getCursor(tu, location) cursor._tu = tu return cursor def __eq__(self, other): - return lib.clang_equalCursors(self, other) + return conf.lib.clang_equalCursors(self, other) def __ne__(self, other): return not self.__eq__(other) @@ -1054,13 +1065,13 @@ class Cursor(Structure): Returns true if the declaration pointed at by the cursor is also a definition of that entity. """ - return lib.clang_isCursorDefinition(self) + return conf.lib.clang_isCursorDefinition(self) def is_static_method(self): """Returns True if the cursor refers to a C++ member function or member function template that is declared 'static'. """ - return lib.clang_CXXMethod_isStatic(self) + return conf.lib.clang_CXXMethod_isStatic(self) def get_definition(self): """ @@ -1070,7 +1081,7 @@ class Cursor(Structure): """ # TODO: Should probably check that this is either a reference or # declaration prior to issuing the lookup. - return lib.clang_getCursorDefinition(self) + return conf.lib.clang_getCursorDefinition(self) def get_usr(self): """Return the Unified Symbol Resultion (USR) for the entity referenced @@ -1081,7 +1092,7 @@ class Cursor(Structure): 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 lib.clang_getCursorUSR(self) + return conf.lib.clang_getCursorUSR(self) @property def kind(self): @@ -1096,7 +1107,7 @@ class Cursor(Structure): # this, for consistency with clang_getCursorUSR. return None if not hasattr(self, '_spelling'): - self._spelling = lib.clang_getCursorSpelling(self) + self._spelling = conf.lib.clang_getCursorSpelling(self) return self._spelling @@ -1110,7 +1121,7 @@ class Cursor(Structure): class template specialization. """ if not hasattr(self, '_displayname'): - self._displayname = lib.clang_getCursorDisplayName(self) + self._displayname = conf.lib.clang_getCursorDisplayName(self) return self._displayname @@ -1121,7 +1132,7 @@ class Cursor(Structure): pointed at by the cursor. """ if not hasattr(self, '_loc'): - self._loc = lib.clang_getCursorLocation(self) + self._loc = conf.lib.clang_getCursorLocation(self) return self._loc @@ -1132,7 +1143,7 @@ class Cursor(Structure): pointed at by the cursor. """ if not hasattr(self, '_extent'): - self._extent = lib.clang_getCursorExtent(self) + self._extent = conf.lib.clang_getCursorExtent(self) return self._extent @@ -1142,7 +1153,7 @@ class Cursor(Structure): Retrieve the Type (if any) of the entity pointed at by the cursor. """ if not hasattr(self, '_type'): - self._type = lib.clang_getCursorType(self) + self._type = conf.lib.clang_getCursorType(self) return self._type @@ -1156,7 +1167,7 @@ class Cursor(Structure): declarations will be identical. """ if not hasattr(self, '_canonical'): - self._canonical = lib.clang_getCanonicalCursor(self) + self._canonical = conf.lib.clang_getCanonicalCursor(self) return self._canonical @@ -1164,7 +1175,7 @@ class Cursor(Structure): def result_type(self): """Retrieve the Type of the result for this Cursor.""" if not hasattr(self, '_result_type'): - self._result_type = lib.clang_getResultType(self.type) + self._result_type = conf.lib.clang_getResultType(self.type) return self._result_type @@ -1177,7 +1188,8 @@ class Cursor(Structure): """ if not hasattr(self, '_underlying_type'): assert self.kind.is_declaration() - self._underlying_type = lib.clang_getTypedefDeclUnderlyingType(self) + self._underlying_type = \ + conf.lib.clang_getTypedefDeclUnderlyingType(self) return self._underlying_type @@ -1190,7 +1202,7 @@ class Cursor(Structure): """ if not hasattr(self, '_enum_type'): assert self.kind == CursorKind.ENUM_DECL - self._enum_type = lib.clang_getEnumDeclIntegerType(self) + self._enum_type = conf.lib.clang_getEnumDeclIntegerType(self) return self._enum_type @@ -1213,16 +1225,18 @@ class Cursor(Structure): TypeKind.ULONG, TypeKind.ULONGLONG, TypeKind.UINT128): - self._enum_value = lib.clang_getEnumConstantDeclUnsignedValue(self) + self._enum_value = \ + conf.lib.clang_getEnumConstantDeclUnsignedValue(self) else: - self._enum_value = lib.clang_getEnumConstantDeclValue(self) + self._enum_value = conf.lib.clang_getEnumConstantDeclValue(self) return self._enum_value @property def objc_type_encoding(self): """Return the Objective-C type encoding as a str.""" if not hasattr(self, '_objc_type_encoding'): - self._objc_type_encoding = lib.clang_getDeclObjCTypeEncoding(self) + self._objc_type_encoding = \ + conf.lib.clang_getDeclObjCTypeEncoding(self) return self._objc_type_encoding @@ -1230,7 +1244,7 @@ class Cursor(Structure): def hash(self): """Returns a hash of the cursor as an int.""" if not hasattr(self, '_hash'): - self._hash = lib.clang_hashCursor(self) + self._hash = conf.lib.clang_hashCursor(self) return self._hash @@ -1238,7 +1252,7 @@ class Cursor(Structure): def semantic_parent(self): """Return the semantic parent for this cursor.""" if not hasattr(self, '_semantic_parent'): - self._semantic_parent = lib.clang_getCursorSemanticParent(self) + self._semantic_parent = conf.lib.clang_getCursorSemanticParent(self) return self._semantic_parent @@ -1246,7 +1260,7 @@ class Cursor(Structure): def lexical_parent(self): """Return the lexical parent for this cursor.""" if not hasattr(self, '_lexical_parent'): - self._lexical_parent = lib.clang_getCursorLexicalParent(self) + self._lexical_parent = conf.lib.clang_getCursorLexicalParent(self) return self._lexical_parent @@ -1257,6 +1271,12 @@ class Cursor(Structure): # created. return self._tu + def get_arguments(self): + """Return an iterator for accessing the arguments of this cursor.""" + num_args = conf.lib.clang_Cursor_getNumArguments(self) + for i in range(0, num_args): + yield conf.lib.clang_Cursor_getArgument(self, i) + def get_children(self): """Return an iterator for accessing the children of this cursor.""" @@ -1264,14 +1284,14 @@ class Cursor(Structure): def visitor(child, parent, children): # FIXME: Document this assertion in API. # FIXME: There should just be an isNull method. - assert child != lib.clang_getNullCursor() + assert child != conf.lib.clang_getNullCursor() # Create reference to TU so it isn't GC'd before Cursor. child._tu = self._tu children.append(child) return 1 # continue children = [] - lib.clang_visitChildren(self, callbacks['cursor_visit'](visitor), + conf.lib.clang_visitChildren(self, callbacks['cursor_visit'](visitor), children) return iter(children) @@ -1287,7 +1307,7 @@ class Cursor(Structure): def from_result(res, fn, args): assert isinstance(res, Cursor) # FIXME: There should just be an isNull method. - if res == lib.clang_getNullCursor(): + if res == conf.lib.clang_getNullCursor(): return None # Store a reference to the TU in the Python object so it won't get GC'd @@ -1310,7 +1330,7 @@ class Cursor(Structure): @staticmethod def from_cursor_result(res, fn, args): assert isinstance(res, Cursor) - if res == lib.clang_getNullCursor(): + if res == conf.lib.clang_getNullCursor(): return None res._tu = args[0]._tu @@ -1352,7 +1372,7 @@ class TypeKind(object): @property def spelling(self): """Retrieve the spelling of this TypeKind.""" - return lib.clang_getTypeKindSpelling(self.value) + return conf.lib.clang_getTypeKindSpelling(self.value) @staticmethod def from_id(id): @@ -1432,7 +1452,7 @@ class Type(Structure): def __len__(self): if self.length is None: - self.length = lib.clang_getNumArgTypes(self.parent) + self.length = conf.lib.clang_getNumArgTypes(self.parent) return self.length @@ -1448,7 +1468,7 @@ class Type(Structure): raise IndexError("Index greater than container length: " "%d > %d" % ( key, len(self) )) - result = lib.clang_getArgType(self.parent, key) + result = conf.lib.clang_getArgType(self.parent, key) if result.kind == TypeKind.INVALID: raise IndexError("Argument could not be retrieved.") @@ -1464,7 +1484,7 @@ class Type(Structure): If accessed on a type that is not an array, complex, or vector type, an exception will be raised. """ - result = lib.clang_getElementType(self) + result = conf.lib.clang_getElementType(self) if result.kind == TypeKind.INVALID: raise Exception('Element type not available on this type.') @@ -1478,7 +1498,7 @@ class Type(Structure): If the Type is not an array or vector, this raises. """ - result = lib.clang_getNumElements(self) + result = conf.lib.clang_getNumElements(self) if result < 0: raise Exception('Type does not have elements.') @@ -1516,7 +1536,7 @@ class Type(Structure): example, if 'T' is a typedef for 'int', the canonical type for 'T' would be 'int'. """ - return lib.clang_getCanonicalType(self) + return conf.lib.clang_getCanonicalType(self) def is_const_qualified(self): """Determine whether a Type has the "const" qualifier set. @@ -1524,7 +1544,7 @@ class Type(Structure): This does not look through typedefs that may have added "const" at a different level. """ - return lib.clang_isConstQualifiedType(self) + return conf.lib.clang_isConstQualifiedType(self) def is_volatile_qualified(self): """Determine whether a Type has the "volatile" qualifier set. @@ -1532,7 +1552,7 @@ class Type(Structure): This does not look through typedefs that may have added "volatile" at a different level. """ - return lib.clang_isVolatileQualifiedType(self) + return conf.lib.clang_isVolatileQualifiedType(self) def is_restrict_qualified(self): """Determine whether a Type has the "restrict" qualifier set. @@ -1540,53 +1560,53 @@ class Type(Structure): This does not look through typedefs that may have added "restrict" at a different level. """ - return lib.clang_isRestrictQualifiedType(self) + return conf.lib.clang_isRestrictQualifiedType(self) def is_function_variadic(self): """Determine whether this function Type is a variadic function type.""" assert self.kind == TypeKind.FUNCTIONPROTO - return lib.clang_isFunctionTypeVariadic(self) + return conf.lib.clang_isFunctionTypeVariadic(self) def is_pod(self): """Determine whether this Type represents plain old data (POD).""" - return lib.clang_isPODType(self) + return conf.lib.clang_isPODType(self) def get_pointee(self): """ For pointer types, returns the type of the pointee. """ - return lib.clang_getPointeeType(self) + return conf.lib.clang_getPointeeType(self) def get_declaration(self): """ Return the cursor for the declaration of the given type. """ - return lib.clang_getTypeDeclaration(self) + return conf.lib.clang_getTypeDeclaration(self) def get_result(self): """ Retrieve the result type associated with a function type. """ - return lib.clang_getResultType(self) + return conf.lib.clang_getResultType(self) def get_array_element_type(self): """ Retrieve the type of the elements of the array type. """ - return lib.clang_getArrayElementType(self) + return conf.lib.clang_getArrayElementType(self) def get_array_size(self): """ Retrieve the size of the constant array. """ - return lib.clang_getArraySize(self) + return conf.lib.clang_getArraySize(self) def __eq__(self, other): if type(other) != type(self): return False - return lib.clang_equalTypes(self, other) + return conf.lib.clang_equalTypes(self, other) def __ne__(self, other): return not self.__eq__(other) @@ -1632,18 +1652,19 @@ class CompletionChunk: def __repr__(self): return "{'" + self.spelling + "', " + str(self.kind) + "}" - @property + @CachedProperty def spelling(self): - return lib.clang_getCompletionChunkText(self.cs, self.key).spelling + return conf.lib.clang_getCompletionChunkText(self.cs, self.key).spelling - @property + @CachedProperty def kind(self): - res = lib.clang_getCompletionChunkKind(self.cs, self.key) + res = conf.lib.clang_getCompletionChunkKind(self.cs, self.key) return completionChunkKindMap[res] - @property + @CachedProperty def string(self): - res = lib.clang_getCompletionChunkCompletionString(self.cs, self.key) + res = conf.lib.clang_getCompletionChunkCompletionString(self.cs, + self.key) if (res): return CompletionString(res) @@ -1700,31 +1721,43 @@ class CompletionString(ClangObject): return "<Availability: %s>" % self def __len__(self): - return lib.clang_getNumCompletionChunks(self.obj) + self.num_chunks + + @CachedProperty + def num_chunks(self): + return conf.lib.clang_getNumCompletionChunks(self.obj) def __getitem__(self, key): - if len(self) <= key: + if self.num_chunks <= key: raise IndexError return CompletionChunk(self.obj, key) @property def priority(self): - return lib.clang_getCompletionPriority(self.obj) + return conf.lib.clang_getCompletionPriority(self.obj) @property def availability(self): - res = lib.clang_getCompletionAvailability(self.obj) + res = conf.lib.clang_getCompletionAvailability(self.obj) return availabilityKinds[res] + @property + def briefComment(self): + if conf.function_exists("clang_getCompletionBriefComment"): + return conf.lib.clang_getCompletionBriefComment(self.obj) + return _CXString() + def __repr__(self): return " | ".join([str(a) for a in self]) \ + " || Priority: " + str(self.priority) \ - + " || Availability: " + str(self.availability) + + " || Availability: " + str(self.availability) \ + + " || Brief comment: " + str(self.briefComment.spelling) availabilityKinds = { 0: CompletionChunk.Kind("Available"), 1: CompletionChunk.Kind("Deprecated"), - 2: CompletionChunk.Kind("NotAvailable")} + 2: CompletionChunk.Kind("NotAvailable"), + 3: CompletionChunk.Kind("NotAccessible")} class CodeCompletionResult(Structure): _fields_ = [('cursorKind', c_int), ('completionString', c_object_p)] @@ -1762,7 +1795,7 @@ class CodeCompletionResults(ClangObject): return self._as_parameter_ def __del__(self): - CodeCompletionResults_dispose(self) + conf.lib.clang_disposeCodeCompleteResults(self) @property def results(self): @@ -1775,10 +1808,11 @@ class CodeCompletionResults(ClangObject): self.ccr= ccr def __len__(self): - return int(lib.clang_codeCompleteGetNumDiagnostics(self.ccr)) + return int(\ + conf.lib.clang_codeCompleteGetNumDiagnostics(self.ccr)) def __getitem__(self, key): - return lib.clang_codeCompleteGetDiagnostic(self.ccr, key) + return conf.lib.clang_codeCompleteGetDiagnostic(self.ccr, key) return DiagnosticsItr(self) @@ -1797,10 +1831,10 @@ class Index(ClangObject): Parameters: excludeDecls -- Exclude local declarations from translation units. """ - return Index(lib.clang_createIndex(excludeDecls, 0)) + return Index(conf.lib.clang_createIndex(excludeDecls, 0)) def __del__(self): - lib.clang_disposeIndex(self) + conf.lib.clang_disposeIndex(self) def read(self, path): """Load a TranslationUnit from the given AST file.""" @@ -1857,6 +1891,10 @@ class TranslationUnit(ClangObject): # searching for declarations/definitions. PARSE_SKIP_FUNCTION_BODIES = 64 + # Used to indicate that brief documentation comments should be included + # into the set of code completions returned from this translation unit. + PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION = 128 + @classmethod def from_source(cls, filename, args=None, unsaved_files=None, options=0, index=None): @@ -1923,7 +1961,7 @@ class TranslationUnit(ClangObject): unsaved_array[i].contents = contents unsaved_array[i].length = len(contents) - ptr = lib.clang_parseTranslationUnit(index, filename, args_array, + ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array, len(args), unsaved_array, len(unsaved_files), options) @@ -1948,7 +1986,7 @@ class TranslationUnit(ClangObject): if index is None: index = Index.create() - ptr = lib.clang_createTranslationUnit(index, filename) + ptr = conf.lib.clang_createTranslationUnit(index, filename) if ptr is None: raise TranslationUnitLoadError(filename) @@ -1965,17 +2003,17 @@ class TranslationUnit(ClangObject): ClangObject.__init__(self, ptr) def __del__(self): - lib.clang_disposeTranslationUnit(self) + conf.lib.clang_disposeTranslationUnit(self) @property def cursor(self): """Retrieve the cursor that represents the given translation unit.""" - return lib.clang_getTranslationUnitCursor(self) + return conf.lib.clang_getTranslationUnitCursor(self) @property def spelling(self): """Get the original translation unit source file name.""" - return lib.clang_getTranslationUnitSpelling(self) + return conf.lib.clang_getTranslationUnitSpelling(self) def get_includes(self): """ @@ -1992,7 +2030,7 @@ class TranslationUnit(ClangObject): # Automatically adapt CIndex/ctype pointers to python objects includes = [] - lib.clang_getInclusions(self, + conf.lib.clang_getInclusions(self, callbacks['translation_unit_includes'](visitor), includes) return iter(includes) @@ -2068,10 +2106,10 @@ class TranslationUnit(ClangObject): self.tu = tu def __len__(self): - return int(lib.clang_getNumDiagnostics(self.tu)) + return int(conf.lib.clang_getNumDiagnostics(self.tu)) def __getitem__(self, key): - diag = lib.clang_getDiagnostic(self.tu, key) + diag = conf.lib.clang_getDiagnostic(self.tu, key) if not diag: raise IndexError return Diagnostic(diag) @@ -2104,7 +2142,7 @@ class TranslationUnit(ClangObject): unsaved_files_array[i].name = name unsaved_files_array[i].contents = value unsaved_files_array[i].length = len(value) - ptr = lib.clang_reparseTranslationUnit(self, len(unsaved_files), + ptr = conf.lib.clang_reparseTranslationUnit(self, len(unsaved_files), unsaved_files_array, options) def save(self, filename): @@ -2122,13 +2160,16 @@ class TranslationUnit(ClangObject): filename -- The path to save the translation unit to. """ - options = lib.clang_defaultSaveOptions(self) - result = int(lib.clang_saveTranslationUnit(self, filename, options)) + options = conf.lib.clang_defaultSaveOptions(self) + result = int(conf.lib.clang_saveTranslationUnit(self, filename, + options)) if result != 0: raise TranslationUnitSaveError(result, 'Error saving TranslationUnit.') - def codeComplete(self, path, line, column, unsaved_files=None, options=0): + def codeComplete(self, path, line, column, unsaved_files=None, + include_macros=False, include_code_patterns=False, + include_brief_comments=False): """ Code complete in this translation unit. @@ -2137,6 +2178,17 @@ class TranslationUnit(ClangObject): and the second should be the contents to be substituted for the file. The contents may be passed as strings or file objects. """ + options = 0 + + if include_macros: + options += 1 + + if include_code_patterns: + options += 2 + + if include_brief_comments: + options += 4 + if unsaved_files is None: unsaved_files = [] @@ -2154,7 +2206,7 @@ class TranslationUnit(ClangObject): unsaved_files_array[i].name = name unsaved_files_array[i].contents = value unsaved_files_array[i].length = len(value) - ptr = lib.clang_codeCompleteAt(self, path, line, column, + ptr = conf.lib.clang_codeCompleteAt(self, path, line, column, unsaved_files_array, len(unsaved_files), options) if ptr: return CodeCompletionResults(ptr) @@ -2182,17 +2234,17 @@ class File(ClangObject): @staticmethod def from_name(translation_unit, file_name): """Retrieve a file handle within the given translation unit.""" - return File(lib.clang_getFile(translation_unit, file_name)) + return File(conf.lib.clang_getFile(translation_unit, file_name)) @property def name(self): """Return the complete file and path name of the file.""" - return lib.clang_getCString(lib.clang_getFileName(self)) + return conf.lib.clang_getCString(conf.lib.clang_getFileName(self)) @property def time(self): """Return the last modification time of the file.""" - return lib.clang_getFileTime(self) + return conf.lib.clang_getFileTime(self) def __str__(self): return self.name @@ -2264,7 +2316,7 @@ class CompileCommand(object): @property def directory(self): """Get the working directory for this CompileCommand""" - return lib.clang_CompileCommand_getDirectory(self.cmd) + return conf.lib.clang_CompileCommand_getDirectory(self.cmd) @property def arguments(self): @@ -2274,9 +2326,9 @@ class CompileCommand(object): Invariant : the first argument is the compiler executable """ - length = lib.clang_CompileCommand_getNumArgs(self.cmd) + length = conf.lib.clang_CompileCommand_getNumArgs(self.cmd) for i in xrange(length): - yield lib.clang_CompileCommand_getArg(self.cmd, i) + yield conf.lib.clang_CompileCommand_getArg(self.cmd, i) class CompileCommands(object): """ @@ -2287,13 +2339,13 @@ class CompileCommands(object): self.ccmds = ccmds def __del__(self): - lib.clang_CompileCommands_dispose(self.ccmds) + conf.lib.clang_CompileCommands_dispose(self.ccmds) def __len__(self): - return int(lib.clang_CompileCommands_getSize(self.ccmds)) + return int(conf.lib.clang_CompileCommands_getSize(self.ccmds)) def __getitem__(self, i): - cc = lib.clang_CompileCommands_getCommand(self.ccmds, i) + cc = conf.lib.clang_CompileCommands_getCommand(self.ccmds, i) if not cc: raise IndexError return CompileCommand(cc, self) @@ -2313,7 +2365,7 @@ class CompilationDatabase(ClangObject): """ def __del__(self): - lib.clang_CompilationDatabase_dispose(self) + conf.lib.clang_CompilationDatabase_dispose(self) @staticmethod def from_result(res, fn, args): @@ -2327,7 +2379,7 @@ class CompilationDatabase(ClangObject): """Builds a CompilationDatabase from the database found in buildDir""" errorCode = c_uint() try: - cdb = lib.clang_CompilationDatabase_fromDirectory(buildDir, + cdb = conf.lib.clang_CompilationDatabase_fromDirectory(buildDir, byref(errorCode)) except CompilationDatabaseError as e: raise CompilationDatabaseError(int(errorCode.value), @@ -2339,7 +2391,8 @@ class CompilationDatabase(ClangObject): Get an iterable object providing all the CompileCommands available to build filename. Returns None if filename is not found in the database. """ - return lib.clang_CompilationDatabase_getCompileCommands(self, filename) + return conf.lib.clang_CompilationDatabase_getCompileCommands(self, + filename) class Token(Structure): """Represents a single token from the preprocessor. @@ -2361,29 +2414,29 @@ class Token(Structure): This is the textual representation of the token in source. """ - return lib.clang_getTokenSpelling(self._tu, self) + return conf.lib.clang_getTokenSpelling(self._tu, self) @property def kind(self): """Obtain the TokenKind of the current token.""" - return TokenKind.from_value(lib.clang_getTokenKind(self)) + return TokenKind.from_value(conf.lib.clang_getTokenKind(self)) @property def location(self): """The SourceLocation this Token occurs at.""" - return lib.clang_getTokenLocation(self._tu, self) + return conf.lib.clang_getTokenLocation(self._tu, self) @property def extent(self): """The SourceRange this Token occupies.""" - return lib.clang_getTokenExtent(self._tu, self) + return conf.lib.clang_getTokenExtent(self._tu, self) @property def cursor(self): """The Cursor this Token corresponds to.""" cursor = Cursor() - lib.clang_annotateTokens(self._tu, byref(self), 1, byref(cursor)) + conf.lib.clang_annotateTokens(self._tu, byref(self), 1, byref(cursor)) return cursor @@ -2394,434 +2447,691 @@ callbacks['translation_unit_includes'] = CFUNCTYPE(None, c_object_p, POINTER(SourceLocation), c_uint, py_object) callbacks['cursor_visit'] = CFUNCTYPE(c_int, Cursor, Cursor, py_object) -def register_functions(lib): - """Register function prototypes with a libclang library instance. - - This must be called as part of library instantiation so Python knows how - to call out to the shared library. - """ - # Functions are registered in strictly alphabetical order. - lib.clang_annotateTokens.argtype = [TranslationUnit, POINTER(Token), - c_uint, POINTER(Cursor)] - - lib.clang_CompilationDatabase_dispose.argtypes = [c_object_p] - - lib.clang_CompilationDatabase_fromDirectory.argtypes = [c_char_p, - POINTER(c_uint)] - lib.clang_CompilationDatabase_fromDirectory.restype = c_object_p - lib.clang_CompilationDatabase_fromDirectory.errcheck = CompilationDatabase.from_result - - lib.clang_CompilationDatabase_getCompileCommands.argtypes = [c_object_p, c_char_p] - lib.clang_CompilationDatabase_getCompileCommands.restype = c_object_p - lib.clang_CompilationDatabase_getCompileCommands.errcheck = CompileCommands.from_result - - lib.clang_CompileCommands_dispose.argtypes = [c_object_p] - - lib.clang_CompileCommands_getCommand.argtypes = [c_object_p, c_uint] - lib.clang_CompileCommands_getCommand.restype = c_object_p - - lib.clang_CompileCommands_getSize.argtypes = [c_object_p] - lib.clang_CompileCommands_getSize.restype = c_uint - - lib.clang_CompileCommand_getArg.argtypes = [c_object_p, c_uint] - lib.clang_CompileCommand_getArg.restype = _CXString - lib.clang_CompileCommand_getArg.errcheck = _CXString.from_result - - lib.clang_CompileCommand_getDirectory.argtypes = [c_object_p] - lib.clang_CompileCommand_getDirectory.restype = _CXString - lib.clang_CompileCommand_getDirectory.errcheck = _CXString.from_result - - lib.clang_CompileCommand_getNumArgs.argtypes = [c_object_p] - lib.clang_CompileCommand_getNumArgs.restype = c_uint - - lib.clang_codeCompleteAt.argtypes = [TranslationUnit, c_char_p, c_int, - c_int, c_void_p, c_int, c_int] - lib.clang_codeCompleteAt.restype = POINTER(CCRStructure) - - lib.clang_codeCompleteGetDiagnostic.argtypes = [CodeCompletionResults, - c_int] - lib.clang_codeCompleteGetDiagnostic.restype = Diagnostic - - lib.clang_codeCompleteGetNumDiagnostics.argtypes = [CodeCompletionResults] - lib.clang_codeCompleteGetNumDiagnostics.restype = c_int - - lib.clang_createIndex.argtypes = [c_int, c_int] - lib.clang_createIndex.restype = c_object_p - - lib.clang_createTranslationUnit.argtypes = [Index, c_char_p] - lib.clang_createTranslationUnit.restype = c_object_p - - lib.clang_CXXMethod_isStatic.argtypes = [Cursor] - lib.clang_CXXMethod_isStatic.restype = bool - - lib.clang_CXXMethod_isVirtual.argtypes = [Cursor] - lib.clang_CXXMethod_isVirtual.restype = bool - - lib.clang_defaultSaveOptions.argtypes = [TranslationUnit] - lib.clang_defaultSaveOptions.restype = c_uint - - lib.clang_disposeCodeCompleteResults.argtypes = [CodeCompletionResults] - - #lib.clang_disposeCXTUResourceUsage.argtypes = [CXTUResourceUsage] - - lib.clang_disposeDiagnostic.argtypes = [Diagnostic] - - lib.clang_disposeIndex.argtypes = [Index] - - lib.clang_disposeString.argtypes = [_CXString] - - lib.clang_disposeTokens.argtype = [TranslationUnit, POINTER(Token), c_uint] - - lib.clang_disposeTranslationUnit.argtypes = [TranslationUnit] - - lib.clang_equalCursors.argtypes = [Cursor, Cursor] - lib.clang_equalCursors.restype = bool - - lib.clang_equalLocations.argtypes = [SourceLocation, SourceLocation] - lib.clang_equalLocations.restype = bool - - lib.clang_equalRanges.argtypes = [SourceRange, SourceRange] - lib.clang_equalRanges.restype = bool - - lib.clang_equalTypes.argtypes = [Type, Type] - lib.clang_equalTypes.restype = bool - - lib.clang_getArgType.argtypes = [Type, c_uint] - lib.clang_getArgType.restype = Type - lib.clang_getArgType.errcheck = Type.from_result - - lib.clang_getArrayElementType.argtypes = [Type] - lib.clang_getArrayElementType.restype = Type - lib.clang_getArrayElementType.errcheck = Type.from_result - - lib.clang_getArraySize.argtypes = [Type] - lib.clang_getArraySize.restype = c_longlong - - lib.clang_getCanonicalCursor.argtypes = [Cursor] - lib.clang_getCanonicalCursor.restype = Cursor - lib.clang_getCanonicalCursor.errcheck = Cursor.from_cursor_result +# Functions strictly alphabetical order. +functionList = [ + ("clang_annotateTokens", + [TranslationUnit, POINTER(Token), c_uint, POINTER(Cursor)]), - lib.clang_getCanonicalType.argtypes = [Type] - lib.clang_getCanonicalType.restype = Type - lib.clang_getCanonicalType.errcheck = Type.from_result + ("clang_CompilationDatabase_dispose", + [c_object_p]), - lib.clang_getCompletionAvailability.argtypes = [c_void_p] - lib.clang_getCompletionAvailability.restype = c_int + ("clang_CompilationDatabase_fromDirectory", + [c_char_p, POINTER(c_uint)], + c_object_p, + CompilationDatabase.from_result), - lib.clang_getCompletionChunkCompletionString.argtypes = [c_void_p, c_int] - lib.clang_getCompletionChunkCompletionString.restype = c_object_p + ("clang_CompilationDatabase_getCompileCommands", + [c_object_p, c_char_p], + c_object_p, + CompileCommands.from_result), - lib.clang_getCompletionChunkKind.argtypes = [c_void_p, c_int] - lib.clang_getCompletionChunkKind.restype = c_int + ("clang_CompileCommands_dispose", + [c_object_p]), - lib.clang_getCompletionChunkText.argtypes = [c_void_p, c_int] - lib.clang_getCompletionChunkText.restype = _CXString + ("clang_CompileCommands_getCommand", + [c_object_p, c_uint], + c_object_p), - lib.clang_getCompletionPriority.argtypes = [c_void_p] - lib.clang_getCompletionPriority.restype = c_int + ("clang_CompileCommands_getSize", + [c_object_p], + c_uint), - lib.clang_getCString.argtypes = [_CXString] - lib.clang_getCString.restype = c_char_p + ("clang_CompileCommand_getArg", + [c_object_p, c_uint], + _CXString, + _CXString.from_result), - lib.clang_getCursor.argtypes = [TranslationUnit, SourceLocation] - lib.clang_getCursor.restype = Cursor + ("clang_CompileCommand_getDirectory", + [c_object_p], + _CXString, + _CXString.from_result), - lib.clang_getCursorDefinition.argtypes = [Cursor] - lib.clang_getCursorDefinition.restype = Cursor - lib.clang_getCursorDefinition.errcheck = Cursor.from_result + ("clang_CompileCommand_getNumArgs", + [c_object_p], + c_uint), - lib.clang_getCursorDisplayName.argtypes = [Cursor] - lib.clang_getCursorDisplayName.restype = _CXString - lib.clang_getCursorDisplayName.errcheck = _CXString.from_result + ("clang_codeCompleteAt", + [TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int], + POINTER(CCRStructure)), - lib.clang_getCursorExtent.argtypes = [Cursor] - lib.clang_getCursorExtent.restype = SourceRange + ("clang_codeCompleteGetDiagnostic", + [CodeCompletionResults, c_int], + Diagnostic), - lib.clang_getCursorLexicalParent.argtypes = [Cursor] - lib.clang_getCursorLexicalParent.restype = Cursor - lib.clang_getCursorLexicalParent.errcheck = Cursor.from_cursor_result + ("clang_codeCompleteGetNumDiagnostics", + [CodeCompletionResults], + c_int), - lib.clang_getCursorLocation.argtypes = [Cursor] - lib.clang_getCursorLocation.restype = SourceLocation + ("clang_createIndex", + [c_int, c_int], + c_object_p), - lib.clang_getCursorReferenced.argtypes = [Cursor] - lib.clang_getCursorReferenced.restype = Cursor - lib.clang_getCursorReferenced.errcheck = Cursor.from_result + ("clang_createTranslationUnit", + [Index, c_char_p], + c_object_p), - lib.clang_getCursorReferenceNameRange.argtypes = [Cursor, c_uint, c_uint] - lib.clang_getCursorReferenceNameRange.restype = SourceRange + ("clang_CXXMethod_isStatic", + [Cursor], + bool), - lib.clang_getCursorSemanticParent.argtypes = [Cursor] - lib.clang_getCursorSemanticParent.restype = Cursor - lib.clang_getCursorSemanticParent.errcheck = Cursor.from_cursor_result + ("clang_CXXMethod_isVirtual", + [Cursor], + bool), - lib.clang_getCursorSpelling.argtypes = [Cursor] - lib.clang_getCursorSpelling.restype = _CXString - lib.clang_getCursorSpelling.errcheck = _CXString.from_result + ("clang_defaultSaveOptions", + [TranslationUnit], + c_uint), - lib.clang_getCursorType.argtypes = [Cursor] - lib.clang_getCursorType.restype = Type - lib.clang_getCursorType.errcheck = Type.from_result + ("clang_disposeCodeCompleteResults", + [CodeCompletionResults]), - lib.clang_getCursorUSR.argtypes = [Cursor] - lib.clang_getCursorUSR.restype = _CXString - lib.clang_getCursorUSR.errcheck = _CXString.from_result +# ("clang_disposeCXTUResourceUsage", +# [CXTUResourceUsage]), - #lib.clang_getCXTUResourceUsage.argtypes = [TranslationUnit] - #lib.clang_getCXTUResourceUsage.restype = CXTUResourceUsage + ("clang_disposeDiagnostic", + [Diagnostic]), - lib.clang_getCXXAccessSpecifier.argtypes = [Cursor] - lib.clang_getCXXAccessSpecifier.restype = c_uint + ("clang_disposeIndex", + [Index]), - lib.clang_getDeclObjCTypeEncoding.argtypes = [Cursor] - lib.clang_getDeclObjCTypeEncoding.restype = _CXString - lib.clang_getDeclObjCTypeEncoding.errcheck = _CXString.from_result + ("clang_disposeString", + [_CXString]), - lib.clang_getDiagnostic.argtypes = [c_object_p, c_uint] - lib.clang_getDiagnostic.restype = c_object_p + ("clang_disposeTokens", + [TranslationUnit, POINTER(Token), c_uint]), - lib.clang_getDiagnosticCategory.argtypes = [Diagnostic] - lib.clang_getDiagnosticCategory.restype = c_uint + ("clang_disposeTranslationUnit", + [TranslationUnit]), - lib.clang_getDiagnosticCategoryName.argtypes = [c_uint] - lib.clang_getDiagnosticCategoryName.restype = _CXString - lib.clang_getDiagnosticCategoryName.errcheck = _CXString.from_result + ("clang_equalCursors", + [Cursor, Cursor], + bool), - lib.clang_getDiagnosticFixIt.argtypes = [Diagnostic, c_uint, - POINTER(SourceRange)] - lib.clang_getDiagnosticFixIt.restype = _CXString - lib.clang_getDiagnosticFixIt.errcheck = _CXString.from_result + ("clang_equalLocations", + [SourceLocation, SourceLocation], + bool), + + ("clang_equalRanges", + [SourceRange, SourceRange], + bool), + + ("clang_equalTypes", + [Type, Type], + bool), + + ("clang_getArgType", + [Type, c_uint], + Type, + Type.from_result), + + ("clang_getArrayElementType", + [Type], + Type, + Type.from_result), + + ("clang_getArraySize", + [Type], + c_longlong), + + ("clang_getCanonicalCursor", + [Cursor], + Cursor, + Cursor.from_cursor_result), + + ("clang_getCanonicalType", + [Type], + Type, + Type.from_result), + + ("clang_getCompletionAvailability", + [c_void_p], + c_int), + + ("clang_getCompletionBriefComment", + [c_void_p], + _CXString), + + ("clang_getCompletionChunkCompletionString", + [c_void_p, c_int], + c_object_p), + + ("clang_getCompletionChunkKind", + [c_void_p, c_int], + c_int), + + ("clang_getCompletionChunkText", + [c_void_p, c_int], + _CXString), + + ("clang_getCompletionPriority", + [c_void_p], + c_int), + + ("clang_getCString", + [_CXString], + c_char_p), + + ("clang_getCursor", + [TranslationUnit, SourceLocation], + Cursor), + + ("clang_getCursorDefinition", + [Cursor], + Cursor, + Cursor.from_result), + + ("clang_getCursorDisplayName", + [Cursor], + _CXString, + _CXString.from_result), + + ("clang_getCursorExtent", + [Cursor], + SourceRange), + + ("clang_getCursorLexicalParent", + [Cursor], + Cursor, + Cursor.from_cursor_result), + + ("clang_getCursorLocation", + [Cursor], + SourceLocation), + + ("clang_getCursorReferenced", + [Cursor], + Cursor, + Cursor.from_result), + + ("clang_getCursorReferenceNameRange", + [Cursor, c_uint, c_uint], + SourceRange), + + ("clang_getCursorSemanticParent", + [Cursor], + Cursor, + Cursor.from_cursor_result), + + ("clang_getCursorSpelling", + [Cursor], + _CXString, + _CXString.from_result), + + ("clang_getCursorType", + [Cursor], + Type, + Type.from_result), + + ("clang_getCursorUSR", + [Cursor], + _CXString, + _CXString.from_result), + +# ("clang_getCXTUResourceUsage", +# [TranslationUnit], +# CXTUResourceUsage), + + ("clang_getCXXAccessSpecifier", + [Cursor], + c_uint), + + ("clang_getDeclObjCTypeEncoding", + [Cursor], + _CXString, + _CXString.from_result), + + ("clang_getDiagnostic", + [c_object_p, c_uint], + c_object_p), + + ("clang_getDiagnosticCategory", + [Diagnostic], + c_uint), + + ("clang_getDiagnosticCategoryName", + [c_uint], + _CXString, + _CXString.from_result), + + ("clang_getDiagnosticFixIt", + [Diagnostic, c_uint, POINTER(SourceRange)], + _CXString, + _CXString.from_result), + + ("clang_getDiagnosticLocation", + [Diagnostic], + SourceLocation), + + ("clang_getDiagnosticNumFixIts", + [Diagnostic], + c_uint), + + ("clang_getDiagnosticNumRanges", + [Diagnostic], + c_uint), + + ("clang_getDiagnosticOption", + [Diagnostic, POINTER(_CXString)], + _CXString, + _CXString.from_result), + + ("clang_getDiagnosticRange", + [Diagnostic, c_uint], + SourceRange), + + ("clang_getDiagnosticSeverity", + [Diagnostic], + c_int), + + ("clang_getDiagnosticSpelling", + [Diagnostic], + _CXString, + _CXString.from_result), + + ("clang_getElementType", + [Type], + Type, + Type.from_result), + + ("clang_getEnumConstantDeclUnsignedValue", + [Cursor], + c_ulonglong), + + ("clang_getEnumConstantDeclValue", + [Cursor], + c_longlong), + + ("clang_getEnumDeclIntegerType", + [Cursor], + Type, + Type.from_result), + + ("clang_getFile", + [TranslationUnit, c_char_p], + c_object_p), + + ("clang_getFileName", + [File], + _CXString), # TODO go through _CXString.from_result? + + ("clang_getFileTime", + [File], + c_uint), + + ("clang_getIBOutletCollectionType", + [Cursor], + Type, + Type.from_result), + + ("clang_getIncludedFile", + [Cursor], + File, + File.from_cursor_result), + + ("clang_getInclusions", + [TranslationUnit, callbacks['translation_unit_includes'], py_object]), + + ("clang_getInstantiationLocation", + [SourceLocation, POINTER(c_object_p), POINTER(c_uint), POINTER(c_uint), + POINTER(c_uint)]), + + ("clang_getLocation", + [TranslationUnit, File, c_uint, c_uint], + SourceLocation), + + ("clang_getLocationForOffset", + [TranslationUnit, File, c_uint], + SourceLocation), + + ("clang_getNullCursor", + None, + Cursor), + + ("clang_getNumArgTypes", + [Type], + c_uint), + + ("clang_getNumCompletionChunks", + [c_void_p], + c_int), + + ("clang_getNumDiagnostics", + [c_object_p], + c_uint), + + ("clang_getNumElements", + [Type], + c_longlong), + + ("clang_getNumOverloadedDecls", + [Cursor], + c_uint), + + ("clang_getOverloadedDecl", + [Cursor, c_uint], + Cursor, + Cursor.from_cursor_result), + + ("clang_getPointeeType", + [Type], + Type, + Type.from_result), + + ("clang_getRange", + [SourceLocation, SourceLocation], + SourceRange), + + ("clang_getRangeEnd", + [SourceRange], + SourceLocation), + + ("clang_getRangeStart", + [SourceRange], + SourceLocation), + + ("clang_getResultType", + [Type], + Type, + Type.from_result), + + ("clang_getSpecializedCursorTemplate", + [Cursor], + Cursor, + Cursor.from_cursor_result), + + ("clang_getTemplateCursorKind", + [Cursor], + c_uint), + + ("clang_getTokenExtent", + [TranslationUnit, Token], + SourceRange), + + ("clang_getTokenKind", + [Token], + c_uint), + + ("clang_getTokenLocation", + [TranslationUnit, Token], + SourceLocation), + + ("clang_getTokenSpelling", + [TranslationUnit, Token], + _CXString, + _CXString.from_result), + + ("clang_getTranslationUnitCursor", + [TranslationUnit], + Cursor, + Cursor.from_result), + + ("clang_getTranslationUnitSpelling", + [TranslationUnit], + _CXString, + _CXString.from_result), + + ("clang_getTUResourceUsageName", + [c_uint], + c_char_p), + + ("clang_getTypeDeclaration", + [Type], + Cursor, + Cursor.from_result), + + ("clang_getTypedefDeclUnderlyingType", + [Cursor], + Type, + Type.from_result), + + ("clang_getTypeKindSpelling", + [c_uint], + _CXString, + _CXString.from_result), + + ("clang_hashCursor", + [Cursor], + c_uint), + + ("clang_isAttribute", + [CursorKind], + bool), + + ("clang_isConstQualifiedType", + [Type], + bool), + + ("clang_isCursorDefinition", + [Cursor], + bool), + + ("clang_isDeclaration", + [CursorKind], + bool), + + ("clang_isExpression", + [CursorKind], + bool), + + ("clang_isFileMultipleIncludeGuarded", + [TranslationUnit, File], + bool), + + ("clang_isFunctionTypeVariadic", + [Type], + bool), + + ("clang_isInvalid", + [CursorKind], + bool), + + ("clang_isPODType", + [Type], + bool), + + ("clang_isPreprocessing", + [CursorKind], + bool), + + ("clang_isReference", + [CursorKind], + bool), + + ("clang_isRestrictQualifiedType", + [Type], + bool), + + ("clang_isStatement", + [CursorKind], + bool), + + ("clang_isTranslationUnit", + [CursorKind], + bool), + + ("clang_isUnexposed", + [CursorKind], + bool), + + ("clang_isVirtualBase", + [Cursor], + bool), + + ("clang_isVolatileQualifiedType", + [Type], + bool), + + ("clang_parseTranslationUnit", + [Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int], + c_object_p), + + ("clang_reparseTranslationUnit", + [TranslationUnit, c_int, c_void_p, c_int], + c_int), + + ("clang_saveTranslationUnit", + [TranslationUnit, c_char_p, c_uint], + c_int), + + ("clang_tokenize", + [TranslationUnit, SourceRange, POINTER(POINTER(Token)), POINTER(c_uint)]), + + ("clang_visitChildren", + [Cursor, callbacks['cursor_visit'], py_object], + c_uint), + + ("clang_Cursor_getNumArguments", + [Cursor], + c_int), - lib.clang_getDiagnosticLocation.argtypes = [Diagnostic] - lib.clang_getDiagnosticLocation.restype = SourceLocation - - lib.clang_getDiagnosticNumFixIts.argtypes = [Diagnostic] - lib.clang_getDiagnosticNumFixIts.restype = c_uint - - lib.clang_getDiagnosticNumRanges.argtypes = [Diagnostic] - lib.clang_getDiagnosticNumRanges.restype = c_uint - - lib.clang_getDiagnosticOption.argtypes = [Diagnostic, POINTER(_CXString)] - lib.clang_getDiagnosticOption.restype = _CXString - lib.clang_getDiagnosticOption.errcheck = _CXString.from_result - - lib.clang_getDiagnosticRange.argtypes = [Diagnostic, c_uint] - lib.clang_getDiagnosticRange.restype = SourceRange - - lib.clang_getDiagnosticSeverity.argtypes = [Diagnostic] - lib.clang_getDiagnosticSeverity.restype = c_int - - lib.clang_getDiagnosticSpelling.argtypes = [Diagnostic] - lib.clang_getDiagnosticSpelling.restype = _CXString - lib.clang_getDiagnosticSpelling.errcheck = _CXString.from_result - - lib.clang_getElementType.argtypes = [Type] - lib.clang_getElementType.restype = Type - lib.clang_getElementType.errcheck = Type.from_result - - lib.clang_getEnumConstantDeclUnsignedValue.argtypes = [Cursor] - lib.clang_getEnumConstantDeclUnsignedValue.restype = c_ulonglong - - lib.clang_getEnumConstantDeclValue.argtypes = [Cursor] - lib.clang_getEnumConstantDeclValue.restype = c_longlong - - lib.clang_getEnumDeclIntegerType.argtypes = [Cursor] - lib.clang_getEnumDeclIntegerType.restype = Type - lib.clang_getEnumDeclIntegerType.errcheck = Type.from_result - - lib.clang_getFile.argtypes = [TranslationUnit, c_char_p] - lib.clang_getFile.restype = c_object_p - - lib.clang_getFileName.argtypes = [File] - lib.clang_getFileName.restype = _CXString - # TODO go through _CXString.from_result? - - lib.clang_getFileTime.argtypes = [File] - lib.clang_getFileTime.restype = c_uint - - lib.clang_getIBOutletCollectionType.argtypes = [Cursor] - lib.clang_getIBOutletCollectionType.restype = Type - lib.clang_getIBOutletCollectionType.errcheck = Type.from_result - - lib.clang_getIncludedFile.argtypes = [Cursor] - lib.clang_getIncludedFile.restype = File - lib.clang_getIncludedFile.errcheck = File.from_cursor_result - - lib.clang_getInclusions.argtypes = [TranslationUnit, - callbacks['translation_unit_includes'], py_object] - - lib.clang_getInstantiationLocation.argtypes = [SourceLocation, - POINTER(c_object_p), POINTER(c_uint), POINTER(c_uint), POINTER(c_uint)] - - lib.clang_getLocation.argtypes = [TranslationUnit, File, c_uint, c_uint] - lib.clang_getLocation.restype = SourceLocation - - lib.clang_getLocationForOffset.argtypes = [TranslationUnit, File, c_uint] - lib.clang_getLocationForOffset.restype = SourceLocation - - lib.clang_getNullCursor.restype = Cursor - - lib.clang_getNumArgTypes.argtypes = [Type] - lib.clang_getNumArgTypes.restype = c_uint - - lib.clang_getNumCompletionChunks.argtypes = [c_void_p] - lib.clang_getNumCompletionChunks.restype = c_int - - lib.clang_getNumDiagnostics.argtypes = [c_object_p] - lib.clang_getNumDiagnostics.restype = c_uint - - lib.clang_getNumElements.argtypes = [Type] - lib.clang_getNumElements.restype = c_longlong - - lib.clang_getNumOverloadedDecls.argtypes = [Cursor] - lib.clang_getNumOverloadedDecls.restyp = c_uint - - lib.clang_getOverloadedDecl.argtypes = [Cursor, c_uint] - lib.clang_getOverloadedDecl.restype = Cursor - lib.clang_getOverloadedDecl.errcheck = Cursor.from_cursor_result - - lib.clang_getPointeeType.argtypes = [Type] - lib.clang_getPointeeType.restype = Type - lib.clang_getPointeeType.errcheck = Type.from_result - - lib.clang_getRange.argtypes = [SourceLocation, SourceLocation] - lib.clang_getRange.restype = SourceRange - - lib.clang_getRangeEnd.argtypes = [SourceRange] - lib.clang_getRangeEnd.restype = SourceLocation - - lib.clang_getRangeStart.argtypes = [SourceRange] - lib.clang_getRangeStart.restype = SourceLocation - - lib.clang_getResultType.argtypes = [Type] - lib.clang_getResultType.restype = Type - lib.clang_getResultType.errcheck = Type.from_result - - lib.clang_getSpecializedCursorTemplate.argtypes = [Cursor] - lib.clang_getSpecializedCursorTemplate.restype = Cursor - lib.clang_getSpecializedCursorTemplate.errcheck = Cursor.from_cursor_result - - lib.clang_getTemplateCursorKind.argtypes = [Cursor] - lib.clang_getTemplateCursorKind.restype = c_uint - - lib.clang_getTokenExtent.argtypes = [TranslationUnit, Token] - lib.clang_getTokenExtent.restype = SourceRange - - lib.clang_getTokenKind.argtypes = [Token] - lib.clang_getTokenKind.restype = c_uint - - lib.clang_getTokenLocation.argtype = [TranslationUnit, Token] - lib.clang_getTokenLocation.restype = SourceLocation - - lib.clang_getTokenSpelling.argtype = [TranslationUnit, Token] - lib.clang_getTokenSpelling.restype = _CXString - lib.clang_getTokenSpelling.errcheck = _CXString.from_result - - lib.clang_getTranslationUnitCursor.argtypes = [TranslationUnit] - lib.clang_getTranslationUnitCursor.restype = Cursor - lib.clang_getTranslationUnitCursor.errcheck = Cursor.from_result - - lib.clang_getTranslationUnitSpelling.argtypes = [TranslationUnit] - lib.clang_getTranslationUnitSpelling.restype = _CXString - lib.clang_getTranslationUnitSpelling.errcheck = _CXString.from_result - - lib.clang_getTUResourceUsageName.argtypes = [c_uint] - lib.clang_getTUResourceUsageName.restype = c_char_p - - lib.clang_getTypeDeclaration.argtypes = [Type] - lib.clang_getTypeDeclaration.restype = Cursor - lib.clang_getTypeDeclaration.errcheck = Cursor.from_result - - lib.clang_getTypedefDeclUnderlyingType.argtypes = [Cursor] - lib.clang_getTypedefDeclUnderlyingType.restype = Type - lib.clang_getTypedefDeclUnderlyingType.errcheck = Type.from_result - - lib.clang_getTypeKindSpelling.argtypes = [c_uint] - lib.clang_getTypeKindSpelling.restype = _CXString - lib.clang_getTypeKindSpelling.errcheck = _CXString.from_result - - lib.clang_hashCursor.argtypes = [Cursor] - lib.clang_hashCursor.restype = c_uint - - lib.clang_isAttribute.argtypes = [CursorKind] - lib.clang_isAttribute.restype = bool - - lib.clang_isConstQualifiedType.argtypes = [Type] - lib.clang_isConstQualifiedType.restype = bool + ("clang_Cursor_getArgument", + [Cursor, c_uint], + Cursor, + Cursor.from_result), +] - lib.clang_isCursorDefinition.argtypes = [Cursor] - lib.clang_isCursorDefinition.restype = bool +class LibclangError(Exception): + def __init__(self, message): + self.m = message - lib.clang_isDeclaration.argtypes = [CursorKind] - lib.clang_isDeclaration.restype = bool + def __str__(self): + return self.m + +def register_function(lib, item, ignore_errors): + # A function may not exist, if these bindings are used with an older or + # incompatible version of libclang.so. + try: + func = getattr(lib, item[0]) + except AttributeError as e: + msg = str(e) + ". Please ensure that your python bindings are "\ + "compatible with your libclang.so version." + if ignore_errors: + return + raise LibclangError(msg) - lib.clang_isExpression.argtypes = [CursorKind] - lib.clang_isExpression.restype = bool + if len(item) >= 2: + func.argtypes = item[1] - lib.clang_isFileMultipleIncludeGuarded.argtypes = [TranslationUnit, File] - lib.clang_isFileMultipleIncludeGuarded.restype = bool + if len(item) >= 3: + func.restype = item[2] - lib.clang_isFunctionTypeVariadic.argtypes = [Type] - lib.clang_isFunctionTypeVariadic.restype = bool + if len(item) == 4: + func.errcheck = item[3] - lib.clang_isInvalid.argtypes = [CursorKind] - lib.clang_isInvalid.restype = bool +def register_functions(lib, ignore_errors): + """Register function prototypes with a libclang library instance. - lib.clang_isPODType.argtypes = [Type] - lib.clang_isPODType.restype = bool + This must be called as part of library instantiation so Python knows how + to call out to the shared library. + """ - lib.clang_isPreprocessing.argtypes = [CursorKind] - lib.clang_isPreprocessing.restype = bool + def register(item): + return register_function(lib, item, ignore_errors) - lib.clang_isReference.argtypes = [CursorKind] - lib.clang_isReference.restype = bool + map(register, functionList) - lib.clang_isRestrictQualifiedType.argtypes = [Type] - lib.clang_isRestrictQualifiedType.restype = bool +class Config: + library_path = None + library_file = None + compatibility_check = True + loaded = False - lib.clang_isStatement.argtypes = [CursorKind] - lib.clang_isStatement.restype = bool + @staticmethod + def set_library_path(path): + """Set the path in which to search for libclang""" + if Config.loaded: + raise Exception("library path must be set before before using " \ + "any other functionalities in libclang.") - lib.clang_isTranslationUnit.argtypes = [CursorKind] - lib.clang_isTranslationUnit.restype = bool + Config.library_path = path - lib.clang_isUnexposed.argtypes = [CursorKind] - lib.clang_isUnexposed.restype = bool + @staticmethod + def set_library_file(file): + """Set the exact location of libclang from""" + if Config.loaded: + raise Exception("library file must be set before before using " \ + "any other functionalities in libclang.") - lib.clang_isVirtualBase.argtypes = [Cursor] - lib.clang_isVirtualBase.restype = bool + Config.library_file = path - lib.clang_isVolatileQualifiedType.argtypes = [Type] - lib.clang_isVolatileQualifiedType.restype = bool + @staticmethod + def set_compatibility_check(check_status): + """ Perform compatibility check when loading libclang + + The python bindings are only tested and evaluated with the version of + libclang they are provided with. To ensure correct behavior a (limited) + compatibility check is performed when loading the bindings. This check + will throw an exception, as soon as it fails. + + In case these bindings are used with an older version of libclang, parts + that have been stable between releases may still work. Users of the + python bindings can disable the compatibility check. This will cause + the python bindings to load, even though they are written for a newer + version of libclang. Failures now arise if unsupported or incompatible + features are accessed. The user is required to test himself if the + features he is using are available and compatible between different + libclang versions. + """ + if Config.loaded: + raise Exception("compatibility_check must be set before before " \ + "using any other functionalities in libclang.") + + Config.compatibility_check = check_status + + @CachedProperty + def lib(self): + lib = self.get_cindex_library() + register_functions(lib, not Config.compatibility_check) + Config.loaded = True + return lib + + def get_filename(self): + if Config.library_file: + return Config.library_file + + import platform + name = platform.system() + + if name == 'Darwin': + file = 'libclang.dylib' + elif name == 'Windows': + file = 'libclang.dll' + else: + file = 'libclang.so' - lib.clang_parseTranslationUnit.argypes = [Index, c_char_p, c_void_p, c_int, - c_void_p, c_int, c_int] - lib.clang_parseTranslationUnit.restype = c_object_p + if Config.library_path: + file = Config.library_path + '/' + file - lib.clang_reparseTranslationUnit.argtypes = [TranslationUnit, c_int, - c_void_p, c_int] - lib.clang_reparseTranslationUnit.restype = c_int + return file - lib.clang_saveTranslationUnit.argtypes = [TranslationUnit, c_char_p, - c_uint] - lib.clang_saveTranslationUnit.restype = c_int + def get_cindex_library(self): + try: + library = cdll.LoadLibrary(self.get_filename()) + except OSError as e: + msg = str(e) + ". To provide a path to libclang use " \ + "Config.set_library_path() or " \ + "Config.set_library_file()." + raise LibclangError(msg) - lib.clang_tokenize.argtypes = [TranslationUnit, SourceRange, - POINTER(POINTER(Token)), POINTER(c_uint)] + return library - lib.clang_visitChildren.argtypes = [Cursor, callbacks['cursor_visit'], - py_object] - lib.clang_visitChildren.restype = c_uint + def function_exists(self, name): + try: + getattr(self.lib, name) + except AttributeError: + return False -register_functions(lib) + return True def register_enumerations(): for name, value in clang.enumerations.TokenKinds: TokenKind.register(value, name) +conf = Config() register_enumerations() __all__ = [ + 'Config', 'CodeCompletionResults', 'CompilationDatabase', 'CompileCommands', |