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