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_static_method(): 101 """Ensure Cursor.is_static_method works.""" 102 103 source = 'class X { static void foo(); void bar(); };' 104 tu = get_tu(source, lang='cpp') 105 106 cls = get_cursor(tu, 'X') 107 foo = get_cursor(tu, 'foo') 108 bar = get_cursor(tu, 'bar') 109 assert cls is not None 110 assert foo is not None 111 assert bar is not None 112 113 assert foo.is_static_method() 114 assert not bar.is_static_method() 115 116def test_underlying_type(): 117 tu = get_tu('typedef int foo;') 118 typedef = get_cursor(tu, 'foo') 119 assert typedef is not None 120 121 assert typedef.kind.is_declaration() 122 underlying = typedef.underlying_typedef_type 123 assert underlying.kind == TypeKind.INT 124 125kParentTest = """\ 126 class C { 127 void f(); 128 } 129 130 void C::f() { } 131 """ 132def test_semantic_parent(): 133 tu = get_tu(kParentTest, 'cpp') 134 curs = get_cursors(tu, 'f') 135 decl = get_cursor(tu, 'C') 136 assert(len(curs) == 2) 137 assert(curs[0].semantic_parent == curs[1].semantic_parent) 138 assert(curs[0].semantic_parent == decl) 139 140def test_lexical_parent(): 141 tu = get_tu(kParentTest, 'cpp') 142 curs = get_cursors(tu, 'f') 143 decl = get_cursor(tu, 'C') 144 assert(len(curs) == 2) 145 assert(curs[0].lexical_parent != curs[1].lexical_parent) 146 assert(curs[0].lexical_parent == decl) 147 assert(curs[1].lexical_parent == tu.cursor) 148 149def test_enum_type(): 150 tu = get_tu('enum TEST { FOO=1, BAR=2 };') 151 enum = get_cursor(tu, 'TEST') 152 assert enum is not None 153 154 assert enum.kind == CursorKind.ENUM_DECL 155 enum_type = enum.enum_type 156 assert enum_type.kind == TypeKind.UINT 157 158def test_enum_type_cpp(): 159 tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") 160 enum = get_cursor(tu, 'TEST') 161 assert enum is not None 162 163 assert enum.kind == CursorKind.ENUM_DECL 164 assert enum.enum_type.kind == TypeKind.LONGLONG 165 166def test_objc_type_encoding(): 167 tu = get_tu('int i;', lang='objc') 168 i = get_cursor(tu, 'i') 169 170 assert i is not None 171 assert i.objc_type_encoding == 'i' 172 173def test_enum_values(): 174 tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') 175 enum = get_cursor(tu, 'TEST') 176 assert enum is not None 177 178 assert enum.kind == CursorKind.ENUM_DECL 179 180 enum_constants = list(enum.get_children()) 181 assert len(enum_constants) == 3 182 183 spam, egg, ham = enum_constants 184 185 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 186 assert spam.enum_value == 1 187 assert egg.kind == CursorKind.ENUM_CONSTANT_DECL 188 assert egg.enum_value == 2 189 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 190 assert ham.enum_value == 40 191 192def test_enum_values_cpp(): 193 tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") 194 enum = get_cursor(tu, 'TEST') 195 assert enum is not None 196 197 assert enum.kind == CursorKind.ENUM_DECL 198 199 enum_constants = list(enum.get_children()) 200 assert len(enum_constants) == 2 201 202 spam, ham = enum_constants 203 204 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 205 assert spam.enum_value == -1 206 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 207 assert ham.enum_value == 0x10000000000 208 209def test_annotation_attribute(): 210 tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') 211 212 foo = get_cursor(tu, 'foo') 213 assert foo is not None 214 215 for c in foo.get_children(): 216 if c.kind == CursorKind.ANNOTATE_ATTR: 217 assert c.displayname == "here be annotation attribute" 218 break 219 else: 220 assert False, "Couldn't find annotation" 221 222def test_result_type(): 223 tu = get_tu('int foo();') 224 foo = get_cursor(tu, 'foo') 225 226 assert foo is not None 227 t = foo.result_type 228 assert t.kind == TypeKind.INT 229 230def test_get_tokens(): 231 """Ensure we can map cursors back to tokens.""" 232 tu = get_tu('int foo(int i);') 233 foo = get_cursor(tu, 'foo') 234 235 tokens = list(foo.get_tokens()) 236 assert len(tokens) == 7 237 assert tokens[0].spelling == 'int' 238 assert tokens[1].spelling == 'foo' 239 240def test_get_arguments(): 241 tu = get_tu('void foo(int i, int j);') 242 foo = get_cursor(tu, 'foo') 243 arguments = list(foo.get_arguments()) 244 245 assert len(arguments) == 2 246 assert arguments[0].spelling == "i" 247 assert arguments[1].spelling == "j" 248 249kTemplateArgTest = """\ 250 template <int kInt, typename T, bool kBool> 251 void foo(); 252 253 template<> 254 void foo<-7, float, true>(); 255 """ 256 257def test_get_num_template_arguments(): 258 tu = get_tu(kTemplateArgTest, lang='cpp') 259 foos = get_cursors(tu, 'foo') 260 261 assert foos[1].get_num_template_arguments() == 3 262 263def test_get_template_argument_kind(): 264 tu = get_tu(kTemplateArgTest, lang='cpp') 265 foos = get_cursors(tu, 'foo') 266 267 assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL 268 assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE 269 assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL 270 271def test_get_template_argument_type(): 272 tu = get_tu(kTemplateArgTest, lang='cpp') 273 foos = get_cursors(tu, 'foo') 274 275 assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT 276 277def test_get_template_argument_value(): 278 tu = get_tu(kTemplateArgTest, lang='cpp') 279 foos = get_cursors(tu, 'foo') 280 281 assert foos[1].get_template_argument_value(0) == -7 282 assert foos[1].get_template_argument_value(2) == True 283 284def test_get_template_argument_unsigned_value(): 285 tu = get_tu(kTemplateArgTest, lang='cpp') 286 foos = get_cursors(tu, 'foo') 287 288 assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7 289 assert foos[1].get_template_argument_unsigned_value(2) == True 290 291def test_referenced(): 292 tu = get_tu('void foo(); void bar() { foo(); }') 293 foo = get_cursor(tu, 'foo') 294 bar = get_cursor(tu, 'bar') 295 for c in bar.get_children(): 296 if c.kind == CursorKind.CALL_EXPR: 297 assert c.referenced.spelling == foo.spelling 298 break 299 300def test_mangled_name(): 301 kInputForMangling = """\ 302 int foo(int, int); 303 """ 304 tu = get_tu(kInputForMangling, lang='cpp') 305 foo = get_cursor(tu, 'foo') 306 307 # Since libclang does not link in targets, we cannot pass a triple to it 308 # and force the target. To enable this test to pass on all platforms, accept 309 # all valid manglings. 310 # [c-index-test handles this by running the source through clang, emitting 311 # an AST file and running libclang on that AST file] 312 assert foo.mangled_name in ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH') 313