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