From 44af0246c480b9421f391dd71376298b43a99e2a Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Wed, 3 Dec 2014 12:39:23 +0100 Subject: [PATCH] Warn about unused attributes This may not be the best approach, but it's a start --- compiler/valacompiler.vala | 6 ++ vala/Makefile.am | 1 + vala/valacodecontext.vala | 6 ++ vala/valausedattr.vala | 186 +++++++++++++++++++++++++++++++++++++ vapi/glib-2.0.vapi | 1 - 5 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 vala/valausedattr.vala diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index 3f881244d..fe0fdb9ae 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -457,6 +457,12 @@ class Vala.Compiler { context.write_dependencies (dependencies); } + context.used_attr.check_unused (context); + + if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) { + return quit (); + } + if (!ccode_only) { var ccompiler = new CCodeCompiler (); if (cc_command == null && Environment.get_variable ("CC") != null) { diff --git a/vala/Makefile.am b/vala/Makefile.am index c7fbc0e4e..a5a99d173 100644 --- a/vala/Makefile.am +++ b/vala/Makefile.am @@ -156,6 +156,7 @@ libvalacore_la_VALASOURCES = \ valaunlockstatement.vala \ valaunresolvedsymbol.vala \ valaunresolvedtype.vala \ + valausedattr.vala \ valausingdirective.vala \ valavaluetype.vala \ valavariable.vala \ diff --git a/vala/valacodecontext.vala b/vala/valacodecontext.vala index 00c242c50..b9ac824c2 100644 --- a/vala/valacodecontext.vala +++ b/vala/valacodecontext.vala @@ -230,10 +230,16 @@ public class Vala.CodeContext { */ public CodeGenerator codegen { get; set; } + /** + * Mark attributes used by the compiler and report unused at the end. + */ + public UsedAttr used_attr { get; set; } + public CodeContext () { resolver = new SymbolResolver (); analyzer = new SemanticAnalyzer (); flow_analyzer = new FlowAnalyzer (); + used_attr = new UsedAttr (); } /** diff --git a/vala/valausedattr.vala b/vala/valausedattr.vala new file mode 100644 index 000000000..ecd4c0622 --- /dev/null +++ b/vala/valausedattr.vala @@ -0,0 +1,186 @@ +/* valaunusedattr.vala + * + * Copyright (C) 2014-2015 Jürg Billeter + * Copyright (C) 2014-2015 Luca Bruno + * + * 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: + * Luca Bruno + */ + +using GLib; + +/** + * Code visitor to warn about unused attributes + */ +public class Vala.UsedAttr : CodeVisitor { + public Vala.Map> marked = new HashMap> (str_hash, str_equal); + + const string valac_default_attrs[] = { + "CCode", "type_signature", "default_value", "set_value_function", "type_id", "cprefix", "cheader_filename", + "marshaller_type_name", "get_value_function", "cname", "cheader_filename", "destroy_function", "lvalue_access", + "has_type_id", "instance_pos", "const_cname", "take_value_function", "copy_function", "free_function", + "param_spec_function", "has_target", "type_cname", "ref_function", "ref_function_void", "unref_function", "type", + "has_construct_function", "returns_floating_reference", "gir_namespace", "gir_version", "construct_function", + "lower_case_cprefix", "simple_generics", "sentinel", "scope", "has_destroy_function", + "has_copy_function", "lower_case_csuffix", "ref_sink_function", "dup_function", "finish_function", + "array_length_type", "array_length", "array_length_cname", "array_length_cexpr", "array_null_terminated", + "vfunc_name", "finish_name", "free_function_address_of", "pos", "delegate_target", "delegate_target_cname", "", + + "Immutable", "", + "Compact", "", + "Flags", "", + "Experimental", "", + "NoReturn", "", + "Assert", "", + "ErrorBase", "", + "Deprecated", "since", "replacement", "", + + "IntegerType", "rank", "min", "max", "", + "FloatingType", "rank", "", + "BooleanType", "", + "SimpleType", "", + "PrintfFormat", "", + + "GIR", "name", "", + + }; + + public UsedAttr () { + // mark default valac attrs + var curattr = ""; + foreach (unowned string val in valac_default_attrs) { + if (val == "") { + curattr = ""; + } else { + if (curattr == "") { + curattr = val; + mark (curattr, null); + } else { + mark (curattr, val); + } + } + } + } + + /** + * Mark the attribute or attribute argument as used by the compiler + */ + public void mark (string attribute, string? argument) { + var set = marked.get (attribute); + if (set == null) { + set = new HashSet (str_hash, str_equal); + marked.set (attribute, set); + } + + if (argument != null) { + set.add (argument); + } + } + + /** + * Traverse the code tree and warn about unused attributes. + * + * @param context a code context + */ + public void check_unused (CodeContext context) { + context.root.accept (this); + } + + void check_unused_attr (Symbol sym) { + // optimize by not looking at all the symbols + if (sym.used) { + foreach (unowned Attribute attr in sym.attributes) { + var set = marked.get (attr.name); + if (set == null) { + Report.warning (attr.source_reference, "attribute `%s' never used".printf (attr.name)); + } else { + foreach (var arg in attr.args.get_keys()) { + if (!set.contains (arg)) { + Report.warning (attr.source_reference, "argument `%s' never used".printf (arg)); + } + } + } + } + } + } + + public override void visit_namespace (Namespace ns) { + check_unused_attr (ns); + ns.accept_children (this); + } + + public override void visit_class (Class cl) { + check_unused_attr (cl); + cl.accept_children (this); + } + + public override void visit_struct (Struct st) { + check_unused_attr (st); + st.accept_children (this); + } + + public override void visit_interface (Interface iface) { + check_unused_attr (iface); + iface.accept_children (this); + } + + public override void visit_enum (Enum en) { + check_unused_attr (en); + en.accept_children (this); + } + + public override void visit_error_domain (ErrorDomain ed) { + check_unused_attr (ed); + ed.accept_children (this); + } + + public override void visit_delegate (Delegate cb) { + check_unused_attr (cb); + cb.accept_children (this); + } + + public override void visit_constant (Constant c) { + check_unused_attr (c); + } + + public override void visit_field (Field f) { + check_unused_attr (f); + } + + public override void visit_method (Method m) { + check_unused_attr (m); + m.accept_children (this); + } + + public override void visit_creation_method (CreationMethod m) { + check_unused_attr (m); + m.accept_children (this); + } + + public override void visit_formal_parameter (Parameter p) { + check_unused_attr (p); + } + + public override void visit_property (Property prop) { + check_unused_attr (prop); + } + + public override void visit_signal (Signal sig) { + check_unused_attr (sig); + sig.accept_children (this); + } +} diff --git a/vapi/glib-2.0.vapi b/vapi/glib-2.0.vapi index 8ce14333b..7a7c20ee4 100644 --- a/vapi/glib-2.0.vapi +++ b/vapi/glib-2.0.vapi @@ -5016,7 +5016,6 @@ namespace GLib { } [Compact] - [CCode (copy_func = "g_variant_iter_copy", free_func = "g_variant_iter_free")] public class VariantIter { public VariantIter (Variant value); public size_t n_children (); -- 2.47.2