8143964: JShell API: convert query responses to Stream instead of List

Reviewed-by: psandoz, shinyafox
This commit is contained in:
Robert Field 2016-08-09 23:00:49 -07:00
parent 719eeed2d2
commit 81c36d2f40
9 changed files with 283 additions and 149 deletions

View File

@ -973,10 +973,10 @@ public class JShellTool implements MessageHandler {
p.getFileName().toString().endsWith(".jar"));
}
private CompletionProvider snippetCompletion(Supplier<List<? extends Snippet>> snippetsSupplier) {
private CompletionProvider snippetCompletion(Supplier<Stream<? extends Snippet>> snippetsSupplier) {
return (prefix, cursor, anchor) -> {
anchor[0] = 0;
return snippetsSupplier.get() .stream()
return snippetsSupplier.get()
.flatMap(k -> (k instanceof DeclarationSnippet)
? Stream.of(String.valueOf(k.id()), ((DeclarationSnippet) k).name())
: Stream.of(String.valueOf(k.id())))
@ -986,7 +986,7 @@ public class JShellTool implements MessageHandler {
};
}
private CompletionProvider snippetKeywordCompletion(Supplier<List<? extends Snippet>> snippetsSupplier) {
private CompletionProvider snippetKeywordCompletion(Supplier<Stream<? extends Snippet>> snippetsSupplier) {
return (code, cursor, anchor) -> {
List<Suggestion> result = new ArrayList<>();
result.addAll(KEYWORD_COMPLETION_PROVIDER.completionSuggestions(code, cursor, anchor));
@ -1020,36 +1020,32 @@ public class JShellTool implements MessageHandler {
// Snippet lists
List<Snippet> allSnippets() {
Stream<Snippet> allSnippets() {
return state.snippets();
}
List<PersistentSnippet> dropableSnippets() {
return state.snippets().stream()
Stream<PersistentSnippet> dropableSnippets() {
return state.snippets()
.filter(sn -> state.status(sn).isActive() && sn instanceof PersistentSnippet)
.map(sn -> (PersistentSnippet) sn)
.collect(toList());
.map(sn -> (PersistentSnippet) sn);
}
List<VarSnippet> allVarSnippets() {
return state.snippets().stream()
Stream<VarSnippet> allVarSnippets() {
return state.snippets()
.filter(sn -> sn.kind() == Snippet.Kind.VAR)
.map(sn -> (VarSnippet) sn)
.collect(toList());
.map(sn -> (VarSnippet) sn);
}
List<MethodSnippet> allMethodSnippets() {
return state.snippets().stream()
Stream<MethodSnippet> allMethodSnippets() {
return state.snippets()
.filter(sn -> sn.kind() == Snippet.Kind.METHOD)
.map(sn -> (MethodSnippet) sn)
.collect(toList());
.map(sn -> (MethodSnippet) sn);
}
List<TypeDeclSnippet> allTypeSnippets() {
return state.snippets().stream()
Stream<TypeDeclSnippet> allTypeSnippets() {
return state.snippets()
.filter(sn -> sn.kind() == Snippet.Kind.TYPE_DECL)
.map(sn -> (TypeDeclSnippet) sn)
.collect(toList());
.map(sn -> (TypeDeclSnippet) sn);
}
// Table of commands -- with command forms, argument kinds, helpKey message, implementation, ...
@ -1549,7 +1545,7 @@ public class JShellTool implements MessageHandler {
* string
* @return a Stream of referenced snippets or null if no matches are found
*/
private <T extends Snippet> Stream<T> argsOptionsToSnippets(List<T> snippets,
private <T extends Snippet> Stream<T> argsOptionsToSnippets(Supplier<Stream<T>> snippetSupplier,
Predicate<Snippet> defFilter, String rawargs, String cmd) {
ArgTokenizer at = new ArgTokenizer(cmd, rawargs.trim());
at.allowedOptions("-all", "-start");
@ -1571,38 +1567,38 @@ public class JShellTool implements MessageHandler {
}
if (at.hasOption("-all")) {
// all snippets including start-up, failed, and overwritten
return snippets.stream();
return snippetSupplier.get();
}
if (at.hasOption("-start")) {
// start-up snippets
return snippets.stream()
return snippetSupplier.get()
.filter(this::inStartUp);
}
if (args.isEmpty()) {
// Default is all active user snippets
return snippets.stream()
return snippetSupplier.get()
.filter(defFilter);
}
return argsToSnippets(snippets, args);
return argsToSnippets(snippetSupplier, args);
}
/**
* Convert user arguments to a Stream of snippets referenced by those
* arguments.
*
* @param snippets the base list of possible snippets
* @param snippetSupplier the base list of possible snippets
* @param args the user's argument to the command, maybe be the empty list
* @return a Stream of referenced snippets or null if no matches to specific
* arg
*/
private <T extends Snippet> Stream<T> argsToSnippets(List<T> snippets,
private <T extends Snippet> Stream<T> argsToSnippets(Supplier<Stream<T>> snippetSupplier,
List<String> args) {
Stream<T> result = null;
for (String arg : args) {
// Find the best match
Stream<T> st = layeredSnippetSearch(snippets, arg);
Stream<T> st = layeredSnippetSearch(snippetSupplier, arg);
if (st == null) {
Stream<Snippet> est = layeredSnippetSearch(state.snippets(), arg);
Stream<Snippet> est = layeredSnippetSearch(state::snippets, arg);
if (est == null) {
errormsg("jshell.err.no.such.snippets", arg);
} else {
@ -1620,10 +1616,10 @@ public class JShellTool implements MessageHandler {
return result;
}
private <T extends Snippet> Stream<T> layeredSnippetSearch(List<T> snippets, String arg) {
private <T extends Snippet> Stream<T> layeredSnippetSearch(Supplier<Stream<T>> snippetSupplier, String arg) {
return nonEmptyStream(
// the stream supplier
() -> snippets.stream(),
snippetSupplier,
// look for active user declarations matching the name
sn -> isActive(sn) && matchingDeclaration(sn, arg),
// else, look for any declarations matching the name
@ -1648,7 +1644,7 @@ public class JShellTool implements MessageHandler {
errormsg("jshell.err.drop.arg");
return false;
}
Stream<PersistentSnippet> stream = argsToSnippets(dropableSnippets(), args);
Stream<PersistentSnippet> stream = argsToSnippets(this::dropableSnippets, args);
if (stream == null) {
// Snippet not found. Error already printed
fluffmsg("jshell.msg.see.classes.etc");
@ -1670,7 +1666,7 @@ public class JShellTool implements MessageHandler {
}
private boolean cmdEdit(String arg) {
Stream<Snippet> stream = argsOptionsToSnippets(state.snippets(),
Stream<Snippet> stream = argsOptionsToSnippets(state::snippets,
this::mainActive, arg, "/edit");
if (stream == null) {
return false;
@ -1775,7 +1771,7 @@ public class JShellTool implements MessageHandler {
if (arg.length() >= 2 && "-history".startsWith(arg)) {
return cmdHistory();
}
Stream<Snippet> stream = argsOptionsToSnippets(state.snippets(),
Stream<Snippet> stream = argsOptionsToSnippets(state::snippets,
this::mainActive, arg, "/list");
if (stream == null) {
return false;
@ -1896,13 +1892,12 @@ public class JShellTool implements MessageHandler {
} else if (at.hasOption("-start")) {
writer.append(startup);
} else {
List<Snippet> sns = at.hasOption("-all")
String sources = (at.hasOption("-all")
? state.snippets()
: state.snippets().stream().filter(this::mainActive).collect(toList());
for (Snippet sn : sns) {
writer.write(sn.source());
writer.write("\n");
}
: state.snippets().filter(this::mainActive))
.map(Snippet::source)
.collect(Collectors.joining("\n"));
writer.write(sources);
}
} catch (FileNotFoundException e) {
errormsg("jshell.err.file.not.found", "/save", filename, e.getMessage());
@ -1915,7 +1910,7 @@ public class JShellTool implements MessageHandler {
}
private boolean cmdVars(String arg) {
Stream<VarSnippet> stream = argsOptionsToSnippets(allVarSnippets(),
Stream<VarSnippet> stream = argsOptionsToSnippets(this::allVarSnippets,
this::isActive, arg, "/vars");
if (stream == null) {
return false;
@ -1931,7 +1926,7 @@ public class JShellTool implements MessageHandler {
}
private boolean cmdMethods(String arg) {
Stream<MethodSnippet> stream = argsOptionsToSnippets(allMethodSnippets(),
Stream<MethodSnippet> stream = argsOptionsToSnippets(this::allMethodSnippets,
this::isActive, arg, "/methods");
if (stream == null) {
return false;
@ -1943,7 +1938,7 @@ public class JShellTool implements MessageHandler {
}
private boolean cmdTypes(String arg) {
Stream<TypeDeclSnippet> stream = argsOptionsToSnippets(allTypeSnippets(),
Stream<TypeDeclSnippet> stream = argsOptionsToSnippets(this::allTypeSnippets,
this::isActive, arg, "/types");
if (stream == null) {
return false;
@ -1982,7 +1977,7 @@ public class JShellTool implements MessageHandler {
}
private boolean cmdUseHistoryEntry(int index) {
List<Snippet> keys = state.snippets();
List<Snippet> keys = state.snippets().collect(toList());
if (index < 0)
index += keys.size();
else
@ -2012,7 +2007,7 @@ public class JShellTool implements MessageHandler {
}
private boolean rerunHistoryEntryById(String id) {
Optional<Snippet> snippet = state.snippets().stream()
Optional<Snippet> snippet = state.snippets()
.filter(s -> s.id().equals(id))
.findFirst();
return snippet.map(s -> {
@ -2135,7 +2130,7 @@ public class JShellTool implements MessageHandler {
debug("Event with null key: %s", ste);
return false;
}
List<Diag> diagnostics = state.diagnostics(sn);
List<Diag> diagnostics = state.diagnostics(sn).collect(toList());
String source = sn.source();
if (ste.causeSnippet() == null) {
// main event
@ -2212,7 +2207,7 @@ public class JShellTool implements MessageHandler {
//where
void printUnresolvedException(UnresolvedReferenceException ex) {
DeclarationSnippet corralled = ex.getSnippet();
List<Diag> otherErrors = errorsOnly(state.diagnostics(corralled));
List<Diag> otherErrors = errorsOnly(state.diagnostics(corralled).collect(toList()));
new DisplayEvent(corralled, state.status(corralled), FormatAction.USED, true, null, otherErrors)
.displayDeclarationAndValue();
}
@ -2280,13 +2275,13 @@ public class JShellTool implements MessageHandler {
for (Diag d : errors) {
displayDiagnostics(sn.source(), d, errorLines);
}
int unresolvedCount;
long unresolvedCount;
if (sn instanceof DeclarationSnippet && (status == Status.RECOVERABLE_DEFINED || status == Status.RECOVERABLE_NOT_DEFINED)) {
resolution = (status == Status.RECOVERABLE_NOT_DEFINED)
? FormatResolve.NOTDEFINED
: FormatResolve.DEFINED;
unresolved = unresolved((DeclarationSnippet) sn);
unresolvedCount = state.unresolvedDependencies((DeclarationSnippet) sn).size();
unresolvedCount = state.unresolvedDependencies((DeclarationSnippet) sn).count();
} else {
resolution = FormatResolve.OK;
unresolved = "";
@ -2305,7 +2300,7 @@ public class JShellTool implements MessageHandler {
}
private String unresolved(DeclarationSnippet key) {
List<String> unr = state.unresolvedDependencies(key);
List<String> unr = state.unresolvedDependencies(key).collect(toList());
StringBuilder sb = new StringBuilder();
int fromLast = unr.size();
if (fromLast > 0) {

View File

@ -43,6 +43,7 @@ import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream;
import jdk.internal.jshell.debug.InternalDebugControl;
import jdk.jshell.Snippet.Status;
import jdk.jshell.execution.JDIDefaultExecutionControl;
@ -504,9 +505,9 @@ public class JShell implements AutoCloseable {
* @return the snippets for all current snippets in id order.
* @throws IllegalStateException if this JShell instance is closed.
*/
public List<Snippet> snippets() throws IllegalStateException {
public Stream<Snippet> snippets() throws IllegalStateException {
checkIfAlive();
return Collections.unmodifiableList(maps.snippetList());
return maps.snippetList().stream();
}
/**
@ -518,11 +519,10 @@ public class JShell implements AutoCloseable {
* @return the active declared variables.
* @throws IllegalStateException if this JShell instance is closed.
*/
public List<VarSnippet> variables() throws IllegalStateException {
return snippets().stream()
public Stream<VarSnippet> variables() throws IllegalStateException {
return snippets()
.filter(sn -> status(sn).isActive() && sn.kind() == Snippet.Kind.VAR)
.map(sn -> (VarSnippet) sn)
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
.map(sn -> (VarSnippet) sn);
}
/**
@ -534,11 +534,10 @@ public class JShell implements AutoCloseable {
* @return the active declared methods.
* @throws IllegalStateException if this JShell instance is closed.
*/
public List<MethodSnippet> methods() throws IllegalStateException {
return snippets().stream()
public Stream<MethodSnippet> methods() throws IllegalStateException {
return snippets()
.filter(sn -> status(sn).isActive() && sn.kind() == Snippet.Kind.METHOD)
.map(sn -> (MethodSnippet)sn)
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
.map(sn -> (MethodSnippet)sn);
}
/**
@ -550,11 +549,10 @@ public class JShell implements AutoCloseable {
* @return the active declared type declarations.
* @throws IllegalStateException if this JShell instance is closed.
*/
public List<TypeDeclSnippet> types() throws IllegalStateException {
return snippets().stream()
public Stream<TypeDeclSnippet> types() throws IllegalStateException {
return snippets()
.filter(sn -> status(sn).isActive() && sn.kind() == Snippet.Kind.TYPE_DECL)
.map(sn -> (TypeDeclSnippet) sn)
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
.map(sn -> (TypeDeclSnippet) sn);
}
/**
@ -566,11 +564,10 @@ public class JShell implements AutoCloseable {
* @return the active declared import declarations.
* @throws IllegalStateException if this JShell instance is closed.
*/
public List<ImportSnippet> imports() throws IllegalStateException {
return snippets().stream()
public Stream<ImportSnippet> imports() throws IllegalStateException {
return snippets()
.filter(sn -> status(sn).isActive() && sn.kind() == Snippet.Kind.IMPORT)
.map(sn -> (ImportSnippet) sn)
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
.map(sn -> (ImportSnippet) sn);
}
/**
@ -598,8 +595,8 @@ public class JShell implements AutoCloseable {
* @throws IllegalArgumentException if the snippet is not associated with
* this {@code JShell} instance.
*/
public List<Diag> diagnostics(Snippet snippet) {
return Collections.unmodifiableList(checkValidSnippet(snippet).diagnostics());
public Stream<Diag> diagnostics(Snippet snippet) {
return checkValidSnippet(snippet).diagnostics().stream();
}
/**
@ -611,13 +608,13 @@ public class JShell implements AutoCloseable {
* {@code eval()} or {@code drop()} of another snippet causes
* an update of a dependency.
* @param snippet the declaration {@code Snippet} to look up
* @return the list of symbol names that are currently unresolvedDependencies.
* @return a stream of symbol names that are currently unresolvedDependencies.
* @throws IllegalStateException if this {@code JShell} instance is closed.
* @throws IllegalArgumentException if the snippet is not associated with
* this {@code JShell} instance.
*/
public List<String> unresolvedDependencies(DeclarationSnippet snippet) {
return Collections.unmodifiableList(checkValidSnippet(snippet).unresolved());
public Stream<String> unresolvedDependencies(DeclarationSnippet snippet) {
return checkValidSnippet(snippet).unresolved().stream();
}
/**

View File

@ -414,25 +414,29 @@ final class Unit {
// types are the same. if so, consider it an overwrite replacement.
private Status overwriteMatchingMethod(MethodSnippet msi) {
String qpt = msi.qualifiedParameterTypes();
List<MethodSnippet> matching = state.methods()
.filter(sn ->
sn != null
&& sn != msi
&& sn.status().isActive()
&& sn.name().equals(msi.name())
&& qpt.equals(sn.qualifiedParameterTypes()))
.collect(toList());
// Look through all methods for a method of the same name, with the
// same computed qualified parameter types
Status overwrittenStatus = null;
for (MethodSnippet sn : state.methods()) {
if (sn != null && sn != msi && sn.status().isActive() && sn.name().equals(msi.name())) {
if (qpt.equals(sn.qualifiedParameterTypes())) {
overwrittenStatus = sn.status();
SnippetEvent se = new SnippetEvent(
sn, overwrittenStatus, OVERWRITTEN,
false, msi, null, null);
sn.setOverwritten();
secondaryEvents.add(se);
state.debug(DBG_EVNT,
"Overwrite event #%d -- key: %s before: %s status: %s sig: %b cause: %s\n",
secondaryEvents.size(), se.snippet(), se.previousStatus(),
se.status(), se.isSignatureChange(), se.causeSnippet());
}
}
for (MethodSnippet sn : matching) {
overwrittenStatus = sn.status();
SnippetEvent se = new SnippetEvent(
sn, overwrittenStatus, OVERWRITTEN,
false, msi, null, null);
sn.setOverwritten();
secondaryEvents.add(se);
state.debug(DBG_EVNT,
"Overwrite event #%d -- key: %s before: %s status: %s sig: %b cause: %s\n",
secondaryEvents.size(), se.snippet(), se.previousStatus(),
se.status(), se.isSignatureChange(), se.causeSnippet());
}
return overwrittenStatus;
}

View File

@ -41,6 +41,7 @@ import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import jdk.jshell.Diag;
import static java.util.stream.Collectors.toList;
import static jdk.jshell.Snippet.Status.VALID;
import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED;
import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED;
@ -210,8 +211,8 @@ public class ClassesTest extends KullaTesting {
ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET));
***/
// It is random which one it shows up in, but cyclic error should be there
List<Diag> diagsA = getState().diagnostics(a);
List<Diag> diagsB = getState().diagnostics(b);
List<Diag> diagsA = getState().diagnostics(a).collect(toList());
List<Diag> diagsB = getState().diagnostics(b).collect(toList());
List<Diag> diags;
if (diagsA.isEmpty()) {
diags = diagsB;

View File

@ -0,0 +1,131 @@
/*
* 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.
*/
/*
* @test
* @bug 8143964
* @summary test queries to the JShell that return Streams
* @build KullaTesting
* @run testng JShellQueryTest
*/
import java.util.Set;
import java.util.stream.Stream;
import jdk.jshell.Snippet;
import org.testng.annotations.Test;
import jdk.jshell.ImportSnippet;
import jdk.jshell.MethodSnippet;
import jdk.jshell.TypeDeclSnippet;
import jdk.jshell.VarSnippet;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toSet;
import static org.testng.Assert.assertEquals;
@Test
public class JShellQueryTest extends KullaTesting {
private <T> void checkStreamMatch(Stream<T> result, T... expected) {
Set<T> sns = result.collect(toSet());
Set<T> exp = Stream.of(expected).collect(toSet());
assertEquals(sns, exp);
}
public void testSnippets() {
checkStreamMatch(getState().snippets());
VarSnippet sx = varKey(assertEval("int x = 5;"));
VarSnippet sfoo = varKey(assertEval("String foo;"));
MethodSnippet smm = methodKey(assertEval("int mm() { return 6; }"));
MethodSnippet svv = methodKey(assertEval("void vv() { }"));
checkStreamMatch(getState().snippets(), sx, sfoo, smm, svv);
TypeDeclSnippet sc = classKey(assertEval("class C { }"));
TypeDeclSnippet si = classKey(assertEval("interface I { }"));
ImportSnippet simp = importKey(assertEval("import java.lang.reflect.*;"));
checkStreamMatch(getState().snippets(), sx, sfoo, smm, svv, sc, si, simp);
}
public void testVars() {
checkStreamMatch(getState().variables());
VarSnippet sx = varKey(assertEval("int x = 5;"));
VarSnippet sfoo = varKey(assertEval("String foo;"));
MethodSnippet smm = methodKey(assertEval("int mm() { return 6; }"));
MethodSnippet svv = methodKey(assertEval("void vv() { }"));
checkStreamMatch(getState().variables(), sx, sfoo);
TypeDeclSnippet sc = classKey(assertEval("class C { }"));
TypeDeclSnippet si = classKey(assertEval("interface I { }"));
ImportSnippet simp = importKey(assertEval("import java.lang.reflect.*;"));
checkStreamMatch(getState().variables(), sx, sfoo);
}
public void testMethods() {
checkStreamMatch(getState().methods());
VarSnippet sx = varKey(assertEval("int x = 5;"));
VarSnippet sfoo = varKey(assertEval("String foo;"));
MethodSnippet smm = methodKey(assertEval("int mm() { return 6; }"));
MethodSnippet svv = methodKey(assertEval("void vv() { }"));
TypeDeclSnippet sc = classKey(assertEval("class C { }"));
TypeDeclSnippet si = classKey(assertEval("interface I { }"));
ImportSnippet simp = importKey(assertEval("import java.lang.reflect.*;"));
checkStreamMatch(getState().methods(), smm, svv);
}
public void testTypes() {
checkStreamMatch(getState().types());
VarSnippet sx = varKey(assertEval("int x = 5;"));
VarSnippet sfoo = varKey(assertEval("String foo;"));
MethodSnippet smm = methodKey(assertEval("int mm() { return 6; }"));
MethodSnippet svv = methodKey(assertEval("void vv() { }"));
TypeDeclSnippet sc = classKey(assertEval("class C { }"));
TypeDeclSnippet si = classKey(assertEval("interface I { }"));
ImportSnippet simp = importKey(assertEval("import java.lang.reflect.*;"));
checkStreamMatch(getState().types(), sc, si);
}
public void testImports() {
checkStreamMatch(getState().imports());
VarSnippet sx = varKey(assertEval("int x = 5;"));
VarSnippet sfoo = varKey(assertEval("String foo;"));
MethodSnippet smm = methodKey(assertEval("int mm() { return 6; }"));
MethodSnippet svv = methodKey(assertEval("void vv() { }"));
TypeDeclSnippet sc = classKey(assertEval("class C { }"));
TypeDeclSnippet si = classKey(assertEval("interface I { }"));
ImportSnippet simp = importKey(assertEval("import java.lang.reflect.*;"));
checkStreamMatch(getState().imports(), simp);
}
public void testDiagnostics() {
Snippet sx = varKey(assertEval("int x = 5;"));
checkStreamMatch(getState().diagnostics(sx));
Snippet broken = methodKey(assertEvalFail("int m() { blah(); return \"hello\"; }"));
String res = getState().diagnostics(broken)
.map(d -> d.getCode())
.collect(joining("+"));
assertEquals(res, "compiler.err.cant.resolve.location.args+compiler.err.prob.found.req");
}
public void testUnresolvedDependencies() {
VarSnippet sx = varKey(assertEval("int x = 5;"));
checkStreamMatch(getState().unresolvedDependencies(sx));
MethodSnippet unr = methodKey(getState().eval("void uu() { baz(); zips(); }"));
checkStreamMatch(getState().unresolvedDependencies(unr), "method zips()", "method baz()");
}
}

View File

@ -70,6 +70,7 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import jdk.jshell.Diag;
import static java.util.stream.Collectors.toList;
import static jdk.jshell.Snippet.Status.*;
import static org.testng.Assert.*;
import static jdk.jshell.Snippet.SubKind.METHOD_SUBKIND;
@ -183,7 +184,7 @@ public class KullaTesting {
}
public List<String> assertUnresolvedDependencies(DeclarationSnippet key, int unresolvedSize) {
List<String> unresolved = getState().unresolvedDependencies(key);
List<String> unresolved = getState().unresolvedDependencies(key).collect(toList());
assertEquals(unresolved.size(), unresolvedSize, "Input: " + key.source() + ", checking unresolved: ");
return unresolved;
}
@ -202,8 +203,8 @@ public class KullaTesting {
SnippetEvent ste = events.get(0);
DeclarationSnippet sn = ((UnresolvedReferenceException) ste.exception()).getSnippet();
assertEquals(sn.name(), name, "Given input: " + input + ", checking name");
assertEquals(getState().unresolvedDependencies(sn).size(), unresolvedSize, "Given input: " + input + ", checking unresolved");
assertEquals(getState().diagnostics(sn).size(), diagnosticsSize, "Given input: " + input + ", checking diagnostics");
assertEquals(getState().unresolvedDependencies(sn).count(), unresolvedSize, "Given input: " + input + ", checking unresolved");
assertEquals(getState().diagnostics(sn).count(), (long) diagnosticsSize, "Given input: " + input + ", checking diagnostics");
return sn;
}
@ -546,7 +547,7 @@ public class KullaTesting {
" got: " + main.exception().toString());
}
}
List<Diag> diagnostics = getState().diagnostics(mainKey);
List<Diag> diagnostics = getState().diagnostics(mainKey).collect(toList());
switch (diagMain) {
case DIAG_OK:
assertEquals(diagnostics.size(), 0, "Expected no diagnostics, got: " + diagnosticsToString(diagnostics));
@ -560,7 +561,7 @@ public class KullaTesting {
}
if (eventChain.mainInfo != null) {
for (STEInfo ste : eventChain.updates) {
diagnostics = getState().diagnostics(ste.snippet());
diagnostics = getState().diagnostics(ste.snippet()).collect(toList());
switch (diagUpdates) {
case DIAG_OK:
assertEquals(diagnostics.size(), 0, "Expected no diagnostics, got: " + diagnosticsToString(diagnostics));
@ -637,7 +638,7 @@ public class KullaTesting {
SnippetEvent e = events.get(0);
Snippet key = e.snippet();
assertEquals(getState().status(key), REJECTED);
List<Diag> diagnostics = getState().diagnostics(e.snippet());
List<Diag> diagnostics = getState().diagnostics(e.snippet()).collect(toList());
assertTrue(diagnostics.size() > 0, "Expected diagnostics, got none");
assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic);
assertTrue(key != null, "key must never be null, but it was for: " + input);
@ -656,7 +657,7 @@ public class KullaTesting {
List<SnippetEvent> events = assertEval(input, IGNORE_VALUE, null,
DiagCheck.DIAG_WARNING, DiagCheck.DIAG_IGNORE, mainInfo, updates);
SnippetEvent e = events.get(0);
List<Diag> diagnostics = getState().diagnostics(e.snippet());
List<Diag> diagnostics = getState().diagnostics(e.snippet()).collect(toList());
if (expectedDiagnostic != null) assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic);
return e.snippet();
}
@ -704,12 +705,12 @@ public class KullaTesting {
String source = declarationKey.source();
assertEquals(declarationKey.name(), expectedName,
"Expected " + source + " to have the name: " + expectedName + ", got: " + declarationKey.name());
List<String> unresolved = getState().unresolvedDependencies(declarationKey);
assertEquals(unresolved.size(), unressz, "Expected " + source + " to have " + unressz
+ " unresolved symbols, got: " + unresolved.size());
List<Diag> otherCorralledErrors = getState().diagnostics(declarationKey);
assertEquals(otherCorralledErrors.size(), othersz, "Expected " + source + " to have " + othersz
+ " other errors, got: " + otherCorralledErrors.size());
long unresolved = getState().unresolvedDependencies(declarationKey).count();
assertEquals(unresolved, unressz, "Expected " + source + " to have " + unressz
+ " unresolved symbols, got: " + unresolved);
long otherCorralledErrorsCount = getState().diagnostics(declarationKey).count();
assertEquals(otherCorralledErrorsCount, othersz, "Expected " + source + " to have " + othersz
+ " other errors, got: " + otherCorralledErrorsCount);
}
public void assertKey(Snippet key, Status expectedStatus, SubKind expectedSubKind) {
@ -757,31 +758,20 @@ public class KullaTesting {
}
public void assertNumberOfActiveVariables(int cnt) {
Collection<VarSnippet> variables = getState().variables();
assertEquals(variables.size(), cnt, "Variables : " + variables);
assertEquals(getState().variables().count(), cnt, "Variables : " + getState().variables().collect(toList()));
}
public void assertNumberOfActiveMethods(int cnt) {
Collection<MethodSnippet> methods = getState().methods();
assertEquals(methods.size(), cnt, "Methods : " + methods);
assertEquals(getState().methods().count(), cnt, "Methods : " + getState().methods().collect(toList()));
}
public void assertNumberOfActiveClasses(int cnt) {
Collection<TypeDeclSnippet> classes = getState().types();
assertEquals(classes.size(), cnt, "Classes : " + classes);
}
public void assertMembers(Collection<? extends Snippet> members, Set<MemberInfo> expected) {
assertEquals(members.size(), expected.size(), "Expected : " + expected + ", actual : " + members);
assertEquals(members.stream()
.map(this::getMemberInfo)
.collect(Collectors.toSet()),
expected);
assertEquals(getState().types().count(), cnt, "Types : " + getState().types().collect(toList()));
}
public void assertKeys(MemberInfo... expected) {
int index = 0;
List<Snippet> snippets = getState().snippets();
List<Snippet> snippets = getState().snippets().collect(toList());
assertEquals(allSnippets.size(), snippets.size());
for (Snippet sn : snippets) {
if (sn.kind().isPersistent() && getState().status(sn).isActive()) {
@ -801,7 +791,7 @@ public class KullaTesting {
public void assertActiveKeys(Snippet... expected) {
int index = 0;
for (Snippet key : getState().snippets()) {
for (Snippet key : getState().snippets().collect(toList())) {
if (state.status(key).isActive()) {
assertEquals(expected[index], key, String.format("Difference in #%d. Expected: %s, actual: %s", index, key, expected[index]));
++index;
@ -809,31 +799,43 @@ public class KullaTesting {
}
}
private List<Snippet> filterDeclaredKeys(Predicate<Snippet> p) {
return getActiveKeys().stream()
private void assertActiveSnippets(Stream<? extends Snippet> snippets, Predicate<Snippet> p, String label) {
Set<Snippet> active = getActiveKeys().stream()
.filter(p)
.collect(Collectors.toList());
.collect(Collectors.toSet());
Set<Snippet> got = snippets
.collect(Collectors.toSet());
assertEquals(active, got, label);
}
public void assertVariables() {
assertEquals(getState().variables(), filterDeclaredKeys((key) -> key instanceof VarSnippet), "Variables");
assertActiveSnippets(getState().variables(), (key) -> key instanceof VarSnippet, "Variables");
}
public void assertMethods() {
assertEquals(getState().methods(), filterDeclaredKeys((key) -> key instanceof MethodSnippet), "Methods");
assertActiveSnippets(getState().methods(), (key) -> key instanceof MethodSnippet, "Methods");
}
public void assertClasses() {
assertEquals(getState().types(), filterDeclaredKeys((key) -> key instanceof TypeDeclSnippet), "Classes");
assertActiveSnippets(getState().types(), (key) -> key instanceof TypeDeclSnippet, "Classes");
}
public void assertMembers(Stream<? extends Snippet> members, MemberInfo...expectedInfos) {
Set<MemberInfo> expected = Stream.of(expectedInfos).collect(Collectors.toSet());
Set<MemberInfo> got = members
.map(this::getMemberInfo)
.collect(Collectors.toSet());
assertEquals(got.size(), expected.size(), "Expected : " + expected + ", actual : " + members);
assertEquals(got, expected);
}
public void assertVariables(MemberInfo...expected) {
assertMembers(getState().variables(), Stream.of(expected).collect(Collectors.toSet()));
assertMembers(getState().variables(), expected);
}
public void assertMethods(MemberInfo...expected) {
assertMembers(getState().methods(), Stream.of(expected).collect(Collectors.toSet()));
for (MethodSnippet methodKey : getState().methods()) {
assertMembers(getState().methods(), expected);
getState().methods().forEach(methodKey -> {
MemberInfo expectedInfo = null;
for (MemberInfo info : expected) {
if (info.name.equals(methodKey.name()) && info.type.equals(methodKey.signature())) {
@ -843,11 +845,11 @@ public class KullaTesting {
assertNotNull(expectedInfo, "Not found method: " + methodKey.name());
int lastIndexOf = expectedInfo.type.lastIndexOf(')');
assertEquals(methodKey.parameterTypes(), expectedInfo.type.substring(1, lastIndexOf), "Parameter types");
}
});
}
public void assertClasses(MemberInfo...expected) {
assertMembers(getState().types(), Stream.of(expected).collect(Collectors.toSet()));
assertMembers(getState().types(), expected);
}
public void assertCompletion(String code, String... expected) {

View File

@ -39,6 +39,7 @@ import jdk.jshell.Snippet.Kind;
import jdk.jshell.Snippet.Status;
import jdk.jshell.SnippetEvent;
import static java.util.stream.Collectors.toList;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
@ -49,7 +50,7 @@ public class RejectedFailedTest extends KullaTesting {
List<SnippetEvent> events = assertEvalFail(input);
assertEquals(events.size(), 1, "Expected one event, got: " + events.size());
SnippetEvent e = events.get(0);
List<Diag> diagnostics = getState().diagnostics(e.snippet());
List<Diag> diagnostics = getState().diagnostics(e.snippet()).collect(toList());
assertTrue(diagnostics.size() > 0, "Expected diagnostics, got none");
assertEquals(e.exception(), null, "Expected exception to be null.");
assertEquals(e.value(), null, "Expected value to be null.");
@ -60,7 +61,7 @@ public class RejectedFailedTest extends KullaTesting {
SubKind expectedSubKind = kind == Kind.ERRONEOUS ? SubKind.UNKNOWN_SUBKIND : SubKind.METHOD_SUBKIND;
assertEquals(key.subKind(), expectedSubKind, "SubKind: ");
assertTrue(key.id().compareTo(prevId) > 0, "Current id: " + key.id() + ", previous: " + prevId);
assertEquals(getState().diagnostics(key), diagnostics, "Expected retrieved diagnostics to match, but didn't.");
assertEquals(getState().diagnostics(key).collect(toList()), diagnostics, "Expected retrieved diagnostics to match, but didn't.");
assertEquals(key.source(), input, "Expected retrieved source: " +
key.source() + " to match input: " + input);
assertEquals(getState().status(key), Status.REJECTED, "Expected status of REJECTED, got: " + getState().status(key));

View File

@ -28,9 +28,9 @@
* @run testng ReplaceTest
*/
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;
import jdk.jshell.Snippet;
import jdk.jshell.MethodSnippet;
import jdk.jshell.PersistentSnippet;
@ -42,6 +42,7 @@ import org.testng.annotations.Test;
import jdk.jshell.SnippetEvent;
import jdk.jshell.UnresolvedReferenceException;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static jdk.jshell.Snippet.Status.*;
import static jdk.jshell.Snippet.SubKind.*;
import static org.testng.Assert.assertTrue;
@ -90,17 +91,22 @@ public class ReplaceTest extends KullaTesting {
assertActiveKeys();
}
private <T extends Snippet> void identityMatch(Stream<T> got, T expected) {
Iterator<T> it = got.iterator();
assertTrue(it.hasNext(), "expected exactly one");
assertTrue(expected == it.next(), "Identity must not change");
assertFalse(it.hasNext(), "expected exactly one");
}
public void testReplaceVarToMethod() {
Snippet x = varKey(assertEval("int x;"));
Snippet musn = methodKey(assertEval("double mu() { return x * 4; }"));
MethodSnippet musn = methodKey(assertEval("double mu() { return x * 4; }"));
assertEval("x == 0;", "true");
assertEval("mu() == 0.0;", "true");
assertEval("double x = 2.5;",
ste(MAIN_SNIPPET, VALID, VALID, true, null),
ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
Collection<MethodSnippet> meths = getState().methods();
assertEquals(meths.size(), 1);
assertTrue(musn == meths.iterator().next(), "Identity must not change");
identityMatch(getState().methods(), musn);
assertEval("x == 2.5;", "true");
assertEval("mu() == 10.0;", "true"); // Auto redefine
assertActiveKeys();
@ -132,15 +138,13 @@ public class ReplaceTest extends KullaTesting {
public void testReplaceVarToClass() {
Snippet x = varKey(assertEval("int x;"));
Snippet c = classKey(assertEval("class A { double a = 4 * x; }"));
TypeDeclSnippet c = classKey(assertEval("class A { double a = 4 * x; }"));
assertEval("x == 0;", "true");
assertEval("new A().a == 0.0;", "true");
assertEval("double x = 2.5;",
ste(MAIN_SNIPPET, VALID, VALID, true, null),
ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
Collection<TypeDeclSnippet> classes = getState().types();
assertEquals(classes.size(), 1);
assertTrue(c == classes.iterator().next(), "Identity must not change");
identityMatch(getState().types(), c);
assertEval("x == 2.5;", "true");
assertEval("new A().a == 10.0;", "true");
assertActiveKeys();
@ -148,16 +152,14 @@ public class ReplaceTest extends KullaTesting {
public void testReplaceMethodToClass() {
Snippet x = methodKey(assertEval("int x() { return 0; }"));
Snippet c = classKey(assertEval("class A { double a = 4 * x(); }"));
TypeDeclSnippet c = classKey(assertEval("class A { double a = 4 * x(); }"));
assertEval("x() == 0;", "true");
assertEval("new A().a == 0.0;", "true");
assertEval("double x() { return 2.5; }",
ste(MAIN_SNIPPET, VALID, VALID, true, null),
ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
assertEval("x();", "2.5");
Collection<TypeDeclSnippet> classes = getState().types();
assertEquals(classes.size(), 1);
assertTrue(c == classes.iterator().next(), "Identity must not change");
identityMatch(getState().types(), c);
assertEval("x() == 2.5;", "true");
assertEval("new A().a == 10.0;", "true");
assertActiveKeys();
@ -313,8 +315,8 @@ public class ReplaceTest extends KullaTesting {
Snippet assn = ste.snippet();
DeclarationSnippet unsn = ((UnresolvedReferenceException) ste.exception()).getSnippet();
assertEquals(unsn.name(), "A", "Wrong with unresolved");
assertEquals(getState().unresolvedDependencies(unsn).size(), 1, "Wrong size unresolved");
assertEquals(getState().diagnostics(unsn).size(), 0, "Expected no diagnostics");
assertEquals(getState().unresolvedDependencies(unsn).count(), 1, "Wrong size unresolved");
assertEquals(getState().diagnostics(unsn).count(), 0L, "Expected no diagnostics");
Snippet g = varKey(assertEval("int g = 10;", "10",
added(VALID),

View File

@ -39,6 +39,7 @@ import jdk.jshell.Snippet.SubKind;
import jdk.jshell.SnippetEvent;
import org.testng.annotations.Test;
import static java.util.stream.Collectors.toList;
import static jdk.jshell.Snippet.Status.*;
import static jdk.jshell.Snippet.SubKind.VAR_DECLARATION_SUBKIND;
import static org.testng.Assert.assertEquals;
@ -331,7 +332,7 @@ public class VariablesTest extends KullaTesting {
//assertEquals(getState().source(snippet), src);
//assertEquals(snippet, undefKey);
assertEquals(getState().status(undefKey), RECOVERABLE_NOT_DEFINED);
List<String> unr = getState().unresolvedDependencies((VarSnippet) undefKey);
List<String> unr = getState().unresolvedDependencies((VarSnippet) undefKey).collect(toList());;
assertEquals(unr.size(), 1);
assertEquals(unr.get(0), "class undefined");
assertVariables(variable("undefined", "d"));