8131025: JShell: crash on tab-complete reference to bad class file
Summary: Catching CompletionFailure when iterating through Scope.
Reviewed-by: rfield
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Wed Sep 07 12:15:22 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Thu Sep 08 15:48:28 2016 +0200
@@ -838,8 +838,31 @@
}
private Stream<Element> localElements(Scope scope) {
- @SuppressWarnings("unchecked")
- Stream<Element> elements = Util.stream((Iterable<Element>)scope.getLocalElements());
+ //workaround for: JDK-8024687
+ Iterable<Element> elementsIt = () -> new Iterator<Element>() {
+ Iterator<? extends Element> it = scope.getLocalElements().iterator();
+ @Override
+ public boolean hasNext() {
+ while (true) {
+ try {
+ return it.hasNext();
+ } catch (CompletionFailure cf) {
+ //ignore...
+ }
+ }
+ }
+ @Override
+ public Element next() {
+ while (true) {
+ try {
+ return it.next();
+ } catch (CompletionFailure cf) {
+ //ignore...
+ }
+ }
+ }
+ };
+ Stream<Element> elements = Util.stream(elementsIt);
if (scope.getEnclosingScope() != null &&
scope.getEnclosingClass() != scope.getEnclosingScope().getEnclosingClass()) {
--- a/langtools/test/jdk/jshell/CompletionSuggestionTest.java Wed Sep 07 12:15:22 2016 -0700
+++ b/langtools/test/jdk/jshell/CompletionSuggestionTest.java Thu Sep 08 15:48:28 2016 +0200
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8141092 8153761
+ * @bug 8131025 8141092 8153761
* @summary Test Completion
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -610,4 +610,26 @@
keepParameterNames.setAccessible(true);
keepParameterNames.set(getAnalysis(), new String[0]);
}
+
+ public void testBrokenClassFile2() throws IOException {
+ Path broken = outDir.resolve("broken");
+ compiler.compile(broken,
+ "package p;\n" +
+ "public class BrokenA {\n" +
+ "}",
+ "package p.q;\n" +
+ "public class BrokenB {\n" +
+ "}",
+ "package p;\n" +
+ "public class BrokenC {\n" +
+ "}");
+ Path cp = compiler.getPath(broken);
+ Path target = cp.resolve("p").resolve("BrokenB.class");
+ Files.deleteIfExists(target);
+ Files.move(cp.resolve("p").resolve("q").resolve("BrokenB.class"), target);
+ addToClasspath(cp);
+
+ assertEval("import p.*;");
+ assertCompletion("Broke|", "BrokenA", "BrokenC");
+ }
}