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