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