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
20 * Jürg Billeter <j@bitron.ch>
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
> ();
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
;
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
);
74 * Returns a copy of the list of namespaces.
76 * @return comment list
78 public List
<Comment
> get_comments () {
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
);
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 () {
151 * Adds the specified class to this namespace.
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
);
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.
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
);
205 scope
.add (st
.name
, st
);
209 * Removes the specified struct from this namespace.
213 public void remove_struct (Struct st
) {
215 scope
.remove (st
.name
);
219 * Adds the specified enum to this namespace.
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
);
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
);
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 () {
285 * Returns a copy of the list of classes.
289 public List
<Class
> get_classes () {
294 * Returns a copy of the list of interfaces.
296 * @return interface list
298 public List
<Interface
> get_interfaces () {
303 * Returns a copy of the list of enums.
307 public List
<Enum
> get_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.
325 public List
<Field
> get_fields () {
330 * Returns a copy of the list of constants.
332 * @return constant list
334 public List
<Constant
> get_constants () {
339 * Returns a copy of the list of delegates.
341 * @return delegate list
343 public List
<Delegate
> get_delegates () {
348 * Returns a copy of the list of methods.
350 * @return method list
352 public List
<Method
> get_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.
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");
395 } else if (f
.binding
== MemberBinding
.CLASS
) {
396 Report
.error (f
.source_reference
, "class members are not allowed outside of classes");
401 if (f
.owner
== null) {
402 f
.source_reference
.file
.add_node (f
);
406 scope
.add (f
.name
, f
);
410 * Adds the specified method to this namespace.
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");
430 if (m
.binding
== MemberBinding
.INSTANCE
) {
431 Report
.error (m
.source_reference
, "instance members are not allowed outside of data types");
434 } else if (m
.binding
== MemberBinding
.CLASS
) {
435 Report
.error (m
.source_reference
, "class members are not allowed outside of classes");
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
);
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
) {
465 /* process enums first to avoid order problems in C code */
466 foreach (Enum en
in enums
) {
470 foreach (ErrorDomain edomain
in error_domains
) {
471 edomain
.accept (visitor
);
474 foreach (Class cl
in classes
) {
478 foreach (Interface iface
in interfaces
) {
479 iface
.accept (visitor
);
482 foreach (Struct st
in structs
) {
486 foreach (Delegate d
in delegates
) {
490 foreach (Constant c
in constants
) {
494 foreach (Field f
in fields
) {
498 foreach (Method m
in methods
) {
503 public override string get_cprefix () {
504 if (cprefixes
.size
> 0) {
506 } else if (null != name
) {
507 string parent_prefix
;
508 if (parent_symbol
== null) {
511 parent_prefix
= parent_symbol
.get_cprefix ();
513 return parent_prefix
+ name
;
519 public List
<string> get_cprefixes () {
520 if (0 == cprefixes
.size
&& null != name
)
521 cprefixes
.add (name
);
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) {
545 lower_case_cprefix
= "";
547 string parent_prefix
;
548 if (parent_symbol
== null) {
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");
573 // split of an empty string returns an empty array
576 foreach (string name
in value
.split (",")) {
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 (SemanticAnalyzer analyzer
) {
616 process_attributes ();
618 foreach (Namespace ns
in namespaces
) {