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
20 * Jürg Billeter <j@bitron.ch>
26 * Represents a get or set accessor of a property in the source code.
28 public class Vala
.PropertyAccessor
: Subroutine
{
30 * The corresponding property.
32 public Property prop
{
33 get { return parent_symbol as Property
; }
39 public DataType? value_type
{
40 get { return _value_type
; }
44 _value_type
.parent_node
= this
;
50 * Specifies whether this accessor may be used to get the property.
52 public bool readable
{ get; set; }
55 * Specifies whether this accessor may be used to set the property.
57 public bool writable
{ get; set; }
60 * Specifies whether this accessor may be used to construct the
63 public bool construction
{ get; set; }
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
; }
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
;
83 return "%sget_%s".printf (t
.get_lower_case_cprefix (), prop
.name
);
85 return "%sset_%s".printf (t
.get_lower_case_cprefix (), prop
.name
);
90 * The publicly accessible name of the function that performs the
93 public string get_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
;
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
);
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
) {
159 process_attributes ();
161 if (!value_type
.check (context
)) {
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
) {
176 Report
.error (source_reference
, "Automatic properties can't be used in interfaces");
179 automatic_body
= true;
180 body
= new
Block (source_reference
);
181 var ma
= new MemberAccess
.simple ("_%s".printf (prop
.name
), source_reference
);
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
));
187 body
.add_statement (new
ReturnStatement (ma
, source_reference
));
190 var assignment
= new
Assignment (ma
, new MemberAccess
.simple ("value", source_reference
), AssignmentOperator
.SIMPLE
, source_reference
);
191 body
.add_statement (new
ExpressionStatement (assignment
));
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
;
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 ();