girparser: Add common parse_symbol_from_string method
[vala-lang.git] / vala / valanamespace.vala
blob45abd68de4e6a8fb886a9d21459f9b1d5fefd099
1 /* valanamespace.vala
3 * Copyright (C) 2006-2010 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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * Represents a namespace declaration in the source code.
28 public class Vala.Namespace : Symbol {
29 private List<Class> classes = new ArrayList<Class> ();
30 private List<Interface> interfaces = new ArrayList<Interface> ();
31 private List<Struct> structs = new ArrayList<Struct> ();
32 private List<Enum> enums = new ArrayList<Enum> ();
33 private List<ErrorDomain> error_domains = new ArrayList<ErrorDomain> ();
34 private List<Delegate> delegates = new ArrayList<Delegate> ();
35 private List<Constant> constants = new ArrayList<Constant> ();
36 private List<Field> fields = new ArrayList<Field> ();
37 private List<Method> methods = new ArrayList<Method> ();
39 private List<Comment> comments = new ArrayList<Comment> ();
41 private List<string> cprefixes = new ArrayList<string> ();
42 private string lower_case_cprefix;
44 private List<Namespace> namespaces = new ArrayList<Namespace> ();
46 private List<UsingDirective> using_directives = new ArrayList<UsingDirective> ();
48 /**
49 * Creates a new namespace.
51 * @param name namespace name
52 * @param source_reference reference to source code
53 * @return newly created namespace
55 public Namespace (string? name, SourceReference? source_reference = null) {
56 base (name, source_reference);
57 access = SymbolAccessibility.PUBLIC;
60 /**
61 * Adds a new using directive with the specified namespace.
63 * @param ns reference to namespace
65 public void add_using_directive (UsingDirective ns) {
66 using_directives.add (ns);
69 public void add_comment (Comment comment) {
70 comments.add (comment);
73 /**
74 * Returns a copy of the list of namespaces.
76 * @return comment list
78 public List<Comment> get_comments () {
79 return comments;
82 /**
83 * Adds the specified namespace to this source file.
85 * @param ns a namespace
87 public override void add_namespace (Namespace ns) {
88 if (ns.owner == null) {
89 ns.source_reference.file.add_node (ns);
92 if (scope.lookup (ns.name) is Namespace) {
93 // merge if namespace already exists
94 var old_ns = (Namespace) scope.lookup (ns.name);
95 if (old_ns.external_package && !ns.external_package) {
96 old_ns.source_reference = ns.source_reference;
99 foreach (var using_directive in ns.using_directives) {
100 old_ns.add_using_directive (using_directive);
102 foreach (Namespace sub_ns in ns.get_namespaces ()) {
103 old_ns.add_namespace (sub_ns);
105 foreach (Class cl in ns.get_classes ()) {
106 old_ns.add_class (cl);
108 foreach (Struct st in ns.get_structs ()) {
109 old_ns.add_struct (st);
111 foreach (Interface iface in ns.get_interfaces ()) {
112 old_ns.add_interface (iface);
114 foreach (Delegate d in ns.get_delegates ()) {
115 old_ns.add_delegate (d);
117 foreach (Enum en in ns.get_enums ()) {
118 old_ns.add_enum (en);
120 foreach (ErrorDomain ed in ns.get_error_domains ()) {
121 old_ns.add_error_domain (ed);
123 foreach (Constant c in ns.get_constants ()) {
124 old_ns.add_constant (c);
126 foreach (Field f in ns.get_fields ()) {
127 old_ns.add_field (f);
129 foreach (Method m in ns.get_methods ()) {
130 old_ns.add_method (m);
132 foreach (Comment c in ns.get_comments ()) {
133 old_ns.add_comment (c);
135 } else {
136 namespaces.add (ns);
137 scope.add (ns.name, ns);
142 * Returns a copy of the list of namespaces.
144 * @return namespace list
146 public List<Namespace> get_namespaces () {
147 return namespaces;
151 * Adds the specified class to this namespace.
153 * @param cl a class
155 public override void add_class (Class cl) {
156 // namespaces do not support private memebers
157 if (cl.access == SymbolAccessibility.PRIVATE) {
158 cl.access = SymbolAccessibility.INTERNAL;
161 if (cl.owner == null) {
162 cl.source_reference.file.add_node (cl);
165 classes.add (cl);
166 scope.add (cl.name, cl);
170 * Adds the specified interface to this namespace.
172 * @param iface an interface
174 public override void add_interface (Interface iface) {
175 // namespaces do not support private memebers
176 if (iface.access == SymbolAccessibility.PRIVATE) {
177 iface.access = SymbolAccessibility.INTERNAL;
180 if (iface.owner == null) {
181 iface.source_reference.file.add_node (iface);
184 interfaces.add (iface);
185 scope.add (iface.name, iface);
190 * Adds the specified struct to this namespace.
192 * @param st a struct
194 public override void add_struct (Struct st) {
195 // namespaces do not support private memebers
196 if (st.access == SymbolAccessibility.PRIVATE) {
197 st.access = SymbolAccessibility.INTERNAL;
200 if (st.owner == null) {
201 st.source_reference.file.add_node (st);
204 structs.add (st);
205 scope.add (st.name, st);
209 * Removes the specified struct from this namespace.
211 * @param st a struct
213 public void remove_struct (Struct st) {
214 structs.remove (st);
215 scope.remove (st.name);
219 * Adds the specified enum to this namespace.
221 * @param en an enum
223 public override void add_enum (Enum en) {
224 // namespaces do not support private memebers
225 if (en.access == SymbolAccessibility.PRIVATE) {
226 en.access = SymbolAccessibility.INTERNAL;
229 if (en.owner == null) {
230 en.source_reference.file.add_node (en);
233 enums.add (en);
234 scope.add (en.name, en);
238 * Adds the specified error domain to this namespace.
240 * @param edomain an error domain
242 public override void add_error_domain (ErrorDomain edomain) {
243 // namespaces do not support private memebers
244 if (edomain.access == SymbolAccessibility.PRIVATE) {
245 edomain.access = SymbolAccessibility.INTERNAL;
248 if (edomain.owner == null) {
249 edomain.source_reference.file.add_node (edomain);
252 error_domains.add (edomain);
253 scope.add (edomain.name, edomain);
257 * Adds the specified delegate to this namespace.
259 * @param d a delegate
261 public override void add_delegate (Delegate d) {
262 // namespaces do not support private memebers
263 if (d.access == SymbolAccessibility.PRIVATE) {
264 d.access = SymbolAccessibility.INTERNAL;
267 if (d.owner == null) {
268 d.source_reference.file.add_node (d);
271 delegates.add (d);
272 scope.add (d.name, d);
276 * Returns a copy of the list of structs.
278 * @return struct list
280 public List<Struct> get_structs () {
281 return structs;
285 * Returns a copy of the list of classes.
287 * @return class list
289 public List<Class> get_classes () {
290 return classes;
294 * Returns a copy of the list of interfaces.
296 * @return interface list
298 public List<Interface> get_interfaces () {
299 return interfaces;
303 * Returns a copy of the list of enums.
305 * @return enum list
307 public List<Enum> get_enums () {
308 return enums;
312 * Returns a copy of the list of error domains.
314 * @return error domain list
316 public List<ErrorDomain> get_error_domains () {
317 return error_domains;
321 * Returns a copy of the list of fields.
323 * @return field list
325 public List<Field> get_fields () {
326 return fields;
330 * Returns a copy of the list of constants.
332 * @return constant list
334 public List<Constant> get_constants () {
335 return constants;
339 * Returns a copy of the list of delegates.
341 * @return delegate list
343 public List<Delegate> get_delegates () {
344 return delegates;
348 * Returns a copy of the list of methods.
350 * @return method list
352 public List<Method> get_methods () {
353 return methods;
357 * Adds the specified constant to this namespace.
359 * @param constant a constant
361 public override void add_constant (Constant constant) {
362 // namespaces do not support private memebers
363 if (constant.access == SymbolAccessibility.PRIVATE) {
364 constant.access = SymbolAccessibility.INTERNAL;
367 if (constant.owner == null) {
368 constant.source_reference.file.add_node (constant);
371 constants.add (constant);
372 scope.add (constant.name, constant);
376 * Adds the specified field to this namespace.
378 * @param f a field
380 public override void add_field (Field f) {
381 if (f.binding == MemberBinding.INSTANCE) {
382 // default to static member binding
383 f.binding = MemberBinding.STATIC;
386 // namespaces do not support private memebers
387 if (f.access == SymbolAccessibility.PRIVATE) {
388 f.access = SymbolAccessibility.INTERNAL;
391 if (f.binding == MemberBinding.INSTANCE) {
392 Report.error (f.source_reference, "instance members are not allowed outside of data types");
393 f.error = true;
394 return;
395 } else if (f.binding == MemberBinding.CLASS) {
396 Report.error (f.source_reference, "class members are not allowed outside of classes");
397 f.error = true;
398 return;
401 if (f.owner == null) {
402 f.source_reference.file.add_node (f);
405 fields.add (f);
406 scope.add (f.name, f);
410 * Adds the specified method to this namespace.
412 * @param m a method
414 public override void add_method (Method m) {
415 if (m.binding == MemberBinding.INSTANCE) {
416 // default to static member binding
417 m.binding = MemberBinding.STATIC;
420 // namespaces do not support private memebers
421 if (m.access == SymbolAccessibility.PRIVATE) {
422 m.access = SymbolAccessibility.INTERNAL;
425 if (m is CreationMethod) {
426 Report.error (m.source_reference, "construction methods may only be declared within classes and structs");
427 m.error = true;
428 return;
430 if (m.binding == MemberBinding.INSTANCE) {
431 Report.error (m.source_reference, "instance members are not allowed outside of data types");
432 m.error = true;
433 return;
434 } else if (m.binding == MemberBinding.CLASS) {
435 Report.error (m.source_reference, "class members are not allowed outside of classes");
436 m.error = true;
437 return;
439 if (!(m.return_type is VoidType) && (CodeContext.get ().profile == Profile.DOVA || m.get_postconditions ().size > 0)) {
440 m.result_var = new LocalVariable (m.return_type.copy (), "result", null, source_reference);
441 m.result_var.is_result = true;
444 if (m.owner == null) {
445 m.source_reference.file.add_node (m);
448 methods.add (m);
449 scope.add (m.name, m);
452 public override void accept (CodeVisitor visitor) {
453 visitor.visit_namespace (this);
456 public override void accept_children (CodeVisitor visitor) {
457 foreach (UsingDirective ns_ref in using_directives) {
458 ns_ref.accept (visitor);
461 foreach (Namespace ns in namespaces) {
462 ns.accept (visitor);
465 /* process enums first to avoid order problems in C code */
466 foreach (Enum en in enums) {
467 en.accept (visitor);
470 foreach (ErrorDomain edomain in error_domains) {
471 edomain.accept (visitor);
474 foreach (Class cl in classes) {
475 cl.accept (visitor);
478 foreach (Interface iface in interfaces) {
479 iface.accept (visitor);
482 foreach (Struct st in structs) {
483 st.accept (visitor);
486 foreach (Delegate d in delegates) {
487 d.accept (visitor);
490 foreach (Constant c in constants) {
491 c.accept (visitor);
494 foreach (Field f in fields) {
495 f.accept (visitor);
498 foreach (Method m in methods) {
499 m.accept (visitor);
503 public override string get_cprefix () {
504 if (cprefixes.size > 0) {
505 return cprefixes[0];
506 } else if (null != name) {
507 string parent_prefix;
508 if (parent_symbol == null) {
509 parent_prefix = "";
510 } else {
511 parent_prefix = parent_symbol.get_cprefix ();
513 return parent_prefix + name;
514 } else {
515 return "";
519 public List<string> get_cprefixes () {
520 if (0 == cprefixes.size && null != name)
521 cprefixes.add (name);
523 return cprefixes;
527 * Adds a camel case string to be prepended to the name of members of
528 * this namespace when used in C code.
530 * @param cprefixes the camel case prefixes used in C code
532 public void add_cprefix (string cprefix) {
533 cprefixes.add (cprefix);
537 * Returns the lower case string to be prepended to the name of members
538 * of this namespace when used in C code.
540 * @return the lower case prefix to be used in C code
542 public override string get_lower_case_cprefix () {
543 if (lower_case_cprefix == null) {
544 if (name == null) {
545 lower_case_cprefix = "";
546 } else {
547 string parent_prefix;
548 if (parent_symbol == null) {
549 parent_prefix = "";
550 } else {
551 parent_prefix = parent_symbol.get_lower_case_cprefix ();
553 lower_case_cprefix = "%s%s_".printf (parent_prefix, camel_case_to_lower_case (name));
556 return lower_case_cprefix;
560 * Sets the lower case string to be prepended to the name of members of
561 * this namespace when used in C code.
563 * @param cprefix the lower case prefix to be used in C code
565 public void set_lower_case_cprefix (string cprefix) {
566 this.lower_case_cprefix = cprefix;
569 private void process_ccode_attribute (Attribute a) {
570 if (a.has_argument ("cprefix")) {
571 string value = a.get_string ("cprefix");
572 if (value == "") {
573 // split of an empty string returns an empty array
574 add_cprefix ("");
575 } else {
576 foreach (string name in value.split (",")) {
577 add_cprefix (name);
581 if (a.has_argument ("lower_case_cprefix")) {
582 set_lower_case_cprefix (a.get_string ("lower_case_cprefix"));
584 if (a.has_argument ("cheader_filename")) {
585 var val = a.get_string ("cheader_filename");
586 foreach (string filename in val.split (",")) {
587 add_cheader_filename (filename);
590 if (a.has_argument ("gir_namespace")) {
591 source_reference.file.gir_namespace = a.get_string ("gir_namespace");
593 if (a.has_argument ("gir_version")) {
594 source_reference.file.gir_version = a.get_string ("gir_version");
599 * Process all associated attributes.
601 public void process_attributes () {
602 foreach (Attribute a in attributes) {
603 if (a.name == "CCode") {
604 process_ccode_attribute (a);
609 public override bool check (CodeContext context) {
610 if (checked) {
611 return !error;
614 checked = true;
616 process_attributes ();
618 foreach (Namespace ns in namespaces) {
619 ns.check (context);
622 return !error;