Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(400)

Side by Side Diff: runtime/lib/errors_patch.dart

Issue 2405353002: Improvements to NoSuchMethodError.toString (Closed)
Patch Set: Fix for Ryan's comments. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | runtime/vm/isolate_reload_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:_internal' as internal; 5 import 'dart:_internal' as internal;
6 import 'dart:convert' show JSON; 6 import 'dart:convert' show JSON;
7 7
8 @patch class Error { 8 @patch class Error {
9 @patch static String _objectToString(Object object) { 9 @patch static String _objectToString(Object object) {
10 return Object._toString(object); 10 return Object._toString(object);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 static void _throwNew(Object receiver, 159 static void _throwNew(Object receiver,
160 String memberName, 160 String memberName,
161 int invocation_type, 161 int invocation_type,
162 List arguments, 162 List arguments,
163 List argumentNames, 163 List argumentNames,
164 List existingArgumentNames) { 164 List existingArgumentNames) {
165 int numNamedArguments = argumentNames == null ? 0 : argumentNames.length; 165 int numNamedArguments = argumentNames == null ? 0 : argumentNames.length;
166 int numPositionalArguments = arguments == null ? 0 : arguments.length; 166 int numPositionalArguments = arguments == null ? 0 : arguments.length;
167 numPositionalArguments -= numNamedArguments; 167 numPositionalArguments -= numNamedArguments;
168 List positionalArguments; 168 List positionalArguments;
169 if (numPositionalArguments == 0) { 169 if (numPositionalArguments > 0) {
170 // Differ between no arguments specified and 0 arguments. 170 // TODO(srdjan): Unresolvable static methods sometimes do not provide the
171 // TODO(srdjan): This can currently occur for unresolvable static methods. 171 // arguments, because the arguments are evaluated but not passed to the
172 // In that case, the arguments are evaluated but not passed to the
173 // throwing stub (see EffectGraphVisitor::BuildThrowNoSuchMethodError and 172 // throwing stub (see EffectGraphVisitor::BuildThrowNoSuchMethodError and
174 // Parser::ThrowNoSuchMethodError)). 173 // Parser::ThrowNoSuchMethodError)). There is no way to distinguish the
175 positionalArguments = argumentNames == null ? null : []; 174 // case of no arguments from the case of the arguments not being passed
176 } else { 175 // in here, though. See https://github.com/dart-lang/sdk/issues/27572
177 positionalArguments = arguments.sublist(0, numPositionalArguments); 176 positionalArguments = arguments.sublist(0, numPositionalArguments);
178 } 177 }
179 Map<Symbol, dynamic> namedArguments = new Map<Symbol, dynamic>(); 178 Map<Symbol, dynamic> namedArguments = new Map<Symbol, dynamic>();
180 for (int i = 0; i < numNamedArguments; i++) { 179 for (int i = 0; i < numNamedArguments; i++) {
181 var arg_value = arguments[numPositionalArguments + i]; 180 var arg_value = arguments[numPositionalArguments + i];
182 namedArguments[new Symbol(argumentNames[i])] = arg_value; 181 namedArguments[new Symbol(argumentNames[i])] = arg_value;
183 } 182 }
184 throw new NoSuchMethodError._withType(receiver, 183 throw new NoSuchMethodError._withType(receiver,
185 new Symbol(memberName), 184 new Symbol(memberName),
186 invocation_type, 185 invocation_type,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 (memberName is String) ? new Symbol(memberName) : memberName, 226 (memberName is String) ? new Symbol(memberName) : memberName,
228 this._namedArguments = 227 this._namedArguments =
229 (namedArguments == null) 228 (namedArguments == null)
230 ? null 229 ? null
231 : new Map<Symbol, dynamic>.fromIterable( 230 : new Map<Symbol, dynamic>.fromIterable(
232 namedArguments.keys, 231 namedArguments.keys,
233 key: (k) => (k is String) ? new Symbol(k) : k, 232 key: (k) => (k is String) ? new Symbol(k) : k,
234 value: (k) => namedArguments[k]), 233 value: (k) => namedArguments[k]),
235 this._existingArgumentNames = existingArgumentNames; 234 this._existingArgumentNames = existingArgumentNames;
236 235
237 236 @patch String toString() {
238 String _developerMessage(args_mismatch) { 237 var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) &
239 if (_invocation_type < 0) { 238 _InvocationMirror._CALL_MASK;
240 return "";
241 }
242 var type = _invocation_type & _InvocationMirror._TYPE_MASK; 239 var type = _invocation_type & _InvocationMirror._TYPE_MASK;
243 var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) & 240 String memberName = (_memberName == null) ? "" :
244 _InvocationMirror._CALL_MASK; 241 internal.Symbol.getUnmangledName(_memberName);
245 var type_str =
246 (const ["method", "getter", "setter", "getter or setter", "variable"])[t ype];
247 var args_message = args_mismatch ? " with matching arguments" : "";
248 var msg;
249 var memberName =
250 (_memberName == null) ? "" : internal.Symbol.getUnmangledName(_memberNam e);
251 242
252 if (type == _InvocationMirror._LOCAL_VAR) { 243 if (type == _InvocationMirror._LOCAL_VAR) {
253 return "cannot assign to final variable '$memberName'.\n\n"; 244 return "NoSuchMethodError: Cannot assign to final variable '$memberName'";
254 } 245 }
246
247 StringBuffer arguments = new StringBuffer();
248 int argumentCount = 0;
249 if (_arguments != null) {
250 for (; argumentCount < _arguments.length; argumentCount++) {
251 if (argumentCount > 0) {
252 arguments.write(", ");
253 }
254 arguments.write(Error.safeToString(_arguments[argumentCount]));
255 }
256 }
257 if (_namedArguments != null) {
258 _namedArguments.forEach((Symbol key, var value) {
259 if (argumentCount > 0) {
260 arguments.write(", ");
261 }
262 arguments.write(internal.Symbol.getUnmangledName(key));
263 arguments.write(": ");
264 arguments.write(Error.safeToString(value));
265 argumentCount++;
266 });
267 }
268 bool args_mismatch = _existingArgumentNames != null;
269 String args_message = args_mismatch ? " with matching arguments" : "";
270
271 String type_str;
272 if (type >= 0 && type < 5) {
273 type_str = (const ["method", "getter", "setter", "getter or setter",
274 "variable"])[type];
275 }
276
277 StringBuffer msg_buf = new StringBuffer("NoSuchMethodError: ");
255 switch (level) { 278 switch (level) {
256 case _InvocationMirror._DYNAMIC: { 279 case _InvocationMirror._DYNAMIC: {
257 if (_receiver == null) { 280 if (_receiver == null) {
258 msg = "The null object does not have a $type_str '$memberName'" 281 if (args_mismatch) {
259 "$args_message."; 282 msg_buf.writeln("The null object does not have a $type_str "
283 "'$memberName'$args_message.");
284 } else {
285 msg_buf.writeln("The $type_str '$memberName' was called on null.");
286 }
260 } else { 287 } else {
261 if (_receiver is Function) { 288 if (_receiver is Function) {
262 msg = "Closure call with mismatched arguments: " 289 msg_buf.writeln("Closure call with mismatched arguments: "
263 "function '$memberName'"; 290 "function '$memberName'");
264 } else { 291 } else {
265 msg = "Class '${_receiver.runtimeType}' has no instance $type_str " 292 msg_buf.writeln("Class '${_receiver.runtimeType}' has no instance "
266 "'$memberName'$args_message."; 293 "$type_str '$memberName'$args_message.");
267 } 294 }
268 } 295 }
269 break; 296 break;
270 } 297 }
271 case _InvocationMirror._SUPER: { 298 case _InvocationMirror._SUPER: {
272 msg = "Super class of class '${_receiver.runtimeType}' has no instance " 299 msg_buf.writeln("Super class of class '${_receiver.runtimeType}' has "
273 "$type_str '$memberName'$args_message."; 300 "no instance $type_str '$memberName'$args_message.");
301 memberName = "super.$memberName";
274 break; 302 break;
275 } 303 }
276 case _InvocationMirror._STATIC: { 304 case _InvocationMirror._STATIC: {
277 msg = "No static $type_str '$memberName' declared in class " 305 msg_buf.writeln("No static $type_str '$memberName'$args_message "
278 "'$_receiver'."; 306 "declared in class '$_receiver'.");
279 break; 307 break;
280 } 308 }
281 case _InvocationMirror._CONSTRUCTOR: { 309 case _InvocationMirror._CONSTRUCTOR: {
282 msg = "No constructor '$memberName'$args_message declared in class '$_re ceiver'."; 310 msg_buf.writeln("No constructor '$memberName'$args_message declared "
311 "in class '$_receiver'.");
312 memberName = "new $memberName";
283 break; 313 break;
284 } 314 }
285 case _InvocationMirror._TOP_LEVEL: { 315 case _InvocationMirror._TOP_LEVEL: {
286 msg = "No top-level $type_str '$memberName'$args_message declared."; 316 msg_buf.writeln("No top-level $type_str '$memberName'$args_message "
317 "declared.");
287 break; 318 break;
288 } 319 }
289 } 320 }
290 return "$msg\n\n";
291 }
292 321
293 @patch String toString() { 322 if (level == _InvocationMirror._TOP_LEVEL) {
294 StringBuffer actual_buf = new StringBuffer(); 323 msg_buf.writeln("Receiver: top-level");
295 int i = 0;
296 if (_arguments == null) {
297 // Actual arguments unknown.
298 // TODO(srdjan): Remove once arguments are passed for unresolvable
299 // static methods.
300 actual_buf.write("...");
301 } else { 324 } else {
302 for (; i < _arguments.length; i++) { 325 msg_buf.writeln("Receiver: ${Error.safeToString(_receiver)}");
303 if (i > 0) {
304 actual_buf.write(", ");
305 }
306 actual_buf.write(Error.safeToString(_arguments[i]));
307 }
308 } 326 }
309 if (_namedArguments != null) { 327
310 _namedArguments.forEach((Symbol key, var value) { 328 if (type == _InvocationMirror._METHOD) {
311 if (i > 0) { 329 msg_buf.write("Tried calling: $memberName($arguments)");
312 actual_buf.write(", "); 330 } else if (argumentCount == 0) {
313 } 331 msg_buf.write("Tried calling: $memberName");
314 actual_buf.write(internal.Symbol.getUnmangledName(key)); 332 } else if (type == _InvocationMirror._SETTER) {
315 actual_buf.write(": "); 333 msg_buf.write("Tried calling: $memberName$arguments");
316 actual_buf.write(Error.safeToString(value)); 334 } else {
317 i++; 335 msg_buf.write("Tried calling: $memberName = $arguments");
318 });
319 } 336 }
320 var args_mismatch = _existingArgumentNames != null; 337
321 StringBuffer msg_buf = new StringBuffer(_developerMessage(args_mismatch)); 338 if (args_mismatch) {
322 String receiver_str; 339 StringBuffer formalParameters = new StringBuffer();
323 var level = (_invocation_type >> _InvocationMirror._CALL_SHIFT) &
324 _InvocationMirror._CALL_MASK;
325 if ( level == _InvocationMirror._TOP_LEVEL) {
326 receiver_str = "top-level";
327 } else {
328 receiver_str = Error.safeToString(_receiver);
329 }
330 var memberName =
331 (_memberName == null) ? "" : internal.Symbol.getUnmangledName(_memberNam e);
332 var type = _invocation_type & _InvocationMirror._TYPE_MASK;
333 if (type == _InvocationMirror._LOCAL_VAR) {
334 msg_buf.write(
335 "NoSuchMethodError: cannot assign to final variable '$memberName'");
336 } else if (!args_mismatch) {
337 msg_buf.write(
338 "NoSuchMethodError: method not found: '$memberName'\n"
339 "Receiver: $receiver_str\n"
340 "Arguments: [$actual_buf]");
341 } else {
342 String actualParameters = actual_buf.toString();
343 StringBuffer formal_buf = new StringBuffer();
344 for (int i = 0; i < _existingArgumentNames.length; i++) { 340 for (int i = 0; i < _existingArgumentNames.length; i++) {
345 if (i > 0) { 341 if (i > 0) {
346 formal_buf.write(", "); 342 formalParameters.write(", ");
347 } 343 }
348 formal_buf.write(_existingArgumentNames[i]); 344 formalParameters.write(_existingArgumentNames[i]);
349 } 345 }
350 String formalParameters = formal_buf.toString(); 346 msg_buf.write("\nFound: $memberName($formalParameters)");
351 msg_buf.write(
352 "NoSuchMethodError: incorrect number of arguments passed to "
353 "method named '$memberName'\n"
354 "Receiver: $receiver_str\n"
355 "Tried calling: $memberName($actualParameters)\n"
356 "Found: $memberName($formalParameters)");
357 } 347 }
348
358 return msg_buf.toString(); 349 return msg_buf.toString();
359 } 350 }
360 } 351 }
361 352
362 353
363 class _CompileTimeError extends Error { 354 class _CompileTimeError extends Error {
364 final String _errorMsg; 355 final String _errorMsg;
365 _CompileTimeError(this._errorMsg); 356 _CompileTimeError(this._errorMsg);
366 String toString() => _errorMsg; 357 String toString() => _errorMsg;
367 } 358 }
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/isolate_reload_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698