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.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.prefs.BackingStoreException;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@ -97,7 +96,7 @@ class ConsoleIOContext extends IOContext {
|
|||||||
List<String> persistenHistory = Stream.of(repl.prefs.keys())
|
List<String> persistenHistory = Stream.of(repl.prefs.keys())
|
||||||
.filter(key -> key.startsWith(HISTORY_LINE_PREFIX))
|
.filter(key -> key.startsWith(HISTORY_LINE_PREFIX))
|
||||||
.sorted()
|
.sorted()
|
||||||
.map(key -> repl.prefs.get(key, null))
|
.map(key -> repl.prefs.get(key))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
in.setHistory(history = new EditingHistory(in, persistenHistory) {
|
in.setHistory(history = new EditingHistory(in, persistenHistory) {
|
||||||
@Override protected boolean isComplete(CharSequence input) {
|
@Override protected boolean isComplete(CharSequence input) {
|
||||||
@ -215,23 +214,21 @@ class ConsoleIOContext extends IOContext {
|
|||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
//save history:
|
//save history:
|
||||||
try {
|
for (String key : repl.prefs.keys()) {
|
||||||
for (String key : repl.prefs.keys()) {
|
if (key.startsWith(HISTORY_LINE_PREFIX)) {
|
||||||
if (key.startsWith(HISTORY_LINE_PREFIX))
|
repl.prefs.remove(key);
|
||||||
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();
|
in.shutdown();
|
||||||
try {
|
try {
|
||||||
in.getTerminal().restore();
|
in.getTerminal().restore();
|
||||||
@ -417,6 +414,7 @@ class ConsoleIOContext extends IOContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void beforeUserCode() {
|
public void beforeUserCode() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
inputBytes = null;
|
inputBytes = null;
|
||||||
@ -424,6 +422,7 @@ class ConsoleIOContext extends IOContext {
|
|||||||
input.setState(State.BUFFER);
|
input.setState(State.BUFFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void afterUserCode() {
|
public void afterUserCode() {
|
||||||
input.setState(State.WAIT);
|
input.setState(State.WAIT);
|
||||||
}
|
}
|
||||||
|
@ -136,25 +136,12 @@ public class JShellTool implements MessageHandler {
|
|||||||
final InputStream userin;
|
final InputStream userin;
|
||||||
final PrintStream userout;
|
final PrintStream userout;
|
||||||
final PrintStream usererr;
|
final PrintStream usererr;
|
||||||
final Preferences prefs;
|
final PersistentStorage prefs;
|
||||||
final Map<String, String> envvars;
|
final Map<String, String> envvars;
|
||||||
final Locale locale;
|
final Locale locale;
|
||||||
|
|
||||||
final Feedback feedback = new Feedback();
|
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).
|
* The complete constructor for the tool (used by test harnesses).
|
||||||
* @param cmdin command line input -- snippets and commands
|
* @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 userin code execution input, or null to use IOContext
|
||||||
* @param userout code execution output -- System.out.printf("hi")
|
* @param userout code execution output -- System.out.printf("hi")
|
||||||
* @param usererr code execution error stream -- System.err.printf("Oops")
|
* @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 envvars environment variable mapping to use
|
||||||
* @param locale locale to use
|
* @param locale locale to use
|
||||||
*/
|
*/
|
||||||
public JShellTool(InputStream cmdin, PrintStream cmdout, PrintStream cmderr,
|
JShellTool(InputStream cmdin, PrintStream cmdout, PrintStream cmderr,
|
||||||
PrintStream console,
|
PrintStream console,
|
||||||
InputStream userin, PrintStream userout, PrintStream usererr,
|
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.cmdin = cmdin;
|
||||||
this.cmdout = cmdout;
|
this.cmdout = cmdout;
|
||||||
this.cmderr = cmderr;
|
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 {
|
public void start(String[] args) throws Exception {
|
||||||
List<String> loadList = processCommandArgs(args);
|
List<String> loadList = processCommandArgs(args);
|
||||||
if (loadList == null) {
|
if (loadList == null) {
|
||||||
@ -502,7 +479,7 @@ public class JShellTool implements MessageHandler {
|
|||||||
private void start(IOContext in, List<String> loadList) {
|
private void start(IOContext in, List<String> loadList) {
|
||||||
// If startup hasn't been set by command line, set from retained/default
|
// If startup hasn't been set by command line, set from retained/default
|
||||||
if (startup == null) {
|
if (startup == null) {
|
||||||
startup = prefs.get(STARTUP_KEY, null);
|
startup = prefs.get(STARTUP_KEY);
|
||||||
if (startup == null) {
|
if (startup == null) {
|
||||||
startup = DEFAULT_STARTUP;
|
startup = DEFAULT_STARTUP;
|
||||||
}
|
}
|
||||||
@ -513,7 +490,7 @@ public class JShellTool implements MessageHandler {
|
|||||||
resetState(); // Initialize
|
resetState(); // Initialize
|
||||||
|
|
||||||
// Read replay history from last jshell session into previous history
|
// 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) {
|
if (prevReplay != null) {
|
||||||
replayableHistoryPrevious = Arrays.asList(prevReplay.split(RECORD_SEPARATOR));
|
replayableHistoryPrevious = Arrays.asList(prevReplay.split(RECORD_SEPARATOR));
|
||||||
}
|
}
|
||||||
@ -788,7 +765,7 @@ public class JShellTool implements MessageHandler {
|
|||||||
// These predefined modes are read-only
|
// These predefined modes are read-only
|
||||||
feedback.markModesReadOnly();
|
feedback.markModesReadOnly();
|
||||||
// Restore user defined modes retained on previous run with /set mode -retain
|
// 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 (encoded != null && !encoded.isEmpty()) {
|
||||||
if (!feedback.restoreEncodedModes(initmh, encoded)) {
|
if (!feedback.restoreEncodedModes(initmh, encoded)) {
|
||||||
// Catastrophic corruption -- remove the retained modes
|
// Catastrophic corruption -- remove the retained modes
|
||||||
@ -802,7 +779,7 @@ public class JShellTool implements MessageHandler {
|
|||||||
}
|
}
|
||||||
commandLineFeedbackMode = null;
|
commandLineFeedbackMode = null;
|
||||||
} else {
|
} else {
|
||||||
String fb = prefs.get(FEEDBACK_KEY, null);
|
String fb = prefs.get(FEEDBACK_KEY);
|
||||||
if (fb != null) {
|
if (fb != null) {
|
||||||
// Restore the feedback mode to use that was retained
|
// Restore the feedback mode to use that was retained
|
||||||
// on a previous run with /set feedback -retain
|
// on a previous run with /set feedback -retain
|
||||||
@ -1485,9 +1462,9 @@ public class JShellTool implements MessageHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns null if not stored in preferences
|
// returns null if not stored in preferences
|
||||||
static EditorSetting fromPrefs(Preferences prefs) {
|
static EditorSetting fromPrefs(PersistentStorage prefs) {
|
||||||
// Read retained editor setting (if any)
|
// Read retained editor setting (if any)
|
||||||
String editorString = prefs.get(EDITOR_KEY, "");
|
String editorString = prefs.get(EDITOR_KEY);
|
||||||
if (editorString == null || editorString.isEmpty()) {
|
if (editorString == null || editorString.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
} else if (editorString.equals(BUILT_IN_REP)) {
|
} 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);
|
prefs.remove(EDITOR_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toPrefs(Preferences prefs) {
|
void toPrefs(PersistentStorage prefs) {
|
||||||
prefs.put(EDITOR_KEY, (this == BUILT_IN_EDITOR)
|
prefs.put(EDITOR_KEY, (this == BUILT_IN_EDITOR)
|
||||||
? BUILT_IN_REP
|
? BUILT_IN_REP
|
||||||
: (wait ? WAIT_PREFIX : NORMAL_PREFIX) + String.join(RECORD_SEPARATOR, cmd));
|
: (wait ? WAIT_PREFIX : NORMAL_PREFIX) + String.join(RECORD_SEPARATOR, cmd));
|
||||||
@ -1676,7 +1653,7 @@ public class JShellTool implements MessageHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showSetStart() {
|
void showSetStart() {
|
||||||
String retained = prefs.get(STARTUP_KEY, null);
|
String retained = prefs.get(STARTUP_KEY);
|
||||||
if (retained != null) {
|
if (retained != null) {
|
||||||
showSetStart(true, retained);
|
showSetStart(true, retained);
|
||||||
}
|
}
|
||||||
@ -1774,6 +1751,7 @@ public class JShellTool implements MessageHandler {
|
|||||||
replayableHistory.subList(first + 1, replayableHistory.size()));
|
replayableHistory.subList(first + 1, replayableHistory.size()));
|
||||||
prefs.put(REPLAY_RESTORE_KEY, hist);
|
prefs.put(REPLAY_RESTORE_KEY, hist);
|
||||||
}
|
}
|
||||||
|
prefs.flush();
|
||||||
fluffmsg("jshell.msg.goodbye");
|
fluffmsg("jshell.msg.goodbye");
|
||||||
return true;
|
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
|
* Java™ Programming Language 'snippet' evaluating tools, such as
|
||||||
* Read-Eval-Print Loops (REPLs).
|
* 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 {
|
module jdk.jshell {
|
||||||
requires transitive java.compiler;
|
requires transitive java.compiler;
|
||||||
requires transitive jdk.jdi;
|
requires transitive jdk.jdi;
|
||||||
requires java.prefs;
|
requires transitive java.prefs;
|
||||||
requires jdk.compiler;
|
requires jdk.compiler;
|
||||||
requires jdk.internal.le;
|
requires jdk.internal.le;
|
||||||
requires jdk.internal.ed;
|
requires jdk.internal.ed;
|
||||||
@ -40,6 +64,9 @@ module jdk.jshell {
|
|||||||
exports jdk.jshell;
|
exports jdk.jshell;
|
||||||
exports jdk.jshell.spi;
|
exports jdk.jshell.spi;
|
||||||
exports jdk.jshell.execution;
|
exports jdk.jshell.execution;
|
||||||
|
exports jdk.jshell.tool;
|
||||||
|
|
||||||
uses jdk.internal.editor.spi.BuildInEditorProvider;
|
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.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
import org.testng.annotations.Test;
|
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 class CommandCompletionTest extends ReplToolTesting {
|
||||||
|
|
||||||
public void testCommand() {
|
|
||||||
assertCompletion("/deb|", false);
|
private JShellTool repl;
|
||||||
assertCompletion("/re|", false, "/reload ", "/reset ");
|
|
||||||
assertCompletion("/h|", false, "/help ", "/history ");
|
@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() {
|
public void testList() {
|
||||||
test(false, new String[] {"--no-startup"},
|
test(false, new String[] {"--no-startup"},
|
||||||
a -> assertCompletion(a, "/l|", false, "/list "),
|
a -> assertCompletion(a, "/l|", false, "/list "),
|
||||||
@ -72,6 +123,7 @@ public class CommandCompletionTest extends ReplToolTesting {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testDrop() {
|
public void testDrop() {
|
||||||
test(false, new String[] {"--no-startup"},
|
test(false, new String[] {"--no-startup"},
|
||||||
a -> assertCompletion(a, "/d|", false, "/drop "),
|
a -> assertCompletion(a, "/d|", false, "/drop "),
|
||||||
@ -83,6 +135,7 @@ public class CommandCompletionTest extends ReplToolTesting {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testEdit() {
|
public void testEdit() {
|
||||||
test(false, new String[]{"--no-startup"},
|
test(false, new String[]{"--no-startup"},
|
||||||
a -> assertCompletion(a, "/e|", false, "/edit ", "/exit "),
|
a -> assertCompletion(a, "/e|", false, "/edit ", "/exit "),
|
||||||
@ -101,31 +154,38 @@ public class CommandCompletionTest extends ReplToolTesting {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testHelp() {
|
public void testHelp() {
|
||||||
assertCompletion("/help |", false,
|
testNoStartUp(
|
||||||
|
a -> assertCompletion(a, "/help |", false,
|
||||||
"/! ", "/-<n> ", "/<id> ", "/? ", "/classpath ", "/drop ",
|
"/! ", "/-<n> ", "/<id> ", "/? ", "/classpath ", "/drop ",
|
||||||
"/edit ", "/exit ", "/help ", "/history ", "/imports ",
|
"/edit ", "/exit ", "/help ", "/history ", "/imports ",
|
||||||
"/list ", "/methods ", "/open ", "/reload ", "/reset ",
|
"/list ", "/methods ", "/open ", "/reload ", "/reset ",
|
||||||
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts ");
|
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts "),
|
||||||
assertCompletion("/? |", false,
|
a -> assertCompletion(a, "/? |", false,
|
||||||
"/! ", "/-<n> ", "/<id> ", "/? ", "/classpath ", "/drop ",
|
"/! ", "/-<n> ", "/<id> ", "/? ", "/classpath ", "/drop ",
|
||||||
"/edit ", "/exit ", "/help ", "/history ", "/imports ",
|
"/edit ", "/exit ", "/help ", "/history ", "/imports ",
|
||||||
"/list ", "/methods ", "/open ", "/reload ", "/reset ",
|
"/list ", "/methods ", "/open ", "/reload ", "/reset ",
|
||||||
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts ");
|
"/save ", "/set ", "/types ", "/vars ", "intro ", "shortcuts "),
|
||||||
assertCompletion("/help /s|", false,
|
a -> assertCompletion(a, "/help /s|", false,
|
||||||
"/save ", "/set ");
|
"/save ", "/set "),
|
||||||
assertCompletion("/help /set |", false,
|
a -> assertCompletion(a, "/help /set |", false,
|
||||||
"editor", "feedback", "format", "mode", "prompt", "start", "truncation");
|
"editor", "feedback", "format", "mode", "prompt", "start", "truncation"),
|
||||||
assertCompletion("/help /edit |", false);
|
a -> assertCompletion(a, "/help /edit |", false)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testReload() {
|
public void testReload() {
|
||||||
assertCompletion("/reload |", false, "-quiet ", "-restore ");
|
testNoStartUp(
|
||||||
assertCompletion("/reload -restore |", false, "-quiet");
|
a -> assertCompletion(a, "/reload |", false, "-quiet ", "-restore "),
|
||||||
assertCompletion("/reload -quiet |", false, "-restore");
|
a -> assertCompletion(a, "/reload -restore |", false, "-quiet"),
|
||||||
assertCompletion("/reload -restore -quiet |", false);
|
a -> assertCompletion(a, "/reload -quiet |", false, "-restore"),
|
||||||
|
a -> assertCompletion(a, "/reload -restore -quiet |", false)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testVarsMethodsTypes() {
|
public void testVarsMethodsTypes() {
|
||||||
test(false, new String[]{"--no-startup"},
|
test(false, new String[]{"--no-startup"},
|
||||||
a -> assertCompletion(a, "/v|", false, "/vars "),
|
a -> assertCompletion(a, "/v|", false, "/vars "),
|
||||||
@ -141,36 +201,53 @@ public class CommandCompletionTest extends ReplToolTesting {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testOpen() throws IOException {
|
public void testOpen() throws IOException {
|
||||||
Compiler compiler = new Compiler();
|
Compiler compiler = new Compiler();
|
||||||
assertCompletion("/o|", false, "/open ");
|
testNoStartUp(
|
||||||
|
a -> assertCompletion(a, "/o|", false, "/open ")
|
||||||
|
);
|
||||||
List<String> p1 = listFiles(Paths.get(""));
|
List<String> p1 = listFiles(Paths.get(""));
|
||||||
getRootDirectories().forEach(s -> p1.add(s.toString()));
|
getRootDirectories().forEach(s -> p1.add(s.toString()));
|
||||||
Collections.sort(p1);
|
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();
|
Path classDir = compiler.getClassDir();
|
||||||
List<String> p2 = listFiles(classDir);
|
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 {
|
public void testSave() throws IOException {
|
||||||
Compiler compiler = new Compiler();
|
Compiler compiler = new Compiler();
|
||||||
assertCompletion("/s|", false, "/save ", "/set ");
|
testNoStartUp(
|
||||||
|
a -> assertCompletion(a, "/s|", false, "/save ", "/set ")
|
||||||
|
);
|
||||||
List<String> p1 = listFiles(Paths.get(""));
|
List<String> p1 = listFiles(Paths.get(""));
|
||||||
Collections.addAll(p1, "-all ", "-history ", "-start ");
|
Collections.addAll(p1, "-all ", "-history ", "-start ");
|
||||||
getRootDirectories().forEach(s -> p1.add(s.toString()));
|
getRootDirectories().forEach(s -> p1.add(s.toString()));
|
||||||
Collections.sort(p1);
|
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();
|
Path classDir = compiler.getClassDir();
|
||||||
List<String> p2 = listFiles(classDir);
|
List<String> p2 = listFiles(classDir);
|
||||||
assertCompletion("/save " + classDir + "/|",
|
testNoStartUp(
|
||||||
false, p2.toArray(new String[p2.size()]));
|
a -> assertCompletion(a, "/save " + classDir + "/|",
|
||||||
assertCompletion("/save -all " + classDir + "/|",
|
false, p2.toArray(new String[p2.size()])),
|
||||||
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 {
|
public void testClassPath() throws IOException {
|
||||||
assertCompletion("/classp|", false, "/classpath ");
|
testNoStartUp(
|
||||||
|
a -> assertCompletion(a, "/classp|", false, "/classpath ")
|
||||||
|
);
|
||||||
Compiler compiler = new Compiler();
|
Compiler compiler = new Compiler();
|
||||||
Path outDir = compiler.getPath("testClasspathCompletion");
|
Path outDir = compiler.getPath("testClasspathCompletion");
|
||||||
Files.createDirectories(outDir);
|
Files.createDirectories(outDir);
|
||||||
@ -182,9 +259,12 @@ public class CommandCompletionTest extends ReplToolTesting {
|
|||||||
compiler.jar(outDir, jarName, "pkg/A.class");
|
compiler.jar(outDir, jarName, "pkg/A.class");
|
||||||
compiler.getPath(outDir).resolve(jarName);
|
compiler.getPath(outDir).resolve(jarName);
|
||||||
List<String> paths = listFiles(outDir, CLASSPATH_FILTER);
|
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 {
|
public void testUserHome() throws IOException {
|
||||||
List<String> completions;
|
List<String> completions;
|
||||||
Path home = Paths.get(System.getProperty("user.home"));
|
Path home = Paths.get(System.getProperty("user.home"));
|
||||||
@ -194,9 +274,12 @@ public class CommandCompletionTest extends ReplToolTesting {
|
|||||||
.sorted()
|
.sorted()
|
||||||
.collect(Collectors.toList());
|
.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 {
|
public void testSet() throws IOException {
|
||||||
List<String> p1 = listFiles(Paths.get(""));
|
List<String> p1 = listFiles(Paths.get(""));
|
||||||
getRootDirectories().forEach(s -> p1.add(s.toString()));
|
getRootDirectories().forEach(s -> p1.add(s.toString()));
|
||||||
|
@ -32,13 +32,29 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.Locale;
|
||||||
import jdk.internal.jline.extra.EditingHistory;
|
import jdk.internal.jline.extra.EditingHistory;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
import jdk.internal.jshell.tool.JShellTool;
|
||||||
|
import jdk.internal.jshell.tool.JShellToolBuilder;
|
||||||
import static org.testng.Assert.*;
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
@Test
|
|
||||||
public class HistoryTest extends ReplToolTesting {
|
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() {
|
public void testHistory() {
|
||||||
test(
|
test(
|
||||||
a -> {if (!a) setCommandInput("void test() {\n");},
|
a -> {if (!a) setCommandInput("void test() {\n");},
|
||||||
@ -76,6 +92,7 @@ public class HistoryTest extends ReplToolTesting {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void test8166744() {
|
public void test8166744() {
|
||||||
test(
|
test(
|
||||||
a -> {if (!a) setCommandInput("class C {\n");},
|
a -> {if (!a) setCommandInput("class C {\n");},
|
||||||
|
@ -25,7 +25,6 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -36,17 +35,15 @@ import java.util.function.Function;
|
|||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.prefs.AbstractPreferences;
|
import java.util.prefs.AbstractPreferences;
|
||||||
import java.util.prefs.BackingStoreException;
|
import java.util.prefs.BackingStoreException;
|
||||||
import java.util.prefs.Preferences;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import jdk.internal.jshell.tool.JShellTool;
|
|
||||||
import jdk.jshell.SourceCodeAnalysis.Suggestion;
|
|
||||||
|
|
||||||
import org.testng.annotations.BeforeMethod;
|
import org.testng.annotations.BeforeMethod;
|
||||||
|
|
||||||
|
import jdk.jshell.tool.JavaShellToolBuilder;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertNotNull;
|
import static org.testng.Assert.assertNotNull;
|
||||||
@ -92,11 +89,9 @@ public class ReplToolTesting {
|
|||||||
private Map<String, ClassInfo> classes;
|
private Map<String, ClassInfo> classes;
|
||||||
private Map<String, ImportInfo> imports;
|
private Map<String, ImportInfo> imports;
|
||||||
private boolean isDefaultStartUp = true;
|
private boolean isDefaultStartUp = true;
|
||||||
private Preferences prefs;
|
private Map<String, String> prefsMap;
|
||||||
private Map<String, String> envvars;
|
private Map<String, String> envvars;
|
||||||
|
|
||||||
public JShellTool repl = null;
|
|
||||||
|
|
||||||
public interface ReplTest {
|
public interface ReplTest {
|
||||||
void run(boolean after);
|
void run(boolean after);
|
||||||
}
|
}
|
||||||
@ -202,6 +197,10 @@ public class ReplToolTesting {
|
|||||||
test(Locale.ROOT, isDefaultStartUp, args, DEFAULT_STARTUP_MESSAGE, tests);
|
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) {
|
public void test(Locale locale, boolean isDefaultStartUp, String[] args, String startUpMessage, ReplTest... tests) {
|
||||||
this.isDefaultStartUp = isDefaultStartUp;
|
this.isDefaultStartUp = isDefaultStartUp;
|
||||||
initSnippets();
|
initSnippets();
|
||||||
@ -232,7 +231,7 @@ public class ReplToolTesting {
|
|||||||
|
|
||||||
@BeforeMethod
|
@BeforeMethod
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
prefs = new MemoryPreferences();
|
prefsMap = new HashMap<>();
|
||||||
envvars = new HashMap<>();
|
envvars = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +239,25 @@ public class ReplToolTesting {
|
|||||||
envvars.put(name, value);
|
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();
|
cmdin = new WaitingTestingInputStream();
|
||||||
cmdout = new ByteArrayOutputStream();
|
cmdout = new ByteArrayOutputStream();
|
||||||
cmderr = new ByteArrayOutputStream();
|
cmderr = new ByteArrayOutputStream();
|
||||||
@ -248,23 +265,18 @@ public class ReplToolTesting {
|
|||||||
userin = new TestingInputStream();
|
userin = new TestingInputStream();
|
||||||
userout = new ByteArrayOutputStream();
|
userout = new ByteArrayOutputStream();
|
||||||
usererr = new ByteArrayOutputStream();
|
usererr = new ByteArrayOutputStream();
|
||||||
repl = new JShellTool(
|
}
|
||||||
cmdin,
|
|
||||||
new PrintStream(cmdout),
|
protected void testRawRun(Locale locale, String[] args) {
|
||||||
new PrintStream(cmderr),
|
|
||||||
new PrintStream(console),
|
|
||||||
userin,
|
|
||||||
new PrintStream(userout),
|
|
||||||
new PrintStream(usererr),
|
|
||||||
prefs,
|
|
||||||
envvars,
|
|
||||||
locale);
|
|
||||||
repl.testPrompt = true;
|
|
||||||
try {
|
try {
|
||||||
repl.start(args);
|
builder(locale)
|
||||||
|
.run(args);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
fail("Repl tool died with exception", ex);
|
fail("Repl tool died with exception", ex);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testRawCheck(Locale locale) {
|
||||||
// perform internal consistency checks on state, if desired
|
// perform internal consistency checks on state, if desired
|
||||||
String cos = getCommandOutput();
|
String cos = getCommandOutput();
|
||||||
String ceos = getCommandErrorOutput();
|
String ceos = getCommandErrorOutput();
|
||||||
@ -272,9 +284,9 @@ public class ReplToolTesting {
|
|||||||
String ueos = getUserErrorOutput();
|
String ueos = getUserErrorOutput();
|
||||||
assertTrue((cos.isEmpty() || cos.startsWith("| Goodbye") || !locale.equals(Locale.ROOT)),
|
assertTrue((cos.isEmpty() || cos.startsWith("| Goodbye") || !locale.equals(Locale.ROOT)),
|
||||||
"Expected a goodbye, but got: " + cos);
|
"Expected a goodbye, but got: " + cos);
|
||||||
assertTrue(ceos.isEmpty(), "Expected empty error output, got: " + ceos);
|
assertTrue(ceos.isEmpty(), "Expected empty command error output, got: " + ceos);
|
||||||
assertTrue(uos.isEmpty(), "Expected empty output, got: " + uos);
|
assertTrue(uos.isEmpty(), "Expected empty user output, got: " + uos);
|
||||||
assertTrue(ueos.isEmpty(), "Expected empty error output, got: " + ueos);
|
assertTrue(ueos.isEmpty(), "Expected empty user error output, got: " + ueos);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertReset(boolean after, String cmd) {
|
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) {
|
public Consumer<String> assertStartsWith(String prefix) {
|
||||||
return (output) -> assertTrue(output.startsWith(prefix), "Output: \'" + output + "' does not start with: " + 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.
|
* @summary Testing start-up options.
|
||||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||||
* jdk.compiler/com.sun.tools.javac.main
|
* jdk.compiler/com.sun.tools.javac.main
|
||||||
@ -33,19 +33,21 @@
|
|||||||
* @run testng StartOptionTest
|
* @run testng StartOptionTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import jdk.internal.jshell.tool.JShellTool;
|
import javax.tools.Tool;
|
||||||
import org.testng.annotations.AfterMethod;
|
import org.testng.annotations.AfterMethod;
|
||||||
import org.testng.annotations.BeforeMethod;
|
import org.testng.annotations.BeforeMethod;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
import jdk.jshell.tool.JavaShellToolBuilder;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
import static org.testng.Assert.fail;
|
import static org.testng.Assert.fail;
|
||||||
@ -59,21 +61,26 @@ public class StartOptionTest {
|
|||||||
private ByteArrayOutputStream userout;
|
private ByteArrayOutputStream userout;
|
||||||
private ByteArrayOutputStream usererr;
|
private ByteArrayOutputStream usererr;
|
||||||
|
|
||||||
private JShellTool getShellTool() {
|
private JavaShellToolBuilder builder() {
|
||||||
return new JShellTool(
|
return JavaShellToolBuilder
|
||||||
new TestingInputStream(),
|
.builder()
|
||||||
new PrintStream(cmdout),
|
.out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout))
|
||||||
new PrintStream(cmderr),
|
.err(new PrintStream(cmderr), new PrintStream(usererr))
|
||||||
new PrintStream(console),
|
.persistence(new HashMap<>())
|
||||||
null,
|
.env(new HashMap<>())
|
||||||
new PrintStream(userout),
|
.locale(Locale.ROOT);
|
||||||
new PrintStream(usererr),
|
|
||||||
new ReplToolTesting.MemoryPreferences(),
|
|
||||||
new HashMap<>(),
|
|
||||||
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();
|
byte[] bytes = str.toByteArray();
|
||||||
str.reset();
|
str.reset();
|
||||||
String out = new String(bytes, StandardCharsets.UTF_8);
|
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 {
|
protected void start(Consumer<String> checkCmdOutput,
|
||||||
JShellTool tool = getShellTool();
|
Consumer<String> checkUserOutput, Consumer<String> checkError,
|
||||||
tool.start(args);
|
String... args) throws Exception {
|
||||||
check(cmdout, checkOutput, "cmdout");
|
runShell(args);
|
||||||
|
check(cmdout, checkCmdOutput, "cmdout");
|
||||||
check(cmderr, checkError, "cmderr");
|
check(cmderr, checkError, "cmderr");
|
||||||
check(console, null, "console");
|
check(console, null, "console");
|
||||||
check(userout, null, "userout");
|
check(userout, checkUserOutput, "userout");
|
||||||
check(usererr, null, "usererr");
|
check(usererr, null, "usererr");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void start(String expectedOutput, String expectedError, String... args) throws Exception {
|
protected void start(String expectedCmdOutput, String expectedError, String... args) throws Exception {
|
||||||
start(s -> assertEquals(s.trim(), expectedOutput, "cmdout: "), s -> assertEquals(s.trim(), expectedError, "cmderr: "), args);
|
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
|
@BeforeMethod
|
||||||
@ -107,21 +124,31 @@ public class StartOptionTest {
|
|||||||
usererr = new ByteArrayOutputStream();
|
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 {
|
public void testUsage() throws Exception {
|
||||||
for (String opt : new String[]{"-h", "--help"}) {
|
for (String opt : new String[]{"-h", "--help"}) {
|
||||||
start(s -> {
|
start(s -> {
|
||||||
assertTrue(s.split("\n").length >= 7, "Not enough usage lines: " + s);
|
assertTrue(s.split("\n").length >= 7, "Not enough usage lines: " + s);
|
||||||
assertTrue(s.startsWith("Usage: jshell <options>"), "Unexpect usage start: " + s);
|
assertTrue(s.startsWith("Usage: jshell <options>"), "Unexpect usage start: " + s);
|
||||||
}, null, opt);
|
}, null, null, opt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUnknown() throws Exception {
|
public void testUnknown() throws Exception {
|
||||||
start(s -> { },
|
start(null, null,
|
||||||
s -> assertEquals(s.trim(), "Unknown option: u"), "-unknown");
|
s -> assertEquals(s.trim(), "Unknown option: u"), "-unknown");
|
||||||
start(s -> { },
|
start(null, null,
|
||||||
s -> assertEquals(s.trim(), "Unknown option: unknown"), "--unknown");
|
s -> assertEquals(s.trim(), "Unknown option: unknown"), "--unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +165,7 @@ public class StartOptionTest {
|
|||||||
|
|
||||||
public void testStartupFailedOption() throws Exception {
|
public void testStartupFailedOption() throws Exception {
|
||||||
try {
|
try {
|
||||||
start("", "", "-R-hoge-foo-bar");
|
builder().run("-R-hoge-foo-bar");
|
||||||
} catch (IllegalStateException ex) {
|
} catch (IllegalStateException ex) {
|
||||||
String s = ex.getMessage();
|
String s = ex.getMessage();
|
||||||
assertTrue(s.startsWith("Launching JShell execution engine threw: Failed remote"), s);
|
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");
|
start("", "File 'UNKNOWN' for '--startup' is not found.", "--startup", "UNKNOWN");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testClasspath() throws Exception {
|
public void testClasspath() throws Exception {
|
||||||
for (String cp : new String[] {"--class-path"}) {
|
for (String cp : new String[] {"--class-path"}) {
|
||||||
start("", "Only one --class-path option may be used.", cp, ".", "--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 {
|
public void testFeedbackOptionConflict() throws Exception {
|
||||||
start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.",
|
start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.",
|
||||||
"--feedback", "concise", "--feedback", "verbose");
|
"--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");
|
start("", "Only one feedback option (--feedback, -q, -s, or -v) may be used.", "-q", "-s");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNegFeedbackOption() throws Exception {
|
public void testNegFeedbackOption() throws Exception {
|
||||||
start("", "Argument to feedback missing.", "--feedback");
|
start("", "Argument to feedback missing.", "--feedback");
|
||||||
start("", "Does not match any current feedback mode: blorp -- --feedback blorp", "--feedback", "blorp");
|
start("", "Does not match any current feedback mode: blorp -- --feedback blorp", "--feedback", "blorp");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testVersion() throws Exception {
|
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
|
@AfterMethod
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @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
|
* @summary Tests for Basic tests for REPL tool
|
||||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||||
* jdk.compiler/com.sun.tools.javac.main
|
* jdk.compiler/com.sun.tools.javac.main
|
||||||
@ -49,8 +49,6 @@ import java.util.Scanner;
|
|||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.prefs.BackingStoreException;
|
|
||||||
import java.util.prefs.Preferences;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@ -305,22 +303,18 @@ public class ToolBasicTest extends ReplToolTesting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testStartupFileOption() {
|
public void testStartupFileOption() {
|
||||||
try {
|
Compiler compiler = new Compiler();
|
||||||
Compiler compiler = new Compiler();
|
Path startup = compiler.getPath("StartupFileOption/startup.txt");
|
||||||
Path startup = compiler.getPath("StartupFileOption/startup.txt");
|
compiler.writeToFile(startup, "class A { public String toString() { return \"A\"; } }");
|
||||||
compiler.writeToFile(startup, "class A { public String toString() { return \"A\"; } }");
|
test(new String[]{"--startup", startup.toString()},
|
||||||
test(new String[]{"--startup", startup.toString()},
|
(a) -> evaluateExpression(a, "A", "new A()", "A")
|
||||||
(a) -> evaluateExpression(a, "A", "new A()", "A")
|
);
|
||||||
);
|
test(new String[]{"--no-startup"},
|
||||||
test(new String[]{"--no-startup"},
|
(a) -> assertCommandCheckOutput(a, "printf(\"\")", assertStartsWith("| Error:\n| cannot find symbol"))
|
||||||
(a) -> assertCommandCheckOutput(a, "printf(\"\")", assertStartsWith("| Error:\n| cannot find symbol"))
|
);
|
||||||
);
|
test(
|
||||||
test(
|
(a) -> assertCommand(a, "printf(\"A\")", "", "", null, "A", "")
|
||||||
(a) -> assertCommand(a, "printf(\"A\")", "", "", null, "A", "")
|
);
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
removeStartup();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLoadingFromArgs() {
|
public void testLoadingFromArgs() {
|
||||||
@ -436,45 +430,34 @@ public class ToolBasicTest extends ReplToolTesting {
|
|||||||
assertEquals(Files.readAllLines(path), output);
|
assertEquals(Files.readAllLines(path), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testStartRetain() throws BackingStoreException {
|
public void testStartRetain() {
|
||||||
try {
|
Compiler compiler = new Compiler();
|
||||||
Compiler compiler = new Compiler();
|
Path startUpFile = compiler.getPath("startUp.txt");
|
||||||
Path startUpFile = compiler.getPath("startUp.txt");
|
test(
|
||||||
test(
|
(a) -> assertVariable(a, "int", "a"),
|
||||||
(a) -> assertVariable(a, "int", "a"),
|
(a) -> assertVariable(a, "double", "b", "10", "10.0"),
|
||||||
(a) -> assertVariable(a, "double", "b", "10", "10.0"),
|
(a) -> assertMethod(a, "void f() {}", "()V", "f"),
|
||||||
(a) -> assertMethod(a, "void f() {}", "()V", "f"),
|
(a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
|
||||||
(a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
|
(a) -> assertCommand(a, "/save " + startUpFile.toString(), null),
|
||||||
(a) -> assertCommand(a, "/save " + startUpFile.toString(), null),
|
(a) -> assertCommand(a, "/set start -retain " + startUpFile.toString(), null)
|
||||||
(a) -> assertCommand(a, "/set start -retain " + startUpFile.toString(), null)
|
);
|
||||||
);
|
Path unknown = compiler.getPath("UNKNOWN");
|
||||||
Path unknown = compiler.getPath("UNKNOWN");
|
test(
|
||||||
test(
|
(a) -> assertCommandOutputStartsWith(a, "/set start -retain " + unknown.toString(),
|
||||||
(a) -> assertCommandOutputStartsWith(a, "/set start -retain " + unknown.toString(),
|
"| File '" + unknown + "' for '/set start' is not found.")
|
||||||
"| File '" + unknown + "' for '/set start' is not found.")
|
);
|
||||||
);
|
test(false, new String[0],
|
||||||
test(false, new String[0],
|
(a) -> {
|
||||||
(a) -> {
|
loadVariable(a, "int", "a");
|
||||||
loadVariable(a, "int", "a");
|
loadVariable(a, "double", "b", "10.0", "10.0");
|
||||||
loadVariable(a, "double", "b", "10.0", "10.0");
|
loadMethod(a, "void f() {}", "()void", "f");
|
||||||
loadMethod(a, "void f() {}", "()void", "f");
|
loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
|
||||||
loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
|
assertCommandCheckOutput(a, "/types", assertClasses());
|
||||||
assertCommandCheckOutput(a, "/types", assertClasses());
|
},
|
||||||
},
|
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
|
||||||
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
|
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
|
||||||
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
|
(a) -> assertCommandCheckOutput(a, "/imports", assertImports())
|
||||||
(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 testStartSave() throws IOException {
|
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