3 * Copyright (C) 2006-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 * Represents a namespace declaration in the source code.
29 public class Vala
.Namespace
: Symbol
{
30 private Gee
.List
<Class
> classes
= new ArrayList
<Class
> ();
31 private Gee
.List
<Interface
> interfaces
= new ArrayList
<Interface
> ();
32 private Gee
.List
<Struct
> structs
= new ArrayList
<Struct
> ();
33 private Gee
.List
<Enum
> enums
= new ArrayList
<Enum
> ();
34 private Gee
.List
<ErrorDomain
> error_domains
= new ArrayList
<ErrorDomain
> ();
35 private Gee
.List
<Delegate
> delegates
= new ArrayList
<Delegate
> ();
36 private Gee
.List
<Constant
> constants
= new ArrayList
<Constant
> ();
37 private Gee
.List
<Field
> fields
= new ArrayList
<Field
> ();
38 private Gee
.List
<Method
> methods
= new ArrayList
<Method
> ();
40 private Gee
.List
<string> cprefixes
= new ArrayList
<string> ();
41 private string lower_case_cprefix
;
43 private Gee
.List
<string> cheader_filenames
= new ArrayList
<string> ();
45 private Gee
.List
<Namespace
> namespaces
= new ArrayList
<Namespace
> ();
48 * Creates a new namespace.
50 * @param name namespace name
51 * @param source_reference reference to source code
52 * @return newly created namespace
54 public Namespace (string? name
, SourceReference? source_reference
= null) {
55 base (name
, source_reference
);
56 access
= SymbolAccessibility
.PUBLIC
;
60 * Adds the specified namespace to this source file.
62 * @param ns a namespace
64 public void add_namespace (Namespace ns
) {
65 if (scope
.lookup (ns
.name
) is Namespace
) {
66 // merge if namespace already exists
67 var old_ns
= (Namespace
) scope
.lookup (ns
.name
);
68 if (old_ns
.external_package
&& !ns
.external_package
) {
69 old_ns
.source_reference
= ns
.source_reference
;
71 foreach (Namespace sub_ns
in ns
.get_namespaces ()) {
72 old_ns
.add_namespace (sub_ns
);
74 foreach (Class cl
in ns
.get_classes ()) {
75 old_ns
.add_class (cl
);
77 foreach (Struct st
in ns
.get_structs ()) {
78 old_ns
.add_struct (st
);
80 foreach (Interface iface
in ns
.get_interfaces ()) {
81 old_ns
.add_interface (iface
);
83 foreach (Delegate d
in ns
.get_delegates ()) {
84 old_ns
.add_delegate (d
);
86 foreach (Enum en
in ns
.get_enums ()) {
89 foreach (ErrorDomain ed
in ns
.get_error_types ()) {
90 old_ns
.add_error_domain (ed
);
92 foreach (Constant c
in ns
.get_constants ()) {
93 old_ns
.add_constant (c
);
95 foreach (Field f
in ns
.get_fields ()) {
98 foreach (Method m
in ns
.get_methods ()) {
99 old_ns
.add_method (m
);
103 scope
.add (ns
.name
, ns
);
108 * Returns a copy of the list of namespaces.
110 * @return namespace list
112 public Gee
.List
<Namespace
> get_namespaces () {
113 return new ReadOnlyList
<Namespace
> (namespaces
);
117 * Adds the specified class to this namespace.
121 public void add_class (Class cl
) {
122 if (scope
.lookup (cl
.name
) is Class
) {
124 var old_class
= (Class
) scope
.lookup (cl
.name
);
125 foreach (DataType base_type
in cl
.get_base_types ()) {
126 old_class
.add_base_type (base_type
);
128 foreach (Field f
in cl
.get_fields ()) {
129 old_class
.add_field (f
);
131 foreach (Method m
in cl
.get_methods ()) {
132 if (m
== cl
.default_construction_method
&& old_class
.default_construction_method
!= null) {
133 // ignore secondary default creation method
136 old_class
.add_method (m
);
138 if (cl
.constructor
!= null) {
139 old_class
.constructor
= cl
.constructor
;
141 cl
.source_reference
.file
.remove_node (cl
);
144 scope
.add (cl
.name
, cl
);
149 * Adds the specified interface to this namespace.
151 * @param iface an interface
153 public void add_interface (Interface iface
) {
154 interfaces
.add (iface
);
155 scope
.add (iface
.name
, iface
);
159 * Adds the specified struct to this namespace.
163 public void add_struct (Struct st
) {
165 scope
.add (st
.name
, st
);
169 * Removes the specified struct from this namespace.
173 public void remove_struct (Struct st
) {
175 scope
.remove (st
.name
);
179 * Adds the specified enum to this namespace.
183 public void add_enum (Enum en
) {
185 scope
.add (en
.name
, en
);
189 * Adds the specified error domain to this namespace.
191 * @param edomain an error domain
193 public void add_error_domain (ErrorDomain edomain
) {
194 error_domains
.add (edomain
);
195 scope
.add (edomain
.name
, edomain
);
199 * Adds the specified delegate to this namespace.
201 * @param d a delegate
203 public void add_delegate (Delegate d
) {
205 scope
.add (d
.name
, d
);
209 * Returns a copy of the list of structs.
211 * @return struct list
213 public Gee
.List
<Struct
> get_structs () {
214 return new ReadOnlyList
<Struct
> (structs
);
218 * Returns a copy of the list of classes.
222 public Gee
.List
<Class
> get_classes () {
223 return new ReadOnlyList
<Class
> (classes
);
227 * Returns a copy of the list of interfaces.
229 * @return interface list
231 public Gee
.List
<Interface
> get_interfaces () {
232 return new ReadOnlyList
<Interface
> (interfaces
);
236 * Returns a copy of the list of enums.
240 public Gee
.List
<Enum
> get_enums () {
241 return new ReadOnlyList
<Enum
> (enums
);
245 * Returns a copy of the list of error domains.
247 * @return error domain list
249 public Gee
.List
<ErrorDomain
> get_error_types () {
250 return new ReadOnlyList
<ErrorDomain
> (error_domains
);
254 * Returns a copy of the list of fields.
258 public Gee
.List
<Field
> get_fields () {
259 return new ReadOnlyList
<Field
> (fields
);
263 * Returns a copy of the list of constants.
265 * @return constant list
267 public Gee
.List
<Constant
> get_constants () {
268 return new ReadOnlyList
<Constant
> (constants
);
272 * Returns a copy of the list of delegates.
274 * @return delegate list
276 public Gee
.List
<Delegate
> get_delegates () {
277 return new ReadOnlyList
<Delegate
> (delegates
);
281 * Returns a copy of the list of methods.
283 * @return method list
285 public Gee
.List
<Method
> get_methods () {
286 return new ReadOnlyList
<Method
> (methods
);
290 * Adds the specified constant to this namespace.
292 * @param constant a constant
294 public void add_constant (Constant constant
) {
295 constants
.add (constant
);
296 scope
.add (constant
.name
, constant
);
300 * Adds the specified field to this namespace.
304 public void add_field (Field f
) {
305 if (f
.binding
== MemberBinding
.INSTANCE
) {
306 Report
.error (f
.source_reference
, "instance members are not allowed outside of data types");
309 } else if (f
.binding
== MemberBinding
.CLASS
) {
310 Report
.error (f
.source_reference
, "class members are not allowed outside of classes");
316 scope
.add (f
.name
, f
);
320 * Adds the specified method to this namespace.
324 public void add_method (Method m
) {
325 if (m is CreationMethod
) {
326 Report
.error (m
.source_reference
, "construction methods may only be declared within classes and structs");
330 if (m
.binding
== MemberBinding
.INSTANCE
) {
331 Report
.error (m
.source_reference
, "instance members are not allowed outside of data types");
334 } else if (m
.binding
== MemberBinding
.CLASS
) {
335 Report
.error (m
.source_reference
, "class members are not allowed outside of classes");
341 scope
.add (m
.name
, m
);
344 public override void accept (CodeVisitor visitor
) {
345 visitor
.visit_namespace (this
);
348 public override void accept_children (CodeVisitor visitor
) {
349 foreach (Namespace ns
in namespaces
) {
353 /* process enums first to avoid order problems in C code */
354 foreach (Enum en
in enums
) {
358 foreach (ErrorDomain edomain
in error_domains
) {
359 edomain
.accept (visitor
);
362 foreach (Class cl
in classes
) {
366 foreach (Interface iface
in interfaces
) {
367 iface
.accept (visitor
);
370 foreach (Struct st
in structs
) {
374 foreach (Delegate d
in delegates
) {
378 foreach (Constant c
in constants
) {
382 foreach (Field f
in fields
) {
386 foreach (Method m
in methods
) {
391 public override string get_cprefix () {
392 if (cprefixes
.size
> 0) {
394 } else if (null != name
) {
395 string parent_prefix
;
396 if (parent_symbol
== null) {
399 parent_prefix
= parent_symbol
.get_cprefix ();
401 return parent_prefix
+ name
;
407 public Gee
.List
<string> get_cprefixes () {
408 if (0 == cprefixes
.size
&& null != name
)
409 cprefixes
.add (name
);
415 * Adds a camel case string to be prepended to the name of members of
416 * this namespace when used in C code.
418 * @param cprefixes the camel case prefixes used in C code
420 public void add_cprefix (string cprefix
) {
421 return_if_fail (cprefix
.len() >= 1);
422 cprefixes
.add (cprefix
);
426 * Returns the lower case string to be prepended to the name of members
427 * of this namespace when used in C code.
429 * @return the lower case prefix to be used in C code
431 public override string get_lower_case_cprefix () {
432 if (lower_case_cprefix
== null) {
434 lower_case_cprefix
= "";
436 string parent_prefix
;
437 if (parent_symbol
== null) {
440 parent_prefix
= parent_symbol
.get_lower_case_cprefix ();
442 lower_case_cprefix
= "%s%s_".printf (parent_prefix
, camel_case_to_lower_case (name
));
445 return lower_case_cprefix
;
449 * Sets the lower case string to be prepended to the name of members of
450 * this namespace when used in C code.
452 * @param cprefix the lower case prefix to be used in C code
454 public void set_lower_case_cprefix (string cprefix
) {
455 this
.lower_case_cprefix
= cprefix
;
458 public override Gee
.List
<string> get_cheader_filenames () {
459 return new ReadOnlyList
<string> (cheader_filenames
);
463 * Returns the C header filename of this namespace.
465 * @return header filename
467 public string get_cheader_filename () {
468 var s
= new
StringBuilder ();
470 foreach (string cheader_filename
in get_cheader_filenames ()) {
476 s
.append (cheader_filename
);
482 * Sets the C header filename of this namespace to the specified
485 * @param cheader_filename header filename
487 public void set_cheader_filename (string cheader_filename
) {
488 cheader_filenames
= new ArrayList
<string> ();
489 cheader_filenames
.add (cheader_filename
);
492 private void process_ccode_attribute (Attribute a
) {
493 if (a
.has_argument ("cprefix")) {
494 foreach (string name
in a
.get_string ("cprefix").split (","))
497 if (a
.has_argument ("lower_case_cprefix")) {
498 set_lower_case_cprefix (a
.get_string ("lower_case_cprefix"));
500 if (a
.has_argument ("cheader_filename")) {
501 var val
= a
.get_string ("cheader_filename");
502 foreach (string filename
in val
.split (",")) {
503 cheader_filenames
.add (filename
);
509 * Process all associated attributes.
511 public void process_attributes () {
512 foreach (Attribute a
in attributes
) {
513 if (a
.name
== "CCode") {
514 process_ccode_attribute (a
);
519 public override bool check (SemanticAnalyzer analyzer
) {
526 process_attributes ();
528 foreach (Namespace ns
in namespaces
) {