girparser: Provide default constructor for classes.
[vala-lang.git] / vala / valapropertyaccessor.vala
blobfbec601cc41349b05e02b68aa3005465d2d1fd04
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 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; set; }
54 /**
55 * Specifies whether this accessor may be used to set the property.
57 public bool writable { get; set; }
59 /**
60 * Specifies whether this accessor may be used to construct the
61 * property.
63 public bool construction { get; set; }
65 /**
66 * True if the body was automatically generated
68 public bool automatic_body { get; 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; set; }
79 public virtual string get_default_cname () {
80 var t = (TypeSymbol) prop.parent_symbol;
82 if (readable) {
83 return "%sget_%s".printf (t.get_lower_case_cprefix (), prop.name);
84 } else {
85 return "%sset_%s".printf (t.get_lower_case_cprefix (), prop.name);
89 /**
90 * The publicly accessible name of the function that performs the
91 * access in C code.
93 public string get_cname () {
94 if (_cname != null) {
95 return _cname;
97 return get_default_cname ();
100 private DataType _value_type;
101 private string? _cname;
104 * Creates a new property accessor.
106 * @param readable true if get accessor, false otherwise
107 * @param writable true if set accessor, false otherwise
108 * @param construction true if construct accessor, false otherwise
109 * @param body accessor body
110 * @param source reference to source code
111 * @return newly created property accessor
113 public PropertyAccessor (bool readable, bool writable, bool construction, DataType? value_type, Block? body, SourceReference? source_reference, Comment? comment = null) {
114 base (null, source_reference, comment);
115 this.readable = readable;
116 this.writable = writable;
117 this.construction = construction;
118 this.value_type = value_type;
119 this.body = body;
120 this.access = SymbolAccessibility.PUBLIC;
123 public override void accept (CodeVisitor visitor) {
124 visitor.visit_property_accessor (this);
127 public override void accept_children (CodeVisitor visitor) {
128 value_type.accept (visitor);
130 if (result_var != null) {
131 result_var.accept (visitor);
134 if (body != null) {
135 body.accept (visitor);
140 * Process all associated attributes.
142 public void process_attributes () {
143 foreach (Attribute a in attributes) {
144 if (a.name == "CCode") {
145 if (a.has_argument ("cname")) {
146 _cname = a.get_string ("cname");
152 public override bool check (CodeContext context) {
153 if (checked) {
154 return !error;
157 checked = true;
159 process_attributes ();
161 if (!value_type.check (context)) {
162 error = true;
163 return false;
166 var old_symbol = context.analyzer.current_symbol;
168 context.analyzer.current_symbol = this;
170 if (prop.source_type == SourceFileType.SOURCE) {
171 if (body == null && !prop.interface_only && !prop.is_abstract) {
172 /* no accessor body specified, insert default body */
174 if (prop.parent_symbol is Interface) {
175 error = true;
176 Report.error (source_reference, "Automatic properties can't be used in interfaces");
177 return false;
179 automatic_body = true;
180 body = new Block (source_reference);
181 var ma = new MemberAccess.simple ("_%s".printf (prop.name), source_reference);
182 if (readable) {
183 if (context.profile == Profile.DOVA) {
184 body.add_statement (new ExpressionStatement (new Assignment (new MemberAccess.simple ("result", source_reference), ma, AssignmentOperator.SIMPLE, source_reference), source_reference));
185 body.add_statement (new ReturnStatement (null, source_reference));
186 } else {
187 body.add_statement (new ReturnStatement (ma, source_reference));
189 } else {
190 var assignment = new Assignment (ma, new MemberAccess.simple ("value", source_reference), AssignmentOperator.SIMPLE, source_reference);
191 body.add_statement (new ExpressionStatement (assignment));
196 if (body != null) {
197 if (readable && context.profile == Profile.DOVA) {
198 result_var = new LocalVariable (value_type.copy (), "result", null, source_reference);
199 result_var.is_result = true;
201 result_var.check (context);
202 } else if (writable || construction) {
203 value_parameter = new Parameter ("value", value_type, source_reference);
204 body.scope.add (value_parameter.name, value_parameter);
207 body.check (context);
209 if (context.profile != Profile.DOVA) {
210 foreach (DataType body_error_type in body.get_error_types ()) {
211 if (!((ErrorType) body_error_type).dynamic_error) {
212 Report.warning (body_error_type.source_reference, "unhandled error `%s'".printf (body_error_type.to_string()));
218 context.analyzer.current_symbol = old_symbol;
220 return !error;
223 public override void replace_type (DataType old_type, DataType new_type) {
224 if (value_type == old_type) {
225 value_type = new_type;
229 public override List<string> get_cheader_filenames () {
230 return parent_symbol.get_cheader_filenames ();