8151755: jshell tool: properly cover resolution issues in output configuration
8152246: jshell tool: history overflow Reviewed-by: jlahoda
This commit is contained in:
parent
af5594cf2c
commit
e16d374ab5
File diff suppressed because it is too large
Load Diff
@ -75,7 +75,6 @@ import jdk.jshell.MethodSnippet;
|
||||
import jdk.jshell.PersistentSnippet;
|
||||
import jdk.jshell.Snippet;
|
||||
import jdk.jshell.Snippet.Status;
|
||||
import jdk.jshell.Snippet.SubKind;
|
||||
import jdk.jshell.SnippetEvent;
|
||||
import jdk.jshell.SourceCodeAnalysis;
|
||||
import jdk.jshell.SourceCodeAnalysis.CompletionInfo;
|
||||
@ -95,10 +94,11 @@ import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import jdk.internal.jshell.tool.Feedback.FormatAction;
|
||||
import jdk.internal.jshell.tool.Feedback.FormatCase;
|
||||
import jdk.internal.jshell.tool.Feedback.FormatErrors;
|
||||
import jdk.internal.jshell.tool.Feedback.FormatResolve;
|
||||
import jdk.internal.jshell.tool.Feedback.FormatUnresolved;
|
||||
import jdk.internal.jshell.tool.Feedback.FormatWhen;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static jdk.jshell.Snippet.Kind.METHOD;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND;
|
||||
|
||||
@ -113,6 +113,12 @@ public class JShellTool {
|
||||
private static final Pattern HISTORY_ALL_START_FILENAME = Pattern.compile(
|
||||
"((?<cmd>(all|history|start))(\\z|\\p{javaWhitespace}+))?(?<filename>.*)");
|
||||
private static final String RECORD_SEPARATOR = "\u241E";
|
||||
private static final String RB_NAME_PREFIX = "jdk.internal.jshell.tool.resources";
|
||||
private static final String VERSION_RB_NAME = RB_NAME_PREFIX + ".version";
|
||||
private static final String L10N_RB_NAME = RB_NAME_PREFIX + ".l10n";
|
||||
private static ResourceBundle versionRB = null;
|
||||
private static ResourceBundle outputRB = null;
|
||||
|
||||
|
||||
final InputStream cmdin;
|
||||
final PrintStream cmdout;
|
||||
@ -148,82 +154,18 @@ public class JShellTool {
|
||||
this.userout = userout;
|
||||
this.usererr = usererr;
|
||||
this.prefs = prefs;
|
||||
initializeFeedbackModes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the default set of feedback modes
|
||||
*/
|
||||
final void initializeFeedbackModes() {
|
||||
// Initialize normal feedback mode
|
||||
cmdSet("newmode normal command");
|
||||
cmdSet("prompt normal '\n-> ' '>> '");
|
||||
cmdSet("field normal pre '| '");
|
||||
cmdSet("field normal post '%n'");
|
||||
cmdSet("field normal errorpre '| '");
|
||||
cmdSet("field normal errorpost '%n'");
|
||||
cmdSet("field normal action 'Added' added-primary");
|
||||
cmdSet("field normal action 'Modified' modified-primary");
|
||||
cmdSet("field normal action 'Replaced' replaced-primary");
|
||||
cmdSet("field normal action 'Overwrote' overwrote-primary");
|
||||
cmdSet("field normal action 'Dropped' dropped-primary");
|
||||
cmdSet("field normal action 'Rejected' rejected-primary");
|
||||
cmdSet("field normal action ' Update added' added-update");
|
||||
cmdSet("field normal action ' Update modified' modified-update");
|
||||
cmdSet("field normal action ' Update replaced' replaced-update");
|
||||
cmdSet("field normal action ' Update overwrote' overwrote-update");
|
||||
cmdSet("field normal action ' Update dropped' dropped-update");
|
||||
cmdSet("field normal action ' Update rejected' rejected-update");
|
||||
cmdSet("field normal resolve '' ok-*");
|
||||
cmdSet("field normal resolve ', however, it cannot be invoked until%s is declared' defined-primary");
|
||||
cmdSet("field normal resolve ', however, it cannot be referenced until%s is declared' notdefined-primary");
|
||||
cmdSet("field normal resolve ' which cannot be invoked until%s is declared' defined-update");
|
||||
cmdSet("field normal resolve ' which cannot be referenced until%s is declared' notdefined-update");
|
||||
cmdSet("field normal name '%s'");
|
||||
cmdSet("field normal type '%s'");
|
||||
cmdSet("field normal result '%s'");
|
||||
|
||||
cmdSet("format normal '' *-*-*");
|
||||
|
||||
cmdSet("format normal '{pre}{action} class {name}{resolve}{post}' class");
|
||||
cmdSet("format normal '{pre}{action} interface {name}{resolve}{post}' interface");
|
||||
cmdSet("format normal '{pre}{action} enum {name}{resolve}{post}' enum");
|
||||
cmdSet("format normal '{pre}{action} annotation interface {name}{resolve}{post}' annotation");
|
||||
|
||||
cmdSet("format normal '{pre}{action} method {name}({type}){resolve}{post}' method");
|
||||
|
||||
cmdSet("format normal '{pre}{action} variable {name} of type {type}{resolve}{post}' vardecl");
|
||||
cmdSet("format normal '{pre}{action} variable {name} of type {type} with initial value {result}{resolve}{post}' varinit");
|
||||
cmdSet("format normal '{pre}{action} variable {name}{resolve}{post}' vardeclrecoverable");
|
||||
cmdSet("format normal '{pre}{action} variable {name}, reset to null{post}' varreset-*-update");
|
||||
|
||||
cmdSet("format normal '{pre}Expression value is: {result}{post}" +
|
||||
"{pre} assigned to temporary variable {name} of type {type}{post}' expression");
|
||||
cmdSet("format normal '{pre}Variable {name} of type {type} has value {result}{post}' varvalue");
|
||||
cmdSet("format normal '{pre}Variable {name} has been assigned the value {result}{post}' assignment");
|
||||
|
||||
cmdSet("feedback normal");
|
||||
|
||||
// Initialize off feedback mode
|
||||
cmdSet("newmode off quiet");
|
||||
cmdSet("prompt off '-> ' '>> '");
|
||||
cmdSet("field off pre '| '");
|
||||
cmdSet("field off post '%n'");
|
||||
cmdSet("field off errorpre '| '");
|
||||
cmdSet("field off errorpost '%n'");
|
||||
cmdSet("format off '' *-*-*");
|
||||
}
|
||||
|
||||
private IOContext input = null;
|
||||
private boolean regenerateOnDeath = true;
|
||||
private boolean live = false;
|
||||
private boolean feedbackInitialized = false;
|
||||
|
||||
SourceCodeAnalysis analysis;
|
||||
JShell state = null;
|
||||
Subscription shutdownSubscription = null;
|
||||
|
||||
private boolean debug = false;
|
||||
private boolean displayPrompt = true;
|
||||
public boolean testPrompt = false;
|
||||
private String cmdlineClasspath = null;
|
||||
private String cmdlineStartup = null;
|
||||
@ -326,6 +268,43 @@ public class JShellTool {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print using resource bundle look-up and adding prefix and postfix
|
||||
*
|
||||
* @param key the resource key
|
||||
*/
|
||||
String getResourceString(String key) {
|
||||
if (outputRB == null) {
|
||||
try {
|
||||
outputRB = ResourceBundle.getBundle(L10N_RB_NAME);
|
||||
} catch (MissingResourceException mre) {
|
||||
error("Cannot find ResourceBundle: %s", L10N_RB_NAME);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
String s;
|
||||
try {
|
||||
s = outputRB.getString(key);
|
||||
} catch (MissingResourceException mre) {
|
||||
error("Missing resource: %s in %s", key, L10N_RB_NAME);
|
||||
return "";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print using resource bundle look-up and adding prefix and postfix
|
||||
*
|
||||
* @param key the resource key
|
||||
*/
|
||||
void hardrb(String key) {
|
||||
String s = getResourceString(key);
|
||||
String out = feedback.getPre()
|
||||
+ s.substring(0, s.length() - 1).replaceAll("\\R", "\n" + feedback.getPre())
|
||||
+ s.substring(s.length() - 1, s.length());
|
||||
cmdout.print(out);
|
||||
}
|
||||
|
||||
<T> void hardPairs(Stream<T> stream, Function<T, String> a, Function<T, String> b) {
|
||||
Map<String, String> a2b = stream.collect(toMap(a, b,
|
||||
(m1, m2) -> m1,
|
||||
@ -342,26 +321,6 @@ public class JShellTool {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User custom feedback mode only
|
||||
*
|
||||
* @param fcase Event to report
|
||||
* @param update Is this an update (rather than primary)
|
||||
* @param fa Action
|
||||
* @param fr Resolution status
|
||||
* @param name Name string
|
||||
* @param type Type string or null
|
||||
* @param result Result value or null
|
||||
* @param unresolved The unresolved symbols
|
||||
*/
|
||||
void custom(FormatCase fcase, boolean update, FormatAction fa, FormatResolve fr,
|
||||
String name, String type, String unresolved, String result) {
|
||||
String format = feedback.getFormat(fcase,
|
||||
(update ? FormatWhen.UPDATE : FormatWhen.PRIMARY), fa, fr,
|
||||
name != null, type != null, result != null);
|
||||
fluffRaw(format, unresolved, name, type, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim whitespace off end of string
|
||||
*
|
||||
@ -544,7 +503,6 @@ public class JShellTool {
|
||||
? currentNameSpace.tid(sn)
|
||||
: errorNamespace.tid(sn))
|
||||
.build();
|
||||
analysis = state.sourceCodeAnalysis();
|
||||
shutdownSubscription = state.onShutdown((JShell deadState) -> {
|
||||
if (deadState == state) {
|
||||
hard("State engine terminated.");
|
||||
@ -552,7 +510,12 @@ public class JShellTool {
|
||||
live = false;
|
||||
}
|
||||
});
|
||||
analysis = state.sourceCodeAnalysis();
|
||||
live = true;
|
||||
if (!feedbackInitialized) {
|
||||
startUpRun(getResourceString("startup.feedback"));
|
||||
feedbackInitialized = true;
|
||||
}
|
||||
|
||||
if (cmdlineClasspath != null) {
|
||||
state.addToClasspath(cmdlineClasspath);
|
||||
@ -568,12 +531,16 @@ public class JShellTool {
|
||||
} else {
|
||||
start = cmdlineStartup;
|
||||
}
|
||||
startUpRun(start);
|
||||
currentNameSpace = mainNamespace;
|
||||
}
|
||||
//where
|
||||
private void startUpRun(String start) {
|
||||
try (IOContext suin = new FileScannerIOContext(new StringReader(start))) {
|
||||
run(suin);
|
||||
} catch (Exception ex) {
|
||||
hard("Unexpected exception reading start-up: %s\n", ex);
|
||||
}
|
||||
currentNameSpace = mainNamespace;
|
||||
}
|
||||
|
||||
private void closeState() {
|
||||
@ -596,7 +563,7 @@ public class JShellTool {
|
||||
String incomplete = "";
|
||||
while (live) {
|
||||
String prompt;
|
||||
if (displayPrompt) {
|
||||
if (currentNameSpace == mainNamespace) {
|
||||
prompt = testPrompt
|
||||
? incomplete.isEmpty()
|
||||
? "\u0005" //ENQ
|
||||
@ -679,21 +646,22 @@ public class JShellTool {
|
||||
cmd = cmd.substring(0, idx);
|
||||
}
|
||||
Command[] candidates = findCommand(cmd, c -> c.kind.isRealCommand);
|
||||
if (candidates.length == 0) {
|
||||
if (!rerunHistoryEntryById(cmd.substring(1))) {
|
||||
error("No such command or snippet id: %s", cmd);
|
||||
switch (candidates.length) {
|
||||
case 0:
|
||||
if (!rerunHistoryEntryById(cmd.substring(1))) {
|
||||
error("No such command or snippet id: %s", cmd);
|
||||
fluff("Type /help for help.");
|
||||
} break;
|
||||
case 1:
|
||||
Command command = candidates[0];
|
||||
// If comand was successful and is of a replayable kind, add it the replayable history
|
||||
if (command.run.apply(arg) && command.kind == CommandKind.REPLAY) {
|
||||
addToReplayHistory((command.command + " " + arg).trim());
|
||||
} break;
|
||||
default:
|
||||
error("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", ")));
|
||||
fluff("Type /help for help.");
|
||||
}
|
||||
} else if (candidates.length == 1) {
|
||||
Command command = candidates[0];
|
||||
|
||||
// If comand was successful and is of a replayable kind, add it the replayable history
|
||||
if (command.run.apply(arg) && command.kind == CommandKind.REPLAY) {
|
||||
addToReplayHistory((command.command + " " + arg).trim());
|
||||
}
|
||||
} else {
|
||||
error("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", ")));
|
||||
fluff("Type /help for help.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1022,7 +990,7 @@ public class JShellTool {
|
||||
" -- Display information about the specified help subject. Example: /help intro\n",
|
||||
arg -> cmdHelp(arg),
|
||||
EMPTY_COMPLETION_PROVIDER));
|
||||
registerCommand(new Command("/set", "editor|start|feedback|newmode|prompt|format|field ...", "set jshell configuration information",
|
||||
registerCommand(new Command("/set", "editor|start|feedback|newmode|prompt|format ...", "set jshell configuration information",
|
||||
"Set jshell configuration information, including:\n" +
|
||||
"the external editor to use, the start-up definitions to use, a new feedback mode,\n" +
|
||||
"the command prompt, the feedback mode to use, or the format of output.\n" +
|
||||
@ -1043,16 +1011,13 @@ public class JShellTool {
|
||||
"/set prompt <mode> \"<prompt>\" \"<continuation-prompt>\"\n" +
|
||||
" -- Set the displayed prompts for a given feedback mode.\n" +
|
||||
"\n" +
|
||||
"/set format <mode> \"<format>\" <selector>...\n" +
|
||||
" -- Configure a feedback mode by setting the format to use in a specified set of cases.\n" +
|
||||
"\n" +
|
||||
"/set field name|type|result|when|action|resolve|pre|post|errorpre|errorpost \"<format>\" <format-case>...\n" +
|
||||
" -- Set the format of a field within the <format-string> of a \"/set format\" command\n" +
|
||||
"/set format <mode> <field> \"<format>\" <selector>...\n" +
|
||||
" -- Configure a feedback mode by setting the format of a field when the selector matchs.\n" +
|
||||
"\n" +
|
||||
"To get more information about one of these forms, use /help with the form specified.\n" +
|
||||
"For example: /help /set format\n",
|
||||
arg -> cmdSet(arg),
|
||||
new FixedCompletionProvider("format", "field", "feedback", "prompt", "newmode", "start", "editor")));
|
||||
new FixedCompletionProvider("format", "feedback", "prompt", "newmode", "start", "editor")));
|
||||
registerCommand(new Command("/?", "", "get information about jshell",
|
||||
"Display information about jshell (abbreviation for /help).\n" +
|
||||
"/?\n" +
|
||||
@ -1153,11 +1118,9 @@ public class JShellTool {
|
||||
|
||||
// --- Command implementations ---
|
||||
|
||||
private static final String[] setSub = new String[]{
|
||||
"format", "field", "feedback", "newmode", "prompt", "editor", "start"};
|
||||
private static final String[] SET_SUBCOMMANDS = new String[]{
|
||||
"format", "feedback", "newmode", "prompt", "editor", "start"};
|
||||
|
||||
// The /set command. Currently /set format, /set field and /set feedback.
|
||||
// Other commands will fold here, see: 8148317
|
||||
final boolean cmdSet(String arg) {
|
||||
ArgTokenizer at = new ArgTokenizer(arg.trim());
|
||||
String which = setSubCommand(at);
|
||||
@ -1167,8 +1130,6 @@ public class JShellTool {
|
||||
switch (which) {
|
||||
case "format":
|
||||
return feedback.setFormat(this, at);
|
||||
case "field":
|
||||
return feedback.setField(this, at);
|
||||
case "feedback":
|
||||
return feedback.setFeedback(this, at);
|
||||
case "newmode":
|
||||
@ -1229,9 +1190,6 @@ public class JShellTool {
|
||||
case "format":
|
||||
feedback.printFormatHelp(this);
|
||||
return true;
|
||||
case "field":
|
||||
feedback.printFieldHelp(this);
|
||||
return true;
|
||||
case "feedback":
|
||||
feedback.printFeedbackHelp(this);
|
||||
return true;
|
||||
@ -1265,13 +1223,13 @@ public class JShellTool {
|
||||
}
|
||||
|
||||
String setSubCommand(ArgTokenizer at) {
|
||||
String[] matches = at.next(setSub);
|
||||
String[] matches = at.next(SET_SUBCOMMANDS);
|
||||
if (matches == null) {
|
||||
error("The /set command requires arguments. See: /help /set");
|
||||
return null;
|
||||
} else if (matches.length == 0) {
|
||||
error("Not a valid argument to /set: %s", at.val());
|
||||
fluff("/set is followed by one of: %s", Arrays.stream(setSub)
|
||||
fluff("/set is followed by one of: %s", Arrays.stream(SET_SUBCOMMANDS)
|
||||
.collect(Collectors.joining(", "))
|
||||
);
|
||||
return null;
|
||||
@ -1349,8 +1307,20 @@ public class JShellTool {
|
||||
regenerateOnDeath = false;
|
||||
live = false;
|
||||
if (!replayableHistory.isEmpty()) {
|
||||
prefs.put(REPLAY_RESTORE_KEY, replayableHistory.stream().reduce(
|
||||
(a, b) -> a + RECORD_SEPARATOR + b).get());
|
||||
// Prevent history overflow by calculating what will fit, starting
|
||||
// with must recent
|
||||
int sepLen = RECORD_SEPARATOR.length();
|
||||
int length = 0;
|
||||
int first = replayableHistory.size();
|
||||
while(length < Preferences.MAX_VALUE_LENGTH && --first >= 0) {
|
||||
length += replayableHistory.get(first).length() + sepLen;
|
||||
}
|
||||
String hist = replayableHistory
|
||||
.subList(first + 1, replayableHistory.size())
|
||||
.stream()
|
||||
.reduce( (a, b) -> a + RECORD_SEPARATOR + b)
|
||||
.get();
|
||||
prefs.put(REPLAY_RESTORE_KEY, hist);
|
||||
}
|
||||
fluff("Goodbye\n");
|
||||
return true;
|
||||
@ -1841,68 +1811,55 @@ public class JShellTool {
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
void printDiagnostics(String source, List<Diag> diagnostics, boolean embed) {
|
||||
String padding = embed? " " : "";
|
||||
for (Diag diag : diagnostics) {
|
||||
//assert diag.getSource().equals(source);
|
||||
|
||||
if (!embed) {
|
||||
if (diag.isError()) {
|
||||
hard("Error:");
|
||||
} else {
|
||||
hard("Warning:");
|
||||
}
|
||||
void displayDiagnostics(String source, Diag diag, List<String> toDisplay) {
|
||||
for (String line : diag.getMessage(null).split("\\r?\\n")) { // TODO: Internationalize
|
||||
if (!line.trim().startsWith("location:")) {
|
||||
toDisplay.add(line);
|
||||
}
|
||||
|
||||
for (String line : diag.getMessage(null).split("\\r?\\n")) { // TODO: Internationalize
|
||||
if (!line.trim().startsWith("location:")) {
|
||||
hard("%s%s", padding, line);
|
||||
}
|
||||
}
|
||||
|
||||
int pstart = (int) diag.getStartPosition();
|
||||
int pend = (int) diag.getEndPosition();
|
||||
Matcher m = LINEBREAK.matcher(source);
|
||||
int pstartl = 0;
|
||||
int pendl = -2;
|
||||
while (m.find(pstartl)) {
|
||||
pendl = m.start();
|
||||
if (pendl >= pstart) {
|
||||
break;
|
||||
} else {
|
||||
pstartl = m.end();
|
||||
}
|
||||
}
|
||||
if (pendl < pstart) {
|
||||
pendl = source.length();
|
||||
}
|
||||
fluff("%s%s", padding, source.substring(pstartl, pendl));
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int start = pstart - pstartl;
|
||||
for (int i = 0; i < start; ++i) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append('^');
|
||||
boolean multiline = pend > pendl;
|
||||
int end = (multiline ? pendl : pend) - pstartl - 1;
|
||||
if (end > start) {
|
||||
for (int i = start + 1; i < end; ++i) {
|
||||
sb.append('-');
|
||||
}
|
||||
if (multiline) {
|
||||
sb.append("-...");
|
||||
} else {
|
||||
sb.append('^');
|
||||
}
|
||||
}
|
||||
fluff("%s%s", padding, sb.toString());
|
||||
|
||||
debug("printDiagnostics start-pos = %d ==> %d -- wrap = %s", diag.getStartPosition(), start, this);
|
||||
debug("Code: %s", diag.getCode());
|
||||
debug("Pos: %d (%d - %d)", diag.getPosition(),
|
||||
diag.getStartPosition(), diag.getEndPosition());
|
||||
}
|
||||
|
||||
int pstart = (int) diag.getStartPosition();
|
||||
int pend = (int) diag.getEndPosition();
|
||||
Matcher m = LINEBREAK.matcher(source);
|
||||
int pstartl = 0;
|
||||
int pendl = -2;
|
||||
while (m.find(pstartl)) {
|
||||
pendl = m.start();
|
||||
if (pendl >= pstart) {
|
||||
break;
|
||||
} else {
|
||||
pstartl = m.end();
|
||||
}
|
||||
}
|
||||
if (pendl < pstart) {
|
||||
pendl = source.length();
|
||||
}
|
||||
toDisplay.add(source.substring(pstartl, pendl));
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int start = pstart - pstartl;
|
||||
for (int i = 0; i < start; ++i) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append('^');
|
||||
boolean multiline = pend > pendl;
|
||||
int end = (multiline ? pendl : pend) - pstartl - 1;
|
||||
if (end > start) {
|
||||
for (int i = start + 1; i < end; ++i) {
|
||||
sb.append('-');
|
||||
}
|
||||
if (multiline) {
|
||||
sb.append("-...");
|
||||
} else {
|
||||
sb.append('^');
|
||||
}
|
||||
}
|
||||
toDisplay.add(sb.toString());
|
||||
|
||||
debug("printDiagnostics start-pos = %d ==> %d -- wrap = %s", diag.getStartPosition(), start, this);
|
||||
debug("Code: %s", diag.getCode());
|
||||
debug("Pos: %d (%d - %d)", diag.getPosition(),
|
||||
diag.getStartPosition(), diag.getEndPosition());
|
||||
}
|
||||
|
||||
private String processSource(String srcInput) throws IllegalStateException {
|
||||
@ -1943,6 +1900,7 @@ public class JShellTool {
|
||||
return failed;
|
||||
}
|
||||
|
||||
// Handle incoming snippet events -- return true on failure
|
||||
private boolean handleEvent(SnippetEvent ste) {
|
||||
Snippet sn = ste.snippet();
|
||||
if (sn == null) {
|
||||
@ -1953,162 +1911,49 @@ public class JShellTool {
|
||||
String source = sn.source();
|
||||
if (ste.causeSnippet() == null) {
|
||||
// main event
|
||||
printDiagnostics(source, diagnostics, false);
|
||||
if (ste.status().isActive) {
|
||||
for (Diag d : diagnostics) {
|
||||
if (d.isError()) {
|
||||
hard("Error:");
|
||||
} else {
|
||||
hard("Warning:");
|
||||
}
|
||||
List<String> disp = new ArrayList<>();
|
||||
displayDiagnostics(source, d, disp);
|
||||
disp.stream()
|
||||
.forEach(l -> hard(l));
|
||||
}
|
||||
|
||||
if (ste.status() != Status.REJECTED) {
|
||||
if (ste.exception() != null) {
|
||||
if (ste.exception() instanceof EvalException) {
|
||||
printEvalException((EvalException) ste.exception());
|
||||
return true;
|
||||
} else if (ste.exception() instanceof UnresolvedReferenceException) {
|
||||
printUnresolved((UnresolvedReferenceException) ste.exception());
|
||||
printUnresolvedException((UnresolvedReferenceException) ste.exception());
|
||||
} else {
|
||||
hard("Unexpected execution exception: %s", ste.exception());
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
displayDeclarationAndValue(ste, false, ste.value());
|
||||
new DisplayEvent(ste, false, ste.value(), diagnostics).displayDeclarationAndValue();
|
||||
}
|
||||
} else if (ste.status() == Status.REJECTED) {
|
||||
} else {
|
||||
if (diagnostics.isEmpty()) {
|
||||
hard("Failed.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (ste.status() == Status.REJECTED) {
|
||||
//TODO -- I don't believe updates can cause failures any more
|
||||
hard("Caused failure of dependent %s --", ((DeclarationSnippet) sn).name());
|
||||
printDiagnostics(source, diagnostics, true);
|
||||
} else {
|
||||
// Update
|
||||
if (sn instanceof DeclarationSnippet) {
|
||||
// display update information
|
||||
displayDeclarationAndValue(ste, true, ste.value());
|
||||
|
||||
List<Diag> other = errorsOnly(diagnostics);
|
||||
if (other.size() > 0) {
|
||||
printDiagnostics(source, other, true);
|
||||
}
|
||||
|
||||
// display update information
|
||||
new DisplayEvent(ste, true, ste.value(), other).displayDeclarationAndValue();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
private void displayDeclarationAndValue(SnippetEvent ste, boolean update, String value) {
|
||||
Snippet key = ste.snippet();
|
||||
FormatAction action;
|
||||
Status status = ste.status();
|
||||
switch (status) {
|
||||
case VALID:
|
||||
case RECOVERABLE_DEFINED:
|
||||
case RECOVERABLE_NOT_DEFINED:
|
||||
if (ste.previousStatus().isActive) {
|
||||
action = ste.isSignatureChange()
|
||||
? FormatAction.REPLACED
|
||||
: FormatAction.MODIFIED;
|
||||
} else {
|
||||
action = FormatAction.ADDED;
|
||||
}
|
||||
break;
|
||||
case OVERWRITTEN:
|
||||
action = FormatAction.OVERWROTE;
|
||||
break;
|
||||
case DROPPED:
|
||||
action = FormatAction.DROPPED;
|
||||
break;
|
||||
case REJECTED:
|
||||
action = FormatAction.REJECTED;
|
||||
break;
|
||||
case NONEXISTENT:
|
||||
default:
|
||||
// Should not occur
|
||||
error("Unexpected status: " + ste.previousStatus().toString() + "=>" + status.toString());
|
||||
return;
|
||||
}
|
||||
FormatResolve resolution;
|
||||
String unresolved;
|
||||
if (key instanceof DeclarationSnippet && (status == Status.RECOVERABLE_DEFINED || status == Status.RECOVERABLE_NOT_DEFINED)) {
|
||||
resolution = (status == Status.RECOVERABLE_NOT_DEFINED)
|
||||
? FormatResolve.NOTDEFINED
|
||||
: FormatResolve.DEFINED;
|
||||
unresolved = unresolved((DeclarationSnippet) key);
|
||||
} else {
|
||||
resolution = FormatResolve.OK;
|
||||
unresolved = "";
|
||||
}
|
||||
switch (key.subKind()) {
|
||||
case CLASS_SUBKIND:
|
||||
custom(FormatCase.CLASS, update, action, resolution,
|
||||
((TypeDeclSnippet) key).name(), null, unresolved, null);
|
||||
break;
|
||||
case INTERFACE_SUBKIND:
|
||||
custom(FormatCase.INTERFACE, update, action, resolution,
|
||||
((TypeDeclSnippet) key).name(), null, unresolved, null);
|
||||
break;
|
||||
case ENUM_SUBKIND:
|
||||
custom(FormatCase.ENUM, update, action, resolution,
|
||||
((TypeDeclSnippet) key).name(), null, unresolved, null);
|
||||
break;
|
||||
case ANNOTATION_TYPE_SUBKIND:
|
||||
custom(FormatCase.ANNOTATION, update, action, resolution,
|
||||
((TypeDeclSnippet) key).name(), null, unresolved, null);
|
||||
break;
|
||||
case METHOD_SUBKIND:
|
||||
custom(FormatCase.METHOD, update, action, resolution,
|
||||
((MethodSnippet) key).name(), ((MethodSnippet) key).parameterTypes(), unresolved, null);
|
||||
break;
|
||||
case VAR_DECLARATION_SUBKIND:
|
||||
case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND: {
|
||||
VarSnippet vk = (VarSnippet) key;
|
||||
if (status == Status.RECOVERABLE_NOT_DEFINED) {
|
||||
custom(FormatCase.VARDECLRECOVERABLE, update, action, resolution,
|
||||
vk.name(), null, unresolved, null);
|
||||
} else if (update && ste.isSignatureChange()) {
|
||||
custom(FormatCase.VARRESET, update, action, resolution,
|
||||
vk.name(), null, unresolved, value);
|
||||
} else if (key.subKind() == SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND) {
|
||||
custom(FormatCase.VARINIT, update, action, resolution,
|
||||
vk.name(), vk.typeName(), unresolved, value);
|
||||
} else {
|
||||
custom(FormatCase.VARDECL, update, action, resolution,
|
||||
vk.name(), vk.typeName(), unresolved, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TEMP_VAR_EXPRESSION_SUBKIND: {
|
||||
VarSnippet vk = (VarSnippet) key;
|
||||
custom(FormatCase.EXPRESSION, update, action, resolution,
|
||||
vk.name(), vk.typeName(), null, value);
|
||||
break;
|
||||
}
|
||||
case OTHER_EXPRESSION_SUBKIND:
|
||||
error("Unexpected expression form -- value is: %s", (value));
|
||||
break;
|
||||
case VAR_VALUE_SUBKIND: {
|
||||
ExpressionSnippet ek = (ExpressionSnippet) key;
|
||||
custom(FormatCase.VARVALUE, update, action, resolution,
|
||||
ek.name(), ek.typeName(), null, value);
|
||||
break;
|
||||
}
|
||||
case ASSIGNMENT_SUBKIND: {
|
||||
ExpressionSnippet ek = (ExpressionSnippet) key;
|
||||
custom(FormatCase.ASSIGNMENT, update, action, resolution,
|
||||
ek.name(), ek.typeName(), null, value);
|
||||
break;
|
||||
}
|
||||
case SINGLE_TYPE_IMPORT_SUBKIND:
|
||||
case TYPE_IMPORT_ON_DEMAND_SUBKIND:
|
||||
case SINGLE_STATIC_IMPORT_SUBKIND:
|
||||
case STATIC_IMPORT_ON_DEMAND_SUBKIND:
|
||||
custom(FormatCase.IMPORT, update, action, resolution,
|
||||
((ImportSnippet) key).name(), null, null, null);
|
||||
break;
|
||||
case STATEMENT_SUBKIND:
|
||||
custom(FormatCase.STATEMENT, update, action, resolution,
|
||||
null, null, null, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
//where
|
||||
void printStackTrace(StackTraceElement[] stes) {
|
||||
for (StackTraceElement ste : stes) {
|
||||
@ -2141,31 +1986,11 @@ public class JShellTool {
|
||||
}
|
||||
}
|
||||
//where
|
||||
void printUnresolved(UnresolvedReferenceException ex) {
|
||||
void printUnresolvedException(UnresolvedReferenceException ex) {
|
||||
DeclarationSnippet corralled = ex.getSnippet();
|
||||
List<Diag> otherErrors = errorsOnly(state.diagnostics(corralled));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (otherErrors.size() > 0) {
|
||||
if (state.unresolvedDependencies(corralled).size() > 0) {
|
||||
sb.append(" and");
|
||||
}
|
||||
if (otherErrors.size() == 1) {
|
||||
sb.append(" this error is addressed --");
|
||||
} else {
|
||||
sb.append(" these errors are addressed --");
|
||||
}
|
||||
} else {
|
||||
sb.append(".");
|
||||
}
|
||||
|
||||
String format = corralled.kind() == METHOD
|
||||
? "Attempted to call %s which cannot be invoked until%s"
|
||||
: "Attempted to use %s which cannot be accessed until%s";
|
||||
hard(format, corralled.name(),
|
||||
unresolved(corralled), sb.toString());
|
||||
if (otherErrors.size() > 0) {
|
||||
printDiagnostics(corralled.source(), otherErrors, true);
|
||||
}
|
||||
new DisplayEvent(corralled, state.status(corralled), FormatAction.USED, true, null, otherErrors)
|
||||
.displayDeclarationAndValue();
|
||||
}
|
||||
//where
|
||||
void printEvalException(EvalException ex) {
|
||||
@ -2176,26 +2001,180 @@ public class JShellTool {
|
||||
}
|
||||
printStackTrace(ex.getStackTrace());
|
||||
}
|
||||
//where
|
||||
String unresolved(DeclarationSnippet key) {
|
||||
List<String> unr = state.unresolvedDependencies(key);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int fromLast = unr.size();
|
||||
if (fromLast > 0) {
|
||||
sb.append(" ");
|
||||
|
||||
private FormatAction toAction(Status status, Status previousStatus, boolean isSignatureChange) {
|
||||
FormatAction act;
|
||||
switch (status) {
|
||||
case VALID:
|
||||
case RECOVERABLE_DEFINED:
|
||||
case RECOVERABLE_NOT_DEFINED:
|
||||
if (previousStatus.isActive) {
|
||||
act = isSignatureChange
|
||||
? FormatAction.REPLACED
|
||||
: FormatAction.MODIFIED;
|
||||
} else {
|
||||
act = FormatAction.ADDED;
|
||||
}
|
||||
break;
|
||||
case OVERWRITTEN:
|
||||
act = FormatAction.OVERWROTE;
|
||||
break;
|
||||
case DROPPED:
|
||||
act = FormatAction.DROPPED;
|
||||
break;
|
||||
case REJECTED:
|
||||
case NONEXISTENT:
|
||||
default:
|
||||
// Should not occur
|
||||
error("Unexpected status: " + previousStatus.toString() + "=>" + status.toString());
|
||||
act = FormatAction.DROPPED;
|
||||
}
|
||||
for (String u : unr) {
|
||||
--fromLast;
|
||||
sb.append(u);
|
||||
if (fromLast == 0) {
|
||||
// No suffix
|
||||
} else if (fromLast == 1) {
|
||||
sb.append(", and ");
|
||||
return act;
|
||||
}
|
||||
|
||||
class DisplayEvent {
|
||||
private final Snippet sn;
|
||||
private final FormatAction action;
|
||||
private final boolean update;
|
||||
private final String value;
|
||||
private final List<String> errorLines;
|
||||
private final FormatResolve resolution;
|
||||
private final String unresolved;
|
||||
private final FormatUnresolved unrcnt;
|
||||
private final FormatErrors errcnt;
|
||||
|
||||
DisplayEvent(SnippetEvent ste, boolean update, String value, List<Diag> errors) {
|
||||
this(ste.snippet(), ste.status(), toAction(ste.status(), ste.previousStatus(), ste.isSignatureChange()), update, value, errors);
|
||||
}
|
||||
|
||||
DisplayEvent(Snippet sn, Status status, FormatAction action, boolean update, String value, List<Diag> errors) {
|
||||
this.sn = sn;
|
||||
this.action = action;
|
||||
this.update = update;
|
||||
this.value = value;
|
||||
this.errorLines = new ArrayList<>();
|
||||
for (Diag d : errors) {
|
||||
displayDiagnostics(sn.source(), d, errorLines);
|
||||
}
|
||||
int unresolvedCount;
|
||||
if (sn instanceof DeclarationSnippet && (status == Status.RECOVERABLE_DEFINED || status == Status.RECOVERABLE_NOT_DEFINED)) {
|
||||
resolution = (status == Status.RECOVERABLE_NOT_DEFINED)
|
||||
? FormatResolve.NOTDEFINED
|
||||
: FormatResolve.DEFINED;
|
||||
unresolved = unresolved((DeclarationSnippet) sn);
|
||||
unresolvedCount = state.unresolvedDependencies((DeclarationSnippet) sn).size();
|
||||
} else {
|
||||
sb.append(", ");
|
||||
resolution = FormatResolve.OK;
|
||||
unresolved = "";
|
||||
unresolvedCount = 0;
|
||||
}
|
||||
unrcnt = unresolvedCount == 0
|
||||
? FormatUnresolved.UNRESOLVED0
|
||||
: unresolvedCount == 1
|
||||
? FormatUnresolved.UNRESOLVED1
|
||||
: FormatUnresolved.UNRESOLVED2;
|
||||
errcnt = errors.isEmpty()
|
||||
? FormatErrors.ERROR0
|
||||
: errors.size() == 1
|
||||
? FormatErrors.ERROR1
|
||||
: FormatErrors.ERROR2;
|
||||
}
|
||||
|
||||
private String unresolved(DeclarationSnippet key) {
|
||||
List<String> unr = state.unresolvedDependencies(key);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int fromLast = unr.size();
|
||||
if (fromLast > 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
for (String u : unr) {
|
||||
--fromLast;
|
||||
sb.append(u);
|
||||
switch (fromLast) {
|
||||
// No suffix
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
sb.append(", and ");
|
||||
break;
|
||||
default:
|
||||
sb.append(", ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void custom(FormatCase fcase, String name) {
|
||||
custom(fcase, name, null);
|
||||
}
|
||||
|
||||
private void custom(FormatCase fcase, String name, String type) {
|
||||
String display = feedback.format(fcase, action, (update ? FormatWhen.UPDATE : FormatWhen.PRIMARY),
|
||||
resolution, unrcnt, errcnt,
|
||||
name, type, value, unresolved, errorLines);
|
||||
if (interactive()) {
|
||||
cmdout.print(display);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
private void displayDeclarationAndValue() {
|
||||
switch (sn.subKind()) {
|
||||
case CLASS_SUBKIND:
|
||||
custom(FormatCase.CLASS, ((TypeDeclSnippet) sn).name());
|
||||
break;
|
||||
case INTERFACE_SUBKIND:
|
||||
custom(FormatCase.INTERFACE, ((TypeDeclSnippet) sn).name());
|
||||
break;
|
||||
case ENUM_SUBKIND:
|
||||
custom(FormatCase.ENUM, ((TypeDeclSnippet) sn).name());
|
||||
break;
|
||||
case ANNOTATION_TYPE_SUBKIND:
|
||||
custom(FormatCase.ANNOTATION, ((TypeDeclSnippet) sn).name());
|
||||
break;
|
||||
case METHOD_SUBKIND:
|
||||
custom(FormatCase.METHOD, ((MethodSnippet) sn).name(), ((MethodSnippet) sn).parameterTypes());
|
||||
break;
|
||||
case VAR_DECLARATION_SUBKIND: {
|
||||
VarSnippet vk = (VarSnippet) sn;
|
||||
custom(FormatCase.VARDECL, vk.name(), vk.typeName());
|
||||
break;
|
||||
}
|
||||
case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND: {
|
||||
VarSnippet vk = (VarSnippet) sn;
|
||||
custom(FormatCase.VARINIT, vk.name(), vk.typeName());
|
||||
break;
|
||||
}
|
||||
case TEMP_VAR_EXPRESSION_SUBKIND: {
|
||||
VarSnippet vk = (VarSnippet) sn;
|
||||
custom(FormatCase.EXPRESSION, vk.name(), vk.typeName());
|
||||
break;
|
||||
}
|
||||
case OTHER_EXPRESSION_SUBKIND:
|
||||
error("Unexpected expression form -- value is: %s", (value));
|
||||
break;
|
||||
case VAR_VALUE_SUBKIND: {
|
||||
ExpressionSnippet ek = (ExpressionSnippet) sn;
|
||||
custom(FormatCase.VARVALUE, ek.name(), ek.typeName());
|
||||
break;
|
||||
}
|
||||
case ASSIGNMENT_SUBKIND: {
|
||||
ExpressionSnippet ek = (ExpressionSnippet) sn;
|
||||
custom(FormatCase.ASSIGNMENT, ek.name(), ek.typeName());
|
||||
break;
|
||||
}
|
||||
case SINGLE_TYPE_IMPORT_SUBKIND:
|
||||
case TYPE_IMPORT_ON_DEMAND_SUBKIND:
|
||||
case SINGLE_STATIC_IMPORT_SUBKIND:
|
||||
case STATIC_IMPORT_ON_DEMAND_SUBKIND:
|
||||
custom(FormatCase.IMPORT, ((ImportSnippet) sn).name());
|
||||
break;
|
||||
case STATEMENT_SUBKIND:
|
||||
custom(FormatCase.STATEMENT, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** The current version number as a string.
|
||||
@ -2210,13 +2189,10 @@ public class JShellTool {
|
||||
return version("full"); // mm.mm.oo[-milestone]-build
|
||||
}
|
||||
|
||||
private static final String versionRBName = "jdk.internal.jshell.tool.resources.version";
|
||||
private static ResourceBundle versionRB;
|
||||
|
||||
private static String version(String key) {
|
||||
if (versionRB == null) {
|
||||
try {
|
||||
versionRB = ResourceBundle.getBundle(versionRBName);
|
||||
versionRB = ResourceBundle.getBundle(VERSION_RB_NAME);
|
||||
} catch (MissingResourceException e) {
|
||||
return "(version info not available)";
|
||||
}
|
||||
|
@ -0,0 +1,179 @@
|
||||
#
|
||||
# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
help.set.format = \
|
||||
Set the format for reporting a snippet event.\n\
|
||||
\n\
|
||||
/set format <mode> <field> "<format>" <selector>...\n\
|
||||
\n\
|
||||
Where <mode> is the name of a previously defined feedback mode -- see '/help /set newmode'.\n\
|
||||
Where <field> is the name of context-specific format to define.\n\
|
||||
Where <format> is a quoted string which will be the value of the field if one of\n\
|
||||
the selectors matches (or there are no selectors). When the format is used,\n\
|
||||
field names enclosed in braces are replaced with the value of the field at that\n\
|
||||
time. These fields may have been previously defined with this command or may be\n\
|
||||
one of these predefined fields specific to the context:\n\t\
|
||||
{name} == The name, e.g.: the variable name, ...\n\t\
|
||||
{type} == The type name. The type of a variable or expression, the\n\t\t\t\
|
||||
parameter types of a method\n\t\
|
||||
{value} == The result value of an expression or variable initialization\n\t\
|
||||
{unresolved} == The list of unresolved references\n\t\
|
||||
{errors} == The list of recoverable errors (during the processing of the\n\t\t\t\
|
||||
"display" field only)\n\t\
|
||||
{err} == An unformatted error line (during the processing of the\n\t\t\t\
|
||||
"errorline" field only)\n\
|
||||
The following fields are accessed by the tool to determine the displayed feedback:\n\t\
|
||||
{display} == The displayed message for a snippet event\n\t\
|
||||
{errorline} == The format of one error line within the "errors" field\n\t\
|
||||
{pre} == The feedback prefix (begins command feedback)\n\t\
|
||||
{post} == The feedback postfix (ends command feedback)\n\t\
|
||||
{errorpre} == The error prefix (begins error feedback)\n\t\
|
||||
{errorpost} == The error postfix (ends error feedback)\n\
|
||||
These fields have default settings (which may be overwritten).\n\
|
||||
Where <selector> is the context in which the format is applied.\n\
|
||||
The structure of selector is a hyphen separated list of selector kind lists.\n\
|
||||
A selector kind list is a comma separated list of values of one selector kind.\n\
|
||||
A selector matches if each selector kind list matches; A selector kind list\n\
|
||||
matches if one of the values matches.\n
|
||||
help.set.format.case = The case selector kind describes the kind of snippet. The values are:\n
|
||||
help.set.format.action = The action selector kind describes what happened to the snippet. The values are:\n
|
||||
help.set.format.when = The when-did-it-occur selector kind describes if this is a direct or indirect action. The values are:\n
|
||||
help.set.format.resolve = The resolution-state selector kind describes the state of resolution/definition of the snippet. The values are:\n
|
||||
help.set.format.unresolved = The unresolved-count selector kind describes the number of unresolved references. The values are:\n
|
||||
help.set.format.errors = The errors-count selector kind describes the number of errors. The values are:\n
|
||||
help.set.format.end = \n\
|
||||
Examples:\n\t\
|
||||
/set format myformat action 'Created' added-primary\n\t\
|
||||
/set format myformat action 'Update replaced' replaced-update\n\t\
|
||||
/set format myformat display '{pre}{action} class {name}{post}' class-ok\n\t\
|
||||
/set format myformat display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update\n\n\
|
||||
Note that subsequent selectors for a field may overwrite some or all of previous used selectors -- last one wins\n
|
||||
|
||||
help.set.feedback = \
|
||||
Set the feedback mode describing displayed feedback for entered snippets and commands.\n\
|
||||
\n\
|
||||
/set feedback <mode>\n\
|
||||
\n\
|
||||
Where <mode> is the name of a previously defined feedback mode.\n\
|
||||
You may use just enough letters to make it unique.\n\
|
||||
User-defined modes can be added, see '/help /set newmode'\n\
|
||||
Currently defined feedback modes:\n
|
||||
|
||||
help.set.newmode = \
|
||||
Create a user-defined feedback mode, optionally copying from an existing mode.\n\
|
||||
\n\
|
||||
/set newmode <new-mode> [command|quiet [<old-mode>]]\n\
|
||||
\n\
|
||||
Where <new-mode> is the name of a mode you wish to create.\n\
|
||||
Where <old-mode> is the name of a previously defined feedback mode.\n\
|
||||
If <old-mode> is present, its settings are copied to the new mode.\n\
|
||||
'command' vs 'quiet' determines if informative/verifying command feedback is displayed.\n\
|
||||
\n\
|
||||
Once the new mode is created, use '/set format' and '/set prompt' to configure it.\n\
|
||||
Use '/set feedback' to use the new mode.\n\
|
||||
|
||||
help.set.prompt = \
|
||||
Set the prompts. Both the normal prompt and the continuation-prompt must be set.\n\
|
||||
\n\
|
||||
/set prompt <mode> \"<prompt>\" \"<continuation-propmt>\"\n\
|
||||
\n\
|
||||
Where <mode> is the name of a previously defined feedback mode.\n\
|
||||
Where <prompt> and <continuation-propmt> are quoted strings printed as input prompts;\n\
|
||||
Both may optionally contain '%s' which will be substituted with the next snippet id --\n\
|
||||
note that what is entered may not be assigned that id, for example it may be an error or command.\n\
|
||||
The continuation-prompt is used on the second and subsequent lines of a multi-line snippet.\n
|
||||
|
||||
startup.feedback = \
|
||||
/set newmode normal command \n\
|
||||
/set prompt normal '\\n-> ' '>> ' \n\
|
||||
/set format normal pre '| ' \n\
|
||||
/set format normal post '%n' \n\
|
||||
/set format normal errorpre '| ' \n\
|
||||
/set format normal errorpost '%n' \n\
|
||||
\n\
|
||||
/set format normal errorline '{post}{pre} {err}' \n\
|
||||
\n\
|
||||
/set format normal action 'Added' added-primary \n\
|
||||
/set format normal action 'Modified' modified-primary \n\
|
||||
/set format normal action 'Replaced' replaced-primary \n\
|
||||
/set format normal action 'Overwrote' overwrote-primary \n\
|
||||
/set format normal action 'Dropped' dropped-primary \n\
|
||||
/set format normal action ' Update added' added-update \n\
|
||||
/set format normal action ' Update modified' modified-update \n\
|
||||
/set format normal action ' Update replaced' replaced-update \n\
|
||||
/set format normal action ' Update overwrote' overwrote-update \n\
|
||||
/set format normal action ' Update dropped' dropped-update \n\
|
||||
\n\
|
||||
/set format normal until ', however, it cannot be instanciated or its methods invoked until' defined-class-primary \n\
|
||||
/set format normal until ', however, its methods cannot be invoked until' defined-interface-primary \n\
|
||||
/set format normal until ', however, it cannot be used until' defined-enum,annotation-primary \n\
|
||||
/set format normal until ', however, it cannot be invoked until' defined-method-primary \n\
|
||||
/set format normal until ', however, it cannot be referenced until' notdefined-primary \n\
|
||||
/set format normal until ' which cannot be instanciated or its methods invoked until' defined-class-update \n\
|
||||
/set format normal until ' whose methods cannot be invoked until' defined-interface-update \n\
|
||||
/set format normal until ' which cannot be invoked until' defined-method-update \n\
|
||||
/set format normal until ' which cannot be referenced until' notdefined-update \n\
|
||||
\n\
|
||||
/set format normal unrerr '{unresolved} is declared' unresolved1-error0 \n\
|
||||
/set format normal unrerr '{unresolved} are declared' unresolved2-error0 \n\
|
||||
/set format normal unrerr ' this error is corrected: {errors}' unresolved0-error1 \n\
|
||||
/set format normal unrerr '{unresolved} is declared and this error is corrected: {errors}' unresolved1-error1 \n\
|
||||
/set format normal unrerr '{unresolved} are declared and this error is corrected: {errors}' unresolved2-error1 \n\
|
||||
/set format normal unrerr ' these errors are corrected: {errors}' unresolved0-error2 \n\
|
||||
/set format normal unrerr '{unresolved} is declared and these errors are corrected: {errors}' unresolved1-error2 \n\
|
||||
/set format normal unrerr '{unresolved} are declared and these errors are corrected: {errors}' unresolved2-error2 \n\
|
||||
\n\
|
||||
/set format normal resolve '{until}{unrerr}' added,modified,replaced,used \n\
|
||||
\n\
|
||||
/set format normal typeKind 'class' class \n\
|
||||
/set format normal typeKind 'interface' interface \n\
|
||||
/set format normal typeKind 'enum' enum \n\
|
||||
/set format normal typeKind 'annotation interface' annotation \n\
|
||||
\n\
|
||||
/set format normal display '{pre}{action} {typeKind} {name}{resolve}{post}' class,interface,enum,annotation \n\
|
||||
/set format normal display '{pre}{action} method {name}({type}){resolve}{post}' method \n\
|
||||
\n\
|
||||
/set format normal display '{pre}{action} variable {name} of type {type}{resolve}{post}' vardecl \n\
|
||||
/set format normal display '{pre}{action} variable {name} of type {type} with initial value {value}{resolve}{post}' varinit \n\
|
||||
/set format normal display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update \n\
|
||||
/set format normal display '{pre}{action} variable {name}{resolve}{post}' vardecl,varinit-notdefined \n\
|
||||
/set format normal display '{pre}{action} variable {name}{post}' overwrote,dropped-vardecl,varinit \n\
|
||||
\n\
|
||||
/set format normal display '{pre}Expression value is: {value}{post}{pre} assigned to temporary variable {name} of type {type}{post}' expression \n\
|
||||
/set format normal display '{pre}Variable {name} of type {type} has value {value}{post}' varvalue \n\
|
||||
/set format normal display '{pre}Variable {name} has been assigned the value {value}{post}' assignment \n\
|
||||
\n\
|
||||
/set format normal display '{pre}Attempted to use {typeKind} {name}{resolve}{post}' used-class,interface,enum,annotation \n\
|
||||
/set format normal display '{pre}Attempted to call method {name}({type}){resolve}{post}' used-method \n\
|
||||
\n\
|
||||
/set feedback normal \n\
|
||||
\n\
|
||||
/set newmode off quiet \n\
|
||||
/set prompt off '-> ' '>> ' \n\
|
||||
/set format off pre '| ' \n\
|
||||
/set format off post '%n' \n\
|
||||
/set format off errorpre '| ' \n\
|
||||
/set format off errorpost '%n' \n\
|
||||
/set format off display '' \n
|
@ -374,8 +374,8 @@ public class ReplToolTesting {
|
||||
}
|
||||
}
|
||||
|
||||
private void dropKey(boolean after, String cmd, String name, Map<String, ? extends MemberInfo> map) {
|
||||
assertCommand(after, cmd, "");
|
||||
private void dropKey(boolean after, String cmd, String name, Map<String, ? extends MemberInfo> map, String output) {
|
||||
assertCommand(after, cmd, output);
|
||||
if (after) {
|
||||
map.remove(name);
|
||||
for (int i = 0; i < keys.size(); ++i) {
|
||||
@ -389,20 +389,20 @@ public class ReplToolTesting {
|
||||
}
|
||||
}
|
||||
|
||||
public void dropVariable(boolean after, String cmd, String name) {
|
||||
dropKey(after, cmd, name, variables);
|
||||
public void dropVariable(boolean after, String cmd, String name, String output) {
|
||||
dropKey(after, cmd, name, variables, output);
|
||||
}
|
||||
|
||||
public void dropMethod(boolean after, String cmd, String name) {
|
||||
dropKey(after, cmd, name, methods);
|
||||
public void dropMethod(boolean after, String cmd, String name, String output) {
|
||||
dropKey(after, cmd, name, methods, output);
|
||||
}
|
||||
|
||||
public void dropClass(boolean after, String cmd, String name) {
|
||||
dropKey(after, cmd, name, classes);
|
||||
public void dropClass(boolean after, String cmd, String name, String output) {
|
||||
dropKey(after, cmd, name, classes, output);
|
||||
}
|
||||
|
||||
public void dropImport(boolean after, String cmd, String name) {
|
||||
dropKey(after, cmd, name, imports);
|
||||
public void dropImport(boolean after, String cmd, String name, String output) {
|
||||
dropKey(after, cmd, name, imports, output);
|
||||
}
|
||||
|
||||
public void assertCommand(boolean after, String cmd, String out) {
|
||||
@ -436,10 +436,10 @@ public class ReplToolTesting {
|
||||
}
|
||||
setCommandInput(cmd + "\n");
|
||||
} else {
|
||||
assertOutput(getCommandOutput(), out, "command");
|
||||
assertOutput(getCommandErrorOutput(), err, "command error");
|
||||
assertOutput(getUserOutput(), print, "user");
|
||||
assertOutput(getUserErrorOutput(), usererr, "user error");
|
||||
assertOutput(getCommandOutput(), out, "command output: " + cmd);
|
||||
assertOutput(getCommandErrorOutput(), err, "command error: " + cmd);
|
||||
assertOutput(getUserOutput(), print, "user output: " + cmd);
|
||||
assertOutput(getUserErrorOutput(), usererr, "user error: " + cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,9 +476,9 @@ public class ReplToolTesting {
|
||||
return (output) -> assertTrue(output.startsWith(prefix), "Output: \'" + output + "' does not start with: " + prefix);
|
||||
}
|
||||
|
||||
public void assertOutput(String got, String expected, String kind) {
|
||||
public void assertOutput(String got, String expected, String display) {
|
||||
if (expected != null) {
|
||||
assertEquals(got, expected, "Kind: " + kind + ".\n");
|
||||
assertEquals(got, expected, display + ".\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -755,13 +755,13 @@ public class ToolBasicTest extends ReplToolTesting {
|
||||
public void testDrop() {
|
||||
test(false, new String[]{"-nostartup"},
|
||||
a -> assertVariable(a, "int", "a"),
|
||||
a -> dropVariable(a, "/drop 1", "int a = 0"),
|
||||
a -> dropVariable(a, "/drop 1", "int a = 0", "| Dropped variable a\n"),
|
||||
a -> assertMethod(a, "int b() { return 0; }", "()I", "b"),
|
||||
a -> dropMethod(a, "/drop 2", "b ()I"),
|
||||
a -> dropMethod(a, "/drop 2", "b ()I", "| Dropped method b()\n"),
|
||||
a -> assertClass(a, "class A {}", "class", "A"),
|
||||
a -> dropClass(a, "/drop 3", "class A"),
|
||||
a -> dropClass(a, "/drop 3", "class A", "| Dropped class A\n"),
|
||||
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, "/methods", assertMethods()),
|
||||
a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
|
||||
@ -769,11 +769,11 @@ public class ToolBasicTest extends ReplToolTesting {
|
||||
);
|
||||
test(false, new String[]{"-nostartup"},
|
||||
a -> assertVariable(a, "int", "a"),
|
||||
a -> dropVariable(a, "/drop a", "int a = 0"),
|
||||
a -> dropVariable(a, "/drop a", "int a = 0", "| Dropped variable a\n"),
|
||||
a -> assertMethod(a, "int b() { return 0; }", "()I", "b"),
|
||||
a -> dropMethod(a, "/drop b", "b ()I"),
|
||||
a -> dropMethod(a, "/drop b", "b ()I", "| Dropped method b()\n"),
|
||||
a -> assertClass(a, "class A {}", "class", "A"),
|
||||
a -> dropClass(a, "/drop A", "class A"),
|
||||
a -> dropClass(a, "/drop A", "class A", "| Dropped class A\n"),
|
||||
a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
|
||||
a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
|
||||
a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8148316 8148317
|
||||
* @bug 8148316 8148317 8151755 8152246
|
||||
* @summary Tests for output customization
|
||||
* @library /tools/lib
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
@ -33,6 +33,8 @@
|
||||
* @build KullaTesting TestingInputStream ToolBox Compiler
|
||||
* @run testng ToolFormatTest
|
||||
*/
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test
|
||||
@ -42,28 +44,34 @@ public class ToolFormatTest extends ReplToolTesting {
|
||||
try {
|
||||
test(
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode test command", "| Created new feedback mode: test"),
|
||||
(a) -> assertCommand(a, "/set field test pre '$ '", ""),
|
||||
(a) -> assertCommand(a, "/set field test post ''", ""),
|
||||
(a) -> assertCommand(a, "/set field test action 'ADD ' added-primary", ""),
|
||||
(a) -> assertCommand(a, "/set field test action 'MOD ' modified-primary", ""),
|
||||
(a) -> assertCommand(a, "/set field test action 'REP ' replaced-primary", ""),
|
||||
(a) -> assertCommand(a, "/set field test action 'UP-ADD ' added-update", ""),
|
||||
(a) -> assertCommand(a, "/set field test action 'UP-MOD ' modified-update", ""),
|
||||
(a) -> assertCommand(a, "/set field test action 'UP-REP ' replaced-update", ""),
|
||||
(a) -> assertCommand(a, "/set field test resolve 'OK' ok-*", ""),
|
||||
(a) -> assertCommand(a, "/set field test resolve 'DEF' defined-*", ""),
|
||||
(a) -> assertCommand(a, "/set field test resolve 'NODEF' notdefined-*", ""),
|
||||
(a) -> assertCommand(a, "/set field test name ':%s ' ", ""),
|
||||
(a) -> assertCommand(a, "/set field test type '[%s]' ", ""),
|
||||
(a) -> assertCommand(a, "/set field test result '=%s ' ", ""),
|
||||
(a) -> assertCommand(a, "/set format test '{pre}{action}{type}{name}{result}{resolve}' *-*-*", ""),
|
||||
(a) -> assertCommand(a, "/set format test '{pre}HI this is enum' enum", ""),
|
||||
(a) -> assertCommand(a, "/set format test pre '$ '", ""),
|
||||
(a) -> assertCommand(a, "/set format test post ''", ""),
|
||||
(a) -> assertCommand(a, "/set format test act 'ADD' added", ""),
|
||||
(a) -> assertCommand(a, "/set format test act 'MOD' modified", ""),
|
||||
(a) -> assertCommand(a, "/set format test act 'REP' replaced", ""),
|
||||
(a) -> assertCommand(a, "/set format test act 'OVR' overwrote", ""),
|
||||
(a) -> assertCommand(a, "/set format test act 'USE' used", ""),
|
||||
(a) -> assertCommand(a, "/set format test act 'DRP' dropped", ""),
|
||||
(a) -> assertCommand(a, "/set format test up 'UP-' update", ""),
|
||||
(a) -> assertCommand(a, "/set format test action '{up}{act} '", ""),
|
||||
(a) -> assertCommand(a, "/set format test resolve 'OK' ok", ""),
|
||||
(a) -> assertCommand(a, "/set format test resolve 'DEF' defined", ""),
|
||||
(a) -> assertCommand(a, "/set format test resolve 'NODEF' notdefined", ""),
|
||||
(a) -> assertCommand(a, "/set format test fname ':{name} ' ", ""),
|
||||
(a) -> assertCommand(a, "/set format test ftype '[{type}]' method,expression", ""),
|
||||
(a) -> assertCommand(a, "/set format test result '={value} ' expression", ""),
|
||||
(a) -> assertCommand(a, "/set format test display '{pre}{action}{ftype}{fname}{result}{resolve}'", ""),
|
||||
(a) -> assertCommand(a, "/set format test display '{pre}HI this is enum' enum", ""),
|
||||
(a) -> assertCommand(a, "/set feedback test", "$ Feedback mode: test"),
|
||||
(a) -> assertCommand(a, "class D {}", "$ ADD :D OK"),
|
||||
(a) -> assertCommand(a, "void m() {}", "$ ADD []:m OK"),
|
||||
(a) -> assertCommand(a, "interface EX extends EEX {}", "$ ADD :EX NODEF"),
|
||||
(a) -> assertCommand(a, "56", "$ ADD [int]:$4 =56 OK"),
|
||||
(a) -> assertCommand(a, "class D { int hh; }", "$ REP :D OK$ OVERWROTE-UPDATE:D OK"),
|
||||
(a) -> assertCommand(a, "class D { int hh; }", "$ REP :D OK$ UP-OVR :D OK"),
|
||||
(a) -> assertCommand(a, "enum E {A,B}", "$ HI this is enum"),
|
||||
(a) -> assertCommand(a, "int z() { return f(); }", "$ ADD []:z DEF"),
|
||||
(a) -> assertCommand(a, "z()", "$ UP-USE []:z DEF"),
|
||||
(a) -> assertCommand(a, "/drop z", "$ DRP []:z OK"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback normal", "| Feedback mode: normal")
|
||||
);
|
||||
} finally {
|
||||
@ -72,7 +80,82 @@ public class ToolFormatTest extends ReplToolTesting {
|
||||
}
|
||||
}
|
||||
|
||||
public void testNewModeQuiet() {
|
||||
public void testSetFormatSelector() {
|
||||
List<ReplTest> tests = new ArrayList<>();
|
||||
tests.add((a) -> assertCommandOutputStartsWith(a, "/set newmode ate quiet",
|
||||
"| Created new feedback mode: ate"));
|
||||
tests.add((a) -> assertCommand(a, "/set feedback ate", ""));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
class KindList {
|
||||
final String[] values;
|
||||
final int matchIndex;
|
||||
int current;
|
||||
boolean match;
|
||||
KindList(String[] values, int matchIndex) {
|
||||
this.values = values;
|
||||
this.matchIndex = matchIndex;
|
||||
this.current = 1 << values.length;
|
||||
}
|
||||
boolean next() {
|
||||
if (current <= 0) {
|
||||
return false;
|
||||
}
|
||||
--current;
|
||||
return true;
|
||||
}
|
||||
boolean append(boolean ahead) {
|
||||
boolean any = false;
|
||||
match = false;
|
||||
for (int i = values.length - 1; i >= 0 ; --i) {
|
||||
if ((current & (1 << i)) != 0) {
|
||||
match |= i == matchIndex;
|
||||
if (any) {
|
||||
sb.append(",");
|
||||
} else {
|
||||
if (ahead) {
|
||||
sb.append("-");
|
||||
}
|
||||
}
|
||||
sb.append(values[i]);
|
||||
any = true;
|
||||
}
|
||||
}
|
||||
match |= !any;
|
||||
return ahead || any;
|
||||
}
|
||||
}
|
||||
KindList klcase = new KindList(new String[] {"class", "method", "expression", "vardecl"}, 2);
|
||||
while (klcase.next()) {
|
||||
KindList klact = new KindList(new String[] {"added", "modified", "replaced"}, 0);
|
||||
while (klact.next()) {
|
||||
KindList klwhen = new KindList(new String[] {"update", "primary"}, 1);
|
||||
while (klwhen.next()) {
|
||||
sb.setLength(0);
|
||||
klwhen.append(
|
||||
klact.append(
|
||||
klcase.append(false)));
|
||||
boolean match = klcase.match && klact.match && klwhen.match;
|
||||
String select = sb.toString();
|
||||
String yes = "+++" + select + "+++";
|
||||
String no = "---" + select + "---";
|
||||
String expect = match? yes : no;
|
||||
tests.add((a) -> assertCommand(a, "/set format ate display '" + no + "'", ""));
|
||||
tests.add((a) -> assertCommand(a, "/set format ate display '" + yes + "' " + select, ""));
|
||||
tests.add((a) -> assertCommand(a, "\"" + select + "\"", expect));
|
||||
}
|
||||
}
|
||||
}
|
||||
tests.add((a) -> assertCommandOutputStartsWith(a, "/set feedback normal", "| Feedback mode: normal"));
|
||||
|
||||
try {
|
||||
test(tests.toArray(new ReplTest[tests.size()]));
|
||||
} finally {
|
||||
assertCommandCheckOutput(false, "/set feedback normal", s -> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void testSetNewModeQuiet() {
|
||||
try {
|
||||
test(
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode nmq quiet normal", "| Created new feedback mode: nmq"),
|
||||
@ -82,7 +165,8 @@ public class ToolFormatTest extends ReplToolTesting {
|
||||
(a) -> assertCommand(a, "/set newmode nmc command normal", ""),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback nmc", "| Feedback mode: nmc"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode nm", "| Created new feedback mode: nm"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback nm", "| Feedback mode: nm")
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback nm", "| Feedback mode: nm"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback normal", "| Feedback mode: normal")
|
||||
);
|
||||
} finally {
|
||||
assertCommandCheckOutput(false, "/set feedback normal", s -> {
|
||||
@ -93,38 +177,75 @@ public class ToolFormatTest extends ReplToolTesting {
|
||||
public void testSetError() {
|
||||
try {
|
||||
test(
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal", "| Created new feedback mode: te"),
|
||||
(a) -> assertCommand(a, "/set field te errorpre 'ERROR: '", ""),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback te", ""),
|
||||
(a) -> assertCommandCheckOutput(a, "/set ", assertStartsWith("ERROR: The /set command requires arguments")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set xyz", assertStartsWith("ERROR: Not a valid argument to /set")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set f", assertStartsWith("ERROR: Ambiguous argument to /set")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set feedback", assertStartsWith("ERROR: Expected a feedback mode")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set feedback xyz", assertStartsWith("ERROR: Does not match any current feedback mode")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set format", assertStartsWith("ERROR: Expected a feedback mode")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set format xyz", assertStartsWith("ERROR: Does not match any current feedback mode")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set format te", assertStartsWith("ERROR: Expected format missing")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set format te aaa", assertStartsWith("ERROR: Format 'aaa' must be quoted")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set format te 'aaa'", assertStartsWith("ERROR: At least one selector required")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set format te 'aaa' frog", assertStartsWith("ERROR: Not a valid case")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set format te 'aaa' import-frog", assertStartsWith("ERROR: Not a valid action")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set newmode", assertStartsWith("ERROR: Expected new feedback mode")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set newmode te", assertStartsWith("ERROR: Expected a new feedback mode name")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set newmode x xyz", assertStartsWith("ERROR: Specify either 'command' or 'quiet'")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set newmode x quiet y", assertStartsWith("ERROR: Does not match any current feedback mode")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set prompt", assertStartsWith("ERROR: Expected a feedback mode")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set prompt te", assertStartsWith("ERROR: Expected format missing")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set prompt te aaa xyz", assertStartsWith("ERROR: Format 'aaa' must be quoted")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set prompt te 'aaa' xyz", assertStartsWith("ERROR: Format 'xyz' must be quoted")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set prompt", assertStartsWith("ERROR: Expected a feedback mode")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set prompt te", assertStartsWith("ERROR: Expected format missing")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set prompt te aaa", assertStartsWith("ERROR: Format 'aaa' must be quoted")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set prompt te 'aaa'", assertStartsWith("ERROR: Expected format missing")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set field", assertStartsWith("ERROR: Expected a feedback mode")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set field xyz", assertStartsWith("ERROR: Does not match any current feedback mode: xyz")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set field te xyz", assertStartsWith("ERROR: Not a valid field: xyz, must be one of: when")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set field te action", assertStartsWith("ERROR: Expected format missing")),
|
||||
(a) -> assertCommandCheckOutput(a, "/set field te action 'act'", assertStartsWith("ERROR: At least one selector required"))
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode tee command foo",
|
||||
"| Does not match any current feedback mode: foo"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode tee flurb",
|
||||
"| Specify either 'command' or 'quiet'"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode te2",
|
||||
"| Created new feedback mode: te2"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode te2 command",
|
||||
"| Expected a new feedback mode name. te2 is a known feedback mode"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal",
|
||||
"| Created new feedback mode: te"),
|
||||
(a) -> assertCommand(a, "/set format te errorpre 'ERROR: '", ""),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback te",
|
||||
""),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set ",
|
||||
"ERROR: The /set command requires arguments"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set xyz",
|
||||
"ERROR: Not a valid argument to /set"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set f",
|
||||
"ERROR: Ambiguous argument to /set"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback",
|
||||
"ERROR: Expected a feedback mode"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback xyz",
|
||||
"ERROR: Does not match any current feedback mode"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format",
|
||||
"ERROR: Expected a feedback mode"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format xyz",
|
||||
"ERROR: Does not match any current feedback mode"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format t",
|
||||
"ERROR: Matches more then one current feedback mode: t"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format te",
|
||||
"ERROR: Expected field name missing"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format te fld",
|
||||
"ERROR: Expected format missing"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format te fld aaa",
|
||||
"ERROR: Format 'aaa' must be quoted"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format te fld 'aaa' frog",
|
||||
"ERROR: Not a valid selector"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format te fld 'aaa' import-frog",
|
||||
"ERROR: Not a valid selector"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format te fld 'aaa' import-import",
|
||||
"ERROR: Selector kind in multiple sections of"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set format te fld 'aaa' import,added",
|
||||
"ERROR: Different selector kinds in same sections of"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode",
|
||||
"ERROR: Expected new feedback mode"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode te",
|
||||
"ERROR: Expected a new feedback mode name"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode x xyz",
|
||||
"ERROR: Specify either 'command' or 'quiet'"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode x quiet y",
|
||||
"ERROR: Does not match any current feedback mode"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set prompt",
|
||||
"ERROR: Expected a feedback mode"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set prompt te",
|
||||
"ERROR: Expected format missing"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set prompt te aaa xyz",
|
||||
"ERROR: Format 'aaa' must be quoted"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set prompt te 'aaa' xyz",
|
||||
"ERROR: Format 'xyz' must be quoted"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set prompt",
|
||||
"ERROR: Expected a feedback mode"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set prompt te",
|
||||
"ERROR: Expected format missing"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set prompt te aaa",
|
||||
"ERROR: Format 'aaa' must be quoted"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set prompt te 'aaa'",
|
||||
"ERROR: Expected format missing"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback normal",
|
||||
"| Feedback mode: normal")
|
||||
);
|
||||
} finally {
|
||||
assertCommandCheckOutput(false, "/set feedback normal", s -> {
|
||||
@ -136,7 +257,7 @@ public class ToolFormatTest extends ReplToolTesting {
|
||||
try {
|
||||
test(
|
||||
(a) -> assertCommandOutputContains(a, "/help /set", "command to launch"),
|
||||
(a) -> assertCommandOutputContains(a, "/help /set format", "vardecl"),
|
||||
(a) -> assertCommandOutputContains(a, "/help /set format", "display"),
|
||||
(a) -> assertCommandOutputContains(a, "/hel /se for", "vardecl"),
|
||||
(a) -> assertCommandOutputContains(a, "/help /set editor", "temporary file")
|
||||
);
|
||||
@ -150,7 +271,7 @@ public class ToolFormatTest extends ReplToolTesting {
|
||||
try {
|
||||
test(
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal", "| Created new feedback mode: te"),
|
||||
(a) -> assertCommand(a, "/set field te errorpre 'ERROR: '", ""),
|
||||
(a) -> assertCommand(a, "/set format te errorpre 'ERROR: '", ""),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback te", "| Feedback mode: te"),
|
||||
(a) -> assertCommandOutputContains(a, "/help /set xyz", "ERROR: Not a valid argument to /set: xyz"),
|
||||
(a) -> assertCommandOutputContains(a, "/help /set f", "ERROR: Ambiguous argument to /set: f")
|
||||
|
@ -92,11 +92,11 @@ public class ToolReloadTest extends ReplToolTesting {
|
||||
public void testReloadDrop() {
|
||||
test(false, new String[]{"-nostartup"},
|
||||
a -> assertVariable(a, "int", "a"),
|
||||
a -> dropVariable(a, "/dr 1", "int a = 0"),
|
||||
a -> dropVariable(a, "/dr 1", "int a = 0", "| Dropped variable a\n"),
|
||||
a -> assertMethod(a, "int b() { return 0; }", "()I", "b"),
|
||||
a -> dropMethod(a, "/drop b", "b ()I"),
|
||||
a -> dropMethod(a, "/drop b", "b ()I", "| Dropped method b()\n"),
|
||||
a -> assertClass(a, "class A {}", "class", "A"),
|
||||
a -> dropClass(a, "/dr A", "class A"),
|
||||
a -> dropClass(a, "/dr A", "class A", "| Dropped class A\n"),
|
||||
a -> assertCommand(a, "/reload",
|
||||
"| Restarting and restoring state.\n" +
|
||||
"-: int a;\n" +
|
||||
@ -115,11 +115,11 @@ public class ToolReloadTest extends ReplToolTesting {
|
||||
public void testReloadQuiet() {
|
||||
test(false, new String[]{"-nostartup"},
|
||||
a -> assertVariable(a, "int", "a"),
|
||||
a -> dropVariable(a, "/dr 1", "int a = 0"),
|
||||
a -> dropVariable(a, "/dr 1", "int a = 0", "| Dropped variable a\n"),
|
||||
a -> assertMethod(a, "int b() { return 0; }", "()I", "b"),
|
||||
a -> dropMethod(a, "/drop b", "b ()I"),
|
||||
a -> dropMethod(a, "/drop b", "b ()I", "| Dropped method b()\n"),
|
||||
a -> assertClass(a, "class A {}", "class", "A"),
|
||||
a -> dropClass(a, "/dr A", "class A"),
|
||||
a -> dropClass(a, "/dr A", "class A", "| Dropped class A\n"),
|
||||
a -> assertCommand(a, "/reload quiet",
|
||||
"| Restarting and restoring state.\n"),
|
||||
a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
|
||||
|
Loading…
Reference in New Issue
Block a user