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
20 * Jürg Billeter <j@bitron.ch>
26 * Code visitor resolving symbol names.
28 public class Vala
.SymbolResolver
: CodeVisitor
{
31 List
<weak NamespaceReference
> current_using_directives
;
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 ()));
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) {
171 Report
.error (ns
.source_reference
, "The namespace name `%s' could not be found".printf (ns
.name
));
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;
183 if (type
.namespace_name
== 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
195 foreach (NamespaceReference ns
in current_using_directives
) {
200 var local_sym
= ns
.namespace_symbol
.lookup (type
.type_name
);
201 if (local_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 ()));
211 Report
.error (type
.source_reference
, "The type name `%s' could not be found".printf (type
.type_name
));
214 if (sym
.node is TypeParameter
) {
215 type
.type_parameter
= (TypeParameter
) sym
.node
;
217 type
.data_type
= (DataType
) sym
.node
;
220 var ns_symbol
= root_symbol
.lookup (type
.namespace_name
);
221 if (ns_symbol
== null) {
223 Report
.error (type
.source_reference
, "The namespace name `%s' could not be found".printf (type
.namespace_name
));
227 var sym
= ns_symbol
.lookup (type
.type_name
);
229 Report
.error (type
.source_reference
, "The type name `%s' does not exist in the namespace `%s'".printf (type
.type_name
, type
.namespace_name
));
232 type
.data_type
= (DataType
) sym
.node
;
235 if (type
.pointer_level
> 0) {
236 if (type
.data_type
== null) {
238 Report
.error (type
.source_reference
, "Pointer to `%s' not supported".printf (type
.type_name
));
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
);
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;