src/jdk.jshell/share/classes/jdk/jshell/Eval.java
changeset 47268 48ec75306997
parent 47216 71c04702a3d5
child 47318 423f5e46016e
--- a/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Tue Sep 26 15:08:56 2017 +0530
+++ b/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Tue Sep 26 12:52:53 2017 +0100
@@ -40,6 +40,7 @@
 import com.sun.source.tree.IdentifierTree;
 import com.sun.source.tree.MethodTree;
 import com.sun.source.tree.ModifiersTree;
+import com.sun.source.tree.NewClassTree;
 import com.sun.source.tree.Tree;
 import com.sun.source.tree.VariableTree;
 import com.sun.tools.javac.tree.JCTree;
@@ -59,6 +60,7 @@
 import jdk.jshell.TaskFactory.BaseTask;
 import jdk.jshell.TaskFactory.CompileTask;
 import jdk.jshell.TaskFactory.ParseTask;
+import jdk.jshell.Wrap.CompoundWrap;
 import jdk.jshell.Wrap.Range;
 import jdk.jshell.Snippet.Status;
 import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
@@ -274,26 +276,119 @@
         for (Tree unitTree : units) {
             VariableTree vt = (VariableTree) unitTree;
             String name = vt.getName().toString();
-            String typeName = EvalPretty.prettyExpr((JCTree) vt.getType(), false);
-            Tree baseType = vt.getType();
+            String typeName;
+            String fullTypeName;
             TreeDependencyScanner tds = new TreeDependencyScanner();
-            tds.scan(baseType); // Not dependent on initializer
+            Wrap typeWrap;
+            Wrap anonDeclareWrap = null;
+            Wrap winit = null;
             StringBuilder sbBrackets = new StringBuilder();
-            while (baseType instanceof ArrayTypeTree) {
-                //TODO handle annotations too
-                baseType = ((ArrayTypeTree) baseType).getType();
-                sbBrackets.append("[]");
+            Tree baseType = vt.getType();
+            if (baseType != null) {
+                tds.scan(baseType); // Not dependent on initializer
+                fullTypeName = typeName = EvalPretty.prettyExpr((JCTree) vt.getType(), false);
+                while (baseType instanceof ArrayTypeTree) {
+                    //TODO handle annotations too
+                    baseType = ((ArrayTypeTree) baseType).getType();
+                    sbBrackets.append("[]");
+                }
+                Range rtype = dis.treeToRange(baseType);
+                typeWrap = Wrap.rangeWrap(compileSource, rtype);
+            } else {
+                Tree init = vt.getInitializer();
+                if (init != null) {
+                    Range rinit = dis.treeToRange(init);
+                    String initCode = rinit.part(compileSource);
+                    ExpressionInfo ei =
+                            ExpressionToTypeInfo.localVariableTypeForInitializer(initCode, state);
+                    typeName = ei == null ? "java.lang.Object" : ei.typeName;
+                    fullTypeName = ei == null ? "java.lang.Object" : ei.fullTypeName;
+                    if (ei != null && init.getKind() == Tree.Kind.NEW_CLASS &&
+                        ((NewClassTree) init).getClassBody() != null) {
+                        NewClassTree nct = (NewClassTree) init;
+                        StringBuilder constructor = new StringBuilder();
+                        constructor.append(fullTypeName).append("(");
+                        String sep = "";
+                        if (ei.enclosingInstanceType != null) {
+                            constructor.append(ei.enclosingInstanceType);
+                            constructor.append(" encl");
+                            sep = ", ";
+                        }
+                        int idx = 0;
+                        for (String type : ei.parameterTypes) {
+                            constructor.append(sep);
+                            constructor.append(type);
+                            constructor.append(" ");
+                            constructor.append("arg" + idx++);
+                            sep = ", ";
+                        }
+                        if (ei.enclosingInstanceType != null) {
+                            constructor.append(") { encl.super (");
+                        } else {
+                            constructor.append(") { super (");
+                        }
+                        sep = "";
+                        for (int i = 0; i < idx; i++) {
+                            constructor.append(sep);
+                            constructor.append("arg" + i++);
+                            sep = ", ";
+                        }
+                        constructor.append("); }");
+                        List<? extends Tree> members = nct.getClassBody().getMembers();
+                        Range bodyRange = dis.treeListToRange(members);
+                        Wrap bodyWrap;
+
+                        if (bodyRange != null) {
+                            bodyWrap = Wrap.rangeWrap(compileSource, bodyRange);
+                        } else {
+                            bodyWrap = Wrap.simpleWrap(" ");
+                        }
+
+                        Range argRange = dis.treeListToRange(nct.getArguments());
+                        Wrap argWrap;
+
+                        if (argRange != null) {
+                            argWrap = Wrap.rangeWrap(compileSource, argRange);
+                        } else {
+                            argWrap = Wrap.simpleWrap(" ");
+                        }
+
+                        if (ei.enclosingInstanceType != null) {
+                            Range enclosingRanges =
+                                    dis.treeToRange(nct.getEnclosingExpression());
+                            Wrap enclosingWrap = Wrap.rangeWrap(compileSource, enclosingRanges);
+                            argWrap = argRange != null ? new CompoundWrap(enclosingWrap,
+                                                                          Wrap.simpleWrap(","),
+                                                                          argWrap)
+                                                       : enclosingWrap;
+                        }
+                        Wrap hwrap = Wrap.simpleWrap("public static class " + fullTypeName +
+                                                     (ei.isClass ? " extends " : " implements ") +
+                                                     typeName + " { " + constructor);
+                        anonDeclareWrap = new CompoundWrap(hwrap, bodyWrap, Wrap.simpleWrap("}"));
+                        winit = new CompoundWrap("new " + fullTypeName + "(", argWrap, ")");
+
+                        String superType = typeName;
+
+                        typeName = fullTypeName;
+                        fullTypeName = ei.isClass ? "<anonymous class extending " + superType + ">"
+                                                  : "<anonymous class implementing " + superType + ">";
+                    }
+                    tds.scan(init);
+                } else {
+                    fullTypeName = typeName = "java.lang.Object";
+                }
+                typeWrap = Wrap.identityWrap(typeName);
             }
-            Range rtype = dis.treeToRange(baseType);
             Range runit = dis.treeToRange(vt);
             runit = new Range(runit.begin, runit.end - 1);
             ExpressionTree it = vt.getInitializer();
-            Range rinit = null;
             int nameMax = runit.end - 1;
             SubKind subkind;
             if (it != null) {
                 subkind = SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND;
-                rinit = dis.treeToRange(it);
+                Range rinit = dis.treeToRange(it);
+                winit = winit == null ? Wrap.rangeWrap(compileSource, rinit) : winit;
                 nameMax = rinit.begin - 1;
             } else {
                 subkind = SubKind.VAR_DECLARATION_SUBKIND;
@@ -304,10 +399,11 @@
             }
             int nameEnd = nameStart + name.length();
             Range rname = new Range(nameStart, nameEnd);
-            Wrap guts = Wrap.varWrap(compileSource, rtype, sbBrackets.toString(), rname, rinit);
-            DiagList modDiag = modifierDiagnostics(vt.getModifiers(), dis, true);
+            Wrap guts = Wrap.varWrap(compileSource, typeWrap, sbBrackets.toString(), rname,
+                                     winit, anonDeclareWrap);
+                        DiagList modDiag = modifierDiagnostics(vt.getModifiers(), dis, true);
             Snippet snip = new VarSnippet(state.keyMap.keyForVariable(name), userSource, guts,
-                    name, subkind, typeName,
+                    name, subkind, fullTypeName,
                     tds.declareReferences(), modDiag);
             snippets.add(snip);
         }