[vala/wip/error-gtype: 7/11] codegen: Emit GType definition for error domains




commit 54379bab80330dc7d9daa3d4574216c2eca307f6
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 c7fc91341..b786e66ec 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 80e0f1c0f..25a0d11af 100644
--- a/codegen/valaccode.vala
+++ b/codegen/valaccode.vala
@@ -237,7 +237,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 bd4c6b29d..ffb963772 100644
--- a/codegen/valaccodeattribute.vala
+++ b/codegen/valaccodeattribute.vala
@@ -1073,6 +1073,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 a559a4d00..2b4c6cf85 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -56,6 +56,31 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                requires_vala_extern = true;
 
                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 696c6c8a6..115d4ff98 100644
--- a/codegen/valagirwriter.vala
+++ b/codegen/valagirwriter.vala
@@ -932,7 +932,11 @@ public class Vala.GIRWriter : CodeVisitor {
 
                write_indent ();
                buffer.append_printf ("<enumeration name=\"%s\"", get_gir_name (edomain));
-               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 28a29744c..7bc8eaf83 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -2408,6 +2408,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 a3236b94c..7502294cb 100644
--- a/codegen/valatyperegisterfunction.vala
+++ b/codegen/valatyperegisterfunction.vala
@@ -155,6 +155,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")));
@@ -203,6 +205,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 72b408d5a..d884e9f64 100644
--- a/tests/girwriter/GirTest-1.0.gir-expected
+++ b/tests/girwriter/GirTest-1.0.gir-expected
@@ -37,11 +37,16 @@
        <bitfield name="RenamedBitfield" c:type="GirTestNamedBitfield" glib:type-name="GirTestNamedBitfield" 
glib:get-type="gir_test_named_bitfield_get_type">
                <member name="value1" c:identifier="GIR_TEST_NAMED_BITFIELD_VALUE1" value="1"/>
        </bitfield>
-       <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>
        <enumeration name="RenamedError" c:type="GirTestNamedError" 
glib:error-domain="gir-test-named-error-quark">
                <member name="failed" c:identifier="GIR_TEST_NAMED_ERROR_FAILED" value="0"/>
        </enumeration>
diff --git a/tests/girwriter/girtest.vala b/tests/girwriter/girtest.vala
index 82d146ecc..b2b107385 100644
--- a/tests/girwriter/girtest.vala
+++ b/tests/girwriter/girtest.vala
@@ -111,6 +111,13 @@ namespace GirTest {
                FISHY = 23
        }
 
+       [CCode (has_type_id = false)]
+       public errordomain PlainErrorTest {
+               FAILED,
+               SMELLY,
+               FISHY = 23
+       }
+
        [GIR (name = "RenamedError")]
        public errordomain NamedError {
                FAILED
diff --git a/tests/girwriter/girtest.vapi-expected b/tests/girwriter/girtest.vapi-expected
index 0350bd8e6..48d8832ca 100644
--- a/tests/girwriter/girtest.vapi-expected
+++ b/tests/girwriter/girtest.vapi-expected
@@ -244,6 +244,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")]
        [GIR (name = "RenamedError")]
        public errordomain NamedError {
diff --git a/vala/valaerrorcode.vala b/vala/valaerrorcode.vala
index 525fb7d55..5fcff7585 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]