--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java Mon Oct 19 19:15:16 2015 +0200
@@ -0,0 +1,458 @@
+/*
+ * Copyright (c) 2015, 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.List;
+import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME;
+
+/**
+ * Wrapping of source into Java methods, fields, etc. All but outer layer
+ * wrapping with imports and class.
+ *
+ * @author Robert Field
+ */
+abstract class Wrap implements GeneralWrap {
+
+ private static Wrap methodWrap(String prefix, String source, String suffix) {
+ Wrap wunit = new NoWrap(source);
+ return new DoitMethodWrap(new CompoundWrap(prefix, wunit, suffix));
+ }
+
+ public static Wrap methodWrap(String source) {
+ return methodWrap("", source, semi(source) + " return null;\n");
+ }
+
+ public static Wrap methodReturnWrap(String source) {
+ return methodWrap("return ", source, semi(source));
+ }
+
+ public static Wrap methodUnreachableSemiWrap(String source) {
+ return methodWrap("", source, semi(source));
+ }
+
+ public static Wrap methodUnreachableWrap(String source) {
+ return methodWrap("", source, "");
+ }
+
+ public static Wrap corralledMethod(String source, Range modRange, Range tpRange, Range typeRange, String name, Range paramRange, Range throwsRange, int id) {
+ List<Object> l = new ArrayList<>();
+ l.add(" public static\n ");
+ if (!modRange.isEmpty()) {
+ l.add(new RangeWrap(source, modRange));
+ l.add(" ");
+ }
+ if (tpRange != null) {
+ l.add("<");
+ l.add(new RangeWrap(source, tpRange));
+ l.add("> ");
+ }
+ l.add(new RangeWrap(source, typeRange));
+ l.add(" " + name + "(\n ");
+ if (paramRange != null) {
+ l.add(new RangeWrap(source, paramRange));
+ }
+ l.add(") ");
+ if (throwsRange != null) {
+ l.add("throws ");
+ l.add(new RangeWrap(source, throwsRange));
+ }
+ l.add(" {\n throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");\n}\n");
+ return new CompoundWrap(l.toArray());
+ }
+
+ /**
+ *
+ * @param in
+ * @param rname
+ * @param rinit Initializer or null
+ * @param rdecl Type name and name
+ * @return
+ */
+ public static Wrap varWrap(String source, Range rtype, String brackets, Range rname, Range rinit) {
+ RangeWrap wname = new RangeWrap(source, rname);
+ RangeWrap wtype = new RangeWrap(source, rtype);
+ Wrap wVarDecl = new VarDeclareWrap(wtype, brackets, wname);
+ Wrap wmeth;
+
+ if (rinit == null) {
+ wmeth = new CompoundWrap(new NoWrap(" "), " return null;\n");
+ } else {
+ RangeWrap winit = new RangeWrap(source, rinit);
+ // int x = y
+ // int x_ = y; return x = x_;
+ // decl + "_ = " + init ; + "return " + name + "=" + name + "_ ;"
+ wmeth = new CompoundWrap(
+ wtype, brackets + " ", wname, "_ =\n ", winit, semi(winit),
+ " return ", wname, " = ", wname, "_;\n"
+ );
+ }
+ Wrap wInitMeth = new DoitMethodWrap(wmeth);
+ return new CompoundWrap(wVarDecl, wInitMeth);
+ }
+
+ public static Wrap tempVarWrap(String source, String typename, String name) {
+ RangeWrap winit = new NoWrap(source);
+ // y
+ // return $1 = y;
+ // "return " + $1 + "=" + init ;
+ Wrap wmeth = new CompoundWrap("return " + name + " =\n ", winit, semi(winit));
+ Wrap wInitMeth = new DoitMethodWrap(wmeth);
+
+ String varDecl = " public static\n " + typename + " " + name + ";\n";
+ return new CompoundWrap(varDecl, wInitMeth);
+ }
+
+ public static Wrap importWrap(String source) {
+ return new NoWrap(source);
+ }
+
+ public static Wrap classMemberWrap(String source) {
+ Wrap w = new NoWrap(source);
+ return new CompoundWrap(" public static\n ", w);
+ }
+
+ private static int countLines(String s) {
+ return countLines(s, 0, s.length());
+ }
+
+ private static int countLines(String s, int from, int toEx) {
+ int cnt = 0;
+ int idx = from;
+ while ((idx = s.indexOf('\n', idx)) > 0) {
+ if (idx >= toEx) break;
+ ++cnt;
+ ++idx;
+ }
+ return cnt;
+ }
+
+ public static final class Range {
+ final int begin;
+ final int end;
+
+ Range(int begin, int end) {
+ this.begin = begin;
+ this.end = end;
+ }
+
+ Range(String s) {
+ this.begin = 0;
+ this.end = s.length();
+ }
+
+ String part(String s) {
+ return s.substring(begin, end);
+ }
+
+ int length() {
+ return end - begin;
+ }
+
+ boolean isEmpty() {
+ return end == begin;
+ }
+
+ void verify(String s) {
+ if (begin < 0 || end <= begin || end > s.length()) {
+ throw new InternalError("Bad Range: " + s + "[" + begin + "," + end + "]");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Range[" + begin + "," + end + "]";
+ }
+ }
+
+ public static class CompoundWrap extends Wrap {
+
+ final Object[] os;
+ final String wrapped;
+ final int snidxFirst;
+ final int snidxLast;
+ final int snlineFirst;
+ final int snlineLast;
+
+ CompoundWrap(Object... os) {
+ this.os = os;
+ int sniFirst = Integer.MAX_VALUE;
+ int sniLast = Integer.MIN_VALUE;
+ int snlnFirst = Integer.MAX_VALUE;
+ int snlnLast = Integer.MIN_VALUE;
+ StringBuilder sb = new StringBuilder();
+ for (Object o : os) {
+ if (o instanceof String) {
+ String s = (String) o;
+ sb.append(s);
+ } else if (o instanceof Wrap) {
+ Wrap w = (Wrap) o;
+ if (w.firstSnippetIndex() < sniFirst) {
+ sniFirst = w.firstSnippetIndex();
+ }
+ if (w.lastSnippetIndex() > sniLast) {
+ sniLast = w.lastSnippetIndex();
+ }
+ if (w.firstSnippetLine() < snlnFirst) {
+ snlnFirst = w.firstSnippetLine();
+ }
+ if (w.lastSnippetLine() > snlnLast) {
+ snlnLast = w.lastSnippetLine();
+ }
+ sb.append(w.wrapped());
+ } else {
+ throw new InternalError("Bad object in CommoundWrap: " + o);
+ }
+ }
+ this.wrapped = sb.toString();
+ this.snidxFirst = sniFirst;
+ this.snidxLast = sniLast;
+ this.snlineFirst = snlnFirst;
+ this.snlineLast = snlnLast;
+ }
+
+ @Override
+ public String wrapped() {
+ return wrapped;
+ }
+
+ @Override
+ public int snippetIndexToWrapIndex(int sni) {
+ int before = 0;
+ for (Object o : os) {
+ if (o instanceof String) {
+ String s = (String) o;
+ before += s.length();
+ } else if (o instanceof Wrap) {
+ Wrap w = (Wrap) o;
+ if (sni >= w.firstSnippetIndex() && sni <= w.lastSnippetIndex()) {
+ return w.snippetIndexToWrapIndex(sni) + before;
+ }
+ before += w.wrapped().length();
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public int wrapIndexToSnippetIndex(int wi) {
+ int before = 0;
+ for (Object o : os) {
+ if (o instanceof String) {
+ String s = (String) o;
+ before += s.length();
+ } else if (o instanceof Wrap) {
+ 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.wrapIndexToSnippetIndex(wi - before);
+ }
+ before += len;
+ }
+ }
+ return lastSnippetIndex();
+ }
+
+ @Override
+ public int firstSnippetIndex() {
+ return snidxFirst;
+ }
+
+ @Override
+ public int lastSnippetIndex() {
+ return snidxLast;
+ }
+
+ @Override
+ public int snippetLineToWrapLine(int snline) {
+ int before = 0;
+ for (Object o : os) {
+ if (o instanceof String) {
+ String s = (String) o;
+ before += countLines(s);
+ } else if (o instanceof Wrap) {
+ Wrap w = (Wrap) o;
+ if (snline >= w.firstSnippetLine() && snline <= w.lastSnippetLine()) {
+ return w.snippetLineToWrapLine(snline) + before;
+ }
+ before += countLines(w.wrapped());
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public int wrapLineToSnippetLine(int wline) {
+ int before = 0;
+ for (Object o : os) {
+ if (o instanceof String) {
+ String s = (String) o;
+ before += countLines(s);
+ } else if (o instanceof Wrap) {
+ Wrap w = (Wrap) o;
+ int lns = countLines(w.wrapped());
+ if ((wline - before) < lns) {
+ return w.wrapLineToSnippetLine(wline - before);
+ }
+ before += lns;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public int firstSnippetLine() {
+ return snlineFirst;
+ }
+
+ @Override
+ public int lastSnippetLine() {
+ return snlineLast;
+ }
+
+
+ }
+
+ private static class RangeWrap extends Wrap {
+
+ final Range range;
+ final String wrapped;
+ final int firstSnline;
+ final int lastSnline;
+
+ RangeWrap(String snippetSource, Range usedWithinSnippet) {
+ this.range = usedWithinSnippet;
+ this.wrapped = usedWithinSnippet.part(snippetSource);
+ usedWithinSnippet.verify(snippetSource);
+ this.firstSnline = countLines(snippetSource, 0, range.begin);
+ this.lastSnline = firstSnline + countLines(snippetSource, range.begin, range.end);
+ }
+
+ @Override
+ public String wrapped() {
+ return wrapped;
+ }
+
+ @Override
+ public int snippetIndexToWrapIndex(int sni) {
+ if (sni < range.begin) {
+ return 0;
+ }
+ if (sni > range.end) {
+ return range.length();
+ }
+ return sni - range.begin;
+ }
+
+ @Override
+ public int wrapIndexToSnippetIndex(int wi) {
+ if (wi < 0) {
+ return 0; // bad index
+ }
+ int max = range.length();
+ if (wi > max) {
+ wi = max;
+ }
+ return wi + range.begin;
+ }
+
+ @Override
+ public int firstSnippetIndex() {
+ return range.begin;
+ }
+
+ @Override
+ public int lastSnippetIndex() {
+ return range.end;
+ }
+
+ @Override
+ public int snippetLineToWrapLine(int snline) {
+ if (snline < firstSnline) {
+ return 0;
+ }
+ if (snline >= lastSnline) {
+ return lastSnline - firstSnline;
+ }
+ return snline - firstSnline;
+ }
+
+ @Override
+ public int wrapLineToSnippetLine(int wline) {
+ if (wline < 0) {
+ return 0; // bad index
+ }
+ int max = lastSnline - firstSnline;
+ if (wline > max) {
+ wline = max;
+ }
+ return wline + firstSnline;
+ }
+
+ @Override
+ public int firstSnippetLine() {
+ return firstSnline;
+ }
+
+ @Override
+ public int lastSnippetLine() {
+ return lastSnline;
+ }
+
+ }
+
+ private static class NoWrap extends RangeWrap {
+
+ NoWrap(String unit) {
+ super(unit, new Range(unit));
+ }
+ }
+
+ private static String semi(Wrap w) {
+ return semi(w.wrapped());
+ }
+
+ private static String semi(String s) {
+ return ((s.endsWith(";")) ? "\n" : ((s.endsWith(";\n")) ? "" : ";\n"));
+ }
+
+ private static class DoitMethodWrap extends CompoundWrap {
+
+ DoitMethodWrap(Wrap w) {
+ super(" public static Object " + DOIT_METHOD_NAME + "() throws Throwable {\n"
+ + " ", w,
+ " }\n");
+ }
+ }
+
+ private static class VarDeclareWrap extends CompoundWrap {
+
+ VarDeclareWrap(Wrap wtype, String brackets, Wrap wname) {
+ super(" public static ", wtype, brackets + " ", wname, semi(wname));
+ }
+ }
+}