OLD | NEW |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |