You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by cc...@apache.org on 2015/10/07 21:26:28 UTC
[08/37] incubator-groovy git commit: Add some closure variants for
nicer DSL
Add some closure variants for nicer DSL
Project: http://git-wip-us.apache.org/repos/asf/incubator-groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-groovy/commit/7704cf90
Tree: http://git-wip-us.apache.org/repos/asf/incubator-groovy/tree/7704cf90
Diff: http://git-wip-us.apache.org/repos/asf/incubator-groovy/diff/7704cf90
Branch: refs/heads/master
Commit: 7704cf90379790d59db8917c4ed38b8052518cb6
Parents: a522e8f
Author: Cedric Champeau <ce...@gmail.com>
Authored: Wed Oct 15 10:08:33 2014 +0200
Committer: Sergei Egorov <bs...@gmail.com>
Committed: Mon Sep 28 14:32:05 2015 +0300
----------------------------------------------------------------------
.../groovy/ast/ContextualClassCodeVisitor.java | 63 +++++++++++++++++++-
1 file changed, 60 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/7704cf90/src/main/org/codehaus/groovy/ast/ContextualClassCodeVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/ContextualClassCodeVisitor.java b/src/main/org/codehaus/groovy/ast/ContextualClassCodeVisitor.java
index 742cb72..360a91e 100644
--- a/src/main/org/codehaus/groovy/ast/ContextualClassCodeVisitor.java
+++ b/src/main/org/codehaus/groovy/ast/ContextualClassCodeVisitor.java
@@ -16,6 +16,7 @@
package org.codehaus.groovy.ast;
import groovy.lang.Closure;
+import groovy.lang.DelegatesTo;
import groovy.lang.MapWithDefault;
import org.codehaus.groovy.ast.expr.*;
import org.codehaus.groovy.ast.stmt.AssertStatement;
@@ -36,6 +37,8 @@ import org.codehaus.groovy.ast.stmt.ThrowStatement;
import org.codehaus.groovy.ast.stmt.TryCatchStatement;
import org.codehaus.groovy.ast.stmt.WhileStatement;
import org.codehaus.groovy.classgen.BytecodeExpression;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -72,12 +75,33 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
}
protected TreeContext popContext() {
- TreeContext treeContext = treeContextStack.pop();
+ final TreeContext treeContext = treeContextStack.pop();
List<TreeContextAction> actions = treeContext.getOnPopHandlers();
for (TreeContextAction contextAction : actions) {
contextAction.call(treeContext);
}
lastContext = treeContext;
+ ASTNode parentNode = treeContext.parent!=null?treeContext.parent.node:null;
+ if (treeContext.node instanceof Expression && parentNode !=null) {
+ ClassCodeExpressionTransformer trn = new ClassCodeExpressionTransformer() {
+ @Override
+ protected SourceUnit getSourceUnit() {
+ return null;
+ }
+
+ @Override
+ public Expression transform(final Expression exp) {
+ if (exp==treeContext.node) {
+ Expression replacement = treeContext.getReplacement();
+ if (replacement!=null) {
+ return replacement;
+ }
+ }
+ return super.transform(exp);
+ }
+ };
+ parentNode.visit(trn);
+ }
return treeContext;
}
@@ -485,6 +509,14 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ @SuppressWarnings("unchecked")
+ private static <T> Closure<T> cloneWithDelegate(final Closure<T> predicate, final Object delegate) {
+ Closure<T> clone = (Closure<T>) predicate.clone();
+ clone.setDelegate(delegate);
+ clone.setResolveStrategy(Closure.DELEGATE_FIRST);
+ return clone;
+ }
+
public List<TreeContext> getTreePath() {
List<TreeContext> path = new LinkedList<TreeContext>();
path.add(lastContext);
@@ -493,6 +525,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
}
return path;
}
+
public List<TreeContext> pathMatches(List<ASTNodePredicate> predicates) {
List<TreeContext> path = new LinkedList<TreeContext>();
TreeContext current = lastContext.parent;
@@ -549,14 +582,17 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
// ----------------------------- inner classes --------------------------------------
public static class TreeContext {
+ private static enum TreeContextKey {
+ expression_replacement
+ }
final TreeContext parent;
final ASTNode node;
final List<TreeContext> siblings = new LinkedList<TreeContext>();
final List<TreeContextAction> onPopHandlers = new LinkedList<TreeContextAction>();
- final Map<?, List<?>> userdata = MapWithDefault.newInstance(
+ final Map<Object, List<?>> userdata = MapWithDefault.newInstance(
new HashMap<Object, List<?>>(),
new Closure(this) {
- public Object doCall(String key) {
+ public Object doCall(Object key) {
return new LinkedList<Object>();
}
}
@@ -585,6 +621,10 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
return predicate.matches(node);
}
+ public boolean matches(@DelegatesTo(value=ASTNode.class, strategy=Closure.DELEGATE_FIRST) Closure<Boolean> predicate) {
+ return cloneWithDelegate(predicate, node).call();
+ }
+
public List<TreeContext> getSiblings() {
return Collections.unmodifiableList(siblings);
}
@@ -597,6 +637,23 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
onPopHandlers.add(action);
}
+ public void afterVisit(@DelegatesTo(value=TreeContext.class, strategy=Closure.DELEGATE_FIRST) Closure<?> action) {
+ Closure<?> clone = cloneWithDelegate(action, this);
+ afterVisit(DefaultGroovyMethods.asType(clone, TreeContextAction.class));
+ }
+
+ public void setReplacement(Expression replacement) {
+ userdata.put(TreeContextKey.expression_replacement, Collections.singletonList(replacement));
+ }
+
+ public Expression getReplacement() {
+ List<?> list = userdata.get(TreeContextKey.expression_replacement);
+ if (list.size()==1) {
+ return (Expression) list.get(0);
+ }
+ return null;
+ }
+
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("TreeContext{");