]> granicus.if.org Git - clang/commitdiff
[clang.py] Implement Type.argument_types()
authorGregory Szorc <gregory.szorc@gmail.com>
Mon, 20 Feb 2012 17:45:30 +0000 (17:45 +0000)
committerGregory Szorc <gregory.szorc@gmail.com>
Mon, 20 Feb 2012 17:45:30 +0000 (17:45 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150970 91177308-0d34-0410-b5e6-96231b3b80d8

bindings/python/clang/cindex.py
bindings/python/tests/cindex/test_type.py

index e2ef3c366542dfd4b5f9874efc6aec92c52dc7bb..15948570239230668bac05299b5ecafb4cc48e30 100644 (file)
@@ -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
index b07ef643bdc703a17d279994c8e3305d52bf45d9..86b81422590c09926d2685f9fbe6abc2d73ff192 100644 (file)
@@ -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