cindex.py revision ef7f798c0921cde7e665935a5630578cc1065e0f
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('libCIndex.dylib')
75    elif name == 'Windows':
76        return cdll.LoadLibrary('libCIndex.dll')
77    else:
78        return cdll.LoadLibrary('libCIndex.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, severity, location, spelling, ranges, fixits):
191        self.severity = severity
192        self.location = location
193        self.spelling = spelling
194        self.ranges = ranges
195        self.fixits = fixits
196
197    def __repr__(self):
198        return "<Diagnostic severity %r, location %r, spelling %r>" % (
199            self.severity, self.location, self.spelling)
200
201class FixIt(object):
202    """
203    A FixIt represents a transformation to be applied to the source to
204    "fix-it". The fix-it shouldbe applied by replacing the given source range
205    with the given value.
206    """
207
208    def __init__(self, range, value):
209        self.range = range
210        self.value = value
211
212    def __repr__(self):
213        return "<FixIt range %r, value %r>" % (self.range, self.value)
214
215### Cursor Kinds ###
216
217class CursorKind(object):
218    """
219    A CursorKind describes the kind of entity that a cursor points to.
220    """
221
222    # The unique kind objects, indexed by id.
223    _kinds = []
224    _name_map = None
225
226    def __init__(self, value):
227        if value >= len(CursorKind._kinds):
228            CursorKind._kinds += [None] * (value - len(CursorKind._kinds) + 1)
229        if CursorKind._kinds[value] is not None:
230            raise ValueError,'CursorKind already loaded'
231        self.value = value
232        CursorKind._kinds[value] = self
233        CursorKind._name_map = None
234
235    def from_param(self):
236        return self.value
237
238    @property
239    def name(self):
240        """Get the enumeration name of this cursor kind."""
241        if self._name_map is None:
242            self._name_map = {}
243            for key,value in CursorKind.__dict__.items():
244                if isinstance(value,CursorKind):
245                    self._name_map[value] = key
246        return self._name_map[self]
247
248    @staticmethod
249    def from_id(id):
250        if id >= len(CursorKind._kinds) or CursorKind._kinds[id] is None:
251            raise ValueError,'Unknown cursor kind'
252        return CursorKind._kinds[id]
253
254    @staticmethod
255    def get_all_kinds():
256        """Return all CursorKind enumeration instances."""
257        return filter(None, CursorKind._kinds)
258
259    def is_declaration(self):
260        """Test if this is a declaration kind."""
261        return CursorKind_is_decl(self)
262
263    def is_reference(self):
264        """Test if this is a reference kind."""
265        return CursorKind_is_ref(self)
266
267    def is_expression(self):
268        """Test if this is an expression kind."""
269        return CursorKind_is_expr(self)
270
271    def is_statement(self):
272        """Test if this is a statement kind."""
273        return CursorKind_is_stmt(self)
274
275    def is_invalid(self):
276        """Test if this is an invalid kind."""
277        return CursorKind_is_inv(self)
278
279    def __repr__(self):
280        return 'CursorKind.%s' % (self.name,)
281
282# FIXME: Is there a nicer way to expose this enumeration? We could potentially
283# represent the nested structure, or even build a class hierarchy. The main
284# things we want for sure are (a) simple external access to kinds, (b) a place
285# to hang a description and name, (c) easy to keep in sync with Index.h.
286
287###
288# Declaration Kinds
289
290# A declaration whose specific kind is not exposed via this interface.
291#
292# Unexposed declarations have the same operations as any other kind of
293# declaration; one can extract their location information, spelling, find their
294# definitions, etc. However, the specific kind of the declaration is not
295# reported.
296CursorKind.UNEXPOSED_DECL = CursorKind(1)
297
298# A C or C++ struct.
299CursorKind.STRUCT_DECL = CursorKind(2)
300
301# A C or C++ union.
302CursorKind.UNION_DECL = CursorKind(3)
303
304# A C++ class.
305CursorKind.CLASS_DECL = CursorKind(4)
306
307# An enumeration.
308CursorKind.ENUM_DECL = CursorKind(5)
309
310# A field (in C) or non-static data member (in C++) in a struct, union, or C++
311# class.
312CursorKind.FIELD_DECL = CursorKind(6)
313
314# An enumerator constant.
315CursorKind.ENUM_CONSTANT_DECL = CursorKind(7)
316
317# A function.
318CursorKind.FUNCTION_DECL = CursorKind(8)
319
320# A variable.
321CursorKind.VAR_DECL = CursorKind(9)
322
323# A function or method parameter.
324CursorKind.PARM_DECL = CursorKind(10)
325
326# An Objective-C @interface.
327CursorKind.OBJC_INTERFACE_DECL = CursorKind(11)
328
329# An Objective-C @interface for a category.
330CursorKind.OBJC_CATEGORY_DECL = CursorKind(12)
331
332# An Objective-C @protocol declaration.
333CursorKind.OBJC_PROTOCOL_DECL = CursorKind(13)
334
335# An Objective-C @property declaration.
336CursorKind.OBJC_PROPERTY_DECL = CursorKind(14)
337
338# An Objective-C instance variable.
339CursorKind.OBJC_IVAR_DECL = CursorKind(15)
340
341# An Objective-C instance method.
342CursorKind.OBJC_INSTANCE_METHOD_DECL = CursorKind(16)
343
344# An Objective-C class method.
345CursorKind.OBJC_CLASS_METHOD_DECL = CursorKind(17)
346
347# An Objective-C @implementation.
348CursorKind.OBJC_IMPLEMENTATION_DECL = CursorKind(18)
349
350# An Objective-C @implementation for a category.
351CursorKind.OBJC_CATEGORY_IMPL_DECL = CursorKind(19)
352
353# A typedef.
354CursorKind.TYPEDEF_DECL = CursorKind(20)
355
356###
357# Reference Kinds
358
359CursorKind.OBJC_SUPER_CLASS_REF = CursorKind(40)
360CursorKind.OBJC_PROTOCOL_REF = CursorKind(41)
361CursorKind.OBJC_CLASS_REF = CursorKind(42)
362
363# A reference to a type declaration.
364#
365# A type reference occurs anywhere where a type is named but not
366# declared. For example, given:
367#   typedef unsigned size_type;
368#   size_type size;
369#
370# The typedef is a declaration of size_type (CXCursor_TypedefDecl),
371# while the type of the variable "size" is referenced. The cursor
372# referenced by the type of size is the typedef for size_type.
373CursorKind.TYPE_REF = CursorKind(43)
374
375###
376# Invalid/Error Kinds
377
378CursorKind.INVALID_FILE = CursorKind(70)
379CursorKind.NO_DECL_FOUND = CursorKind(71)
380CursorKind.NOT_IMPLEMENTED = CursorKind(72)
381
382###
383# Expression Kinds
384
385# An expression whose specific kind is not exposed via this interface.
386#
387# Unexposed expressions have the same operations as any other kind of
388# expression; one can extract their location information, spelling, children,
389# etc. However, the specific kind of the expression is not reported.
390CursorKind.UNEXPOSED_EXPR = CursorKind(100)
391
392# An expression that refers to some value declaration, such as a function,
393# varible, or enumerator.
394CursorKind.DECL_REF_EXPR = CursorKind(101)
395
396# An expression that refers to a member of a struct, union, class, Objective-C
397# class, etc.
398CursorKind.MEMBER_REF_EXPR = CursorKind(102)
399
400# An expression that calls a function.
401CursorKind.CALL_EXPR = CursorKind(103)
402
403# An expression that sends a message to an Objective-C object or class.
404CursorKind.OBJC_MESSAGE_EXPR = CursorKind(104)
405
406# A statement whose specific kind is not exposed via this interface.
407#
408# Unexposed statements have the same operations as any other kind of statement;
409# one can extract their location information, spelling, children, etc. However,
410# the specific kind of the statement is not reported.
411CursorKind.UNEXPOSED_STMT = CursorKind(200)
412
413###
414# Other Kinds
415
416# Cursor that represents the translation unit itself.
417#
418# The translation unit cursor exists primarily to act as the root cursor for
419# traversing the contents of a translation unit.
420CursorKind.TRANSLATION_UNIT = CursorKind(300)
421
422### Cursors ###
423
424class Cursor(Structure):
425    """
426    The Cursor class represents a reference to an element within the AST. It
427    acts as a kind of iterator.
428    """
429    _fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)]
430
431    def __eq__(self, other):
432        return Cursor_eq(self, other)
433
434    def __ne__(self, other):
435        return not Cursor_eq(self, other)
436
437    def is_definition(self):
438        """
439        Returns true if the declaration pointed at by the cursor is also a
440        definition of that entity.
441        """
442        return Cursor_is_def(self)
443
444    def get_definition(self):
445        """
446        If the cursor is a reference to a declaration or a declaration of
447        some entity, return a cursor that points to the definition of that
448        entity.
449        """
450        # TODO: Should probably check that this is either a reference or
451        # declaration prior to issuing the lookup.
452        return Cursor_def(self)
453
454    def get_usr(self):
455        """Return the Unified Symbol Resultion (USR) for the entity referenced
456        by the given cursor (or None).
457
458        A Unified Symbol Resolution (USR) is a string that identifies a
459        particular entity (function, class, variable, etc.) within a
460        program. USRs can be compared across translation units to determine,
461        e.g., when references in one translation refer to an entity defined in
462        another translation unit."""
463        return Cursor_usr(self)
464
465    @property
466    def kind(self):
467        """Return the kind of this cursor."""
468        return CursorKind.from_id(self._kind_id)
469
470    @property
471    def spelling(self):
472        """Return the spelling of the entity pointed at by the cursor."""
473        if not self.kind.is_declaration():
474            # FIXME: clang_getCursorSpelling should be fixed to not assert on
475            # this, for consistency with clang_getCursorUSR.
476            return None
477        return Cursor_spelling(self)
478
479    @property
480    def location(self):
481        """
482        Return the source location (the starting character) of the entity
483        pointed at by the cursor.
484        """
485        return Cursor_loc(self)
486
487    @property
488    def extent(self):
489        """
490        Return the source range (the range of text) occupied by the entity
491        pointed at by the cursor.
492        """
493        return Cursor_extent(self)
494
495    def get_children(self):
496        """Return an iterator for accessing the children of this cursor."""
497
498        # FIXME: Expose iteration from CIndex, PR6125.
499        def visitor(child, parent, children):
500            # FIXME: Document this assertion in API.
501            # FIXME: There should just be an isNull method.
502            assert child != Cursor_null()
503            children.append(child)
504            return 1 # continue
505        children = []
506        Cursor_visit(self, Cursor_visit_callback(visitor), children)
507        return iter(children)
508
509    @staticmethod
510    def from_result(res, fn, args):
511        assert isinstance(res, Cursor)
512        # FIXME: There should just be an isNull method.
513        if res == Cursor_null():
514            return None
515        return res
516
517## CIndex Objects ##
518
519# CIndex objects (derived from ClangObject) are essentially lightweight
520# wrappers attached to some underlying object, which is exposed via CIndex as
521# a void*.
522
523class ClangObject(object):
524    """
525    A helper for Clang objects. This class helps act as an intermediary for
526    the ctypes library and the Clang CIndex library.
527    """
528    def __init__(self, obj):
529        assert isinstance(obj, c_object_p) and obj
530        self.obj = self._as_parameter_ = obj
531
532    def from_param(self):
533        return self._as_parameter_
534
535
536class _CXUnsavedFile(Structure):
537    """Helper for passing unsaved file arguments."""
538    _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)]
539
540## Diagnostic Conversion ##
541
542# Diagnostic objects are temporary, we must extract all the information from the
543# diagnostic object when it is passed to the callback.
544
545_clang_getDiagnosticSeverity = lib.clang_getDiagnosticSeverity
546_clang_getDiagnosticSeverity.argtypes = [c_object_p]
547_clang_getDiagnosticSeverity.restype = c_int
548
549_clang_getDiagnosticLocation = lib.clang_getDiagnosticLocation
550_clang_getDiagnosticLocation.argtypes = [c_object_p]
551_clang_getDiagnosticLocation.restype = SourceLocation
552
553_clang_getDiagnosticSpelling = lib.clang_getDiagnosticSpelling
554_clang_getDiagnosticSpelling.argtypes = [c_object_p]
555_clang_getDiagnosticSpelling.restype = _CXString
556_clang_getDiagnosticSpelling.errcheck = _CXString.from_result
557
558_clang_getDiagnosticNumRanges = lib.clang_getDiagnosticNumRanges
559_clang_getDiagnosticNumRanges.argtypes = [c_object_p]
560_clang_getDiagnosticNumRanges.restype = c_uint
561
562_clang_getDiagnosticRange = lib.clang_getDiagnosticRange
563_clang_getDiagnosticRange.argtypes = [c_object_p, c_uint]
564_clang_getDiagnosticRange.restype = SourceRange
565
566_clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts
567_clang_getDiagnosticNumFixIts.argtypes = [c_object_p]
568_clang_getDiagnosticNumFixIts.restype = c_uint
569
570_clang_getDiagnosticFixItKind = lib.clang_getDiagnosticFixItKind
571_clang_getDiagnosticFixItKind.argtypes = [c_object_p, c_uint]
572_clang_getDiagnosticFixItKind.restype = c_int
573
574_clang_getDiagnosticFixItInsertion = lib.clang_getDiagnosticFixItInsertion
575_clang_getDiagnosticFixItInsertion.argtypes = [c_object_p, c_uint,
576                                               POINTER(SourceLocation)]
577_clang_getDiagnosticFixItInsertion.restype = _CXString
578_clang_getDiagnosticFixItInsertion.errcheck = _CXString.from_result
579
580_clang_getDiagnosticFixItRemoval = lib.clang_getDiagnosticFixItRemoval
581_clang_getDiagnosticFixItRemoval.argtypes = [c_object_p, c_uint,
582                                             POINTER(SourceLocation)]
583_clang_getDiagnosticFixItRemoval.restype = _CXString
584_clang_getDiagnosticFixItRemoval.errcheck = _CXString.from_result
585
586_clang_getDiagnosticFixItReplacement = lib.clang_getDiagnosticFixItReplacement
587_clang_getDiagnosticFixItReplacement.argtypes = [c_object_p, c_uint,
588                                                 POINTER(SourceRange)]
589_clang_getDiagnosticFixItReplacement.restype = _CXString
590_clang_getDiagnosticFixItReplacement.errcheck = _CXString.from_result
591
592def _convert_fixit(diag_ptr, index):
593    # We normalize all the fix-its to a single representation, this is more
594    # convenient.
595    #
596    # FIXME: Push this back into API? It isn't exactly clear what the
597    # SourceRange semantics are, we should make sure we can represent an empty
598    # range.
599    kind = _clang_getDiagnosticFixItKind(diag_ptr, index)
600    range = None
601    value = None
602    if kind == 0: # insertion
603        location = SourceLocation()
604        value = _clang_getDiagnosticFixItInsertion(diag_ptr, index,
605                                                   byref(location))
606        range = SourceRange.from_locations(location, location)
607    elif kind == 1: # removal
608        range = _clang_getDiagnosticFixItRemoval(diag_ptr, index)
609        value = ''
610    else: # replacement
611        assert kind == 2
612        range = SourceRange()
613        value = _clang_getDiagnosticFixItReplacement(diag_ptr, index,
614                                                     byref(range))
615    return FixIt(range, value)
616
617def _convert_diag(diag_ptr, diag_list):
618    severity = _clang_getDiagnosticSeverity(diag_ptr)
619    loc = _clang_getDiagnosticLocation(diag_ptr)
620    spelling = _clang_getDiagnosticSpelling(diag_ptr)
621
622    # Diagnostic ranges.
623    num_ranges = _clang_getDiagnosticNumRanges(diag_ptr)
624    ranges = [_clang_getDiagnosticRange(diag_ptr, i)
625              for i in range(num_ranges)]
626
627    fixits = [_convert_fixit(diag_ptr, i)
628              for i in range(_clang_getDiagnosticNumFixIts(diag_ptr))]
629
630    diag_list.append(Diagnostic(severity, loc, spelling, ranges, fixits))
631
632###
633
634class Index(ClangObject):
635    """
636    The Index type provides the primary interface to the Clang CIndex library,
637    primarily by providing an interface for reading and parsing translation
638    units.
639    """
640
641    @staticmethod
642    def create(excludeDecls=False):
643        """
644        Create a new Index.
645        Parameters:
646        excludeDecls -- Exclude local declarations from translation units.
647        """
648        return Index(Index_create(excludeDecls))
649
650    def __del__(self):
651        Index_dispose(self)
652
653    def read(self, path):
654        """Load the translation unit from the given AST file."""
655        # FIXME: In theory, we could support streaming diagnostics. It's hard to
656        # integrate this into the API cleanly, however. Resolve.
657        diags = []
658        ptr = TranslationUnit_read(self, path,
659                                   Diagnostic_callback(_convert_diag), diags)
660        return TranslationUnit(ptr) if ptr else None
661
662    def parse(self, path, args = [], unsaved_files = []):
663        """
664        Load the translation unit from the given source code file by running
665        clang and generating the AST before loading. Additional command line
666        parameters can be passed to clang via the args parameter.
667
668        In-memory contents for files can be provided by passing a list of pairs
669        to as unsaved_files, the first item should be the filenames to be mapped
670        and the second should be the contents to be substituted for the
671        file. The contents may be passed as strings or file objects.
672        """
673        arg_array = 0
674        if len(args):
675            arg_array = (c_char_p * len(args))(* args)
676        unsaved_files_array = 0
677        if len(unsaved_files):
678            unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
679            for i,(name,value) in enumerate(unsaved_files):
680                if not isinstance(value, str):
681                    # FIXME: It would be great to support an efficient version
682                    # of this, one day.
683                    value = value.read()
684                    print value
685                if not isinstance(value, str):
686                    raise TypeError,'Unexpected unsaved file contents.'
687                unsaved_files_array[i].name = name
688                unsaved_files_array[i].contents = value
689                unsaved_files_array[i].length = len(value)
690        # FIXME: In theory, we could support streaming diagnostics. It's hard to
691        # integrate this into the API cleanly, however. Resolve.
692        diags = []
693        ptr = TranslationUnit_parse(self, path, len(args), arg_array,
694                                    len(unsaved_files), unsaved_files_array,
695                                    Diagnostic_callback(_convert_diag), diags)
696        return TranslationUnit(ptr, diags) if ptr else None
697
698
699class TranslationUnit(ClangObject):
700    """
701    The TranslationUnit class represents a source code translation unit and
702    provides read-only access to its top-level declarations.
703    """
704
705    def __init__(self, ptr, diagnostics):
706        ClangObject.__init__(self, ptr)
707        self.diagnostics = diagnostics
708
709    def __del__(self):
710        TranslationUnit_dispose(self)
711
712    @property
713    def cursor(self):
714        """Retrieve the cursor that represents the given translation unit."""
715        return TranslationUnit_cursor(self)
716
717    @property
718    def spelling(self):
719        """Get the original translation unit source file name."""
720        return TranslationUnit_spelling(self)
721
722    def get_includes(self):
723        """
724        Return an iterable sequence of FileInclusion objects that describe the
725        sequence of inclusions in a translation unit. The first object in
726        this sequence is always the input file. Note that this method will not
727        recursively iterate over header files included through precompiled
728        headers.
729        """
730        def visitor(fobj, lptr, depth, includes):
731            loc = lptr.contents
732            includes.append(FileInclusion(loc.file, File(fobj), loc, depth))
733
734        # Automatically adapt CIndex/ctype pointers to python objects
735        includes = []
736        TranslationUnit_includes(self,
737                                 TranslationUnit_includes_callback(visitor),
738                                 includes)
739        return iter(includes)
740
741class File(ClangObject):
742    """
743    The File class represents a particular source file that is part of a
744    translation unit.
745    """
746
747    @property
748    def name(self):
749        """Return the complete file and path name of the file."""
750        return File_name(self)
751
752    @property
753    def time(self):
754        """Return the last modification time of the file."""
755        return File_time(self)
756
757class FileInclusion(object):
758    """
759    The FileInclusion class represents the inclusion of one source file by
760    another via a '#include' directive or as the input file for the translation
761    unit. This class provides information about the included file, the including
762    file, the location of the '#include' directive and the depth of the included
763    file in the stack. Note that the input file has depth 0.
764    """
765
766    def __init__(self, src, tgt, loc, depth):
767        self.source = src
768        self.include = tgt
769        self.location = loc
770        self.depth = depth
771
772    @property
773    def is_input_file(self):
774        """True if the included file is the input file."""
775        return self.depth == 0
776
777# Additional Functions and Types
778
779# String Functions
780_CXString_dispose = lib.clang_disposeString
781_CXString_dispose.argtypes = [_CXString]
782
783_CXString_getCString = lib.clang_getCString
784_CXString_getCString.argtypes = [_CXString]
785_CXString_getCString.restype = c_char_p
786
787# Source Location Functions
788SourceLocation_loc = lib.clang_getInstantiationLocation
789SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p),
790                               POINTER(c_uint), POINTER(c_uint),
791                               POINTER(c_uint)]
792
793# Source Range Functions
794SourceRange_getRange = lib.clang_getRange
795SourceRange_getRange.argtypes = [SourceLocation, SourceLocation]
796SourceRange_getRange.restype = SourceRange
797
798SourceRange_start = lib.clang_getRangeStart
799SourceRange_start.argtypes = [SourceRange]
800SourceRange_start.restype = SourceLocation
801
802SourceRange_end = lib.clang_getRangeEnd
803SourceRange_end.argtypes = [SourceRange]
804SourceRange_end.restype = SourceLocation
805
806# CursorKind Functions
807CursorKind_is_decl = lib.clang_isDeclaration
808CursorKind_is_decl.argtypes = [CursorKind]
809CursorKind_is_decl.restype = bool
810
811CursorKind_is_ref = lib.clang_isReference
812CursorKind_is_ref.argtypes = [CursorKind]
813CursorKind_is_ref.restype = bool
814
815CursorKind_is_expr = lib.clang_isExpression
816CursorKind_is_expr.argtypes = [CursorKind]
817CursorKind_is_expr.restype = bool
818
819CursorKind_is_stmt = lib.clang_isStatement
820CursorKind_is_stmt.argtypes = [CursorKind]
821CursorKind_is_stmt.restype = bool
822
823CursorKind_is_inv = lib.clang_isInvalid
824CursorKind_is_inv.argtypes = [CursorKind]
825CursorKind_is_inv.restype = bool
826
827# Cursor Functions
828# TODO: Implement this function
829Cursor_get = lib.clang_getCursor
830Cursor_get.argtypes = [TranslationUnit, SourceLocation]
831Cursor_get.restype = Cursor
832
833Cursor_null = lib.clang_getNullCursor
834Cursor_null.restype = Cursor
835
836Cursor_usr = lib.clang_getCursorUSR
837Cursor_usr.argtypes = [Cursor]
838Cursor_usr.restype = _CXString
839Cursor_usr.errcheck = _CXString.from_result
840
841Cursor_is_def = lib.clang_isCursorDefinition
842Cursor_is_def.argtypes = [Cursor]
843Cursor_is_def.restype = bool
844
845Cursor_def = lib.clang_getCursorDefinition
846Cursor_def.argtypes = [Cursor]
847Cursor_def.restype = Cursor
848Cursor_def.errcheck = Cursor.from_result
849
850Cursor_eq = lib.clang_equalCursors
851Cursor_eq.argtypes = [Cursor, Cursor]
852Cursor_eq.restype = c_uint
853
854Cursor_spelling = lib.clang_getCursorSpelling
855Cursor_spelling.argtypes = [Cursor]
856Cursor_spelling.restype = _CXString
857Cursor_spelling.errcheck = _CXString.from_result
858
859Cursor_loc = lib.clang_getCursorLocation
860Cursor_loc.argtypes = [Cursor]
861Cursor_loc.restype = SourceLocation
862
863Cursor_extent = lib.clang_getCursorExtent
864Cursor_extent.argtypes = [Cursor]
865Cursor_extent.restype = SourceRange
866
867Cursor_ref = lib.clang_getCursorReferenced
868Cursor_ref.argtypes = [Cursor]
869Cursor_ref.restype = Cursor
870Cursor_ref.errcheck = Cursor.from_result
871
872Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
873Cursor_visit = lib.clang_visitChildren
874Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
875Cursor_visit.restype = c_uint
876
877# Index Functions
878Index_create = lib.clang_createIndex
879Index_create.argtypes = [c_int]
880Index_create.restype = c_object_p
881
882Index_dispose = lib.clang_disposeIndex
883Index_dispose.argtypes = [Index]
884
885# Translation Unit Functions
886Diagnostic_callback = CFUNCTYPE(None, c_object_p, py_object)
887
888TranslationUnit_read = lib.clang_createTranslationUnit
889TranslationUnit_read.argtypes = [Index, c_char_p,
890                                 Diagnostic_callback, py_object]
891TranslationUnit_read.restype = c_object_p
892
893TranslationUnit_parse = lib.clang_createTranslationUnitFromSourceFile
894TranslationUnit_parse.argtypes = [Index, c_char_p, c_int, c_void_p,
895                                  c_int, c_void_p,
896                                  Diagnostic_callback, py_object]
897TranslationUnit_parse.restype = c_object_p
898
899TranslationUnit_cursor = lib.clang_getTranslationUnitCursor
900TranslationUnit_cursor.argtypes = [TranslationUnit]
901TranslationUnit_cursor.restype = Cursor
902TranslationUnit_cursor.errcheck = Cursor.from_result
903
904TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling
905TranslationUnit_spelling.argtypes = [TranslationUnit]
906TranslationUnit_spelling.restype = _CXString
907TranslationUnit_spelling.errcheck = _CXString.from_result
908
909TranslationUnit_dispose = lib.clang_disposeTranslationUnit
910TranslationUnit_dispose.argtypes = [TranslationUnit]
911
912TranslationUnit_includes_callback = CFUNCTYPE(None,
913                                              c_object_p,
914                                              POINTER(SourceLocation),
915                                              c_uint, py_object)
916TranslationUnit_includes = lib.clang_getInclusions
917TranslationUnit_includes.argtypes = [TranslationUnit,
918                                     TranslationUnit_includes_callback,
919                                     py_object]
920
921# File Functions
922File_name = lib.clang_getFileName
923File_name.argtypes = [File]
924File_name.restype = c_char_p
925
926File_time = lib.clang_getFileTime
927File_time.argtypes = [File]
928File_time.restype = c_uint
929
930###
931
932__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind',
933           'Diagnostic', 'FixIt', 'SourceRange', 'SourceLocation', 'File']
934