test_cursor.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. import ctypes
  2. import gc
  3. from clang.cindex import CursorKind
  4. from clang.cindex import TemplateArgumentKind
  5. from clang.cindex import TranslationUnit
  6. from clang.cindex import TypeKind
  7. from .util import get_cursor
  8. from .util import get_cursors
  9. from .util import get_tu
  10. kInput = """\
  11. struct s0 {
  12. int a;
  13. int b;
  14. };
  15. struct s1;
  16. void f0(int a0, int a1) {
  17. int l0, l1;
  18. if (a0)
  19. return;
  20. for (;;) {
  21. break;
  22. }
  23. }
  24. """
  25. def test_get_children():
  26. tu = get_tu(kInput)
  27. it = tu.cursor.get_children()
  28. tu_nodes = list(it)
  29. assert len(tu_nodes) == 3
  30. for cursor in tu_nodes:
  31. assert cursor.translation_unit is not None
  32. assert tu_nodes[0] != tu_nodes[1]
  33. assert tu_nodes[0].kind == CursorKind.STRUCT_DECL
  34. assert tu_nodes[0].spelling == 's0'
  35. assert tu_nodes[0].is_definition() == True
  36. assert tu_nodes[0].location.file.name == 't.c'
  37. assert tu_nodes[0].location.line == 1
  38. assert tu_nodes[0].location.column == 8
  39. assert tu_nodes[0].hash > 0
  40. assert tu_nodes[0].translation_unit is not None
  41. s0_nodes = list(tu_nodes[0].get_children())
  42. assert len(s0_nodes) == 2
  43. assert s0_nodes[0].kind == CursorKind.FIELD_DECL
  44. assert s0_nodes[0].spelling == 'a'
  45. assert s0_nodes[0].type.kind == TypeKind.INT
  46. assert s0_nodes[1].kind == CursorKind.FIELD_DECL
  47. assert s0_nodes[1].spelling == 'b'
  48. assert s0_nodes[1].type.kind == TypeKind.INT
  49. assert tu_nodes[1].kind == CursorKind.STRUCT_DECL
  50. assert tu_nodes[1].spelling == 's1'
  51. assert tu_nodes[1].displayname == 's1'
  52. assert tu_nodes[1].is_definition() == False
  53. assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL
  54. assert tu_nodes[2].spelling == 'f0'
  55. assert tu_nodes[2].displayname == 'f0(int, int)'
  56. assert tu_nodes[2].is_definition() == True
  57. def test_references():
  58. """Ensure that references to TranslationUnit are kept."""
  59. tu = get_tu('int x;')
  60. cursors = list(tu.cursor.get_children())
  61. assert len(cursors) > 0
  62. cursor = cursors[0]
  63. assert isinstance(cursor.translation_unit, TranslationUnit)
  64. # Delete reference to TU and perform a full GC.
  65. del tu
  66. gc.collect()
  67. assert isinstance(cursor.translation_unit, TranslationUnit)
  68. # If the TU was destroyed, this should cause a segfault.
  69. parent = cursor.semantic_parent
  70. def test_canonical():
  71. source = 'struct X; struct X; struct X { int member; };'
  72. tu = get_tu(source)
  73. cursors = []
  74. for cursor in tu.cursor.get_children():
  75. if cursor.spelling == 'X':
  76. cursors.append(cursor)
  77. assert len(cursors) == 3
  78. assert cursors[1].canonical == cursors[2].canonical
  79. def test_is_static_method():
  80. """Ensure Cursor.is_static_method works."""
  81. source = 'class X { static void foo(); void bar(); };'
  82. tu = get_tu(source, lang='cpp')
  83. cls = get_cursor(tu, 'X')
  84. foo = get_cursor(tu, 'foo')
  85. bar = get_cursor(tu, 'bar')
  86. assert cls is not None
  87. assert foo is not None
  88. assert bar is not None
  89. assert foo.is_static_method()
  90. assert not bar.is_static_method()
  91. def test_underlying_type():
  92. tu = get_tu('typedef int foo;')
  93. typedef = get_cursor(tu, 'foo')
  94. assert typedef is not None
  95. assert typedef.kind.is_declaration()
  96. underlying = typedef.underlying_typedef_type
  97. assert underlying.kind == TypeKind.INT
  98. kParentTest = """\
  99. class C {
  100. void f();
  101. }
  102. void C::f() { }
  103. """
  104. def test_semantic_parent():
  105. tu = get_tu(kParentTest, 'cpp')
  106. curs = get_cursors(tu, 'f')
  107. decl = get_cursor(tu, 'C')
  108. assert(len(curs) == 2)
  109. assert(curs[0].semantic_parent == curs[1].semantic_parent)
  110. assert(curs[0].semantic_parent == decl)
  111. def test_lexical_parent():
  112. tu = get_tu(kParentTest, 'cpp')
  113. curs = get_cursors(tu, 'f')
  114. decl = get_cursor(tu, 'C')
  115. assert(len(curs) == 2)
  116. assert(curs[0].lexical_parent != curs[1].lexical_parent)
  117. assert(curs[0].lexical_parent == decl)
  118. assert(curs[1].lexical_parent == tu.cursor)
  119. def test_enum_type():
  120. tu = get_tu('enum TEST { FOO=1, BAR=2 };')
  121. enum = get_cursor(tu, 'TEST')
  122. assert enum is not None
  123. assert enum.kind == CursorKind.ENUM_DECL
  124. enum_type = enum.enum_type
  125. assert enum_type.kind == TypeKind.UINT
  126. def test_enum_type_cpp():
  127. tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp")
  128. enum = get_cursor(tu, 'TEST')
  129. assert enum is not None
  130. assert enum.kind == CursorKind.ENUM_DECL
  131. assert enum.enum_type.kind == TypeKind.LONGLONG
  132. def test_objc_type_encoding():
  133. tu = get_tu('int i;', lang='objc')
  134. i = get_cursor(tu, 'i')
  135. assert i is not None
  136. assert i.objc_type_encoding == 'i'
  137. def test_enum_values():
  138. tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};')
  139. enum = get_cursor(tu, 'TEST')
  140. assert enum is not None
  141. assert enum.kind == CursorKind.ENUM_DECL
  142. enum_constants = list(enum.get_children())
  143. assert len(enum_constants) == 3
  144. spam, egg, ham = enum_constants
  145. assert spam.kind == CursorKind.ENUM_CONSTANT_DECL
  146. assert spam.enum_value == 1
  147. assert egg.kind == CursorKind.ENUM_CONSTANT_DECL
  148. assert egg.enum_value == 2
  149. assert ham.kind == CursorKind.ENUM_CONSTANT_DECL
  150. assert ham.enum_value == 40
  151. def test_enum_values_cpp():
  152. tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp")
  153. enum = get_cursor(tu, 'TEST')
  154. assert enum is not None
  155. assert enum.kind == CursorKind.ENUM_DECL
  156. enum_constants = list(enum.get_children())
  157. assert len(enum_constants) == 2
  158. spam, ham = enum_constants
  159. assert spam.kind == CursorKind.ENUM_CONSTANT_DECL
  160. assert spam.enum_value == -1
  161. assert ham.kind == CursorKind.ENUM_CONSTANT_DECL
  162. assert ham.enum_value == 0x10000000000
  163. def test_annotation_attribute():
  164. tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));')
  165. foo = get_cursor(tu, 'foo')
  166. assert foo is not None
  167. for c in foo.get_children():
  168. if c.kind == CursorKind.ANNOTATE_ATTR:
  169. assert c.displayname == "here be annotation attribute"
  170. break
  171. else:
  172. assert False, "Couldn't find annotation"
  173. def test_result_type():
  174. tu = get_tu('int foo();')
  175. foo = get_cursor(tu, 'foo')
  176. assert foo is not None
  177. t = foo.result_type
  178. assert t.kind == TypeKind.INT
  179. def test_get_tokens():
  180. """Ensure we can map cursors back to tokens."""
  181. tu = get_tu('int foo(int i);')
  182. foo = get_cursor(tu, 'foo')
  183. tokens = list(foo.get_tokens())
  184. assert len(tokens) == 7
  185. assert tokens[0].spelling == 'int'
  186. assert tokens[1].spelling == 'foo'
  187. def test_get_arguments():
  188. tu = get_tu('void foo(int i, int j);')
  189. foo = get_cursor(tu, 'foo')
  190. arguments = list(foo.get_arguments())
  191. assert len(arguments) == 2
  192. assert arguments[0].spelling == "i"
  193. assert arguments[1].spelling == "j"
  194. kTemplateArgTest = """\
  195. template <int kInt, typename T, bool kBool>
  196. void foo();
  197. template<>
  198. void foo<-7, float, true>();
  199. """
  200. def test_get_num_template_arguments():
  201. tu = get_tu(kTemplateArgTest, lang='cpp')
  202. foos = get_cursors(tu, 'foo')
  203. assert foos[1].get_num_template_arguments() == 3
  204. def test_get_template_argument_kind():
  205. tu = get_tu(kTemplateArgTest, lang='cpp')
  206. foos = get_cursors(tu, 'foo')
  207. assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL
  208. assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE
  209. assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL
  210. def test_get_template_argument_type():
  211. tu = get_tu(kTemplateArgTest, lang='cpp')
  212. foos = get_cursors(tu, 'foo')
  213. assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT
  214. def test_get_template_argument_value():
  215. tu = get_tu(kTemplateArgTest, lang='cpp')
  216. foos = get_cursors(tu, 'foo')
  217. assert foos[1].get_template_argument_value(0) == -7
  218. assert foos[1].get_template_argument_value(2) == True
  219. def test_get_template_argument_unsigned_value():
  220. tu = get_tu(kTemplateArgTest, lang='cpp')
  221. foos = get_cursors(tu, 'foo')
  222. assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7
  223. assert foos[1].get_template_argument_unsigned_value(2) == True
  224. def test_referenced():
  225. tu = get_tu('void foo(); void bar() { foo(); }')
  226. foo = get_cursor(tu, 'foo')
  227. bar = get_cursor(tu, 'bar')
  228. for c in bar.get_children():
  229. if c.kind == CursorKind.CALL_EXPR:
  230. assert c.referenced.spelling == foo.spelling
  231. break
  232. def test_mangled_name():
  233. kInputForMangling = """\
  234. int foo(int, int);
  235. """
  236. tu = get_tu(kInputForMangling, lang='cpp')
  237. foo = get_cursor(tu, 'foo')
  238. # Since libclang does not link in targets, we cannot pass a triple to it
  239. # and force the target. To enable this test to pass on all platforms, accept
  240. # all valid manglings.
  241. # [c-index-test handles this by running the source through clang, emitting
  242. # an AST file and running libclang on that AST file]
  243. assert foo.mangled_name in ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH')