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 an object signal. Signals enable objects to provide notifications.
28 public class Vala
.Signal
: Symbol
, Lockable
{
30 * The return type of handlers of this signal.
32 public DataType return_type
{
33 get { return _return_type
; }
36 _return_type
.parent_node
= this
;
51 * Specifies whether this signal has an emitter wrapper function.
53 public bool has_emitter
{ get; set; }
56 * Specifies whether this signal has virtual method handler.
58 public bool is_virtual
{ get; set; }
60 private List
<Parameter
> parameters
= new ArrayList
<Parameter
> ();
62 * Refers to the default signal handler, which is an anonymous
63 * function in the scope.
65 public Method default_handler
{ get; private set; }
67 public bool is_detailed
{ get; set; }
69 public bool no_recurse
{ get; set; }
71 public string run_type
{ get; set; }
73 public bool is_action
{ get; set; }
75 public bool no_hooks
{ get; set; }
80 private bool lock_used
= false;
82 private DataType _return_type
;
87 * Creates a new signal.
89 * @param name signal name
90 * @param return_type signal return type
91 * @param source reference to source code
92 * @return newly created signal
94 public Signal (string name
, DataType return_type
, SourceReference? source_reference
= null, Comment? comment
= null) {
95 base (name
, source_reference
, comment
);
96 this
.return_type
= return_type
;
97 this
.run_type
= "last";
101 * Appends parameter to signal handler.
103 * @param param a formal parameter
105 public void add_parameter (Parameter param
) {
106 // default C parameter position
107 param
.cparameter_position
= parameters
.size
+ 1;
108 param
.carray_length_parameter_position
= param
.cparameter_position
+ 0.1;
109 param
.cdelegate_target_parameter_position
= param
.cparameter_position
+ 0.1;
110 param
.cdestroy_notify_parameter_position
= param
.cparameter_position
+ 0.1;
112 parameters
.add (param
);
113 scope
.add (param
.name
, param
);
116 public List
<Parameter
> get_parameters () {
121 * Returns generated delegate to be used for signal handlers.
125 public Delegate
get_delegate (DataType sender_type
, CodeNode node_reference
) {
126 var actual_return_type
= return_type
.get_actual_type (sender_type
, null, node_reference
);
128 var generated_delegate
= new
Delegate (null, actual_return_type
);
129 generated_delegate
.has_target
= true;
130 generated_delegate
.access
= SymbolAccessibility
.PUBLIC
;
131 generated_delegate
.owner
= scope
;
133 // sender parameter is never null and doesn't own its value
134 var sender_param_type
= sender_type
.copy ();
135 sender_param_type
.value_owned
= false;
136 sender_param_type
.nullable
= false;
138 generated_delegate
.sender_type
= sender_param_type
;
140 foreach (Parameter param
in parameters
) {
141 var actual_param
= param
.copy ();
142 actual_param
.variable_type
= actual_param
.variable_type
.get_actual_type (sender_type
, null, node_reference
);
143 generated_delegate
.add_parameter (actual_param
);
146 scope
.add (null, generated_delegate
);
148 return generated_delegate
;
152 * Returns the name of this signal as it is used in C code.
154 * @return the name to be used in C code
156 public string get_cname () {
158 cname
= camel_case_to_lower_case (name
);
163 public void set_cname (string cname
) {
168 * Returns the string literal of this signal to be used in C code.
170 * @return string literal to be used in C code
172 public CCodeConstant
get_canonical_cconstant (string? detail
= null) {
173 var str
= new
StringBuilder ("\"");
175 string i
= get_cname ();
177 while (i
.length
> 0) {
178 unichar c
= i
.get_char ();
182 str
.append_unichar (c
);
188 if (detail
!= null) {
195 return new
CCodeConstant (str
.str
);
198 public override void accept (CodeVisitor visitor
) {
199 visitor
.visit_signal (this
);
202 public override void accept_children (CodeVisitor visitor
) {
203 return_type
.accept (visitor
);
205 foreach (Parameter param
in parameters
) {
206 param
.accept (visitor
);
208 if (default_handler
== null && body
!= null) {
209 body
.accept (visitor
);
210 } else if (default_handler
!= null) {
211 default_handler
.accept (visitor
);
215 void process_signal_attribute (Attribute a
) {
216 if (a
.has_argument ("detailed")) {
217 is_detailed
= a
.get_bool ("detailed");
219 if (a
.has_argument ("no_recurse")) {
220 no_recurse
= a
.get_bool ("no_recurse");
222 if (a
.has_argument ("run")) {
223 var arg
= a
.get_string ("run");
224 if (arg
== "first") {
226 } else if (arg
== "last") {
228 } else if (arg
== "cleanup") {
229 run_type
= "cleanup";
233 if (a
.has_argument ("action")) {
234 is_action
= a
.get_bool ("action");
237 if (a
.has_argument ("no_hooks")) {
238 no_hooks
= a
.get_bool ("no_hooks");
243 * Process all associated attributes.
245 public void process_attributes () {
246 foreach (Attribute a
in attributes
) {
247 if (a
.name
== "HasEmitter") {
249 } else if (a
.name
== "Signal") {
250 process_signal_attribute (a
);
251 } else if (a
.name
== "Deprecated") {
252 process_deprecated_attribute (a
);
257 public bool get_lock_used () {
261 public void set_lock_used (bool used
) {
265 public override void replace_type (DataType old_type
, DataType new_type
) {
266 if (return_type
== old_type
) {
267 return_type
= new_type
;
271 public override bool check (CodeContext context
) {
278 process_attributes ();
280 return_type
.check (context
);
282 foreach (Parameter param
in parameters
) {
283 param
.check (context
);
286 if (!is_virtual
&& body
!= null) {
287 Report
.error (source_reference
, "Only virtual signals can have a default signal handler body");
292 default_handler
= new
Method (name
, return_type
, source_reference
);
294 default_handler
.owner
= owner
;
295 default_handler
.access
= access
;
296 default_handler
.external
= external
;
297 default_handler
.is_virtual
= true;
298 default_handler
.vfunc_name
= name
;
299 default_handler
.signal_reference
= this
;
300 default_handler
.body
= body
;
303 foreach (Parameter param
in parameters
) {
304 default_handler
.add_parameter (param
);
307 var cl
= parent_symbol as ObjectTypeSymbol
;
309 cl
.add_hidden_method (default_handler
);
310 default_handler
.check (context
);
314 if (!external_package
&& !hides
&& get_hidden_member () != null) {
315 Report
.warning (source_reference
, "%s hides inherited signal `%s'. Use the `new' keyword if hiding was intentional".printf (get_full_name (), get_hidden_member ().get_full_name ()));