mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 10:48:25 +00:00
Allow NoSuchMethodError.withInvocation
to accept any Invocation
.
Currently the VM only accepts an `_InvocationMirror` instance, not a user created `Invocation`. Fixes #33124 Bug: http://dartbug.com/33124 Change-Id: Ifdc95861cbe632bc317ca8d9fb92cf0d3ae600f0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/140100 Reviewed-by: Siva Annamalai <asiva@google.com> Commit-Queue: Lasse R.H. Nielsen <lrn@google.com>
This commit is contained in:
parent
497bdc5226
commit
2ca3555c44
|
@ -187,12 +187,12 @@ class NoSuchMethodError {
|
|||
List _existingArgumentNames;
|
||||
|
||||
final Object _receiver;
|
||||
final _InvocationMirror _invocation;
|
||||
final Invocation _invocation;
|
||||
|
||||
@patch
|
||||
NoSuchMethodError.withInvocation(Object receiver, Invocation invocation)
|
||||
: _receiver = receiver,
|
||||
_invocation = invocation as _InvocationMirror;
|
||||
_invocation = invocation;
|
||||
|
||||
static void _throwNewInvocation(Object receiver, Invocation invocation) {
|
||||
throw new NoSuchMethodError.withInvocation(receiver, invocation);
|
||||
|
@ -285,155 +285,210 @@ class NoSuchMethodError {
|
|||
@patch
|
||||
String toString() {
|
||||
// TODO(regis): Remove this null check once dart2js is updated.
|
||||
if (_invocation == null) {
|
||||
var invocation = _invocation;
|
||||
if (invocation == null) {
|
||||
// Use deprecated version of toString.
|
||||
return _toStringDeprecated();
|
||||
}
|
||||
String memberName =
|
||||
internal.Symbol.computeUnmangledName(_invocation.memberName);
|
||||
var level = (_invocation._type >> _InvocationMirror._LEVEL_SHIFT) &
|
||||
_InvocationMirror._LEVEL_MASK;
|
||||
var kind = _invocation._type & _InvocationMirror._KIND_MASK;
|
||||
if (kind == _InvocationMirror._LOCAL_VAR) {
|
||||
return "NoSuchMethodError: Cannot assign to final variable '$memberName'";
|
||||
}
|
||||
|
||||
StringBuffer typeArgumentsBuf = null;
|
||||
var typeArguments = _invocation.typeArguments;
|
||||
if ((typeArguments != null) && (typeArguments.length > 0)) {
|
||||
typeArgumentsBuf = new StringBuffer();
|
||||
typeArgumentsBuf.write("<");
|
||||
for (int i = 0; i < typeArguments.length; i++) {
|
||||
if (i > 0) {
|
||||
typeArgumentsBuf.write(", ");
|
||||
}
|
||||
typeArgumentsBuf.write(Error.safeToString(typeArguments[i]));
|
||||
if (invocation is _InvocationMirror) {
|
||||
String memberName =
|
||||
internal.Symbol.computeUnmangledName(invocation.memberName);
|
||||
var level = (invocation._type >> _InvocationMirror._LEVEL_SHIFT) &
|
||||
_InvocationMirror._LEVEL_MASK;
|
||||
var kind = invocation._type & _InvocationMirror._KIND_MASK;
|
||||
if (kind == _InvocationMirror._LOCAL_VAR) {
|
||||
return "NoSuchMethodError: Cannot assign to final variable '$memberName'";
|
||||
}
|
||||
typeArgumentsBuf.write(">");
|
||||
}
|
||||
StringBuffer argumentsBuf = new StringBuffer();
|
||||
var positionalArguments = _invocation.positionalArguments;
|
||||
int argumentCount = 0;
|
||||
if (positionalArguments != null) {
|
||||
for (; argumentCount < positionalArguments.length; argumentCount++) {
|
||||
if (argumentCount > 0) {
|
||||
argumentsBuf.write(", ");
|
||||
}
|
||||
argumentsBuf
|
||||
.write(Error.safeToString(positionalArguments[argumentCount]));
|
||||
}
|
||||
}
|
||||
var namedArguments = _invocation.namedArguments;
|
||||
if (namedArguments != null) {
|
||||
namedArguments.forEach((Symbol key, var value) {
|
||||
if (argumentCount > 0) {
|
||||
argumentsBuf.write(", ");
|
||||
}
|
||||
argumentsBuf.write(internal.Symbol.computeUnmangledName(key));
|
||||
argumentsBuf.write(": ");
|
||||
argumentsBuf.write(Error.safeToString(value));
|
||||
argumentCount++;
|
||||
});
|
||||
}
|
||||
String existingSig =
|
||||
_existingMethodSignature(_receiver, memberName, _invocation._type);
|
||||
String argsMsg = existingSig != null ? " with matching arguments" : "";
|
||||
|
||||
String kindBuf;
|
||||
if (kind >= 0 && kind < 5) {
|
||||
kindBuf = (const [
|
||||
"method",
|
||||
"getter",
|
||||
"setter",
|
||||
"getter or setter",
|
||||
"variable"
|
||||
])[kind];
|
||||
}
|
||||
|
||||
StringBuffer msgBuf = new StringBuffer("NoSuchMethodError: ");
|
||||
bool is_type_call = false;
|
||||
switch (level) {
|
||||
case _InvocationMirror._DYNAMIC:
|
||||
{
|
||||
if (_receiver == null) {
|
||||
if (existingSig != null) {
|
||||
msgBuf.writeln("The null object does not have a $kindBuf "
|
||||
"'$memberName'$argsMsg.");
|
||||
} else {
|
||||
msgBuf.writeln("The $kindBuf '$memberName' was called on null.");
|
||||
}
|
||||
} else {
|
||||
if (_receiver is _Closure) {
|
||||
msgBuf.writeln("Closure call with mismatched arguments: "
|
||||
"function '$memberName'");
|
||||
} else if (_receiver is _Type && memberName == "call") {
|
||||
is_type_call = true;
|
||||
String name = _receiver.toString();
|
||||
msgBuf.writeln("Attempted to use type '$name' as a function. "
|
||||
"Since types do not define a method 'call', this is not "
|
||||
"possible. Did you intend to call the $name constructor and "
|
||||
"forget the 'new' operator?");
|
||||
} else {
|
||||
msgBuf.writeln("Class '${_receiver.runtimeType}' has no instance "
|
||||
"$kindBuf '$memberName'$argsMsg.");
|
||||
}
|
||||
StringBuffer typeArgumentsBuf = null;
|
||||
var typeArguments = invocation.typeArguments;
|
||||
if ((typeArguments != null) && (typeArguments.length > 0)) {
|
||||
typeArgumentsBuf = new StringBuffer();
|
||||
typeArgumentsBuf.write("<");
|
||||
for (int i = 0; i < typeArguments.length; i++) {
|
||||
if (i > 0) {
|
||||
typeArgumentsBuf.write(", ");
|
||||
}
|
||||
break;
|
||||
typeArgumentsBuf.write(Error.safeToString(typeArguments[i]));
|
||||
}
|
||||
case _InvocationMirror._SUPER:
|
||||
{
|
||||
msgBuf.writeln("Super class of class '${_receiver.runtimeType}' has "
|
||||
"no instance $kindBuf '$memberName'$argsMsg.");
|
||||
memberName = "super.$memberName";
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._STATIC:
|
||||
{
|
||||
msgBuf.writeln("No static $kindBuf '$memberName'$argsMsg "
|
||||
"declared in class '$_receiver'.");
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._CONSTRUCTOR:
|
||||
{
|
||||
msgBuf.writeln("No constructor '$memberName'$argsMsg declared "
|
||||
"in class '$_receiver'.");
|
||||
memberName = "new $memberName";
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._TOP_LEVEL:
|
||||
{
|
||||
msgBuf.writeln("No top-level $kindBuf '$memberName'$argsMsg "
|
||||
"declared.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (level == _InvocationMirror._TOP_LEVEL) {
|
||||
msgBuf.writeln("Receiver: top-level");
|
||||
} else {
|
||||
msgBuf.writeln("Receiver: ${Error.safeToString(_receiver)}");
|
||||
}
|
||||
|
||||
if (kind == _InvocationMirror._METHOD) {
|
||||
String m = is_type_call ? "$_receiver" : "$memberName";
|
||||
msgBuf.write("Tried calling: $m");
|
||||
if (typeArgumentsBuf != null) {
|
||||
msgBuf.write(typeArgumentsBuf);
|
||||
typeArgumentsBuf.write(">");
|
||||
}
|
||||
msgBuf.write("($argumentsBuf)");
|
||||
} else if (argumentCount == 0) {
|
||||
msgBuf.write("Tried calling: $memberName");
|
||||
} else if (kind == _InvocationMirror._SETTER) {
|
||||
msgBuf.write("Tried calling: $memberName$argumentsBuf");
|
||||
} else {
|
||||
msgBuf.write("Tried calling: $memberName = $argumentsBuf");
|
||||
}
|
||||
StringBuffer argumentsBuf = new StringBuffer();
|
||||
var positionalArguments = invocation.positionalArguments;
|
||||
int argumentCount = 0;
|
||||
if (positionalArguments != null) {
|
||||
for (; argumentCount < positionalArguments.length; argumentCount++) {
|
||||
if (argumentCount > 0) {
|
||||
argumentsBuf.write(", ");
|
||||
}
|
||||
argumentsBuf
|
||||
.write(Error.safeToString(positionalArguments[argumentCount]));
|
||||
}
|
||||
}
|
||||
var namedArguments = invocation.namedArguments;
|
||||
if (namedArguments != null) {
|
||||
namedArguments.forEach((Symbol key, var value) {
|
||||
if (argumentCount > 0) {
|
||||
argumentsBuf.write(", ");
|
||||
}
|
||||
argumentsBuf.write(internal.Symbol.computeUnmangledName(key));
|
||||
argumentsBuf.write(": ");
|
||||
argumentsBuf.write(Error.safeToString(value));
|
||||
argumentCount++;
|
||||
});
|
||||
}
|
||||
String existingSig =
|
||||
_existingMethodSignature(_receiver, memberName, invocation._type);
|
||||
String argsMsg = existingSig != null ? " with matching arguments" : "";
|
||||
|
||||
if (existingSig != null) {
|
||||
msgBuf.write("\nFound: $memberName$existingSig");
|
||||
}
|
||||
String kindBuf;
|
||||
if (kind >= 0 && kind < 5) {
|
||||
kindBuf = (const [
|
||||
"method",
|
||||
"getter",
|
||||
"setter",
|
||||
"getter or setter",
|
||||
"variable"
|
||||
])[kind];
|
||||
}
|
||||
|
||||
return msgBuf.toString();
|
||||
StringBuffer msgBuf = new StringBuffer("NoSuchMethodError: ");
|
||||
bool is_type_call = false;
|
||||
switch (level) {
|
||||
case _InvocationMirror._DYNAMIC:
|
||||
{
|
||||
if (_receiver == null) {
|
||||
if (existingSig != null) {
|
||||
msgBuf.writeln("The null object does not have a $kindBuf "
|
||||
"'$memberName'$argsMsg.");
|
||||
} else {
|
||||
msgBuf
|
||||
.writeln("The $kindBuf '$memberName' was called on null.");
|
||||
}
|
||||
} else {
|
||||
if (_receiver is _Closure) {
|
||||
msgBuf.writeln("Closure call with mismatched arguments: "
|
||||
"function '$memberName'");
|
||||
} else if (_receiver is _Type && memberName == "call") {
|
||||
is_type_call = true;
|
||||
String name = _receiver.toString();
|
||||
msgBuf.writeln("Attempted to use type '$name' as a function. "
|
||||
"Since types do not define a method 'call', this is not "
|
||||
"possible. Did you intend to call the $name constructor and "
|
||||
"forget the 'new' operator?");
|
||||
} else {
|
||||
msgBuf
|
||||
.writeln("Class '${_receiver.runtimeType}' has no instance "
|
||||
"$kindBuf '$memberName'$argsMsg.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._SUPER:
|
||||
{
|
||||
msgBuf
|
||||
.writeln("Super class of class '${_receiver.runtimeType}' has "
|
||||
"no instance $kindBuf '$memberName'$argsMsg.");
|
||||
memberName = "super.$memberName";
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._STATIC:
|
||||
{
|
||||
msgBuf.writeln("No static $kindBuf '$memberName'$argsMsg "
|
||||
"declared in class '$_receiver'.");
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._CONSTRUCTOR:
|
||||
{
|
||||
msgBuf.writeln("No constructor '$memberName'$argsMsg declared "
|
||||
"in class '$_receiver'.");
|
||||
memberName = "new $memberName";
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._TOP_LEVEL:
|
||||
{
|
||||
msgBuf.writeln("No top-level $kindBuf '$memberName'$argsMsg "
|
||||
"declared.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (level == _InvocationMirror._TOP_LEVEL) {
|
||||
msgBuf.writeln("Receiver: top-level");
|
||||
} else {
|
||||
msgBuf.writeln("Receiver: ${Error.safeToString(_receiver)}");
|
||||
}
|
||||
|
||||
if (kind == _InvocationMirror._METHOD) {
|
||||
String m = is_type_call ? "$_receiver" : "$memberName";
|
||||
msgBuf.write("Tried calling: $m");
|
||||
if (typeArgumentsBuf != null) {
|
||||
msgBuf.write(typeArgumentsBuf);
|
||||
}
|
||||
msgBuf.write("($argumentsBuf)");
|
||||
} else if (argumentCount == 0) {
|
||||
msgBuf.write("Tried calling: $memberName");
|
||||
} else if (kind == _InvocationMirror._SETTER) {
|
||||
msgBuf.write("Tried calling: $memberName$argumentsBuf");
|
||||
} else {
|
||||
msgBuf.write("Tried calling: $memberName = $argumentsBuf");
|
||||
}
|
||||
|
||||
if (existingSig != null) {
|
||||
msgBuf.write("\nFound: $memberName$existingSig");
|
||||
}
|
||||
|
||||
return msgBuf.toString();
|
||||
}
|
||||
return _toStringPlain(_receiver, invocation);
|
||||
}
|
||||
|
||||
/// Creates a string representation of an invocation.
|
||||
///
|
||||
/// Used for situations where there is no extra information available
|
||||
/// about the failed invocation than the [Invocation] object and receiver,
|
||||
/// which includes errors created using [NoSuchMethodError.withInvocation].
|
||||
static String _toStringPlain(Object receiver, Invocation invocation) {
|
||||
var name = _symbolToString(invocation.memberName);
|
||||
var receiverType = "${receiver.runtimeType}";
|
||||
if (invocation.isAccessor) {
|
||||
return "NoSuchMethodError: $receiverType has no $name ${invocation.isGetter ? "getter" : "setter"}";
|
||||
}
|
||||
var buffer = StringBuffer("NoSuchMethodError")..write(": ");
|
||||
buffer.write("$receiverType has no $name method accepting arguments ");
|
||||
var separator = "";
|
||||
if (invocation.typeArguments.isNotEmpty) {
|
||||
buffer.write("<");
|
||||
for (var type in invocation.typeArguments) {
|
||||
buffer..write(separator)..write("_");
|
||||
separator = ", ";
|
||||
}
|
||||
buffer.write(">");
|
||||
separator = "";
|
||||
}
|
||||
buffer.write("(");
|
||||
for (var argument in invocation.positionalArguments) {
|
||||
buffer..write(separator)..write("_");
|
||||
separator = ", ";
|
||||
}
|
||||
if (invocation.namedArguments.isNotEmpty) {
|
||||
buffer..write(separator)..write("{");
|
||||
separator = "";
|
||||
for (var name in invocation.namedArguments.keys) {
|
||||
buffer..write(separator)..write(_symbolToString(name))..write(": _");
|
||||
separator = ",";
|
||||
}
|
||||
buffer.write("}");
|
||||
}
|
||||
buffer.write(")");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
static String _symbolToString(Symbol symbol) {
|
||||
if (symbol is internal.Symbol) {
|
||||
return internal.Symbol.computeUnmangledName(symbol);
|
||||
}
|
||||
return "$symbol";
|
||||
}
|
||||
|
||||
// TODO(regis): Remove this function once dart2js is updated.
|
||||
|
|
|
@ -184,13 +184,13 @@ class NoSuchMethodError {
|
|||
List? _existingArgumentNames;
|
||||
|
||||
final Object _receiver;
|
||||
final _InvocationMirror? _invocation;
|
||||
final Invocation? _invocation;
|
||||
|
||||
// Issue(dartbug.com/127160): Remove the cast to [_InvocationMirror].
|
||||
@patch
|
||||
NoSuchMethodError.withInvocation(Object receiver, Invocation invocation)
|
||||
: _receiver = receiver,
|
||||
_invocation = invocation as _InvocationMirror;
|
||||
_invocation = invocation;
|
||||
|
||||
static void _throwNewInvocation(Object receiver, Invocation invocation) {
|
||||
throw new NoSuchMethodError.withInvocation(receiver, invocation);
|
||||
|
@ -288,152 +288,208 @@ class NoSuchMethodError {
|
|||
// Use deprecated version of toString.
|
||||
return _toStringDeprecated();
|
||||
}
|
||||
var internalName = localInvocation.memberName as internal.Symbol;
|
||||
String memberName = internal.Symbol.computeUnmangledName(internalName);
|
||||
if (localInvocation is _InvocationMirror) {
|
||||
var internalName = localInvocation.memberName as internal.Symbol;
|
||||
String memberName = internal.Symbol.computeUnmangledName(internalName);
|
||||
|
||||
var level = (localInvocation._type >> _InvocationMirror._LEVEL_SHIFT) &
|
||||
_InvocationMirror._LEVEL_MASK;
|
||||
var kind = localInvocation._type & _InvocationMirror._KIND_MASK;
|
||||
if (kind == _InvocationMirror._LOCAL_VAR) {
|
||||
return "NoSuchMethodError: Cannot assign to final variable '$memberName'";
|
||||
}
|
||||
|
||||
StringBuffer? typeArgumentsBuf = null;
|
||||
final typeArguments = localInvocation.typeArguments;
|
||||
if ((typeArguments != null) && (typeArguments.length > 0)) {
|
||||
final argsBuf = new StringBuffer();
|
||||
argsBuf.write("<");
|
||||
for (int i = 0; i < typeArguments.length; i++) {
|
||||
if (i > 0) {
|
||||
argsBuf.write(", ");
|
||||
}
|
||||
argsBuf.write(Error.safeToString(typeArguments[i]));
|
||||
var level = (localInvocation._type >> _InvocationMirror._LEVEL_SHIFT) &
|
||||
_InvocationMirror._LEVEL_MASK;
|
||||
var kind = localInvocation._type & _InvocationMirror._KIND_MASK;
|
||||
if (kind == _InvocationMirror._LOCAL_VAR) {
|
||||
return "NoSuchMethodError: Cannot assign to final variable '$memberName'";
|
||||
}
|
||||
argsBuf.write(">");
|
||||
typeArgumentsBuf = argsBuf;
|
||||
}
|
||||
StringBuffer argumentsBuf = new StringBuffer();
|
||||
var positionalArguments = localInvocation.positionalArguments;
|
||||
int argumentCount = 0;
|
||||
if (positionalArguments != null) {
|
||||
for (; argumentCount < positionalArguments.length; argumentCount++) {
|
||||
if (argumentCount > 0) {
|
||||
argumentsBuf.write(", ");
|
||||
}
|
||||
argumentsBuf
|
||||
.write(Error.safeToString(positionalArguments[argumentCount]));
|
||||
}
|
||||
}
|
||||
var namedArguments = localInvocation.namedArguments;
|
||||
if (namedArguments != null) {
|
||||
namedArguments.forEach((Symbol key, var value) {
|
||||
if (argumentCount > 0) {
|
||||
argumentsBuf.write(", ");
|
||||
}
|
||||
var internalName = key as internal.Symbol;
|
||||
argumentsBuf.write(internal.Symbol.computeUnmangledName(internalName));
|
||||
argumentsBuf.write(": ");
|
||||
argumentsBuf.write(Error.safeToString(value));
|
||||
argumentCount++;
|
||||
});
|
||||
}
|
||||
String? existingSig =
|
||||
_existingMethodSignature(_receiver, memberName, localInvocation._type);
|
||||
String argsMsg = existingSig != null ? " with matching arguments" : "";
|
||||
|
||||
assert(kind >= 0 && kind < 5);
|
||||
final String kindBuf = (const [
|
||||
"method",
|
||||
"getter",
|
||||
"setter",
|
||||
"getter or setter",
|
||||
"variable"
|
||||
])[kind];
|
||||
|
||||
StringBuffer msgBuf = new StringBuffer("NoSuchMethodError: ");
|
||||
bool isTypeCall = false;
|
||||
switch (level) {
|
||||
case _InvocationMirror._DYNAMIC:
|
||||
{
|
||||
if (_receiver == null) {
|
||||
if (existingSig != null) {
|
||||
msgBuf.writeln("The null object does not have a $kindBuf "
|
||||
"'$memberName'$argsMsg.");
|
||||
} else {
|
||||
msgBuf.writeln("The $kindBuf '$memberName' was called on null.");
|
||||
}
|
||||
} else {
|
||||
if (_receiver is _Closure) {
|
||||
msgBuf.writeln("Closure call with mismatched arguments: "
|
||||
"function '$memberName'");
|
||||
} else if (_receiver is _Type && memberName == "call") {
|
||||
isTypeCall = true;
|
||||
String name = _receiver.toString();
|
||||
msgBuf.writeln("Attempted to use type '$name' as a function. "
|
||||
"Since types do not define a method 'call', this is not "
|
||||
"possible. Did you intend to call the $name constructor and "
|
||||
"forget the 'new' operator?");
|
||||
} else {
|
||||
msgBuf.writeln("Class '${_receiver.runtimeType}' has no instance "
|
||||
"$kindBuf '$memberName'$argsMsg.");
|
||||
}
|
||||
StringBuffer? typeArgumentsBuf = null;
|
||||
final typeArguments = localInvocation.typeArguments;
|
||||
if ((typeArguments != null) && (typeArguments.length > 0)) {
|
||||
final argsBuf = new StringBuffer();
|
||||
argsBuf.write("<");
|
||||
for (int i = 0; i < typeArguments.length; i++) {
|
||||
if (i > 0) {
|
||||
argsBuf.write(", ");
|
||||
}
|
||||
break;
|
||||
argsBuf.write(Error.safeToString(typeArguments[i]));
|
||||
}
|
||||
case _InvocationMirror._SUPER:
|
||||
{
|
||||
msgBuf.writeln("Super class of class '${_receiver.runtimeType}' has "
|
||||
"no instance $kindBuf '$memberName'$argsMsg.");
|
||||
memberName = "super.$memberName";
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._STATIC:
|
||||
{
|
||||
msgBuf.writeln("No static $kindBuf '$memberName'$argsMsg "
|
||||
"declared in class '$_receiver'.");
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._CONSTRUCTOR:
|
||||
{
|
||||
msgBuf.writeln("No constructor '$memberName'$argsMsg declared "
|
||||
"in class '$_receiver'.");
|
||||
memberName = "new $memberName";
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._TOP_LEVEL:
|
||||
{
|
||||
msgBuf.writeln("No top-level $kindBuf '$memberName'$argsMsg "
|
||||
"declared.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (level == _InvocationMirror._TOP_LEVEL) {
|
||||
msgBuf.writeln("Receiver: top-level");
|
||||
} else {
|
||||
msgBuf.writeln("Receiver: ${Error.safeToString(_receiver)}");
|
||||
}
|
||||
|
||||
if (kind == _InvocationMirror._METHOD) {
|
||||
String m = isTypeCall ? "$_receiver" : "$memberName";
|
||||
msgBuf.write("Tried calling: $m");
|
||||
if (typeArgumentsBuf != null) {
|
||||
msgBuf.write(typeArgumentsBuf);
|
||||
argsBuf.write(">");
|
||||
typeArgumentsBuf = argsBuf;
|
||||
}
|
||||
msgBuf.write("($argumentsBuf)");
|
||||
} else if (argumentCount == 0) {
|
||||
msgBuf.write("Tried calling: $memberName");
|
||||
} else if (kind == _InvocationMirror._SETTER) {
|
||||
msgBuf.write("Tried calling: $memberName$argumentsBuf");
|
||||
} else {
|
||||
msgBuf.write("Tried calling: $memberName = $argumentsBuf");
|
||||
}
|
||||
StringBuffer argumentsBuf = new StringBuffer();
|
||||
var positionalArguments = localInvocation.positionalArguments;
|
||||
int argumentCount = 0;
|
||||
if (positionalArguments != null) {
|
||||
for (; argumentCount < positionalArguments.length; argumentCount++) {
|
||||
if (argumentCount > 0) {
|
||||
argumentsBuf.write(", ");
|
||||
}
|
||||
argumentsBuf
|
||||
.write(Error.safeToString(positionalArguments[argumentCount]));
|
||||
}
|
||||
}
|
||||
var namedArguments = localInvocation.namedArguments;
|
||||
if (namedArguments != null) {
|
||||
namedArguments.forEach((Symbol key, var value) {
|
||||
if (argumentCount > 0) {
|
||||
argumentsBuf.write(", ");
|
||||
}
|
||||
var internalName = key as internal.Symbol;
|
||||
argumentsBuf
|
||||
.write(internal.Symbol.computeUnmangledName(internalName));
|
||||
argumentsBuf.write(": ");
|
||||
argumentsBuf.write(Error.safeToString(value));
|
||||
argumentCount++;
|
||||
});
|
||||
}
|
||||
String? existingSig = _existingMethodSignature(
|
||||
_receiver, memberName, localInvocation._type);
|
||||
String argsMsg = existingSig != null ? " with matching arguments" : "";
|
||||
|
||||
if (existingSig != null) {
|
||||
msgBuf.write("\nFound: $memberName$existingSig");
|
||||
}
|
||||
assert(kind >= 0 && kind < 5);
|
||||
final String kindBuf = (const [
|
||||
"method",
|
||||
"getter",
|
||||
"setter",
|
||||
"getter or setter",
|
||||
"variable"
|
||||
])[kind];
|
||||
|
||||
return msgBuf.toString();
|
||||
StringBuffer msgBuf = new StringBuffer("NoSuchMethodError: ");
|
||||
bool isTypeCall = false;
|
||||
switch (level) {
|
||||
case _InvocationMirror._DYNAMIC:
|
||||
{
|
||||
if (_receiver == null) {
|
||||
if (existingSig != null) {
|
||||
msgBuf.writeln("The null object does not have a $kindBuf "
|
||||
"'$memberName'$argsMsg.");
|
||||
} else {
|
||||
msgBuf
|
||||
.writeln("The $kindBuf '$memberName' was called on null.");
|
||||
}
|
||||
} else {
|
||||
if (_receiver is _Closure) {
|
||||
msgBuf.writeln("Closure call with mismatched arguments: "
|
||||
"function '$memberName'");
|
||||
} else if (_receiver is _Type && memberName == "call") {
|
||||
isTypeCall = true;
|
||||
String name = _receiver.toString();
|
||||
msgBuf.writeln("Attempted to use type '$name' as a function. "
|
||||
"Since types do not define a method 'call', this is not "
|
||||
"possible. Did you intend to call the $name constructor and "
|
||||
"forget the 'new' operator?");
|
||||
} else {
|
||||
msgBuf
|
||||
.writeln("Class '${_receiver.runtimeType}' has no instance "
|
||||
"$kindBuf '$memberName'$argsMsg.");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._SUPER:
|
||||
{
|
||||
msgBuf
|
||||
.writeln("Super class of class '${_receiver.runtimeType}' has "
|
||||
"no instance $kindBuf '$memberName'$argsMsg.");
|
||||
memberName = "super.$memberName";
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._STATIC:
|
||||
{
|
||||
msgBuf.writeln("No static $kindBuf '$memberName'$argsMsg "
|
||||
"declared in class '$_receiver'.");
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._CONSTRUCTOR:
|
||||
{
|
||||
msgBuf.writeln("No constructor '$memberName'$argsMsg declared "
|
||||
"in class '$_receiver'.");
|
||||
memberName = "new $memberName";
|
||||
break;
|
||||
}
|
||||
case _InvocationMirror._TOP_LEVEL:
|
||||
{
|
||||
msgBuf.writeln("No top-level $kindBuf '$memberName'$argsMsg "
|
||||
"declared.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (level == _InvocationMirror._TOP_LEVEL) {
|
||||
msgBuf.writeln("Receiver: top-level");
|
||||
} else {
|
||||
msgBuf.writeln("Receiver: ${Error.safeToString(_receiver)}");
|
||||
}
|
||||
|
||||
if (kind == _InvocationMirror._METHOD) {
|
||||
String m = isTypeCall ? "$_receiver" : "$memberName";
|
||||
msgBuf.write("Tried calling: $m");
|
||||
if (typeArgumentsBuf != null) {
|
||||
msgBuf.write(typeArgumentsBuf);
|
||||
}
|
||||
msgBuf.write("($argumentsBuf)");
|
||||
} else if (argumentCount == 0) {
|
||||
msgBuf.write("Tried calling: $memberName");
|
||||
} else if (kind == _InvocationMirror._SETTER) {
|
||||
msgBuf.write("Tried calling: $memberName$argumentsBuf");
|
||||
} else {
|
||||
msgBuf.write("Tried calling: $memberName = $argumentsBuf");
|
||||
}
|
||||
|
||||
if (existingSig != null) {
|
||||
msgBuf.write("\nFound: $memberName$existingSig");
|
||||
}
|
||||
|
||||
return msgBuf.toString();
|
||||
}
|
||||
return _toStringPlain(_receiver, localInvocation);
|
||||
}
|
||||
|
||||
/// Creates a string representation of an invocation.
|
||||
///
|
||||
/// Used for situations where there is no extra information available
|
||||
/// about the failed invocation than the [Invocation] object and receiver,
|
||||
/// which includes errors created using [NoSuchMethodError.withInvocation].
|
||||
static String _toStringPlain(Object receiver, Invocation invocation) {
|
||||
var name = _symbolToString(invocation.memberName);
|
||||
var receiverType = "${receiver.runtimeType}";
|
||||
if (invocation.isAccessor) {
|
||||
return "NoSuchMethodError: $receiverType has no $name "
|
||||
"${invocation.isGetter ? "getter" : "setter"}";
|
||||
}
|
||||
var buffer = StringBuffer("NoSuchMethodError")..write(": ");
|
||||
buffer.write("$receiverType has no $name method accepting arguments ");
|
||||
var separator = "";
|
||||
if (invocation.typeArguments.isNotEmpty) {
|
||||
buffer.write("<");
|
||||
for (var type in invocation.typeArguments) {
|
||||
buffer..write(separator)..write("_");
|
||||
separator = ", ";
|
||||
}
|
||||
buffer.write(">");
|
||||
separator = "";
|
||||
}
|
||||
buffer.write("(");
|
||||
for (var argument in invocation.positionalArguments) {
|
||||
buffer..write(separator)..write("_");
|
||||
separator = ", ";
|
||||
}
|
||||
if (invocation.namedArguments.isNotEmpty) {
|
||||
buffer..write(separator)..write("{");
|
||||
separator = "";
|
||||
for (var name in invocation.namedArguments.keys) {
|
||||
buffer..write(separator)..write(_symbolToString(name))..write(": _");
|
||||
separator = ",";
|
||||
}
|
||||
buffer.write("}");
|
||||
}
|
||||
buffer.write(")");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
static String _symbolToString(Symbol symbol) {
|
||||
if (symbol is internal.Symbol) {
|
||||
return internal.Symbol.computeUnmangledName(symbol);
|
||||
}
|
||||
return "$symbol";
|
||||
}
|
||||
|
||||
// TODO(regis): Remove this function once dart2js is updated.
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
// Using withInvocation constructor.
|
||||
var receiver = Object();
|
||||
{
|
||||
var invocationGet = Invocation.getter(#foo);
|
||||
var errorGet = NoSuchMethodError.withInvocation(receiver, invocationGet);
|
||||
var errorString = errorGet.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "01: $errorString");
|
||||
Expect.isTrue(errorString.contains("getter"), "02: $errorString");
|
||||
}
|
||||
{
|
||||
var invocationSet = Invocation.setter(#foo, 42);
|
||||
var error = NoSuchMethodError.withInvocation(receiver, invocationSet);
|
||||
var errorString = error.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "03: $errorString");
|
||||
Expect.isTrue(errorString.contains("setter"), "04: $errorString");
|
||||
}
|
||||
{
|
||||
var invocationCall = Invocation.method(#foo, [42]);
|
||||
var error = NoSuchMethodError.withInvocation(receiver, invocationCall);
|
||||
var errorString = error.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "05: $errorString");
|
||||
Expect.isTrue(errorString.contains("method"), "06: $errorString");
|
||||
Expect.isTrue(errorString.contains("(_)"), "07: $errorString");
|
||||
}
|
||||
{
|
||||
var invocationCall = Invocation.method(#foo, [42], {#bar: 37});
|
||||
var error = NoSuchMethodError.withInvocation(receiver, invocationCall);
|
||||
var errorString = error.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "08: $errorString");
|
||||
Expect.isTrue(errorString.contains("method"), "09: $errorString");
|
||||
Expect.isTrue(errorString.contains("(_, {bar: _})"), "10: $errorString");
|
||||
}
|
||||
{
|
||||
var invocationCall = Invocation.genericMethod(#foo, [int], [42]);
|
||||
var error = NoSuchMethodError.withInvocation(receiver, invocationCall);
|
||||
var errorString = error.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "11: $errorString");
|
||||
Expect.isTrue(errorString.contains("method"), "12: $errorString");
|
||||
Expect.isTrue(errorString.contains("<_>(_)"), "13: $errorString");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
// Using withInvocation constructor.
|
||||
var receiver = Object();
|
||||
{
|
||||
var invocationGet = Invocation.getter(#foo);
|
||||
var errorGet = NoSuchMethodError.withInvocation(receiver, invocationGet);
|
||||
var errorString = errorGet.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "01: $errorString");
|
||||
Expect.isTrue(errorString.contains("getter"), "02: $errorString");
|
||||
}
|
||||
{
|
||||
var invocationSet = Invocation.setter(#foo, 42);
|
||||
var error = NoSuchMethodError.withInvocation(receiver, invocationSet);
|
||||
var errorString = error.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "03: $errorString");
|
||||
Expect.isTrue(errorString.contains("setter"), "04: $errorString");
|
||||
}
|
||||
{
|
||||
var invocationCall = Invocation.method(#foo, [42]);
|
||||
var error = NoSuchMethodError.withInvocation(receiver, invocationCall);
|
||||
var errorString = error.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "05: $errorString");
|
||||
Expect.isTrue(errorString.contains("method"), "06: $errorString");
|
||||
Expect.isTrue(errorString.contains("(_)"), "07: $errorString");
|
||||
}
|
||||
{
|
||||
var invocationCall = Invocation.method(#foo, [42], {#bar: 37});
|
||||
var error = NoSuchMethodError.withInvocation(receiver, invocationCall);
|
||||
var errorString = error.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "08: $errorString");
|
||||
Expect.isTrue(errorString.contains("method"), "09: $errorString");
|
||||
Expect.isTrue(errorString.contains("(_, {bar: _})"), "10: $errorString");
|
||||
}
|
||||
{
|
||||
var invocationCall = Invocation.genericMethod(#foo, [int], [42]);
|
||||
var error = NoSuchMethodError.withInvocation(receiver, invocationCall);
|
||||
var errorString = error.toString();
|
||||
Expect.isTrue(errorString.contains("foo"), "11: $errorString");
|
||||
Expect.isTrue(errorString.contains("method"), "12: $errorString");
|
||||
Expect.isTrue(errorString.contains("<_>(_)"), "13: $errorString");
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue