Skip to content

Commit

Permalink
8306560: Add TOOLING.jsh load file
Browse files Browse the repository at this point in the history
Reviewed-by: jlahoda
  • Loading branch information
sormuras committed May 28, 2023
1 parent ca54f4e commit 547a8b4
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2016, 2023, 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
Expand Down Expand Up @@ -230,7 +230,7 @@ where possible options include:\n\
\ --help-extra, -X Print help on non-standard options and exit\n\
\n\
A file argument may be a file name, or one of the predefined file names: DEFAULT,\n\
PRINTING, or JAVASE.\n\
PRINTING, TOOLING, or JAVASE.\n\
A load-file may also be "-" to indicate standard input, without interactive I/O.\n\
\n\
For more information on the evaluation context options (--class-path,\n\
Expand Down Expand Up @@ -331,10 +331,10 @@ Open a file and read its contents as snippets and commands.\n\
Download and use the specified URL as the jshell tool input.\n\
\n\
The <file> may be an operating system file name, or one of the predefined\n\
file names: DEFAULT, PRINTING, or JAVASE.\n\
file names: DEFAULT, PRINTING, TOOLING, or JAVASE.\n\
These are respectively: the default import snippets (as used by -default),\n\
definitions of print(), println(), and printf() method snippets, or\n\
imports of all Java SE packages.\n
definitions of print(), println(), and printf() method snippets, definitions\n\
of method snippets running JDK tools, or imports of all Java SE packages.\n

help.vars.summary = list the declared variables and their values
help.vars.args = [<name or id>|-all|-start]
Expand Down Expand Up @@ -1136,7 +1136,7 @@ Note: if the startup was last set from a file, this is shown with the\n\
'set start' command followed by the contents of the file.\n\
\n\
The <file> may be an operating system file name, or one of the predefined\n\
startup file names: DEFAULT, PRINTING, or JAVASE.\n\
startup file names: DEFAULT, PRINTING, TOOLING, or JAVASE.\n\
These are respectively: the default import snippets (as used by -default),\n\
definitions of print(), println(), and printf() method snippets, or\n\
imports of all Java SE packages.\n\
Expand Down
49 changes: 49 additions & 0 deletions src/jdk.jshell/share/classes/jdk/jshell/tool/resources/TOOLING.jsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
void jar(String... args) { run("jar", args); }
void javac(String... args) { run("javac", args); }
void javadoc(String... args) { run("javadoc", args); }
void javap(String... args) { run("javap", args); }
void jdeps(String... args) { run("jdeps", args); }
void jlink(String... args) { run("jlink", args); }
void jmod(String... args) { run("jmod", args); }
void jpackage(String... args) { run("jpackage", args); }

void javap(Class<?> type) throws Exception {
try {
var name = type.getCanonicalName();
if (name == null) throw new IllegalArgumentException("Type not supported: " + type);
if (type == Class.forName(name, false, ClassLoader.getSystemClassLoader())) {
run("javap", "-c", "-v", "-s", name);
return;
}
} catch (ClassNotFoundException ignored) {
// fall-through
}
var temp = java.nio.file.Files.createTempFile("TOOLING-", ".class");
try {
var name = type.getName().replace('.', '/') + ".class";
try (var in = type.getClassLoader().getResourceAsStream(name);
var out = java.nio.file.Files.newOutputStream(temp)) {
if (in == null) throw new AssertionError("Resource not found: " + name);
in.transferTo(out);
}
run("javap", "-c", "-v", "-s", temp.toString());
} finally {
java.nio.file.Files.delete(temp);
}
}

void run(String name, String... args) {
var tool = java.util.spi.ToolProvider.findFirst(name);
if (tool.isEmpty()) throw new RuntimeException("No such tool found: " + name);
var code = tool.get().run(System.out, System.err, args);
if (code == 0) return;
System.err.println(name + " returned non-zero exit code: " + code);
}

void tools() {
java.util.ServiceLoader.load(java.util.spi.ToolProvider.class).stream()
.map(java.util.ServiceLoader.Provider::get)
.map(java.util.spi.ToolProvider::name)
.sorted()
.forEach(System.out::println);
}
22 changes: 21 additions & 1 deletion test/langtools/jdk/jshell/ReplToolTesting.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2023, 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
Expand Down Expand Up @@ -510,6 +510,26 @@ public void assertCommandCheckOutput(boolean after, String cmd, Consumer<String>
}
}

