/* 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", "destroy_function", "lvalue_access", "has_type_id", "instance_pos", "const_cname", "take_value_function", "copy_function", "free_function", "param_spec_function", "has_target", "has_typedef", "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", "ordering", "type_check_function", "type_get_function", "has_copy_function", "lower_case_csuffix", "ref_sink_function", "dup_function", "finish_function", "generic_type_pos", "array_length_type", "array_length", "array_length_cname", "array_length_cexpr", "array_null_terminated", "vfunc_name", "finish_vfunc_name", "finish_name", "free_function_address_of", "pos", "delegate_target", "delegate_target_cname", "array_length_pos", "delegate_target_pos", "destroy_notify_pos", "ctype", "has_new_function", "notify", "finish_instance", "use_inplace", "feature_test_macro", "default_value_on_error", "async_result_pos", "error_pos", "destroy_notify_cname", "", "Immutable", "", "SingleInstance", "", "Compact", "opaque", "", "NoWrapper", "", "NoThrow", "", "DestroysInstance", "", "Flags", "", "Experimental", "", // deprecated "NoReturn", "", "NoArrayLength", "", // deprecated "Assert", "", "ErrorBase", "", "GenericAccessors", "", "Diagnostics", "", "NoAccessorMethod", "", "ConcreteAccessor", "", "HasEmitter", "", "ReturnsModifiedPointer", "", "Deprecated", "since", "replacement", "", // deprecated "Version", "since", "replacement", "deprecated", "deprecated_since", "experimental", "experimental_until", "", "Signal", "detailed", "run", "no_recurse", "action", "no_hooks", "", "Description", "nick", "blurb", "", "IntegerType", "rank", "min", "max", "signed", "width", "", "FloatingType", "rank", "decimal", "width", "", "BooleanType", "", "SimpleType", "", "PointerType", "", "Print", "", "PrintfFormat", "", "ScanfFormat", "", "FormatArg", "", "Source", "filename", "line", "column", "", "GtkChild", "name", "internal", "", "GtkTemplate", "ui", "", "GtkCallback", "name", "", "ModuleInit", "", "Profile", "", "DBus", "name", "no_reply", "result", "use_string_marshalling", "value", "signature", "visible", "timeout", "", "GIR", "fullname", "name", "visible", "" }; 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) { 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", attr.name); } else { foreach (var arg in attr.args.get_keys()) { if (!set.contains (arg)) { Report.warning (attr.source_reference, "Argument `%s' never used", 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); } }