3 * Copyright (C) 2008 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jürg Billeter <j@bitron.ch>
27 * Code visitor generating .gir file for the public interface.
29 public class Vala
.GIRWriter
: CodeVisitor
{
30 private CodeContext context
;
36 private TypeSymbol gobject_type
;
39 * Writes the public interface of the specified code context into the
42 * @param context a code context
43 * @param filename a relative or absolute filename
45 public void write_file (CodeContext context
, string filename
) {
46 this
.context
= context
;
48 var root_symbol
= context
.root
;
49 var glib_ns
= root_symbol
.scope
.lookup ("GLib");
50 gobject_type
= (TypeSymbol
) glib_ns
.scope
.lookup ("Object");
52 stream
= FileStream
.open (filename
, "w");
54 stream
.printf ("<?xml version=\"1.0\"?>\n");
56 stream
.printf ("<repository version=\"1.0\">\n");
58 context
.accept (this
);
60 stream
.printf ("</repository>\n");
65 public override void visit_namespace (Namespace ns
) {
66 if (ns
.external_package
) {
70 if (ns
.name
== null) {
72 ns
.accept_children (this
);
76 if (ns
.parent_symbol
.name
!= null) {
78 // not supported in GIR at the moment
83 stream
.printf ("<namespace name=\"%s\" version=\"1.0\">\n", ns
.name
);
86 ns
.accept_children (this
);
90 stream
.printf ("</namespace>\n");
93 public override void visit_class (Class cl
) {
94 if (cl
.external_package
) {
98 if (!check_accessibility (cl
)) {
102 if (cl
.is_subtype_of (gobject_type
)) {
104 stream
.printf ("<class name=\"%s\"", cl
.name
);
105 stream
.printf (" parent=\"%s\"", cl
.base_class
.get_full_name ());
106 stream
.printf (" glib:type-name=\"%s\"", cl
.get_cname ());
107 stream
.printf (" glib:get-type=\"%sget_type\"", cl
.get_lower_case_cprefix ());
108 stream
.printf (">\n");
111 // write implemented interfaces
113 foreach (DataType base_type
in cl
.get_base_types ()) {
114 var object_type
= (ObjectType
) base_type
;
115 if (object_type
.type_symbol is Interface
) {
118 stream
.printf ("<implements>\n");
123 stream
.printf ("<interface name=\"%s\"/>\n", object_type
.type_symbol
.get_full_name ());
129 stream
.printf ("</implements>\n");
132 cl
.accept_children (this
);
136 stream
.printf ("</class>\n");
139 stream
.printf ("<record name=\"%s\"", cl
.name
);
140 stream
.printf (">\n");
143 cl
.accept_children (this
);
147 stream
.printf ("</record>\n");
151 public override void visit_struct (Struct st
) {
152 if (st
.external_package
) {
156 if (!check_accessibility (st
)) {
161 stream
.printf ("<record name=\"%s\"", st
.name
);
162 stream
.printf (">\n");
165 st
.accept_children (this
);
169 stream
.printf ("</record>\n");
172 public override void visit_interface (Interface iface
) {
173 if (iface
.external_package
) {
177 if (!check_accessibility (iface
)) {
182 stream
.printf ("<interface name=\"%s\"", iface
.name
);
183 stream
.printf (" glib:get-type=\"%sget_type\"", iface
.get_lower_case_cprefix ());
184 stream
.printf (">\n");
187 // write prerequisites
188 if (iface
.get_prerequisites ().size
> 0) {
190 stream
.printf ("<requires>\n");
193 foreach (DataType base_type
in iface
.get_prerequisites ()) {
194 var object_type
= (ObjectType
) base_type
;
195 if (object_type
.type_symbol is Class
) {
197 stream
.printf ("<object name=\"%s\"/>\n", object_type
.type_symbol
.get_full_name ());
198 } else if (object_type
.type_symbol is Interface
) {
200 stream
.printf ("<interface name=\"%s\"/>\n", object_type
.type_symbol
.get_full_name ());
202 assert_not_reached ();
208 stream
.printf ("</requires>\n");
211 iface
.accept_children (this
);
215 stream
.printf ("</interface>\n");
218 public override void visit_enum (Enum en
) {
219 if (en
.external_package
) {
223 if (!check_accessibility (en
)) {
228 stream
.printf ("<enumeration name=\"%s\"", en
.name
);
229 stream
.printf (" c:type=\"%s\"", en
.get_cname ());
230 stream
.printf (" glib:get-type=\"%sget_type\"", en
.get_lower_case_cprefix ());
231 stream
.printf (">\n");
234 en
.accept_children (this
);
238 stream
.printf ("</enumeration>\n");
241 public override void visit_enum_value (EnumValue ev
) {
243 stream
.printf ("<member name=\"%s\"/>\n", string.joinv ("-", ev
.name
.down ().split ("_")));
246 public override void visit_error_domain (ErrorDomain edomain
) {
247 if (edomain
.external_package
) {
251 if (!check_accessibility (edomain
)) {
256 stream
.printf ("<errordomain name=\"%s\"", edomain
.get_cname ());
257 stream
.printf (">\n");
260 edomain
.accept_children (this
);
264 stream
.printf ("</errordomain>\n");
267 public override void visit_error_code (ErrorCode ecode
) {
269 stream
.printf ("<member name=\"%s\"/>\n", ecode
.get_cname ());
272 public override void visit_constant (Constant c
) {
273 if (c
.external_package
) {
277 if (!check_accessibility (c
)) {
282 stream
.printf ("<constant name=\"%s\"/>\n", c
.get_cname ());
285 public override void visit_field (Field f
) {
286 if (f
.external_package
) {
290 if (!check_accessibility (f
)) {
295 stream
.printf ("<field name=\"%s\">\n", f
.get_cname ());
298 write_type (f
.field_type
);
302 stream
.printf ("</field>\n");
305 private void write_params (Gee
.List
<FormalParameter
> params
, DataType? instance_type
= null) {
307 stream
.printf ("<parameters>\n");
310 if (instance_type
!= null) {
312 stream
.printf ("<parameter name=\"self\">\n");
315 write_type (instance_type
);
319 stream
.printf ("</parameter>\n");
322 foreach (FormalParameter param
in params
) {
324 stream
.printf ("<parameter name=\"%s\"", param
.name
);
325 if (param
.direction
== ParameterDirection
.REF
) {
326 stream
.printf (" direction=\"inout\"");
328 if (param
.parameter_type
.value_owned
) {
329 stream
.printf (" transfer-ownership=\"full\"");
331 } else if (param
.direction
== ParameterDirection
.OUT
) {
333 stream
.printf (" direction=\"out\"");
334 if (param
.parameter_type
.value_owned
) {
335 stream
.printf (" transfer-ownership=\"full\"");
338 // normal in paramter
339 if (param
.parameter_type
.value_owned
) {
340 stream
.printf (" transfer-ownership=\"full\"");
343 stream
.printf (">\n");
346 write_type (param
.parameter_type
);
350 stream
.printf ("</parameter>\n");
355 stream
.printf ("</parameters>\n");
358 public override void visit_delegate (Delegate cb
) {
359 if (cb
.external_package
) {
363 if (!check_accessibility (cb
)) {
368 stream
.printf ("<callback name=\"%s\"", cb
.get_cname ());
369 stream
.printf (">\n");
372 write_params (cb
.get_parameters ());
374 write_return_type (cb
.return_type
);
378 stream
.printf ("</callback>\n");
381 public override void visit_method (Method m
) {
382 if (m
.external_package
) {
386 // don't write interface implementation unless it's an abstract or virtual method
387 if (!check_accessibility (m
) || m
.overrides
|| (m
.base_interface_method
!= null && !m
.is_abstract
&& !m
.is_virtual
)) {
392 stream
.printf ("<method name=\"%s\" c:identifier=\"%s\"", m
.name
, m
.get_cname ());
393 stream
.printf (">\n");
396 DataType instance_type
= null;
397 if (m
.binding
== MemberBinding
.INSTANCE
) {
398 instance_type
= CCodeBaseModule
.get_data_type_for_symbol ((TypeSymbol
) m
.parent_symbol
);
401 write_params (m
.get_parameters (), instance_type
);
403 write_return_type (m
.return_type
);
407 stream
.printf ("</method>\n");
410 public override void visit_creation_method (CreationMethod m
) {
411 if (m
.external_package
) {
415 if (!check_accessibility (m
)) {
420 stream
.printf ("<constructor name=\"%s\" c:identifier=\"%s\"", m
.name
, m
.get_cname ());
421 stream
.printf (">\n");
424 write_params (m
.get_parameters ());
426 write_return_type (CCodeBaseModule
.get_data_type_for_symbol ((TypeSymbol
) m
.parent_symbol
));
430 stream
.printf ("</constructor>\n");
433 public override void visit_property (Property prop
) {
434 if (!check_accessibility (prop
) || prop
.overrides
|| (prop
.base_interface_property
!= null && !prop
.is_abstract
&& !prop
.is_virtual
)) {
439 stream
.printf ("<property name=\"%s\"", prop
.name
);
440 if (prop
.get_accessor
!= null) {
441 stream
.printf (" readable=\"1\"");
443 if (prop
.set_accessor
!= null) {
444 stream
.printf (" writable=\"1\"");
446 stream
.printf (">\n");
449 write_type (prop
.property_type
);
453 stream
.printf ("</property>\n");
456 public override void visit_signal (Signal sig
) {
457 if (!check_accessibility (sig
)) {
462 stream
.printf ("<glib:signal name=\"%s\"", sig
.get_cname ());
463 stream
.printf (">\n");
466 write_params (sig
.get_parameters ());
468 write_return_type (sig
.return_type
);
472 stream
.printf ("</glib:signal>\n");
475 private void write_indent () {
478 for (i
= 0; i
< indent
; i
++) {
483 private void write_return_type (DataType type
) {
485 stream
.printf ("<return-value");
486 if (type
.value_owned
) {
487 stream
.printf (" transfer-ownership=\"full\"");
489 stream
.printf (">\n");
496 stream
.printf ("</return-value>\n");
499 private void write_type (DataType type
) {
500 if (type is ArrayType
) {
501 var array_type
= (ArrayType
) type
;
504 stream
.printf ("<array>\n");
507 write_type (array_type
.element_type
);
511 stream
.printf ("</array>\n");
512 } else if (type is VoidType
) {
514 stream
.printf ("<type name=\"none\"/>\n");
517 stream
.printf ("<type name=\"%s\"/>\n", type
.to_string ());
521 private bool check_accessibility (Symbol sym
) {
522 if (sym
.access
== SymbolAccessibility
.PUBLIC
||
523 sym
.access
== SymbolAccessibility
.PROTECTED
) {