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);
|