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