[vala/wip/error-gtype: 403/405] codegen: Emit GType definition for error domains



commit 8719e49e2c2acb2474e0b74b95577b070059513c
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Sat Nov 17 22:22:03 2018 +0100

    codegen: Emit GType definition for error domains
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/699

 codegen/Makefile.am                          |  1 +
 codegen/valaccode.vala                       |  2 +-
 codegen/valaccodeattribute.vala              |  7 ++++
 codegen/valaerrordomainregisterfunction.vala | 51 ++++++++++++++++++++++++++++
 codegen/valagerrormodule.vala                | 25 ++++++++++++++
 codegen/valagirwriter.vala                   |  6 +++-
 codegen/valagtypemodule.vala                 | 12 +++++++
 codegen/valatyperegisterfunction.vala        | 30 ++++++++++++++++
 tests/girwriter/GirTest-1.0.gir-expected     |  7 +++-
 tests/girwriter/girtest.vala                 |  7 ++++
 tests/girwriter/girtest.vapi-expected        |  6 ++++
 vala/valaerrorcode.vala                      | 16 +++++++++
 12 files changed, 167 insertions(+), 3 deletions(-)
---
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index d22ecfd58..9d1295f3e 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -40,6 +40,7 @@ libvalaccodegen_la_VALASOURCES = \
        valaclassregisterfunction.vala \
        valactype.vala \
        valaenumregisterfunction.vala \
+       valaerrordomainregisterfunction.vala \
        valagasyncmodule.vala \
        valagdbusclientmodule.vala \
        valagdbusmodule.vala \
diff --git a/codegen/valaccode.vala b/codegen/valaccode.vala
index c8dfb167c..7aaba06e7 100644
--- a/codegen/valaccode.vala
+++ b/codegen/valaccode.vala
@@ -229,7 +229,7 @@ namespace Vala {
        }
 
        public static string get_ccode_type_function (TypeSymbol sym) {
-               assert (!((sym is Class && ((Class) sym).is_compact) || sym is ErrorCode || sym is 
ErrorDomain || sym is Delegate));
+               assert (!((sym is Class && ((Class) sym).is_compact) || sym is ErrorCode || sym is Delegate));
                return "%s_get_type".printf (get_ccode_lower_case_name (sym));
        }
 
diff --git a/codegen/valaccodeattribute.vala b/codegen/valaccodeattribute.vala
index 316570273..191cca949 100644
--- a/codegen/valaccodeattribute.vala
+++ b/codegen/valaccodeattribute.vala
@@ -1005,6 +1005,13 @@ public class Vala.CCodeAttribute : AttributeCache {
                                } else {
                                        return en.is_flags ? "G_TYPE_UINT" : "G_TYPE_INT";
                                }
+                       } else if (sym is ErrorDomain) {
+                               unowned ErrorDomain edomain = (ErrorDomain) sym;
+                               if (get_ccode_has_type_id (edomain)) {
+                                       return get_ccode_upper_case_name (edomain, "TYPE_");
+                               } else {
+                                       return "G_TYPE_INT";
+                               }
                        } else {
                                return "G_TYPE_POINTER";
                        }
diff --git a/codegen/valaerrordomainregisterfunction.vala b/codegen/valaerrordomainregisterfunction.vala
new file mode 100644
index 000000000..b4be3295e
--- /dev/null
+++ b/codegen/valaerrordomainregisterfunction.vala
@@ -0,0 +1,51 @@
+/* valaerrordomainregisterfunction.vala
+ *
+ * Copyright (C) 2018  Rico Tzschichholz
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Rico Tzschichholz <ricotz ubuntu com>
+ */
+
+using GLib;
+
+/**
+ * C function to register an error domain at runtime.
+ */
+public class Vala.ErrorDomainRegisterFunction : TypeRegisterFunction {
+       /**
+        * Specifies the error domain to be registered.
+        */
+       public weak ErrorDomain error_domain_reference { get; set; }
+
+       /**
+        * Creates a new C function to register the specified error domain at runtime.
+        *
+        * @param edomain an error domain
+        * @return        newly created error domain register function
+        */
+       public ErrorDomainRegisterFunction (ErrorDomain edomain) {
+               error_domain_reference = edomain;
+       }
+
+       public override TypeSymbol get_type_declaration () {
+               return error_domain_reference;
+       }
+
+       public override SymbolAccessibility get_accessibility () {
+               return error_domain_reference.access;
+       }
+}
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index d54f0d9d1..bc2b305c4 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -56,6 +56,31 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                var cquark_fun = new CCodeFunction (quark_fun_name, get_ccode_name (gquark_type.type_symbol));
 
                decl_space.add_function_declaration (cquark_fun);
