├── .gitignore ├── Makefile ├── README.rst ├── bin └── cc_args.py ├── doc └── clang_complete.txt ├── examples └── boost.cpp └── plugin ├── clang ├── __init__.py ├── cindex.py └── enumerations.py ├── clang_complete.vim ├── libclang.py └── snippets ├── __init__.py ├── clang_complete.py ├── dummy.py └── ultisnips.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.vmb 3 | *.cache 4 | tags 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /usr/bin/env bash 2 | FILES := $(shell git ls-files autoload bin doc plugin) 3 | 4 | all: clang_complete.vmb 5 | 6 | clang_complete.vmb: $(FILES) 7 | vim -c "r! git ls-files autoload bin doc plugin" \ 8 | -c '$$,$$d _' \ 9 | -c "%MkVimball! $@ ." -c 'q!' 10 | 11 | .PHONY: install uninstall 12 | install: clang_complete.vmb 13 | vim $< -c 'so %' -c 'q' 14 | uninstall: 15 | vim -c 'RmVimball clang_complete.vmb' -c 'q' 16 | 17 | .PHONY: clean 18 | clean: 19 | rm -f clang_complete.vmb 20 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ============== 2 | clang-complete 3 | ============== 4 | 5 | This plugin uses clang for accurately completing C and C++ code. 6 | 7 | To build and install in one step, type:: 8 | 9 | $ make install 10 | 11 | To build and install in two steps, type:: 12 | 13 | $ make 14 | $ vim clang_complete.vmb -c 'so %' -c 'q' 15 | 16 | Alternatively, you can also put the files in ``~/.vim/`` 17 | 18 | You need Vim 7.3 or higher, compiled with ``python3`` support and ideally, with 19 | the ``conceal`` feature. 20 | 21 | See ``doc/clang_complete.txt`` for help and license. 22 | -------------------------------------------------------------------------------- /bin/cc_args.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | import sys 5 | 6 | CONFIG_NAME = ".clang_complete" 7 | 8 | def readConfiguration(): 9 | try: 10 | f = open(CONFIG_NAME, "r") 11 | except IOError: 12 | return [] 13 | 14 | result = [] 15 | for line in f.readlines(): 16 | strippedLine = line.strip() 17 | if strippedLine: 18 | result.append(strippedLine) 19 | f.close() 20 | return result 21 | 22 | def writeConfiguration(lines): 23 | f = open(CONFIG_NAME, "w") 24 | f.writelines(lines) 25 | f.close() 26 | 27 | def parseArguments(arguments): 28 | nextIsInclude = False 29 | nextIsDefine = False 30 | nextIsIncludeFile = False 31 | 32 | includes = [] 33 | defines = [] 34 | include_file = [] 35 | options = [] 36 | 37 | for arg in arguments: 38 | if nextIsInclude: 39 | includes += [arg] 40 | nextIsInclude = False 41 | elif nextIsDefine: 42 | defines += [arg] 43 | nextIsDefine = False 44 | elif nextIsIncludeFile: 45 | include_file += [arg] 46 | nextIsIncludeFile = False 47 | elif arg in ('-I', '-isystem'): 48 | nextIsInclude = True 49 | elif arg == "-D": 50 | nextIsDefine = True 51 | elif arg[:2] == "-I": 52 | includes += [arg[2:]] 53 | elif arg[:2] == "-D": 54 | defines += [arg[2:]] 55 | elif arg == "-include": 56 | nextIsIncludeFile = True 57 | elif arg.startswith('-std='): 58 | options.append(arg) 59 | elif arg == '-ansi': 60 | options.append(arg) 61 | elif arg.startswith('-pedantic'): 62 | options.append(arg) 63 | elif arg.startswith('-W'): 64 | options.append(arg) 65 | 66 | result = list(["-I" + x for x in includes]) 67 | result.extend(["-D" + x for x in defines]) 68 | result.extend(["-include " + x for x in include_file]) 69 | result.extend(options) 70 | 71 | return result 72 | 73 | def mergeLists(base, new): 74 | result = list(base) 75 | for newLine in new: 76 | if newLine not in result: 77 | result.append(newLine) 78 | return result 79 | 80 | configuration = readConfiguration() 81 | args = parseArguments(sys.argv) 82 | result = mergeLists(configuration, args) 83 | writeConfiguration([x + "\n" for x in result]) 84 | 85 | 86 | import subprocess 87 | proc = subprocess.Popen(sys.argv[1:]) 88 | ret = proc.wait() 89 | 90 | if ret is None: 91 | sys.exit(1) 92 | sys.exit(ret) 93 | 94 | # vim: set ts=2 sts=2 sw=2 expandtab : 95 | -------------------------------------------------------------------------------- /doc/clang_complete.txt: -------------------------------------------------------------------------------- 1 | *clang_complete.txt* For Vim version 7.3. Last change: 2014 Apr 13 2 | 3 | 4 | clang_complete plugin documentation 5 | 6 | 7 | clang_complete plugin *clang_complete* 8 | 9 | 1. Description |clang_complete-description| 10 | 2. Key bindings |clang_complete-keybindings| 11 | 3. Completion kinds |clang_complete-compl_kinds| 12 | 4. Configuration |clang_complete-configuration| 13 | 5. Options |clang_complete-options| 14 | 6. Known issues |clang_complete-issues| 15 | 7. cc_args.py script |clang_complete-cc_args| 16 | 8. To do |clang_complete-todo| 17 | 9. FAQ |clang_complete-faq| 18 | 10. License |clang_complete-license| 19 | 20 | Author: Xavier Deguillard *clang_complete-author* 21 | 22 | ============================================================================== 23 | 1. Description *clang_complete-description* 24 | 25 | This plugin use clang for accurately completing C and C++ code. 26 | 27 | Note: This plugin is incompatible with omnicppcomplete due to the 28 | unconditionnaly set mapping done by omnicppcomplete. So don't forget to 29 | suppress it before using this plugin. 30 | 31 | ============================================================================== 32 | 2. Key bindings *clang_complete-keybindings* 33 | 34 | Completion is started with CTRL-X CTRL-U |i_CTRL-X_CTRL-U|, or automatically 35 | depending on the value of |clang_complete-auto|. 36 | 37 | You can also jump to the declaration of the symbol under the cursor with 38 | . Jumping back is done with . Since clang_complete uses 39 | |jumplist|, you can navigate through the jumps with and 40 | 41 | ============================================================================== 42 | 3. Completion kinds *clang_complete-compl_kinds* 43 | 44 | Because libclang provides a lot of information about completion, there are 45 | some additional kinds of completion along with standard ones (see 46 | |complete-items| for details): 47 | '+' - constructor 48 | '~' - destructor 49 | 'e' - enumerator constant 50 | 'a' - parameter ('a' from "argument") of a function, method or template 51 | 'u' - unknown or buildin type (int, float, ...) 52 | 'n' - namespace or its alias 53 | 'p' - template ('p' from "pattern") 54 | 55 | ============================================================================== 56 | 4. Configuration *clang_complete-configuration* 57 | 58 | Each project can have a .clang_complete at its root, containing the compiler 59 | options. This is useful if you're using some non-standard include paths or 60 | need to specify particular architecture type, frameworks to use, path to 61 | precompiled headers, precompiler definitions etc. 62 | 63 | Note that as with other option sources, .clang_complete file is loaded and 64 | parsed by the plugin only on buffer loading (or reloading, for example with 65 | :edit! command). Thus no changes made to .clang_complete file after loading 66 | source file into Vim's buffer will take effect until buffer will be closed and 67 | opened again, reloaded or Vim is restarted. 68 | 69 | Compiler options should go on individual lines (multiple options on one line 70 | can work sometimes too, but since there are some not obvious conditions for 71 | that, it's better to have one option per line). 72 | 73 | Linking isn't performed during completion, so one doesn't need to specify any 74 | of linker arguments in .clang_complete file. They will lead to completion 75 | failure when using clang executable and will be completely ignored by 76 | libclang. 77 | 78 | Example .clang_complete file: > 79 | -DDEBUG 80 | -include ../config.h 81 | -I../common 82 | -I/usr/include/c++/4.5.3/ 83 | -I/usr/include/c++/4.5.3/x86_64-slackware-linux/ 84 | < 85 | ============================================================================== 86 | 5. Options *clang_complete-options* 87 | 88 | *clang_complete-loaded* 89 | *g:clang_complete_loaded* 90 | If set, clang_complete won't be loaded. 91 | Default: unset. 92 | 93 | *clang_complete-auto_select* 94 | *g:clang_auto_select* 95 | If equal to 0, nothing is selected. 96 | If equal to 1, automatically select the first entry in the popup menu, but 97 | without inserting it into the code. 98 | If equal to 2, automatically select the first entry in the popup menu, and 99 | insert it into the code. 100 | Default: 0 101 | 102 | *clang_complete-complete_auto* 103 | *g:clang_complete_auto* 104 | If equal to 1, automatically complete after ->, ., :: 105 | Default: 1 106 | 107 | *clang_complete-copen* 108 | *g:clang_complete_copen* 109 | If equal to 1, open quickfix window on error. 110 | Default: 0 111 | 112 | *clang_complete-hl_errors* 113 | *g:clang_hl_errors* 114 | If equal to 1, it will highlight the warnings and errors the same way clang 115 | does it. 116 | Default: 1 117 | 118 | *clang_complete-periodic_quickfix* 119 | *g:clang_periodic_quickfix* 120 | If equal to 1, it will periodically update the quickfix window. 121 | Default: 0 122 | Note: You could use the g:ClangUpdateQuickFix() to do the same with a mapping. 123 | 124 | *clang_complete-snippets* 125 | *g:clang_snippets* 126 | If equal to 1, it will do some snippets magic on code placeholders like 127 | function argument, template parameters, etc. 128 | Default: 0 129 | 130 | *clang_complete-snippets_engine* 131 | *g:clang_snippets_engine* 132 | The snippets engine (clang_complete, ultisnips... see the snippets 133 | subdirectory). 134 | Default: "clang_complete" 135 | 136 | *clang_complete-conceal_snippets* 137 | *g:clang_conceal_snippets* 138 | Note: This option is specific to clang_complete snippets engine. 139 | If equal to 1, clang_complete will use vim 7.3 conceal feature to hide the 140 | snippet placeholders. 141 | 142 | Example of conceal configuration (see |'concealcursor'| and |'conceallevel'| 143 | for details): > 144 | " conceal in insert (i), normal (n) and visual (v) modes 145 | set concealcursor=inv 146 | " hide concealed text completely unless replacement character is defined 147 | set conceallevel=2 148 | 149 | Default: 1 (0 if conceal not available) 150 | 151 | *clang_complete-clang_trailing_placeholder* 152 | *g:clang_trailing_placeholder* 153 | Note: This option is specific to clang_complete snippets engine. 154 | If equal to 1, clang_complete will add a trailing placeholder after functions 155 | to let you add you continue writing code faster. 156 | Default: 0 157 | 158 | *clang_complete-clang_restore_cr_imap* 159 | *g:clang_restore_cr_imap* 160 | This option is used for versions of Vim without the Dictionary version of 161 | |maparg()| introduced in 7.3.32. The variable is executed after completion to 162 | restore the insert-mode map of . Occurrences of "" in the variable 163 | are replaced with the appropriate "" code based on the original map. 164 | Default: 'iunmap ' 165 | 166 | *clang_close-preview* 167 | *g:clang_close_preview* 168 | If equal to 1, the preview window will be close automatically after a 169 | completion. 170 | Default: 0 171 | 172 | *clang_complete-user_options* 173 | *g:clang_user_options* 174 | Additionnal compilation argument passed to libclang. 175 | 176 | Example: > 177 | " compile all sources as c++11 (just for example, use .clang_complete for 178 | " setting version of the language per project) 179 | let g:clang_user_options = '-std=c++11' 180 | < 181 | Default: "" 182 | 183 | *clang_complete-auto_user_options* 184 | *g:clang_auto_user_options* 185 | Set sources for user options passed to clang. Available sources are: 186 | - path - use &path content as list of include directories (relative paths are 187 | ignored); 188 | - .clang_complete - use information from .clang_complete file Multiple options 189 | are separated by comma; 190 | - compile_commands.json - get the compilation arguments for the sources from a 191 | compilation database. For example, recent versions of CMake (>=2.8.7) can 192 | output this information. clang_complete will search upwards from where vi 193 | was started for a database named 'compile_commands.json'. 194 | Note : compilation databases can only be used when 'g:clang_use_library' 195 | equals 1 and the clang libraries are recent enough (clang>=3.2). The 196 | compilation database only contains information for the C/C++ sources files, 197 | so when editing a header, clang_complete will reuse the compilation 198 | arguments from the last file found in the database. 199 | - {anything} else will be treaded as a custom option source in the following 200 | manner: clang_complete will try to load the autoload-function named 201 | getopts#{anything}#getopts, which then will be able to modify 202 | b:clang_user_options variable. See help on |autoload| if you don't know 203 | what it is. 204 | 205 | This option is processed and all sources are used on buffer loading, not each 206 | time before doing completion. 207 | 208 | Default: ".clang_complete, path" 209 | 210 | *clang_complete-compilation_database* 211 | *g:clang_compilation_database* 212 | By default, clang_complete will search upwards from where it was started to 213 | find a compilation database. In case this behaviour does not match your needs, 214 | you can set |g:clang_compilation_database| to the directory where the database 215 | can be loaded from. 216 | 217 | *clang_complete-use_library* 218 | *g:clang_use_library* 219 | Instead of calling the clang/clang++ tool use libclang directly. This gives 220 | access to many more clang features. Furthermore it automatically caches all 221 | includes in memory. Updates after changes in the same file will therefore be a 222 | lot faster. 223 | Note: This version doesn't support calling clang binary for completion. If you 224 | cannot use libclang, you should download clang_complete from vim.org website. 225 | Default: 1 226 | 227 | *clang_complete-library_path* 228 | *g:clang_library_path* 229 | If libclang is not in your library search path, set this to the absolute path 230 | where libclang is available. This should either be a directory containing a 231 | file named libclang.[dll/so/dylib] or the clang shared library file itself. 232 | Default: "" 233 | 234 | *clang_complete-sort_algo* 235 | *g:clang_sort_algo* 236 | How results are sorted (alpha, priority, none). Currently only works with 237 | libclang. 238 | Default: "priority" 239 | 240 | *clang_complete-complete_macros* 241 | *g:clang_complete_macros* 242 | If clang should complete preprocessor macros and constants. 243 | Default: 0 244 | 245 | *clang_complete-complete_patterns* 246 | *g:clang_complete_patterns* 247 | If clang should complete code patterns, i.e loop constructs etc. 248 | Defaut: 0 249 | 250 | *clang_complete-jumpto_declaration_key* 251 | *g:clang_jumpto_declaration_key* 252 | Set the key used to jump to declaration. 253 | Defaut: "" 254 | Note: You could use the g:ClangGotoDeclaration() to do the same with a mapping. 255 | 256 | *clang_complete-jumpto_declaration_in_preview_key* 257 | *g:clang_jumpto_declaration_in_preview_key* 258 | Set the key used to jump to declaration in a preview window. 259 | Defaut: "]" 260 | Note: You could use the g:ClangGotoDeclarationPreview() to do the same with a mapping. 261 | 262 | *clang_complete-jumpto_back_key* 263 | *g:clang_jumpto_back_key* 264 | Set the key used to jump back. 265 | Note: Effectively this will be remapped to . The default value is chosen 266 | to be coherent with ctags implementation. 267 | Defaut: "" 268 | 269 | *clang_complete-make_default_keymappings* 270 | *g:clang_make_default_keymappings* 271 | If this option is set, the default keymappings will be set by clang_complete. 272 | Otherwise none are set and the user will have to provide those keymappings. 273 | Default: 1 274 | 275 | ============================================================================== 276 | 6. Known issues *clang_complete-issues* 277 | 278 | If you get following error message while trying to complete anything: > 279 | E121: Undefined variable: b:should_overload 280 | it means that your version of Vim is too old (this is an old bug and it has 281 | been fixed with one of patches for Vim 7.2) and you need to update it. 282 | 283 | Ubuntu users may need to install libclang-dev: > 284 | apt-get install libclang-dev 285 | 286 | ============================================================================== 287 | 7. cc_args.py script *clang_complete-cc_args* 288 | 289 | This script, installed at ~/.vim/bin/cc_args.py, could be used to generate or 290 | update the .clang_complete file. It works similar to gccsence's gccrec and 291 | simply stores -I and -D arguments passed to the compiler in the 292 | .clang_complete file. Just add the cc_args.py script as the first argument of 293 | the compile command. You should do that every time compile options have 294 | changed. 295 | 296 | Example (we need -B flag to force compiling even if project is up to date): > 297 | make CC='~/.vim/bin/cc_args.py gcc' CXX='~/.vim/bin/cc_args.py g++' -B 298 | After running this command, .clang_complete will be created or updated with 299 | new options. If you don't want to update an existing configuration file, 300 | delete it before running make. 301 | 302 | ============================================================================== 303 | 8. To do *clang_complete-todo* 304 | 305 | - Write some unit tests 306 | - Explore "jump to declaration/definition" with libclang FGJ 307 | - Think about supertab ( with supertab and clang_auto_select) 308 | 309 | ============================================================================== 310 | 9. FAQ *clang_complete-faq* 311 | 312 | *) clang_complete doesn't work! I always get the message "pattern not found". 313 | 314 | This can have multiple reasons. You can try to open the quickfix window 315 | (:copen) that displays the error messages from clang to get a better idea what 316 | goes on. It might be that you need to update your .clang_complete file. If 317 | this does not help, keep in mind that clang_complete can cause clang to search 318 | for header files first in the system-wide paths and then in the ones specified 319 | locally in .clang_complete. Therefore you might have to add "-nostdinc" and 320 | the system include paths in the right order to .clang_complete. 321 | 322 | *) Only function names get completed but not the parentheses/parameters. 323 | 324 | Enable the snippets-support by adding the following lines to your .vimrc, 325 | for example: 326 | 327 | let g:clang_snippets = 1 328 | let g:clang_snippets_engine = 'clang_complete' 329 | 330 | If you have ultisnips installed, you can use 331 | 332 | let g:clang_snippets = 1 333 | let g:clang_snippets_engine = 'ultisnips' 334 | 335 | instead. After a completion you can use in normal mode to jump to the 336 | next parameter. 337 | 338 | *) Can I configure clang_complete to insert the text automatically when there 339 | is only one possibility? 340 | 341 | You can configure vim to complete automatically the longest common match by 342 | adding the following line to your vimrc: 343 | 344 | set completeopt=menu,longest 345 | 346 | ============================================================================== 347 | 10. License *clang_complete-license* 348 | 349 | Copyright (c) 2010, 2011, 2012, 2013 Xavier Deguillard, Tobias Grosser 350 | All rights reserved. 351 | 352 | Redistribution and use in source and binary forms, with or without 353 | modification, are permitted provided that the following conditions are met: 354 | * Redistributions of source code must retain the above copyright 355 | notice, this list of conditions and the following disclaimer. 356 | * Redistributions in binary form must reproduce the above copyright 357 | notice, this list of conditions and the following disclaimer in the 358 | documentation and/or other materials provided with the distribution. 359 | * Neither the name of the copyright holders nor the names of their 360 | contributors may be used to endorse or promote products derived from 361 | this software without specific prior written permission. 362 | 363 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 364 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 365 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 366 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE 367 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 368 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 369 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 370 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 371 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 372 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 373 | 374 | Note: This license does not cover the files that come from the LLVM project, 375 | namely, cindex.py and __init__.py, which are covered by the LLVM license. 376 | 377 | vim:tw=78:ts=8:ft=help:norl: 378 | -------------------------------------------------------------------------------- /examples/boost.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main() 15 | { 16 | boost::matc 17 | // ^ Code complete here by typing ":" 18 | } 19 | -------------------------------------------------------------------------------- /plugin/clang/__init__.py: -------------------------------------------------------------------------------- 1 | #===- __init__.py - Clang Python 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 | 10 | r""" 11 | Clang Library Bindings 12 | ====================== 13 | 14 | This package provides access to the Clang compiler and libraries. 15 | 16 | The available modules are: 17 | 18 | cindex 19 | 20 | Bindings for the Clang indexing library. 21 | """ 22 | 23 | __all__ = ['cindex'] 24 | -------------------------------------------------------------------------------- /plugin/clang/cindex.py: -------------------------------------------------------------------------------- 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 | 10 | r""" 11 | Clang Indexing Library Bindings 12 | =============================== 13 | 14 | This module provides an interface to the Clang indexing library. It is a 15 | low-level interface to the indexing library which attempts to match the Clang 16 | API directly while also being "pythonic". Notable differences from the C API 17 | are: 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 | 25 | The 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 | 44 | Most object information is exposed using properties, when the underlying API 45 | call 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 | 65 | from ctypes import ( 66 | CFUNCTYPE, POINTER, Structure, 67 | c_void_p, c_uint, c_int, c_ulong, c_longlong, c_ulonglong, c_char_p, 68 | byref, cast, cdll, py_object 69 | ) 70 | import collections 71 | import sys 72 | 73 | import clang.enumerations 74 | 75 | # ctypes doesn't implicitly convert c_void_p to the appropriate wrapper 76 | # object. This is a problem, because it means that from_parameter will see an 77 | # integer and pass the wrong value on platforms where int != void*. Work around 78 | # this by marshalling object arguments as void**. 79 | c_object_p = POINTER(c_void_p) 80 | 81 | callbacks = {} 82 | 83 | 84 | def encode(value): 85 | if sys.version_info[0] == 2: 86 | return value 87 | else: 88 | return value.encode('utf-8') 89 | 90 | 91 | ### Exception Classes ### 92 | 93 | class TranslationUnitLoadError(Exception): 94 | """Represents an error that occurred when loading a TranslationUnit. 95 | 96 | This is raised in the case where a TranslationUnit could not be 97 | instantiated due to failure in the libclang library. 98 | 99 | FIXME: Make libclang expose additional error information in this scenario. 100 | """ 101 | 102 | class TranslationUnitSaveError(Exception): 103 | """Represents an error that occurred when saving a TranslationUnit. 104 | 105 | Each error has associated with it an enumerated value, accessible under 106 | e.save_error. Consumers can compare the value with one of the ERROR_ 107 | constants in this class. 108 | """ 109 | 110 | # Indicates that an unknown error occurred. This typically indicates that 111 | # I/O failed during save. 112 | ERROR_UNKNOWN = 1 113 | 114 | # Indicates that errors during translation prevented saving. The errors 115 | # should be available via the TranslationUnit's diagnostics. 116 | ERROR_TRANSLATION_ERRORS = 2 117 | 118 | # Indicates that the translation unit was somehow invalid. 119 | ERROR_INVALID_TU = 3 120 | 121 | def __init__(self, enumeration, message): 122 | assert isinstance(enumeration, int) 123 | 124 | if enumeration < 1 or enumeration > 3: 125 | raise Exception("Encountered undefined TranslationUnit save error " 126 | "constant: %d. Please file a bug to have this " 127 | "value supported." % enumeration) 128 | 129 | self.save_error = enumeration 130 | Exception.__init__(self, 'Error %d: %s' % (enumeration, message)) 131 | 132 | ### Structures and Utility Classes ### 133 | 134 | class CachedProperty(object): 135 | """Decorator that lazy-loads the value of a property. 136 | 137 | The first time the property is accessed, the original property function is 138 | executed. The value it returns is set as the new value of that instance's 139 | property, replacing the original method. 140 | """ 141 | 142 | def __init__(self, wrapped): 143 | self.wrapped = wrapped 144 | try: 145 | self.__doc__ = wrapped.__doc__ 146 | except: 147 | pass 148 | 149 | def __get__(self, instance, instance_type=None): 150 | if instance is None: 151 | return self 152 | 153 | value = self.wrapped(instance) 154 | setattr(instance, self.wrapped.__name__, value) 155 | 156 | return value 157 | 158 | 159 | class _CXString(Structure): 160 | """Helper for transforming CXString results.""" 161 | 162 | _fields_ = [("spelling", c_char_p), ("free", c_int)] 163 | 164 | def __del__(self): 165 | conf.lib.clang_disposeString(self) 166 | 167 | @staticmethod 168 | def from_result(res, fn, args): 169 | assert isinstance(res, _CXString) 170 | return conf.lib.clang_getCString(res) 171 | 172 | class SourceLocation(Structure): 173 | """ 174 | A SourceLocation represents a particular location within a source file. 175 | """ 176 | _fields_ = [("ptr_data", c_void_p * 2), ("int_data", c_uint)] 177 | _data = None 178 | 179 | def _get_instantiation(self): 180 | if self._data is None: 181 | f, l, c, o = c_object_p(), c_uint(), c_uint(), c_uint() 182 | conf.lib.clang_getInstantiationLocation(self, byref(f), byref(l), 183 | byref(c), byref(o)) 184 | if f: 185 | f = File(f) 186 | else: 187 | f = None 188 | self._data = (f, int(l.value), int(c.value), int(o.value)) 189 | return self._data 190 | 191 | @staticmethod 192 | def from_position(tu, file, line, column): 193 | """ 194 | Retrieve the source location associated with a given file/line/column in 195 | a particular translation unit. 196 | """ 197 | return conf.lib.clang_getLocation(tu, file, line, column) 198 | 199 | @staticmethod 200 | def from_offset(tu, file, offset): 201 | """Retrieve a SourceLocation from a given character offset. 202 | 203 | tu -- TranslationUnit file belongs to 204 | file -- File instance to obtain offset from 205 | offset -- Integer character offset within file 206 | """ 207 | return conf.lib.clang_getLocationForOffset(tu, file, offset) 208 | 209 | @property 210 | def file(self): 211 | """Get the file represented by this source location.""" 212 | return self._get_instantiation()[0] 213 | 214 | @property 215 | def line(self): 216 | """Get the line represented by this source location.""" 217 | return self._get_instantiation()[1] 218 | 219 | @property 220 | def column(self): 221 | """Get the column represented by this source location.""" 222 | return self._get_instantiation()[2] 223 | 224 | @property 225 | def offset(self): 226 | """Get the file offset represented by this source location.""" 227 | return self._get_instantiation()[3] 228 | 229 | def __eq__(self, other): 230 | return conf.lib.clang_equalLocations(self, other) 231 | 232 | def __ne__(self, other): 233 | return not self.__eq__(other) 234 | 235 | def __repr__(self): 236 | if self.file: 237 | filename = self.file.name 238 | else: 239 | filename = None 240 | return "" % ( 241 | filename, self.line, self.column) 242 | 243 | class SourceRange(Structure): 244 | """ 245 | A SourceRange describes a range of source locations within the source 246 | code. 247 | """ 248 | _fields_ = [ 249 | ("ptr_data", c_void_p * 2), 250 | ("begin_int_data", c_uint), 251 | ("end_int_data", c_uint)] 252 | 253 | # FIXME: Eliminate this and make normal constructor? Requires hiding ctypes 254 | # object. 255 | @staticmethod 256 | def from_locations(start, end): 257 | return conf.lib.clang_getRange(start, end) 258 | 259 | @property 260 | def start(self): 261 | """ 262 | Return a SourceLocation representing the first character within a 263 | source range. 264 | """ 265 | return conf.lib.clang_getRangeStart(self) 266 | 267 | @property 268 | def end(self): 269 | """ 270 | Return a SourceLocation representing the last character within a 271 | source range. 272 | """ 273 | return conf.lib.clang_getRangeEnd(self) 274 | 275 | def __eq__(self, other): 276 | return conf.lib.clang_equalRanges(self, other) 277 | 278 | def __ne__(self, other): 279 | return not self.__eq__(other) 280 | 281 | def __repr__(self): 282 | return "" % (self.start, self.end) 283 | 284 | class Diagnostic(object): 285 | """ 286 | A Diagnostic is a single instance of a Clang diagnostic. It includes the 287 | diagnostic severity, the message, the location the diagnostic occurred, as 288 | well as additional source ranges and associated fix-it hints. 289 | """ 290 | 291 | Ignored = 0 292 | Note = 1 293 | Warning = 2 294 | Error = 3 295 | Fatal = 4 296 | 297 | def __init__(self, ptr): 298 | self.ptr = ptr 299 | 300 | def __del__(self): 301 | conf.lib.clang_disposeDiagnostic(self) 302 | 303 | @property 304 | def severity(self): 305 | return conf.lib.clang_getDiagnosticSeverity(self) 306 | 307 | @property 308 | def location(self): 309 | return conf.lib.clang_getDiagnosticLocation(self) 310 | 311 | @property 312 | def spelling(self): 313 | return conf.lib.clang_getDiagnosticSpelling(self) 314 | 315 | @property 316 | def ranges(self): 317 | class RangeIterator: 318 | def __init__(self, diag): 319 | self.diag = diag 320 | 321 | def __len__(self): 322 | return int(conf.lib.clang_getDiagnosticNumRanges(self.diag)) 323 | 324 | def __getitem__(self, key): 325 | if (key >= len(self)): 326 | raise IndexError 327 | return conf.lib.clang_getDiagnosticRange(self.diag, key) 328 | 329 | return RangeIterator(self) 330 | 331 | @property 332 | def fixits(self): 333 | class FixItIterator: 334 | def __init__(self, diag): 335 | self.diag = diag 336 | 337 | def __len__(self): 338 | return int(conf.lib.clang_getDiagnosticNumFixIts(self.diag)) 339 | 340 | def __getitem__(self, key): 341 | range = SourceRange() 342 | value = conf.lib.clang_getDiagnosticFixIt(self.diag, key, 343 | byref(range)) 344 | if len(value) == 0: 345 | raise IndexError 346 | 347 | return FixIt(range, value) 348 | 349 | return FixItIterator(self) 350 | 351 | @property 352 | def category_number(self): 353 | """The category number for this diagnostic.""" 354 | return conf.lib.clang_getDiagnosticCategory(self) 355 | 356 | @property 357 | def category_name(self): 358 | """The string name of the category for this diagnostic.""" 359 | return conf.lib.clang_getDiagnosticCategoryName(self.category_number) 360 | 361 | @property 362 | def option(self): 363 | """The command-line option that enables this diagnostic.""" 364 | return conf.lib.clang_getDiagnosticOption(self, None) 365 | 366 | @property 367 | def disable_option(self): 368 | """The command-line option that disables this diagnostic.""" 369 | disable = _CXString() 370 | conf.lib.clang_getDiagnosticOption(self, byref(disable)) 371 | 372 | return conf.lib.clang_getCString(disable) 373 | 374 | def __repr__(self): 375 | return "" % ( 376 | self.severity, self.location, self.spelling) 377 | 378 | def from_param(self): 379 | return self.ptr 380 | 381 | class FixIt(object): 382 | """ 383 | A FixIt represents a transformation to be applied to the source to 384 | "fix-it". The fix-it shouldbe applied by replacing the given source range 385 | with the given value. 386 | """ 387 | 388 | def __init__(self, range, value): 389 | self.range = range 390 | self.value = value 391 | 392 | def __repr__(self): 393 | return "" % (self.range, self.value) 394 | 395 | class TokenGroup(object): 396 | """Helper class to facilitate token management. 397 | 398 | Tokens are allocated from libclang in chunks. They must be disposed of as a 399 | collective group. 400 | 401 | One purpose of this class is for instances to represent groups of allocated 402 | tokens. Each token in a group contains a reference back to an instance of 403 | this class. When all tokens from a group are garbage collected, it allows 404 | this class to be garbage collected. When this class is garbage collected, 405 | it calls the libclang destructor which invalidates all tokens in the group. 406 | 407 | You should not instantiate this class outside of this module. 408 | """ 409 | def __init__(self, tu, memory, count): 410 | self._tu = tu 411 | self._memory = memory 412 | self._count = count 413 | 414 | def __del__(self): 415 | conf.lib.clang_disposeTokens(self._tu, self._memory, self._count) 416 | 417 | @staticmethod 418 | def get_tokens(tu, extent): 419 | """Helper method to return all tokens in an extent. 420 | 421 | This functionality is needed multiple places in this module. We define 422 | it here because it seems like a logical place. 423 | """ 424 | tokens_memory = POINTER(Token)() 425 | tokens_count = c_uint() 426 | 427 | conf.lib.clang_tokenize(tu, extent, byref(tokens_memory), 428 | byref(tokens_count)) 429 | 430 | count = int(tokens_count.value) 431 | 432 | # If we get no tokens, no memory was allocated. Be sure not to return 433 | # anything and potentially call a destructor on nothing. 434 | if count < 1: 435 | return 436 | 437 | tokens_array = cast(tokens_memory, POINTER(Token * count)).contents 438 | 439 | token_group = TokenGroup(tu, tokens_memory, tokens_count) 440 | 441 | for i in range(0, count): 442 | token = Token() 443 | token.int_data = tokens_array[i].int_data 444 | token.ptr_data = tokens_array[i].ptr_data 445 | token._tu = tu 446 | token._group = token_group 447 | 448 | yield token 449 | 450 | class TokenKind(object): 451 | """Describes a specific type of a Token.""" 452 | 453 | _value_map = {} # int -> TokenKind 454 | 455 | def __init__(self, value, name): 456 | """Create a new TokenKind instance from a numeric value and a name.""" 457 | self.value = value 458 | self.name = name 459 | 460 | def __repr__(self): 461 | return 'TokenKind.%s' % (self.name,) 462 | 463 | @staticmethod 464 | def from_value(value): 465 | """Obtain a registered TokenKind instance from its value.""" 466 | result = TokenKind._value_map.get(value, None) 467 | 468 | if result is None: 469 | raise ValueError('Unknown TokenKind: %d' % value) 470 | 471 | return result 472 | 473 | @staticmethod 474 | def register(value, name): 475 | """Register a new TokenKind enumeration. 476 | 477 | This should only be called at module load time by code within this 478 | package. 479 | """ 480 | if value in TokenKind._value_map: 481 | raise ValueError('TokenKind already registered: %d' % value) 482 | 483 | kind = TokenKind(value, name) 484 | TokenKind._value_map[value] = kind 485 | setattr(TokenKind, name, kind) 486 | 487 | ### Cursor Kinds ### 488 | 489 | class CursorKind(object): 490 | """ 491 | A CursorKind describes the kind of entity that a cursor points to. 492 | """ 493 | 494 | # The unique kind objects, indexed by id. 495 | _kinds = [] 496 | _name_map = None 497 | 498 | def __init__(self, value): 499 | if value >= len(CursorKind._kinds): 500 | CursorKind._kinds += [None] * (value - len(CursorKind._kinds) + 1) 501 | if CursorKind._kinds[value] is not None: 502 | raise ValueError('CursorKind already loaded') 503 | self.value = value 504 | CursorKind._kinds[value] = self 505 | CursorKind._name_map = None 506 | 507 | def from_param(self): 508 | return self.value 509 | 510 | @property 511 | def name(self): 512 | """Get the enumeration name of this cursor kind.""" 513 | if self._name_map is None: 514 | self._name_map = {} 515 | for key,value in list(CursorKind.__dict__.items()): 516 | if isinstance(value,CursorKind): 517 | self._name_map[value] = key 518 | return self._name_map[self] 519 | 520 | @staticmethod 521 | def from_id(id): 522 | if id >= len(CursorKind._kinds) or CursorKind._kinds[id] is None: 523 | raise ValueError('Unknown cursor kind') 524 | return CursorKind._kinds[id] 525 | 526 | @staticmethod 527 | def get_all_kinds(): 528 | """Return all CursorKind enumeration instances.""" 529 | return [_f for _f in CursorKind._kinds if _f] 530 | 531 | def is_declaration(self): 532 | """Test if this is a declaration kind.""" 533 | return conf.lib.clang_isDeclaration(self) 534 | 535 | def is_reference(self): 536 | """Test if this is a reference kind.""" 537 | return conf.lib.clang_isReference(self) 538 | 539 | def is_expression(self): 540 | """Test if this is an expression kind.""" 541 | return conf.lib.clang_isExpression(self) 542 | 543 | def is_statement(self): 544 | """Test if this is a statement kind.""" 545 | return conf.lib.clang_isStatement(self) 546 | 547 | def is_attribute(self): 548 | """Test if this is an attribute kind.""" 549 | return conf.lib.clang_isAttribute(self) 550 | 551 | def is_invalid(self): 552 | """Test if this is an invalid kind.""" 553 | return conf.lib.clang_isInvalid(self) 554 | 555 | def is_translation_unit(self): 556 | """Test if this is a translation unit kind.""" 557 | return conf.lib.clang_isTranslationUnit(self) 558 | 559 | def is_preprocessing(self): 560 | """Test if this is a preprocessing kind.""" 561 | return conf.lib.clang_isPreprocessing(self) 562 | 563 | def is_unexposed(self): 564 | """Test if this is an unexposed kind.""" 565 | return conf.lib.clang_isUnexposed(self) 566 | 567 | def __repr__(self): 568 | return 'CursorKind.%s' % (self.name,) 569 | 570 | # FIXME: Is there a nicer way to expose this enumeration? We could potentially 571 | # represent the nested structure, or even build a class hierarchy. The main 572 | # things we want for sure are (a) simple external access to kinds, (b) a place 573 | # to hang a description and name, (c) easy to keep in sync with Index.h. 574 | 575 | ### 576 | # Declaration Kinds 577 | 578 | # A declaration whose specific kind is not exposed via this interface. 579 | # 580 | # Unexposed declarations have the same operations as any other kind of 581 | # declaration; one can extract their location information, spelling, find their 582 | # definitions, etc. However, the specific kind of the declaration is not 583 | # reported. 584 | CursorKind.UNEXPOSED_DECL = CursorKind(1) 585 | 586 | # A C or C++ struct. 587 | CursorKind.STRUCT_DECL = CursorKind(2) 588 | 589 | # A C or C++ union. 590 | CursorKind.UNION_DECL = CursorKind(3) 591 | 592 | # A C++ class. 593 | CursorKind.CLASS_DECL = CursorKind(4) 594 | 595 | # An enumeration. 596 | CursorKind.ENUM_DECL = CursorKind(5) 597 | 598 | # A field (in C) or non-static data member (in C++) in a struct, union, or C++ 599 | # class. 600 | CursorKind.FIELD_DECL = CursorKind(6) 601 | 602 | # An enumerator constant. 603 | CursorKind.ENUM_CONSTANT_DECL = CursorKind(7) 604 | 605 | # A function. 606 | CursorKind.FUNCTION_DECL = CursorKind(8) 607 | 608 | # A variable. 609 | CursorKind.VAR_DECL = CursorKind(9) 610 | 611 | # A function or method parameter. 612 | CursorKind.PARM_DECL = CursorKind(10) 613 | 614 | # An Objective-C @interface. 615 | CursorKind.OBJC_INTERFACE_DECL = CursorKind(11) 616 | 617 | # An Objective-C @interface for a category. 618 | CursorKind.OBJC_CATEGORY_DECL = CursorKind(12) 619 | 620 | # An Objective-C @protocol declaration. 621 | CursorKind.OBJC_PROTOCOL_DECL = CursorKind(13) 622 | 623 | # An Objective-C @property declaration. 624 | CursorKind.OBJC_PROPERTY_DECL = CursorKind(14) 625 | 626 | # An Objective-C instance variable. 627 | CursorKind.OBJC_IVAR_DECL = CursorKind(15) 628 | 629 | # An Objective-C instance method. 630 | CursorKind.OBJC_INSTANCE_METHOD_DECL = CursorKind(16) 631 | 632 | # An Objective-C class method. 633 | CursorKind.OBJC_CLASS_METHOD_DECL = CursorKind(17) 634 | 635 | # An Objective-C @implementation. 636 | CursorKind.OBJC_IMPLEMENTATION_DECL = CursorKind(18) 637 | 638 | # An Objective-C @implementation for a category. 639 | CursorKind.OBJC_CATEGORY_IMPL_DECL = CursorKind(19) 640 | 641 | # A typedef. 642 | CursorKind.TYPEDEF_DECL = CursorKind(20) 643 | 644 | # A C++ class method. 645 | CursorKind.CXX_METHOD = CursorKind(21) 646 | 647 | # A C++ namespace. 648 | CursorKind.NAMESPACE = CursorKind(22) 649 | 650 | # A linkage specification, e.g. 'extern "C"'. 651 | CursorKind.LINKAGE_SPEC = CursorKind(23) 652 | 653 | # A C++ constructor. 654 | CursorKind.CONSTRUCTOR = CursorKind(24) 655 | 656 | # A C++ destructor. 657 | CursorKind.DESTRUCTOR = CursorKind(25) 658 | 659 | # A C++ conversion function. 660 | CursorKind.CONVERSION_FUNCTION = CursorKind(26) 661 | 662 | # A C++ template type parameter 663 | CursorKind.TEMPLATE_TYPE_PARAMETER = CursorKind(27) 664 | 665 | # A C++ non-type template paramater. 666 | CursorKind.TEMPLATE_NON_TYPE_PARAMETER = CursorKind(28) 667 | 668 | # A C++ template template parameter. 669 | CursorKind.TEMPLATE_TEMPLATE_PARAMETER = CursorKind(29) 670 | 671 | # A C++ function template. 672 | CursorKind.FUNCTION_TEMPLATE = CursorKind(30) 673 | 674 | # A C++ class template. 675 | CursorKind.CLASS_TEMPLATE = CursorKind(31) 676 | 677 | # A C++ class template partial specialization. 678 | CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION = CursorKind(32) 679 | 680 | # A C++ namespace alias declaration. 681 | CursorKind.NAMESPACE_ALIAS = CursorKind(33) 682 | 683 | # A C++ using directive 684 | CursorKind.USING_DIRECTIVE = CursorKind(34) 685 | 686 | # A C++ using declaration 687 | CursorKind.USING_DECLARATION = CursorKind(35) 688 | 689 | # A Type alias decl. 690 | CursorKind.TYPE_ALIAS_DECL = CursorKind(36) 691 | 692 | # A Objective-C synthesize decl 693 | CursorKind.OBJC_SYNTHESIZE_DECL = CursorKind(37) 694 | 695 | # A Objective-C dynamic decl 696 | CursorKind.OBJC_DYNAMIC_DECL = CursorKind(38) 697 | 698 | # A C++ access specifier decl. 699 | CursorKind.CXX_ACCESS_SPEC_DECL = CursorKind(39) 700 | 701 | 702 | ### 703 | # Reference Kinds 704 | 705 | CursorKind.OBJC_SUPER_CLASS_REF = CursorKind(40) 706 | CursorKind.OBJC_PROTOCOL_REF = CursorKind(41) 707 | CursorKind.OBJC_CLASS_REF = CursorKind(42) 708 | 709 | # A reference to a type declaration. 710 | # 711 | # A type reference occurs anywhere where a type is named but not 712 | # declared. For example, given: 713 | # typedef unsigned size_type; 714 | # size_type size; 715 | # 716 | # The typedef is a declaration of size_type (CXCursor_TypedefDecl), 717 | # while the type of the variable "size" is referenced. The cursor 718 | # referenced by the type of size is the typedef for size_type. 719 | CursorKind.TYPE_REF = CursorKind(43) 720 | CursorKind.CXX_BASE_SPECIFIER = CursorKind(44) 721 | 722 | # A reference to a class template, function template, template 723 | # template parameter, or class template partial specialization. 724 | CursorKind.TEMPLATE_REF = CursorKind(45) 725 | 726 | # A reference to a namespace or namepsace alias. 727 | CursorKind.NAMESPACE_REF = CursorKind(46) 728 | 729 | # A reference to a member of a struct, union, or class that occurs in 730 | # some non-expression context, e.g., a designated initializer. 731 | CursorKind.MEMBER_REF = CursorKind(47) 732 | 733 | # A reference to a labeled statement. 734 | CursorKind.LABEL_REF = CursorKind(48) 735 | 736 | # A reference toa a set of overloaded functions or function templates 737 | # that has not yet been resolved to a specific function or function template. 738 | CursorKind.OVERLOADED_DECL_REF = CursorKind(49) 739 | 740 | ### 741 | # Invalid/Error Kinds 742 | 743 | CursorKind.INVALID_FILE = CursorKind(70) 744 | CursorKind.NO_DECL_FOUND = CursorKind(71) 745 | CursorKind.NOT_IMPLEMENTED = CursorKind(72) 746 | CursorKind.INVALID_CODE = CursorKind(73) 747 | 748 | ### 749 | # Expression Kinds 750 | 751 | # An expression whose specific kind is not exposed via this interface. 752 | # 753 | # Unexposed expressions have the same operations as any other kind of 754 | # expression; one can extract their location information, spelling, children, 755 | # etc. However, the specific kind of the expression is not reported. 756 | CursorKind.UNEXPOSED_EXPR = CursorKind(100) 757 | 758 | # An expression that refers to some value declaration, such as a function, 759 | # varible, or enumerator. 760 | CursorKind.DECL_REF_EXPR = CursorKind(101) 761 | 762 | # An expression that refers to a member of a struct, union, class, Objective-C 763 | # class, etc. 764 | CursorKind.MEMBER_REF_EXPR = CursorKind(102) 765 | 766 | # An expression that calls a function. 767 | CursorKind.CALL_EXPR = CursorKind(103) 768 | 769 | # An expression that sends a message to an Objective-C object or class. 770 | CursorKind.OBJC_MESSAGE_EXPR = CursorKind(104) 771 | 772 | # An expression that represents a block literal. 773 | CursorKind.BLOCK_EXPR = CursorKind(105) 774 | 775 | # An integer literal. 776 | CursorKind.INTEGER_LITERAL = CursorKind(106) 777 | 778 | # A floating point number literal. 779 | CursorKind.FLOATING_LITERAL = CursorKind(107) 780 | 781 | # An imaginary number literal. 782 | CursorKind.IMAGINARY_LITERAL = CursorKind(108) 783 | 784 | # A string literal. 785 | CursorKind.STRING_LITERAL = CursorKind(109) 786 | 787 | # A character literal. 788 | CursorKind.CHARACTER_LITERAL = CursorKind(110) 789 | 790 | # A parenthesized expression, e.g. "(1)". 791 | # 792 | # This AST node is only formed if full location information is requested. 793 | CursorKind.PAREN_EXPR = CursorKind(111) 794 | 795 | # This represents the unary-expression's (except sizeof and 796 | # alignof). 797 | CursorKind.UNARY_OPERATOR = CursorKind(112) 798 | 799 | # [C99 6.5.2.1] Array Subscripting. 800 | CursorKind.ARRAY_SUBSCRIPT_EXPR = CursorKind(113) 801 | 802 | # A builtin binary operation expression such as "x + y" or 803 | # "x <= y". 804 | CursorKind.BINARY_OPERATOR = CursorKind(114) 805 | 806 | # Compound assignment such as "+=". 807 | CursorKind.COMPOUND_ASSIGNMENT_OPERATOR = CursorKind(115) 808 | 809 | # The ?: ternary operator. 810 | CursorKind.CONDITIONAL_OPERATOR = CursorKind(116) 811 | 812 | # An explicit cast in C (C99 6.5.4) or a C-style cast in C++ 813 | # (C++ [expr.cast]), which uses the syntax (Type)expr. 814 | # 815 | # For example: (int)f. 816 | CursorKind.CSTYLE_CAST_EXPR = CursorKind(117) 817 | 818 | # [C99 6.5.2.5] 819 | CursorKind.COMPOUND_LITERAL_EXPR = CursorKind(118) 820 | 821 | # Describes an C or C++ initializer list. 822 | CursorKind.INIT_LIST_EXPR = CursorKind(119) 823 | 824 | # The GNU address of label extension, representing &&label. 825 | CursorKind.ADDR_LABEL_EXPR = CursorKind(120) 826 | 827 | # This is the GNU Statement Expression extension: ({int X=4; X;}) 828 | CursorKind.StmtExpr = CursorKind(121) 829 | 830 | # Represents a C11 generic selection. 831 | CursorKind.GENERIC_SELECTION_EXPR = CursorKind(122) 832 | 833 | # Implements the GNU __null extension, which is a name for a null 834 | # pointer constant that has integral type (e.g., int or long) and is the same 835 | # size and alignment as a pointer. 836 | # 837 | # The __null extension is typically only used by system headers, which define 838 | # NULL as __null in C++ rather than using 0 (which is an integer that may not 839 | # match the size of a pointer). 840 | CursorKind.GNU_NULL_EXPR = CursorKind(123) 841 | 842 | # C++'s static_cast<> expression. 843 | CursorKind.CXX_STATIC_CAST_EXPR = CursorKind(124) 844 | 845 | # C++'s dynamic_cast<> expression. 846 | CursorKind.CXX_DYNAMIC_CAST_EXPR = CursorKind(125) 847 | 848 | # C++'s reinterpret_cast<> expression. 849 | CursorKind.CXX_REINTERPRET_CAST_EXPR = CursorKind(126) 850 | 851 | # C++'s const_cast<> expression. 852 | CursorKind.CXX_CONST_CAST_EXPR = CursorKind(127) 853 | 854 | # Represents an explicit C++ type conversion that uses "functional" 855 | # notion (C++ [expr.type.conv]). 856 | # 857 | # Example: 858 | # \code 859 | # x = int(0.5); 860 | # \endcode 861 | CursorKind.CXX_FUNCTIONAL_CAST_EXPR = CursorKind(128) 862 | 863 | # A C++ typeid expression (C++ [expr.typeid]). 864 | CursorKind.CXX_TYPEID_EXPR = CursorKind(129) 865 | 866 | # [C++ 2.13.5] C++ Boolean Literal. 867 | CursorKind.CXX_BOOL_LITERAL_EXPR = CursorKind(130) 868 | 869 | # [C++0x 2.14.7] C++ Pointer Literal. 870 | CursorKind.CXX_NULL_PTR_LITERAL_EXPR = CursorKind(131) 871 | 872 | # Represents the "this" expression in C++ 873 | CursorKind.CXX_THIS_EXPR = CursorKind(132) 874 | 875 | # [C++ 15] C++ Throw Expression. 876 | # 877 | # This handles 'throw' and 'throw' assignment-expression. When 878 | # assignment-expression isn't present, Op will be null. 879 | CursorKind.CXX_THROW_EXPR = CursorKind(133) 880 | 881 | # A new expression for memory allocation and constructor calls, e.g: 882 | # "new CXXNewExpr(foo)". 883 | CursorKind.CXX_NEW_EXPR = CursorKind(134) 884 | 885 | # A delete expression for memory deallocation and destructor calls, 886 | # e.g. "delete[] pArray". 887 | CursorKind.CXX_DELETE_EXPR = CursorKind(135) 888 | 889 | # Represents a unary expression. 890 | CursorKind.CXX_UNARY_EXPR = CursorKind(136) 891 | 892 | # ObjCStringLiteral, used for Objective-C string literals i.e. "foo". 893 | CursorKind.OBJC_STRING_LITERAL = CursorKind(137) 894 | 895 | # ObjCEncodeExpr, used for in Objective-C. 896 | CursorKind.OBJC_ENCODE_EXPR = CursorKind(138) 897 | 898 | # ObjCSelectorExpr used for in Objective-C. 899 | CursorKind.OBJC_SELECTOR_EXPR = CursorKind(139) 900 | 901 | # Objective-C's protocol expression. 902 | CursorKind.OBJC_PROTOCOL_EXPR = CursorKind(140) 903 | 904 | # An Objective-C "bridged" cast expression, which casts between 905 | # Objective-C pointers and C pointers, transferring ownership in the process. 906 | # 907 | # \code 908 | # NSString *str = (__bridge_transfer NSString *)CFCreateString(); 909 | # \endcode 910 | CursorKind.OBJC_BRIDGE_CAST_EXPR = CursorKind(141) 911 | 912 | # Represents a C++0x pack expansion that produces a sequence of 913 | # expressions. 914 | # 915 | # A pack expansion expression contains a pattern (which itself is an 916 | # expression) followed by an ellipsis. For example: 917 | CursorKind.PACK_EXPANSION_EXPR = CursorKind(142) 918 | 919 | # Represents an expression that computes the length of a parameter 920 | # pack. 921 | CursorKind.SIZE_OF_PACK_EXPR = CursorKind(143) 922 | 923 | # A statement whose specific kind is not exposed via this interface. 924 | # 925 | # Unexposed statements have the same operations as any other kind of statement; 926 | # one can extract their location information, spelling, children, etc. However, 927 | # the specific kind of the statement is not reported. 928 | CursorKind.UNEXPOSED_STMT = CursorKind(200) 929 | 930 | # A labelled statement in a function. 931 | CursorKind.LABEL_STMT = CursorKind(201) 932 | 933 | # A compound statement 934 | CursorKind.COMPOUND_STMT = CursorKind(202) 935 | 936 | # A case statement. 937 | CursorKind.CASE_STMT = CursorKind(203) 938 | 939 | # A default statement. 940 | CursorKind.DEFAULT_STMT = CursorKind(204) 941 | 942 | # An if statement. 943 | CursorKind.IF_STMT = CursorKind(205) 944 | 945 | # A switch statement. 946 | CursorKind.SWITCH_STMT = CursorKind(206) 947 | 948 | # A while statement. 949 | CursorKind.WHILE_STMT = CursorKind(207) 950 | 951 | # A do statement. 952 | CursorKind.DO_STMT = CursorKind(208) 953 | 954 | # A for statement. 955 | CursorKind.FOR_STMT = CursorKind(209) 956 | 957 | # A goto statement. 958 | CursorKind.GOTO_STMT = CursorKind(210) 959 | 960 | # An indirect goto statement. 961 | CursorKind.INDIRECT_GOTO_STMT = CursorKind(211) 962 | 963 | # A continue statement. 964 | CursorKind.CONTINUE_STMT = CursorKind(212) 965 | 966 | # A break statement. 967 | CursorKind.BREAK_STMT = CursorKind(213) 968 | 969 | # A return statement. 970 | CursorKind.RETURN_STMT = CursorKind(214) 971 | 972 | # A GNU-style inline assembler statement. 973 | CursorKind.ASM_STMT = CursorKind(215) 974 | 975 | # Objective-C's overall @try-@catch-@finally statement. 976 | CursorKind.OBJC_AT_TRY_STMT = CursorKind(216) 977 | 978 | # Objective-C's @catch statement. 979 | CursorKind.OBJC_AT_CATCH_STMT = CursorKind(217) 980 | 981 | # Objective-C's @finally statement. 982 | CursorKind.OBJC_AT_FINALLY_STMT = CursorKind(218) 983 | 984 | # Objective-C's @throw statement. 985 | CursorKind.OBJC_AT_THROW_STMT = CursorKind(219) 986 | 987 | # Objective-C's @synchronized statement. 988 | CursorKind.OBJC_AT_SYNCHRONIZED_STMT = CursorKind(220) 989 | 990 | # Objective-C's autorealease pool statement. 991 | CursorKind.OBJC_AUTORELEASE_POOL_STMT = CursorKind(221) 992 | 993 | # Objective-C's for collection statement. 994 | CursorKind.OBJC_FOR_COLLECTION_STMT = CursorKind(222) 995 | 996 | # C++'s catch statement. 997 | CursorKind.CXX_CATCH_STMT = CursorKind(223) 998 | 999 | # C++'s try statement. 1000 | CursorKind.CXX_TRY_STMT = CursorKind(224) 1001 | 1002 | # C++'s for (* : *) statement. 1003 | CursorKind.CXX_FOR_RANGE_STMT = CursorKind(225) 1004 | 1005 | # Windows Structured Exception Handling's try statement. 1006 | CursorKind.SEH_TRY_STMT = CursorKind(226) 1007 | 1008 | # Windows Structured Exception Handling's except statement. 1009 | CursorKind.SEH_EXCEPT_STMT = CursorKind(227) 1010 | 1011 | # Windows Structured Exception Handling's finally statement. 1012 | CursorKind.SEH_FINALLY_STMT = CursorKind(228) 1013 | 1014 | # The null statement. 1015 | CursorKind.NULL_STMT = CursorKind(230) 1016 | 1017 | # Adaptor class for mixing declarations with statements and expressions. 1018 | CursorKind.DECL_STMT = CursorKind(231) 1019 | 1020 | ### 1021 | # Other Kinds 1022 | 1023 | # Cursor that represents the translation unit itself. 1024 | # 1025 | # The translation unit cursor exists primarily to act as the root cursor for 1026 | # traversing the contents of a translation unit. 1027 | CursorKind.TRANSLATION_UNIT = CursorKind(300) 1028 | 1029 | ### 1030 | # Attributes 1031 | 1032 | # An attribute whoe specific kind is note exposed via this interface 1033 | CursorKind.UNEXPOSED_ATTR = CursorKind(400) 1034 | 1035 | CursorKind.IB_ACTION_ATTR = CursorKind(401) 1036 | CursorKind.IB_OUTLET_ATTR = CursorKind(402) 1037 | CursorKind.IB_OUTLET_COLLECTION_ATTR = CursorKind(403) 1038 | 1039 | CursorKind.CXX_FINAL_ATTR = CursorKind(404) 1040 | CursorKind.CXX_OVERRIDE_ATTR = CursorKind(405) 1041 | CursorKind.ANNOTATE_ATTR = CursorKind(406) 1042 | CursorKind.ASM_LABEL_ATTR = CursorKind(407) 1043 | 1044 | ### 1045 | # Preprocessing 1046 | CursorKind.PREPROCESSING_DIRECTIVE = CursorKind(500) 1047 | CursorKind.MACRO_DEFINITION = CursorKind(501) 1048 | CursorKind.MACRO_INSTANTIATION = CursorKind(502) 1049 | CursorKind.INCLUSION_DIRECTIVE = CursorKind(503) 1050 | 1051 | ### Cursors ### 1052 | 1053 | class Cursor(Structure): 1054 | """ 1055 | The Cursor class represents a reference to an element within the AST. It 1056 | acts as a kind of iterator. 1057 | """ 1058 | _fields_ = [("_kind_id", c_int), ("xdata", c_int), ("data", c_void_p * 3)] 1059 | 1060 | @staticmethod 1061 | def from_location(tu, location): 1062 | # We store a reference to the TU in the instance so the TU won't get 1063 | # collected before the cursor. 1064 | cursor = conf.lib.clang_getCursor(tu, location) 1065 | cursor._tu = tu 1066 | 1067 | return cursor 1068 | 1069 | def __eq__(self, other): 1070 | return conf.lib.clang_equalCursors(self, other) 1071 | 1072 | def __ne__(self, other): 1073 | return not self.__eq__(other) 1074 | 1075 | def is_definition(self): 1076 | """ 1077 | Returns true if the declaration pointed at by the cursor is also a 1078 | definition of that entity. 1079 | """ 1080 | return conf.lib.clang_isCursorDefinition(self) 1081 | 1082 | def is_static_method(self): 1083 | """Returns True if the cursor refers to a C++ member function or member 1084 | function template that is declared 'static'. 1085 | """ 1086 | return conf.lib.clang_CXXMethod_isStatic(self) 1087 | 1088 | def get_definition(self): 1089 | """ 1090 | If the cursor is a reference to a declaration or a declaration of 1091 | some entity, return a cursor that points to the definition of that 1092 | entity. 1093 | """ 1094 | # TODO: Should probably check that this is either a reference or 1095 | # declaration prior to issuing the lookup. 1096 | return conf.lib.clang_getCursorDefinition(self) 1097 | 1098 | def get_usr(self): 1099 | """Return the Unified Symbol Resultion (USR) for the entity referenced 1100 | by the given cursor (or None). 1101 | 1102 | A Unified Symbol Resolution (USR) is a string that identifies a 1103 | particular entity (function, class, variable, etc.) within a 1104 | program. USRs can be compared across translation units to determine, 1105 | e.g., when references in one translation refer to an entity defined in 1106 | another translation unit.""" 1107 | return conf.lib.clang_getCursorUSR(self) 1108 | 1109 | @property 1110 | def kind(self): 1111 | """Return the kind of this cursor.""" 1112 | return CursorKind.from_id(self._kind_id) 1113 | 1114 | @property 1115 | def spelling(self): 1116 | """Return the spelling of the entity pointed at by the cursor.""" 1117 | if not self.kind.is_declaration(): 1118 | # FIXME: clang_getCursorSpelling should be fixed to not assert on 1119 | # this, for consistency with clang_getCursorUSR. 1120 | return None 1121 | if not hasattr(self, '_spelling'): 1122 | self._spelling = conf.lib.clang_getCursorSpelling(self) 1123 | 1124 | return self._spelling 1125 | 1126 | @property 1127 | def displayname(self): 1128 | """ 1129 | Return the display name for the entity referenced by this cursor. 1130 | 1131 | The display name contains extra information that helps identify the cursor, 1132 | such as the parameters of a function or template or the arguments of a 1133 | class template specialization. 1134 | """ 1135 | if not hasattr(self, '_displayname'): 1136 | self._displayname = conf.lib.clang_getCursorDisplayName(self) 1137 | 1138 | return self._displayname 1139 | 1140 | @property 1141 | def location(self): 1142 | """ 1143 | Return the source location (the starting character) of the entity 1144 | pointed at by the cursor. 1145 | """ 1146 | if not hasattr(self, '_loc'): 1147 | self._loc = conf.lib.clang_getCursorLocation(self) 1148 | 1149 | return self._loc 1150 | 1151 | @property 1152 | def extent(self): 1153 | """ 1154 | Return the source range (the range of text) occupied by the entity 1155 | pointed at by the cursor. 1156 | """ 1157 | if not hasattr(self, '_extent'): 1158 | self._extent = conf.lib.clang_getCursorExtent(self) 1159 | 1160 | return self._extent 1161 | 1162 | @property 1163 | def type(self): 1164 | """ 1165 | Retrieve the Type (if any) of the entity pointed at by the cursor. 1166 | """ 1167 | if not hasattr(self, '_type'): 1168 | self._type = conf.lib.clang_getCursorType(self) 1169 | 1170 | return self._type 1171 | 1172 | @property 1173 | def canonical(self): 1174 | """Return the canonical Cursor corresponding to this Cursor. 1175 | 1176 | The canonical cursor is the cursor which is representative for the 1177 | underlying entity. For example, if you have multiple forward 1178 | declarations for the same class, the canonical cursor for the forward 1179 | declarations will be identical. 1180 | """ 1181 | if not hasattr(self, '_canonical'): 1182 | self._canonical = conf.lib.clang_getCanonicalCursor(self) 1183 | 1184 | return self._canonical 1185 | 1186 | @property 1187 | def result_type(self): 1188 | """Retrieve the Type of the result for this Cursor.""" 1189 | if not hasattr(self, '_result_type'): 1190 | self._result_type = conf.lib.clang_getResultType(self.type) 1191 | 1192 | return self._result_type 1193 | 1194 | @property 1195 | def underlying_typedef_type(self): 1196 | """Return the underlying type of a typedef declaration. 1197 | 1198 | Returns a Type for the typedef this cursor is a declaration for. If 1199 | the current cursor is not a typedef, this raises. 1200 | """ 1201 | if not hasattr(self, '_underlying_type'): 1202 | assert self.kind.is_declaration() 1203 | self._underlying_type = \ 1204 | conf.lib.clang_getTypedefDeclUnderlyingType(self) 1205 | 1206 | return self._underlying_type 1207 | 1208 | @property 1209 | def enum_type(self): 1210 | """Return the integer type of an enum declaration. 1211 | 1212 | Returns a Type corresponding to an integer. If the cursor is not for an 1213 | enum, this raises. 1214 | """ 1215 | if not hasattr(self, '_enum_type'): 1216 | assert self.kind == CursorKind.ENUM_DECL 1217 | self._enum_type = conf.lib.clang_getEnumDeclIntegerType(self) 1218 | 1219 | return self._enum_type 1220 | 1221 | @property 1222 | def enum_value(self): 1223 | """Return the value of an enum constant.""" 1224 | if not hasattr(self, '_enum_value'): 1225 | assert self.kind == CursorKind.ENUM_CONSTANT_DECL 1226 | # Figure out the underlying type of the enum to know if it 1227 | # is a signed or unsigned quantity. 1228 | underlying_type = self.type 1229 | if underlying_type.kind == TypeKind.ENUM: 1230 | underlying_type = underlying_type.get_declaration().enum_type 1231 | if underlying_type.kind in (TypeKind.CHAR_U, 1232 | TypeKind.UCHAR, 1233 | TypeKind.CHAR16, 1234 | TypeKind.CHAR32, 1235 | TypeKind.USHORT, 1236 | TypeKind.UINT, 1237 | TypeKind.ULONG, 1238 | TypeKind.ULONGLONG, 1239 | TypeKind.UINT128): 1240 | self._enum_value = \ 1241 | conf.lib.clang_getEnumConstantDeclUnsignedValue(self) 1242 | else: 1243 | self._enum_value = conf.lib.clang_getEnumConstantDeclValue(self) 1244 | return self._enum_value 1245 | 1246 | @property 1247 | def objc_type_encoding(self): 1248 | """Return the Objective-C type encoding as a str.""" 1249 | if not hasattr(self, '_objc_type_encoding'): 1250 | self._objc_type_encoding = \ 1251 | conf.lib.clang_getDeclObjCTypeEncoding(self) 1252 | 1253 | return self._objc_type_encoding 1254 | 1255 | @property 1256 | def hash(self): 1257 | """Returns a hash of the cursor as an int.""" 1258 | if not hasattr(self, '_hash'): 1259 | self._hash = conf.lib.clang_hashCursor(self) 1260 | 1261 | return self._hash 1262 | 1263 | @property 1264 | def semantic_parent(self): 1265 | """Return the semantic parent for this cursor.""" 1266 | if not hasattr(self, '_semantic_parent'): 1267 | self._semantic_parent = conf.lib.clang_getCursorSemanticParent(self) 1268 | 1269 | return self._semantic_parent 1270 | 1271 | @property 1272 | def lexical_parent(self): 1273 | """Return the lexical parent for this cursor.""" 1274 | if not hasattr(self, '_lexical_parent'): 1275 | self._lexical_parent = conf.lib.clang_getCursorLexicalParent(self) 1276 | 1277 | return self._lexical_parent 1278 | 1279 | @property 1280 | def translation_unit(self): 1281 | """Returns the TranslationUnit to which this Cursor belongs.""" 1282 | # If this triggers an AttributeError, the instance was not properly 1283 | # created. 1284 | return self._tu 1285 | 1286 | @property 1287 | def referenced(self): 1288 | """ 1289 | For a cursor that is a reference, returns a cursor 1290 | representing the entity that it references. 1291 | """ 1292 | if not hasattr(self, '_referenced'): 1293 | self._referenced = conf.lib.clang_getCursorReferenced(self) 1294 | 1295 | return self._referenced 1296 | 1297 | def get_arguments(self): 1298 | """Return an iterator for accessing the arguments of this cursor.""" 1299 | num_args = conf.lib.clang_Cursor_getNumArguments(self) 1300 | for i in range(0, num_args): 1301 | yield conf.lib.clang_Cursor_getArgument(self, i) 1302 | 1303 | def get_children(self): 1304 | """Return an iterator for accessing the children of this cursor.""" 1305 | 1306 | # FIXME: Expose iteration from CIndex, PR6125. 1307 | def visitor(child, parent, children): 1308 | # FIXME: Document this assertion in API. 1309 | # FIXME: There should just be an isNull method. 1310 | assert child != conf.lib.clang_getNullCursor() 1311 | 1312 | # Create reference to TU so it isn't GC'd before Cursor. 1313 | child._tu = self._tu 1314 | children.append(child) 1315 | return 1 # continue 1316 | children = [] 1317 | conf.lib.clang_visitChildren(self, callbacks['cursor_visit'](visitor), 1318 | children) 1319 | return iter(children) 1320 | 1321 | def get_tokens(self): 1322 | """Obtain Token instances formulating that compose this Cursor. 1323 | 1324 | This is a generator for Token instances. It returns all tokens which 1325 | occupy the extent this cursor occupies. 1326 | """ 1327 | return TokenGroup.get_tokens(self._tu, self.extent) 1328 | 1329 | @staticmethod 1330 | def from_result(res, fn, args): 1331 | assert isinstance(res, Cursor) 1332 | # FIXME: There should just be an isNull method. 1333 | if res == conf.lib.clang_getNullCursor(): 1334 | return None 1335 | 1336 | # Store a reference to the TU in the Python object so it won't get GC'd 1337 | # before the Cursor. 1338 | tu = None 1339 | for arg in args: 1340 | if isinstance(arg, TranslationUnit): 1341 | tu = arg 1342 | break 1343 | 1344 | if hasattr(arg, 'translation_unit'): 1345 | tu = arg.translation_unit 1346 | break 1347 | 1348 | assert tu is not None 1349 | 1350 | res._tu = tu 1351 | return res 1352 | 1353 | @staticmethod 1354 | def from_cursor_result(res, fn, args): 1355 | assert isinstance(res, Cursor) 1356 | if res == conf.lib.clang_getNullCursor(): 1357 | return None 1358 | 1359 | res._tu = args[0]._tu 1360 | return res 1361 | 1362 | ### Type Kinds ### 1363 | 1364 | class TypeKind(object): 1365 | """ 1366 | Describes the kind of type. 1367 | """ 1368 | 1369 | # The unique kind objects, indexed by id. 1370 | _kinds = [] 1371 | _name_map = None 1372 | 1373 | def __init__(self, value): 1374 | if value >= len(TypeKind._kinds): 1375 | TypeKind._kinds += [None] * (value - len(TypeKind._kinds) + 1) 1376 | if TypeKind._kinds[value] is not None: 1377 | raise ValueError('TypeKind already loaded') 1378 | self.value = value 1379 | TypeKind._kinds[value] = self 1380 | TypeKind._name_map = None 1381 | 1382 | def from_param(self): 1383 | return self.value 1384 | 1385 | @property 1386 | def name(self): 1387 | """Get the enumeration name of this cursor kind.""" 1388 | if self._name_map is None: 1389 | self._name_map = {} 1390 | for key,value in list(TypeKind.__dict__.items()): 1391 | if isinstance(value,TypeKind): 1392 | self._name_map[value] = key 1393 | return self._name_map[self] 1394 | 1395 | @property 1396 | def spelling(self): 1397 | """Retrieve the spelling of this TypeKind.""" 1398 | return conf.lib.clang_getTypeKindSpelling(self.value) 1399 | 1400 | @staticmethod 1401 | def from_id(id): 1402 | if id >= len(TypeKind._kinds) or TypeKind._kinds[id] is None: 1403 | raise ValueError('Unknown type kind %d' % id) 1404 | return TypeKind._kinds[id] 1405 | 1406 | def __repr__(self): 1407 | return 'TypeKind.%s' % (self.name,) 1408 | 1409 | TypeKind.INVALID = TypeKind(0) 1410 | TypeKind.UNEXPOSED = TypeKind(1) 1411 | TypeKind.VOID = TypeKind(2) 1412 | TypeKind.BOOL = TypeKind(3) 1413 | TypeKind.CHAR_U = TypeKind(4) 1414 | TypeKind.UCHAR = TypeKind(5) 1415 | TypeKind.CHAR16 = TypeKind(6) 1416 | TypeKind.CHAR32 = TypeKind(7) 1417 | TypeKind.USHORT = TypeKind(8) 1418 | TypeKind.UINT = TypeKind(9) 1419 | TypeKind.ULONG = TypeKind(10) 1420 | TypeKind.ULONGLONG = TypeKind(11) 1421 | TypeKind.UINT128 = TypeKind(12) 1422 | TypeKind.CHAR_S = TypeKind(13) 1423 | TypeKind.SCHAR = TypeKind(14) 1424 | TypeKind.WCHAR = TypeKind(15) 1425 | TypeKind.SHORT = TypeKind(16) 1426 | TypeKind.INT = TypeKind(17) 1427 | TypeKind.LONG = TypeKind(18) 1428 | TypeKind.LONGLONG = TypeKind(19) 1429 | TypeKind.INT128 = TypeKind(20) 1430 | TypeKind.FLOAT = TypeKind(21) 1431 | TypeKind.DOUBLE = TypeKind(22) 1432 | TypeKind.LONGDOUBLE = TypeKind(23) 1433 | TypeKind.NULLPTR = TypeKind(24) 1434 | TypeKind.OVERLOAD = TypeKind(25) 1435 | TypeKind.DEPENDENT = TypeKind(26) 1436 | TypeKind.OBJCID = TypeKind(27) 1437 | TypeKind.OBJCCLASS = TypeKind(28) 1438 | TypeKind.OBJCSEL = TypeKind(29) 1439 | TypeKind.COMPLEX = TypeKind(100) 1440 | TypeKind.POINTER = TypeKind(101) 1441 | TypeKind.BLOCKPOINTER = TypeKind(102) 1442 | TypeKind.LVALUEREFERENCE = TypeKind(103) 1443 | TypeKind.RVALUEREFERENCE = TypeKind(104) 1444 | TypeKind.RECORD = TypeKind(105) 1445 | TypeKind.ENUM = TypeKind(106) 1446 | TypeKind.TYPEDEF = TypeKind(107) 1447 | TypeKind.OBJCINTERFACE = TypeKind(108) 1448 | TypeKind.OBJCOBJECTPOINTER = TypeKind(109) 1449 | TypeKind.FUNCTIONNOPROTO = TypeKind(110) 1450 | TypeKind.FUNCTIONPROTO = TypeKind(111) 1451 | TypeKind.CONSTANTARRAY = TypeKind(112) 1452 | TypeKind.VECTOR = TypeKind(113) 1453 | 1454 | class Type(Structure): 1455 | """ 1456 | The type of an element in the abstract syntax tree. 1457 | """ 1458 | _fields_ = [("_kind_id", c_int), ("data", c_void_p * 2)] 1459 | 1460 | @property 1461 | def kind(self): 1462 | """Return the kind of this type.""" 1463 | return TypeKind.from_id(self._kind_id) 1464 | 1465 | def argument_types(self): 1466 | """Retrieve a container for the non-variadic arguments for this type. 1467 | 1468 | The returned object is iterable and indexable. Each item in the 1469 | container is a Type instance. 1470 | """ 1471 | class ArgumentsIterator(collections.Sequence): 1472 | def __init__(self, parent): 1473 | self.parent = parent 1474 | self.length = None 1475 | 1476 | def __len__(self): 1477 | if self.length is None: 1478 | self.length = conf.lib.clang_getNumArgTypes(self.parent) 1479 | 1480 | return self.length 1481 | 1482 | def __getitem__(self, key): 1483 | # FIXME Support slice objects. 1484 | if not isinstance(key, int): 1485 | raise TypeError("Must supply a non-negative int.") 1486 | 1487 | if key < 0: 1488 | raise IndexError("Only non-negative indexes are accepted.") 1489 | 1490 | if key >= len(self): 1491 | raise IndexError("Index greater than container length: " 1492 | "%d > %d" % ( key, len(self) )) 1493 | 1494 | result = conf.lib.clang_getArgType(self.parent, key) 1495 | if result.kind == TypeKind.INVALID: 1496 | raise IndexError("Argument could not be retrieved.") 1497 | 1498 | return result 1499 | 1500 | assert self.kind == TypeKind.FUNCTIONPROTO 1501 | return ArgumentsIterator(self) 1502 | 1503 | @property 1504 | def element_type(self): 1505 | """Retrieve the Type of elements within this Type. 1506 | 1507 | If accessed on a type that is not an array, complex, or vector type, an 1508 | exception will be raised. 1509 | """ 1510 | result = conf.lib.clang_getElementType(self) 1511 | if result.kind == TypeKind.INVALID: 1512 | raise Exception('Element type not available on this type.') 1513 | 1514 | return result 1515 | 1516 | @property 1517 | def element_count(self): 1518 | """Retrieve the number of elements in this type. 1519 | 1520 | Returns an int. 1521 | 1522 | If the Type is not an array or vector, this raises. 1523 | """ 1524 | result = conf.lib.clang_getNumElements(self) 1525 | if result < 0: 1526 | raise Exception('Type does not have elements.') 1527 | 1528 | return result 1529 | 1530 | @property 1531 | def translation_unit(self): 1532 | """The TranslationUnit to which this Type is associated.""" 1533 | # If this triggers an AttributeError, the instance was not properly 1534 | # instantiated. 1535 | return self._tu 1536 | 1537 | @staticmethod 1538 | def from_result(res, fn, args): 1539 | assert isinstance(res, Type) 1540 | 1541 | tu = None 1542 | for arg in args: 1543 | if hasattr(arg, 'translation_unit'): 1544 | tu = arg.translation_unit 1545 | break 1546 | 1547 | assert tu is not None 1548 | res._tu = tu 1549 | 1550 | return res 1551 | 1552 | def get_canonical(self): 1553 | """ 1554 | Return the canonical type for a Type. 1555 | 1556 | Clang's type system explicitly models typedefs and all the 1557 | ways a specific type can be represented. The canonical type 1558 | is the underlying type with all the "sugar" removed. For 1559 | example, if 'T' is a typedef for 'int', the canonical type for 1560 | 'T' would be 'int'. 1561 | """ 1562 | return conf.lib.clang_getCanonicalType(self) 1563 | 1564 | def is_const_qualified(self): 1565 | """Determine whether a Type has the "const" qualifier set. 1566 | 1567 | This does not look through typedefs that may have added "const" 1568 | at a different level. 1569 | """ 1570 | return conf.lib.clang_isConstQualifiedType(self) 1571 | 1572 | def is_volatile_qualified(self): 1573 | """Determine whether a Type has the "volatile" qualifier set. 1574 | 1575 | This does not look through typedefs that may have added "volatile" 1576 | at a different level. 1577 | """ 1578 | return conf.lib.clang_isVolatileQualifiedType(self) 1579 | 1580 | def is_restrict_qualified(self): 1581 | """Determine whether a Type has the "restrict" qualifier set. 1582 | 1583 | This does not look through typedefs that may have added "restrict" at 1584 | a different level. 1585 | """ 1586 | return conf.lib.clang_isRestrictQualifiedType(self) 1587 | 1588 | def is_function_variadic(self): 1589 | """Determine whether this function Type is a variadic function type.""" 1590 | assert self.kind == TypeKind.FUNCTIONPROTO 1591 | 1592 | return conf.lib.clang_isFunctionTypeVariadic(self) 1593 | 1594 | def is_pod(self): 1595 | """Determine whether this Type represents plain old data (POD).""" 1596 | return conf.lib.clang_isPODType(self) 1597 | 1598 | def get_pointee(self): 1599 | """ 1600 | For pointer types, returns the type of the pointee. 1601 | """ 1602 | return conf.lib.clang_getPointeeType(self) 1603 | 1604 | def get_declaration(self): 1605 | """ 1606 | Return the cursor for the declaration of the given type. 1607 | """ 1608 | return conf.lib.clang_getTypeDeclaration(self) 1609 | 1610 | def get_result(self): 1611 | """ 1612 | Retrieve the result type associated with a function type. 1613 | """ 1614 | return conf.lib.clang_getResultType(self) 1615 | 1616 | def get_array_element_type(self): 1617 | """ 1618 | Retrieve the type of the elements of the array type. 1619 | """ 1620 | return conf.lib.clang_getArrayElementType(self) 1621 | 1622 | def get_array_size(self): 1623 | """ 1624 | Retrieve the size of the constant array. 1625 | """ 1626 | return conf.lib.clang_getArraySize(self) 1627 | 1628 | def __eq__(self, other): 1629 | if type(other) != type(self): 1630 | return False 1631 | 1632 | return conf.lib.clang_equalTypes(self, other) 1633 | 1634 | def __ne__(self, other): 1635 | return not self.__eq__(other) 1636 | 1637 | ## CIndex Objects ## 1638 | 1639 | # CIndex objects (derived from ClangObject) are essentially lightweight 1640 | # wrappers attached to some underlying object, which is exposed via CIndex as 1641 | # a void*. 1642 | 1643 | class ClangObject(object): 1644 | """ 1645 | A helper for Clang objects. This class helps act as an intermediary for 1646 | the ctypes library and the Clang CIndex library. 1647 | """ 1648 | def __init__(self, obj): 1649 | assert isinstance(obj, c_object_p) and obj 1650 | self.obj = self._as_parameter_ = obj 1651 | 1652 | def from_param(self): 1653 | return self._as_parameter_ 1654 | 1655 | 1656 | class _CXUnsavedFile(Structure): 1657 | """Helper for passing unsaved file arguments.""" 1658 | _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)] 1659 | 1660 | # Functions calls through the python interface are rather slow. Fortunately, 1661 | # for most symboles, we do not need to perform a function call. Their spelling 1662 | # never changes and is consequently provided by this spelling cache. 1663 | SpellingCache = { 1664 | # 0: CompletionChunk.Kind("Optional"), 1665 | # 1: CompletionChunk.Kind("TypedText"), 1666 | # 2: CompletionChunk.Kind("Text"), 1667 | # 3: CompletionChunk.Kind("Placeholder"), 1668 | # 4: CompletionChunk.Kind("Informative"), 1669 | # 5 : CompletionChunk.Kind("CurrentParameter"), 1670 | 6: '(', # CompletionChunk.Kind("LeftParen"), 1671 | 7: ')', # CompletionChunk.Kind("RightParen"), 1672 | 8: ']', # CompletionChunk.Kind("LeftBracket"), 1673 | 9: ']', # CompletionChunk.Kind("RightBracket"), 1674 | 10: '{', # CompletionChunk.Kind("LeftBrace"), 1675 | 11: '}', # CompletionChunk.Kind("RightBrace"), 1676 | 12: '<', # CompletionChunk.Kind("LeftAngle"), 1677 | 13: '>', # CompletionChunk.Kind("RightAngle"), 1678 | 14: ', ', # CompletionChunk.Kind("Comma"), 1679 | # 15: CompletionChunk.Kind("ResultType"), 1680 | 16: ':', # CompletionChunk.Kind("Colon"), 1681 | 17: ';', # CompletionChunk.Kind("SemiColon"), 1682 | 18: '=', # CompletionChunk.Kind("Equal"), 1683 | 19: ' ', # CompletionChunk.Kind("HorizontalSpace"), 1684 | # 20: CompletionChunk.Kind("VerticalSpace") 1685 | } 1686 | 1687 | class CompletionChunk: 1688 | class Kind: 1689 | def __init__(self, name): 1690 | self.name = name 1691 | 1692 | def __str__(self): 1693 | return self.name 1694 | 1695 | def __repr__(self): 1696 | return "" % self 1697 | 1698 | def __init__(self, completionString, key): 1699 | self.cs = completionString 1700 | self.key = key 1701 | self.__kindNumberCache = -1 1702 | 1703 | def __repr__(self): 1704 | return "{'" + self.spelling + "', " + str(self.kind) + "}" 1705 | 1706 | @CachedProperty 1707 | def spelling(self): 1708 | if self.__kindNumber in SpellingCache: 1709 | return SpellingCache[self.__kindNumber] 1710 | return conf.lib.clang_getCompletionChunkText(self.cs, self.key).spelling 1711 | 1712 | # We do not use @CachedProperty here, as the manual implementation is 1713 | # apparently still significantly faster. Please profile carefully if you 1714 | # would like to add CachedProperty back. 1715 | @property 1716 | def __kindNumber(self): 1717 | if self.__kindNumberCache == -1: 1718 | self.__kindNumberCache = \ 1719 | conf.lib.clang_getCompletionChunkKind(self.cs, self.key) 1720 | return self.__kindNumberCache 1721 | 1722 | @CachedProperty 1723 | def kind(self): 1724 | return completionChunkKindMap[self.__kindNumber] 1725 | 1726 | @CachedProperty 1727 | def string(self): 1728 | res = conf.lib.clang_getCompletionChunkCompletionString(self.cs, 1729 | self.key) 1730 | 1731 | if (res): 1732 | return CompletionString(res) 1733 | else: 1734 | None 1735 | 1736 | def isKindOptional(self): 1737 | return self.__kindNumber == 0 1738 | 1739 | def isKindTypedText(self): 1740 | return self.__kindNumber == 1 1741 | 1742 | def isKindPlaceHolder(self): 1743 | return self.__kindNumber == 3 1744 | 1745 | def isKindInformative(self): 1746 | return self.__kindNumber == 4 1747 | 1748 | def isKindResultType(self): 1749 | return self.__kindNumber == 15 1750 | 1751 | completionChunkKindMap = { 1752 | 0: CompletionChunk.Kind("Optional"), 1753 | 1: CompletionChunk.Kind("TypedText"), 1754 | 2: CompletionChunk.Kind("Text"), 1755 | 3: CompletionChunk.Kind("Placeholder"), 1756 | 4: CompletionChunk.Kind("Informative"), 1757 | 5: CompletionChunk.Kind("CurrentParameter"), 1758 | 6: CompletionChunk.Kind("LeftParen"), 1759 | 7: CompletionChunk.Kind("RightParen"), 1760 | 8: CompletionChunk.Kind("LeftBracket"), 1761 | 9: CompletionChunk.Kind("RightBracket"), 1762 | 10: CompletionChunk.Kind("LeftBrace"), 1763 | 11: CompletionChunk.Kind("RightBrace"), 1764 | 12: CompletionChunk.Kind("LeftAngle"), 1765 | 13: CompletionChunk.Kind("RightAngle"), 1766 | 14: CompletionChunk.Kind("Comma"), 1767 | 15: CompletionChunk.Kind("ResultType"), 1768 | 16: CompletionChunk.Kind("Colon"), 1769 | 17: CompletionChunk.Kind("SemiColon"), 1770 | 18: CompletionChunk.Kind("Equal"), 1771 | 19: CompletionChunk.Kind("HorizontalSpace"), 1772 | 20: CompletionChunk.Kind("VerticalSpace")} 1773 | 1774 | class CompletionString(ClangObject): 1775 | class Availability: 1776 | def __init__(self, name): 1777 | self.name = name 1778 | 1779 | def __str__(self): 1780 | return self.name 1781 | 1782 | def __repr__(self): 1783 | return "" % self 1784 | 1785 | def __len__(self): 1786 | self.num_chunks 1787 | 1788 | @CachedProperty 1789 | def num_chunks(self): 1790 | return conf.lib.clang_getNumCompletionChunks(self.obj) 1791 | 1792 | def __getitem__(self, key): 1793 | if self.num_chunks <= key: 1794 | raise IndexError 1795 | return CompletionChunk(self.obj, key) 1796 | 1797 | @property 1798 | def priority(self): 1799 | return conf.lib.clang_getCompletionPriority(self.obj) 1800 | 1801 | @property 1802 | def availability(self): 1803 | res = conf.lib.clang_getCompletionAvailability(self.obj) 1804 | return availabilityKinds[res] 1805 | 1806 | @property 1807 | def briefComment(self): 1808 | if conf.function_exists("clang_getCompletionBriefComment"): 1809 | return conf.lib.clang_getCompletionBriefComment(self.obj) 1810 | return _CXString() 1811 | 1812 | def __repr__(self): 1813 | return " | ".join([str(a) for a in self]) \ 1814 | + " || Priority: " + str(self.priority) \ 1815 | + " || Availability: " + str(self.availability) \ 1816 | + " || Brief comment: " + str(self.briefComment.spelling) 1817 | 1818 | availabilityKinds = { 1819 | 0: CompletionChunk.Kind("Available"), 1820 | 1: CompletionChunk.Kind("Deprecated"), 1821 | 2: CompletionChunk.Kind("NotAvailable"), 1822 | 3: CompletionChunk.Kind("NotAccessible")} 1823 | 1824 | class CodeCompletionResult(Structure): 1825 | _fields_ = [('cursorKind', c_int), ('completionString', c_object_p)] 1826 | 1827 | def __repr__(self): 1828 | return str(CompletionString(self.completionString)) 1829 | 1830 | @property 1831 | def kind(self): 1832 | return CursorKind.from_id(self.cursorKind) 1833 | 1834 | @property 1835 | def string(self): 1836 | return CompletionString(self.completionString) 1837 | 1838 | class CCRStructure(Structure): 1839 | _fields_ = [('results', POINTER(CodeCompletionResult)), 1840 | ('numResults', c_int)] 1841 | 1842 | def __len__(self): 1843 | return self.numResults 1844 | 1845 | def __getitem__(self, key): 1846 | if len(self) <= key: 1847 | raise IndexError 1848 | 1849 | return self.results[key] 1850 | 1851 | class CodeCompletionResults(ClangObject): 1852 | def __init__(self, ptr): 1853 | assert isinstance(ptr, POINTER(CCRStructure)) and ptr 1854 | self.ptr = self._as_parameter_ = ptr 1855 | 1856 | def from_param(self): 1857 | return self._as_parameter_ 1858 | 1859 | def __del__(self): 1860 | conf.lib.clang_disposeCodeCompleteResults(self) 1861 | 1862 | @property 1863 | def results(self): 1864 | return self.ptr.contents 1865 | 1866 | @property 1867 | def diagnostics(self): 1868 | class DiagnosticsItr: 1869 | def __init__(self, ccr): 1870 | self.ccr= ccr 1871 | 1872 | def __len__(self): 1873 | return int( 1874 | conf.lib.clang_codeCompleteGetNumDiagnostics(self.ccr)) 1875 | 1876 | def __getitem__(self, key): 1877 | return conf.lib.clang_codeCompleteGetDiagnostic(self.ccr, key) 1878 | 1879 | return DiagnosticsItr(self) 1880 | 1881 | 1882 | class Index(ClangObject): 1883 | """ 1884 | The Index type provides the primary interface to the Clang CIndex library, 1885 | primarily by providing an interface for reading and parsing translation 1886 | units. 1887 | """ 1888 | 1889 | @staticmethod 1890 | def create(excludeDecls=False): 1891 | """ 1892 | Create a new Index. 1893 | Parameters: 1894 | excludeDecls -- Exclude local declarations from translation units. 1895 | """ 1896 | return Index(conf.lib.clang_createIndex(excludeDecls, 0)) 1897 | 1898 | def __del__(self): 1899 | conf.lib.clang_disposeIndex(self) 1900 | 1901 | def read(self, path): 1902 | """Load a TranslationUnit from the given AST file.""" 1903 | return TranslationUnit.from_ast(path, self) 1904 | 1905 | def parse(self, path, args=None, unsaved_files=None, options = 0): 1906 | """Load the translation unit from the given source code file by running 1907 | clang and generating the AST before loading. Additional command line 1908 | parameters can be passed to clang via the args parameter. 1909 | 1910 | In-memory contents for files can be provided by passing a list of pairs 1911 | to as unsaved_files, the first item should be the filenames to be mapped 1912 | and the second should be the contents to be substituted for the 1913 | file. The contents may be passed as strings or file objects. 1914 | 1915 | If an error was encountered during parsing, a TranslationUnitLoadError 1916 | will be raised. 1917 | """ 1918 | return TranslationUnit.from_source(path, args, unsaved_files, options, 1919 | self) 1920 | 1921 | class TranslationUnit(ClangObject): 1922 | """Represents a source code translation unit. 1923 | 1924 | This is one of the main types in the API. Any time you wish to interact 1925 | with Clang's representation of a source file, you typically start with a 1926 | translation unit. 1927 | """ 1928 | 1929 | # Default parsing mode. 1930 | PARSE_NONE = 0 1931 | 1932 | # Instruct the parser to create a detailed processing record containing 1933 | # metadata not normally retained. 1934 | PARSE_DETAILED_PROCESSING_RECORD = 1 1935 | 1936 | # Indicates that the translation unit is incomplete. This is typically used 1937 | # when parsing headers. 1938 | PARSE_INCOMPLETE = 2 1939 | 1940 | # Instruct the parser to create a pre-compiled preamble for the translation 1941 | # unit. This caches the preamble (included files at top of source file). 1942 | # This is useful if the translation unit will be reparsed and you don't 1943 | # want to incur the overhead of reparsing the preamble. 1944 | PARSE_PRECOMPILED_PREAMBLE = 4 1945 | 1946 | # Cache code completion information on parse. This adds time to parsing but 1947 | # speeds up code completion. 1948 | PARSE_CACHE_COMPLETION_RESULTS = 8 1949 | 1950 | # Flags with values 16 and 32 are deprecated and intentionally omitted. 1951 | 1952 | # Do not parse function bodies. This is useful if you only care about 1953 | # searching for declarations/definitions. 1954 | PARSE_SKIP_FUNCTION_BODIES = 64 1955 | 1956 | # Used to indicate that brief documentation comments should be included 1957 | # into the set of code completions returned from this translation unit. 1958 | PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION = 128 1959 | 1960 | @classmethod 1961 | def from_source(cls, filename, args=None, unsaved_files=None, options=0, 1962 | index=None): 1963 | """Create a TranslationUnit by parsing source. 1964 | 1965 | This is capable of processing source code both from files on the 1966 | filesystem as well as in-memory contents. 1967 | 1968 | Command-line arguments that would be passed to clang are specified as 1969 | a list via args. These can be used to specify include paths, warnings, 1970 | etc. e.g. ["-Wall", "-I/path/to/include"]. 1971 | 1972 | In-memory file content can be provided via unsaved_files. This is an 1973 | iterable of 2-tuples. The first element is the str filename. The 1974 | second element defines the content. Content can be provided as str 1975 | source code or as file objects (anything with a read() method). If 1976 | a file object is being used, content will be read until EOF and the 1977 | read cursor will not be reset to its original position. 1978 | 1979 | options is a bitwise or of TranslationUnit.PARSE_XXX flags which will 1980 | control parsing behavior. 1981 | 1982 | index is an Index instance to utilize. If not provided, a new Index 1983 | will be created for this TranslationUnit. 1984 | 1985 | To parse source from the filesystem, the filename of the file to parse 1986 | is specified by the filename argument. Or, filename could be None and 1987 | the args list would contain the filename(s) to parse. 1988 | 1989 | To parse source from an in-memory buffer, set filename to the virtual 1990 | filename you wish to associate with this source (e.g. "test.c"). The 1991 | contents of that file are then provided in unsaved_files. 1992 | 1993 | If an error occurs, a TranslationUnitLoadError is raised. 1994 | 1995 | Please note that a TranslationUnit with parser errors may be returned. 1996 | It is the caller's responsibility to check tu.diagnostics for errors. 1997 | 1998 | Also note that Clang infers the source language from the extension of 1999 | the input filename. If you pass in source code containing a C++ class 2000 | declaration with the filename "test.c" parsing will fail. 2001 | """ 2002 | if args is None: 2003 | args = [] 2004 | 2005 | if unsaved_files is None: 2006 | unsaved_files = [] 2007 | 2008 | if index is None: 2009 | index = Index.create() 2010 | 2011 | args_array = None 2012 | if len(args) > 0: 2013 | args_array = (c_char_p * len(args))(* [encode(argument) 2014 | for argument in args]) 2015 | 2016 | unsaved_array = None 2017 | if len(unsaved_files) > 0: 2018 | unsaved_array = (_CXUnsavedFile * len(unsaved_files))() 2019 | for i, (name, contents) in enumerate(unsaved_files): 2020 | if hasattr(contents, "read"): 2021 | contents = contents.read() 2022 | 2023 | unsaved_array[i].name = encode(name) 2024 | unsaved_array[i].contents = encode(contents) 2025 | unsaved_array[i].length = len(contents) 2026 | 2027 | ptr = conf.lib.clang_parseTranslationUnit(index, encode(filename), args_array, 2028 | len(args), unsaved_array, 2029 | len(unsaved_files), options) 2030 | 2031 | if not ptr: 2032 | raise TranslationUnitLoadError("Error parsing translation unit.") 2033 | 2034 | return cls(ptr, index=index) 2035 | 2036 | @classmethod 2037 | def from_ast_file(cls, filename, index=None): 2038 | """Create a TranslationUnit instance from a saved AST file. 2039 | 2040 | A previously-saved AST file (provided with -emit-ast or 2041 | TranslationUnit.save()) is loaded from the filename specified. 2042 | 2043 | If the file cannot be loaded, a TranslationUnitLoadError will be 2044 | raised. 2045 | 2046 | index is optional and is the Index instance to use. If not provided, 2047 | a default Index will be created. 2048 | """ 2049 | if index is None: 2050 | index = Index.create() 2051 | 2052 | ptr = conf.lib.clang_createTranslationUnit(index, filename) 2053 | if not ptr: 2054 | raise TranslationUnitLoadError(filename) 2055 | 2056 | return cls(ptr=ptr, index=index) 2057 | 2058 | def __init__(self, ptr, index): 2059 | """Create a TranslationUnit instance. 2060 | 2061 | TranslationUnits should be created using one of the from_* @classmethod 2062 | functions above. __init__ is only called internally. 2063 | """ 2064 | assert isinstance(index, Index) 2065 | 2066 | ClangObject.__init__(self, ptr) 2067 | 2068 | def __del__(self): 2069 | conf.lib.clang_disposeTranslationUnit(self) 2070 | 2071 | @property 2072 | def cursor(self): 2073 | """Retrieve the cursor that represents the given translation unit.""" 2074 | return conf.lib.clang_getTranslationUnitCursor(self) 2075 | 2076 | @property 2077 | def spelling(self): 2078 | """Get the original translation unit source file name.""" 2079 | return conf.lib.clang_getTranslationUnitSpelling(self) 2080 | 2081 | def get_includes(self): 2082 | """ 2083 | Return an iterable sequence of FileInclusion objects that describe the 2084 | sequence of inclusions in a translation unit. The first object in 2085 | this sequence is always the input file. Note that this method will not 2086 | recursively iterate over header files included through precompiled 2087 | headers. 2088 | """ 2089 | def visitor(fobj, lptr, depth, includes): 2090 | if depth > 0: 2091 | loc = lptr.contents 2092 | includes.append(FileInclusion(loc.file, File(fobj), loc, depth)) 2093 | 2094 | # Automatically adapt CIndex/ctype pointers to python objects 2095 | includes = [] 2096 | conf.lib.clang_getInclusions(self, 2097 | callbacks['translation_unit_includes'](visitor), includes) 2098 | 2099 | return iter(includes) 2100 | 2101 | def get_file(self, filename): 2102 | """Obtain a File from this translation unit.""" 2103 | 2104 | return File.from_name(self, filename) 2105 | 2106 | def get_location(self, filename, position): 2107 | """Obtain a SourceLocation for a file in this translation unit. 2108 | 2109 | The position can be specified by passing: 2110 | 2111 | - Integer file offset. Initial file offset is 0. 2112 | - 2-tuple of (line number, column number). Initial file position is 2113 | (0, 0) 2114 | """ 2115 | f = self.get_file(filename) 2116 | 2117 | if isinstance(position, int): 2118 | return SourceLocation.from_offset(self, f, position) 2119 | 2120 | return SourceLocation.from_position(self, f, position[0], position[1]) 2121 | 2122 | def get_extent(self, filename, locations): 2123 | """Obtain a SourceRange from this translation unit. 2124 | 2125 | The bounds of the SourceRange must ultimately be defined by a start and 2126 | end SourceLocation. For the locations argument, you can pass: 2127 | 2128 | - 2 SourceLocation instances in a 2-tuple or list. 2129 | - 2 int file offsets via a 2-tuple or list. 2130 | - 2 2-tuple or lists of (line, column) pairs in a 2-tuple or list. 2131 | 2132 | e.g. 2133 | 2134 | get_extent('foo.c', (5, 10)) 2135 | get_extent('foo.c', ((1, 1), (1, 15))) 2136 | """ 2137 | f = self.get_file(filename) 2138 | 2139 | if len(locations) < 2: 2140 | raise Exception('Must pass object with at least 2 elements') 2141 | 2142 | start_location, end_location = locations 2143 | 2144 | if hasattr(start_location, '__len__'): 2145 | start_location = SourceLocation.from_position(self, f, 2146 | start_location[0], start_location[1]) 2147 | elif isinstance(start_location, int): 2148 | start_location = SourceLocation.from_offset(self, f, 2149 | start_location) 2150 | 2151 | if hasattr(end_location, '__len__'): 2152 | end_location = SourceLocation.from_position(self, f, 2153 | end_location[0], end_location[1]) 2154 | elif isinstance(end_location, int): 2155 | end_location = SourceLocation.from_offset(self, f, end_location) 2156 | 2157 | assert isinstance(start_location, SourceLocation) 2158 | assert isinstance(end_location, SourceLocation) 2159 | 2160 | return SourceRange.from_locations(start_location, end_location) 2161 | 2162 | @property 2163 | def diagnostics(self): 2164 | """ 2165 | Return an iterable (and indexable) object containing the diagnostics. 2166 | """ 2167 | class DiagIterator: 2168 | def __init__(self, tu): 2169 | self.tu = tu 2170 | 2171 | def __len__(self): 2172 | return int(conf.lib.clang_getNumDiagnostics(self.tu)) 2173 | 2174 | def __getitem__(self, key): 2175 | diag = conf.lib.clang_getDiagnostic(self.tu, key) 2176 | if not diag: 2177 | raise IndexError 2178 | return Diagnostic(diag) 2179 | 2180 | return DiagIterator(self) 2181 | 2182 | def reparse(self, unsaved_files=None, options=0): 2183 | """ 2184 | Reparse an already parsed translation unit. 2185 | 2186 | In-memory contents for files can be provided by passing a list of pairs 2187 | as unsaved_files, the first items should be the filenames to be mapped 2188 | and the second should be the contents to be substituted for the 2189 | file. The contents may be passed as strings or file objects. 2190 | """ 2191 | if unsaved_files is None: 2192 | unsaved_files = [] 2193 | 2194 | unsaved_files_array = 0 2195 | if len(unsaved_files): 2196 | unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() 2197 | for i,(name,value) in enumerate(unsaved_files): 2198 | if not isinstance(value, str): 2199 | # FIXME: It would be great to support an efficient version 2200 | # of this, one day. 2201 | value = value.read() 2202 | print(value) 2203 | if not isinstance(value, str): 2204 | raise TypeError('Unexpected unsaved file contents.') 2205 | unsaved_files_array[i].name = encode(name) 2206 | unsaved_files_array[i].contents = encode(value) 2207 | unsaved_files_array[i].length = len(value) 2208 | conf.lib.clang_reparseTranslationUnit(self, len(unsaved_files), 2209 | unsaved_files_array, options) 2210 | 2211 | def save(self, filename): 2212 | """Saves the TranslationUnit to a file. 2213 | 2214 | This is equivalent to passing -emit-ast to the clang frontend. The 2215 | saved file can be loaded back into a TranslationUnit. Or, if it 2216 | corresponds to a header, it can be used as a pre-compiled header file. 2217 | 2218 | If an error occurs while saving, a TranslationUnitSaveError is raised. 2219 | If the error was TranslationUnitSaveError.ERROR_INVALID_TU, this means 2220 | the constructed TranslationUnit was not valid at time of save. In this 2221 | case, the reason(s) why should be available via 2222 | TranslationUnit.diagnostics(). 2223 | 2224 | filename -- The path to save the translation unit to. 2225 | """ 2226 | options = conf.lib.clang_defaultSaveOptions(self) 2227 | result = int(conf.lib.clang_saveTranslationUnit(self, filename, 2228 | options)) 2229 | if result != 0: 2230 | raise TranslationUnitSaveError(result, 2231 | 'Error saving TranslationUnit.') 2232 | 2233 | def codeComplete(self, path, line, column, unsaved_files=None, 2234 | include_macros=False, include_code_patterns=False, 2235 | include_brief_comments=False): 2236 | """ 2237 | Code complete in this translation unit. 2238 | 2239 | In-memory contents for files can be provided by passing a list of pairs 2240 | as unsaved_files, the first items should be the filenames to be mapped 2241 | and the second should be the contents to be substituted for the 2242 | file. The contents may be passed as strings or file objects. 2243 | """ 2244 | options = 0 2245 | 2246 | if include_macros: 2247 | options += 1 2248 | 2249 | if include_code_patterns: 2250 | options += 2 2251 | 2252 | if include_brief_comments: 2253 | options += 4 2254 | 2255 | if unsaved_files is None: 2256 | unsaved_files = [] 2257 | 2258 | unsaved_files_array = 0 2259 | if len(unsaved_files): 2260 | unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() 2261 | for i,(name,value) in enumerate(unsaved_files): 2262 | if not isinstance(value, str): 2263 | # FIXME: It would be great to support an efficient version 2264 | # of this, one day. 2265 | value = value.read() 2266 | print(value) 2267 | if not isinstance(value, str): 2268 | raise TypeError('Unexpected unsaved file contents.') 2269 | unsaved_files_array[i].name = encode(name) 2270 | unsaved_files_array[i].contents = encode(value) 2271 | unsaved_files_array[i].length = len(value) 2272 | ptr = conf.lib.clang_codeCompleteAt(self, encode(path), line, column, 2273 | unsaved_files_array, len(unsaved_files), options) 2274 | if ptr: 2275 | return CodeCompletionResults(ptr) 2276 | return None 2277 | 2278 | def get_tokens(self, locations=None, extent=None): 2279 | """Obtain tokens in this translation unit. 2280 | 2281 | This is a generator for Token instances. The caller specifies a range 2282 | of source code to obtain tokens for. The range can be specified as a 2283 | 2-tuple of SourceLocation or as a SourceRange. If both are defined, 2284 | behavior is undefined. 2285 | """ 2286 | if locations is not None: 2287 | extent = SourceRange(start=locations[0], end=locations[1]) 2288 | 2289 | return TokenGroup.get_tokens(self, extent) 2290 | 2291 | class File(ClangObject): 2292 | """ 2293 | The File class represents a particular source file that is part of a 2294 | translation unit. 2295 | """ 2296 | 2297 | @staticmethod 2298 | def from_name(translation_unit, file_name): 2299 | """Retrieve a file handle within the given translation unit.""" 2300 | return File(conf.lib.clang_getFile(translation_unit, 2301 | encode(file_name))) 2302 | 2303 | @property 2304 | def name(self): 2305 | """Return the complete file and path name of the file.""" 2306 | return conf.lib.clang_getCString(conf.lib.clang_getFileName(self)) 2307 | 2308 | @property 2309 | def time(self): 2310 | """Return the last modification time of the file.""" 2311 | return conf.lib.clang_getFileTime(self) 2312 | 2313 | def __str__(self): 2314 | return self.name 2315 | 2316 | def __repr__(self): 2317 | return "" % (self.name) 2318 | 2319 | @staticmethod 2320 | def from_cursor_result(res, fn, args): 2321 | assert isinstance(res, File) 2322 | 2323 | # Copy a reference to the TranslationUnit to prevent premature GC. 2324 | res._tu = args[0]._tu 2325 | return res 2326 | 2327 | class FileInclusion(object): 2328 | """ 2329 | The FileInclusion class represents the inclusion of one source file by 2330 | another via a '#include' directive or as the input file for the translation 2331 | unit. This class provides information about the included file, the including 2332 | file, the location of the '#include' directive and the depth of the included 2333 | file in the stack. Note that the input file has depth 0. 2334 | """ 2335 | 2336 | def __init__(self, src, tgt, loc, depth): 2337 | self.source = src 2338 | self.include = tgt 2339 | self.location = loc 2340 | self.depth = depth 2341 | 2342 | @property 2343 | def is_input_file(self): 2344 | """True if the included file is the input file.""" 2345 | return self.depth == 0 2346 | 2347 | class CompilationDatabaseError(Exception): 2348 | """Represents an error that occurred when working with a CompilationDatabase 2349 | 2350 | Each error is associated to an enumerated value, accessible under 2351 | e.cdb_error. Consumers can compare the value with one of the ERROR_ 2352 | constants in this class. 2353 | """ 2354 | 2355 | # An unknown error occurred 2356 | ERROR_UNKNOWN = 0 2357 | 2358 | # The database could not be loaded 2359 | ERROR_CANNOTLOADDATABASE = 1 2360 | 2361 | def __init__(self, enumeration, message): 2362 | assert isinstance(enumeration, int) 2363 | 2364 | if enumeration > 1: 2365 | raise Exception("Encountered undefined CompilationDatabase error " 2366 | "constant: %d. Please file a bug to have this " 2367 | "value supported." % enumeration) 2368 | 2369 | self.cdb_error = enumeration 2370 | Exception.__init__(self, 'Error %d: %s' % (enumeration, message)) 2371 | 2372 | class CompileCommand(object): 2373 | """Represents the compile command used to build a file""" 2374 | def __init__(self, cmd, ccmds): 2375 | self.cmd = cmd 2376 | # Keep a reference to the originating CompileCommands 2377 | # to prevent garbage collection 2378 | self.ccmds = ccmds 2379 | 2380 | @property 2381 | def directory(self): 2382 | """Get the working directory for this CompileCommand""" 2383 | return conf.lib.clang_CompileCommand_getDirectory(self.cmd) 2384 | 2385 | @property 2386 | def arguments(self): 2387 | """ 2388 | Get an iterable object providing each argument in the 2389 | command line for the compiler invocation as a _CXString. 2390 | 2391 | Invariant : the first argument is the compiler executable 2392 | """ 2393 | length = conf.lib.clang_CompileCommand_getNumArgs(self.cmd) 2394 | for i in range(length): 2395 | yield conf.lib.clang_CompileCommand_getArg(self.cmd, i) 2396 | 2397 | class CompileCommands(object): 2398 | """ 2399 | CompileCommands is an iterable object containing all CompileCommand 2400 | that can be used for building a specific file. 2401 | """ 2402 | def __init__(self, ccmds): 2403 | self.ccmds = ccmds 2404 | 2405 | def __del__(self): 2406 | conf.lib.clang_CompileCommands_dispose(self.ccmds) 2407 | 2408 | def __len__(self): 2409 | return int(conf.lib.clang_CompileCommands_getSize(self.ccmds)) 2410 | 2411 | def __getitem__(self, i): 2412 | cc = conf.lib.clang_CompileCommands_getCommand(self.ccmds, i) 2413 | if not cc: 2414 | raise IndexError 2415 | return CompileCommand(cc, self) 2416 | 2417 | @staticmethod 2418 | def from_result(res, fn, args): 2419 | if not res: 2420 | return None 2421 | return CompileCommands(res) 2422 | 2423 | class CompilationDatabase(ClangObject): 2424 | """ 2425 | The CompilationDatabase is a wrapper class around 2426 | clang::tooling::CompilationDatabase 2427 | 2428 | It enables querying how a specific source file can be built. 2429 | """ 2430 | 2431 | def __del__(self): 2432 | conf.lib.clang_CompilationDatabase_dispose(self) 2433 | 2434 | @staticmethod 2435 | def from_result(res, fn, args): 2436 | if not res: 2437 | raise CompilationDatabaseError(0, 2438 | "CompilationDatabase loading failed") 2439 | return CompilationDatabase(res) 2440 | 2441 | @staticmethod 2442 | def fromDirectory(buildDir): 2443 | """Builds a CompilationDatabase from the database found in buildDir""" 2444 | errorCode = c_uint() 2445 | try: 2446 | cdb = conf.lib.clang_CompilationDatabase_fromDirectory(buildDir, 2447 | byref(errorCode)) 2448 | except CompilationDatabaseError: 2449 | raise CompilationDatabaseError(int(errorCode.value), 2450 | "CompilationDatabase loading failed") 2451 | return cdb 2452 | 2453 | def getCompileCommands(self, filename): 2454 | """ 2455 | Get an iterable object providing all the CompileCommands available to 2456 | build filename. Returns None if filename is not found in the database. 2457 | """ 2458 | return conf.lib.clang_CompilationDatabase_getCompileCommands(self, 2459 | filename) 2460 | 2461 | class Token(Structure): 2462 | """Represents a single token from the preprocessor. 2463 | 2464 | Tokens are effectively segments of source code. Source code is first parsed 2465 | into tokens before being converted into the AST and Cursors. 2466 | 2467 | Tokens are obtained from parsed TranslationUnit instances. You currently 2468 | can't create tokens manually. 2469 | """ 2470 | _fields_ = [ 2471 | ('int_data', c_uint * 4), 2472 | ('ptr_data', c_void_p) 2473 | ] 2474 | 2475 | @property 2476 | def spelling(self): 2477 | """The spelling of this token. 2478 | 2479 | This is the textual representation of the token in source. 2480 | """ 2481 | return conf.lib.clang_getTokenSpelling(self._tu, self) 2482 | 2483 | @property 2484 | def kind(self): 2485 | """Obtain the TokenKind of the current token.""" 2486 | return TokenKind.from_value(conf.lib.clang_getTokenKind(self)) 2487 | 2488 | @property 2489 | def location(self): 2490 | """The SourceLocation this Token occurs at.""" 2491 | return conf.lib.clang_getTokenLocation(self._tu, self) 2492 | 2493 | @property 2494 | def extent(self): 2495 | """The SourceRange this Token occupies.""" 2496 | return conf.lib.clang_getTokenExtent(self._tu, self) 2497 | 2498 | @property 2499 | def cursor(self): 2500 | """The Cursor this Token corresponds to.""" 2501 | cursor = Cursor() 2502 | 2503 | conf.lib.clang_annotateTokens(self._tu, byref(self), 1, byref(cursor)) 2504 | 2505 | return cursor 2506 | 2507 | # Now comes the plumbing to hook up the C library. 2508 | 2509 | # Register callback types in common container. 2510 | callbacks['translation_unit_includes'] = CFUNCTYPE(None, c_object_p, 2511 | POINTER(SourceLocation), c_uint, py_object) 2512 | callbacks['cursor_visit'] = CFUNCTYPE(c_int, Cursor, Cursor, py_object) 2513 | 2514 | # Functions strictly alphabetical order. 2515 | functionList = [ 2516 | ("clang_annotateTokens", 2517 | [TranslationUnit, POINTER(Token), c_uint, POINTER(Cursor)]), 2518 | 2519 | ("clang_CompilationDatabase_dispose", 2520 | [c_object_p]), 2521 | 2522 | ("clang_CompilationDatabase_fromDirectory", 2523 | [c_char_p, POINTER(c_uint)], 2524 | c_object_p, 2525 | CompilationDatabase.from_result), 2526 | 2527 | ("clang_CompilationDatabase_getCompileCommands", 2528 | [c_object_p, c_char_p], 2529 | c_object_p, 2530 | CompileCommands.from_result), 2531 | 2532 | ("clang_CompileCommands_dispose", 2533 | [c_object_p]), 2534 | 2535 | ("clang_CompileCommands_getCommand", 2536 | [c_object_p, c_uint], 2537 | c_object_p), 2538 | 2539 | ("clang_CompileCommands_getSize", 2540 | [c_object_p], 2541 | c_uint), 2542 | 2543 | ("clang_CompileCommand_getArg", 2544 | [c_object_p, c_uint], 2545 | _CXString, 2546 | _CXString.from_result), 2547 | 2548 | ("clang_CompileCommand_getDirectory", 2549 | [c_object_p], 2550 | _CXString, 2551 | _CXString.from_result), 2552 | 2553 | ("clang_CompileCommand_getNumArgs", 2554 | [c_object_p], 2555 | c_uint), 2556 | 2557 | ("clang_codeCompleteAt", 2558 | [TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int], 2559 | POINTER(CCRStructure)), 2560 | 2561 | ("clang_codeCompleteGetDiagnostic", 2562 | [CodeCompletionResults, c_int], 2563 | Diagnostic), 2564 | 2565 | ("clang_codeCompleteGetNumDiagnostics", 2566 | [CodeCompletionResults], 2567 | c_int), 2568 | 2569 | ("clang_createIndex", 2570 | [c_int, c_int], 2571 | c_object_p), 2572 | 2573 | ("clang_createTranslationUnit", 2574 | [Index, c_char_p], 2575 | c_object_p), 2576 | 2577 | ("clang_CXXMethod_isStatic", 2578 | [Cursor], 2579 | bool), 2580 | 2581 | ("clang_CXXMethod_isVirtual", 2582 | [Cursor], 2583 | bool), 2584 | 2585 | ("clang_defaultSaveOptions", 2586 | [TranslationUnit], 2587 | c_uint), 2588 | 2589 | ("clang_disposeCodeCompleteResults", 2590 | [CodeCompletionResults]), 2591 | 2592 | # ("clang_disposeCXTUResourceUsage", 2593 | # [CXTUResourceUsage]), 2594 | 2595 | ("clang_disposeDiagnostic", 2596 | [Diagnostic]), 2597 | 2598 | ("clang_disposeIndex", 2599 | [Index]), 2600 | 2601 | ("clang_disposeString", 2602 | [_CXString]), 2603 | 2604 | ("clang_disposeTokens", 2605 | [TranslationUnit, POINTER(Token), c_uint]), 2606 | 2607 | ("clang_disposeTranslationUnit", 2608 | [TranslationUnit]), 2609 | 2610 | ("clang_equalCursors", 2611 | [Cursor, Cursor], 2612 | bool), 2613 | 2614 | ("clang_equalLocations", 2615 | [SourceLocation, SourceLocation], 2616 | bool), 2617 | 2618 | ("clang_equalRanges", 2619 | [SourceRange, SourceRange], 2620 | bool), 2621 | 2622 | ("clang_equalTypes", 2623 | [Type, Type], 2624 | bool), 2625 | 2626 | ("clang_getArgType", 2627 | [Type, c_uint], 2628 | Type, 2629 | Type.from_result), 2630 | 2631 | ("clang_getArrayElementType", 2632 | [Type], 2633 | Type, 2634 | Type.from_result), 2635 | 2636 | ("clang_getArraySize", 2637 | [Type], 2638 | c_longlong), 2639 | 2640 | ("clang_getCanonicalCursor", 2641 | [Cursor], 2642 | Cursor, 2643 | Cursor.from_cursor_result), 2644 | 2645 | ("clang_getCanonicalType", 2646 | [Type], 2647 | Type, 2648 | Type.from_result), 2649 | 2650 | ("clang_getCompletionAvailability", 2651 | [c_void_p], 2652 | c_int), 2653 | 2654 | ("clang_getCompletionBriefComment", 2655 | [c_void_p], 2656 | _CXString), 2657 | 2658 | ("clang_getCompletionChunkCompletionString", 2659 | [c_void_p, c_int], 2660 | c_object_p), 2661 | 2662 | ("clang_getCompletionChunkKind", 2663 | [c_void_p, c_int], 2664 | c_int), 2665 | 2666 | ("clang_getCompletionChunkText", 2667 | [c_void_p, c_int], 2668 | _CXString), 2669 | 2670 | ("clang_getCompletionPriority", 2671 | [c_void_p], 2672 | c_int), 2673 | 2674 | ("clang_getCString", 2675 | [_CXString], 2676 | c_char_p), 2677 | 2678 | ("clang_getCursor", 2679 | [TranslationUnit, SourceLocation], 2680 | Cursor), 2681 | 2682 | ("clang_getCursorDefinition", 2683 | [Cursor], 2684 | Cursor, 2685 | Cursor.from_result), 2686 | 2687 | ("clang_getCursorDisplayName", 2688 | [Cursor], 2689 | _CXString, 2690 | _CXString.from_result), 2691 | 2692 | ("clang_getCursorExtent", 2693 | [Cursor], 2694 | SourceRange), 2695 | 2696 | ("clang_getCursorLexicalParent", 2697 | [Cursor], 2698 | Cursor, 2699 | Cursor.from_cursor_result), 2700 | 2701 | ("clang_getCursorLocation", 2702 | [Cursor], 2703 | SourceLocation), 2704 | 2705 | ("clang_getCursorReferenced", 2706 | [Cursor], 2707 | Cursor, 2708 | Cursor.from_result), 2709 | 2710 | ("clang_getCursorReferenceNameRange", 2711 | [Cursor, c_uint, c_uint], 2712 | SourceRange), 2713 | 2714 | ("clang_getCursorSemanticParent", 2715 | [Cursor], 2716 | Cursor, 2717 | Cursor.from_cursor_result), 2718 | 2719 | ("clang_getCursorSpelling", 2720 | [Cursor], 2721 | _CXString, 2722 | _CXString.from_result), 2723 | 2724 | ("clang_getCursorType", 2725 | [Cursor], 2726 | Type, 2727 | Type.from_result), 2728 | 2729 | ("clang_getCursorUSR", 2730 | [Cursor], 2731 | _CXString, 2732 | _CXString.from_result), 2733 | 2734 | # ("clang_getCXTUResourceUsage", 2735 | # [TranslationUnit], 2736 | # CXTUResourceUsage), 2737 | 2738 | ("clang_getCXXAccessSpecifier", 2739 | [Cursor], 2740 | c_uint), 2741 | 2742 | ("clang_getDeclObjCTypeEncoding", 2743 | [Cursor], 2744 | _CXString, 2745 | _CXString.from_result), 2746 | 2747 | ("clang_getDiagnostic", 2748 | [c_object_p, c_uint], 2749 | c_object_p), 2750 | 2751 | ("clang_getDiagnosticCategory", 2752 | [Diagnostic], 2753 | c_uint), 2754 | 2755 | ("clang_getDiagnosticCategoryName", 2756 | [c_uint], 2757 | _CXString, 2758 | _CXString.from_result), 2759 | 2760 | ("clang_getDiagnosticFixIt", 2761 | [Diagnostic, c_uint, POINTER(SourceRange)], 2762 | _CXString, 2763 | _CXString.from_result), 2764 | 2765 | ("clang_getDiagnosticLocation", 2766 | [Diagnostic], 2767 | SourceLocation), 2768 | 2769 | ("clang_getDiagnosticNumFixIts", 2770 | [Diagnostic], 2771 | c_uint), 2772 | 2773 | ("clang_getDiagnosticNumRanges", 2774 | [Diagnostic], 2775 | c_uint), 2776 | 2777 | ("clang_getDiagnosticOption", 2778 | [Diagnostic, POINTER(_CXString)], 2779 | _CXString, 2780 | _CXString.from_result), 2781 | 2782 | ("clang_getDiagnosticRange", 2783 | [Diagnostic, c_uint], 2784 | SourceRange), 2785 | 2786 | ("clang_getDiagnosticSeverity", 2787 | [Diagnostic], 2788 | c_int), 2789 | 2790 | ("clang_getDiagnosticSpelling", 2791 | [Diagnostic], 2792 | _CXString, 2793 | _CXString.from_result), 2794 | 2795 | ("clang_getElementType", 2796 | [Type], 2797 | Type, 2798 | Type.from_result), 2799 | 2800 | ("clang_getEnumConstantDeclUnsignedValue", 2801 | [Cursor], 2802 | c_ulonglong), 2803 | 2804 | ("clang_getEnumConstantDeclValue", 2805 | [Cursor], 2806 | c_longlong), 2807 | 2808 | ("clang_getEnumDeclIntegerType", 2809 | [Cursor], 2810 | Type, 2811 | Type.from_result), 2812 | 2813 | ("clang_getFile", 2814 | [TranslationUnit, c_char_p], 2815 | c_object_p), 2816 | 2817 | ("clang_getFileName", 2818 | [File], 2819 | _CXString), # TODO go through _CXString.from_result? 2820 | 2821 | ("clang_getFileTime", 2822 | [File], 2823 | c_uint), 2824 | 2825 | ("clang_getIBOutletCollectionType", 2826 | [Cursor], 2827 | Type, 2828 | Type.from_result), 2829 | 2830 | ("clang_getIncludedFile", 2831 | [Cursor], 2832 | File, 2833 | File.from_cursor_result), 2834 | 2835 | ("clang_getInclusions", 2836 | [TranslationUnit, callbacks['translation_unit_includes'], py_object]), 2837 | 2838 | ("clang_getInstantiationLocation", 2839 | [SourceLocation, POINTER(c_object_p), POINTER(c_uint), POINTER(c_uint), 2840 | POINTER(c_uint)]), 2841 | 2842 | ("clang_getLocation", 2843 | [TranslationUnit, File, c_uint, c_uint], 2844 | SourceLocation), 2845 | 2846 | ("clang_getLocationForOffset", 2847 | [TranslationUnit, File, c_uint], 2848 | SourceLocation), 2849 | 2850 | ("clang_getNullCursor", 2851 | None, 2852 | Cursor), 2853 | 2854 | ("clang_getNumArgTypes", 2855 | [Type], 2856 | c_uint), 2857 | 2858 | ("clang_getNumCompletionChunks", 2859 | [c_void_p], 2860 | c_int), 2861 | 2862 | ("clang_getNumDiagnostics", 2863 | [c_object_p], 2864 | c_uint), 2865 | 2866 | ("clang_getNumElements", 2867 | [Type], 2868 | c_longlong), 2869 | 2870 | ("clang_getNumOverloadedDecls", 2871 | [Cursor], 2872 | c_uint), 2873 | 2874 | ("clang_getOverloadedDecl", 2875 | [Cursor, c_uint], 2876 | Cursor, 2877 | Cursor.from_cursor_result), 2878 | 2879 | ("clang_getPointeeType", 2880 | [Type], 2881 | Type, 2882 | Type.from_result), 2883 | 2884 | ("clang_getRange", 2885 | [SourceLocation, SourceLocation], 2886 | SourceRange), 2887 | 2888 | ("clang_getRangeEnd", 2889 | [SourceRange], 2890 | SourceLocation), 2891 | 2892 | ("clang_getRangeStart", 2893 | [SourceRange], 2894 | SourceLocation), 2895 | 2896 | ("clang_getResultType", 2897 | [Type], 2898 | Type, 2899 | Type.from_result), 2900 | 2901 | ("clang_getSpecializedCursorTemplate", 2902 | [Cursor], 2903 | Cursor, 2904 | Cursor.from_cursor_result), 2905 | 2906 | ("clang_getTemplateCursorKind", 2907 | [Cursor], 2908 | c_uint), 2909 | 2910 | ("clang_getTokenExtent", 2911 | [TranslationUnit, Token], 2912 | SourceRange), 2913 | 2914 | ("clang_getTokenKind", 2915 | [Token], 2916 | c_uint), 2917 | 2918 | ("clang_getTokenLocation", 2919 | [TranslationUnit, Token], 2920 | SourceLocation), 2921 | 2922 | ("clang_getTokenSpelling", 2923 | [TranslationUnit, Token], 2924 | _CXString, 2925 | _CXString.from_result), 2926 | 2927 | ("clang_getTranslationUnitCursor", 2928 | [TranslationUnit], 2929 | Cursor, 2930 | Cursor.from_result), 2931 | 2932 | ("clang_getTranslationUnitSpelling", 2933 | [TranslationUnit], 2934 | _CXString, 2935 | _CXString.from_result), 2936 | 2937 | ("clang_getTUResourceUsageName", 2938 | [c_uint], 2939 | c_char_p), 2940 | 2941 | ("clang_getTypeDeclaration", 2942 | [Type], 2943 | Cursor, 2944 | Cursor.from_result), 2945 | 2946 | ("clang_getTypedefDeclUnderlyingType", 2947 | [Cursor], 2948 | Type, 2949 | Type.from_result), 2950 | 2951 | ("clang_getTypeKindSpelling", 2952 | [c_uint], 2953 | _CXString, 2954 | _CXString.from_result), 2955 | 2956 | ("clang_hashCursor", 2957 | [Cursor], 2958 | c_uint), 2959 | 2960 | ("clang_isAttribute", 2961 | [CursorKind], 2962 | bool), 2963 | 2964 | ("clang_isConstQualifiedType", 2965 | [Type], 2966 | bool), 2967 | 2968 | ("clang_isCursorDefinition", 2969 | [Cursor], 2970 | bool), 2971 | 2972 | ("clang_isDeclaration", 2973 | [CursorKind], 2974 | bool), 2975 | 2976 | ("clang_isExpression", 2977 | [CursorKind], 2978 | bool), 2979 | 2980 | ("clang_isFileMultipleIncludeGuarded", 2981 | [TranslationUnit, File], 2982 | bool), 2983 | 2984 | ("clang_isFunctionTypeVariadic", 2985 | [Type], 2986 | bool), 2987 | 2988 | ("clang_isInvalid", 2989 | [CursorKind], 2990 | bool), 2991 | 2992 | ("clang_isPODType", 2993 | [Type], 2994 | bool), 2995 | 2996 | ("clang_isPreprocessing", 2997 | [CursorKind], 2998 | bool), 2999 | 3000 | ("clang_isReference", 3001 | [CursorKind], 3002 | bool), 3003 | 3004 | ("clang_isRestrictQualifiedType", 3005 | [Type], 3006 | bool), 3007 | 3008 | ("clang_isStatement", 3009 | [CursorKind], 3010 | bool), 3011 | 3012 | ("clang_isTranslationUnit", 3013 | [CursorKind], 3014 | bool), 3015 | 3016 | ("clang_isUnexposed", 3017 | [CursorKind], 3018 | bool), 3019 | 3020 | ("clang_isVirtualBase", 3021 | [Cursor], 3022 | bool), 3023 | 3024 | ("clang_isVolatileQualifiedType", 3025 | [Type], 3026 | bool), 3027 | 3028 | ("clang_parseTranslationUnit", 3029 | [Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int], 3030 | c_object_p), 3031 | 3032 | ("clang_reparseTranslationUnit", 3033 | [TranslationUnit, c_int, c_void_p, c_int], 3034 | c_int), 3035 | 3036 | ("clang_saveTranslationUnit", 3037 | [TranslationUnit, c_char_p, c_uint], 3038 | c_int), 3039 | 3040 | ("clang_tokenize", 3041 | [TranslationUnit, SourceRange, POINTER(POINTER(Token)), POINTER(c_uint)]), 3042 | 3043 | ("clang_visitChildren", 3044 | [Cursor, callbacks['cursor_visit'], py_object], 3045 | c_uint), 3046 | 3047 | ("clang_Cursor_getNumArguments", 3048 | [Cursor], 3049 | c_int), 3050 | 3051 | ("clang_Cursor_getArgument", 3052 | [Cursor, c_uint], 3053 | Cursor, 3054 | Cursor.from_result), 3055 | ] 3056 | 3057 | class LibclangError(Exception): 3058 | def __init__(self, message): 3059 | self.m = message 3060 | 3061 | def __str__(self): 3062 | return self.m 3063 | 3064 | def register_function(lib, item, ignore_errors): 3065 | # A function may not exist, if these bindings are used with an older or 3066 | # incompatible version of libclang.so. 3067 | try: 3068 | func = getattr(lib, item[0]) 3069 | except AttributeError as e: 3070 | msg = str(e) + ". Please ensure that your python bindings are "\ 3071 | "compatible with your libclang.so version." 3072 | if ignore_errors: 3073 | return 3074 | raise LibclangError(msg) 3075 | 3076 | if len(item) >= 2: 3077 | func.argtypes = item[1] 3078 | 3079 | if len(item) >= 3: 3080 | func.restype = item[2] 3081 | 3082 | if len(item) == 4: 3083 | func.errcheck = item[3] 3084 | 3085 | def register_functions(lib, ignore_errors): 3086 | """Register function prototypes with a libclang library instance. 3087 | 3088 | This must be called as part of library instantiation so Python knows how 3089 | to call out to the shared library. 3090 | """ 3091 | 3092 | def register(item): 3093 | return register_function(lib, item, ignore_errors) 3094 | 3095 | list(map(register, functionList)) 3096 | 3097 | class Config: 3098 | library_path = None 3099 | library_file = None 3100 | compatibility_check = True 3101 | loaded = False 3102 | 3103 | @staticmethod 3104 | def set_library_path(path): 3105 | """Set the path in which to search for libclang""" 3106 | if Config.loaded: 3107 | raise Exception("library path must be set before before using " 3108 | "any other functionalities in libclang.") 3109 | 3110 | Config.library_path = path 3111 | 3112 | @staticmethod 3113 | def set_library_file(filename): 3114 | """Set the exact location of libclang""" 3115 | if Config.loaded: 3116 | raise Exception("library file must be set before before using " 3117 | "any other functionalities in libclang.") 3118 | 3119 | Config.library_file = filename 3120 | 3121 | @staticmethod 3122 | def set_compatibility_check(check_status): 3123 | """ Perform compatibility check when loading libclang 3124 | 3125 | The python bindings are only tested and evaluated with the version of 3126 | libclang they are provided with. To ensure correct behavior a (limited) 3127 | compatibility check is performed when loading the bindings. This check 3128 | will throw an exception, as soon as it fails. 3129 | 3130 | In case these bindings are used with an older version of libclang, parts 3131 | that have been stable between releases may still work. Users of the 3132 | python bindings can disable the compatibility check. This will cause 3133 | the python bindings to load, even though they are written for a newer 3134 | version of libclang. Failures now arise if unsupported or incompatible 3135 | features are accessed. The user is required to test himself if the 3136 | features he is using are available and compatible between different 3137 | libclang versions. 3138 | """ 3139 | if Config.loaded: 3140 | raise Exception("compatibility_check must be set before before " 3141 | "using any other functionalities in libclang.") 3142 | 3143 | Config.compatibility_check = check_status 3144 | 3145 | @CachedProperty 3146 | def lib(self): 3147 | lib = self.get_cindex_library() 3148 | register_functions(lib, not Config.compatibility_check) 3149 | Config.loaded = True 3150 | return lib 3151 | 3152 | def get_filename(self): 3153 | if Config.library_file: 3154 | return Config.library_file 3155 | 3156 | import platform 3157 | name = platform.system() 3158 | 3159 | if name == 'Darwin': 3160 | file = 'libclang.dylib' 3161 | elif name == 'Windows': 3162 | file = 'libclang.dll' 3163 | else: 3164 | file = 'libclang.so' 3165 | 3166 | if Config.library_path: 3167 | file = Config.library_path + '/' + file 3168 | 3169 | return file 3170 | 3171 | def get_cindex_library(self): 3172 | try: 3173 | library = cdll.LoadLibrary(self.get_filename()) 3174 | except OSError as e: 3175 | msg = str(e) + ". To provide a path to libclang use " \ 3176 | "Config.set_library_path() or " \ 3177 | "Config.set_library_file()." 3178 | raise LibclangError(msg) 3179 | 3180 | return library 3181 | 3182 | def function_exists(self, name): 3183 | try: 3184 | getattr(self.lib, name) 3185 | except AttributeError: 3186 | return False 3187 | 3188 | return True 3189 | 3190 | def register_enumerations(): 3191 | for name, value in clang.enumerations.TokenKinds: 3192 | TokenKind.register(value, name) 3193 | 3194 | conf = Config() 3195 | register_enumerations() 3196 | 3197 | __all__ = [ 3198 | 'Config', 3199 | 'CodeCompletionResults', 3200 | 'CompilationDatabase', 3201 | 'CompileCommands', 3202 | 'CompileCommand', 3203 | 'CursorKind', 3204 | 'Cursor', 3205 | 'Diagnostic', 3206 | 'File', 3207 | 'FixIt', 3208 | 'Index', 3209 | 'SourceLocation', 3210 | 'SourceRange', 3211 | 'TokenKind', 3212 | 'Token', 3213 | 'TranslationUnitLoadError', 3214 | 'TranslationUnit', 3215 | 'TypeKind', 3216 | 'Type', 3217 | ] 3218 | -------------------------------------------------------------------------------- /plugin/clang/enumerations.py: -------------------------------------------------------------------------------- 1 | #===- enumerations.py - Python Enumerations ------------------*- 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 | 10 | """ 11 | Clang Enumerations 12 | ================== 13 | 14 | This module provides static definitions of enumerations that exist in libclang. 15 | 16 | Enumerations are typically defined as a list of tuples. The exported values are 17 | typically munged into other types or classes at module load time. 18 | 19 | All enumerations are centrally defined in this file so they are all grouped 20 | together and easier to audit. And, maybe even one day this file will be 21 | automatically generated by scanning the libclang headers! 22 | """ 23 | 24 | # Maps to CXTokenKind. Note that libclang maintains a separate set of token 25 | # enumerations from the C++ API. 26 | TokenKinds = [ 27 | ('PUNCTUATION', 0), 28 | ('KEYWORD', 1), 29 | ('IDENTIFIER', 2), 30 | ('LITERAL', 3), 31 | ('COMMENT', 4), 32 | ] 33 | 34 | __all__ = ['TokenKinds'] 35 | -------------------------------------------------------------------------------- /plugin/clang_complete.vim: -------------------------------------------------------------------------------- 1 | " 2 | " File: clang_complete.vim 3 | " Author: Xavier Deguillard 4 | " 5 | " Description: Use of clang to complete in C/C++. 6 | " 7 | " Help: Use :help clang_complete 8 | " 9 | 10 | if exists('g:clang_complete_loaded') 11 | finish 12 | endif 13 | let g:clang_complete_loaded = 1 14 | 15 | au FileType c,cpp,objc,objcpp call ClangCompleteInit() 16 | au FileType c.*,cpp.*,objc.*,objcpp.* call ClangCompleteInit() 17 | 18 | let b:clang_parameters = '' 19 | let b:clang_user_options = '' 20 | let b:my_changedtick = 0 21 | 22 | " Store plugin path, as this is available only when sourcing the file, 23 | " not during a function call. 24 | let s:plugin_path = escape(expand(':p:h'), '\') 25 | 26 | " Older versions of Vim can't check if a map was made with 27 | let s:use_maparg = v:version > 703 || (v:version == 703 && has('patch32')) 28 | 29 | function! s:ClangCompleteInit() 30 | let l:bufname = bufname("%") 31 | if l:bufname == '' 32 | return 33 | endif 34 | 35 | if exists('g:clang_use_library') && g:clang_use_library == 0 36 | echoe "clang_complete: You can't use clang binary anymore." 37 | echoe 'For more information see g:clang_use_library help.' 38 | return 39 | endif 40 | 41 | if !exists('g:clang_auto_select') 42 | let g:clang_auto_select = 0 43 | endif 44 | 45 | if !exists('g:clang_complete_auto') 46 | let g:clang_complete_auto = 1 47 | endif 48 | 49 | if !exists('g:clang_close_preview') 50 | let g:clang_close_preview = 0 51 | endif 52 | 53 | if !exists('g:clang_complete_copen') 54 | let g:clang_complete_copen = 0 55 | endif 56 | 57 | if !exists('g:clang_hl_errors') 58 | let g:clang_hl_errors = 1 59 | endif 60 | 61 | if !exists('g:clang_periodic_quickfix') 62 | let g:clang_periodic_quickfix = 0 63 | endif 64 | 65 | if !exists('g:clang_snippets') || g:clang_snippets == 0 66 | let g:clang_snippets_engine = 'dummy' 67 | endif 68 | 69 | if !exists('g:clang_snippets_engine') 70 | let g:clang_snippets_engine = 'clang_complete' 71 | endif 72 | 73 | if !exists('g:clang_user_options') 74 | let g:clang_user_options = '' 75 | endif 76 | 77 | if !exists('g:clang_conceal_snippets') 78 | let g:clang_conceal_snippets = has('conceal') 79 | elseif g:clang_conceal_snippets == 1 && !has('conceal') 80 | echoe 'clang_complete: conceal feature not available but requested' 81 | endif 82 | 83 | if !exists('g:clang_trailing_placeholder') 84 | let g:clang_trailing_placeholder = 0 85 | endif 86 | 87 | if !exists('g:clang_compilation_database') 88 | let g:clang_compilation_database = '' 89 | endif 90 | 91 | if !exists('g:clang_library_path') 92 | let g:clang_library_path = '' 93 | endif 94 | 95 | if !exists('g:clang_complete_macros') 96 | let g:clang_complete_macros = 0 97 | endif 98 | 99 | if !exists('g:clang_complete_patterns') 100 | let g:clang_complete_patterns = 0 101 | endif 102 | 103 | if !exists('g:clang_debug') 104 | let g:clang_debug = 0 105 | endif 106 | 107 | if !exists('g:clang_quiet') 108 | let g:clang_quiet = 0 109 | endif 110 | 111 | if !exists('g:clang_sort_algo') 112 | let g:clang_sort_algo = 'priority' 113 | endif 114 | 115 | if !exists('g:clang_auto_user_options') 116 | let g:clang_auto_user_options = '.clang_complete, path' 117 | endif 118 | 119 | if !exists('g:clang_jumpto_declaration_key') 120 | let g:clang_jumpto_declaration_key = '' 121 | endif 122 | 123 | if !exists('g:clang_jumpto_declaration_in_preview_key') 124 | let g:clang_jumpto_declaration_in_preview_key = ']' 125 | endif 126 | 127 | if !exists('g:clang_jumpto_back_key') 128 | let g:clang_jumpto_back_key = '' 129 | endif 130 | 131 | if !exists('g:clang_make_default_keymappings') 132 | let g:clang_make_default_keymappings = 1 133 | endif 134 | 135 | if !exists('g:clang_restore_cr_imap') 136 | let g:clang_restore_cr_imap = 'iunmap ' 137 | endif 138 | 139 | call LoadUserOptions() 140 | 141 | let b:my_changedtick = b:changedtick 142 | let b:clang_parameters = '-x c' 143 | 144 | if &filetype =~ 'objc' 145 | let b:clang_parameters = '-x objective-c' 146 | endif 147 | 148 | if &filetype == 'cpp' || &filetype == 'objcpp' 149 | let b:clang_parameters .= '++' 150 | endif 151 | 152 | if expand('%:e') =~ 'h.*' 153 | let b:clang_parameters .= '-header' 154 | endif 155 | 156 | let g:clang_complete_lib_flags = 0 157 | 158 | if g:clang_complete_macros == 1 159 | let g:clang_complete_lib_flags = 1 160 | endif 161 | 162 | if g:clang_complete_patterns == 1 163 | let g:clang_complete_lib_flags += 2 164 | endif 165 | 166 | if s:initClangCompletePython() != 1 167 | return 168 | endif 169 | 170 | execute s:get_python() . "snippetsInit()" 171 | 172 | if g:clang_make_default_keymappings == 1 173 | inoremap LaunchCompletion() 174 | inoremap . CompleteDot() 175 | inoremap > CompleteArrow() 176 | inoremap : CompleteColon() 177 | execute "nnoremap " . g:clang_jumpto_declaration_key . " :call GotoDeclaration(0)" 178 | execute "nnoremap " . g:clang_jumpto_declaration_in_preview_key . " :call GotoDeclaration(1)" 179 | execute "nnoremap " . g:clang_jumpto_back_key . " " 180 | endif 181 | 182 | " Force menuone. Without it, when there's only one completion result, 183 | " it can be confusing (not completing and no popup) 184 | if g:clang_auto_select != 2 185 | set completeopt-=menu 186 | set completeopt+=menuone 187 | endif 188 | 189 | " Disable every autocmd that could have been set. 190 | augroup ClangComplete 191 | autocmd! 192 | augroup end 193 | 194 | if g:clang_periodic_quickfix == 1 195 | augroup ClangComplete 196 | au CursorHold,CursorHoldI call DoPeriodicQuickFix() 197 | augroup end 198 | endif 199 | 200 | setlocal completefunc=ClangComplete 201 | setlocal omnifunc=ClangComplete 202 | endfunction 203 | 204 | function! LoadUserOptions() 205 | let b:clang_user_options = '' 206 | 207 | let l:option_sources = split(g:clang_auto_user_options, ',') 208 | let l:remove_spaces_cmd = 'substitute(v:val, "\\s*\\(.*\\)\\s*", "\\1", "")' 209 | let l:option_sources = map(l:option_sources, l:remove_spaces_cmd) 210 | 211 | for l:source in l:option_sources 212 | if l:source == 'gcc' || l:source == 'clang' 213 | echo "'" . l:source . "' in clang_auto_user_options is deprecated." 214 | continue 215 | endif 216 | if l:source == 'path' 217 | call s:parsePathOption() 218 | elseif l:source == 'compile_commands.json' 219 | call s:findCompilationDatase(l:source) 220 | elseif l:source == '.clang_complete' 221 | call s:parseConfig() 222 | else 223 | let l:getopts = 'getopts#' . l:source . '#getopts' 224 | silent call eval(l:getopts . '()') 225 | endif 226 | endfor 227 | endfunction 228 | 229 | " Used to tell if a flag needs a space between the flag and file 230 | let s:flagInfo = { 231 | \ '-I': { 232 | \ 'pattern': '-I\s*', 233 | \ 'output': '-I' 234 | \ }, 235 | \ '-F': { 236 | \ 'pattern': '-F\s*', 237 | \ 'output': '-F' 238 | \ }, 239 | \ '-iquote': { 240 | \ 'pattern': '-iquote\s*', 241 | \ 'output': '-iquote' 242 | \ }, 243 | \ '-include': { 244 | \ 'pattern': '-include\s\+', 245 | \ 'output': '-include ' 246 | \ } 247 | \ } 248 | 249 | let s:flagPatterns = [] 250 | for s:flag in values(s:flagInfo) 251 | let s:flagPatterns = add(s:flagPatterns, s:flag.pattern) 252 | endfor 253 | let s:flagPattern = '\%(' . join(s:flagPatterns, '\|') . '\)' 254 | 255 | 256 | function! s:processFilename(filename, root) 257 | " Handle Unix absolute path 258 | if matchstr(a:filename, '\C^[''"\\]\=/') != '' 259 | let l:filename = a:filename 260 | " Handle Windows absolute path 261 | elseif s:isWindows() 262 | \ && matchstr(a:filename, '\C^"\=[a-zA-Z]:[/\\]') != '' 263 | let l:filename = a:filename 264 | " Convert relative path to absolute path 265 | else 266 | " If a windows file, the filename may need to be quoted. 267 | if s:isWindows() 268 | if matchstr(a:filename, '\C^".*"\s*$') == '' 269 | let l:filename = substitute(a:filename, '\C^\(.\{-}\)\s*$' 270 | \ , '"' . a:root . '\1"', 'g') 271 | else 272 | " Strip first double-quote and prepend the root. 273 | let l:filename = substitute(a:filename, '\C^"\(.\{-}\)\s*$' 274 | \ , '"' . a:root . '\1"', 'g') 275 | endif 276 | else 277 | " For Unix, assume the filename is already escaped/quoted correctly 278 | let l:filename = shellescape(a:root) . a:filename 279 | endif 280 | endif 281 | 282 | return l:filename 283 | endfunction 284 | 285 | function! s:parseConfig() 286 | let l:local_conf = findfile('.clang_complete', getcwd() . ',.;') 287 | if l:local_conf == '' || !filereadable(l:local_conf) 288 | let l:local_conf = findfile('.syntastic_' . &filetype . '_config', 289 | \ getcwd() . ',.;') 290 | if l:local_conf == '' || !filereadable(l:local_conf) 291 | return 292 | endif 293 | endif 294 | 295 | let l:sep = '/' 296 | if s:isWindows() 297 | let l:sep = '\' 298 | endif 299 | 300 | let l:root = fnamemodify(l:local_conf, ':p:h') . l:sep 301 | 302 | let l:opts = readfile(l:local_conf) 303 | for l:opt in l:opts 304 | " Ensure passed filenames are absolute. Only performed on flags which 305 | " require a filename/directory as an argument, as specified in s:flagInfo 306 | if matchstr(l:opt, '\C^\s*' . s:flagPattern . '\s*') != '' 307 | let l:flag = substitute(l:opt, '\C^\s*\(' . s:flagPattern . '\).*' 308 | \ , '\1', 'g') 309 | let l:flag = substitute(l:flag, '^\(.\{-}\)\s*$', '\1', 'g') 310 | let l:filename = substitute(l:opt, 311 | \ '\C^\s*' . s:flagPattern . '\(.\{-}\)\s*$', 312 | \ '\1', 'g') 313 | let l:filename = s:processFilename(l:filename, l:root) 314 | let l:opt = s:flagInfo[l:flag].output . l:filename 315 | endif 316 | 317 | let b:clang_user_options .= ' ' . l:opt 318 | endfor 319 | endfunction 320 | 321 | function! s:findCompilationDatase(cdb) 322 | if g:clang_compilation_database == '' 323 | let l:local_conf = findfile(a:cdb, getcwd() . ',.;') 324 | if l:local_conf != '' && filereadable(l:local_conf) 325 | let g:clang_compilation_database = fnamemodify(l:local_conf, ":p:h") 326 | endif 327 | endif 328 | endfunction 329 | 330 | function! s:parsePathOption() 331 | let l:dirs = map(split(&path, '\\\@ 0 && l:line[l:wsstart - 1] =~ '\s' 475 | let l:wsstart -= 1 476 | endwhile 477 | endif 478 | while l:start > 0 && l:line[l:start - 1] =~ '\i' 479 | let l:start -= 1 480 | endwhile 481 | let b:col = l:start + 1 482 | return l:start 483 | else 484 | if g:clang_debug == 1 485 | let l:time_start = reltime() 486 | endif 487 | 488 | execute s:get_python() . "snippetsReset()" 489 | 490 | execute s:get_python() . "completions, timer = getCurrentCompletions(vim.eval('a:base'))" 491 | execute s:get_python() . "vim.command('let l:res = ' + completions)" 492 | execute s:get_python() . "timer.registerEvent('Load into vimscript')" 493 | 494 | " @vimlint(EVL101, 1, l:res) 495 | if g:clang_make_default_keymappings == 1 496 | if s:use_maparg 497 | let s:old_cr = maparg('', 'i', 0, 1) 498 | else 499 | let s:old_snr = matchstr(maparg('', 'i'), '\d\+_') 500 | endif 501 | inoremap HandlePossibleSelectionCtrlY() 502 | inoremap HandlePossibleSelectionEnter() 503 | endif 504 | augroup ClangComplete 505 | au CursorMovedI call TriggerSnippet() 506 | if exists('##CompleteDone') 507 | au CompleteDone,InsertLeave call StopMonitoring() 508 | else 509 | au InsertLeave call StopMonitoring() 510 | endif 511 | augroup end 512 | let b:snippet_chosen = 0 513 | 514 | execute s:get_python() . "timer.finish()" 515 | 516 | if g:clang_debug == 1 517 | " @vimlint(EVL104, 1, l:time_start) 518 | echom 'clang_complete: completion time ' . split(reltimestr(reltime(l:time_start)))[0] 519 | " @vimlint(EVL104, 0, l:time_start) 520 | endif 521 | return l:res 522 | " @vimlint(EVL101, 0, l:res) 523 | endif 524 | endfunction 525 | " @vimlint(EVL103, 0, a:base) 526 | 527 | function! s:HandlePossibleSelectionEnter() 528 | if pumvisible() 529 | let b:snippet_chosen = 1 530 | return "\" 531 | end 532 | return "\" 533 | endfunction 534 | 535 | function! s:HandlePossibleSelectionCtrlY() 536 | if pumvisible() 537 | let b:snippet_chosen = 1 538 | end 539 | return "\" 540 | endfunction 541 | 542 | function! s:StopMonitoring() 543 | if b:snippet_chosen 544 | call s:TriggerSnippet() 545 | return 546 | endif 547 | 548 | if g:clang_make_default_keymappings == 1 549 | " Restore original return and Ctrl-Y key mappings 550 | 551 | if s:use_maparg 552 | if get(s:old_cr, 'buffer', 0) 553 | silent! execute s:old_cr.mode. 554 | \ (s:old_cr.noremap ? 'noremap ' : 'map'). 555 | \ (s:old_cr.buffer ? ' ' : ''). 556 | \ (s:old_cr.expr ? ' ' : ''). 557 | \ (s:old_cr.nowait ? ' ' : ''). 558 | \ s:old_cr.lhs.' '. 559 | \ substitute(s:old_cr.rhs, '', ''.s:old_cr.sid.'_', 'g') 560 | else 561 | silent! iunmap 562 | endif 563 | else 564 | silent! execute substitute(g:clang_restore_cr_imap, '', s:old_snr, 'g') 565 | endif 566 | 567 | silent! iunmap 568 | endif 569 | 570 | augroup ClangComplete 571 | au! CursorMovedI,InsertLeave 572 | if exists('##CompleteDone') 573 | au! CompleteDone 574 | endif 575 | augroup END 576 | endfunction 577 | 578 | function! s:TriggerSnippet() 579 | " Dont bother doing anything until we're sure the user exited the menu 580 | if !b:snippet_chosen 581 | return 582 | endif 583 | 584 | " Stop monitoring as we'll trigger a snippet 585 | let b:snippet_chosen = 0 586 | call s:StopMonitoring() 587 | 588 | " Trigger the snippet 589 | execute s:get_python() . "snippetsTrigger()" 590 | 591 | if g:clang_close_preview 592 | pclose 593 | endif 594 | endfunction 595 | 596 | function! s:ShouldComplete() 597 | if (getline('.') =~ '#\s*\(include\|import\)') 598 | return 0 599 | else 600 | if col('.') == 1 601 | return 1 602 | endif 603 | for l:id in synstack(line('.'), col('.') - 1) 604 | if match(synIDattr(l:id, 'name'), '\CComment\|String\|Number') 605 | \ != -1 606 | return 0 607 | endif 608 | endfor 609 | return 1 610 | endif 611 | endfunction 612 | 613 | function! s:LaunchCompletion() 614 | let l:result = "" 615 | if s:ShouldComplete() 616 | let l:result = "\\" 617 | if g:clang_auto_select != 2 618 | let l:result .= "\" 619 | endif 620 | if g:clang_auto_select == 1 621 | let l:result .= "\=(pumvisible() ? \"\\\" : '')\" 622 | endif 623 | endif 624 | return l:result 625 | endfunction 626 | 627 | function! s:CompleteDot() 628 | if g:clang_complete_auto == 1 629 | return '.' . s:LaunchCompletion() 630 | endif 631 | return '.' 632 | endfunction 633 | 634 | function! s:CompleteArrow() 635 | if g:clang_complete_auto != 1 || getline('.')[col('.') - 2] != '-' 636 | return '>' 637 | endif 638 | return '>' . s:LaunchCompletion() 639 | endfunction 640 | 641 | function! s:CompleteColon() 642 | if g:clang_complete_auto != 1 || getline('.')[col('.') - 2] != ':' 643 | return ':' 644 | endif 645 | return ':' . s:LaunchCompletion() 646 | endfunction 647 | 648 | " @vimlint(EVL103, 1, a:preview) 649 | function! s:GotoDeclaration(preview) 650 | try 651 | execute s:get_python() . "gotoDeclaration(vim.eval('a:preview') == '1')" 652 | catch /^Vim\%((\a\+)\)\=:E37/ 653 | echoe "The current file is not saved, and 'hidden' is not set." 654 | \ "Either save the file or add 'set hidden' in your vimrc." 655 | endtry 656 | return '' 657 | endfunction 658 | " @vimlint(EVL103, 0, a:preview) 659 | 660 | " May be used in a mapping to update the quickfix window. 661 | function! g:ClangUpdateQuickFix() 662 | call s:DoPeriodicQuickFix() 663 | return '' 664 | endfunction 665 | 666 | function! g:ClangGotoDeclaration() 667 | call s:GotoDeclaration(0) 668 | return '' 669 | endfunction 670 | 671 | function! g:ClangGotoDeclarationPreview() 672 | call s:GotoDeclaration(1) 673 | return '' 674 | endfunction 675 | 676 | " vim: set ts=2 sts=2 sw=2 expandtab : 677 | -------------------------------------------------------------------------------- /plugin/libclang.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import time 4 | import threading 5 | import os 6 | import shlex 7 | import sys 8 | 9 | from clang.cindex import ( 10 | CompilationDatabase, 11 | Config, 12 | Cursor, 13 | File, 14 | Index, 15 | SourceLocation, 16 | TranslationUnit, 17 | TranslationUnitLoadError 18 | ) 19 | import vim 20 | 21 | 22 | builtinHeaderPath = None 23 | compilation_database = None 24 | complete_flags = None 25 | index = None 26 | libclangLock = None 27 | snippetsAddSnippet = None 28 | snippetsFormatPlaceHolder = None 29 | translationUnits = None 30 | 31 | 32 | def decode(value): 33 | if sys.version_info[0] == 2: 34 | return value 35 | else: 36 | return value.decode('utf-8') 37 | 38 | 39 | # Check if libclang is able to find the builtin include files. 40 | # 41 | # libclang sometimes fails to correctly locate its builtin include files. This 42 | # happens especially if libclang is not installed at a standard location. This 43 | # function checks if the builtin includes are available. 44 | def canFindBuiltinHeaders(index, args = []): 45 | flags = 0 46 | currentFile = ("test.c", '#include "stddef.h"') 47 | try: 48 | tu = index.parse("test.c", args, [currentFile], flags) 49 | except TranslationUnitLoadError: 50 | return 0 51 | return len(tu.diagnostics) == 0 52 | 53 | # Derive path to clang builtin headers. 54 | # 55 | # This function tries to derive a path to clang's builtin header files. We are 56 | # just guessing, but the guess is very educated. In fact, we should be right 57 | # for all manual installations (the ones where the builtin header path problem 58 | # is very common) as well as a set of very common distributions. 59 | def getBuiltinHeaderPath(library_path): 60 | if os.path.isfile(library_path): 61 | library_path = os.path.dirname(library_path) 62 | 63 | knownPaths = [ 64 | library_path + "/../lib/clang", # default value 65 | library_path + "/../clang", # gentoo 66 | library_path + "/clang", # opensuse 67 | library_path + "/", # Google 68 | "/usr/lib64/clang", # x86_64 (openSUSE, Fedora) 69 | "/usr/lib/clang" 70 | ] 71 | 72 | for path in knownPaths: 73 | try: 74 | files = os.listdir(path) 75 | if len(files) >= 1: 76 | files = sorted(files) 77 | subDir = files[-1] 78 | else: 79 | subDir = '.' 80 | path = path + "/" + subDir + "/include/" 81 | arg = "-I" + path 82 | if canFindBuiltinHeaders(index, [arg]): 83 | return path 84 | except: 85 | pass 86 | 87 | return None 88 | 89 | def initClangComplete(clang_complete_flags, clang_compilation_database, 90 | library_path): 91 | global index 92 | 93 | debug = int(vim.eval("g:clang_debug")) == 1 94 | quiet = int(vim.eval("g:clang_quiet")) == 1 95 | 96 | if library_path: 97 | if os.path.isdir(library_path): 98 | Config.set_library_path(library_path) 99 | else: 100 | Config.set_library_file(library_path) 101 | 102 | Config.set_compatibility_check(False) 103 | 104 | try: 105 | index = Index.create() 106 | except Exception as e: 107 | if quiet: 108 | return 0 109 | if library_path: 110 | suggestion = "Are you sure '%s' contains libclang?" % library_path 111 | else: 112 | suggestion = "Consider setting g:clang_library_path." 113 | 114 | if debug: 115 | exception_msg = str(e) 116 | else: 117 | exception_msg = '' 118 | 119 | print('''Loading libclang failed, completion won't be available. %s 120 | %s 121 | ''' % (suggestion, exception_msg)) 122 | return 0 123 | 124 | global builtinHeaderPath 125 | builtinHeaderPath = None 126 | if not canFindBuiltinHeaders(index): 127 | builtinHeaderPath = getBuiltinHeaderPath(library_path) 128 | 129 | if not builtinHeaderPath: 130 | print("WARNING: libclang can not find the builtin includes.") 131 | print(" This will cause slow code completion.") 132 | print(" Please report the problem.") 133 | 134 | global translationUnits 135 | translationUnits = dict() 136 | global complete_flags 137 | complete_flags = int(clang_complete_flags) 138 | global compilation_database 139 | if clang_compilation_database != '': 140 | compilation_database = CompilationDatabase.fromDirectory(clang_compilation_database) 141 | else: 142 | compilation_database = None 143 | global libclangLock 144 | libclangLock = threading.Lock() 145 | return 1 146 | 147 | # Get a tuple (fileName, fileContent) for the file opened in the current 148 | # vim buffer. The fileContent contains the unsafed buffer content. 149 | def getCurrentFile(): 150 | file = "\n".join(vim.current.buffer[:] + ["\n"]) 151 | return (vim.current.buffer.name, file) 152 | 153 | class CodeCompleteTimer: 154 | def __init__(self, debug, file, line, column, params): 155 | self._debug = debug 156 | 157 | if not debug: 158 | return 159 | 160 | content = vim.current.line 161 | print(" ") 162 | print("libclang code completion") 163 | print("========================") 164 | print("Command: clang %s -fsyntax-only " % " ".join(params['args']), end=' ') 165 | print("-Xclang -code-completion-at=%s:%d:%d %s" % (file, line, column, file)) 166 | print("cwd: %s" % params['cwd']) 167 | print("File: %s" % file) 168 | print("Line: %d, Column: %d" % (line, column)) 169 | print(" ") 170 | print("%s" % content) 171 | 172 | print(" ") 173 | 174 | current = time.time() 175 | self._start = current 176 | self._last = current 177 | self._events = [] 178 | 179 | def registerEvent(self, event): 180 | if not self._debug: 181 | return 182 | 183 | current = time.time() 184 | since_last = current - self._last 185 | self._last = current 186 | self._events.append((event, since_last)) 187 | 188 | def finish(self): 189 | if not self._debug: 190 | return 191 | 192 | overall = self._last - self._start 193 | 194 | for event in self._events: 195 | name, since_last = event 196 | percent = 1 / overall * since_last * 100 197 | print("libclang code completion - %25s: %.3fs (%5.1f%%)" % 198 | (name, since_last, percent)) 199 | 200 | print(" ") 201 | print("Overall: %.3f s" % overall) 202 | print("========================") 203 | print(" ") 204 | 205 | def getCurrentTranslationUnit(args, currentFile, fileName, timer, 206 | update = False): 207 | tu = translationUnits.get(fileName) 208 | if tu != None: 209 | if update: 210 | tu.reparse([currentFile]) 211 | timer.registerEvent("Reparsing") 212 | return tu 213 | 214 | flags = TranslationUnit.PARSE_PRECOMPILED_PREAMBLE | \ 215 | TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD 216 | try: 217 | tu = index.parse(fileName, args, [currentFile], flags) 218 | timer.registerEvent("First parse") 219 | except TranslationUnitLoadError: 220 | return None 221 | 222 | translationUnits[fileName] = tu 223 | 224 | # Reparse to initialize the PCH cache even for auto completion 225 | # This should be done by index.parse(), however it is not. 226 | # So we need to reparse ourselves. 227 | tu.reparse([currentFile]) 228 | timer.registerEvent("Generate PCH cache") 229 | return tu 230 | 231 | def splitOptions(options): 232 | # Use python's shell command lexer to correctly split the list of options in 233 | # accordance with the POSIX standard if running a Unix system, or split 234 | # according to Windows shell rules 235 | posixMode = os.name == "posix" 236 | return shlex.split(options, posix=posixMode) 237 | 238 | def getQuickFix(diagnostic): 239 | # Some diagnostics have no file, e.g. "too many errors emitted, stopping now" 240 | if diagnostic.location.file: 241 | filename = diagnostic.location.file.name 242 | else: 243 | filename = "" 244 | 245 | if diagnostic.severity == diagnostic.Ignored: 246 | type = 'I' 247 | elif diagnostic.severity == diagnostic.Note: 248 | type = 'I' 249 | elif diagnostic.severity == diagnostic.Warning: 250 | if "argument unused during compilation" in diagnostic.spelling: 251 | return None 252 | type = 'W' 253 | elif diagnostic.severity == diagnostic.Error: 254 | type = 'E' 255 | elif diagnostic.severity == diagnostic.Fatal: 256 | type = 'E' 257 | else: 258 | return None 259 | 260 | return dict({ 'bufnr' : int(vim.eval("bufnr('" + filename + "', 1)")), 261 | 'lnum' : diagnostic.location.line, 262 | 'col' : diagnostic.location.column, 263 | 'text' : diagnostic.spelling, 264 | 'type' : type}) 265 | 266 | def getQuickFixList(tu): 267 | return [_f for _f in map (getQuickFix, tu.diagnostics) if _f] 268 | 269 | def highlightRange(range, hlGroup): 270 | pattern = '/\%' + str(range.start.line) + 'l' + '\%' \ 271 | + str(range.start.column) + 'c' + '.*' \ 272 | + '\%' + str(range.end.column) + 'c/' 273 | command = "exe 'syntax match' . ' " + hlGroup + ' ' + pattern + "'" 274 | vim.command(command) 275 | 276 | def highlightDiagnostic(diagnostic): 277 | if diagnostic.severity == diagnostic.Warning: 278 | hlGroup = 'SpellLocal' 279 | elif diagnostic.severity == diagnostic.Error: 280 | hlGroup = 'SpellBad' 281 | else: 282 | return 283 | 284 | pattern = '/\%' + str(diagnostic.location.line) + 'l\%' \ 285 | + str(diagnostic.location.column) + 'c./' 286 | command = "exe 'syntax match' . ' " + hlGroup + ' ' + pattern + "'" 287 | vim.command(command) 288 | 289 | for range in diagnostic.ranges: 290 | highlightRange(range, hlGroup) 291 | 292 | def highlightDiagnostics(tu): 293 | list(map (highlightDiagnostic, tu.diagnostics)) 294 | 295 | def highlightCurrentDiagnostics(): 296 | if vim.current.buffer.name in translationUnits: 297 | highlightDiagnostics(translationUnits[vim.current.buffer.name]) 298 | 299 | def getCurrentQuickFixList(): 300 | if vim.current.buffer.name in translationUnits: 301 | return getQuickFixList(translationUnits[vim.current.buffer.name]) 302 | return [] 303 | 304 | # Get the compilation parameters from the compilation database for source 305 | # 'fileName'. The parameters are returned as map with the following keys : 306 | # 307 | # 'args' : compiler arguments. 308 | # Compilation database returns the complete command line. We need 309 | # to filter at least the compiler invocation, the '-o' + output 310 | # file, the input file and the '-c' arguments. We alter -I paths 311 | # to make them absolute, so that we can launch clang from wherever 312 | # we are. 313 | # Note : we behave differently from cc_args.py which only keeps 314 | # '-I', '-D' and '-include' options. 315 | # 316 | # 'cwd' : the compiler working directory 317 | # 318 | # The last found args and cwd are remembered and reused whenever a file is 319 | # not found in the compilation database. For example, this is the case for 320 | # all headers. This achieve very good results in practice. 321 | def getCompilationDBParams(fileName): 322 | if compilation_database: 323 | cmds = compilation_database.getCompileCommands(fileName) 324 | if cmds != None: 325 | cwd = cmds[0].directory 326 | args = [] 327 | skip_next = 1 # Skip compiler invocation 328 | for arg in cmds[0].arguments: 329 | if skip_next: 330 | skip_next = 0; 331 | continue 332 | if arg == '-c': 333 | continue 334 | if arg == fileName or \ 335 | os.path.realpath(os.path.join(cwd, arg)) == fileName: 336 | continue 337 | if arg == '-o': 338 | skip_next = 1; 339 | continue 340 | if arg.startswith('-I'): 341 | includePath = arg[2:] 342 | if not os.path.isabs(includePath): 343 | includePath = os.path.normpath(os.path.join(cwd, includePath)) 344 | args.append('-I'+includePath) 345 | continue 346 | args.append(arg) 347 | getCompilationDBParams.last_query = { 'args': args, 'cwd': cwd } 348 | 349 | # Do not directly return last_query, but make sure we return a deep copy. 350 | # Otherwise users of that result may accidentally change it and store invalid 351 | # values in our cache. 352 | query = getCompilationDBParams.last_query 353 | return { 'args': list(query['args']), 'cwd': query['cwd']} 354 | 355 | getCompilationDBParams.last_query = { 'args': [], 'cwd': None } 356 | 357 | def getCompileParams(fileName): 358 | global builtinHeaderPath 359 | params = getCompilationDBParams(fileName) 360 | args = params['args'] 361 | args += splitOptions(vim.eval("g:clang_user_options")) 362 | args += splitOptions(vim.eval("b:clang_user_options")) 363 | args += splitOptions(vim.eval("b:clang_parameters")) 364 | 365 | if builtinHeaderPath: 366 | args.append("-I" + builtinHeaderPath) 367 | 368 | return { 'args' : args, 369 | 'cwd' : params['cwd'] } 370 | 371 | def updateCurrentDiagnostics(): 372 | global debug 373 | debug = int(vim.eval("g:clang_debug")) == 1 374 | params = getCompileParams(vim.current.buffer.name) 375 | timer = CodeCompleteTimer(debug, vim.current.buffer.name, -1, -1, params) 376 | 377 | with libclangLock: 378 | getCurrentTranslationUnit(params['args'], getCurrentFile(), 379 | vim.current.buffer.name, timer, update = True) 380 | timer.finish() 381 | 382 | def getCurrentCompletionResults(line, column, args, currentFile, fileName, 383 | timer): 384 | 385 | tu = getCurrentTranslationUnit(args, currentFile, fileName, timer) 386 | timer.registerEvent("Get TU") 387 | 388 | if tu == None: 389 | return None 390 | 391 | cr = tu.codeComplete(fileName, line, column, [currentFile], 392 | complete_flags) 393 | timer.registerEvent("Code Complete") 394 | return cr 395 | 396 | def formatResult(result): 397 | completion = dict() 398 | returnValue = None 399 | abbr = "" 400 | word = "" 401 | info = "" 402 | 403 | for chunk in result.string: 404 | 405 | if chunk.isKindInformative(): 406 | continue 407 | 408 | if chunk.isKindResultType(): 409 | returnValue = chunk 410 | continue 411 | 412 | chunk_spelling = chunk.spelling 413 | try: 414 | chunk_spelling = decode(chunk_spelling) 415 | except AttributeError: 416 | pass 417 | 418 | if chunk.isKindTypedText(): 419 | abbr = chunk_spelling 420 | 421 | if chunk.isKindPlaceHolder(): 422 | word += snippetsFormatPlaceHolder(chunk_spelling) 423 | else: 424 | word += chunk_spelling 425 | 426 | info += chunk_spelling 427 | 428 | menu = info 429 | 430 | if returnValue: 431 | menu = decode(returnValue.spelling) + " " + menu 432 | 433 | completion['word'] = snippetsAddSnippet(info, word, abbr) 434 | completion['abbr'] = abbr 435 | completion['menu'] = menu 436 | completion['info'] = info 437 | completion['dup'] = 1 438 | 439 | # Replace the number that represents a specific kind with a better 440 | # textual representation. 441 | completion['kind'] = kinds[result.cursorKind] 442 | 443 | return completion 444 | 445 | 446 | class CompleteThread(threading.Thread): 447 | def __init__(self, line, column, currentFile, fileName, params, timer): 448 | threading.Thread.__init__(self) 449 | # Complete threads are daemon threads. Python and consequently vim does not 450 | # wait for daemon threads to finish execution when existing itself. As 451 | # clang may compile for a while, we do not have to wait for the compilation 452 | # to finish before vim can quit. Before adding this flags, vim was hanging 453 | # for a couple of seconds before it exited. 454 | self.daemon = True 455 | self.line = line 456 | self.column = column 457 | self.currentFile = currentFile 458 | self.fileName = fileName 459 | self.result = None 460 | self.args = params['args'] 461 | self.cwd = params['cwd'] 462 | self.timer = timer 463 | 464 | def run(self): 465 | with libclangLock: 466 | if self.line == -1: 467 | # Warm up the caches. For this it is sufficient to get the 468 | # current translation unit. No need to retrieve completion 469 | # results. This short pause is necessary to allow vim to 470 | # initialize itself. Otherwise we would get: E293: block was 471 | # not locked The user does not see any delay, as we just pause 472 | # a background thread. 473 | time.sleep(0.1) 474 | getCurrentTranslationUnit(self.args, self.currentFile, self.fileName, 475 | self.timer) 476 | else: 477 | self.result = getCurrentCompletionResults(self.line, self.column, 478 | self.args, self.currentFile, 479 | self.fileName, self.timer) 480 | 481 | def WarmupCache(): 482 | params = getCompileParams(vim.current.buffer.name) 483 | timer = CodeCompleteTimer(0, "", -1, -1, params) 484 | t = CompleteThread(-1, -1, getCurrentFile(), vim.current.buffer.name, 485 | params, timer) 486 | t.start() 487 | 488 | def getCurrentCompletions(base): 489 | global debug 490 | debug = int(vim.eval("g:clang_debug")) == 1 491 | sorting = vim.eval("g:clang_sort_algo") 492 | line, _ = vim.current.window.cursor 493 | column = int(vim.eval("b:col")) 494 | params = getCompileParams(vim.current.buffer.name) 495 | 496 | timer = CodeCompleteTimer(debug, vim.current.buffer.name, line, column, 497 | params) 498 | 499 | t = CompleteThread(line, column, getCurrentFile(), vim.current.buffer.name, 500 | params, timer) 501 | t.start() 502 | while t.isAlive(): 503 | t.join(0.01) 504 | cancel = int(vim.eval('complete_check()')) 505 | if cancel != 0: 506 | return (str([]), timer) 507 | 508 | cr = t.result 509 | if cr is None: 510 | print("Cannot parse this source file. The following arguments " 511 | + "are used for clang: " + " ".join(params['args'])) 512 | return (str([]), timer) 513 | 514 | results = cr.results 515 | 516 | timer.registerEvent("Count # Results (%s)" % str(len(results))) 517 | 518 | if base != "": 519 | results = [x for x in results if getAbbr(x.string).startswith(base)] 520 | 521 | timer.registerEvent("Filter") 522 | 523 | if sorting == 'priority': 524 | def getPriority(x): 525 | return x.string.priority 526 | results = sorted(results, key=getPriority) 527 | if sorting == 'alpha': 528 | def getAbbrevation(x): 529 | return getAbbr(x.string).lower() 530 | results = sorted(results, key=getAbbrevation) 531 | 532 | timer.registerEvent("Sort") 533 | 534 | result = list(map(formatResult, results)) 535 | 536 | timer.registerEvent("Format") 537 | return (str(result), timer) 538 | 539 | def getAbbr(strings): 540 | for chunks in strings: 541 | if chunks.isKindTypedText(): 542 | return decode(chunks.spelling) 543 | return "" 544 | 545 | def jumpToLocation(filename, line, column, preview): 546 | filenameEscaped = decode(filename).replace(" ", "\\ ") 547 | if preview: 548 | command = "pedit +%d %s" % (line, filenameEscaped) 549 | elif filename != vim.current.buffer.name: 550 | command = "edit %s" % filenameEscaped 551 | else: 552 | command = "normal m'" 553 | try: 554 | vim.command(command) 555 | except: 556 | # For some unknown reason, whenever an exception occurs in 557 | # vim.command, vim goes crazy and output tons of useless python 558 | # errors, catch those. 559 | return 560 | if not preview: 561 | vim.current.window.cursor = (line, column - 1) 562 | 563 | def gotoDeclaration(preview=True): 564 | global debug 565 | debug = int(vim.eval("g:clang_debug")) == 1 566 | params = getCompileParams(vim.current.buffer.name) 567 | line, col = vim.current.window.cursor 568 | timer = CodeCompleteTimer(debug, vim.current.buffer.name, line, col, params) 569 | 570 | with libclangLock: 571 | tu = getCurrentTranslationUnit(params['args'], getCurrentFile(), 572 | vim.current.buffer.name, timer, 573 | update = True) 574 | if tu is None: 575 | print("Couldn't get the TranslationUnit") 576 | return 577 | 578 | f = File.from_name(tu, vim.current.buffer.name) 579 | loc = SourceLocation.from_position(tu, f, line, col + 1) 580 | cursor = Cursor.from_location(tu, loc) 581 | defs = [cursor.get_definition(), cursor.referenced] 582 | 583 | for d in defs: 584 | if d is not None and loc != d.location: 585 | loc = d.location 586 | if loc.file is not None: 587 | jumpToLocation(loc.file.name, loc.line, loc.column, preview) 588 | break 589 | 590 | timer.finish() 591 | 592 | # Manually extracted from Index.h 593 | # Doing it by hand is long, error prone and horrible, we must find a way 594 | # to do that automatically. 595 | kinds = dict({ 596 | # Declarations 597 | 1 : 't', # CXCursor_UnexposedDecl (A declaration whose specific kind is not 598 | # exposed via this interface) 599 | 2 : 't', # CXCursor_StructDecl (A C or C++ struct) 600 | 3 : 't', # CXCursor_UnionDecl (A C or C++ union) 601 | 4 : 't', # CXCursor_ClassDecl (A C++ class) 602 | 5 : 't', # CXCursor_EnumDecl (An enumeration) 603 | 6 : 'm', # CXCursor_FieldDecl (A field (in C) or non-static data member 604 | # (in C++) in a struct, union, or C++ class) 605 | 7 : 'e', # CXCursor_EnumConstantDecl (An enumerator constant) 606 | 8 : 'f', # CXCursor_FunctionDecl (A function) 607 | 9 : 'v', # CXCursor_VarDecl (A variable) 608 | 10 : 'a', # CXCursor_ParmDecl (A function or method parameter) 609 | 11 : '11', # CXCursor_ObjCInterfaceDecl (An Objective-C @interface) 610 | 12 : '12', # CXCursor_ObjCCategoryDecl (An Objective-C @interface for a 611 | # category) 612 | 13 : '13', # CXCursor_ObjCProtocolDecl (An Objective-C @protocol declaration) 613 | 14 : '14', # CXCursor_ObjCPropertyDecl (An Objective-C @property declaration) 614 | 15 : '15', # CXCursor_ObjCIvarDecl (An Objective-C instance variable) 615 | 16 : '16', # CXCursor_ObjCInstanceMethodDecl (An Objective-C instance method) 616 | 17 : '17', # CXCursor_ObjCClassMethodDecl (An Objective-C class method) 617 | 18 : '18', # CXCursor_ObjCImplementationDec (An Objective-C @implementation) 618 | 19 : '19', # CXCursor_ObjCCategoryImplDecll (An Objective-C @implementation 619 | # for a category) 620 | 20 : 't', # CXCursor_TypedefDecl (A typedef) 621 | 21 : 'f', # CXCursor_CXXMethod (A C++ class method) 622 | 22 : 'n', # CXCursor_Namespace (A C++ namespace) 623 | 23 : '23', # CXCursor_LinkageSpec (A linkage specification, e.g. 'extern "C"') 624 | 24 : '+', # CXCursor_Constructor (A C++ constructor) 625 | 25 : '~', # CXCursor_Destructor (A C++ destructor) 626 | 26 : '26', # CXCursor_ConversionFunction (A C++ conversion function) 627 | 27 : 'a', # CXCursor_TemplateTypeParameter (A C++ template type parameter) 628 | 28 : 'a', # CXCursor_NonTypeTemplateParameter (A C++ non-type template 629 | # parameter) 630 | 29 : 'a', # CXCursor_TemplateTemplateParameter (A C++ template template 631 | # parameter) 632 | 30 : 'f', # CXCursor_FunctionTemplate (A C++ function template) 633 | 31 : 'p', # CXCursor_ClassTemplate (A C++ class template) 634 | 32 : '32', # CXCursor_ClassTemplatePartialSpecialization (A C++ class template 635 | # partial specialization) 636 | 33 : 'n', # CXCursor_NamespaceAlias (A C++ namespace alias declaration) 637 | 34 : '34', # CXCursor_UsingDirective (A C++ using directive) 638 | 35 : '35', # CXCursor_UsingDeclaration (A C++ using declaration) 639 | 36 : 't', # CXCursor_TypeAliasDecl (A C++ alias declaration) 640 | 37 : '37', # CXCursor_ObjCSynthesizeDecl (An Objective-C synthesize definition) 641 | 38 : '38', # CXCursor_ObjCDynamicDecl (An Objective-C dynamic definition) 642 | 39 : '39', # CXCursor_CXXAccessSpecifier (An access specifier) 643 | 644 | # References 645 | 40 : '40', # CXCursor_ObjCSuperClassRef 646 | 41 : '41', # CXCursor_ObjCProtocolRef 647 | 42 : '42', # CXCursor_ObjCClassRef 648 | 43 : '43', # CXCursor_TypeRef 649 | 44 : '44', # CXCursor_CXXBaseSpecifier 650 | 45 : '45', # CXCursor_TemplateRef (A reference to a class template, function 651 | # template, template template parameter, or class template partial 652 | # specialization) 653 | 46 : '46', # CXCursor_NamespaceRef (A reference to a namespace or namespace 654 | # alias) 655 | 47 : '47', # CXCursor_MemberRef (A reference to a member of a struct, union, 656 | # or class that occurs in some non-expression context, e.g., a 657 | # designated initializer) 658 | 48 : '48', # CXCursor_LabelRef (A reference to a labeled statement) 659 | 49 : '49', # CXCursor_OverloadedDeclRef (A reference to a set of overloaded 660 | # functions or function templates that has not yet been resolved to 661 | # a specific function or function template) 662 | 50 : '50', # CXCursor_VariableRef 663 | 664 | # Error conditions 665 | #70 : '70', # CXCursor_FirstInvalid 666 | 70 : '70', # CXCursor_InvalidFile 667 | 71 : '71', # CXCursor_NoDeclFound 668 | 72 : 'u', # CXCursor_NotImplemented 669 | 73 : '73', # CXCursor_InvalidCode 670 | 671 | # Expressions 672 | 100 : '100', # CXCursor_UnexposedExpr (An expression whose specific kind is 673 | # not exposed via this interface) 674 | 101 : '101', # CXCursor_DeclRefExpr (An expression that refers to some value 675 | # declaration, such as a function, varible, or enumerator) 676 | 102 : '102', # CXCursor_MemberRefExpr (An expression that refers to a member 677 | # of a struct, union, class, Objective-C class, etc) 678 | 103 : '103', # CXCursor_CallExpr (An expression that calls a function) 679 | 104 : '104', # CXCursor_ObjCMessageExpr (An expression that sends a message 680 | # to an Objective-C object or class) 681 | 105 : '105', # CXCursor_BlockExpr (An expression that represents a block 682 | # literal) 683 | 106 : '106', # CXCursor_IntegerLiteral (An integer literal) 684 | 107 : '107', # CXCursor_FloatingLiteral (A floating point number literal) 685 | 108 : '108', # CXCursor_ImaginaryLiteral (An imaginary number literal) 686 | 109 : '109', # CXCursor_StringLiteral (A string literal) 687 | 110 : '110', # CXCursor_CharacterLiteral (A character literal) 688 | 111 : '111', # CXCursor_ParenExpr (A parenthesized expression, e.g. "(1)") 689 | 112 : '112', # CXCursor_UnaryOperator (This represents the unary-expression's 690 | # (except sizeof and alignof)) 691 | 113 : '113', # CXCursor_ArraySubscriptExpr ([C99 6.5.2.1] Array Subscripting) 692 | 114 : '114', # CXCursor_BinaryOperator (A builtin binary operation expression 693 | # such as "x + y" or "x <= y") 694 | 115 : '115', # CXCursor_CompoundAssignOperator (Compound assignment such as 695 | # "+=") 696 | 116 : '116', # CXCursor_ConditionalOperator (The ?: ternary operator) 697 | 117 : '117', # CXCursor_CStyleCastExpr (An explicit cast in C (C99 6.5.4) or a 698 | # C-style cast in C++ (C++ [expr.cast]), which uses the syntax 699 | # (Type)expr) 700 | 118 : '118', # CXCursor_CompoundLiteralExpr ([C99 6.5.2.5]) 701 | 119 : '119', # CXCursor_InitListExpr (Describes an C or C++ initializer list) 702 | 120 : '120', # CXCursor_AddrLabelExpr (The GNU address of label extension, 703 | # representing &&label) 704 | 121 : '121', # CXCursor_StmtExpr (This is the GNU Statement Expression 705 | # extension: ({int X=4; X;}) 706 | 122 : '122', # CXCursor_GenericSelectionExpr (brief Represents a C11 generic 707 | # selection) 708 | 123 : '123', # CXCursor_GNUNullExpr (Implements the GNU __null extension) 709 | 124 : '124', # CXCursor_CXXStaticCastExpr (C++'s static_cast<> expression) 710 | 125 : '125', # CXCursor_CXXDynamicCastExpr (C++'s dynamic_cast<> expression) 711 | 126 : '126', # CXCursor_CXXReinterpretCastExpr (C++'s reinterpret_cast<> 712 | # expression) 713 | 127 : '127', # CXCursor_CXXConstCastExpr (C++'s const_cast<> expression) 714 | 128 : '128', # CXCursor_CXXFunctionalCastExpr (Represents an explicit C++ type 715 | # conversion that uses "functional" notion 716 | # (C++ [expr.type.conv])) 717 | 129 : '129', # CXCursor_CXXTypeidExpr (A C++ typeid expression 718 | # (C++ [expr.typeid])) 719 | 130 : '130', # CXCursor_CXXBoolLiteralExpr (brief [C++ 2.13.5] C++ Boolean 720 | # Literal) 721 | 131 : '131', # CXCursor_CXXNullPtrLiteralExpr ([C++0x 2.14.7] C++ Pointer 722 | # Literal) 723 | 132 : '132', # CXCursor_CXXThisExpr (Represents the "this" expression in C+) 724 | 133 : '133', # CXCursor_CXXThrowExpr ([C++ 15] C++ Throw Expression) 725 | 134 : '134', # CXCursor_CXXNewExpr (A new expression for memory allocation 726 | # and constructor calls) 727 | 135 : '135', # CXCursor_CXXDeleteExpr (A delete expression for memory 728 | # deallocation and destructor calls) 729 | 136 : '136', # CXCursor_UnaryExpr (A unary expression) 730 | 137 : '137', # CXCursor_ObjCStringLiteral (An Objective-C string literal 731 | # i.e. @"foo") 732 | 138 : '138', # CXCursor_ObjCEncodeExpr (An Objective-C \@encode expression) 733 | 139 : '139', # CXCursor_ObjCSelectorExpr (An Objective-C \@selector expression 734 | 140 : '140', # CXCursor_ObjCProtocolExpr (An Objective-C \@protocol expression 735 | 141 : '141', # CXCursor_ObjCBridgedCastExpr (An Objective-C "bridged" cast 736 | # expression, which casts between Objective-C pointers and C 737 | # pointers, transferring ownership in the process) 738 | 142 : '142', # CXCursor_PackExpansionExpr (Represents a C++0x pack expansion 739 | # that produces a sequence of expressions) 740 | 143 : '143', # CXCursor_SizeOfPackExpr (Represents an expression that computes 741 | # the length of a parameter pack) 742 | 144 : '144', # CXCursor_LambdaExpr (Represents a C++ lambda expression that 743 | # produces a local function object) 744 | 145 : '145', # CXCursor_ObjCBoolLiteralExpr (Objective-c Boolean Literal) 745 | 746 | # Statements 747 | 200 : '200', # CXCursor_UnexposedStmt (A statement whose specific kind is not 748 | # exposed via this interface) 749 | 201 : '201', # CXCursor_LabelStmt (A labelled statement in a function) 750 | 202 : '202', # CXCursor_CompoundStmt (A group of statements like 751 | # { stmt stmt }. 752 | 203 : '203', # CXCursor_CaseStmt (A case statement) 753 | 204 : '204', # CXCursor_DefaultStmt (A default statement) 754 | 205 : '205', # CXCursor_IfStmt (An if statemen) 755 | 206 : '206', # CXCursor_SwitchStmt (A switch statement) 756 | 207 : '207', # CXCursor_WhileStmt (A while statement) 757 | 208 : '208', # CXCursor_DoStmt (A do statement) 758 | 209 : '209', # CXCursor_ForStmt (A for statement) 759 | 210 : '210', # CXCursor_GotoStmt (A goto statement) 760 | 211 : '211', # CXCursor_IndirectGotoStmt (An indirect goto statement) 761 | 212 : '212', # CXCursor_ContinueStmt (A continue statement) 762 | 213 : '213', # CXCursor_BreakStmt (A break statement) 763 | 214 : '214', # CXCursor_ReturnStmt (A return statement) 764 | 215 : '215', # CXCursor_GCCAsmStmt (A GCC inline assembly statement extension) 765 | 216 : '216', # CXCursor_ObjCAtTryStmt (Objective-C's overall try-catch-finally 766 | # statement. 767 | 217 : '217', # CXCursor_ObjCAtCatchStmt (Objective-C's catch statement) 768 | 218 : '218', # CXCursor_ObjCAtFinallyStmt (Objective-C's finally statement) 769 | 219 : '219', # CXCursor_ObjCAtThrowStmt (Objective-C's throw statement) 770 | 220 : '220', # CXCursor_ObjCAtSynchronizedStmt (Objective-C's synchronized 771 | # statement) 772 | 221 : '221', # CXCursor_ObjCAutoreleasePoolStmt (Objective-C's autorelease 773 | # pool statement) 774 | 222 : '222', # CXCursor_ObjCForCollectionStmt (Objective-C's collection 775 | # statement) 776 | 223 : '223', # CXCursor_CXXCatchStmt (C++'s catch statement) 777 | 224 : '224', # CXCursor_CXXTryStmt (C++'s try statement) 778 | 225 : '225', # CXCursor_CXXForRangeStmt (C++'s for (* : *) statement) 779 | 226 : '226', # CXCursor_SEHTryStmt (Windows Structured Exception Handling's 780 | # try statement) 781 | 227 : '227', # CXCursor_SEHExceptStmt (Windows Structured Exception Handling's 782 | # except statement. 783 | 228 : '228', # CXCursor_SEHFinallyStmt (Windows Structured Exception 784 | # Handling's finally statement) 785 | 229 : '229', # CXCursor_MSAsmStmt (A MS inline assembly statement extension) 786 | 230 : '230', # CXCursor_NullStmt (The null satement ";": C99 6.8.3p3) 787 | 231 : '231', # CXCursor_DeclStmt (Adaptor class for mixing declarations with 788 | # statements and expressions) 789 | 790 | # Translation unit 791 | 300 : '300', # CXCursor_TranslationUnit (Cursor that represents the 792 | # translation unit itself) 793 | 794 | # Attributes 795 | 400 : '400', # CXCursor_UnexposedAttr (An attribute whose specific kind is 796 | # not exposed via this interface) 797 | 401 : '401', # CXCursor_IBActionAttr 798 | 402 : '402', # CXCursor_IBOutletAttr 799 | 403 : '403', # CXCursor_IBOutletCollectionAttr 800 | 404 : '404', # CXCursor_CXXFinalAttr 801 | 405 : '405', # CXCursor_CXXOverrideAttr 802 | 406 : '406', # CXCursor_AnnotateAttr 803 | 407 : '407', # CXCursor_AsmLabelAttr 804 | 805 | # Preprocessing 806 | 500 : '500', # CXCursor_PreprocessingDirective 807 | 501 : 'd', # CXCursor_MacroDefinition 808 | 502 : '502', # CXCursor_MacroInstantiation 809 | 503 : '503', # CXCursor_InclusionDirective 810 | 811 | # Modules 812 | 600 : '600', # CXCursor_ModuleImportDecl (A module import declaration) 813 | }) 814 | 815 | # vim: set ts=2 sts=2 sw=2 expandtab : 816 | -------------------------------------------------------------------------------- /plugin/snippets/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['clang_complete', 'ultisnips', 'dummy'] 2 | -------------------------------------------------------------------------------- /plugin/snippets/clang_complete.py: -------------------------------------------------------------------------------- 1 | import re 2 | import vim 3 | 4 | def snippetsInit(): 5 | vim.command("noremap :python updateSnips()") 6 | vim.command("snoremap :python updateSnips()") 7 | if int(vim.eval("g:clang_conceal_snippets")) == 1: 8 | vim.command("syntax match placeHolder /\$`[^`]*`/ contains=placeHolderMark") 9 | vim.command("syntax match placeHolderMark contained /\$`/ conceal") 10 | vim.command("syntax match placeHolderMark contained /`/ conceal") 11 | 12 | # The two following function are performance sensitive, do _nothing_ 13 | # more that the strict necessary. 14 | 15 | def snippetsFormatPlaceHolder(word): 16 | return "$`%s`" % word 17 | 18 | def snippetsAddSnippet(fullname, word, abbr): 19 | return word 20 | 21 | r = re.compile('\$`[^`]*`') 22 | 23 | def snippetsTrigger(): 24 | if r.search(vim.current.line) is None: 25 | return 26 | vim.command('call feedkeys("\^\")') 27 | 28 | def snippetsReset(): 29 | pass 30 | 31 | def updateSnips(): 32 | line = vim.current.line 33 | row, col = vim.current.window.cursor 34 | 35 | result = r.search(line, col) 36 | if result is None: 37 | result = r.search(line) 38 | if result is None: 39 | vim.command('call feedkeys("\", "n")') 40 | return 41 | 42 | start, end = result.span() 43 | vim.current.window.cursor = row, start 44 | isInclusive = vim.eval("&selection") == "inclusive" 45 | vim.command('call feedkeys("\v%dl\", "n")' % (end - start - isInclusive)) 46 | 47 | # vim: set ts=2 sts=2 sw=2 expandtab : 48 | -------------------------------------------------------------------------------- /plugin/snippets/dummy.py: -------------------------------------------------------------------------------- 1 | def snippetsInit(): 2 | pass 3 | 4 | def snippetsFormatPlaceHolder(word): 5 | return '' 6 | 7 | def snippetsAddSnippet(fullname, word, abbr): 8 | return abbr 9 | 10 | def snippetsTrigger(): 11 | pass 12 | 13 | def snippetsReset(): 14 | pass 15 | 16 | # vim: set ts=2 sts=2 sw=2 expandtab : 17 | -------------------------------------------------------------------------------- /plugin/snippets/ultisnips.py: -------------------------------------------------------------------------------- 1 | import vim 2 | 3 | try: 4 | from UltiSnips import UltiSnips_Manager 5 | except: 6 | from UltiSnips import SnippetManager 7 | 8 | UltiSnips_Manager = SnippetManager( 9 | vim.eval('g:UltiSnipsExpandTrigger'), 10 | vim.eval('g:UltiSnipsJumpForwardTrigger'), 11 | vim.eval('g:UltiSnipsJumpBackwardTrigger')) 12 | 13 | 14 | ultisnips_idx = 0 15 | 16 | 17 | def snippetsInit(): 18 | global ultisnips_idx 19 | ultisnips_idx = 0 20 | UltiSnips_Manager.add_buffer_filetypes('%s.clang_complete' % vim.eval('&filetype')) 21 | 22 | def snippetsFormatPlaceHolder(word): 23 | # Better way to do that? 24 | global ultisnips_idx 25 | ultisnips_idx += 1 26 | return '${%d:%s}' % (ultisnips_idx, word) 27 | 28 | def snippetsAddSnippet(fullname, word, abbr): 29 | global ultisnips_idx 30 | ultisnips_idx = 0 31 | UltiSnips_Manager.add_snippet(fullname, word, fullname, "i", "clang_complete") 32 | return fullname 33 | 34 | def snippetsTrigger(): 35 | print(vim.current.line) 36 | UltiSnips_Manager.expand() 37 | 38 | def snippetsReset(): 39 | if "clang_complete" in UltiSnips_Manager._added_snippets_source._snippets: 40 | UltiSnips_Manager._added_snippets_source._snippets["clang_complete"]._snippets = [] 41 | 42 | # vim: set ts=2 sts=2 sw=2 expandtab : 43 | --------------------------------------------------------------------------------