Repository: groovy Updated Branches: refs/heads/parrot 09bac89dc -> 3495bc2f6
Merge PR#443 from Sergei Egorov manually Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/3495bc2f Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/3495bc2f Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/3495bc2f Branch: refs/heads/parrot Commit: 3495bc2f672168294c9ce2211903d42d79f0c2d2 Parents: 09bac89 Author: Daniel Sun <sun...@apache.org> Authored: Mon Nov 14 21:57:06 2016 +0800 Committer: Daniel Sun <sun...@apache.org> Committed: Mon Nov 14 21:57:06 2016 +0800 ---------------------------------------------------------------------- .gitignore | 1 + .../groovy/macro/runtime/MacroBuilder.java | 23 ++--- .../macro/runtime/MacroSubstitutionKey.java | 99 -------------------- .../macro/transform/MacroInvocationTrap.java | 23 ++--- .../org/codehaus/groovy/macro/MacroTest.groovy | 23 +++++ 5 files changed, 40 insertions(+), 129 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/3495bc2f/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index e00d9d0..539da50 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ bin/ .settings/ .classpath .project +.shelf http://git-wip-us.apache.org/repos/asf/groovy/blob/3495bc2f/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroBuilder.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroBuilder.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroBuilder.java index ab4c4f3..d7cc5ce 100644 --- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroBuilder.java +++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroBuilder.java @@ -33,8 +33,8 @@ import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.macro.transform.MacroInvocationTrap; import org.codehaus.groovy.macro.transform.MacroTransformation; +import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; /** @@ -44,27 +44,25 @@ import java.util.concurrent.atomic.AtomicInteger; public enum MacroBuilder { INSTANCE; - public <T> T macro(String source, final Map<MacroSubstitutionKey, Closure<Expression>> context, Class<T> resultClass) { + public <T> T macro(String source, final List<Closure<Expression>> context, Class<T> resultClass) { return macro(false, source, context, resultClass); } - public <T> T macro(boolean asIs, String source, final Map<MacroSubstitutionKey, Closure<Expression>> context, Class<T> resultClass) { + public <T> T macro(boolean asIs, String source, final List<Closure<Expression>> context, Class<T> resultClass) { return macro(CompilePhase.CONVERSION, asIs, source, context, resultClass); } - public <T> T macro(CompilePhase compilePhase, String source, final Map<MacroSubstitutionKey, Closure<Expression>> context, Class<T> resultClass) { + public <T> T macro(CompilePhase compilePhase, String source, final List<Closure<Expression>> context, Class<T> resultClass) { return macro(compilePhase, false, source, context, resultClass); } private final static AtomicInteger COUNTER = new AtomicInteger(); @SuppressWarnings("unchecked") - public <T> T macro(CompilePhase compilePhase, boolean asIs, String source, final Map<MacroSubstitutionKey, Closure<Expression>> context, Class<T> resultClass) { + public <T> T macro(CompilePhase compilePhase, boolean asIs, String source, final List<Closure<Expression>> context, Class<T> resultClass) { boolean isClosure = source.startsWith("{"); final String label = isClosure ?"__synthesized__label__" + COUNTER.incrementAndGet() + "__:":""; final String labelledSource = label + source; - final int linesOffset = 1; - final int columnsOffset = label.length() + (isClosure?1:0); // +1 because of { List<ASTNode> nodes = (new AstBuilder()).buildFromString(compilePhase, true, labelledSource); @@ -75,21 +73,22 @@ public enum MacroBuilder { if (!statements.isEmpty()) { BlockStatement closureBlock = (BlockStatement) statements.get(0); - performSubstitutions(linesOffset, columnsOffset, context, closureBlock); + performSubstitutions(context, closureBlock); return (T) getMacroValue(closureBlock, asIs); } } if (node instanceof ClassNode) { - performSubstitutions(linesOffset, columnsOffset, context, node); + performSubstitutions(context, node); return (T) node; } } return null; } - private static void performSubstitutions(final int linesOffset, final int columnsOffset, final Map<MacroSubstitutionKey, Closure<Expression>> context, final ASTNode astNode) { + private static void performSubstitutions(final List<Closure<Expression>> context, final ASTNode astNode) { + final Iterator<Closure<Expression>> iterator = context.iterator(); ClassCodeExpressionTransformer trn = new ClassCodeExpressionTransformer() { public Expression transform(Expression expression) { if (!(expression instanceof MethodCallExpression)) { @@ -102,9 +101,7 @@ public enum MacroBuilder { return super.transform(expression); } - MacroSubstitutionKey key = new MacroSubstitutionKey(call, linesOffset, columnsOffset); - - return context.get(key).call(); + return iterator.next().call(); } @Override http://git-wip-us.apache.org/repos/asf/groovy/blob/3495bc2f/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroSubstitutionKey.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroSubstitutionKey.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroSubstitutionKey.java deleted file mode 100644 index 5b382e5..0000000 --- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroSubstitutionKey.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.codehaus.groovy.macro.runtime; - -import org.codehaus.groovy.ast.ClassHelper; -import org.codehaus.groovy.ast.expr.ArgumentListExpression; -import org.codehaus.groovy.ast.expr.ConstantExpression; -import org.codehaus.groovy.ast.expr.ConstructorCallExpression; -import org.codehaus.groovy.ast.expr.Expression; - -/** - * - * @author Sergei Egorov <bsid...@gmail.com> - */ -public class MacroSubstitutionKey { - - private final int startLine; - private final int startColumn; - private final int endLine; - private final int endColumn; - - public MacroSubstitutionKey(int startLine, int startColumn, int endLine, int endColumn) { - this.startLine = startLine; - this.startColumn = startColumn; - this.endLine = endLine; - this.endColumn = endColumn; - } - - public MacroSubstitutionKey(Expression expression, int linesOffset, int columnsOffset) { - this( - expression.getLineNumber() - linesOffset, - expression.getColumnNumber() - (expression.getLineNumber() == linesOffset ? columnsOffset : 0), - expression.getLastLineNumber() - linesOffset, - expression.getLastColumnNumber() - (expression.getLastLineNumber() == linesOffset ? columnsOffset : 0) - ); - } - - public ConstructorCallExpression toConstructorCallExpression() { - return new ConstructorCallExpression( - ClassHelper.make(this.getClass()), - new ArgumentListExpression(new Expression[] { - new ConstantExpression(startLine), - new ConstantExpression(startColumn), - new ConstantExpression(endLine), - new ConstantExpression(endColumn) - }) - ); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MacroSubstitutionKey that = (MacroSubstitutionKey) o; - - if (endColumn != that.endColumn) return false; - if (endLine != that.endLine) return false; - if (startColumn != that.startColumn) return false; - if (startLine != that.startLine) return false; - - return true; - } - - @Override - public int hashCode() { - int result = startLine; - result = 31 * result + startColumn; - result = 31 * result + endLine; - result = 31 * result + endColumn; - return result; - } - - @Override - public String toString() { - return "SubstitutionKey{" + - "startLine=" + startLine + - ", startColumn=" + startColumn + - ", endLine=" + endLine + - ", endColumn=" + endColumn + - '}'; - } -} http://git-wip-us.apache.org/repos/asf/groovy/blob/3495bc2f/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java index a8cac37..73c14db 100644 --- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java +++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java @@ -30,7 +30,7 @@ import org.codehaus.groovy.ast.expr.ClosureExpression; import org.codehaus.groovy.ast.expr.ConstantExpression; import org.codehaus.groovy.ast.expr.ConstructorCallExpression; import org.codehaus.groovy.ast.expr.Expression; -import org.codehaus.groovy.ast.expr.MapExpression; +import org.codehaus.groovy.ast.expr.ListExpression; import org.codehaus.groovy.ast.expr.MethodCallExpression; import org.codehaus.groovy.ast.expr.PropertyExpression; import org.codehaus.groovy.ast.expr.TupleExpression; @@ -40,13 +40,10 @@ import org.codehaus.groovy.ast.tools.GeneralUtils; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.control.io.ReaderSource; import org.codehaus.groovy.macro.runtime.MacroBuilder; -import org.codehaus.groovy.macro.runtime.MacroSubstitutionKey; -import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Map; import static org.codehaus.groovy.ast.expr.VariableExpression.THIS_EXPRESSION; @@ -126,8 +123,6 @@ public class MacroInvocationTrap extends MethodInvocationTrap { return true; } - final MapExpression mapExpression = buildSubstitutionMap(closureExpression); - String source = convertClosureToSource(closureExpression); BlockStatement closureBlock = (BlockStatement) closureExpression.getCode(); @@ -159,7 +154,7 @@ public class MacroInvocationTrap extends MethodInvocationTrap { macroArgumentsExpressions.remove(macroArgumentsExpressions.size() - 1); macroArgumentsExpressions.add(new ConstantExpression(source)); - macroArgumentsExpressions.add(mapExpression); + macroArgumentsExpressions.add(buildSubstitutionMap(closureExpression)); macroArgumentsExpressions.add(new ClassExpression(ClassHelper.makeWithoutCaching(MacroBuilder.getMacroValue(closureBlock, asIs).getClass(), false))); macroCall.setObjectExpression(new PropertyExpression(new ClassExpression(ClassHelper.makeWithoutCaching(MacroBuilder.class, false)), "INSTANCE")); @@ -170,9 +165,8 @@ public class MacroInvocationTrap extends MethodInvocationTrap { return true; } - private MapExpression buildSubstitutionMap(final ASTNode expr) { - final Map<MacroSubstitutionKey, ClosureExpression> map = new HashMap<MacroSubstitutionKey, ClosureExpression>(); - final MapExpression mapExpression = new MapExpression(); + private ListExpression buildSubstitutionMap(final ASTNode expr) { + final ListExpression listExpression = new ListExpression(); ClassCodeVisitorSupport visitor = new ClassCodeVisitorSupport() { @Override @@ -206,9 +200,7 @@ public class MacroInvocationTrap extends MethodInvocationTrap { ((BlockStatement) code).setVariableScope(null); } - MacroSubstitutionKey key = new MacroSubstitutionKey(call, expr.getLineNumber(), expr.getColumnNumber()); - - map.put(key, substitutionClosureExpression); + listExpression.addExpression(substitutionClosureExpression); } } }; @@ -217,10 +209,7 @@ public class MacroInvocationTrap extends MethodInvocationTrap { } else { expr.visit(visitor); } - for (Map.Entry<MacroSubstitutionKey, ClosureExpression> entry : map.entrySet()) { - mapExpression.addMapEntryExpression(entry.getKey().toConstructorCallExpression(), entry.getValue()); - } - return mapExpression; + return listExpression; } @Override http://git-wip-us.apache.org/repos/asf/groovy/blob/3495bc2f/subprojects/groovy-macro/src/test/groovy/org/codehaus/groovy/macro/MacroTest.groovy ---------------------------------------------------------------------- diff --git a/subprojects/groovy-macro/src/test/groovy/org/codehaus/groovy/macro/MacroTest.groovy b/subprojects/groovy-macro/src/test/groovy/org/codehaus/groovy/macro/MacroTest.groovy index 3b740c9..1febbfa 100644 --- a/subprojects/groovy-macro/src/test/groovy/org/codehaus/groovy/macro/MacroTest.groovy +++ b/subprojects/groovy-macro/src/test/groovy/org/codehaus/groovy/macro/MacroTest.groovy @@ -186,4 +186,27 @@ class MacroTest extends GroovyTestCase { AstAssert.assertSyntaxTree([expected], [getReturnStatement()]); ''' } + + void testMultipleSubstitutions() { + assertScript ''' + import org.codehaus.groovy.ast.expr.*; + import org.codehaus.groovy.ast.stmt.*; + import org.codehaus.groovy.ast.ClassHelper; + import org.codehaus.groovy.ast.builder.AstAssert; + + import static org.codehaus.groovy.ast.tools.GeneralUtils.*; + + def var1 = new VariableExpression("a") + def var2 = new VariableExpression("b") + def var3 = new VariableExpression("c") + + ReturnStatement result = macro { + return new NonExistingClass($v{var1}, $v{var2}) + $v{var3} + } + + def expected = returnS(plusX(ctorX(ClassHelper.make("NonExistingClass"), args(var1, var2)), var3)) + + AstAssert.assertSyntaxTree([expected], [result]) +''' + } }