# HG changeset patch # User rfield # Date 1461599416 25200 # Node ID 33cf53901cac0f7947d97e9262921878b27f3e90 # Parent 626e07816dce8a3f25f1b8d89d0dfec66edcef2d 8154485: JShell: infrastructure for multi-Snippet class wrappers Reviewed-by: jlahoda diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteAgent.java Mon Apr 25 08:50:16 2016 -0700 @@ -262,9 +262,14 @@ } } + /** + * Expunge internal info from string + * @param s string to process + * @return string the display, JShell package and wrapper class names removed + */ static String expunge(String s) { StringBuilder sb = new StringBuilder(); - for (String comp : prefixPattern.split(s)) { + for (String comp : PREFIX_PATTERN.split(s)) { sb.append(comp); } return sb.toString(); diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java Mon Apr 25 08:50:16 2016 -0700 @@ -47,8 +47,12 @@ public static final int RESULT_CORRALLED = 103; public static final int RESULT_KILLED = 104; + // String constants + public static final String REPL_PACKAGE = "REPL"; + public static final String REPL_CLASS_PREFIX = "$JShell$"; public static final String DOIT_METHOD_NAME = "do_it$"; - public static final String replClass = "\\$REPL(?\\d+)[A-Z]*"; - public static final Pattern prefixPattern = Pattern.compile("(REPL\\.)?" + replClass + "[\\$\\.]?"); - + public static final Pattern PREFIX_PATTERN = Pattern.compile( + "(" + REPL_PACKAGE + "\\.)?" + + "(?" + Pattern.quote(REPL_CLASS_PREFIX) + + "\\w+" + ")" + "[\\$\\.]?"); } diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Mon Apr 25 08:50:16 2016 -0700 @@ -512,7 +512,7 @@ /set format verbose errorpre '| ' \n\ /set format verbose errorpost '%n' \n\ \n\ -/set format verbose errorline '{pre} {err}' \n\ +/set format verbose errorline '{post}{pre} {err}' \n\ \n\ /set format verbose action 'created' added-primary \n\ /set format verbose action 'modified' modified-primary \n\ diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ClassTracker.java Mon Apr 25 08:50:16 2016 -0700 @@ -27,6 +27,7 @@ import java.util.Arrays; import java.util.HashMap; +import java.util.Objects; import com.sun.jdi.ReferenceType; /** @@ -82,6 +83,17 @@ } return rt; } + + @Override + public boolean equals(Object o) { + return o instanceof ClassInfo && + ((ClassInfo) o).className.equals(className); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.className); + } } ClassInfo classInfo(String className, byte[] bytes) { @@ -93,5 +105,4 @@ ClassInfo get(String className) { return map.get(className); } - } diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java Mon Apr 25 08:50:16 2016 -0700 @@ -84,6 +84,6 @@ @Override String importLine(JShell state) { - return "import static " + state.maps.classFullName(this) + "." + name() + ";\n"; + return "import static " + classFullName() + "." + name() + ";\n"; } } diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java Mon Apr 25 08:50:16 2016 -0700 @@ -100,10 +100,12 @@ // *** Internal support *** /** - * Internal: If this is from a compile, extract the compilation Unit. + * Internal: If this is from a compile/analyze wrapped in an outer class, extract the snippet. * Otherwise null. */ - abstract Unit unitOrNull(); + Snippet snippetOrNull() { + return null; + } /** * This is an unreachable-statement error @@ -124,6 +126,7 @@ */ boolean isResolutionError() { //TODO: try javac RESOLVE_ERROR flag - return getCode().startsWith("compiler.err.cant.resolve"); + return getCode().startsWith("compiler.err.cant.resolve") + || getCode().equals("compiler.err.cant.apply.symbol"); } } diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DiagList.java Mon Apr 25 08:50:16 2016 -0700 @@ -106,7 +106,10 @@ DiagList ofUnit(Unit u) { return this.stream() - .filter(d -> d.unitOrNull() == u) + .filter(d -> { + Snippet snn = d.snippetOrNull(); + return snn == u.snippet(); + }) .collect(Collectors.toCollection(() -> new DiagList())); } diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Mon Apr 25 08:50:16 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -22,7 +22,6 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package jdk.jshell; import java.util.ArrayList; @@ -50,7 +49,6 @@ import java.io.Writer; import java.util.LinkedHashSet; import java.util.Set; -import com.sun.tools.javac.util.Context; import jdk.jshell.ClassTracker.ClassInfo; import jdk.jshell.Key.ErroneousKey; import jdk.jshell.Key.MethodKey; @@ -68,7 +66,7 @@ import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; import static jdk.jshell.Util.*; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; -import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; import static jdk.jshell.Snippet.SubKind.SINGLE_TYPE_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.SINGLE_STATIC_IMPORT_SUBKIND; import static jdk.jshell.Snippet.SubKind.TYPE_IMPORT_ON_DEMAND_SUBKIND; @@ -339,18 +337,8 @@ return declare(snip); } - private OuterWrap wrapInClass(String className, Set except, String userSource, Wrap guts, Collection plus) { - String imports = state.maps.packageAndImportsExcept(except, plus); - return OuterWrap.wrapInClass(state.maps.packageName(), className, imports, userSource, guts); - } - - OuterWrap wrapInClass(Snippet snip, Set except, Wrap guts, Collection plus) { - return wrapInClass(snip.className(), except, snip.source(), guts, plus); - } - private AnalyzeTask trialCompile(Wrap guts) { - OuterWrap outer = wrapInClass(REPL_DOESNOTMATTER_CLASS_NAME, - Collections.emptySet(), "", guts, null); + OuterWrap outer = state.outerMap.wrapInTrialClass(guts); return state.taskFactory.new AnalyzeTask(outer); } @@ -468,7 +456,7 @@ if (si.status().isDefined) { if (si.isExecutable()) { try { - value = state.executionControl().commandInvoke(state.maps.classFullName(si)); + value = state.executionControl().commandInvoke(si.classFullName()); value = si.subKind().hasValue() ? expunge(value) : ""; @@ -504,37 +492,54 @@ return events(c, outs, value, exception); } + private boolean interestingEvent(SnippetEvent e) { + return e.isSignatureChange() + || e.causeSnippet() == null + || e.status() != e.previousStatus() + || e.exception() != null; + } + private List events(Unit c, Collection outs, String value, Exception exception) { List events = new ArrayList<>(); events.add(c.event(value, exception)); events.addAll(outs.stream() .filter(u -> u != c) .map(u -> u.event(null, null)) + .filter(this::interestingEvent) .collect(Collectors.toList())); events.addAll(outs.stream() .flatMap(u -> u.secondaryEvents().stream()) + .filter(this::interestingEvent) .collect(Collectors.toList())); //System.err.printf("Events: %s\n", events); return events; } + private Set outerWrapSet(Collection units) { + return units.stream() + .map(u -> u.snippet().outerWrap()) + .collect(toSet()); + } + private Set compileAndLoad(Set ins) { if (ins.isEmpty()) { return ins; } Set replaced = new LinkedHashSet<>(); + // Loop until dependencies and errors are stable while (true) { state.debug(DBG_GEN, "compileAndLoad %s\n", ins); - ins.stream().forEach(u -> u.initialize(ins)); - AnalyzeTask at = state.taskFactory.new AnalyzeTask(ins); + ins.stream().forEach(u -> u.initialize()); + ins.stream().forEach(u -> u.setWrap(ins, ins)); + AnalyzeTask at = state.taskFactory.new AnalyzeTask(outerWrapSet(ins)); ins.stream().forEach(u -> u.setDiagnostics(at)); // corral any Snippets that need it AnalyzeTask cat; if (ins.stream().anyMatch(u -> u.corralIfNeeded(ins))) { // if any were corralled, re-analyze everything - cat = state.taskFactory.new AnalyzeTask(ins); + cat = state.taskFactory.new AnalyzeTask(outerWrapSet(ins)); ins.stream().forEach(u -> u.setCorralledDiagnostics(cat)); } else { cat = at; @@ -556,7 +561,7 @@ legit.stream().forEach(u -> u.setWrap(ins, legit)); // generate class files for those capable - CompileTask ct = state.taskFactory.new CompileTask(legit); + CompileTask ct = state.taskFactory.new CompileTask(outerWrapSet(legit)); if (!ct.compile()) { // oy! compile failed because of recursive new unresolved if (legit.stream() @@ -572,8 +577,8 @@ // load all new classes load(legit.stream() - .flatMap(u -> u.classesToLoad(ct.classInfoList(u))) - .collect(toList())); + .flatMap(u -> u.classesToLoad(ct.classInfoList(u.snippet().outerWrap()))) + .collect(toSet())); // attempt to redefine the remaining classes List toReplace = legit.stream() .filter(u -> !u.doRedefines()) @@ -607,7 +612,7 @@ } } - private void load(List cil) { + private void load(Set cil) { if (!cil.isEmpty()) { state.executionControl().commandLoad(cil); } @@ -625,20 +630,14 @@ StackTraceElement[] elems = new StackTraceElement[last + 1]; for (int i = 0; i <= last; ++i) { StackTraceElement r = raw[i]; - String rawKlass = r.getClassName(); - Matcher matcher = prefixPattern.matcher(rawKlass); - String num; - if (matcher.find() && (num = matcher.group("num")) != null) { - int end = matcher.end(); - if (rawKlass.charAt(end - 1) == '$') { - --end; - } - int id = Integer.parseInt(num); - Snippet si = state.maps.getSnippet(id); - String klass = expunge(rawKlass); + OuterSnippetsClassWrap outer = state.outerMap.getOuter(r.getClassName()); + if (outer != null) { + String klass = expunge(r.getClassName()); String method = r.getMethodName().equals(DOIT_METHOD_NAME) ? "" : r.getMethodName(); - String file = "#" + id; - int line = si.outerWrap().wrapLineToSnippetLine(r.getLineNumber() - 1) + 1; + int wln = r.getLineNumber() - 1; + int line = outer.wrapLineToSnippetLine(wln) + 1; + Snippet sn = outer.wrapLineToSnippet(wln); + String file = "#" + sn.id(); elems[i] = new StackTraceElement(klass, method, file, line); } else if (r.getFileName().equals("")) { elems[i] = new StackTraceElement(r.getClassName(), r.getMethodName(), null, r.getLineNumber()); @@ -654,7 +653,7 @@ } private boolean isWrap(StackTraceElement ste) { - return prefixPattern.matcher(ste.getClassName()).find(); + return PREFIX_PATTERN.matcher(ste.getClassName()).find(); } private DiagList modifierDiagnostics(ModifiersTree modtree, @@ -714,11 +713,6 @@ public String getMessage(Locale locale) { return message; } - - @Override - Unit unitOrNull() { - return null; - } } List list = new ArrayList<>(); diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Mon Apr 25 08:50:16 2016 -0700 @@ -36,6 +36,7 @@ import java.net.Socket; import com.sun.jdi.*; import java.io.EOFException; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -94,7 +95,7 @@ } - boolean commandLoad(List cil) { + boolean commandLoad(Collection cil) { try { out.writeInt(CMD_LOAD); out.writeInt(cil.size()); @@ -122,7 +123,7 @@ String result = in.readUTF(); return result; } - } catch (IOException | ClassNotFoundException ex) { + } catch (IOException | RuntimeException ex) { if (!env.connection().isRunning()) { env.shutdown(); } else { @@ -204,7 +205,7 @@ } } - private boolean readAndReportExecutionResult() throws IOException, ClassNotFoundException, EvalException, UnresolvedReferenceException { + private boolean readAndReportExecutionResult() throws IOException, EvalException, UnresolvedReferenceException { int ok = in.readInt(); switch (ok) { case RESULT_SUCCESS: @@ -224,7 +225,7 @@ case RESULT_CORRALLED: { int id = in.readInt(); StackTraceElement[] elems = readStackTrace(); - Snippet si = maps.getSnippet(id); + Snippet si = maps.getSnippetDeadOrAlive(id); throw new UnresolvedReferenceException((DeclarationSnippet) si, elems); } case RESULT_KILLED: { diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Mon Apr 25 08:50:16 2016 -0700 @@ -77,6 +77,7 @@ final SnippetMaps maps; final KeyMap keyMap; + final OuterWrapMap outerMap; final TaskFactory taskFactory; final InputStream in; final PrintStream out; @@ -106,8 +107,8 @@ this.idGenerator = b.idGenerator; this.maps = new SnippetMaps(this); - maps.setPackageName("REPL"); this.keyMap = new KeyMap(this); + this.outerMap = new OuterWrapMap(this); this.taskFactory = new TaskFactory(this); this.eval = new Eval(this); this.classTracker = new ClassTracker(this); @@ -563,7 +564,7 @@ throw new IllegalArgumentException( messageFormat("jshell.exc.var.not.valid", snippet, snippet.status())); } - String value = executionControl().commandVarValue(maps.classFullName(snippet), snippet.name()); + String value = executionControl().commandVarValue(snippet.classFullName(), snippet.name()); return expunge(value); } diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterImportSnippetWrap.java Mon Apr 25 08:50:16 2016 -0700 @@ -0,0 +1,61 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.jshell; + +import java.util.IdentityHashMap; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + +/** + * The outer wrap for a set of snippets wrapped in a generated class + * @author Robert Field + */ +public class OuterImportSnippetWrap extends OuterWrap { + + private final Snippet snippet; + + OuterImportSnippetWrap(Wrap wrap, Snippet snippet) { + super(wrap); + this.snippet = snippet; + } + + @Override + Diag wrapDiag(Diagnostic d) { + return new WrappedDiagnostic(d) { + + @Override + Snippet snippetOrNull() { + return snippet; + } + }; + } + + @Override + public String toString() { + return "OISW(" + w + ")"; + } +} diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterSnippetsClassWrap.java Mon Apr 25 08:50:16 2016 -0700 @@ -0,0 +1,95 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.jshell; + +import java.util.LinkedHashMap; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import jdk.jshell.Wrap.CompoundWrap; + +/** + * The outer wrap for a set of snippets wrapped in a generated class + * @author Robert Field + */ +public class OuterSnippetsClassWrap extends OuterWrap { + + private final String className; + private final LinkedHashMap wrapToSnippet; + + OuterSnippetsClassWrap(String className, CompoundWrap w, List snippets, List wraps) { + super(w); + assert snippets == null || snippets.size() == wraps.size(); + this.className = className; + wrapToSnippet = new LinkedHashMap<>(); + for (int i = 0; i < snippets.size(); ++i) { + wrapToSnippet.put(wraps.get(i), snippets.get(i)); + } + } + + public Snippet wrapLineToSnippet(int wline) { + Wrap wrap = ((CompoundWrap)w).wrapLineToWrap(wline); + return wrapToSnippet.get(wrap); + } + + @Override + Diag wrapDiag(Diagnostic d) { + return new WrappedDiagnostic(d) { + + @Override + Snippet snippetOrNull() { + Wrap wrap = ((CompoundWrap) w).wrapIndexToWrap(diag.getPosition()); + Snippet sn = wrapToSnippet.get(wrap); + if (sn != null) { + return sn; + } else { + return super.snippetOrNull(); + } + } + }; + } + + int ordinal(Snippet sn) { + int i = 0; + for (Snippet si : wrapToSnippet.values()) { + if (si == sn) { + return i; + } + ++i; + } + return -1; + } + + @Override + public String className() { + return className; + } + + @Override + public String toString() { + return "OSCW(" + className + ":" + w + ")"; + } +} diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java Mon Apr 25 08:50:16 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015-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 @@ -25,47 +25,23 @@ package jdk.jshell; -import jdk.jshell.Wrap.CompoundWrap; -import static jdk.jshell.Util.*; import java.util.Locale; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; -import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject; -import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN; +import jdk.internal.jshell.remote.RemoteCodes; +import static jdk.jshell.Util.*; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_PACKAGE; /** * * @author Robert Field */ -final class OuterWrap implements GeneralWrap { - - private final String packageName; - private final String className; - private final String userSource; - private final GeneralWrap w; - private final Wrap guts; +class OuterWrap implements GeneralWrap { - public static OuterWrap wrapInClass(String packageName, String className, - String imports, String userSource, Wrap guts) { - GeneralWrap kw = new CompoundWrap( - imports - + "class " + className + " {\n", - guts, - "}\n"); - return new OuterWrap(packageName, className, userSource, kw, guts); - } + protected final Wrap w; - public static OuterWrap wrapImport(String userSource, Wrap guts) { - return new OuterWrap("", "", userSource, guts, guts); - } - - private OuterWrap(String packageName, String className, String userSource, - GeneralWrap w, Wrap guts) { - this.packageName = packageName; - this.className = className; - this.userSource = userSource; - this.w = w; - this.guts = guts; + OuterWrap(Wrap wrap) { + this.w = wrap; } @Override @@ -114,19 +90,28 @@ } public String className() { - return className; + return REPL_DOESNOTMATTER_CLASS_NAME; } public String classFullName() { - return packageName + "." + className; + return REPL_PACKAGE + "." + className(); + } + + @Override + public int hashCode() { + return className().hashCode(); } - public String getUserSource() { - return userSource; + @Override + public boolean equals(Object o) { + return (o instanceof OuterWrap) + ? className().equals(((OuterWrap) o).className()) + : false; } - Wrap guts() { - return guts; + @Override + public String toString() { + return "OW(" + w + ")"; } Diag wrapDiag(Diagnostic d) { @@ -135,7 +120,7 @@ class WrappedDiagnostic extends Diag { - private final Diagnostic diag; + final Diagnostic diag; WrappedDiagnostic(Diagnostic diag) { this.diag = diag; @@ -172,25 +157,13 @@ } @Override - Unit unitOrNull() { - JavaFileObject fo = diag.getSource(); - if (fo instanceof SourceMemoryJavaFileObject) { - SourceMemoryJavaFileObject sfo = (SourceMemoryJavaFileObject) fo; - if (sfo.getOrigin() instanceof Unit) { - return (Unit) sfo.getOrigin(); - } - } - return null; - } - - @Override boolean isResolutionError() { if (!super.isResolutionError()) { return false; } for (String line : diag.getMessage(PARSED_LOCALE).split("\\r?\\n")) { if (line.trim().startsWith("location:")) { - if (!line.contains(REPL_CLASS_PREFIX)) { + if (!line.contains(RemoteCodes.REPL_CLASS_PREFIX)) { // Resolution error must occur within a REPL class or it is not resolvable return false; } diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java Mon Apr 25 08:50:16 2016 -0700 @@ -0,0 +1,98 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package jdk.jshell; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.stream.Collectors; +import jdk.jshell.Wrap.CompoundWrap; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_CLASS_PREFIX; +import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; +import static jdk.jshell.Util.asLetters; + +/** + * + * @author Robert Field + */ +public class OuterWrapMap { + + private final JShell state; + private final Map classOuters = new HashMap<>(); + + OuterWrapMap(JShell state) { + this.state = state; + } + + OuterSnippetsClassWrap getOuter(String className) { + Matcher matcher = PREFIX_PATTERN.matcher(className); + String cn; + if (matcher.find() && (cn = matcher.group("class")) != null) { + return classOuters.get(cn); + } + return null; + } + + private CompoundWrap wrappedInClass(String className, String imports, List wraps) { + List elems = new ArrayList<>(wraps.size() + 2); + elems.add(imports + + "class " + className + " {\n"); + elems.addAll(wraps); + elems.add("}\n"); + return new CompoundWrap(elems.toArray()); + } + + OuterWrap wrapInClass(Set except, Collection plus, + List snippets, List wraps) { + String imports = state.maps.packageAndImportsExcept(except, plus); + // className is unique to the set of snippets and their version (seq) + String className = REPL_CLASS_PREFIX + snippets.stream() + .sorted((sn1, sn2) -> sn1.key().index() - sn2.key().index()) + .map(sn -> "" + sn.key().index() + asLetters(sn.sequenceNumber())) + .collect(Collectors.joining("_")); + CompoundWrap w = wrappedInClass(className, imports, wraps); + OuterSnippetsClassWrap now = new OuterSnippetsClassWrap(className, w, snippets, wraps); + classOuters.put(className, now); + return now; + } + + OuterWrap wrapInTrialClass(Wrap wrap) { + String imports = state.maps.packageAndImportsExcept(null, null); + CompoundWrap w = wrappedInClass(REPL_DOESNOTMATTER_CLASS_NAME, imports, + Collections.singletonList(wrap)); + return new OuterWrap(w); + } + + OuterWrap wrapImport(Wrap guts, Snippet sn) { + return new OuterImportSnippetWrap(guts, sn); + } +} diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Snippet.java Mon Apr 25 08:50:16 2016 -0700 @@ -28,8 +28,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import static jdk.jshell.Util.REPL_CLASS_PREFIX; -import static jdk.jshell.Util.asLetters; /** * A Snippet represents a snippet of Java source code as passed to @@ -503,7 +501,6 @@ private final SubKind subkind; private int seq; - private String className; private String id; private OuterWrap outer; private Status status; @@ -615,7 +612,6 @@ final void setSequenceNumber(int seq) { this.seq = seq; - this.className = REPL_CLASS_PREFIX + key().index() + asLetters(seq); } void setOuterWrap(OuterWrap outer) { @@ -653,7 +649,11 @@ } String className() { - return className; + return outer.className(); + } + + String classFullName() { + return outer.classFullName(); } /** diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java Mon Apr 25 08:50:16 2016 -0700 @@ -38,8 +38,9 @@ import java.util.stream.Stream; import static java.util.stream.Collectors.toList; -import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; import static jdk.internal.jshell.debug.InternalDebugControl.DBG_DEP; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_PACKAGE; /** * Maintain relationships between the significant entities: Snippets, @@ -48,7 +49,6 @@ */ final class SnippetMaps { - private String packageName; private final List keyIndexToSnippet = new ArrayList<>(); private final Set snippets = new LinkedHashSet<>(); private final Map> dependencies = new HashMap<>(); @@ -81,6 +81,13 @@ } Snippet getSnippet(int ki) { + Snippet sn = getSnippetDeadOrAlive(ki); + return (sn != null && !sn.status().isActive) + ? null + : sn; + } + + Snippet getSnippetDeadOrAlive(int ki) { if (ki >= keyIndexToSnippet.size()) { return null; } @@ -91,21 +98,9 @@ return new ArrayList<>(snippets); } - void setPackageName(String n) { - packageName = n; - } - - String packageName() { - return packageName; - } - - String classFullName(Snippet sn) { - return packageName + "." + sn.className(); - } - String packageAndImportsExcept(Set except, Collection plus) { StringBuilder sb = new StringBuilder(); - sb.append("package ").append(packageName()).append(";\n"); + sb.append("package ").append(REPL_PACKAGE).append(";\n"); for (Snippet si : keyIndexToSnippet) { if (si != null && si.status().isDefined && (except == null || !except.contains(si.key()))) { sb.append(si.importLine(state)); @@ -137,7 +132,7 @@ } List deps = new ArrayList<>(); for (Integer dss : depset) { - Snippet dep = getSnippet(dss); + Snippet dep = getSnippetDeadOrAlive(dss); if (dep != null) { deps.add(dep); state.debug(DBG_DEP, "Found dependency %s -> %s\n", snip.name(), dep.name()); @@ -161,7 +156,7 @@ } String fullClassNameAndPackageToClass(String full, String pkg) { - Matcher mat = prefixPattern.matcher(full); + Matcher mat = PREFIX_PATTERN.matcher(full); if (mat.lookingAt()) { return full.substring(mat.end()); } @@ -195,6 +190,6 @@ private Stream importSnippets() { return state.keyMap.importKeys() .map(key -> (ImportSnippet)getSnippet(key)) - .filter(sn -> state.status(sn).isDefined); + .filter(sn -> sn != null && state.status(sn).isDefined); } } diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Mon Apr 25 08:50:16 2016 -0700 @@ -211,11 +211,6 @@ throw new InternalError(); } - private OuterWrap wrapInClass(Wrap guts) { - String imports = proc.maps.packageAndImportsExcept(null, null); - return OuterWrap.wrapInClass(proc.maps.packageName(), REPL_DOESNOTMATTER_CLASS_NAME, imports, "", guts); - } - private Tree.Kind guessKind(String code) { ParseTask pt = proc.taskFactory.new ParseTask(code); List units = pt.units(); @@ -258,13 +253,13 @@ OuterWrap codeWrap; switch (guessKind(code)) { case IMPORT: - codeWrap = OuterWrap.wrapImport(null, Wrap.simpleWrap(code + "any.any")); + codeWrap = proc.outerMap.wrapImport(Wrap.simpleWrap(code + "any.any"), null); break; case METHOD: - codeWrap = wrapInClass(Wrap.classMemberWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.classMemberWrap(code)); break; default: - codeWrap = wrapInClass(Wrap.methodWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); break; } String requiredPrefix = identifier; @@ -946,7 +941,7 @@ if (guessKind(code) == Kind.IMPORT) return null; - OuterWrap codeWrap = wrapInClass(Wrap.methodWrap(code)); + OuterWrap codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); SourcePositions sp = at.trees().getSourcePositions(); CompilationUnitTree topLevel = at.firstCuTree(); @@ -1064,7 +1059,7 @@ case INTERFACE: case ANNOTATION_TYPE: case VARIABLE: return null; default: - codeWrap = wrapInClass(Wrap.methodWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); break; } AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); @@ -1104,10 +1099,10 @@ case IMPORT: return new QualifiedNames(Collections.emptyList(), -1, true, false); case METHOD: - codeWrap = wrapInClass(Wrap.classMemberWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.classMemberWrap(code)); break; default: - codeWrap = wrapInClass(Wrap.methodWrap(code)); + codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); break; } AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Mon Apr 25 08:50:16 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -148,23 +148,12 @@ public String getMessage(Locale locale) { return expunge(d.getMessage(locale)); } - - @Override - Unit unitOrNull() { - return null; - } }; } } private class WrapSourceHandler implements SourceHandler { - final OuterWrap wrap; - - WrapSourceHandler(OuterWrap wrap) { - this.wrap = wrap; - } - @Override public JavaFileObject sourceToFileObject(MemoryFileManager fm, OuterWrap w) { return fm.createSourceFileObject(w, w.classFullName(), w.wrapped()); @@ -172,24 +161,9 @@ @Override public Diag diag(Diagnostic d) { - return wrap.wrapDiag(d); - } - } - - private class UnitSourceHandler implements SourceHandler { - - @Override - public JavaFileObject sourceToFileObject(MemoryFileManager fm, Unit u) { - return fm.createSourceFileObject(u, - state.maps.classFullName(u.snippet()), - u.snippet().outerWrap().wrapped()); - } - - @Override - public Diag diag(Diagnostic d) { SourceMemoryJavaFileObject smjfo = (SourceMemoryJavaFileObject) d.getSource(); - Unit u = (Unit) smjfo.getOrigin(); - return u.snippet().outerWrap().wrapDiag(d); + OuterWrap w = (OuterWrap) smjfo.getOrigin(); + return w.wrapDiag(d); } } @@ -242,13 +216,12 @@ private final Iterable cuts; AnalyzeTask(final OuterWrap wrap) { - this(Stream.of(wrap), - new WrapSourceHandler(wrap), - "-XDshouldStopPolicy=FLOW", "-proc:none"); + this(Collections.singletonList(wrap)); } - AnalyzeTask(final Collection units) { - this(units.stream(), new UnitSourceHandler(), + AnalyzeTask(final Collection wraps) { + this(wraps.stream(), + new WrapSourceHandler(), "-XDshouldStopPolicy=FLOW", "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none"); } @@ -287,10 +260,10 @@ */ class CompileTask extends BaseTask { - private final Map> classObjs = new HashMap<>(); + private final Map> classObjs = new HashMap<>(); - CompileTask(Collection units) { - super(units.stream(), new UnitSourceHandler(), + CompileTask(final Collection wraps) { + super(wraps.stream(), new WrapSourceHandler(), "-Xlint:unchecked", "-XaddExports:jdk.jshell/jdk.internal.jshell.remote=ALL-UNNAMED", "-proc:none"); } @@ -302,8 +275,8 @@ } - List classInfoList(Unit u) { - List l = classObjs.get(u); + List classInfoList(OuterWrap w) { + List l = classObjs.get(w); if (l == null) return Collections.emptyList(); return l.stream() .map(fo -> state.classTracker.classInfo(fo.getName(), fo.getBytes())) @@ -315,11 +288,11 @@ //debug("listenForNewClassFile %s loc=%s kind=%s\n", className, location, kind); if (location == CLASS_OUTPUT) { state.debug(DBG_GEN, "Compiler generating class %s\n", className); - Unit u = ((sibling instanceof SourceMemoryJavaFileObject) - && (((SourceMemoryJavaFileObject) sibling).getOrigin() instanceof Unit)) - ? (Unit) ((SourceMemoryJavaFileObject) sibling).getOrigin() + OuterWrap w = ((sibling instanceof SourceMemoryJavaFileObject) + && (((SourceMemoryJavaFileObject) sibling).getOrigin() instanceof OuterWrap)) + ? (OuterWrap) ((SourceMemoryJavaFileObject) sibling).getOrigin() : null; - classObjs.compute(u, (k, v) -> (v == null)? new ArrayList<>() : v) + classObjs.compute(w, (k, v) -> (v == null)? new ArrayList<>() : v) .add(jfo); } } diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java Mon Apr 25 08:50:16 2016 -0700 @@ -162,18 +162,28 @@ return new Range(start, end); } - Tree firstClassMember() { - if (targetClass != null) { - //TODO: missing classes - for (Tree mem : targetClass.getMembers()) { - if (mem.getKind() == Tree.Kind.VARIABLE) { - return mem; - } - if (mem.getKind() == Tree.Kind.METHOD) { - MethodTree mt = (MethodTree) mem; - if (!isDoIt(mt.getName()) && !mt.getName().toString().equals("")) { + MethodTree method(MethodSnippet msn) { + if (targetClass == null) { + return null; + } + OuterWrap ow = msn.outerWrap(); + if (!(ow instanceof OuterSnippetsClassWrap)) { + return null; + } + int ordinal = ((OuterSnippetsClassWrap) ow).ordinal(msn); + if (ordinal < 0) { + return null; + } + int count = 0; + String name = msn.name(); + for (Tree mem : targetClass.getMembers()) { + if (mem.getKind() == Tree.Kind.METHOD) { + MethodTree mt = (MethodTree) mem; + if (mt.getName().toString().equals(name)) { + if (count == ordinal) { return mt; } + ++count; } } } @@ -244,8 +254,8 @@ return ei; } - String typeOfMethod() { - Tree unitTree = firstClassMember(); + String typeOfMethod(MethodSnippet msn) { + Tree unitTree = method(msn); if (unitTree instanceof JCMethodDecl) { JCMethodDecl mtree = (JCMethodDecl) unitTree; Type mt = types().erasure(mtree.type); diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java Mon Apr 25 08:50:16 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -68,7 +68,7 @@ private final DiagList generatedDiagnostics; private int seq; - private int seqInitial; + private String classNameInitial; private Wrap activeGuts; private Status status; private Status prevStatus; @@ -95,7 +95,7 @@ this.generatedDiagnostics = generatedDiagnostics; this.seq = isNew? 0 : siOld.sequenceNumber(); - this.seqInitial = seq; + this.classNameInitial = isNew? "" : siOld.className(); this.prevStatus = (isNew || isDependency) ? si.status() : siOld.status(); @@ -136,28 +136,50 @@ return isDependency; } - boolean isNew() { - return isNew; - } - - void initialize(Collection working) { + void initialize() { isAttemptingCorral = false; dependenciesNeeded = false; toRedefine = null; // assure NPE if classToLoad not called activeGuts = si.guts(); markOldDeclarationOverwritten(); - setWrap(working, working); } - void setWrap(Collection except, Collection plus) { - si.setOuterWrap(isImport() - ? OuterWrap.wrapImport(si.source(), activeGuts) - : state.eval.wrapInClass(si, - except.stream().map(u -> u.snippet().key()).collect(toSet()), - activeGuts, - plus.stream().map(u -> u.snippet()) - .filter(sn -> sn != si) - .collect(toList()))); + // Set the outer wrap of our Snippet + void setWrap(Collection exceptUnit, Collection plusUnfiltered) { + if (isImport()) { + si.setOuterWrap(state.outerMap.wrapImport(activeGuts, si)); + } else { + // Collect Units for be wrapped together. Just this except for overloaded methods + List units; + if (snippet().kind() == Kind.METHOD) { + String name = ((MethodSnippet) snippet()).name(); + units = plusUnfiltered.stream() + .filter(u -> u.snippet().kind() == Kind.METHOD && + ((MethodSnippet) u.snippet()).name().equals(name)) + .collect(toList()); + } else { + units = Collections.singletonList(this); + } + // Keys to exclude from imports + Set except = exceptUnit.stream() + .map(u -> u.snippet().key()) + .collect(toSet()); + // Snippets to add to imports + Collection plus = plusUnfiltered.stream() + .filter(u -> !units.contains(u)) + .map(u -> u.snippet()) + .collect(toList()); + // Snippets to wrap in an outer + List snippets = units.stream() + .map(u -> u.snippet()) + .collect(toList()); + // Snippet wraps to wrap in an outer + List wraps = units.stream() + .map(u -> u.activeGuts) + .collect(toList()); + // Set the outer wrap for this snippet + si.setOuterWrap(state.outerMap.wrapInClass(except, plus, snippets, wraps)); + } } void setDiagnostics(AnalyzeTask ct) { @@ -302,11 +324,13 @@ private boolean sigChanged() { return (status.isDefined != prevStatus.isDefined) - || (seq != seqInitial && status.isDefined) + || (status.isDefined && !si.className().equals(classNameInitial)) || signatureChanged; } Stream effectedDependents() { + //System.err.printf("effectedDependents sigChanged=%b dependenciesNeeded=%b status=%s\n", + // sigChanged(), dependenciesNeeded, status); return sigChanged() || dependenciesNeeded || status == RECOVERABLE_NOT_DEFINED ? dependents() : Stream.empty(); @@ -361,7 +385,7 @@ if (replaceOldEvent != null) secondaryEvents.add(replaceOldEvent); // Defined methods can overwrite methods of other (equivalent) snippets - if (si.kind() == Kind.METHOD && status.isDefined) { + if (isNew && si.kind() == Kind.METHOD && status.isDefined) { MethodSnippet msi = (MethodSnippet)si; String oqpt = msi.qualifiedParameterTypes(); String nqpt = computeQualifiedParameterTypes(at, msi); @@ -405,7 +429,7 @@ } private String computeQualifiedParameterTypes(AnalyzeTask at, MethodSnippet msi) { - String rawSig = TreeDissector.createBySnippet(at, msi).typeOfMethod(); + String rawSig = TreeDissector.createBySnippet(at, msi).typeOfMethod(msi); String signature = expunge(rawSig); int paren = signature.lastIndexOf(')'); @@ -425,7 +449,9 @@ } List secondaryEvents() { - return secondaryEvents; + return secondaryEvents==null + ? Collections.emptyList() + : secondaryEvents; } @Override diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java Mon Apr 25 08:50:16 2016 -0700 @@ -30,7 +30,8 @@ import java.util.stream.StreamSupport; import javax.lang.model.element.Name; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; -import static jdk.internal.jshell.remote.RemoteCodes.prefixPattern; +import static jdk.internal.jshell.remote.RemoteCodes.PREFIX_PATTERN; +import static jdk.internal.jshell.remote.RemoteCodes.REPL_CLASS_PREFIX; /** * Assorted shared utilities. @@ -38,8 +39,7 @@ */ class Util { - static final String REPL_CLASS_PREFIX = "$REPL"; - static final String REPL_DOESNOTMATTER_CLASS_NAME = REPL_CLASS_PREFIX+"00DOESNOTMATTER"; + static final String REPL_DOESNOTMATTER_CLASS_NAME = REPL_CLASS_PREFIX+"DOESNOTMATTER"; static final Locale PARSED_LOCALE = Locale.ROOT; @@ -53,7 +53,7 @@ static String expunge(String s) { StringBuilder sb = new StringBuilder(); - for (String comp : prefixPattern.split(s)) { + for (String comp : PREFIX_PATTERN.split(s)) { sb.append(comp); } return sb.toString(); diff -r 626e07816dce -r 33cf53901cac langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java Mon Apr 25 08:50:16 2016 -0700 @@ -25,6 +25,8 @@ package jdk.jshell; +import java.util.Arrays; +import static java.util.stream.Collectors.joining; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; /** @@ -237,6 +239,27 @@ return 0; } + Wrap wrapIndexToWrap(long wi) { + int before = 0; + Wrap w = null; + for (Object o : os) { + if (o instanceof String) { + String s = (String) o; + before += s.length(); + } else if (o instanceof Wrap) { + w = (Wrap) o; + int len = w.wrapped().length(); + if ((wi - before) <= len) { + //System.err.printf("Defer to wrap %s - wi: %d. before; %d -- %s >>> %s\n", + // w, wi, before, w.debugPos(wi - before), w.wrapped()); + return w; + } + before += len; + } + } + return w; + } + @Override public int wrapIndexToSnippetIndex(int wi) { int before = 0; @@ -286,6 +309,25 @@ return 0; } + Wrap wrapLineToWrap(int wline) { + int before = 0; + Wrap w = null; + for (Object o : os) { + if (o instanceof String) { + String s = (String) o; + before += countLines(s); + } else if (o instanceof Wrap) { + w = (Wrap) o; + int lns = countLines(w.wrapped()); + if ((wline - before) < lns) { + return w; + } + before += lns; + } + } + return w; + } + @Override public int wrapLineToSnippetLine(int wline) { int before = 0; @@ -315,7 +357,10 @@ return snlineLast; } - + @Override + public String toString() { + return "CompoundWrap(" + Arrays.stream(os).map(u -> u.toString()).collect(joining(",")) + ")"; + } } private static class RangeWrap extends Wrap { @@ -404,6 +449,10 @@ return lastSnline; } + @Override + public String toString() { + return "RangeWrap(" + range + ")"; + } } private static class NoWrap extends RangeWrap { diff -r 626e07816dce -r 33cf53901cac langtools/test/jdk/jshell/ClassesTest.java --- a/langtools/test/jdk/jshell/ClassesTest.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/test/jdk/jshell/ClassesTest.java Mon Apr 25 08:50:16 2016 -0700 @@ -47,6 +47,7 @@ import static jdk.jshell.Snippet.Status.DROPPED; import static jdk.jshell.Snippet.Status.REJECTED; import static jdk.jshell.Snippet.Status.OVERWRITTEN; +import static jdk.jshell.Snippet.Status.NONEXISTENT; import static jdk.jshell.Snippet.SubKind.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @@ -83,7 +84,7 @@ TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareFail("class A { void f() { return g(); } }", "compiler.err.prob.found.req"); assertTypeDeclSnippet(c1, "A", REJECTED, CLASS_SUBKIND, 0, 2); TypeDeclSnippet c2 = classKey(assertEval("class A { int f() { return g(); } }", - ste(c1, REJECTED, RECOVERABLE_DEFINED, true, null))); + ste(c1, NONEXISTENT, RECOVERABLE_DEFINED, true, null))); assertTypeDeclSnippet(c2, "A", RECOVERABLE_DEFINED, CLASS_SUBKIND, 1, 0); assertDrop(c2, ste(c2, RECOVERABLE_DEFINED, DROPPED, true, null)); @@ -176,6 +177,7 @@ assertActiveKeys(); } + //8154496: test3 update: sig change should false public void classesRedeclaration3() { Snippet a = classKey(assertEval("class A { }")); assertClasses(clazz(KullaTesting.ClassType.CLASS, "A")); @@ -190,7 +192,7 @@ ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(test1, VALID, VALID, true, MAIN_SNIPPET), ste(test2, VALID, VALID, true, MAIN_SNIPPET), - ste(test3, VALID, VALID, false, MAIN_SNIPPET), + ste(test3, VALID, VALID, true, MAIN_SNIPPET), ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A")); assertMethods(method("()A", "test"), method("(A)void", "test"), method("(int)void", "test")); @@ -201,8 +203,7 @@ Snippet b = classKey(assertEval("class B extends A { }", added(RECOVERABLE_NOT_DEFINED))); Snippet a = classKey(assertEval("class A extends B { }", DiagCheck.DIAG_IGNORE, DiagCheck.DIAG_IGNORE, - added(RECOVERABLE_NOT_DEFINED), - ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET))); + added(REJECTED))); /*** assertDeclareFail("class A extends B { }", "****", added(REJECTED), diff -r 626e07816dce -r 33cf53901cac langtools/test/jdk/jshell/DropTest.java --- a/langtools/test/jdk/jshell/DropTest.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/test/jdk/jshell/DropTest.java Mon Apr 25 08:50:16 2016 -0700 @@ -57,10 +57,10 @@ assertActiveKeys(); method = methodKey(assertEval("int mu() { return x * 4; }", - ste(MAIN_SNIPPET, DROPPED, RECOVERABLE_DEFINED, true, null), + added(RECOVERABLE_DEFINED), ste(clazz, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); assertEval("int x = 10;", "10", - ste(MAIN_SNIPPET, DROPPED, VALID, true, null), + added(VALID), ste(method, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET)); PersistentSnippet c0 = varKey(assertEval("C c0 = new C();")); assertEval("c0.v();", "\"#40\""); @@ -189,12 +189,11 @@ assertDrop(c, DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, - ste(c, RECOVERABLE_NOT_DEFINED, DROPPED, false, null), - ste(d, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, c)); + ste(c, RECOVERABLE_NOT_DEFINED, DROPPED, false, null)); assertEval("interface A {}", null, null, - DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, - ste(a, DROPPED, VALID, true, null), - ste(b, RECOVERABLE_NOT_DEFINED, RECOVERABLE_NOT_DEFINED, false, MAIN_SNIPPET)); + DiagCheck.DIAG_OK, + DiagCheck.DIAG_ERROR, + added(VALID)); assertClasses(); assertActiveKeys(); } diff -r 626e07816dce -r 33cf53901cac langtools/test/jdk/jshell/KullaTesting.java --- a/langtools/test/jdk/jshell/KullaTesting.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/test/jdk/jshell/KullaTesting.java Mon Apr 25 08:50:16 2016 -0700 @@ -651,7 +651,7 @@ DiagCheck.DIAG_WARNING, DiagCheck.DIAG_IGNORE, mainInfo, updates); SnippetEvent e = events.get(0); List diagnostics = getState().diagnostics(e.snippet()); - assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic); + if (expectedDiagnostic != null) assertDiagnostic(input, diagnostics.get(0), expectedDiagnostic); return e.snippet(); } diff -r 626e07816dce -r 33cf53901cac langtools/test/jdk/jshell/MethodsTest.java --- a/langtools/test/jdk/jshell/MethodsTest.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/test/jdk/jshell/MethodsTest.java Mon Apr 25 08:50:16 2016 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -58,7 +58,7 @@ MethodSnippet m1 = (MethodSnippet) assertDeclareFail("void f() { return g(); }", "compiler.err.prob.found.req"); assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2); MethodSnippet m2 = methodKey(assertEval("int f() { return g(); }", - ste(m1, REJECTED, RECOVERABLE_DEFINED, true, null))); + added(RECOVERABLE_DEFINED))); assertMethodDeclSnippet(m1, "f", "()void", REJECTED, 0, 2); assertMethodDeclSnippet(m2, "f", "()int", RECOVERABLE_DEFINED, 1, 0); } @@ -115,6 +115,26 @@ assertActiveKeys(); } + /*** + public void methodOverloadDependent() { + assertEval("String m(String s) { return s + s; }"); + assertEval("String m(double d) { return m(\"#\" + d); }"); + assertEval("String m(int x) { return m(2.25 * x); }"); + assertEval("String m() { return m(3); }"); + assertMethods( + method("(String)String", "m"), + method("(double)String", "m"), + method("(int)String", "m"), + method("()String", "m") + ); + assertEval("m();", "\"#6.75#6.75\""); + assertEval("m(2);", "\"#4.5#4.5\""); + assertEval("m(3.14);", "\"#3.14#3.14\""); + assertEval("m(\"hi\");", "\"hihi\""); + assertActiveKeys(); + } + ***/ + public void methodsRedeclaration1() { Snippet x = methodKey(assertEval("int x() { return 10; }")); Snippet y = methodKey(assertEval("String y() { return \"\"; }")); @@ -149,8 +169,7 @@ assertEval("double b() { return 3.14159; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(c, VALID, VALID, false, MAIN_SNIPPET)); + ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertMethods(method("()int", "a"), method("()double", "b"), method("()double", "c")); assertEval("c();", "3.14159"); assertActiveKeys(); @@ -202,7 +221,7 @@ assertActiveKeys(); assertDeclareFail("int f() {}", "compiler.err.missing.ret.stmt", - ste(MAIN_SNIPPET, REJECTED, REJECTED, false, null)); + added(REJECTED)); assertNumberOfActiveMethods(0); assertActiveKeys(); diff -r 626e07816dce -r 33cf53901cac langtools/test/jdk/jshell/ReplaceTest.java --- a/langtools/test/jdk/jshell/ReplaceTest.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/test/jdk/jshell/ReplaceTest.java Mon Apr 25 08:50:16 2016 -0700 @@ -97,8 +97,7 @@ assertEval("mu() == 0.0;", "true"); assertEval("double x = 2.5;", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(musn, VALID, VALID, false, MAIN_SNIPPET)); + ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); Collection meths = getState().methods(); assertEquals(meths.size(), 1); assertTrue(musn == meths.iterator().next(), "Identity must not change"); @@ -115,8 +114,7 @@ assertEval("d();", "1060.0"); assertEval("int a() { return 5; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(b, VALID, VALID, false, MAIN_SNIPPET)); + ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("d();", "1150.0"); assertActiveKeys(); } @@ -127,8 +125,7 @@ assertEval("m();", "7"); assertEval("class C { int x = 99; int f() { return x; } }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(m, VALID, VALID, false, MAIN_SNIPPET)); + ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("m();", "99"); assertActiveKeys(); } @@ -140,8 +137,7 @@ 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), - ste(c, VALID, VALID, false, MAIN_SNIPPET)); + ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); Collection classes = getState().types(); assertEquals(classes.size(), 1); assertTrue(c == classes.iterator().next(), "Identity must not change"); @@ -157,8 +153,7 @@ 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), - ste(c, VALID, VALID, false, MAIN_SNIPPET)); + ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertEval("x();", "2.5"); Collection classes = getState().types(); assertEquals(classes.size(), 1); @@ -875,18 +870,15 @@ MethodSnippet k1 = methodKey(assertEval(ms1, added(VALID))); VarSnippet xd = varKey(assertEval(xsd, ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(xi, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(k1, VALID, VALID, false, MAIN_SNIPPET))); + ste(xi, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); MethodSnippet k2 = methodKey(assertEval(ms2, ste(MAIN_SNIPPET, VALID, VALID, true, null), //TODO: technically, should be false ste(k1, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); VarSnippet xi2 = varKey(assertEval(xsi, ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(xd, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(k2, VALID, VALID, false, MAIN_SNIPPET))); + ste(xd, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); varKey(assertEval(xsd, ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(xi2, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(k2, VALID, VALID, false, MAIN_SNIPPET))); + ste(xi2, VALID, OVERWRITTEN, false, MAIN_SNIPPET))); } } diff -r 626e07816dce -r 33cf53901cac langtools/test/jdk/jshell/SnippetStatusListenerTest.java --- a/langtools/test/jdk/jshell/SnippetStatusListenerTest.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/test/jdk/jshell/SnippetStatusListenerTest.java Mon Apr 25 08:50:16 2016 -0700 @@ -65,7 +65,7 @@ getState().unsubscribe(subscription1); assertDrop(f, DiagCheck.DIAG_IGNORE, DiagCheck.DIAG_IGNORE, ste(f, REJECTED, DROPPED, false, null)); - assertEval("void f() { }", ste(MAIN_SNIPPET, DROPPED, VALID, true, null)); + assertEval("void f() { }", added(VALID)); assertEvalException("throw new RuntimeException();"); assertEquals(listener1.getEvents(), events1, "Checking that unsubscribed listener does not get events"); diff -r 626e07816dce -r 33cf53901cac langtools/test/jdk/jshell/SnippetTest.java --- a/langtools/test/jdk/jshell/SnippetTest.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/test/jdk/jshell/SnippetTest.java Mon Apr 25 08:50:16 2016 -0700 @@ -142,8 +142,7 @@ assertActiveKeys(); assertEval("double f() { return 0.0; }", ste(MAIN_SNIPPET, VALID, VALID, true, null), - ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(g, VALID, VALID, false, MAIN_SNIPPET)); + ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); assertKeys(method("()void", "g"), clazz(KullaTesting.ClassType.INTERFACE, "A"), method("()double", "f")); assertActiveKeys(); diff -r 626e07816dce -r 33cf53901cac langtools/test/jdk/jshell/VariablesTest.java --- a/langtools/test/jdk/jshell/VariablesTest.java Tue Mar 22 13:14:12 2016 +0100 +++ b/langtools/test/jdk/jshell/VariablesTest.java Mon Apr 25 08:50:16 2016 -0700 @@ -83,7 +83,7 @@ public void testVarValue2() { VarSnippet v1 = (VarSnippet) assertDeclareFail("int a = 0.0;", "compiler.err.prob.found.req"); badVarValue(v1); - VarSnippet v2 = varKey(assertEval("int a = 0;", ste(v1, REJECTED, VALID, true, null))); + VarSnippet v2 = varKey(assertEval("int a = 0;", added(VALID))); assertDrop(v2, ste(MAIN_SNIPPET, VALID, DROPPED, true, null)); badVarValue(v2); } @@ -111,7 +111,7 @@ VarSnippet v1 = (VarSnippet) assertDeclareFail("int a = 0.0;", "compiler.err.prob.found.req"); assertVariableDeclSnippet(v1, "a", "int", REJECTED, SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, 0, 1); VarSnippet v2 = varKey(assertEval("int a = 0;", - ste(v1, REJECTED, VALID, true, null))); + added(VALID))); assertVariableDeclSnippet(v2, "a", "int", VALID, SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, 0, 0); assertDrop(v2, ste(MAIN_SNIPPET, VALID, DROPPED, true, null)); assertVariableDeclSnippet(v2, "a", "int", DROPPED, SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND, 0, 0);