jbcoe updated this revision to Diff 47747.
jbcoe added a comment.

Add missing test for types - apologies for noise.


http://reviews.llvm.org/D15654

Files:
  bindings/python/clang/cppmodel.py
  bindings/python/tests/cppmodel/__init__.py
  bindings/python/tests/cppmodel/test_classes.py
  bindings/python/tests/cppmodel/test_free_functions.py
  bindings/python/tests/cppmodel/test_types.py

Index: bindings/python/tests/cppmodel/test_types.py
===================================================================
--- /dev/null
+++ bindings/python/tests/cppmodel/test_types.py
@@ -0,0 +1,81 @@
+from ..cindex.util import get_tu
+from clang import cppmodel
+from clang.cindex import TypeKind
+
+def test_pointer_type():
+    source = "double* pd();"
+
+    tu = get_tu(source, 'cpp')
+    model = cppmodel.Model(tu)
+    f = model.functions[0]
+
+    assert f.return_type.kind == TypeKind.POINTER
+    assert not f.return_type.is_const
+    assert f.return_type.pointee.kind == TypeKind.DOUBLE
+    assert not f.return_type.pointee.is_const
+
+
+def test_const_pointer_to_double_type():
+    source = "double* const cpd();"
+
+    tu = get_tu(source, 'cpp')
+    model = cppmodel.Model(tu)
+    f = model.functions[0]
+
+    assert f.return_type.kind == TypeKind.POINTER
+    assert f.return_type.is_const
+    assert f.return_type.pointee.kind == TypeKind.DOUBLE
+    assert not f.return_type.pointee.is_const
+
+
+def test_const_pointer_to_const_double_type():
+    source = "const double* const cpcd();"
+
+    tu = get_tu(source, 'cpp')
+    model = cppmodel.Model(tu)
+    functions = model.functions
+    f = model.functions[0]
+
+    assert f.return_type.kind == TypeKind.POINTER
+    assert f.return_type.is_const
+    assert f.return_type.pointee.kind == TypeKind.DOUBLE
+    assert f.return_type.pointee.is_const
+
+
+def test_pointer_to_pointer_type():
+    source = "double** ppd();"
+
+    tu = get_tu(source, 'cpp')
+    model = cppmodel.Model(tu)
+    f = model.functions[0]
+
+    assert f.return_type.kind == TypeKind.POINTER
+    assert f.return_type.is_pointer
+    assert f.return_type.pointee.kind == TypeKind.POINTER
+    assert f.return_type.pointee.is_pointer
+    assert f.return_type.pointee.pointee.kind == TypeKind.DOUBLE
+
+
+def test_pointer_to_record_type():
+    source = "class A{}; A* pA();"
+
+    tu = get_tu(source, 'cpp')
+    model = cppmodel.Model(tu)
+    f = model.functions[0]
+
+    assert f.return_type.kind == TypeKind.POINTER
+    assert f.return_type.is_pointer
+    assert f.return_type.pointee.kind == TypeKind.RECORD
+
+def test_reference_to_record_type():
+    source = "class A{}; A& pA();"
+
+    tu = get_tu(source, 'cpp')
+    model = cppmodel.Model(tu)
+    f = model.functions[0]
+
+    assert f.return_type.kind == TypeKind.LVALUEREFERENCE
+    assert not f.return_type.is_pointer
+    assert f.return_type.is_reference
+    assert f.return_type.pointee.kind == TypeKind.RECORD
+
Index: bindings/python/tests/cppmodel/test_free_functions.py
===================================================================
--- /dev/null
+++ bindings/python/tests/cppmodel/test_free_functions.py
@@ -0,0 +1,55 @@
+from ..cindex.util import get_tu
+from clang import cppmodel
+from clang.cindex import TypeKind
+
+def test_function_name():
+    source = """
+    void foo();
+    void bar();
+    """
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    functions = model.functions
+
+    assert len(functions) == 2
+    assert functions[0].name == 'foo'
+    assert functions[1].name == 'bar'
+
+
+def test_function_return_type():
+    source = """
+    int foo();
+    double* bar();
+    """
+
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    functions = model.functions
+
+    assert functions[0].return_type.kind == TypeKind.INT
+    assert functions[1].return_type.kind == TypeKind.POINTER
+    assert functions[1].return_type.is_pointer
+    assert functions[1].return_type.pointee.kind == TypeKind.DOUBLE
+    assert not functions[1].return_type.pointee.is_const
+
+
+def test_function_arguments():
+    source = """
+    int foo();
+    double bar(int x, char y);
+    """
+
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    functions = model.functions
+
+    assert len(functions[0].arguments) == 0
+    assert len(functions[1].arguments) == 2
+    assert functions[1].arguments[0].type.kind == TypeKind.INT
+    assert functions[1].arguments[0].name == 'x'
+    assert functions[1].arguments[1].type.kind == TypeKind.CHAR_S
+    assert functions[1].arguments[1].name == 'y'
+
Index: bindings/python/tests/cppmodel/test_classes.py
===================================================================
--- /dev/null
+++ bindings/python/tests/cppmodel/test_classes.py
@@ -0,0 +1,129 @@
+from ..cindex.util import get_tu
+from clang import cppmodel
+from clang.cindex import TypeKind
+
+def test_class_name():
+    source = 'class A{};'
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    classes = model.classes
+
+    assert len(classes)==1
+    assert classes[0].name == 'A'
+
+def test_class_methods():
+    source = """
+    class A{};
+    class B{
+        void foo();
+        int bar();
+    };"""
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    classes = model.classes
+
+    assert len(classes[0].methods) == 0
+    assert len(classes[1].methods) == 2
+
+def test_class_method_return_types():
+    source = """
+    class B{
+        void foo();
+        int bar();
+    };"""
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    classes = model.classes
+
+    assert classes[0].methods[0].return_type.kind == TypeKind.VOID
+    assert classes[0].methods[1].return_type.kind == TypeKind.INT
+
+def test_class_method_argument_types():
+    source = """
+    class A {
+        int foo(int i, const char* p);
+    };"""
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    classes = model.classes
+    args = classes[0].methods[0].arguments
+
+    assert args[0].type.kind == TypeKind.INT
+    assert args[0].name == "i"
+    assert args[1].type.kind == TypeKind.POINTER
+    assert args[1].name == "p"
+
+def test_class_method_const_qualifiers():
+    source = """
+    class A {
+        int foo() const;
+        int bar();
+    };"""
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    classes = model.classes
+    methods = classes[0].methods
+
+    assert methods[0].is_const
+    assert not methods[1].is_const
+
+def test_class_methods_are_virtual():
+    source = """
+    class A {
+        virtual int foo();
+        int bar();
+        virtual int foobar() = 0;
+    };"""
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    classes = model.classes
+    methods = classes[0].methods
+
+    assert methods[0].is_virtual
+    assert not methods[0].is_pure_virtual
+    assert not methods[1].is_virtual
+    assert methods[2].is_pure_virtual
+
+def test_namespaces():
+    source = """
+    class A{};
+    namespace outer {
+        class B{};
+        namespace inner {
+            class C{};
+        } // end inner
+        class D{};
+    } // end outer
+    class E{};"""
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    classes = model.classes
+
+    assert classes[0].namespace == ""
+    assert classes[1].namespace == "outer"
+    assert classes[2].namespace == "outer::inner"
+    assert classes[3].namespace == "outer"
+    assert classes[4].namespace == ""
+
+def test_access_specifiers():
+    source = """
+    class A { int foo(); };
+    struct B { int foo(); };
+    class C { public: int foo(); };
+    """
+    tu = get_tu(source, 'cpp')
+
+    model = cppmodel.Model(tu)
+    classes = model.classes
+
+    assert not classes[0].methods[0].is_public
+    assert classes[1].methods[0].is_public
+    assert classes[2].methods[0].is_public
+
Index: bindings/python/clang/cppmodel.py
===================================================================
--- /dev/null
+++ bindings/python/clang/cppmodel.py
@@ -0,0 +1,110 @@
+import os
+import sys
+import clang.cindex
+from clang.cindex import AccessSpecifier, CursorKind, TypeKind
+
+def _get_annotations(node):
+    return [c.displayname for c in node.get_children()
+            if c.kind == CursorKind.ANNOTATE_ATTR]
+
+class Type:
+    def __init__(self, cindex_type):
+        self.kind = cindex_type.kind
+        self.name = cindex_type.spelling
+        self.is_pointer = self.kind == TypeKind.POINTER
+        self.is_reference = self.kind == TypeKind.LVALUEREFERENCE
+        self.is_const = cindex_type.is_const_qualified()
+        if self.is_pointer or self.is_reference:
+            self.pointee = Type(cindex_type.get_pointee())
+        else: self.pointee = None
+
+    def __repr__(self):
+        return self.name
+
+
+class FunctionArgument:
+    def __repr__(self):
+        return str(self.type)+":\""+str(self.name)+"\""
+
+    def __init__(self, type, name):
+        self.type = type
+        self.name = name
+
+
+class _Function(object):
+    def __repr__(self):
+        return str(self.name)
+
+    def __init__(self, cursor):
+        self.name = cursor.spelling
+        arguments = [x.spelling for x in cursor.get_arguments()]
+        argument_types = [Type(x) for x in cursor.type.argument_types()]
+
+        self.return_type = Type(cursor.type.get_result())
+        self.arguments = []
+        self.annotations = _get_annotations(cursor)
+
+        for t,n in zip(argument_types,arguments):
+            self.arguments.append(FunctionArgument(t,n))
+
+
+class Function(_Function):
+
+    def __init__(self, cursor, namespaces=[]):
+        _Function.__init__(self, cursor)
+        self.namespace = '::'.join(namespaces)
+
+
+class Method(Function):
+
+    def __init__(self, cursor):
+        _Function.__init__(self, cursor)
+        self.is_const = cursor.is_const_method()
+        self.is_virtual = cursor.is_virtual_method()
+        self.is_pure_virtual = cursor.is_pure_virtual_method()
+        self.is_public = (cursor.access_specifier == AccessSpecifier.PUBLIC)
+
+
+class Class(object):
+    def __repr__(self):
+        return "Class:%s"%str(self.name)
+
+    def __init__(self, cursor, namespaces):
+        self.name = cursor.spelling
+        self.namespace = '::'.join(namespaces)
+        self.constructors = []
+        self.methods = []
+        self.fields = []
+        self.annotations = _get_annotations(cursor)
+        self.base_classes = []
+
+        for c in cursor.get_children():
+            if (c.kind == CursorKind.CXX_METHOD):
+                f = Method(c)
+                self.methods.append(f)
+            elif (c.kind == CursorKind.CONSTRUCTOR):
+                f = Method(c)
+                self.constructors.append(f)
+            elif (c.kind == CursorKind.CXX_BASE_SPECIFIER):
+                self.base_classes.append(c.type.spelling)
+
+class Model(object):
+    def __repr__(self):
+        return "Classes:[{}]".format(",".join(self.classes))
+
+    def __init__(self, translation_unit):
+       self.functions = []
+       self.classes = []
+       self.add_child_nodes(translation_unit.cursor, [])
+
+    def add_child_nodes(self, cursor, namespaces=[]):
+        for c in cursor.get_children():
+            if c.kind == CursorKind.CLASS_DECL or c.kind == CursorKind.STRUCT_DECL:
+                self.classes.append(Class(c,namespaces))
+            if c.kind == CursorKind.FUNCTION_DECL:
+                self.functions.append(Function(c,namespaces))
+            elif c.kind == CursorKind.NAMESPACE:
+                child_namespaces = list(namespaces)
+                child_namespaces.append(c.spelling)
+                self.add_child_nodes(c, child_namespaces)
+
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to