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{");