remove obsolete ref modifier and callback keyword
[vala-lang.git] / vala / valasymbolresolver.vala
blobe2c9f017e13f658b869e88b2b2b7a5d709a5331e
1 /* valasymbolresolver.vala
3 * Copyright (C) 2006-2007 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 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 * Code visitor resolving symbol names.
28 public class Vala.SymbolResolver : CodeVisitor {
29 Symbol root_symbol;
30 Symbol current_scope;
31 List<weak NamespaceReference> current_using_directives;
33 Class object_class;
35 /**
36 * Resolve symbol names in the specified code context.
38 * @param context a code context
40 public void resolve (CodeContext! context) {
41 root_symbol = context.get_root ();
42 current_scope = root_symbol;
44 // TODO: don't require GLib namespace in symbol resolver
45 var glib_ns = root_symbol.lookup ("GLib");
46 if (glib_ns != null) {
47 object_class = (Class) glib_ns.lookup ("Object").node;
50 context.accept (this);
53 public override void visit_source_file (SourceFile! file) {
54 current_using_directives = file.get_using_directives ();
56 file.accept_children (this);
58 current_using_directives = null;
61 public override void visit_namespace (Namespace! ns) {
62 current_scope = ns.symbol;
64 ns.accept_children (this);
66 // don't use current_scope.parent_symbol as that would be null
67 // if the current namespace is SourceFile.global_namespace
68 current_scope = root_symbol;
71 public override void visit_class (Class! cl) {
72 current_scope = cl.symbol;
74 cl.accept_children (this);
76 foreach (TypeReference type in cl.get_base_types ()) {
77 if (type.data_type is Class) {
78 if (cl.base_class != null) {
79 Report.error (type.source_reference, "%s: Classes cannot have multiple base classes (`%s' and `%s')".printf (cl.symbol.get_full_name (), cl.base_class.symbol.get_full_name (), type.data_type.symbol.get_full_name ()));
80 return;
82 cl.base_class = (Class) type.data_type;
85 if (cl.base_class == null && cl != object_class) {
86 var object_type = new TypeReference ();
87 object_type.data_type = object_class;
88 cl.add_base_type (object_type);
89 cl.base_class = object_class;
92 current_scope = current_scope.parent_symbol;
95 public override void visit_struct (Struct! st) {
96 current_scope = st.symbol;
98 st.accept_children (this);
100 current_scope = current_scope.parent_symbol;
103 public override void visit_interface (Interface! iface) {
104 current_scope = iface.symbol;
106 iface.accept_children (this);
108 current_scope = current_scope.parent_symbol;
111 public override void visit_enum (Enum! en) {
112 current_scope = en.symbol;
114 en.accept_children (this);
116 current_scope = current_scope.parent_symbol;
119 public override void visit_callback (Callback! cb) {
120 current_scope = cb.symbol;
122 cb.accept_children (this);
124 current_scope = current_scope.parent_symbol;
127 public override void visit_constant (Constant! c) {
128 c.accept_children (this);
131 public override void visit_field (Field! f) {
132 f.accept_children (this);
135 public override void visit_method (Method! m) {
136 m.accept_children (this);
139 public override void visit_creation_method (CreationMethod! m) {
140 m.accept_children (this);
143 public override void visit_formal_parameter (FormalParameter! p) {
144 p.accept_children (this);
147 public override void visit_property (Property! prop) {
148 prop.accept_children (this);
151 public override void visit_property_accessor (PropertyAccessor! acc) {
152 acc.accept_children (this);
155 public override void visit_signal (Signal! sig) {
156 sig.accept_children (this);
159 public override void visit_constructor (Constructor! c) {
160 c.accept_children (this);
163 public override void visit_destructor (Destructor! d) {
164 d.accept_children (this);
167 public override void visit_namespace_reference (NamespaceReference! ns) {
168 ns.namespace_symbol = current_scope.lookup (ns.name);
169 if (ns.namespace_symbol == null) {
170 ns.error = true;
171 Report.error (ns.source_reference, "The namespace name `%s' could not be found".printf (ns.name));
172 return;
176 public override void visit_type_reference (TypeReference! type) {
177 if (type.type_name == null || type.type_name == "void") {
178 // reset transfers_ownership
179 type.transfers_ownership = false;
180 return;
183 if (type.namespace_name == null) {
184 Symbol sym = null;
185 Symbol scope = current_scope;
186 while (sym == null && scope != null) {
187 sym = scope.lookup (type.type_name);
188 scope = scope.parent_symbol;
189 if (sym != null && !(sym.node is DataType) && !(sym.node is TypeParameter)) {
190 // ignore non-type symbols
191 sym = null;
194 if (sym == null) {
195 foreach (NamespaceReference ns in current_using_directives) {
196 if (ns.error) {
197 continue;
200 var local_sym = ns.namespace_symbol.lookup (type.type_name);
201 if (local_sym != null) {
202 if (sym != null) {
203 Report.error (type.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (type.type_name, sym.get_full_name (), local_sym.get_full_name ()));
204 return;
206 sym = local_sym;
210 if (sym == null) {
211 Report.error (type.source_reference, "The type name `%s' could not be found".printf (type.type_name));
212 return;
214 if (sym.node is TypeParameter) {
215 type.type_parameter = (TypeParameter) sym.node;
216 } else {
217 type.data_type = (DataType) sym.node;
219 } else {
220 var ns_symbol = root_symbol.lookup (type.namespace_name);
221 if (ns_symbol == null) {
222 type.error = true;
223 Report.error (type.source_reference, "The namespace name `%s' could not be found".printf (type.namespace_name));
224 return;
227 var sym = ns_symbol.lookup (type.type_name);
228 if (sym == null) {
229 Report.error (type.source_reference, "The type name `%s' does not exist in the namespace `%s'".printf (type.type_name, type.namespace_name));
230 return;
232 type.data_type = (DataType) sym.node;
235 if (type.pointer_level > 0) {
236 if (type.data_type == null) {
237 type.error = true;
238 Report.error (type.source_reference, "Pointer to `%s' not supported".printf (type.type_name));
239 return;
241 var referent_type = new TypeReference ();
242 referent_type.data_type = type.data_type;
243 referent_type.pointer_level = type.pointer_level - 1;
245 if (type.data_type.is_reference_type ()) {
246 referent_type.takes_ownership = type.takes_ownership;
248 type.data_type = referent_type.data_type.get_pointer ();
249 type.add_type_argument (referent_type);
251 visit_type_reference (referent_type);
254 /* check for array */
255 if (type.array_rank > 0) {
256 var element_type = new TypeReference ();
257 element_type.data_type = type.data_type;
258 element_type.type_parameter = type.type_parameter;
259 foreach (TypeReference type_arg in type.get_type_arguments ()) {
260 element_type.add_type_argument (type_arg);
262 type.remove_all_type_arguments ();
264 if (type.data_type != null) {
265 if (type.data_type.is_reference_type ()) {
266 element_type.takes_ownership = type.takes_ownership;
268 type.data_type = element_type.data_type.get_array (type.array_rank);
269 } else {
270 type.data_type = element_type.type_parameter.get_array (type.array_rank);
271 type.type_parameter = null;
273 type.add_type_argument (element_type);
276 if (type.data_type != null && !type.data_type.is_reference_type ()) {
277 /* reset takes_ownership and transfers_ownership of
278 * value-types for contexts where types are ref by
279 * default (field declarations and method return types)
281 type.takes_ownership = false;
282 type.transfers_ownership = false;