gtk+-4.0: Update to 3.93.0+f4c1a404
[vala-gnome.git] / vala / valasignal.vala
blobd0a6ac0c3897d9a839bef024014fa7adc4249133
1 /* valasignal.vala
3 * Copyright (C) 2006-2012 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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * Represents an object signal. Signals enable objects to provide notifications.
28 public class Vala.Signal : Symbol, Lockable, Callable {
29 /**
30 * The return type of handlers of this signal.
32 public DataType return_type {
33 get { return _return_type; }
34 set {
35 _return_type = value;
36 _return_type.parent_node = this;
40 public Block body {
41 get { return _body; }
42 set {
43 _body = value;
44 if (_body != null) {
45 _body.owner = scope;
50 /**
51 * Specifies whether this signal has virtual method handler.
53 public bool is_virtual { get; set; }
55 private List<Parameter> parameters = new ArrayList<Parameter> ();
56 /**
57 * Refers to the default signal handler, which is an anonymous
58 * function in the scope.
59 * */
60 public Method default_handler { get; private set; }
62 /**
63 * Refers to the public signal emitter method, which is an anonymous
64 * function in the scope.
65 * */
66 public Method emitter { get; private set; }
68 private bool lock_used = false;
70 private DataType _return_type;
72 private Block _body;
74 /**
75 * Creates a new signal.
77 * @param name signal name
78 * @param return_type signal return type
79 * @param source_reference reference to source code
80 * @return newly created signal
82 public Signal (string name, DataType return_type, SourceReference? source_reference = null, Comment? comment = null) {
83 base (name, source_reference, comment);
84 this.return_type = return_type;
87 /**
88 * Appends parameter to signal handler.
90 * @param param a formal parameter
92 public void add_parameter (Parameter param) {
93 parameters.add (param);
94 scope.add (param.name, param);
97 public List<Parameter> get_parameters () {
98 return parameters;
102 * Returns generated delegate to be used for signal handlers.
104 * @return delegate
106 public Delegate get_delegate (DataType sender_type, CodeNode node_reference) {
107 var actual_return_type = return_type.get_actual_type (sender_type, null, node_reference);
109 var generated_delegate = new Delegate (null, actual_return_type);
110 generated_delegate.access = SymbolAccessibility.PUBLIC;
111 generated_delegate.owner = scope;
113 // sender parameter is never null and doesn't own its value
114 var sender_param_type = sender_type.copy ();
115 sender_param_type.value_owned = false;
116 sender_param_type.nullable = false;
118 generated_delegate.sender_type = sender_param_type;
120 bool is_generic = false;
122 foreach (Parameter param in parameters) {
123 var actual_param = param.copy ();
124 actual_param.variable_type = actual_param.variable_type.get_actual_type (sender_type, null, node_reference);
125 generated_delegate.add_parameter (actual_param);
127 if (actual_param.variable_type is GenericType) {
128 is_generic = true;
132 if (is_generic) {
133 var cl = (ObjectTypeSymbol) parent_symbol;
134 foreach (var type_param in cl.get_type_parameters ()) {
135 generated_delegate.add_type_parameter (new TypeParameter (type_param.name, type_param.source_reference));
138 // parameter types must refer to the delegate type parameters
139 // instead of to the class type parameters
140 foreach (var param in generated_delegate.get_parameters ()) {
141 var generic_type = param.variable_type as GenericType;
142 if (generic_type != null) {
143 generic_type.type_parameter = generated_delegate.get_type_parameters ().get (generated_delegate.get_type_parameter_index (generic_type.type_parameter.name));
148 scope.add (null, generated_delegate);
150 return generated_delegate;
153 public override void accept (CodeVisitor visitor) {
154 visitor.visit_signal (this);
157 public override void accept_children (CodeVisitor visitor) {
158 return_type.accept (visitor);
160 foreach (Parameter param in parameters) {
161 param.accept (visitor);
163 if (default_handler == null && body != null) {
164 body.accept (visitor);
165 } else if (default_handler != null) {
166 default_handler.accept (visitor);
168 if (emitter != null) {
169 emitter.accept (visitor);
173 public bool get_lock_used () {
174 return lock_used;
177 public void set_lock_used (bool used) {
178 lock_used = used;
181 public override void replace_type (DataType old_type, DataType new_type) {
182 if (return_type == old_type) {
183 return_type = new_type;
187 public override bool check (CodeContext context) {
188 if (checked) {
189 return !error;
192 checked = true;
194 return_type.check (context);
196 foreach (Parameter param in parameters) {
197 if (param.ellipsis) {
198 Report.error (param.source_reference, "Signals with variable argument lists are not supported");
199 return false;
202 param.check (context);
205 if (!is_virtual && body != null) {
206 Report.error (source_reference, "Only virtual signals can have a default signal handler body");
210 if (is_virtual) {
211 default_handler = new Method (name, return_type, source_reference);
213 default_handler.owner = owner;
214 default_handler.access = access;
215 default_handler.external = external;
216 default_handler.hides = hides;
217 default_handler.is_virtual = true;
218 default_handler.signal_reference = this;
219 default_handler.body = body;
222 foreach (Parameter param in parameters) {
223 default_handler.add_parameter (param);
226 var cl = parent_symbol as ObjectTypeSymbol;
228 cl.add_hidden_method (default_handler);
229 default_handler.check (context);
232 if (!external_package && get_attribute ("HasEmitter") != null) {
233 emitter = new Method (name, return_type, source_reference);
235 emitter.owner = owner;
236 emitter.access = access;
238 var body = new Block (source_reference);
239 var call = new MethodCall (new MemberAccess.simple (name, source_reference), source_reference);
241 foreach (Parameter param in parameters) {
242 emitter.add_parameter (param);
243 call.add_argument (new MemberAccess.simple (param.name, source_reference));
246 if (return_type is VoidType) {
247 body.add_statement (new ExpressionStatement (call, source_reference));
248 } else {
249 body.add_statement (new ReturnStatement (call, source_reference));
251 emitter.body = body;
253 var cl = parent_symbol as ObjectTypeSymbol;
255 cl.add_hidden_method (emitter);
256 emitter.check (context);
260 if (!external_package && !hides && get_hidden_member () != null) {
261 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 ()));
264 return !error;