src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java
changeset 49515 083318155ad1
parent 48939 ba545e52b932
child 49856 5f63af8f9d7f
equal deleted inserted replaced
49514:25695fce1601 49515:083318155ad1
    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) {