1/* class.vala
2 *
3 * Copyright (C) 2008-2011  Florian Brosch
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 * 	Florian Brosch <flo.brosch@gmail.com>
21 */
22
23
24using Valadoc.Content;
25
26/**
27 * Represents a class declaration.
28 */
29public class Valadoc.Api.Class : TypeSymbol {
30	private Vala.ArrayList<TypeReference> interfaces;
31
32	private string? dbus_name;
33	private string? take_value_function_cname;
34	private string? get_value_function_cname;
35	private string? set_value_function_cname;
36	private string? unref_function_name;
37	private string? ref_function_name;
38	private string? free_function_name;
39	private string? finalize_function_name;
40	private string? param_spec_function_name;
41	private string? type_id;
42	private string? is_class_type_macro_name;
43	private string? class_type_macro_name;
44	private string? class_macro_name;
45	private string? private_cname;
46	private string? cname;
47
48	public Class (Node parent, SourceFile file, string name, Vala.SymbolAccessibility accessibility,
49				  SourceComment? comment,
50				  Vala.Class data)
51	{
52		bool is_basic_type = data.base_class == null && data.name == "string";
53
54		base (parent, file, name, accessibility, comment, is_basic_type, data);
55
56		this.interfaces = new Vala.ArrayList<TypeReference> ();
57
58		if (!data.is_compact) {
59			this.is_class_type_macro_name = Vala.get_ccode_class_type_check_function (data);
60			this.class_type_macro_name = Vala.get_ccode_class_type_function (data);
61			this.class_macro_name = Vala.get_ccode_type_get_function (data);
62			this.private_cname = _get_private_cname (data);
63		}
64		this.dbus_name = Vala.GDBusModule.get_dbus_name (data);
65		this.type_id = Vala.get_ccode_type_id (data);
66		this.cname = Vala.get_ccode_name (data);
67
68		this.param_spec_function_name = Vala.get_ccode_param_spec_function (data);
69
70		this.unref_function_name = Vala.get_ccode_unref_function (data);
71		this.ref_function_name = Vala.get_ccode_ref_function (data);
72		this.finalize_function_name = (data.is_fundamental () ? "%sfinalize".printf (Vala.get_ccode_lower_case_prefix (data)) : null);
73		this.free_function_name = (data.is_compact ? Vala.get_ccode_free_function (data) : null);
74
75		this.take_value_function_cname = Vala.get_ccode_take_value_function (data);
76		this.get_value_function_cname = Vala.get_ccode_get_value_function (data);
77		this.set_value_function_cname = Vala.get_ccode_set_value_function (data);
78
79		this.is_fundamental = data.is_fundamental ();
80		this.is_abstract = data.is_abstract;
81		this.is_sealed = data.is_sealed;
82	}
83
84	string? _get_private_cname (Vala.Class element) {
85		if (element.is_compact) {
86			return null;
87		}
88
89		string? cname = Vala.get_ccode_name (element);
90		return (cname != null ? cname + "Private" : null);
91	}
92
93	/**
94	 * Specifies the base class.
95	 */
96	public TypeReference? base_type {
97		set;
98		get;
99	}
100
101	/**
102	 * Returns the name of this class as it is used in C.
103	 */
104	public string? get_cname () {
105		return cname;
106	}
107
108	/**
109	 * Returns the name of this class' private data structure as it is used in C.
110	 */
111	public string? get_private_cname () {
112		return private_cname;
113	}
114
115	/**
116	 * Returns the C symbol representing the runtime type id for this data type.
117	 */
118	public string? get_type_id () {
119		return type_id;
120	}
121
122	/**
123	 * Returns the C function name that increments the reference count of
124	 * instances of this data type.
125	 *
126	 * @return the name of the C function or null if this data type does not
127	 *         support reference counting
128	 */
129	public string? get_ref_function_cname () {
130		return ref_function_name;
131	}
132
133	/**
134	 * Returns the C function name that decrements the reference count of
135	 * instances of this data type.
136	 *
137	 * @return the name of the C function or null if this data type does not
138	 *         support reference counting
139	 */
140	public string? get_unref_function_cname () {
141		return unref_function_name;
142	}
143
144	/**
145	 * Returns the C function name that frees the
146	 * instances of this data type.
147	 *
148	 * @return the name of the C function or null
149	 */
150	public string? get_free_function_name () {
151		return free_function_name;
152	}
153
154	/**
155	 * Returns the C function name that finalizes the
156	 * instances of this data type.
157	 *
158	 * @return the name of the C function or null
159	 */
160	public string? get_finalize_function_name () {
161		return finalize_function_name;
162	}
163
164	/**
165	 * Returns the cname of the GValue parameter spec function.
166	 */
167	public string? get_param_spec_function_cname () {
168		return param_spec_function_name;
169	}
170
171	/**
172	 * Returns the cname of the GValue setter function.
173	 */
174	public string? get_set_value_function_cname () {
175		return set_value_function_cname;
176	}
177
178	/**
179	 * Returns the cname of the GValue getter function.
180	 */
181	public string? get_get_value_function_cname () {
182		return get_value_function_cname;
183	}
184
185	/**
186	 * Returns the cname of the GValue taker function.
187	 */
188	public string? get_take_value_function_cname () {
189		return take_value_function_cname;
190	}
191
192	/**
193	 * Returns the dbus-name.
194	 */
195	public string? get_dbus_name () {
196		return dbus_name;
197	}
198
199	/**
200	 * Gets the name of the GType macro which returns the class struct.
201	 */
202	public string get_class_macro_name () {
203		return class_macro_name;
204	}
205
206	/**
207	 * Gets the name of the GType macro which returns the type of the class.
208	 */
209	public string get_class_type_macro_name () {
210		return class_type_macro_name;
211	}
212
213	/**
214	 * Gets the name of the GType macro which returns whether a class instance is of a given type.
215	 */
216	public string get_is_class_type_macro_name () {
217		return is_class_type_macro_name;
218	}
219
220	/**
221	 * Returns a list of all newly implemented interfaces.
222	 *
223	 * @see get_full_implemented_interface_list
224	 */
225	public Vala.Collection<TypeReference> get_implemented_interface_list () {
226		return this.interfaces;
227	}
228
229	private Vala.Collection<TypeReference> _full_implemented_interfaces = null;
230
231	/**
232	 * Returns a list of all implemented interfaces.
233	 *
234	 * @see get_implemented_interface_list
235	 */
236	public Vala.Collection<TypeReference> get_full_implemented_interface_list () {
237		if (_full_implemented_interfaces == null) {
238			_full_implemented_interfaces = new Vala.ArrayList<TypeReference> ();
239			_full_implemented_interfaces.add_all (this.interfaces);
240
241			if (base_type != null) {
242				_full_implemented_interfaces.add_all (((Class) base_type.data_type).get_full_implemented_interface_list ());
243			}
244		}
245
246		return _full_implemented_interfaces;
247	}
248
249	public void add_interface (TypeReference iface) {
250		interfaces.add (iface);
251	}
252
253	/**
254	 * Specifies whether this class is abstract.
255	 */
256	public bool is_abstract {
257		private set;
258		get;
259	}
260
261	/**
262	 * Specifies whether this class is sealed. Sealed classes may not be
263	 * sub-classed.
264	 */
265	public bool is_sealed {
266		private set;
267		get;
268	}
269
270	/**
271	 * Specifies whether this class is fundamental.
272	 */
273	public bool is_fundamental {
274		private set;
275		get;
276	}
277
278	public bool is_compact {
279		get {
280			return ((Vala.Class) data).is_compact;
281		}
282	}
283
284	/**
285	 * {@inheritDoc}
286	 */
287	public override NodeType node_type { get { return NodeType.CLASS; } }
288
289	/**
290	 * {@inheritDoc}
291	 */
292	public override void accept (Visitor visitor) {
293		visitor.visit_class (this);
294	}
295
296	private Vala.Set<Interface> _known_derived_interfaces = new Vala.HashSet<Interface> ();
297	private Vala.Set<Class> _known_child_classes = new Vala.HashSet<Class> ();
298
299	/**
300	 * Returns a list of all known classes based on this class
301	 */
302	public Vala.Collection<Class> get_known_child_classes () {
303		return _known_child_classes;
304	}
305
306	/**
307	 * Returns a list of all known interfaces based on this class
308	 */
309	public Vala.Collection<Interface> get_known_derived_interfaces () {
310		return _known_derived_interfaces;
311	}
312
313	public void register_derived_interface (Interface iface) {
314		_known_derived_interfaces.add (iface);
315	}
316
317	public void register_child_class (Class cl) {
318		if (this.base_type != null) {
319			((Class) this.base_type.data_type).register_child_class (cl);
320		}
321
322		_known_child_classes.add (cl);
323	}
324
325	/**
326	 * {@inheritDoc}
327	 */
328	protected override Inline build_signature () {
329		var signature = new SignatureBuilder ();
330
331		signature.append_keyword (accessibility.to_string ());
332		if (is_abstract) {
333			signature.append_keyword ("abstract");
334		}
335		if (is_sealed) {
336			signature.append_keyword ("sealed");
337		}
338		signature.append_keyword ("class");
339		signature.append_symbol (this);
340
341		var type_parameters = get_children_by_type (NodeType.TYPE_PARAMETER, false);
342		if (type_parameters.size > 0) {
343			signature.append ("<", false);
344			bool first = true;
345			foreach (Item param in type_parameters) {
346				if (!first) {
347					signature.append (",", false);
348				}
349				signature.append_content (param.signature, false);
350				first = false;
351			}
352			signature.append (">", false);
353		}
354
355		bool first = true;
356		if (base_type != null) {
357			signature.append (":");
358
359			signature.append_content (base_type.signature);
360			first = false;
361		}
362
363		if (interfaces.size > 0) {
364			if (first) {
365				signature.append (":");
366			}
367
368			foreach (Item implemented_interface in interfaces) {
369				if (!first) {
370					signature.append (",", false);
371				}
372				signature.append_content (implemented_interface.signature);
373				first = false;
374			}
375		}
376
377		return signature.get ();
378	}
379}
380
381