You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/03/28 06:04:47 UTC
[4/5] groovy git commit: CR fixes, split code into smaller parts,
add @Incubating and @since to different classes
CR fixes, split code into smaller parts, add @Incubating and @since to different classes
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/30949043
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/30949043
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/30949043
Branch: refs/heads/master
Commit: 30949043538a813e78c8e334f07bfe8e79e953cb
Parents: ada0e2c
Author: Sergei Egorov <se...@zeroturnaround.com>
Authored: Sat Mar 25 16:44:48 2017 +0200
Committer: paulk <pa...@asert.com.au>
Committed: Tue Mar 28 16:02:26 2017 +1000
----------------------------------------------------------------------
.../codehaus/groovy/macro/runtime/Macro.java | 1 +
.../groovy/macro/runtime/MacroBuilder.java | 6 +
.../groovy/macro/runtime/MacroContext.java | 15 ++
.../groovy/macro/runtime/MacroStub.java | 1 +
.../transform/MacroCallTransformingVisitor.java | 126 +++++++++++-----
.../groovy/macro/transform/MacroClass.java | 8 ++
.../transform/MacroClassTransformation.java | 142 +++++++++++--------
.../macro/transform/MacroMethodsCache.java | 1 +
.../macro/transform/MacroTransformation.java | 1 +
9 files changed, 205 insertions(+), 96 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/30949043/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/Macro.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/Macro.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/Macro.java
index b6a8938..a0fa4fc 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/Macro.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/Macro.java
@@ -27,6 +27,7 @@ import java.lang.annotation.Target;
/**
* @author Sergei Egorov <bs...@gmail.com>
+ * @since 2.5.0
*/
@Retention(RetentionPolicy.RUNTIME)
http://git-wip-us.apache.org/repos/asf/groovy/blob/30949043/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 ef857e9..73cb0e2 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
@@ -19,6 +19,7 @@
package org.codehaus.groovy.macro.runtime;
import groovy.lang.Closure;
+import org.apache.groovy.lang.annotation.Incubating;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
import org.codehaus.groovy.ast.ClassNode;
@@ -38,8 +39,13 @@ import java.util.concurrent.atomic.AtomicInteger;
import static org.codehaus.groovy.macro.methods.MacroGroovyMethods.DOLLAR_VALUE;
/**
+ * Runtime support for <pre>{@code macro {} }</pre> method.
+ *
* @author Sergei Egorov <bs...@gmail.com>
+ * @since 2.5.0
*/
+
+@Incubating
public enum MacroBuilder {
INSTANCE;
http://git-wip-us.apache.org/repos/asf/groovy/blob/30949043/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroContext.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroContext.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroContext.java
index e181a2a..07df293 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroContext.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroContext.java
@@ -24,7 +24,10 @@ import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.SourceUnit;
/**
+ * Macro method context. Every macro method must be an extension method of it.
+ *
* @author Sergei Egorov <bs...@gmail.com>
+ * @since 2.5.0
*/
@Incubating
@@ -42,14 +45,26 @@ public class MacroContext {
this.call = call;
}
+ /**
+ *
+ * @return original method call expression
+ */
public MethodCallExpression getCall() {
return call;
}
+ /**
+ *
+ * @return current source unit
+ */
public SourceUnit getSourceUnit() {
return sourceUnit;
}
+ /**
+ *
+ * @return current compilation unit
+ */
public CompilationUnit getCompilationUnit() {
return compilationUnit;
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/30949043/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java
index b0590b5..cf4b2f7 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java
@@ -22,6 +22,7 @@ package org.codehaus.groovy.macro.runtime;
* Stub for macro calls.
*
* @author Sergei Egorov <bs...@gmail.com>
+ * @since 2.5.0
*/
public enum MacroStub {
INSTANCE;
http://git-wip-us.apache.org/repos/asf/groovy/blob/30949043/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroCallTransformingVisitor.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroCallTransformingVisitor.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroCallTransformingVisitor.java
index 6af1afe..1afbeb7 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroCallTransformingVisitor.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroCallTransformingVisitor.java
@@ -1,3 +1,21 @@
+/*
+ * 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.transform;
import org.codehaus.groovy.ast.*;
@@ -11,9 +29,19 @@ import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.transform.stc.ExtensionMethodNode;
import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
-import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+/**
+ * Visitor to find and transform macro method calls. For the performance reasons it's not a transformer,
+ * but transforming visitor - it mutates {@link MethodCallExpression} if it's a macro method call by replacing
+ * original call (i.e. {@code myMacroMethod("foo", "bar")} with something like:
+ * {@code MacroStub.INSTANCE.macroMethod(123)}
+ * (where {@code myMacroMethod} returns constant expression {@code 123})
+ *
+ * @author Sergei Egorov <bs...@gmail.com>
+ * @since 2.5.0
+ */
class MacroCallTransformingVisitor extends ClassCodeVisitorSupport {
private static final ClassNode MACRO_CONTEXT_CLASS_NODE = ClassHelper.make(MacroContext.class);
@@ -43,58 +71,82 @@ class MacroCallTransformingVisitor extends ClassCodeVisitorSupport {
public void visitMethodCallExpression(MethodCallExpression call) {
super.visitMethodCallExpression(call);
- List<MethodNode> methods = MacroMethodsCache.get(classLoader).get(call.getMethodAsString());
-
- if (methods == null) {
- // Not a macro call
- return;
- }
-
List<Expression> callArguments = InvocationWriter.makeArgumentList(call.getArguments()).getExpressions();
- ClassNode[] argumentsList = new ClassNode[callArguments.size()];
+ List<MethodNode> macroMethods = findMacroMethods(call.getMethodAsString(), callArguments);
- for (int i = 0; i < callArguments.size(); i++) {
- argumentsList[i] = ClassHelper.make(callArguments.get(i).getClass());
+ if (macroMethods.isEmpty()) {
+ // Early return to avoid macro context and arguments creation
+ return;
}
- methods = StaticTypeCheckingSupport.chooseBestMethod(MACRO_CONTEXT_CLASS_NODE, methods, argumentsList);
+ MacroContext macroContext = new MacroContext(unit, sourceUnit, call);
- for (MethodNode macroMethodNode : methods) {
+ Object[] macroArguments = new Object[callArguments.size() + 1];
+ macroArguments[0] = macroContext;
+ System.arraycopy(callArguments.toArray(), 0, macroArguments, 1, callArguments.size());
+
+ for (MethodNode macroMethodNode : macroMethods) {
if (!(macroMethodNode instanceof ExtensionMethodNode)) {
- // TODO is it even possible?
- continue;
+ throw new IllegalStateException(macroMethodNode + " is not an instance of ExtensionMethodNode");
}
- MethodNode macroExtensionMethodNode = ((ExtensionMethodNode) macroMethodNode).getExtensionMethodNode();
-
- final Class clazz;
- try {
- clazz = classLoader.loadClass(macroExtensionMethodNode.getDeclaringClass().getName());
- } catch (ClassNotFoundException e) {
- //TODO different reaction?
- continue;
+ if (tryMacroMethod(call, (ExtensionMethodNode) macroMethodNode, macroArguments)) {
+ break;
}
+ }
+ }
- MacroContext macroContext = new MacroContext(unit, sourceUnit, call);
+ /**
+ * Finds all extension methods of {@link MacroContext} for given methodName
+ * with @{@link org.codehaus.groovy.macro.runtime.Macro} annotation.
+ */
+ private List<MethodNode> findMacroMethods(String methodName, List<Expression> callArguments) {
+ List<MethodNode> methods = MacroMethodsCache.get(classLoader).get(methodName);
- List<Object> macroArguments = new ArrayList<>();
- macroArguments.add(macroContext);
- macroArguments.addAll(callArguments);
+ if (methods == null) {
+ // Not a macro call
+ return Collections.emptyList();
+ }
- Expression result = (Expression) InvokerHelper.invokeStaticMethod(clazz, macroMethodNode.getName(), macroArguments.toArray());
+ ClassNode[] argumentsList = new ClassNode[callArguments.size()];
- call.setObjectExpression(MACRO_STUB_INSTANCE);
- call.setMethod(new ConstantExpression(MACRO_STUB_METHOD_NAME));
+ for (int i = 0; i < callArguments.size(); i++) {
+ argumentsList[i] = ClassHelper.make(callArguments.get(i).getClass());
+ }
- // TODO check that we reset everything here
- call.setSpreadSafe(false);
- call.setSafe(false);
- call.setImplicitThis(false);
- call.setArguments(result);
- call.setGenericsTypes(new GenericsType[0]);
+ return StaticTypeCheckingSupport.chooseBestMethod(MACRO_CONTEXT_CLASS_NODE, methods, argumentsList);
+ }
- break;
+ /**
+ * Attempts to call given macroMethod
+ * @param call MethodCallExpression before the transformation
+ * @param macroMethod a macro method candidate
+ * @param macroArguments arguments to pass to
+ * @return true if call succeeded and current call was transformed
+ */
+ private boolean tryMacroMethod(MethodCallExpression call, ExtensionMethodNode macroMethod, Object[] macroArguments) {
+ Expression result = (Expression) InvokerHelper.invokeStaticMethod(
+ macroMethod.getExtensionMethodNode().getDeclaringClass().getTypeClass(),
+ macroMethod.getName(),
+ macroArguments
+ );
+
+ if (result == null) {
+ // Allow macro methods to return null as an indicator that they didn't match a method call
+ return false;
}
+
+ call.setObjectExpression(MACRO_STUB_INSTANCE);
+ call.setMethod(new ConstantExpression(MACRO_STUB_METHOD_NAME));
+
+ // TODO check that we reset everything here
+ call.setSpreadSafe(false);
+ call.setSafe(false);
+ call.setImplicitThis(false);
+ call.setArguments(result);
+ call.setGenericsTypes(new GenericsType[0]);
+
+ return true;
}
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/30949043/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClass.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClass.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClass.java
index 0b01efa..d9d3f7c 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClass.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClass.java
@@ -18,5 +18,13 @@
*/
package org.codehaus.groovy.macro.transform;
+import org.apache.groovy.lang.annotation.Incubating;
+
+/**
+ *
+ * since 2.5.0
+ */
+
+@Incubating
public abstract class MacroClass {
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/30949043/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClassTransformation.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClassTransformation.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClassTransformation.java
index 292d59d..4ecd42e 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClassTransformation.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClassTransformation.java
@@ -34,6 +34,12 @@ import java.util.List;
import static org.codehaus.groovy.ast.tools.GeneralUtils.*;
+/**
+ * Transforms {@link MacroClass} calls into it's ClassNode
+ *
+ * @since 2.5.0
+ */
+
@GroovyASTTransformation(phase = CompilePhase.CONVERSION)
public class MacroClassTransformation extends MethodCallTransformation {
@@ -42,73 +48,91 @@ public class MacroClassTransformation extends MethodCallTransformation {
@Override
protected GroovyCodeVisitor getTransformer(final ASTNode[] nodes, final SourceUnit sourceUnit) {
- ClassCodeExpressionTransformer transformer = new ClassCodeExpressionTransformer() {
- @Override
- protected SourceUnit getSourceUnit() {
- return sourceUnit;
- }
+ ClassCodeExpressionTransformer transformer = new MacroClassTransformer(sourceUnit);
- @Override
- public Expression transform(final Expression exp) {
- if (exp instanceof ConstructorCallExpression) {
- MethodCallExpression call = exp.getNodeMetaData(MacroTransformation.class);
- if (call != null) {
- return call;
- }
+ return new MacroClassTransformingCodeVisitor(transformer, sourceUnit);
+ }
+
+ private static class MacroClassTransformer extends ClassCodeExpressionTransformer {
+
+ private final SourceUnit sourceUnit;
+
+ public MacroClassTransformer(SourceUnit sourceUnit) {
+ this.sourceUnit = sourceUnit;
+ }
+
+ @Override
+ protected SourceUnit getSourceUnit() {
+ return sourceUnit;
+ }
+
+ @Override
+ public Expression transform(final Expression exp) {
+ if (exp instanceof ConstructorCallExpression) {
+ MethodCallExpression call = exp.getNodeMetaData(MacroTransformation.class);
+ if (call != null) {
+ return call;
}
- return super.transform(exp);
}
- };
-
- return new TransformingCodeVisitor(transformer) {
-
- @Override
- public void visitConstructorCallExpression(final ConstructorCallExpression call) {
- ClassNode type = call.getType();
- if (type instanceof InnerClassNode) {
- if (((InnerClassNode) type).isAnonymous() &&
- MACROCLASS_TYPE.getNameWithoutPackage().equals(type.getSuperClass().getNameWithoutPackage())) {
- try {
- String source = convertInnerClassToSource(type);
-
- MethodCallExpression macroCall = callX(
- propX(classX(ClassHelper.makeWithoutCaching(MacroBuilder.class, false)), "INSTANCE"),
- MACRO_METHOD,
- args(
- constX(source),
- MacroGroovyMethods.buildSubstitutionMap(sourceUnit, type),
- classX(ClassHelper.make(ClassNode.class))
- )
- );
-
- macroCall.setSpreadSafe(false);
- macroCall.setSafe(false);
- macroCall.setImplicitThis(false);
- call.putNodeMetaData(MacroTransformation.class, macroCall);
- List<ClassNode> classes = sourceUnit.getAST().getClasses();
- for (Iterator<ClassNode> iterator = classes.iterator(); iterator.hasNext(); ) {
- final ClassNode aClass = iterator.next();
- if (aClass == type || type == aClass.getOuterClass()) {
- iterator.remove();
- }
+ return super.transform(exp);
+ }
+ }
+
+ private static class MacroClassTransformingCodeVisitor extends TransformingCodeVisitor {
+
+ private final SourceUnit sourceUnit;
+
+ public MacroClassTransformingCodeVisitor(ClassCodeExpressionTransformer transformer, SourceUnit sourceUnit) {
+ super(transformer);
+ this.sourceUnit = sourceUnit;
+ }
+
+ @Override
+ public void visitConstructorCallExpression(final ConstructorCallExpression call) {
+ ClassNode type = call.getType();
+ if (type instanceof InnerClassNode) {
+ if (((InnerClassNode) type).isAnonymous() &&
+ MACROCLASS_TYPE.getNameWithoutPackage().equals(type.getSuperClass().getNameWithoutPackage())) {
+ try {
+ String source = convertInnerClassToSource(type);
+
+ MethodCallExpression macroCall = callX(
+ propX(classX(ClassHelper.makeWithoutCaching(MacroBuilder.class, false)), "INSTANCE"),
+ MACRO_METHOD,
+ args(
+ constX(source),
+ MacroGroovyMethods.buildSubstitutionMap(sourceUnit, type),
+ classX(ClassHelper.make(ClassNode.class))
+ )
+ );
+
+ macroCall.setSpreadSafe(false);
+ macroCall.setSafe(false);
+ macroCall.setImplicitThis(false);
+ call.putNodeMetaData(MacroTransformation.class, macroCall);
+ List<ClassNode> classes = sourceUnit.getAST().getClasses();
+ for (Iterator<ClassNode> iterator = classes.iterator(); iterator.hasNext(); ) {
+ final ClassNode aClass = iterator.next();
+ if (aClass == type || type == aClass.getOuterClass()) {
+ iterator.remove();
}
- } catch (Exception e) {
- // FIXME
- e.printStackTrace();
}
- return;
+ } catch (Exception e) {
+ // FIXME
+ e.printStackTrace();
}
+ return;
}
- super.visitConstructorCallExpression(call);
-
}
+ super.visitConstructorCallExpression(call);
- private String convertInnerClassToSource(final ClassNode type) throws Exception {
- String source = GeneralUtils.convertASTToSource(sourceUnit.getSource(), type);
- // we need to remove the leading "{" and trailing "}"
- source = source.substring(source.indexOf('{') + 1, source.lastIndexOf('}') - 1);
- return source;
- }
- };
+ }
+
+ private String convertInnerClassToSource(final ClassNode type) throws Exception {
+ String source = GeneralUtils.convertASTToSource(sourceUnit.getSource(), type);
+ // we need to remove the leading "{" and trailing "}"
+ source = source.substring(source.indexOf('{') + 1, source.lastIndexOf('}') - 1);
+ return source;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/30949043/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
index d3e8ed4..90ca15b 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
@@ -34,6 +34,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* TODO share some code with {@link org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.ExtensionMethodCache}
* @author Sergei Egorov <bs...@gmail.com>
+ * @since 2.5.0
*/
class MacroMethodsCache {
http://git-wip-us.apache.org/repos/asf/groovy/blob/30949043/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroTransformation.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroTransformation.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroTransformation.java
index 983ba18..3ea441a 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroTransformation.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroTransformation.java
@@ -27,6 +27,7 @@ import org.codehaus.groovy.transform.GroovyASTTransformation;
/**
* @author Sergei Egorov <bs...@gmail.com>
+ * @since 2.5.0
*/
@GroovyASTTransformation(phase = CompilePhase.CONVERSION)