79 import jdk.jshell.EvalException; |
79 import jdk.jshell.EvalException; |
80 import jdk.jshell.ExpressionSnippet; |
80 import jdk.jshell.ExpressionSnippet; |
81 import jdk.jshell.ImportSnippet; |
81 import jdk.jshell.ImportSnippet; |
82 import jdk.jshell.JShell; |
82 import jdk.jshell.JShell; |
83 import jdk.jshell.JShell.Subscription; |
83 import jdk.jshell.JShell.Subscription; |
|
84 import jdk.jshell.JShellException; |
84 import jdk.jshell.MethodSnippet; |
85 import jdk.jshell.MethodSnippet; |
85 import jdk.jshell.Snippet; |
86 import jdk.jshell.Snippet; |
86 import jdk.jshell.Snippet.Kind; |
87 import jdk.jshell.Snippet.Kind; |
87 import jdk.jshell.Snippet.Status; |
88 import jdk.jshell.Snippet.Status; |
88 import jdk.jshell.SnippetEvent; |
89 import jdk.jshell.SnippetEvent; |
3355 } |
3356 } |
3356 |
3357 |
3357 /** |
3358 /** |
3358 * Print out a snippet exception. |
3359 * Print out a snippet exception. |
3359 * |
3360 * |
3360 * @param exception the exception to print |
3361 * @param exception the throwable to print |
3361 * @return true on fatal exception |
3362 * @return true on fatal exception |
3362 */ |
3363 */ |
3363 private boolean displayException(Exception exception) { |
3364 private boolean displayException(Throwable exception) { |
|
3365 Throwable rootCause = exception; |
|
3366 while (rootCause instanceof EvalException) { |
|
3367 rootCause = rootCause.getCause(); |
|
3368 } |
|
3369 if (rootCause != exception && rootCause instanceof UnresolvedReferenceException) { |
|
3370 // An unresolved reference caused a chained exception, just show the unresolved |
|
3371 return displayException(rootCause, null); |
|
3372 } else { |
|
3373 return displayException(exception, null); |
|
3374 } |
|
3375 } |
|
3376 //where |
|
3377 private boolean displayException(Throwable exception, StackTraceElement[] caused) { |
3364 if (exception instanceof EvalException) { |
3378 if (exception instanceof EvalException) { |
3365 printEvalException((EvalException) exception); |
3379 // User exception |
3366 return true; |
3380 return displayEvalException((EvalException) exception, caused); |
3367 } else if (exception instanceof UnresolvedReferenceException) { |
3381 } else if (exception instanceof UnresolvedReferenceException) { |
3368 printUnresolvedException((UnresolvedReferenceException) exception); |
3382 // Reference to an undefined snippet |
3369 return false; |
3383 return displayUnresolvedException((UnresolvedReferenceException) exception); |
3370 } else { |
3384 } else { |
|
3385 // Should never occur |
3371 error("Unexpected execution exception: %s", exception); |
3386 error("Unexpected execution exception: %s", exception); |
3372 return true; |
3387 return true; |
3373 } |
3388 } |
|
3389 } |
|
3390 //where |
|
3391 private boolean displayUnresolvedException(UnresolvedReferenceException ex) { |
|
3392 // Display the resolution issue |
|
3393 printSnippetStatus(ex.getSnippet(), false); |
|
3394 return false; |
|
3395 } |
|
3396 |
|
3397 //where |
|
3398 private boolean displayEvalException(EvalException ex, StackTraceElement[] caused) { |
|
3399 // The message for the user exception is configured based on the |
|
3400 // existance of an exception message and if this is a recursive |
|
3401 // invocation for a chained exception. |
|
3402 String msg = ex.getMessage(); |
|
3403 String key = "jshell.err.exception" + |
|
3404 (caused == null? ".thrown" : ".cause") + |
|
3405 (msg == null? "" : ".message"); |
|
3406 errormsg(key, ex.getExceptionClassName(), msg); |
|
3407 // The caused trace is sent to truncate duplicate elements in the cause trace |
|
3408 printStackTrace(ex.getStackTrace(), caused); |
|
3409 JShellException cause = ex.getCause(); |
|
3410 if (cause != null) { |
|
3411 // Display the cause (recursively) |
|
3412 displayException(cause, ex.getStackTrace()); |
|
3413 } |
|
3414 return true; |
3374 } |
3415 } |
3375 |
3416 |
3376 /** |
3417 /** |
3377 * Display a list of diagnostics. |
3418 * Display a list of diagnostics. |
3378 * |
3419 * |
3516 .displayDeclarationAndValue(); |
3557 .displayDeclarationAndValue(); |
3517 } |
3558 } |
3518 } |
3559 } |
3519 return false; |
3560 return false; |
3520 } |
3561 } |
3521 //where |
3562 |
3522 void printStackTrace(StackTraceElement[] stes) { |
3563 // Print a stack trace, elide frames displayed for the caused exception |
3523 for (StackTraceElement ste : stes) { |
3564 void printStackTrace(StackTraceElement[] stes, StackTraceElement[] caused) { |
|
3565 int overlap = 0; |
|
3566 if (caused != null) { |
|
3567 int maxOverlap = Math.min(stes.length, caused.length); |
|
3568 while (overlap < maxOverlap |
|
3569 && stes[stes.length - (overlap + 1)].equals(caused[caused.length - (overlap + 1)])) { |
|
3570 ++overlap; |
|
3571 } |
|
3572 } |
|
3573 for (int i = 0; i < stes.length - overlap; ++i) { |
|
3574 StackTraceElement ste = stes[i]; |
3524 StringBuilder sb = new StringBuilder(); |
3575 StringBuilder sb = new StringBuilder(); |
3525 String cn = ste.getClassName(); |
3576 String cn = ste.getClassName(); |
3526 if (!cn.isEmpty()) { |
3577 if (!cn.isEmpty()) { |
3527 int dot = cn.lastIndexOf('.'); |
3578 int dot = cn.lastIndexOf('.'); |
3528 if (dot > 0) { |
3579 if (dot > 0) { |
3546 ? fileName + ":" + lineNumber |
3597 ? fileName + ":" + lineNumber |
3547 : fileName; |
3598 : fileName; |
3548 error(" at %s(%s)", sb, loc); |
3599 error(" at %s(%s)", sb, loc); |
3549 |
3600 |
3550 } |
3601 } |
3551 } |
3602 if (overlap != 0) { |
3552 //where |
3603 error(" ..."); |
3553 void printUnresolvedException(UnresolvedReferenceException ex) { |
3604 } |
3554 printSnippetStatus(ex.getSnippet(), false); |
|
3555 } |
|
3556 //where |
|
3557 void printEvalException(EvalException ex) { |
|
3558 if (ex.getMessage() == null) { |
|
3559 error("%s thrown", ex.getExceptionClassName()); |
|
3560 } else { |
|
3561 error("%s thrown: %s", ex.getExceptionClassName(), ex.getMessage()); |
|
3562 } |
|
3563 printStackTrace(ex.getStackTrace()); |
|
3564 } |
3605 } |
3565 |
3606 |
3566 private FormatAction toAction(Status status, Status previousStatus, boolean isSignatureChange) { |
3607 private FormatAction toAction(Status status, Status previousStatus, boolean isSignatureChange) { |
3567 FormatAction act; |
3608 FormatAction act; |
3568 switch (status) { |
3609 switch (status) { |