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>
26 * Represents an object signal. Signals enable objects to provide notifications.
28 public class Vala
.Signal
: Member
, 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
<FormalParameter
> parameters
= new ArrayList
<FormalParameter
> ();
62 * Refers to the default signal handler, which is an anonymous
63 * function in the scope.
65 public Method default_handler
{ get; private set; }
69 private bool lock_used
= false;
71 private DataType _return_type
;
76 * Creates a new signal.
78 * @param name signal name
79 * @param return_type signal return type
80 * @param source reference to source code
81 * @return newly created signal
83 public Signal (string name
, DataType return_type
, SourceReference? source_reference
= null, Comment? comment
= null) {
84 base (name
, source_reference
, comment
);
85 this
.return_type
= return_type
;
89 * Appends parameter to signal handler.
91 * @param param a formal parameter
93 public void add_parameter (FormalParameter param
) {
94 // default C parameter position
95 param
.cparameter_position
= parameters
.size
+ 1;
96 param
.carray_length_parameter_position
= param
.cparameter_position
+ 0.1;
97 param
.cdelegate_target_parameter_position
= param
.cparameter_position
+ 0.1;
99 parameters
.add (param
);
100 scope
.add (param
.name
, param
);
103 public List
<FormalParameter
> get_parameters () {
104 return new ReadOnlyList
<FormalParameter
> (parameters
);
108 * Returns generated delegate to be used for signal handlers.
112 public Delegate
get_delegate (DataType sender_type
, CodeNode node_reference
) {
113 var actual_return_type
= return_type
.get_actual_type (sender_type
, null, node_reference
);
115 var generated_delegate
= new
Delegate (null, actual_return_type
);
116 generated_delegate
.has_target
= true;
117 generated_delegate
.access
= SymbolAccessibility
.PUBLIC
;
118 generated_delegate
.owner
= scope
;
120 // sender parameter is never null and doesn't own its value
121 var sender_param_type
= sender_type
.copy ();
122 sender_param_type
.value_owned
= false;
123 sender_param_type
.nullable
= false;
125 generated_delegate
.sender_type
= sender_param_type
;
127 foreach (FormalParameter param
in parameters
) {
128 var actual_param
= param
.copy ();
129 actual_param
.parameter_type
= actual_param
.parameter_type
.get_actual_type (sender_type
, null, node_reference
);
130 generated_delegate
.add_parameter (actual_param
);
133 scope
.add (null, generated_delegate
);
135 return generated_delegate
;
139 * Returns the name of this signal as it is used in C code.
141 * @return the name to be used in C code
143 public string get_cname () {
145 cname
= camel_case_to_lower_case (name
);
150 public void set_cname (string cname
) {
155 * Returns the string literal of this signal to be used in C code.
157 * @return string literal to be used in C code
159 public CCodeConstant
get_canonical_cconstant (string? detail
= null) {
160 var str
= new
StringBuilder ("\"");
162 string i
= get_cname ();
164 while (i
.len () > 0) {
165 unichar c
= i
.get_char ();
169 str
.append_unichar (c
);
175 if (detail
!= null) {
182 return new
CCodeConstant (str
.str
);
185 public override void accept (CodeVisitor visitor
) {
186 visitor
.visit_member (this
);
188 visitor
.visit_signal (this
);
191 public override void accept_children (CodeVisitor visitor
) {
192 return_type
.accept (visitor
);
194 foreach (FormalParameter param
in parameters
) {
195 param
.accept (visitor
);
197 if (default_handler
!= null) {
198 default_handler
.accept (visitor
);
203 * Process all associated attributes.
205 public void process_attributes () {
206 foreach (Attribute a
in attributes
) {
207 if (a
.name
== "HasEmitter") {
213 public bool get_lock_used () {
217 public void set_lock_used (bool used
) {
221 public override void replace_type (DataType old_type
, DataType new_type
) {
222 if (return_type
== old_type
) {
223 return_type
= new_type
;
227 public override bool check (SemanticAnalyzer analyzer
) {
234 process_attributes ();
236 return_type
.check (analyzer
);
238 foreach (FormalParameter param
in parameters
) {
239 param
.check (analyzer
);
242 if (!is_virtual
&& body
!= null) {
243 Report
.error (source_reference
, "Only virtual signals can have a default signal handler body");
248 default_handler
= new
Method (name
, return_type
, source_reference
);
250 default_handler
.owner
= owner
;
251 default_handler
.access
= access
;
252 default_handler
.external
= external
;
253 default_handler
.is_virtual
= true;
254 default_handler
.vfunc_name
= name
;
255 default_handler
.signal_reference
= this
;
256 default_handler
.body
= body
;
259 foreach (FormalParameter param
in parameters
) {
260 default_handler
.add_parameter (param
);
263 var cl
= parent_symbol as Class
;
265 cl
.add_hidden_method (default_handler
);
266 default_handler
.check (analyzer
);
270 if (!external_package
&& !hides
&& get_hidden_member () != null) {
271 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 ()));