cindex.py revision f498e00a30ca7fdaf4f49e778862f4cf84ffab2a
1#===- cindex.py - Python Indexing Library Bindings -----------*- python -*--===# 2# 3# The LLVM Compiler Infrastructure 4# 5# This file is distributed under the University of Illinois Open Source 6# License. See LICENSE.TXT for details. 7# 8#===------------------------------------------------------------------------===# 9 10r""" 11Clang Indexing Library Bindings 12=============================== 13 14This module provides an interface to the Clang indexing library. It is a 15low-level interface to the indexing library which attempts to match the Clang 16API directly while also being "pythonic". Notable differences from the C API 17are: 18 19 * string results are returned as Python strings, not CXString objects. 20 21 * null cursors are translated to None. 22 23 * access to child cursors is done via iteration, not visitation. 24 25The major indexing objects are: 26 27 Index 28 29 The top-level object which manages some global library state. 30 31 TranslationUnit 32 33 High-level object encapsulating the AST for a single translation unit. These 34 can be loaded from .ast files or parsed on the fly. 35 36 Cursor 37 38 Generic object for representing a node in the AST. 39 40 SourceRange, SourceLocation, and File 41 42 Objects representing information about the input source. 43 44Most object information is exposed using properties, when the underlying API 45call is efficient. 46""" 47 48# TODO 49# ==== 50# 51# o API support for invalid translation units. Currently we can't even get the 52# diagnostics on failure because they refer to locations in an object that 53# will have been invalidated. 54# 55# o fix memory management issues (currently client must hold on to index and 56# translation unit, or risk crashes). 57# 58# o expose code completion APIs. 59# 60# o cleanup ctypes wrapping, would be nice to separate the ctypes details more 61# clearly, and hide from the external interface (i.e., help(cindex)). 62# 63# o implement additional SourceLocation, SourceRange, and File methods. 64 65from ctypes import * 66 67def get_cindex_library(): 68 # FIXME: It's probably not the case that the library is actually found in 69 # this location. We need a better system of identifying and loading the 70 # CIndex library. It could be on path or elsewhere, or versioned, etc. 71 import platform 72 name = platform.system() 73 if name == 'Darwin': 74 return cdll.LoadLibrary('libclang.dylib') 75 elif name == 'Windows': 76 return cdll.LoadLibrary('libclang.dll') 77 else: 78 return cdll.LoadLibrary('libclang.so') 79 80# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper 81# object. This is a problem, because it means that from_parameter will see an 82# integer and pass the wrong value on platforms where int != void*. Work around 83# this by marshalling object arguments as void**. 84c_object_p = POINTER(c_void_p) 85 86lib = get_cindex_library() 87 88### Structures and Utility Classes ### 89 90class _CXString(Structure): 91 """Helper for transforming CXString results.""" 92 93 _fields_ = [("spelling", c_char_p), ("free", c_int)] 94 95 def __del__(self): 96 _CXString_dispose(self) 97 98 @staticmethod 99 def from_result(res, fn, args): 100 assert isinstance(res, _CXString) 101 return _CXString_getCString(res) 102 103class SourceLocation(Structure): 104 """ 105 A SourceLocation represents a particular location within a source file. 106 """ 107 _fields_ = [("ptr_data", c_void_p * 2), ("int_data", c_uint)] 108 _data = None 109 110 def _get_instantiation(self): 111 if self._data is None: 112 f, l, c, o = c_object_p(), c_uint(), c_uint(), c_uint() 113 SourceLocation_loc(self, byref(f), byref(l), byref(c), byref(o)) 114 f = File(f) if f else None 115 self._data = (f, int(l.value), int(c.value), int(c.value)) 116 return self._data 117 118 @property 119 def file(self): 120 """Get the file represented by this source location.""" 121 return self._get_instantiation()[0] 122 123 @property 124 def line(self): 125 """Get the line represented by this source location.""" 126 return self._get_instantiation()[1] 127 128 @property 129 def column(self): 130 """Get the column represented by this source location.""" 131 return self._get_instantiation()[2] 132 133 @property 134 def offset(self): 135 """Get the file offset represented by this source location.""" 136 return self._get_instantiation()[3] 137 138 def __repr__(self): 139 return "<SourceLocation file %r, line %r, column %r>" % ( 140 self.file.name if self.file else None, self.line, self.column) 141 142class SourceRange(Structure): 143 """ 144 A SourceRange describes a range of source locations within the source 145 code. 146 """ 147 _fields_ = [ 148 ("ptr_data", c_void_p * 2), 149 ("begin_int_data", c_uint), 150 ("end_int_data", c_uint)] 151 152 # FIXME: Eliminate this and make normal constructor? Requires hiding ctypes 153 # object. 154 @staticmethod 155 def from_locations(start, end): 156 return SourceRange_getRange(start, end) 157 158 @property 159 def start(self): 160 """ 161 Return a SourceLocation representing the first character within a 162 source range. 163 """ 164 return SourceRange_start(self) 165 166 @property 167 def end(self): 168 """ 169 Return a SourceLocation representing the last character within a 170 source range. 171 """ 172 return SourceRange_end(self) 173 174 def __repr__(self): 175 return "<SourceRange start %r, end %r>" % (self.start, self.end) 176 177class Diagnostic(object): 178 """ 179 A Diagnostic is a single instance of a Clang diagnostic. It includes the 180 diagnostic severity, the message, the location the diagnostic occurred, as 181 well as additional source ranges and associated fix-it hints. 182 """ 183 184 Ignored = 0 185 Note = 1 186 Warning = 2 187 Error = 3 188 Fatal = 4 189 190 def __init__(self, ptr): 191 self.ptr = ptr 192 193 def __del__(self): 194 _clang_disposeDiagnostic(self) 195 196 @property 197 def severity(self): 198 return _clang_getDiagnosticSeverity(self) 199 200 @property 201 def location(self): 202 return _clang_getDiagnosticLocation(self) 203 204 @property 205 def spelling(self): 206 return _clang_getDiagnosticSpelling(self) 207 208 @property 209 def ranges(self): 210 class RangeIterator: 211 def __init__(self, diag): 212 self.diag = diag 213 214 def __len__(self): 215 return int(_clang_getDiagnosticNumRanges(self.diag)) 216 217 def __getitem__(self, key): 218 if (key >= len(self)): 219 raise IndexError 220 return _clang_getDiagnosticRange(self.diag, key) 221 222 return RangeIterator(self) 223 224 @property 225 def fixits(self): 226 class FixItIterator: 227 def __init__(self, diag): 228 self.diag = diag 229 230 def __len__(self): 231 return int(_clang_getDiagnosticNumFixIts(self.diag)) 232 233 def __getitem__(self, key): 234 range = SourceRange() 235 value = _clang_getDiagnosticFixIt(self.diag, key, byref(range)) 236 if len(value) == 0: 237 raise IndexError 238 239 return FixIt(range, value) 240 241 return FixItIterator(self) 242 243 def __repr__(self): 244 return "<Diagnostic severity %r, location %r, spelling %r>" % ( 245 self.severity, self.location, self.spelling) 246 247 def from_param(self): 248 return self.ptr 249 250class FixIt(object): 251 """ 252 A FixIt represents a transformation to be applied to the source to 253 "fix-it". The fix-it shouldbe applied by replacing the given source range 254 with the given value. 255 """ 256 257 def __init__(self, range, value): 258 self.range = range 259 self.value = value 260 261 def __repr__(self): 262 return "<FixIt range %r, value %r>" % (self.range, self.value) 263 264### Cursor Kinds ### 265 266class CursorKind(object): 267 """ 268 A CursorKind describes the kind of entity that a cursor points to. 269 """ 270 271 # The unique kind objects, indexed by id. 272 _kinds = [] 273 _name_map = None 274 275 def __init__(self, value): 276 if value >= len(CursorKind._kinds): 277 CursorKind._kinds += [None] * (value - len(CursorKind._kinds) + 1) 278 if CursorKind._kinds[value] is not None: 279 raise ValueError,'CursorKind already loaded' 280 self.value = value 281 CursorKind._kinds[value] = self 282 CursorKind._name_map = None 283 284 def from_param(self): 285 return self.value 286 287 @property 288 def name(self): 289 """Get the enumeration name of this cursor kind.""" 290 if self._name_map is None: 291 self._name_map = {} 292 for key,value in CursorKind.__dict__.items(): 293 if isinstance(value,CursorKind): 294 self._name_map[value] = key 295 return self._name_map[self] 296 297 @staticmethod 298 def from_id(id): 299 if id >= len(CursorKind._kinds) or CursorKind._kinds[id] is None: 300 raise ValueError,'Unknown cursor kind' 301 return CursorKind._kinds[id] 302 303 @staticmethod 304 def get_all_kinds(): 305 """Return all CursorKind enumeration instances.""" 306 return filter(None, CursorKind._kinds) 307 308 def is_declaration(self): 309 """Test if this is a declaration kind.""" 310 return CursorKind_is_decl(self) 311 312 def is_reference(self): 313 """Test if this is a reference kind.""" 314 return CursorKind_is_ref(self) 315 316 def is_expression(self): 317 """Test if this is an expression kind.""" 318 return CursorKind_is_expr(self) 319 320 def is_statement(self): 321 """Test if this is a statement kind.""" 322 return CursorKind_is_stmt(self) 323 324 def is_invalid(self): 325 """Test if this is an invalid kind.""" 326 return CursorKind_is_inv(self) 327 328 def __repr__(self): 329 return 'CursorKind.%s' % (self.name,) 330 331# FIXME: Is there a nicer way to expose this enumeration? We could potentially 332# represent the nested structure, or even build a class hierarchy. The main 333# things we want for sure are (a) simple external access to kinds, (b) a place 334# to hang a description and name, (c) easy to keep in sync with Index.h. 335 336### 337# Declaration Kinds 338 339# A declaration whose specific kind is not exposed via this interface. 340# 341# Unexposed declarations have the same operations as any other kind of 342# declaration; one can extract their location information, spelling, find their 343# definitions, etc. However, the specific kind of the declaration is not 344# reported. 345CursorKind.UNEXPOSED_DECL = CursorKind(1) 346 347# A C or C++ struct. 348CursorKind.STRUCT_DECL = CursorKind(2) 349 350# A C or C++ union. 351CursorKind.UNION_DECL = CursorKind(3) 352 353# A C++ class. 354CursorKind.CLASS_DECL = CursorKind(4) 355 356# An enumeration. 357CursorKind.ENUM_DECL = CursorKind(5) 358 359# A field (in C) or non-static data member (in C++) in a struct, union, or C++ 360# class. 361CursorKind.FIELD_DECL = CursorKind(6) 362 363# An enumerator constant. 364CursorKind.ENUM_CONSTANT_DECL = CursorKind(7) 365 366# A function. 367CursorKind.FUNCTION_DECL = CursorKind(8) 368 369# A variable. 370CursorKind.VAR_DECL = CursorKind(9) 371 372# A function or method parameter. 373CursorKind.PARM_DECL = CursorKind(10) 374 375# An Objective-C @interface. 376CursorKind.OBJC_INTERFACE_DECL = CursorKind(11) 377 378# An Objective-C @interface for a category. 379CursorKind.OBJC_CATEGORY_DECL = CursorKind(12) 380 381# An Objective-C @protocol declaration. 382CursorKind.OBJC_PROTOCOL_DECL = CursorKind(13) 383 384# An Objective-C @property declaration. 385CursorKind.OBJC_PROPERTY_DECL = CursorKind(14) 386 387# An Objective-C instance variable. 388CursorKind.OBJC_IVAR_DECL = CursorKind(15) 389 390# An Objective-C instance method. 391CursorKind.OBJC_INSTANCE_METHOD_DECL = CursorKind(16) 392 393# An Objective-C class method. 394CursorKind.OBJC_CLASS_METHOD_DECL = CursorKind(17) 395 396# An Objective-C @implementation. 397CursorKind.OBJC_IMPLEMENTATION_DECL = CursorKind(18) 398 399# An Objective-C @implementation for a category. 400CursorKind.OBJC_CATEGORY_IMPL_DECL = CursorKind(19) 401 402# A typedef. 403CursorKind.TYPEDEF_DECL = CursorKind(20) 404 405# A C++ class method. 406CursorKind.CXX_METHOD = CursorKind(21) 407 408# A C++ namespace. 409CursorKind.NAMESPACE = CursorKind(22) 410 411# A linkage specification, e.g. 'extern "C"'. 412CursorKind.LINKAGE_SPEC = CursorKind(23) 413 414# A C++ constructor. 415CursorKind.CONSTRUCTOR = CursorKind(24) 416 417# A C++ destructor. 418CursorKind.DESTRUCTOR = CursorKind(25) 419 420# A C++ conversion function. 421CursorKind.CONVERSION_FUNCTION = CursorKind(26) 422 423# A C++ template type parameter 424CursorKind.TEMPLATE_TYPE_PARAMETER = CursorKind(27) 425 426# A C++ non-type template paramater. 427CursorKind.TEMPLATE_NON_TYPE_PARAMETER = CursorKind(28) 428 429# A C++ template template parameter. 430CursorKind.TEMPLATE_TEMPLATE_PARAMTER = CursorKind(29) 431 432# A C++ function template. 433CursorKind.FUNCTION_TEMPLATE = CursorKind(30) 434 435# A C++ class template. 436CursorKind.CLASS_TEMPLATE = CursorKind(31) 437 438# A C++ class template partial specialization. 439CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION = CursorKind(32) 440 441# A C++ namespace alias declaration. 442CursorKind.NAMESPACE_ALIAS = CursorKind(33) 443 444# A C++ using directive 445CursorKind.USING_DIRECTIVE = CursorKind(34) 446 447# A C++ using declaration 448CursorKind.USING_DECLARATION = CursorKind(35) 449 450### 451# Reference Kinds 452 453CursorKind.OBJC_SUPER_CLASS_REF = CursorKind(40) 454CursorKind.OBJC_PROTOCOL_REF = CursorKind(41) 455CursorKind.OBJC_CLASS_REF = CursorKind(42) 456 457# A reference to a type declaration. 458# 459# A type reference occurs anywhere where a type is named but not 460# declared. For example, given: 461# typedef unsigned size_type; 462# size_type size; 463# 464# The typedef is a declaration of size_type (CXCursor_TypedefDecl), 465# while the type of the variable "size" is referenced. The cursor 466# referenced by the type of size is the typedef for size_type. 467CursorKind.TYPE_REF = CursorKind(43) 468CursorKind.CXX_BASE_SPECIFIER = CursorKind(44) 469 470# A reference to a class template, function template, template 471# template parameter, or class template partial specialization. 472CursorKind.TEMPLATE_REF = CursorKind(45) 473 474# A reference to a namespace or namepsace alias. 475CursorKind.NAMESPACE_REF = CursorKind(46) 476 477# A reference to a member of a struct, union, or class that occurs in 478# some non-expression context, e.g., a designated initializer. 479CursorKind.MEMBER_REF = CursorKind(47) 480 481# A reference to a labeled statement. 482CursorKind.LABEL_REF = CursorKind(48) 483 484# A reference toa a set of overloaded functions or function templates 485# that has not yet been resolved to a specific function or function template. 486CursorKind.OVERLOADED_DECL_REF = CursorKind(49) 487 488### 489# Invalid/Error Kinds 490 491CursorKind.INVALID_FILE = CursorKind(70) 492CursorKind.NO_DECL_FOUND = CursorKind(71) 493CursorKind.NOT_IMPLEMENTED = CursorKind(72) 494CursorKind.INVALID_CODE = CursorKind(73) 495 496### 497# Expression Kinds 498 499# An expression whose specific kind is not exposed via this interface. 500# 501# Unexposed expressions have the same operations as any other kind of 502# expression; one can extract their location information, spelling, children, 503# etc. However, the specific kind of the expression is not reported. 504CursorKind.UNEXPOSED_EXPR = CursorKind(100) 505 506# An expression that refers to some value declaration, such as a function, 507# varible, or enumerator. 508CursorKind.DECL_REF_EXPR = CursorKind(101) 509 510# An expression that refers to a member of a struct, union, class, Objective-C 511# class, etc. 512CursorKind.MEMBER_REF_EXPR = CursorKind(102) 513 514# An expression that calls a function. 515CursorKind.CALL_EXPR = CursorKind(103) 516 517# An expression that sends a message to an Objective-C object or class. 518CursorKind.OBJC_MESSAGE_EXPR = CursorKind(104) 519 520# An expression that represents a block literal. 521CursorKind.BLOCK_EXPR = CursorKind(105) 522 523# A statement whose specific kind is not exposed via this interface. 524# 525# Unexposed statements have the same operations as any other kind of statement; 526# one can extract their location information, spelling, children, etc. However, 527# the specific kind of the statement is not reported. 528CursorKind.UNEXPOSED_STMT = CursorKind(200) 529 530# A labelled statement in a function. 531CursorKind.LABEL_STMT = CursorKind(201) 532 533 534### 535# Other Kinds 536 537# Cursor that represents the translation unit itself. 538# 539# The translation unit cursor exists primarily to act as the root cursor for 540# traversing the contents of a translation unit. 541CursorKind.TRANSLATION_UNIT = CursorKind(300) 542 543### 544# Attributes 545 546# An attribute whoe specific kind is note exposed via this interface 547CursorKind.UNEXPOSED_ATTR = CursorKind(400) 548 549CursorKind.IB_ACTION_ATTR = CursorKind(401) 550CursorKind.IB_OUTLET_ATTR = CursorKind(402) 551CursorKind.IB_OUTLET_COLLECTION_ATTR = CursorKind(403) 552 553### 554# Preprocessing 555CursorKind.PREPROCESSING_DIRECTIVE = CursorKind(500) 556CursorKind.MACRO_DEFINITION = CursorKind(501) 557CursorKind.MACRO_INSTANTIATION = CursorKind(502) 558CursorKind.INCLUSION_DIRECTIVE = CursorKind(503) 559 560### Cursors ### 561 562class Cursor(Structure): 563 """ 564 The Cursor class represents a reference to an element within the AST. It 565 acts as a kind of iterator. 566 """ 567 _fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)] 568 569 def __eq__(self, other): 570 return Cursor_eq(self, other) 571 572 def __ne__(self, other): 573 return not Cursor_eq(self, other) 574 575 def is_definition(self): 576 """ 577 Returns true if the declaration pointed at by the cursor is also a 578 definition of that entity. 579 """ 580 return Cursor_is_def(self) 581 582 def get_definition(self): 583 """ 584 If the cursor is a reference to a declaration or a declaration of 585 some entity, return a cursor that points to the definition of that 586 entity. 587 """ 588 # TODO: Should probably check that this is either a reference or 589 # declaration prior to issuing the lookup. 590 return Cursor_def(self) 591 592 def get_usr(self): 593 """Return the Unified Symbol Resultion (USR) for the entity referenced 594 by the given cursor (or None). 595 596 A Unified Symbol Resolution (USR) is a string that identifies a 597 particular entity (function, class, variable, etc.) within a 598 program. USRs can be compared across translation units to determine, 599 e.g., when references in one translation refer to an entity defined in 600 another translation unit.""" 601 return Cursor_usr(self) 602 603 @property 604 def kind(self): 605 """Return the kind of this cursor.""" 606 return CursorKind.from_id(self._kind_id) 607 608 @property 609 def spelling(self): 610 """Return the spelling of the entity pointed at by the cursor.""" 611 if not self.kind.is_declaration(): 612 # FIXME: clang_getCursorSpelling should be fixed to not assert on 613 # this, for consistency with clang_getCursorUSR. 614 return None 615 return Cursor_spelling(self) 616 617 @property 618 def location(self): 619 """ 620 Return the source location (the starting character) of the entity 621 pointed at by the cursor. 622 """ 623 return Cursor_loc(self) 624 625 @property 626 def extent(self): 627 """ 628 Return the source range (the range of text) occupied by the entity 629 pointed at by the cursor. 630 """ 631 return Cursor_extent(self) 632 633 def get_children(self): 634 """Return an iterator for accessing the children of this cursor.""" 635 636 # FIXME: Expose iteration from CIndex, PR6125. 637 def visitor(child, parent, children): 638 # FIXME: Document this assertion in API. 639 # FIXME: There should just be an isNull method. 640 assert child != Cursor_null() 641 children.append(child) 642 return 1 # continue 643 children = [] 644 Cursor_visit(self, Cursor_visit_callback(visitor), children) 645 return iter(children) 646 647 @staticmethod 648 def from_result(res, fn, args): 649 assert isinstance(res, Cursor) 650 # FIXME: There should just be an isNull method. 651 if res == Cursor_null(): 652 return None 653 return res 654 655## CIndex Objects ## 656 657# CIndex objects (derived from ClangObject) are essentially lightweight 658# wrappers attached to some underlying object, which is exposed via CIndex as 659# a void*. 660 661class ClangObject(object): 662 """ 663 A helper for Clang objects. This class helps act as an intermediary for 664 the ctypes library and the Clang CIndex library. 665 """ 666 def __init__(self, obj): 667 assert isinstance(obj, c_object_p) and obj 668 self.obj = self._as_parameter_ = obj 669 670 def from_param(self): 671 return self._as_parameter_ 672 673 674class _CXUnsavedFile(Structure): 675 """Helper for passing unsaved file arguments.""" 676 _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)] 677 678## Diagnostic Conversion ## 679 680_clang_getNumDiagnostics = lib.clang_getNumDiagnostics 681_clang_getNumDiagnostics.argtypes = [c_object_p] 682_clang_getNumDiagnostics.restype = c_uint 683 684_clang_getDiagnostic = lib.clang_getDiagnostic 685_clang_getDiagnostic.argtypes = [c_object_p, c_uint] 686_clang_getDiagnostic.restype = c_object_p 687 688_clang_disposeDiagnostic = lib.clang_disposeDiagnostic 689_clang_disposeDiagnostic.argtypes = [Diagnostic] 690 691_clang_getDiagnosticSeverity = lib.clang_getDiagnosticSeverity 692_clang_getDiagnosticSeverity.argtypes = [Diagnostic] 693_clang_getDiagnosticSeverity.restype = c_int 694 695_clang_getDiagnosticLocation = lib.clang_getDiagnosticLocation 696_clang_getDiagnosticLocation.argtypes = [Diagnostic] 697_clang_getDiagnosticLocation.restype = SourceLocation 698 699_clang_getDiagnosticSpelling = lib.clang_getDiagnosticSpelling 700_clang_getDiagnosticSpelling.argtypes = [Diagnostic] 701_clang_getDiagnosticSpelling.restype = _CXString 702_clang_getDiagnosticSpelling.errcheck = _CXString.from_result 703 704_clang_getDiagnosticNumRanges = lib.clang_getDiagnosticNumRanges 705_clang_getDiagnosticNumRanges.argtypes = [Diagnostic] 706_clang_getDiagnosticNumRanges.restype = c_uint 707 708_clang_getDiagnosticRange = lib.clang_getDiagnosticRange 709_clang_getDiagnosticRange.argtypes = [Diagnostic, c_uint] 710_clang_getDiagnosticRange.restype = SourceRange 711 712_clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts 713_clang_getDiagnosticNumFixIts.argtypes = [Diagnostic] 714_clang_getDiagnosticNumFixIts.restype = c_uint 715 716_clang_getDiagnosticFixIt = lib.clang_getDiagnosticFixIt 717_clang_getDiagnosticFixIt.argtypes = [Diagnostic, c_uint, POINTER(SourceRange)] 718_clang_getDiagnosticFixIt.restype = _CXString 719_clang_getDiagnosticFixIt.errcheck = _CXString.from_result 720 721### 722 723class Index(ClangObject): 724 """ 725 The Index type provides the primary interface to the Clang CIndex library, 726 primarily by providing an interface for reading and parsing translation 727 units. 728 """ 729 730 @staticmethod 731 def create(excludeDecls=False): 732 """ 733 Create a new Index. 734 Parameters: 735 excludeDecls -- Exclude local declarations from translation units. 736 """ 737 return Index(Index_create(excludeDecls, 0)) 738 739 def __del__(self): 740 Index_dispose(self) 741 742 def read(self, path): 743 """Load the translation unit from the given AST file.""" 744 ptr = TranslationUnit_read(self, path) 745 return TranslationUnit(ptr) if ptr else None 746 747 def parse(self, path, args = [], unsaved_files = []): 748 """ 749 Load the translation unit from the given source code file by running 750 clang and generating the AST before loading. Additional command line 751 parameters can be passed to clang via the args parameter. 752 753 In-memory contents for files can be provided by passing a list of pairs 754 to as unsaved_files, the first item should be the filenames to be mapped 755 and the second should be the contents to be substituted for the 756 file. The contents may be passed as strings or file objects. 757 """ 758 arg_array = 0 759 if len(args): 760 arg_array = (c_char_p * len(args))(* args) 761 unsaved_files_array = 0 762 if len(unsaved_files): 763 unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() 764 for i,(name,value) in enumerate(unsaved_files): 765 if not isinstance(value, str): 766 # FIXME: It would be great to support an efficient version 767 # of this, one day. 768 value = value.read() 769 print value 770 if not isinstance(value, str): 771 raise TypeError,'Unexpected unsaved file contents.' 772 unsaved_files_array[i].name = name 773 unsaved_files_array[i].contents = value 774 unsaved_files_array[i].length = len(value) 775 ptr = TranslationUnit_parse(self, path, len(args), arg_array, 776 len(unsaved_files), unsaved_files_array) 777 return TranslationUnit(ptr) if ptr else None 778 779 780class TranslationUnit(ClangObject): 781 """ 782 The TranslationUnit class represents a source code translation unit and 783 provides read-only access to its top-level declarations. 784 """ 785 786 def __init__(self, ptr): 787 ClangObject.__init__(self, ptr) 788 789 def __del__(self): 790 TranslationUnit_dispose(self) 791 792 @property 793 def cursor(self): 794 """Retrieve the cursor that represents the given translation unit.""" 795 return TranslationUnit_cursor(self) 796 797 @property 798 def spelling(self): 799 """Get the original translation unit source file name.""" 800 return TranslationUnit_spelling(self) 801 802 def get_includes(self): 803 """ 804 Return an iterable sequence of FileInclusion objects that describe the 805 sequence of inclusions in a translation unit. The first object in 806 this sequence is always the input file. Note that this method will not 807 recursively iterate over header files included through precompiled 808 headers. 809 """ 810 def visitor(fobj, lptr, depth, includes): 811 loc = lptr.contents 812 includes.append(FileInclusion(loc.file, File(fobj), loc, depth)) 813 814 # Automatically adapt CIndex/ctype pointers to python objects 815 includes = [] 816 TranslationUnit_includes(self, 817 TranslationUnit_includes_callback(visitor), 818 includes) 819 return iter(includes) 820 821 @property 822 def diagnostics(self): 823 """ 824 Return an iterable (and indexable) object containing the diagnostics. 825 """ 826 class DiagIterator: 827 def __init__(self, tu): 828 self.tu = tu 829 830 def __len__(self): 831 return int(_clang_getNumDiagnostics(self.tu)) 832 833 def __getitem__(self, key): 834 diag = _clang_getDiagnostic(self.tu, key) 835 if not diag: 836 raise IndexError 837 return Diagnostic(diag) 838 839 return DiagIterator(self) 840 841class File(ClangObject): 842 """ 843 The File class represents a particular source file that is part of a 844 translation unit. 845 """ 846 847 @property 848 def name(self): 849 """Return the complete file and path name of the file.""" 850 return File_name(self) 851 852 @property 853 def time(self): 854 """Return the last modification time of the file.""" 855 return File_time(self) 856 857class FileInclusion(object): 858 """ 859 The FileInclusion class represents the inclusion of one source file by 860 another via a '#include' directive or as the input file for the translation 861 unit. This class provides information about the included file, the including 862 file, the location of the '#include' directive and the depth of the included 863 file in the stack. Note that the input file has depth 0. 864 """ 865 866 def __init__(self, src, tgt, loc, depth): 867 self.source = src 868 self.include = tgt 869 self.location = loc 870 self.depth = depth 871 872 @property 873 def is_input_file(self): 874 """True if the included file is the input file.""" 875 return self.depth == 0 876 877# Additional Functions and Types 878 879# String Functions 880_CXString_dispose = lib.clang_disposeString 881_CXString_dispose.argtypes = [_CXString] 882 883_CXString_getCString = lib.clang_getCString 884_CXString_getCString.argtypes = [_CXString] 885_CXString_getCString.restype = c_char_p 886 887# Source Location Functions 888SourceLocation_loc = lib.clang_getInstantiationLocation 889SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p), 890 POINTER(c_uint), POINTER(c_uint), 891 POINTER(c_uint)] 892 893# Source Range Functions 894SourceRange_getRange = lib.clang_getRange 895SourceRange_getRange.argtypes = [SourceLocation, SourceLocation] 896SourceRange_getRange.restype = SourceRange 897 898SourceRange_start = lib.clang_getRangeStart 899SourceRange_start.argtypes = [SourceRange] 900SourceRange_start.restype = SourceLocation 901 902SourceRange_end = lib.clang_getRangeEnd 903SourceRange_end.argtypes = [SourceRange] 904SourceRange_end.restype = SourceLocation 905 906# CursorKind Functions 907CursorKind_is_decl = lib.clang_isDeclaration 908CursorKind_is_decl.argtypes = [CursorKind] 909CursorKind_is_decl.restype = bool 910 911CursorKind_is_ref = lib.clang_isReference 912CursorKind_is_ref.argtypes = [CursorKind] 913CursorKind_is_ref.restype = bool 914 915CursorKind_is_expr = lib.clang_isExpression 916CursorKind_is_expr.argtypes = [CursorKind] 917CursorKind_is_expr.restype = bool 918 919CursorKind_is_stmt = lib.clang_isStatement 920CursorKind_is_stmt.argtypes = [CursorKind] 921CursorKind_is_stmt.restype = bool 922 923CursorKind_is_inv = lib.clang_isInvalid 924CursorKind_is_inv.argtypes = [CursorKind] 925CursorKind_is_inv.restype = bool 926 927# Cursor Functions 928# TODO: Implement this function 929Cursor_get = lib.clang_getCursor 930Cursor_get.argtypes = [TranslationUnit, SourceLocation] 931Cursor_get.restype = Cursor 932 933Cursor_null = lib.clang_getNullCursor 934Cursor_null.restype = Cursor 935 936Cursor_usr = lib.clang_getCursorUSR 937Cursor_usr.argtypes = [Cursor] 938Cursor_usr.restype = _CXString 939Cursor_usr.errcheck = _CXString.from_result 940 941Cursor_is_def = lib.clang_isCursorDefinition 942Cursor_is_def.argtypes = [Cursor] 943Cursor_is_def.restype = bool 944 945Cursor_def = lib.clang_getCursorDefinition 946Cursor_def.argtypes = [Cursor] 947Cursor_def.restype = Cursor 948Cursor_def.errcheck = Cursor.from_result 949 950Cursor_eq = lib.clang_equalCursors 951Cursor_eq.argtypes = [Cursor, Cursor] 952Cursor_eq.restype = c_uint 953 954Cursor_spelling = lib.clang_getCursorSpelling 955Cursor_spelling.argtypes = [Cursor] 956Cursor_spelling.restype = _CXString 957Cursor_spelling.errcheck = _CXString.from_result 958 959Cursor_loc = lib.clang_getCursorLocation 960Cursor_loc.argtypes = [Cursor] 961Cursor_loc.restype = SourceLocation 962 963Cursor_extent = lib.clang_getCursorExtent 964Cursor_extent.argtypes = [Cursor] 965Cursor_extent.restype = SourceRange 966 967Cursor_ref = lib.clang_getCursorReferenced 968Cursor_ref.argtypes = [Cursor] 969Cursor_ref.restype = Cursor 970Cursor_ref.errcheck = Cursor.from_result 971 972Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object) 973Cursor_visit = lib.clang_visitChildren 974Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object] 975Cursor_visit.restype = c_uint 976 977# Index Functions 978Index_create = lib.clang_createIndex 979Index_create.argtypes = [c_int, c_int] 980Index_create.restype = c_object_p 981 982Index_dispose = lib.clang_disposeIndex 983Index_dispose.argtypes = [Index] 984 985# Translation Unit Functions 986TranslationUnit_read = lib.clang_createTranslationUnit 987TranslationUnit_read.argtypes = [Index, c_char_p] 988TranslationUnit_read.restype = c_object_p 989 990TranslationUnit_parse = lib.clang_createTranslationUnitFromSourceFile 991TranslationUnit_parse.argtypes = [Index, c_char_p, c_int, c_void_p, 992 c_int, c_void_p] 993TranslationUnit_parse.restype = c_object_p 994 995TranslationUnit_cursor = lib.clang_getTranslationUnitCursor 996TranslationUnit_cursor.argtypes = [TranslationUnit] 997TranslationUnit_cursor.restype = Cursor 998TranslationUnit_cursor.errcheck = Cursor.from_result 999 1000TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling 1001TranslationUnit_spelling.argtypes = [TranslationUnit] 1002TranslationUnit_spelling.restype = _CXString 1003TranslationUnit_spelling.errcheck = _CXString.from_result 1004 1005TranslationUnit_dispose = lib.clang_disposeTranslationUnit 1006TranslationUnit_dispose.argtypes = [TranslationUnit] 1007 1008TranslationUnit_includes_callback = CFUNCTYPE(None, 1009 c_object_p, 1010 POINTER(SourceLocation), 1011 c_uint, py_object) 1012TranslationUnit_includes = lib.clang_getInclusions 1013TranslationUnit_includes.argtypes = [TranslationUnit, 1014 TranslationUnit_includes_callback, 1015 py_object] 1016 1017# File Functions 1018File_name = lib.clang_getFileName 1019File_name.argtypes = [File] 1020File_name.restype = c_char_p 1021 1022File_time = lib.clang_getFileTime 1023File_time.argtypes = [File] 1024File_time.restype = c_uint 1025 1026### 1027 1028__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind', 1029 'Diagnostic', 'FixIt', 'SourceRange', 'SourceLocation', 'File'] 1030