+               decl_space.add_type_definition (new CCodeNewline ());
+
+               if (!get_ccode_has_type_id (edomain)) {
+                       return;
+               }
+
+               decl_space.add_include ("glib-object.h");
+               decl_space.add_type_declaration (new CCodeNewline ());
+
+               var fun_name = get_ccode_type_function (edomain);
+
+               var macro = "(%s ())".printf (fun_name);
+               decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (edomain), 
macro));
+
+               var regfun = new CCodeFunction (fun_name, "GType");
+               regfun.modifiers = CCodeModifiers.CONST;
+
+               if (edomain.is_private_symbol ()) {
+                       // avoid C warning as this function is not always used
+                       regfun.modifiers |= CCodeModifiers.STATIC | CCodeModifiers.UNUSED;
+               } else if (context.hide_internal && edomain.is_internal_symbol ()) {
+                       regfun.modifiers |= CCodeModifiers.INTERNAL;
+               }
+
+               decl_space.add_function_declaration (regfun);
        }
 
        public override void visit_error_domain (ErrorDomain edomain) {
diff --git a/codegen/valagirwriter.vala b/codegen/valagirwriter.vala
index e92ab1514..99880f3b6 100644
--- a/codegen/valagirwriter.vala
+++ b/codegen/valagirwriter.vala
@@ -847,7 +847,11 @@ public class Vala.GIRWriter : CodeVisitor {
 
                write_indent ();
                buffer.append_printf ("<enumeration name=\"%s\"", edomain.name);
-               write_ctype_attributes (edomain);
+               if (get_ccode_has_type_id (edomain)) {
+                       write_gtype_attributes (edomain);
+               } else {
+                       write_ctype_attributes (edomain);
+               }
                buffer.append_printf (" glib:error-domain=\"%s\"", get_ccode_quark_name (edomain));
                write_symbol_attributes (edomain);
                buffer.append_printf (">\n");
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index 4eb7878a1..7ad62bd65 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -2358,6 +2358,18 @@ public class Vala.GTypeModule : GErrorModule {
                }
        }
 
+       public override void visit_error_domain (ErrorDomain edomain) {
+               base.visit_error_domain (edomain);
+
+               if (get_ccode_has_type_id (edomain)) {
+                       push_line (edomain.source_reference);
+                       var type_fun = new ErrorDomainRegisterFunction (edomain);
+                       type_fun.init_from_type (context, false, false);
+                       cfile.add_type_member_definition (type_fun.get_definition ());
+                       pop_line ();
+               }
+       }
+
        public override void visit_method_call (MethodCall expr) {
                var ma = expr.call as MemberAccess;
                var mtype = expr.call.value_type as MethodType;
diff --git a/codegen/valatyperegisterfunction.vala b/codegen/valatyperegisterfunction.vala
index 394295f9b..54b81b22b 100644
--- a/codegen/valatyperegisterfunction.vala
+++ b/codegen/valatyperegisterfunction.vala
@@ -143,6 +143,8 @@ public abstract class Vala.TypeRegisterFunction {
                        } else {
                                reg_call = new CCodeFunctionCall (new CCodeIdentifier 
("g_enum_register_static"));
                        }
+               } else if (type_symbol is ErrorDomain) {
+                       reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_enum_register_static"));
                } else if (fundamental) {
                        reg_call = new CCodeFunctionCall (new CCodeIdentifier 
("g_type_register_fundamental"));
                        reg_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier 
("g_type_fundamental_next")));
@@ -191,6 +193,34 @@ public abstract class Vala.TypeRegisterFunction {
 
                        type_init.add_statement (cdecl);
 
+                       reg_call.add_argument (new CCodeIdentifier ("values"));
+               } else if (type_symbol is ErrorDomain) {
+                       unowned ErrorDomain edomain = (ErrorDomain) type_symbol;
+                       var clist = new CCodeInitializerList (); /* or during visit time? */
+
+                       CCodeInitializerList clist_ec = null;
+                       foreach (ErrorCode ec in edomain.get_codes ()) {
+                               clist_ec = new CCodeInitializerList ();
+                               clist_ec.append (new CCodeConstant (get_ccode_name (ec)));
+                               clist_ec.append (new CCodeConstant ("\"%s\"".printf (get_ccode_name (ec))));
+                               clist_ec.append (new CCodeConstant ("\"%s\"".printf (ec.nick)));
+                               clist.append (clist_ec);
+                       }
+
+                       clist_ec = new CCodeInitializerList ();
+                       clist_ec.append (new CCodeConstant ("0"));
+                       clist_ec.append (new CCodeConstant ("NULL"));
+                       clist_ec.append (new CCodeConstant ("NULL"));
+                       clist.append (clist_ec);
+
+                       var edomain_decl = new CCodeVariableDeclarator ("values[]", clist);
+
+                       cdecl = new CCodeDeclaration ("const GEnumValue");
+                       cdecl.add_declarator (edomain_decl);
+                       cdecl.modifiers = CCodeModifiers.STATIC;
+
+                       type_init.add_statement (cdecl);
+
                        reg_call.add_argument (new CCodeIdentifier ("values"));
                } else {
                        reg_call.add_argument (new CCodeIdentifier ("&g_define_type_info"));
diff --git a/tests/girwriter/GirTest-1.0.gir-expected b/tests/girwriter/GirTest-1.0.gir-expected
index 034f48418..7dbcce29b 100644
--- a/tests/girwriter/GirTest-1.0.gir-expected
+++ b/tests/girwriter/GirTest-1.0.gir-expected
@@ -26,11 +26,16 @@
        <enumeration name="SkippedFlags" c:type="GirTestSkippedFlags" glib:type-name="GirTestSkippedFlags" 
glib:get-type="gir_test_skipped_flags_get_type" introspectable="0">
                <member name="value1" c:identifier="GIR_TEST_SKIPPED_FLAGS_VALUE1" value="0"/>
        </enumeration>
-       <enumeration name="ErrorTest" c:type="GirTestErrorTest" glib:error-domain="gir-test-error-test-quark">
+       <enumeration name="ErrorTest" c:type="GirTestErrorTest" glib:type-name="GirTestErrorTest" 
glib:get-type="gir_test_error_test_get_type" glib:error-domain="gir-test-error-test-quark">
                <member name="failed" c:identifier="GIR_TEST_ERROR_TEST_FAILED" value="0"/>
                <member name="smelly" c:identifier="GIR_TEST_ERROR_TEST_SMELLY" value="1"/>
                <member name="fishy" c:identifier="GIR_TEST_ERROR_TEST_FISHY" value="23"/>
        </enumeration>
+       <enumeration name="PlainErrorTest" c:type="GirTestPlainErrorTest" 
glib:error-domain="gir-test-plain-error-test-quark">
+               <member name="failed" c:identifier="GIR_TEST_PLAIN_ERROR_TEST_FAILED" value="0"/>
+               <member name="smelly" c:identifier="GIR_TEST_PLAIN_ERROR_TEST_SMELLY" value="1"/>
+               <member name="fishy" c:identifier="GIR_TEST_PLAIN_ERROR_TEST_FISHY" value="23"/>
+       </enumeration>
        <class name="TypeTest" c:type="GirTestTypeTest" glib:type-name="GirTestTypeTest" 
glib:get-type="gir_test_typetest_get_type" glib:type-struct="TypeTestClass" glib:fundamental="1" 
glib:ref-func="gir_test_typetest_ref" glib:unref-func="gir_test_typetest_unref" 
glib:set-value-func="gir_test_value_set_typetest" glib:get-value-func="gir_test_value_get_typetest">
                <field name="parent_instance">
                        <type name="GObject.TypeInstance" c:type="GTypeInstance"/>
diff --git a/tests/girwriter/girtest.vala b/tests/girwriter/girtest.vala
index 3ace08a5b..791d4388d 100644
--- a/tests/girwriter/girtest.vala
+++ b/tests/girwriter/girtest.vala
@@ -65,6 +65,13 @@ namespace GirTest {
                FISHY = 23
        }
 
+       [CCode (has_type_id = false)]
+       public errordomain PlainErrorTest {
+               FAILED,
+               SMELLY,
+               FISHY = 23
+       }
+
        public interface InterfaceTest : Object {
                public abstract int property { get; construct set; }
                public virtual void int8_in (int8 param) {
diff --git a/tests/girwriter/girtest.vapi-expected b/tests/girwriter/girtest.vapi-expected
index 52d23d16a..38c2aa6a7 100644
--- a/tests/girwriter/girtest.vapi-expected
+++ b/tests/girwriter/girtest.vapi-expected
@@ -161,6 +161,12 @@ namespace GirTest {
                SMELLY,
                FISHY
        }
+       [CCode (cheader_filename = "girtest.h", has_type_id = false)]
+       public errordomain PlainErrorTest {
+               FAILED,
+               SMELLY,
+               FISHY
+       }
        [CCode (cheader_filename = "girtest.h")]
        public delegate bool DelegateTest (void* a, void* b);
        [CCode (cheader_filename = "girtest.h")]
diff --git a/vala/valaerrorcode.vala b/vala/valaerrorcode.vala
index 3e3c57b37..18812d254 100644
--- a/vala/valaerrorcode.vala
+++ b/vala/valaerrorcode.vala
@@ -54,8 +54,24 @@ public class Vala.ErrorCode : TypeSymbol {
                }
        }
 
+       /**
+        * The nick of this error code
+        */
+       public string nick {
+               get {
+                       if (_nick == null) {
+                               _nick = get_attribute_string ("Description", "nick");
+                               if (_nick == null) {
+                                       _nick = name.down ().replace ("_", "-");
+                               }
+                       }
+                       return _nick;
+               }
+       }
+
        private Expression _value;
        private Constant _code;
+       private string? _nick = null;
 
        /**
         * Creates a new enum value.


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]