From: Jürg Billeter Date: Wed, 7 Mar 2007 21:20:05 +0000 (+0000) Subject: check whether a class implements all abstract methods of base classes fix X-Git-Tag: VALA_0_0_8~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=75ac8a9a324c0b3ad1040cf8be39dad0ffa58d17;p=thirdparty%2Fvala.git check whether a class implements all abstract methods of base classes fix 2007-03-07 Jürg Billeter * vala/valasemanticanalyzer.vala: check whether a class implements all abstract methods of base classes * vala/valacodenode.vala, vala/valadatatype.vala, vala/valaexpression.vala, vala/valaliteral.vala: fix build with added checks svn path=/trunk/; revision=228 --- diff --git a/vala/ChangeLog b/vala/ChangeLog index 18d832fd9..6faa917bc 100644 --- a/vala/ChangeLog +++ b/vala/ChangeLog @@ -1,3 +1,11 @@ +2007-03-07 Jürg Billeter + + * vala/valasemanticanalyzer.vala: check whether a class implements all + abstract methods of base classes + * vala/valacodenode.vala, vala/valadatatype.vala, + vala/valaexpression.vala, vala/valaliteral.vala: fix build with added + checks + 2007-03-07 Jürg Billeter * vala/valaclass.vala: implement get_type_parameter_index diff --git a/vala/vala/valacodenode.vala b/vala/vala/valacodenode.vala index 22a030932..92df6fcb1 100644 --- a/vala/vala/valacodenode.vala +++ b/vala/vala/valacodenode.vala @@ -79,7 +79,8 @@ public abstract class Vala.CodeNode { * * @param visitor the visitor to be called while traversing */ - public abstract void accept (CodeVisitor! visitor); + public virtual void accept (CodeVisitor! visitor) { + } public virtual void replace (CodeNode! old_node, CodeNode! new_node) { } @@ -108,10 +109,10 @@ public abstract class Vala.CodeNode { * * @return a string representation */ - public ref string to_string () { + public virtual ref string! to_string () { if (source_reference != null) { return source_reference.to_string (); } - return null; + return "(unknown)"; } } diff --git a/vala/vala/valadatatype.vala b/vala/vala/valadatatype.vala index 15ce34395..d9585c11e 100644 --- a/vala/vala/valadatatype.vala +++ b/vala/vala/valadatatype.vala @@ -173,7 +173,9 @@ public abstract class Vala.DataType : CodeNode { * name or null * @return the upper case name to be used in C code */ - public abstract ref string get_upper_case_cname (string infix = null); + public virtual ref string get_upper_case_cname (string infix = null) { + return null; + } /** * Returns the C name of this data type in lower case. Words are @@ -184,7 +186,9 @@ public abstract class Vala.DataType : CodeNode { * name or null * @return the lower case name to be used in C code */ - public abstract ref string get_lower_case_cname (string infix = null); + public virtual ref string get_lower_case_cname (string infix = null) { + return null; + } /** * Returns the string to be prefixed to members of this data type in @@ -192,7 +196,9 @@ public abstract class Vala.DataType : CodeNode { * * @return the lower case prefix to be used in C code */ - public abstract ref string get_lower_case_cprefix (); + public virtual ref string get_lower_case_cprefix () { + return null; + } /** * Returns a list of C header filenames users of this data type must diff --git a/vala/vala/valaexpression.vala b/vala/vala/valaexpression.vala index b4a44b2db..38a8a9f72 100644 --- a/vala/vala/valaexpression.vala +++ b/vala/vala/valaexpression.vala @@ -1,6 +1,6 @@ /* valaexpression.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -73,6 +73,4 @@ public abstract class Vala.Expression : CodeNode { * The code generator sets and uses them for memory management. */ public List temp_vars; - - public abstract ref string! to_string (); } diff --git a/vala/vala/valaliteral.vala b/vala/vala/valaliteral.vala index aab9f21db..01886bf9f 100644 --- a/vala/vala/valaliteral.vala +++ b/vala/vala/valaliteral.vala @@ -1,6 +1,6 @@ /* valaliteral.vala * - * Copyright (C) 2006 Jürg Billeter + * Copyright (C) 2006-2007 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,6 +30,4 @@ public abstract class Vala.Literal : CodeNode { * Specifies the type of this literal. */ public TypeReference static_type { get; set; } - - public abstract ref string! to_string (); } diff --git a/vala/vala/valasemanticanalyzer.vala b/vala/vala/valasemanticanalyzer.vala index 6af2738bf..344046aed 100644 --- a/vala/vala/valasemanticanalyzer.vala +++ b/vala/vala/valasemanticanalyzer.vala @@ -178,22 +178,44 @@ public class Vala.SemanticAnalyzer : CodeVisitor { Report.error (cl.source_reference, error_string); } - /* all virtual symbols defined in interfaces have to be at least defined (or implemented) also in this type */ + /* all abstract symbols defined in base types have to be at least defined (or implemented) also in this type */ foreach (TypeReference base_type in cl.get_base_types ()) { if (base_type.data_type is Interface) { - Interface iface = (Interface)base_type.data_type; - + Interface iface = (Interface) base_type.data_type; + /* We do not need to do expensive equality checking here since this is done * already. We only need to guarantee the symbols are present. */ - + /* check methods */ foreach (Method m in iface.get_methods ()) { - if (cl.symbol.lookup (m.name) == null && m.is_abstract) { - cl.error = true; - Report.error (cl.source_reference, "`%s' does not implement interface method `%s'".printf (cl.symbol.get_full_name (), m.symbol.get_full_name ())); + if (m.is_abstract) { + var sym = cl.symbol.lookup (m.name); + if (sym == null || !(sym.node is Method) || ((Method) sym.node).base_interface_method != m) { + cl.error = true; + Report.error (cl.source_reference, "`%s' does not implement interface method `%s'".printf (cl.symbol.get_full_name (), m.symbol.get_full_name ())); + } + } + } + } + } + + /* all abstract symbols defined in base classes have to be implemented in non-abstract classes + * VAPI classes don't have to specify overridden methods + */ + if (!cl.is_abstract && !cl.source_reference.file.pkg) { + var base_class = cl.base_class; + while (base_class != null && base_class.is_abstract) { + foreach (Method m in base_class.get_methods ()) { + if (m.is_abstract) { + var sym = cl.symbol.lookup (m.name); + if (sym == null || !(sym.node is Method) || ((Method) sym.node).base_method != m) { + cl.error = true; + Report.error (cl.source_reference, "`%s' does not implement abstract method `%s'".printf (cl.symbol.get_full_name (), m.symbol.get_full_name ())); + } } } + base_class = base_class.base_class; } }