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