8143964: JShell API: convert query responses to Stream instead of List
authorrfield
Tue, 09 Aug 2016 23:00:49 -0700
changeset 40304 0318f4e75c6d
parent 40303 96a1226aca18
child 40305 4262ef5fc5f0
8143964: JShell API: convert query responses to Stream instead of List Reviewed-by: psandoz, shinyafox
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java
langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java
langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java
langtools/test/jdk/jshell/ClassesTest.java
langtools/test/jdk/jshell/JShellQueryTest.java
langtools/test/jdk/jshell/KullaTesting.java
langtools/test/jdk/jshell/RejectedFailedTest.java
langtools/test/jdk/jshell/ReplaceTest.java
langtools/test/jdk/jshell/VariablesTest.java
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Tue Aug 09 13:22:57 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Tue Aug 09 23:00:49 2016 -0700
@@ -973,10 +973,10 @@
                                     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 @@
         };
     }
 
-    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 @@
 
     // 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 @@
      * 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 @@
         }
         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 @@
         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 @@
             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 @@
     }
 
     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 @@
         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 @@
             } 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 @@
     }
 
     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 @@
     }
 
     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 @@
     }
 
     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 @@
     }
 
     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 @@
     }
 
     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 @@
             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 @@
     //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 @@
             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 @@
         }
 
         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) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java	Tue Aug 09 13:22:57 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java	Tue Aug 09 23:00:49 2016 -0700
@@ -43,6 +43,7 @@
 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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      * @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 @@
      * {@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();
     }
 
     /**
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java	Tue Aug 09 13:22:57 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java	Tue Aug 09 23:00:49 2016 -0700
@@ -414,25 +414,29 @@
     // 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;
     }
--- a/langtools/test/jdk/jshell/ClassesTest.java	Tue Aug 09 13:22:57 2016 -0700
+++ b/langtools/test/jdk/jshell/ClassesTest.java	Tue Aug 09 23:00:49 2016 -0700
@@ -41,6 +41,7 @@
 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 @@
                 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;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/JShellQueryTest.java	Tue Aug 09 23:00:49 2016 -0700
@@ -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()");
+    }
+}
--- a/langtools/test/jdk/jshell/KullaTesting.java	Tue Aug 09 13:22:57 2016 -0700
+++ b/langtools/test/jdk/jshell/KullaTesting.java	Tue Aug 09 23:00:49 2016 -0700
@@ -70,6 +70,7 @@
 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 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 @@
         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 @@
                                     " 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 @@
             }
             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 @@
         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 @@
         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 @@
         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 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 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 @@
         }
     }
 
-    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 @@
             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) {
--- a/langtools/test/jdk/jshell/RejectedFailedTest.java	Tue Aug 09 13:22:57 2016 -0700
+++ b/langtools/test/jdk/jshell/RejectedFailedTest.java	Tue Aug 09 23:00:49 2016 -0700
@@ -39,6 +39,7 @@
 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 @@
         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 @@
         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));
--- a/langtools/test/jdk/jshell/ReplaceTest.java	Tue Aug 09 13:22:57 2016 -0700
+++ b/langtools/test/jdk/jshell/ReplaceTest.java	Tue Aug 09 23:00:49 2016 -0700
@@ -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 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 @@
         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 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 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 @@
         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),
--- a/langtools/test/jdk/jshell/VariablesTest.java	Tue Aug 09 13:22:57 2016 -0700
+++ b/langtools/test/jdk/jshell/VariablesTest.java	Tue Aug 09 23:00:49 2016 -0700
@@ -39,6 +39,7 @@
 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 @@
         //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"));