cindex.py revision 8be80e1e6effd5a333bc70e7f030dc9397d0554e
1#===- cindex.py - Python Indexing Library Bindings -----------*- python -*--===#
2#
3#                     The LLVM Compiler Infrastructure
4#
5# This file is distributed under the University of Illinois Open Source
6# License. See LICENSE.TXT for details.
7#
8#===------------------------------------------------------------------------===#
9
10r"""
11Clang Indexing Library Bindings
12===============================
13
14This module provides an interface to the Clang indexing library. It is a
15low-level interface to the indexing library which attempts to match the Clang
16API directly while also being "pythonic". Notable differences from the C API
17are:
18
19 * string results are returned as Python strings, not CXString objects.
20
21 * null cursors are translated to None.
22
23 * access to child cursors is done via iteration, not visitation.
24
25The major indexing objects are:
26
27  Index
28
29    The top-level object which manages some global library state.
30
31  TranslationUnit
32
33    High-level object encapsulating the AST for a single translation unit. These
34    can be loaded from .ast files or parsed on the fly.
35
36  Cursor
37
38    Generic object for representing a node in the AST.
39
40  SourceRange, SourceLocation, and File
41
42    Objects representing information about the input source.
43
44Most object information is exposed using properties, when the underlying API
45call is efficient.
46"""
47
48# TODO
49# ====
50#
51# o API support for invalid translation units. Currently we can't even get the
52#   diagnostics on failure because they refer to locations in an object that
53#   will have been invalidated.
54#
55# o fix memory management issues (currently client must hold on to index and
56#   translation unit, or risk crashes).
57#
58# o expose code completion APIs.
59#
60# o cleanup ctypes wrapping, would be nice to separate the ctypes details more
61#   clearly, and hide from the external interface (i.e., help(cindex)).
62#
63# o implement additional SourceLocation, SourceRange, and File methods.
64
65from ctypes import *
66
67def get_cindex_library():
68    # FIXME: It's probably not the case that the library is actually found in
69    # this location. We need a better system of identifying and loading the
70    # CIndex library. It could be on path or elsewhere, or versioned, etc.
71    import platform
72    name = platform.system()
73    if name == 'Darwin':
74        return cdll.LoadLibrary('libclang.dylib')
75    elif name == 'Windows':
76        return cdll.LoadLibrary('libclang.dll')
77    else:
78        return cdll.LoadLibrary('libclang.so')
79
80# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
81# object. This is a problem, because it means that from_parameter will see an
82# integer and pass the wrong value on platforms where int != void*. Work around
83# this by marshalling object arguments as void**.
84c_object_p = POINTER(c_void_p)
85
86lib = get_cindex_library()
87
88### Structures and Utility Classes ###
89
90class _CXString(Structure):
91    """Helper for transforming CXString results."""
92
93    _fields_ = [("spelling", c_char_p), ("free", c_int)]
94
95    def __del__(self):
96        _CXString_dispose(self)
97
98    @staticmethod
99    def from_result(res, fn, args):
100        assert isinstance(res, _CXString)
101        return _CXString_getCString(res)
102
103class SourceLocation(Structure):
104    """
105    A SourceLocation represents a particular location within a source file.
106    """
107    _fields_ = [("ptr_data", c_void_p * 2), ("int_data", c_uint)]
108    _data = None
109
110    def _get_instantiation(self):
111        if self._data is None:
112            f, l, c, o = c_object_p(), c_uint(), c_uint(), c_uint()
113            SourceLocation_loc(self, byref(f), byref(l), byref(c), byref(o))
114            f = File(f) if f else None
115            self._data = (f, int(l.value), int(c.value), int(c.value))
116        return self._data
117
118    @property
119    def file(self):
120        """Get the file represented by this source location."""
121        return self._get_instantiation()[0]
122
123    @property
124    def line(self):
125        """Get the line represented by this source location."""
126        return self._get_instantiation()[1]
127
128    @property
129    def column(self):
130        """Get the column represented by this source location."""
131        return self._get_instantiation()[2]
132
133    @property
134    def offset(self):
135        """Get the file offset represented by this source location."""
136        return self._get_instantiation()[3]
137
138    def __repr__(self):
139        return "<SourceLocation file %r, line %r, column %r>" % (
140            self.file.name if self.file else None, self.line, self.column)
141
142class SourceRange(Structure):
143    """
144    A SourceRange describes a range of source locations within the source
145    code.
146    """
147    _fields_ = [
148        ("ptr_data", c_void_p * 2),
149        ("begin_int_data", c_uint),
150        ("end_int_data", c_uint)]
151
152    # FIXME: Eliminate this and make normal constructor? Requires hiding ctypes
153    # object.
154    @staticmethod
155    def from_locations(start, end):
156        return SourceRange_getRange(start, end)
157
158    @property
159    def start(self):
160        """
161        Return a SourceLocation representing the first character within a
162        source range.
163        """
164        return SourceRange_start(self)
165
166    @property
167    def end(self):
168        """
169        Return a SourceLocation representing the last character within a
170        source range.
171        """
172        return SourceRange_end(self)
173
174    def __repr__(self):
175        return "<SourceRange start %r, end %r>" % (self.start, self.end)
176
177class Diagnostic(object):
178    """
179    A Diagnostic is a single instance of a Clang diagnostic. It includes the
180    diagnostic severity, the message, the location the diagnostic occurred, as
181    well as additional source ranges and associated fix-it hints.
182    """
183
184    Ignored = 0
185    Note    = 1
186    Warning = 2
187    Error   = 3
188    Fatal   = 4
189
190    def __init__(self, ptr):
191        self.ptr = ptr
192
193    def __del__(self):
194        _clang_disposeDiagnostic(self)
195
196    @property
197    def severity(self):
198        return _clang_getDiagnosticSeverity(self)
199
200    @property
201    def location(self):
202        return _clang_getDiagnosticLocation(self)
203
204    @property
205    def spelling(self):
206        return _clang_getDiagnosticSpelling(self)
207
208    @property
209    def ranges(self):
210        class RangeIterator:
211            def __init__(self, diag):
212                self.diag = diag
213
214            def __len__(self):
215                return int(_clang_getDiagnosticNumRanges(self.diag))
216
217            def __getitem__(self, key):
218		if (key >= len(self)):
219			raise IndexError
220                return _clang_getDiagnosticRange(self.diag, key)
221
222        return RangeIterator(self)
223
224    @property
225    def fixits(self):
226        class FixItIterator:
227            def __init__(self, diag):
228                self.diag = diag
229
230            def __len__(self):
231                return int(_clang_getDiagnosticNumFixIts(self.diag))
232
233            def __getitem__(self, key):
234                range = SourceRange()
235                value = _clang_getDiagnosticFixIt(self.diag, key, byref(range))
236                if len(value) == 0:
237                    raise IndexError
238
239                return FixIt(range, value)
240
241        return FixItIterator(self)
242
243    def __repr__(self):
244        return "<Diagnostic severity %r, location %r, spelling %r>" % (
245            self.severity, self.location, self.spelling)
246
247    def from_param(self):
248      return self.ptr
249
250class FixIt(object):
251    """
252    A FixIt represents a transformation to be applied to the source to
253    "fix-it". The fix-it shouldbe applied by replacing the given source range
254    with the given value.
255    """
256
257    def __init__(self, range, value):
258        self.range = range
259        self.value = value
260
261    def __repr__(self):
262        return "<FixIt range %r, value %r>" % (self.range, self.value)
263
264### Cursor Kinds ###
265
266class CursorKind(object):
267    """
268    A CursorKind describes the kind of entity that a cursor points to.
269    """
270
271    # The unique kind objects, indexed by id.
272    _kinds = []
273    _name_map = None
274
275    def __init__(self, value):
276        if value >= len(CursorKind._kinds):
277            CursorKind._kinds += [None] * (value - len(CursorKind._kinds) + 1)
278        if CursorKind._kinds[value] is not None:
279            raise ValueError,'CursorKind already loaded'
280        self.value = value
281        CursorKind._kinds[value] = self
282        CursorKind._name_map = None
283
284    def from_param(self):
285        return self.value
286
287    @property
288    def name(self):
289        """Get the enumeration name of this cursor kind."""
290        if self._name_map is None:
291            self._name_map = {}
292            for key,value in CursorKind.__dict__.items():
293                if isinstance(value,CursorKind):
294                    self._name_map[value] = key
295        return self._name_map[self]
296
297    @staticmethod
298    def from_id(id):
299        if id >= len(CursorKind._kinds) or CursorKind._kinds[id] is None:
300            raise ValueError,'Unknown cursor kind'
301        return CursorKind._kinds[id]
302
303    @staticmethod
304    def get_all_kinds():
305        """Return all CursorKind enumeration instances."""
306        return filter(None, CursorKind._kinds)
307
308    def is_declaration(self):
309        """Test if this is a declaration kind."""
310        return CursorKind_is_decl(self)
311
312    def is_reference(self):
313        """Test if this is a reference kind."""
314        return CursorKind_is_ref(self)
315
316    def is_expression(self):
317        """Test if this is an expression kind."""
318        return CursorKind_is_expr(self)
319
320    def is_statement(self):
321        """Test if this is a statement kind."""
322        return CursorKind_is_stmt(self)
323
324    def is_attribute(self):
325        """Test if this is an attribute kind."""
326        return CursorKind_is_attribute(self)
327
328    def is_invalid(self):
329        """Test if this is an invalid kind."""
330        return CursorKind_is_inv(self)
331
332    def __repr__(self):
333        return 'CursorKind.%s' % (self.name,)
334
335# FIXME: Is there a nicer way to expose this enumeration? We could potentially
336# represent the nested structure, or even build a class hierarchy. The main
337# things we want for sure are (a) simple external access to kinds, (b) a place
338# to hang a description and name, (c) easy to keep in sync with Index.h.
339
340###
341# Declaration Kinds
342
343# A declaration whose specific kind is not exposed via this interface.
344#
345# Unexposed declarations have the same operations as any other kind of
346# declaration; one can extract their location information, spelling, find their
347# definitions, etc. However, the specific kind of the declaration is not
348# reported.
349CursorKind.UNEXPOSED_DECL = CursorKind(1)
350
351# A C or C++ struct.
352CursorKind.STRUCT_DECL = CursorKind(2)
353
354# A C or C++ union.
355CursorKind.UNION_DECL = CursorKind(3)
356
357# A C++ class.
358CursorKind.CLASS_DECL = CursorKind(4)
359
360# An enumeration.
361CursorKind.ENUM_DECL = CursorKind(5)
362
363# A field (in C) or non-static data member (in C++) in a struct, union, or C++
364# class.
365CursorKind.FIELD_DECL = CursorKind(6)
366
367# An enumerator constant.
368CursorKind.ENUM_CONSTANT_DECL = CursorKind(7)
369
370# A function.
371CursorKind.FUNCTION_DECL = CursorKind(8)
372
373# A variable.
374CursorKind.VAR_DECL = CursorKind(9)
375
376# A function or method parameter.
377CursorKind.PARM_DECL = CursorKind(10)
378
379# An Objective-C @interface.
380CursorKind.OBJC_INTERFACE_DECL = CursorKind(11)
381
382# An Objective-C @interface for a category.
383CursorKind.OBJC_CATEGORY_DECL = CursorKind(12)
384
385# An Objective-C @protocol declaration.
386CursorKind.OBJC_PROTOCOL_DECL = CursorKind(13)
387
388# An Objective-C @property declaration.
389CursorKind.OBJC_PROPERTY_DECL = CursorKind(14)
390
391# An Objective-C instance variable.
392CursorKind.OBJC_IVAR_DECL = CursorKind(15)
393
394# An Objective-C instance method.
395CursorKind.OBJC_INSTANCE_METHOD_DECL = CursorKind(16)
396
397# An Objective-C class method.
398CursorKind.OBJC_CLASS_METHOD_DECL = CursorKind(17)
399
400# An Objective-C @implementation.
401CursorKind.OBJC_IMPLEMENTATION_DECL = CursorKind(18)
402
403# An Objective-C @implementation for a category.
404CursorKind.OBJC_CATEGORY_IMPL_DECL = CursorKind(19)
405
406# A typedef.
407CursorKind.TYPEDEF_DECL = CursorKind(20)
408
409# A C++ class method.
410CursorKind.CXX_METHOD = CursorKind(21)
411
412# A C++ namespace.
413CursorKind.NAMESPACE = CursorKind(22)
414
415# A linkage specification, e.g. 'extern "C"'.
416CursorKind.LINKAGE_SPEC = CursorKind(23)
417
418# A C++ constructor.
419CursorKind.CONSTRUCTOR = CursorKind(24)
420
421# A C++ destructor.
422CursorKind.DESTRUCTOR = CursorKind(25)
423
424# A C++ conversion function.
425CursorKind.CONVERSION_FUNCTION = CursorKind(26)
426
427# A C++ template type parameter
428CursorKind.TEMPLATE_TYPE_PARAMETER = CursorKind(27)
429
430# A C++ non-type template paramater.
431CursorKind.TEMPLATE_NON_TYPE_PARAMETER = CursorKind(28)
432
433# A C++ template template parameter.
434CursorKind.TEMPLATE_TEMPLATE_PARAMTER = CursorKind(29)
435
436# A C++ function template.
437CursorKind.FUNCTION_TEMPLATE = CursorKind(30)
438
439# A C++ class template.
440CursorKind.CLASS_TEMPLATE = CursorKind(31)
441
442# A C++ class template partial specialization.
443CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION = CursorKind(32)
444
445# A C++ namespace alias declaration.
446CursorKind.NAMESPACE_ALIAS = CursorKind(33)
447
448# A C++ using directive
449CursorKind.USING_DIRECTIVE = CursorKind(34)
450
451# A C++ using declaration
452CursorKind.USING_DECLARATION = CursorKind(35)
453
454###
455# Reference Kinds
456
457CursorKind.OBJC_SUPER_CLASS_REF = CursorKind(40)
458CursorKind.OBJC_PROTOCOL_REF = CursorKind(41)
459CursorKind.OBJC_CLASS_REF = CursorKind(42)
460
461# A reference to a type declaration.
462#
463# A type reference occurs anywhere where a type is named but not
464# declared. For example, given:
465#   typedef unsigned size_type;
466#   size_type size;
467#
468# The typedef is a declaration of size_type (CXCursor_TypedefDecl),
469# while the type of the variable "size" is referenced. The cursor
470# referenced by the type of size is the typedef for size_type.
471CursorKind.TYPE_REF = CursorKind(43)
472CursorKind.CXX_BASE_SPECIFIER = CursorKind(44)
473
474# A reference to a class template, function template, template
475# template parameter, or class template partial specialization.
476CursorKind.TEMPLATE_REF = CursorKind(45)
477
478# A reference to a namespace or namepsace alias.
479CursorKind.NAMESPACE_REF = CursorKind(46)
480
481# A reference to a member of a struct, union, or class that occurs in
482# some non-expression context, e.g., a designated initializer.
483CursorKind.MEMBER_REF = CursorKind(47)
484
485# A reference to a labeled statement.
486CursorKind.LABEL_REF = CursorKind(48)
487
488# A reference toa a set of overloaded functions or function templates
489# that has not yet been resolved to a specific function or function template.
490CursorKind.OVERLOADED_DECL_REF = CursorKind(49)
491
492###
493# Invalid/Error Kinds
494
495CursorKind.INVALID_FILE = CursorKind(70)
496CursorKind.NO_DECL_FOUND = CursorKind(71)
497CursorKind.NOT_IMPLEMENTED = CursorKind(72)
498CursorKind.INVALID_CODE = CursorKind(73)
499
500###
501# Expression Kinds
502
503# An expression whose specific kind is not exposed via this interface.
504#
505# Unexposed expressions have the same operations as any other kind of
506# expression; one can extract their location information, spelling, children,
507# etc. However, the specific kind of the expression is not reported.
508CursorKind.UNEXPOSED_EXPR = CursorKind(100)
509
510# An expression that refers to some value declaration, such as a function,
511# varible, or enumerator.
512CursorKind.DECL_REF_EXPR = CursorKind(101)
513
514# An expression that refers to a member of a struct, union, class, Objective-C
515# class, etc.
516CursorKind.MEMBER_REF_EXPR = CursorKind(102)
517
518# An expression that calls a function.
519CursorKind.CALL_EXPR = CursorKind(103)
520
521# An expression that sends a message to an Objective-C object or class.
522CursorKind.OBJC_MESSAGE_EXPR = CursorKind(104)
523
524# An expression that represents a block literal.
525CursorKind.BLOCK_EXPR = CursorKind(105)
526
527# A statement whose specific kind is not exposed via this interface.
528#
529# Unexposed statements have the same operations as any other kind of statement;
530# one can extract their location information, spelling, children, etc. However,
531# the specific kind of the statement is not reported.
532CursorKind.UNEXPOSED_STMT = CursorKind(200)
533
534# A labelled statement in a function.
535CursorKind.LABEL_STMT = CursorKind(201)
536
537
538###
539# Other Kinds
540
541# Cursor that represents the translation unit itself.
542#
543# The translation unit cursor exists primarily to act as the root cursor for
544# traversing the contents of a translation unit.
545CursorKind.TRANSLATION_UNIT = CursorKind(300)
546
547###
548# Attributes
549
550# An attribute whoe specific kind is note exposed via this interface
551CursorKind.UNEXPOSED_ATTR = CursorKind(400)
552
553CursorKind.IB_ACTION_ATTR = CursorKind(401)
554CursorKind.IB_OUTLET_ATTR = CursorKind(402)
555CursorKind.IB_OUTLET_COLLECTION_ATTR = CursorKind(403)
556
557###
558# Preprocessing
559CursorKind.PREPROCESSING_DIRECTIVE = CursorKind(500)
560CursorKind.MACRO_DEFINITION = CursorKind(501)
561CursorKind.MACRO_INSTANTIATION = CursorKind(502)
562CursorKind.INCLUSION_DIRECTIVE = CursorKind(503)
563
564### Cursors ###
565
566class Cursor(Structure):
567    """
568    The Cursor class represents a reference to an element within the AST. It
569    acts as a kind of iterator.
570    """
571    _fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)]
572
573    def __eq__(self, other):
574        return Cursor_eq(self, other)
575
576    def __ne__(self, other):
577        return not Cursor_eq(self, other)
578
579    def is_definition(self):
580        """
581        Returns true if the declaration pointed at by the cursor is also a
582        definition of that entity.
583        """
584        return Cursor_is_def(self)
585
586    def get_definition(self):
587        """
588        If the cursor is a reference to a declaration or a declaration of
589        some entity, return a cursor that points to the definition of that
590        entity.
591        """
592        # TODO: Should probably check that this is either a reference or
593        # declaration prior to issuing the lookup.
594        return Cursor_def(self)
595
596    def get_usr(self):
597        """Return the Unified Symbol Resultion (USR) for the entity referenced
598        by the given cursor (or None).
599
600        A Unified Symbol Resolution (USR) is a string that identifies a
601        particular entity (function, class, variable, etc.) within a
602        program. USRs can be compared across translation units to determine,
603        e.g., when references in one translation refer to an entity defined in
604        another translation unit."""
605        return Cursor_usr(self)
606
607    @property
608    def kind(self):
609        """Return the kind of this cursor."""
610        return CursorKind.from_id(self._kind_id)
611
612    @property
613    def spelling(self):
614        """Return the spelling of the entity pointed at by the cursor."""
615        if not self.kind.is_declaration():
616            # FIXME: clang_getCursorSpelling should be fixed to not assert on
617            # this, for consistency with clang_getCursorUSR.
618            return None
619        return Cursor_spelling(self)
620
621    @property
622    def location(self):
623        """
624        Return the source location (the starting character) of the entity
625        pointed at by the cursor.
626        """
627        return Cursor_loc(self)
628
629    @property
630    def extent(self):
631        """
632        Return the source range (the range of text) occupied by the entity
633        pointed at by the cursor.
634        """
635        return Cursor_extent(self)
636
637    def get_children(self):
638        """Return an iterator for accessing the children of this cursor."""
639
640        # FIXME: Expose iteration from CIndex, PR6125.
641        def visitor(child, parent, children):
642            # FIXME: Document this assertion in API.
643            # FIXME: There should just be an isNull method.
644            assert child != Cursor_null()
645            children.append(child)
646            return 1 # continue
647        children = []
648        Cursor_visit(self, Cursor_visit_callback(visitor), children)
649        return iter(children)
650
651    @staticmethod
652    def from_result(res, fn, args):
653        assert isinstance(res, Cursor)
654        # FIXME: There should just be an isNull method.
655        if res == Cursor_null():
656            return None
657        return res
658
659## CIndex Objects ##
660
661# CIndex objects (derived from ClangObject) are essentially lightweight
662# wrappers attached to some underlying object, which is exposed via CIndex as
663# a void*.
664
665class ClangObject(object):
666    """
667    A helper for Clang objects. This class helps act as an intermediary for
668    the ctypes library and the Clang CIndex library.
669    """
670    def __init__(self, obj):
671        assert isinstance(obj, c_object_p) and obj
672        self.obj = self._as_parameter_ = obj
673
674    def from_param(self):
675        return self._as_parameter_
676
677
678class _CXUnsavedFile(Structure):
679    """Helper for passing unsaved file arguments."""
680    _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)]
681
682## Diagnostic Conversion ##
683
684_clang_getNumDiagnostics = lib.clang_getNumDiagnostics
685_clang_getNumDiagnostics.argtypes = [c_object_p]
686_clang_getNumDiagnostics.restype = c_uint
687
688_clang_getDiagnostic = lib.clang_getDiagnostic
689_clang_getDiagnostic.argtypes = [c_object_p, c_uint]
690_clang_getDiagnostic.restype = c_object_p
691
692_clang_disposeDiagnostic = lib.clang_disposeDiagnostic
693_clang_disposeDiagnostic.argtypes = [Diagnostic]
694
695_clang_getDiagnosticSeverity = lib.clang_getDiagnosticSeverity
696_clang_getDiagnosticSeverity.argtypes = [Diagnostic]
697_clang_getDiagnosticSeverity.restype = c_int
698
699_clang_getDiagnosticLocation = lib.clang_getDiagnosticLocation
700_clang_getDiagnosticLocation.argtypes = [Diagnostic]
701_clang_getDiagnosticLocation.restype = SourceLocation
702
703_clang_getDiagnosticSpelling = lib.clang_getDiagnosticSpelling
704_clang_getDiagnosticSpelling.argtypes = [Diagnostic]
705_clang_getDiagnosticSpelling.restype = _CXString
706_clang_getDiagnosticSpelling.errcheck = _CXString.from_result
707
708_clang_getDiagnosticNumRanges = lib.clang_getDiagnosticNumRanges
709_clang_getDiagnosticNumRanges.argtypes = [Diagnostic]
710_clang_getDiagnosticNumRanges.restype = c_uint
711
712_clang_getDiagnosticRange = lib.clang_getDiagnosticRange
713_clang_getDiagnosticRange.argtypes = [Diagnostic, c_uint]
714_clang_getDiagnosticRange.restype = SourceRange
715
716_clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts
717_clang_getDiagnosticNumFixIts.argtypes = [Diagnostic]
718_clang_getDiagnosticNumFixIts.restype = c_uint
719
720_clang_getDiagnosticFixIt = lib.clang_getDiagnosticFixIt
721_clang_getDiagnosticFixIt.argtypes = [Diagnostic, c_uint, POINTER(SourceRange)]
722_clang_getDiagnosticFixIt.restype = _CXString
723_clang_getDiagnosticFixIt.errcheck = _CXString.from_result
724
725###
726
727class CompletionChunk:
728    class Kind:
729        def __init__(self, name):
730            self.name = name
731
732        def __str__(self):
733            return self.name
734
735        def __repr__(self):
736            return "<ChunkKind: %s>" % self
737
738    def __init__(self, completionString, key):
739        self.cs = completionString
740        self.key = key
741
742    def __repr__(self):
743        return "{'" + self.spelling + "', " + str(self.kind) + "}"
744
745    @property
746    def spelling(self):
747        return _clang_getCompletionChunkText(self.cs, self.key).spelling
748
749    @property
750    def kind(self):
751        res = _clang_getCompletionChunkKind(self.cs, self.key)
752        return completionChunkKindMap[res]
753
754    @property
755    def string(self):
756        res = _clang_getCompletionChunkCompletionString(self.cs, self.key)
757
758        if (res):
759          return CompletionString(res)
760        else:
761          None
762
763    def isKindOptional(self):
764      return self.kind == completionChunkKindMap[0]
765
766    def isKindTypedText(self):
767      return self.kind == completionChunkKindMap[1]
768
769    def isKindPlaceHolder(self):
770      return self.kind == completionChunkKindMap[3]
771
772    def isKindInformative(self):
773      return self.kind == completionChunkKindMap[4]
774
775    def isKindResultType(self):
776      return self.kind == completionChunkKindMap[15]
777
778completionChunkKindMap = {
779            0: CompletionChunk.Kind("Optional"),
780            1: CompletionChunk.Kind("TypedText"),
781            2: CompletionChunk.Kind("Text"),
782            3: CompletionChunk.Kind("Placeholder"),
783            4: CompletionChunk.Kind("Informative"),
784            5: CompletionChunk.Kind("CurrentParameter"),
785            6: CompletionChunk.Kind("LeftParen"),
786            7: CompletionChunk.Kind("RightParen"),
787            8: CompletionChunk.Kind("LeftBracket"),
788            9: CompletionChunk.Kind("RightBracket"),
789            10: CompletionChunk.Kind("LeftBrace"),
790            11: CompletionChunk.Kind("RightBrace"),
791            12: CompletionChunk.Kind("LeftAngle"),
792            13: CompletionChunk.Kind("RightAngle"),
793            14: CompletionChunk.Kind("Comma"),
794            15: CompletionChunk.Kind("ResultType"),
795            16: CompletionChunk.Kind("Colon"),
796            17: CompletionChunk.Kind("SemiColon"),
797            18: CompletionChunk.Kind("Equal"),
798            19: CompletionChunk.Kind("HorizontalSpace"),
799            20: CompletionChunk.Kind("VerticalSpace")}
800
801class CompletionString(ClangObject):
802    class Availability:
803        def __init__(self, name):
804            self.name = name
805
806        def __str__(self):
807            return self.name
808
809        def __repr__(self):
810            return "<Availability: %s>" % self
811
812    def __len__(self):
813        return _clang_getNumCompletionChunks(self.obj)
814
815    def __getitem__(self, key):
816        if len(self) <= key:
817            raise IndexError
818        return CompletionChunk(self.obj, key)
819
820    @property
821    def priority(self):
822        return _clang_getCompletionPriority(self.obj)
823
824    @property
825    def availability(self):
826        res = _clang_getCompletionAvailability(self.obj)
827        return availabilityKinds[res]
828
829    def __repr__(self):
830        return " | ".join([str(a) for a in self]) \
831               + " || Priority: " + str(self.priority) \
832               + " || Availability: " + str(self.availability)
833
834availabilityKinds = {
835            0: CompletionChunk.Kind("Available"),
836            1: CompletionChunk.Kind("Deprecated"),
837            2: CompletionChunk.Kind("NotAvailable")}
838
839class CodeCompletionResult(Structure):
840    _fields_ = [('cursorKind', c_int), ('completionString', c_object_p)]
841
842    def __repr__(self):
843        return str(CompletionString(self.completionString))
844
845    @property
846    def kind(self):
847        return CursorKind.from_id(self.cursorKind)
848
849    @property
850    def string(self):
851        return CompletionString(self.completionString)
852
853class CCRStructure(Structure):
854    _fields_ = [('results', POINTER(CodeCompletionResult)),
855                ('numResults', c_int)]
856
857    def __len__(self):
858        return self.numResults
859
860    def __getitem__(self, key):
861        if len(self) <= key:
862            raise IndexError
863
864        return self.results[key]
865
866class CodeCompletionResults(ClangObject):
867    def __init__(self, ptr):
868        assert isinstance(ptr, POINTER(CCRStructure)) and ptr
869        self.ptr = self._as_parameter_ = ptr
870
871    def from_param(self):
872        return self._as_parameter_
873
874    def __del__(self):
875        CodeCompletionResults_dispose(self)
876
877    @property
878    def results(self):
879        return self.ptr.contents
880
881    @property
882    def diagnostics(self):
883        class DiagnosticsItr:
884            def __init__(self, ccr):
885                self.ccr= ccr
886
887            def __len__(self):
888                return int(_clang_codeCompleteGetNumDiagnostics(self.ccr))
889
890            def __getitem__(self, key):
891                return _clang_codeCompleteGetDiagnostic(self.ccr, key)
892
893        return DiagnosticsItr(self)
894
895
896class Index(ClangObject):
897    """
898    The Index type provides the primary interface to the Clang CIndex library,
899    primarily by providing an interface for reading and parsing translation
900    units.
901    """
902
903    @staticmethod
904    def create(excludeDecls=False):
905        """
906        Create a new Index.
907        Parameters:
908        excludeDecls -- Exclude local declarations from translation units.
909        """
910        return Index(Index_create(excludeDecls, 0))
911
912    def __del__(self):
913        Index_dispose(self)
914
915    def read(self, path):
916        """Load the translation unit from the given AST file."""
917        ptr = TranslationUnit_read(self, path)
918        return TranslationUnit(ptr) if ptr else None
919
920    def parse(self, path, args = [], unsaved_files = [], options = 0):
921        """
922        Load the translation unit from the given source code file by running
923        clang and generating the AST before loading. Additional command line
924        parameters can be passed to clang via the args parameter.
925
926        In-memory contents for files can be provided by passing a list of pairs
927        to as unsaved_files, the first item should be the filenames to be mapped
928        and the second should be the contents to be substituted for the
929        file. The contents may be passed as strings or file objects.
930        """
931        arg_array = 0
932        if len(args):
933            arg_array = (c_char_p * len(args))(* args)
934        unsaved_files_array = 0
935        if len(unsaved_files):
936            unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
937            for i,(name,value) in enumerate(unsaved_files):
938                if not isinstance(value, str):
939                    # FIXME: It would be great to support an efficient version
940                    # of this, one day.
941                    value = value.read()
942                    print value
943                if not isinstance(value, str):
944                    raise TypeError,'Unexpected unsaved file contents.'
945                unsaved_files_array[i].name = name
946                unsaved_files_array[i].contents = value
947                unsaved_files_array[i].length = len(value)
948        ptr = TranslationUnit_parse(self, path, arg_array, len(args),
949                                    unsaved_files_array, len(unsaved_files),
950                                    options)
951        return TranslationUnit(ptr) if ptr else None
952
953
954class TranslationUnit(ClangObject):
955    """
956    The TranslationUnit class represents a source code translation unit and
957    provides read-only access to its top-level declarations.
958    """
959
960    def __init__(self, ptr):
961        ClangObject.__init__(self, ptr)
962
963    def __del__(self):
964        TranslationUnit_dispose(self)
965
966    @property
967    def cursor(self):
968        """Retrieve the cursor that represents the given translation unit."""
969        return TranslationUnit_cursor(self)
970
971    @property
972    def spelling(self):
973        """Get the original translation unit source file name."""
974        return TranslationUnit_spelling(self)
975
976    def get_includes(self):
977        """
978        Return an iterable sequence of FileInclusion objects that describe the
979        sequence of inclusions in a translation unit. The first object in
980        this sequence is always the input file. Note that this method will not
981        recursively iterate over header files included through precompiled
982        headers.
983        """
984        def visitor(fobj, lptr, depth, includes):
985            if depth > 0:
986                loc = lptr.contents
987                includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
988
989        # Automatically adapt CIndex/ctype pointers to python objects
990        includes = []
991        TranslationUnit_includes(self,
992                                 TranslationUnit_includes_callback(visitor),
993                                 includes)
994        return iter(includes)
995
996    @property
997    def diagnostics(self):
998        """
999        Return an iterable (and indexable) object containing the diagnostics.
1000        """
1001        class DiagIterator:
1002            def __init__(self, tu):
1003                self.tu = tu
1004
1005            def __len__(self):
1006                return int(_clang_getNumDiagnostics(self.tu))
1007
1008            def __getitem__(self, key):
1009                diag = _clang_getDiagnostic(self.tu, key)
1010                if not diag:
1011                    raise IndexError
1012                return Diagnostic(diag)
1013
1014        return DiagIterator(self)
1015
1016    def reparse(self, unsaved_files = [], options = 0):
1017        """
1018        Reparse an already parsed translation unit.
1019
1020        In-memory contents for files can be provided by passing a list of pairs
1021        as unsaved_files, the first items should be the filenames to be mapped
1022        and the second should be the contents to be substituted for the
1023        file. The contents may be passed as strings or file objects.
1024        """
1025        unsaved_files_array = 0
1026        if len(unsaved_files):
1027            unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
1028            for i,(name,value) in enumerate(unsaved_files):
1029                if not isinstance(value, str):
1030                    # FIXME: It would be great to support an efficient version
1031                    # of this, one day.
1032                    value = value.read()
1033                    print value
1034                if not isinstance(value, str):
1035                    raise TypeError,'Unexpected unsaved file contents.'
1036                unsaved_files_array[i].name = name
1037                unsaved_files_array[i].contents = value
1038                unsaved_files_array[i].length = len(value)
1039        ptr = TranslationUnit_reparse(self, len(unsaved_files),
1040                                      unsaved_files_array,
1041                                      options)
1042    def codeComplete(self, path, line, column, unsaved_files = [], options = 0):
1043        """
1044        Code complete in this translation unit.
1045
1046        In-memory contents for files can be provided by passing a list of pairs
1047        as unsaved_files, the first items should be the filenames to be mapped
1048        and the second should be the contents to be substituted for the
1049        file. The contents may be passed as strings or file objects.
1050        """
1051        unsaved_files_array = 0
1052        if len(unsaved_files):
1053            unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
1054            for i,(name,value) in enumerate(unsaved_files):
1055                if not isinstance(value, str):
1056                    # FIXME: It would be great to support an efficient version
1057                    # of this, one day.
1058                    value = value.read()
1059                    print value
1060                if not isinstance(value, str):
1061                    raise TypeError,'Unexpected unsaved file contents.'
1062                unsaved_files_array[i].name = name
1063                unsaved_files_array[i].contents = value
1064                unsaved_files_array[i].length = len(value)
1065        ptr = TranslationUnit_codeComplete(self, path,
1066                                           line, column,
1067                                           unsaved_files_array,
1068                                           len(unsaved_files),
1069                                           options)
1070        return CodeCompletionResults(ptr) if ptr else None
1071
1072
1073class File(ClangObject):
1074    """
1075    The File class represents a particular source file that is part of a
1076    translation unit.
1077    """
1078
1079    @property
1080    def name(self):
1081        """Return the complete file and path name of the file."""
1082        return _CXString_getCString(File_name(self))
1083
1084    @property
1085    def time(self):
1086        """Return the last modification time of the file."""
1087        return File_time(self)
1088
1089class FileInclusion(object):
1090    """
1091    The FileInclusion class represents the inclusion of one source file by
1092    another via a '#include' directive or as the input file for the translation
1093    unit. This class provides information about the included file, the including
1094    file, the location of the '#include' directive and the depth of the included
1095    file in the stack. Note that the input file has depth 0.
1096    """
1097
1098    def __init__(self, src, tgt, loc, depth):
1099        self.source = src
1100        self.include = tgt
1101        self.location = loc
1102        self.depth = depth
1103
1104    @property
1105    def is_input_file(self):
1106        """True if the included file is the input file."""
1107        return self.depth == 0
1108
1109# Additional Functions and Types
1110
1111# String Functions
1112_CXString_dispose = lib.clang_disposeString
1113_CXString_dispose.argtypes = [_CXString]
1114
1115_CXString_getCString = lib.clang_getCString
1116_CXString_getCString.argtypes = [_CXString]
1117_CXString_getCString.restype = c_char_p
1118
1119# Source Location Functions
1120SourceLocation_loc = lib.clang_getInstantiationLocation
1121SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p),
1122                               POINTER(c_uint), POINTER(c_uint),
1123                               POINTER(c_uint)]
1124
1125# Source Range Functions
1126SourceRange_getRange = lib.clang_getRange
1127SourceRange_getRange.argtypes = [SourceLocation, SourceLocation]
1128SourceRange_getRange.restype = SourceRange
1129
1130SourceRange_start = lib.clang_getRangeStart
1131SourceRange_start.argtypes = [SourceRange]
1132SourceRange_start.restype = SourceLocation
1133
1134SourceRange_end = lib.clang_getRangeEnd
1135SourceRange_end.argtypes = [SourceRange]
1136SourceRange_end.restype = SourceLocation
1137
1138# CursorKind Functions
1139CursorKind_is_decl = lib.clang_isDeclaration
1140CursorKind_is_decl.argtypes = [CursorKind]
1141CursorKind_is_decl.restype = bool
1142
1143CursorKind_is_ref = lib.clang_isReference
1144CursorKind_is_ref.argtypes = [CursorKind]
1145CursorKind_is_ref.restype = bool
1146
1147CursorKind_is_expr = lib.clang_isExpression
1148CursorKind_is_expr.argtypes = [CursorKind]
1149CursorKind_is_expr.restype = bool
1150
1151CursorKind_is_stmt = lib.clang_isStatement
1152CursorKind_is_stmt.argtypes = [CursorKind]
1153CursorKind_is_stmt.restype = bool
1154
1155CursorKind_is_attribute = lib.clang_isAttribute
1156CursorKind_is_attribute.argtypes = [CursorKind]
1157CursorKind_is_attribute.restype = bool
1158
1159CursorKind_is_inv = lib.clang_isInvalid
1160CursorKind_is_inv.argtypes = [CursorKind]
1161CursorKind_is_inv.restype = bool
1162
1163# Cursor Functions
1164# TODO: Implement this function
1165Cursor_get = lib.clang_getCursor
1166Cursor_get.argtypes = [TranslationUnit, SourceLocation]
1167Cursor_get.restype = Cursor
1168
1169Cursor_null = lib.clang_getNullCursor
1170Cursor_null.restype = Cursor
1171
1172Cursor_usr = lib.clang_getCursorUSR
1173Cursor_usr.argtypes = [Cursor]
1174Cursor_usr.restype = _CXString
1175Cursor_usr.errcheck = _CXString.from_result
1176
1177Cursor_is_def = lib.clang_isCursorDefinition
1178Cursor_is_def.argtypes = [Cursor]
1179Cursor_is_def.restype = bool
1180
1181Cursor_def = lib.clang_getCursorDefinition
1182Cursor_def.argtypes = [Cursor]
1183Cursor_def.restype = Cursor
1184Cursor_def.errcheck = Cursor.from_result
1185
1186Cursor_eq = lib.clang_equalCursors
1187Cursor_eq.argtypes = [Cursor, Cursor]
1188Cursor_eq.restype = c_uint
1189
1190Cursor_spelling = lib.clang_getCursorSpelling
1191Cursor_spelling.argtypes = [Cursor]
1192Cursor_spelling.restype = _CXString
1193Cursor_spelling.errcheck = _CXString.from_result
1194
1195Cursor_displayname = lib.clang_getCursorDisplayName
1196Cursor_displayname.argtypes = [Cursor]
1197Cursor_displayname.restype = _CXString
1198Cursor_displayname.errcheck = _CXString.from_result
1199
1200Cursor_loc = lib.clang_getCursorLocation
1201Cursor_loc.argtypes = [Cursor]
1202Cursor_loc.restype = SourceLocation
1203
1204Cursor_extent = lib.clang_getCursorExtent
1205Cursor_extent.argtypes = [Cursor]
1206Cursor_extent.restype = SourceRange
1207
1208Cursor_ref = lib.clang_getCursorReferenced
1209Cursor_ref.argtypes = [Cursor]
1210Cursor_ref.restype = Cursor
1211Cursor_ref.errcheck = Cursor.from_result
1212
1213Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
1214Cursor_visit = lib.clang_visitChildren
1215Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
1216Cursor_visit.restype = c_uint
1217
1218# Index Functions
1219Index_create = lib.clang_createIndex
1220Index_create.argtypes = [c_int, c_int]
1221Index_create.restype = c_object_p
1222
1223Index_dispose = lib.clang_disposeIndex
1224Index_dispose.argtypes = [Index]
1225
1226# Translation Unit Functions
1227TranslationUnit_read = lib.clang_createTranslationUnit
1228TranslationUnit_read.argtypes = [Index, c_char_p]
1229TranslationUnit_read.restype = c_object_p
1230
1231TranslationUnit_parse = lib.clang_parseTranslationUnit
1232TranslationUnit_parse.argtypes = [Index, c_char_p, c_void_p,
1233                                  c_int, c_void_p, c_int, c_int]
1234TranslationUnit_parse.restype = c_object_p
1235
1236TranslationUnit_reparse = lib.clang_reparseTranslationUnit
1237TranslationUnit_reparse.argtypes = [TranslationUnit, c_int, c_void_p, c_int]
1238TranslationUnit_reparse.restype = c_int
1239
1240TranslationUnit_codeComplete = lib.clang_codeCompleteAt
1241TranslationUnit_codeComplete.argtypes = [TranslationUnit, c_char_p, c_int,
1242                                         c_int, c_void_p, c_int, c_int]
1243TranslationUnit_codeComplete.restype = POINTER(CCRStructure)
1244
1245TranslationUnit_cursor = lib.clang_getTranslationUnitCursor
1246TranslationUnit_cursor.argtypes = [TranslationUnit]
1247TranslationUnit_cursor.restype = Cursor
1248TranslationUnit_cursor.errcheck = Cursor.from_result
1249
1250TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling
1251TranslationUnit_spelling.argtypes = [TranslationUnit]
1252TranslationUnit_spelling.restype = _CXString
1253TranslationUnit_spelling.errcheck = _CXString.from_result
1254
1255TranslationUnit_dispose = lib.clang_disposeTranslationUnit
1256TranslationUnit_dispose.argtypes = [TranslationUnit]
1257
1258TranslationUnit_includes_callback = CFUNCTYPE(None,
1259                                              c_object_p,
1260                                              POINTER(SourceLocation),
1261                                              c_uint, py_object)
1262TranslationUnit_includes = lib.clang_getInclusions
1263TranslationUnit_includes.argtypes = [TranslationUnit,
1264                                     TranslationUnit_includes_callback,
1265                                     py_object]
1266
1267# File Functions
1268File_name = lib.clang_getFileName
1269File_name.argtypes = [File]
1270File_name.restype = _CXString
1271
1272File_time = lib.clang_getFileTime
1273File_time.argtypes = [File]
1274File_time.restype = c_uint
1275
1276# Code completion
1277
1278CodeCompletionResults_dispose = lib.clang_disposeCodeCompleteResults
1279CodeCompletionResults_dispose.argtypes = [CodeCompletionResults]
1280
1281_clang_codeCompleteGetNumDiagnostics = lib.clang_codeCompleteGetNumDiagnostics
1282_clang_codeCompleteGetNumDiagnostics.argtypes = [CodeCompletionResults]
1283_clang_codeCompleteGetNumDiagnostics.restype = c_int
1284
1285_clang_codeCompleteGetDiagnostic = lib.clang_codeCompleteGetDiagnostic
1286_clang_codeCompleteGetDiagnostic.argtypes = [CodeCompletionResults, c_int]
1287_clang_codeCompleteGetDiagnostic.restype = Diagnostic
1288
1289_clang_getCompletionChunkText = lib.clang_getCompletionChunkText
1290_clang_getCompletionChunkText.argtypes = [c_void_p, c_int]
1291_clang_getCompletionChunkText.restype = _CXString
1292
1293_clang_getCompletionChunkKind = lib.clang_getCompletionChunkKind
1294_clang_getCompletionChunkKind.argtypes = [c_void_p, c_int]
1295_clang_getCompletionChunkKind.restype = c_int
1296
1297_clang_getCompletionChunkCompletionString = lib.clang_getCompletionChunkCompletionString
1298_clang_getCompletionChunkCompletionString.argtypes = [c_void_p, c_int]
1299_clang_getCompletionChunkCompletionString.restype = c_object_p
1300
1301_clang_getNumCompletionChunks = lib.clang_getNumCompletionChunks
1302_clang_getNumCompletionChunks.argtypes = [c_void_p]
1303_clang_getNumCompletionChunks.restype = c_int
1304
1305_clang_getCompletionAvailability = lib.clang_getCompletionAvailability
1306_clang_getCompletionAvailability.argtypes = [c_void_p]
1307_clang_getCompletionAvailability.restype = c_int
1308
1309_clang_getCompletionPriority = lib.clang_getCompletionPriority
1310_clang_getCompletionPriority.argtypes = [c_void_p]
1311_clang_getCompletionPriority.restype = c_int
1312
1313
1314###
1315
1316__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind',
1317           'Diagnostic', 'FixIt', 'CodeCompletionResults', 'SourceRange',
1318           'SourceLocation', 'File']
1319