Do not free values returned via g_object_get prematurely, require
[vala-lang.git] / vala / valasignal.vala
blobb4dcc7d2db49940947d62f0e52755d11ff3fcaea
1 /* valasignal.vala
3 * Copyright (C) 2006-2008 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;
24 using Gee;
26 /**
27 * Represents an object signal. Signals enable objects to provide notifications.
29 public class Vala.Signal : Member, Lockable {
30 /**
31 * The return type of handlers of this signal.
33 public DataType return_type {
34 get { return _return_type; }
35 set {
36 _return_type = value;
37 _return_type.parent_node = this;
41 /**
42 * Specifies whether this signal has an emitter wrapper function.
44 public bool has_emitter { get; set; }
46 /**
47 * Specifies whether this signal has virtual method handler.
49 public bool is_virtual { get; set; }
51 private Gee.List<FormalParameter> parameters = new ArrayList<FormalParameter> ();
52 private Method generated_method;
54 private string cname;
56 private bool lock_used = false;
58 private DataType _return_type;
60 /**
61 * Creates a new signal.
63 * @param name signal name
64 * @param return_type signal return type
65 * @param source reference to source code
66 * @return newly created signal
68 public Signal (string name, DataType return_type, SourceReference? source_reference = null) {
69 base (name, source_reference);
70 this.return_type = return_type;
73 /**
74 * Appends parameter to signal handler.
76 * @param param a formal parameter
78 public void add_parameter (FormalParameter param) {
79 // default C parameter position
80 param.cparameter_position = parameters.size + 1;
81 param.carray_length_parameter_position = param.cparameter_position + 0.1;
82 param.cdelegate_target_parameter_position = param.cparameter_position + 0.1;
84 parameters.add (param);
85 scope.add (param.name, param);
88 public Gee.List<FormalParameter> get_parameters () {
89 return new ReadOnlyList<FormalParameter> (parameters);
92 /**
93 * Returns generated delegate to be used for signal handlers.
95 * @return delegate
97 public Delegate get_delegate (DataType sender_type, CodeNode node_reference) {
98 var actual_return_type = return_type.get_actual_type (sender_type, node_reference);
100 var generated_delegate = new Delegate (null, actual_return_type);
101 generated_delegate.has_target = true;
103 // sender parameter is never null and doesn't own its value
104 var sender_param_type = sender_type.copy ();
105 sender_param_type.value_owned = false;
106 sender_param_type.nullable = false;
108 var sender_param = new FormalParameter ("_sender", sender_param_type);
109 generated_delegate.add_parameter (sender_param);
111 foreach (FormalParameter param in parameters) {
112 var actual_param = param.copy ();
113 actual_param.parameter_type = actual_param.parameter_type.get_actual_type (sender_type, node_reference);
114 generated_delegate.add_parameter (actual_param);
117 scope.add (null, generated_delegate);
119 return generated_delegate;
123 * Returns the name of this signal as it is used in C code.
125 * @return the name to be used in C code
127 public string get_cname () {
128 if (cname == null) {
129 cname = camel_case_to_lower_case (name);
131 return cname;
134 public void set_cname (string cname) {
135 this.cname = cname;
139 * Returns the string literal of this signal to be used in C code.
141 * @return string literal to be used in C code
143 public CCodeConstant get_canonical_cconstant (string? detail = null) {
144 var str = new StringBuilder ("\"");
146 string i = get_cname ();
148 while (i.len () > 0) {
149 unichar c = i.get_char ();
150 if (c == '_') {
151 str.append_c ('-');
152 } else {
153 str.append_unichar (c);
156 i = i.next_char ();
159 if (detail != null) {
160 str.append ("::");
161 str.append (detail);
164 str.append_c ('"');
166 return new CCodeConstant (str.str);
169 public override void accept (CodeVisitor visitor) {
170 visitor.visit_member (this);
172 visitor.visit_signal (this);
175 public override void accept_children (CodeVisitor visitor) {
176 return_type.accept (visitor);
178 foreach (FormalParameter param in parameters) {
179 param.accept (visitor);
184 * Process all associated attributes.
186 public void process_attributes () {
187 foreach (Attribute a in attributes) {
188 if (a.name == "HasEmitter") {
189 has_emitter = true;
194 public bool get_lock_used () {
195 return lock_used;
198 public void set_lock_used (bool used) {
199 lock_used = used;
202 public override void replace_type (DataType old_type, DataType new_type) {
203 if (return_type == old_type) {
204 return_type = new_type;
208 public Method get_method_handler () {
209 assert (is_virtual);
211 if (generated_method == null) {
212 generated_method = new Method (name, return_type, source_reference);
213 generated_method.is_virtual = true;
214 generated_method.vfunc_name = name;
216 foreach (FormalParameter param in parameters) {
217 generated_method.add_parameter (param);
220 parent_symbol.scope.add (null, generated_method);
223 return generated_method;
226 public override bool check (SemanticAnalyzer analyzer) {
227 if (checked) {
228 return !error;
231 checked = true;
233 process_attributes ();
235 return_type.check (analyzer);
237 foreach (FormalParameter param in parameters) {
238 param.check (analyzer);
241 return !error;