[cfe-commits] r150970 - in /cfe/trunk/bindings/python: clang/cindex.py tests/cindex/test_type.py

Gregory Szorc gregory.szorc at gmail.com
Mon Feb 20 09:45:30 PST 2012


Author: gps
Date: Mon Feb 20 11:45:30 2012
New Revision: 150970

URL: http://llvm.org/viewvc/llvm-project?rev=150970&view=rev
Log:
[clang.py] Implement Type.argument_types()

Modified:
    cfe/trunk/bindings/python/clang/cindex.py
    cfe/trunk/bindings/python/tests/cindex/test_type.py

Modified: cfe/trunk/bindings/python/clang/cindex.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/clang/cindex.py?rev=150970&r1=150969&r2=150970&view=diff
==============================================================================
--- cfe/trunk/bindings/python/clang/cindex.py (original)
+++ cfe/trunk/bindings/python/clang/cindex.py Mon Feb 20 11:45:30 2012
@@ -63,6 +63,7 @@
 # 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 @@
         """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.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

Modified: cfe/trunk/bindings/python/tests/cindex/test_type.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/tests/cindex/test_type.py?rev=150970&r1=150969&r2=150970&view=diff
==============================================================================
--- cfe/trunk/bindings/python/tests/cindex/test_type.py (original)
+++ cfe/trunk/bindings/python/tests/cindex/test_type.py Mon Feb 20 11:45:30 2012
@@ -30,63 +30,63 @@
     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 @@
 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 @@
     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]
+
+ at 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']
+
+ at 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]
+
+ at 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]
+
+ at 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 @@
 """
 
     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 @@
 
 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_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





More information about the cfe-commits mailing list