girparser: Fix parameter index calculation
[vala-lang.git] / vala / valaformalparameter.vala
blobe01ad49faf7798165e6c498cb856d49a866f5d95
1 /* valaformalparameter.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * Author:
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
25 using GLib;
27 /**
28 * Represents a formal parameter in method and callback signatures.
30 public class Vala.FormalParameter : Symbol {
31 /**
32 * The parameter type.
34 public DataType parameter_type {
35 get { return _data_type; }
36 set {
37 _data_type = value;
38 _data_type.parent_node = this;
42 public ParameterDirection direction { get; set; default = ParameterDirection.IN; }
44 /**
45 * Specifies whether the methods accepts an indefinite number of
46 * parameters.
48 public bool ellipsis { get; set; }
50 /**
51 * Specifies whether the methods accepts an indefinite number of
52 * parameters.
54 public bool params_array { get; set; }
56 /**
57 * Specifies the expression used when the caller doesn't supply an
58 * argument for this parameter.
60 public Expression? default_expression {
61 get { return _default_expression; }
62 set {
63 _default_expression = value;
64 if (_default_expression != null) {
65 _default_expression.parent_node = this;
70 /**
71 * Specifies whether the array length should be passed implicitly
72 * if the parameter type is an array.
74 public bool no_array_length { get; set; }
76 /**
77 * Specifies whether the array is null terminated.
79 public bool array_null_terminated { get; set; }
81 /**
82 * Specifies a custom type for the array length.
84 public string? array_length_type { get; set; default = null; }
86 /**
87 * Specifies the position of the parameter in the C function.
89 public double cparameter_position { get; set; }
91 /**
92 * Specifies the position of the array length parameter in the C
93 * function.
95 public double carray_length_parameter_position { get; set; }
97 /**
98 * Specifies the position of the delegate target parameter in the C
99 * function.
101 public double cdelegate_target_parameter_position { get; set; }
103 public double cdestroy_notify_parameter_position { get; set; }
106 * Specifies the type of the parameter in the C function.
108 public string? ctype { get; set; }
110 public bool captured { get; set; }
112 private DataType _data_type;
113 private Expression? _default_expression;
116 * Creates a new formal parameter.
118 * @param name parameter name
119 * @param type parameter type
120 * @param source reference to source code
121 * @return newly created formal parameter
123 public FormalParameter (string name, DataType parameter_type, SourceReference? source_reference = null) {
124 base (name, source_reference);
125 this.parameter_type = parameter_type;
127 access = SymbolAccessibility.PUBLIC;
131 * Creates a new ellipsis parameter representing an indefinite number of
132 * parameters.
134 public FormalParameter.with_ellipsis (SourceReference? source_reference = null) {
135 base (null, source_reference);
136 ellipsis = true;
138 access = SymbolAccessibility.PUBLIC;
141 public override void accept (CodeVisitor visitor) {
142 visitor.visit_formal_parameter (this);
145 public override void accept_children (CodeVisitor visitor) {
146 if (!ellipsis) {
147 parameter_type.accept (visitor);
149 if (default_expression != null) {
150 default_expression.accept (visitor);
155 public override void replace_type (DataType old_type, DataType new_type) {
156 if (parameter_type == old_type) {
157 parameter_type = new_type;
161 public override void replace_expression (Expression old_node, Expression new_node) {
162 if (default_expression == old_node) {
163 default_expression = new_node;
167 private void process_ccode_attribute (Attribute a) {
168 if (a.has_argument ("type")) {
169 ctype = a.get_string ("type");
171 if (a.has_argument ("pos")) {
172 cparameter_position = a.get_double ("pos");
174 if (a.has_argument ("array_length")) {
175 no_array_length = !a.get_bool ("array_length");
177 if (a.has_argument ("array_length_type")) {
178 array_length_type = a.get_string ("array_length_type");
180 if (a.has_argument ("array_null_terminated")) {
181 array_null_terminated = a.get_bool ("array_null_terminated");
183 if (a.has_argument ("array_length_pos")) {
184 carray_length_parameter_position = a.get_double ("array_length_pos");
186 if (a.has_argument ("delegate_target_pos")) {
187 cdelegate_target_parameter_position = a.get_double ("delegate_target_pos");
189 if (a.has_argument ("destroy_notify_pos")) {
190 cdestroy_notify_parameter_position = a.get_double ("destroy_notify_pos");
195 * Process all associated attributes.
197 public void process_attributes () {
198 foreach (Attribute a in attributes) {
199 if (a.name == "CCode") {
200 process_ccode_attribute (a);
205 public FormalParameter copy () {
206 if (!ellipsis) {
207 var result = new FormalParameter (name, parameter_type, source_reference);
208 result.params_array = params_array;
209 result.direction = this.direction;
210 result.default_expression = this.default_expression;
211 return result;
212 } else {
213 return new FormalParameter.with_ellipsis ();
217 public override bool check (SemanticAnalyzer analyzer) {
218 if (checked) {
219 return !error;
222 checked = true;
224 process_attributes ();
226 var old_source_file = analyzer.current_source_file;
227 var old_symbol = analyzer.current_symbol;
229 if (source_reference != null) {
230 analyzer.current_source_file = source_reference.file;
232 analyzer.current_symbol = parent_symbol;
234 if (parameter_type != null) {
235 parameter_type.check (analyzer);
238 if (!ellipsis) {
239 parameter_type.check (analyzer);
241 if (params_array && !(parameter_type is ArrayType)) {
242 error = true;
243 Report.error (source_reference, "parameter array expected");
244 return false;
247 if (default_expression != null) {
248 default_expression.check (analyzer);
252 if (default_expression != null) {
253 if (default_expression is NullLiteral
254 && !parameter_type.nullable
255 && direction != ParameterDirection.OUT) {
256 Report.warning (source_reference, "`null' incompatible with parameter type `%s`".printf (parameter_type.to_string ()));
260 if (!ellipsis) {
261 // check whether parameter type is at least as accessible as the method
262 if (!analyzer.is_type_accessible (this, parameter_type)) {
263 error = true;
264 Report.error (source_reference, "parameter type `%s` is less accessible than method `%s`".printf (parameter_type.to_string (), parent_symbol.get_full_name ()));
268 analyzer.current_source_file = old_source_file;
269 analyzer.current_symbol = old_symbol;
271 return !error;
275 public enum Vala.ParameterDirection {
277 OUT,