--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Fri Jul 01 14:16:28 2016 -0700
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Fri Jul 01 14:41:07 2016 -0700
@@ -52,6 +52,7 @@
import jdk.jshell.Key.ErroneousKey;
import jdk.jshell.Key.MethodKey;
import jdk.jshell.Key.TypeDeclKey;
+import jdk.jshell.Snippet.Kind;
import jdk.jshell.Snippet.SubKind;
import jdk.jshell.TaskFactory.AnalyzeTask;
import jdk.jshell.TaskFactory.BaseTask;
@@ -62,6 +63,7 @@
import jdk.jshell.Snippet.Status;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
+import static java.util.Collections.singletonList;
import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
import static jdk.jshell.Util.DOIT_METHOD_NAME;
import static jdk.jshell.Util.PREFIX_PATTERN;
@@ -89,24 +91,75 @@
this.state = state;
}
+ /**
+ * Evaluates a snippet of source.
+ *
+ * @param userSource the source of the snippet
+ * @return the list of primary and update events
+ * @throws IllegalStateException
+ */
List<SnippetEvent> eval(String userSource) throws IllegalStateException {
+ List<SnippetEvent> allEvents = new ArrayList<>();
+ for (Snippet snip : sourceToSnippets(userSource)) {
+ if (snip.kind() == Kind.ERRONEOUS) {
+ state.maps.installSnippet(snip);
+ allEvents.add(new SnippetEvent(
+ snip, Status.NONEXISTENT, Status.REJECTED,
+ false, null, null, null));
+ } else {
+ allEvents.addAll(declare(snip, snip.syntheticDiags()));
+ }
+ }
+ return allEvents;
+ }
+
+ /**
+ * Converts the user source of a snippet into a Snippet list -- Snippet will
+ * have wrappers.
+ *
+ * @param userSource the source of the snippet
+ * @return usually a singleton list of Snippet, but may be empty or multiple
+ */
+ List<Snippet> sourceToSnippetsWithWrappers(String userSource) {
+ List<Snippet> snippets = sourceToSnippets(userSource);
+ for (Snippet snip : snippets) {
+ if (snip.outerWrap() == null) {
+ snip.setOuterWrap(
+ (snip.kind() == Kind.IMPORT)
+ ? state.outerMap.wrapImport(snip.guts(), snip)
+ : state.outerMap.wrapInTrialClass(snip.guts())
+ );
+ }
+ }
+ return snippets;
+ }
+
+ /**
+ * Converts the user source of a snippet into a Snippet object (or list of
+ * objects in the case of: int x, y, z;). Does not install the Snippets
+ * or execute them.
+ *
+ * @param userSource the source of the snippet
+ * @return usually a singleton list of Snippet, but may be empty or multiple
+ */
+ private List<Snippet> sourceToSnippets(String userSource) {
String compileSource = Util.trimEnd(new MaskCommentsAndModifiers(userSource, false).cleared());
if (compileSource.length() == 0) {
return Collections.emptyList();
}
- // String folding messes up position information.
ParseTask pt = state.taskFactory.new ParseTask(compileSource);
+ List<? extends Tree> units = pt.units();
+ if (units.isEmpty()) {
+ return compileFailResult(pt, userSource, Kind.ERRONEOUS);
+ }
+ Tree unitTree = units.get(0);
if (pt.getDiagnostics().hasOtherThanNotStatementErrors()) {
- return compileFailResult(pt, userSource);
+ return compileFailResult(pt, userSource, kindOfTree(unitTree));
}
- List<? extends Tree> units = pt.units();
- if (units.isEmpty()) {
- return compileFailResult(pt, userSource);
- }
- // Erase illegal modifiers
+ // Erase illegal/ignored modifiers
compileSource = new MaskCommentsAndModifiers(compileSource, true).cleared();
- Tree unitTree = units.get(0);
+
state.debug(DBG_GEN, "Kind: %s -- %s\n", unitTree.getKind(), unitTree);
switch (unitTree.getKind()) {
case IMPORT:
@@ -130,7 +183,7 @@
}
}
- private List<SnippetEvent> processImport(String userSource, String compileSource) {
+ private List<Snippet> processImport(String userSource, String compileSource) {
Wrap guts = Wrap.simpleWrap(compileSource);
Matcher mat = IMPORT_PATTERN.matcher(compileSource);
String fullname;
@@ -155,7 +208,7 @@
: (isStatic ? SINGLE_STATIC_IMPORT_SUBKIND : SINGLE_TYPE_IMPORT_SUBKIND);
Snippet snip = new ImportSnippet(state.keyMap.keyForImport(keyName, snippetKind),
userSource, guts, fullname, name, snippetKind, fullkey, isStatic, isStar);
- return declare(snip);
+ return singletonList(snip);
}
private static class EvalPretty extends Pretty {
@@ -187,8 +240,8 @@
}
}
- private List<SnippetEvent> processVariables(String userSource, List<? extends Tree> units, String compileSource, ParseTask pt) {
- List<SnippetEvent> allEvents = new ArrayList<>();
+ private List<Snippet> processVariables(String userSource, List<? extends Tree> units, String compileSource, ParseTask pt) {
+ List<Snippet> snippets = new ArrayList<>();
TreeDissector dis = TreeDissector.createByFirstClass(pt);
for (Tree unitTree : units) {
VariableTree vt = (VariableTree) unitTree;
@@ -224,18 +277,16 @@
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);
Snippet snip = new VarSnippet(state.keyMap.keyForVariable(name), userSource, guts,
name, subkind, typeName,
- tds.declareReferences());
- DiagList modDiag = modifierDiagnostics(vt.getModifiers(), dis, true);
- List<SnippetEvent> res1 = declare(snip, modDiag);
- allEvents.addAll(res1);
+ tds.declareReferences(), modDiag);
+ snippets.add(snip);
}
-
- return allEvents;
+ return snippets;
}
- private List<SnippetEvent> processExpression(String userSource, String compileSource) {
+ private List<Snippet> processExpression(String userSource, String compileSource) {
String name = null;
ExpressionInfo ei = typeOfExpression(compileSource);
ExpressionTree assignVar;
@@ -266,7 +317,7 @@
guts = Wrap.tempVarWrap(compileSource, typeName, name);
Collection<String> declareReferences = null; //TODO
snip = new VarSnippet(state.keyMap.keyForVariable(name), userSource, guts,
- name, SubKind.TEMP_VAR_EXPRESSION_SUBKIND, typeName, declareReferences);
+ name, SubKind.TEMP_VAR_EXPRESSION_SUBKIND, typeName, declareReferences, null);
} else {
guts = Wrap.methodReturnWrap(compileSource);
snip = new ExpressionSnippet(state.keyMap.keyForExpression(name, typeName), userSource, guts,
@@ -282,15 +333,15 @@
at = trialCompile(guts);
}
if (at.hasErrors()) {
- return compileFailResult(at, userSource);
+ return compileFailResult(at, userSource, Kind.EXPRESSION);
}
}
snip = new StatementSnippet(state.keyMap.keyForStatement(), userSource, guts);
}
- return declare(snip);
+ return singletonList(snip);
}
- private List<SnippetEvent> processClass(String userSource, Tree unitTree, String compileSource, SubKind snippetKind, ParseTask pt) {
+ private List<Snippet> processClass(String userSource, Tree unitTree, String compileSource, SubKind snippetKind, ParseTask pt) {
TreeDependencyScanner tds = new TreeDependencyScanner();
tds.scan(unitTree);
@@ -306,11 +357,11 @@
Wrap guts = Wrap.classMemberWrap(compileSource);
Snippet snip = new TypeDeclSnippet(key, userSource, guts,
name, snippetKind,
- corralled, tds.declareReferences(), tds.bodyReferences());
- return declare(snip, modDiag);
+ corralled, tds.declareReferences(), tds.bodyReferences(), modDiag);
+ return singletonList(snip);
}
- private List<SnippetEvent> processStatement(String userSource, String compileSource) {
+ private List<Snippet> processStatement(String userSource, String compileSource) {
Wrap guts = Wrap.methodWrap(compileSource);
// Check for unreachable by trying
AnalyzeTask at = trialCompile(guts);
@@ -325,15 +376,15 @@
at = trialCompile(guts);
}
if (at.hasErrors()) {
- return compileFailResult(at, userSource);
+ return compileFailResult(at, userSource, Kind.STATEMENT);
}
}
} else {
- return compileFailResult(at, userSource);
+ return compileFailResult(at, userSource, Kind.STATEMENT);
}
}
Snippet snip = new StatementSnippet(state.keyMap.keyForStatement(), userSource, guts);
- return declare(snip);
+ return singletonList(snip);
}
private AnalyzeTask trialCompile(Wrap guts) {
@@ -341,7 +392,7 @@
return state.taskFactory.new AnalyzeTask(outer);
}
- private List<SnippetEvent> processMethod(String userSource, Tree unitTree, String compileSource, ParseTask pt) {
+ private List<Snippet> processMethod(String userSource, Tree unitTree, String compileSource, ParseTask pt) {
TreeDependencyScanner tds = new TreeDependencyScanner();
tds.scan(unitTree);
TreeDissector dis = TreeDissector.createByFirstClass(pt);
@@ -360,7 +411,7 @@
Wrap corralled = new Corraller(key.index(), pt.getContext()).corralMethod(mt);
if (modDiag.hasErrors()) {
- return compileFailResult(modDiag, userSource);
+ return compileFailResult(modDiag, userSource, Kind.METHOD);
}
Wrap guts = Wrap.classMemberWrap(compileSource);
Range typeRange = dis.treeToRange(returnType);
@@ -368,37 +419,76 @@
Snippet snip = new MethodSnippet(key, userSource, guts,
name, signature,
- corralled, tds.declareReferences(), tds.bodyReferences());
- return declare(snip, modDiag);
+ corralled, tds.declareReferences(), tds.bodyReferences(), modDiag);
+ return singletonList(snip);
}
- /**
- * The snippet has failed, return with the rejected event
- *
- * @param xt the task from which to extract the failure diagnostics
- * @param userSource the incoming bad user source
- * @return a rejected snippet event
- */
- private List<SnippetEvent> compileFailResult(BaseTask xt, String userSource) {
- return compileFailResult(xt.getDiagnostics(), userSource);
+ private Kind kindOfTree(Tree tree) {
+ switch (tree.getKind()) {
+ case IMPORT:
+ return Kind.IMPORT;
+ case VARIABLE:
+ return Kind.VAR;
+ case EXPRESSION_STATEMENT:
+ return Kind.EXPRESSION;
+ case CLASS:
+ case ENUM:
+ case ANNOTATION_TYPE:
+ case INTERFACE:
+ return Kind.TYPE_DECL;
+ case METHOD:
+ return Kind.METHOD;
+ default:
+ return Kind.STATEMENT;
+ }
}
/**
- * The snippet has failed, return with the rejected event
+ * The snippet has failed, return with the rejected snippet
+ *
+ * @param xt the task from which to extract the failure diagnostics
+ * @param userSource the incoming bad user source
+ * @return a rejected snippet
+ */
+ private List<Snippet> compileFailResult(BaseTask xt, String userSource, Kind probableKind) {
+ return compileFailResult(xt.getDiagnostics(), userSource, probableKind);
+ }
+
+ /**
+ * The snippet has failed, return with the rejected snippet
*
* @param diags the failure diagnostics
* @param userSource the incoming bad user source
- * @return a rejected snippet event
+ * @return a rejected snippet
*/
- private List<SnippetEvent> compileFailResult(DiagList diags, String userSource) {
+ private List<Snippet> compileFailResult(DiagList diags, String userSource, Kind probableKind) {
ErroneousKey key = state.keyMap.keyForErroneous();
- Snippet snip = new ErroneousSnippet(key, userSource, null, SubKind.UNKNOWN_SUBKIND);
+ Snippet snip = new ErroneousSnippet(key, userSource, null,
+ probableKind, SubKind.UNKNOWN_SUBKIND);
snip.setFailed(diags);
- state.maps.installSnippet(snip);
- return Collections.singletonList(new SnippetEvent(
- snip, Status.NONEXISTENT, Status.REJECTED,
- false, null, null, null)
- );
+
+ // Install wrapper for query by SourceCodeAnalysis.wrapper
+ String compileSource = Util.trimEnd(new MaskCommentsAndModifiers(userSource, true).cleared());
+ OuterWrap outer;
+ switch (probableKind) {
+ case IMPORT:
+ outer = state.outerMap.wrapImport(Wrap.simpleWrap(compileSource), snip);
+ break;
+ case EXPRESSION:
+ outer = state.outerMap.wrapInTrialClass(Wrap.methodReturnWrap(compileSource));
+ break;
+ case VAR:
+ case TYPE_DECL:
+ case METHOD:
+ outer = state.outerMap.wrapInTrialClass(Wrap.classMemberWrap(compileSource));
+ break;
+ default:
+ outer = state.outerMap.wrapInTrialClass(Wrap.methodWrap(compileSource));
+ break;
+ }
+ snip.setOuterWrap(outer);
+
+ return singletonList(snip);
}
private ExpressionInfo typeOfExpression(String expression) {
@@ -430,10 +520,6 @@
return events(c, outs, null, null);
}
- private List<SnippetEvent> declare(Snippet si) {
- return declare(si, new DiagList());
- }
-
private List<SnippetEvent> declare(Snippet si, DiagList generatedDiagnostics) {
Unit c = new Unit(state, si, null, generatedDiagnostics);
Set<Unit> ins = new LinkedHashSet<>();