|
14 | 14 | from clang.cindex import TranslationUnit
|
15 | 15 | from clang.cindex import TypeKind
|
16 | 16 | from clang.cindex import BinaryOperator
|
| 17 | +from clang.cindex import StorageClass |
17 | 18 | from .util import get_cursor
|
18 | 19 | from .util import get_cursors
|
19 | 20 | from .util import get_tu
|
@@ -279,6 +280,90 @@ def test_is_default_method(self):
|
279 | 280 | self.assertTrue(xc.is_default_method())
|
280 | 281 | self.assertFalse(yc.is_default_method())
|
281 | 282 |
|
| 283 | + def test_is_deleted_method(self): |
| 284 | + source = "class X { X() = delete; }; class Y { Y(); };" |
| 285 | + tu = get_tu(source, lang="cpp") |
| 286 | + |
| 287 | + xs = get_cursors(tu, "X") |
| 288 | + ys = get_cursors(tu, "Y") |
| 289 | + |
| 290 | + self.assertEqual(len(xs), 2) |
| 291 | + self.assertEqual(len(ys), 2) |
| 292 | + |
| 293 | + xc = xs[1] |
| 294 | + yc = ys[1] |
| 295 | + |
| 296 | + self.assertTrue(xc.is_deleted_method()) |
| 297 | + self.assertFalse(yc.is_deleted_method()) |
| 298 | + |
| 299 | + def test_is_copy_assignment_operator_method(self): |
| 300 | + source_with_copy_assignment_operators = """ |
| 301 | + struct Foo { |
| 302 | + // Those are copy-assignment operators |
| 303 | + bool operator=(const Foo&); |
| 304 | + bool operator=(Foo&); |
| 305 | + Foo operator=(Foo); |
| 306 | + bool operator=(volatile Foo&); |
| 307 | + bool operator=(const volatile Foo&); |
| 308 | +
|
| 309 | + // Positive-check that the recognition works for templated classes too |
| 310 | + template <typename T> |
| 311 | + class Bar { |
| 312 | + bool operator=(const Bar&); |
| 313 | + Bar operator=(const Bar); |
| 314 | + bool operator=(Bar<T>&); |
| 315 | + bool operator=(volatile Bar&); |
| 316 | + bool operator=(const volatile Bar<T>&); |
| 317 | + }; |
| 318 | + """ |
| 319 | + source_without_copy_assignment_operators = """ |
| 320 | + struct Foo { |
| 321 | + // Those are not copy-assignment operators |
| 322 | + template<typename T> |
| 323 | + bool operator=(const T&); |
| 324 | + bool operator=(const bool&); |
| 325 | + bool operator=(char&); |
| 326 | + bool operator=(volatile unsigned int&); |
| 327 | + bool operator=(const volatile unsigned char&); |
| 328 | + bool operator=(int); |
| 329 | + bool operator=(Foo&&); |
| 330 | + }; |
| 331 | + """ |
| 332 | + tu_with_copy_assignment_operators = get_tu( |
| 333 | + source_with_copy_assignment_operators, lang="cpp" |
| 334 | + ) |
| 335 | + tu_without_copy_assignment_operators = get_tu( |
| 336 | + source_without_copy_assignment_operators, lang="cpp" |
| 337 | + ) |
| 338 | + |
| 339 | + copy_assignment_operators_cursors = get_cursors( |
| 340 | + tu_with_copy_assignment_operators, "operator=" |
| 341 | + ) |
| 342 | + non_copy_assignment_operators_cursors = get_cursors( |
| 343 | + tu_without_copy_assignment_operators, "operator=" |
| 344 | + ) |
| 345 | + |
| 346 | + self.assertEqual(len(copy_assignment_operators_cursors), 10) |
| 347 | + self.assertTrue(len(non_copy_assignment_operators_cursors), 9) |
| 348 | + |
| 349 | + self.assertTrue( |
| 350 | + all( |
| 351 | + [ |
| 352 | + cursor.is_copy_assignment_operator_method() |
| 353 | + for cursor in copy_assignment_operators_cursors |
| 354 | + ] |
| 355 | + ) |
| 356 | + ) |
| 357 | + |
| 358 | + self.assertFalse( |
| 359 | + any( |
| 360 | + [ |
| 361 | + cursor.is_copy_assignment_operator_method() |
| 362 | + for cursor in non_copy_assignment_operators_cursors |
| 363 | + ] |
| 364 | + ) |
| 365 | + ) |
| 366 | + |
282 | 367 | def test_is_move_assignment_operator_method(self):
|
283 | 368 | """Ensure Cursor.is_move_assignment_operator_method works."""
|
284 | 369 | source_with_move_assignment_operators = """
|
@@ -482,6 +567,41 @@ def test_is_scoped_enum(self):
|
482 | 567 | self.assertFalse(regular_enum.is_scoped_enum())
|
483 | 568 | self.assertTrue(scoped_enum.is_scoped_enum())
|
484 | 569 |
|
| 570 | + def test_get_definition(self): |
| 571 | + """Ensure Cursor.get_definition works.""" |
| 572 | + tu = get_tu( |
| 573 | + """ |
| 574 | +class A { |
| 575 | + constexpr static int f(){return 3;} |
| 576 | +}; |
| 577 | +struct B { |
| 578 | + int b = A::f(); |
| 579 | +}; |
| 580 | +""", |
| 581 | + lang="cpp", |
| 582 | + ) |
| 583 | + curs = get_cursors(tu, "f") |
| 584 | + self.assertEqual(len(curs), 4) |
| 585 | + self.assertEqual(curs[0].kind, CursorKind.CXX_METHOD) |
| 586 | + self.assertEqual(curs[1].get_definition(), curs[0]) |
| 587 | + self.assertEqual(curs[2].get_definition(), curs[0]) |
| 588 | + self.assertEqual(curs[3].get_definition(), curs[0]) |
| 589 | + |
| 590 | + def test_get_usr(self): |
| 591 | + """Ensure Cursor.get_usr works.""" |
| 592 | + tu = get_tu( |
| 593 | + """ |
| 594 | +int add(int, int); |
| 595 | +int add(int a, int b) { return a + b; } |
| 596 | +int add(float a, float b) { return a + b; } |
| 597 | +""", |
| 598 | + lang="cpp", |
| 599 | + ) |
| 600 | + curs = get_cursors(tu, "add") |
| 601 | + self.assertEqual(len(curs), 3) |
| 602 | + self.assertEqual(curs[0].get_usr(), curs[1].get_usr()) |
| 603 | + self.assertNotEqual(curs[0].get_usr(), curs[2].get_usr()) |
| 604 | + |
485 | 605 | def test_underlying_type(self):
|
486 | 606 | tu = get_tu("typedef int foo;")
|
487 | 607 | typedef = get_cursor(tu, "foo")
|
@@ -570,6 +690,23 @@ def test_enum_values_cpp(self):
|
570 | 690 | self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)
|
571 | 691 | self.assertEqual(ham.enum_value, 0x10000000000)
|
572 | 692 |
|
| 693 | + def test_enum_values_unsigned(self): |
| 694 | + tu = get_tu("enum TEST : unsigned char { SPAM=0, HAM = 200};", lang="cpp") |
| 695 | + enum = get_cursor(tu, "TEST") |
| 696 | + self.assertIsNotNone(enum) |
| 697 | + |
| 698 | + self.assertEqual(enum.kind, CursorKind.ENUM_DECL) |
| 699 | + |
| 700 | + enum_constants = list(enum.get_children()) |
| 701 | + self.assertEqual(len(enum_constants), 2) |
| 702 | + |
| 703 | + spam, ham = enum_constants |
| 704 | + |
| 705 | + self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL) |
| 706 | + self.assertEqual(spam.enum_value, 0) |
| 707 | + self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL) |
| 708 | + self.assertEqual(ham.enum_value, 200) |
| 709 | + |
573 | 710 | def test_annotation_attribute(self):
|
574 | 711 | tu = get_tu(
|
575 | 712 | 'int foo (void) __attribute__ ((annotate("here be annotation attribute")));'
|
@@ -625,6 +762,25 @@ def test_result_type_objc_method_decl(self):
|
625 | 762 | self.assertEqual(cursor.kind, CursorKind.OBJC_INSTANCE_METHOD_DECL)
|
626 | 763 | self.assertEqual(result_type.kind, TypeKind.VOID)
|
627 | 764 |
|
| 765 | + def test_storage_class(self): |
| 766 | + tu = get_tu( |
| 767 | + """ |
| 768 | +extern int ex; |
| 769 | +register int reg; |
| 770 | +int count(int a, int b){ |
| 771 | + static int counter = 0; |
| 772 | + return 0; |
| 773 | +} |
| 774 | +""", |
| 775 | + lang="cpp", |
| 776 | + ) |
| 777 | + cursor = get_cursor(tu, "ex") |
| 778 | + self.assertEqual(cursor.storage_class, StorageClass.EXTERN) |
| 779 | + cursor = get_cursor(tu, "counter") |
| 780 | + self.assertEqual(cursor.storage_class, StorageClass.STATIC) |
| 781 | + cursor = get_cursor(tu, "reg") |
| 782 | + self.assertEqual(cursor.storage_class, StorageClass.REGISTER) |
| 783 | + |
628 | 784 | def test_availability(self):
|
629 | 785 | tu = get_tu("class A { A(A const&) = delete; };", lang="cpp")
|
630 | 786 |
|
@@ -681,6 +837,23 @@ def test_get_token_cursor(self):
|
681 | 837 | r_cursor = t_cursor.referenced # should not raise an exception
|
682 | 838 | self.assertEqual(r_cursor.kind, CursorKind.CLASS_DECL)
|
683 | 839 |
|
| 840 | + def test_get_field_offsetof(self): |
| 841 | + tu = get_tu( |
| 842 | + "struct myStruct {int a; char b; char c; short d; char e;};", lang="cpp" |
| 843 | + ) |
| 844 | + c1 = get_cursor(tu, "myStruct") |
| 845 | + c2 = get_cursor(tu, "a") |
| 846 | + c3 = get_cursor(tu, "b") |
| 847 | + c4 = get_cursor(tu, "c") |
| 848 | + c5 = get_cursor(tu, "d") |
| 849 | + c6 = get_cursor(tu, "e") |
| 850 | + self.assertEqual(c1.get_field_offsetof(), -1) |
| 851 | + self.assertEqual(c2.get_field_offsetof(), 0) |
| 852 | + self.assertEqual(c3.get_field_offsetof(), 32) |
| 853 | + self.assertEqual(c4.get_field_offsetof(), 40) |
| 854 | + self.assertEqual(c5.get_field_offsetof(), 48) |
| 855 | + self.assertEqual(c6.get_field_offsetof(), 64) |
| 856 | + |
684 | 857 | def test_get_arguments(self):
|
685 | 858 | tu = get_tu("void foo(int i, int j);")
|
686 | 859 | foo = get_cursor(tu, "foo")
|
@@ -799,3 +972,13 @@ def test_binop(self):
|
799 | 972 | for op, typ in operators.items():
|
800 | 973 | c = get_cursor(tu, op)
|
801 | 974 | assert c.binary_operator == typ
|
| 975 | + |
| 976 | + def test_from_result_null(self): |
| 977 | + tu = get_tu("int a = 1+2;", lang="cpp") |
| 978 | + op = next(next(tu.cursor.get_children()).get_children()) |
| 979 | + self.assertEqual(op.kind, CursorKind.BINARY_OPERATOR) |
| 980 | + self.assertEqual(op.get_definition(), None) |
| 981 | + |
| 982 | + def test_from_cursor_result_null(self): |
| 983 | + tu = get_tu("") |
| 984 | + self.assertEqual(tu.cursor.semantic_parent, None) |
0 commit comments