diff options
author | Gregory Szorc <gregory.szorc@gmail.com> | 2012-02-20 17:45:30 +0000 |
---|---|---|
committer | Gregory Szorc <gregory.szorc@gmail.com> | 2012-02-20 17:45:30 +0000 |
commit | 826fce53d64e0ca8fdcfdd11f4e9aab6c8be224f (patch) | |
tree | 6fcfdec9178d80cebc6069a2aaf617275939a744 /bindings | |
parent | 7eb691a7b61ba895695bbbf92e944d98ef49390d (diff) |
[clang.py] Implement Type.argument_types()
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150970 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'bindings')
-rw-r--r-- | bindings/python/clang/cindex.py | 48 | ||||
-rw-r--r-- | bindings/python/tests/cindex/test_type.py | 242 |
2 files changed, 183 insertions, 107 deletions
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index e2ef3c3665..1594857023 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -63,6 +63,7 @@ call is efficient. # o implement additional SourceLocation, SourceRange, and File methods. from ctypes import * +import collections def get_cindex_library(): # FIXME: It's probably not the case that the library is actually found in @@ -1137,6 +1138,44 @@ class Type(Structure): """Return the kind of this type.""" return TypeKind.from_id(self._kind_id) + def argument_types(self): + """Retrieve a container for the non-variadic arguments for this type. + + The returned object is iterable and indexable. Each item in the + container is a Type instance. + """ + class ArgumentsIterator(collections.Sequence): + def __init__(self, parent): + self.parent = parent + self.length = None + + def __len__(self): + if self.length is None: + self.length = Type_get_num_arg_types(self.parent) + + return self.length + + def __getitem__(self, key): + # FIXME Support slice objects. + if not isinstance(key, int): + raise TypeError("Must supply a non-negative int.") + + if key < 0: + raise IndexError("Only non-negative indexes are accepted.") + + if key >= len(self): + raise IndexError("Index greater than container length: " + "%d > %d" % ( key, len(self) )) + + result = Type_get_arg_type(self.parent, key) + if result.kind == TypeKind.INVALID: + raise IndexError("Argument could not be retrieved.") + + return result + + assert self.kind == TypeKind.FUNCTIONPROTO + return ArgumentsIterator(self) + @property def element_type(self): """Retrieve the Type of elements within this Type. @@ -1927,7 +1966,16 @@ Type_get_result.argtypes = [Type] Type_get_result.restype = Type Type_get_result.errcheck = Type.from_result +Type_get_num_arg_types = lib.clang_getNumArgTypes +Type_get_num_arg_types.argtypes = [Type] +Type_get_num_arg_types.restype = c_uint + +Type_get_arg_type = lib.clang_getArgType +Type_get_arg_type.argtypes = [Type, c_uint] +Type_get_arg_type.restype = Type +Type_get_arg_type.errcheck = Type.from_result Type_get_element_type = lib.clang_getElementType + Type_get_element_type.argtypes = [Type] Type_get_element_type.restype = Type Type_get_element_type.errcheck = Type.from_result diff --git a/bindings/python/tests/cindex/test_type.py b/bindings/python/tests/cindex/test_type.py index b07ef643bd..86b8142259 100644 --- a/bindings/python/tests/cindex/test_type.py +++ b/bindings/python/tests/cindex/test_type.py @@ -30,63 +30,63 @@ def get_tu(source=kInput, lang='c'): assert tu is not None return tu -def test_a_struct(): - tu = get_tu(kInput) - - for n in tu.cursor.get_children(): - if n.spelling == 'teststruct': - fields = list(n.get_children()) - - assert all(x.kind == CursorKind.FIELD_DECL for x in fields) - - assert fields[0].spelling == 'a' - assert not fields[0].type.is_const_qualified() - assert fields[0].type.kind == TypeKind.INT - assert fields[0].type.get_canonical().kind == TypeKind.INT - - assert fields[1].spelling == 'b' - assert not fields[1].type.is_const_qualified() - assert fields[1].type.kind == TypeKind.TYPEDEF - assert fields[1].type.get_canonical().kind == TypeKind.INT - assert fields[1].type.get_declaration().spelling == 'I' - - assert fields[2].spelling == 'c' - assert not fields[2].type.is_const_qualified() - assert fields[2].type.kind == TypeKind.LONG - assert fields[2].type.get_canonical().kind == TypeKind.LONG - - assert fields[3].spelling == 'd' - assert not fields[3].type.is_const_qualified() - assert fields[3].type.kind == TypeKind.ULONG - assert fields[3].type.get_canonical().kind == TypeKind.ULONG - - assert fields[4].spelling == 'e' - assert not fields[4].type.is_const_qualified() - assert fields[4].type.kind == TypeKind.LONG - assert fields[4].type.get_canonical().kind == TypeKind.LONG - - assert fields[5].spelling == 'f' - assert fields[5].type.is_const_qualified() - assert fields[5].type.kind == TypeKind.INT - assert fields[5].type.get_canonical().kind == TypeKind.INT - - assert fields[6].spelling == 'g' - assert not fields[6].type.is_const_qualified() - assert fields[6].type.kind == TypeKind.POINTER - assert fields[6].type.get_pointee().kind == TypeKind.INT - - assert fields[7].spelling == 'h' - assert not fields[7].type.is_const_qualified() - assert fields[7].type.kind == TypeKind.POINTER - assert fields[7].type.get_pointee().kind == TypeKind.POINTER - assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER - assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT +def get_cursor(tu, spelling): + for cursor in tu.cursor.get_children(): + if cursor.spelling == spelling: + return cursor - break + return None - else: - assert False, "Didn't find teststruct??" +def test_a_struct(): + tu = get_tu(kInput) + teststruct = get_cursor(tu, 'teststruct') + assert teststruct is not None, "Could not find teststruct." + fields = list(teststruct.get_children()) + assert all(x.kind == CursorKind.FIELD_DECL for x in fields) + + assert fields[0].spelling == 'a' + assert not fields[0].type.is_const_qualified() + assert fields[0].type.kind == TypeKind.INT + assert fields[0].type.get_canonical().kind == TypeKind.INT + + assert fields[1].spelling == 'b' + assert not fields[1].type.is_const_qualified() + assert fields[1].type.kind == TypeKind.TYPEDEF + assert fields[1].type.get_canonical().kind == TypeKind.INT + assert fields[1].type.get_declaration().spelling == 'I' + + assert fields[2].spelling == 'c' + assert not fields[2].type.is_const_qualified() + assert fields[2].type.kind == TypeKind.LONG + assert fields[2].type.get_canonical().kind == TypeKind.LONG + + assert fields[3].spelling == 'd' + assert not fields[3].type.is_const_qualified() + assert fields[3].type.kind == TypeKind.ULONG + assert fields[3].type.get_canonical().kind == TypeKind.ULONG + + assert fields[4].spelling == 'e' + assert not fields[4].type.is_const_qualified() + assert fields[4].type.kind == TypeKind.LONG + assert fields[4].type.get_canonical().kind == TypeKind.LONG + + assert fields[5].spelling == 'f' + assert fields[5].type.is_const_qualified() + assert fields[5].type.kind == TypeKind.INT + assert fields[5].type.get_canonical().kind == TypeKind.INT + + assert fields[6].spelling == 'g' + assert not fields[6].type.is_const_qualified() + assert fields[6].type.kind == TypeKind.POINTER + assert fields[6].type.get_pointee().kind == TypeKind.INT + + assert fields[7].spelling == 'h' + assert not fields[7].type.is_const_qualified() + assert fields[7].type.kind == TypeKind.POINTER + assert fields[7].type.get_pointee().kind == TypeKind.POINTER + assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER + assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT constarrayInput=""" struct teststruct { @@ -96,33 +96,23 @@ struct teststruct { def testConstantArray(): tu = get_tu(constarrayInput) - for n in tu.cursor.get_children(): - if n.spelling == 'teststruct': - fields = list(n.get_children()) - assert fields[0].spelling == 'A' - assert fields[0].type.kind == TypeKind.CONSTANTARRAY - assert fields[0].type.get_array_element_type() is not None - assert fields[0].type.get_array_element_type().kind == TypeKind.POINTER - assert fields[0].type.get_array_size() == 2 - - break - else: - assert False, "Didn't find teststruct??" + teststruct = get_cursor(tu, 'teststruct') + assert teststruct is not None, "Didn't find teststruct??" + fields = list(teststruct.get_children()) + assert fields[0].spelling == 'A' + assert fields[0].type.kind == TypeKind.CONSTANTARRAY + assert fields[0].type.get_array_element_type() is not None + assert fields[0].type.get_array_element_type().kind == TypeKind.POINTER + assert fields[0].type.get_array_size() == 2 def test_equal(): """Ensure equivalence operators work on Type.""" source = 'int a; int b; void *v;' tu = get_tu(source) - a, b, v = None, None, None - - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'a': - a = cursor - elif cursor.spelling == 'b': - b = cursor - elif cursor.spelling == 'v': - v = cursor + a = get_cursor(tu, 'a') + b = get_cursor(tu, 'b') + v = get_cursor(tu, 'v') assert a is not None assert b is not None @@ -134,15 +124,72 @@ def test_equal(): assert a.type != None assert a.type != 'foo' +def test_function_argument_types(): + """Ensure that Type.argument_types() works as expected.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + assert f is not None + + args = f.type.argument_types() + assert args is not None + assert len(args) == 2 + + t0 = args[0] + assert t0 is not None + assert t0.kind == TypeKind.INT + + t1 = args[1] + assert t1 is not None + assert t1.kind == TypeKind.INT + + args2 = list(args) + assert len(args2) == 2 + assert t0 == args2[0] + assert t1 == args2[1] + +@raises(TypeError) +def test_argument_types_string_key(): + """Ensure that non-int keys raise a TypeError.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + assert f is not None + + args = f.type.argument_types() + assert len(args) == 2 + + args['foo'] + +@raises(IndexError) +def test_argument_types_negative_index(): + """Ensure that negative indexes on argument_types Raises an IndexError.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + args = f.type.argument_types() + + args[-1] + +@raises(IndexError) +def test_argument_types_overflow_index(): + """Ensure that indexes beyond the length of Type.argument_types() raise.""" + tu = get_tu('void f(int, int);') + f = get_cursor(tu, 'f') + args = f.type.argument_types() + + args[2] + +@raises(Exception) +def test_argument_types_invalid_type(): + """Ensure that obtaining argument_types on a Type without them raises.""" + tu = get_tu('int i;') + i = get_cursor(tu, 'i') + assert i is not None + + i.type.argument_types() + def test_is_pod(): tu = get_tu('int i; void f();') - i, f = None, None - - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'i': - i = cursor - elif cursor.spelling == 'f': - f = cursor + i = get_cursor(tu, 'i') + f = get_cursor(tu, 'f') assert i is not None assert f is not None @@ -161,12 +208,8 @@ void bar(int a, int b); """ tu = get_tu(source) - foo, bar = None, None - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'foo': - foo = cursor - elif cursor.spelling == 'bar': - bar = cursor + foo = get_cursor(tu, 'foo') + bar = get_cursor(tu, 'bar') assert foo is not None assert bar is not None @@ -177,12 +220,7 @@ void bar(int a, int b); def test_element_type(): tu = get_tu('int i[5];') - i = None - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'i': - i = cursor - break - + i = get_cursor(tu, 'i') assert i is not None assert i.type.kind == TypeKind.CONSTANTARRAY @@ -192,24 +230,14 @@ def test_element_type(): def test_invalid_element_type(): """Ensure Type.element_type raises if type doesn't have elements.""" tu = get_tu('int i;') - - i = None - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'i': - i = cursor - break - + i = get_cursor(tu, 'i') assert i is not None i.element_type def test_element_count(): tu = get_tu('int i[5]; int j;') - - for cursor in tu.cursor.get_children(): - if cursor.spelling == 'i': - i = cursor - elif cursor.spelling == 'j': - j = cursor + i = get_cursor(tu, 'i') + j = get_cursor(tu, 'j') assert i is not None assert j is not None |