mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8154812: jshell tool: value printing truncation
Reviewed-by: vromero
This commit is contained in:
parent
358e25664a
commit
f53f69489a
@ -47,6 +47,9 @@ class Feedback {
|
||||
// Patern for substituted fields within a customized format string
|
||||
private static final Pattern FIELD_PATTERN = Pattern.compile("\\{(.*?)\\}");
|
||||
|
||||
// Internal field name for truncation length
|
||||
private static final String TRUNCATION_FIELD = "<truncation>";
|
||||
|
||||
// Current mode
|
||||
private Mode mode = new Mode("", false); // initial value placeholder during start-up
|
||||
|
||||
@ -103,6 +106,10 @@ class Feedback {
|
||||
return new Setter(messageHandler, at).setFormat();
|
||||
}
|
||||
|
||||
public boolean setTruncation(MessageHandler messageHandler, ArgTokenizer at) {
|
||||
return new Setter(messageHandler, at).setTruncation();
|
||||
}
|
||||
|
||||
public boolean setNewMode(MessageHandler messageHandler, ArgTokenizer at) {
|
||||
return new Setter(messageHandler, at).setNewMode();
|
||||
}
|
||||
@ -251,13 +258,42 @@ class Feedback {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// Compute the display output given full context and values
|
||||
String format(FormatCase fc, FormatAction fa, FormatWhen fw,
|
||||
FormatResolve fr, FormatUnresolved fu, FormatErrors fe,
|
||||
String name, String type, String value, String unresolved, List<String> errorLines) {
|
||||
// Convert the context into a bit representation used as selectors for store field formats
|
||||
long bits = bits(fc, fa, fw, fr, fu, fe);
|
||||
String fname = name==null? "" : name;
|
||||
String ftype = type==null? "" : type;
|
||||
String fvalue = value==null? "" : value;
|
||||
// Compute the representation of value
|
||||
String fvalue;
|
||||
if (value==null) {
|
||||
fvalue = "";
|
||||
} else {
|
||||
// Retrieve the truncation length
|
||||
String truncField = format(TRUNCATION_FIELD, bits);
|
||||
if (truncField.isEmpty()) {
|
||||
// No truncation set, use whole value
|
||||
fvalue = value;
|
||||
} else {
|
||||
// Convert truncation length to int
|
||||
// this is safe since it has been tested before it is set
|
||||
int trunc = Integer.parseUnsignedInt(truncField);
|
||||
if (value.length() > trunc) {
|
||||
if (trunc <= 5) {
|
||||
// Very short truncations have no room for "..."
|
||||
fvalue = value.substring(0, trunc);
|
||||
} else {
|
||||
// Normal truncation, make total length equal truncation length
|
||||
fvalue = value.substring(0, trunc - 4) + " ...";
|
||||
}
|
||||
} else {
|
||||
// Within truncation length, use whole value
|
||||
fvalue = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
String funresolved = unresolved==null? "" : unresolved;
|
||||
String errors = errorLines.stream()
|
||||
.map(el -> String.format(
|
||||
@ -619,7 +655,32 @@ class Feedback {
|
||||
errorat("jshell.err.feedback.expected.field");
|
||||
valid = false;
|
||||
}
|
||||
String format = valid? nextFormat() : null;
|
||||
String format = valid ? nextFormat() : null;
|
||||
return installFormat(m, field, format, "/help /set format");
|
||||
}
|
||||
|
||||
// For /set truncation <mode> <length> <selector>...
|
||||
boolean setTruncation() {
|
||||
Mode m = nextMode();
|
||||
String length = at.next();
|
||||
if (length == null) {
|
||||
errorat("jshell.err.truncation.expected.length");
|
||||
valid = false;
|
||||
} else {
|
||||
try {
|
||||
// Assure that integer format is correct
|
||||
Integer.parseUnsignedInt(length);
|
||||
} catch (NumberFormatException ex) {
|
||||
errorat("jshell.err.truncation.length.not.integer", length);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
// install length into an internal format field
|
||||
return installFormat(m, TRUNCATION_FIELD, length, "/help /set truncation");
|
||||
}
|
||||
|
||||
// install the format of a field under parsed selectors
|
||||
boolean installFormat(Mode m, String field, String format, String help) {
|
||||
String slRaw;
|
||||
List<SelectorList> slList = new ArrayList<>();
|
||||
while (valid && (slRaw = at.next()) != null) {
|
||||
@ -629,8 +690,10 @@ class Feedback {
|
||||
}
|
||||
if (valid) {
|
||||
if (slList.isEmpty()) {
|
||||
// No selectors specified, then always the format
|
||||
m.set(field, ALWAYS, format);
|
||||
} else {
|
||||
// Set the format of the field for specified selector
|
||||
slList.stream()
|
||||
.forEach(sl -> m.set(field,
|
||||
sl.cases.getSet(), sl.actions.getSet(), sl.whens.getSet(),
|
||||
@ -638,7 +701,7 @@ class Feedback {
|
||||
format));
|
||||
}
|
||||
} else {
|
||||
fluffmsg("jshell.msg.see", "/help /set format");
|
||||
fluffmsg("jshell.msg.see", help);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
@ -1019,7 +1019,7 @@ public class JShellTool implements MessageHandler {
|
||||
EMPTY_COMPLETION_PROVIDER));
|
||||
registerCommand(new Command("/set",
|
||||
arg -> cmdSet(arg),
|
||||
new FixedCompletionProvider("format", "feedback", "prompt", "newmode", "start", "editor")));
|
||||
new FixedCompletionProvider(SET_SUBCOMMANDS)));
|
||||
registerCommand(new Command("/?",
|
||||
"help.quest",
|
||||
arg -> cmdHelp(arg),
|
||||
@ -1094,7 +1094,7 @@ public class JShellTool implements MessageHandler {
|
||||
// --- Command implementations ---
|
||||
|
||||
private static final String[] SET_SUBCOMMANDS = new String[]{
|
||||
"format", "feedback", "newmode", "prompt", "editor", "start"};
|
||||
"format", "truncation", "feedback", "newmode", "prompt", "editor", "start"};
|
||||
|
||||
final boolean cmdSet(String arg) {
|
||||
ArgTokenizer at = new ArgTokenizer("/set ", arg.trim());
|
||||
@ -1105,6 +1105,8 @@ public class JShellTool implements MessageHandler {
|
||||
switch (which) {
|
||||
case "format":
|
||||
return feedback.setFormat(this, at);
|
||||
case "truncation":
|
||||
return feedback.setTruncation(this, at);
|
||||
case "feedback":
|
||||
return feedback.setFeedback(this, at);
|
||||
case "newmode":
|
||||
|
||||
@ -117,6 +117,9 @@ jshell.msg.feedback.new.mode = Created new feedback mode: {0}
|
||||
jshell.msg.feedback.mode = Feedback mode: {0}
|
||||
jshell.msg.feedback.mode.following = The feedback mode should be one of the following:
|
||||
|
||||
jshell.err.truncation.expected.length = Expected truncation length -- {0}
|
||||
jshell.err.truncation.length.not.integer = Truncation length must be an integer: {0} -- {1}
|
||||
|
||||
jshell.console.see.more = <press tab to see more>
|
||||
jshell.console.do.nothing = Do nothing
|
||||
jshell.console.choice = Choice: \
|
||||
@ -318,6 +321,8 @@ the command prompt, the feedback mode to use, or the format of output.\n\
|
||||
Create a user-defined feedback mode, optionally copying from an existing mode.\n\n\
|
||||
/set prompt <mode> "<prompt>" "<continuation-prompt>"\n\t\
|
||||
Set the displayed prompts for a given feedback mode.\n\n\
|
||||
/set truncation <mode> <length> <selector>...\n\t\
|
||||
Set the maximum length of a displayed value\n\t\
|
||||
/set format <mode> <field> "<format>" <selector>...\n\t\
|
||||
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\
|
||||
@ -462,6 +467,37 @@ Examples:\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.truncation = \
|
||||
Set the max length a displayed value.\n\
|
||||
\n\t\
|
||||
/set truncation <mode> <length> <selector>...\n\
|
||||
\n\
|
||||
Where <mode> is the name of a previously defined feedback mode -- see '/help /set newmode'.\n\
|
||||
Where <length> is an unsigned integer representing a maximum length.\n\
|
||||
Where <format> is a quoted string which will be the value of the field if one of\n\
|
||||
Where <selector> is only needed if you wish to fine-tune value truncation length\n\
|
||||
by context, <selector> is the context in which the truncation 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\n\
|
||||
Below are the relevant selector kinds for truncation.\n\n\
|
||||
The case selector kind describes the kind of snippet. The values are:\n\t\
|
||||
vardecl -- variable declaration without init\n\t\
|
||||
varinit -- variable declaration with init\n\t\
|
||||
expression -- expression -- note: {name}==scratch-variable-name\n\t\
|
||||
varvalue -- variable value expression\n\t\
|
||||
assignment -- assign variable\n\t\
|
||||
The action selector kind describes what happened to the snippet. The values are:\n\t\
|
||||
added -- snippet has been added\n\t\
|
||||
modified -- an existing snippet has been modified\n\t\
|
||||
replaced -- an existing snippet has been replaced with a new snippet\n\
|
||||
Examples:\n\t\
|
||||
/set trunc mymode 80\n\t\
|
||||
/set truncation mymode 45 expression\n\t\
|
||||
/set truncation mymode 0 vardecl-modified,replaced\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\t\
|
||||
@ -578,6 +614,9 @@ startup.feedback = \
|
||||
/set format verbose display '{pre}attempted to use {typeKind} {name}{resolve}{post}' used-class,interface,enum,annotation \n\
|
||||
/set format verbose display '{pre}attempted to call method {name}({type}){resolve}{post}' used-method \n\
|
||||
\n\
|
||||
/set truncation verbose 80\n\
|
||||
/set truncation verbose 500 varvalue\n\
|
||||
\n\
|
||||
/set newmode normal command verbose \n\
|
||||
/set format normal display '' added,modified,replaced,overwrote,dropped-update \n\
|
||||
/set format normal display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update \n\
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8148316 8148317 8151755 8152246 8153551
|
||||
* @bug 8148316 8148317 8151755 8152246 8153551 8154812
|
||||
* @summary Tests for output customization
|
||||
* @library /tools/lib
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
@ -155,6 +155,29 @@ public class ToolFormatTest extends ReplToolTesting {
|
||||
}
|
||||
}
|
||||
|
||||
public void testSetTruncation() {
|
||||
try {
|
||||
test(
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback normal", ""),
|
||||
(a) -> assertCommand(a, "String s = java.util.stream.IntStream.range(65, 74)"+
|
||||
".mapToObj(i -> \"\"+(char)i).reduce((a,b) -> a + b + a).get()",
|
||||
"s ==> \"ABACABADABACABAEABACABADABACABAFABACABADABACABAEABACABADABACABAGABACABADABA ..."),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set newmode test quiet", ""),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set feedback test", ""),
|
||||
(a) -> assertCommand(a, "/set format test display '{type}:{value}' primary", ""),
|
||||
(a) -> assertCommand(a, "/set truncation test 20", ""),
|
||||
(a) -> assertCommand(a, "/set trunc test 10 varvalue", ""),
|
||||
(a) -> assertCommand(a, "/set trunc test 3 assignment", ""),
|
||||
(a) -> assertCommand(a, "String r = s", "String:\"ABACABADABACABA ..."),
|
||||
(a) -> assertCommand(a, "r", "String:\"ABACA ..."),
|
||||
(a) -> assertCommand(a, "r=s", "String:\"AB")
|
||||
);
|
||||
} finally {
|
||||
assertCommandCheckOutput(false, "/set feedback normal", s -> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void testShowFeedbackModes() {
|
||||
test(
|
||||
(a) -> assertCommandOutputContains(a, "/set feedback", "normal")
|
||||
@ -226,6 +249,12 @@ public class ToolFormatTest extends ReplToolTesting {
|
||||
"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 trunc te 20x",
|
||||
"ERROR: Truncation length must be an integer: 20x"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set trunc te",
|
||||
"ERROR: Expected truncation length"),
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set truncation te 111 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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user