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