cindex.py revision 8be80e1e6effd5a333bc70e7f030dc9397d0554e
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_attribute(self): 325 """Test if this is an attribute kind.""" 326 return CursorKind_is_attribute(self) 327 328 def is_invalid(self): 329 """Test if this is an invalid kind.""" 330 return CursorKind_is_inv(self) 331 332 def __repr__(self): 333 return 'CursorKind.%s' % (self.name,) 334 335# FIXME: Is there a nicer way to expose this enumeration? We could potentially 336# represent the nested structure, or even build a class hierarchy. The main 337# things we want for sure are (a) simple external access to kinds, (b) a place 338# to hang a description and name, (c) easy to keep in sync with Index.h. 339 340### 341# Declaration Kinds 342 343# A declaration whose specific kind is not exposed via this interface. 344# 345# Unexposed declarations have the same operations as any other kind of 346# declaration; one can extract their location information, spelling, find their 347# definitions, etc. However, the specific kind of the declaration is not 348# reported. 349CursorKind.UNEXPOSED_DECL = CursorKind(1) 350 351# A C or C++ struct. 352CursorKind.STRUCT_DECL = CursorKind(2) 353 354# A C or C++ union. 355CursorKind.UNION_DECL = CursorKind(3) 356 357# A C++ class. 358CursorKind.CLASS_DECL = CursorKind(4) 359 360# An enumeration. 361CursorKind.ENUM_DECL = CursorKind(5) 362 363# A field (in C) or non-static data member (in C++) in a struct, union, or C++ 364# class. 365CursorKind.FIELD_DECL = CursorKind(6) 366 367# An enumerator constant. 368CursorKind.ENUM_CONSTANT_DECL = CursorKind(7) 369 370# A function. 371CursorKind.FUNCTION_DECL = CursorKind(8) 372 373# A variable. 374CursorKind.VAR_DECL = CursorKind(9) 375 376# A function or method parameter. 377CursorKind.PARM_DECL = CursorKind(10) 378 379# An Objective-C @interface. 380CursorKind.OBJC_INTERFACE_DECL = CursorKind(11) 381 382# An Objective-C @interface for a category. 383CursorKind.OBJC_CATEGORY_DECL = CursorKind(12) 384 385# An Objective-C @protocol declaration. 386CursorKind.OBJC_PROTOCOL_DECL = CursorKind(13) 387 388# An Objective-C @property declaration. 389CursorKind.OBJC_PROPERTY_DECL = CursorKind(14) 390 391# An Objective-C instance variable. 392CursorKind.OBJC_IVAR_DECL = CursorKind(15) 393 394# An Objective-C instance method. 395CursorKind.OBJC_INSTANCE_METHOD_DECL = CursorKind(16) 396 397# An Objective-C class method. 398CursorKind.OBJC_CLASS_METHOD_DECL = CursorKind(17) 399 400# An Objective-C @implementation. 401CursorKind.OBJC_IMPLEMENTATION_DECL = CursorKind(18) 402 403# An Objective-C @implementation for a category. 404CursorKind.OBJC_CATEGORY_IMPL_DECL = CursorKind(19) 405 406# A typedef. 407CursorKind.TYPEDEF_DECL = CursorKind(20) 408 409# A C++ class method. 410CursorKind.CXX_METHOD = CursorKind(21) 411 412# A C++ namespace. 413CursorKind.NAMESPACE = CursorKind(22) 414 415# A linkage specification, e.g. 'extern "C"'. 416CursorKind.LINKAGE_SPEC = CursorKind(23) 417 418# A C++ constructor. 419CursorKind.CONSTRUCTOR = CursorKind(24) 420 421# A C++ destructor. 422CursorKind.DESTRUCTOR = CursorKind(25) 423 424# A C++ conversion function. 425CursorKind.CONVERSION_FUNCTION = CursorKind(26) 426 427# A C++ template type parameter 428CursorKind.TEMPLATE_TYPE_PARAMETER = CursorKind(27) 429 430# A C++ non-type template paramater. 431CursorKind.TEMPLATE_NON_TYPE_PARAMETER = CursorKind(28) 432 433# A C++ template template parameter. 434CursorKind.TEMPLATE_TEMPLATE_PARAMTER = CursorKind(29) 435 436# A C++ function template. 437CursorKind.FUNCTION_TEMPLATE = CursorKind(30) 438 439# A C++ class template. 440CursorKind.CLASS_TEMPLATE = CursorKind(31) 441 442# A C++ class template partial specialization. 443CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION = CursorKind(32) 444 445# A C++ namespace alias declaration. 446CursorKind.NAMESPACE_ALIAS = CursorKind(33) 447 448# A C++ using directive 449CursorKind.USING_DIRECTIVE = CursorKind(34) 450 451# A C++ using declaration 452CursorKind.USING_DECLARATION = CursorKind(35) 453 454### 455# Reference Kinds 456 457CursorKind.OBJC_SUPER_CLASS_REF = CursorKind(40) 458CursorKind.OBJC_PROTOCOL_REF = CursorKind(41) 459CursorKind.OBJC_CLASS_REF = CursorKind(42) 460 461# A reference to a type declaration. 462# 463# A type reference occurs anywhere where a type is named but not 464# declared. For example, given: 465# typedef unsigned size_type; 466# size_type size; 467# 468# The typedef is a declaration of size_type (CXCursor_TypedefDecl), 469# while the type of the variable "size" is referenced. The cursor 470# referenced by the type of size is the typedef for size_type. 471CursorKind.TYPE_REF = CursorKind(43) 472CursorKind.CXX_BASE_SPECIFIER = CursorKind(44) 473 474# A reference to a class template, function template, template 475# template parameter, or class template partial specialization. 476CursorKind.TEMPLATE_REF = CursorKind(45) 477 478# A reference to a namespace or namepsace alias. 479CursorKind.NAMESPACE_REF = CursorKind(46) 480 481# A reference to a member of a struct, union, or class that occurs in 482# some non-expression context, e.g., a designated initializer. 483CursorKind.MEMBER_REF = CursorKind(47) 484 485# A reference to a labeled statement. 486CursorKind.LABEL_REF = CursorKind(48) 487 488# A reference toa a set of overloaded functions or function templates 489# that has not yet been resolved to a specific function or function template. 490CursorKind.OVERLOADED_DECL_REF = CursorKind(49) 491 492### 493# Invalid/Error Kinds 494 495CursorKind.INVALID_FILE = CursorKind(70) 496CursorKind.NO_DECL_FOUND = CursorKind(71) 497CursorKind.NOT_IMPLEMENTED = CursorKind(72) 498CursorKind.INVALID_CODE = CursorKind(73) 499 500### 501# Expression Kinds 502 503# An expression whose specific kind is not exposed via this interface. 504# 505# Unexposed expressions have the same operations as any other kind of 506# expression; one can extract their location information, spelling, children, 507# etc. However, the specific kind of the expression is not reported. 508CursorKind.UNEXPOSED_EXPR = CursorKind(100) 509 510# An expression that refers to some value declaration, such as a function, 511# varible, or enumerator. 512CursorKind.DECL_REF_EXPR = CursorKind(101) 513 514# An expression that refers to a member of a struct, union, class, Objective-C 515# class, etc. 516CursorKind.MEMBER_REF_EXPR = CursorKind(102) 517 518# An expression that calls a function. 519CursorKind.CALL_EXPR = CursorKind(103) 520 521# An expression that sends a message to an Objective-C object or class. 522CursorKind.OBJC_MESSAGE_EXPR = CursorKind(104) 523 524# An expression that represents a block literal. 525CursorKind.BLOCK_EXPR = CursorKind(105) 526 527# A statement whose specific kind is not exposed via this interface. 528# 529# Unexposed statements have the same operations as any other kind of statement; 530# one can extract their location information, spelling, children, etc. However, 531# the specific kind of the statement is not reported. 532CursorKind.UNEXPOSED_STMT = CursorKind(200) 533 534# A labelled statement in a function. 535CursorKind.LABEL_STMT = CursorKind(201) 536 537 538### 539# Other Kinds 540 541# Cursor that represents the translation unit itself. 542# 543# The translation unit cursor exists primarily to act as the root cursor for 544# traversing the contents of a translation unit. 545CursorKind.TRANSLATION_UNIT = CursorKind(300) 546 547### 548# Attributes 549 550# An attribute whoe specific kind is note exposed via this interface 551CursorKind.UNEXPOSED_ATTR = CursorKind(400) 552 553CursorKind.IB_ACTION_ATTR = CursorKind(401) 554CursorKind.IB_OUTLET_ATTR = CursorKind(402) 555CursorKind.IB_OUTLET_COLLECTION_ATTR = CursorKind(403) 556 557### 558# Preprocessing 559CursorKind.PREPROCESSING_DIRECTIVE = CursorKind(500) 560CursorKind.MACRO_DEFINITION = CursorKind(501) 561CursorKind.MACRO_INSTANTIATION = CursorKind(502) 562CursorKind.INCLUSION_DIRECTIVE = CursorKind(503) 563 564### Cursors ### 565 566class Cursor(Structure): 567 """ 568 The Cursor class represents a reference to an element within the AST. It 569 acts as a kind of iterator. 570 """ 571 _fields_ = [("_kind_id", c_int), ("data", c_void_p * 3)] 572 573 def __eq__(self, other): 574 return Cursor_eq(self, other) 575 576 def __ne__(self, other): 577 return not Cursor_eq(self, other) 578 579 def is_definition(self): 580 """ 581 Returns true if the declaration pointed at by the cursor is also a 582 definition of that entity. 583 """ 584 return Cursor_is_def(self) 585 586 def get_definition(self): 587 """ 588 If the cursor is a reference to a declaration or a declaration of 589 some entity, return a cursor that points to the definition of that 590 entity. 591 """ 592 # TODO: Should probably check that this is either a reference or 593 # declaration prior to issuing the lookup. 594 return Cursor_def(self) 595 596 def get_usr(self): 597 """Return the Unified Symbol Resultion (USR) for the entity referenced 598 by the given cursor (or None). 599 600 A Unified Symbol Resolution (USR) is a string that identifies a 601 particular entity (function, class, variable, etc.) within a 602 program. USRs can be compared across translation units to determine, 603 e.g., when references in one translation refer to an entity defined in 604 another translation unit.""" 605 return Cursor_usr(self) 606 607 @property 608 def kind(self): 609 """Return the kind of this cursor.""" 610 return CursorKind.from_id(self._kind_id) 611 612 @property 613 def spelling(self): 614 """Return the spelling of the entity pointed at by the cursor.""" 615 if not self.kind.is_declaration(): 616 # FIXME: clang_getCursorSpelling should be fixed to not assert on 617 # this, for consistency with clang_getCursorUSR. 618 return None 619 return Cursor_spelling(self) 620 621 @property 622 def location(self): 623 """ 624 Return the source location (the starting character) of the entity 625 pointed at by the cursor. 626 """ 627 return Cursor_loc(self) 628 629 @property 630 def extent(self): 631 """ 632 Return the source range (the range of text) occupied by the entity 633 pointed at by the cursor. 634 """ 635 return Cursor_extent(self) 636 637 def get_children(self): 638 """Return an iterator for accessing the children of this cursor.""" 639 640 # FIXME: Expose iteration from CIndex, PR6125. 641 def visitor(child, parent, children): 642 # FIXME: Document this assertion in API. 643 # FIXME: There should just be an isNull method. 644 assert child != Cursor_null() 645 children.append(child) 646 return 1 # continue 647 children = [] 648 Cursor_visit(self, Cursor_visit_callback(visitor), children) 649 return iter(children) 650 651 @staticmethod 652 def from_result(res, fn, args): 653 assert isinstance(res, Cursor) 654 # FIXME: There should just be an isNull method. 655 if res == Cursor_null(): 656 return None 657 return res 658 659## CIndex Objects ## 660 661# CIndex objects (derived from ClangObject) are essentially lightweight 662# wrappers attached to some underlying object, which is exposed via CIndex as 663# a void*. 664 665class ClangObject(object): 666 """ 667 A helper for Clang objects. This class helps act as an intermediary for 668 the ctypes library and the Clang CIndex library. 669 """ 670 def __init__(self, obj): 671 assert isinstance(obj, c_object_p) and obj 672 self.obj = self._as_parameter_ = obj 673 674 def from_param(self): 675 return self._as_parameter_ 676 677 678class _CXUnsavedFile(Structure): 679 """Helper for passing unsaved file arguments.""" 680 _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)] 681 682## Diagnostic Conversion ## 683 684_clang_getNumDiagnostics = lib.clang_getNumDiagnostics 685_clang_getNumDiagnostics.argtypes = [c_object_p] 686_clang_getNumDiagnostics.restype = c_uint 687 688_clang_getDiagnostic = lib.clang_getDiagnostic 689_clang_getDiagnostic.argtypes = [c_object_p, c_uint] 690_clang_getDiagnostic.restype = c_object_p 691 692_clang_disposeDiagnostic = lib.clang_disposeDiagnostic 693_clang_disposeDiagnostic.argtypes = [Diagnostic] 694 695_clang_getDiagnosticSeverity = lib.clang_getDiagnosticSeverity 696_clang_getDiagnosticSeverity.argtypes = [Diagnostic] 697_clang_getDiagnosticSeverity.restype = c_int 698 699_clang_getDiagnosticLocation = lib.clang_getDiagnosticLocation 700_clang_getDiagnosticLocation.argtypes = [Diagnostic] 701_clang_getDiagnosticLocation.restype = SourceLocation 702 703_clang_getDiagnosticSpelling = lib.clang_getDiagnosticSpelling 704_clang_getDiagnosticSpelling.argtypes = [Diagnostic] 705_clang_getDiagnosticSpelling.restype = _CXString 706_clang_getDiagnosticSpelling.errcheck = _CXString.from_result 707 708_clang_getDiagnosticNumRanges = lib.clang_getDiagnosticNumRanges 709_clang_getDiagnosticNumRanges.argtypes = [Diagnostic] 710_clang_getDiagnosticNumRanges.restype = c_uint 711 712_clang_getDiagnosticRange = lib.clang_getDiagnosticRange 713_clang_getDiagnosticRange.argtypes = [Diagnostic, c_uint] 714_clang_getDiagnosticRange.restype = SourceRange 715 716_clang_getDiagnosticNumFixIts = lib.clang_getDiagnosticNumFixIts 717_clang_getDiagnosticNumFixIts.argtypes = [Diagnostic] 718_clang_getDiagnosticNumFixIts.restype = c_uint 719 720_clang_getDiagnosticFixIt = lib.clang_getDiagnosticFixIt 721_clang_getDiagnosticFixIt.argtypes = [Diagnostic, c_uint, POINTER(SourceRange)] 722_clang_getDiagnosticFixIt.restype = _CXString 723_clang_getDiagnosticFixIt.errcheck = _CXString.from_result 724 725### 726 727class CompletionChunk: 728 class Kind: 729 def __init__(self, name): 730 self.name = name 731 732 def __str__(self): 733 return self.name 734 735 def __repr__(self): 736 return "<ChunkKind: %s>" % self 737 738 def __init__(self, completionString, key): 739 self.cs = completionString 740 self.key = key 741 742 def __repr__(self): 743 return "{'" + self.spelling + "', " + str(self.kind) + "}" 744 745 @property 746 def spelling(self): 747 return _clang_getCompletionChunkText(self.cs, self.key).spelling 748 749 @property 750 def kind(self): 751 res = _clang_getCompletionChunkKind(self.cs, self.key) 752 return completionChunkKindMap[res] 753 754 @property 755 def string(self): 756 res = _clang_getCompletionChunkCompletionString(self.cs, self.key) 757 758 if (res): 759 return CompletionString(res) 760 else: 761 None 762 763 def isKindOptional(self): 764 return self.kind == completionChunkKindMap[0] 765 766 def isKindTypedText(self): 767 return self.kind == completionChunkKindMap[1] 768 769 def isKindPlaceHolder(self): 770 return self.kind == completionChunkKindMap[3] 771 772 def isKindInformative(self): 773 return self.kind == completionChunkKindMap[4] 774 775 def isKindResultType(self): 776 return self.kind == completionChunkKindMap[15] 777 778completionChunkKindMap = { 779 0: CompletionChunk.Kind("Optional"), 780 1: CompletionChunk.Kind("TypedText"), 781 2: CompletionChunk.Kind("Text"), 782 3: CompletionChunk.Kind("Placeholder"), 783 4: CompletionChunk.Kind("Informative"), 784 5: CompletionChunk.Kind("CurrentParameter"), 785 6: CompletionChunk.Kind("LeftParen"), 786 7: CompletionChunk.Kind("RightParen"), 787 8: CompletionChunk.Kind("LeftBracket"), 788 9: CompletionChunk.Kind("RightBracket"), 789 10: CompletionChunk.Kind("LeftBrace"), 790 11: CompletionChunk.Kind("RightBrace"), 791 12: CompletionChunk.Kind("LeftAngle"), 792 13: CompletionChunk.Kind("RightAngle"), 793 14: CompletionChunk.Kind("Comma"), 794 15: CompletionChunk.Kind("ResultType"), 795 16: CompletionChunk.Kind("Colon"), 796 17: CompletionChunk.Kind("SemiColon"), 797 18: CompletionChunk.Kind("Equal"), 798 19: CompletionChunk.Kind("HorizontalSpace"), 799 20: CompletionChunk.Kind("VerticalSpace")} 800 801class CompletionString(ClangObject): 802 class Availability: 803 def __init__(self, name): 804 self.name = name 805 806 def __str__(self): 807 return self.name 808 809 def __repr__(self): 810 return "<Availability: %s>" % self 811 812 def __len__(self): 813 return _clang_getNumCompletionChunks(self.obj) 814 815 def __getitem__(self, key): 816 if len(self) <= key: 817 raise IndexError 818 return CompletionChunk(self.obj, key) 819 820 @property 821 def priority(self): 822 return _clang_getCompletionPriority(self.obj) 823 824 @property 825 def availability(self): 826 res = _clang_getCompletionAvailability(self.obj) 827 return availabilityKinds[res] 828 829 def __repr__(self): 830 return " | ".join([str(a) for a in self]) \ 831 + " || Priority: " + str(self.priority) \ 832 + " || Availability: " + str(self.availability) 833 834availabilityKinds = { 835 0: CompletionChunk.Kind("Available"), 836 1: CompletionChunk.Kind("Deprecated"), 837 2: CompletionChunk.Kind("NotAvailable")} 838 839class CodeCompletionResult(Structure): 840 _fields_ = [('cursorKind', c_int), ('completionString', c_object_p)] 841 842 def __repr__(self): 843 return str(CompletionString(self.completionString)) 844 845 @property 846 def kind(self): 847 return CursorKind.from_id(self.cursorKind) 848 849 @property 850 def string(self): 851 return CompletionString(self.completionString) 852 853class CCRStructure(Structure): 854 _fields_ = [('results', POINTER(CodeCompletionResult)), 855 ('numResults', c_int)] 856 857 def __len__(self): 858 return self.numResults 859 860 def __getitem__(self, key): 861 if len(self) <= key: 862 raise IndexError 863 864 return self.results[key] 865 866class CodeCompletionResults(ClangObject): 867 def __init__(self, ptr): 868 assert isinstance(ptr, POINTER(CCRStructure)) and ptr 869 self.ptr = self._as_parameter_ = ptr 870 871 def from_param(self): 872 return self._as_parameter_ 873 874 def __del__(self): 875 CodeCompletionResults_dispose(self) 876 877 @property 878 def results(self): 879 return self.ptr.contents 880 881 @property 882 def diagnostics(self): 883 class DiagnosticsItr: 884 def __init__(self, ccr): 885 self.ccr= ccr 886 887 def __len__(self): 888 return int(_clang_codeCompleteGetNumDiagnostics(self.ccr)) 889 890 def __getitem__(self, key): 891 return _clang_codeCompleteGetDiagnostic(self.ccr, key) 892 893 return DiagnosticsItr(self) 894 895 896class Index(ClangObject): 897 """ 898 The Index type provides the primary interface to the Clang CIndex library, 899 primarily by providing an interface for reading and parsing translation 900 units. 901 """ 902 903 @staticmethod 904 def create(excludeDecls=False): 905 """ 906 Create a new Index. 907 Parameters: 908 excludeDecls -- Exclude local declarations from translation units. 909 """ 910 return Index(Index_create(excludeDecls, 0)) 911 912 def __del__(self): 913 Index_dispose(self) 914 915 def read(self, path): 916 """Load the translation unit from the given AST file.""" 917 ptr = TranslationUnit_read(self, path) 918 return TranslationUnit(ptr) if ptr else None 919 920 def parse(self, path, args = [], unsaved_files = [], options = 0): 921 """ 922 Load the translation unit from the given source code file by running 923 clang and generating the AST before loading. Additional command line 924 parameters can be passed to clang via the args parameter. 925 926 In-memory contents for files can be provided by passing a list of pairs 927 to as unsaved_files, the first item should be the filenames to be mapped 928 and the second should be the contents to be substituted for the 929 file. The contents may be passed as strings or file objects. 930 """ 931 arg_array = 0 932 if len(args): 933 arg_array = (c_char_p * len(args))(* args) 934 unsaved_files_array = 0 935 if len(unsaved_files): 936 unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() 937 for i,(name,value) in enumerate(unsaved_files): 938 if not isinstance(value, str): 939 # FIXME: It would be great to support an efficient version 940 # of this, one day. 941 value = value.read() 942 print value 943 if not isinstance(value, str): 944 raise TypeError,'Unexpected unsaved file contents.' 945 unsaved_files_array[i].name = name 946 unsaved_files_array[i].contents = value 947 unsaved_files_array[i].length = len(value) 948 ptr = TranslationUnit_parse(self, path, arg_array, len(args), 949 unsaved_files_array, len(unsaved_files), 950 options) 951 return TranslationUnit(ptr) if ptr else None 952 953 954class TranslationUnit(ClangObject): 955 """ 956 The TranslationUnit class represents a source code translation unit and 957 provides read-only access to its top-level declarations. 958 """ 959 960 def __init__(self, ptr): 961 ClangObject.__init__(self, ptr) 962 963 def __del__(self): 964 TranslationUnit_dispose(self) 965 966 @property 967 def cursor(self): 968 """Retrieve the cursor that represents the given translation unit.""" 969 return TranslationUnit_cursor(self) 970 971 @property 972 def spelling(self): 973 """Get the original translation unit source file name.""" 974 return TranslationUnit_spelling(self) 975 976 def get_includes(self): 977 """ 978 Return an iterable sequence of FileInclusion objects that describe the 979 sequence of inclusions in a translation unit. The first object in 980 this sequence is always the input file. Note that this method will not 981 recursively iterate over header files included through precompiled 982 headers. 983 """ 984 def visitor(fobj, lptr, depth, includes): 985 if depth > 0: 986 loc = lptr.contents 987 includes.append(FileInclusion(loc.file, File(fobj), loc, depth)) 988 989 # Automatically adapt CIndex/ctype pointers to python objects 990 includes = [] 991 TranslationUnit_includes(self, 992 TranslationUnit_includes_callback(visitor), 993 includes) 994 return iter(includes) 995 996 @property 997 def diagnostics(self): 998 """ 999 Return an iterable (and indexable) object containing the diagnostics. 1000 """ 1001 class DiagIterator: 1002 def __init__(self, tu): 1003 self.tu = tu 1004 1005 def __len__(self): 1006 return int(_clang_getNumDiagnostics(self.tu)) 1007 1008 def __getitem__(self, key): 1009 diag = _clang_getDiagnostic(self.tu, key) 1010 if not diag: 1011 raise IndexError 1012 return Diagnostic(diag) 1013 1014 return DiagIterator(self) 1015 1016 def reparse(self, unsaved_files = [], options = 0): 1017 """ 1018 Reparse an already parsed translation unit. 1019 1020 In-memory contents for files can be provided by passing a list of pairs 1021 as unsaved_files, the first items should be the filenames to be mapped 1022 and the second should be the contents to be substituted for the 1023 file. The contents may be passed as strings or file objects. 1024 """ 1025 unsaved_files_array = 0 1026 if len(unsaved_files): 1027 unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() 1028 for i,(name,value) in enumerate(unsaved_files): 1029 if not isinstance(value, str): 1030 # FIXME: It would be great to support an efficient version 1031 # of this, one day. 1032 value = value.read() 1033 print value 1034 if not isinstance(value, str): 1035 raise TypeError,'Unexpected unsaved file contents.' 1036 unsaved_files_array[i].name = name 1037 unsaved_files_array[i].contents = value 1038 unsaved_files_array[i].length = len(value) 1039 ptr = TranslationUnit_reparse(self, len(unsaved_files), 1040 unsaved_files_array, 1041 options) 1042 def codeComplete(self, path, line, column, unsaved_files = [], options = 0): 1043 """ 1044 Code complete in this translation unit. 1045 1046 In-memory contents for files can be provided by passing a list of pairs 1047 as unsaved_files, the first items should be the filenames to be mapped 1048 and the second should be the contents to be substituted for the 1049 file. The contents may be passed as strings or file objects. 1050 """ 1051 unsaved_files_array = 0 1052 if len(unsaved_files): 1053 unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() 1054 for i,(name,value) in enumerate(unsaved_files): 1055 if not isinstance(value, str): 1056 # FIXME: It would be great to support an efficient version 1057 # of this, one day. 1058 value = value.read() 1059 print value 1060 if not isinstance(value, str): 1061 raise TypeError,'Unexpected unsaved file contents.' 1062 unsaved_files_array[i].name = name 1063 unsaved_files_array[i].contents = value 1064 unsaved_files_array[i].length = len(value) 1065 ptr = TranslationUnit_codeComplete(self, path, 1066 line, column, 1067 unsaved_files_array, 1068 len(unsaved_files), 1069 options) 1070 return CodeCompletionResults(ptr) if ptr else None 1071 1072 1073class File(ClangObject): 1074 """ 1075 The File class represents a particular source file that is part of a 1076 translation unit. 1077 """ 1078 1079 @property 1080 def name(self): 1081 """Return the complete file and path name of the file.""" 1082 return _CXString_getCString(File_name(self)) 1083 1084 @property 1085 def time(self): 1086 """Return the last modification time of the file.""" 1087 return File_time(self) 1088 1089class FileInclusion(object): 1090 """ 1091 The FileInclusion class represents the inclusion of one source file by 1092 another via a '#include' directive or as the input file for the translation 1093 unit. This class provides information about the included file, the including 1094 file, the location of the '#include' directive and the depth of the included 1095 file in the stack. Note that the input file has depth 0. 1096 """ 1097 1098 def __init__(self, src, tgt, loc, depth): 1099 self.source = src 1100 self.include = tgt 1101 self.location = loc 1102 self.depth = depth 1103 1104 @property 1105 def is_input_file(self): 1106 """True if the included file is the input file.""" 1107 return self.depth == 0 1108 1109# Additional Functions and Types 1110 1111# String Functions 1112_CXString_dispose = lib.clang_disposeString 1113_CXString_dispose.argtypes = [_CXString] 1114 1115_CXString_getCString = lib.clang_getCString 1116_CXString_getCString.argtypes = [_CXString] 1117_CXString_getCString.restype = c_char_p 1118 1119# Source Location Functions 1120SourceLocation_loc = lib.clang_getInstantiationLocation 1121SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p), 1122 POINTER(c_uint), POINTER(c_uint), 1123 POINTER(c_uint)] 1124 1125# Source Range Functions 1126SourceRange_getRange = lib.clang_getRange 1127SourceRange_getRange.argtypes = [SourceLocation, SourceLocation] 1128SourceRange_getRange.restype = SourceRange 1129 1130SourceRange_start = lib.clang_getRangeStart 1131SourceRange_start.argtypes = [SourceRange] 1132SourceRange_start.restype = SourceLocation 1133 1134SourceRange_end = lib.clang_getRangeEnd 1135SourceRange_end.argtypes = [SourceRange] 1136SourceRange_end.restype = SourceLocation 1137 1138# CursorKind Functions 1139CursorKind_is_decl = lib.clang_isDeclaration 1140CursorKind_is_decl.argtypes = [CursorKind] 1141CursorKind_is_decl.restype = bool 1142 1143CursorKind_is_ref = lib.clang_isReference 1144CursorKind_is_ref.argtypes = [CursorKind] 1145CursorKind_is_ref.restype = bool 1146 1147CursorKind_is_expr = lib.clang_isExpression 1148CursorKind_is_expr.argtypes = [CursorKind] 1149CursorKind_is_expr.restype = bool 1150 1151CursorKind_is_stmt = lib.clang_isStatement 1152CursorKind_is_stmt.argtypes = [CursorKind] 1153CursorKind_is_stmt.restype = bool 1154 1155CursorKind_is_attribute = lib.clang_isAttribute 1156CursorKind_is_attribute.argtypes = [CursorKind] 1157CursorKind_is_attribute.restype = bool 1158 1159CursorKind_is_inv = lib.clang_isInvalid 1160CursorKind_is_inv.argtypes = [CursorKind] 1161CursorKind_is_inv.restype = bool 1162 1163# Cursor Functions 1164# TODO: Implement this function 1165Cursor_get = lib.clang_getCursor 1166Cursor_get.argtypes = [TranslationUnit, SourceLocation] 1167Cursor_get.restype = Cursor 1168 1169Cursor_null = lib.clang_getNullCursor 1170Cursor_null.restype = Cursor 1171 1172Cursor_usr = lib.clang_getCursorUSR 1173Cursor_usr.argtypes = [Cursor] 1174Cursor_usr.restype = _CXString 1175Cursor_usr.errcheck = _CXString.from_result 1176 1177Cursor_is_def = lib.clang_isCursorDefinition 1178Cursor_is_def.argtypes = [Cursor] 1179Cursor_is_def.restype = bool 1180 1181Cursor_def = lib.clang_getCursorDefinition 1182Cursor_def.argtypes = [Cursor] 1183Cursor_def.restype = Cursor 1184Cursor_def.errcheck = Cursor.from_result 1185 1186Cursor_eq = lib.clang_equalCursors 1187Cursor_eq.argtypes = [Cursor, Cursor] 1188Cursor_eq.restype = c_uint 1189 1190Cursor_spelling = lib.clang_getCursorSpelling 1191Cursor_spelling.argtypes = [Cursor] 1192Cursor_spelling.restype = _CXString 1193Cursor_spelling.errcheck = _CXString.from_result 1194 1195Cursor_displayname = lib.clang_getCursorDisplayName 1196Cursor_displayname.argtypes = [Cursor] 1197Cursor_displayname.restype = _CXString 1198Cursor_displayname.errcheck = _CXString.from_result 1199 1200Cursor_loc = lib.clang_getCursorLocation 1201Cursor_loc.argtypes = [Cursor] 1202Cursor_loc.restype = SourceLocation 1203 1204Cursor_extent = lib.clang_getCursorExtent 1205Cursor_extent.argtypes = [Cursor] 1206Cursor_extent.restype = SourceRange 1207 1208Cursor_ref = lib.clang_getCursorReferenced 1209Cursor_ref.argtypes = [Cursor] 1210Cursor_ref.restype = Cursor 1211Cursor_ref.errcheck = Cursor.from_result 1212 1213Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object) 1214Cursor_visit = lib.clang_visitChildren 1215Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object] 1216Cursor_visit.restype = c_uint 1217 1218# Index Functions 1219Index_create = lib.clang_createIndex 1220Index_create.argtypes = [c_int, c_int] 1221Index_create.restype = c_object_p 1222 1223Index_dispose = lib.clang_disposeIndex 1224Index_dispose.argtypes = [Index] 1225 1226# Translation Unit Functions 1227TranslationUnit_read = lib.clang_createTranslationUnit 1228TranslationUnit_read.argtypes = [Index, c_char_p] 1229TranslationUnit_read.restype = c_object_p 1230 1231TranslationUnit_parse = lib.clang_parseTranslationUnit 1232TranslationUnit_parse.argtypes = [Index, c_char_p, c_void_p, 1233 c_int, c_void_p, c_int, c_int] 1234TranslationUnit_parse.restype = c_object_p 1235 1236TranslationUnit_reparse = lib.clang_reparseTranslationUnit 1237TranslationUnit_reparse.argtypes = [TranslationUnit, c_int, c_void_p, c_int] 1238TranslationUnit_reparse.restype = c_int 1239 1240TranslationUnit_codeComplete = lib.clang_codeCompleteAt 1241TranslationUnit_codeComplete.argtypes = [TranslationUnit, c_char_p, c_int, 1242 c_int, c_void_p, c_int, c_int] 1243TranslationUnit_codeComplete.restype = POINTER(CCRStructure) 1244 1245TranslationUnit_cursor = lib.clang_getTranslationUnitCursor 1246TranslationUnit_cursor.argtypes = [TranslationUnit] 1247TranslationUnit_cursor.restype = Cursor 1248TranslationUnit_cursor.errcheck = Cursor.from_result 1249 1250TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling 1251TranslationUnit_spelling.argtypes = [TranslationUnit] 1252TranslationUnit_spelling.restype = _CXString 1253TranslationUnit_spelling.errcheck = _CXString.from_result 1254 1255TranslationUnit_dispose = lib.clang_disposeTranslationUnit 1256TranslationUnit_dispose.argtypes = [TranslationUnit] 1257 1258TranslationUnit_includes_callback = CFUNCTYPE(None, 1259 c_object_p, 1260 POINTER(SourceLocation), 1261 c_uint, py_object) 1262TranslationUnit_includes = lib.clang_getInclusions 1263TranslationUnit_includes.argtypes = [TranslationUnit, 1264 TranslationUnit_includes_callback, 1265 py_object] 1266 1267# File Functions 1268File_name = lib.clang_getFileName 1269File_name.argtypes = [File] 1270File_name.restype = _CXString 1271 1272File_time = lib.clang_getFileTime 1273File_time.argtypes = [File] 1274File_time.restype = c_uint 1275 1276# Code completion 1277 1278CodeCompletionResults_dispose = lib.clang_disposeCodeCompleteResults 1279CodeCompletionResults_dispose.argtypes = [CodeCompletionResults] 1280 1281_clang_codeCompleteGetNumDiagnostics = lib.clang_codeCompleteGetNumDiagnostics 1282_clang_codeCompleteGetNumDiagnostics.argtypes = [CodeCompletionResults] 1283_clang_codeCompleteGetNumDiagnostics.restype = c_int 1284 1285_clang_codeCompleteGetDiagnostic = lib.clang_codeCompleteGetDiagnostic 1286_clang_codeCompleteGetDiagnostic.argtypes = [CodeCompletionResults, c_int] 1287_clang_codeCompleteGetDiagnostic.restype = Diagnostic 1288 1289_clang_getCompletionChunkText = lib.clang_getCompletionChunkText 1290_clang_getCompletionChunkText.argtypes = [c_void_p, c_int] 1291_clang_getCompletionChunkText.restype = _CXString 1292 1293_clang_getCompletionChunkKind = lib.clang_getCompletionChunkKind 1294_clang_getCompletionChunkKind.argtypes = [c_void_p, c_int] 1295_clang_getCompletionChunkKind.restype = c_int 1296 1297_clang_getCompletionChunkCompletionString = lib.clang_getCompletionChunkCompletionString 1298_clang_getCompletionChunkCompletionString.argtypes = [c_void_p, c_int] 1299_clang_getCompletionChunkCompletionString.restype = c_object_p 1300 1301_clang_getNumCompletionChunks = lib.clang_getNumCompletionChunks 1302_clang_getNumCompletionChunks.argtypes = [c_void_p] 1303_clang_getNumCompletionChunks.restype = c_int 1304 1305_clang_getCompletionAvailability = lib.clang_getCompletionAvailability 1306_clang_getCompletionAvailability.argtypes = [c_void_p] 1307_clang_getCompletionAvailability.restype = c_int 1308 1309_clang_getCompletionPriority = lib.clang_getCompletionPriority 1310_clang_getCompletionPriority.argtypes = [c_void_p] 1311_clang_getCompletionPriority.restype = c_int 1312 1313 1314### 1315 1316__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind', 1317 'Diagnostic', 'FixIt', 'CodeCompletionResults', 'SourceRange', 1318 'SourceLocation', 'File'] 1319