8341631: JShell should auto-import java.io.IO.*

Reviewed-by: asotona, cstein
This commit is contained in:
Jan Lahoda 2024-11-20 09:24:05 +00:00
parent 5b12a87dcb
commit cf158bc6cd
7 changed files with 141 additions and 17 deletions

View File

@ -1001,6 +1001,11 @@ class ConsoleIOContext extends IOContext {
return doReadUserLine(prompt, null);
}
@Override
public String readUserLine() throws IOException {
return readUserLine("");
}
private synchronized String doReadUserLine(String prompt, Character mask) throws IOException {
History prevHistory = in.getHistory();
boolean prevDisableCr = Display.DISABLE_CR;

View File

@ -64,6 +64,8 @@ abstract class IOContext implements AutoCloseable {
}
public String readUserLine(String prompt) throws IOException {
userOutput().write(prompt);
userOutput().flush();
throw new UserInterruptException("");
}
@ -76,6 +78,8 @@ abstract class IOContext implements AutoCloseable {
}
public char[] readPassword(String prompt) throws IOException {
userOutput().write(prompt);
userOutput().flush();
throw new UserInterruptException("");
}

View File

@ -35,6 +35,7 @@ import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Reader;
@ -1192,7 +1193,7 @@ public class JShellTool implements MessageHandler {
//where
private void startUpRun(String start) {
try (IOContext suin = new ScannerIOContext(new StringReader(start))) {
try (IOContext suin = new ScannerIOContext(new StringReader(start), userout)) {
while (run(suin)) {
if (!live) {
resetState();
@ -3125,7 +3126,7 @@ public class JShellTool implements MessageHandler {
throw new FileNotFoundException(filename);
}
}
try (var scannerIOContext = new ScannerIOContext(scanner)) {
try (var scannerIOContext = new ScannerIOContext(scanner, userout)) {
run(scannerIOContext);
}
return true;
@ -3288,8 +3289,10 @@ public class JShellTool implements MessageHandler {
resetState();
}
if (history != null) {
run(new ReloadIOContext(history.iterable(),
echo ? cmdout : null));
try (ReloadIOContext ctx = new ReloadIOContext(history.iterable(),
echo ? cmdout : null, userout)) {
run(ctx);
}
}
return true;
}
@ -4107,6 +4110,8 @@ public class JShellTool implements MessageHandler {
public String readLine(String prompt) {
try {
return input.readUserLine(prompt);
} catch (UserInterruptException ex) {
return null;
} catch (IOException ex) {
throw new IOError(ex);
}
@ -4125,6 +4130,8 @@ public class JShellTool implements MessageHandler {
public char[] readPassword(String prompt) {
try {
return input.readPassword(prompt);
} catch (UserInterruptException ex) {
return null;
} catch (IOException ex) {
throw new IOError(ex);
}
@ -4144,6 +4151,12 @@ public class JShellTool implements MessageHandler {
abstract class NonInteractiveIOContext extends IOContext {
private final Writer userOutput;
public NonInteractiveIOContext(PrintStream userOutput) {
this.userOutput = new OutputStreamWriter(userOutput);
}
@Override
public boolean interactiveOutput() {
return false;
@ -4178,17 +4191,33 @@ abstract class NonInteractiveIOContext extends IOContext {
@Override
public void replaceLastHistoryEntry(String source) {
}
@Override
public Writer userOutput() {
return userOutput;
}
@Override
public void close() {
try {
userOutput.flush();
} catch (IOException _) {
//ignore
}
}
}
class ScannerIOContext extends NonInteractiveIOContext {
private final Scanner scannerIn;
ScannerIOContext(Scanner scannerIn) {
ScannerIOContext(Scanner scannerIn, PrintStream userOutput) {
super(userOutput);
this.scannerIn = scannerIn;
}
ScannerIOContext(Reader rdr) throws FileNotFoundException {
this(new Scanner(rdr));
ScannerIOContext(Reader rdr, PrintStream userOutput) throws FileNotFoundException {
this(new Scanner(rdr), userOutput);
}
@Override
@ -4202,6 +4231,7 @@ class ScannerIOContext extends NonInteractiveIOContext {
@Override
public void close() {
super.close();
scannerIn.close();
}
@ -4215,7 +4245,8 @@ class ReloadIOContext extends NonInteractiveIOContext {
private final Iterator<String> it;
private final PrintStream echoStream;
ReloadIOContext(Iterable<String> history, PrintStream echoStream) {
ReloadIOContext(Iterable<String> history, PrintStream echoStream, PrintStream userOutput) {
super(userOutput);
this.it = history.iterator();
this.echoStream = echoStream;
}

View File

@ -117,6 +117,9 @@ public class ConsoleImpl {
private char[] readChars() throws IOException {
int actualLen = readInt();
if (actualLen == (-1)) {
return null;
}
char[] result = new char[actualLen];
for (int i = 0; i < actualLen; i++) {
result[i] = (char) ((remoteOutput.read() << 8) |
@ -267,6 +270,9 @@ public class ConsoleImpl {
remoteInput.write(Task.READ_LINE.ordinal());
sendChars(chars, 0, chars.length);
char[] line = readChars();
if (line == null) {
return null;
}
return new String(line);
});
} catch (IOException ex) {
@ -417,8 +423,12 @@ public class ConsoleImpl {
char[] data = readCharsOrNull(1);
if (data != null) {
String line = console.readLine(new String(data));
char[] chars = line.toCharArray();
sendChars(sinkOutput, chars, 0, chars.length);
if (line == null) {
sendInt(sinkOutput, -1);
} else {
char[] chars = line.toCharArray();
sendChars(sinkOutput, chars, 0, chars.length);
}
bp = 0;
}
}
@ -432,7 +442,11 @@ public class ConsoleImpl {
char[] data = readCharsOrNull(1);
if (data != null) {
char[] chars = console.readPassword(new String(data));
sendChars(sinkOutput, chars, 0, chars.length);
if (chars == null) {
sendInt(sinkOutput, -1);
} else {
sendChars(sinkOutput, chars, 0, chars.length);
}
bp = 0;
}
}

View File

@ -1 +1,2 @@
import module java.base;
import static java.io.IO.*;

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 8331535
* @bug 8331535 8341631
* @summary Test the JShell tool Console handling
* @modules jdk.internal.le/jdk.internal.org.jline.reader
* jdk.jshell/jdk.internal.jshell.tool:+open
@ -56,6 +56,40 @@ public class ConsoleToolTest extends ReplToolTesting {
);
}
@Test //JDK-8341631
public void testIO() {
test(new String[] {"--enable-preview"},
a -> {assertCommandWithOutputAndTerminal(a,
"java.io.IO.readln(\"%%s\");\ninput", //newline automatically appended
"$1 ==> \"input\"",
"""
\u0005java.io.IO.readln(\"%%s\");
%%sinput
""");},
a -> {assertCommandWithOutputAndTerminal(a,
"java.io.IO.readln();\ninput!", //newline automatically appended
"$2 ==> \"input!\"",
"""
\u0005java.io.IO.readln();
input!
""");},
a -> {assertCommandWithOutputAndTerminal(a,
"java.io.IO.println(\"Hello, World!\");",
"",
"""
\u0005java.io.IO.println(\"Hello, World!\");
Hello, World!
""");},
a -> {assertCommandWithOutputAndTerminal(a,
"java.io.IO.println();",
"",
"""
\u0005java.io.IO.println();
""");}
);
}
void assertCommandWithOutputAndTerminal(boolean a, String command, String out, String terminalOut) {
assertCommand(a, command, out, null, null, null, null, terminalOut);
}

View File

@ -22,7 +22,7 @@
*/
/*
* @test 8151754 8080883 8160089 8170162 8166581 8172102 8171343 8178023 8186708 8179856 8185840 8190383
* @test 8151754 8080883 8160089 8170162 8166581 8172102 8171343 8178023 8186708 8179856 8185840 8190383 8341631
* @summary Testing startExCe-up options.
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@ -366,14 +366,49 @@ public class StartOptionTest {
}
public void testPreviewEnabled() {
String fn = writeToFile("System.out.println(\"prefix\");\n" +
"System.out.println(MethodHandle.class.getName());\n" +
"System.out.println(\"suffix\");\n" +
"/exit\n");
String fn = writeToFile(
"""
System.out.println(\"prefix\");
System.out.println(MethodHandle.class.getName());
System.out.println(\"suffix\");
/exit
""");
startCheckUserOutput(s -> assertEquals(s, "prefix\nsuffix\n"),
fn);
startCheckUserOutput(s -> assertEquals(s, "prefix\njava.lang.invoke.MethodHandle\nsuffix\n"),
"--enable-preview", fn);
//JDK-8341631:
String fn2 = writeToFile(
"""
System.out.println(\"prefix\");
IO.println(\"test\");
System.out.println(\"suffix\");
/exit
""");
startCheckUserOutput(s -> assertEquals(s, "prefix\nsuffix\n"),
fn2);
startCheckUserOutput(s -> assertEquals(s, "prefix\ntest\nsuffix\n"),
"--enable-preview", fn2);
}
public void testInput() {
//readLine(String):
String readLinePrompt = writeToFile(
"""
var v = System.console().readLine("prompt: ");
System.out.println(v);
/exit
""");
startCheckUserOutput(s -> assertEquals(s, "prompt: null\n"),
readLinePrompt);
//readPassword(String):
String readPasswordPrompt = writeToFile(
"""
var v = System.console().readPassword("prompt: ");
System.out.println(java.util.Arrays.toString(v));
/exit
""");
startCheckUserOutput(s -> assertEquals(s, "prompt: null\n"),
readPasswordPrompt);
}
@AfterMethod