1import ctypes 2import gc 3 4from clang.cindex import AvailabilityKind 5from clang.cindex import CursorKind 6from clang.cindex import TemplateArgumentKind 7from clang.cindex import TranslationUnit 8from clang.cindex import TypeKind 9from .util import get_cursor 10from .util import get_cursors 11from .util import get_tu 12 13kInput = """\ 14struct s0 { 15 int a; 16 int b; 17}; 18 19struct s1; 20 21void f0(int a0, int a1) { 22 int l0, l1; 23 24 if (a0) 25 return; 26 27 for (;;) { 28 break; 29 } 30} 31""" 32 33def test_get_children(): 34 tu = get_tu(kInput) 35 36 it = tu.cursor.get_children() 37 tu_nodes = list(it) 38 39 assert len(tu_nodes) == 3 40 for cursor in tu_nodes: 41 assert cursor.translation_unit is not None 42 43 assert tu_nodes[0] != tu_nodes[1] 44 assert tu_nodes[0].kind == CursorKind.STRUCT_DECL 45 assert tu_nodes[0].spelling == 's0' 46 assert tu_nodes[0].is_definition() == True 47 assert tu_nodes[0].location.file.name == 't.c' 48 assert tu_nodes[0].location.line == 1 49 assert tu_nodes[0].location.column == 8 50 assert tu_nodes[0].hash > 0 51 assert tu_nodes[0].translation_unit is not None 52 53 s0_nodes = list(tu_nodes[0].get_children()) 54 assert len(s0_nodes) == 2 55 assert s0_nodes[0].kind == CursorKind.FIELD_DECL 56 assert s0_nodes[0].spelling == 'a' 57 assert s0_nodes[0].type.kind == TypeKind.INT 58 assert s0_nodes[1].kind == CursorKind.FIELD_DECL 59 assert s0_nodes[1].spelling == 'b' 60 assert s0_nodes[1].type.kind == TypeKind.INT 61 62 assert tu_nodes[1].kind == CursorKind.STRUCT_DECL 63 assert tu_nodes[1].spelling == 's1' 64 assert tu_nodes[1].displayname == 's1' 65 assert tu_nodes[1].is_definition() == False 66 67 assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL 68 assert tu_nodes[2].spelling == 'f0' 69 assert tu_nodes[2].displayname == 'f0(int, int)' 70 assert tu_nodes[2].is_definition() == True 71 72def test_references(): 73 """Ensure that references to TranslationUnit are kept.""" 74 tu = get_tu('int x;') 75 cursors = list(tu.cursor.get_children()) 76 assert len(cursors) > 0 77 78 cursor = cursors[0] 79 assert isinstance(cursor.translation_unit, TranslationUnit) 80 81 # Delete reference to TU and perform a full GC. 82 del tu 83 gc.collect() 84 assert isinstance(cursor.translation_unit, TranslationUnit) 85 86 # If the TU was destroyed, this should cause a segfault. 87 parent = cursor.semantic_parent 88 89def test_canonical(): 90 source = 'struct X; struct X; struct X { int member; };' 91 tu = get_tu(source) 92 93 cursors = [] 94 for cursor in tu.cursor.get_children(): 95 if cursor.spelling == 'X': 96 cursors.append(cursor) 97 98 assert len(cursors) == 3 99 assert cursors[1].canonical == cursors[2].canonical 100 101def test_is_const_method(): 102 """Ensure Cursor.is_const_method works.""" 103 source = 'class X { void foo() const; void bar(); };' 104 tu = get_tu(source, lang='cpp') 105 106 cls = get_cursor(tu, 'X') 107 foo = get_cursor(tu, 'foo') 108 bar = get_cursor(tu, 'bar') 109 assert cls is not None 110 assert foo is not None 111 assert bar is not None 112 113 assert foo.is_const_method() 114 assert not bar.is_const_method() 115 116def test_is_converting_constructor(): 117 """Ensure Cursor.is_converting_constructor works.""" 118 source = 'class X { explicit X(int); X(double); X(); };' 119 tu = get_tu(source, lang='cpp') 120 121 xs = get_cursors(tu, 'X') 122 123 assert len(xs) == 4 124 assert xs[0].kind == CursorKind.CLASS_DECL 125 cs = xs[1:] 126 assert cs[0].kind == CursorKind.CONSTRUCTOR 127 assert cs[1].kind == CursorKind.CONSTRUCTOR 128 assert cs[2].kind == CursorKind.CONSTRUCTOR 129 130 assert not cs[0].is_converting_constructor() 131 assert cs[1].is_converting_constructor() 132 assert not cs[2].is_converting_constructor() 133 134 135def test_is_copy_constructor(): 136 """Ensure Cursor.is_copy_constructor works.""" 137 source = 'class X { X(); X(const X&); X(X&&); };' 138 tu = get_tu(source, lang='cpp') 139 140 xs = get_cursors(tu, 'X') 141 assert xs[0].kind == CursorKind.CLASS_DECL 142 cs = xs[1:] 143 assert cs[0].kind == CursorKind.CONSTRUCTOR 144 assert cs[1].kind == CursorKind.CONSTRUCTOR 145 assert cs[2].kind == CursorKind.CONSTRUCTOR 146 147 assert not cs[0].is_copy_constructor() 148 assert cs[1].is_copy_constructor() 149 assert not cs[2].is_copy_constructor() 150 151def test_is_default_constructor(): 152 """Ensure Cursor.is_default_constructor works.""" 153 source = 'class X { X(); X(int); };' 154 tu = get_tu(source, lang='cpp') 155 156 xs = get_cursors(tu, 'X') 157 assert xs[0].kind == CursorKind.CLASS_DECL 158 cs = xs[1:] 159 assert cs[0].kind == CursorKind.CONSTRUCTOR 160 assert cs[1].kind == CursorKind.CONSTRUCTOR 161 162 assert cs[0].is_default_constructor() 163 assert not cs[1].is_default_constructor() 164 165def test_is_move_constructor(): 166 """Ensure Cursor.is_move_constructor works.""" 167 source = 'class X { X(); X(const X&); X(X&&); };' 168 tu = get_tu(source, lang='cpp') 169 170 xs = get_cursors(tu, 'X') 171 assert xs[0].kind == CursorKind.CLASS_DECL 172 cs = xs[1:] 173 assert cs[0].kind == CursorKind.CONSTRUCTOR 174 assert cs[1].kind == CursorKind.CONSTRUCTOR 175 assert cs[2].kind == CursorKind.CONSTRUCTOR 176 177 assert not cs[0].is_move_constructor() 178 assert not cs[1].is_move_constructor() 179 assert cs[2].is_move_constructor() 180 181def test_is_default_method(): 182 """Ensure Cursor.is_default_method works.""" 183 source = 'class X { X() = default; }; class Y { Y(); };' 184 tu = get_tu(source, lang='cpp') 185 186 xs = get_cursors(tu, 'X') 187 ys = get_cursors(tu, 'Y') 188 189 assert len(xs) == 2 190 assert len(ys) == 2 191 192 xc = xs[1] 193 yc = ys[1] 194 195 assert xc.is_default_method() 196 assert not yc.is_default_method() 197 198def test_is_mutable_field(): 199 """Ensure Cursor.is_mutable_field works.""" 200 source = 'class X { int x_; mutable int y_; };' 201 tu = get_tu(source, lang='cpp') 202 203 cls = get_cursor(tu, 'X') 204 x_ = get_cursor(tu, 'x_') 205 y_ = get_cursor(tu, 'y_') 206 assert cls is not None 207 assert x_ is not None 208 assert y_ is not None 209 210 assert not x_.is_mutable_field() 211 assert y_.is_mutable_field() 212 213def test_is_static_method(): 214 """Ensure Cursor.is_static_method works.""" 215 216 source = 'class X { static void foo(); void bar(); };' 217 tu = get_tu(source, lang='cpp') 218 219 cls = get_cursor(tu, 'X') 220 foo = get_cursor(tu, 'foo') 221 bar = get_cursor(tu, 'bar') 222 assert cls is not None 223 assert foo is not None 224 assert bar is not None 225 226 assert foo.is_static_method() 227 assert not bar.is_static_method() 228 229def test_is_pure_virtual_method(): 230 """Ensure Cursor.is_pure_virtual_method works.""" 231 source = 'class X { virtual void foo() = 0; virtual void bar(); };' 232 tu = get_tu(source, lang='cpp') 233 234 cls = get_cursor(tu, 'X') 235 foo = get_cursor(tu, 'foo') 236 bar = get_cursor(tu, 'bar') 237 assert cls is not None 238 assert foo is not None 239 assert bar is not None 240 241 assert foo.is_pure_virtual_method() 242 assert not bar.is_pure_virtual_method() 243 244def test_is_virtual_method(): 245 """Ensure Cursor.is_virtual_method works.""" 246 source = 'class X { virtual void foo(); void bar(); };' 247 tu = get_tu(source, lang='cpp') 248 249 cls = get_cursor(tu, 'X') 250 foo = get_cursor(tu, 'foo') 251 bar = get_cursor(tu, 'bar') 252 assert cls is not None 253 assert foo is not None 254 assert bar is not None 255 256 assert foo.is_virtual_method() 257 assert not bar.is_virtual_method() 258 259def test_is_scoped_enum(): 260 """Ensure Cursor.is_scoped_enum works.""" 261 source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};' 262 tu = get_tu(source, lang='cpp') 263 264 cls = get_cursor(tu, 'X') 265 regular_enum = get_cursor(tu, 'RegularEnum') 266 scoped_enum = get_cursor(tu, 'ScopedEnum') 267 assert cls is not None 268 assert regular_enum is not None 269 assert scoped_enum is not None 270 271 assert not cls.is_scoped_enum() 272 assert not regular_enum.is_scoped_enum() 273 assert scoped_enum.is_scoped_enum() 274 275def test_underlying_type(): 276 tu = get_tu('typedef int foo;') 277 typedef = get_cursor(tu, 'foo') 278 assert typedef is not None 279 280 assert typedef.kind.is_declaration() 281 underlying = typedef.underlying_typedef_type 282 assert underlying.kind == TypeKind.INT 283 284kParentTest = """\ 285 class C { 286 void f(); 287 } 288 289 void C::f() { } 290 """ 291def test_semantic_parent(): 292 tu = get_tu(kParentTest, 'cpp') 293 curs = get_cursors(tu, 'f') 294 decl = get_cursor(tu, 'C') 295 assert(len(curs) == 2) 296 assert(curs[0].semantic_parent == curs[1].semantic_parent) 297 assert(curs[0].semantic_parent == decl) 298 299def test_lexical_parent(): 300 tu = get_tu(kParentTest, 'cpp') 301 curs = get_cursors(tu, 'f') 302 decl = get_cursor(tu, 'C') 303 assert(len(curs) == 2) 304 assert(curs[0].lexical_parent != curs[1].lexical_parent) 305 assert(curs[0].lexical_parent == decl) 306 assert(curs[1].lexical_parent == tu.cursor) 307 308def test_enum_type(): 309 tu = get_tu('enum TEST { FOO=1, BAR=2 };') 310 enum = get_cursor(tu, 'TEST') 311 assert enum is not None 312 313 assert enum.kind == CursorKind.ENUM_DECL 314 enum_type = enum.enum_type 315 assert enum_type.kind == TypeKind.UINT 316 317def test_enum_type_cpp(): 318 tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") 319 enum = get_cursor(tu, 'TEST') 320 assert enum is not None 321 322 assert enum.kind == CursorKind.ENUM_DECL 323 assert enum.enum_type.kind == TypeKind.LONGLONG 324 325def test_objc_type_encoding(): 326 tu = get_tu('int i;', lang='objc') 327 i = get_cursor(tu, 'i') 328 329 assert i is not None 330 assert i.objc_type_encoding == 'i' 331 332def test_enum_values(): 333 tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') 334 enum = get_cursor(tu, 'TEST') 335 assert enum is not None 336 337 assert enum.kind == CursorKind.ENUM_DECL 338 339 enum_constants = list(enum.get_children()) 340 assert len(enum_constants) == 3 341 342 spam, egg, ham = enum_constants 343 344 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 345 assert spam.enum_value == 1 346 assert egg.kind == CursorKind.ENUM_CONSTANT_DECL 347 assert egg.enum_value == 2 348 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 349 assert ham.enum_value == 40 350 351def test_enum_values_cpp(): 352 tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") 353 enum = get_cursor(tu, 'TEST') 354 assert enum is not None 355 356 assert enum.kind == CursorKind.ENUM_DECL 357 358 enum_constants = list(enum.get_children()) 359 assert len(enum_constants) == 2 360 361 spam, ham = enum_constants 362 363 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 364 assert spam.enum_value == -1 365 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 366 assert ham.enum_value == 0x10000000000 367 368def test_annotation_attribute(): 369 tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') 370 371 foo = get_cursor(tu, 'foo') 372 assert foo is not None 373 374 for c in foo.get_children(): 375 if c.kind == CursorKind.ANNOTATE_ATTR: 376 assert c.displayname == "here be annotation attribute" 377 break 378 else: 379 assert False, "Couldn't find annotation" 380 381def test_annotation_template(): 382 annotation = '__attribute__ ((annotate("annotation")))' 383 for source, kind in [ 384 ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE), 385 ('class %s foo {};', CursorKind.CLASS_TEMPLATE), 386 ]: 387 source = 'template<typename T> ' + (source % annotation) 388 tu = get_tu(source, lang="cpp") 389 390 foo = get_cursor(tu, 'foo') 391 assert foo is not None 392 assert foo.kind == kind 393 394 for c in foo.get_children(): 395 if c.kind == CursorKind.ANNOTATE_ATTR: 396 assert c.displayname == "annotation" 397 break 398 else: 399 assert False, "Couldn't find annotation for {}".format(kind) 400 401def test_result_type(): 402 tu = get_tu('int foo();') 403 foo = get_cursor(tu, 'foo') 404 405 assert foo is not None 406 t = foo.result_type 407 assert t.kind == TypeKind.INT 408 409def test_availability(): 410 tu = get_tu('class A { A(A const&) = delete; };', lang='cpp') 411 412 # AvailabilityKind.AVAILABLE 413 cursor = get_cursor(tu, 'A') 414 assert cursor.kind == CursorKind.CLASS_DECL 415 assert cursor.availability == AvailabilityKind.AVAILABLE 416 417 # AvailabilityKind.NOT_AVAILABLE 418 cursors = get_cursors(tu, 'A') 419 for c in cursors: 420 if c.kind == CursorKind.CONSTRUCTOR: 421 assert c.availability == AvailabilityKind.NOT_AVAILABLE 422 break 423 else: 424 assert False, "Could not find cursor for deleted constructor" 425 426 # AvailabilityKind.DEPRECATED 427 tu = get_tu('void test() __attribute__((deprecated));', lang='cpp') 428 cursor = get_cursor(tu, 'test') 429 assert cursor.availability == AvailabilityKind.DEPRECATED 430 431 # AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results 432 433def test_get_tokens(): 434 """Ensure we can map cursors back to tokens.""" 435 tu = get_tu('int foo(int i);') 436 foo = get_cursor(tu, 'foo') 437 438 tokens = list(foo.get_tokens()) 439 assert len(tokens) == 6 440 assert tokens[0].spelling == 'int' 441 assert tokens[1].spelling == 'foo' 442 443def test_get_token_cursor(): 444 """Ensure we can map tokens to cursors.""" 445 tu = get_tu('class A {}; int foo(A var = A());', lang='cpp') 446 foo = get_cursor(tu, 'foo') 447 448 for cursor in foo.walk_preorder(): 449 if cursor.kind.is_expression() and not cursor.kind.is_statement(): 450 break 451 else: 452 assert False, "Could not find default value expression" 453 454 tokens = list(cursor.get_tokens()) 455 assert len(tokens) == 4, [t.spelling for t in tokens] 456 assert tokens[0].spelling == '=' 457 assert tokens[1].spelling == 'A' 458 assert tokens[2].spelling == '(' 459 assert tokens[3].spelling == ')' 460 t_cursor = tokens[1].cursor 461 assert t_cursor.kind == CursorKind.TYPE_REF 462 r_cursor = t_cursor.referenced # should not raise an exception 463 assert r_cursor.kind == CursorKind.CLASS_DECL 464 465def test_get_arguments(): 466 tu = get_tu('void foo(int i, int j);') 467 foo = get_cursor(tu, 'foo') 468 arguments = list(foo.get_arguments()) 469 470 assert len(arguments) == 2 471 assert arguments[0].spelling == "i" 472 assert arguments[1].spelling == "j" 473 474kTemplateArgTest = """\ 475 template <int kInt, typename T, bool kBool> 476 void foo(); 477 478 template<> 479 void foo<-7, float, true>(); 480 """ 481 482def test_get_num_template_arguments(): 483 tu = get_tu(kTemplateArgTest, lang='cpp') 484 foos = get_cursors(tu, 'foo') 485 486 assert foos[1].get_num_template_arguments() == 3 487 488def test_get_template_argument_kind(): 489 tu = get_tu(kTemplateArgTest, lang='cpp') 490 foos = get_cursors(tu, 'foo') 491 492 assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL 493 assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE 494 assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL 495 496def test_get_template_argument_type(): 497 tu = get_tu(kTemplateArgTest, lang='cpp') 498 foos = get_cursors(tu, 'foo') 499 500 assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT 501 502def test_get_template_argument_value(): 503 tu = get_tu(kTemplateArgTest, lang='cpp') 504 foos = get_cursors(tu, 'foo') 505 506 assert foos[1].get_template_argument_value(0) == -7 507 assert foos[1].get_template_argument_value(2) == True 508 509def test_get_template_argument_unsigned_value(): 510 tu = get_tu(kTemplateArgTest, lang='cpp') 511 foos = get_cursors(tu, 'foo') 512 513 assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7 514 assert foos[1].get_template_argument_unsigned_value(2) == True 515 516def test_referenced(): 517 tu = get_tu('void foo(); void bar() { foo(); }') 518 foo = get_cursor(tu, 'foo') 519 bar = get_cursor(tu, 'bar') 520 for c in bar.get_children(): 521 if c.kind == CursorKind.CALL_EXPR: 522 assert c.referenced.spelling == foo.spelling 523 break 524 525def test_mangled_name(): 526 kInputForMangling = """\ 527 int foo(int, int); 528 """ 529 tu = get_tu(kInputForMangling, lang='cpp') 530 foo = get_cursor(tu, 'foo') 531 532 # Since libclang does not link in targets, we cannot pass a triple to it 533 # and force the target. To enable this test to pass on all platforms, accept 534 # all valid manglings. 535 # [c-index-test handles this by running the source through clang, emitting 536 # an AST file and running libclang on that AST file] 537 assert foo.mangled_name in ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH') 538