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 node in the symbol tree.
28 public abstract class Vala
.Symbol
: CodeNode
{
30 * The parent of this symbol.
32 public weak Symbol? parent_symbol
{
43 * The scope this symbol is a part of
45 public weak Scope owner
{
51 _scope
.parent_scope
= value
;
58 public string? name
{ get; set; }
61 * Specifies whether this symbol is active.
63 * Symbols may become inactive when they only apply to a part of a
64 * scope. This is used for local variables not declared at the beginning
65 * of the block to determine which variables need to be freed before
68 public bool active
{ get; set; default = true; }
71 * Specifies whether this symbol has been accessed.
73 public bool used
{ get; set; }
76 * Specifies whether this symbol is anonymous and has no public defintion.
78 public bool anonymous
{ get; set; }
81 * Specifies the accessibility of this symbol. Public accessibility
82 * doesn't limit access. Default accessibility limits access to this
83 * program or library. Private accessibility limits access to instances
84 * of the contained type.
86 public SymbolAccessibility access
{ get; set; }
88 public Comment? comment
{ get; set; }
91 private VersionAttribute _version
;
94 * The associated [Version] attribute
96 public VersionAttribute version
{
98 if (_version
== null) {
99 _version
= new
VersionAttribute (this
);
107 * Specifies whether this method explicitly hides a member of a base
110 public bool hides
{ get; set; }
113 * Check if this symbol is just internal API (and therefore doesn't need
114 * to be listed in header files for instance) by traversing parent symbols
115 * and checking their accessibility.
117 public bool is_internal_symbol () {
118 if (!external
&& external_package
) {
119 // non-external symbols in VAPI files are internal symbols
123 for (Symbol sym
= this
; null != sym
; sym
= sym
.parent_symbol
) {
124 if (sym
.access
== SymbolAccessibility
.PRIVATE
125 || sym
.access
== SymbolAccessibility
.INTERNAL
) {
133 public bool is_private_symbol () {
134 if (!external
&& external_package
) {
135 // non-external symbols in VAPI files are private symbols
139 for (Symbol sym
= this
; null != sym
; sym
= sym
.parent_symbol
) {
140 if (sym
.access
== SymbolAccessibility
.PRIVATE
) {
149 * The scope this symbol opens.
152 get { return _scope
; }
156 * Specifies whether the implementation is external, for example in
157 * a separate C source file or in an external library.
159 public bool external
{ get; set; }
162 * Specifies whether the implementation is in an external library.
164 public bool external_package
{
166 return source_type
== SourceFileType
.PACKAGE
;
171 * Specifies whether the implementation came from the commandline.
173 public bool from_commandline
{
175 if (source_reference
!= null) {
176 return source_reference
.file
.from_commandline
;
184 * Gets the SourceFileType of the source file that this symbol
185 * came from, or SourceFileType.NONE.
187 public SourceFileType source_type
{
189 if (source_reference
!= null) {
190 return source_reference
.file
.file_type
;
192 return SourceFileType
.NONE
;
197 private weak Scope _owner
;
198 private Scope _scope
;
200 public Symbol (string? name
, SourceReference? source_reference
, Comment? comment
= null) {
202 this
.source_reference
= source_reference
;
203 this
.comment
= comment
;
204 _scope
= new
Scope (this
);
208 * Returns the fully expanded name of this symbol for use in
209 * human-readable messages.
213 public string get_full_name () {
214 if (parent_symbol
== null) {
219 return parent_symbol
.get_full_name ();
222 if (parent_symbol
.get_full_name () == null) {
226 if (name
.has_prefix (".")) {
227 return "%s%s".printf (parent_symbol
.get_full_name (), name
);
229 return "%s.%s".printf (parent_symbol
.get_full_name (), name
);
234 * Converts a string from CamelCase to lower_case.
236 * @param camel_case a string in camel case
237 * @return the specified string converted to lower case
239 public static string camel_case_to_lower_case (string camel_case
) {
240 if ("_" in camel_case
) {
241 // do not insert additional underscores if input is not real camel case
242 return camel_case
.down ();
245 var result_builder
= new
StringBuilder ("");
247 weak string i
= camel_case
;
250 while (i
.length
> 0) {
251 unichar c
= i
.get_char ();
252 if (c
.isupper () && !first
) {
253 /* current character is upper case and
254 * we're not at the beginning */
255 weak string t
= i
.prev_char ();
256 bool prev_upper
= t
.get_char ().isupper ();
258 bool next_upper
= t
.get_char ().isupper ();
259 if (!prev_upper
|| (i
.length
>= 2 && !next_upper
)) {
260 /* previous character wasn't upper case or
261 * next character isn't upper case*/
262 long len
= result_builder
.str
.length
;
263 if (len
!= 1 && result_builder
.str
.get_char (len
- 2) != '_') {
264 /* we're not creating 1 character words */
265 result_builder
.append_c ('_');
270 result_builder
.append_unichar (c
.tolower ());
276 return result_builder
.str
;
280 * Converts a string from lower_case to CamelCase.
282 * @param lower_case a string in lower case
283 * @return the specified string converted to camel case
285 public static string lower_case_to_camel_case (string lower_case
) {
286 var result_builder
= new
StringBuilder ("");
288 weak string i
= lower_case
;
290 bool last_underscore
= true;
291 while (i
.length
> 0) {
292 unichar c
= i
.get_char ();
294 last_underscore
= true;
295 } else if (c
.isupper ()) {
296 // original string is not lower_case, don't apply transformation
298 } else if (last_underscore
) {
299 result_builder
.append_unichar (c
.toupper ());
300 last_underscore
= false;
302 result_builder
.append_unichar (c
);
308 return result_builder
.str
;
311 // get the top scope from where this symbol is still accessible
312 public Scope?
get_top_accessible_scope (bool is_internal
= false) {
313 if (access
== SymbolAccessibility
.PRIVATE
) {
314 // private symbols are accessible within the scope where the symbol has been declared
318 if (access
== SymbolAccessibility
.INTERNAL
) {
322 if (parent_symbol
== null) {
323 // this is the root symbol
325 // only accessible within the same library
334 // if this is a public symbol, it's equally accessible as the parent symbol
335 return parent_symbol
.get_top_accessible_scope (is_internal
);
338 public virtual bool is_instance_member () {
339 bool instance
= true;
341 var f
= (Field
) this
;
342 instance
= (f
.binding
== MemberBinding
.INSTANCE
);
343 } else if (this is Method
) {
344 var m
= (Method
) this
;
345 if (!(m is CreationMethod
)) {
346 instance
= (m
.binding
== MemberBinding
.INSTANCE
);
348 } else if (this is Property
) {
349 var prop
= (Property
) this
;
350 instance
= (prop
.binding
== MemberBinding
.INSTANCE
);
351 } else if (this is EnumValue
) {
353 } else if (this is ErrorCode
) {
360 public virtual bool is_class_member () {
363 var f
= (Field
) this
;
364 isclass
= (f
.binding
== MemberBinding
.CLASS
);
365 } else if (this is Method
) {
366 var m
= (Method
) this
;
367 if (!(m is CreationMethod
)) {
368 isclass
= (m
.binding
== MemberBinding
.CLASS
);
370 } else if (this is Property
) {
371 var prop
= (Property
) this
;
372 isclass
= (prop
.binding
== MemberBinding
.CLASS
);
373 } else if (this is EnumValue
) {
375 } else if (this is ErrorCode
) {
382 public Symbol?
get_hidden_member () {
385 if (parent_symbol is Class
) {
386 var cl
= ((Class
) parent_symbol
).base_class
;
388 sym
= cl
.scope
.lookup (name
);
389 if (sym
!= null && sym
.access
!= SymbolAccessibility
.PRIVATE
) {
394 } else if (parent_symbol is Struct
) {
395 var st
= ((Struct
) parent_symbol
).base_struct
;
397 sym
= st
.scope
.lookup (name
);
398 if (sym
!= null && sym
.access
!= SymbolAccessibility
.PRIVATE
) {
408 // check whether this symbol is at least as accessible as the specified symbol
409 public bool is_accessible (Symbol sym
) {
410 Scope sym_scope
= sym
.get_top_accessible_scope ();
411 Scope this_scope
= this
.get_top_accessible_scope ();
412 if ((sym_scope
== null && this_scope
!= null)
413 || (sym_scope
!= null && !sym_scope
.is_subscope_of (this_scope
))) {
420 public virtual void add_namespace (Namespace ns
) {
421 Report
.error (ns
.source_reference
, "unexpected declaration");
424 public virtual void add_class (Class cl
) {
425 Report
.error (cl
.source_reference
, "unexpected declaration");
428 public virtual void add_interface (Interface iface
) {
429 Report
.error (iface
.source_reference
, "unexpected declaration");
432 public virtual void add_struct (Struct st
) {
433 Report
.error (st
.source_reference
, "unexpected declaration");
436 public virtual void add_enum (Enum en
) {
437 Report
.error (en
.source_reference
, "unexpected declaration");
440 public virtual void add_error_domain (ErrorDomain edomain
) {
441 Report
.error (edomain
.source_reference
, "unexpected declaration");
444 public virtual void add_delegate (Delegate d
) {
445 Report
.error (d
.source_reference
, "unexpected declaration");
448 public virtual void add_constant (Constant constant
) {
449 Report
.error (constant
.source_reference
, "unexpected declaration");
452 public virtual void add_field (Field f
) {
453 Report
.error (f
.source_reference
, "unexpected declaration");
456 public virtual void add_method (Method m
) {
457 Report
.error (m
.source_reference
, "unexpected declaration");
460 public virtual void add_property (Property prop
) {
461 Report
.error (prop
.source_reference
, "unexpected declaration");
464 public virtual void add_signal (Signal sig
) {
465 Report
.error (sig
.source_reference
, "unexpected declaration");
468 public virtual void add_constructor (Constructor c
) {
469 Report
.error (c
.source_reference
, "unexpected declaration");
472 public virtual void add_destructor (Destructor d
) {
473 Report
.error (d
.source_reference
, "unexpected declaration");
477 public enum Vala
.SymbolAccessibility
{
484 public enum Vala
.MemberBinding
{