8143037: JShell should determine commands by prefix

Reviewed-by: rfield, mcimadamore, briangoetz
This commit is contained in:
Jan Lahoda 2015-11-30 17:31:55 +01:00
parent 3b399ff099
commit ad5ccf3886
3 changed files with 221 additions and 274 deletions
langtools
src/jdk.jshell/share/classes/jdk/internal/jshell/tool
test/jdk/jshell

@ -97,8 +97,8 @@ import static java.util.stream.Collectors.toList;
public class JShellTool { public class JShellTool {
private static final Pattern LINEBREAK = Pattern.compile("\\R"); private static final Pattern LINEBREAK = Pattern.compile("\\R");
private static final Pattern HISTORY_ALL_FILENAME = Pattern.compile( private static final Pattern HISTORY_ALL_START_FILENAME = Pattern.compile(
"((?<cmd>(all|history))(\\z|\\p{javaWhitespace}+))?(?<filename>.*)"); "((?<cmd>(all|history|start))(\\z|\\p{javaWhitespace}+))?(?<filename>.*)");
final InputStream cmdin; final InputStream cmdin;
final PrintStream cmdout; final PrintStream cmdout;
@ -504,15 +504,30 @@ public class JShellTool {
arg = cmd.substring(idx + 1).trim(); arg = cmd.substring(idx + 1).trim();
cmd = cmd.substring(0, idx); cmd = cmd.substring(0, idx);
} }
Command command = commands.get(cmd); Command[] candidates = findCommand(cmd, c -> c.kind != CommandKind.HELP_ONLY);
if (command == null || command.kind == CommandKind.HELP_ONLY) { if (candidates.length == 0) {
hard("No such command: %s", cmd); hard("No such command: %s", cmd);
fluff("Type /help for help."); fluff("Type /help for help.");
} else if (candidates.length == 1) {
candidates[0].run.accept(arg);
} else { } else {
command.run.accept(arg); hard("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", ")));
fluff("Type /help for help.");
} }
} }
private Command[] findCommand(String cmd, Predicate<Command> filter) {
Command exact = commands.get(cmd);
if (exact != null)
return new Command[] {exact};
return commands.values()
.stream()
.filter(filter)
.filter(command -> command.command.startsWith(cmd))
.toArray(size -> new Command[size]);
}
private static Path toPathResolvingUserHome(String pathString) { private static Path toPathResolvingUserHome(String pathString) {
if (pathString.replace(File.separatorChar, '/').startsWith("~/")) if (pathString.replace(File.separatorChar, '/').startsWith("~/"))
return Paths.get(System.getProperty("user.home"), pathString.substring(2)); return Paths.get(System.getProperty("user.home"), pathString.substring(2));
@ -521,19 +536,19 @@ public class JShellTool {
} }
static final class Command { static final class Command {
public final String[] aliases; public final String command;
public final String params; public final String params;
public final String description; public final String description;
public final Consumer<String> run; public final Consumer<String> run;
public final CompletionProvider completions; public final CompletionProvider completions;
public final CommandKind kind; public final CommandKind kind;
public Command(String command, String alias, String params, String description, Consumer<String> run, CompletionProvider completions) { public Command(String command, String params, String description, Consumer<String> run, CompletionProvider completions) {
this(command, alias, params, description, run, completions, CommandKind.NORMAL); this(command, params, description, run, completions, CommandKind.NORMAL);
} }
public Command(String command, String alias, String params, String description, Consumer<String> run, CompletionProvider completions, CommandKind kind) { public Command(String command, String params, String description, Consumer<String> run, CompletionProvider completions, CommandKind kind) {
this.aliases = alias != null ? new String[] {command, alias} : new String[] {command}; this.command = command;
this.params = params; this.params = params;
this.description = description; this.description = description;
this.run = run; this.run = run;
@ -582,9 +597,7 @@ public class JShellTool {
private static final CompletionProvider FILE_COMPLETION_PROVIDER = fileCompletions(p -> true); private static final CompletionProvider FILE_COMPLETION_PROVIDER = fileCompletions(p -> true);
private final Map<String, Command> commands = new LinkedHashMap<>(); private final Map<String, Command> commands = new LinkedHashMap<>();
private void registerCommand(Command cmd) { private void registerCommand(Command cmd) {
for (String str : cmd.aliases) { commands.put(cmd.command, cmd);
commands.put(str, cmd);
}
} }
private static CompletionProvider fileCompletions(Predicate<Path> accept) { private static CompletionProvider fileCompletions(Predicate<Path> accept) {
return (code, cursor, anchor) -> { return (code, cursor, anchor) -> {
@ -632,7 +645,7 @@ public class JShellTool {
} }
private static CompletionProvider saveCompletion() { private static CompletionProvider saveCompletion() {
CompletionProvider keyCompletion = new FixedCompletionProvider("all ", "history "); CompletionProvider keyCompletion = new FixedCompletionProvider("all ", "history ", "start ");
return (code, cursor, anchor) -> { return (code, cursor, anchor) -> {
List<Suggestion> result = new ArrayList<>(); List<Suggestion> result = new ArrayList<>();
int space = code.indexOf(' '); int space = code.indexOf(' ');
@ -648,75 +661,78 @@ public class JShellTool {
// Table of commands -- with command forms, argument kinds, help message, implementation, ... // Table of commands -- with command forms, argument kinds, help message, implementation, ...
{ {
registerCommand(new Command("/list", "/l", "[all]", "list the source you have typed", registerCommand(new Command("/list", "[all]", "list the source you have typed",
arg -> cmdList(arg), arg -> cmdList(arg),
new FixedCompletionProvider("all"))); new FixedCompletionProvider("all")));
registerCommand(new Command("/seteditor", null, "<executable>", "set the external editor command to use", registerCommand(new Command("/seteditor", "<executable>", "set the external editor command to use",
arg -> cmdSetEditor(arg), arg -> cmdSetEditor(arg),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/edit", "/e", "<name or id>", "edit a source entry referenced by name or id", registerCommand(new Command("/edit", "<name or id>", "edit a source entry referenced by name or id",
arg -> cmdEdit(arg), arg -> cmdEdit(arg),
editCompletion())); editCompletion()));
registerCommand(new Command("/drop", "/d", "<name or id>", "delete a source entry referenced by name or id", registerCommand(new Command("/drop", "<name or id>", "delete a source entry referenced by name or id",
arg -> cmdDrop(arg), arg -> cmdDrop(arg),
editCompletion())); editCompletion()));
registerCommand(new Command("/save", "/s", "[all|history] <file>", "save the source you have typed", registerCommand(new Command("/save", "[all|history|start] <file>", "save: <none> - current source;\n" +
" all - source including overwritten, failed, and start-up code;\n" +
" history - editing history;\n" +
" start - default start-up definitions",
arg -> cmdSave(arg), arg -> cmdSave(arg),
saveCompletion())); saveCompletion()));
registerCommand(new Command("/open", "/o", "<file>", "open a file as source input", registerCommand(new Command("/open", "<file>", "open a file as source input",
arg -> cmdOpen(arg), arg -> cmdOpen(arg),
FILE_COMPLETION_PROVIDER)); FILE_COMPLETION_PROVIDER));
registerCommand(new Command("/vars", "/v", null, "list the declared variables and their values", registerCommand(new Command("/vars", null, "list the declared variables and their values",
arg -> cmdVars(), arg -> cmdVars(),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/methods", "/m", null, "list the declared methods and their signatures", registerCommand(new Command("/methods", null, "list the declared methods and their signatures",
arg -> cmdMethods(), arg -> cmdMethods(),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/classes", "/c", null, "list the declared classes", registerCommand(new Command("/classes", null, "list the declared classes",
arg -> cmdClasses(), arg -> cmdClasses(),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/imports", "/i", null, "list the imported items", registerCommand(new Command("/imports", null, "list the imported items",
arg -> cmdImports(), arg -> cmdImports(),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/exit", "/x", null, "exit the REPL", registerCommand(new Command("/exit", null, "exit the REPL",
arg -> cmdExit(), arg -> cmdExit(),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/reset", "/r", null, "reset everything in the REPL", registerCommand(new Command("/reset", null, "reset everything in the REPL",
arg -> cmdReset(), arg -> cmdReset(),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/feedback", "/f", "<level>", "feedback information: off, concise, normal, verbose, default, or ?", registerCommand(new Command("/feedback", "<level>", "feedback information: off, concise, normal, verbose, default, or ?",
arg -> cmdFeedback(arg), arg -> cmdFeedback(arg),
new FixedCompletionProvider("off", "concise", "normal", "verbose", "default", "?"))); new FixedCompletionProvider("off", "concise", "normal", "verbose", "default", "?")));
registerCommand(new Command("/prompt", "/p", null, "toggle display of a prompt", registerCommand(new Command("/prompt", null, "toggle display of a prompt",
arg -> cmdPrompt(), arg -> cmdPrompt(),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/classpath", "/cp", "<path>", "add a path to the classpath", registerCommand(new Command("/classpath", "<path>", "add a path to the classpath",
arg -> cmdClasspath(arg), arg -> cmdClasspath(arg),
classPathCompletion())); classPathCompletion()));
registerCommand(new Command("/history", "/h", null, "history of what you have typed", registerCommand(new Command("/history", null, "history of what you have typed",
arg -> cmdHistory(), arg -> cmdHistory(),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/setstart", null, "<file>", "read file and set as the new start-up definitions", registerCommand(new Command("/setstart", "<file>", "read file and set as the new start-up definitions",
arg -> cmdSetStart(arg), arg -> cmdSetStart(arg),
FILE_COMPLETION_PROVIDER)); FILE_COMPLETION_PROVIDER));
registerCommand(new Command("/savestart", null, "<file>", "save the default start-up definitions to the file", registerCommand(new Command("/debug", "", "toggle debugging of the REPL",
arg -> cmdSaveStart(arg),
FILE_COMPLETION_PROVIDER));
registerCommand(new Command("/debug", "/db", "", "toggle debugging of the REPL",
arg -> cmdDebug(arg), arg -> cmdDebug(arg),
EMPTY_COMPLETION_PROVIDER, EMPTY_COMPLETION_PROVIDER,
CommandKind.HIDDEN)); CommandKind.HIDDEN));
registerCommand(new Command("/help", "/?", "", "this help message", registerCommand(new Command("/help", "", "this help message",
arg -> cmdHelp(), arg -> cmdHelp(),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/!", null, "", "re-run last snippet", registerCommand(new Command("/?", "", "this help message",
arg -> cmdHelp(),
EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/!", "", "re-run last snippet",
arg -> cmdUseHistoryEntry(-1), arg -> cmdUseHistoryEntry(-1),
EMPTY_COMPLETION_PROVIDER)); EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/<n>", null, "", "re-run n-th snippet", registerCommand(new Command("/<n>", "", "re-run n-th snippet",
arg -> { throw new IllegalStateException(); }, arg -> { throw new IllegalStateException(); },
EMPTY_COMPLETION_PROVIDER, EMPTY_COMPLETION_PROVIDER,
CommandKind.HELP_ONLY)); CommandKind.HELP_ONLY));
registerCommand(new Command("/-<n>", null, "", "re-run n-th previous snippet", registerCommand(new Command("/-<n>", "", "re-run n-th previous snippet",
arg -> { throw new IllegalStateException(); }, arg -> { throw new IllegalStateException(); },
EMPTY_COMPLETION_PROVIDER, EMPTY_COMPLETION_PROVIDER,
CommandKind.HELP_ONLY)); CommandKind.HELP_ONLY));
@ -732,16 +748,16 @@ public class JShellTool {
.stream() .stream()
.distinct() .distinct()
.filter(cmd -> cmd.kind != CommandKind.HIDDEN && cmd.kind != CommandKind.HELP_ONLY) .filter(cmd -> cmd.kind != CommandKind.HIDDEN && cmd.kind != CommandKind.HELP_ONLY)
.map(cmd -> cmd.aliases[0]) .map(cmd -> cmd.command)
.filter(key -> key.startsWith(prefix)) .filter(key -> key.startsWith(prefix))
.map(key -> new Suggestion(key + " ", false)); .map(key -> new Suggestion(key + " ", false));
anchor[0] = 0; anchor[0] = 0;
} else { } else {
String arg = prefix.substring(space + 1); String arg = prefix.substring(space + 1);
String cmd = prefix.substring(0, space); String cmd = prefix.substring(0, space);
Command command = commands.get(cmd); Command[] candidates = findCommand(cmd, c -> true);
if (command != null) { if (candidates.length == 1) {
result = command.completions.completionSuggestions(arg, cursor - space, anchor).stream(); result = candidates[0].completions.completionSuggestions(arg, cursor - space, anchor).stream();
anchor[0] += space + 1; anchor[0] += space + 1;
} else { } else {
result = Stream.empty(); result = Stream.empty();
@ -885,12 +901,7 @@ public class JShellTool {
if (cmd.kind == CommandKind.HIDDEN) if (cmd.kind == CommandKind.HIDDEN)
continue; continue;
StringBuilder synopsis = new StringBuilder(); StringBuilder synopsis = new StringBuilder();
if (cmd.aliases.length > 1) { synopsis.append(cmd.command);
synopsis.append(String.format("%-3s or ", cmd.aliases[1]));
} else {
synopsis.append(" ");
}
synopsis.append(cmd.aliases[0]);
if (cmd.params != null) if (cmd.params != null)
synopsis.append(" ").append(cmd.params); synopsis.append(" ").append(cmd.params);
synopsis2Description.put(synopsis.toString(), cmd.description); synopsis2Description.put(synopsis.toString(), cmd.description);
@ -901,7 +912,9 @@ public class JShellTool {
for (Entry<String, String> e : synopsis2Description.entrySet()) { for (Entry<String, String> e : synopsis2Description.entrySet()) {
cmdout.print(String.format("%-" + synopsisLen + "s", e.getKey())); cmdout.print(String.format("%-" + synopsisLen + "s", e.getKey()));
cmdout.print(" -- "); cmdout.print(" -- ");
cmdout.println(e.getValue()); String indentedNewLine = System.getProperty("line.separator") +
String.format("%-" + (synopsisLen + 4) + "s", "");
cmdout.println(e.getValue().replace("\n", indentedNewLine));
} }
cmdout.println(); cmdout.println();
cmdout.println("Supported shortcuts include:"); cmdout.println("Supported shortcuts include:");
@ -1141,13 +1154,14 @@ public class JShellTool {
} }
private void cmdSave(String arg_filename) { private void cmdSave(String arg_filename) {
Matcher mat = HISTORY_ALL_FILENAME.matcher(arg_filename); Matcher mat = HISTORY_ALL_START_FILENAME.matcher(arg_filename);
if (!mat.find()) { if (!mat.find()) {
hard("Malformed argument to the /save command: %s", arg_filename); hard("Malformed argument to the /save command: %s", arg_filename);
return; return;
} }
boolean useHistory = false; boolean useHistory = false;
boolean saveAll = false; boolean saveAll = false;
boolean saveStart = false;
String cmd = mat.group("cmd"); String cmd = mat.group("cmd");
if (cmd != null) switch (cmd) { if (cmd != null) switch (cmd) {
case "all": case "all":
@ -1156,6 +1170,9 @@ public class JShellTool {
case "history": case "history":
useHistory = true; useHistory = true;
break; break;
case "start":
saveStart = true;
break;
} }
String filename = mat.group("filename"); String filename = mat.group("filename");
if (filename == null ||filename.isEmpty()) { if (filename == null ||filename.isEmpty()) {
@ -1170,6 +1187,8 @@ public class JShellTool {
writer.write(s); writer.write(s);
writer.write("\n"); writer.write("\n");
} }
} else if (saveStart) {
writer.append(DEFAULT_STARTUP);
} else { } else {
for (Snippet sn : state.snippets()) { for (Snippet sn : state.snippets()) {
if (saveAll || notInStartUp(sn)) { if (saveAll || notInStartUp(sn)) {
@ -1203,22 +1222,6 @@ public class JShellTool {
} }
} }
private void cmdSaveStart(String filename) {
if (filename.isEmpty()) {
hard("The /savestart command requires a filename argument.");
} else {
try {
Files.write(toPathResolvingUserHome(filename), DEFAULT_STARTUP.getBytes());
} catch (AccessDeniedException e) {
hard("File '%s' for /savestart is not accessible.", filename);
} catch (NoSuchFileException e) {
hard("File '%s' for /savestart cannot be located.", filename);
} catch (Exception e) {
hard("Exception while saving default startup file: %s", e);
}
}
}
private void cmdVars() { private void cmdVars() {
for (VarSnippet vk : state.variables()) { for (VarSnippet vk : state.variables()) {
String val = state.status(vk) == Status.VALID String val = state.status(vk) == Status.VALID

@ -100,9 +100,9 @@ public class CommandCompletionTest extends ReplToolTesting {
public void testSave() throws IOException { public void testSave() throws IOException {
Compiler compiler = new Compiler(); Compiler compiler = new Compiler();
assertCompletion("/s|", false, "/save ", "/savestart ", "/seteditor ", "/setstart "); assertCompletion("/s|", false, "/save ", "/seteditor ", "/setstart ");
List<String> p1 = listFiles(Paths.get("")); List<String> p1 = listFiles(Paths.get(""));
Collections.addAll(p1, "all ", "history "); Collections.addAll(p1, "all ", "history ", "start ");
FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString())); FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString()));
Collections.sort(p1); Collections.sort(p1);
assertCompletion("/save |", false, p1.toArray(new String[p1.size()])); assertCompletion("/save |", false, p1.toArray(new String[p1.size()]));

@ -23,6 +23,7 @@
/* /*
* @test * @test
* @bug 8143037
* @summary Tests for Basic tests for REPL tool * @summary Tests for Basic tests for REPL tool
* @ignore 8139873 * @ignore 8139873
* @library /tools/lib * @library /tools/lib
@ -124,28 +125,28 @@ public class ToolBasicTest extends ReplToolTesting {
interrupt, interrupt,
(a) -> assertCommand(a, "int a\u0003", ""), (a) -> assertCommand(a, "int a\u0003", ""),
(a) -> assertCommand(a, "int a = 2 + 2\u0003", ""), (a) -> assertCommand(a, "int a = 2 + 2\u0003", ""),
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> evaluateExpression(a, "int", "2", "2"), (a) -> evaluateExpression(a, "int", "2", "2"),
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> assertCommand(a, "void f() {", ""), (a) -> assertCommand(a, "void f() {", ""),
(a) -> assertCommand(a, "int q = 10;" + s, ""), (a) -> assertCommand(a, "int q = 10;" + s, ""),
interrupt, interrupt,
(a) -> assertCommand(a, "void f() {}\u0003", ""), (a) -> assertCommand(a, "void f() {}\u0003", ""),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertMethod(a, "int f() { return 0; }", "()int", "f"), (a) -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertCommand(a, "class A {" + s, ""), (a) -> assertCommand(a, "class A {" + s, ""),
interrupt, interrupt,
(a) -> assertCommand(a, "class A {}\u0003", ""), (a) -> assertCommand(a, "class A {}\u0003", ""),
(a) -> assertCommandCheckOutput(a, "/c", assertClasses()), (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
(a) -> assertClass(a, "interface A {}", "interface", "A"), (a) -> assertClass(a, "interface A {}", "interface", "A"),
(a) -> assertCommandCheckOutput(a, "/c", assertClasses()), (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
(a) -> assertCommand(a, "import java.util.stream." + s, ""), (a) -> assertCommand(a, "import java.util.stream." + s, ""),
interrupt, interrupt,
(a) -> assertCommand(a, "import java.util.stream.\u0003", ""), (a) -> assertCommand(a, "import java.util.stream.\u0003", ""),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
(a) -> assertImport(a, "import java.util.stream.Stream", "", "java.util.stream.Stream"), (a) -> assertImport(a, "import java.util.stream.Stream", "", "java.util.stream.Stream"),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()) (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
); );
} }
} }
@ -265,10 +266,10 @@ public class ToolBasicTest extends ReplToolTesting {
public void testDebug() { public void testDebug() {
test( test(
(a) -> assertCommand(a, "/db", "| Debugging on\n"), (a) -> assertCommand(a, "/deb", "| Debugging on\n"),
(a) -> assertCommand(a, "/debug", "| Debugging off\n"), (a) -> assertCommand(a, "/debug", "| Debugging off\n"),
(a) -> assertCommand(a, "/debug", "| Debugging on\n"), (a) -> assertCommand(a, "/debug", "| Debugging on\n"),
(a) -> assertCommand(a, "/db", "| Debugging off\n") (a) -> assertCommand(a, "/deb", "| Debugging off\n")
); );
} }
@ -295,106 +296,70 @@ public class ToolBasicTest extends ReplToolTesting {
public void defineVariables() { public void defineVariables() {
test( test(
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()),
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> assertVariable(a, "int", "a"), (a) -> assertVariable(a, "int", "a"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()),
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> assertVariable(a, "double", "a", "1", "1.0"), (a) -> assertVariable(a, "double", "a", "1", "1.0"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()),
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> evaluateExpression(a, "double", "2 * a", "2.0"), (a) -> evaluateExpression(a, "double", "2 * a", "2.0"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()),
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()) (a) -> assertCommandCheckOutput(a, "/vars", assertVariables())
); );
} }
public void defineMethods() { public void defineMethods() {
test( test(
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()),
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertMethod(a, "int f() { return 0; }", "()int", "f"), (a) -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()),
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertMethod(a, "void f(int a) { g(); }", "(int)void", "f"), (a) -> assertMethod(a, "void f(int a) { g(); }", "(int)void", "f"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()),
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertMethod(a, "void g() {}", "()void", "g"), (a) -> assertMethod(a, "void g() {}", "()void", "g"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()),
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()) (a) -> assertCommandCheckOutput(a, "/methods", assertMethods())
); );
} }
public void defineClasses() { public void defineClasses() {
test( test(
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/c", assertClasses()),
(a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
(a) -> assertClass(a, "class A { }", "class", "A"), (a) -> assertClass(a, "class A { }", "class", "A"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/c", assertClasses()),
(a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
(a) -> assertClass(a, "interface A { }", "interface", "A"), (a) -> assertClass(a, "interface A { }", "interface", "A"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/c", assertClasses()),
(a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
(a) -> assertClass(a, "enum A { }", "enum", "A"), (a) -> assertClass(a, "enum A { }", "enum", "A"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/c", assertClasses()),
(a) -> assertCommandCheckOutput(a, "/classes", assertClasses()), (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
(a) -> assertClass(a, "@interface A { }", "@interface", "A"), (a) -> assertClass(a, "@interface A { }", "@interface", "A"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/c", assertClasses()),
(a) -> assertCommandCheckOutput(a, "/classes", assertClasses()) (a) -> assertCommandCheckOutput(a, "/classes", assertClasses())
); );
} }
public void defineImports() { public void defineImports() {
test( test(
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()),
(a) -> assertCommandCheckOutput(a, "/imports", assertImports()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
(a) -> assertImport(a, "import java.util.stream.Stream;", "", "java.util.stream.Stream"), (a) -> assertImport(a, "import java.util.stream.Stream;", "", "java.util.stream.Stream"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()),
(a) -> assertCommandCheckOutput(a, "/imports", assertImports()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
(a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()),
(a) -> assertCommandCheckOutput(a, "/imports", assertImports()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
(a) -> assertImport(a, "import static java.lang.Math.PI;", "static", "java.lang.Math.PI"), (a) -> assertImport(a, "import static java.lang.Math.PI;", "static", "java.lang.Math.PI"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()),
(a) -> assertCommandCheckOutput(a, "/imports", assertImports()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
(a) -> assertImport(a, "import static java.lang.Math.*;", "static", "java.lang.Math.*"), (a) -> assertImport(a, "import static java.lang.Math.*;", "static", "java.lang.Math.*"),
(a) -> assertCommandCheckOutput(a, "/l", assertList()),
(a) -> assertCommandCheckOutput(a, "/list", assertList()), (a) -> assertCommandCheckOutput(a, "/list", assertList()),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()),
(a) -> assertCommandCheckOutput(a, "/imports", assertImports()) (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
); );
} }
@ -405,7 +370,7 @@ public class ToolBasicTest extends ReplToolTesting {
compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }"); compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
Path classpath = compiler.getPath(outDir); Path classpath = compiler.getPath(outDir);
test( test(
(a) -> assertCommand(a, "/cp " + classpath, String.format("| Path %s added to classpath\n", classpath)), (a) -> assertCommand(a, "/classpath " + classpath, String.format("| Path %s added to classpath\n", classpath)),
(a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "\"A\"") (a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "\"A\"")
); );
test(new String[] { "-cp", classpath.toString() }, test(new String[] { "-cp", classpath.toString() },
@ -471,20 +436,20 @@ public class ToolBasicTest extends ReplToolTesting {
public void testReset() { public void testReset() {
test( test(
(a) -> assertReset(a, "/r"), (a) -> assertReset(a, "/r"),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertVariable(a, "int", "x"), (a) -> assertVariable(a, "int", "x"),
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> assertMethod(a, "void f() { }", "()void", "f"), (a) -> assertMethod(a, "void f() { }", "()void", "f"),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertClass(a, "class A { }", "class", "A"), (a) -> assertClass(a, "class A { }", "class", "A"),
(a) -> assertCommandCheckOutput(a, "/c", assertClasses()), (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
(a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()), (a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
(a) -> assertReset(a, "/reset"), (a) -> assertReset(a, "/reset"),
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertCommandCheckOutput(a, "/c", assertClasses()), (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()) (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
); );
} }
@ -508,11 +473,11 @@ public class ToolBasicTest extends ReplToolTesting {
loadClass(a, "class A { public String toString() { return \"A\"; } }", loadClass(a, "class A { public String toString() { return \"A\"; } }",
"class", "A"); "class", "A");
loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*"); loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
assertCommandCheckOutput(a, "/c", assertClasses()); assertCommandCheckOutput(a, "/classes", assertClasses());
}, },
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()) (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
); );
Path unknown = compiler.getPath("UNKNOWN.repl"); Path unknown = compiler.getPath("UNKNOWN.repl");
test( test(
@ -531,15 +496,13 @@ public class ToolBasicTest extends ReplToolTesting {
"int a;", "int a;",
"class A { public String toString() { return \"A\"; } }" "class A { public String toString() { return \"A\"; } }"
); );
for (String s : new String[]{"/s", "/save"}) { test(
test( (a) -> assertVariable(a, "int", "a"),
(a) -> assertVariable(a, "int", "a"), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
(a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), (a) -> assertCommand(a, "/save " + path.toString(), "")
(a) -> assertCommand(a, s + " " + path.toString(), "") );
); assertEquals(Files.readAllLines(path), list);
assertEquals(Files.readAllLines(path), list); {
}
for (String s : new String[]{"/s", "/save"}) {
List<String> output = new ArrayList<>(); List<String> output = new ArrayList<>();
test( test(
(a) -> assertCommand(a, "int a;", null), (a) -> assertCommand(a, "int a;", null),
@ -550,24 +513,22 @@ public class ToolBasicTest extends ReplToolTesting {
.map(str -> str.substring(str.indexOf(':') + 2)) .map(str -> str.substring(str.indexOf(':') + 2))
.filter(str -> !str.startsWith("/")) .filter(str -> !str.startsWith("/"))
.collect(Collectors.toList()))), .collect(Collectors.toList()))),
(a) -> assertCommand(a, s + " all " + path.toString(), "") (a) -> assertCommand(a, "/save all " + path.toString(), "")
); );
assertEquals(Files.readAllLines(path), output); assertEquals(Files.readAllLines(path), output);
} }
for (String s : new String[]{"/s", "/save"}) { List<String> output = new ArrayList<>();
List<String> output = new ArrayList<>(); test(
test( (a) -> assertVariable(a, "int", "a"),
(a) -> assertVariable(a, "int", "a"), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
(a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), (a) -> assertCommandCheckOutput(a, "/history", (out) ->
(a) -> assertCommandCheckOutput(a, "/h", (out) -> output.addAll(Stream.of(out.split("\n"))
output.addAll(Stream.of(out.split("\n")) .filter(str -> !str.isEmpty())
.filter(str -> !str.isEmpty()) .collect(Collectors.toList()))),
.collect(Collectors.toList()))), (a) -> assertCommand(a, "/save history " + path.toString(), "")
(a) -> assertCommand(a, s + " history " + path.toString(), "") );
); output.add("/save history " + path.toString());
output.add(s + " history " + path.toString()); assertEquals(Files.readAllLines(path), output);
assertEquals(Files.readAllLines(path), output);
}
} }
public void testStartSet() throws BackingStoreException { public void testStartSet() throws BackingStoreException {
@ -579,7 +540,7 @@ public class ToolBasicTest extends ReplToolTesting {
(a) -> assertVariable(a, "double", "b", "10", "10.0"), (a) -> assertVariable(a, "double", "b", "10", "10.0"),
(a) -> assertMethod(a, "void f() {}", "()V", "f"), (a) -> assertMethod(a, "void f() {}", "()V", "f"),
(a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
(a) -> assertCommand(a, "/s " + startUpFile.toString(), null), (a) -> assertCommand(a, "/save " + startUpFile.toString(), null),
(a) -> assertCommand(a, "/setstart " + startUpFile.toString(), null) (a) -> assertCommand(a, "/setstart " + startUpFile.toString(), null)
); );
Path unknown = compiler.getPath("UNKNOWN"); Path unknown = compiler.getPath("UNKNOWN");
@ -593,11 +554,11 @@ public class ToolBasicTest extends ReplToolTesting {
loadVariable(a, "double", "b", "10.0", "10.0"); loadVariable(a, "double", "b", "10.0", "10.0");
loadMethod(a, "void f() {}", "()void", "f"); loadMethod(a, "void f() {}", "()void", "f");
loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*"); loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
assertCommandCheckOutput(a, "/c", assertClasses()); assertCommandCheckOutput(a, "/classes", assertClasses());
}, },
(a) -> assertCommandCheckOutput(a, "/v", assertVariables()), (a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> assertCommandCheckOutput(a, "/m", assertMethods()), (a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertCommandCheckOutput(a, "/i", assertImports()) (a) -> assertCommandCheckOutput(a, "/imports", assertImports())
); );
} finally { } finally {
removeStartup(); removeStartup();
@ -618,24 +579,14 @@ public class ToolBasicTest extends ReplToolTesting {
} }
public void testEmptyClassPath() { public void testEmptyClassPath() {
String[] commands = {"/cp", "/classpath"}; test(after -> assertCommand(after, "/classpath", "| /classpath requires a path argument\n"));
test(Stream.of(commands)
.map(cmd -> (ReplTest) after -> assertCommand(after, cmd, "| /classpath requires a path argument\n"))
.toArray(ReplTest[]::new));
} }
public void testNoArgument() { public void testNoArgument() {
String[] commands = {"/s", "/save", "/o", "/open", "/setstart", "/savestart"}; String[] commands = {"/save", "/open", "/setstart"};
test(Stream.of(commands) test(Stream.of(commands)
.map(cmd -> { .map(cmd -> {
String c = cmd; String c = cmd;
if ("/s".equals(cmd)) {
c = "/save";
}
if ("/o".equals(cmd)) {
c = "/open";
}
final String finalC = c; final String finalC = c;
return (ReplTest) after -> assertCommand(after, cmd, return (ReplTest) after -> assertCommand(after, cmd,
"| The " + finalC + " command requires a filename argument.\n"); "| The " + finalC + " command requires a filename argument.\n");
@ -646,7 +597,7 @@ public class ToolBasicTest extends ReplToolTesting {
public void testStartSave() throws IOException { public void testStartSave() throws IOException {
Compiler compiler = new Compiler(); Compiler compiler = new Compiler();
Path startSave = compiler.getPath("startSave.txt"); Path startSave = compiler.getPath("startSave.txt");
test(a -> assertCommand(a, "/savestart " + startSave.toString(), null)); test(a -> assertCommand(a, "/save start " + startSave.toString(), null));
List<String> lines = Files.lines(startSave) List<String> lines = Files.lines(startSave)
.filter(s -> !s.isEmpty()) .filter(s -> !s.isEmpty())
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -673,49 +624,42 @@ public class ToolBasicTest extends ReplToolTesting {
public void testRemoteExit() { public void testRemoteExit() {
test( test(
a -> assertVariable(a, "int", "x"), a -> assertVariable(a, "int", "x"),
a -> assertCommandCheckOutput(a, "/v", assertVariables()), a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
a -> assertCommandCheckOutput(a, "System.exit(5);", s -> a -> assertCommandCheckOutput(a, "System.exit(5);", s ->
assertTrue(s.contains("terminated"), s)), assertTrue(s.contains("terminated"), s)),
a -> assertCommandCheckOutput(a, "/v", s -> a -> assertCommandCheckOutput(a, "/vars", s ->
assertTrue(s.trim().isEmpty(), s)), assertTrue(s.trim().isEmpty(), s)),
a -> assertMethod(a, "void f() { }", "()void", "f"), a -> assertMethod(a, "void f() { }", "()void", "f"),
a -> assertCommandCheckOutput(a, "/m", assertMethods()) a -> assertCommandCheckOutput(a, "/methods", assertMethods())
); );
} }
public void testListArgs() { public void testListArgs() {
Consumer<String> assertList = s -> assertTrue(s.split("\n").length >= 7, s); Consumer<String> assertList = s -> assertTrue(s.split("\n").length >= 4, s);
String arg = "qqqq"; String arg = "qqqq";
Consumer<String> assertError = s -> assertEquals(s, "| Invalid /list argument: " + arg + "\n"); Consumer<String> assertError = s -> assertEquals(s, "| Invalid /list argument: " + arg + "\n");
test( test(
a -> assertCommandCheckOutput(a, "/l all", assertList),
a -> assertCommandCheckOutput(a, "/list all", assertList), a -> assertCommandCheckOutput(a, "/list all", assertList),
a -> assertCommandCheckOutput(a, "/l " + arg, assertError),
a -> assertCommandCheckOutput(a, "/list " + arg, assertError), a -> assertCommandCheckOutput(a, "/list " + arg, assertError),
a -> assertVariable(a, "int", "a"), a -> assertVariable(a, "int", "a"),
a -> assertCommandCheckOutput(a, "/l history", assertList),
a -> assertCommandCheckOutput(a, "/list history", assertList) a -> assertCommandCheckOutput(a, "/list history", assertList)
); );
} }
public void testFeedbackNegative() { public void testFeedbackNegative() {
for (String feedback : new String[]{"/f", "/feedback"}) { test(a -> assertCommandCheckOutput(a, "/feedback aaaa",
test(a -> assertCommandCheckOutput(a, feedback + " aaaa", assertStartsWith("| Follow /feedback with of the following")));
assertStartsWith("| Follow /feedback with of the following")));
}
} }
public void testFeedbackOff() { public void testFeedbackOff() {
for (String feedback : new String[]{"/f", "/feedback"}) { for (String off : new String[]{"o", "off"}) {
for (String off : new String[]{"o", "off"}) { test(
test( a -> assertCommand(a, "/feedback " + off, ""),
a -> assertCommand(a, feedback + " " + off, ""), a -> assertCommand(a, "int a", ""),
a -> assertCommand(a, "int a", ""), a -> assertCommand(a, "void f() {}", ""),
a -> assertCommand(a, "void f() {}", ""), a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("| Error:")),
a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("| Error:")), a -> assertCommandCheckOutput(a, "public void f() {}", assertStartsWith("| Warning:"))
a -> assertCommandCheckOutput(a, "public void f() {}", assertStartsWith("| Warning:")) );
);
}
} }
} }
@ -724,17 +668,15 @@ public class ToolBasicTest extends ReplToolTesting {
Path testConciseFile = compiler.getPath("testConciseFeedback"); Path testConciseFile = compiler.getPath("testConciseFeedback");
String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"}; String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"};
compiler.writeToFile(testConciseFile, sources); compiler.writeToFile(testConciseFile, sources);
for (String feedback : new String[]{"/f", "/feedback"}) { for (String concise : new String[]{"c", "concise"}) {
for (String concise : new String[]{"c", "concise"}) { test(
test( a -> assertCommand(a, "/feedback " + concise, ""),
a -> assertCommand(a, feedback + " " + concise, ""), a -> assertCommand(a, sources[0], ""),
a -> assertCommand(a, sources[0], ""), a -> assertCommand(a, sources[1], ""),
a -> assertCommand(a, sources[1], ""), a -> assertCommand(a, sources[2], ""),
a -> assertCommand(a, sources[2], ""), a -> assertCommand(a, sources[3], "| a : 10\n"),
a -> assertCommand(a, sources[3], "| a : 10\n"), a -> assertCommand(a, "/o " + testConciseFile.toString(), "| a : 10\n")
a -> assertCommand(a, "/o " + testConciseFile.toString(), "| a : 10\n") );
);
}
} }
} }
@ -788,65 +730,59 @@ public class ToolBasicTest extends ReplToolTesting {
"| Variable a has been assigned the value 10\n" "| Variable a has been assigned the value 10\n"
}; };
compiler.writeToFile(testDefaultFile, sources); compiler.writeToFile(testDefaultFile, sources);
for (String feedback : new String[]{"/f", "/feedback"}) { for (String defaultFeedback : new String[]{"", "d", "default"}) {
for (String defaultFeedback : new String[]{"", "d", "default"}) { test(
test( a -> assertCommand(a, "/feedback o", ""),
a -> assertCommand(a, "/f o", ""), a -> assertCommand(a, "int x", ""),
a -> assertCommand(a, "int x", ""), a -> assertCommand(a, "/feedback " + defaultFeedback, "| Feedback mode: default\n"),
a -> assertCommand(a, feedback + " " + defaultFeedback, "| Feedback mode: default\n"), a -> assertCommand(a, sources[0], output[0]),
a -> assertCommand(a, sources[0], output[0]), a -> assertCommand(a, sources[1], output[1]),
a -> assertCommand(a, sources[1], output[1]), a -> assertCommand(a, sources[2], output[2]),
a -> assertCommand(a, sources[2], output[2]), a -> assertCommand(a, sources[3], output[3]),
a -> assertCommand(a, sources[3], output[3]), a -> assertCommand(a, "/o " + testDefaultFile.toString(), "")
a -> assertCommand(a, "/o " + testDefaultFile.toString(), "") );
);
}
} }
} }
public void testDrop() { public void testDrop() {
for (String drop : new String[]{"/d", "/drop"}) { test(false, new String[]{"-nostartup"},
test(false, new String[]{"-nostartup"}, a -> assertVariable(a, "int", "a"),
a -> assertVariable(a, "int", "a"), a -> dropVariable(a, "/drop 1", "int a = 0"),
a -> dropVariable(a, drop + " 1", "int a = 0"), a -> assertMethod(a, "int b() { return 0; }", "()I", "b"),
a -> assertMethod(a, "int b() { return 0; }", "()I", "b"), a -> dropMethod(a, "/drop 2", "b ()I"),
a -> dropMethod(a, drop + " 2", "b ()I"), a -> assertClass(a, "class A {}", "class", "A"),
a -> assertClass(a, "class A {}", "class", "A"), a -> dropClass(a, "/drop 3", "class A"),
a -> dropClass(a, drop + " 3", "class A"), a -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
a -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), a -> dropImport(a, "/drop 4", "import java.util.stream.*"),
a -> dropImport(a, drop + " 4", "import java.util.stream.*"), a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
a -> assertCommandCheckOutput(a, "/v", assertVariables()), a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
a -> assertCommandCheckOutput(a, "/m", assertMethods()), a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
a -> assertCommandCheckOutput(a, "/c", assertClasses()), a -> assertCommandCheckOutput(a, "/imports", assertImports())
a -> assertCommandCheckOutput(a, "/i", assertImports()) );
); test(false, new String[]{"-nostartup"},
test(false, new String[]{"-nostartup"}, a -> assertVariable(a, "int", "a"),
a -> assertVariable(a, "int", "a"), a -> dropVariable(a, "/drop a", "int a = 0"),
a -> dropVariable(a, drop + " a", "int a = 0"), a -> assertMethod(a, "int b() { return 0; }", "()I", "b"),
a -> assertMethod(a, "int b() { return 0; }", "()I", "b"), a -> dropMethod(a, "/drop b", "b ()I"),
a -> dropMethod(a, drop + " b", "b ()I"), a -> assertClass(a, "class A {}", "class", "A"),
a -> assertClass(a, "class A {}", "class", "A"), a -> dropClass(a, "/drop A", "class A"),
a -> dropClass(a, drop + " A", "class A"), a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
a -> assertCommandCheckOutput(a, "/v", assertVariables()), a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
a -> assertCommandCheckOutput(a, "/m", assertMethods()), a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
a -> assertCommandCheckOutput(a, "/c", assertClasses()), a -> assertCommandCheckOutput(a, "/imports", assertImports())
a -> assertCommandCheckOutput(a, "/i", assertImports()) );
);
}
} }
public void testDropNegative() { public void testDropNegative() {
for (String drop : new String[]{"/d", "/drop"}) { test(false, new String[]{"-nostartup"},
test(false, new String[]{"-nostartup"}, a -> assertCommand(a, "/drop 0", "| No definition or id named 0 found. See /classes /methods /vars or /list\n"),
a -> assertCommand(a, drop + " 0", "| No definition or id named 0 found. See /classes /methods /vars or /list\n"), a -> assertCommand(a, "/drop a", "| No definition or id named a found. See /classes /methods /vars or /list\n"),
a -> assertCommand(a, drop + " a", "| No definition or id named a found. See /classes /methods /vars or /list\n"), a -> assertCommandCheckOutput(a, "/drop",
a -> assertCommandCheckOutput(a, drop, assertStartsWith("| In the /drop argument, please specify an import, variable, method, or class to drop.")),
assertStartsWith("| In the /drop argument, please specify an import, variable, method, or class to drop.")), a -> assertVariable(a, "int", "a"),
a -> assertVariable(a, "int", "a"), a -> assertCommand(a, "a", "| Variable a of type int has value 0\n"),
a -> assertCommand(a, "a", "| Variable a of type int has value 0\n"), a -> assertCommand(a, "/drop 2", "| The argument did not specify an import, variable, method, or class to drop.\n")
a -> assertCommand(a, drop + " 2", "| The argument did not specify an import, variable, method, or class to drop.\n") );
);
}
} }
public void testAmbiguousDrop() { public void testAmbiguousDrop() {
@ -855,25 +791,23 @@ public class ToolBasicTest extends ReplToolTesting {
int lines = s.split("\n").length; int lines = s.split("\n").length;
assertEquals(lines, 5, "Expected 3 ambiguous keys, but found: " + (lines - 2) + "\n" + s); assertEquals(lines, 5, "Expected 3 ambiguous keys, but found: " + (lines - 2) + "\n" + s);
}; };
for (String drop : new String[]{"/d", "/drop"}) { test(
test( a -> assertVariable(a, "int", "a"),
a -> assertVariable(a, "int", "a"), a -> assertMethod(a, "int a() { return 0; }", "()int", "a"),
a -> assertMethod(a, "int a() { return 0; }", "()int", "a"), a -> assertClass(a, "class a {}", "class", "a"),
a -> assertClass(a, "class a {}", "class", "a"), a -> assertCommandCheckOutput(a, "/drop a", check),
a -> assertCommandCheckOutput(a, drop + " a", check), a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
a -> assertCommandCheckOutput(a, "/v", assertVariables()), a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
a -> assertCommandCheckOutput(a, "/m", assertMethods()), a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
a -> assertCommandCheckOutput(a, "/c", assertClasses()), a -> assertCommandCheckOutput(a, "/imports", assertImports())
a -> assertCommandCheckOutput(a, "/i", assertImports()) );
); test(
test( a -> assertMethod(a, "int a() { return 0; }", "()int", "a"),
a -> assertMethod(a, "int a() { return 0; }", "()int", "a"), a -> assertMethod(a, "double a(int a) { return 0; }", "(int)double", "a"),
a -> assertMethod(a, "double a(int a) { return 0; }", "(int)double", "a"), a -> assertMethod(a, "double a(double a) { return 0; }", "(double)double", "a"),
a -> assertMethod(a, "double a(double a) { return 0; }", "(double)double", "a"), a -> assertCommandCheckOutput(a, "/drop a", check),
a -> assertCommandCheckOutput(a, drop + " a", check), a -> assertCommandCheckOutput(a, "/methods", assertMethods())
a -> assertCommandCheckOutput(a, "/m", assertMethods()) );
);
}
} }
public void testHistoryReference() { public void testHistoryReference() {
@ -893,4 +827,14 @@ public class ToolBasicTest extends ReplToolTesting {
a -> assertCommand(a, "/1", "System.err.println(1)\n", "", null, "", "1\n") a -> assertCommand(a, "/1", "System.err.println(1)\n", "", null, "", "1\n")
); );
} }
public void testCommandPrefix() {
test(a -> assertCommandCheckOutput(a, "/s",
assertStartsWith("| Command: /s is ambiguous: /seteditor, /save, /setstart")),
a -> assertCommand(a, "int var", "| Added variable var of type int\n"),
a -> assertCommandCheckOutput(a, "/va",
assertStartsWith("| int var = 0")),
a -> assertCommandCheckOutput(a, "/save",
assertStartsWith("| The /save command requires a filename argument.")));
}
} }