cindex.py revision a87dbcc04987ebf91adec3e00ac5e1548af6d865
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 CompletionChunk: 724 class Kind: 725 def __init__(self, name): 726 self.name = name 727 728 def __str__(self): 729 return self.name 730 731 def __repr__(self): 732 return "<ChunkKind: %s>" % self 733 734 def __init__(self, completionString, key): 735 self.cs = completionString 736 self.key = key 737 738 def __repr__(self): 739 return "{'" + self.spelling + "', " + str(self.kind) + "}" 740 741 @property 742 def spelling(self): 743 return _clang_getCompletionChunkText(self.cs, self.key).spelling 744 745 @property 746 def kind(self): 747 res = _clang_getCompletionChunkKind(self.cs, self.key) 748 return completionChunkKindMap[res] 749 750 @property 751 def string(self): 752 res = _clang_getCompletionChunkCompletionString(self.cs, self.key) 753 754 if (res): 755 return CompletionString(res) 756 else: 757 None 758 759 def isKindOptional(self): 760 return self.kind == completionChunkKindMap[0] 761 762 def isKindTypedText(self): 763 return self.kind == completionChunkKindMap[1] 764 765 def isKindPlaceHolder(self): 766 return self.kind == completionChunkKindMap[3] 767 768 def isKindInformative(self): 769 return self.kind == completionChunkKindMap[4] 770 771 def isKindResultType(self): 772 return self.kind == completionChunkKindMap[15] 773 774completionChunkKindMap = { 775 0: CompletionChunk.Kind("Optional"), 776 1: CompletionChunk.Kind("TypedText"), 777 2: CompletionChunk.Kind("Text"), 778 3: CompletionChunk.Kind("Placeholder"), 779 4: CompletionChunk.Kind("Informative"), 780 5: CompletionChunk.Kind("CurrentParameter"), 781 6: CompletionChunk.Kind("LeftParen"), 782 7: CompletionChunk.Kind("RightParen"), 783 8: CompletionChunk.Kind("LeftBracket"), 784 9: CompletionChunk.Kind("RightBracket"), 785 10: CompletionChunk.Kind("LeftBrace"), 786 11: CompletionChunk.Kind("RightBrace"), 787 12: CompletionChunk.Kind("LeftAngle"), 788 13: CompletionChunk.Kind("RightAngle"), 789 14: CompletionChunk.Kind("Comma"), 790 15: CompletionChunk.Kind("ResultType"), 791 16: CompletionChunk.Kind("Colon"), 792 17: CompletionChunk.Kind("SemiColon"), 793 18: CompletionChunk.Kind("Equal"), 794 19: CompletionChunk.Kind("HorizontalSpace"), 795 20: CompletionChunk.Kind("VerticalSpace")} 796 797class CompletionString(ClangObject): 798 class Availability: 799 def __init__(self, name): 800 self.name = name 801 802 def __str__(self): 803 return self.name 804 805 def __repr__(self): 806 return "<Availability: %s>" % self 807 808 def __len__(self): 809 return _clang_getNumCompletionChunks(self.obj) 810 811 def __getitem__(self, key): 812 if len(self) <= key: 813 raise IndexError 814 return CompletionChunk(self.obj, key) 815 816 @property 817 def priority(self): 818 return _clang_getCompletionPriority(self.obj) 819 820 @property 821 def availability(self): 822 res = _clang_getCompletionAvailability(self.obj) 823 return availabilityKinds[res] 824 825 def __repr__(self): 826 return " | ".join([str(a) for a in self]) \ 827 + " || Priority: " + str(self.priority) \ 828 + " || Availability: " + str(self.availability) 829 830availabilityKinds = { 831 0: CompletionChunk.Kind("Available"), 832 1: CompletionChunk.Kind("Deprecated"), 833 2: CompletionChunk.Kind("NotAvailable")} 834 835class CodeCompletionResult(Structure): 836 _fields_ = [('cursorKind', c_int), ('completionString', c_object_p)] 837 838 def __repr__(self): 839 return str(CompletionString(self.completionString)) 840 841 @property 842 def kind(self): 843 return CursorKind.from_id(self.cursorKind) 844 845 @property 846 def string(self): 847 return CompletionString(self.completionString) 848 849class CCRStructure(Structure): 850 _fields_ = [('results', POINTER(CodeCompletionResult)), 851 ('numResults', c_int)] 852 853 def __len__(self): 854 return self.numResults 855 856 def __getitem__(self, key): 857 if len(self) <= key: 858 raise IndexError 859 860 return self.results[key] 861 862class CodeCompletionResults(ClangObject): 863 def __init__(self, ptr): 864 assert isinstance(ptr, POINTER(CCRStructure)) and ptr 865 self.ptr = self._as_parameter_ = ptr 866 867 def from_param(self): 868 return self._as_parameter_ 869 870 def __del__(self): 871 CodeCompletionResults_dispose(self) 872 873 @property 874 def results(self): 875 return self.ptr.contents 876 877 @property 878 def diagnostics(self): 879 class DiagnosticsItr: 880 def __init__(self, ccr): 881 self.ccr= ccr 882 883 def __len__(self): 884 return int(_clang_codeCompleteGetNumDiagnostics(self.ccr)) 885 886 def __getitem__(self, key): 887 return _clang_codeCompleteGetDiagnostic(self.ccr, key) 888 889 return DiagnosticsItr(self) 890 891 892class Index(ClangObject): 893 """ 894 The Index type provides the primary interface to the Clang CIndex library, 895 primarily by providing an interface for reading and parsing translation 896 units. 897 """ 898 899 @staticmethod 900 def create(excludeDecls=False): 901 """ 902 Create a new Index. 903 Parameters: 904 excludeDecls -- Exclude local declarations from translation units. 905 """ 906 return Index(Index_create(excludeDecls, 0)) 907 908 def __del__(self): 909 Index_dispose(self) 910 911 def read(self, path): 912 """Load the translation unit from the given AST file.""" 913 ptr = TranslationUnit_read(self, path) 914 return TranslationUnit(ptr) if ptr else None 915 916 def parse(self, path, args = [], unsaved_files = [], options = 0): 917 """ 918 Load the translation unit from the given source code file by running 919 clang and generating the AST before loading. Additional command line 920 parameters can be passed to clang via the args parameter. 921 922 In-memory contents for files can be provided by passing a list of pairs 923 to as unsaved_files, the first item should be the filenames to be mapped 924 and the second should be the contents to be substituted for the 925 file. The contents may be passed as strings or file objects. 926 """ 927 arg_array = 0 928 if len(args): 929 arg_array = (c_char_p * len(args))(* args) 930 unsaved_files_array = 0 931 if len(unsaved_files): 932 unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() 933 for i,(name,value) in enumerate(unsaved_files): 934 if not isinstance(value, str): 935 # FIXME: It would be great to support an efficient version 936 # of this, one day. 937 value = value.read() 938 print value 939 if not isinstance(value, str): 940 raise TypeError,'Unexpected unsaved file contents.' 941 unsaved_files_array[i].name = name 942 unsaved_files_array[i].contents = value 943 unsaved_files_array[i].length = len(value) 944 ptr = TranslationUnit_parse(self, path, arg_array, len(args), 945 unsaved_files_array, len(unsaved_files), 946 options) 947 return TranslationUnit(ptr) if ptr else None 948 949 950class TranslationUnit(ClangObject): 951 """ 952 The TranslationUnit class represents a source code translation unit and 953 provides read-only access to its top-level declarations. 954 """ 955 956 def __init__(self, ptr): 957 ClangObject.__init__(self, ptr) 958 959 def __del__(self): 960 TranslationUnit_dispose(self) 961 962 @property 963 def cursor(self): 964 """Retrieve the cursor that represents the given translation unit.""" 965 return TranslationUnit_cursor(self) 966 967 @property 968 def spelling(self): 969 """Get the original translation unit source file name.""" 970 return TranslationUnit_spelling(self) 971 972 def get_includes(self): 973 """ 974 Return an iterable sequence of FileInclusion objects that describe the 975 sequence of inclusions in a translation unit. The first object in 976 this sequence is always the input file. Note that this method will not 977 recursively iterate over header files included through precompiled 978 headers. 979 """ 980 def visitor(fobj, lptr, depth, includes): 981 loc = lptr.contents 982 includes.append(FileInclusion(loc.file, File(fobj), loc, depth)) 983 984 # Automatically adapt CIndex/ctype pointers to python objects 985 includes = [] 986 TranslationUnit_includes(self, 987 TranslationUnit_includes_callback(visitor), 988 includes) 989 return iter(includes) 990 991 @property 992 def diagnostics(self): 993 """ 994 Return an iterable (and indexable) object containing the diagnostics. 995 """ 996 class DiagIterator: 997 def __init__(self, tu): 998 self.tu = tu 999 1000 def __len__(self): 1001 return int(_clang_getNumDiagnostics(self.tu)) 1002 1003 def __getitem__(self, key): 1004 diag = _clang_getDiagnostic(self.tu, key) 1005 if not diag: 1006 raise IndexError 1007 return Diagnostic(diag) 1008 1009 return DiagIterator(self) 1010 1011 def reparse(self, unsaved_files = [], options = 0): 1012 """ 1013 Reparse an already parsed translation unit. 1014 1015 In-memory contents for files can be provided by passing a list of pairs 1016 as unsaved_files, the first items should be the filenames to be mapped 1017 and the second should be the contents to be substituted for the 1018 file. The contents may be passed as strings or file objects. 1019 """ 1020 unsaved_files_array = 0 1021 if len(unsaved_files): 1022 unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() 1023 for i,(name,value) in enumerate(unsaved_files): 1024 if not isinstance(value, str): 1025 # FIXME: It would be great to support an efficient version 1026 # of this, one day. 1027 value = value.read() 1028 print value 1029 if not isinstance(value, str): 1030 raise TypeError,'Unexpected unsaved file contents.' 1031 unsaved_files_array[i].name = name 1032 unsaved_files_array[i].contents = value 1033 unsaved_files_array[i].length = len(value) 1034 ptr = TranslationUnit_reparse(self, len(unsaved_files), 1035 unsaved_files_array, 1036 options) 1037 def codeComplete(self, path, line, column, unsaved_files = [], options = 0): 1038 """ 1039 Code complete in this translation unit. 1040 1041 In-memory contents for files can be provided by passing a list of pairs 1042 as unsaved_files, the first items should be the filenames to be mapped 1043 and the second should be the contents to be substituted for the 1044 file. The contents may be passed as strings or file objects. 1045 """ 1046 unsaved_files_array = 0 1047 if len(unsaved_files): 1048 unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() 1049 for i,(name,value) in enumerate(unsaved_files): 1050 if not isinstance(value, str): 1051 # FIXME: It would be great to support an efficient version 1052 # of this, one day. 1053 value = value.read() 1054 print value 1055 if not isinstance(value, str): 1056 raise TypeError,'Unexpected unsaved file contents.' 1057 unsaved_files_array[i].name = name 1058 unsaved_files_array[i].contents = value 1059 unsaved_files_array[i].length = len(value) 1060 ptr = TranslationUnit_codeComplete(self, path, 1061 line, column, 1062 unsaved_files_array, 1063 len(unsaved_files), 1064 options) 1065 return CodeCompletionResults(ptr) if ptr else None 1066 1067 1068class File(ClangObject): 1069 """ 1070 The File class represents a particular source file that is part of a 1071 translation unit. 1072 """ 1073 1074 @property 1075 def name(self): 1076 """Return the complete file and path name of the file.""" 1077 return File_name(self) 1078 1079 @property 1080 def time(self): 1081 """Return the last modification time of the file.""" 1082 return File_time(self) 1083 1084class FileInclusion(object): 1085 """ 1086 The FileInclusion class represents the inclusion of one source file by 1087 another via a '#include' directive or as the input file for the translation 1088 unit. This class provides information about the included file, the including 1089 file, the location of the '#include' directive and the depth of the included 1090 file in the stack. Note that the input file has depth 0. 1091 """ 1092 1093 def __init__(self, src, tgt, loc, depth): 1094 self.source = src 1095 self.include = tgt 1096 self.location = loc 1097 self.depth = depth 1098 1099 @property 1100 def is_input_file(self): 1101 """True if the included file is the input file.""" 1102 return self.depth == 0 1103 1104# Additional Functions and Types 1105 1106# String Functions 1107_CXString_dispose = lib.clang_disposeString 1108_CXString_dispose.argtypes = [_CXString] 1109 1110_CXString_getCString = lib.clang_getCString 1111_CXString_getCString.argtypes = [_CXString] 1112_CXString_getCString.restype = c_char_p 1113 1114# Source Location Functions 1115SourceLocation_loc = lib.clang_getInstantiationLocation 1116SourceLocation_loc.argtypes = [SourceLocation, POINTER(c_object_p), 1117 POINTER(c_uint), POINTER(c_uint), 1118 POINTER(c_uint)] 1119 1120# Source Range Functions 1121SourceRange_getRange = lib.clang_getRange 1122SourceRange_getRange.argtypes = [SourceLocation, SourceLocation] 1123SourceRange_getRange.restype = SourceRange 1124 1125SourceRange_start = lib.clang_getRangeStart 1126SourceRange_start.argtypes = [SourceRange] 1127SourceRange_start.restype = SourceLocation 1128 1129SourceRange_end = lib.clang_getRangeEnd 1130SourceRange_end.argtypes = [SourceRange] 1131SourceRange_end.restype = SourceLocation 1132 1133# CursorKind Functions 1134CursorKind_is_decl = lib.clang_isDeclaration 1135CursorKind_is_decl.argtypes = [CursorKind] 1136CursorKind_is_decl.restype = bool 1137 1138CursorKind_is_ref = lib.clang_isReference 1139CursorKind_is_ref.argtypes = [CursorKind] 1140CursorKind_is_ref.restype = bool 1141 1142CursorKind_is_expr = lib.clang_isExpression 1143CursorKind_is_expr.argtypes = [CursorKind] 1144CursorKind_is_expr.restype = bool 1145 1146CursorKind_is_stmt = lib.clang_isStatement 1147CursorKind_is_stmt.argtypes = [CursorKind] 1148CursorKind_is_stmt.restype = bool 1149 1150CursorKind_is_inv = lib.clang_isInvalid 1151CursorKind_is_inv.argtypes = [CursorKind] 1152CursorKind_is_inv.restype = bool 1153 1154# Cursor Functions 1155# TODO: Implement this function 1156Cursor_get = lib.clang_getCursor 1157Cursor_get.argtypes = [TranslationUnit, SourceLocation] 1158Cursor_get.restype = Cursor 1159 1160Cursor_null = lib.clang_getNullCursor 1161Cursor_null.restype = Cursor 1162 1163Cursor_usr = lib.clang_getCursorUSR 1164Cursor_usr.argtypes = [Cursor] 1165Cursor_usr.restype = _CXString 1166Cursor_usr.errcheck = _CXString.from_result 1167 1168Cursor_is_def = lib.clang_isCursorDefinition 1169Cursor_is_def.argtypes = [Cursor] 1170Cursor_is_def.restype = bool 1171 1172Cursor_def = lib.clang_getCursorDefinition 1173Cursor_def.argtypes = [Cursor] 1174Cursor_def.restype = Cursor 1175Cursor_def.errcheck = Cursor.from_result 1176 1177Cursor_eq = lib.clang_equalCursors 1178Cursor_eq.argtypes = [Cursor, Cursor] 1179Cursor_eq.restype = c_uint 1180 1181Cursor_spelling = lib.clang_getCursorSpelling 1182Cursor_spelling.argtypes = [Cursor] 1183Cursor_spelling.restype = _CXString 1184Cursor_spelling.errcheck = _CXString.from_result 1185 1186Cursor_loc = lib.clang_getCursorLocation 1187Cursor_loc.argtypes = [Cursor] 1188Cursor_loc.restype = SourceLocation 1189 1190Cursor_extent = lib.clang_getCursorExtent 1191Cursor_extent.argtypes = [Cursor] 1192Cursor_extent.restype = SourceRange 1193 1194Cursor_ref = lib.clang_getCursorReferenced 1195Cursor_ref.argtypes = [Cursor] 1196Cursor_ref.restype = Cursor 1197Cursor_ref.errcheck = Cursor.from_result 1198 1199Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object) 1200Cursor_visit = lib.clang_visitChildren 1201Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object] 1202Cursor_visit.restype = c_uint 1203 1204# Index Functions 1205Index_create = lib.clang_createIndex 1206Index_create.argtypes = [c_int, c_int] 1207Index_create.restype = c_object_p 1208 1209Index_dispose = lib.clang_disposeIndex 1210Index_dispose.argtypes = [Index] 1211 1212# Translation Unit Functions 1213TranslationUnit_read = lib.clang_createTranslationUnit 1214TranslationUnit_read.argtypes = [Index, c_char_p] 1215TranslationUnit_read.restype = c_object_p 1216 1217TranslationUnit_parse = lib.clang_parseTranslationUnit 1218TranslationUnit_parse.argtypes = [Index, c_char_p, c_void_p, 1219 c_int, c_void_p, c_int, c_int] 1220TranslationUnit_parse.restype = c_object_p 1221 1222TranslationUnit_reparse = lib.clang_reparseTranslationUnit 1223TranslationUnit_reparse.argtypes = [TranslationUnit, c_int, c_void_p, c_int] 1224TranslationUnit_reparse.restype = c_int 1225 1226TranslationUnit_codeComplete = lib.clang_codeCompleteAt 1227TranslationUnit_codeComplete.argtypes = [TranslationUnit, c_char_p, c_int, 1228 c_int, c_void_p, c_int, c_int] 1229TranslationUnit_codeComplete.restype = POINTER(CCRStructure) 1230 1231TranslationUnit_cursor = lib.clang_getTranslationUnitCursor 1232TranslationUnit_cursor.argtypes = [TranslationUnit] 1233TranslationUnit_cursor.restype = Cursor 1234TranslationUnit_cursor.errcheck = Cursor.from_result 1235 1236TranslationUnit_spelling = lib.clang_getTranslationUnitSpelling 1237TranslationUnit_spelling.argtypes = [TranslationUnit] 1238TranslationUnit_spelling.restype = _CXString 1239TranslationUnit_spelling.errcheck = _CXString.from_result 1240 1241TranslationUnit_dispose = lib.clang_disposeTranslationUnit 1242TranslationUnit_dispose.argtypes = [TranslationUnit] 1243 1244TranslationUnit_includes_callback = CFUNCTYPE(None, 1245 c_object_p, 1246 POINTER(SourceLocation), 1247 c_uint, py_object) 1248TranslationUnit_includes = lib.clang_getInclusions 1249TranslationUnit_includes.argtypes = [TranslationUnit, 1250 TranslationUnit_includes_callback, 1251 py_object] 1252 1253# File Functions 1254File_name = lib.clang_getFileName 1255File_name.argtypes = [File] 1256File_name.restype = c_char_p 1257 1258File_time = lib.clang_getFileTime 1259File_time.argtypes = [File] 1260File_time.restype = c_uint 1261 1262# Code completion 1263 1264CodeCompletionResults_dispose = lib.clang_disposeCodeCompleteResults 1265CodeCompletionResults_dispose.argtypes = [CodeCompletionResults] 1266 1267_clang_codeCompleteGetNumDiagnostics = lib.clang_codeCompleteGetNumDiagnostics 1268_clang_codeCompleteGetNumDiagnostics.argtypes = [CodeCompletionResults] 1269_clang_codeCompleteGetNumDiagnostics.restype = c_int 1270 1271_clang_codeCompleteGetDiagnostic = lib.clang_codeCompleteGetDiagnostic 1272_clang_codeCompleteGetDiagnostic.argtypes = [CodeCompletionResults, c_int] 1273_clang_codeCompleteGetDiagnostic.restype = Diagnostic 1274 1275_clang_getCompletionChunkText = lib.clang_getCompletionChunkText 1276_clang_getCompletionChunkText.argtypes = [c_void_p, c_int] 1277_clang_getCompletionChunkText.restype = _CXString 1278 1279_clang_getCompletionChunkKind = lib.clang_getCompletionChunkKind 1280_clang_getCompletionChunkKind.argtypes = [c_void_p, c_int] 1281_clang_getCompletionChunkKind.restype = c_int 1282 1283_clang_getCompletionChunkCompletionString = lib.clang_getCompletionChunkCompletionString 1284_clang_getCompletionChunkCompletionString.argtypes = [c_void_p, c_int] 1285_clang_getCompletionChunkCompletionString.restype = c_object_p 1286 1287_clang_getNumCompletionChunks = lib.clang_getNumCompletionChunks 1288_clang_getNumCompletionChunks.argtypes = [c_void_p] 1289_clang_getNumCompletionChunks.restype = c_int 1290 1291_clang_getCompletionAvailability = lib.clang_getCompletionAvailability 1292_clang_getCompletionAvailability.argtypes = [c_void_p] 1293_clang_getCompletionAvailability.restype = c_int 1294 1295_clang_getCompletionPriority = lib.clang_getCompletionPriority 1296_clang_getCompletionPriority.argtypes = [c_void_p] 1297_clang_getCompletionPriority.restype = c_int 1298 1299 1300### 1301 1302__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind', 1303 'Diagnostic', 'FixIt', 'CodeCompletionResults', 'SourceRange', 1304 'SourceLocation', 'File'] 1305