Commit 652e0134 authored by Rico Tzschichholz's avatar Rico Tzschichholz

Improve error while method is incompatible with delegate

Add virtual DataType.to_prototype_string() and use a common implementation
in CallableType for its descendents.
parent 95a4c556
......@@ -360,7 +360,7 @@ public class Vala.GtkModule : GSignalModule {
var signal_type = new SignalType (sig);
var delegate_type = signal_type.get_handler_type ();
if (!method_type.compatible (delegate_type)) {
Report.error (m.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (method_type.to_string (), delegate_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
Report.error (m.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (method_type.to_string (), delegate_type.to_string (), delegate_type.to_prototype_string (m.name)));
} else {
var wrapper = generate_delegate_wrapper (m, signal_type.get_handler_type (), m);
......
......@@ -298,7 +298,7 @@ public class Vala.Assignment : Expression {
var delegate_type = (DelegateType) right.target_type;
error = true;
Report.error (right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (right.value_type.to_string (), right.target_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
Report.error (right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (right.value_type.to_string (), right.target_type.to_string (), delegate_type.to_prototype_string (m.name)));
return false;
} else if (right_ma != null && right_ma.prototype_access) {
error = true;
......
......@@ -26,4 +26,77 @@ using GLib;
* A callable type, i.e. a delegate, method, or signal type.
*/
public abstract class Vala.CallableType : DataType {
public override string to_prototype_string (string? override_name = null) {
StringBuilder builder = new StringBuilder ();
// Append return-type
var return_type = get_return_type ();
if (return_type.is_weak ()) {
builder.append ("unowned ");
}
builder.append (return_type.to_qualified_string ());
// Append name
builder.append_c (' ');
builder.append (override_name ?? this.to_string ());
builder.append_c (' ');
// Append parameter-list
builder.append_c ('(');
int i = 1;
foreach (Parameter param in get_parameters ()) {
if (i > 1) {
builder.append (", ");
}
if (param.ellipsis) {
builder.append ("...");
continue;
}
if (param.direction == ParameterDirection.IN) {
if (param.variable_type.value_owned) {
builder.append ("owned ");
}
} else {
if (param.direction == ParameterDirection.REF) {
builder.append ("ref ");
} else if (param.direction == ParameterDirection.OUT) {
builder.append ("out ");
}
if (!param.variable_type.value_owned && param.variable_type is ReferenceType) {
builder.append ("weak ");
}
}
builder.append (param.variable_type.to_qualified_string ());
if (param.initializer != null) {
builder.append (" = ");
builder.append (param.initializer.to_string ());
}
i++;
}
builder.append_c (')');
// Append error-types
var error_types = get_error_types ();
if (error_types.size > 0) {
builder.append (" throws ");
bool first = true;
foreach (DataType type in error_types) {
if (!first) {
builder.append (", ");
} else {
first = false;
}
builder.append (type.to_string ());
}
}
return builder.str;
}
}
......@@ -486,6 +486,16 @@ public abstract class Vala.DataType : CodeNode {
return null;
}
/**
* Returns a stringified representation used for detailed error output
*
* @param override_name used as name if given
* @return stringified representation
*/
public virtual string to_prototype_string (string? override_name = null) {
return "%s%s".printf (is_weak () ? "unowned " : "", to_qualified_string ());
}
public bool is_weak () {
if (this.value_owned) {
return false;
......
......@@ -241,54 +241,6 @@ public class Vala.Delegate : TypeSymbol, Callable {
}
}
public string get_prototype_string (string name) {
return "%s %s %s".printf (get_return_type_string (), name, get_parameters_string ());
}
string get_return_type_string () {
string str = "";
if (!return_type.value_owned && return_type is ReferenceType) {
str = "weak ";
}
str += return_type.to_string ();
return str;
}
string get_parameters_string () {
string str = "(";
int i = 1;
foreach (Parameter param in parameters) {
if (i > 1) {
str += ", ";
}
if (param.direction == ParameterDirection.IN) {
if (param.variable_type.value_owned) {
str += "owned ";
}
} else {
if (param.direction == ParameterDirection.REF) {
str += "ref ";
} else if (param.direction == ParameterDirection.OUT) {
str += "out ";
}
if (!param.variable_type.value_owned && param.variable_type is ReferenceType) {
str += "weak ";
}
}
str += param.variable_type.to_string ();
i++;
}
str += ")";
return str;
}
public override bool check (CodeContext context) {
if (checked) {
return !error;
......
......@@ -72,45 +72,4 @@ public class Vala.MethodType : CallableType {
}
return null;
}
public string to_prototype_string (bool with_type_parameters = false) {
var proto = "%s %s (".printf (get_return_type ().to_string (), this.to_string ());
int i = 1;
foreach (Parameter param in get_parameters ()) {
if (i > 1) {
proto += ", ";
}
if (param.ellipsis) {
proto += "...";
continue;
}
if (param.direction == ParameterDirection.IN) {
if (param.variable_type.value_owned) {
proto += "owned ";
}
} else {
if (param.direction == ParameterDirection.REF) {
proto += "ref ";
} else if (param.direction == ParameterDirection.OUT) {
proto += "out ";
}
if (param.variable_type.is_weak ()) {
proto += "unowned ";
}
}
proto = "%s%s %s".printf (proto, param.variable_type.to_qualified_string (), param.name);
if (param.initializer != null) {
proto = "%s = %s".printf (proto, param.initializer.to_string ());
}
i++;
}
return proto + ")";
}
}
......@@ -552,12 +552,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
if (arg.target_type != null) {
if ((direction == ParameterDirection.IN || direction == ParameterDirection.REF)
&& !arg.value_type.compatible (arg.target_type)) {
Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.value_type.to_string (), arg.target_type.to_string ()));
Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.value_type.to_prototype_string (), arg.target_type.to_prototype_string ()));
return false;
} else if ((direction == ParameterDirection.REF || direction == ParameterDirection.OUT)
&& !arg.target_type.compatible (arg.value_type)
&& !(arg is NullLiteral)) {
Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.target_type.to_string (), arg.value_type.to_string ()));
Report.error (arg.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.target_type.to_prototype_string (), arg.value_type.to_prototype_string ()));
return false;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment