Files
sdk/runtime/lib/errors_patch.dart
T
regis@google.com dec11d8b7b Add support for javascript incompatibility warnings (work in progress).
For now, warnings are only issued when applicable for type tests, type casts,
and toString.
Fix newly reported lint errors.

R=srdjan@google.com

Review URL: https://codereview.chromium.org//260713008

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36001 260f80e4-7a28-3924-810f-c04153c831b5
2014-05-09 22:42:10 +00:00

345 lines
12 KiB
Dart

// Copyright (c) 2012, 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.
patch class Error {
/* patch */ static String _objectToString(Object object) {
return Object._toString(object);
}
/* patch */ StackTrace get stackTrace => _stackTrace;
StackTrace _stackTrace;
}
patch class AssertionError extends Error {
AssertionError._create(
this._failedAssertion, this._url, this._line, this._column);
static _throwNew(int assertionStart, int assertionEnd)
native "AssertionError_throwNew";
String toString() {
var columnInfo = "";
if (_column > 0) {
// Only add column information if it is valid.
columnInfo = " pos $_column";
}
return "'$_url': Failed assertion: line $_line$columnInfo: "
"'$_failedAssertion' is not true.";
}
final String _failedAssertion;
final String _url;
final int _line;
final int _column;
}
patch class TypeError extends AssertionError {
TypeError._create(String url, int line, int column,
this._srcType, this._dstType, this._dstName,
this._errorMsg)
: super._create("is assignable", url, line, column);
static _throwNew(int location,
Object src_value,
String dst_type_name,
String dst_name,
String error_msg)
native "TypeError_throwNew";
String toString() {
String str = (_errorMsg != null) ? _errorMsg : "";
if ((_dstName != null) && (_dstName.length > 0)) {
str = "${str}type '$_srcType' is not a subtype of "
"type '$_dstType' of '$_dstName'.";
} else {
str = "${str}type error.";
}
return str;
}
final String _srcType;
final String _dstType;
final String _dstName;
final String _errorMsg;
}
patch class CastError extends Error {
CastError._create(this._url, this._line, this._column,
this._srcType, this._dstType, this._dstName,
this._errorMsg);
// A CastError is allocated by TypeError._throwNew() when dst_name equals
// Exceptions::kCastErrorDstName.
String toString() {
String str = (_errorMsg != null) ? _errorMsg : "";
str = "${str}type '$_srcType' is not a subtype of "
"type '$_dstType' in type cast.";
return str;
}
// Fields _url, _line, and _column are only used for debugging purposes.
final String _url;
final int _line;
final int _column;
final String _srcType;
final String _dstType;
final String _dstName;
final String _errorMsg;
}
patch class FallThroughError {
FallThroughError._create(this._url, this._line);
static _throwNew(int case_clause_pos) native "FallThroughError_throwNew";
/* patch */ String toString() {
return "'$_url': Switch case fall-through at line $_line.";
}
// These new fields cannot be declared final, because a constructor exists
// in the original version of this patched class.
String _url;
int _line;
}
class _InternalError {
const _InternalError(this._msg);
String toString() => "InternalError: '${_msg}'";
final String _msg;
}
patch class CyclicInitializationError {
static _throwNew(String variableName) {
throw new CyclicInitializationError(variableName);
}
}
patch class AbstractClassInstantiationError {
AbstractClassInstantiationError._create(
this._className, this._url, this._line);
static _throwNew(int case_clause_pos, String className)
native "AbstractClassInstantiationError_throwNew";
/* patch */ String toString() {
return "Cannot instantiate abstract class $_className: "
"_url '$_url' line $_line";
}
// These new fields cannot be declared final, because a constructor exists
// in the original version of this patched class.
String _url;
int _line;
}
patch class NoSuchMethodError {
// The compiler emits a call to _throwNew when it cannot resolve a static
// method at compile time. The receiver is actually the literal class of the
// unresolved method.
static void _throwNew(Object receiver,
String memberName,
int invocation_type,
List arguments,
List argumentNames,
List existingArgumentNames) {
int numNamedArguments = argumentNames == null ? 0 : argumentNames.length;
int numPositionalArguments = arguments == null ? 0 : arguments.length;
numPositionalArguments -= numNamedArguments;
List positionalArguments;
if (numPositionalArguments == 0) {
// Differ between no arguments specified and 0 arguments.
// TODO(srdjan): This can currently occur for unresolvable static methods.
// In that case, the arguments are evaluated but not passed to the
// throwing stub (see EffectGraphVisitor::BuildThrowNoSuchMethodError and
// Parser::ThrowNoSuchMethodError)).
positionalArguments = argumentNames == null ? null : [];
} else {
positionalArguments = arguments.sublist(0, numPositionalArguments);
}
Map<Symbol, dynamic> namedArguments = new Map<Symbol, dynamic>();
for (int i = 0; i < numNamedArguments; i++) {
var arg_value = arguments[numPositionalArguments + i];
namedArguments[new Symbol(argumentNames[i])] = arg_value;
}
throw new NoSuchMethodError._withType(receiver,
new Symbol(memberName),
invocation_type,
positionalArguments,
namedArguments,
existingArgumentNames);
}
// Remember the type from the invocation mirror or static compilation
// analysis when thrown directly with _throwNew. A negative value means
// that no information is available.
final int _invocation_type;
NoSuchMethodError(Object this._receiver,
Symbol this._memberName,
List this._arguments,
Map<Symbol, dynamic> this._namedArguments,
[List existingArgumentNames = null])
: this._existingArgumentNames = existingArgumentNames,
this._invocation_type = -1;
// This constructor seems to be called with either strings or
// values read from another NoSuchMethodError.
NoSuchMethodError._withType(Object this._receiver,
/*String|Symbol*/ memberName,
this._invocation_type,
List this._arguments,
Map<dynamic, dynamic> namedArguments,
[List existingArgumentNames = null])
: this._memberName =
(memberName is String) ? new Symbol(memberName) : memberName,
this._namedArguments =
(namedArguments == null)
? null
: new Map<Symbol, dynamic>.fromIterable(
namedArguments.keys,
key: (k) => (k is String) ? new Symbol(k) : k,
value: (k) => namedArguments[k]),
this._existingArgumentNames = existingArgumentNames;
String _developerMessage(args_mismatch) {
if (_invocation_type < 0) {
return "";
}
var type = _invocation_type & _InvocationMirror._TYPE_MASK;
var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) &
_InvocationMirror._CALL_MASK;
var type_str =
(const ["method", "getter", "setter", "getter or setter", "variable"])[type];
var args_message = args_mismatch ? " with matching arguments" : "";
var msg;
var memberName =
(_memberName == null) ? "" : internal.Symbol.getName(_memberName);
if (type == _InvocationMirror._LOCAL_VAR) {
return "cannot assign to final variable '$memberName'.\n\n";
}
switch (level) {
case _InvocationMirror._DYNAMIC: {
if (_receiver == null) {
msg = "The null object does not have a $type_str '$memberName'"
"$args_message.";
} else {
if (_receiver is Function) {
msg = "Closure call with mismatched arguments: "
"function '$memberName'";
} else {
msg = "Class '${_receiver.runtimeType}' has no instance $type_str "
"'$memberName'$args_message.";
}
}
break;
}
case _InvocationMirror._SUPER: {
msg = "Super class of class '${_receiver.runtimeType}' has no instance "
"$type_str '$memberName'$args_message.";
break;
}
case _InvocationMirror._STATIC: {
msg = "No static $type_str '$memberName' declared in class "
"'$_receiver'.";
break;
}
case _InvocationMirror._CONSTRUCTOR: {
msg = "No constructor '$memberName'$args_message declared in class '$_receiver'.";
break;
}
case _InvocationMirror._TOP_LEVEL: {
msg = "No top-level $type_str '$memberName'$args_message declared.";
break;
}
}
return "$msg\n\n";
}
/* patch */ String toString() {
StringBuffer actual_buf = new StringBuffer();
int i = 0;
if (_arguments == null) {
// Actual arguments unknown.
// TODO(srdjan): Remove once arguments are passed for unresolvable
// static methods.
actual_buf.write("...");
} else {
for (; i < _arguments.length; i++) {
if (i > 0) {
actual_buf.write(", ");
}
actual_buf.write(Error.safeToString(_arguments[i]));
}
}
if (_namedArguments != null) {
_namedArguments.forEach((Symbol key, var value) {
if (i > 0) {
actual_buf.write(", ");
}
actual_buf.write(internal.Symbol.getName(key));
actual_buf.write(": ");
actual_buf.write(Error.safeToString(value));
i++;
});
}
var args_mismatch = _existingArgumentNames != null;
StringBuffer msg_buf = new StringBuffer(_developerMessage(args_mismatch));
String receiver_str;
var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) &
_InvocationMirror._CALL_MASK;
if ( level == _InvocationMirror._TOP_LEVEL) {
receiver_str = "top-level";
} else {
receiver_str = Error.safeToString(_receiver);
}
var memberName =
(_memberName == null) ? "" : internal.Symbol.getName(_memberName);
var type = _invocation_type & _InvocationMirror._TYPE_MASK;
if (type == _InvocationMirror._LOCAL_VAR) {
msg_buf.write(
"NoSuchMethodError: cannot assign to final variable '$memberName'");
} else if (!args_mismatch) {
msg_buf.write(
"NoSuchMethodError: method not found: '$memberName'\n"
"Receiver: $receiver_str\n"
"Arguments: [$actual_buf]");
} else {
String actualParameters = actual_buf.toString();
StringBuffer formal_buf = new StringBuffer();
for (int i = 0; i < _existingArgumentNames.length; i++) {
if (i > 0) {
formal_buf.write(", ");
}
formal_buf.write(_existingArgumentNames[i]);
}
String formalParameters = formal_buf.toString();
msg_buf.write(
"NoSuchMethodError: incorrect number of arguments passed to "
"method named '$memberName'\n"
"Receiver: $receiver_str\n"
"Tried calling: $memberName($actualParameters)\n"
"Found: $memberName($formalParameters)");
}
return msg_buf.toString();
}
}
class _JavascriptIntegerOverflowError extends Error {
final Object _value;
_JavascriptIntegerOverflowError(this._value);
String toString() => "Javascript Integer Overflow: $_value";
}
class _JavascriptCompatibilityError extends Error {
final String _msg;
_JavascriptCompatibilityError(this._msg);
String toString() => "Javascript Compatibility Error: $_msg";
}