From 601b8149bf81231a09e2977dbdbfe8e8e568c1f4 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 14 Oct 2020 00:17:14 +0200
Subject: Defined proper Python bindings for class/enum types.

---
 plugins/dexbnf/shorty.c                         |   2 +-
 plugins/dexbnf/type.c                           |   4 +-
 plugins/itanium/abi.c                           |  12 +--
 plugins/itanium/component.c                     |  16 ++--
 plugins/javadesc/field.c                        |   4 +-
 plugins/pychrysalide/analysis/types/basic.c     |  13 +--
 plugins/pychrysalide/analysis/types/constants.c | 101 ++++++++++++++++++++++
 plugins/pychrysalide/analysis/types/constants.h |   6 ++
 plugins/pychrysalide/analysis/types/cse.c       | 110 ++++++++++++------------
 src/analysis/type.c                             |   3 +
 src/analysis/types/cse.c                        |  24 +++---
 src/analysis/types/cse.h                        |  24 +++---
 tests/analysis/types/basic.py                   |   4 +-
 tests/analysis/types/cse.py                     |  30 +++++++
 14 files changed, 245 insertions(+), 108 deletions(-)
 create mode 100644 tests/analysis/types/cse.py

diff --git a/plugins/dexbnf/shorty.c b/plugins/dexbnf/shorty.c
index 434aa3b..2dbd019 100644
--- a/plugins/dexbnf/shorty.c
+++ b/plugins/dexbnf/shorty.c
@@ -213,7 +213,7 @@ static GDataType *dsd_shorty_field_type(input_buffer *buffer, char ahead)
             break;
 
         case 'L':
-            result = g_class_enum_type_new(CET_CLASS, NULL);
+            result = g_class_enum_type_new(CEK_CLASS, NULL);
             break;
 
         default:
diff --git a/plugins/dexbnf/type.c b/plugins/dexbnf/type.c
index 5a0d82c..db838c1 100644
--- a/plugins/dexbnf/type.c
+++ b/plugins/dexbnf/type.c
@@ -88,7 +88,7 @@ static GDataType *dtd_full_class_name(input_buffer *buffer)
     }
 
     else
-        result = g_class_enum_type_new(CET_CLASS, name);
+        result = g_class_enum_type_new(CEK_CLASS, name);
 
     /* Eventuels autres étages précédents */
 
@@ -114,7 +114,7 @@ static GDataType *dtd_full_class_name(input_buffer *buffer)
 
         ns = result;
 
-        result = g_class_enum_type_new(CET_CLASS, name);
+        result = g_class_enum_type_new(CEK_CLASS, name);
 
         g_data_type_set_namespace(result, ns, strdup("."));
 
diff --git a/plugins/itanium/abi.c b/plugins/itanium/abi.c
index 0304938..213d5f7 100644
--- a/plugins/itanium/abi.c
+++ b/plugins/itanium/abi.c
@@ -1926,7 +1926,7 @@ static itanium_component *itd_type(GItaniumDemangling *context)
 
             else
             {
-                builtin = g_class_enum_type_new(CET_UNKNOWN, itd_translate_component(vendor, NULL));
+                builtin = g_class_enum_type_new(CEK_UNKNOWN, itd_translate_component(vendor, NULL));
                 result = itd_make_type(builtin);
                 itd_set_type(result, ICT_VENDOR_TYPE);
                 itd_unref_comp(vendor);
@@ -2348,9 +2348,9 @@ static itanium_component *itd_builtin_type(GItaniumDemangling *context)
 
                 case 'n':
 
-                    std = g_class_enum_type_new(CET_NAMESPACE, strdup("std"));
+                    std = g_class_enum_type_new(CEK_NAMESPACE, strdup("std"));
 
-                    builtin = g_class_enum_type_new(CET_CLASS, strdup("nullptr_t"));
+                    builtin = g_class_enum_type_new(CEK_CLASS, strdup("nullptr_t"));
                     g_data_type_set_namespace(builtin, std, strdup("::"));
 
                     result = itd_make_type(builtin);
@@ -2377,7 +2377,7 @@ static itanium_component *itd_builtin_type(GItaniumDemangling *context)
                 result = NULL;
             else
             {
-                builtin = g_class_enum_type_new(CET_UNKNOWN, itd_translate_component(vendor, NULL));
+                builtin = g_class_enum_type_new(CEK_UNKNOWN, itd_translate_component(vendor, NULL));
                 result = itd_make_type(builtin);
                 itd_unref_comp(vendor);
             }
@@ -3480,14 +3480,14 @@ static itanium_component *itd_substitution(GItaniumDemangling *context)
 
             if (stdinfo->code == cur)
             {
-                std = g_class_enum_type_new(CET_NAMESPACE, strdup("std"));
+                std = g_class_enum_type_new(CEK_NAMESPACE, strdup("std"));
 
                 if (stdinfo->class == NULL)
                     type = std;
 
                 else
                 {
-                    type = g_class_enum_type_new(CET_CLASS, strdup(stdinfo->class));
+                    type = g_class_enum_type_new(CEK_CLASS, strdup(stdinfo->class));
                     g_data_type_set_namespace(type, std, strdup("::"));
                 }
 
diff --git a/plugins/itanium/component.c b/plugins/itanium/component.c
index f035e36..3791c4c 100644
--- a/plugins/itanium/component.c
+++ b/plugins/itanium/component.c
@@ -1415,14 +1415,14 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp, Routin
     {
         case ICT_NAME:
             name = itd_translate_component(comp, NULL);
-            result = g_class_enum_type_new(CET_STRUCT, name);
+            result = g_class_enum_type_new(CEK_STRUCT, name);
             break;
 
         case ICT_STD_UNSCOPED_NAME:
             result = itd_translate_component_to_type(comp->unary, rtype);
             if (result != NULL)
             {
-                ns = g_class_enum_type_new(CET_NAMESPACE, strdup("std"));
+                ns = g_class_enum_type_new(CEK_NAMESPACE, strdup("std"));
                 itd_prepend_namespace_to_type(result, ns);
             }
             break;
@@ -1434,7 +1434,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp, Routin
                 name = itd_translate_component(comp->binary.left, NULL);
                 name = itd_translate_component(comp->binary.right, name);
 
-                result = g_class_enum_type_new(CET_CLASS, name);
+                result = g_class_enum_type_new(CEK_CLASS, name);
 
             }
 
@@ -1515,7 +1515,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp, Routin
                 name = itd_translate_component(comp->binary.left, NULL);
                 name = itd_translate_component(comp->binary.right, name);
 
-                result = g_class_enum_type_new(CET_CLASS, name);
+                result = g_class_enum_type_new(CEK_CLASS, name);
 
             }
 
@@ -1544,7 +1544,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp, Routin
                 name = itd_translate_component(comp->binary.left, NULL);
                 name = itd_translate_component(comp->binary.right, name);
 
-                result = g_class_enum_type_new(CET_CLASS, name);
+                result = g_class_enum_type_new(CEK_CLASS, name);
 
             }
 
@@ -1582,7 +1582,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp, Routin
 
         case ICT_OPERATOR_NAME:
             name = itd_translate_component(comp, NULL);
-            result = g_class_enum_type_new(CET_STRUCT, name);
+            result = g_class_enum_type_new(CEK_STRUCT, name);
             break;
 
         case ICT_SPECIAL_NAME_VTABLE:
@@ -1594,7 +1594,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp, Routin
 
             else
             {
-                result = g_class_enum_type_new(CET_VIRTUAL_TABLE, NULL);
+                result = g_class_enum_type_new(CEK_VIRTUAL_TABLE, NULL);
                 itd_prepend_namespace_to_type(result, ns);
             }
 
