Line data Source code
1 : /* valanamespace.vala
2 : *
3 : * Copyright (C) 2006-2010 Jürg Billeter
4 : *
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.
9 :
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.
14 :
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
18 : *
19 : * Author:
20 : * Jürg Billeter <j@bitron.ch>
21 : */
22 :
23 : using GLib;
24 :
25 : /**
26 : * Represents a namespace declaration in the source code.
27 : */
28 141755 : public class Vala.Namespace : Symbol {
29 140217 : private List<Class> classes = new ArrayList<Class> ();
30 140217 : private List<Interface> interfaces = new ArrayList<Interface> ();
31 140217 : private List<Struct> structs = new ArrayList<Struct> ();
32 140217 : private List<Enum> enums = new ArrayList<Enum> ();
33 140217 : private List<ErrorDomain> error_domains = new ArrayList<ErrorDomain> ();
34 140217 : private List<Delegate> delegates = new ArrayList<Delegate> ();
35 140217 : private List<Constant> constants = new ArrayList<Constant> ();
36 140217 : private List<Field> fields = new ArrayList<Field> ();
37 140217 : private List<Method> methods = new ArrayList<Method> ();
38 :
39 140217 : private List<Comment> comments = new ArrayList<Comment> ();
40 :
41 140217 : private List<Namespace> namespaces = new ArrayList<Namespace> ();
42 :
43 140217 : private List<UsingDirective> using_directives = new ArrayList<UsingDirective> ();
44 :
45 : /**
46 : * Creates a new namespace.
47 : *
48 : * @param name namespace name
49 : * @param source_reference reference to source code
50 : * @return newly created namespace
51 : */
52 70109 : public Namespace (string? name, SourceReference? source_reference = null) {
53 70109 : base (name, source_reference);
54 70109 : access = SymbolAccessibility.PUBLIC;
55 : }
56 :
57 : /**
58 : * Adds a new using directive with the specified namespace.
59 : *
60 : * @param ns reference to namespace
61 : */
62 1895 : public void add_using_directive (UsingDirective ns) {
63 1895 : using_directives.add (ns);
64 : }
65 :
66 1529 : public void add_comment (Comment comment) {
67 1529 : comments.add (comment);
68 : }
69 :
70 : /**
71 : * Returns the list of namespaces.
72 : *
73 : * @return comment list
74 : */
75 3673 : public unowned List<Comment> get_comments () {
76 3673 : return comments;
77 : }
78 :
79 : /**
80 : * Adds the specified namespace to this source file.
81 : *
82 : * @param ns a namespace
83 : */
84 77829 : public override void add_namespace (Namespace ns) {
85 77829 : if (ns.owner == null) {
86 68571 : ns.source_reference.file.add_node (ns);
87 : }
88 :
89 81405 : if (scope.lookup (ns.name) is Namespace) {
90 : // merge if namespace already exists
91 3576 : var old_ns = (Namespace) scope.lookup (ns.name);
92 3576 : if (old_ns.external_package && !ns.external_package) {
93 14 : old_ns.source_reference = ns.source_reference;
94 : }
95 :
96 3576 : foreach (var using_directive in ns.using_directives) {
97 0 : old_ns.add_using_directive (using_directive);
98 : }
99 22092 : foreach (Namespace sub_ns in ns.get_namespaces ()) {
100 9258 : old_ns.add_namespace (sub_ns);
101 : }
102 504094 : foreach (Class cl in ns.get_classes ()) {
103 250259 : old_ns.add_class (cl);
104 : }
105 77990 : foreach (Struct st in ns.get_structs ()) {
106 37207 : old_ns.add_struct (st);
107 : }
108 118458 : foreach (Interface iface in ns.get_interfaces ()) {
109 57441 : old_ns.add_interface (iface);
110 : }
111 189442 : foreach (Delegate d in ns.get_delegates ()) {
112 92933 : old_ns.add_delegate (d);
113 : }
114 260732 : foreach (Enum en in ns.get_enums ()) {
115 128578 : old_ns.add_enum (en);
116 : }
117 21786 : foreach (ErrorDomain ed in ns.get_error_domains ()) {
118 9105 : old_ns.add_error_domain (ed);
119 : }
120 13842 : foreach (Constant c in ns.get_constants ()) {
121 5133 : old_ns.add_constant (c);
122 : }
123 6692 : foreach (Field f in ns.get_fields ()) {
124 1558 : old_ns.add_field (f);
125 : }
126 90766 : foreach (Method m in ns.get_methods ()) {
127 43595 : old_ns.add_method (m);
128 : }
129 3576 : foreach (Comment c in ns.get_comments ()) {
130 0 : old_ns.add_comment (c);
131 : }
132 71718 : foreach (Attribute a in ns.attributes) {
133 3159 : if (!old_ns.has_attribute (a.name)) {
134 20 : old_ns.attributes.append(a);
135 : }
136 : }
137 : } else {
138 74253 : namespaces.add (ns);
139 74253 : scope.add (ns.name, ns);
140 : }
141 : }
142 :
143 : /**
144 : * Returns the list of namespaces.
145 : *
146 : * @return namespace list
147 : */
148 4612 : public unowned List<Namespace> get_namespaces () {
149 4612 : return namespaces;
150 : }
151 :
152 : /**
153 : * Adds the specified class to this namespace.
154 : *
155 : * @param cl a class
156 : */
157 624543 : public override void add_class (Class cl) {
158 : // namespaces do not support private members
159 624543 : if (cl.access == SymbolAccessibility.PRIVATE) {
160 704 : cl.access = SymbolAccessibility.INTERNAL;
161 : }
162 :
163 624543 : if (cl.owner == null) {
164 374284 : cl.source_reference.file.add_node (cl);
165 : }
166 :
167 624543 : classes.add (cl);
168 624543 : scope.add (cl.name, cl);
169 : }
170 :
171 : /**
172 : * Adds the specified interface to this namespace.
173 : *
174 : * @param iface an interface
175 : */
176 116011 : public override void add_interface (Interface iface) {
177 : // namespaces do not support private members
178 116011 : if (iface.access == SymbolAccessibility.PRIVATE) {
179 119 : iface.access = SymbolAccessibility.INTERNAL;
180 : }
181 :
182 116011 : if (iface.owner == null) {
183 58570 : iface.source_reference.file.add_node (iface);
184 : }
185 :
186 116011 : interfaces.add (iface);
187 116011 : scope.add (iface.name, iface);
188 :
189 : }
190 :
191 : /**
192 : * Adds the specified struct to this namespace.
193 : *
194 : * @param st a struct
195 : */
196 180501 : public override void add_struct (Struct st) {
197 : // namespaces do not support private members
198 180501 : if (st.access == SymbolAccessibility.PRIVATE) {
199 202 : st.access = SymbolAccessibility.INTERNAL;
200 : }
201 :
202 180501 : if (st.owner == null) {
203 143294 : st.source_reference.file.add_node (st);
204 : }
205 :
206 180501 : structs.add (st);
207 180501 : scope.add (st.name, st);
208 : }
209 :
210 : /**
211 : * Adds the specified enum to this namespace.
212 : *
213 : * @param en an enum
214 : */
215 336455 : public override void add_enum (Enum en) {
216 : // namespaces do not support private members
217 336455 : if (en.access == SymbolAccessibility.PRIVATE) {
218 55 : en.access = SymbolAccessibility.INTERNAL;
219 : }
220 :
221 336455 : if (en.owner == null) {
222 207877 : en.source_reference.file.add_node (en);
223 : }
224 :
225 336455 : enums.add (en);
226 336455 : scope.add (en.name, en);
227 : }
228 :
229 : /**
230 : * Adds the specified error domain to this namespace.
231 : *
232 : * @param edomain an error domain
233 : */
234 39937 : public override void add_error_domain (ErrorDomain edomain) {
235 : // namespaces do not support private members
236 39937 : if (edomain.access == SymbolAccessibility.PRIVATE) {
237 53 : edomain.access = SymbolAccessibility.INTERNAL;
238 : }
239 :
240 39937 : if (edomain.owner == null) {
241 30832 : edomain.source_reference.file.add_node (edomain);
242 : }
243 :
244 39937 : error_domains.add (edomain);
245 39937 : scope.add (edomain.name, edomain);
246 : }
247 :
248 : /**
249 : * Adds the specified delegate to this namespace.
250 : *
251 : * @param d a delegate
252 : */
253 283902 : public override void add_delegate (Delegate d) {
254 : // namespaces do not support private members
255 283902 : if (d.access == SymbolAccessibility.PRIVATE) {
256 137 : d.access = SymbolAccessibility.INTERNAL;
257 : }
258 :
259 283902 : if (d.owner == null) {
260 190969 : d.source_reference.file.add_node (d);
261 : }
262 :
263 283902 : delegates.add (d);
264 283902 : scope.add (d.name, d);
265 : }
266 :
267 : /**
268 : * Returns the list of structs.
269 : *
270 : * @return struct list
271 : */
272 3673 : public unowned List<Struct> get_structs () {
273 3673 : return structs;
274 : }
275 :
276 : /**
277 : * Returns the list of classes.
278 : *
279 : * @return class list
280 : */
281 4612 : public unowned List<Class> get_classes () {
282 4612 : return classes;
283 : }
284 :
285 : /**
286 : * Returns the list of interfaces.
287 : *
288 : * @return interface list
289 : */
290 3716 : public unowned List<Interface> get_interfaces () {
291 3716 : return interfaces;
292 : }
293 :
294 : /**
295 : * Returns the list of enums.
296 : *
297 : * @return enum list
298 : */
299 3673 : public unowned List<Enum> get_enums () {
300 3673 : return enums;
301 : }
302 :
303 : /**
304 : * Returns the list of error domains.
305 : *
306 : * @return error domain list
307 : */
308 3673 : public unowned List<ErrorDomain> get_error_domains () {
309 3673 : return error_domains;
310 : }
311 :
312 : /**
313 : * Returns the list of fields.
314 : *
315 : * @return field list
316 : */
317 3673 : public unowned List<Field> get_fields () {
318 3673 : return fields;
319 : }
320 :
321 : /**
322 : * Returns the list of constants.
323 : *
324 : * @return constant list
325 : */
326 3673 : public unowned List<Constant> get_constants () {
327 3673 : return constants;
328 : }
329 :
330 : /**
331 : * Returns the list of delegates.
332 : *
333 : * @return delegate list
334 : */
335 3673 : public unowned List<Delegate> get_delegates () {
336 3673 : return delegates;
337 : }
338 :
339 : /**
340 : * Returns the list of methods.
341 : *
342 : * @return method list
343 : */
344 3673 : public unowned List<Method> get_methods () {
345 3673 : return methods;
346 : }
347 :
348 : /**
349 : * Adds the specified constant to this namespace.
350 : *
351 : * @param constant a constant
352 : */
353 433301 : public override void add_constant (Constant constant) {
354 : // namespaces do not support private members
355 433301 : if (constant.access == SymbolAccessibility.PRIVATE) {
356 3218 : constant.access = SymbolAccessibility.INTERNAL;
357 : }
358 :
359 433301 : if (constant.owner == null) {
360 428168 : constant.source_reference.file.add_node (constant);
361 : }
362 :
363 433301 : constants.add (constant);
364 433301 : scope.add (constant.name, constant);
365 : }
366 :
367 : /**
368 : * Adds the specified field to this namespace.
369 : *
370 : * @param f a field
371 : */
372 41769 : public override void add_field (Field f) {
373 : // namespaces do not support private members
374 41769 : if (f.access == SymbolAccessibility.PRIVATE) {
375 1674 : f.access = SymbolAccessibility.INTERNAL;
376 : }
377 :
378 41769 : if (f.owner == null) {
379 40211 : f.source_reference.file.add_node (f);
380 : }
381 :
382 41769 : fields.add (f);
383 41769 : scope.add (f.name, f);
384 : }
385 :
386 : /**
387 : * Adds the specified method to this namespace.
388 : *
389 : * @param m a method
390 : */
391 971687 : public override void add_method (Method m) {
392 : // namespaces do not support private members
393 971687 : if (m.access == SymbolAccessibility.PRIVATE) {
394 3761 : m.access = SymbolAccessibility.INTERNAL;
395 : }
396 :
397 971687 : if (!(m.return_type is VoidType) && m.get_postconditions ().size > 0) {
398 10 : m.result_var = new LocalVariable (m.return_type.copy (), "result", null, m.source_reference);
399 10 : m.result_var.is_result = true;
400 : }
401 :
402 971687 : if (m.owner == null) {
403 928092 : m.source_reference.file.add_node (m);
404 : }
405 :
406 971687 : methods.add (m);
407 971687 : scope.add (m.name, m);
408 : }
409 :
410 157208 : public override void accept (CodeVisitor visitor) {
411 157208 : visitor.visit_namespace (this);
412 : }
413 :
414 106848 : public override void accept_children (CodeVisitor visitor) {
415 113762 : foreach (UsingDirective ns_ref in using_directives) {
416 3457 : ns_ref.accept (visitor);
417 : }
418 :
419 316016 : foreach (Namespace ns in namespaces) {
420 104584 : ns.accept (visitor);
421 : }
422 :
423 : /* process enums first to avoid order problems in C code */
424 781340 : foreach (Enum en in enums) {
425 337246 : en.accept (visitor);
426 : }
427 :
428 205598 : foreach (ErrorDomain edomain in error_domains) {
429 49375 : edomain.accept (visitor);
430 : }
431 :
432 1317570 : foreach (Class cl in classes) {
433 605361 : cl.accept (visitor);
434 : }
435 :
436 294204 : foreach (Interface iface in interfaces) {
437 93678 : iface.accept (visitor);
438 : }
439 :
440 576582 : foreach (Struct st in structs) {
441 234867 : st.accept (visitor);
442 : }
443 :
444 723306 : foreach (Delegate d in delegates) {
445 308229 : d.accept (visitor);
446 : }
447 :
448 1603608 : foreach (Constant c in constants) {
449 748380 : c.accept (visitor);
450 : }
451 :
452 235772 : foreach (Field f in fields) {
453 64462 : f.accept (visitor);
454 : }
455 :
456 3106472 : foreach (Method m in methods) {
457 1499812 : m.accept (visitor);
458 : }
459 : }
460 :
461 362640 : public override bool check (CodeContext context) {
462 362640 : if (checked) {
463 297667 : return !error;
464 : }
465 :
466 64973 : checked = true;
467 :
468 64973 : var a = get_attribute ("CCode");
469 22229 : if (a != null && a.has_argument ("gir_namespace")) {
470 4602 : var new_gir = a.get_string ("gir_namespace");
471 4602 : var old_gir = source_reference.file.gir_namespace;
472 4602 : if (old_gir != null && old_gir != new_gir) {
473 2 : source_reference.file.gir_ambiguous = true;
474 : }
475 4602 : source_reference.file.gir_namespace = new_gir;
476 : }
477 64973 : if (a != null && a.has_argument ("gir_version")) {
478 4602 : source_reference.file.gir_version = a.get_string ("gir_version");
479 : }
480 :
481 142355 : foreach (Field f in fields) {
482 38691 : if (f.binding == MemberBinding.INSTANCE) {
483 0 : Report.error (f.source_reference, "instance fields are not allowed outside of data types");
484 0 : f.error = true;
485 0 : error = true;
486 38691 : } else if (f.binding == MemberBinding.CLASS) {
487 0 : Report.error (f.source_reference, "class fields are not allowed outside of classes");
488 0 : f.error = true;
489 0 : error = true;
490 : }
491 : }
492 :
493 1868177 : foreach (Method m in methods) {
494 901602 : if (m is CreationMethod) {
495 0 : Report.error (m.source_reference, "construction methods may only be declared within classes and structs");
496 0 : m.error = true;
497 0 : error = true;
498 : }
499 901602 : if (m.binding == MemberBinding.INSTANCE) {
500 0 : Report.error (m.source_reference, "instance methods are not allowed outside of data types");
501 0 : m.error = true;
502 0 : error = true;
503 901602 : } else if (m.binding == MemberBinding.CLASS) {
504 0 : Report.error (m.source_reference, "class methods are not allowed outside of classes");
505 0 : m.error = true;
506 0 : error = true;
507 : }
508 : }
509 :
510 202525 : foreach (Namespace ns in namespaces) {
511 68776 : ns.check (context);
512 : }
513 :
514 64973 : return !error;
515 : }
516 :
517 0 : public override string to_string () {
518 0 : if (name == null) {
519 0 : return "(root namespace)";
520 : } else {
521 0 : return "namespace %s".printf (name);
522 : }
523 : }
524 : }
|