src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java

Print this page




  77 import jdk.jshell.PersistentSnippet;
  78 import jdk.jshell.Snippet;
  79 import jdk.jshell.Snippet.Status;
  80 import jdk.jshell.SnippetEvent;
  81 import jdk.jshell.SourceCodeAnalysis;
  82 import jdk.jshell.SourceCodeAnalysis.CompletionInfo;
  83 import jdk.jshell.SourceCodeAnalysis.Suggestion;
  84 import jdk.jshell.TypeDeclSnippet;
  85 import jdk.jshell.UnresolvedReferenceException;
  86 import jdk.jshell.VarSnippet;
  87 
  88 import static java.nio.file.StandardOpenOption.CREATE;
  89 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
  90 import static java.nio.file.StandardOpenOption.WRITE;
  91 import java.util.MissingResourceException;
  92 import java.util.Optional;
  93 import java.util.ResourceBundle;
  94 import java.util.Spliterators;
  95 import java.util.function.Function;
  96 import java.util.function.Supplier;

  97 import jdk.internal.jshell.tool.Feedback.FormatAction;
  98 import jdk.internal.jshell.tool.Feedback.FormatCase;
  99 import jdk.internal.jshell.tool.Feedback.FormatErrors;
 100 import jdk.internal.jshell.tool.Feedback.FormatResolve;
 101 import jdk.internal.jshell.tool.Feedback.FormatUnresolved;
 102 import jdk.internal.jshell.tool.Feedback.FormatWhen;



 103 import static java.util.stream.Collectors.toList;
 104 import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND;
 105 import static java.util.stream.Collectors.toMap;
 106 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_COMPA;
 107 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP;
 108 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_EVNT;
 109 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_FMGR;
 110 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
 111 
 112 /**
 113  * Command line REPL tool for Java using the JShell API.
 114  * @author Robert Field
 115  */
 116 public class JShellTool implements MessageHandler {
 117 
 118     private static final String LINE_SEP = System.getProperty("line.separator");
 119     private static final Pattern LINEBREAK = Pattern.compile("\\R");
 120     private static final String RECORD_SEPARATOR = "\u241E";
 121     private static final String RB_NAME_PREFIX  = "jdk.internal.jshell.tool.resources";
 122     private static final String VERSION_RB_NAME = RB_NAME_PREFIX + ".version";


 498 
 499         try {
 500             while (regenerateOnDeath) {
 501                 if (!live) {
 502                     resetState();
 503                 }
 504                 run(in);
 505             }
 506         } finally {
 507             closeState();
 508         }
 509     }
 510 
 511     /**
 512      * Process the command line arguments.
 513      * Set options.
 514      * @param args the command line arguments
 515      * @return the list of files to be loaded
 516      */
 517     private List<String> processCommandArgs(String[] args) {
 518         List<String> loadList = new ArrayList<>();
 519         Iterator<String> ai = Arrays.asList(args).iterator();
 520         while (ai.hasNext()) {
 521             String arg = ai.next();
 522             if (arg.startsWith("-")) {
 523                 switch (arg) {
 524                     case "-classpath":
 525                     case "-cp":
 526                         if (cmdlineClasspath != null) {
 527                             startmsg("jshell.err.opt.classpath.conflict");
 528                             return null;
 529                         }
 530                         if (ai.hasNext()) {
 531                             cmdlineClasspath = ai.next();






 532                         } else {
 533                             startmsg("jshell.err.opt.classpath.arg");







 534                             return null;
 535                         }
 536                         break;
 537                     case "-help":
 538                         printUsage();
 539                         return null;
 540                     case "-version":

 541                         cmdout.printf("jshell %s\n", version());
 542                         return null;
 543                     case "-fullversion":

 544                         cmdout.printf("jshell %s\n", fullVersion());
 545                         return null;
 546                     case "-feedback":
 547                         if (ai.hasNext()) {
 548                             commandLineFeedbackMode = ai.next();
 549                         } else {
 550                             startmsg("jshell.err.opt.feedback.arg");
 551                             return null;
 552                         }
 553                         break;
 554                     case "-q":
 555                         commandLineFeedbackMode = "concise";
 556                         break;
 557                     case "-qq":
 558                         commandLineFeedbackMode = "silent";
 559                         break;
 560                     case "-v":
 561                         commandLineFeedbackMode = "verbose";
 562                         break;
 563                     case "-startup":
 564                         if (startup != null) {
 565                             startmsg("jshell.err.opt.startup.one");
 566                             return null;
 567                         }
 568                         startup = readFile(ai.hasNext()? ai.next() : null, "-startup");
 569                         if (startup == null) {
 570                             return null;
 571                         }
 572                         break;
 573                     case "-nostartup":
 574                         if (startup != null) {
 575                             startmsg("jshell.err.opt.startup.one");
 576                             return null;
 577                         }

 578                         startup = "";
 579                         break;
 580                     default:
 581                         if (arg.startsWith("-R")) {
 582                             remoteVMOptions.add(arg.substring(2));
 583                             break;
 584                         }
 585                         startmsg("jshell.err.opt.unknown", arg);
 586                         printUsage();


 587                         return null;
 588                 }
 589             } else {
 590                 loadList.add(arg);
 591             }


 592         }
 593         return loadList;










 594     }
 595 
 596     private void printUsage() {
 597         cmdout.print(getResourceString("help.usage"));
 598     }
 599 
 600     /**
 601      * Message handler to use during initial start-up.
 602      */
 603     private class InitMessageHandler implements MessageHandler {
 604 
 605         @Override
 606         public void fluff(String format, Object... args) {
 607             //ignore
 608         }
 609 
 610         @Override
 611         public void fluffmsg(String messageKey, Object... args) {
 612             //ignore
 613         }


 669     }
 670 
 671     //where -- one-time per run initialization of feedback modes
 672     private void initFeedback() {
 673         // No fluff, no prefix, for init failures
 674         MessageHandler initmh = new InitMessageHandler();
 675         // Execute the feedback initialization code in the resource file
 676         startUpRun(getResourceString("startup.feedback"));
 677         // These predefined modes are read-only
 678         feedback.markModesReadOnly();
 679         // Restore user defined modes retained on previous run with /retain mode
 680         String encoded = prefs.get(MODE_KEY, null);
 681         if (encoded != null && !encoded.isEmpty()) {
 682             if (!feedback.restoreEncodedModes(initmh, encoded)) {
 683                 // Catastrophic corruption -- remove the retained modes
 684                 prefs.remove(MODE_KEY);
 685             }
 686         }
 687         if (commandLineFeedbackMode != null) {
 688             // The feedback mode to use was specified on the command line, use it
 689             if (!feedback.setFeedback(initmh, new ArgTokenizer("-feedback", commandLineFeedbackMode))) {
 690                 regenerateOnDeath = false;
 691             }
 692             commandLineFeedbackMode = null;
 693         } else {
 694             String fb = prefs.get(FEEDBACK_KEY, null);
 695             if (fb != null) {
 696                 // Restore the feedback mode to use that was retained
 697                 // on a previous run with /retain feedback
 698                 feedback.retainFeedback(initmh, new ArgTokenizer("/retain feedback", fb));
 699             }
 700         }
 701     }
 702 
 703     //where
 704     private void startUpRun(String start) {
 705         try (IOContext suin = new FileScannerIOContext(new StringReader(start))) {
 706             run(suin);
 707         } catch (Exception ex) {
 708             hardmsg("jshell.err.startup.unexpected.exception", ex);
 709             ex.printStackTrace(cmdout);




  77 import jdk.jshell.PersistentSnippet;
  78 import jdk.jshell.Snippet;
  79 import jdk.jshell.Snippet.Status;
  80 import jdk.jshell.SnippetEvent;
  81 import jdk.jshell.SourceCodeAnalysis;
  82 import jdk.jshell.SourceCodeAnalysis.CompletionInfo;
  83 import jdk.jshell.SourceCodeAnalysis.Suggestion;
  84 import jdk.jshell.TypeDeclSnippet;
  85 import jdk.jshell.UnresolvedReferenceException;
  86 import jdk.jshell.VarSnippet;
  87 
  88 import static java.nio.file.StandardOpenOption.CREATE;
  89 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
  90 import static java.nio.file.StandardOpenOption.WRITE;
  91 import java.util.MissingResourceException;
  92 import java.util.Optional;
  93 import java.util.ResourceBundle;
  94 import java.util.Spliterators;
  95 import java.util.function.Function;
  96 import java.util.function.Supplier;
  97 import jdk.internal.joptsimple.*;
  98 import jdk.internal.jshell.tool.Feedback.FormatAction;
  99 import jdk.internal.jshell.tool.Feedback.FormatCase;
 100 import jdk.internal.jshell.tool.Feedback.FormatErrors;
 101 import jdk.internal.jshell.tool.Feedback.FormatResolve;
 102 import jdk.internal.jshell.tool.Feedback.FormatUnresolved;
 103 import jdk.internal.jshell.tool.Feedback.FormatWhen;
 104 import static java.util.Arrays.asList;
 105 import static java.util.Arrays.stream;
 106 import static java.util.stream.Collectors.joining;
 107 import static java.util.stream.Collectors.toList;
 108 import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND;
 109 import static java.util.stream.Collectors.toMap;
 110 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_COMPA;
 111 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP;
 112 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_EVNT;
 113 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_FMGR;
 114 import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
 115 
 116 /**
 117  * Command line REPL tool for Java using the JShell API.
 118  * @author Robert Field
 119  */
 120 public class JShellTool implements MessageHandler {
 121 
 122     private static final String LINE_SEP = System.getProperty("line.separator");
 123     private static final Pattern LINEBREAK = Pattern.compile("\\R");
 124     private static final String RECORD_SEPARATOR = "\u241E";
 125     private static final String RB_NAME_PREFIX  = "jdk.internal.jshell.tool.resources";
 126     private static final String VERSION_RB_NAME = RB_NAME_PREFIX + ".version";


 502 
 503         try {
 504             while (regenerateOnDeath) {
 505                 if (!live) {
 506                     resetState();
 507                 }
 508                 run(in);
 509             }
 510         } finally {
 511             closeState();
 512         }
 513     }
 514 
 515     /**
 516      * Process the command line arguments.
 517      * Set options.
 518      * @param args the command line arguments
 519      * @return the list of files to be loaded
 520      */
 521     private List<String> processCommandArgs(String[] args) {
 522         OptionParser parser = new OptionParser();
 523         OptionSpec<String> cp = parser.accepts("class-path").withRequiredArg();
 524         OptionSpec<String> st = parser.accepts("startup").withRequiredArg();
 525         parser.acceptsAll(asList("n", "no-startup"));
 526         OptionSpec<String> fb = parser.accepts("feedback").withRequiredArg();
 527         parser.accepts("q");
 528         parser.accepts("s");
 529         parser.accepts("v");
 530         OptionSpec<String> r = parser.accepts("R").withRequiredArg();
 531         parser.acceptsAll(asList("h", "help"));
 532         parser.accepts("version");
 533         parser.accepts("full-version");
 534         NonOptionArgumentSpec<String> loadFileSpec = parser.nonOptions();
 535 
 536         OptionSet options;
 537         try {
 538             options = parser.parse(args);
 539         } catch (OptionException ex) {
 540             if (ex.options().isEmpty()) {
 541                 startmsg("jshell.err.opt.invalid", stream(args).collect(joining(", ")));
 542             } else {
 543                 boolean isKnown = parser.recognizedOptions().containsKey(ex.options().iterator().next());
 544                 startmsg(isKnown
 545                         ? "jshell.err.opt.arg"
 546                         : "jshell.err.opt.unknown",
 547                         ex.options()
 548                         .stream()
 549                         .collect(joining(", ")));
 550             }
 551             return null;
 552         }
 553 
 554         if (options.has("help")) {
 555             printUsage();
 556             return null;
 557         }
 558         if (options.has("version")) {
 559             cmdout.printf("jshell %s\n", version());
 560             return null;
 561         }
 562         if (options.has("full-version")) {
 563             cmdout.printf("jshell %s\n", fullVersion());
 564             return null;
 565         }
 566         if (options.has(cp)) {
 567             List<String> cps = options.valuesOf(cp);
 568             if (cps.size() > 1) {
 569                 startmsg("jshell.err.opt.one", "--class-path");
 570                 return null;
 571             }
 572             cmdlineClasspath = cps.get(0);
 573         }
 574         if (options.has(st)) {
 575             List<String> sts = options.valuesOf(st);
 576             if (sts.size() != 1 || options.has("no-startup")) {







 577                 startmsg("jshell.err.opt.startup.one");
 578                 return null;
 579             }
 580             startup = readFile(sts.get(0), "--startup");
 581             if (startup == null) {
 582                 return null;
 583             }





 584         }
 585         if (options.has("no-startup")) {
 586             startup = "";





 587         }
 588         if (options.has(fb)) {
 589             List<String> fbs = options.valuesOf(fb);
 590             if (fbs.size() != 1) {
 591                 startmsg("jshell.err.opt.one", "--feedback");
 592                 return null;
 593             }
 594             commandLineFeedbackMode = fbs.get(0);

 595         }
 596         if (options.has("q")) {
 597             commandLineFeedbackMode = "concise";
 598         }
 599         if (options.has("s")) {
 600             commandLineFeedbackMode = "silent";
 601         }
 602         if (options.has("v")) {
 603             commandLineFeedbackMode = "verbose";
 604         }
 605         if (options.has(r)) {
 606             remoteVMOptions = options.valuesOf(r);
 607         }
 608 
 609         return options.valuesOf(loadFileSpec);
 610     }
 611 
 612     private void printUsage() {
 613         cmdout.print(getResourceString("help.usage"));
 614     }
 615 
 616     /**
 617      * Message handler to use during initial start-up.
 618      */
 619     private class InitMessageHandler implements MessageHandler {
 620 
 621         @Override
 622         public void fluff(String format, Object... args) {
 623             //ignore
 624         }
 625 
 626         @Override
 627         public void fluffmsg(String messageKey, Object... args) {
 628             //ignore
 629         }


 685     }
 686 
 687     //where -- one-time per run initialization of feedback modes
 688     private void initFeedback() {
 689         // No fluff, no prefix, for init failures
 690         MessageHandler initmh = new InitMessageHandler();
 691         // Execute the feedback initialization code in the resource file
 692         startUpRun(getResourceString("startup.feedback"));
 693         // These predefined modes are read-only
 694         feedback.markModesReadOnly();
 695         // Restore user defined modes retained on previous run with /retain mode
 696         String encoded = prefs.get(MODE_KEY, null);
 697         if (encoded != null && !encoded.isEmpty()) {
 698             if (!feedback.restoreEncodedModes(initmh, encoded)) {
 699                 // Catastrophic corruption -- remove the retained modes
 700                 prefs.remove(MODE_KEY);
 701             }
 702         }
 703         if (commandLineFeedbackMode != null) {
 704             // The feedback mode to use was specified on the command line, use it
 705             if (!feedback.setFeedback(initmh, new ArgTokenizer("--feedback", commandLineFeedbackMode))) {
 706                 regenerateOnDeath = false;
 707             }
 708             commandLineFeedbackMode = null;
 709         } else {
 710             String fb = prefs.get(FEEDBACK_KEY, null);
 711             if (fb != null) {
 712                 // Restore the feedback mode to use that was retained
 713                 // on a previous run with /retain feedback
 714                 feedback.retainFeedback(initmh, new ArgTokenizer("/retain feedback", fb));
 715             }
 716         }
 717     }
 718 
 719     //where
 720     private void startUpRun(String start) {
 721         try (IOContext suin = new FileScannerIOContext(new StringReader(start))) {
 722             run(suin);
 723         } catch (Exception ex) {
 724             hardmsg("jshell.err.startup.unexpected.exception", ex);
 725             ex.printStackTrace(cmdout);