cindex.py revision 532fc63b51cd0eb795df36d3fe306645b8b980e4
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_getDiagnosticRanges = lib.clang_getDiagnosticRanges
559_clang_getDiagnosticRanges.argtypes = [c_object_p,
560                                       POINTER(POINTER(SourceRange)),
561                                       POINTER(c_uint)]
562_clang_getDiagnosticRanges.restype = None
563
564_clang_disposeDiagnosticRanges = lib.clang_disposeDiagnosticRanges
565_clang_disposeDiagnosticRanges.argtypes = [POINTER(SourceRange), c_uint]
566_clang_disposeDiagnosticRanges.restype = None
567
568_clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts
569_clang_getDiagnosticNumFixIts.argtypes = [c_object_p]
570_clang_getDiagnosticNumFixIts.restype = c_uint
571
572_clang_getDiagnosticFixItKind = lib.clang_getDiagnosticFixItKind
573_clang_getDiagnosticFixItKind.argtypes = [c_object_p, c_uint]
574_clang_getDiagnosticFixItKind.restype = c_int
575
576_clang_getDiagnosticFixItInsertion = lib.clang_getDiagnosticFixItInsertion
577_clang_getDiagnosticFixItInsertion.argtypes = [c_object_p, c_uint,
578                                               POINTER(SourceLocation)]
579_clang_getDiagnosticFixItInsertion.restype = _CXString
580_clang_getDiagnosticFixItInsertion.errcheck = _CXString.from_result
581
582_clang_getDiagnosticFixItRemoval = lib.clang_getDiagnosticFixItRemoval
583_clang_getDiagnosticFixItRemoval.argtypes = [c_object_p, c_uint,
584                                             POINTER(SourceLocation)]
585_clang_getDiagnosticFixItRemoval.restype = _CXString
586_clang_getDiagnosticFixItRemoval.errcheck = _CXString.from_result
587
588_clang_getDiagnosticFixItReplacement = lib.clang_getDiagnosticFixItReplacement
589_clang_getDiagnosticFixItReplacement.argtypes = [c_object_p, c_uint,
590                                                 POINTER(SourceRange)]
591_clang_getDiagnosticFixItReplacement.restype = _CXString
592_clang_getDiagnosticFixItReplacement.errcheck = _CXString.from_result
593
594def _convert_fixit(diag_ptr, index):
595    # We normalize all the fix-its to a single representation, this is more
596    # convenient.
597    #
598    # FIXME: Push this back into API? It isn't exactly clear what the
599    # SourceRange semantics are, we should make sure we can represent an empty
600    # range.
601    kind = _clang_getDiagnosticFixItKind(diag_ptr, index)
602    range = None
603    value = None
604    if kind == 0: # insertion
605        location = SourceLocation()
606        value = _clang_getDiagnosticFixItInsertion(diag_ptr, index,
607                                                   byref(location))
608        range = SourceRange.from_locations(location, location)
609    elif kind == 1: # removal
610        range = _clang_getDiagnosticFixItRemoval(diag_ptr, index)
611        value = ''
612    else: # replacement
613        assert kind == 2
614        range = SourceRange()
615        value = _clang_getDiagnosticFixItReplacement(diag_ptr, index,
616                                                     byref(range))
617    return FixIt(range, value)
618
619def _convert_diag(diag_ptr, diag_list):
620    severity = _clang_getDiagnosticSeverity(diag_ptr)
621    loc = _clang_getDiagnosticLocation(diag_ptr)
622    spelling = _clang_getDiagnosticSpelling(diag_ptr)
623
624    # Diagnostic ranges.
625    #
626    # FIXME: Use getNum... based API?
627    num_ranges = c_uint()
628    ranges_array = POINTER(SourceRange)()
629    _clang_getDiagnosticRanges(diag_ptr, byref(ranges_array), byref(num_ranges))
630
631    # Copy the ranges array so we can dispose the original.
632    ranges = [SourceRange.from_buffer_copy(ranges_array[i])
633              for i in range(num_ranges.value)]
634    _clang_disposeDiagnosticRanges(ranges_array, num_ranges)
635
636    fixits = [_convert_fixit(diag_ptr, i)
637              for i in range(_clang_getDiagnosticNumFixIts(diag_ptr))]
638
639    diag_list.append(Diagnostic(severity, loc, spelling, ranges, fixits))
640
641###
642
643class Index(ClangObject):
644    """
645    The Index type provides the primary interface to the Clang CIndex library,
646    primarily by providing an interface for reading and parsing translation
647    units.
648    """
649
650    @staticmethod
651    def create(excludeDecls=False):
652        """
653        Create a new Index.
654        Parameters:
655        excludeDecls -- Exclude local declarations from translation units.
656        """
657        return Index(Index_create(excludeDecls))
658
659    def __del__(self):
660        Index_dispose(self)
661
662    def read(self, path):
663        """Load the translation unit from the given AST file."""
664        # FIXME: In theory, we could support streaming diagnostics. It's hard to
665        # integrate this into the API cleanly, however. Resolve.
666        diags = []
667        ptr = TranslationUnit_read(self, path,
668                                   Diagnostic_callback(_convert_diag), diags)
669        return TranslationUnit(ptr) if ptr else None
670
671    def parse(self, path, args = [], unsaved_files = []):
672        """
673        Load the translation unit from the given source code file by running
674        clang and generating the AST before loading. Additional command line
675        parameters can be passed to clang via the args parameter.
676
677        In-memory contents for files can be provided by passing a list of pairs
678        to as unsaved_files, the first item should be the filenames to be mapped
679        and the second should be the contents to be substituted for the
680        file. The contents may be passed as strings or file objects.
681        """
682        arg_array = 0
683        if len(args):
684            arg_array = (c_char_p * len(args))(* args)
685        unsaved_files_array = 0
686        if len(unsaved_files):
687            unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))()
688            for i,(name,value) in enumerate(unsaved_files):
689                if not isinstance(value, str):
690                    # FIXME: It would be great to support an efficient version
691                    # of this, one day.
692                    value = value.read()
693                    print value
694                if not isinstance(value, str):
695                    raise TypeError,'Unexpected unsaved file contents.'
696                unsaved_files_array[i].name = name
697                unsaved_files_array[i].contents = value
698                unsaved_files_array[i].length = len(value)
699        # FIXME: In theory, we could support streaming diagnostics. It's hard to
700        # integrate this into the API cleanly, however. Resolve.
701        diags = []
702        ptr = TranslationUnit_parse(self, path, len(args), arg_array,
703                                    len(unsaved_files), unsaved_files_array,
704                                    Diagnostic_callback(_convert_diag), diags)
705        return TranslationUnit(ptr, diags) if ptr else None
706
707
708class TranslationUnit(ClangObject):
709    """
710    The TranslationUnit class represents a source code translation unit and
711    provides read-only access to its top-level declarations.
712    """
713
714    def __init__(self, ptr, diagnostics):
715        ClangObject.__init__(self, ptr)
716        self.diagnostics = diagnostics
717
718    def __del__(self):
719        TranslationUnit_dispose(self)
720
721    @property
722    def cursor(self):
723        """Retrieve the cursor that represents the given translation unit."""
724        return TranslationUnit_cursor(self)
725
726    @property
727    def spelling(self):
728        """Get the original translation unit source file name."""
729        return TranslationUnit_spelling(self)
730
731class File(ClangObject):
732    """
733    The File class represents a particular source file that is part of a
734    translation unit.
735    """
736
737    @property
738    def name(self):
739        """Return the complete file and path name of the file."""
740        return File_name(self)
741
742    @property
743    def time(self):
744        """Return the last modification time of the file."""
745        return File_time(self)
746
747# Additional Functions and Types
748
749# String Functions
750_CXString_dispose = lib.clang_disposeString
751_CXString_dispose.argtypes = [_CXString]
752
753_CXString_getCString = lib.clang_getCString
754_CXString_getCString.argtypes = [_CXString]
755_CXString_getCString.restype = c_char_p
756
757# Source Location Functions
758SourceLocation_loc = lib.clang_getInstantiationLocation
759SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p),
760                               POINTER(c_uint), POINTER(c_uint),
761                               POINTER(c_uint)]
762
763# Source Range Functions
764SourceRange_getRange = lib.clang_getRange
765SourceRange_getRange.argtypes = [SourceLocation, SourceLocation]
766SourceRange_getRange.restype = SourceRange
767
768SourceRange_start = lib.clang_getRangeStart
769SourceRange_start.argtypes = [SourceRange]
770SourceRange_start.restype = SourceLocation
771
772SourceRange_end = lib.clang_getRangeEnd
773SourceRange_end.argtypes = [SourceRange]
774SourceRange_end.restype = SourceLocation
775
776# CursorKind Functions
777CursorKind_is_decl = lib.clang_isDeclaration
778CursorKind_is_decl.argtypes = [CursorKind]
779CursorKind_is_decl.restype = bool
780
781CursorKind_is_ref = lib.clang_isReference
782CursorKind_is_ref.argtypes = [CursorKind]
783CursorKind_is_ref.restype = bool
784
785CursorKind_is_expr = lib.clang_isExpression
786CursorKind_is_expr.argtypes = [CursorKind]
787CursorKind_is_expr.restype = bool
788
789CursorKind_is_stmt = lib.clang_isStatement
790CursorKind_is_stmt.argtypes = [CursorKind]
791CursorKind_is_stmt.restype = bool
792
793CursorKind_is_inv = lib.clang_isInvalid
794CursorKind_is_inv.argtypes = [CursorKind]
795CursorKind_is_inv.restype = bool
796
797# Cursor Functions
798# TODO: Implement this function
799Cursor_get = lib.clang_getCursor
800Cursor_get.argtypes = [TranslationUnit, SourceLocation]
801Cursor_get.restype = Cursor
802
803Cursor_null = lib.clang_getNullCursor
804Cursor_null.restype = Cursor
805
806Cursor_usr = lib.clang_getCursorUSR
807Cursor_usr.argtypes = [Cursor]
808Cursor_usr.restype = _CXString
809Cursor_usr.errcheck = _CXString.from_result
810
811Cursor_is_def = lib.clang_isCursorDefinition
812Cursor_is_def.argtypes = [Cursor]
813Cursor_is_def.restype = bool
814
815Cursor_def = lib.clang_getCursorDefinition
816Cursor_def.argtypes = [Cursor]
817Cursor_def.restype = Cursor
818Cursor_def.errcheck = Cursor.from_result
819
820Cursor_eq = lib.clang_equalCursors
821Cursor_eq.argtypes = [Cursor, Cursor]
822Cursor_eq.restype = c_uint
823
824Cursor_spelling = lib.clang_getCursorSpelling
825Cursor_spelling.argtypes = [Cursor]
826Cursor_spelling.restype = _CXString
827Cursor_spelling.errcheck = _CXString.from_result
828
829Cursor_loc = lib.clang_getCursorLocation
830Cursor_loc.argtypes = [Cursor]
831Cursor_loc.restype = SourceLocation
832
833Cursor_extent = lib.clang_getCursorExtent
834Cursor_extent.argtypes = [Cursor]
835Cursor_extent.restype = SourceRange
836
837Cursor_ref = lib.clang_getCursorReferenced
838Cursor_ref.argtypes = [Cursor]
839Cursor_ref.restype = Cursor
840Cursor_ref.errcheck = Cursor.from_result
841
842Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
843Cursor_visit = lib.clang_visitChildren
844Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
845Cursor_visit.restype = c_uint
846
847# Index Functions
848Index_create = lib.clang_createIndex
849Index_create.argtypes = [c_int]
850Index_create.restype = c_object_p
851
852Index_dispose = lib.clang_disposeIndex
853Index_dispose.argtypes = [Index]
854
855# Translation Unit Functions
856Diagnostic_callback = CFUNCTYPE(None, c_object_p, py_object)
857
858TranslationUnit_read = lib.clang_createTranslationUnit
859TranslationUnit_read.argtypes = [Index, c_char_p,
860                                 Diagnostic_callback, py_object]
861TranslationUnit_read.restype = c_object_p
862
863TranslationUnit_parse = lib.clang_createTranslationUnitFromSourceFile
864TranslationUnit_parse.argtypes = [Index, c_char_p, c_int, c_void_p,
865                                  c_int, c_void_p,
866                                  Diagnostic_callback, py_object]
867TranslationUnit_parse.restype = c_object_p
868
869TranslationUnit_cursor = lib.clang_getTranslationUnitCursor
870TranslationUnit_cursor.argtypes = [TranslationUnit]
871TranslationUnit_cursor.restype = Cursor
872TranslationUnit_cursor.errcheck = Cursor.from_result
873
874TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling
875TranslationUnit_spelling.argtypes = [TranslationUnit]
876TranslationUnit_spelling.restype = _CXString
877TranslationUnit_spelling.errcheck = _CXString.from_result
878
879TranslationUnit_dispose = lib.clang_disposeTranslationUnit
880TranslationUnit_dispose.argtypes = [TranslationUnit]
881
882# File Functions
883File_name = lib.clang_getFileName
884File_name.argtypes = [File]
885File_name.restype = c_char_p
886
887File_time = lib.clang_getFileTime
888File_time.argtypes = [File]
889File_time.restype = c_uint
890
891###
892
893__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind',
894           'Diagnostic', 'FixIt', 'SourceRange', 'SourceLocation', 'File']
895