public void assertCommandUserOutputContains(boolean after, String cmd, String... hasThese) {
assertCommandCheckUserOutput(after, cmd, (s)
-> assertTrue(Arrays.stream(hasThese)
.allMatch(has -> s.contains(has)),
"User output: \'" + s + "' does not contain: "
+ Arrays.stream(hasThese)
.filter(has -> !s.contains(has))
.collect(Collectors.joining(", "))));
}

public void assertCommandCheckUserOutput(boolean after, String cmd, Consumer<String> check) {
if (!after) {
assertCommand(false, cmd, null);
} else {
String got = getUserOutput();
check.accept(got);
assertCommand(true, cmd, null);
}
}

public void assertCommand(boolean after, String cmd, String out, String err,
String userinput, String print, String usererr) {
if (!after) {
Expand Down
6 changes: 3 additions & 3 deletions test/langtools/jdk/jshell/ToolLocalSimpleTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2023, 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
Expand Down Expand Up @@ -71,9 +71,9 @@ public void testOptionR() {
@Override
@Test
public void testCompoundStart() {
test(new String[]{"--startup", "DEFAULT", "--startup", "PRINTING"},
test(new String[]{"--startup", "DEFAULT", "--startup", "PRINTING", "--startup", "TOOLING"},
(a) -> assertCommandOutputContains(a, "/list -start",
"System.out.println", "import java.util.concurrent")
"System.out.println", "import java.util.concurrent", "tools()")
);
}

Expand Down
10 changes: 6 additions & 4 deletions test/langtools/jdk/jshell/ToolSimpleTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2023, 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
Expand Down Expand Up @@ -27,7 +27,7 @@
* 8167128 8154513 8170015 8170368 8172102 8172103 8165405 8173073 8173848
* 8174041 8173916 8174028 8174262 8174797 8177079 8180508 8177466 8172154
* 8192979 8191842 8198573 8198801 8210596 8210959 8215099 8199623 8236715
* 8239536 8247456 8246774 8238173 8292625
* 8239536 8247456 8246774 8238173 8292625 8306560
* @summary Simple jshell tool tests
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
Expand Down Expand Up @@ -749,9 +749,11 @@ public void testBlankLinesInSnippetContinuation() {
@Test
public void testCompoundStart() {
test(new String[]{"-R", "-Duser.language=en", "-R", "-Duser.country=US",
"--startup", "DEFAULT", "--startup", "PRINTING"},
"--startup", "DEFAULT", "--startup", "PRINTING", "--startup", "TOOLING"},
(a) -> assertCommand(a, "printf(\"%4.2f\", Math.PI)",
"", "", null, "3.14", "")
"", "", null, "3.14", ""),
(a) -> assertCommand(a, "jar(\"--version\")",
"", "", null, "jar " + System.getProperty("java.version") + "\n", "")
);
}

Expand Down
82 changes: 82 additions & 0 deletions test/langtools/jdk/jshell/ToolingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2023, 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.
*/

/*
* @test
* @bug 8306560
* @summary Tests for snippets and methods defined in TOOLING.jsh
* @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
* @build KullaTesting TestingInputStream
* @run testng ToolingTest
*/

import org.testng.Assert;
import org.testng.annotations.Test;

public class ToolingTest extends ReplToolTesting {
@Test
public void testListToolingSnippets() {
test(
a -> assertCommand(a, "/open TOOLING",
""),
a -> assertCommandOutputContains(a, "/list",
// Tool methods
"void jar(String... args)",
// ...
"void jpackage(String... args)",
// Utility methods
"void javap(Class<?> type) throws Exception",
"void run(String name, String... args)",
"void tools()")
);
}

@Test
public void testDisassembleJavaLangObjectClass() {
test(
a -> assertCommand(a, "/open TOOLING",
""),
a -> assertCommandUserOutputContains(a, "javap(Object.class)",
"Classfile jrt:/java.base/java/lang/Object.class",
"SourceFile: \"Object.java\"")
);
}

@Test
public void testDisassembleNewRecordClass() {
test(
a -> assertCommand(a, "record Point(int x, int y) {}",
"| created record Point"),
a -> assertCommand(a, "/open TOOLING",
""),
a -> assertCommandUserOutputContains(a, "javap(Point.class)",
"Classfile ", // Classfile /.../TOOLING-13366652659767559204.class
"Point extends java.lang.Record", // public final class REPL.$JShell$11$Point extends java.lang.Record
"SourceFile: \"$JShell$" // SourceFile: "$JShell$11.java"
)
);
}
}

1 comment on commit 547a8b4

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.