Return-Path: X-Original-To: apmail-groovy-commits-archive@minotaur.apache.org Delivered-To: apmail-groovy-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 5B9D518BC2 for ; Wed, 7 Oct 2015 19:26:40 +0000 (UTC) Received: (qmail 6571 invoked by uid 500); 7 Oct 2015 19:26:40 -0000 Delivered-To: apmail-groovy-commits-archive@groovy.apache.org Received: (qmail 6538 invoked by uid 500); 7 Oct 2015 19:26:40 -0000 Mailing-List: contact commits-help@groovy.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@groovy.incubator.apache.org Delivered-To: mailing list commits@groovy.incubator.apache.org Received: (qmail 6527 invoked by uid 99); 7 Oct 2015 19:26:40 -0000 Received: from Unknown (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 07 Oct 2015 19:26:40 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id C6AE5180E49 for ; Wed, 7 Oct 2015 19:26:39 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 0.79 X-Spam-Level: X-Spam-Status: No, score=0.79 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, T_RP_MATCHES_RCVD=-0.01] autolearn=disabled Received: from mx1-eu-west.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id qroGrv_i9iDe for ; Wed, 7 Oct 2015 19:26:24 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-eu-west.apache.org (ASF Mail Server at mx1-eu-west.apache.org) with SMTP id 6364324E1C for ; Wed, 7 Oct 2015 19:26:22 +0000 (UTC) Received: (qmail 3133 invoked by uid 99); 7 Oct 2015 19:26:21 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 07 Oct 2015 19:26:21 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 4BDE6E0ADA; Wed, 7 Oct 2015 19:26:21 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: cchampeau@apache.org To: commits@groovy.incubator.apache.org Date: Wed, 07 Oct 2015 19:26:22 -0000 Message-Id: <245405859e4349ceaeaf9ded30202a2d@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [02/37] incubator-groovy git commit: shared code between MacroGroovy and AstBuilderTransformation shared code between MacroGroovy and AstBuilderTransformation Project: http://git-wip-us.apache.org/repos/asf/incubator-groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-groovy/commit/546868aa Tree: http://git-wip-us.apache.org/repos/asf/incubator-groovy/tree/546868aa Diff: http://git-wip-us.apache.org/repos/asf/incubator-groovy/diff/546868aa Branch: refs/heads/master Commit: 546868aaae30335b9b6fc1a67bb6cf1dc2b84cff Parents: 0b5f0b0 Author: Sergey Egorov Authored: Thu Jul 3 12:45:29 2014 +0300 Committer: Sergei Egorov Committed: Mon Sep 28 14:32:03 2015 +0300 ---------------------------------------------------------------------- .../groovy/ast/MethodCallTransformation.java | 113 ++++++++++++ .../groovy/ast/MethodInvocationTrap.java | 94 ++++++++++ .../ast/builder/AstBuilderTransformation.java | 181 +++---------------- .../macro/transform/MacroInvocationTrap.java | 148 +++++---------- .../macro/transform/MacroTransformation.java | 41 +---- 5 files changed, 289 insertions(+), 288 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/546868aa/src/main/org/codehaus/groovy/ast/MethodCallTransformation.java ---------------------------------------------------------------------- diff --git a/src/main/org/codehaus/groovy/ast/MethodCallTransformation.java b/src/main/org/codehaus/groovy/ast/MethodCallTransformation.java new file mode 100644 index 0000000..85c6f2c --- /dev/null +++ b/src/main/org/codehaus/groovy/ast/MethodCallTransformation.java @@ -0,0 +1,113 @@ +/* + * Copyright 2003-2013 the original author or authors. + * + * Licensed 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.ast; + +import groovy.lang.MissingPropertyException; +import org.codehaus.groovy.ast.stmt.Statement; +import org.codehaus.groovy.control.SourceUnit; +import org.codehaus.groovy.transform.ASTTransformation; + +/** + * + * @author Hamlet D'Arcy + * @author Sergei Egorov + */ + +public abstract class MethodCallTransformation implements ASTTransformation { + + public void visit(ASTNode[] nodes, SourceUnit sourceUnit) { + + GroovyCodeVisitor transformer = getTransformer(nodes, sourceUnit); + + if (nodes != null) { + for (ASTNode it : nodes) { + if (!(it instanceof AnnotationNode) && !(it instanceof ClassNode)) { + it.visit(transformer); + } + } + } + if (sourceUnit.getAST() != null) { + sourceUnit.getAST().visit(transformer); + if (sourceUnit.getAST().getStatementBlock() != null) { + sourceUnit.getAST().getStatementBlock().visit(transformer); + } + if (sourceUnit.getAST().getClasses() != null) { + for (ClassNode classNode : sourceUnit.getAST().getClasses()) { + if (classNode.getMethods() != null) { + for (MethodNode node : classNode.getMethods()) { + if (node != null && node.getCode() != null) { + node.getCode().visit(transformer); + } + } + } + + try { + if (classNode.getDeclaredConstructors() != null) { + for (MethodNode node : classNode.getDeclaredConstructors()) { + if (node != null && node.getCode() != null) { + node.getCode().visit(transformer); + } + } + } + } catch (MissingPropertyException ignored) { + // todo: inner class nodes don't have a constructors field available + } + + // all properties are also always fields + if (classNode.getFields() != null) { + for (FieldNode node : classNode.getFields()) { + if (node.getInitialValueExpression() != null) { + node.getInitialValueExpression().visit(transformer); + } + } + } + + try { + if (classNode.getObjectInitializerStatements() != null) { + for (Statement node : classNode.getObjectInitializerStatements()) { + if (node != null) { + node.visit(transformer); + } + } + } + } catch (MissingPropertyException ignored) { + // todo: inner class nodes don't have a objectInitializers field available + } + + // todo: is there anything to do with the module ??? + } + } + if (sourceUnit.getAST().getMethods() != null) { + for (MethodNode node : sourceUnit.getAST().getMethods()) { + if (node != null) { + if (node.getParameters() != null) { + for (Parameter parameter : node.getParameters()) { + if (parameter != null && parameter.getInitialExpression() != null) { + parameter.getInitialExpression().visit(transformer); + } + } + } + if (node.getCode() != null) { + node.getCode().visit(transformer); + } + } + } + } + } + } + + protected abstract GroovyCodeVisitor getTransformer(ASTNode[] nodes, SourceUnit sourceUnit); +} http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/546868aa/src/main/org/codehaus/groovy/ast/MethodInvocationTrap.java ---------------------------------------------------------------------- diff --git a/src/main/org/codehaus/groovy/ast/MethodInvocationTrap.java b/src/main/org/codehaus/groovy/ast/MethodInvocationTrap.java new file mode 100644 index 0000000..6d51a5c --- /dev/null +++ b/src/main/org/codehaus/groovy/ast/MethodInvocationTrap.java @@ -0,0 +1,94 @@ +/* + * Copyright 2003-2013 the original author or authors. + * + * Licensed 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.ast; + +import org.codehaus.groovy.ast.expr.ClosureExpression; +import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.tools.ClosureUtils; +import org.codehaus.groovy.control.SourceUnit; +import org.codehaus.groovy.control.io.ReaderSource; +import org.codehaus.groovy.control.messages.SyntaxErrorMessage; +import org.codehaus.groovy.syntax.SyntaxException; + +/** + * + * @author Hamlet D'Arcy + * @author Sergei Egorov + */ +public abstract class MethodInvocationTrap extends CodeVisitorSupport { + + protected final ReaderSource source; + protected final SourceUnit sourceUnit; + + public MethodInvocationTrap(ReaderSource source, SourceUnit sourceUnit) { + if (source == null) throw new IllegalArgumentException("Null: source"); + if (sourceUnit == null) throw new IllegalArgumentException("Null: sourceUnit"); + this.source = source; + this.sourceUnit = sourceUnit; + } + + /** + * Attempts to find AstBuilder 'from code' invocations. When found, converts them into calls + * to the 'from string' approach. + * + * @param call the method call expression that may or may not be an AstBuilder 'from code' invocation. + */ + public void visitMethodCallExpression(MethodCallExpression call) { + boolean shouldContinueWalking = true; + + if (isBuildInvocation(call)) { + shouldContinueWalking = handleTargetMethodCallExpression(call); + } + + if(shouldContinueWalking) { + // continue normal tree walking + call.getObjectExpression().visit(this); + call.getMethod().visit(this); + call.getArguments().visit(this); + } + } + + /** + * Reports an error back to the source unit. + * + * @param msg the error message + * @param expr the expression that caused the error message. + */ + protected void addError(String msg, ASTNode expr) { + sourceUnit.getErrorCollector().addErrorAndContinue( + new SyntaxErrorMessage(new SyntaxException(msg + '\n', expr.getLineNumber(), expr.getColumnNumber(), expr.getLastLineNumber(), expr.getLastColumnNumber()), sourceUnit) + ); + } + + /** + * Converts a ClosureExpression into the String source. + * + * @param expression a closure + * @return the source the closure was created from + */ + protected String convertClosureToSource(ClosureExpression expression) { + try { + return ClosureUtils.convertClosureToSource(source, expression); + } catch(Exception e) { + addError(e.getMessage(), expression); + } + return null; + } + + protected abstract boolean handleTargetMethodCallExpression(MethodCallExpression call); + + protected abstract boolean isBuildInvocation(MethodCallExpression call); +} http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/546868aa/src/main/org/codehaus/groovy/ast/builder/AstBuilderTransformation.java ---------------------------------------------------------------------- diff --git a/src/main/org/codehaus/groovy/ast/builder/AstBuilderTransformation.java b/src/main/org/codehaus/groovy/ast/builder/AstBuilderTransformation.java index 20a4aea..4143e34 100644 --- a/src/main/org/codehaus/groovy/ast/builder/AstBuilderTransformation.java +++ b/src/main/org/codehaus/groovy/ast/builder/AstBuilderTransformation.java @@ -18,17 +18,11 @@ */ package org.codehaus.groovy.ast.builder; -import groovy.lang.MissingPropertyException; import org.codehaus.groovy.ast.*; import org.codehaus.groovy.ast.expr.*; -import org.codehaus.groovy.ast.stmt.Statement; -import org.codehaus.groovy.ast.tools.ClosureUtils; import org.codehaus.groovy.control.CompilePhase; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.control.io.ReaderSource; -import org.codehaus.groovy.control.messages.SyntaxErrorMessage; -import org.codehaus.groovy.syntax.SyntaxException; -import org.codehaus.groovy.transform.ASTTransformation; import org.codehaus.groovy.transform.GroovyASTTransformation; import java.util.ArrayList; @@ -49,92 +43,17 @@ import java.util.List; */ @GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS) -public class AstBuilderTransformation implements ASTTransformation { - - public void visit(ASTNode[] nodes, SourceUnit sourceUnit) { +public class AstBuilderTransformation extends MethodCallTransformation { + @Override + protected GroovyCodeVisitor getTransformer(ASTNode[] nodes, SourceUnit sourceUnit) { // todo : are there other import types that can be specified? - AstBuilderInvocationTrap transformer = new AstBuilderInvocationTrap( - sourceUnit.getAST().getImports(), - sourceUnit.getAST().getStarImports(), - sourceUnit.getSource(), - sourceUnit + return new AstBuilderInvocationTrap( + sourceUnit.getAST().getImports(), + sourceUnit.getAST().getStarImports(), + sourceUnit.getSource(), + sourceUnit ); - if (nodes != null) { - for (ASTNode it : nodes) { - if (!(it instanceof AnnotationNode) && !(it instanceof ClassNode)) { - it.visit(transformer); - } - } - } - if (sourceUnit.getAST() != null) { - sourceUnit.getAST().visit(transformer); - if (sourceUnit.getAST().getStatementBlock() != null) { - sourceUnit.getAST().getStatementBlock().visit(transformer); - } - if (sourceUnit.getAST().getClasses() != null) { - for (ClassNode classNode : sourceUnit.getAST().getClasses()) { - if (classNode.getMethods() != null) { - for (MethodNode node : classNode.getMethods()) { - if (node != null && node.getCode() != null) { - node.getCode().visit(transformer); - } - } - } - - try { - if (classNode.getDeclaredConstructors() != null) { - for (MethodNode node : classNode.getDeclaredConstructors()) { - if (node != null && node.getCode() != null) { - node.getCode().visit(transformer); - } - } - } - } catch (MissingPropertyException ignored) { - // todo: inner class nodes don't have a constructors field available - } - - // all properties are also always fields - if (classNode.getFields() != null) { - for (FieldNode node : classNode.getFields()) { - if (node.getInitialValueExpression() != null) { - node.getInitialValueExpression().visit(transformer); - } - } - } - - try { - if (classNode.getObjectInitializerStatements() != null) { - for (Statement node : classNode.getObjectInitializerStatements()) { - if (node != null) { - node.visit(transformer); - } - } - } - } catch (MissingPropertyException ignored) { - // todo: inner class nodes don't have a objectInitializers field available - } - - // todo: is there anything to do with the module ??? - } - } - if (sourceUnit.getAST().getMethods() != null) { - for (MethodNode node : sourceUnit.getAST().getMethods()) { - if (node != null) { - if (node.getParameters() != null) { - for (Parameter parameter : node.getParameters()) { - if (parameter != null && parameter.getInitialExpression() != null) { - parameter.getInitialExpression().visit(transformer); - } - } - } - if (node.getCode() != null) { - node.getCode().visit(transformer); - } - } - } - } - } } /** @@ -142,11 +61,9 @@ public class AstBuilderTransformation implements ASTTransformation { * the contents of the closure into expressions by reading the source of the Closure and sending * that as a String to AstBuilder.build(String, CompilePhase, boolean) at runtime. */ - private static class AstBuilderInvocationTrap extends CodeVisitorSupport { + private static class AstBuilderInvocationTrap extends MethodInvocationTrap { private final List factoryTargets = new ArrayList(); - private final ReaderSource source; - private final SourceUnit sourceUnit; /** * Creates the trap and captures all the ways in which a class may be referenced via imports. @@ -157,10 +74,7 @@ public class AstBuilderTransformation implements ASTTransformation { * @param sourceUnit the source unit being compiled. Used for error messages. */ AstBuilderInvocationTrap(List imports, List importPackages, ReaderSource source, SourceUnit sourceUnit) { - if (source == null) throw new IllegalArgumentException("Null: source"); - if (sourceUnit == null) throw new IllegalArgumentException("Null: sourceUnit"); - this.source = source; - this.sourceUnit = sourceUnit; + super(source, sourceUnit); // factory type may be references as fully qualified, an import, or an alias factoryTargets.add("org.codehaus.groovy.ast.builder.AstBuilder");//default package @@ -182,47 +96,22 @@ public class AstBuilderTransformation implements ASTTransformation { } } } - - /** - * Reports an error back to the source unit. - * - * @param msg the error message - * @param expr the expression that caused the error message. - */ - private void addError(String msg, ASTNode expr) { - sourceUnit.getErrorCollector().addErrorAndContinue( - new SyntaxErrorMessage(new SyntaxException(msg + '\n', expr.getLineNumber(), expr.getColumnNumber(), expr.getLastLineNumber(), expr.getLastColumnNumber()), sourceUnit) - ); - } - - - /** - * Attempts to find AstBuilder 'from code' invocations. When found, converts them into calls - * to the 'from string' approach. - * - * @param call the method call expression that may or may not be an AstBuilder 'from code' invocation. - */ - public void visitMethodCallExpression(MethodCallExpression call) { - - if (isBuildInvocation(call)) { - - ClosureExpression closureExpression = getClosureArgument(call); - List otherArgs = getNonClosureArguments(call); - String source = convertClosureToSource(closureExpression); - - // parameter order is build(CompilePhase, boolean, String) - otherArgs.add(new ConstantExpression(source)); - call.setArguments(new ArgumentListExpression(otherArgs)); - call.setMethod(new ConstantExpression("buildFromBlock")); - call.setSpreadSafe(false); - call.setSafe(false); - call.setImplicitThis(false); - } else { - // continue normal tree walking - call.getObjectExpression().visit(this); - call.getMethod().visit(this); - call.getArguments().visit(this); - } + + @Override + protected boolean handleTargetMethodCallExpression(MethodCallExpression call) { + ClosureExpression closureExpression = getClosureArgument(call); + List otherArgs = getNonClosureArguments(call); + String source = convertClosureToSource(closureExpression); + + // parameter order is build(CompilePhase, boolean, String) + otherArgs.add(new ConstantExpression(source)); + call.setArguments(new ArgumentListExpression(otherArgs)); + call.setMethod(new ConstantExpression("buildFromBlock")); + call.setSpreadSafe(false); + call.setSafe(false); + call.setImplicitThis(false); + + return false; } private List getNonClosureArguments(MethodCallExpression call) { @@ -255,7 +144,8 @@ public class AstBuilderTransformation implements ASTTransformation { * * @param call the method call expression, may not be null */ - private boolean isBuildInvocation(MethodCallExpression call) { + @Override + protected boolean isBuildInvocation(MethodCallExpression call) { if (call == null) throw new IllegalArgumentException("Null: call"); // is method name correct? @@ -281,21 +171,6 @@ public class AstBuilderTransformation implements ASTTransformation { } return false; } - - /** - * Converts a ClosureExpression into the String source. - * - * @param expression a closure - * @return the source the closure was created from - */ - private String convertClosureToSource(ClosureExpression expression) { - try { - return ClosureUtils.convertClosureToSource(source, expression); - } catch(Exception e) { - addError(e.getMessage(), expression); - } - return null; - } } } http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/546868aa/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java b/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java index 7ac10df..b082e8b 100644 --- a/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java +++ b/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroInvocationTrap.java @@ -15,18 +15,15 @@ */ package org.codehaus.groovy.macro.transform; -import org.codehaus.groovy.ast.ASTNode; import org.codehaus.groovy.ast.ClassHelper; import org.codehaus.groovy.ast.CodeVisitorSupport; +import org.codehaus.groovy.ast.MethodInvocationTrap; import org.codehaus.groovy.ast.expr.*; import org.codehaus.groovy.ast.stmt.BlockStatement; -import org.codehaus.groovy.ast.tools.ClosureUtils; import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.control.io.ReaderSource; -import org.codehaus.groovy.control.messages.SyntaxErrorMessage; import org.codehaus.groovy.macro.runtime.MacroBuilder; import org.codehaus.groovy.macro.runtime.MacroSubstitutionKey; -import org.codehaus.groovy.syntax.SyntaxException; import java.util.ArrayList; import java.util.List; @@ -37,106 +34,73 @@ import static org.codehaus.groovy.ast.expr.VariableExpression.THIS_EXPRESSION; * * @author Sergei Egorov */ -public class MacroInvocationTrap { - - private final ReaderSource source; - private final SourceUnit sourceUnit; - - /** - * Creates the trap and captures all macro method calls. - * - * @param source the reader source that contains source for the SourceUnit - * @param sourceUnit the source unit being compiled. Used for error messages. - */ - MacroInvocationTrap(ReaderSource source, SourceUnit sourceUnit) { - if (source == null) throw new IllegalArgumentException("Null: source"); - if (sourceUnit == null) throw new IllegalArgumentException("Null: sourceUnit"); - this.source = source; - this.sourceUnit = sourceUnit; - } +public class MacroInvocationTrap extends MethodInvocationTrap { - /** - * Reports an error back to the source unit. - * - * @param msg the error message - * @param expr the expression that caused the error message. - */ - private void addError(String msg, ASTNode expr) { - sourceUnit.getErrorCollector().addErrorAndContinue( - new SyntaxErrorMessage(new SyntaxException(msg + '\n', expr.getLineNumber(), expr.getColumnNumber(), expr.getLastLineNumber(), expr.getLastColumnNumber()), sourceUnit) - ); + public MacroInvocationTrap(ReaderSource source, SourceUnit sourceUnit) { + super(source, sourceUnit); } - /** - * Attempts to find 'macro' invocations. When found, converts them into calls - * to the 'from string' approach. - * - * @param macroCall the method call expression that may or may not be a 'macro' invocation. - */ - public void visitMethodCallExpression(final MethodCallExpression macroCall) { - - if (!isBuildInvocation(macroCall, MacroTransformation.MACRO_METHOD)) { - return; - } - + @Override + protected boolean handleTargetMethodCallExpression(MethodCallExpression macroCall) { final ClosureExpression closureExpression = getClosureArgument(macroCall); - + if(closureExpression == null) { - return; + return true; } if(closureExpression.getParameters() != null && closureExpression.getParameters().length > 0) { addError("Macro closure arguments are not allowed", closureExpression); + return true; } - + final MapExpression mapExpression = new MapExpression(); - + (new CodeVisitorSupport() { @Override public void visitMethodCallExpression(MethodCallExpression call) { super.visitMethodCallExpression(call); - + if(isBuildInvocation(call, MacroTransformation.DOLLAR_VALUE)) { ClosureExpression substitutionClosureExpression = getClosureArgument(call); - + if(substitutionClosureExpression == null) { return; } MacroSubstitutionKey key = new MacroSubstitutionKey(call, closureExpression.getLineNumber(), closureExpression.getColumnNumber()); - + mapExpression.addMapEntryExpression(key.toConstructorCallExpression(), substitutionClosureExpression); } } }).visitClosureExpression(closureExpression); - - String source = convertClosureToSource(this.source, closureExpression); + + String source = convertClosureToSource(closureExpression); BlockStatement closureBlock = (BlockStatement) closureExpression.getCode(); - + Boolean asIs = false; - + TupleExpression macroArguments = getMacroArguments(macroCall); - + if(macroArguments == null) { - return; + return true; } List macroArgumentsExpressions = macroArguments.getExpressions(); - + if(macroArgumentsExpressions.size() > 1) { Expression firstArgument = macroArgumentsExpressions.get(0); - + if(!(firstArgument instanceof ConstantExpression)) { addError("AsIs argument value should be constant(true or false)", firstArgument); - return; + return true; } - + ConstantExpression asIsConstantExpression = (ConstantExpression) firstArgument; - + if(!(asIsConstantExpression.getValue() instanceof Boolean)) { addError("AsIs argument value should be boolean", asIsConstantExpression); - return; + return true; } asIs = (Boolean) asIsConstantExpression.getValue(); @@ -153,6 +117,29 @@ public class MacroInvocationTrap { macroCall.setSpreadSafe(false); macroCall.setSafe(false); macroCall.setImplicitThis(false); + + return true; + } + + @Override + protected boolean isBuildInvocation(MethodCallExpression call) { + return isBuildInvocation(call, MacroTransformation.MACRO_METHOD); + } + + public static boolean isBuildInvocation(MethodCallExpression call, String methodName) { + if (call == null) throw new IllegalArgumentException("Null: call"); + if(methodName == null) throw new IllegalArgumentException("Null: methodName"); + + if(!(call.getMethod() instanceof ConstantExpression)) { + return false; + } + + if(!(methodName.equals(call.getMethodAsString()))) { + return false; + } + + // is method object correct type? + return call.getObjectExpression() == THIS_EXPRESSION; } protected TupleExpression getMacroArguments(MethodCallExpression call) { @@ -193,41 +180,4 @@ public class MacroInvocationTrap { return (ClosureExpression) result; } - - /** - * Looks for 'macro' method calls. - * - * @param call the method call expression, may not be null - */ - public static boolean isBuildInvocation(MethodCallExpression call, String methodName) { - if (call == null) throw new IllegalArgumentException("Null: call"); - if(methodName == null) throw new IllegalArgumentException("Null: methodName"); - - if(!(call.getMethod() instanceof ConstantExpression)) { - return false; - } - - if(!(methodName.equals(call.getMethodAsString()))) { - return false; - } - - // is method object correct type? - return call.getObjectExpression() == THIS_EXPRESSION; - } - - /** - * Converts a ClosureExpression into the String source. - * - * @param expression a closure - * @return the source the closure was created from - */ - private String convertClosureToSource(ReaderSource source, ClosureExpression expression) { - - try { - return ClosureUtils.convertClosureToSource(source, expression); - } catch (Exception e) { - addError(e.getMessage(), expression); - } - return null; - } } http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/546868aa/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroTransformation.java ---------------------------------------------------------------------- diff --git a/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroTransformation.java b/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroTransformation.java index cdf0f07..65284b5 100644 --- a/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroTransformation.java +++ b/subprojects/groovy-macro/src/main/java/org/codehaus/groovy/macro/transform/MacroTransformation.java @@ -15,56 +15,25 @@ */ package org.codehaus.groovy.macro.transform; -import org.codehaus.groovy.ast.ASTNode; -import org.codehaus.groovy.ast.ClassCodeVisitorSupport; -import org.codehaus.groovy.ast.ClassNode; -import org.codehaus.groovy.ast.ModuleNode; -import org.codehaus.groovy.ast.expr.MethodCallExpression; +import org.codehaus.groovy.ast.*; import org.codehaus.groovy.control.CompilePhase; import org.codehaus.groovy.control.SourceUnit; -import org.codehaus.groovy.transform.ASTTransformation; import org.codehaus.groovy.transform.GroovyASTTransformation; /** * * @author Sergei Egorov */ + @GroovyASTTransformation(phase = CompilePhase.CONVERSION) -public class MacroTransformation extends ClassCodeVisitorSupport implements ASTTransformation { +public class MacroTransformation extends MethodCallTransformation { public static final String DOLLAR_VALUE = "$v"; public static final String MACRO_METHOD = "macro"; - SourceUnit source; - - MacroInvocationTrap transformer; - - public void visit(ASTNode[] nodes, SourceUnit source) { - this.source = source; - - transformer = new MacroInvocationTrap(source.getSource(), source); - - for(ASTNode node : nodes) { - if(node instanceof ClassNode) { - visitClass((ClassNode) node); - } else if(node instanceof ModuleNode) { - ModuleNode moduleNode = (ModuleNode) node; - for (ClassNode classNode : moduleNode.getClasses()) { - visitClass(classNode); - } - } - } - } - - @Override - public void visitMethodCallExpression(MethodCallExpression call) { - transformer.visitMethodCallExpression(call); - super.visitMethodCallExpression(call); - } - @Override - protected SourceUnit getSourceUnit() { - return source; + protected GroovyCodeVisitor getTransformer(ASTNode[] nodes, SourceUnit sourceUnit) { + return new MacroInvocationTrap(sourceUnit.getSource(), sourceUnit); } }