3 * Copyright (C) 2006-2009 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>
27 * Represents a node in the symbol tree.
29 public abstract class Vala
.Symbol
: CodeNode
{
31 * The parent of this symbol.
33 public weak Symbol? parent_symbol
{
44 * The scope this symbol opens.
46 public weak Scope owner
{
52 _scope
.parent_scope
= value
;
59 public string? name
{ get; set; }
62 * Specifies whether this symbol is active.
64 * Symbols may become inactive when they only apply to a part of a
65 * scope. This is used for local variables not declared at the beginning
66 * of the block to determine which variables need to be freed before
69 public bool active
{ get; set; default = true; }
72 * Specifies whether this symbol has been accessed.
74 public bool used
{ get; set; }
77 * Specifies the accessibility of this symbol. Public accessibility
78 * doesn't limit access. Default accessibility limits access to this
79 * program or library. Private accessibility limits access to instances
80 * of the contained type.
82 public SymbolAccessibility access
{ get; set; }
85 * Check if this symbol is just internal API (and therefore doesn't need
86 * to be listed in header files for instance) by traversing parent symbols
87 * and checking their accessibility.
89 public bool is_internal_symbol () {
90 if (!external
&& external_package
) {
91 // non-external symbols in VAPI files are internal symbols
95 for (Symbol sym
= this
; null != sym
; sym
= sym
.parent_symbol
) {
96 if (SymbolAccessibility
.PRIVATE
== sym
.access
) {
105 get { return _scope
; }
109 * Specifies whether the implementation is external, for example in
110 * a separate C source file or in an external library.
112 public bool external
{ get; set; }
115 * Specifies whether the implementation is in an external library.
117 public bool external_package
{
119 return (source_reference
!= null && source_reference
.file
.external_package
);
123 private weak Scope _owner
;
124 private Scope _scope
;
126 public Symbol (string? name
, SourceReference? source_reference
) {
128 this
.source_reference
= source_reference
;
129 _scope
= new
Scope (this
);
133 * Returns the fully expanded name of this symbol for use in
134 * human-readable messages.
138 public string get_full_name () {
139 if (parent_symbol
== null) {
144 return parent_symbol
.get_full_name ();
147 if (parent_symbol
.get_full_name () == null) {
151 return "%s.%s".printf (parent_symbol
.get_full_name (), name
);
155 * Returns the camel case string to be prepended to the name of members
156 * of this symbol when used in C code.
158 * @return the camel case prefix to be used in C code
160 public virtual string get_cprefix () {
169 * Returns the C name of this symbol in lower case. Words are
170 * separated by underscores. The lower case C name of the parent symbol
171 * is prefix of the result, if there is one.
173 * @param infix a string to be placed between namespace and data type
175 * @return the lower case name to be used in C code
177 public virtual string?
get_lower_case_cname (string? infix
= null) {
182 * Returns the string to be prefixed to members of this symbol in
183 * lower case when used in C code.
185 * @return the lower case prefix to be used in C code
187 public virtual string get_lower_case_cprefix () {
192 * Returns a list of C header filenames users of this symbol must
195 * @return list of C header filenames for this symbol
197 public virtual Gee
.List
<string> get_cheader_filenames () {
198 return new ArrayList
<string> ();
202 * Converts a string from CamelCase to lower_case.
204 * @param camel_case a string in camel case
205 * @return the specified string converted to lower case
207 public static string camel_case_to_lower_case (string camel_case
) {
208 var result_builder
= new
StringBuilder ("");
210 weak string i
= camel_case
;
213 while (i
.len () > 0) {
214 unichar c
= i
.get_char ();
215 if (c
.isupper () && !first
) {
216 /* current character is upper case and
217 * we're not at the beginning */
218 weak string t
= i
.prev_char ();
219 bool prev_upper
= t
.get_char ().isupper ();
221 bool next_upper
= t
.get_char ().isupper ();
222 if (!prev_upper
|| (i
.len () >= 2 && !next_upper
)) {
223 /* previous character wasn't upper case or
224 * next character isn't upper case*/
225 long len
= result_builder
.str
.len ();
226 if (len
!= 1 && result_builder
.str
.offset (len
- 2).get_char () != '_') {
227 /* we're not creating 1 character words */
228 result_builder
.append_c ('_');
233 result_builder
.append_unichar (c
.tolower ());
239 return result_builder
.str
;
243 * Converts a string from lower_case to CamelCase.
245 * @param lower_case a string in lower case
246 * @return the specified string converted to camel case
248 public static string lower_case_to_camel_case (string lower_case
) {
249 var result_builder
= new
StringBuilder ("");
251 weak string i
= lower_case
;
253 bool last_underscore
= true;
254 while (i
.len () > 0) {
255 unichar c
= i
.get_char ();
257 last_underscore
= true;
258 } else if (c
.isupper ()) {
259 // original string is not lower_case, don't apply transformation
261 } else if (last_underscore
) {
262 result_builder
.append_unichar (c
.toupper ());
263 last_underscore
= false;
265 result_builder
.append_unichar (c
);
271 return result_builder
.str
;
274 // get the top scope from where this symbol is still accessible
275 public Scope?
get_top_accessible_scope () {
276 if (access
!= SymbolAccessibility
.PUBLIC
) {
277 // private symbols are accessible within the scope where the symbol has been declared
280 // skip scopes of normal namespaces, they don't influence accessibility
281 while (scope
!= null && scope
.owner is Namespace
&& scope
.owner
.name
!= null) {
282 scope
= scope
.parent_scope
;
288 if (parent_symbol
== null) {
292 // if this is a public symbol, it's equally accessible as the parent symbol
293 return parent_symbol
.get_top_accessible_scope ();
297 public enum Vala
.SymbolAccessibility
{