From b9202be13671bc0b6440f638fda773e3003e4675 Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Tue, 11 Mar 2008 13:25:53 +0000 Subject: [PATCH] add GIdlWriter to generate .gidl files when building libraries 2008-03-11 Juerg Billeter * gobject/Makefile.am, gobject/valagidlwriter.vala, compiler/valacompiler.vala: add GIdlWriter to generate .gidl files when building libraries svn path=/trunk/; revision=1122 --- ChangeLog | 6 + compiler/valacompiler.vala | 14 +- gobject/Makefile.am | 1 + gobject/valagidlwriter.vala | 489 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 509 insertions(+), 1 deletion(-) create mode 100644 gobject/valagidlwriter.vala diff --git a/ChangeLog b/ChangeLog index d4951e8..3ee8325 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2008-03-11 Jürg Billeter + * gobject/Makefile.am, gobject/valagidlwriter.vala, + compiler/valacompiler.vala: add GIdlWriter to generate .gidl files + when building libraries + +2008-03-11 Jürg Billeter + * gobject-introspection/grealpath.h: add missing file 2008-03-10 Jürg Billeter diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala index a589f5e..8d0b7c8 100644 --- a/compiler/valacompiler.vala +++ b/compiler/valacompiler.vala @@ -269,7 +269,19 @@ class Vala.Compiler : Object { } interface_writer.write_file (context, vapi_filename); - + + + var gidl_writer = new GIdlWriter (); + string gidl_filename = "%s.gidl".printf (library); + + // put .gidl file in current directory unless -d has been explicitly specified + if (directory != null) { + gidl_filename = "%s/%s".printf (context.directory, gidl_filename); + } + + gidl_writer.write_file (context, gidl_filename); + + library = null; } diff --git a/gobject/Makefile.am b/gobject/Makefile.am index ed08457..f8b471f 100644 --- a/gobject/Makefile.am +++ b/gobject/Makefile.am @@ -32,6 +32,7 @@ libvala_la_VALASOURCES = \ valadbusbindingprovider.vala \ valadbusmethod.vala \ valadbussignal.vala \ + valagidlwriter.vala \ valainterfaceregisterfunction.vala \ valatyperegisterfunction.vala \ $(NULL) diff --git a/gobject/valagidlwriter.vala b/gobject/valagidlwriter.vala new file mode 100644 index 0000000..eeeb9c9 --- /dev/null +++ b/gobject/valagidlwriter.vala @@ -0,0 +1,489 @@ +/* valagidlwriter.vala + * + * Copyright (C) 2008 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 + * 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: + * Jürg Billeter + */ + +using GLib; +using Gee; + +/** + * Code visitor generating .gidl file for the public interface. + */ +public class Vala.GIdlWriter : CodeVisitor { + private CodeContext context; + + FileStream stream; + + int indent; + + private Typesymbol gobject_type; + + /** + * Writes the public interface of the specified code context into the + * specified file. + * + * @param context a code context + * @param filename a relative or absolute filename + */ + public void write_file (CodeContext! context, string! filename) { + this.context = context; + + var root_symbol = context.root; + var glib_ns = root_symbol.scope.lookup ("GLib"); + gobject_type = (Typesymbol) glib_ns.scope.lookup ("Object"); + + stream = FileStream.open (filename, "w"); + + stream.printf ("\n"); + + stream.printf ("\n"); + + context.accept (this); + + stream.printf ("\n"); + + stream = null; + } + + public override void visit_namespace (Namespace! ns) { + if (ns.pkg) { + return; + } + + if (ns.name == null) { + // global namespace + ns.accept_children (this); + return; + } + + write_indent (); + stream.printf ("\n", ns.name); + indent++; + + ns.accept_children (this); + + indent--; + write_indent (); + stream.printf ("\n"); + } + + public override void visit_class (Class! cl) { + if (cl.source_reference != null && cl.source_reference.file.pkg) { + return; + } + + if (!check_accessibility (cl)) { + return; + } + + if (cl.is_subtype_of (gobject_type)) { + write_indent (); + stream.printf ("\n"); + indent++; + + // write implemented interfaces + bool first = true; + foreach (DataType base_type in cl.get_base_types ()) { + var iface_type = base_type as InterfaceType; + if (iface_type != null) { + if (first) { + write_indent (); + stream.printf ("\n"); + indent++; + first = false; + } + write_indent (); + stream.printf ("\n", iface_type.interface_symbol.get_full_name ()); + } + } + if (!first) { + indent--; + write_indent (); + stream.printf ("\n"); + } + + cl.accept_children (this); + + indent--; + write_indent (); + stream.printf ("\n"); + } else { + write_indent (); + stream.printf ("\n"); + indent++; + + cl.accept_children (this); + + indent--; + write_indent (); + stream.printf ("\n"); + } + } + + public override void visit_struct (Struct! st) { + if (st.source_reference != null && st.source_reference.file.pkg) { + return; + } + + if (!check_accessibility (st)) { + return; + } + + write_indent (); + stream.printf ("\n"); + indent++; + + st.accept_children (this); + + indent--; + write_indent (); + stream.printf ("\n"); + } + + public override void visit_interface (Interface! iface) { + if (iface.source_reference != null && iface.source_reference.file.pkg) { + return; + } + + if (!check_accessibility (iface)) { + return; + } + + write_indent (); + stream.printf ("\n"); + indent++; + + // write prerequisites + if (iface.get_prerequisites ().size > 0) { + write_indent (); + stream.printf ("\n"); + indent++; + + foreach (DataType base_type in iface.get_prerequisites ()) { + var class_type = base_type as ClassType; + var iface_type = base_type as InterfaceType; + if (class_type != null) { + write_indent (); + stream.printf ("\n", class_type.class_symbol.get_full_name ()); + } else if (iface_type != null) { + write_indent (); + stream.printf ("\n", iface_type.interface_symbol.get_full_name ()); + } else { + assert_not_reached (); + } + } + + indent--; + write_indent (); + stream.printf ("\n"); + } + + iface.accept_children (this); + + indent--; + write_indent (); + stream.printf ("\n"); + } + + public override void visit_enum (Enum! en) { + if (en.source_reference != null && en.source_reference.file.pkg) { + return; + } + + if (!check_accessibility (en)) { + return; + } + + write_indent (); + stream.printf ("\n"); + indent++; + + en.accept_children (this); + + indent--; + write_indent (); + stream.printf ("\n"); + } + + public override void visit_enum_value (EnumValue! ev) { + write_indent (); + stream.printf ("\n", ev.get_cname ()); + } + + public override void visit_error_domain (ErrorDomain edomain) { + if (edomain.source_reference != null && edomain.source_reference.file.pkg) { + return; + } + + if (!check_accessibility (edomain)) { + return; + } + + write_indent (); + stream.printf ("\n"); + indent++; + + edomain.accept_children (this); + + indent--; + write_indent (); + stream.printf ("\n"); + } + + public override void visit_error_code (ErrorCode ecode) { + write_indent (); + stream.printf ("\n", ecode.get_cname ()); + } + + public override void visit_constant (Constant! c) { + if (c.source_reference != null && c.source_reference.file.pkg) { + return; + } + + if (!check_accessibility (c)) { + return; + } + + write_indent (); + stream.printf ("\n", c.get_cname ()); + } + + public override void visit_field (Field! f) { + if (f.source_reference != null && f.source_reference.file.pkg) { + return; + } + + if (!check_accessibility (f)) { + return; + } + + write_indent (); + stream.printf ("\n", f.get_cname ()); + } + + private string get_gidl_type_name (DataType type) { + // workaround to get GIDL-specific type name + string gidl_type = type.get_cname (); + if (type.data_type != null) { + string cname = type.data_type.get_cname (); + if (gidl_type.has_prefix (cname)) { + gidl_type = type.data_type.get_full_name () + gidl_type.substring (cname.len (), gidl_type.len () - cname.len ()); + } + } else if (type is DelegateType) { + var dt = (DelegateType) type; + string cname = dt.get_cname (); + if (gidl_type.has_prefix (cname)) { + gidl_type = dt.delegate_symbol.get_full_name () + gidl_type.substring (cname.len (), gidl_type.len () - cname.len ()); + } + } + return gidl_type; + } + + private void write_params (Collection params, DataType? instance_type = null) { + write_indent (); + stream.printf ("\n"); + indent++; + + if (instance_type != null) { + write_indent (); + stream.printf ("\n", get_gidl_type_name (instance_type)); + } + + foreach (FormalParameter param in params) { + write_indent (); + stream.printf ("\n"); + } + + indent--; + write_indent (); + stream.printf ("\n"); + } + + public override void visit_delegate (Delegate! cb) { + if (cb.source_reference != null && cb.source_reference.file.pkg) { + return; + } + + if (!check_accessibility (cb)) { + return; + } + + write_indent (); + stream.printf ("\n"); + indent++; + + write_params (cb.get_parameters ()); + + write_return_type (cb.return_type); + + indent--; + write_indent (); + stream.printf ("\n"); + } + + public override void visit_method (Method! m) { + if (m.source_reference != null && m.source_reference.file.pkg) { + return; + } + + // don't write interface implementation unless it's an abstract or virtual method + if (!check_accessibility (m) || m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) { + return; + } + + write_indent (); + stream.printf ("\n"); + indent++; + + DataType instance_type = null; + if (m.instance) { + instance_type = CCodeGenerator.get_data_type_for_symbol ((Typesymbol) m.parent_symbol); + } + + write_params (m.get_parameters (), instance_type); + + write_return_type (m.return_type); + + indent--; + write_indent (); + stream.printf ("\n"); + } + + public override void visit_creation_method (CreationMethod! m) { + if (m.source_reference != null && m.source_reference.file.pkg) { + return; + } + + if (!check_accessibility (m)) { + return; + } + + string name = "new"; + if (m.name.has_prefix (".new.")) { + name = m.name.substring (5, m.name.len () - 5); + } + + write_indent (); + stream.printf ("\n"); + indent++; + + write_params (m.get_parameters ()); + + write_return_type (CCodeGenerator.get_data_type_for_symbol ((Typesymbol) m.parent_symbol)); + + indent--; + write_indent (); + stream.printf ("\n"); + } + + public override void visit_property (Property! prop) { + if (!check_accessibility (prop) || prop.overrides || prop.base_interface_property != null) { + return; + } + + write_indent (); + stream.printf ("\n"); + } + + public override void visit_signal (Signal! sig) { + if (!check_accessibility (sig)) { + return; + } + + write_indent (); + stream.printf ("\n"); + indent++; + + write_params (sig.get_parameters ()); + + write_return_type (sig.return_type); + + indent--; + write_indent (); + stream.printf ("\n"); + } + + private void write_indent () { + int i; + + for (i = 0; i < indent; i++) { + stream.putc ('\t'); + } + } + + private void write_return_type (DataType! type) { + write_indent (); + stream.printf ("\n"); + } + + private bool check_accessibility (Symbol! sym) { + if (sym.access == SymbolAccessibility.PUBLIC || + sym.access == SymbolAccessibility.PROTECTED) { + return true; + } + + return false; + } +} -- 2.7.4