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



commit d320b88a168b471f39c95f53b2628663aa623c54
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/valaccodeattribute.vala              |  7 ++++
 codegen/valaerrordomainregisterfunction.vala | 51 ++++++++++++++++++++++++++++
 codegen/valagerrormodule.vala                | 24 +++++++++++++
 codegen/valagirwriter.vala                   |  2 +-
 codegen/valagtypemodule.vala                 | 12 +++++++
 codegen/valatyperegisterfunction.vala        | 30 ++++++++++++++++
 vala/valaerrorcode.vala                      | 16 +++++++++
 8 files changed, 142 insertions(+), 1 deletion(-)
---
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index 036652ef3..64f5444f3 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -38,6 +38,7 @@ libvalaccodegen_la_VALASOURCES = \
        valaclassregisterfunction.vala \
        valactype.vala \
        valaenumregisterfunction.vala \
+       valaerrordomainregisterfunction.vala \
        valagasyncmodule.vala \
        valagdbusclientmodule.vala \
        valagdbusmodule.vala \
diff --git a/codegen/valaccodeattribute.vala b/codegen/valaccodeattribute.vala
index 0b89230e8..43b308b59 100644
--- a/codegen/valaccodeattribute.vala
+++ b/codegen/valaccodeattribute.vala
@@ -962,6 +962,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 a0cefb9d1..72d9b55cc 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -54,6 +54,30 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                var cquark_fun = new CCodeFunction (quark_fun_name, get_ccode_name (gquark_type.data_type));
 
                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 macro = "(%s_get_type ())".printf (get_ccode_lower_case_name (edomain, null));
+               decl_space.add_type_declaration (new CCodeMacroReplacement (get_ccode_type_id (edomain), 
macro));
+
+               var fun_name = "%s_get_type".printf (get_ccode_lower_case_name (edomain, null));
+               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 a35036a06..1565066c9 100644
--- a/codegen/valagirwriter.vala
+++ b/codegen/valagirwriter.vala
@@ -727,7 +727,7 @@ public class Vala.GIRWriter : CodeVisitor {
 
                write_indent ();
                buffer.append_printf ("<enumeration name=\"%s\"", edomain.name);
-               write_ctype_attributes (edomain);
+               write_gtype_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 e46573cda..858b7f92d 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -2367,6 +2367,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 c4c860624..00bcd70c2 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/vala/valaerrorcode.vala b/vala/valaerrorcode.vala
index ef5f36410..18d4cce29 100644
--- a/vala/valaerrorcode.vala
+++ b/vala/valaerrorcode.vala
@@ -39,7 +39,23 @@ 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 string? _nick = null;
 
        /**
         * Creates a new enum value.


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