@@ -1609,7 +1609,7 @@ GDataType *itd_translate_component_to_type(const itanium_component *comp, Routin
 
             else
             {
-                result = g_class_enum_type_new(CET_VIRTUAL_STRUCT, NULL);
+                result = g_class_enum_type_new(CEK_VIRTUAL_STRUCT, NULL);
                 itd_prepend_namespace_to_type(result, ns);
             }
 
diff --git a/plugins/javadesc/field.c b/plugins/javadesc/field.c
index 95b0b8f..799d39d 100644
--- a/plugins/javadesc/field.c
+++ b/plugins/javadesc/field.c
@@ -91,7 +91,7 @@ static GDataType *jtd_object_type_descriptor(input_buffer *buffer)
 
             name[len - 1] = '\0';
 
-            root = g_class_enum_type_new(CET_CLASS, name);
+            root = g_class_enum_type_new(CEK_CLASS, name);
 
             /**
              * Pour éviter les fuites si aucun paquet n'est présent...
@@ -154,7 +154,7 @@ static GDataType *jtd_object_type_descriptor(input_buffer *buffer)
     while (1);
 
     if (name != NULL)
-        result = g_class_enum_type_new(CET_CLASS, name);
+        result = g_class_enum_type_new(CEK_CLASS, name);
 
     return result;
 
diff --git a/plugins/pychrysalide/analysis/types/basic.c b/plugins/pychrysalide/analysis/types/basic.c
index 539bcad..9ae4f8f 100644
--- a/plugins/pychrysalide/analysis/types/basic.c
+++ b/plugins/pychrysalide/analysis/types/basic.c
@@ -116,12 +116,13 @@ static PyObject *py_basic_type_get_base(PyObject *self, void *closure)
     GBasicType *type;                       /* Version GLib du type        */
     BaseType base;                          /* Type de base à renvoyer     */
 
-#define BASIC_TYPE_BASE_ATTRIB PYTHON_GET_DEF_FULL                      \
-(                                                                       \
-    base, py_basic_type,                                                \
-    "Provide the internal identifier of the basic type.\n"              \
-    "\n"                                                                \
-    "This property provides a pychrysalide.analysis.BaseType value."    \
+#define BASIC_TYPE_BASE_ATTRIB PYTHON_GET_DEF_FULL              \
+(                                                               \
+    base, py_basic_type,                                        \
+    "Provide the internal identifier of the basic type.\n"      \
+    "\n"                                                        \
+    "This property provides a"                                  \
+    " pychrysalide.analysis.types.BasicType.BaseType value."    \
 )
 
     type = G_BASIC_TYPE(pygobject_get(self));
diff --git a/plugins/pychrysalide/analysis/types/constants.c b/plugins/pychrysalide/analysis/types/constants.c
index 6562fa0..1112410 100644
--- a/plugins/pychrysalide/analysis/types/constants.c
+++ b/plugins/pychrysalide/analysis/types/constants.c
@@ -26,6 +26,7 @@
 
 
 #include <analysis/types/basic.h>
+#include <analysis/types/cse.h>
 
 
 #include "../../helpers.h"
@@ -153,3 +154,103 @@ int convert_to_basic_type_base_type(PyObject *arg, void *dst)
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : type = type dont le dictionnaire est à compléter.            *
+*                                                                             *
+*  Description : Définit les constantes relatives aux classes et énumérations.*
+*                                                                             *
+*  Retour      : true en cas de succès de l'opération, false sinon.           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool define_class_enum_type_constants(PyTypeObject *type)
+{
+    bool result;                            /* Bilan à retourner           */
+    PyObject *values;                       /* Groupe de valeurs à établir */
+
+    values = PyDict_New();
+
+    result = add_const_to_group(values, "UNKNOWN", CEK_UNKNOWN);
+    if (result) result = add_const_to_group(values, "STRUCT", CEK_STRUCT);
+    if (result) result = add_const_to_group(values, "ENUM", CEK_ENUM);
+    if (result) result = add_const_to_group(values, "CLASS", CEK_CLASS);
+    if (result) result = add_const_to_group(values, "NAMESPACE", CEK_NAMESPACE);
+    if (result) result = add_const_to_group(values, "VIRTUAL_TABLE", CEK_VIRTUAL_TABLE);
+    if (result) result = add_const_to_group(values, "VIRTUAL_STRUCT", CEK_VIRTUAL_STRUCT);
+    if (result) result = add_const_to_group(values, "COUNT", CEK_COUNT);
+
+    if (!result)
+    {
+        Py_DECREF(values);
+        goto exit;
+    }
+
+    result = attach_constants_group_to_type(type, false, "ClassEnumKind", values,
+                                            "Kind of types such as classes, structures and enumerations.");
+
+ exit:
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en constante ClassEnumKind.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_class_enum_type_class_enum_kind(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+    unsigned long value;                    /* Valeur transcrite           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type);
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to ClassEnumKind");
+            break;
+
+        case 1:
+            value = PyLong_AsUnsignedLong(arg);
+
+            if (value > CEK_COUNT)
+            {
+                PyErr_SetString(PyExc_TypeError, "invalid value for ClassEnumKind");
+                result = 0;
+            }
+
+            else
+                *((ClassEnumKind *)dst) = value;
+
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/analysis/types/constants.h b/plugins/pychrysalide/analysis/types/constants.h
index 9598f75..b695e8d 100644
--- a/plugins/pychrysalide/analysis/types/constants.h
+++ b/plugins/pychrysalide/analysis/types/constants.h
@@ -37,6 +37,12 @@ bool define_basic_type_constants(PyTypeObject *);
 /* Tente de convertir en constante BaseType. */
 int convert_to_basic_type_base_type(PyObject *, void *);
 
+/* Définit les constantes relatives aux classes et énumérations. */
+bool define_class_enum_type_constants(PyTypeObject *);
+
+/* Tente de convertir en constante ClassEnumKind. */
+int convert_to_class_enum_type_class_enum_kind(PyObject *, void *);
+
 
 
 #endif  /* _PLUGINS_PYCHRYSALIDE_ANALYSIS_TYPES_CONSTANTS_H */
diff --git a/plugins/pychrysalide/analysis/types/cse.c b/plugins/pychrysalide/analysis/types/cse.c
index 5f0bb0a..7701d48 100644
--- a/plugins/pychrysalide/analysis/types/cse.c
+++ b/plugins/pychrysalide/analysis/types/cse.c
@@ -32,6 +32,7 @@
 #include <analysis/types/cse.h>
 
 
+#include "constants.h"
 #include "../type.h"
 #include "../../access.h"
 #include "../../helpers.h"
@@ -42,14 +43,11 @@
 static PyObject *py_class_enum_type_new(PyTypeObject *, PyObject *, PyObject *);
 
 /* Fournit le type pris en compte géré par le type. */
-static PyObject *py_class_enum_type_get_base_type(PyObject *, void *);
+static PyObject *py_class_enum_type_get_kind(PyObject *, void *);
 
 /* Donne la désignation de la classe / structure / énumération. */
 static PyObject *py_class_enum_type_get_name(PyObject *, void *);
 
-/* Définit les constantes pour les types de classe/énumération. */
-static bool py_class_enum_type_define_constants(PyTypeObject *);
-
 
 
 /******************************************************************************
@@ -69,21 +67,35 @@ static bool py_class_enum_type_define_constants(PyTypeObject *);
 static PyObject *py_class_enum_type_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     PyObject *result;                       /* Instance à retourner        */
-    unsigned long base;                     /* Type de base à créer        */
+    ClassEnumKind kind;                     /* Type de base à créer        */
     const char *name;                       /* Désignation humaine         */
     int ret;                                /* Bilan de lecture des args.  */
     GDataType *dtype;                       /* Version GLib du type        */
 
-    ret = PyArg_ParseTuple(args, "ks", &base, &name);
+#define CLASS_ENUM_TYPE_DOC                                                 \
+    "The ClassEnumType class handles types embedding other types, such as"  \
+    " classes, structures or enumerations.\n"                               \
+    "\n"                                                                    \
+    "Instances can be created using the following constructor:\n"           \
+    "\n"                                                                    \
+    "    ClassEnumType(kind, name=None)"                                    \
+    "\n"                                                                    \
+    "Where *kind* is one of the"                                            \
+    " pychrysalide.analysis.types.ClassEnumType.ClassEnumKind values,"      \
+    " except *ClassEnumKind.COUNT*, and *name* is an optional string."
+
+    name = NULL;
+
+    ret = PyArg_ParseTuple(args, "O&|s", convert_to_class_enum_type_class_enum_kind, &kind, &name);
     if (!ret) return NULL;
 
-    if (base >= CET_COUNT)
+    if (kind >= CEK_COUNT)
     {
-        PyErr_SetString(PyExc_TypeError, _("Bad basic type."));
+        PyErr_SetString(PyExc_TypeError, _("Bad class/enum kind."));
         return NULL;
     }
 
-    dtype = g_class_enum_type_new(base, strdup(name));
+    dtype = g_class_enum_type_new(kind, name != NULL ? strdup(name) : NULL);
     result = pygobject_new(G_OBJECT(dtype));
     g_object_unref(dtype);
 
@@ -105,17 +117,26 @@ static PyObject *py_class_enum_type_new(PyTypeObject *type, PyObject *args, PyOb
 *                                                                             *
 ******************************************************************************/
 
-static PyObject *py_class_enum_type_get_base_type(PyObject *self, void *closure)
+static PyObject *py_class_enum_type_get_kind(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Résultat à retourner        */
     GClassEnumType *type;                   /* Version GLib du type        */
-    ClassEnumType base;                     /* Type de base à renvoyer     */
+    ClassEnumKind kind;                     /* Type de base à renvoyer     */
+
+#define CLASS_ENUM_TYPE_KIND_ATTRIB PYTHON_GET_DEF_FULL                 \
+(                                                                       \
+    kind, py_class_enum_type,                                           \
+    "Provide the internal identifier for the kind of the type.\n"       \
+    "\n"                                                                \
+    "This property provides a"                                          \
+    " pychrysalide.analysis.types.ClassEnumType.ClassEnumKind value."   \
+)
 
     type = G_CLASS_ENUM_TYPE(pygobject_get(self));
 
-    base = g_class_enum_type_get_base(type);
+    kind = g_class_enum_type_get_kind(type);
 
-    result = PyLong_FromUnsignedLong(base);
+    result = cast_with_constants_group_from_type(get_python_class_enum_type_type(), "ClassEnumKind", kind);
 
     return result;
 
@@ -141,11 +162,25 @@ static PyObject *py_class_enum_type_get_name(PyObject *self, void *closure)
     GClassEnumType *type;                   /* Version GLib du type        */
     const char *name;                       /* Désignation humaine         */
 
+#define CLASS_ENUM_TYPE_NAME_ATTRIB PYTHON_GET_DEF_FULL                 \
+(                                                                       \
+    name, py_class_enum_type,                                           \
+    "Provide the name registered for the type.\n"                       \
+    "\n"                                                                \
+    "This property provides a string or None if no value is defined."   \
+)
+
     type = G_CLASS_ENUM_TYPE(pygobject_get(self));
 
     name = g_class_enum_type_get_name(type);
 
-    result = PyUnicode_FromString(name);
+    if (name != NULL)
+        result = PyUnicode_FromString(name);
+    else
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
 
     return result;
 
@@ -171,14 +206,8 @@ PyTypeObject *get_python_class_enum_type_type(void)
     };
 
     static PyGetSetDef py_class_enum_type_getseters[] = {
-        {
-            "base", py_class_enum_type_get_base_type, NULL,
-            "Provide the internal identifier of the type.", NULL
-        },
-        {
-            "name", py_class_enum_type_get_name, NULL,
-            "Provide the name of the type.", NULL
-        },
+        CLASS_ENUM_TYPE_KIND_ATTRIB,
+        CLASS_ENUM_TYPE_NAME_ATTRIB,
         { NULL }
     };
 
@@ -191,7 +220,7 @@ PyTypeObject *get_python_class_enum_type_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
 
-        .tp_doc         = "PyChrysalide basic type",
+        .tp_doc         = CLASS_ENUM_TYPE_DOC,
 
         .tp_methods     = py_class_enum_type_methods,
         .tp_getset      = py_class_enum_type_getseters,
@@ -206,39 +235,6 @@ PyTypeObject *get_python_class_enum_type_type(void)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        *
-*                                                                             *
-*  Description : Définit les constantes pour les types de classe/énumération. *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool py_class_enum_type_define_constants(PyTypeObject *obj_type)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = true;
-
-    result &= PyDict_AddULongMacro(obj_type, CET_UNKNOWN);
-    result &= PyDict_AddULongMacro(obj_type, CET_STRUCT);
-    result &= PyDict_AddULongMacro(obj_type, CET_ENUM);
-    result &= PyDict_AddULongMacro(obj_type, CET_CLASS);
-    result &= PyDict_AddULongMacro(obj_type, CET_NAMESPACE);
-    result &= PyDict_AddULongMacro(obj_type, CET_VIRTUAL_TABLE);
-    result &= PyDict_AddULongMacro(obj_type, CET_VIRTUAL_STRUCT);
-
-    result &= PyDict_AddULongMacro(obj_type, CET_COUNT);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : module = module dont la définition est à compléter.          *
 *                                                                             *
 *  Description : Prend en charge l'objet 'pychrysalide.....ClassEnumType'.    *
@@ -269,7 +265,7 @@ bool ensure_python_class_enum_type_is_registered(void)
         if (!register_class_for_pygobject(dict, G_TYPE_CLASS_ENUM_TYPE, type, get_python_data_type_type()))
             return false;
 
-        if (!py_class_enum_type_define_constants(type))
+        if (!define_class_enum_type_constants(type))
             return false;
 
     }
diff --git a/src/analysis/type.c b/src/analysis/type.c
index f19d846..9a8e85b 100644
--- a/src/analysis/type.c
+++ b/src/analysis/type.c
@@ -198,6 +198,9 @@ char *g_data_type_to_string(const GDataType *type, bool include)
 
     result = class->to_string(type, include);
 
+    if (result == NULL)
+        result = strdup("");
+
     if (include && type->namespace != NULL && g_data_type_handle_namespaces(type))
     {
         namespace = g_data_type_to_string(type->namespace, true);
diff --git a/src/analysis/types/cse.c b/src/analysis/types/cse.c
index 54884af..9f9adcd 100644
--- a/src/analysis/types/cse.c
+++ b/src/analysis/types/cse.c
@@ -37,7 +37,7 @@ struct _GClassEnumType
 {
     GDataType parent;                       /* A laisser en premier        */
 
-    ClassEnumType type;                     /* Type représenté si connu    */
+    ClassEnumKind kind;                     /* Type représenté si connu    */
     char *name;                             /* Description humaine         */
 
 };
@@ -118,7 +118,7 @@ static void g_class_enum_type_class_init(GClassEnumTypeClass *klass)
 
 static void g_class_enum_type_init(GClassEnumType *type)
 {
-    type->type = CET_COUNT;
+    type->kind = CEK_COUNT;
     type->name = NULL;
 
 }
@@ -167,7 +167,7 @@ static void g_class_enum_type_finalize(GClassEnumType *type)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : type = type de structure à représenter.                      *
+*  Paramètres  : kind = type de structure à représenter.                      *
 *                name = désignation humaine du type.                          *
 *                                                                             *
 *  Description : Crée une représentation de classe, structure ou énumération. *
@@ -178,13 +178,13 @@ static void g_class_enum_type_finalize(GClassEnumType *type)
 *                                                                             *
 ******************************************************************************/
 
-GDataType *g_class_enum_type_new(ClassEnumType type, char *name)
+GDataType *g_class_enum_type_new(ClassEnumKind kind, char *name)
 {
     GClassEnumType *result;                 /* Structure à retourner       */
 
     result = g_object_new(G_TYPE_CLASS_ENUM_TYPE, NULL);
 
-    result->type = type;
+    result->kind = kind;
     result->name = name;
 
     return G_DATA_TYPE(result);
@@ -211,7 +211,7 @@ static GDataType *g_class_enum_type_dup(const GClassEnumType *type)
 
     name = (type->name != NULL ? strdup(type->name) : NULL);
 
-    result = g_class_enum_type_new(type->type, name);
+    result = g_class_enum_type_new(type->kind, name);
 
     return result;
 
@@ -235,13 +235,13 @@ static char *g_class_enum_type_to_string(const GClassEnumType *type, bool includ
 {
     char *result;                           /* Valeur à renvoyer           */
 
-    switch (type->type)
+    switch (type->kind)
     {
-        case CET_VIRTUAL_TABLE:
+        case CEK_VIRTUAL_TABLE:
             result = strdup("vtable");
             break;
 
-        case CET_VIRTUAL_STRUCT:
+        case CEK_VIRTUAL_STRUCT:
             result = strdup("vstruct");
             break;
 
@@ -268,11 +268,11 @@ static char *g_class_enum_type_to_string(const GClassEnumType *type, bool includ
 *                                                                             *
 ******************************************************************************/
 
-ClassEnumType g_class_enum_type_get_base(const GClassEnumType *type)
+ClassEnumKind g_class_enum_type_get_kind(const GClassEnumType *type)
 {
-    ClassEnumType result;                   /* Type de base à renvoyer     */
+    ClassEnumKind result;                   /* Type de base à renvoyer     */
 
-    result = type->type;
+    result = type->kind;
 
     return result;
 
diff --git a/src/analysis/types/cse.h b/src/analysis/types/cse.h
index ad0bc58..5831928 100644
--- a/src/analysis/types/cse.h
+++ b/src/analysis/types/cse.h
@@ -48,29 +48,29 @@ typedef struct _GClassEnumTypeClass GClassEnumTypeClass;
 
 
 /* Type pris en compte */
-typedef enum _ClassEnumType
+typedef enum _ClassEnumKind
 {
-    CET_UNKNOWN,                            /* Statut inconnu              */
-    CET_STRUCT,                             /* Structure                   */
-    CET_ENUM,                               /* Enumération                 */
-    CET_CLASS,                              /* Classe                      */
-    CET_NAMESPACE,                          /* Espace de nom               */
-    CET_VIRTUAL_TABLE,                      /* Table virtuelle             */
-    CET_VIRTUAL_STRUCT,                     /* Indice de construction VT   */
+    CEK_UNKNOWN,                            /* Statut inconnu              */
+    CEK_STRUCT,                             /* Structure                   */
+    CEK_ENUM,                               /* Enumération                 */
+    CEK_CLASS,                              /* Classe                      */
+    CEK_NAMESPACE,                          /* Espace de nom               */
+    CEK_VIRTUAL_TABLE,                      /* Table virtuelle             */
+    CEK_VIRTUAL_STRUCT,                     /* Indice de construction VT   */
 
-    CET_COUNT
+    CEK_COUNT
 
-} ClassEnumType;
+} ClassEnumKind;
 
 
 /* Indique le type défini pour un type classe ou assimilé. */
 GType g_class_enum_type_get_type(void);
 
 /* Crée une représentation de classe, structure ou énumération. */
-GDataType *g_class_enum_type_new(ClassEnumType, char *);
+GDataType *g_class_enum_type_new(ClassEnumKind, char *);
 
 /* Fournit le type pris en compte géré par le type. */
-ClassEnumType g_class_enum_type_get_base(const GClassEnumType *);
+ClassEnumKind g_class_enum_type_get_kind(const GClassEnumType *);
 
 /* Donne la désignation de la classe / structure / énumération. */
 const char *g_class_enum_type_get_name(const GClassEnumType *);
diff --git a/tests/analysis/types/basic.py b/tests/analysis/types/basic.py
index 7b7403b..65700bd 100644
--- a/tests/analysis/types/basic.py
+++ b/tests/analysis/types/basic.py
@@ -6,8 +6,8 @@ from chrysacase import ChrysalideTestCase
 from pychrysalide.analysis.types import BasicType
 
 
-class TestDataType(ChrysalideTestCase):
-    """TestCase for analysis.DataType."""
+class TestBasicType(ChrysalideTestCase):
+    """TestCase for analysis.BasicType."""
 
 
     def testBasicTypeConstructor(self):
diff --git a/tests/analysis/types/cse.py b/tests/analysis/types/cse.py
new file mode 100644
index 0000000..9b6b016
--- /dev/null
+++ b/tests/analysis/types/cse.py
@@ -0,0 +1,30 @@
+#!/usr/bin/python3-dbg
+# -*- coding: utf-8 -*-
+
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.types import ClassEnumType
+
+
+class TestClassEnumType(ChrysalideTestCase):
+    """TestCase for analysis.ClassEnumType."""
+
+
+    def testClassEnumTypeConstructor(self):
+        """Build some class/enum types."""
+
+        tp = ClassEnumType(ClassEnumType.ClassEnumKind.STRUCT)
+
+        self.assertEqual(str(tp), '')
+
+        tp = ClassEnumType(ClassEnumType.ClassEnumKind.STRUCT, 'XXX')
+
+        self.assertEqual(str(tp), 'XXX')
+
+        with self.assertRaisesRegex(TypeError, 'Bad class/enum kind.'):
+
+            tp = ClassEnumType(ClassEnumType.ClassEnumKind.COUNT)
+
+        with self.assertRaisesRegex(TypeError, 'invalid value for ClassEnumKind'):
+
+            tp = ClassEnumType(0x1234)
-- 
cgit v0.11.2-87-g4458