8165405: jshell tool: /classpath is inconsistent
8172103: JShell: crash in TaskFactory$WrapSourceHandler.diag Reviewed-by: jlahoda
This commit is contained in:
parent
4ec30a933a
commit
6f796f5684
langtools
src/jdk.jshell/share/classes/jdk
test/jdk/jshell
@ -47,7 +47,9 @@ import java.nio.file.Paths;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@ -185,10 +187,7 @@ public class JShellTool implements MessageHandler {
|
||||
private IOContext input = null;
|
||||
private boolean regenerateOnDeath = true;
|
||||
private boolean live = false;
|
||||
private boolean feedbackInitialized = false;
|
||||
private String commandLineFeedbackMode = null;
|
||||
private List<String> remoteVMOptions = new ArrayList<>();
|
||||
private List<String> compilerOptions = new ArrayList<>();
|
||||
private Options options;
|
||||
|
||||
SourceCodeAnalysis analysis;
|
||||
JShell state = null;
|
||||
@ -198,7 +197,6 @@ public class JShellTool implements MessageHandler {
|
||||
|
||||
private boolean debug = false;
|
||||
public boolean testPrompt = false;
|
||||
private String cmdlineClasspath = null;
|
||||
private String defaultStartup = null;
|
||||
private String startup = null;
|
||||
private String executionControlSpec = null;
|
||||
@ -221,6 +219,16 @@ public class JShellTool implements MessageHandler {
|
||||
static final Pattern BUILTIN_FILE_PATTERN = Pattern.compile("\\w+");
|
||||
static final String BUILTIN_FILE_PATH_FORMAT = "jrt:/jdk.jshell/jdk/jshell/tool/resources/%s.jsh";
|
||||
|
||||
// match anything followed by whitespace
|
||||
private static final Pattern OPTION_PRE_PATTERN =
|
||||
Pattern.compile("\\s*(\\S+\\s+)*?");
|
||||
// match a (possibly incomplete) option flag with optional double-dash and/or internal dashes
|
||||
private static final Pattern OPTION_PATTERN =
|
||||
Pattern.compile(OPTION_PRE_PATTERN.pattern() + "(?<dd>-??)(?<flag>-([a-z][a-z\\-]*)?)");
|
||||
// match an option flag and a (possibly missing or incomplete) value
|
||||
private static final Pattern OPTION_VALUE_PATTERN =
|
||||
Pattern.compile(OPTION_PATTERN.pattern() + "\\s+(?<val>\\S*)");
|
||||
|
||||
// Tool id (tid) mapping: the three name spaces
|
||||
NameSpace mainNamespace;
|
||||
NameSpace startNamespace;
|
||||
@ -229,7 +237,278 @@ public class JShellTool implements MessageHandler {
|
||||
// Tool id (tid) mapping: the current name spaces
|
||||
NameSpace currentNameSpace;
|
||||
|
||||
Map<Snippet,SnippetInfo> mapSnippet;
|
||||
Map<Snippet, SnippetInfo> mapSnippet;
|
||||
|
||||
// Kinds of compiler/runtime init options
|
||||
private enum OptionKind {
|
||||
CLASS_PATH("--class-path", true),
|
||||
MODULE_PATH("--module-path", true),
|
||||
ADD_MODULES("--add-modules", false),
|
||||
ADD_EXPORTS("--add-exports", false),
|
||||
TO_COMPILER("-C", false, false, true, false),
|
||||
TO_REMOTE_VM("-R", false, false, false, true),;
|
||||
final String optionFlag;
|
||||
final boolean onlyOne;
|
||||
final boolean passFlag;
|
||||
final boolean toCompiler;
|
||||
final boolean toRemoteVm;
|
||||
|
||||
private OptionKind(String optionFlag, boolean onlyOne) {
|
||||
this(optionFlag, onlyOne, true, true, true);
|
||||
}
|
||||
|
||||
private OptionKind(String optionFlag, boolean onlyOne, boolean passFlag,
|
||||
boolean toCompiler, boolean toRemoteVm) {
|
||||
this.optionFlag = optionFlag;
|
||||
this.onlyOne = onlyOne;
|
||||
this.passFlag = passFlag;
|
||||
this.toCompiler = toCompiler;
|
||||
this.toRemoteVm = toRemoteVm;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// compiler/runtime init option values
|
||||
private static class Options {
|
||||
|
||||
private Map<OptionKind, List<String>> optMap = new HashMap<>();
|
||||
|
||||
private String[] selectOptions(Predicate<Entry<OptionKind, List<String>>> pred) {
|
||||
return optMap.entrySet().stream()
|
||||
.filter(pred)
|
||||
.flatMap(e -> e.getValue().stream())
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
String[] remoteVmOptions() {
|
||||
return selectOptions(e -> e.getKey().toRemoteVm);
|
||||
}
|
||||
|
||||
String[] compilerOptions() {
|
||||
return selectOptions(e -> e.getKey().toCompiler);
|
||||
}
|
||||
|
||||
String[] commonOptions() {
|
||||
return selectOptions(e -> e.getKey().passFlag);
|
||||
}
|
||||
|
||||
void addAll(OptionKind kind, Collection<String> vals) {
|
||||
optMap.computeIfAbsent(kind, k -> new ArrayList<>())
|
||||
.addAll(vals);
|
||||
}
|
||||
|
||||
void override(Options newer) {
|
||||
newer.optMap.entrySet().stream()
|
||||
.forEach(e -> {
|
||||
if (e.getKey().onlyOne) {
|
||||
// Only one allowed, override last
|
||||
optMap.put(e.getKey(), e.getValue());
|
||||
} else {
|
||||
// Additive
|
||||
addAll(e.getKey(), e.getValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// base option parsing of /env, /reload, and /reset and command-line options
|
||||
private class OptionParserBase {
|
||||
|
||||
final OptionParser parser = new OptionParser();
|
||||
private final OptionSpec<String> argClassPath = parser.accepts("class-path").withRequiredArg();
|
||||
private final OptionSpec<String> argModulePath = parser.accepts("module-path").withRequiredArg();
|
||||
private final OptionSpec<String> argAddModules = parser.accepts("add-modules").withRequiredArg();
|
||||
private final OptionSpec<String> argAddExports = parser.accepts("add-exports").withRequiredArg();
|
||||
private final NonOptionArgumentSpec<String> argNonOptions = parser.nonOptions();
|
||||
|
||||
private Options opts = new Options();
|
||||
private List<String> nonOptions;
|
||||
private boolean failed = false;
|
||||
|
||||
List<String> nonOptions() {
|
||||
return nonOptions;
|
||||
}
|
||||
|
||||
void msg(String key, Object... args) {
|
||||
errormsg(key, args);
|
||||
}
|
||||
|
||||
Options parse(String[] args) throws OptionException {
|
||||
try {
|
||||
OptionSet oset = parser.parse(args);
|
||||
nonOptions = oset.valuesOf(argNonOptions);
|
||||
return parse(oset);
|
||||
} catch (OptionException ex) {
|
||||
if (ex.options().isEmpty()) {
|
||||
msg("jshell.err.opt.invalid", stream(args).collect(joining(", ")));
|
||||
} else {
|
||||
boolean isKnown = parser.recognizedOptions().containsKey(ex.options().iterator().next());
|
||||
msg(isKnown
|
||||
? "jshell.err.opt.arg"
|
||||
: "jshell.err.opt.unknown",
|
||||
ex.options()
|
||||
.stream()
|
||||
.collect(joining(", ")));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Options parse(OptionSet options) {
|
||||
addOptions(OptionKind.CLASS_PATH, options.valuesOf(argClassPath));
|
||||
addOptions(OptionKind.MODULE_PATH, options.valuesOf(argModulePath));
|
||||
addOptions(OptionKind.ADD_MODULES, options.valuesOf(argAddModules));
|
||||
addOptions(OptionKind.ADD_EXPORTS, options.valuesOf(argAddExports).stream()
|
||||
.map(mp -> mp.contains("=") ? mp : mp + "=ALL-UNNAMED")
|
||||
.collect(toList())
|
||||
);
|
||||
|
||||
return failed ? null : opts;
|
||||
}
|
||||
|
||||
void addOptions(OptionKind kind, Collection<String> vals) {
|
||||
if (!vals.isEmpty()) {
|
||||
if (kind.onlyOne && vals.size() > 1) {
|
||||
msg("jshell.err.opt.one", kind.optionFlag);
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
if (kind.passFlag) {
|
||||
vals = vals.stream()
|
||||
.flatMap(mp -> Stream.of(kind.optionFlag, mp))
|
||||
.collect(toList());
|
||||
}
|
||||
opts.addAll(kind, vals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// option parsing for /reload (adds -restore -quiet)
|
||||
private class OptionParserReload extends OptionParserBase {
|
||||
|
||||
private final OptionSpecBuilder argRestore = parser.accepts("restore");
|
||||
private final OptionSpecBuilder argQuiet = parser.accepts("quiet");
|
||||
|
||||
private boolean restore = false;
|
||||
private boolean quiet = false;
|
||||
|
||||
boolean restore() {
|
||||
return restore;
|
||||
}
|
||||
|
||||
boolean quiet() {
|
||||
return quiet;
|
||||
}
|
||||
|
||||
@Override
|
||||
Options parse(OptionSet options) {
|
||||
if (options.has(argRestore)) {
|
||||
restore = true;
|
||||
}
|
||||
if (options.has(argQuiet)) {
|
||||
quiet = true;
|
||||
}
|
||||
return super.parse(options);
|
||||
}
|
||||
}
|
||||
|
||||
// option parsing for command-line
|
||||
private class OptionParserCommandLine extends OptionParserBase {
|
||||
|
||||
private final OptionSpec<String> argStart = parser.accepts("startup").withRequiredArg();
|
||||
private final OptionSpecBuilder argNoStart = parser.acceptsAll(asList("n", "no-startup"));
|
||||
private final OptionSpec<String> argFeedback = parser.accepts("feedback").withRequiredArg();
|
||||
private final OptionSpec<String> argExecution = parser.accepts("execution").withRequiredArg();
|
||||
private final OptionSpecBuilder argQ = parser.accepts("q");
|
||||
private final OptionSpecBuilder argS = parser.accepts("s");
|
||||
private final OptionSpecBuilder argV = parser.accepts("v");
|
||||
private final OptionSpec<String> argR = parser.accepts("R").withRequiredArg();
|
||||
private final OptionSpec<String> argC = parser.accepts("C").withRequiredArg();
|
||||
private final OptionSpecBuilder argHelp = parser.acceptsAll(asList("h", "help"));
|
||||
private final OptionSpecBuilder argVersion = parser.accepts("version");
|
||||
private final OptionSpecBuilder argFullVersion = parser.accepts("full-version");
|
||||
private final OptionSpecBuilder argX = parser.accepts("X");
|
||||
|
||||
private String feedbackMode = null;
|
||||
private String initialStartup = null;
|
||||
|
||||
String feedbackMode() {
|
||||
return feedbackMode;
|
||||
}
|
||||
|
||||
String startup() {
|
||||
return initialStartup;
|
||||
}
|
||||
|
||||
@Override
|
||||
void msg(String key, Object... args) {
|
||||
startmsg(key, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
Options parse(OptionSet options) {
|
||||
if (options.has(argHelp)) {
|
||||
printUsage();
|
||||
return null;
|
||||
}
|
||||
if (options.has(argX)) {
|
||||
printUsageX();
|
||||
return null;
|
||||
}
|
||||
if (options.has(argVersion)) {
|
||||
cmdout.printf("jshell %s\n", version());
|
||||
return null;
|
||||
}
|
||||
if (options.has(argFullVersion)) {
|
||||
cmdout.printf("jshell %s\n", fullVersion());
|
||||
return null;
|
||||
}
|
||||
if ((options.valuesOf(argFeedback).size() +
|
||||
(options.has(argQ) ? 1 : 0) +
|
||||
(options.has(argS) ? 1 : 0) +
|
||||
(options.has(argV) ? 1 : 0)) > 1) {
|
||||
msg("jshell.err.opt.feedback.one");
|
||||
return null;
|
||||
} else if (options.has(argFeedback)) {
|
||||
feedbackMode = options.valueOf(argFeedback);
|
||||
} else if (options.has("q")) {
|
||||
feedbackMode = "concise";
|
||||
} else if (options.has("s")) {
|
||||
feedbackMode = "silent";
|
||||
} else if (options.has("v")) {
|
||||
feedbackMode = "verbose";
|
||||
}
|
||||
if (options.has(argStart)) {
|
||||
List<String> sts = options.valuesOf(argStart);
|
||||
if (options.has("no-startup")) {
|
||||
startmsg("jshell.err.opt.startup.conflict");
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String fn : sts) {
|
||||
String s = readFile(fn, "--startup");
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
sb.append(s);
|
||||
}
|
||||
initialStartup = sb.toString();
|
||||
} else if (options.has(argNoStart)) {
|
||||
initialStartup = "";
|
||||
} else {
|
||||
initialStartup = prefs.get(STARTUP_KEY);
|
||||
if (initialStartup == null) {
|
||||
initialStartup = defaultStartup();
|
||||
}
|
||||
}
|
||||
if (options.has(argExecution)) {
|
||||
executionControlSpec = options.valueOf(argExecution);
|
||||
}
|
||||
addOptions(OptionKind.TO_REMOTE_VM, options.valuesOf(argR));
|
||||
addOptions(OptionKind.TO_COMPILER, options.valuesOf(argC));
|
||||
return super.parse(options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the input/output currently interactive
|
||||
@ -464,43 +743,45 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
|
||||
public void start(String[] args) throws Exception {
|
||||
List<String> loadList = processCommandArgs(args);
|
||||
if (loadList == null) {
|
||||
OptionParserCommandLine commandLineArgs = new OptionParserCommandLine();
|
||||
options = commandLineArgs.parse(args);
|
||||
if (options == null) {
|
||||
// Abort
|
||||
return;
|
||||
}
|
||||
try (IOContext in = new ConsoleIOContext(this, cmdin, console)) {
|
||||
start(in, loadList);
|
||||
}
|
||||
}
|
||||
|
||||
private void start(IOContext in, List<String> loadList) {
|
||||
// If startup hasn't been set by command line, set from retained/default
|
||||
if (startup == null) {
|
||||
startup = prefs.get(STARTUP_KEY);
|
||||
if (startup == null) {
|
||||
startup = defaultStartup();
|
||||
}
|
||||
}
|
||||
|
||||
startup = commandLineArgs.startup();
|
||||
// initialize editor settings
|
||||
configEditor();
|
||||
|
||||
resetState(); // Initialize
|
||||
|
||||
// initialize JShell instance
|
||||
resetState();
|
||||
// Read replay history from last jshell session into previous history
|
||||
String prevReplay = prefs.get(REPLAY_RESTORE_KEY);
|
||||
if (prevReplay != null) {
|
||||
replayableHistoryPrevious = Arrays.asList(prevReplay.split(RECORD_SEPARATOR));
|
||||
}
|
||||
|
||||
for (String loadFile : loadList) {
|
||||
// load snippet/command files given on command-line
|
||||
for (String loadFile : commandLineArgs.nonOptions()) {
|
||||
runFile(loadFile, "jshell");
|
||||
}
|
||||
|
||||
if (regenerateOnDeath && feedback.shouldDisplayCommandFluff()) {
|
||||
hardmsg("jshell.msg.welcome", version());
|
||||
// if we survived that...
|
||||
if (regenerateOnDeath) {
|
||||
// initialize the predefined feedback modes
|
||||
initFeedback(commandLineArgs.feedbackMode());
|
||||
}
|
||||
// check again, as feedback setting could have failed
|
||||
if (regenerateOnDeath) {
|
||||
// if we haven't died, and the feedback mode wants fluff, print welcome
|
||||
if (feedback.shouldDisplayCommandFluff()) {
|
||||
hardmsg("jshell.msg.welcome", version());
|
||||
}
|
||||
// execute from user input
|
||||
try (IOContext in = new ConsoleIOContext(this, cmdin, console)) {
|
||||
start(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void start(IOContext in) {
|
||||
try {
|
||||
while (regenerateOnDeath) {
|
||||
if (!live) {
|
||||
@ -530,144 +811,6 @@ public class JShellTool implements MessageHandler {
|
||||
return editor = BUILT_IN_EDITOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the command line arguments.
|
||||
* Set options.
|
||||
* @param args the command line arguments
|
||||
* @return the list of files to be loaded
|
||||
*/
|
||||
private List<String> processCommandArgs(String[] args) {
|
||||
OptionParser parser = new OptionParser();
|
||||
OptionSpec<String> cp = parser.accepts("class-path").withRequiredArg();
|
||||
OptionSpec<String> mpath = parser.accepts("module-path").withRequiredArg();
|
||||
OptionSpec<String> amods = parser.accepts("add-modules").withRequiredArg();
|
||||
OptionSpec<String> st = parser.accepts("startup").withRequiredArg();
|
||||
parser.acceptsAll(asList("n", "no-startup"));
|
||||
OptionSpec<String> fb = parser.accepts("feedback").withRequiredArg();
|
||||
OptionSpec<String> ec = parser.accepts("execution").withRequiredArg();
|
||||
parser.accepts("q");
|
||||
parser.accepts("s");
|
||||
parser.accepts("v");
|
||||
OptionSpec<String> r = parser.accepts("R").withRequiredArg();
|
||||
OptionSpec<String> c = parser.accepts("C").withRequiredArg();
|
||||
parser.acceptsAll(asList("h", "help"));
|
||||
parser.accepts("version");
|
||||
parser.accepts("full-version");
|
||||
|
||||
parser.accepts("X");
|
||||
OptionSpec<String> addExports = parser.accepts("add-exports").withRequiredArg();
|
||||
|
||||
NonOptionArgumentSpec<String> loadFileSpec = parser.nonOptions();
|
||||
|
||||
OptionSet options;
|
||||
try {
|
||||
options = parser.parse(args);
|
||||
} catch (OptionException ex) {
|
||||
if (ex.options().isEmpty()) {
|
||||
startmsg("jshell.err.opt.invalid", stream(args).collect(joining(", ")));
|
||||
} else {
|
||||
boolean isKnown = parser.recognizedOptions().containsKey(ex.options().iterator().next());
|
||||
startmsg(isKnown
|
||||
? "jshell.err.opt.arg"
|
||||
: "jshell.err.opt.unknown",
|
||||
ex.options()
|
||||
.stream()
|
||||
.collect(joining(", ")));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (options.has("help")) {
|
||||
printUsage();
|
||||
return null;
|
||||
}
|
||||
if (options.has("X")) {
|
||||
printUsageX();
|
||||
return null;
|
||||
}
|
||||
if (options.has("version")) {
|
||||
cmdout.printf("jshell %s\n", version());
|
||||
return null;
|
||||
}
|
||||
if (options.has("full-version")) {
|
||||
cmdout.printf("jshell %s\n", fullVersion());
|
||||
return null;
|
||||
}
|
||||
if (options.has(cp)) {
|
||||
List<String> cps = options.valuesOf(cp);
|
||||
if (cps.size() > 1) {
|
||||
startmsg("jshell.err.opt.one", "--class-path");
|
||||
return null;
|
||||
}
|
||||
cmdlineClasspath = cps.get(0);
|
||||
}
|
||||
if (options.has(st)) {
|
||||
List<String> sts = options.valuesOf(st);
|
||||
if (options.has("no-startup")) {
|
||||
startmsg("jshell.err.opt.startup.conflict");
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String fn : sts) {
|
||||
String s = readFile(fn, "--startup");
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
sb.append(s);
|
||||
}
|
||||
startup = sb.toString();
|
||||
} else if (options.has("no-startup")) {
|
||||
startup = "";
|
||||
}
|
||||
if ((options.valuesOf(fb).size() +
|
||||
(options.has("q") ? 1 : 0) +
|
||||
(options.has("s") ? 1 : 0) +
|
||||
(options.has("v") ? 1 : 0)) > 1) {
|
||||
startmsg("jshell.err.opt.feedback.one");
|
||||
return null;
|
||||
} else if (options.has(fb)) {
|
||||
commandLineFeedbackMode = options.valueOf(fb);
|
||||
} else if (options.has("q")) {
|
||||
commandLineFeedbackMode = "concise";
|
||||
} else if (options.has("s")) {
|
||||
commandLineFeedbackMode = "silent";
|
||||
} else if (options.has("v")) {
|
||||
commandLineFeedbackMode = "verbose";
|
||||
}
|
||||
if (options.has(r)) {
|
||||
remoteVMOptions.addAll(options.valuesOf(r));
|
||||
}
|
||||
if (options.has(c)) {
|
||||
compilerOptions.addAll(options.valuesOf(c));
|
||||
}
|
||||
if (options.has(mpath)) {
|
||||
compilerOptions.add("--module-path");
|
||||
compilerOptions.addAll(options.valuesOf(mpath));
|
||||
remoteVMOptions.add("--module-path");
|
||||
remoteVMOptions.addAll(options.valuesOf(mpath));
|
||||
}
|
||||
if (options.has(amods)) {
|
||||
compilerOptions.add("--add-modules");
|
||||
compilerOptions.addAll(options.valuesOf(amods));
|
||||
remoteVMOptions.add("--add-modules");
|
||||
remoteVMOptions.addAll(options.valuesOf(amods));
|
||||
}
|
||||
if (options.has(ec)) {
|
||||
executionControlSpec = options.valueOf(ec);
|
||||
}
|
||||
|
||||
if (options.has(addExports)) {
|
||||
List<String> exports = options.valuesOf(addExports).stream()
|
||||
.map(mp -> mp + "=ALL-UNNAMED")
|
||||
.flatMap(mp -> Stream.of("--add-exports", mp))
|
||||
.collect(toList());
|
||||
remoteVMOptions.addAll(exports);
|
||||
compilerOptions.addAll(exports);
|
||||
}
|
||||
|
||||
return options.valuesOf(loadFileSpec);
|
||||
}
|
||||
|
||||
private void printUsage() {
|
||||
cmdout.print(getResourceString("help.usage"));
|
||||
}
|
||||
@ -734,8 +877,8 @@ public class JShellTool implements MessageHandler {
|
||||
.idGenerator((sn, i) -> (currentNameSpace == startNamespace || state.status(sn).isActive())
|
||||
? currentNameSpace.tid(sn)
|
||||
: errorNamespace.tid(sn))
|
||||
.remoteVMOptions(remoteVMOptions.stream().toArray(String[]::new))
|
||||
.compilerOptions(compilerOptions.stream().toArray(String[]::new));
|
||||
.remoteVMOptions(options.remoteVmOptions())
|
||||
.compilerOptions(options.compilerOptions());
|
||||
if (executionControlSpec != null) {
|
||||
builder.executionEngine(executionControlSpec);
|
||||
}
|
||||
@ -748,15 +891,6 @@ public class JShellTool implements MessageHandler {
|
||||
});
|
||||
analysis = state.sourceCodeAnalysis();
|
||||
live = true;
|
||||
if (!feedbackInitialized) {
|
||||
// One time per run feedback initialization
|
||||
feedbackInitialized = true;
|
||||
initFeedback();
|
||||
}
|
||||
|
||||
if (cmdlineClasspath != null) {
|
||||
state.addToClasspath(cmdlineClasspath);
|
||||
}
|
||||
|
||||
startUpRun(startup);
|
||||
currentNameSpace = mainNamespace;
|
||||
@ -767,7 +901,7 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
|
||||
//where -- one-time per run initialization of feedback modes
|
||||
private void initFeedback() {
|
||||
private void initFeedback(String initMode) {
|
||||
// No fluff, no prefix, for init failures
|
||||
MessageHandler initmh = new InitMessageHandler();
|
||||
// Execute the feedback initialization code in the resource file
|
||||
@ -782,12 +916,11 @@ public class JShellTool implements MessageHandler {
|
||||
prefs.remove(MODE_KEY);
|
||||
}
|
||||
}
|
||||
if (commandLineFeedbackMode != null) {
|
||||
if (initMode != null) {
|
||||
// The feedback mode to use was specified on the command line, use it
|
||||
if (!setFeedback(initmh, new ArgTokenizer("--feedback", commandLineFeedbackMode))) {
|
||||
if (!setFeedback(initmh, new ArgTokenizer("--feedback", initMode))) {
|
||||
regenerateOnDeath = false;
|
||||
}
|
||||
commandLineFeedbackMode = null;
|
||||
} else {
|
||||
String fb = prefs.get(FEEDBACK_KEY);
|
||||
if (fb != null) {
|
||||
@ -1016,6 +1149,13 @@ public class JShellTool implements MessageHandler {
|
||||
this.alternatives = alternatives;
|
||||
}
|
||||
|
||||
// Add more options to an existing provider
|
||||
public FixedCompletionProvider(FixedCompletionProvider base, String... alternatives) {
|
||||
List<String> l = new ArrayList<>(Arrays.asList(base.alternatives));
|
||||
l.addAll(Arrays.asList(alternatives));
|
||||
this.alternatives = l.toArray(new String[l.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Suggestion> completionSuggestions(String input, int cursor, int[] anchor) {
|
||||
List<Suggestion> result = new ArrayList<>();
|
||||
@ -1037,11 +1177,20 @@ public class JShellTool implements MessageHandler {
|
||||
private static final CompletionProvider SNIPPET_HISTORY_OPTION_COMPLETION_PROVIDER = new FixedCompletionProvider("-all", "-start ", "-history");
|
||||
private static final CompletionProvider SAVE_OPTION_COMPLETION_PROVIDER = new FixedCompletionProvider("-all ", "-start ", "-history ");
|
||||
private static final CompletionProvider SNIPPET_OPTION_COMPLETION_PROVIDER = new FixedCompletionProvider("-all", "-start " );
|
||||
private static final CompletionProvider RELOAD_OPTIONS_COMPLETION_PROVIDER = new FixedCompletionProvider("-restore ", "-quiet ");
|
||||
private static final CompletionProvider RESTORE_COMPLETION_PROVIDER = new FixedCompletionProvider("-restore");
|
||||
private static final CompletionProvider QUIET_COMPLETION_PROVIDER = new FixedCompletionProvider("-quiet");
|
||||
private static final FixedCompletionProvider COMMAND_LINE_LIKE_OPTIONS_COMPLETION_PROVIDER = new FixedCompletionProvider(
|
||||
"-class-path ", "-module-path ", "-add-modules ", "-add-exports ");
|
||||
private static final CompletionProvider RELOAD_OPTIONS_COMPLETION_PROVIDER = new FixedCompletionProvider(
|
||||
COMMAND_LINE_LIKE_OPTIONS_COMPLETION_PROVIDER,
|
||||
"-restore ", "-quiet ");
|
||||
private static final CompletionProvider SET_MODE_OPTIONS_COMPLETION_PROVIDER = new FixedCompletionProvider("-command", "-quiet", "-delete");
|
||||
private static final CompletionProvider FILE_COMPLETION_PROVIDER = fileCompletions(p -> true);
|
||||
private static final Map<String, CompletionProvider> ARG_OPTIONS = new HashMap<>();
|
||||
static {
|
||||
ARG_OPTIONS.put("-class-path", classPathCompletion());
|
||||
ARG_OPTIONS.put("-module-path", fileCompletions(Files::isDirectory));
|
||||
ARG_OPTIONS.put("-add-modules", EMPTY_COMPLETION_PROVIDER);
|
||||
ARG_OPTIONS.put("-add-exports", EMPTY_COMPLETION_PROVIDER);
|
||||
}
|
||||
private final Map<String, Command> commands = new LinkedHashMap<>();
|
||||
private void registerCommand(Command cmd) {
|
||||
commands.put(cmd.command, cmd);
|
||||
@ -1167,32 +1316,70 @@ public class JShellTool implements MessageHandler {
|
||||
};
|
||||
}
|
||||
|
||||
private static CompletionProvider reloadCompletion() {
|
||||
// command-line-like option completion -- options with values
|
||||
private static CompletionProvider optionCompletion(CompletionProvider provider) {
|
||||
return (code, cursor, anchor) -> {
|
||||
CompletionProvider provider;
|
||||
int pastSpace = code.indexOf(' ') + 1; // zero if no space
|
||||
if (pastSpace == 0) {
|
||||
provider = RELOAD_OPTIONS_COMPLETION_PROVIDER;
|
||||
} else {
|
||||
switch (code.substring(0, pastSpace - 1)) {
|
||||
case "-quiet":
|
||||
provider = RESTORE_COMPLETION_PROVIDER;
|
||||
break;
|
||||
case "-restore":
|
||||
provider = QUIET_COMPLETION_PROVIDER;
|
||||
break;
|
||||
default:
|
||||
provider = EMPTY_COMPLETION_PROVIDER;
|
||||
break;
|
||||
Matcher ovm = OPTION_VALUE_PATTERN.matcher(code);
|
||||
if (ovm.matches()) {
|
||||
String flag = ovm.group("flag");
|
||||
List<CompletionProvider> ps = ARG_OPTIONS.entrySet().stream()
|
||||
.filter(es -> es.getKey().startsWith(flag))
|
||||
.map(es -> es.getValue())
|
||||
.collect(toList());
|
||||
if (ps.size() == 1) {
|
||||
int pastSpace = ovm.start("val");
|
||||
List<Suggestion> result = ps.get(0).completionSuggestions(
|
||||
ovm.group("val"), cursor - pastSpace, anchor);
|
||||
anchor[0] += pastSpace;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
List<Suggestion> result = provider.completionSuggestions(
|
||||
code.substring(pastSpace), cursor - pastSpace, anchor);
|
||||
anchor[0] += pastSpace;
|
||||
return result;
|
||||
Matcher om = OPTION_PATTERN.matcher(code);
|
||||
if (om.matches()) {
|
||||
int pastSpace = om.start("flag");
|
||||
List<Suggestion> result = provider.completionSuggestions(
|
||||
om.group("flag"), cursor - pastSpace, anchor);
|
||||
if (!om.group("dd").isEmpty()) {
|
||||
result = result.stream()
|
||||
.map(sug -> new Suggestion() {
|
||||
@Override
|
||||
public String continuation() {
|
||||
return "-" + sug.continuation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesType() {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.collect(toList());
|
||||
--pastSpace;
|
||||
}
|
||||
anchor[0] += pastSpace;
|
||||
return result;
|
||||
}
|
||||
Matcher opp = OPTION_PRE_PATTERN.matcher(code);
|
||||
if (opp.matches()) {
|
||||
int pastSpace = opp.end();
|
||||
List<Suggestion> result = provider.completionSuggestions(
|
||||
"", cursor - pastSpace, anchor);
|
||||
anchor[0] += pastSpace;
|
||||
return result;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
};
|
||||
}
|
||||
|
||||
// /reload command completion
|
||||
private static CompletionProvider reloadCompletion() {
|
||||
return optionCompletion(RELOAD_OPTIONS_COMPLETION_PROVIDER);
|
||||
}
|
||||
|
||||
// /env command completion
|
||||
private static CompletionProvider envCompletion() {
|
||||
return optionCompletion(COMMAND_LINE_LIKE_OPTIONS_COMPLETION_PROVIDER);
|
||||
}
|
||||
|
||||
private static CompletionProvider orMostSpecificCompletion(
|
||||
CompletionProvider left, CompletionProvider right) {
|
||||
return (code, cursor, anchor) -> {
|
||||
@ -1286,16 +1473,15 @@ public class JShellTool implements MessageHandler {
|
||||
registerCommand(new Command("/exit",
|
||||
arg -> cmdExit(),
|
||||
EMPTY_COMPLETION_PROVIDER));
|
||||
registerCommand(new Command("/env",
|
||||
arg -> cmdEnv(arg),
|
||||
envCompletion()));
|
||||
registerCommand(new Command("/reset",
|
||||
arg -> cmdReset(),
|
||||
EMPTY_COMPLETION_PROVIDER));
|
||||
arg -> cmdReset(arg),
|
||||
envCompletion()));
|
||||
registerCommand(new Command("/reload",
|
||||
this::cmdReload,
|
||||
reloadCompletion()));
|
||||
registerCommand(new Command("/classpath",
|
||||
this::cmdClasspath,
|
||||
classPathCompletion(),
|
||||
CommandKind.REPLAY));
|
||||
registerCommand(new Command("/history",
|
||||
arg -> cmdHistory(),
|
||||
EMPTY_COMPLETION_PROVIDER));
|
||||
@ -1344,6 +1530,9 @@ public class JShellTool implements MessageHandler {
|
||||
registerCommand(new Command("shortcuts",
|
||||
"help.shortcuts",
|
||||
CommandKind.HELP_SUBJECT));
|
||||
registerCommand(new Command("context",
|
||||
"help.context",
|
||||
CommandKind.HELP_SUBJECT));
|
||||
|
||||
commandCompletions = new ContinuousCompletionProvider(
|
||||
commands.values().stream()
|
||||
@ -1692,17 +1881,6 @@ public class JShellTool implements MessageHandler {
|
||||
hard(stset);
|
||||
}
|
||||
|
||||
boolean cmdClasspath(String arg) {
|
||||
if (arg.isEmpty()) {
|
||||
errormsg("jshell.err.classpath.arg");
|
||||
return false;
|
||||
} else {
|
||||
state.addToClasspath(toPathResolvingUserHome(arg).toString());
|
||||
fluffmsg("jshell.msg.classpath", arg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean cmdDebug(String arg) {
|
||||
if (arg.isEmpty()) {
|
||||
debug = !debug;
|
||||
@ -2228,7 +2406,6 @@ public class JShellTool implements MessageHandler {
|
||||
|
||||
}
|
||||
|
||||
// Read a built-in file from resources or null
|
||||
String getResource(String name) {
|
||||
if (BUILTIN_FILE_PATTERN.matcher(name).matches()) {
|
||||
try {
|
||||
@ -2266,20 +2443,22 @@ public class JShellTool implements MessageHandler {
|
||||
return defaultStartup;
|
||||
}
|
||||
|
||||
private boolean cmdReset() {
|
||||
private boolean cmdReset(String rawargs) {
|
||||
if (!parseCommandLineLikeFlags(rawargs, new OptionParserBase())) {
|
||||
return false;
|
||||
}
|
||||
live = false;
|
||||
fluffmsg("jshell.msg.resetting.state");
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean cmdReload(String rawargs) {
|
||||
ArgTokenizer at = new ArgTokenizer("/reload", rawargs.trim());
|
||||
at.allowedOptions("-restore", "-quiet");
|
||||
if (!checkOptionsAndRemainingInput(at)) {
|
||||
OptionParserReload ap = new OptionParserReload();
|
||||
if (!parseCommandLineLikeFlags(rawargs, ap)) {
|
||||
return false;
|
||||
}
|
||||
Iterable<String> history;
|
||||
if (at.hasOption("-restore")) {
|
||||
if (ap.restore()) {
|
||||
if (replayableHistoryPrevious == null) {
|
||||
errormsg("jshell.err.reload.no.previous");
|
||||
return false;
|
||||
@ -2290,13 +2469,57 @@ public class JShellTool implements MessageHandler {
|
||||
history = replayableHistory;
|
||||
fluffmsg("jshell.err.reload.restarting.state");
|
||||
}
|
||||
boolean echo = !at.hasOption("-quiet");
|
||||
return doReload(history, !ap.quiet());
|
||||
}
|
||||
|
||||
private boolean cmdEnv(String rawargs) {
|
||||
if (rawargs.trim().isEmpty()) {
|
||||
// No arguments, display current settings (as option flags)
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String a : options.commonOptions()) {
|
||||
sb.append(
|
||||
a.startsWith("-")
|
||||
? sb.length() > 0
|
||||
? "\n "
|
||||
: " "
|
||||
: " ");
|
||||
sb.append(a);
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
rawout(prefix(sb.toString()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!parseCommandLineLikeFlags(rawargs, new OptionParserBase())) {
|
||||
return false;
|
||||
}
|
||||
fluffmsg("jshell.msg.set.restore");
|
||||
return doReload(replayableHistory, false);
|
||||
}
|
||||
|
||||
private boolean doReload(Iterable<String> history, boolean echo) {
|
||||
resetState();
|
||||
run(new ReloadIOContext(history,
|
||||
echo ? cmdout : null));
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean parseCommandLineLikeFlags(String rawargs, OptionParserBase ap) {
|
||||
String[] args = Arrays.stream(rawargs.split("\\s+"))
|
||||
.filter(s -> !s.isEmpty())
|
||||
.toArray(String[]::new);
|
||||
Options opts = ap.parse(args);
|
||||
if (opts == null) {
|
||||
return false;
|
||||
}
|
||||
if (!ap.nonOptions().isEmpty()) {
|
||||
errormsg("jshell.err.unexpected.at.end", ap.nonOptions(), rawargs);
|
||||
return false;
|
||||
}
|
||||
options.override(opts);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean cmdSave(String rawargs) {
|
||||
ArgTokenizer at = new ArgTokenizer("/save", rawargs.trim());
|
||||
at.allowedOptions("-all", "-start", "-history");
|
||||
|
@ -52,6 +52,7 @@ jshell.err.unexpected.exception = Unexpected exception: {0}
|
||||
|
||||
jshell.err.no.such.command.or.snippet.id = No such command or snippet id: {0}
|
||||
jshell.err.command.ambiguous = Command: ''{0}'' is ambiguous: {1}
|
||||
jshell.msg.set.restore = Setting new options and restoring state.
|
||||
jshell.msg.set.editor.set = Editor set to: {0}
|
||||
jshell.msg.set.editor.retain = Editor setting retained: {0}
|
||||
jshell.err.no.builtin.editor = Built-in editor not available.
|
||||
@ -319,21 +320,25 @@ Leave the jshell tool. No work is saved.\n\
|
||||
Save any work before using this command
|
||||
|
||||
help.reset.summary = reset jshell
|
||||
help.reset.args =
|
||||
help.reset.args = \
|
||||
[-class-path <path>] [-module-path <path>] [-add-modules <modules>]...
|
||||
help.reset =\
|
||||
Reset the jshell tool code and execution state:\n\t\
|
||||
* All entered code is lost.\n\t\
|
||||
* Start-up code is re-executed.\n\t\
|
||||
* The execution state is restarted.\n\t\
|
||||
* The classpath is cleared.\n\
|
||||
Tool settings are maintained, as set with: /set ...\n\
|
||||
Save any work before using this command
|
||||
Save any work before using this command.\n\
|
||||
The /reset command accepts context options, see:\n\n\t\
|
||||
/help context\n\
|
||||
|
||||
|
||||
help.reload.summary = reset and replay relevant history -- current or previous (-restore)
|
||||
help.reload.args = [-restore] [-quiet]
|
||||
help.reload.args = \
|
||||
[-restore] [-quiet] [-class-path <path>] [-module-path <path>]...
|
||||
help.reload =\
|
||||
Reset the jshell tool code and execution state then replay each valid snippet\n\
|
||||
and any /drop or /classpath commands in the order they were entered.\n\
|
||||
and any /drop commands in the order they were entered.\n\
|
||||
\n\
|
||||
/reload\n\t\
|
||||
Reset and replay the valid history since jshell was entered, or\n\t\
|
||||
@ -345,12 +350,31 @@ and any /drop or /classpath commands in the order they were entered.\n\
|
||||
command was executed. This can thus be used to restore a previous\n\t\
|
||||
jshell tool session.\n\n\
|
||||
/reload [-restore] -quiet\n\t\
|
||||
With the '-quiet' argument the replay is not shown. Errors will display.
|
||||
With the '-quiet' argument the replay is not shown. Errors will display.\n\
|
||||
\n\
|
||||
Each of the above accepts context options, see:\n\n\t\
|
||||
/help context\n\
|
||||
\n\
|
||||
For example:\n\n\t\
|
||||
/reload -add-modules com.greetings -restore
|
||||
|
||||
help.classpath.summary = add a path to the classpath
|
||||
help.classpath.args = <path>
|
||||
help.classpath =\
|
||||
Append a additional path to the classpath.
|
||||
help.env.summary = view or change the evaluation context
|
||||
help.env.args = \
|
||||
[-class-path <path>] [-module-path <path>] [-add-modules <modules>] ...
|
||||
help.env =\
|
||||
View or change the evaluation context. The evaluation context is the class path,\n\
|
||||
module path, etc.\n\
|
||||
/env\n\t\
|
||||
Show the evaluation context displayed as context options.\n\n\
|
||||
/env [-class-path <path>] [-module-path <path>] [-add-modules <modules>] ...\n\t\
|
||||
With at least one option set, sets the evaluation context. If snippets\n\t\
|
||||
have been defined, the execution state is reset with the new\n\t\
|
||||
evaluation context and the snippets will be replayed -- the replay is not\n\t\
|
||||
shown, however, errors will display. This is equivalent to: /reload -quiet\n\t\
|
||||
For details of context options, see:\n\n\t\t\
|
||||
/help context\n\n\t\
|
||||
For example:\n\n\t\t\
|
||||
/env -add-modules com.greetings
|
||||
|
||||
help.history.summary = history of what you have typed
|
||||
help.history.args =
|
||||
@ -473,6 +497,37 @@ Shift-<tab>\n\t\t\
|
||||
possible fully qualified names based on the content of the specified classpath.\n\t\t\
|
||||
The "<fix-shortcut>" is either Alt-F1 or Alt-Enter, depending on the platform.
|
||||
|
||||
help.context.summary = the evaluation context options for /env /reload and /reset
|
||||
help.context =\
|
||||
These options configure the evaluation context, they can be specified when\n\
|
||||
jshell is started: on the command-line, or restarted with the commands /env,\n\
|
||||
/reload, or /reset.\n\
|
||||
\n\
|
||||
They are:\n\t\
|
||||
--class-path <class search path of directories and zip/jar files>\n\t\t\
|
||||
A list of directories, JAR archives,\n\t\t\
|
||||
and ZIP archives to search for class files.\n\t\t\
|
||||
The list is separated with the path separator\n\t\t\
|
||||
(a : on unix/linux/mac, and ; on windows).\n\t\
|
||||
--module-path <module path>...\n\t\t\
|
||||
A list of directories, each directory\n\t\t\
|
||||
is a directory of modules.\n\t\t\
|
||||
The list is separated with the path separator\n\t\t\
|
||||
(a : on unix/linux/mac, and ; on windows).\n\t\
|
||||
--add-modules <modulename>[,<modulename>...]\n\t\t\
|
||||
root modules to resolve in addition to the initial module.\n\t\t\
|
||||
<modulename> can also be ALL-DEFAULT, ALL-SYSTEM,\n\t\t\
|
||||
ALL-MODULE-PATH.\n\t\
|
||||
--add-exports <module>/<package>=<target-module>(,<target-module>)*\n\t\t\
|
||||
updates <module> to export <package> to <target-module>,\n\t\t\
|
||||
regardless of module declaration.\n\t\t\
|
||||
<target-module> can be ALL-UNNAMED to export to all\n\t\t\
|
||||
unnamed modules. In jshell, if the <target-module> is not\n\t\t\
|
||||
specified (no =) then ALL-UNNAMED is used.\n\
|
||||
\n\
|
||||
On the command-line these options must have two dashes, e.g.: --module-path\n\
|
||||
On jshell commands they can have one or two dashes, e.g.: -module-path\n\
|
||||
|
||||
help.set._retain = \
|
||||
The '-retain' option saves a setting so that it is used in future sessions.\n\
|
||||
The -retain option can be used on the following forms of /set:\n\n\t\
|
||||
|
@ -161,6 +161,10 @@ class TaskFactory {
|
||||
@Override
|
||||
public Diag diag(Diagnostic<? extends JavaFileObject> d) {
|
||||
SourceMemoryJavaFileObject smjfo = (SourceMemoryJavaFileObject) d.getSource();
|
||||
if (smjfo == null) {
|
||||
// Handle failure that doesn't preserve mapping
|
||||
return new StringSourceHandler().diag(d);
|
||||
}
|
||||
OuterWrap w = (OuterWrap) smjfo.getOrigin();
|
||||
return w.wrapDiag(d);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8144095 8164825 8169818 8153402
|
||||
* @bug 8144095 8164825 8169818 8153402 8165405
|
||||
* @summary Test Command Completion
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
@ -138,7 +138,7 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
@Test
|
||||
public void testEdit() {
|
||||
test(false, new String[]{"--no-startup"},
|
||||
a -> assertCompletion(a, "/e|", false, "/edit ", "/exit "),
|
||||
a -> assertCompletion(a, "/e|", false, "/edit ", "/env ", "/exit "),
|
||||
a -> assertCompletion(a, "/ed|", false, "/edit "),
|
||||
a -> assertClass(a, "class cTest {}", "class", "cTest"),
|
||||
a -> assertMethod(a, "int mTest() { return 0; }", "()I", "mTest"),
|
||||
@ -158,15 +158,17 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
public void testHelp() {
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/help |", false,
|
||||
"/! ", "/-<n> ", "/<id> ", "/? ", "/classpath ", "/drop ",
|
||||
"/edit ", "/exit ", "/help ", "/history ", "/imports ",
|
||||
"/! ", "/-<n> ", "/<id> ", "/? ", "/drop ",
|
||||
"/edit ", "/env ", "/exit ",
|
||||
"/help ", "/history ", "/imports ",
|
||||
"/list ", "/methods ", "/open ", "/reload ", "/reset ",
|
||||
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts "),
|
||||
"/save ", "/set ", "/types ", "/vars ", "context ", "intro ", "shortcuts "),
|
||||
a -> assertCompletion(a, "/? |", false,
|
||||
"/! ", "/-<n> ", "/<id> ", "/? ", "/classpath ", "/drop ",
|
||||
"/edit ", "/exit ", "/help ", "/history ", "/imports ",
|
||||
"/! ", "/-<n> ", "/<id> ", "/? ", "/drop ",
|
||||
"/edit ", "/env ", "/exit ",
|
||||
"/help ", "/history ", "/imports ",
|
||||
"/list ", "/methods ", "/open ", "/reload ", "/reset ",
|
||||
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts "),
|
||||
"/save ", "/set ", "/types ", "/vars ", "context ", "intro ", "shortcuts "),
|
||||
a -> assertCompletion(a, "/help /s|", false,
|
||||
"/save ", "/set "),
|
||||
a -> assertCompletion(a, "/help /set |", false,
|
||||
@ -177,17 +179,63 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
|
||||
@Test
|
||||
public void testReload() {
|
||||
String[] ropts = new String[] { "-add-exports ", "-add-modules ",
|
||||
"-class-path ", "-module-path ", "-quiet ", "-restore " };
|
||||
String[] dropts = new String[] { "--add-exports ", "--add-modules ",
|
||||
"--class-path ", "--module-path ", "--quiet ", "--restore " };
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/reload |", false, "-quiet ", "-restore "),
|
||||
a -> assertCompletion(a, "/reload -restore |", false, "-quiet"),
|
||||
a -> assertCompletion(a, "/reload -quiet |", false, "-restore"),
|
||||
a -> assertCompletion(a, "/reload -restore -quiet |", false)
|
||||
a -> assertCompletion(a, "/reloa |", false, ropts),
|
||||
a -> assertCompletion(a, "/relo |", false, ropts),
|
||||
a -> assertCompletion(a, "/reload -|", false, ropts),
|
||||
a -> assertCompletion(a, "/reload --|", false, dropts),
|
||||
a -> assertCompletion(a, "/reload -restore |", false, ropts),
|
||||
a -> assertCompletion(a, "/reload -restore --|", false, dropts),
|
||||
a -> assertCompletion(a, "/reload -rest|", false, "-restore "),
|
||||
a -> assertCompletion(a, "/reload --r|", false, "--restore "),
|
||||
a -> assertCompletion(a, "/reload -q|", false, "-quiet "),
|
||||
a -> assertCompletion(a, "/reload -add|", false, "-add-exports ", "-add-modules "),
|
||||
a -> assertCompletion(a, "/reload -class-path . -quiet |", false, ropts)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnv() {
|
||||
String[] ropts = new String[] { "-add-exports ", "-add-modules ",
|
||||
"-class-path ", "-module-path " };
|
||||
String[] dropts = new String[] { "--add-exports ", "--add-modules ",
|
||||
"--class-path ", "--module-path " };
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/env |", false, ropts),
|
||||
a -> assertCompletion(a, "/env -|", false, ropts),
|
||||
a -> assertCompletion(a, "/env --|", false, dropts),
|
||||
a -> assertCompletion(a, "/env --a|", false, "--add-exports ", "--add-modules "),
|
||||
a -> assertCompletion(a, "/env -add-|", false, "-add-exports ", "-add-modules "),
|
||||
a -> assertCompletion(a, "/env -class-path . |", false, ropts),
|
||||
a -> assertCompletion(a, "/env -class-path . --|", false, dropts)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReset() {
|
||||
String[] ropts = new String[] { "-add-exports ", "-add-modules ",
|
||||
"-class-path ", "-module-path " };
|
||||
String[] dropts = new String[] { "--add-exports ", "--add-modules ",
|
||||
"--class-path ", "--module-path " };
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/reset |", false, ropts),
|
||||
a -> assertCompletion(a, "/res -m|", false, "-module-path "),
|
||||
a -> assertCompletion(a, "/res -module-|", false, "-module-path "),
|
||||
a -> assertCompletion(a, "/res --m|", false, "--module-path "),
|
||||
a -> assertCompletion(a, "/res --module-|", false, "--module-path "),
|
||||
a -> assertCompletion(a, "/reset -add|", false, "-add-exports ", "-add-modules "),
|
||||
a -> assertCompletion(a, "/rese -class-path . |", false, ropts),
|
||||
a -> assertCompletion(a, "/rese -class-path . --|", false, dropts)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarsMethodsTypes() {
|
||||
test(false, new String[]{"--no-startup"},
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/v|", false, "/vars "),
|
||||
a -> assertCompletion(a, "/m|", false, "/methods "),
|
||||
a -> assertCompletion(a, "/t|", false, "/types "),
|
||||
@ -245,9 +293,6 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
|
||||
@Test
|
||||
public void testClassPath() throws IOException {
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/classp|", false, "/classpath ")
|
||||
);
|
||||
Compiler compiler = new Compiler();
|
||||
Path outDir = compiler.getPath("testClasspathCompletion");
|
||||
Files.createDirectories(outDir);
|
||||
@ -259,8 +304,13 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
compiler.jar(outDir, jarName, "pkg/A.class");
|
||||
compiler.getPath(outDir).resolve(jarName);
|
||||
List<String> paths = listFiles(outDir, CLASSPATH_FILTER);
|
||||
String[] pathArray = paths.toArray(new String[paths.size()]);
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/classpath " + outDir + "/|", false, paths.toArray(new String[paths.size()]))
|
||||
a -> assertCompletion(a, "/env -class-path " + outDir + "/|", false, pathArray),
|
||||
a -> assertCompletion(a, "/env --class-path " + outDir + "/|", false, pathArray),
|
||||
a -> assertCompletion(a, "/env -clas " + outDir + "/|", false, pathArray),
|
||||
a -> assertCompletion(a, "/env --class-p " + outDir + "/|", false, pathArray),
|
||||
a -> assertCompletion(a, "/env --module-path . --class-p " + outDir + "/|", false, pathArray)
|
||||
);
|
||||
}
|
||||
|
||||
@ -275,7 +325,7 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/classpath ~/|", false, completions.toArray(new String[completions.size()]))
|
||||
a -> assertCompletion(a, "/env --class-path ~/|", false, completions.toArray(new String[completions.size()]))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162 8172102
|
||||
* @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162 8172102 8165405
|
||||
* @summary Tests for Basic tests for REPL tool
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
@ -263,7 +263,8 @@ public class ToolBasicTest extends ReplToolTesting {
|
||||
compiler.compile(outDir, "package pkg; public class A { public String toString() { return \"A\"; } }");
|
||||
Path classpath = compiler.getPath(outDir);
|
||||
test(
|
||||
(a) -> assertCommand(a, "/classpath " + classpath, String.format("| Path '%s' added to classpath", classpath)),
|
||||
(a) -> assertCommand(a, "/env --class-path " + classpath,
|
||||
"| Setting new options and restoring state."),
|
||||
(a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
|
||||
);
|
||||
test(new String[] { "--class-path", classpath.toString() },
|
||||
@ -279,7 +280,8 @@ public class ToolBasicTest extends ReplToolTesting {
|
||||
compiler.jar(outDir, jarName, "pkg/A.class");
|
||||
Path jarPath = compiler.getPath(outDir).resolve(jarName);
|
||||
test(
|
||||
(a) -> assertCommand(a, "/classpath " + jarPath, String.format("| Path '%s' added to classpath", jarPath)),
|
||||
(a) -> assertCommand(a, "/env --class-path " + jarPath,
|
||||
"| Setting new options and restoring state."),
|
||||
(a) -> evaluateExpression(a, "pkg.A", "new pkg.A();", "A")
|
||||
);
|
||||
test(new String[] { "--class-path", jarPath.toString() },
|
||||
|
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @key intermittent
|
||||
* @bug 8081845 8147898 8143955
|
||||
* @bug 8081845 8147898 8143955 8165405
|
||||
* @summary Tests for /reload in JShell tool
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
@ -70,8 +70,8 @@ public class ToolReloadTest extends ReplToolTesting {
|
||||
compiler.compile(outDir, prog.apply("A"));
|
||||
Path classpath = compiler.getPath(outDir);
|
||||
test(
|
||||
(a) -> assertCommand(a, "/classpath " + classpath,
|
||||
String.format("| Path '%s' added to classpath", classpath)),
|
||||
(a) -> assertCommand(a, "/env --class-path " + classpath,
|
||||
"| Setting new options and restoring state."),
|
||||
(a) -> assertMethod(a, "String foo() { return (new pkg.A()).toString(); }",
|
||||
"()String", "foo"),
|
||||
(a) -> assertVariable(a, "String", "v", "foo()", "\"A\""),
|
||||
@ -79,7 +79,6 @@ public class ToolReloadTest extends ReplToolTesting {
|
||||
if (!a) compiler.compile(outDir, prog.apply("Aprime"));
|
||||
assertCommand(a, "/reload",
|
||||
"| Restarting and restoring state.\n" +
|
||||
"-: /classpath " + classpath + "\n" +
|
||||
"-: String foo() { return (new pkg.A()).toString(); }\n" +
|
||||
"-: String v = foo();\n");
|
||||
},
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102
|
||||
* @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513 8170015 8170368 8172102 8172103 8165405
|
||||
* @summary Simple jshell tool tests
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
@ -196,7 +196,7 @@ public class ToolSimpleTest extends ReplToolTesting {
|
||||
|
||||
@Test
|
||||
public void testEmptyClassPath() {
|
||||
test(after -> assertCommand(after, "/classpath", "| The /classpath command requires a path argument."));
|
||||
test(after -> assertCommand(after, "/env --class-path", "| Argument to class-path missing."));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -605,6 +605,13 @@ public class ToolSimpleTest extends ReplToolTesting {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrapSourceHandlerDiagCrash() {
|
||||
test(new String[]{"--add-exports", "jdk.javadoc/ALL-UNNAMED"},
|
||||
(a) -> assertCommand(a, "1+1", "$1 ==> 2")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test8156910() {
|
||||
test(
|
||||
|
Loading…
x
Reference in New Issue
Block a user