8170162: jshell tool: no mechanism to programmatically launch
8170044: jshell tool: jshell missing from javax.tools.ToolProvider Reviewed-by: jjg
This commit is contained in:
parent
23c1a004ec
commit
ea579f7bec
@ -46,7 +46,6 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ -97,7 +96,7 @@ class ConsoleIOContext extends IOContext {
|
||||
List<String> persistenHistory = Stream.of(repl.prefs.keys())
|
||||
.filter(key -> key.startsWith(HISTORY_LINE_PREFIX))
|
||||
.sorted()
|
||||
.map(key -> repl.prefs.get(key, null))
|
||||
.map(key -> repl.prefs.get(key))
|
||||
.collect(Collectors.toList());
|
||||
in.setHistory(history = new EditingHistory(in, persistenHistory) {
|
||||
@Override protected boolean isComplete(CharSequence input) {
|
||||
@ -215,23 +214,21 @@ class ConsoleIOContext extends IOContext {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
//save history:
|
||||
try {
|
||||
for (String key : repl.prefs.keys()) {
|
||||
if (key.startsWith(HISTORY_LINE_PREFIX))
|
||||
repl.prefs.remove(key);
|
||||
for (String key : repl.prefs.keys()) {
|
||||
if (key.startsWith(HISTORY_LINE_PREFIX)) {
|
||||
repl.prefs.remove(key);
|
||||
}
|
||||
Collection<? extends String> savedHistory = history.save();
|
||||
if (!savedHistory.isEmpty()) {
|
||||
int len = (int) Math.ceil(Math.log10(savedHistory.size()+1));
|
||||
String format = HISTORY_LINE_PREFIX + "%0" + len + "d";
|
||||
int index = 0;
|
||||
for (String historyLine : savedHistory) {
|
||||
repl.prefs.put(String.format(format, index++), historyLine);
|
||||
}
|
||||
}
|
||||
} catch (BackingStoreException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
Collection<? extends String> savedHistory = history.save();
|
||||
if (!savedHistory.isEmpty()) {
|
||||
int len = (int) Math.ceil(Math.log10(savedHistory.size()+1));
|
||||
String format = HISTORY_LINE_PREFIX + "%0" + len + "d";
|
||||
int index = 0;
|
||||
for (String historyLine : savedHistory) {
|
||||
repl.prefs.put(String.format(format, index++), historyLine);
|
||||
}
|
||||
}
|
||||
repl.prefs.flush();
|
||||
in.shutdown();
|
||||
try {
|
||||
in.getTerminal().restore();
|
||||
@ -417,6 +414,7 @@ class ConsoleIOContext extends IOContext {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeUserCode() {
|
||||
synchronized (this) {
|
||||
inputBytes = null;
|
||||
@ -424,6 +422,7 @@ class ConsoleIOContext extends IOContext {
|
||||
input.setState(State.BUFFER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterUserCode() {
|
||||
input.setState(State.WAIT);
|
||||
}
|
||||
|
@ -136,25 +136,12 @@ public class JShellTool implements MessageHandler {
|
||||
final InputStream userin;
|
||||
final PrintStream userout;
|
||||
final PrintStream usererr;
|
||||
final Preferences prefs;
|
||||
final PersistentStorage prefs;
|
||||
final Map<String, String> envvars;
|
||||
final Locale locale;
|
||||
|
||||
final Feedback feedback = new Feedback();
|
||||
|
||||
/**
|
||||
* Simple constructor for the tool used by main.
|
||||
* @param in command line input
|
||||
* @param out command line output, feedback including errors, user System.out
|
||||
* @param err start-up errors and debugging info, user System.err
|
||||
*/
|
||||
public JShellTool(InputStream in, PrintStream out, PrintStream err) {
|
||||
this(in, out, err, out, null, out, err,
|
||||
Preferences.userRoot().node("tool/JShell"),
|
||||
System.getenv(),
|
||||
Locale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* The complete constructor for the tool (used by test harnesses).
|
||||
* @param cmdin command line input -- snippets and commands
|
||||
@ -164,14 +151,14 @@ public class JShellTool implements MessageHandler {
|
||||
* @param userin code execution input, or null to use IOContext
|
||||
* @param userout code execution output -- System.out.printf("hi")
|
||||
* @param usererr code execution error stream -- System.err.printf("Oops")
|
||||
* @param prefs preferences to use
|
||||
* @param prefs persistence implementation to use
|
||||
* @param envvars environment variable mapping to use
|
||||
* @param locale locale to use
|
||||
*/
|
||||
public JShellTool(InputStream cmdin, PrintStream cmdout, PrintStream cmderr,
|
||||
JShellTool(InputStream cmdin, PrintStream cmdout, PrintStream cmderr,
|
||||
PrintStream console,
|
||||
InputStream userin, PrintStream userout, PrintStream usererr,
|
||||
Preferences prefs, Map<String, String> envvars, Locale locale) {
|
||||
PersistentStorage prefs, Map<String, String> envvars, Locale locale) {
|
||||
this.cmdin = cmdin;
|
||||
this.cmdout = cmdout;
|
||||
this.cmderr = cmderr;
|
||||
@ -478,16 +465,6 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normal start entry point
|
||||
* @param args
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
new JShellTool(System.in, System.out, System.err)
|
||||
.start(args);
|
||||
}
|
||||
|
||||
public void start(String[] args) throws Exception {
|
||||
List<String> loadList = processCommandArgs(args);
|
||||
if (loadList == null) {
|
||||
@ -502,7 +479,7 @@ public class JShellTool implements MessageHandler {
|
||||
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, null);
|
||||
startup = prefs.get(STARTUP_KEY);
|
||||
if (startup == null) {
|
||||
startup = DEFAULT_STARTUP;
|
||||
}
|
||||
@ -513,7 +490,7 @@ public class JShellTool implements MessageHandler {
|
||||
resetState(); // Initialize
|
||||
|
||||
// Read replay history from last jshell session into previous history
|
||||
String prevReplay = prefs.get(REPLAY_RESTORE_KEY, null);
|
||||
String prevReplay = prefs.get(REPLAY_RESTORE_KEY);
|
||||
if (prevReplay != null) {
|
||||
replayableHistoryPrevious = Arrays.asList(prevReplay.split(RECORD_SEPARATOR));
|
||||
}
|
||||
@ -788,7 +765,7 @@ public class JShellTool implements MessageHandler {
|
||||
// These predefined modes are read-only
|
||||
feedback.markModesReadOnly();
|
||||
// Restore user defined modes retained on previous run with /set mode -retain
|
||||
String encoded = prefs.get(MODE_KEY, null);
|
||||
String encoded = prefs.get(MODE_KEY);
|
||||
if (encoded != null && !encoded.isEmpty()) {
|
||||
if (!feedback.restoreEncodedModes(initmh, encoded)) {
|
||||
// Catastrophic corruption -- remove the retained modes
|
||||
@ -802,7 +779,7 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
commandLineFeedbackMode = null;
|
||||
} else {
|
||||
String fb = prefs.get(FEEDBACK_KEY, null);
|
||||
String fb = prefs.get(FEEDBACK_KEY);
|
||||
if (fb != null) {
|
||||
// Restore the feedback mode to use that was retained
|
||||
// on a previous run with /set feedback -retain
|
||||
@ -1485,9 +1462,9 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
|
||||
// returns null if not stored in preferences
|
||||
static EditorSetting fromPrefs(Preferences prefs) {
|
||||
static EditorSetting fromPrefs(PersistentStorage prefs) {
|
||||
// Read retained editor setting (if any)
|
||||
String editorString = prefs.get(EDITOR_KEY, "");
|
||||
String editorString = prefs.get(EDITOR_KEY);
|
||||
if (editorString == null || editorString.isEmpty()) {
|
||||
return null;
|
||||
} else if (editorString.equals(BUILT_IN_REP)) {
|
||||
@ -1504,11 +1481,11 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
static void removePrefs(Preferences prefs) {
|
||||
static void removePrefs(PersistentStorage prefs) {
|
||||
prefs.remove(EDITOR_KEY);
|
||||
}
|
||||
|
||||
void toPrefs(Preferences prefs) {
|
||||
void toPrefs(PersistentStorage prefs) {
|
||||
prefs.put(EDITOR_KEY, (this == BUILT_IN_EDITOR)
|
||||
? BUILT_IN_REP
|
||||
: (wait ? WAIT_PREFIX : NORMAL_PREFIX) + String.join(RECORD_SEPARATOR, cmd));
|
||||
@ -1676,7 +1653,7 @@ public class JShellTool implements MessageHandler {
|
||||
}
|
||||
|
||||
void showSetStart() {
|
||||
String retained = prefs.get(STARTUP_KEY, null);
|
||||
String retained = prefs.get(STARTUP_KEY);
|
||||
if (retained != null) {
|
||||
showSetStart(true, retained);
|
||||
}
|
||||
@ -1774,6 +1751,7 @@ public class JShellTool implements MessageHandler {
|
||||
replayableHistory.subList(first + 1, replayableHistory.size()));
|
||||
prefs.put(REPLAY_RESTORE_KEY, hist);
|
||||
}
|
||||
prefs.flush();
|
||||
fluffmsg("jshell.msg.goodbye");
|
||||
return true;
|
||||
}
|
||||
|
@ -0,0 +1,348 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package jdk.internal.jshell.tool;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
import jdk.jshell.tool.JavaShellToolBuilder;
|
||||
|
||||
/**
|
||||
* Builder for programmatically building the jshell tool.
|
||||
*/
|
||||
public class JShellToolBuilder implements JavaShellToolBuilder {
|
||||
|
||||
private static final String PREFERENCES_NODE = "tool/JShell";
|
||||
private InputStream cmdIn = System.in;
|
||||
private InputStream userIn = null;
|
||||
private PrintStream cmdOut = System.out;
|
||||
private PrintStream console = System.out;
|
||||
private PrintStream userOut = System.out;
|
||||
private PrintStream cmdErr = System.err;
|
||||
private PrintStream userErr = System.err;
|
||||
private PersistentStorage prefs = null;
|
||||
private Map<String, String> vars = null;
|
||||
private Locale locale = Locale.getDefault();
|
||||
private boolean capturePrompt = false;
|
||||
|
||||
/**
|
||||
* Set the input channels.
|
||||
* Default, if not set, {@code in(System.in, null)}.
|
||||
*
|
||||
* @param cmdIn source of command input
|
||||
* @param userIn source of input for running user code, or {@code null} to
|
||||
* be extracted from cmdIn
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder in(InputStream cmdIn, InputStream userIn) {
|
||||
this.cmdIn = cmdIn;
|
||||
this.userIn = userIn;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output channels. Same as {@code out(output, output, output)}.
|
||||
* Default, if not set, {@code out(System.out)}.
|
||||
*
|
||||
* @param output destination of command feedback, console interaction, and
|
||||
* user code output
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder out(PrintStream output) {
|
||||
this.cmdOut = output;
|
||||
this.console = output;
|
||||
this.userOut = output;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output channels.
|
||||
* Default, if not set, {@code out(System.out, System.out, System.out)}.
|
||||
*
|
||||
* @param cmdOut destination of command feedback including error messages
|
||||
* for users
|
||||
* @param console destination of console interaction
|
||||
* @param userOut destination of user code output. For example, user snippet
|
||||
* {@code System.out.println("Hello")} when executed {@code Hello} goes to
|
||||
* userOut.
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder out(PrintStream cmdOut, PrintStream console, PrintStream userOut) {
|
||||
this.cmdOut = cmdOut;
|
||||
this.console = console;
|
||||
this.userOut = userOut;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the error channels. Same as {@code err(error, error)}.
|
||||
* Default, if not set, {@code err(System.err)}.
|
||||
*
|
||||
* @param error destination of tool errors, and
|
||||
* user code errors
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder err(PrintStream error) {
|
||||
this.cmdErr = error;
|
||||
this.userErr = error;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the error channels.
|
||||
* Default, if not set, {@code err(System.err, System.err, System.err)}.
|
||||
*
|
||||
* @param cmdErr destination of tool start-up and fatal errors
|
||||
* @param userErr destination of user code error output.
|
||||
* For example, user snippet {@code System.err.println("Oops")}
|
||||
* when executed {@code Oops} goes to userErr.
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder err(PrintStream cmdErr, PrintStream userErr) {
|
||||
this.cmdErr = cmdErr;
|
||||
this.userErr = userErr;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the storage mechanism for persistent information which includes
|
||||
* input history and retained settings. Default if not set is the
|
||||
* tool's standard persistence mechanism.
|
||||
*
|
||||
* @param prefs an instance of {@link java.util.prefs.Preferences} that
|
||||
* is used to retrieve and store persistent information
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder persistence(Preferences prefs) {
|
||||
this.prefs = new PreferencesStorage(prefs);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the storage mechanism for persistent information which includes
|
||||
* input history and retained settings. Default if not set is the
|
||||
* tool's standard persistence mechanism.
|
||||
*
|
||||
* @param prefsMap an instance of {@link java.util.Map} that
|
||||
* is used to retrieve and store persistent information
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder persistence(Map<String, String> prefsMap) {
|
||||
this.prefs = new MapStorage(prefsMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the source for environment variables.
|
||||
* Default, if not set, {@code env(System.getenv())}.
|
||||
*
|
||||
* @param vars the Map of environment variable names to values
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder env(Map<String, String> vars) {
|
||||
this.vars = vars;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the locale.
|
||||
* Default, if not set, {@code locale(Locale.getDefault())}.
|
||||
*
|
||||
* @param locale the locale
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder locale(Locale locale) {
|
||||
this.locale = locale;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the special command capturing prompt override should be used.
|
||||
* Default, if not set, {@code promptCapture(false)}.
|
||||
*
|
||||
* @param capture if {@code true}, basic prompt is the {@code ENQ}
|
||||
* character and continuation prompt is the {@code ACK} character.
|
||||
* If false, prompts are as set with set-up or user {@code /set} commands.
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
@Override
|
||||
public JavaShellToolBuilder promptCapture(boolean capture) {
|
||||
this.capturePrompt = capture;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a tool instance for testing. Not in JavaShellToolBuilder.
|
||||
*
|
||||
* @return the tool instance
|
||||
*/
|
||||
public JShellTool rawTool() {
|
||||
if (prefs == null) {
|
||||
prefs = new PreferencesStorage(Preferences.userRoot().node(PREFERENCES_NODE));
|
||||
}
|
||||
if (vars == null) {
|
||||
vars = System.getenv();
|
||||
}
|
||||
JShellTool sh = new JShellTool(cmdIn, cmdOut, cmdErr, console, userIn,
|
||||
userOut, userErr, prefs, vars, locale);
|
||||
sh.testPrompt = capturePrompt;
|
||||
return sh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run an instance of the Java shell tool as configured by the other methods
|
||||
* in this interface. This call is not destructive, more than one call of
|
||||
* this method may be made from a configured builder.
|
||||
*
|
||||
* @param arguments the command-line arguments (including options), if any
|
||||
* @throws Exception an unexpected fatal exception
|
||||
*/
|
||||
@Override
|
||||
public void run(String... arguments) throws Exception {
|
||||
rawTool().start(arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persistence stored in Preferences.
|
||||
*/
|
||||
private static class PreferencesStorage implements PersistentStorage {
|
||||
|
||||
final Preferences p;
|
||||
|
||||
PreferencesStorage(Preferences p) {
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
try {
|
||||
p.clear();
|
||||
} catch (BackingStoreException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] keys() {
|
||||
try {
|
||||
return p.keys();
|
||||
} catch (BackingStoreException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String key) {
|
||||
return p.get(key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, String value) {
|
||||
p.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String key) {
|
||||
p.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try {
|
||||
p.flush();
|
||||
} catch (BackingStoreException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Persistence stored in a Map.
|
||||
*/
|
||||
private static class MapStorage implements PersistentStorage {
|
||||
|
||||
final Map<String, String> map;
|
||||
|
||||
MapStorage(Map<String, String> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
|
||||
try {
|
||||
map.clear();
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] keys() {
|
||||
Set<String> ks = map.keySet();
|
||||
return ks.toArray(new String[ks.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String key) {
|
||||
Objects.requireNonNull(key);
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, String value) {
|
||||
Objects.requireNonNull(key);
|
||||
Objects.requireNonNull(value);
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(String key) {
|
||||
Objects.requireNonNull(key);
|
||||
map.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
// no-op always up-to-date
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package jdk.internal.jshell.tool;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.tools.Tool;
|
||||
import jdk.jshell.tool.JavaShellToolBuilder;
|
||||
|
||||
/**
|
||||
* Provider for launching the jshell tool.
|
||||
*/
|
||||
public class JShellToolProvider implements Tool {
|
||||
|
||||
/**
|
||||
* Returns the name of this Java shell tool provider.
|
||||
*
|
||||
* @return the name of this tool provider
|
||||
*/
|
||||
@Override
|
||||
public String name() {
|
||||
return "jshell";
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the jshell tool. The streams {@code out} and {@code err} are
|
||||
* converted to {@code PrintStream} if they are not already.
|
||||
* Any {@code Exception} is caught, printed and results in a non-zero return.
|
||||
*
|
||||
* @param in command line input (snippets and commands), and execution
|
||||
* "standard" input; use System.in if null
|
||||
* @param out command line output, feedback including errors, and execution
|
||||
* "standard" output; use System.out if null
|
||||
* @param err start-up errors and execution "standard" error; use System.err
|
||||
* if null
|
||||
* @param arguments arguments to pass to the tool
|
||||
* @return 0 for success; nonzero otherwise
|
||||
* @throws NullPointerException if the array of arguments contains
|
||||
* any {@code null} elements.
|
||||
*/
|
||||
@Override
|
||||
public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) {
|
||||
InputStream xin =
|
||||
(in == null)
|
||||
? System.in
|
||||
: in;
|
||||
PrintStream xout =
|
||||
(out == null)
|
||||
? System.out
|
||||
: (out instanceof PrintStream)
|
||||
? (PrintStream) out
|
||||
: new PrintStream(out);
|
||||
PrintStream xerr =
|
||||
(err == null)
|
||||
? System.err
|
||||
: (err instanceof PrintStream)
|
||||
? (PrintStream) err
|
||||
: new PrintStream(err);
|
||||
try {
|
||||
JavaShellToolBuilder
|
||||
.builder()
|
||||
.in(xin, null)
|
||||
.out(xout)
|
||||
.err(xerr)
|
||||
.run(arguments);
|
||||
return 0;
|
||||
} catch (Throwable ex) {
|
||||
xerr.println(ex.getMessage());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the source versions of the jshell tool.
|
||||
* @return a set of supported source versions
|
||||
*/
|
||||
@Override
|
||||
public Set<SourceVersion> getSourceVersions() {
|
||||
return Collections.unmodifiableSet(
|
||||
EnumSet.range(SourceVersion.RELEASE_9, SourceVersion.latest()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch the tool.
|
||||
* @param arguments the command-line arguments (including options), if any
|
||||
* @throws Exception an unexpected fatal exception
|
||||
*/
|
||||
public static void main(String[] arguments) throws Exception {
|
||||
JavaShellToolBuilder
|
||||
.builder()
|
||||
.run(arguments);
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package jdk.internal.jshell.tool;
|
||||
|
||||
/**
|
||||
* The required functionality jshell uses for persistent storage. Implementable
|
||||
* by both Preferences API and Map.
|
||||
*/
|
||||
interface PersistentStorage {
|
||||
|
||||
/**
|
||||
* Removes all of the preferences (key-value associations) in
|
||||
* preferences.
|
||||
*
|
||||
* @throws IllegalStateException if this operation cannot be completed
|
||||
* because of the state of the system.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Returns all of the keys that have an associated value in
|
||||
* preferences.
|
||||
*
|
||||
* @return an array of the keys that have an associated value in this
|
||||
* preference node.
|
||||
* @throws IllegalStateException if this operation cannot be completed
|
||||
* because of the state of the system.
|
||||
*/
|
||||
String[] keys();
|
||||
|
||||
/**
|
||||
* Returns the value associated with the specified key in preferences.
|
||||
*
|
||||
* @param key key whose associated value is to be returned.
|
||||
* @return the value associated with {@code key}, or {@code null} if no
|
||||
* value is associated with {@code key}.
|
||||
* @throws IllegalStateException if this operation cannot be completed
|
||||
* because of the state of the system.
|
||||
* @throws NullPointerException if {@code key} is {@code null}.
|
||||
*/
|
||||
String get(String key);
|
||||
|
||||
/**
|
||||
* Associates the specified value with the specified key in this
|
||||
* preference node.
|
||||
*
|
||||
* @param key key with which the specified value is to be associated.
|
||||
* @param value value to be associated with the specified key.
|
||||
* @throws NullPointerException if key or value is {@code null}.
|
||||
* @throws IllegalArgumentException if key or value are too long.
|
||||
* @throws IllegalStateException if this operation cannot be completed
|
||||
* because of the state of the system.
|
||||
*/
|
||||
void put(String key, String value);
|
||||
|
||||
/**
|
||||
* Removes the value associated with the specified key in preferences,
|
||||
* if any.
|
||||
*
|
||||
* @param key key whose mapping is to be removed from the preference
|
||||
* node.
|
||||
* @throws NullPointerException if {@code key} is {@code null}.
|
||||
* @throws IllegalStateException if this operation cannot be completed
|
||||
* because of the state of the system.
|
||||
*/
|
||||
void remove(String key);
|
||||
|
||||
/**
|
||||
* Forces any changes in the contents of this preferences to be stored.
|
||||
* Once this method returns successfully, it is safe to assume that all
|
||||
* changes have become as permanent as they are going to be.
|
||||
* <p>
|
||||
* Implementations are free to flush changes into the persistent store
|
||||
* at any time. They do not need to wait for this method to be called.
|
||||
*
|
||||
* @throws IllegalStateException if this operation cannot be completed
|
||||
* because of the state of the system.
|
||||
*/
|
||||
void flush();
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
|
||||
This document is the API specification for JShell -- support for
|
||||
Java™ Programming Language 'snippet' evaluating tools, such as
|
||||
Read-Eval-Print Loops (REPLs).
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package jdk.jshell.tool;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.prefs.Preferences;
|
||||
import jdk.internal.jshell.tool.JShellToolBuilder;
|
||||
|
||||
/**
|
||||
* Interface to configure and run a Java shell tool instance. An instance of the
|
||||
* builder is created with the static {@link #builder} method. This builder can,
|
||||
* optionally, be configured with the configuration methods. All configuration
|
||||
* methods return the builder instance for use in chained initialization. All
|
||||
* configuration methods have sensible defaults which will be used if they are
|
||||
* not called.. After zero or more calls to configuration methods, the tool is
|
||||
* launched with a call to {@link #run(java.lang.String...) }.
|
||||
*/
|
||||
public interface JavaShellToolBuilder {
|
||||
|
||||
/**
|
||||
* Create a builder for launching the JDK jshell tool.
|
||||
*
|
||||
* @return a builder which can be used to configure and launch the jshell
|
||||
* tool
|
||||
*/
|
||||
static JavaShellToolBuilder builder() {
|
||||
return new JShellToolBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the input channels.
|
||||
*
|
||||
* @implSpec If this method is not called, the behavior should be
|
||||
* equivalent to calling {@code in(System.in, null)}.
|
||||
*
|
||||
* @param cmdIn source of command input
|
||||
* @param userIn source of input for running user code, or {@code null} to
|
||||
* extract user input from cmdIn
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder in(InputStream cmdIn, InputStream userIn);
|
||||
|
||||
/**
|
||||
* Set the output channels. Same as {@code out(output, output, output)}.
|
||||
*
|
||||
* @implSpec If neither {@code out} method is called, the behavior should be
|
||||
* equivalent to calling {@code out(System.out)}.
|
||||
*
|
||||
* @param output destination of command feedback, console interaction, and
|
||||
* user code output
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder out(PrintStream output);
|
||||
|
||||
/**
|
||||
* Set the output channels.
|
||||
*
|
||||
* @implSpec If neither {@code out} method is called, the behavior should be
|
||||
* equivalent to calling {@code out(System.out, System.out, System.out)}.
|
||||
*
|
||||
* @param cmdOut destination of command feedback including error messages
|
||||
* for users
|
||||
* @param console destination of console interaction
|
||||
* @param userOut destination of user code output. For example, user snippet
|
||||
* {@code System.out.println("Hello")} when executed {@code Hello} goes to
|
||||
* userOut.
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder out(PrintStream cmdOut, PrintStream console, PrintStream userOut);
|
||||
|
||||
/**
|
||||
* Set the error channels. Same as {@code err(error, error)}.
|
||||
*
|
||||
* @implSpec If neither {@code err} method is called, the behavior should be
|
||||
* equivalent to calling {@code err(System.err)}.
|
||||
*
|
||||
* @param error destination of tool errors, and
|
||||
* user code errors
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder err(PrintStream error);
|
||||
|
||||
/**
|
||||
* Set the error channels.
|
||||
*
|
||||
* @implSpec If neither {@code err} method is called, the behavior should be
|
||||
* equivalent to calling {@code err(System.err, System.err, System.err)}.
|
||||
*
|
||||
* @param cmdErr destination of tool start-up and fatal errors
|
||||
* @param userErr destination of user code error output.
|
||||
* For example, user snippet {@code System.err.println("Oops")}
|
||||
* when executed {@code Oops} goes to userErr.
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder err(PrintStream cmdErr, PrintStream userErr);
|
||||
|
||||
/**
|
||||
* Set the storage mechanism for persistent information which includes
|
||||
* input history and retained settings.
|
||||
*
|
||||
* @implSpec If neither {@code persistence} method is called, the behavior
|
||||
* should be to use the tool's standard persistence mechanism.
|
||||
*
|
||||
* @param prefs an instance of {@link java.util.prefs.Preferences} that
|
||||
* is used to retrieve and store persistent information
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder persistence(Preferences prefs);
|
||||
|
||||
/**
|
||||
* Set the storage mechanism for persistent information which includes
|
||||
* input history and retained settings.
|
||||
*
|
||||
* @implSpec If neither {@code persistence} method is called, the behavior
|
||||
* should be to use the tool's standard persistence mechanism.
|
||||
*
|
||||
* @param prefsMap an instance of {@link java.util.Map} that
|
||||
* is used to retrieve and store persistent information
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder persistence(Map<String,String> prefsMap);
|
||||
|
||||
/**
|
||||
* Set the source for environment variables.
|
||||
*
|
||||
* @implSpec If this method is not called, the behavior should be
|
||||
* equivalent to calling {@code env(System.getenv())}.
|
||||
*
|
||||
* @param vars the Map of environment variable names to values
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder env(Map<String,String> vars);
|
||||
|
||||
/**
|
||||
* Set the locale.
|
||||
*
|
||||
* @implSpec If this method is not called, the behavior should be
|
||||
* equivalent to calling {@code locale(Locale.getDefault())}.
|
||||
*
|
||||
* @param locale the locale
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder locale(Locale locale);
|
||||
|
||||
/**
|
||||
* Set to enable a command capturing prompt override.
|
||||
*
|
||||
* @implSpec If this method is not called, the behavior should be
|
||||
* equivalent to calling {@code promptCapture(false)}.
|
||||
*
|
||||
* @param capture if {@code true}, basic prompt is the {@code ENQ}
|
||||
* character and continuation prompt is the {@code ACK} character.
|
||||
* If false, prompts are as set with set-up or user {@code /set} commands.
|
||||
* @return the {@code JavaShellToolBuilder} instance
|
||||
*/
|
||||
JavaShellToolBuilder promptCapture(boolean capture);
|
||||
|
||||
/**
|
||||
* Run an instance of the Java shell tool as configured by the other methods
|
||||
* in this interface. This call is not destructive, more than one call of
|
||||
* this method may be made from a configured builder.
|
||||
*
|
||||
* @param arguments the command-line arguments (including options), if any
|
||||
* @throws Exception an unexpected fatal exception
|
||||
*/
|
||||
void run(String... arguments) throws Exception;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides a mechanism to launch an instance of a Java™ shell tool.
|
||||
* Allows configuration of the tool before launching. A builder is used
|
||||
* to configure and launch the tool.
|
||||
* <p>
|
||||
* At the simplest, a builder is retrieved, and the builder is used to run the
|
||||
* tool:
|
||||
* <pre>
|
||||
* {@code
|
||||
* JavaShellToolBuilder
|
||||
* .builder()
|
||||
* .run();
|
||||
* }
|
||||
* </pre>
|
||||
* The builder can be configured and the run can have arguments:
|
||||
* <pre>
|
||||
* {@code
|
||||
* JavaShellToolBuilder
|
||||
* .builder()
|
||||
* .out(myCommandPrintStream, myOutputPrintStream)
|
||||
* .locale(Locale.CANADA)
|
||||
* .run("--feedback", "silent", "MyStart");
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
|
||||
package jdk.jshell.tool;
|
||||
|
@ -24,14 +24,38 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* This document is the API specification for JShell -- support for
|
||||
* This module provides support for
|
||||
* Java™ Programming Language 'snippet' evaluating tools, such as
|
||||
* Read-Eval-Print Loops (REPLs).
|
||||
* Separate packages support building tools, configuring the execution of tools,
|
||||
* and programmatically launching the existing Java™ shell tool.
|
||||
* <p>
|
||||
* The {@link jdk.jshell} is the package for creating 'snippet' evaluating tools.
|
||||
* Generally, this is only package that would be needed for creating tools.
|
||||
* </p>
|
||||
* <p>
|
||||
* The {@link jdk.jshell.spi} package specifies a Service Provider Interface (SPI)
|
||||
* for defining execution engine implementations for tools based on the
|
||||
* {@link jdk.jshell} API. The {@link jdk.jshell.execution} package provides
|
||||
* standard implementations of {@link jdk.jshell.spi} interfaces and supporting code. It
|
||||
* also serves as a library of functionality for defining new execution engine
|
||||
* implementations.
|
||||
* </p>
|
||||
* <p>
|
||||
* The {@link jdk.jshell.tool} supports programmatically launching the
|
||||
* "jshell tool".
|
||||
* </p>
|
||||
* <p>
|
||||
* The {@link jdk.jshell.execution} package contains implementations of the
|
||||
* interfaces in {@link jdk.jshell.spi}. Otherwise, the four packages are
|
||||
* independent, operate at different levels, and do not share functionality or
|
||||
* definitions.
|
||||
* </p>
|
||||
*/
|
||||
module jdk.jshell {
|
||||
requires transitive java.compiler;
|
||||
requires transitive jdk.jdi;
|
||||
requires java.prefs;
|
||||
requires transitive java.prefs;
|
||||
requires jdk.compiler;
|
||||
requires jdk.internal.le;
|
||||
requires jdk.internal.ed;
|
||||
@ -40,6 +64,9 @@ module jdk.jshell {
|
||||
exports jdk.jshell;
|
||||
exports jdk.jshell.spi;
|
||||
exports jdk.jshell.execution;
|
||||
exports jdk.jshell.tool;
|
||||
|
||||
uses jdk.internal.editor.spi.BuildInEditorProvider;
|
||||
|
||||
provides javax.tools.Tool with jdk.internal.jshell.tool.JShellToolProvider;
|
||||
}
|
||||
|
@ -43,22 +43,73 @@ import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import jdk.internal.jshell.tool.JShellTool;
|
||||
import jdk.internal.jshell.tool.JShellToolBuilder;
|
||||
import jdk.jshell.SourceCodeAnalysis.Suggestion;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
@Test
|
||||
public class CommandCompletionTest extends ReplToolTesting {
|
||||
|
||||
public void testCommand() {
|
||||
assertCompletion("/deb|", false);
|
||||
assertCompletion("/re|", false, "/reload ", "/reset ");
|
||||
assertCompletion("/h|", false, "/help ", "/history ");
|
||||
|
||||
private JShellTool repl;
|
||||
|
||||
@Override
|
||||
protected void testRawRun(Locale locale, String[] args) {
|
||||
repl = ((JShellToolBuilder) builder(locale))
|
||||
.rawTool();
|
||||
try {
|
||||
repl.start(args);
|
||||
} catch (Exception ex) {
|
||||
fail("Repl tool died with exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void assertCompletion(boolean after, String code, boolean isSmart, String... expected) {
|
||||
if (!after) {
|
||||
setCommandInput("\n");
|
||||
} else {
|
||||
assertCompletion(code, isSmart, expected);
|
||||
}
|
||||
}
|
||||
|
||||
public void assertCompletion(String code, boolean isSmart, String... expected) {
|
||||
List<String> completions = computeCompletions(code, isSmart);
|
||||
assertEquals(completions, Arrays.asList(expected), "Command: " + code + ", output: " +
|
||||
completions.toString());
|
||||
}
|
||||
|
||||
private List<String> computeCompletions(String code, boolean isSmart) {
|
||||
int cursor = code.indexOf('|');
|
||||
code = code.replace("|", "");
|
||||
assertTrue(cursor > -1, "'|' not found: " + code);
|
||||
List<Suggestion> completions =
|
||||
repl.commandCompletionSuggestions(code, cursor, new int[] {-1}); //XXX: ignoring anchor for now
|
||||
return completions.stream()
|
||||
.filter(s -> isSmart == s.matchesType())
|
||||
.map(s -> s.continuation())
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommand() {
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/deb|", false),
|
||||
a -> assertCompletion(a, "/re|", false, "/reload ", "/reset "),
|
||||
a -> assertCompletion(a, "/h|", false, "/help ", "/history ")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testList() {
|
||||
test(false, new String[] {"--no-startup"},
|
||||
a -> assertCompletion(a, "/l|", false, "/list "),
|
||||
@ -72,6 +123,7 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDrop() {
|
||||
test(false, new String[] {"--no-startup"},
|
||||
a -> assertCompletion(a, "/d|", false, "/drop "),
|
||||
@ -83,6 +135,7 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEdit() {
|
||||
test(false, new String[]{"--no-startup"},
|
||||
a -> assertCompletion(a, "/e|", false, "/edit ", "/exit "),
|
||||
@ -101,31 +154,38 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHelp() {
|
||||
assertCompletion("/help |", false,
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/help |", false,
|
||||
"/! ", "/-<n> ", "/<id> ", "/? ", "/classpath ", "/drop ",
|
||||
"/edit ", "/exit ", "/help ", "/history ", "/imports ",
|
||||
"/list ", "/methods ", "/open ", "/reload ", "/reset ",
|
||||
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts ");
|
||||
assertCompletion("/? |", false,
|
||||
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts "),
|
||||
a -> assertCompletion(a, "/? |", false,
|
||||
"/! ", "/-<n> ", "/<id> ", "/? ", "/classpath ", "/drop ",
|
||||
"/edit ", "/exit ", "/help ", "/history ", "/imports ",
|
||||
"/list ", "/methods ", "/open ", "/reload ", "/reset ",
|
||||
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts ");
|
||||
assertCompletion("/help /s|", false,
|
||||
"/save ", "/set ");
|
||||
assertCompletion("/help /set |", false,
|
||||
"editor", "feedback", "format", "mode", "prompt", "start", "truncation");
|
||||
assertCompletion("/help /edit |", false);
|
||||
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts "),
|
||||
a -> assertCompletion(a, "/help /s|", false,
|
||||
"/save ", "/set "),
|
||||
a -> assertCompletion(a, "/help /set |", false,
|
||||
"editor", "feedback", "format", "mode", "prompt", "start", "truncation"),
|
||||
a -> assertCompletion(a, "/help /edit |", false)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReload() {
|
||||
assertCompletion("/reload |", false, "-quiet ", "-restore ");
|
||||
assertCompletion("/reload -restore |", false, "-quiet");
|
||||
assertCompletion("/reload -quiet |", false, "-restore");
|
||||
assertCompletion("/reload -restore -quiet |", false);
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarsMethodsTypes() {
|
||||
test(false, new String[]{"--no-startup"},
|
||||
a -> assertCompletion(a, "/v|", false, "/vars "),
|
||||
@ -141,36 +201,53 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpen() throws IOException {
|
||||
Compiler compiler = new Compiler();
|
||||
assertCompletion("/o|", false, "/open ");
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/o|", false, "/open ")
|
||||
);
|
||||
List<String> p1 = listFiles(Paths.get(""));
|
||||
getRootDirectories().forEach(s -> p1.add(s.toString()));
|
||||
Collections.sort(p1);
|
||||
assertCompletion("/open |", false, p1.toArray(new String[p1.size()]));
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/open |", false, p1.toArray(new String[p1.size()]))
|
||||
);
|
||||
Path classDir = compiler.getClassDir();
|
||||
List<String> p2 = listFiles(classDir);
|
||||
assertCompletion("/open " + classDir + "/|", false, p2.toArray(new String[p2.size()]));
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/open " + classDir + "/|", false, p2.toArray(new String[p2.size()]))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSave() throws IOException {
|
||||
Compiler compiler = new Compiler();
|
||||
assertCompletion("/s|", false, "/save ", "/set ");
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/s|", false, "/save ", "/set ")
|
||||
);
|
||||
List<String> p1 = listFiles(Paths.get(""));
|
||||
Collections.addAll(p1, "-all ", "-history ", "-start ");
|
||||
getRootDirectories().forEach(s -> p1.add(s.toString()));
|
||||
Collections.sort(p1);
|
||||
assertCompletion("/save |", false, p1.toArray(new String[p1.size()]));
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/save |", false, p1.toArray(new String[p1.size()]))
|
||||
);
|
||||
Path classDir = compiler.getClassDir();
|
||||
List<String> p2 = listFiles(classDir);
|
||||
assertCompletion("/save " + classDir + "/|",
|
||||
false, p2.toArray(new String[p2.size()]));
|
||||
assertCompletion("/save -all " + classDir + "/|",
|
||||
false, p2.toArray(new String[p2.size()]));
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/save " + classDir + "/|",
|
||||
false, p2.toArray(new String[p2.size()])),
|
||||
a -> assertCompletion(a, "/save -all " + classDir + "/|",
|
||||
false, p2.toArray(new String[p2.size()]))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassPath() throws IOException {
|
||||
assertCompletion("/classp|", false, "/classpath ");
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/classp|", false, "/classpath ")
|
||||
);
|
||||
Compiler compiler = new Compiler();
|
||||
Path outDir = compiler.getPath("testClasspathCompletion");
|
||||
Files.createDirectories(outDir);
|
||||
@ -182,9 +259,12 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
compiler.jar(outDir, jarName, "pkg/A.class");
|
||||
compiler.getPath(outDir).resolve(jarName);
|
||||
List<String> paths = listFiles(outDir, CLASSPATH_FILTER);
|
||||
assertCompletion("/classpath " + outDir + "/|", false, paths.toArray(new String[paths.size()]));
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/classpath " + outDir + "/|", false, paths.toArray(new String[paths.size()]))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserHome() throws IOException {
|
||||
List<String> completions;
|
||||
Path home = Paths.get(System.getProperty("user.home"));
|
||||
@ -194,9 +274,12 @@ public class CommandCompletionTest extends ReplToolTesting {
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
assertCompletion("/classpath ~/|", false, completions.toArray(new String[completions.size()]));
|
||||
testNoStartUp(
|
||||
a -> assertCompletion(a, "/classpath ~/|", false, completions.toArray(new String[completions.size()]))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSet() throws IOException {
|
||||
List<String> p1 = listFiles(Paths.get(""));
|
||||
getRootDirectories().forEach(s -> p1.add(s.toString()));
|
||||
|
@ -32,13 +32,29 @@
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Locale;
|
||||
import jdk.internal.jline.extra.EditingHistory;
|
||||
import org.testng.annotations.Test;
|
||||
import jdk.internal.jshell.tool.JShellTool;
|
||||
import jdk.internal.jshell.tool.JShellToolBuilder;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class HistoryTest extends ReplToolTesting {
|
||||
|
||||
private JShellTool repl;
|
||||
|
||||
@Override
|
||||
protected void testRawRun(Locale locale, String[] args) {
|
||||
repl = ((JShellToolBuilder) builder(locale))
|
||||
.rawTool();
|
||||
try {
|
||||
repl.start(args);
|
||||
} catch (Exception ex) {
|
||||
fail("Repl tool died with exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistory() {
|
||||
test(
|
||||
a -> {if (!a) setCommandInput("void test() {\n");},
|
||||
@ -76,6 +92,7 @@ public class HistoryTest extends ReplToolTesting {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test8166744() {
|
||||
test(
|
||||
a -> {if (!a) setCommandInput("class C {\n");},
|
||||
|
@ -25,7 +25,6 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -36,17 +35,15 @@ import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.prefs.AbstractPreferences;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.internal.jshell.tool.JShellTool;
|
||||
import jdk.jshell.SourceCodeAnalysis.Suggestion;
|
||||
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
|
||||
import jdk.jshell.tool.JavaShellToolBuilder;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
@ -92,11 +89,9 @@ public class ReplToolTesting {
|
||||
private Map<String, ClassInfo> classes;
|
||||
private Map<String, ImportInfo> imports;
|
||||
private boolean isDefaultStartUp = true;
|
||||
private Preferences prefs;
|
||||
private Map<String, String> prefsMap;
|
||||
private Map<String, String> envvars;
|
||||
|
||||
public JShellTool repl = null;
|
||||
|
||||
public interface ReplTest {
|
||||
void run(boolean after);
|
||||
}
|
||||
@ -202,6 +197,10 @@ public class ReplToolTesting {
|
||||
test(Locale.ROOT, isDefaultStartUp, args, DEFAULT_STARTUP_MESSAGE, tests);
|
||||
}
|
||||
|
||||
public void testNoStartUp(ReplTest... tests) {
|
||||
test(Locale.ROOT, false, new String[] {"--no-startup"}, DEFAULT_STARTUP_MESSAGE, tests);
|
||||
}
|
||||
|
||||
public void test(Locale locale, boolean isDefaultStartUp, String[] args, String startUpMessage, ReplTest... tests) {
|
||||
this.isDefaultStartUp = isDefaultStartUp;
|
||||
initSnippets();
|
||||
@ -232,7 +231,7 @@ public class ReplToolTesting {
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() {
|
||||
prefs = new MemoryPreferences();
|
||||
prefsMap = new HashMap<>();
|
||||
envvars = new HashMap<>();
|
||||
}
|
||||
|
||||
@ -240,7 +239,25 @@ public class ReplToolTesting {
|
||||
envvars.put(name, value);
|
||||
}
|
||||
|
||||
public void testRaw(Locale locale, String[] args, ReplTest... tests) {
|
||||
protected JavaShellToolBuilder builder(Locale locale) {
|
||||
return JavaShellToolBuilder
|
||||
.builder()
|
||||
.in(cmdin, userin)
|
||||
.out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout))
|
||||
.err(new PrintStream(cmderr), new PrintStream(usererr))
|
||||
.persistence(prefsMap)
|
||||
.env(envvars)
|
||||
.locale(locale)
|
||||
.promptCapture(true);
|
||||
}
|
||||
|
||||
private void testRaw(Locale locale, String[] args, ReplTest... tests) {
|
||||
testRawInit(tests);
|
||||
testRawRun(locale, args);
|
||||
testRawCheck(locale);
|
||||
}
|
||||
|
||||
private void testRawInit(ReplTest... tests) {
|
||||
cmdin = new WaitingTestingInputStream();
|
||||
cmdout = new ByteArrayOutputStream();
|
||||
cmderr = new ByteArrayOutputStream();
|
||||
@ -248,23 +265,18 @@ public class ReplToolTesting {
|
||||
userin = new TestingInputStream();
|
||||
userout = new ByteArrayOutputStream();
|
||||
usererr = new ByteArrayOutputStream();
|
||||
repl = new JShellTool(
|
||||
cmdin,
|
||||
new PrintStream(cmdout),
|
||||
new PrintStream(cmderr),
|
||||
new PrintStream(console),
|
||||
userin,
|
||||
new PrintStream(userout),
|
||||
new PrintStream(usererr),
|
||||
prefs,
|
||||
envvars,
|
||||
locale);
|
||||
repl.testPrompt = true;
|
||||
}
|
||||
|
||||
protected void testRawRun(Locale locale, String[] args) {
|
||||
try {
|
||||
repl.start(args);
|
||||
builder(locale)
|
||||
.run(args);
|
||||
} catch (Exception ex) {
|
||||
fail("Repl tool died with exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void testRawCheck(Locale locale) {
|
||||
// perform internal consistency checks on state, if desired
|
||||
String cos = getCommandOutput();
|
||||
String ceos = getCommandErrorOutput();
|
||||
@ -272,9 +284,9 @@ public class ReplToolTesting {
|
||||
String ueos = getUserErrorOutput();
|
||||
assertTrue((cos.isEmpty() || cos.startsWith("| Goodbye") || !locale.equals(Locale.ROOT)),
|
||||
"Expected a goodbye, but got: " + cos);
|
||||
assertTrue(ceos.isEmpty(), "Expected empty error output, got: " + ceos);
|
||||
assertTrue(uos.isEmpty(), "Expected empty output, got: " + uos);
|
||||
assertTrue(ueos.isEmpty(), "Expected empty error output, got: " + ueos);
|
||||
assertTrue(ceos.isEmpty(), "Expected empty command error output, got: " + ceos);
|
||||
assertTrue(uos.isEmpty(), "Expected empty user output, got: " + uos);
|
||||
assertTrue(ueos.isEmpty(), "Expected empty user error output, got: " + ueos);
|
||||
}
|
||||
|
||||
public void assertReset(boolean after, String cmd) {
|
||||
@ -454,36 +466,6 @@ public class ReplToolTesting {
|
||||
}
|
||||
}
|
||||
|
||||
public void assertCompletion(boolean after, String code, boolean isSmart, String... expected) {
|
||||
if (!after) {
|
||||
setCommandInput("\n");
|
||||
} else {
|
||||
assertCompletion(code, isSmart, expected);
|
||||
}
|
||||
}
|
||||
|
||||
public void assertCompletion(String code, boolean isSmart, String... expected) {
|
||||
List<String> completions = computeCompletions(code, isSmart);
|
||||
assertEquals(completions, Arrays.asList(expected), "Command: " + code + ", output: " +
|
||||
completions.toString());
|
||||
}
|
||||
|
||||
private List<String> computeCompletions(String code, boolean isSmart) {
|
||||
JShellTool js = this.repl != null ? this.repl
|
||||
: new JShellTool(null, null, null, null, null, null, null,
|
||||
prefs, envvars, Locale.ROOT);
|
||||
int cursor = code.indexOf('|');
|
||||
code = code.replace("|", "");
|
||||
assertTrue(cursor > -1, "'|' not found: " + code);
|
||||
List<Suggestion> completions =
|
||||
js.commandCompletionSuggestions(code, cursor, new int[] {-1}); //XXX: ignoring anchor for now
|
||||
return completions.stream()
|
||||
.filter(s -> isSmart == s.matchesType())
|
||||
.map(s -> s.continuation())
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Consumer<String> assertStartsWith(String prefix) {
|
||||
return (output) -> assertTrue(output.startsWith(prefix), "Output: \'" + output + "' does not start with: " + prefix);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test 8151754 8080883 8160089 8166581
|
||||
* @test 8151754 8080883 8160089 8170162 8166581
|
||||
* @summary Testing start-up options.
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
@ -33,19 +33,21 @@
|
||||
* @run testng StartOptionTest
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jdk.internal.jshell.tool.JShellTool;
|
||||
import javax.tools.Tool;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import jdk.jshell.tool.JavaShellToolBuilder;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import static org.testng.Assert.fail;
|
||||
@ -59,21 +61,26 @@ public class StartOptionTest {
|
||||
private ByteArrayOutputStream userout;
|
||||
private ByteArrayOutputStream usererr;
|
||||
|
||||
private JShellTool getShellTool() {
|
||||
return new JShellTool(
|
||||
new TestingInputStream(),
|
||||
new PrintStream(cmdout),
|
||||
new PrintStream(cmderr),
|
||||
new PrintStream(console),
|
||||
null,
|
||||
new PrintStream(userout),
|
||||
new PrintStream(usererr),
|
||||
new ReplToolTesting.MemoryPreferences(),
|
||||
new HashMap<>(),
|
||||
Locale.ROOT);
|
||||
private JavaShellToolBuilder builder() {
|
||||
return JavaShellToolBuilder
|
||||
.builder()
|
||||
.out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout))
|
||||
.err(new PrintStream(cmderr), new PrintStream(usererr))
|
||||
.persistence(new HashMap<>())
|
||||
.env(new HashMap<>())
|
||||
.locale(Locale.ROOT);
|
||||
}
|
||||
|
||||
private void check(ByteArrayOutputStream str, Consumer<String> checkOut, String label) {
|
||||
private void runShell(String... args) {
|
||||
try {
|
||||
builder()
|
||||
.run(args);
|
||||
} catch (Exception ex) {
|
||||
fail("Repl tool died with exception", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected void check(ByteArrayOutputStream str, Consumer<String> checkOut, String label) {
|
||||
byte[] bytes = str.toByteArray();
|
||||
str.reset();
|
||||
String out = new String(bytes, StandardCharsets.UTF_8);
|
||||
@ -84,18 +91,28 @@ public class StartOptionTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void start(Consumer<String> checkOutput, Consumer<String> checkError, String... args) throws Exception {
|
||||
JShellTool tool = getShellTool();
|
||||
tool.start(args);
|
||||
check(cmdout, checkOutput, "cmdout");
|
||||
protected void start(Consumer<String> checkCmdOutput,
|
||||
Consumer<String> checkUserOutput, Consumer<String> checkError,
|
||||
String... args) throws Exception {
|
||||
runShell(args);
|
||||
check(cmdout, checkCmdOutput, "cmdout");
|
||||
check(cmderr, checkError, "cmderr");
|
||||
check(console, null, "console");
|
||||
check(userout, null, "userout");
|
||||
check(userout, checkUserOutput, "userout");
|
||||
check(usererr, null, "usererr");
|
||||
}
|
||||
|
||||
private void start(String expectedOutput, String expectedError, String... args) throws Exception {
|
||||
start(s -> assertEquals(s.trim(), expectedOutput, "cmdout: "), s -> assertEquals(s.trim(), expectedError, "cmderr: "), args);
|
||||
protected void start(String expectedCmdOutput, String expectedError, String... args) throws Exception {
|
||||
startWithUserOutput(expectedCmdOutput, "", expectedError, args);
|
||||
}
|
||||
|
||||
private void startWithUserOutput(String expectedCmdOutput, String expectedUserOutput,
|
||||
String expectedError, String... args) throws Exception {
|
||||
start(
|
||||
s -> assertEquals(s.trim(), expectedCmdOutput, "cmdout: "),
|
||||
s -> assertEquals(s.trim(), expectedUserOutput, "userout: "),
|
||||
s -> assertEquals(s.trim(), expectedError, "cmderr: "),
|
||||
args);
|
||||
}
|
||||
|
||||
@BeforeMethod
|
||||
@ -107,21 +124,31 @@ public class StartOptionTest {
|
||||
usererr = new ByteArrayOutputStream();
|
||||
}
|
||||
|
||||
@Test
|
||||
protected String writeToFile(String stuff) throws Exception {
|
||||
Compiler compiler = new Compiler();
|
||||
Path p = compiler.getPath("doit.repl");
|
||||
compiler.writeToFile(p, stuff);
|
||||
return p.toString();
|
||||
}
|
||||
|
||||
public void testCommandFile() throws Exception {
|
||||
String fn = writeToFile("String str = \"Hello \"\n/list\nSystem.out.println(str + str)\n/exit\n");
|
||||
startWithUserOutput("1 : String str = \"Hello \";", "Hello Hello", "", "--no-startup", fn, "-s");
|
||||
}
|
||||
|
||||
public void testUsage() throws Exception {
|
||||
for (String opt : new String[]{"-h", "--help"}) {
|
||||
start(s -> {
|
||||
assertTrue(s.split("\n").length >= 7, "Not enough usage lines: " + s);
|
||||
assertTrue(s.startsWith("Usage: jshell <options>"), "Unexpect usage start: " + s);
|
||||
}, null, opt);
|
||||
}, null, null, opt);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnknown() throws Exception {
|
||||
start(s -> { },
|
||||
start(null, null,
|
||||
s -> assertEquals(s.trim(), "Unknown option: u"), "-unknown");
|
||||
start(s -> { },
|
||||
start(null, null,
|
||||
s -> assertEquals(s.trim(), "Unknown option: unknown"), "--unknown");
|
||||
}
|
||||
|
||||
@ -138,7 +165,7 @@ public class StartOptionTest {
|
||||
|
||||
public void testStartupFailedOption() throws Exception {
|
||||
try {
|
||||
start("", "", "-R-hoge-foo-bar");
|
||||
builder().run("-R-hoge-foo-bar");
|
||||
} catch (IllegalStateException ex) {
|
||||
String s = ex.getMessage();
|
||||
assertTrue(s.startsWith("Launching JShell execution engine threw: Failed remote"), s);
|
||||
@ -151,7 +178,6 @@ public class StartOptionTest {
|
||||
start("", "File 'UNKNOWN' for '--startup' is not found.", "--startup", "UNKNOWN");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClasspath() throws Exception {
|
||||
for (String cp : new String[] {"--class-path"}) {
|
||||
start("", "Only one --class-path option may be used.", cp, ".", "--class-path", ".");
|
||||
@ -159,7 +185,6 @@ public class StartOptionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFeedbackOptionConflict() throws Exception {
|
||||
start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.",
|
||||
"--feedback", "concise", "--feedback", "verbose");
|
||||
@ -173,15 +198,13 @@ public class StartOptionTest {
|
||||
start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-s");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegFeedbackOption() throws Exception {
|
||||
start("", "Argument to feedback missing.", "--feedback");
|
||||
start("", "Does not match any current feedback mode: blorp -- --feedback blorp", "--feedback", "blorp");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVersion() throws Exception {
|
||||
start(s -> assertTrue(s.startsWith("jshell"), "unexpected version: " + s), null, "--version");
|
||||
start(s -> assertTrue(s.startsWith("jshell"), "unexpected version: " + s), null, null, "--version");
|
||||
}
|
||||
|
||||
@AfterMethod
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643
|
||||
* @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643 8170162
|
||||
* @summary Tests for Basic tests for REPL tool
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
@ -49,8 +49,6 @@ import java.util.Scanner;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ -305,22 +303,18 @@ public class ToolBasicTest extends ReplToolTesting {
|
||||
}
|
||||
|
||||
public void testStartupFileOption() {
|
||||
try {
|
||||
Compiler compiler = new Compiler();
|
||||
Path startup = compiler.getPath("StartupFileOption/startup.txt");
|
||||
compiler.writeToFile(startup, "class A { public String toString() { return \"A\"; } }");
|
||||
test(new String[]{"--startup", startup.toString()},
|
||||
(a) -> evaluateExpression(a, "A", "new A()", "A")
|
||||
);
|
||||
test(new String[]{"--no-startup"},
|
||||
(a) -> assertCommandCheckOutput(a, "printf(\"\")", assertStartsWith("| Error:\n| cannot find symbol"))
|
||||
);
|
||||
test(
|
||||
(a) -> assertCommand(a, "printf(\"A\")", "", "", null, "A", "")
|
||||
);
|
||||
} finally {
|
||||
removeStartup();
|
||||
}
|
||||
Compiler compiler = new Compiler();
|
||||
Path startup = compiler.getPath("StartupFileOption/startup.txt");
|
||||
compiler.writeToFile(startup, "class A { public String toString() { return \"A\"; } }");
|
||||
test(new String[]{"--startup", startup.toString()},
|
||||
(a) -> evaluateExpression(a, "A", "new A()", "A")
|
||||
);
|
||||
test(new String[]{"--no-startup"},
|
||||
(a) -> assertCommandCheckOutput(a, "printf(\"\")", assertStartsWith("| Error:\n| cannot find symbol"))
|
||||
);
|
||||
test(
|
||||
(a) -> assertCommand(a, "printf(\"A\")", "", "", null, "A", "")
|
||||
);
|
||||
}
|
||||
|
||||
public void testLoadingFromArgs() {
|
||||
@ -436,45 +430,34 @@ public class ToolBasicTest extends ReplToolTesting {
|
||||
assertEquals(Files.readAllLines(path), output);
|
||||
}
|
||||
|
||||
public void testStartRetain() throws BackingStoreException {
|
||||
try {
|
||||
Compiler compiler = new Compiler();
|
||||
Path startUpFile = compiler.getPath("startUp.txt");
|
||||
test(
|
||||
(a) -> assertVariable(a, "int", "a"),
|
||||
(a) -> assertVariable(a, "double", "b", "10", "10.0"),
|
||||
(a) -> assertMethod(a, "void f() {}", "()V", "f"),
|
||||
(a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
|
||||
(a) -> assertCommand(a, "/save " + startUpFile.toString(), null),
|
||||
(a) -> assertCommand(a, "/set start -retain " + startUpFile.toString(), null)
|
||||
);
|
||||
Path unknown = compiler.getPath("UNKNOWN");
|
||||
test(
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set start -retain " + unknown.toString(),
|
||||
"| File '" + unknown + "' for '/set start' is not found.")
|
||||
);
|
||||
test(false, new String[0],
|
||||
(a) -> {
|
||||
loadVariable(a, "int", "a");
|
||||
loadVariable(a, "double", "b", "10.0", "10.0");
|
||||
loadMethod(a, "void f() {}", "()void", "f");
|
||||
loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
|
||||
assertCommandCheckOutput(a, "/types", assertClasses());
|
||||
},
|
||||
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
|
||||
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
|
||||
(a) -> assertCommandCheckOutput(a, "/imports", assertImports())
|
||||
);
|
||||
} finally {
|
||||
removeStartup();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeStartup() {
|
||||
Preferences preferences = Preferences.userRoot().node("tool/JShell");
|
||||
if (preferences != null) {
|
||||
preferences.remove("STARTUP");
|
||||
}
|
||||
public void testStartRetain() {
|
||||
Compiler compiler = new Compiler();
|
||||
Path startUpFile = compiler.getPath("startUp.txt");
|
||||
test(
|
||||
(a) -> assertVariable(a, "int", "a"),
|
||||
(a) -> assertVariable(a, "double", "b", "10", "10.0"),
|
||||
(a) -> assertMethod(a, "void f() {}", "()V", "f"),
|
||||
(a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
|
||||
(a) -> assertCommand(a, "/save " + startUpFile.toString(), null),
|
||||
(a) -> assertCommand(a, "/set start -retain " + startUpFile.toString(), null)
|
||||
);
|
||||
Path unknown = compiler.getPath("UNKNOWN");
|
||||
test(
|
||||
(a) -> assertCommandOutputStartsWith(a, "/set start -retain " + unknown.toString(),
|
||||
"| File '" + unknown + "' for '/set start' is not found.")
|
||||
);
|
||||
test(false, new String[0],
|
||||
(a) -> {
|
||||
loadVariable(a, "int", "a");
|
||||
loadVariable(a, "double", "b", "10.0", "10.0");
|
||||
loadMethod(a, "void f() {}", "()void", "f");
|
||||
loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
|
||||
assertCommandCheckOutput(a, "/types", assertClasses());
|
||||
},
|
||||
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
|
||||
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
|
||||
(a) -> assertCommandCheckOutput(a, "/imports", assertImports())
|
||||
);
|
||||
}
|
||||
|
||||
public void testStartSave() throws IOException {
|
||||
|
93
langtools/test/jdk/jshell/ToolProviderTest.java
Normal file
93
langtools/test/jdk/jshell/ToolProviderTest.java
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.function.Consumer;
|
||||
import javax.tools.Tool;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8170044
|
||||
* @summary Test ServiceLoader launching of jshell tool
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.main
|
||||
* jdk.jdeps/com.sun.tools.javap
|
||||
* jdk.jshell/jdk.internal.jshell.tool
|
||||
* @library /tools/lib
|
||||
* @build Compiler toolbox.ToolBox
|
||||
* @run testng ToolProviderTest
|
||||
*/
|
||||
@Test
|
||||
public class ToolProviderTest extends StartOptionTest {
|
||||
|
||||
private ByteArrayOutputStream cmdout;
|
||||
private ByteArrayOutputStream cmderr;
|
||||
|
||||
@BeforeMethod
|
||||
@Override
|
||||
public void setUp() {
|
||||
cmdout = new ByteArrayOutputStream();
|
||||
cmderr = new ByteArrayOutputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start(Consumer<String> checkCmdOutput,
|
||||
Consumer<String> checkUserOutput, Consumer<String> checkError,
|
||||
String... args) throws Exception {
|
||||
if (runShellServiceLoader(args) != 0) {
|
||||
fail("Repl tool failed");
|
||||
}
|
||||
check(cmdout, checkCmdOutput, "cmdout");
|
||||
check(cmderr, checkError, "cmderr");
|
||||
}
|
||||
|
||||
private int runShellServiceLoader(String... args) {
|
||||
ServiceLoader<Tool> sl = ServiceLoader.load(Tool.class);
|
||||
for (Tool provider : sl) {
|
||||
if (provider.name().equals("jshell")) {
|
||||
return provider.run(new ByteArrayInputStream(new byte[0]), cmdout, cmderr, args);
|
||||
}
|
||||
}
|
||||
throw new AssertionError("Repl tool not found by ServiceLoader: " + sl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testCommandFile() throws Exception {
|
||||
String fn = writeToFile("String str = \"Hello \"\n/list\nSystem.out.println(str + str)\n/exit\n");
|
||||
start("1 : String str = \"Hello \";" + "\n" + "Hello Hello", "", "--no-startup", fn, "-s");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testStartupFailedOption() throws Exception {
|
||||
if (runShellServiceLoader("-R-hoge-foo-bar") == 0) {
|
||||
fail("Expected tool failure");
|
||||
} else {
|
||||
check(cmderr, s -> s.startsWith("Launching JShell execution engine threw: Failed remote"), "cmderr");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user