From f557ad91f27c99e94105097cbbc5104c51eb57b8 Mon Sep 17 00:00:00 2001 From: Mathias Hasselmann Date: Sun, 2 Sep 2007 10:12:06 +0000 Subject: [PATCH] adding vapicheck as tool to verify Vala bindings. currently only .metadata 2007-09-02 Mathias Hasselmann * vapigen/Makefile.am, vapigen/valavapicheck.vala: adding vapicheck as tool to verify Vala bindings. currently only .metadata files are checked for unresolved symbols. svn path=/trunk/; revision=573 --- ChangeLog | 6 ++ vapigen/Makefile.am | 22 +++++- vapigen/valavapicheck.vala | 176 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 vapigen/valavapicheck.vala diff --git a/ChangeLog b/ChangeLog index ddc5ce0..396770b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2007-09-02 Mathias Hasselmann + * vapigen/Makefile.am, vapigen/valavapicheck.vala: adding vapicheck + as tool to verify Vala bindings. currently only .metadata files are + checked for unresolved symbols. + +2007-09-02 Mathias Hasselmann + * vapi/packages/gtksourceview-2.0/gtksourceview-2.0.gidl, vapi/packages/gtksourceview-2.0/gtksourceview-2.0.metadata, vapi/gtksourceview-2.0.vala: regenerated for release 1.90.4 diff --git a/vapigen/Makefile.am b/vapigen/Makefile.am index e191a35..f03a121 100644 --- a/vapigen/Makefile.am +++ b/vapigen/Makefile.am @@ -11,9 +11,10 @@ INCLUDES = \ bin_PROGRAMS = \ vapigen \ + vapicheck \ $(NULL) -BUILT_SOURCES = vapigen.vala.stamp +BUILT_SOURCES = vapigen.vala.stamp vapicheck.vala.stamp vapigen_SOURCES = \ vapigen.vala.stamp \ @@ -25,12 +26,31 @@ vapigen_SOURCES = \ valavapigen.vala \ $(NULL) +vapicheck_SOURCES = \ + vapicheck.vala.stamp \ + valavapicheck.c \ + valavapicheck.h \ + valavapicheck.vala \ + $(NULL) + vapigen.vala.stamp: $(filter %.vala,$(vapigen_SOURCES)) $(VALAC) --vapidir $(srcdir)/../vapi --vapidir ../gee --pkg gee --vapidir ../ccode --pkg ccode --vapidir ../vala --pkg vala --vapidir ../gobject-introspection --pkg gidl --pkg config $^ touch $@ +vapicheck.vala.stamp: $(filter %.vala,$(vapicheck_SOURCES)) + $(VALAC) --vapidir $(srcdir)/../vapi --vapidir ../gee --pkg gee --vapidir ../ccode --pkg ccode --vapidir ../vala --pkg vala --vapidir ../gobject-introspection --pkg gidl --pkg config $^ + touch $@ + vapigen_LDADD = \ $(GLIB_LIBS) \ + ../gee/libgee.la \ + ../gobject/libvala.la \ + ../gobject-introspection/libgidl.la \ + $(NULL) + +vapicheck_LDADD = \ + $(GLIB_LIBS) \ + ../gee/libgee.la \ ../gobject/libvala.la \ ../gobject-introspection/libgidl.la \ $(NULL) diff --git a/vapigen/valavapicheck.vala b/vapigen/valavapicheck.vala new file mode 100644 index 0000000..fc4f56d --- /dev/null +++ b/vapigen/valavapicheck.vala @@ -0,0 +1,176 @@ +/* valavapicheck.vala + * + * Copyright (C) 2007 Mathias Hasselmann + * + * 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 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: + * Mathias Hasselmann + */ + +using GLib; + +class Vala.VAPICheck : Object { + public VAPICheck (string! gidlname, construct CodeContext! context = new CodeContext ()) { + gidl = new SourceFile (context, gidlname); + metadata = new SourceFile (context, gidlname.substring (0, gidlname.len () - 5) + ".metadata"); + } + + public CodeContext! context { get; construct; } + public SourceFile! gidl { get; construct; } + public SourceFile! metadata { get; construct; } + + private Gee.List _scope; + private Gee.Set _symbols; + + private void parse_gidl () { + _scope = new Gee.ArrayList (); + _symbols = new Gee.HashSet (str_hash, str_equal); + + foreach (weak IdlModule module in Idl.parse_file (gidl.filename)) { + parse_members (module.name, module.entries); + } + + } + + private void add_symbol (string! name, string separator = null) { + + if (null != separator) { + string fullname = get_scope () + separator + name; + _symbols.add (fullname); + } else { + _symbols.add (name); + } + } + + private string! get_scope () { + return _scope[_scope.size - 1]; + } + + private void enter_scope (string! name) { + _scope.add (name); + add_symbol (name); + } + + private void leave_scope () { + _scope.remove_at (_scope.size - 1); + } + + private void parse_members (string !name, List members) { + enter_scope (name); + + foreach (weak IdlNode node in members) { + switch (node.type) { + case IdlNodeTypeId.ENUM: + parse_members (((IdlNodeEnum) node).gtype_name, + ((IdlNodeEnum) node).values); + break; + + case IdlNodeTypeId.FUNCTION: + parse_members (((IdlNodeFunction) node).symbol, + ((IdlNodeFunction) node).parameters); + break; + + case IdlNodeTypeId.BOXED: + parse_members (((IdlNodeBoxed) node).gtype_name, + ((IdlNodeBoxed) node).members); + break; + + case IdlNodeTypeId.INTERFACE: + case IdlNodeTypeId.OBJECT: + parse_members (((IdlNodeInterface) node).gtype_name, + ((IdlNodeInterface) node).members); + break; + + case IdlNodeTypeId.FIELD: + case IdlNodeTypeId.PARAM: + add_symbol (node.name, "."); + break; + + case IdlNodeTypeId.PROPERTY: + case IdlNodeTypeId.SIGNAL: + add_symbol (node.name, "::"); + break; + + case IdlNodeTypeId.STRUCT: + parse_members (node.name, ((IdlNodeStruct) node).members); + break; + + case IdlNodeTypeId.VALUE: + case IdlNodeTypeId.VFUNC: + // Not appliable? + break; + + default: + warning ("TODO: %s: Implement support for type %d nodes", node.name, node.type); + break; + } + } + + leave_scope (); + } + + private int check_metadata () { + try { + var metafile = new IOChannel.file (metadata.filename, "r"); + string line = null; + int lineno = 1; + + while (IOStatus.NORMAL == metafile.read_line (out line, null, null)) { + var tokens = line.split (" ", 2); + var symbol = tokens[0]; + + if (symbol.size () > 0 && !_symbols.contains (symbol)) { + var src = new SourceReference (metadata, lineno, 1, lineno, (int)symbol.len ()); + Report.error (src, "Symbol `%s' not found".printf (symbol)); + } + + lineno += 1; + } + + return 0; + } catch (FileError error) { + Report.error (null, "%s: %s".printf (metadata.filename, error.message)); + return 1; + } + } + + public int run () { + if (!FileUtils.test (gidl.filename, FileTest.IS_REGULAR)) { + Report.error (null, "%s not found".printf (gidl.filename)); + return 2; + } + + if (!FileUtils.test (metadata.filename, FileTest.IS_REGULAR)) { + Report.error (null, "%s not found".printf (metadata.filename)); + return 2; + } + + parse_gidl (); + + return check_metadata (); + } + + static int main (string[] args) { + if (2 != args.length || !args[1].has_suffix (".gidl")) { + stdout.printf ("Usage: %s library.gidl\n", + Path.get_basename (args[0])); + return 2; + } + + var vapicheck = new VAPICheck (args[1]); + return vapicheck.run (); + } +} -- 2.7.4