diff options
Diffstat (limited to 'bindings/python')
29 files changed, 0 insertions, 5235 deletions
diff --git a/bindings/python/README.txt b/bindings/python/README.txt deleted file mode 100644 index 742cf8fbb8fc..000000000000 --- a/bindings/python/README.txt +++ /dev/null @@ -1,17 +0,0 @@ -//===----------------------------------------------------------------------===// -// Clang Python Bindings -//===----------------------------------------------------------------------===// - -This directory implements Python bindings for Clang. - -You may need to alter LD_LIBRARY_PATH so that the Clang library can be -found. The unit tests are designed to be run with 'nosetests'. For example: --- -$ env PYTHONPATH=$(echo ~/llvm/tools/clang/bindings/python/) \ - LD_LIBRARY_PATH=$(llvm-config --libdir) \ - nosetests -v -tests.cindex.test_index.test_create ... ok -... - -OK --- diff --git a/bindings/python/clang/__init__.py b/bindings/python/clang/__init__.py deleted file mode 100644 index 88f30812383f..000000000000 --- a/bindings/python/clang/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -#===- __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'] - diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py deleted file mode 100644 index c103c7078003..000000000000 --- a/bindings/python/clang/cindex.py +++ /dev/null @@ -1,3414 +0,0 @@ -#===- 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. - -from ctypes import * -import collections - -import clang.enumerations - -# 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) - -callbacks = {} - -### Exception Classes ### - -class TranslationUnitLoadError(Exception): - """Represents an error that occurred when loading a TranslationUnit. - - This is raised in the case where a TranslationUnit could not be - instantiated due to failure in the libclang library. - - FIXME: Make libclang expose additional error information in this scenario. - """ - pass - -class TranslationUnitSaveError(Exception): - """Represents an error that occurred when saving a TranslationUnit. - - Each error has associated with it an enumerated value, accessible under - e.save_error. Consumers can compare the value with one of the ERROR_ - constants in this class. - """ - - # Indicates that an unknown error occurred. This typically indicates that - # I/O failed during save. - ERROR_UNKNOWN = 1 - - # Indicates that errors during translation prevented saving. The errors - # should be available via the TranslationUnit's diagnostics. - ERROR_TRANSLATION_ERRORS = 2 - - # Indicates that the translation unit was somehow invalid. - ERROR_INVALID_TU = 3 - - def __init__(self, enumeration, message): - assert isinstance(enumeration, int) - - if enumeration < 1 or enumeration > 3: - raise Exception("Encountered undefined TranslationUnit save error " - "constant: %d. Please file a bug to have this " - "value supported." % enumeration) - - self.save_error = enumeration - Exception.__init__(self, 'Error %d: %s' % (enumeration, message)) - -### 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): - conf.lib.clang_disposeString(self) - - @staticmethod - def from_result(res, fn, args): - assert isinstance(res, _CXString) - return conf.lib.clang_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() - conf.lib.clang_getInstantiationLocation(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(o.value)) - return self._data - - @staticmethod - def from_position(tu, file, line, column): - """ - Retrieve the source location associated with a given file/line/column in - a particular translation unit. - """ - return conf.lib.clang_getLocation(tu, file, line, column) - - @staticmethod - def from_offset(tu, file, offset): - """Retrieve a SourceLocation from a given character offset. - - tu -- TranslationUnit file belongs to - file -- File instance to obtain offset from - offset -- Integer character offset within file - """ - return conf.lib.clang_getLocationForOffset(tu, file, offset) - - @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 __eq__(self, other): - return conf.lib.clang_equalLocations(self, other) - - def __ne__(self, other): - return not self.__eq__(other) - - 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 conf.lib.clang_getRange(start, end) - - @property - def start(self): - """ - Return a SourceLocation representing the first character within a - source range. - """ - return conf.lib.clang_getRangeStart(self) - - @property - def end(self): - """ - Return a SourceLocation representing the last character within a - source range. - """ - return conf.lib.clang_getRangeEnd(self) - - def __eq__(self, other): - return conf.lib.clang_equalRanges(self, other) - - def __ne__(self, other): - return not self.__eq__(other) - - def __contains__(self, other): - """Useful to detect the Token/Lexer bug""" - if not isinstance(other, SourceLocation): - return False - if other.file is None and self.start.file is None: - pass - elif ( self.start.file.name != other.file.name or - other.file.name != self.end.file.name): - # same file name - return False - # same file, in between lines - if self.start.line < other.line < self.end.line: - return True - elif self.start.line == other.line: - # same file first line - if self.start.column <= other.column: - return True - elif other.line == self.end.line: - # same file last line - if other.column <= self.end.column: - return True - return False - - 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): - conf.lib.clang_disposeDiagnostic(self) - - @property - def severity(self): - return conf.lib.clang_getDiagnosticSeverity(self) - - @property - def location(self): - return conf.lib.clang_getDiagnosticLocation(self) - - @property - def spelling(self): - return conf.lib.clang_getDiagnosticSpelling(self) - - @property - def ranges(self): - class RangeIterator: - def __init__(self, diag): - self.diag = diag - - def __len__(self): - return int(conf.lib.clang_getDiagnosticNumRanges(self.diag)) - - def __getitem__(self, key): - if (key >= len(self)): - raise IndexError - return conf.lib.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(conf.lib.clang_getDiagnosticNumFixIts(self.diag)) - - def __getitem__(self, key): - range = SourceRange() - value = conf.lib.clang_getDiagnosticFixIt(self.diag, key, - byref(range)) - if len(value) == 0: - raise IndexError - - return FixIt(range, value) - - return FixItIterator(self) - - @property - def category_number(self): - """The category number for this diagnostic.""" - return conf.lib.clang_getDiagnosticCategory(self) - - @property - def category_name(self): - """The string name of the category for this diagnostic.""" - return conf.lib.clang_getDiagnosticCategoryName(self.category_number) - - @property - def option(self): - """The command-line option that enables this diagnostic.""" - return conf.lib.clang_getDiagnosticOption(self, None) - - @property - def disable_option(self): - """The command-line option that disables this diagnostic.""" - disable = _CXString() - conf.lib.clang_getDiagnosticOption(self, byref(disable)) - - return conf.lib.clang_getCString(disable) - - 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) - -class TokenGroup(object): - """Helper class to facilitate token management. - - Tokens are allocated from libclang in chunks. They must be disposed of as a - collective group. - - One purpose of this class is for instances to represent groups of allocated - tokens. Each token in a group contains a reference back to an instance of - this class. When all tokens from a group are garbage collected, it allows - this class to be garbage collected. When this class is garbage collected, - it calls the libclang destructor which invalidates all tokens in the group. - - You should not instantiate this class outside of this module. - """ - def __init__(self, tu, memory, count): - self._tu = tu - self._memory = memory - self._count = count - - def __del__(self): - conf.lib.clang_disposeTokens(self._tu, self._memory, self._count) - - @staticmethod - def get_tokens(tu, extent): - """Helper method to return all tokens in an extent. - - This functionality is needed multiple places in this module. We define - it here because it seems like a logical place. - """ - tokens_memory = POINTER(Token)() - tokens_count = c_uint() - - conf.lib.clang_tokenize(tu, extent, byref(tokens_memory), - byref(tokens_count)) - - count = int(tokens_count.value) - - # If we get no tokens, no memory was allocated. Be sure not to return - # anything and potentially call a destructor on nothing. - if count < 1: - return - - tokens_array = cast(tokens_memory, POINTER(Token * count)).contents - - token_group = TokenGroup(tu, tokens_memory, tokens_count) - - for i in xrange(0, count): - token = Token() - token.int_data = tokens_array[i].int_data - token.ptr_data = tokens_array[i].ptr_data - token._tu = tu - token._group = token_group - - yield token - -class TokenKind(object): - """Describes a specific type of a Token.""" - - _value_map = {} # int -> TokenKind - - def __init__(self, value, name): - """Create a new TokenKind instance from a numeric value and a name.""" - self.value = value - self.name = name - - def __repr__(self): - return 'TokenKind.%s' % (self.name,) - - @staticmethod - def from_value(value): - """Obtain a registered TokenKind instance from its value.""" - result = TokenKind._value_map.get(value, None) - - if result is None: - raise ValueError('Unknown TokenKind: %d' % value) - - return result - - @staticmethod - def register(value, name): - """Register a new TokenKind enumeration. - - This should only be called at module load time by code within this - package. - """ - if value in TokenKind._value_map: - raise ValueError('TokenKind already registered: %d' % value) - - kind = TokenKind(value, name) - TokenKind._value_map[value] = kind - setattr(TokenKind, name, kind) - -### 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 %d' % id - 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 conf.lib.clang_isDeclaration(self) - - def is_reference(self): - """Test if this is a reference kind.""" - return conf.lib.clang_isReference(self) - - def is_expression(self): - """Test if this is an expression kind.""" - return conf.lib.clang_isExpression(self) - - def is_statement(self): - """Test if this is a statement kind.""" - return conf.lib.clang_isStatement(self) - - def is_attribute(self): - """Test if this is an attribute kind.""" - return conf.lib.clang_isAttribute(self) - - def is_invalid(self): - """Test if this is an invalid kind.""" - return conf.lib.clang_isInvalid(self) - - def is_translation_unit(self): - """Test if this is a translation unit kind.""" - return conf.lib.clang_isTranslationUnit(self) - - def is_preprocessing(self): - """Test if this is a preprocessing kind.""" - return conf.lib.clang_isPreprocessing(self) - - def is_unexposed(self): - """Test if this is an unexposed kind.""" - return conf.lib.clang_isUnexposed(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) - -# A C++ class method. -CursorKind.CXX_METHOD = CursorKind(21) - -# A C++ namespace. -CursorKind.NAMESPACE = CursorKind(22) - -# A linkage specification, e.g. 'extern "C"'. -CursorKind.LINKAGE_SPEC = CursorKind(23) - -# A C++ constructor. -CursorKind.CONSTRUCTOR = CursorKind(24) - -# A C++ destructor. -CursorKind.DESTRUCTOR = CursorKind(25) - -# A C++ conversion function. -CursorKind.CONVERSION_FUNCTION = CursorKind(26) - -# A C++ template type parameter -CursorKind.TEMPLATE_TYPE_PARAMETER = CursorKind(27) - -# A C++ non-type template paramater. -CursorKind.TEMPLATE_NON_TYPE_PARAMETER = CursorKind(28) - -# A C++ template template parameter. -CursorKind.TEMPLATE_TEMPLATE_PARAMETER = CursorKind(29) - -# A C++ function template. -CursorKind.FUNCTION_TEMPLATE = CursorKind(30) - -# A C++ class template. -CursorKind.CLASS_TEMPLATE = CursorKind(31) - -# A C++ class template partial specialization. -CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION = CursorKind(32) - -# A C++ namespace alias declaration. -CursorKind.NAMESPACE_ALIAS = CursorKind(33) - -# A C++ using directive -CursorKind.USING_DIRECTIVE = CursorKind(34) - -# A C++ using declaration -CursorKind.USING_DECLARATION = CursorKind(35) - -# A Type alias decl. -CursorKind.TYPE_ALIAS_DECL = CursorKind(36) - -# A Objective-C synthesize decl -CursorKind.OBJC_SYNTHESIZE_DECL = CursorKind(37) - -# A Objective-C dynamic decl -CursorKind.OBJC_DYNAMIC_DECL = CursorKind(38) - -# A C++ access specifier decl. -CursorKind.CXX_ACCESS_SPEC_DECL = CursorKind(39) - - -### -# 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) -CursorKind.CXX_BASE_SPECIFIER = CursorKind(44) - -# A reference to a class template, function template, template -# template parameter, or class template partial specialization. -CursorKind.TEMPLATE_REF = CursorKind(45) - -# A reference to a namespace or namepsace alias. -CursorKind.NAMESPACE_REF = CursorKind(46) - -# A reference to a member of a struct, union, or class that occurs in -# some non-expression context, e.g., a designated initializer. -CursorKind.MEMBER_REF = CursorKind(47) - -# A reference to a labeled statement. -CursorKind.LABEL_REF = CursorKind(48) - -# A reference to a set of overloaded functions or function templates -# that has not yet been resolved to a specific function or function template. -CursorKind.OVERLOADED_DECL_REF = CursorKind(49) - -# A reference to a variable that occurs in some non-expression -# context, e.g., a C++ lambda capture list. -CursorKind.VARIABLE_REF = CursorKind(50) - -### -# Invalid/Error Kinds - -CursorKind.INVALID_FILE = CursorKind(70) -CursorKind.NO_DECL_FOUND = CursorKind(71) -CursorKind.NOT_IMPLEMENTED = CursorKind(72) -CursorKind.INVALID_CODE = CursorKind(73) - -### -# 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) - -# An expression that represents a block literal. -CursorKind.BLOCK_EXPR = CursorKind(105) - -# An integer literal. -CursorKind.INTEGER_LITERAL = CursorKind(106) - -# A floating point number literal. -CursorKind.FLOATING_LITERAL = CursorKind(107) - -# An imaginary number literal. -CursorKind.IMAGINARY_LITERAL = CursorKind(108) - -# A string literal. -CursorKind.STRING_LITERAL = CursorKind(109) - -# A character literal. -CursorKind.CHARACTER_LITERAL = CursorKind(110) - -# A parenthesized expression, e.g. "(1)". -# -# This AST node is only formed if full location information is requested. -CursorKind.PAREN_EXPR = CursorKind(111) - -# This represents the unary-expression's (except sizeof and -# alignof). -CursorKind.UNARY_OPERATOR = CursorKind(112) - -# [C99 6.5.2.1] Array Subscripting. -CursorKind.ARRAY_SUBSCRIPT_EXPR = CursorKind(113) - -# A builtin binary operation expression such as "x + y" or -# "x <= y". -CursorKind.BINARY_OPERATOR = CursorKind(114) - -# Compound assignment such as "+=". -CursorKind.COMPOUND_ASSIGNMENT_OPERATOR = CursorKind(115) - -# The ?: ternary operator. -CursorKind.CONDITIONAL_OPERATOR = CursorKind(116) - -# An explicit cast in C (C99 6.5.4) or a C-style cast in C++ -# (C++ [expr.cast]), which uses the syntax (Type)expr. -# -# For example: (int)f. -CursorKind.CSTYLE_CAST_EXPR = CursorKind(117) - -# [C99 6.5.2.5] -CursorKind.COMPOUND_LITERAL_EXPR = CursorKind(118) - -# Describes an C or C++ initializer list. -CursorKind.INIT_LIST_EXPR = CursorKind(119) - -# The GNU address of label extension, representing &&label. -CursorKind.ADDR_LABEL_EXPR = CursorKind(120) - -# This is the GNU Statement Expression extension: ({int X=4; X;}) -CursorKind.StmtExpr = CursorKind(121) - -# Represents a C11 generic selection. -CursorKind.GENERIC_SELECTION_EXPR = CursorKind(122) - -# Implements the GNU __null extension, which is a name for a null -# pointer constant that has integral type (e.g., int or long) and is the same -# size and alignment as a pointer. -# -# The __null extension is typically only used by system headers, which define -# NULL as __null in C++ rather than using 0 (which is an integer that may not -# match the size of a pointer). -CursorKind.GNU_NULL_EXPR = CursorKind(123) - -# C++'s static_cast<> expression. -CursorKind.CXX_STATIC_CAST_EXPR = CursorKind(124) - -# C++'s dynamic_cast<> expression. -CursorKind.CXX_DYNAMIC_CAST_EXPR = CursorKind(125) - -# C++'s reinterpret_cast<> expression. -CursorKind.CXX_REINTERPRET_CAST_EXPR = CursorKind(126) - -# C++'s const_cast<> expression. -CursorKind.CXX_CONST_CAST_EXPR = CursorKind(127) - -# Represents an explicit C++ type conversion that uses "functional" -# notion (C++ [expr.type.conv]). -# -# Example: -# \code -# x = int(0.5); -# \endcode -CursorKind.CXX_FUNCTIONAL_CAST_EXPR = CursorKind(128) - -# A C++ typeid expression (C++ [expr.typeid]). -CursorKind.CXX_TYPEID_EXPR = CursorKind(129) - -# [C++ 2.13.5] C++ Boolean Literal. -CursorKind.CXX_BOOL_LITERAL_EXPR = CursorKind(130) - -# [C++0x 2.14.7] C++ Pointer Literal. -CursorKind.CXX_NULL_PTR_LITERAL_EXPR = CursorKind(131) - -# Represents the "this" expression in C++ -CursorKind.CXX_THIS_EXPR = CursorKind(132) - -# [C++ 15] C++ Throw Expression. -# -# This handles 'throw' and 'throw' assignment-expression. When -# assignment-expression isn't present, Op will be null. -CursorKind.CXX_THROW_EXPR = CursorKind(133) - -# A new expression for memory allocation and constructor calls, e.g: -# "new CXXNewExpr(foo)". -CursorKind.CXX_NEW_EXPR = CursorKind(134) - -# A delete expression for memory deallocation and destructor calls, -# e.g. "delete[] pArray". -CursorKind.CXX_DELETE_EXPR = CursorKind(135) - -# Represents a unary expression. -CursorKind.CXX_UNARY_EXPR = CursorKind(136) - -# ObjCStringLiteral, used for Objective-C string literals i.e. "foo". -CursorKind.OBJC_STRING_LITERAL = CursorKind(137) - -# ObjCEncodeExpr, used for in Objective-C. -CursorKind.OBJC_ENCODE_EXPR = CursorKind(138) - -# ObjCSelectorExpr used for in Objective-C. -CursorKind.OBJC_SELECTOR_EXPR = CursorKind(139) - -# Objective-C's protocol expression. -CursorKind.OBJC_PROTOCOL_EXPR = CursorKind(140) - -# An Objective-C "bridged" cast expression, which casts between -# Objective-C pointers and C pointers, transferring ownership in the process. -# -# \code -# NSString *str = (__bridge_transfer NSString *)CFCreateString(); -# \endcode -CursorKind.OBJC_BRIDGE_CAST_EXPR = CursorKind(141) - -# Represents a C++0x pack expansion that produces a sequence of -# expressions. -# -# A pack expansion expression contains a pattern (which itself is an -# expression) followed by an ellipsis. For example: -CursorKind.PACK_EXPANSION_EXPR = CursorKind(142) - -# Represents an expression that computes the length of a parameter -# pack. -CursorKind.SIZE_OF_PACK_EXPR = CursorKind(143) - -# Represents a C++ lambda expression that produces a local function -# object. -# -# \code -# void abssort(float *x, unsigned N) { -# std::sort(x, x + N, -# [](float a, float b) { -# return std::abs(a) < std::abs(b); -# }); -# } -# \endcode -CursorKind.LAMBDA_EXPR = CursorKind(144) - -# Objective-c Boolean Literal. -CursorKind.OBJ_BOOL_LITERAL_EXPR = CursorKind(145) - -# Represents the "self" expression in a ObjC method. -CursorKind.OBJ_SELF_EXPR = CursorKind(146) - - -# 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) - -# A labelled statement in a function. -CursorKind.LABEL_STMT = CursorKind(201) - -# A compound statement -CursorKind.COMPOUND_STMT = CursorKind(202) - -# A case statement. -CursorKind.CASE_STMT = CursorKind(203) - -# A default statement. -CursorKind.DEFAULT_STMT = CursorKind(204) - -# An if statement. -CursorKind.IF_STMT = CursorKind(205) - -# A switch statement. -CursorKind.SWITCH_STMT = CursorKind(206) - -# A while statement. -CursorKind.WHILE_STMT = CursorKind(207) - -# A do statement. -CursorKind.DO_STMT = CursorKind(208) - -# A for statement. -CursorKind.FOR_STMT = CursorKind(209) - -# A goto statement. -CursorKind.GOTO_STMT = CursorKind(210) - -# An indirect goto statement. -CursorKind.INDIRECT_GOTO_STMT = CursorKind(211) - -# A continue statement. -CursorKind.CONTINUE_STMT = CursorKind(212) - -# A break statement. -CursorKind.BREAK_STMT = CursorKind(213) - -# A return statement. -CursorKind.RETURN_STMT = CursorKind(214) - -# A GNU-style inline assembler statement. -CursorKind.ASM_STMT = CursorKind(215) - -# Objective-C's overall @try-@catch-@finally statement. -CursorKind.OBJC_AT_TRY_STMT = CursorKind(216) - -# Objective-C's @catch statement. -CursorKind.OBJC_AT_CATCH_STMT = CursorKind(217) - -# Objective-C's @finally statement. -CursorKind.OBJC_AT_FINALLY_STMT = CursorKind(218) - -# Objective-C's @throw statement. -CursorKind.OBJC_AT_THROW_STMT = CursorKind(219) - -# Objective-C's @synchronized statement. -CursorKind.OBJC_AT_SYNCHRONIZED_STMT = CursorKind(220) - -# Objective-C's autorealease pool statement. -CursorKind.OBJC_AUTORELEASE_POOL_STMT = CursorKind(221) - -# Objective-C's for collection statement. -CursorKind.OBJC_FOR_COLLECTION_STMT = CursorKind(222) - -# C++'s catch statement. -CursorKind.CXX_CATCH_STMT = CursorKind(223) - -# C++'s try statement. -CursorKind.CXX_TRY_STMT = CursorKind(224) - -# C++'s for (* : *) statement. -CursorKind.CXX_FOR_RANGE_STMT = CursorKind(225) - -# Windows Structured Exception Handling's try statement. -CursorKind.SEH_TRY_STMT = CursorKind(226) - -# Windows Structured Exception Handling's except statement. -CursorKind.SEH_EXCEPT_STMT = CursorKind(227) - -# Windows Structured Exception Handling's finally statement. -CursorKind.SEH_FINALLY_STMT = CursorKind(228) - -# A MS inline assembly statement extension. -CursorKind.MS_ASM_STMT = CursorKind(229) - -# The null statement. -CursorKind.NULL_STMT = CursorKind(230) - -# Adaptor class for mixing declarations with statements and expressions. -CursorKind.DECL_STMT = CursorKind(231) - -### -# 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) - -### -# Attributes - -# An attribute whoe specific kind is note exposed via this interface -CursorKind.UNEXPOSED_ATTR = CursorKind(400) - -CursorKind.IB_ACTION_ATTR = CursorKind(401) -CursorKind.IB_OUTLET_ATTR = CursorKind(402) -CursorKind.IB_OUTLET_COLLECTION_ATTR = CursorKind(403) - -CursorKind.CXX_FINAL_ATTR = CursorKind(404) -CursorKind.CXX_OVERRIDE_ATTR = CursorKind(405) -CursorKind.ANNOTATE_ATTR = CursorKind(406) -CursorKind.ASM_LABEL_ATTR = CursorKind(407) -CursorKind.PACKED_ATTR = CursorKind(408) - -### -# Preprocessing -CursorKind.PREPROCESSING_DIRECTIVE = CursorKind(500) -CursorKind.MACRO_DEFINITION = CursorKind(501) -CursorKind.MACRO_INSTANTIATION = CursorKind(502) -CursorKind.INCLUSION_DIRECTIVE = CursorKind(503) - -### -# Extra declaration - -# A module import declaration. -CursorKind.MODULE_IMPORT_DECL = CursorKind(600) - -### 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), ("xdata", c_int), ("data", c_void_p * 3)] - - @staticmethod - 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 = conf.lib.clang_getCursor(tu, location) - cursor._tu = tu - - return cursor - - def __eq__(self, other): - return conf.lib.clang_equalCursors(self, other) - - def __ne__(self, other): - return not self.__eq__(other) - - def is_definition(self): - """ - Returns true if the declaration pointed at by the cursor is also a - definition of that entity. - """ - 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 conf.lib.clang_CXXMethod_isStatic(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 conf.lib.clang_getCursorDefinition(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 conf.lib.clang_getCursorUSR(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 - if not hasattr(self, '_spelling'): - self._spelling = conf.lib.clang_getCursorSpelling(self) - - return self._spelling - - @property - def displayname(self): - """ - Return the display name for the entity referenced by this cursor. - - The display name contains extra information that helps identify the cursor, - such as the parameters of a function or template or the arguments of a - class template specialization. - """ - if not hasattr(self, '_displayname'): - self._displayname = conf.lib.clang_getCursorDisplayName(self) - - return self._displayname - - @property - def location(self): - """ - Return the source location (the starting character) of the entity - pointed at by the cursor. - """ - if not hasattr(self, '_loc'): - self._loc = conf.lib.clang_getCursorLocation(self) - - return self._loc - - @property - def extent(self): - """ - Return the source range (the range of text) occupied by the entity - pointed at by the cursor. - """ - if not hasattr(self, '_extent'): - self._extent = conf.lib.clang_getCursorExtent(self) - - return self._extent - - @property - def type(self): - """ - Retrieve the Type (if any) of the entity pointed at by the cursor. - """ - if not hasattr(self, '_type'): - self._type = conf.lib.clang_getCursorType(self) - - return self._type - - @property - def canonical(self): - """Return the canonical Cursor corresponding to this Cursor. - - The canonical cursor is the cursor which is representative for the - underlying entity. For example, if you have multiple forward - declarations for the same class, the canonical cursor for the forward - declarations will be identical. - """ - if not hasattr(self, '_canonical'): - self._canonical = conf.lib.clang_getCanonicalCursor(self) - - return self._canonical - - @property - def result_type(self): - """Retrieve the Type of the result for this Cursor.""" - if not hasattr(self, '_result_type'): - self._result_type = conf.lib.clang_getResultType(self.type) - - return self._result_type - - @property - def underlying_typedef_type(self): - """Return the underlying type of a typedef declaration. - - Returns a Type for the typedef this cursor is a declaration for. If - the current cursor is not a typedef, this raises. - """ - if not hasattr(self, '_underlying_type'): - assert self.kind.is_declaration() - self._underlying_type = \ - conf.lib.clang_getTypedefDeclUnderlyingType(self) - - return self._underlying_type - - @property - def enum_type(self): - """Return the integer type of an enum declaration. - - Returns a Type corresponding to an integer. If the cursor is not for an - enum, this raises. - """ - if not hasattr(self, '_enum_type'): - assert self.kind == CursorKind.ENUM_DECL - self._enum_type = conf.lib.clang_getEnumDeclIntegerType(self) - - return self._enum_type - - @property - def enum_value(self): - """Return the value of an enum constant.""" - if not hasattr(self, '_enum_value'): - assert self.kind == CursorKind.ENUM_CONSTANT_DECL - # Figure out the underlying type of the enum to know if it - # is a signed or unsigned quantity. - underlying_type = self.type - if underlying_type.kind == TypeKind.ENUM: - underlying_type = underlying_type.get_declaration().enum_type - if underlying_type.kind in (TypeKind.CHAR_U, - TypeKind.UCHAR, - TypeKind.CHAR16, - TypeKind.CHAR32, - TypeKind.USHORT, - TypeKind.UINT, - TypeKind.ULONG, - TypeKind.ULONGLONG, - TypeKind.UINT128): - self._enum_value = \ - conf.lib.clang_getEnumConstantDeclUnsignedValue(self) - else: - 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 = \ - conf.lib.clang_getDeclObjCTypeEncoding(self) - - return self._objc_type_encoding - - @property - def hash(self): - """Returns a hash of the cursor as an int.""" - if not hasattr(self, '_hash'): - self._hash = conf.lib.clang_hashCursor(self) - - return self._hash - - @property - def semantic_parent(self): - """Return the semantic parent for this cursor.""" - if not hasattr(self, '_semantic_parent'): - self._semantic_parent = conf.lib.clang_getCursorSemanticParent(self) - - return self._semantic_parent - - @property - def lexical_parent(self): - """Return the lexical parent for this cursor.""" - if not hasattr(self, '_lexical_parent'): - self._lexical_parent = conf.lib.clang_getCursorLexicalParent(self) - - return self._lexical_parent - - @property - def translation_unit(self): - """Returns the TranslationUnit to which this Cursor belongs.""" - # If this triggers an AttributeError, the instance was not properly - # created. - return self._tu - - @property - def referenced(self): - """ - For a cursor that is a reference, returns a cursor - representing the entity that it references. - """ - if not hasattr(self, '_referenced'): - self._referenced = conf.lib.clang_getCursorReferenced(self) - - return self._referenced - - @property - def brief_comment(self): - """Returns the brief comment text associated with that Cursor""" - return conf.lib.clang_Cursor_getBriefCommentText(self) - - @property - def raw_comment(self): - """Returns the raw comment text associated with that Cursor""" - return conf.lib.clang_Cursor_getRawCommentText(self) - - 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.""" - - # 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 != 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 = [] - conf.lib.clang_visitChildren(self, callbacks['cursor_visit'](visitor), - children) - return iter(children) - - def get_tokens(self): - """Obtain Token instances formulating that compose this Cursor. - - This is a generator for Token instances. It returns all tokens which - occupy the extent this cursor occupies. - """ - return TokenGroup.get_tokens(self._tu, self.extent) - - def is_bitfield(self): - """ - Check if the field is a bitfield. - """ - return conf.lib.clang_Cursor_isBitField(self) - - def get_bitfield_width(self): - """ - Retrieve the width of a bitfield. - """ - return conf.lib.clang_getFieldDeclBitWidth(self) - - @staticmethod - def from_result(res, fn, args): - assert isinstance(res, Cursor) - # FIXME: There should just be an isNull method. - 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 - # before the Cursor. - tu = None - for arg in args: - if isinstance(arg, TranslationUnit): - tu = arg - break - - if hasattr(arg, 'translation_unit'): - tu = arg.translation_unit - break - - assert tu is not None - - res._tu = tu - return res - - @staticmethod - def from_cursor_result(res, fn, args): - assert isinstance(res, Cursor) - if res == conf.lib.clang_getNullCursor(): - return None - - res._tu = args[0]._tu - return res - -### Type Kinds ### - -class TypeKind(object): - """ - Describes the kind of type. - """ - - # The unique kind objects, indexed by id. - _kinds = [] - _name_map = None - - def __init__(self, value): - if value >= len(TypeKind._kinds): - TypeKind._kinds += [None] * (value - len(TypeKind._kinds) + 1) - if TypeKind._kinds[value] is not None: - raise ValueError,'TypeKind already loaded' - self.value = value - TypeKind._kinds[value] = self - TypeKind._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 TypeKind.__dict__.items(): - if isinstance(value,TypeKind): - self._name_map[value] = key - return self._name_map[self] - - @property - def spelling(self): - """Retrieve the spelling of this TypeKind.""" - return conf.lib.clang_getTypeKindSpelling(self.value) - - @staticmethod - def from_id(id): - if id >= len(TypeKind._kinds) or TypeKind._kinds[id] is None: - raise ValueError,'Unknown type kind %d' % id - return TypeKind._kinds[id] - - def __repr__(self): - return 'TypeKind.%s' % (self.name,) - -TypeKind.INVALID = TypeKind(0) -TypeKind.UNEXPOSED = TypeKind(1) -TypeKind.VOID = TypeKind(2) -TypeKind.BOOL = TypeKind(3) -TypeKind.CHAR_U = TypeKind(4) -TypeKind.UCHAR = TypeKind(5) -TypeKind.CHAR16 = TypeKind(6) -TypeKind.CHAR32 = TypeKind(7) -TypeKind.USHORT = TypeKind(8) -TypeKind.UINT = TypeKind(9) -TypeKind.ULONG = TypeKind(10) -TypeKind.ULONGLONG = TypeKind(11) -TypeKind.UINT128 = TypeKind(12) -TypeKind.CHAR_S = TypeKind(13) -TypeKind.SCHAR = TypeKind(14) -TypeKind.WCHAR = TypeKind(15) -TypeKind.SHORT = TypeKind(16) -TypeKind.INT = TypeKind(17) -TypeKind.LONG = TypeKind(18) -TypeKind.LONGLONG = TypeKind(19) -TypeKind.INT128 = TypeKind(20) -TypeKind.FLOAT = TypeKind(21) -TypeKind.DOUBLE = TypeKind(22) -TypeKind.LONGDOUBLE = TypeKind(23) -TypeKind.NULLPTR = TypeKind(24) -TypeKind.OVERLOAD = TypeKind(25) -TypeKind.DEPENDENT = TypeKind(26) -TypeKind.OBJCID = TypeKind(27) -TypeKind.OBJCCLASS = TypeKind(28) -TypeKind.OBJCSEL = TypeKind(29) -TypeKind.COMPLEX = TypeKind(100) -TypeKind.POINTER = TypeKind(101) -TypeKind.BLOCKPOINTER = TypeKind(102) -TypeKind.LVALUEREFERENCE = TypeKind(103) -TypeKind.RVALUEREFERENCE = TypeKind(104) -TypeKind.RECORD = TypeKind(105) -TypeKind.ENUM = TypeKind(106) -TypeKind.TYPEDEF = TypeKind(107) -TypeKind.OBJCINTERFACE = TypeKind(108) -TypeKind.OBJCOBJECTPOINTER = TypeKind(109) -TypeKind.FUNCTIONNOPROTO = TypeKind(110) -TypeKind.FUNCTIONPROTO = TypeKind(111) -TypeKind.CONSTANTARRAY = TypeKind(112) -TypeKind.VECTOR = TypeKind(113) -TypeKind.INCOMPLETEARRAY = TypeKind(114) -TypeKind.VARIABLEARRAY = TypeKind(115) -TypeKind.DEPENDENTSIZEDARRAY = TypeKind(116) -TypeKind.MEMBERPOINTER = TypeKind(117) - -class RefQualifierKind(object): - """Describes a specific ref-qualifier of a type.""" - - # The unique kind objects, indexed by id. - _kinds = [] - _name_map = None - - def __init__(self, value): - if value >= len(RefQualifierKind._kinds): - num_kinds = value - len(RefQualifierKind._kinds) + 1 - RefQualifierKind._kinds += [None] * num_kinds - if RefQualifierKind._kinds[value] is not None: - raise ValueError, 'RefQualifierKind already loaded' - self.value = value - RefQualifierKind._kinds[value] = self - RefQualifierKind._name_map = None - - def from_param(self): - return self.value - - @property - def name(self): - """Get the enumeration name of this kind.""" - if self._name_map is None: - self._name_map = {} - for key, value in RefQualifierKind.__dict__.items(): - if isinstance(value, RefQualifierKind): - self._name_map[value] = key - return self._name_map[self] - - @staticmethod - def from_id(id): - if (id >= len(RefQualifierKind._kinds) or - RefQualifierKind._kinds[id] is None): - raise ValueError, 'Unknown type kind %d' % id - return RefQualifierKind._kinds[id] - - def __repr__(self): - return 'RefQualifierKind.%s' % (self.name,) - -RefQualifierKind.NONE = RefQualifierKind(0) -RefQualifierKind.LVALUE = RefQualifierKind(1) -RefQualifierKind.RVALUE = RefQualifierKind(2) - -class Type(Structure): - """ - The type of an element in the abstract syntax tree. - """ - _fields_ = [("_kind_id", c_int), ("data", c_void_p * 2)] - - @property - def kind(self): - """Return the kind of this type.""" - return TypeKind.from_id(self._kind_id) - - def argument_types(self): - """Retrieve a container for the non-variadic arguments for this type. - - The returned object is iterable and indexable. Each item in the - container is a Type instance. - """ - class ArgumentsIterator(collections.Sequence): - def __init__(self, parent): - self.parent = parent - self.length = None - - def __len__(self): - if self.length is None: - self.length = conf.lib.clang_getNumArgTypes(self.parent) - - return self.length - - def __getitem__(self, key): - # FIXME Support slice objects. - if not isinstance(key, int): - raise TypeError("Must supply a non-negative int.") - - if key < 0: - raise IndexError("Only non-negative indexes are accepted.") - - if key >= len(self): - raise IndexError("Index greater than container length: " - "%d > %d" % ( key, len(self) )) - - result = conf.lib.clang_getArgType(self.parent, key) - if result.kind == TypeKind.INVALID: - raise IndexError("Argument could not be retrieved.") - - return result - - assert self.kind == TypeKind.FUNCTIONPROTO - return ArgumentsIterator(self) - - @property - def element_type(self): - """Retrieve the Type of elements within this Type. - - If accessed on a type that is not an array, complex, or vector type, an - exception will be raised. - """ - result = conf.lib.clang_getElementType(self) - if result.kind == TypeKind.INVALID: - raise Exception('Element type not available on this type.') - - return result - - @property - def element_count(self): - """Retrieve the number of elements in this type. - - Returns an int. - - If the Type is not an array or vector, this raises. - """ - result = conf.lib.clang_getNumElements(self) - if result < 0: - raise Exception('Type does not have elements.') - - return result - - @property - def translation_unit(self): - """The TranslationUnit to which this Type is associated.""" - # If this triggers an AttributeError, the instance was not properly - # instantiated. - return self._tu - - @staticmethod - def from_result(res, fn, args): - assert isinstance(res, Type) - - tu = None - for arg in args: - if hasattr(arg, 'translation_unit'): - tu = arg.translation_unit - break - - assert tu is not None - res._tu = tu - - return res - - def get_canonical(self): - """ - Return the canonical type for a Type. - - Clang's type system explicitly models typedefs and all the - ways a specific type can be represented. The canonical type - is the underlying type with all the "sugar" removed. For - example, if 'T' is a typedef for 'int', the canonical type for - 'T' would be 'int'. - """ - return conf.lib.clang_getCanonicalType(self) - - def is_const_qualified(self): - """Determine whether a Type has the "const" qualifier set. - - This does not look through typedefs that may have added "const" - at a different level. - """ - return conf.lib.clang_isConstQualifiedType(self) - - def is_volatile_qualified(self): - """Determine whether a Type has the "volatile" qualifier set. - - This does not look through typedefs that may have added "volatile" - at a different level. - """ - return conf.lib.clang_isVolatileQualifiedType(self) - - def is_restrict_qualified(self): - """Determine whether a Type has the "restrict" qualifier set. - - This does not look through typedefs that may have added "restrict" at - a different level. - """ - 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 conf.lib.clang_isFunctionTypeVariadic(self) - - def is_pod(self): - """Determine whether this Type represents plain old data (POD).""" - return conf.lib.clang_isPODType(self) - - def get_pointee(self): - """ - For pointer types, returns the type of the pointee. - """ - return conf.lib.clang_getPointeeType(self) - - def get_declaration(self): - """ - Return the cursor for the declaration of the given type. - """ - return conf.lib.clang_getTypeDeclaration(self) - - def get_result(self): - """ - Retrieve the result type associated with a function type. - """ - return conf.lib.clang_getResultType(self) - - def get_array_element_type(self): - """ - Retrieve the type of the elements of the array type. - """ - return conf.lib.clang_getArrayElementType(self) - - def get_array_size(self): - """ - Retrieve the size of the constant array. - """ - return conf.lib.clang_getArraySize(self) - - def get_class_type(self): - """ - Retrieve the class type of the member pointer type. - """ - return conf.lib.clang_Type_getClassType(self) - - def get_align(self): - """ - Retrieve the alignment of the record. - """ - return conf.lib.clang_Type_getAlignOf(self) - - def get_size(self): - """ - Retrieve the size of the record. - """ - return conf.lib.clang_Type_getSizeOf(self) - - def get_offset(self, fieldname): - """ - Retrieve the offset of a field in the record. - """ - return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname)) - - def get_ref_qualifier(self): - """ - Retrieve the ref-qualifier of the type. - """ - return RefQualifierKind.from_id( - conf.lib.clang_Type_getCXXRefQualifier(self)) - - @property - def spelling(self): - """Retrieve the spelling of this Type.""" - return conf.lib.clang_getTypeSpelling(self) - - def __eq__(self, other): - if type(other) != type(self): - return False - - return conf.lib.clang_equalTypes(self, other) - - def __ne__(self, other): - return not self.__eq__(other) - -## 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)] - -# Functions calls through the python interface are rather slow. Fortunately, -# for most symboles, we do not need to perform a function call. Their spelling -# never changes and is consequently provided by this spelling cache. -SpellingCache = { - # 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 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 - self.__kindNumberCache = -1 - - def __repr__(self): - return "{'" + self.spelling + "', " + str(self.kind) + "}" - - @CachedProperty - def spelling(self): - if self.__kindNumber in SpellingCache: - return SpellingCache[self.__kindNumber] - return conf.lib.clang_getCompletionChunkText(self.cs, self.key).spelling - - # We do not use @CachedProperty here, as the manual implementation is - # apparently still significantly faster. Please profile carefully if you - # would like to add CachedProperty back. - @property - def __kindNumber(self): - if self.__kindNumberCache == -1: - self.__kindNumberCache = \ - conf.lib.clang_getCompletionChunkKind(self.cs, self.key) - return self.__kindNumberCache - - @CachedProperty - def kind(self): - return completionChunkKindMap[self.__kindNumber] - - @CachedProperty - def string(self): - res = conf.lib.clang_getCompletionChunkCompletionString(self.cs, - self.key) - - if (res): - return CompletionString(res) - else: - None - - def isKindOptional(self): - return self.__kindNumber == 0 - - def isKindTypedText(self): - return self.__kindNumber == 1 - - def isKindPlaceHolder(self): - return self.__kindNumber == 3 - - def isKindInformative(self): - return self.__kindNumber == 4 - - def isKindResultType(self): - return self.__kindNumber == 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): - self.num_chunks - - @CachedProperty - def num_chunks(self): - return conf.lib.clang_getNumCompletionChunks(self.obj) - - def __getitem__(self, key): - if self.num_chunks <= key: - raise IndexError - return CompletionChunk(self.obj, key) - - @property - def priority(self): - return conf.lib.clang_getCompletionPriority(self.obj) - - @property - def availability(self): - 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) \ - + " || Brief comment: " + str(self.briefComment.spelling) - -availabilityKinds = { - 0: CompletionChunk.Kind("Available"), - 1: CompletionChunk.Kind("Deprecated"), - 2: CompletionChunk.Kind("NotAvailable"), - 3: CompletionChunk.Kind("NotAccessible")} - -class CodeCompletionResult(Structure): - _fields_ = [('cursorKind', c_int), ('completionString', c_object_p)] - - def __repr__(self): - return str(CompletionString(self.completionString)) - - @property - def kind(self): - return CursorKind.from_id(self.cursorKind) - - @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): - conf.lib.clang_disposeCodeCompleteResults(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(\ - conf.lib.clang_codeCompleteGetNumDiagnostics(self.ccr)) - - def __getitem__(self, key): - return conf.lib.clang_codeCompleteGetDiagnostic(self.ccr, key) - - return DiagnosticsItr(self) - - -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(conf.lib.clang_createIndex(excludeDecls, 0)) - - def __del__(self): - conf.lib.clang_disposeIndex(self) - - def read(self, path): - """Load a TranslationUnit from the given AST file.""" - return TranslationUnit.from_ast_file(path, self) - - def parse(self, path, args=None, unsaved_files=None, options = 0): - """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. - - If an error was encountered during parsing, a TranslationUnitLoadError - will be raised. - """ - return TranslationUnit.from_source(path, args, unsaved_files, options, - self) - -class TranslationUnit(ClangObject): - """Represents a source code translation unit. - - This is one of the main types in the API. Any time you wish to interact - with Clang's representation of a source file, you typically start with a - translation unit. - """ - - # Default parsing mode. - PARSE_NONE = 0 - - # Instruct the parser to create a detailed processing record containing - # metadata not normally retained. - PARSE_DETAILED_PROCESSING_RECORD = 1 - - # Indicates that the translation unit is incomplete. This is typically used - # when parsing headers. - PARSE_INCOMPLETE = 2 - - # Instruct the parser to create a pre-compiled preamble for the translation - # unit. This caches the preamble (included files at top of source file). - # This is useful if the translation unit will be reparsed and you don't - # want to incur the overhead of reparsing the preamble. - PARSE_PRECOMPILED_PREAMBLE = 4 - - # Cache code completion information on parse. This adds time to parsing but - # speeds up code completion. - PARSE_CACHE_COMPLETION_RESULTS = 8 - - # Flags with values 16 and 32 are deprecated and intentionally omitted. - - # Do not parse function bodies. This is useful if you only care about - # 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): - """Create a TranslationUnit by parsing source. - - This is capable of processing source code both from files on the - filesystem as well as in-memory contents. - - Command-line arguments that would be passed to clang are specified as - a list via args. These can be used to specify include paths, warnings, - etc. e.g. ["-Wall", "-I/path/to/include"]. - - In-memory file content can be provided via unsaved_files. This is an - iterable of 2-tuples. The first element is the str filename. The - second element defines the content. Content can be provided as str - source code or as file objects (anything with a read() method). If - a file object is being used, content will be read until EOF and the - read cursor will not be reset to its original position. - - options is a bitwise or of TranslationUnit.PARSE_XXX flags which will - control parsing behavior. - - index is an Index instance to utilize. If not provided, a new Index - will be created for this TranslationUnit. - - To parse source from the filesystem, the filename of the file to parse - is specified by the filename argument. Or, filename could be None and - the args list would contain the filename(s) to parse. - - To parse source from an in-memory buffer, set filename to the virtual - filename you wish to associate with this source (e.g. "test.c"). The - contents of that file are then provided in unsaved_files. - - If an error occurs, a TranslationUnitLoadError is raised. - - Please note that a TranslationUnit with parser errors may be returned. - It is the caller's responsibility to check tu.diagnostics for errors. - - Also note that Clang infers the source language from the extension of - the input filename. If you pass in source code containing a C++ class - declaration with the filename "test.c" parsing will fail. - """ - if args is None: - args = [] - - if unsaved_files is None: - unsaved_files = [] - - if index is None: - index = Index.create() - - args_array = None - if len(args) > 0: - args_array = (c_char_p * len(args))(* args) - - unsaved_array = None - if len(unsaved_files) > 0: - unsaved_array = (_CXUnsavedFile * len(unsaved_files))() - for i, (name, contents) in enumerate(unsaved_files): - if hasattr(contents, "read"): - contents = contents.read() - - unsaved_array[i].name = name - unsaved_array[i].contents = contents - unsaved_array[i].length = len(contents) - - ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array, - len(args), unsaved_array, - len(unsaved_files), options) - - if not ptr: - raise TranslationUnitLoadError("Error parsing translation unit.") - - return cls(ptr, index=index) - - @classmethod - def from_ast_file(cls, filename, index=None): - """Create a TranslationUnit instance from a saved AST file. - - A previously-saved AST file (provided with -emit-ast or - TranslationUnit.save()) is loaded from the filename specified. - - If the file cannot be loaded, a TranslationUnitLoadError will be - raised. - - index is optional and is the Index instance to use. If not provided, - a default Index will be created. - """ - if index is None: - index = Index.create() - - ptr = conf.lib.clang_createTranslationUnit(index, filename) - if not ptr: - raise TranslationUnitLoadError(filename) - - return cls(ptr=ptr, index=index) - - def __init__(self, ptr, index): - """Create a TranslationUnit instance. - - TranslationUnits should be created using one of the from_* @classmethod - functions above. __init__ is only called internally. - """ - assert isinstance(index, Index) - - ClangObject.__init__(self, ptr) - - def __del__(self): - conf.lib.clang_disposeTranslationUnit(self) - - @property - def cursor(self): - """Retrieve the cursor that represents the given translation unit.""" - return conf.lib.clang_getTranslationUnitCursor(self) - - @property - def spelling(self): - """Get the original translation unit source file name.""" - return conf.lib.clang_getTranslationUnitSpelling(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): - if depth > 0: - loc = lptr.contents - includes.append(FileInclusion(loc.file, File(fobj), loc, depth)) - - # Automatically adapt CIndex/ctype pointers to python objects - includes = [] - conf.lib.clang_getInclusions(self, - callbacks['translation_unit_includes'](visitor), includes) - - return iter(includes) - - def get_file(self, filename): - """Obtain a File from this translation unit.""" - - return File.from_name(self, filename) - - def get_location(self, filename, position): - """Obtain a SourceLocation for a file in this translation unit. - - The position can be specified by passing: - - - Integer file offset. Initial file offset is 0. - - 2-tuple of (line number, column number). Initial file position is - (0, 0) - """ - f = self.get_file(filename) - - if isinstance(position, int): - return SourceLocation.from_offset(self, f, position) - - return SourceLocation.from_position(self, f, position[0], position[1]) - - def get_extent(self, filename, locations): - """Obtain a SourceRange from this translation unit. - - The bounds of the SourceRange must ultimately be defined by a start and - end SourceLocation. For the locations argument, you can pass: - - - 2 SourceLocation instances in a 2-tuple or list. - - 2 int file offsets via a 2-tuple or list. - - 2 2-tuple or lists of (line, column) pairs in a 2-tuple or list. - - e.g. - - get_extent('foo.c', (5, 10)) - get_extent('foo.c', ((1, 1), (1, 15))) - """ - f = self.get_file(filename) - - if len(locations) < 2: - raise Exception('Must pass object with at least 2 elements') - - start_location, end_location = locations - - if hasattr(start_location, '__len__'): - start_location = SourceLocation.from_position(self, f, - start_location[0], start_location[1]) - elif isinstance(start_location, int): - start_location = SourceLocation.from_offset(self, f, - start_location) - - if hasattr(end_location, '__len__'): - end_location = SourceLocation.from_position(self, f, - end_location[0], end_location[1]) - elif isinstance(end_location, int): - end_location = SourceLocation.from_offset(self, f, end_location) - - assert isinstance(start_location, SourceLocation) - assert isinstance(end_location, SourceLocation) - - return SourceRange.from_locations(start_location, end_location) - - @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(conf.lib.clang_getNumDiagnostics(self.tu)) - - def __getitem__(self, key): - diag = conf.lib.clang_getDiagnostic(self.tu, key) - if not diag: - raise IndexError - return Diagnostic(diag) - - return DiagIterator(self) - - def reparse(self, unsaved_files=None, options=0): - """ - 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. - """ - if unsaved_files is None: - unsaved_files = [] - - 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 = conf.lib.clang_reparseTranslationUnit(self, len(unsaved_files), - unsaved_files_array, options) - - def save(self, filename): - """Saves the TranslationUnit to a file. - - This is equivalent to passing -emit-ast to the clang frontend. The - saved file can be loaded back into a TranslationUnit. Or, if it - corresponds to a header, it can be used as a pre-compiled header file. - - If an error occurs while saving, a TranslationUnitSaveError is raised. - If the error was TranslationUnitSaveError.ERROR_INVALID_TU, this means - the constructed TranslationUnit was not valid at time of save. In this - case, the reason(s) why should be available via - TranslationUnit.diagnostics(). - - filename -- The path to save the translation unit to. - """ - 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, - include_macros=False, include_code_patterns=False, - include_brief_comments=False): - """ - 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. - """ - 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 = [] - - 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 = conf.lib.clang_codeCompleteAt(self, path, line, column, - unsaved_files_array, len(unsaved_files), options) - if ptr: - return CodeCompletionResults(ptr) - return None - - def get_tokens(self, locations=None, extent=None): - """Obtain tokens in this translation unit. - - This is a generator for Token instances. The caller specifies a range - of source code to obtain tokens for. The range can be specified as a - 2-tuple of SourceLocation or as a SourceRange. If both are defined, - behavior is undefined. - """ - if locations is not None: - extent = SourceRange(start=locations[0], end=locations[1]) - - return TokenGroup.get_tokens(self, extent) - -class File(ClangObject): - """ - The File class represents a particular source file that is part of a - translation unit. - """ - - @staticmethod - def from_name(translation_unit, file_name): - """Retrieve a file handle within the given translation unit.""" - 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 conf.lib.clang_getCString(conf.lib.clang_getFileName(self)) - - @property - def time(self): - """Return the last modification time of the file.""" - return conf.lib.clang_getFileTime(self) - - def __str__(self): - return self.name - - def __repr__(self): - return "<File: %s>" % (self.name) - - @staticmethod - def from_cursor_result(res, fn, args): - assert isinstance(res, File) - - # Copy a reference to the TranslationUnit to prevent premature GC. - res._tu = args[0]._tu - return res - -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 - -class CompilationDatabaseError(Exception): - """Represents an error that occurred when working with a CompilationDatabase - - Each error is associated to an enumerated value, accessible under - e.cdb_error. Consumers can compare the value with one of the ERROR_ - constants in this class. - """ - - # An unknown error occured - ERROR_UNKNOWN = 0 - - # The database could not be loaded - ERROR_CANNOTLOADDATABASE = 1 - - def __init__(self, enumeration, message): - assert isinstance(enumeration, int) - - if enumeration > 1: - raise Exception("Encountered undefined CompilationDatabase error " - "constant: %d. Please file a bug to have this " - "value supported." % enumeration) - - self.cdb_error = enumeration - Exception.__init__(self, 'Error %d: %s' % (enumeration, message)) - -class CompileCommand(object): - """Represents the compile command used to build a file""" - def __init__(self, cmd, ccmds): - self.cmd = cmd - # Keep a reference to the originating CompileCommands - # to prevent garbage collection - self.ccmds = ccmds - - @property - def directory(self): - """Get the working directory for this CompileCommand""" - return conf.lib.clang_CompileCommand_getDirectory(self.cmd) - - @property - def arguments(self): - """ - Get an iterable object providing each argument in the - command line for the compiler invocation as a _CXString. - - Invariant : the first argument is the compiler executable - """ - length = conf.lib.clang_CompileCommand_getNumArgs(self.cmd) - for i in xrange(length): - yield conf.lib.clang_CompileCommand_getArg(self.cmd, i) - -class CompileCommands(object): - """ - CompileCommands is an iterable object containing all CompileCommand - that can be used for building a specific file. - """ - def __init__(self, ccmds): - self.ccmds = ccmds - - def __del__(self): - conf.lib.clang_CompileCommands_dispose(self.ccmds) - - def __len__(self): - return int(conf.lib.clang_CompileCommands_getSize(self.ccmds)) - - def __getitem__(self, i): - cc = conf.lib.clang_CompileCommands_getCommand(self.ccmds, i) - if not cc: - raise IndexError - return CompileCommand(cc, self) - - @staticmethod - def from_result(res, fn, args): - if not res: - return None - return CompileCommands(res) - -class CompilationDatabase(ClangObject): - """ - The CompilationDatabase is a wrapper class around - clang::tooling::CompilationDatabase - - It enables querying how a specific source file can be built. - """ - - def __del__(self): - conf.lib.clang_CompilationDatabase_dispose(self) - - @staticmethod - def from_result(res, fn, args): - if not res: - raise CompilationDatabaseError(0, - "CompilationDatabase loading failed") - return CompilationDatabase(res) - - @staticmethod - def fromDirectory(buildDir): - """Builds a CompilationDatabase from the database found in buildDir""" - errorCode = c_uint() - try: - cdb = conf.lib.clang_CompilationDatabase_fromDirectory(buildDir, - byref(errorCode)) - except CompilationDatabaseError as e: - raise CompilationDatabaseError(int(errorCode.value), - "CompilationDatabase loading failed") - return cdb - - def getCompileCommands(self, filename): - """ - Get an iterable object providing all the CompileCommands available to - build filename. Returns None if filename is not found in the database. - """ - return conf.lib.clang_CompilationDatabase_getCompileCommands(self, - filename) - -class Token(Structure): - """Represents a single token from the preprocessor. - - Tokens are effectively segments of source code. Source code is first parsed - into tokens before being converted into the AST and Cursors. - - Tokens are obtained from parsed TranslationUnit instances. You currently - can't create tokens manually. - """ - _fields_ = [ - ('int_data', c_uint * 4), - ('ptr_data', c_void_p) - ] - - @property - def spelling(self): - """The spelling of this token. - - This is the textual representation of the token in source. - """ - return conf.lib.clang_getTokenSpelling(self._tu, self) - - @property - def kind(self): - """Obtain the TokenKind of the current token.""" - return TokenKind.from_value(conf.lib.clang_getTokenKind(self)) - - @property - def location(self): - """The SourceLocation this Token occurs at.""" - return conf.lib.clang_getTokenLocation(self._tu, self) - - @property - def extent(self): - """The SourceRange this Token occupies.""" - return conf.lib.clang_getTokenExtent(self._tu, self) - - @property - def cursor(self): - """The Cursor this Token corresponds to.""" - cursor = Cursor() - - conf.lib.clang_annotateTokens(self._tu, byref(self), 1, byref(cursor)) - - return cursor - -# Now comes the plumbing to hook up the C library. - -# Register callback types in common container. -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) - -# Functions strictly alphabetical order. -functionList = [ - ("clang_annotateTokens", - [TranslationUnit, POINTER(Token), c_uint, POINTER(Cursor)]), - - ("clang_CompilationDatabase_dispose", - [c_object_p]), - - ("clang_CompilationDatabase_fromDirectory", - [c_char_p, POINTER(c_uint)], - c_object_p, - CompilationDatabase.from_result), - - ("clang_CompilationDatabase_getCompileCommands", - [c_object_p, c_char_p], - c_object_p, - CompileCommands.from_result), - - ("clang_CompileCommands_dispose", - [c_object_p]), - - ("clang_CompileCommands_getCommand", - [c_object_p, c_uint], - c_object_p), - - ("clang_CompileCommands_getSize", - [c_object_p], - c_uint), - - ("clang_CompileCommand_getArg", - [c_object_p, c_uint], - _CXString, - _CXString.from_result), - - ("clang_CompileCommand_getDirectory", - [c_object_p], - _CXString, - _CXString.from_result), - - ("clang_CompileCommand_getNumArgs", - [c_object_p], - c_uint), - - ("clang_codeCompleteAt", - [TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int], - POINTER(CCRStructure)), - - ("clang_codeCompleteGetDiagnostic", - [CodeCompletionResults, c_int], - Diagnostic), - - ("clang_codeCompleteGetNumDiagnostics", - [CodeCompletionResults], - c_int), - - ("clang_createIndex", - [c_int, c_int], - c_object_p), - - ("clang_createTranslationUnit", - [Index, c_char_p], - c_object_p), - - ("clang_CXXMethod_isPureVirtual", - [Cursor], - bool), - - ("clang_CXXMethod_isStatic", - [Cursor], - bool), - - ("clang_CXXMethod_isVirtual", - [Cursor], - bool), - - ("clang_defaultSaveOptions", - [TranslationUnit], - c_uint), - - ("clang_disposeCodeCompleteResults", - [CodeCompletionResults]), - -# ("clang_disposeCXTUResourceUsage", -# [CXTUResourceUsage]), - - ("clang_disposeDiagnostic", - [Diagnostic]), - - ("clang_disposeIndex", - [Index]), - - ("clang_disposeString", - [_CXString]), - - ("clang_disposeTokens", - [TranslationUnit, POINTER(Token), c_uint]), - - ("clang_disposeTranslationUnit", - [TranslationUnit]), - - ("clang_equalCursors", - [Cursor, Cursor], - bool), - - ("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_getFieldDeclBitWidth", - [Cursor], - c_int), - - ("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_getTypeSpelling", - [Type], - _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), - - ("clang_Cursor_getArgument", - [Cursor, c_uint], - Cursor, - Cursor.from_result), - - ("clang_Cursor_isBitField", - [Cursor], - bool), - - ("clang_Cursor_getBriefCommentText", - [Cursor], - _CXString, - _CXString.from_result), - - ("clang_Cursor_getRawCommentText", - [Cursor], - _CXString, - _CXString.from_result), - - ("clang_Type_getAlignOf", - [Type], - c_longlong), - - ("clang_Type_getClassType", - [Type], - Type, - Type.from_result), - - ("clang_Type_getOffsetOf", - [Type, c_char_p], - c_longlong), - - ("clang_Type_getSizeOf", - [Type], - c_longlong), - - ("clang_Type_getCXXRefQualifier", - [Type], - c_uint), -] - -class LibclangError(Exception): - def __init__(self, message): - self.m = message - - 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) - - if len(item) >= 2: - func.argtypes = item[1] - - if len(item) >= 3: - func.restype = item[2] - - if len(item) == 4: - func.errcheck = item[3] - -def register_functions(lib, ignore_errors): - """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. - """ - - def register(item): - return register_function(lib, item, ignore_errors) - - map(register, functionList) - -class Config: - library_path = None - library_file = None - compatibility_check = True - loaded = False - - @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.") - - Config.library_path = path - - @staticmethod - def set_library_file(filename): - """Set the exact location of libclang""" - if Config.loaded: - raise Exception("library file must be set before before using " \ - "any other functionalities in libclang.") - - Config.library_file = filename - - @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' - - if Config.library_path: - file = Config.library_path + '/' + file - - return file - - 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) - - return library - - def function_exists(self, name): - try: - getattr(self.lib, name) - except AttributeError: - return False - - 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', - 'CompileCommand', - 'CursorKind', - 'Cursor', - 'Diagnostic', - 'File', - 'FixIt', - 'Index', - 'SourceLocation', - 'SourceRange', - 'TokenKind', - 'Token', - 'TranslationUnitLoadError', - 'TranslationUnit', - 'TypeKind', - 'Type', -] diff --git a/bindings/python/clang/enumerations.py b/bindings/python/clang/enumerations.py deleted file mode 100644 index a86a48ade3bd..000000000000 --- a/bindings/python/clang/enumerations.py +++ /dev/null @@ -1,34 +0,0 @@ -#===- enumerations.py - Python Enumerations ------------------*- python -*--===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -""" -Clang Enumerations -================== - -This module provides static definitions of enumerations that exist in libclang. - -Enumerations are typically defined as a list of tuples. The exported values are -typically munged into other types or classes at module load time. - -All enumerations are centrally defined in this file so they are all grouped -together and easier to audit. And, maybe even one day this file will be -automatically generated by scanning the libclang headers! -""" - -# Maps to CXTokenKind. Note that libclang maintains a separate set of token -# enumerations from the C++ API. -TokenKinds = [ - ('PUNCTUATION', 0), - ('KEYWORD', 1), - ('IDENTIFIER', 2), - ('LITERAL', 3), - ('COMMENT', 4), -] - -__all__ = ['TokenKinds'] diff --git a/bindings/python/examples/cindex/cindex-dump.py b/bindings/python/examples/cindex/cindex-dump.py deleted file mode 100644 index af7ddab6ea53..000000000000 --- a/bindings/python/examples/cindex/cindex-dump.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python - -#===- cindex-dump.py - cindex/Python Source Dump -------------*- python -*--===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -""" -A simple command line tool for dumping a source file using the Clang Index -Library. -""" - -def get_diag_info(diag): - return { 'severity' : diag.severity, - 'location' : diag.location, - 'spelling' : diag.spelling, - 'ranges' : diag.ranges, - 'fixits' : diag.fixits } - -def get_cursor_id(cursor, cursor_list = []): - if not opts.showIDs: - return None - - if cursor is None: - return None - - # FIXME: This is really slow. It would be nice if the index API exposed - # something that let us hash cursors. - for i,c in enumerate(cursor_list): - if cursor == c: - return i - cursor_list.append(cursor) - return len(cursor_list) - 1 - -def get_info(node, depth=0): - if opts.maxDepth is not None and depth >= opts.maxDepth: - children = None - else: - children = [get_info(c, depth+1) - for c in node.get_children()] - return { 'id' : get_cursor_id(node), - 'kind' : node.kind, - 'usr' : node.get_usr(), - 'spelling' : node.spelling, - 'location' : node.location, - 'extent.start' : node.extent.start, - 'extent.end' : node.extent.end, - 'is_definition' : node.is_definition(), - 'definition id' : get_cursor_id(node.get_definition()), - 'children' : children } - -def main(): - from clang.cindex import Index - from pprint import pprint - - from optparse import OptionParser, OptionGroup - - global opts - - parser = OptionParser("usage: %prog [options] {filename} [clang-args*]") - parser.add_option("", "--show-ids", dest="showIDs", - help="Don't compute cursor IDs (very slow)", - default=False) - parser.add_option("", "--max-depth", dest="maxDepth", - help="Limit cursor expansion to depth N", - metavar="N", type=int, default=None) - parser.disable_interspersed_args() - (opts, args) = parser.parse_args() - - if len(args) == 0: - parser.error('invalid number arguments') - - index = Index.create() - tu = index.parse(None, args) - if not tu: - parser.error("unable to load input") - - pprint(('diags', map(get_diag_info, tu.diagnostics))) - pprint(('nodes', get_info(tu.cursor))) - -if __name__ == '__main__': - main() - diff --git a/bindings/python/examples/cindex/cindex-includes.py b/bindings/python/examples/cindex/cindex-includes.py deleted file mode 100644 index 17500227a349..000000000000 --- a/bindings/python/examples/cindex/cindex-includes.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python - -#===- cindex-includes.py - cindex/Python Inclusion Graph -----*- python -*--===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# - -""" -A simple command line tool for dumping a Graphviz description (dot) that -describes include dependencies. -""" - -def main(): - import sys - from clang.cindex import Index - - from optparse import OptionParser, OptionGroup - - parser = OptionParser("usage: %prog [options] {filename} [clang-args*]") - parser.disable_interspersed_args() - (opts, args) = parser.parse_args() - if len(args) == 0: - parser.error('invalid number arguments') - - # FIXME: Add an output file option - out = sys.stdout - - index = Index.create() - tu = index.parse(None, args) - if not tu: - parser.error("unable to load input") - - # A helper function for generating the node name. - def name(f): - if f: - return "\"" + f.name + "\"" - - # Generate the include graph - out.write("digraph G {\n") - for i in tu.get_includes(): - line = " "; - if i.is_input_file: - # Always write the input file as a node just in case it doesn't - # actually include anything. This would generate a 1 node graph. - line += name(i.include) - else: - line += '%s->%s' % (name(i.source), name(i.include)) - line += "\n"; - out.write(line) - out.write("}\n") - -if __name__ == '__main__': - main() - diff --git a/bindings/python/tests/__init__.py b/bindings/python/tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/bindings/python/tests/__init__.py +++ /dev/null diff --git a/bindings/python/tests/cindex/INPUTS/compile_commands.json b/bindings/python/tests/cindex/INPUTS/compile_commands.json deleted file mode 100644 index 944150bf7ba6..000000000000 --- a/bindings/python/tests/cindex/INPUTS/compile_commands.json +++ /dev/null @@ -1,17 +0,0 @@ -[ -{ - "directory": "/home/john.doe/MyProject", - "command": "clang++ -o project.o -c /home/john.doe/MyProject/project.cpp", - "file": "/home/john.doe/MyProject/project.cpp" -}, -{ - "directory": "/home/john.doe/MyProjectA", - "command": "clang++ -o project2.o -c /home/john.doe/MyProject/project2.cpp", - "file": "/home/john.doe/MyProject/project2.cpp" -}, -{ - "directory": "/home/john.doe/MyProjectB", - "command": "clang++ -DFEATURE=1 -o project2-feature.o -c /home/john.doe/MyProject/project2.cpp", - "file": "/home/john.doe/MyProject/project2.cpp" -} -] diff --git a/bindings/python/tests/cindex/INPUTS/header1.h b/bindings/python/tests/cindex/INPUTS/header1.h deleted file mode 100644 index b4eacbee3754..000000000000 --- a/bindings/python/tests/cindex/INPUTS/header1.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef HEADER1 -#define HEADER1 - -#include "header3.h" - -#endif diff --git a/bindings/python/tests/cindex/INPUTS/header2.h b/bindings/python/tests/cindex/INPUTS/header2.h deleted file mode 100644 index c4eddc0c5620..000000000000 --- a/bindings/python/tests/cindex/INPUTS/header2.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef HEADER2 -#define HEADER2 - -#include "header3.h" - -#endif diff --git a/bindings/python/tests/cindex/INPUTS/header3.h b/bindings/python/tests/cindex/INPUTS/header3.h deleted file mode 100644 index 6dca764860e1..000000000000 --- a/bindings/python/tests/cindex/INPUTS/header3.h +++ /dev/null @@ -1,3 +0,0 @@ -// Not a guarded header! - -void f(); diff --git a/bindings/python/tests/cindex/INPUTS/hello.cpp b/bindings/python/tests/cindex/INPUTS/hello.cpp deleted file mode 100644 index 7ef086e56b2c..000000000000 --- a/bindings/python/tests/cindex/INPUTS/hello.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "stdio.h" - -int main(int argc, char* argv[]) { - printf("hello world\n"); - return 0; -} diff --git a/bindings/python/tests/cindex/INPUTS/include.cpp b/bindings/python/tests/cindex/INPUTS/include.cpp deleted file mode 100644 index 60cfdaae4d09..000000000000 --- a/bindings/python/tests/cindex/INPUTS/include.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "header1.h" -#include "header2.h" -#include "header1.h" - -int main() { } diff --git a/bindings/python/tests/cindex/INPUTS/parse_arguments.c b/bindings/python/tests/cindex/INPUTS/parse_arguments.c deleted file mode 100644 index 7196486c78a1..000000000000 --- a/bindings/python/tests/cindex/INPUTS/parse_arguments.c +++ /dev/null @@ -1,2 +0,0 @@ -int DECL_ONE = 1; -int DECL_TWO = 2; diff --git a/bindings/python/tests/cindex/__init__.py b/bindings/python/tests/cindex/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/bindings/python/tests/cindex/__init__.py +++ /dev/null diff --git a/bindings/python/tests/cindex/test_cdb.py b/bindings/python/tests/cindex/test_cdb.py deleted file mode 100644 index d0f580ea9f47..000000000000 --- a/bindings/python/tests/cindex/test_cdb.py +++ /dev/null @@ -1,89 +0,0 @@ -from clang.cindex import CompilationDatabase -from clang.cindex import CompilationDatabaseError -from clang.cindex import CompileCommands -from clang.cindex import CompileCommand -import os -import gc - -kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') - -def test_create_fail(): - """Check we fail loading a database with an assertion""" - path = os.path.dirname(__file__) - try: - cdb = CompilationDatabase.fromDirectory(path) - except CompilationDatabaseError as e: - assert e.cdb_error == CompilationDatabaseError.ERROR_CANNOTLOADDATABASE - else: - assert False - -def test_create(): - """Check we can load a compilation database""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - -def test_lookup_fail(): - """Check file lookup failure""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - assert cdb.getCompileCommands('file_do_not_exist.cpp') == None - -def test_lookup_succeed(): - """Check we get some results if the file exists in the db""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - assert len(cmds) != 0 - -def test_1_compilecommand(): - """Check file with single compile command""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - assert len(cmds) == 1 - assert cmds[0].directory == '/home/john.doe/MyProject' - expected = [ 'clang++', '-o', 'project.o', '-c', - '/home/john.doe/MyProject/project.cpp'] - for arg, exp in zip(cmds[0].arguments, expected): - assert arg == exp - -def test_2_compilecommand(): - """Check file with 2 compile commands""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp') - assert len(cmds) == 2 - expected = [ - { 'wd': '/home/john.doe/MyProjectA', - 'line': ['clang++', '-o', 'project2.o', '-c', - '/home/john.doe/MyProject/project2.cpp']}, - { 'wd': '/home/john.doe/MyProjectB', - 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c', - '/home/john.doe/MyProject/project2.cpp']} - ] - for i in range(len(cmds)): - assert cmds[i].directory == expected[i]['wd'] - for arg, exp in zip(cmds[i].arguments, expected[i]['line']): - assert arg == exp - -def test_compilecommand_iterator_stops(): - """Check that iterator stops after the correct number of elements""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - count = 0 - for cmd in cdb.getCompileCommands('/home/john.doe/MyProject/project2.cpp'): - count += 1 - assert count <= 2 - -def test_compilationDB_references(): - """Ensure CompilationsCommands are independent of the database""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - del cdb - gc.collect() - workingdir = cmds[0].directory - -def test_compilationCommands_references(): - """Ensure CompilationsCommand keeps a reference to CompilationCommands""" - cdb = CompilationDatabase.fromDirectory(kInputsDir) - cmds = cdb.getCompileCommands('/home/john.doe/MyProject/project.cpp') - del cdb - cmd0 = cmds[0] - del cmds - gc.collect() - workingdir = cmd0.directory - diff --git a/bindings/python/tests/cindex/test_code_completion.py b/bindings/python/tests/cindex/test_code_completion.py deleted file mode 100644 index 357d50db5131..000000000000 --- a/bindings/python/tests/cindex/test_code_completion.py +++ /dev/null @@ -1,75 +0,0 @@ -from clang.cindex import TranslationUnit - -def check_completion_results(cr, expected): - assert cr is not None - assert len(cr.diagnostics) == 0 - - completions = [str(c) for c in cr.results] - - for c in expected: - assert c in completions - -def test_code_complete(): - files = [('fake.c', """ -/// Aaa. -int test1; - -/// Bbb. -void test2(void); - -void f() { - -} -""")] - - tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, - options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) - - cr = tu.codeComplete('fake.c', 9, 1, unsaved_files=files, include_brief_comments=True) - - expected = [ - "{'int', ResultType} | {'test1', TypedText} || Priority: 50 || Availability: Available || Brief comment: Aaa.", - "{'void', ResultType} | {'test2', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 50 || Availability: Available || Brief comment: Bbb.", - "{'return', TypedText} || Priority: 40 || Availability: Available || Brief comment: None" - ] - check_completion_results(cr, expected) - -def test_code_complete_availability(): - files = [('fake.cpp', """ -class P { -protected: - int member; -}; - -class Q : public P { -public: - using P::member; -}; - -void f(P x, Q y) { - x.; // member is inaccessible - y.; // member is accessible -} -""")] - - tu = TranslationUnit.from_source('fake.cpp', ['-std=c++98'], unsaved_files=files) - - cr = tu.codeComplete('fake.cpp', 12, 5, unsaved_files=files) - - expected = [ - "{'const', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", - "{'volatile', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", - "{'operator', TypedText} || Priority: 40 || Availability: Available || Brief comment: None", - "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", - "{'Q', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None" - ] - check_completion_results(cr, expected) - - cr = tu.codeComplete('fake.cpp', 13, 5, unsaved_files=files) - expected = [ - "{'P', TypedText} | {'::', Text} || Priority: 75 || Availability: Available || Brief comment: None", - "{'P &', ResultType} | {'operator=', TypedText} | {'(', LeftParen} | {'const P &', Placeholder} | {')', RightParen} || Priority: 34 || Availability: Available || Brief comment: None", - "{'int', ResultType} | {'member', TypedText} || Priority: 35 || Availability: NotAccessible || Brief comment: None", - "{'void', ResultType} | {'~P', TypedText} | {'(', LeftParen} | {')', RightParen} || Priority: 34 || Availability: Available || Brief comment: None" - ] - check_completion_results(cr, expected) diff --git a/bindings/python/tests/cindex/test_comment.py b/bindings/python/tests/cindex/test_comment.py deleted file mode 100644 index d8f3129ac51e..000000000000 --- a/bindings/python/tests/cindex/test_comment.py +++ /dev/null @@ -1,40 +0,0 @@ -from clang.cindex import TranslationUnit -from tests.cindex.util import get_cursor - -def test_comment(): - files = [('fake.c', """ -/// Aaa. -int test1; - -/// Bbb. -/// x -void test2(void); - -void f() { - -} -""")] - # make a comment-aware TU - tu = TranslationUnit.from_source('fake.c', ['-std=c99'], unsaved_files=files, - options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION) - test1 = get_cursor(tu, 'test1') - assert test1 is not None, "Could not find test1." - assert test1.type.is_pod() - raw = test1.raw_comment - brief = test1.brief_comment - assert raw == """/// Aaa.""" - assert brief == """Aaa.""" - - test2 = get_cursor(tu, 'test2') - raw = test2.raw_comment - brief = test2.brief_comment - assert raw == """/// Bbb.\n/// x""" - assert brief == """Bbb. x""" - - f = get_cursor(tu, 'f') - raw = f.raw_comment - brief = f.brief_comment - assert raw is None - assert brief is None - - diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py deleted file mode 100644 index a27525cfe553..000000000000 --- a/bindings/python/tests/cindex/test_cursor.py +++ /dev/null @@ -1,261 +0,0 @@ -import gc - -from clang.cindex import CursorKind -from clang.cindex import TranslationUnit -from clang.cindex import TypeKind -from .util import get_cursor -from .util import get_cursors -from .util import get_tu - -kInput = """\ -// FIXME: Find nicer way to drop builtins and other cruft. -int start_decl; - -struct s0 { - int a; - int b; -}; - -struct s1; - -void f0(int a0, int a1) { - int l0, l1; - - if (a0) - return; - - for (;;) { - break; - } -} -""" - -def test_get_children(): - tu = get_tu(kInput) - - # Skip until past start_decl. - it = tu.cursor.get_children() - while it.next().spelling != 'start_decl': - pass - - tu_nodes = list(it) - - assert len(tu_nodes) == 3 - for cursor in tu_nodes: - assert cursor.translation_unit is not None - - assert tu_nodes[0] != tu_nodes[1] - assert tu_nodes[0].kind == CursorKind.STRUCT_DECL - assert tu_nodes[0].spelling == 's0' - assert tu_nodes[0].is_definition() == True - assert tu_nodes[0].location.file.name == 't.c' - assert tu_nodes[0].location.line == 4 - assert tu_nodes[0].location.column == 8 - assert tu_nodes[0].hash > 0 - assert tu_nodes[0].translation_unit is not None - - s0_nodes = list(tu_nodes[0].get_children()) - assert len(s0_nodes) == 2 - assert s0_nodes[0].kind == CursorKind.FIELD_DECL - assert s0_nodes[0].spelling == 'a' - assert s0_nodes[0].type.kind == TypeKind.INT - assert s0_nodes[1].kind == CursorKind.FIELD_DECL - assert s0_nodes[1].spelling == 'b' - assert s0_nodes[1].type.kind == TypeKind.INT - - assert tu_nodes[1].kind == CursorKind.STRUCT_DECL - assert tu_nodes[1].spelling == 's1' - assert tu_nodes[1].displayname == 's1' - assert tu_nodes[1].is_definition() == False - - assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL - assert tu_nodes[2].spelling == 'f0' - assert tu_nodes[2].displayname == 'f0(int, int)' - assert tu_nodes[2].is_definition() == True - -def test_references(): - """Ensure that references to TranslationUnit are kept.""" - tu = get_tu('int x;') - cursors = list(tu.cursor.get_children()) - assert len(cursors) > 0 - - cursor = cursors[0] - assert isinstance(cursor.translation_unit, TranslationUnit) - - # Delete reference to TU and perform a full GC. - del tu - gc.collect() - assert isinstance(cursor.translation_unit, TranslationUnit) - - # If the TU was destroyed, this should cause a segfault. - parent = cursor.semantic_parent - -def test_canonical(): - source = 'struct X; struct X; struct X { int member; };' - tu = get_tu(source) - - cursors = [] - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'X': - cursors.append(cursor) - - assert len(cursors) == 3 - assert cursors[1].canonical == cursors[2].canonical - -def test_is_static_method(): - """Ensure Cursor.is_static_method works.""" - - source = 'class X { static void foo(); void bar(); };' - tu = get_tu(source, lang='cpp') - - cls = get_cursor(tu, 'X') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - assert cls is not None - assert foo is not None - assert bar is not None - - assert foo.is_static_method() - assert not bar.is_static_method() - -def test_underlying_type(): - tu = get_tu('typedef int foo;') - typedef = get_cursor(tu, 'foo') - assert typedef is not None - - assert typedef.kind.is_declaration() - underlying = typedef.underlying_typedef_type - assert underlying.kind == TypeKind.INT - -kParentTest = """\ - class C { - void f(); - } - - void C::f() { } - """ -def test_semantic_parent(): - tu = get_tu(kParentTest, 'cpp') - curs = get_cursors(tu, 'f') - decl = get_cursor(tu, 'C') - assert(len(curs) == 2) - assert(curs[0].semantic_parent == curs[1].semantic_parent) - assert(curs[0].semantic_parent == decl) - -def test_lexical_parent(): - tu = get_tu(kParentTest, 'cpp') - curs = get_cursors(tu, 'f') - decl = get_cursor(tu, 'C') - assert(len(curs) == 2) - assert(curs[0].lexical_parent != curs[1].lexical_parent) - assert(curs[0].lexical_parent == decl) - assert(curs[1].lexical_parent == tu.cursor) - -def test_enum_type(): - tu = get_tu('enum TEST { FOO=1, BAR=2 };') - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - enum_type = enum.enum_type - assert enum_type.kind == TypeKind.UINT - -def test_enum_type_cpp(): - tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - assert enum.enum_type.kind == TypeKind.LONGLONG - -def test_objc_type_encoding(): - tu = get_tu('int i;', lang='objc') - i = get_cursor(tu, 'i') - - assert i is not None - assert i.objc_type_encoding == 'i' - -def test_enum_values(): - tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - - enum_constants = list(enum.get_children()) - assert len(enum_constants) == 3 - - spam, egg, ham = enum_constants - - assert spam.kind == CursorKind.ENUM_CONSTANT_DECL - assert spam.enum_value == 1 - assert egg.kind == CursorKind.ENUM_CONSTANT_DECL - assert egg.enum_value == 2 - assert ham.kind == CursorKind.ENUM_CONSTANT_DECL - assert ham.enum_value == 40 - -def test_enum_values_cpp(): - tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") - enum = get_cursor(tu, 'TEST') - assert enum is not None - - assert enum.kind == CursorKind.ENUM_DECL - - enum_constants = list(enum.get_children()) - assert len(enum_constants) == 2 - - spam, ham = enum_constants - - assert spam.kind == CursorKind.ENUM_CONSTANT_DECL - assert spam.enum_value == -1 - assert ham.kind == CursorKind.ENUM_CONSTANT_DECL - assert ham.enum_value == 0x10000000000 - -def test_annotation_attribute(): - tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') - - foo = get_cursor(tu, 'foo') - assert foo is not None - - for c in foo.get_children(): - if c.kind == CursorKind.ANNOTATE_ATTR: - assert c.displayname == "here be annotation attribute" - break - else: - assert False, "Couldn't find annotation" - -def test_result_type(): - tu = get_tu('int foo();') - foo = get_cursor(tu, 'foo') - - assert foo is not None - t = foo.result_type - assert t.kind == TypeKind.INT - -def test_get_tokens(): - """Ensure we can map cursors back to tokens.""" - tu = get_tu('int foo(int i);') - foo = get_cursor(tu, 'foo') - - tokens = list(foo.get_tokens()) - assert len(tokens) == 7 - assert tokens[0].spelling == 'int' - assert tokens[1].spelling == 'foo' - -def test_get_arguments(): - tu = get_tu('void foo(int i, int j);') - foo = get_cursor(tu, 'foo') - arguments = list(foo.get_arguments()) - - assert len(arguments) == 2 - assert arguments[0].spelling == "i" - assert arguments[1].spelling == "j" - -def test_referenced(): - tu = get_tu('void foo(); void bar() { foo(); }') - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - for c in bar.get_children(): - if c.kind == CursorKind.CALL_EXPR: - assert c.referenced.spelling == foo.spelling - break diff --git a/bindings/python/tests/cindex/test_cursor_kind.py b/bindings/python/tests/cindex/test_cursor_kind.py deleted file mode 100644 index 8cabc512d4c5..000000000000 --- a/bindings/python/tests/cindex/test_cursor_kind.py +++ /dev/null @@ -1,47 +0,0 @@ -from clang.cindex import CursorKind - -def test_name(): - assert CursorKind.UNEXPOSED_DECL.name is 'UNEXPOSED_DECL' - -def test_get_all_kinds(): - kinds = CursorKind.get_all_kinds() - assert CursorKind.UNEXPOSED_DECL in kinds - assert CursorKind.TRANSLATION_UNIT in kinds - assert CursorKind.VARIABLE_REF in kinds - assert CursorKind.LAMBDA_EXPR in kinds - assert CursorKind.OBJ_BOOL_LITERAL_EXPR in kinds - assert CursorKind.OBJ_SELF_EXPR in kinds - assert CursorKind.MS_ASM_STMT in kinds - assert CursorKind.MODULE_IMPORT_DECL in kinds - -def test_kind_groups(): - """Check that every kind classifies to exactly one group.""" - - assert CursorKind.UNEXPOSED_DECL.is_declaration() - assert CursorKind.TYPE_REF.is_reference() - assert CursorKind.DECL_REF_EXPR.is_expression() - assert CursorKind.UNEXPOSED_STMT.is_statement() - assert CursorKind.INVALID_FILE.is_invalid() - - assert CursorKind.TRANSLATION_UNIT.is_translation_unit() - assert not CursorKind.TYPE_REF.is_translation_unit() - - assert CursorKind.PREPROCESSING_DIRECTIVE.is_preprocessing() - assert not CursorKind.TYPE_REF.is_preprocessing() - - assert CursorKind.UNEXPOSED_DECL.is_unexposed() - assert not CursorKind.TYPE_REF.is_unexposed() - - for k in CursorKind.get_all_kinds(): - group = [n for n in ('is_declaration', 'is_reference', 'is_expression', - 'is_statement', 'is_invalid', 'is_attribute') - if getattr(k, n)()] - - if k in ( CursorKind.TRANSLATION_UNIT, - CursorKind.MACRO_DEFINITION, - CursorKind.MACRO_INSTANTIATION, - CursorKind.INCLUSION_DIRECTIVE, - CursorKind.PREPROCESSING_DIRECTIVE): - assert len(group) == 0 - else: - assert len(group) == 1 diff --git a/bindings/python/tests/cindex/test_diagnostics.py b/bindings/python/tests/cindex/test_diagnostics.py deleted file mode 100644 index 48ab6176fd1d..000000000000 --- a/bindings/python/tests/cindex/test_diagnostics.py +++ /dev/null @@ -1,82 +0,0 @@ -from clang.cindex import * -from .util import get_tu - -# FIXME: We need support for invalid translation units to test better. - -def test_diagnostic_warning(): - tu = get_tu('int f0() {}\n') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 1 - assert tu.diagnostics[0].location.column == 11 - assert (tu.diagnostics[0].spelling == - 'control reaches end of non-void function') - -def test_diagnostic_note(): - # FIXME: We aren't getting notes here for some reason. - tu = get_tu('#define A x\nvoid *A = 1;\n') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 2 - assert tu.diagnostics[0].location.column == 7 - assert 'incompatible' in tu.diagnostics[0].spelling -# assert tu.diagnostics[1].severity == Diagnostic.Note -# assert tu.diagnostics[1].location.line == 1 -# assert tu.diagnostics[1].location.column == 11 -# assert tu.diagnostics[1].spelling == 'instantiated from' - -def test_diagnostic_fixit(): - tu = get_tu('struct { int f0; } x = { f0 : 1 };') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 1 - assert tu.diagnostics[0].location.column == 26 - assert tu.diagnostics[0].spelling.startswith('use of GNU old-style') - assert len(tu.diagnostics[0].fixits) == 1 - assert tu.diagnostics[0].fixits[0].range.start.line == 1 - assert tu.diagnostics[0].fixits[0].range.start.column == 26 - assert tu.diagnostics[0].fixits[0].range.end.line == 1 - assert tu.diagnostics[0].fixits[0].range.end.column == 30 - assert tu.diagnostics[0].fixits[0].value == '.f0 = ' - -def test_diagnostic_range(): - tu = get_tu('void f() { int i = "a" + 1; }') - assert len(tu.diagnostics) == 1 - assert tu.diagnostics[0].severity == Diagnostic.Warning - assert tu.diagnostics[0].location.line == 1 - assert tu.diagnostics[0].location.column == 16 - assert tu.diagnostics[0].spelling.startswith('incompatible pointer to') - assert len(tu.diagnostics[0].fixits) == 0 - assert len(tu.diagnostics[0].ranges) == 1 - assert tu.diagnostics[0].ranges[0].start.line == 1 - assert tu.diagnostics[0].ranges[0].start.column == 20 - assert tu.diagnostics[0].ranges[0].end.line == 1 - assert tu.diagnostics[0].ranges[0].end.column == 27 - try: - tu.diagnostics[0].ranges[1].start.line - except IndexError: - assert True - else: - assert False - -def test_diagnostic_category(): - """Ensure that category properties work.""" - tu = get_tu('int f(int i) { return 7; }', all_warnings=True) - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - - assert d.severity == Diagnostic.Warning - assert d.location.line == 1 - assert d.location.column == 11 - - assert d.category_number == 2 - assert d.category_name == 'Semantic Issue' - -def test_diagnostic_option(): - """Ensure that category option properties work.""" - tu = get_tu('int f(int i) { return 7; }', all_warnings=True) - assert len(tu.diagnostics) == 1 - d = tu.diagnostics[0] - - assert d.option == '-Wunused-parameter' - assert d.disable_option == '-Wno-unused-parameter' diff --git a/bindings/python/tests/cindex/test_file.py b/bindings/python/tests/cindex/test_file.py deleted file mode 100644 index 146e8c570528..000000000000 --- a/bindings/python/tests/cindex/test_file.py +++ /dev/null @@ -1,9 +0,0 @@ -from clang.cindex import Index, File - -def test_file(): - index = Index.create() - tu = index.parse('t.c', unsaved_files = [('t.c', "")]) - file = File.from_name(tu, "t.c") - assert str(file) == "t.c" - assert file.name == "t.c" - assert repr(file) == "<File: t.c>" diff --git a/bindings/python/tests/cindex/test_index.py b/bindings/python/tests/cindex/test_index.py deleted file mode 100644 index dc173f04d218..000000000000 --- a/bindings/python/tests/cindex/test_index.py +++ /dev/null @@ -1,15 +0,0 @@ -from clang.cindex import * -import os - -kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') - -def test_create(): - index = Index.create() - -# FIXME: test Index.read - -def test_parse(): - index = Index.create() - assert isinstance(index, Index) - tu = index.parse(os.path.join(kInputsDir, 'hello.cpp')) - assert isinstance(tu, TranslationUnit) diff --git a/bindings/python/tests/cindex/test_location.py b/bindings/python/tests/cindex/test_location.py deleted file mode 100644 index 9e9ef487af18..000000000000 --- a/bindings/python/tests/cindex/test_location.py +++ /dev/null @@ -1,95 +0,0 @@ -from clang.cindex import Cursor -from clang.cindex import File -from clang.cindex import SourceLocation -from clang.cindex import SourceRange -from .util import get_cursor -from .util import get_tu - -baseInput="int one;\nint two;\n" - -def assert_location(loc, line, column, offset): - assert loc.line == line - assert loc.column == column - assert loc.offset == offset - -def test_location(): - tu = get_tu(baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') - - assert one is not None - assert two is not None - - assert_location(one.location,line=1,column=5,offset=4) - assert_location(two.location,line=2,column=5,offset=13) - - # adding a linebreak at top should keep columns same - tu = get_tu('\n' + baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') - - assert one is not None - assert two is not None - - assert_location(one.location,line=2,column=5,offset=5) - assert_location(two.location,line=3,column=5,offset=14) - - # adding a space should affect column on first line only - tu = get_tu(' ' + baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') - - assert_location(one.location,line=1,column=6,offset=5) - assert_location(two.location,line=2,column=5,offset=14) - - # define the expected location ourselves and see if it matches - # the returned location - tu = get_tu(baseInput) - - file = File.from_name(tu, 't.c') - location = SourceLocation.from_position(tu, file, 1, 5) - cursor = Cursor.from_location(tu, location) - - one = get_cursor(tu, 'one') - assert one is not None - assert one == cursor - - # Ensure locations referring to the same entity are equivalent. - location2 = SourceLocation.from_position(tu, file, 1, 5) - assert location == location2 - location3 = SourceLocation.from_position(tu, file, 1, 4) - assert location2 != location3 - - offset_location = SourceLocation.from_offset(tu, file, 5) - cursor = Cursor.from_location(tu, offset_location) - verified = False - for n in [n for n in tu.cursor.get_children() if n.spelling == 'one']: - assert n == cursor - verified = True - - assert verified - -def test_extent(): - tu = get_tu(baseInput) - one = get_cursor(tu, 'one') - two = get_cursor(tu, 'two') - - assert_location(one.extent.start,line=1,column=1,offset=0) - assert_location(one.extent.end,line=1,column=8,offset=7) - assert baseInput[one.extent.start.offset:one.extent.end.offset] == "int one" - - assert_location(two.extent.start,line=2,column=1,offset=9) - assert_location(two.extent.end,line=2,column=8,offset=16) - assert baseInput[two.extent.start.offset:two.extent.end.offset] == "int two" - - file = File.from_name(tu, 't.c') - location1 = SourceLocation.from_position(tu, file, 1, 1) - location2 = SourceLocation.from_position(tu, file, 1, 8) - - range1 = SourceRange.from_locations(location1, location2) - range2 = SourceRange.from_locations(location1, location2) - assert range1 == range2 - - location3 = SourceLocation.from_position(tu, file, 1, 6) - range3 = SourceRange.from_locations(location1, location3) - assert range1 != range3 diff --git a/bindings/python/tests/cindex/test_token_kind.py b/bindings/python/tests/cindex/test_token_kind.py deleted file mode 100644 index 62ec63e0ad58..000000000000 --- a/bindings/python/tests/cindex/test_token_kind.py +++ /dev/null @@ -1,43 +0,0 @@ -from clang.cindex import TokenKind -from nose.tools import eq_ -from nose.tools import ok_ -from nose.tools import raises - -def test_constructor(): - """Ensure TokenKind constructor works as expected.""" - - t = TokenKind(5, 'foo') - - eq_(t.value, 5) - eq_(t.name, 'foo') - -@raises(ValueError) -def test_bad_register(): - """Ensure a duplicate value is rejected for registration.""" - - TokenKind.register(2, 'foo') - -@raises(ValueError) -def test_unknown_value(): - """Ensure trying to fetch an unknown value raises.""" - - TokenKind.from_value(-1) - -def test_registration(): - """Ensure that items registered appear as class attributes.""" - ok_(hasattr(TokenKind, 'LITERAL')) - literal = TokenKind.LITERAL - - ok_(isinstance(literal, TokenKind)) - -def test_from_value(): - """Ensure registered values can be obtained from from_value().""" - t = TokenKind.from_value(3) - ok_(isinstance(t, TokenKind)) - eq_(t, TokenKind.LITERAL) - -def test_repr(): - """Ensure repr() works.""" - - r = repr(TokenKind.LITERAL) - eq_(r, 'TokenKind.LITERAL') diff --git a/bindings/python/tests/cindex/test_tokens.py b/bindings/python/tests/cindex/test_tokens.py deleted file mode 100644 index 70748429094a..000000000000 --- a/bindings/python/tests/cindex/test_tokens.py +++ /dev/null @@ -1,52 +0,0 @@ -from clang.cindex import CursorKind -from clang.cindex import Index -from clang.cindex import SourceLocation -from clang.cindex import SourceRange -from clang.cindex import TokenKind -from nose.tools import eq_ -from nose.tools import ok_ - -from .util import get_tu - -def test_token_to_cursor(): - """Ensure we can obtain a Cursor from a Token instance.""" - tu = get_tu('int i = 5;') - r = tu.get_extent('t.c', (0, 9)) - tokens = list(tu.get_tokens(extent=r)) - - assert len(tokens) == 5 - assert tokens[1].spelling == 'i' - assert tokens[1].kind == TokenKind.IDENTIFIER - - cursor = tokens[1].cursor - assert cursor.kind == CursorKind.VAR_DECL - assert tokens[1].cursor == tokens[2].cursor - -def test_token_location(): - """Ensure Token.location works.""" - - tu = get_tu('int foo = 10;') - r = tu.get_extent('t.c', (0, 11)) - - tokens = list(tu.get_tokens(extent=r)) - eq_(len(tokens), 4) - - loc = tokens[1].location - ok_(isinstance(loc, SourceLocation)) - eq_(loc.line, 1) - eq_(loc.column, 5) - eq_(loc.offset, 4) - -def test_token_extent(): - """Ensure Token.extent works.""" - tu = get_tu('int foo = 10;') - r = tu.get_extent('t.c', (0, 11)) - - tokens = list(tu.get_tokens(extent=r)) - eq_(len(tokens), 4) - - extent = tokens[1].extent - ok_(isinstance(extent, SourceRange)) - - eq_(extent.start.offset, 4) - eq_(extent.end.offset, 7) diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py deleted file mode 100644 index f77998e52457..000000000000 --- a/bindings/python/tests/cindex/test_translation_unit.py +++ /dev/null @@ -1,258 +0,0 @@ -import gc -import os - -from clang.cindex import CursorKind -from clang.cindex import Cursor -from clang.cindex import File -from clang.cindex import Index -from clang.cindex import SourceLocation -from clang.cindex import SourceRange -from clang.cindex import TranslationUnitSaveError -from clang.cindex import TranslationUnitLoadError -from clang.cindex import TranslationUnit -from .util import get_cursor -from .util import get_tu - -kInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS') - -def test_spelling(): - path = os.path.join(kInputsDir, 'hello.cpp') - tu = TranslationUnit.from_source(path) - assert tu.spelling == path - -def test_cursor(): - path = os.path.join(kInputsDir, 'hello.cpp') - tu = get_tu(path) - c = tu.cursor - assert isinstance(c, Cursor) - assert c.kind is CursorKind.TRANSLATION_UNIT - -def test_parse_arguments(): - path = os.path.join(kInputsDir, 'parse_arguments.c') - tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-2] == 'hello' - assert spellings[-1] == 'hi' - -def test_reparse_arguments(): - path = os.path.join(kInputsDir, 'parse_arguments.c') - tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi']) - tu.reparse() - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-2] == 'hello' - assert spellings[-1] == 'hi' - -def test_unsaved_files(): - tu = TranslationUnit.from_source('fake.c', ['-I./'], unsaved_files = [ - ('fake.c', """ -#include "fake.h" -int x; -int SOME_DEFINE; -"""), - ('./fake.h', """ -#define SOME_DEFINE y -""") - ]) - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-2] == 'x' - assert spellings[-1] == 'y' - -def test_unsaved_files_2(): - import StringIO - tu = TranslationUnit.from_source('fake.c', unsaved_files = [ - ('fake.c', StringIO.StringIO('int x;'))]) - spellings = [c.spelling for c in tu.cursor.get_children()] - assert spellings[-1] == 'x' - -def normpaths_equal(path1, path2): - """ Compares two paths for equality after normalizing them with - os.path.normpath - """ - return os.path.normpath(path1) == os.path.normpath(path2) - -def test_includes(): - def eq(expected, actual): - if not actual.is_input_file: - return normpaths_equal(expected[0], actual.source.name) and \ - normpaths_equal(expected[1], actual.include.name) - else: - return normpaths_equal(expected[1], actual.include.name) - - src = os.path.join(kInputsDir, 'include.cpp') - h1 = os.path.join(kInputsDir, "header1.h") - h2 = os.path.join(kInputsDir, "header2.h") - h3 = os.path.join(kInputsDir, "header3.h") - inc = [(src, h1), (h1, h3), (src, h2), (h2, h3)] - - tu = TranslationUnit.from_source(src) - for i in zip(inc, tu.get_includes()): - assert eq(i[0], i[1]) - -def save_tu(tu): - """Convenience API to save a TranslationUnit to a file. - - Returns the filename it was saved to. - """ - - # FIXME Generate a temp file path using system APIs. - base = 'TEMP_FOR_TRANSLATIONUNIT_SAVE.c' - path = os.path.join(kInputsDir, base) - - # Just in case. - if os.path.exists(path): - os.unlink(path) - - tu.save(path) - - return path - -def test_save(): - """Ensure TranslationUnit.save() works.""" - - tu = get_tu('int foo();') - - path = save_tu(tu) - assert os.path.exists(path) - assert os.path.getsize(path) > 0 - os.unlink(path) - -def test_save_translation_errors(): - """Ensure that saving to an invalid directory raises.""" - - tu = get_tu('int foo();') - - path = '/does/not/exist/llvm-test.ast' - assert not os.path.exists(os.path.dirname(path)) - - try: - tu.save(path) - assert False - except TranslationUnitSaveError as ex: - expected = TranslationUnitSaveError.ERROR_UNKNOWN - assert ex.save_error == expected - -def test_load(): - """Ensure TranslationUnits can be constructed from saved files.""" - - tu = get_tu('int foo();') - assert len(tu.diagnostics) == 0 - path = save_tu(tu) - - assert os.path.exists(path) - assert os.path.getsize(path) > 0 - - tu2 = TranslationUnit.from_ast_file(filename=path) - assert len(tu2.diagnostics) == 0 - - foo = get_cursor(tu2, 'foo') - assert foo is not None - - # Just in case there is an open file descriptor somewhere. - del tu2 - - os.unlink(path) - -def test_index_parse(): - path = os.path.join(kInputsDir, 'hello.cpp') - index = Index.create() - tu = index.parse(path) - assert isinstance(tu, TranslationUnit) - -def test_get_file(): - """Ensure tu.get_file() works appropriately.""" - - tu = get_tu('int foo();') - - f = tu.get_file('t.c') - assert isinstance(f, File) - assert f.name == 't.c' - - try: - f = tu.get_file('foobar.cpp') - except: - pass - else: - assert False - -def test_get_source_location(): - """Ensure tu.get_source_location() works.""" - - tu = get_tu('int foo();') - - location = tu.get_location('t.c', 2) - assert isinstance(location, SourceLocation) - assert location.offset == 2 - assert location.file.name == 't.c' - - location = tu.get_location('t.c', (1, 3)) - assert isinstance(location, SourceLocation) - assert location.line == 1 - assert location.column == 3 - assert location.file.name == 't.c' - -def test_get_source_range(): - """Ensure tu.get_source_range() works.""" - - tu = get_tu('int foo();') - - r = tu.get_extent('t.c', (1,4)) - assert isinstance(r, SourceRange) - assert r.start.offset == 1 - assert r.end.offset == 4 - assert r.start.file.name == 't.c' - assert r.end.file.name == 't.c' - - r = tu.get_extent('t.c', ((1,2), (1,3))) - assert isinstance(r, SourceRange) - assert r.start.line == 1 - assert r.start.column == 2 - assert r.end.line == 1 - assert r.end.column == 3 - assert r.start.file.name == 't.c' - assert r.end.file.name == 't.c' - - start = tu.get_location('t.c', 0) - end = tu.get_location('t.c', 5) - - r = tu.get_extent('t.c', (start, end)) - assert isinstance(r, SourceRange) - assert r.start.offset == 0 - assert r.end.offset == 5 - assert r.start.file.name == 't.c' - assert r.end.file.name == 't.c' - -def test_get_tokens_gc(): - """Ensures get_tokens() works properly with garbage collection.""" - - tu = get_tu('int foo();') - r = tu.get_extent('t.c', (0, 10)) - tokens = list(tu.get_tokens(extent=r)) - - assert tokens[0].spelling == 'int' - gc.collect() - assert tokens[0].spelling == 'int' - - del tokens[1] - gc.collect() - assert tokens[0].spelling == 'int' - - # May trigger segfault if we don't do our job properly. - del tokens - gc.collect() - gc.collect() # Just in case. - -def test_fail_from_source(): - path = os.path.join(kInputsDir, 'non-existent.cpp') - try: - tu = TranslationUnit.from_source(path) - except TranslationUnitLoadError: - tu = None - assert tu == None - -def test_fail_from_ast_file(): - path = os.path.join(kInputsDir, 'non-existent.ast') - try: - tu = TranslationUnit.from_ast_file(path) - except TranslationUnitLoadError: - tu = None - assert tu == None diff --git a/bindings/python/tests/cindex/test_type.py b/bindings/python/tests/cindex/test_type.py deleted file mode 100644 index a02c06fe5a13..000000000000 --- a/bindings/python/tests/cindex/test_type.py +++ /dev/null @@ -1,397 +0,0 @@ -import gc - -from clang.cindex import CursorKind -from clang.cindex import TranslationUnit -from clang.cindex import TypeKind -from nose.tools import raises -from .util import get_cursor -from .util import get_tu - -kInput = """\ - -typedef int I; - -struct teststruct { - int a; - I b; - long c; - unsigned long d; - signed long e; - const int f; - int *g; - int ***h; -}; - -""" - -def test_a_struct(): - tu = get_tu(kInput) - - teststruct = get_cursor(tu, 'teststruct') - assert teststruct is not None, "Could not find teststruct." - fields = list(teststruct.get_children()) - assert all(x.kind == CursorKind.FIELD_DECL for x in fields) - assert all(x.translation_unit is not None for x in fields) - - assert fields[0].spelling == 'a' - assert not fields[0].type.is_const_qualified() - assert fields[0].type.kind == TypeKind.INT - assert fields[0].type.get_canonical().kind == TypeKind.INT - - assert fields[1].spelling == 'b' - assert not fields[1].type.is_const_qualified() - assert fields[1].type.kind == TypeKind.TYPEDEF - assert fields[1].type.get_canonical().kind == TypeKind.INT - assert fields[1].type.get_declaration().spelling == 'I' - - assert fields[2].spelling == 'c' - assert not fields[2].type.is_const_qualified() - assert fields[2].type.kind == TypeKind.LONG - assert fields[2].type.get_canonical().kind == TypeKind.LONG - - assert fields[3].spelling == 'd' - assert not fields[3].type.is_const_qualified() - assert fields[3].type.kind == TypeKind.ULONG - assert fields[3].type.get_canonical().kind == TypeKind.ULONG - - assert fields[4].spelling == 'e' - assert not fields[4].type.is_const_qualified() - assert fields[4].type.kind == TypeKind.LONG - assert fields[4].type.get_canonical().kind == TypeKind.LONG - - assert fields[5].spelling == 'f' - assert fields[5].type.is_const_qualified() - assert fields[5].type.kind == TypeKind.INT - assert fields[5].type.get_canonical().kind == TypeKind.INT - - assert fields[6].spelling == 'g' - assert not fields[6].type.is_const_qualified() - assert fields[6].type.kind == TypeKind.POINTER - assert fields[6].type.get_pointee().kind == TypeKind.INT - - assert fields[7].spelling == 'h' - assert not fields[7].type.is_const_qualified() - assert fields[7].type.kind == TypeKind.POINTER - assert fields[7].type.get_pointee().kind == TypeKind.POINTER - assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER - assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT - -def test_references(): - """Ensure that a Type maintains a reference to a TranslationUnit.""" - - tu = get_tu('int x;') - children = list(tu.cursor.get_children()) - assert len(children) > 0 - - cursor = children[0] - t = cursor.type - - assert isinstance(t.translation_unit, TranslationUnit) - - # Delete main TranslationUnit reference and force a GC. - del tu - gc.collect() - assert isinstance(t.translation_unit, TranslationUnit) - - # If the TU was destroyed, this should cause a segfault. - decl = t.get_declaration() - -constarrayInput=""" -struct teststruct { - void *A[2]; -}; -""" -def testConstantArray(): - tu = get_tu(constarrayInput) - - teststruct = get_cursor(tu, 'teststruct') - assert teststruct is not None, "Didn't find teststruct??" - fields = list(teststruct.get_children()) - assert fields[0].spelling == 'A' - assert fields[0].type.kind == TypeKind.CONSTANTARRAY - assert fields[0].type.get_array_element_type() is not None - assert fields[0].type.get_array_element_type().kind == TypeKind.POINTER - assert fields[0].type.get_array_size() == 2 - -def test_equal(): - """Ensure equivalence operators work on Type.""" - source = 'int a; int b; void *v;' - tu = get_tu(source) - - a = get_cursor(tu, 'a') - b = get_cursor(tu, 'b') - v = get_cursor(tu, 'v') - - assert a is not None - assert b is not None - assert v is not None - - assert a.type == b.type - assert a.type != v.type - - assert a.type != None - assert a.type != 'foo' - -def test_type_spelling(): - """Ensure Type.spelling works.""" - tu = get_tu('int c[5]; int i[]; int x; int v[x];') - c = get_cursor(tu, 'c') - i = get_cursor(tu, 'i') - x = get_cursor(tu, 'x') - v = get_cursor(tu, 'v') - assert c is not None - assert i is not None - assert x is not None - assert v is not None - assert c.type.spelling == "int [5]" - assert i.type.spelling == "int []" - assert x.type.spelling == "int" - assert v.type.spelling == "int [x]" - -def test_typekind_spelling(): - """Ensure TypeKind.spelling works.""" - tu = get_tu('int a;') - a = get_cursor(tu, 'a') - - assert a is not None - assert a.type.kind.spelling == 'Int' - -def test_function_argument_types(): - """Ensure that Type.argument_types() works as expected.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - assert f is not None - - args = f.type.argument_types() - assert args is not None - assert len(args) == 2 - - t0 = args[0] - assert t0 is not None - assert t0.kind == TypeKind.INT - - t1 = args[1] - assert t1 is not None - assert t1.kind == TypeKind.INT - - args2 = list(args) - assert len(args2) == 2 - assert t0 == args2[0] - assert t1 == args2[1] - -@raises(TypeError) -def test_argument_types_string_key(): - """Ensure that non-int keys raise a TypeError.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - assert f is not None - - args = f.type.argument_types() - assert len(args) == 2 - - args['foo'] - -@raises(IndexError) -def test_argument_types_negative_index(): - """Ensure that negative indexes on argument_types Raises an IndexError.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - args = f.type.argument_types() - - args[-1] - -@raises(IndexError) -def test_argument_types_overflow_index(): - """Ensure that indexes beyond the length of Type.argument_types() raise.""" - tu = get_tu('void f(int, int);') - f = get_cursor(tu, 'f') - args = f.type.argument_types() - - args[2] - -@raises(Exception) -def test_argument_types_invalid_type(): - """Ensure that obtaining argument_types on a Type without them raises.""" - tu = get_tu('int i;') - i = get_cursor(tu, 'i') - assert i is not None - - i.type.argument_types() - -def test_is_pod(): - """Ensure Type.is_pod() works.""" - tu = get_tu('int i; void f();') - i = get_cursor(tu, 'i') - f = get_cursor(tu, 'f') - - assert i is not None - assert f is not None - - assert i.type.is_pod() - assert not f.type.is_pod() - -def test_function_variadic(): - """Ensure Type.is_function_variadic works.""" - - source =""" -#include <stdarg.h> - -void foo(int a, ...); -void bar(int a, int b); -""" - - tu = get_tu(source) - foo = get_cursor(tu, 'foo') - bar = get_cursor(tu, 'bar') - - assert foo is not None - assert bar is not None - - assert isinstance(foo.type.is_function_variadic(), bool) - assert foo.type.is_function_variadic() - assert not bar.type.is_function_variadic() - -def test_element_type(): - """Ensure Type.element_type works.""" - tu = get_tu('int c[5]; int i[]; int x; int v[x];') - c = get_cursor(tu, 'c') - i = get_cursor(tu, 'i') - v = get_cursor(tu, 'v') - assert c is not None - assert i is not None - assert v is not None - - assert c.type.kind == TypeKind.CONSTANTARRAY - assert c.type.element_type.kind == TypeKind.INT - assert i.type.kind == TypeKind.INCOMPLETEARRAY - assert i.type.element_type.kind == TypeKind.INT - assert v.type.kind == TypeKind.VARIABLEARRAY - assert v.type.element_type.kind == TypeKind.INT - -@raises(Exception) -def test_invalid_element_type(): - """Ensure Type.element_type raises if type doesn't have elements.""" - tu = get_tu('int i;') - i = get_cursor(tu, 'i') - assert i is not None - i.element_type - -def test_element_count(): - """Ensure Type.element_count works.""" - tu = get_tu('int i[5]; int j;') - i = get_cursor(tu, 'i') - j = get_cursor(tu, 'j') - - assert i is not None - assert j is not None - - assert i.type.element_count == 5 - - try: - j.type.element_count - assert False - except: - assert True - -def test_is_volatile_qualified(): - """Ensure Type.is_volatile_qualified works.""" - - tu = get_tu('volatile int i = 4; int j = 2;') - - i = get_cursor(tu, 'i') - j = get_cursor(tu, 'j') - - assert i is not None - assert j is not None - - assert isinstance(i.type.is_volatile_qualified(), bool) - assert i.type.is_volatile_qualified() - assert not j.type.is_volatile_qualified() - -def test_is_restrict_qualified(): - """Ensure Type.is_restrict_qualified works.""" - - tu = get_tu('struct s { void * restrict i; void * j; };') - - i = get_cursor(tu, 'i') - j = get_cursor(tu, 'j') - - assert i is not None - assert j is not None - - assert isinstance(i.type.is_restrict_qualified(), bool) - assert i.type.is_restrict_qualified() - assert not j.type.is_restrict_qualified() - -def test_record_layout(): - """Ensure Cursor.type.get_size, Cursor.type.get_align and - Cursor.type.get_offset works.""" - - source =""" -struct a { - long a1; - long a2:3; - long a3:4; - long long a4; -}; -""" - tries=[(['-target','i386-linux-gnu'],(4,16,0,32,35,64)), - (['-target','nvptx64-unknown-unknown'],(8,24,0,64,67,128)), - (['-target','i386-pc-win32'],(8,16,0,32,35,64)), - (['-target','msp430-none-none'],(2,14,0,32,35,48))] - for flags, values in tries: - align,total,a1,a2,a3,a4 = values - - tu = get_tu(source, flags=flags) - teststruct = get_cursor(tu, 'a') - fields = list(teststruct.get_children()) - - assert teststruct.type.get_align() == align - assert teststruct.type.get_size() == total - assert teststruct.type.get_offset(fields[0].spelling) == a1 - assert teststruct.type.get_offset(fields[1].spelling) == a2 - assert teststruct.type.get_offset(fields[2].spelling) == a3 - assert teststruct.type.get_offset(fields[3].spelling) == a4 - assert fields[0].is_bitfield() == False - assert fields[1].is_bitfield() == True - assert fields[1].get_bitfield_width() == 3 - assert fields[2].is_bitfield() == True - assert fields[2].get_bitfield_width() == 4 - assert fields[3].is_bitfield() == False - -def test_offset(): - """Ensure Cursor.get_record_field_offset works in anonymous records""" - source=""" -struct Test { - struct { - int bariton; - union { - int foo; - }; - }; - int bar; -};""" - tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64)), - (['-target','nvptx64-unknown-unknown'],(8,24,0,32,64)), - (['-target','i386-pc-win32'],(8,16,0,32,64)), - (['-target','msp430-none-none'],(2,14,0,32,64))] - for flags, values in tries: - align,total,bariton,foo,bar = values - tu = get_tu(source) - teststruct = get_cursor(tu, 'Test') - fields = list(teststruct.get_children()) - assert teststruct.type.get_offset("bariton") == bariton - assert teststruct.type.get_offset("foo") == foo - assert teststruct.type.get_offset("bar") == bar - - -def test_decay(): - """Ensure decayed types are handled as the original type""" - - tu = get_tu("void foo(int a[]);") - foo = get_cursor(tu, 'foo') - a = foo.type.argument_types()[0] - - assert a.kind == TypeKind.INCOMPLETEARRAY - assert a.element_type.kind == TypeKind.INT - assert a.get_canonical().kind == TypeKind.INCOMPLETEARRAY diff --git a/bindings/python/tests/cindex/util.py b/bindings/python/tests/cindex/util.py deleted file mode 100644 index 8614b02ad258..000000000000 --- a/bindings/python/tests/cindex/util.py +++ /dev/null @@ -1,93 +0,0 @@ -# This file provides common utility functions for the test suite. - -from clang.cindex import Cursor -from clang.cindex import TranslationUnit - -def get_tu(source, lang='c', all_warnings=False, flags=[]): - """Obtain a translation unit from source and language. - - By default, the translation unit is created from source file "t.<ext>" - where <ext> is the default file extension for the specified language. By - default it is C, so "t.c" is the default file name. - - Supported languages are {c, cpp, objc}. - - all_warnings is a convenience argument to enable all compiler warnings. - """ - args = list(flags) - name = 't.c' - if lang == 'cpp': - name = 't.cpp' - args.append('-std=c++11') - elif lang == 'objc': - name = 't.m' - elif lang != 'c': - raise Exception('Unknown language: %s' % lang) - - if all_warnings: - args += ['-Wall', '-Wextra'] - - return TranslationUnit.from_source(name, args, unsaved_files=[(name, - source)]) - -def get_cursor(source, spelling): - """Obtain a cursor from a source object. - - This provides a convenient search mechanism to find a cursor with specific - spelling within a source. The first argument can be either a - TranslationUnit or Cursor instance. - - If the cursor is not found, None is returned. - """ - children = [] - if isinstance(source, Cursor): - children = source.get_children() - else: - # Assume TU - children = source.cursor.get_children() - - for cursor in children: - if cursor.spelling == spelling: - return cursor - - # Recurse into children. - result = get_cursor(cursor, spelling) - if result is not None: - return result - - return None - -def get_cursors(source, spelling): - """Obtain all cursors from a source object with a specific spelling. - - This provides a convenient search mechanism to find all cursors with specific - spelling within a source. The first argument can be either a - TranslationUnit or Cursor instance. - - If no cursors are found, an empty list is returned. - """ - cursors = [] - children = [] - if isinstance(source, Cursor): - children = source.get_children() - else: - # Assume TU - children = source.cursor.get_children() - - for cursor in children: - if cursor.spelling == spelling: - cursors.append(cursor) - - # Recurse into children. - cursors.extend(get_cursors(cursor, spelling)) - - return cursors - - - - -__all__ = [ - 'get_cursor', - 'get_cursors', - 'get_tu', -] |