Release 0.41.92
[vala-gnome.git] / vala / valapropertyaccessor.vala
blob46952bb197743ff541b89f762c6c3853eff0487e
1 /* valapropertyaccessor.vala
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
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * Represents a get or set accessor of a property in the source code.
28 public class Vala.PropertyAccessor : Subroutine {
29 /**
30 * The corresponding property.
32 public Property prop {
33 get { return parent_symbol as Property; }
36 /**
37 * The property type.
39 public DataType? value_type {
40 get { return _value_type; }
41 private set {
42 _value_type = value;
43 if (value != null) {
44 _value_type.parent_node = this;
49 /**
50 * Specifies whether this accessor may be used to get the property.
52 public bool readable { get; private set; }
54 /**
55 * Specifies whether this accessor may be used to set the property.
57 public bool writable { get; private set; }
59 /**
60 * Specifies whether this accessor may be used to construct the
61 * property.
63 public bool construction { get; private set; }
65 /**
66 * True if the body was automatically generated
68 public bool automatic_body { get; private set; }
70 public override bool has_result {
71 get { return readable; }
74 /**
75 * Represents the generated value parameter in a set accessor.
77 public Parameter value_parameter { get; private set; }
79 private DataType _value_type;
81 /**
82 * Creates a new property accessor.
84 * @param readable true if get accessor, false otherwise
85 * @param writable true if set accessor, false otherwise
86 * @param construction true if construct accessor, false otherwise
87 * @param body accessor body
88 * @param source_reference reference to source code
89 * @return newly created property accessor
91 public PropertyAccessor (bool readable, bool writable, bool construction, DataType? value_type, Block? body, SourceReference? source_reference, Comment? comment = null) {
92 base (null, source_reference, comment);
93 this.readable = readable;
94 this.writable = writable;
95 this.construction = construction;
96 this.value_type = value_type;
97 this.body = body;
98 this.access = SymbolAccessibility.PUBLIC;
101 public override void accept (CodeVisitor visitor) {
102 visitor.visit_property_accessor (this);
105 public override void accept_children (CodeVisitor visitor) {
106 value_type.accept (visitor);
108 if (result_var != null) {
109 result_var.accept (visitor);
112 if (body != null) {
113 body.accept (visitor);
118 * Get the method representing this property accessor
119 * @return null if the accessor is neither readable nor writable
121 public Method? get_method () {
122 Method? m = null;
123 if (readable) {
124 m = new Method ("get_%s".printf (prop.name), value_type, source_reference, comment);
125 } else if (writable) {
126 m = new Method ("set_%s".printf (prop.name), new VoidType(), source_reference, comment);
127 m.add_parameter (value_parameter.copy ());
130 if (m != null) {
131 m.owner = prop.owner;
132 m.access = access;
133 m.binding = prop.binding;
134 m.is_abstract = prop.is_abstract;
135 m.is_virtual = prop.is_virtual;
138 return m;
141 public override bool check (CodeContext context) {
142 if (checked) {
143 return !error;
146 checked = true;
148 if (!value_type.check (context)) {
149 error = true;
150 return false;
153 var old_symbol = context.analyzer.current_symbol;
155 context.analyzer.current_symbol = this;
157 if (writable || construction) {
158 value_parameter = new Parameter ("value", value_type, source_reference);
161 if (prop.source_type == SourceFileType.SOURCE) {
162 if (body == null && !prop.interface_only && !prop.is_abstract) {
163 /* no accessor body specified, insert default body */
165 automatic_body = true;
166 body = new Block (source_reference);
167 var ma = new MemberAccess.simple ("_%s".printf (prop.name), source_reference);
168 if (readable) {
169 body.add_statement (new ReturnStatement (ma, source_reference));
170 } else {
171 Expression value = new MemberAccess.simple ("value", source_reference);
172 if (value_type.value_owned) {
173 value = new ReferenceTransferExpression (value, source_reference);
175 var assignment = new Assignment (ma, value, AssignmentOperator.SIMPLE, source_reference);
176 body.add_statement (new ExpressionStatement (assignment));
181 if ((prop.is_abstract || prop.is_virtual || prop.overrides) && access == SymbolAccessibility.PRIVATE) {
182 error = true;
183 Report.error (source_reference, "Property `%s' with private accessor cannot be marked as abstract, virtual or override".printf (prop.get_full_name ()));
184 return false;
187 if (body != null && prop.is_abstract) {
188 error = true;
189 Report.error (source_reference, "Accessor of abstract property `%s' cannot have body".printf (prop.get_full_name ()));
190 return false;
193 if (body != null) {
194 if (writable || construction) {
195 body.scope.add (value_parameter.name, value_parameter);
198 body.check (context);
200 foreach (DataType body_error_type in body.get_error_types ()) {
201 if (!((ErrorType) body_error_type).dynamic_error) {
202 Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
207 context.analyzer.current_symbol = old_symbol;
209 return !error;
212 public override void replace_type (DataType old_type, DataType new_type) {
213 if (value_type == old_type) {
214 value_type = new_type;