cindex.py revision a87dbcc04987ebf91adec3e00ac5e1548af6d865
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_invalid(self):
325        """Test if this is an invalid kind."""
326        return CursorKind_is_inv(self)
327
328    def __repr__(self):
329        return 'CursorKind.%s' % (self.name,)
330
331# FIXME: Is there a nicer way to expose this enumeration? We could potentially
332# represent the nested structure, or even build a class hierarchy. The main
333# things we want for sure are (a) simple external access to kinds, (b) a place
334# to hang a description and name, (c) easy to keep in sync with Index.h.
335
336###
337# Declaration Kinds
338
339# A declaration whose specific kind is not exposed via this interface.
340#
341# Unexposed declarations have the same operations as any other kind of
342# declaration; one can extract their location information, spelling, find their
343# definitions, etc. However, the specific kind of the declaration is not
344# reported.
345CursorKind.UNEXPOSED_DECL = CursorKind(1)
346
347# A C or C++ struct.
348CursorKind.STRUCT_DECL = CursorKind(2)
349
350# A C or C++ union.
351CursorKind.UNION_DECL = CursorKind(3)
352
353# A C++ class.
354CursorKind.CLASS_DECL = CursorKind(4)
355
356# An enumeration.
357CursorKind.ENUM_DECL = CursorKind(5)
358
359# A field (in C) or non-static data member (in C++) in a struct, union, or C++
360# class.
361CursorKind.FIELD_DECL = CursorKind(6)
362
363# An enumerator constant.
364CursorKind.ENUM_CONSTANT_DECL = CursorKind(7)
365
366# A function.
367CursorKind.FUNCTION_DECL = CursorKind(8)
368
369# A variable.
370CursorKind.VAR_DECL = CursorKind(9)
371
372# A function or method parameter.
373CursorKind.PARM_DECL = CursorKind(10)
374
375# An Objective-C @interface.
376CursorKind.OBJC_INTERFACE_DECL = CursorKind(11)
377
378# An Objective-C @interface for a category.
379CursorKind.OBJC_CATEGORY_DECL = CursorKind(12)
380
381# An Objective-C @protocol declaration.
382CursorKind.OBJC_PROTOCOL_DECL = CursorKind(13)
383
384# An Objective-C @property declaration.
385CursorKind.OBJC_PROPERTY_DECL = CursorKind(14)
386
387# An Objective-C instance variable.
388CursorKind.OBJC_IVAR_DECL = CursorKind(15)
389
390# An Objective-C instance method.
391CursorKind.OBJC_INSTANCE_METHOD_DECL = CursorKind(16)
392
393# An Objective-C class method.
394CursorKind.OBJC_CLASS_METHOD_DECL = CursorKind(17)
395
396# An Objective-C @implementation.
397CursorKind.OBJC_IMPLEMENTATION_DECL = CursorKind(18)
398
399# An Objective-C @implementation for a category.
400CursorKind.OBJC_CATEGORY_IMPL_DECL = CursorKind(19)
401
402# A typedef.
403CursorKind.TYPEDEF_DECL = CursorKind(20)
404
405# A C++ class method.
406CursorKind.CXX_METHOD = CursorKind(21)
407
408# A C++ namespace.
409CursorKind.NAMESPACE = CursorKind(22)
410
411# A linkage specification, e.g. 'extern "C"'.
412CursorKind.LINKAGE_SPEC = CursorKind(23)
413
414# A C++ constructor.
415CursorKind.CONSTRUCTOR = CursorKind(24)
416
417# A C++ destructor.
418CursorKind.DESTRUCTOR = CursorKind(25)
419
420# A C++ conversion function.
421CursorKind.CONVERSION_FUNCTION = CursorKind(26)
422
423# A C++ template type parameter
424CursorKind.TEMPLATE_TYPE_PARAMETER = CursorKind(27)
425
426# A C++ non-type template paramater.
427CursorKind.TEMPLATE_NON_TYPE_PARAMETER = CursorKind(28)
428
429# A C++ template template parameter.
430CursorKind.TEMPLATE_TEMPLATE_PARAMTER = CursorKind(29)
431
432# A C++ function template.
433CursorKind.FUNCTION_TEMPLATE = CursorKind(30)
434
435# A C++ class template.
436CursorKind.CLASS_TEMPLATE = CursorKind(31)
437
438# A C++ class template partial specialization.
439CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION = CursorKind(32)
440
441# A C++ namespace alias declaration.
442CursorKind.NAMESPACE_ALIAS = CursorKind(33)
443
444# A C++ using directive
445CursorKind.USING_DIRECTIVE = CursorKind(34)
446
447# A C++ using declaration
448CursorKind.USING_DECLARATION = CursorKind(35)
449
450###
451# Reference Kinds
452
453CursorKind.OBJC_SUPER_CLASS_REF = CursorKind(40)
454CursorKind.OBJC_PROTOCOL_REF = CursorKind(41)
455CursorKind.OBJC_CLASS_REF = CursorKind(42)
456
457# A reference to a type declaration.
458#
459# A type reference occurs anywhere where a type is named but not
460# declared. For example, given:
461#   typedef unsigned size_type;
462#   size_type size;
463#
464# The typedef is a declaration of size_type (CXCursor_TypedefDecl),
465# while the type of the variable "size" is referenced. The cursor
466# referenced by the type of size is the typedef for size_type.
467CursorKind.TYPE_REF = CursorKind(43)
468CursorKind.CXX_BASE_SPECIFIER = CursorKind(44)
469
470# A reference to a class template, function template, template
471# template parameter, or class template partial specialization.
472CursorKind.TEMPLATE_REF = CursorKind(45)
473
474# A reference to a namespace or namepsace alias.
475CursorKind.NAMESPACE_REF = CursorKind(46)
476
477# A reference to a member of a struct, union, or class that occurs in
478# some non-expression context, e.g., a designated initializer.
479CursorKind.MEMBER_REF = CursorKind(47)
480
481# A reference to a labeled statement.
482CursorKind.LABEL_REF = CursorKind(48)
483
484# A reference toa a set of overloaded functions or function templates
485# that has not yet been resolved to a specific function or function template.
486CursorKind.OVERLOADED_DECL_REF = CursorKind(49)
487
488###
489# Invalid/Error Kinds
490
491CursorKind.INVALID_FILE = CursorKind(70)
492CursorKind.NO_DECL_FOUND = CursorKind(71)
493CursorKind.NOT_IMPLEMENTED = CursorKind(72)
494CursorKind.INVALID_CODE = CursorKind(73)
495
496###
497# Expression Kinds
498
499# An expression whose specific kind is not exposed via this interface.
500#
501# Unexposed expressions have the same operations as any other kind of
502# expression; one can extract their location information, spelling, children,
503# etc. However, the specific kind of the expression is not reported.
504CursorKind.UNEXPOSED_EXPR = CursorKind(100)
505
506# An expression that refers to some value declaration, such as a function,
507# varible, or enumerator.
508CursorKind.DECL_REF_EXPR = CursorKind(101)
509
510# An expression that refers to a member of a struct, union, class, Objective-C
511# class, etc.
512CursorKind.MEMBER_REF_EXPR = CursorKind(102)
513
514# An expression that calls a function.
515CursorKind.CALL_EXPR = CursorKind(103)
516
517# An expression that sends a message to an Objective-C object or class.
518CursorKind.OBJC_MESSAGE_EXPR = CursorKind(104)
519
520# An expression that represents a block literal.
521CursorKind.BLOCK_EXPR = CursorKind(105)
522
523# A statement whose specific kind is not exposed via this interface.
524#
525# Unexposed statements have the same operations as any other kind of statement;
526# one can extract their location information, spelling, children, etc. However,
527# the specific kind of the statement is not reported.
528CursorKind.UNEXPOSED_STMT = CursorKind(200)
529
530# A labelled statement in a function.
531CursorKind.LABEL_STMT = CursorKind(201)
532
533
534###
535# Other Kinds
536
537# Cursor that represents the translation unit itself.
538#
539# The translation unit cursor exists primarily to act as the root cursor for
540# traversing the contents of a translation unit.
541CursorKind.TRANSLATION_UNIT = CursorKind(300)
542
543###
544# Attributes
545
546# An attribute whoe specific kind is note exposed via this interface
547CursorKind.UNEXPOSED_ATTR = CursorKind(400)
548
549CursorKind.IB_ACTION_ATTR = CursorKind(401)
550CursorKind.IB_OUTLET_ATTR = CursorKind(402)
551CursorKind.IB_OUTLET_COLLECTION_ATTR = CursorKind(403)
552
553###
554# Preprocessing
555CursorKind.PREPROCESSING_DIRECTIVE = CursorKind(500)
556CursorKind.MACRO_DEFINITION = CursorKind(501)
557CursorKind.MACRO_INSTANTIATION = CursorKind(502)
558CursorKind.INCLUSION_DIRECTIVE = CursorKind(503)
559
560### Cursors ###
561
562class Cursor(Structure):
563    """
564    The Cursor class represents a reference to an element within the AST. It
565    acts as a kind of iterator.
566    """
567    _fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)]
568
569    def __eq__(self, other):
570        return Cursor_eq(self, other)
571
572    def __ne__(self, other):
573        return not Cursor_eq(self, other)
574
575    def is_definition(self):
576        """
577        Returns true if the declaration pointed at by the cursor is also a
578        definition of that entity.
579        """
580        return Cursor_is_def(self)
581
582    def get_definition(self):
583        """
584        If the cursor is a reference to a declaration or a declaration of
585        some entity, return a cursor that points to the definition of that
586        entity.
587        """
588        # TODO: Should probably check that this is either a reference or
589        # declaration prior to issuing the lookup.
590        return Cursor_def(self)
591
592    def get_usr(self):
593        """Return the Unified Symbol Resultion (USR) for the entity referenced
594        by the given cursor (or None).
595
596        A Unified Symbol Resolution (USR) is a string that identifies a
597        particular entity (function, class, variable, etc.) within a
598        program. USRs can be compared across translation units to determine,
599        e.g., when references in one translation refer to an entity defined in
600        another translation unit."""
601        return Cursor_usr(self)
602
603    @property
604    def kind(self):
605        """Return the kind of this cursor."""
606        return CursorKind.from_id(self._kind_id)
607
608    @property
609    def spelling(self):
610        """Return the spelling of the entity pointed at by the cursor."""
611        if not self.kind.is_declaration():
612            # FIXME: clang_getCursorSpelling should be fixed to not assert on
613            # this, for consistency with clang_getCursorUSR.
614            return None
615        return Cursor_spelling(self)
616
617    @property
618    def location(self):
619        """
620        Return the source location (the starting character) of the entity
621        pointed at by the cursor.
622        """
623        return Cursor_loc(self)
624
625    @property
626    def extent(self):
627        """
628        Return the source range (the range of text) occupied by the entity
629        pointed at by the cursor.
630        """
631        return Cursor_extent(self)
632
633    def get_children(self):
634        """Return an iterator for accessing the children of this cursor."""
635
636        # FIXME: Expose iteration from CIndex, PR6125.
637        def visitor(child, parent, children):
638            # FIXME: Document this assertion in API.
639            # FIXME: There should just be an isNull method.
640            assert child != Cursor_null()
641            children.append(child)
642            return 1 # continue
643        children = []
644        Cursor_visit(self, Cursor_visit_callback(visitor), children)
645        return iter(children)
646
647    @staticmethod
648    def from_result(res, fn, args):
649        assert isinstance(res, Cursor)
650        # FIXME: There should just be an isNull method.
651        if res == Cursor_null():
652            return None
653        return res
654
655## CIndex Objects ##
656
657# CIndex objects (derived from ClangObject) are essentially lightweight
658# wrappers attached to some underlying object, which is exposed via CIndex as
659# a void*.
660
661class ClangObject(object):
662    """
663    A helper for Clang objects. This class helps act as an intermediary for
664    the ctypes library and the Clang CIndex library.
665    """
666    def __init__(self, obj):
667        assert isinstance(obj, c_object_p) and obj
668        self.obj = self._as_parameter_ = obj
669
670    def from_param(self):
671        return self._as_parameter_
672
673
674class _CXUnsavedFile(Structure):
675    """Helper for passing unsaved file arguments."""
676    _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)]
677
678## Diagnostic Conversion ##
679
680_clang_getNumDiagnostics = lib.clang_getNumDiagnostics
681_clang_getNumDiagnostics.argtypes = [c_object_p]
682_clang_getNumDiagnostics.restype = c_uint
683
684_clang_getDiagnostic = lib.clang_getDiagnostic
685_clang_getDiagnostic.argtypes = [c_object_p, c_uint]
686_clang_getDiagnostic.restype = c_object_p
687
688_clang_disposeDiagnostic = lib.clang_disposeDiagnostic
689_clang_disposeDiagnostic.argtypes = [Diagnostic]
690
691_clang_getDiagnosticSeverity = lib.clang_getDiagnosticSeverity
692_clang_getDiagnosticSeverity.argtypes = [Diagnostic]
693_clang_getDiagnosticSeverity.restype = c_int
694
695_clang_getDiagnosticLocation = lib.clang_getDiagnosticLocation
696_clang_getDiagnosticLocation.argtypes = [Diagnostic]
697_clang_getDiagnosticLocation.restype = SourceLocation
698
699_clang_getDiagnosticSpelling = lib.clang_getDiagnosticSpelling
700_clang_getDiagnosticSpelling.argtypes = [Diagnostic]
701_clang_getDiagnosticSpelling.restype = _CXString
702_clang_getDiagnosticSpelling.errcheck = _CXString.from_result
703
704_clang_getDiagnosticNumRanges = lib.clang_getDiagnosticNumRanges
705_clang_getDiagnosticNumRanges.argtypes = [Diagnostic]
706_clang_getDiagnosticNumRanges.restype = c_uint
707
708_clang_getDiagnosticRange = lib.clang_getDiagnosticRange
709_clang_getDiagnosticRange.argtypes = [Diagnostic, c_uint]
710_clang_getDiagnosticRange.restype = SourceRange
711
712_clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts
713_clang_getDiagnosticNumFixIts.argtypes = [Diagnostic]
714_clang_getDiagnosticNumFixIts.restype = c_uint
715
716_clang_getDiagnosticFixIt = lib.clang_getDiagnosticFixIt
717_clang_getDiagnosticFixIt.argtypes = [Diagnostic, c_uint, POINTER(SourceRange)]
718_clang_getDiagnosticFixIt.restype = _CXString
719_clang_getDiagnosticFixIt.errcheck = _CXString.from_result
720
721###
722
723class CompletionChunk:
724    class Kind:
725        def __init__(self, name):
726            self.name = name
727
728        def __str__(self):
729            return self.name
730
731        def __repr__(self):
732            return "<ChunkKind: %s>" % self
733
734    def __init__(self, completionString, key):
735        self.cs = completionString
736        self.key = key
737
738    def __repr__(self):
739        return "{'" + self.spelling + "', " + str(self.kind) + "}"
740
741    @property
742    def spelling(self):
743        return _clang_getCompletionChunkText(self.cs, self.key).spelling
744
745    @property
746    def kind(self):
747        res = _clang_getCompletionChunkKind(self.cs, self.key)
748        return completionChunkKindMap[res]
749
750    @property
751    def string(self):
752        res = _clang_getCompletionChunkCompletionString(self.cs, self.key)
753
754        if (res):
755          return CompletionString(res)
756        else:
757          None
758
759    def isKindOptional(self):
760      return self.kind == completionChunkKindMap[0]
761
762    def isKindTypedText(self):
763      return self.kind == completionChunkKindMap[1]
764
765    def isKindPlaceHolder(self):
766      return self.kind == completionChunkKindMap[3]
767
768    def isKindInformative(self):
769      return self.kind == completionChunkKindMap[4]
770
771    def isKindResultType(self):
772      return self.kind == completionChunkKindMap[15]
773
774completionChunkKindMap = {
775            0: CompletionChunk.Kind("Optional"),
776            1: CompletionChunk.Kind("TypedText"),
777            2: CompletionChunk.Kind("Text"),
778            3: CompletionChunk.Kind("Placeholder"),
779            4: CompletionChunk.Kind("Informative"),
780            5: CompletionChunk.Kind("CurrentParameter"),
781            6: CompletionChunk.Kind("LeftParen"),
782            7: CompletionChunk.Kind("RightParen"),
783            8: CompletionChunk.Kind("LeftBracket"),
784            9: CompletionChunk.Kind("RightBracket"),
785            10: CompletionChunk.Kind("LeftBrace"),
786            11: CompletionChunk.Kind("RightBrace"),
787            12: CompletionChunk.Kind("LeftAngle"),
788            13: CompletionChunk.Kind("RightAngle"),
789            14: CompletionChunk.Kind("Comma"),
790            15: CompletionChunk.Kind("ResultType"),
791            16: CompletionChunk.Kind("Colon"),
792            17: CompletionChunk.Kind("SemiColon"),
793            18: CompletionChunk.Kind("Equal"),
794            19: CompletionChunk.Kind("HorizontalSpace"),
795            20: CompletionChunk.Kind("VerticalSpace")}
796
797class CompletionString(ClangObject):
798    class Availability:
799        def __init__(self, name):
800            self.name = name
801
802        def __str__(self):
803            return self.name
804
805        def __repr__(self):
806            return "<Availability: %s>" % self
807
808    def __len__(self):
809        return _clang_getNumCompletionChunks(self.obj)
810
811    def __getitem__(self, key):
812        if len(self) <= key:
813            raise IndexError
814        return CompletionChunk(self.obj, key)
815
816    @property
817    def priority(self):
818        return _clang_getCompletionPriority(self.obj)
819
820    @property
821    def availability(self):
822        res = _clang_getCompletionAvailability(self.obj)
823        return availabilityKinds[res]
824
825    def __repr__(self):
826        return " | ".join([str(a) for a in self]) \
827               + " || Priority: " + str(self.priority) \
828               + " || Availability: " + str(self.availability)
829
830availabilityKinds = {
831            0: CompletionChunk.Kind("Available"),
832            1: CompletionChunk.Kind("Deprecated"),
833            2: CompletionChunk.Kind("NotAvailable")}
834
835class CodeCompletionResult(Structure):
836    _fields_ = [('cursorKind', c_int), ('completionString', c_object_p)]
837
838    def __repr__(self):
839        return str(CompletionString(self.completionString))
840
841    @property
842    def kind(self):
843        return CursorKind.from_id(self.cursorKind)
844
845    @property
846    def string(self):
847        return CompletionString(self.completionString)
848
849class CCRStructure(Structure):
850    _fields_ = [('results', POINTER(CodeCompletionResult)),
851                ('numResults', c_int)]
852
853    def __len__(self):
854        return self.numResults
855
856    def __getitem__(self, key):
857        if len(self) <= key:
858            raise IndexError
859
860        return self.results[key]
861
862class CodeCompletionResults(ClangObject):
863    def __init__(self, ptr):
864        assert isinstance(ptr, POINTER(CCRStructure)) and ptr
865        self.ptr = self._as_parameter_ = ptr
866
867    def from_param(self):
868        return self._as_parameter_
869
870    def __del__(self):
871        CodeCompletionResults_dispose(self)
872
873    @property
874    def results(self):
875        return self.ptr.contents
876
877    @property
878    def diagnostics(self):
879        class DiagnosticsItr:
880            def __init__(self, ccr):
881                self.ccr= ccr
882
883            def __len__(self):
884                return int(_clang_codeCompleteGetNumDiagnostics(self.ccr))
885
886            def __getitem__(self, key):
887                return _clang_codeCompleteGetDiagnostic(self.ccr, key)
888
889        return DiagnosticsItr(self)
890
891
892class Index(ClangObject):
893    """
894    The Index type provides the primary interface to the Clang CIndex library,
895    primarily by providing an interface for reading and parsing translation
896    units.
897    """
898
899    @staticmethod
900    def create(excludeDecls=False):
901        """
902        Create a new Index.
903        Parameters:
904        excludeDecls -- Exclude local declarations from translation units.
905        """
906        return Index(Index_create(excludeDecls, 0))
907
908    def __del__(self):
909        Index_dispose(self)
910
911    def read(self, path):
912        """Load the translation unit from the given AST file."""
913        ptr = TranslationUnit_read(self, path)
914        return TranslationUnit(ptr) if ptr else None
915
916    def parse(self, path, args = [], unsaved_files = [], options = 0):
917        """
918        Load the translation unit from the given source code file by running
919        clang and generating the AST before loading. Additional command line
920        parameters can be passed to clang via the args parameter.
921
922        In-memory contents for files can be provided by passing a list of pairs
923        to as unsaved_files, the first item should be the filenames to be mapped
924        and the second should be the contents to be substituted for the
925        file. The contents may be passed as strings or file objects.
926        """
927        arg_array = 0
928        if len(args):
929            arg_array = (c_char_p * len(args))(* args)
930        unsaved_files_array = 0
931        if len(unsaved_files):
932            unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
933            for i,(name,value) in enumerate(unsaved_files):
934                if not isinstance(value, str):
935                    # FIXME: It would be great to support an efficient version
936                    # of this, one day.
937                    value = value.read()
938                    print value
939                if not isinstance(value, str):
940                    raise TypeError,'Unexpected unsaved file contents.'
941                unsaved_files_array[i].name = name
942                unsaved_files_array[i].contents = value
943                unsaved_files_array[i].length = len(value)
944        ptr = TranslationUnit_parse(self, path, arg_array, len(args),
945                                    unsaved_files_array, len(unsaved_files),
946                                    options)
947        return TranslationUnit(ptr) if ptr else None
948
949
950class TranslationUnit(ClangObject):
951    """
952    The TranslationUnit class represents a source code translation unit and
953    provides read-only access to its top-level declarations.
954    """
955
956    def __init__(self, ptr):
957        ClangObject.__init__(self, ptr)
958
959    def __del__(self):
960        TranslationUnit_dispose(self)
961
962    @property
963    def cursor(self):
964        """Retrieve the cursor that represents the given translation unit."""
965        return TranslationUnit_cursor(self)
966
967    @property
968    def spelling(self):
969        """Get the original translation unit source file name."""
970        return TranslationUnit_spelling(self)
971
972    def get_includes(self):
973        """
974        Return an iterable sequence of FileInclusion objects that describe the
975        sequence of inclusions in a translation unit. The first object in
976        this sequence is always the input file. Note that this method will not
977        recursively iterate over header files included through precompiled
978        headers.
979        """
980        def visitor(fobj, lptr, depth, includes):
981            loc = lptr.contents
982            includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
983
984        # Automatically adapt CIndex/ctype pointers to python objects
985        includes = []
986        TranslationUnit_includes(self,
987                                 TranslationUnit_includes_callback(visitor),
988                                 includes)
989        return iter(includes)
990
991    @property
992    def diagnostics(self):
993        """
994        Return an iterable (and indexable) object containing the diagnostics.
995        """
996        class DiagIterator:
997            def __init__(self, tu):
998                self.tu = tu
999
1000            def __len__(self):
1001                return int(_clang_getNumDiagnostics(self.tu))
1002
1003            def __getitem__(self, key):
1004                diag = _clang_getDiagnostic(self.tu, key)
1005                if not diag:
1006                    raise IndexError
1007                return Diagnostic(diag)
1008
1009        return DiagIterator(self)
1010
1011    def reparse(self, unsaved_files = [], options = 0):
1012        """
1013        Reparse an already parsed translation unit.
1014
1015        In-memory contents for files can be provided by passing a list of pairs
1016        as unsaved_files, the first items should be the filenames to be mapped
1017        and the second should be the contents to be substituted for the
1018        file. The contents may be passed as strings or file objects.
1019        """
1020        unsaved_files_array = 0
1021        if len(unsaved_files):
1022            unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
1023            for i,(name,value) in enumerate(unsaved_files):
1024                if not isinstance(value, str):
1025                    # FIXME: It would be great to support an efficient version
1026                    # of this, one day.
1027                    value = value.read()
1028                    print value
1029                if not isinstance(value, str):
1030                    raise TypeError,'Unexpected unsaved file contents.'
1031                unsaved_files_array[i].name = name
1032                unsaved_files_array[i].contents = value
1033                unsaved_files_array[i].length = len(value)
1034        ptr = TranslationUnit_reparse(self, len(unsaved_files),
1035                                      unsaved_files_array,
1036                                      options)
1037    def codeComplete(self, path, line, column, unsaved_files = [], options = 0):
1038        """
1039        Code complete in this translation unit.
1040
1041        In-memory contents for files can be provided by passing a list of pairs
1042        as unsaved_files, the first items should be the filenames to be mapped
1043        and the second should be the contents to be substituted for the
1044        file. The contents may be passed as strings or file objects.
1045        """
1046        unsaved_files_array = 0
1047        if len(unsaved_files):
1048            unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
1049            for i,(name,value) in enumerate(unsaved_files):
1050                if not isinstance(value, str):
1051                    # FIXME: It would be great to support an efficient version
1052                    # of this, one day.
1053                    value = value.read()
1054                    print value
1055                if not isinstance(value, str):
1056                    raise TypeError,'Unexpected unsaved file contents.'
1057                unsaved_files_array[i].name = name
1058                unsaved_files_array[i].contents = value
1059                unsaved_files_array[i].length = len(value)
1060        ptr = TranslationUnit_codeComplete(self, path,
1061                                           line, column,
1062                                           unsaved_files_array,
1063                                           len(unsaved_files),
1064                                           options)
1065        return CodeCompletionResults(ptr) if ptr else None
1066
1067
1068class File(ClangObject):
1069    """
1070    The File class represents a particular source file that is part of a
1071    translation unit.
1072    """
1073
1074    @property
1075    def name(self):
1076        """Return the complete file and path name of the file."""
1077        return File_name(self)
1078
1079    @property
1080    def time(self):
1081        """Return the last modification time of the file."""
1082        return File_time(self)
1083
1084class FileInclusion(object):
1085    """
1086    The FileInclusion class represents the inclusion of one source file by
1087    another via a '#include' directive or as the input file for the translation
1088    unit. This class provides information about the included file, the including
1089    file, the location of the '#include' directive and the depth of the included
1090    file in the stack. Note that the input file has depth 0.
1091    """
1092
1093    def __init__(self, src, tgt, loc, depth):
1094        self.source = src
1095        self.include = tgt
1096        self.location = loc
1097        self.depth = depth
1098
1099    @property
1100    def is_input_file(self):
1101        """True if the included file is the input file."""
1102        return self.depth == 0
1103
1104# Additional Functions and Types
1105
1106# String Functions
1107_CXString_dispose = lib.clang_disposeString
1108_CXString_dispose.argtypes = [_CXString]
1109
1110_CXString_getCString = lib.clang_getCString
1111_CXString_getCString.argtypes = [_CXString]
1112_CXString_getCString.restype = c_char_p
1113
1114# Source Location Functions
1115SourceLocation_loc = lib.clang_getInstantiationLocation
1116SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p),
1117                               POINTER(c_uint), POINTER(c_uint),
1118                               POINTER(c_uint)]
1119
1120# Source Range Functions
1121SourceRange_getRange = lib.clang_getRange
1122SourceRange_getRange.argtypes = [SourceLocation, SourceLocation]
1123SourceRange_getRange.restype = SourceRange
1124
1125SourceRange_start = lib.clang_getRangeStart
1126SourceRange_start.argtypes = [SourceRange]
1127SourceRange_start.restype = SourceLocation
1128
1129SourceRange_end = lib.clang_getRangeEnd
1130SourceRange_end.argtypes = [SourceRange]
1131SourceRange_end.restype = SourceLocation
1132
1133# CursorKind Functions
1134CursorKind_is_decl = lib.clang_isDeclaration
1135CursorKind_is_decl.argtypes = [CursorKind]
1136CursorKind_is_decl.restype = bool
1137
1138CursorKind_is_ref = lib.clang_isReference
1139CursorKind_is_ref.argtypes = [CursorKind]
1140CursorKind_is_ref.restype = bool
1141
1142CursorKind_is_expr = lib.clang_isExpression
1143CursorKind_is_expr.argtypes = [CursorKind]
1144CursorKind_is_expr.restype = bool
1145
1146CursorKind_is_stmt = lib.clang_isStatement
1147CursorKind_is_stmt.argtypes = [CursorKind]
1148CursorKind_is_stmt.restype = bool
1149
1150CursorKind_is_inv = lib.clang_isInvalid
1151CursorKind_is_inv.argtypes = [CursorKind]
1152CursorKind_is_inv.restype = bool
1153
1154# Cursor Functions
1155# TODO: Implement this function
1156Cursor_get = lib.clang_getCursor
1157Cursor_get.argtypes = [TranslationUnit, SourceLocation]
1158Cursor_get.restype = Cursor
1159
1160Cursor_null = lib.clang_getNullCursor
1161Cursor_null.restype = Cursor
1162
1163Cursor_usr = lib.clang_getCursorUSR
1164Cursor_usr.argtypes = [Cursor]
1165Cursor_usr.restype = _CXString
1166Cursor_usr.errcheck = _CXString.from_result
1167
1168Cursor_is_def = lib.clang_isCursorDefinition
1169Cursor_is_def.argtypes = [Cursor]
1170Cursor_is_def.restype = bool
1171
1172Cursor_def = lib.clang_getCursorDefinition
1173Cursor_def.argtypes = [Cursor]
1174Cursor_def.restype = Cursor
1175Cursor_def.errcheck = Cursor.from_result
1176
1177Cursor_eq = lib.clang_equalCursors
1178Cursor_eq.argtypes = [Cursor, Cursor]
1179Cursor_eq.restype = c_uint
1180
1181Cursor_spelling = lib.clang_getCursorSpelling
1182Cursor_spelling.argtypes = [Cursor]
1183Cursor_spelling.restype = _CXString
1184Cursor_spelling.errcheck = _CXString.from_result
1185
1186Cursor_loc = lib.clang_getCursorLocation
1187Cursor_loc.argtypes = [Cursor]
1188Cursor_loc.restype = SourceLocation
1189
1190Cursor_extent = lib.clang_getCursorExtent
1191Cursor_extent.argtypes = [Cursor]
1192Cursor_extent.restype = SourceRange
1193
1194Cursor_ref = lib.clang_getCursorReferenced
1195Cursor_ref.argtypes = [Cursor]
1196Cursor_ref.restype = Cursor
1197Cursor_ref.errcheck = Cursor.from_result
1198
1199Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
1200Cursor_visit = lib.clang_visitChildren
1201Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
1202Cursor_visit.restype = c_uint
1203
1204# Index Functions
1205Index_create = lib.clang_createIndex
1206Index_create.argtypes = [c_int, c_int]
1207Index_create.restype = c_object_p
1208
1209Index_dispose = lib.clang_disposeIndex
1210Index_dispose.argtypes = [Index]
1211
1212# Translation Unit Functions
1213TranslationUnit_read = lib.clang_createTranslationUnit
1214TranslationUnit_read.argtypes = [Index, c_char_p]
1215TranslationUnit_read.restype = c_object_p
1216
1217TranslationUnit_parse = lib.clang_parseTranslationUnit
1218TranslationUnit_parse.argtypes = [Index, c_char_p, c_void_p,
1219                                  c_int, c_void_p, c_int, c_int]
1220TranslationUnit_parse.restype = c_object_p
1221
1222TranslationUnit_reparse = lib.clang_reparseTranslationUnit
1223TranslationUnit_reparse.argtypes = [TranslationUnit, c_int, c_void_p, c_int]
1224TranslationUnit_reparse.restype = c_int
1225
1226TranslationUnit_codeComplete = lib.clang_codeCompleteAt
1227TranslationUnit_codeComplete.argtypes = [TranslationUnit, c_char_p, c_int,
1228                                         c_int, c_void_p, c_int, c_int]
1229TranslationUnit_codeComplete.restype = POINTER(CCRStructure)
1230
1231TranslationUnit_cursor = lib.clang_getTranslationUnitCursor
1232TranslationUnit_cursor.argtypes = [TranslationUnit]
1233TranslationUnit_cursor.restype = Cursor
1234TranslationUnit_cursor.errcheck = Cursor.from_result
1235
1236TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling
1237TranslationUnit_spelling.argtypes = [TranslationUnit]
1238TranslationUnit_spelling.restype = _CXString
1239TranslationUnit_spelling.errcheck = _CXString.from_result
1240
1241TranslationUnit_dispose = lib.clang_disposeTranslationUnit
1242TranslationUnit_dispose.argtypes = [TranslationUnit]
1243
1244TranslationUnit_includes_callback = CFUNCTYPE(None,
1245                                              c_object_p,
1246                                              POINTER(SourceLocation),
1247                                              c_uint, py_object)
1248TranslationUnit_includes = lib.clang_getInclusions
1249TranslationUnit_includes.argtypes = [TranslationUnit,
1250                                     TranslationUnit_includes_callback,
1251                                     py_object]
1252
1253# File Functions
1254File_name = lib.clang_getFileName
1255File_name.argtypes = [File]
1256File_name.restype = c_char_p
1257
1258File_time = lib.clang_getFileTime
1259File_time.argtypes = [File]
1260File_time.restype = c_uint
1261
1262# Code completion
1263
1264CodeCompletionResults_dispose = lib.clang_disposeCodeCompleteResults
1265CodeCompletionResults_dispose.argtypes = [CodeCompletionResults]
1266
1267_clang_codeCompleteGetNumDiagnostics = lib.clang_codeCompleteGetNumDiagnostics
1268_clang_codeCompleteGetNumDiagnostics.argtypes = [CodeCompletionResults]
1269_clang_codeCompleteGetNumDiagnostics.restype = c_int
1270
1271_clang_codeCompleteGetDiagnostic = lib.clang_codeCompleteGetDiagnostic
1272_clang_codeCompleteGetDiagnostic.argtypes = [CodeCompletionResults, c_int]
1273_clang_codeCompleteGetDiagnostic.restype = Diagnostic
1274
1275_clang_getCompletionChunkText = lib.clang_getCompletionChunkText
1276_clang_getCompletionChunkText.argtypes = [c_void_p, c_int]
1277_clang_getCompletionChunkText.restype = _CXString
1278
1279_clang_getCompletionChunkKind = lib.clang_getCompletionChunkKind
1280_clang_getCompletionChunkKind.argtypes = [c_void_p, c_int]
1281_clang_getCompletionChunkKind.restype = c_int
1282
1283_clang_getCompletionChunkCompletionString = lib.clang_getCompletionChunkCompletionString
1284_clang_getCompletionChunkCompletionString.argtypes = [c_void_p, c_int]
1285_clang_getCompletionChunkCompletionString.restype = c_object_p
1286
1287_clang_getNumCompletionChunks = lib.clang_getNumCompletionChunks
1288_clang_getNumCompletionChunks.argtypes = [c_void_p]
1289_clang_getNumCompletionChunks.restype = c_int
1290
1291_clang_getCompletionAvailability = lib.clang_getCompletionAvailability
1292_clang_getCompletionAvailability.argtypes = [c_void_p]
1293_clang_getCompletionAvailability.restype = c_int
1294
1295_clang_getCompletionPriority = lib.clang_getCompletionPriority
1296_clang_getCompletionPriority.argtypes = [c_void_p]
1297_clang_getCompletionPriority.restype = c_int
1298
1299
1300###
1301
1302__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind',
1303           'Diagnostic', 'FixIt', 'CodeCompletionResults', 'SourceRange',
1304           'SourceLocation', 'File']
1305