# HG changeset patch # User rfield # Date 1448994434 28800 # Node ID 64001b0533a2ec0f3a9d923229eba15cd72301b3 # Parent 9f12a05b478671ca88a6a17dbb5d8f20d5745b5c 8142447: JShell tool: Command change: re-run n-th command should be re-run by id Reviewed-by: rfield Contributed-by: bitterfoxc@gmail.com diff -r 9f12a05b4786 -r 64001b0533a2 langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Mon Nov 30 13:27:57 2015 -0800 +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Tue Dec 01 10:27:14 2015 -0800 @@ -86,7 +86,9 @@ import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; import static java.nio.file.StandardOpenOption.WRITE; +import java.util.Locale; import java.util.MissingResourceException; +import java.util.Optional; import java.util.ResourceBundle; import static java.util.stream.Collectors.toList; @@ -491,12 +493,14 @@ } private void processCommand(String cmd) { - try { - //handle "/[number]" - cmdUseHistoryEntry(Integer.parseInt(cmd.substring(1))); - return ; - } catch (NumberFormatException ex) { - //ignore + if (cmd.startsWith("/-")) { + try { + //handle "/-[number]" + cmdUseHistoryEntry(Integer.parseInt(cmd.substring(1))); + return ; + } catch (NumberFormatException ex) { + //ignore + } } String arg = ""; int idx = cmd.indexOf(' '); @@ -506,8 +510,10 @@ } Command[] candidates = findCommand(cmd, c -> c.kind != CommandKind.HELP_ONLY); if (candidates.length == 0) { - hard("No such command: %s", cmd); - fluff("Type /help for help."); + if (!rerunHistoryEntryById(cmd.substring(1))) { + hard("No such command or snippet id: %s", cmd); + fluff("Type /help for help."); + } } else if (candidates.length == 1) { candidates[0].run.accept(arg); } else { @@ -728,7 +734,7 @@ registerCommand(new Command("/!", "", "re-run last snippet", arg -> cmdUseHistoryEntry(-1), EMPTY_COMPLETION_PROVIDER)); - registerCommand(new Command("/", "", "re-run n-th snippet", + registerCommand(new Command("/", "", "re-run snippet by id", arg -> { throw new IllegalStateException(); }, EMPTY_COMPLETION_PROVIDER, CommandKind.HELP_ONLY)); @@ -1275,15 +1281,29 @@ else index--; if (index >= 0 && index < keys.size()) { - String source = keys.get(index).source(); - cmdout.printf("%s\n", source); - input.replaceLastHistoryEntry(source); - processSourceCatchingReset(source); + rerunSnippet(keys.get(index)); } else { hard("Cannot find snippet %d", index + 1); } } + private boolean rerunHistoryEntryById(String id) { + Optional snippet = state.snippets().stream() + .filter(s -> s.id().equals(id)) + .findFirst(); + return snippet.map(s -> { + rerunSnippet(s); + return true; + }).orElse(false); + } + + private void rerunSnippet(Snippet snippet) { + String source = snippet.source(); + cmdout.printf("%s\n", source); + input.replaceLastHistoryEntry(source); + processSourceCatchingReset(source); + } + /** * Filter diagnostics for only errors (no warnings, ...) * @param diagnostics input list diff -r 9f12a05b4786 -r 64001b0533a2 langtools/test/jdk/jshell/ToolBasicTest.java --- a/langtools/test/jdk/jshell/ToolBasicTest.java Mon Nov 30 13:27:57 2015 -0800 +++ b/langtools/test/jdk/jshell/ToolBasicTest.java Tue Dec 01 10:27:14 2015 -0800 @@ -41,7 +41,9 @@ import java.util.Arrays; import java.util.List; import java.util.Scanner; +import java.util.function.BiFunction; import java.util.function.Consumer; +import java.util.function.Function; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import java.util.stream.Collectors; @@ -215,8 +217,8 @@ @Test(enabled = false) // TODO 8130450 public void testRerun() { test(false, new String[] {"-nostartup"}, - (a) -> assertCommand(a, "/0", "| Cannot find snippet 0\n"), - (a) -> assertCommand(a, "/5", "| Cannot find snippet 5\n") + (a) -> assertCommand(a, "/0", "| No such command or snippet id: /0\n| Type /help for help.\n"), + (a) -> assertCommand(a, "/5", "| No such command or snippet id: /5\n| Type /help for help.\n") ); String[] codes = new String[] { "int a = 0;", // var @@ -252,6 +254,35 @@ tests.toArray(new ReplTest[tests.size()])); } + public void test8142447() { + Function> assertRerun = cmd -> (code, assertionCount) -> + (a) -> assertCommandCheckOutput(a, cmd, s -> { + String[] ss = s.split("\n"); + assertEquals(ss[0], code); + loadVariable(a, "int", "assertionCount", Integer.toString(assertionCount), Integer.toString(assertionCount)); + }); + ReplTest assertVariables = (a) -> assertCommandCheckOutput(a, "/v", assertVariables()); + + Compiler compiler = new Compiler(); + Path startup = compiler.getPath("StartupFileOption/startup.txt"); + compiler.writeToFile(startup, "int assertionCount = 0;\n" + // id: s1 + "void add(int n) { assertionCount += n; }"); + test(new String[]{"-startup", startup.toString()}, + (a) -> assertCommand(a, "add(1)", ""), // id: 1 + (a) -> assertCommandCheckOutput(a, "add(ONE)", s -> assertEquals(s.split("\n")[0], "| Error:")), // id: e1 + (a) -> assertVariable(a, "int", "ONE", "1", "1"), + assertRerun.apply("/1").apply("add(1)", 2), assertVariables, + assertRerun.apply("/e1").apply("add(ONE)", 3), assertVariables, + assertRerun.apply("/s1").apply("int assertionCount = 0;", 0), assertVariables + ); + + test(false, new String[] {"-nostartup"}, + (a) -> assertCommand(a, "/s1", "| No such command or snippet id: /s1\n| Type /help for help.\n"), + (a) -> assertCommand(a, "/1", "| No such command or snippet id: /1\n| Type /help for help.\n"), + (a) -> assertCommand(a, "/e1", "| No such command or snippet id: /e1\n| Type /help for help.\n") + ); + } + public void testRemaining() { test( (a) -> assertCommand(a, "int z; z =", "| Added variable z of type int\n"), @@ -574,7 +605,7 @@ public void testUnknownCommand() { test((a) -> assertCommand(a, "/unknown", - "| No such command: /unknown\n" + + "| No such command or snippet id: /unknown\n" + "| Type /help for help.\n")); }