add `g_type_interface_add_prerequisite' calls during interface type
authorRaffaele Sandrini <rasa@gmx.ch>
Mon, 5 Mar 2007 13:10:00 +0000 (13:10 +0000)
committerRaffaele Sandrini <rasa@src.gnome.org>
Mon, 5 Mar 2007 13:10:00 +0000 (13:10 +0000)
2007-03-05  Raffaele Sandrini  <rasa@gmx.ch>

* vala/valainterfaceregisterfunction.vala: add
  `g_type_interface_add_prerequisite' calls during interface type
  creation
* vala/valasemanticanalyzer.vala: add checks for consistent interface
  prerequisites and whether classes are obeying them

svn path=/trunk/; revision=224

vala/ChangeLog
vala/vala/valainterfaceregisterfunction.vala
vala/vala/valasemanticanalyzer.vala

index 1820894..5dd80d1 100644 (file)
@@ -1,3 +1,11 @@
+2007-03-05  Raffaele Sandrini  <rasa@gmx.ch>
+
+       * vala/valainterfaceregisterfunction.vala: add
+         `g_type_interface_add_prerequisite' calls during interface type
+         creation
+       * vala/valasemanticanalyzer.vala: add checks for consistent interface
+         prerequisites and whether classes are obeying them
+
 2007-03-04  Jürg Billeter  <j@bitron.ch>
 
        * configure.ac: Post-release version bump
index 2c9de10..42fcbaf 100644 (file)
@@ -1,6 +1,6 @@
 /* valainterfaceregisterfunction.vala
  *
- * Copyright (C) 2006  Jürg Billeter
+ * Copyright (C) 2006-2007  Jürg Billeter, Raffaele Sandrini
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,6 +18,7 @@
  *
  * Author:
  *     Jürg Billeter <j@bitron.ch>
+ *     Raffaele Sandrini <rasa@gmx.ch>
  */
 
 using GLib;
@@ -62,6 +63,17 @@ public class Vala.InterfaceRegisterFunction : TypeRegisterFunction {
        public override ref CCodeFragment! get_type_interface_init_statements () {
                var frag = new CCodeFragment ();
                
+               /* register all prerequisites */
+               foreach (TypeReference prereq_ref in interface_reference.get_prerequisites ()) {
+                       var prereq = prereq_ref.data_type;
+                       
+                       var func = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_add_prerequisite"));
+                       func.add_argument (new CCodeIdentifier ("g_define_type_id"));
+                       func.add_argument (new CCodeIdentifier (prereq.get_type_id()));
+                       
+                       frag.append (new CCodeExpressionStatement (func));
+               }
+               
                return frag;
        }
 }
index 34aa9a6..4857c14 100644 (file)
@@ -117,8 +117,67 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        current_source_file.add_symbol_dependency (base_type_reference.data_type.symbol, SourceFileDependencyType.HEADER_FULL);
                }
        }
-
+       
+       private ref List<DataType> get_all_prerequisites (Interface! iface) {
+               List<DataType> ret = null;
+               
+               foreach (TypeReference prereq in iface.get_prerequisites ()) {
+                       DataType type = prereq.data_type;
+                       /* skip on previous errors */
+                       if (type == null) {
+                               continue;
+                       }
+                       
+                       ret.prepend (type);
+                       if (type is Interface) {
+                               ret.concat (get_all_prerequisites ((Interface)type));
+                               
+                       }
+               }
+               
+               return ret.reverse ();
+       }
+       
        public override void visit_end_class (Class! cl) {
+               /* gather all prerequisites */
+               List<DataType> prerequisites = null;
+               foreach (TypeReference base_type in cl.get_base_types ()) {
+                       if (base_type.data_type is Interface) {
+                               prerequisites.concat (get_all_prerequisites ((Interface)base_type.data_type));
+                       }
+               }
+               /* check whether all prerequisites are met */
+               List<string> missing_prereqs = null;
+               foreach (DataType prereq in prerequisites) {
+                       bool found = false;
+                       foreach (TypeReference base_type in cl.get_base_types ()) {
+                               if (base_type.data_type == prereq) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+                       if (!found) {
+                               missing_prereqs.prepend (prereq.symbol.get_full_name ());
+                       }
+               }
+               /* report any missing prerequisites */
+               if (missing_prereqs != null) {
+                       cl.error = true;
+                       
+                       string error_string = "%s: some prerequisites (".printf (cl.symbol.get_full_name ());
+                       bool first = true;
+                       foreach (string s in missing_prereqs) {
+                               if (first) {
+                                       error_string = "%s`%s'".printf (error_string, s);
+                                       first = false;
+                               } else {
+                                       error_string = "%s, `%s'".printf (error_string, s);
+                               }
+                       }
+                       error_string += ") are not met";
+                       Report.error (cl.source_reference, error_string);
+               }
+               
                current_symbol = current_symbol.parent_symbol;
                current_class = null;
        }
@@ -142,6 +201,27 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_end_interface (Interface! iface) {
+               /* check prerequisites */
+               Class prereq_class;
+               foreach (TypeReference prereq in iface.get_prerequisites ()) {
+                       DataType class_or_interface = prereq.data_type;
+                       /* skip on previous errors */
+                       if (class_or_interface == null) {
+                               iface.error = true;
+                               continue;
+                       }
+                       /* interfaces are not allowed to have multiple instantiable prerequisites */
+                       if (class_or_interface is Class) {
+                               if (prereq_class != null) {
+                                       iface.error = true;
+                                       Report.error (iface.source_reference, "%s: Interfaces cannot have multiple instantiable prerequisites (`%s' and `%s')".printf (iface.symbol.get_full_name (), class_or_interface.symbol.get_full_name (), prereq_class.symbol.get_full_name ()));
+                                       return;
+                               }
+                               
+                               prereq_class = (Class)class_or_interface;
+                       }
+               }
+               
                current_symbol = current_symbol.parent_symbol;
        }