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 2017/12/14 21:57:03 UTC

[38/57] [abbrv] [partial] groovy git commit: Move Java source set into `src/main/java`

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/AnnotationNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/AnnotationNode.java b/src/main/java/org/codehaus/groovy/ast/AnnotationNode.java
new file mode 100644
index 0000000..c493299
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/AnnotationNode.java
@@ -0,0 +1,189 @@
+/*
+ *  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.ast;
+
+import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.ast.expr.Expression;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Represents an annotation which can be attached to interfaces, classes, methods and fields.
+ */
+public class AnnotationNode extends ASTNode {
+    public static final int CONSTRUCTOR_TARGET = 1 << 1;
+    public static final int METHOD_TARGET = 1 << 2;
+    public static final int FIELD_TARGET = 1 << 3;
+    public static final int PARAMETER_TARGET =  1 << 4;
+    public static final int LOCAL_VARIABLE_TARGET = 1 << 5;
+    public static final int ANNOTATION_TARGET = 1 << 6;
+    public static final int PACKAGE_TARGET = 1 << 7;
+    public static final int TYPE_PARAMETER_TARGET = 1 << 8;
+    public static final int TYPE_USE_TARGET = 1 << 9;
+    public static final int TYPE_TARGET = 1 + ANNOTATION_TARGET;    //GROOVY-7151
+    private static final int ALL_TARGETS = TYPE_TARGET | CONSTRUCTOR_TARGET | METHOD_TARGET
+            | FIELD_TARGET | PARAMETER_TARGET | LOCAL_VARIABLE_TARGET | ANNOTATION_TARGET
+            | PACKAGE_TARGET | TYPE_PARAMETER_TARGET | TYPE_USE_TARGET;
+
+    private final ClassNode classNode;
+    private Map<String, Expression> members;
+    private boolean runtimeRetention= false, sourceRetention= false, classRetention = false;
+    private int allowedTargets = ALL_TARGETS;
+
+    public AnnotationNode(ClassNode classNode) {
+        this.classNode = classNode;
+    }
+
+    public ClassNode getClassNode() {
+        return classNode;
+    }
+
+    public Map<String, Expression> getMembers() {
+        if (members == null) {
+            return Collections.emptyMap();
+        }
+        return members;
+    }
+    
+    public Expression getMember(String name) {
+        if (members == null) {
+            return null;
+        }
+        return members.get(name);
+    }
+
+    private void assertMembers() {
+        if (members == null) {
+             members = new LinkedHashMap<String, Expression>();
+        }
+    }
+
+    public void addMember(String name, Expression value) {
+        assertMembers();
+        Expression oldValue = members.get(name);
+        if (oldValue == null) {
+            members.put(name, value);
+        }
+        else {
+            throw new GroovyBugError(String.format("Annotation member %s has already been added", name));
+        }
+    }
+
+    public void setMember(String name, Expression value) {
+        assertMembers();
+        members.put(name, value);
+    }
+    
+    public boolean isBuiltIn(){
+        return false;
+    }
+
+    /**
+     * Flag corresponding to <code>RetentionPolicy</code>.
+     * @return <tt>true</tt> if the annotation should be visible at runtime, 
+     *      <tt>false</tt> otherwise
+     */
+    public boolean hasRuntimeRetention() {
+        return this.runtimeRetention;
+    }
+
+    /**
+     * Sets the internal flag of this annotation runtime retention policy.
+     * If the current annotation has 
+     * <code>RetentionPolicy.RUNTIME</code> or if <tt>false</tt>
+     * if the <code>RetentionPolicy.CLASS</code>.
+     * @param flag if <tt>true</tt> then current annotation is marked as having
+     *     <code>RetentionPolicy.RUNTIME</code>. If <tt>false</tt> then
+     *     the annotation has <code>RetentionPolicy.CLASS</code>.
+     */
+    public void setRuntimeRetention(boolean flag) {
+        this.runtimeRetention = flag;
+    }
+    
+    /**
+     * Flag corresponding to <code>RetentionPolicy.SOURCE</code>.
+     * @return <tt>true</tt> if the annotation is only allowed in sources 
+     *      <tt>false</tt> otherwise
+     */
+    public boolean hasSourceRetention() {
+        if (!runtimeRetention && !classRetention) return true;
+        return this.sourceRetention;
+    }
+
+    /** Sets the internal flag if the current annotation has 
+     * <code>RetentionPolicy.SOURCE</code>.
+     */ 
+    public void setSourceRetention(boolean flag) {
+        this.sourceRetention = flag;
+    }
+
+    /**
+     * Flag corresponding to <code>RetentionPolicy.CLASS</code>.
+     * @return <tt>true</tt> if the annotation is recorded by the compiler,
+     *                       but not visible at runtime     *
+      *        <tt>false</tt> otherwise
+     */
+    public boolean hasClassRetention() {
+        return this.classRetention;
+    }
+
+    /** Sets the internal flag if the current annotation has
+     * <code>RetentionPolicy.CLASS</code>.
+     */
+    public void setClassRetention(boolean flag) {
+        this.classRetention = flag;
+    }
+
+    public void setAllowedTargets(int bitmap) {
+        this.allowedTargets = bitmap;
+    }
+    
+    public boolean isTargetAllowed(int target) {
+        return (this.allowedTargets & target) == target;
+    }
+    
+    public static String targetToName(int target) {
+        switch(target) {
+            case TYPE_TARGET:
+                return "TYPE";
+            case CONSTRUCTOR_TARGET:
+                return "CONSTRUCTOR";
+            case METHOD_TARGET:
+                return "METHOD";
+            case FIELD_TARGET:
+                return "FIELD";
+            case PARAMETER_TARGET:
+                return "PARAMETER";
+            case LOCAL_VARIABLE_TARGET:
+                return "LOCAL_VARIABLE";
+            case ANNOTATION_TARGET:
+                return "ANNOTATION";
+            case PACKAGE_TARGET:
+                return "PACKAGE";
+            case TYPE_PARAMETER_TARGET:
+                return "TYPE_PARAMETER";
+            case TYPE_USE_TARGET:
+                return "TYPE_USE";
+            default:
+                return "unknown target";
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/AstToTextHelper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/AstToTextHelper.java b/src/main/java/org/codehaus/groovy/ast/AstToTextHelper.java
new file mode 100644
index 0000000..3599fbf
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/AstToTextHelper.java
@@ -0,0 +1,111 @@
+/*
+ *  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.ast;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Helper class for converting AST into text.
+ * @author Hamlet D'Arcy
+ */
+public class AstToTextHelper {
+
+    public static String getClassText(ClassNode node) {
+        if (node == null) return "<unknown>";
+        if (node.getName() == null) return "<unknown>";
+        return node.getName();
+    }
+
+    public static String getParameterText(Parameter node) {
+        if (node == null) return "<unknown>";
+
+        String name = node.getName() == null ? "<unknown>" : node.getName();
+        String type = getClassText(node.getType());
+        if (node.getInitialExpression() != null) {
+            return type + " " + name + " = " + node.getInitialExpression().getText();
+        }
+        return type + " " + name;
+    }
+
+    public static String getParametersText(Parameter[] parameters) {
+        if (parameters == null) return "";
+        if (parameters.length == 0) return "";
+        StringBuilder result = new StringBuilder();
+        int max = parameters.length;
+        for (int x = 0; x < max; x++) {
+            result.append(getParameterText(parameters[x]));
+            if (x < (max - 1)) {
+                result.append(", ");
+            }
+        }
+        return result.toString();
+    }
+
+    public static String getThrowsClauseText(ClassNode[] exceptions) {
+        if (exceptions == null) return "";
+        if (exceptions.length == 0) return "";
+        StringBuilder result = new StringBuilder("throws ");
+        int max = exceptions.length;
+        for (int x = 0; x < max; x++) {
+            result.append(getClassText(exceptions[x]));
+            if (x < (max - 1)) {
+                result.append(", "); 
+            }
+        }
+        return result.toString(); 
+    }
+
+    public static String getModifiersText(int modifiers) {
+        StringBuilder result = new StringBuilder();
+        if (Modifier.isPrivate(modifiers)) {
+            result.append("private ");
+        }
+        if (Modifier.isProtected(modifiers)) {
+            result.append("protected ");
+        }
+        if (Modifier.isPublic(modifiers)) {
+            result.append("public ");
+        }
+        if (Modifier.isStatic(modifiers)) {
+            result.append("static ");
+        }
+        if (Modifier.isAbstract(modifiers)) {
+            result.append("abstract ");
+        }
+        if (Modifier.isFinal(modifiers)) {
+            result.append("final ");
+        }
+        if (Modifier.isInterface(modifiers)) {
+            result.append("interface ");
+        }
+        if (Modifier.isNative(modifiers)) {
+            result.append("native ");
+        }
+        if (Modifier.isSynchronized(modifiers)) {
+            result.append("synchronized ");
+        }
+        if (Modifier.isTransient(modifiers)) {
+            result.append("transient ");
+        }
+        if (Modifier.isVolatile(modifiers)) {
+            result.append("volatile ");
+        }
+        return result.toString().trim();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java b/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java
new file mode 100644
index 0000000..06ef44d
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/ClassCodeExpressionTransformer.java
@@ -0,0 +1,146 @@
+/*
+ *  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.ast;
+
+import org.codehaus.groovy.ast.expr.BooleanExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.ExpressionTransformer;
+import org.codehaus.groovy.ast.stmt.AssertStatement;
+import org.codehaus.groovy.ast.stmt.CaseStatement;
+import org.codehaus.groovy.ast.stmt.DoWhileStatement;
+import org.codehaus.groovy.ast.stmt.ExpressionStatement;
+import org.codehaus.groovy.ast.stmt.ForStatement;
+import org.codehaus.groovy.ast.stmt.IfStatement;
+import org.codehaus.groovy.ast.stmt.ReturnStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.ast.stmt.SwitchStatement;
+import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
+import org.codehaus.groovy.ast.stmt.ThrowStatement;
+import org.codehaus.groovy.ast.stmt.WhileStatement;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Visitor to transform expressions in a whole class.
+ * Transformed Expressions are usually not visited.
+ *
+ * @author Jochen Theodorou
+ */
+public abstract class ClassCodeExpressionTransformer extends ClassCodeVisitorSupport implements ExpressionTransformer {
+
+    protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
+        for (Parameter p : node.getParameters()) {
+            if (p.hasInitialExpression()) {
+                Expression init = p.getInitialExpression();
+                p.setInitialExpression(transform(init));
+            }
+        }
+        super.visitConstructorOrMethod(node, isConstructor);
+    }
+
+    public void visitSwitch(SwitchStatement statement) {
+        Expression exp = statement.getExpression();
+        statement.setExpression(transform(exp));
+        for (CaseStatement caseStatement : statement.getCaseStatements()) {
+            caseStatement.visit(this);
+        }
+        statement.getDefaultStatement().visit(this);
+    }
+
+    public void visitField(FieldNode node) {
+        visitAnnotations(node);
+        Expression init = node.getInitialExpression();
+        node.setInitialValueExpression(transform(init));
+    }
+
+    public void visitProperty(PropertyNode node) {
+        visitAnnotations(node);
+        Statement statement = node.getGetterBlock();
+        visitClassCodeContainer(statement);
+
+        statement = node.getSetterBlock();
+        visitClassCodeContainer(statement);
+    }
+
+    public void visitIfElse(IfStatement ifElse) {
+        ifElse.setBooleanExpression((BooleanExpression) (transform(ifElse.getBooleanExpression())));
+        ifElse.getIfBlock().visit(this);
+        ifElse.getElseBlock().visit(this);
+    }
+
+    public Expression transform(Expression exp) {
+        if (exp == null) return null;
+        return exp.transformExpression(this);
+    }
+
+    public void visitAnnotations(AnnotatedNode node) {
+        List<AnnotationNode> annotations = node.getAnnotations();
+        if (annotations.isEmpty()) return;
+        for (AnnotationNode an : annotations) {
+            // skip built-in properties
+            if (an.isBuiltIn()) continue;
+            for (Map.Entry<String, Expression> member : an.getMembers().entrySet()) {
+                member.setValue(transform(member.getValue()));
+            }
+        }
+    }
+
+    public void visitReturnStatement(ReturnStatement statement) {
+        statement.setExpression(transform(statement.getExpression()));
+    }
+
+    public void visitAssertStatement(AssertStatement as) {
+        as.setBooleanExpression((BooleanExpression) (transform(as.getBooleanExpression())));
+        as.setMessageExpression(transform(as.getMessageExpression()));
+    }
+
+    public void visitCaseStatement(CaseStatement statement) {
+        statement.setExpression(transform(statement.getExpression()));
+        statement.getCode().visit(this);
+    }
+
+    public void visitDoWhileLoop(DoWhileStatement loop) {
+        loop.setBooleanExpression((BooleanExpression) (transform(loop.getBooleanExpression())));
+        super.visitDoWhileLoop(loop);
+    }
+
+    public void visitForLoop(ForStatement forLoop) {
+        forLoop.setCollectionExpression(transform(forLoop.getCollectionExpression()));
+        super.visitForLoop(forLoop);
+    }
+
+    public void visitSynchronizedStatement(SynchronizedStatement sync) {
+        sync.setExpression(transform(sync.getExpression()));
+        super.visitSynchronizedStatement(sync);
+    }
+
+    public void visitThrowStatement(ThrowStatement ts) {
+        ts.setExpression(transform(ts.getExpression()));
+    }
+
+    public void visitWhileLoop(WhileStatement loop) {
+        loop.setBooleanExpression((BooleanExpression) transform(loop.getBooleanExpression()));
+        super.visitWhileLoop(loop);
+    }
+
+    public void visitExpressionStatement(ExpressionStatement es) {
+        es.setExpression(transform(es.getExpression()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java b/src/main/java/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
new file mode 100644
index 0000000..378d2be
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
@@ -0,0 +1,239 @@
+/*
+ *  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.ast;
+
+import org.codehaus.groovy.ast.expr.DeclarationExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.stmt.AssertStatement;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.BreakStatement;
+import org.codehaus.groovy.ast.stmt.CaseStatement;
+import org.codehaus.groovy.ast.stmt.CatchStatement;
+import org.codehaus.groovy.ast.stmt.ContinueStatement;
+import org.codehaus.groovy.ast.stmt.DoWhileStatement;
+import org.codehaus.groovy.ast.stmt.ExpressionStatement;
+import org.codehaus.groovy.ast.stmt.ForStatement;
+import org.codehaus.groovy.ast.stmt.IfStatement;
+import org.codehaus.groovy.ast.stmt.ReturnStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.ast.stmt.SwitchStatement;
+import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
+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.control.SourceUnit;
+import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
+import org.codehaus.groovy.syntax.SyntaxException;
+import org.codehaus.groovy.transform.ErrorCollecting;
+
+import java.util.List;
+import java.util.Map;
+
+public abstract class ClassCodeVisitorSupport extends CodeVisitorSupport implements ErrorCollecting, GroovyClassVisitor {
+
+    public void visitClass(ClassNode node) {
+        visitAnnotations(node);
+        visitPackage(node.getPackage());
+        visitImports(node.getModule());
+        node.visitContents(this);
+        visitObjectInitializerStatements(node);
+    }
+    
+    protected void visitObjectInitializerStatements(ClassNode node) {
+        for (Statement element : node.getObjectInitializerStatements()) {
+            element.visit(this);
+        }
+    }
+
+    public void visitPackage(PackageNode node) {
+        if (node != null) {
+            visitAnnotations(node);
+            node.visit(this);
+        }
+    }
+
+    public void visitImports(ModuleNode node) {
+        if (node != null) {
+            for (ImportNode importNode : node.getImports()) {
+                visitAnnotations(importNode);
+                importNode.visit(this);
+            }
+            for (ImportNode importStarNode : node.getStarImports()) {
+                visitAnnotations(importStarNode);
+                importStarNode.visit(this);
+            }
+            for (ImportNode importStaticNode : node.getStaticImports().values()) {
+                visitAnnotations(importStaticNode);
+                importStaticNode.visit(this);
+            }
+            for (ImportNode importStaticStarNode : node.getStaticStarImports().values()) {
+                visitAnnotations(importStaticStarNode);
+                importStaticStarNode.visit(this);
+            }
+        }
+    }
+
+    public void visitAnnotations(AnnotatedNode node) {
+        List<AnnotationNode> annotations = node.getAnnotations();
+        if (annotations.isEmpty()) return;
+        for (AnnotationNode an : annotations) {
+            // skip built-in properties
+            if (an.isBuiltIn()) continue;
+            for (Map.Entry<String, Expression> member : an.getMembers().entrySet()) {
+                member.getValue().visit(this);
+            }
+        }
+    }
+
+    public void visitBlockStatement(BlockStatement block) {
+        visitStatement(block);
+        super.visitBlockStatement(block);
+    }
+
+    protected void visitClassCodeContainer(Statement code) {
+        if (code != null) code.visit(this);
+    }
+
+    @Override
+    public void visitDeclarationExpression(DeclarationExpression expression) {
+        visitAnnotations(expression);
+        super.visitDeclarationExpression(expression);
+    }
+
+    protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
+        visitAnnotations(node);
+        visitClassCodeContainer(node.getCode());
+        for (Parameter param : node.getParameters()) {
+            visitAnnotations(param);
+        }
+    }
+
+    public void visitConstructor(ConstructorNode node) {
+        visitConstructorOrMethod(node, true);
+    }
+
+    public void visitMethod(MethodNode node) {
+        visitConstructorOrMethod(node, false);
+    }
+
+    public void visitField(FieldNode node) {
+        visitAnnotations(node);
+        Expression init = node.getInitialExpression();
+        if (init != null) init.visit(this);
+    }
+
+    public void visitProperty(PropertyNode node) {
+        visitAnnotations(node);
+        Statement statement = node.getGetterBlock();
+        visitClassCodeContainer(statement);
+
+        statement = node.getSetterBlock();
+        visitClassCodeContainer(statement);
+
+        Expression init = node.getInitialExpression();
+        if (init != null) init.visit(this);
+    }
+
+    public void addError(String msg, ASTNode expr) {
+        SourceUnit source = getSourceUnit();
+        source.getErrorCollector().addErrorAndContinue(
+                new SyntaxErrorMessage(new SyntaxException(msg + '\n', expr.getLineNumber(), expr.getColumnNumber(), expr.getLastLineNumber(), expr.getLastColumnNumber()), source)
+        );
+    }
+
+    protected abstract SourceUnit getSourceUnit();
+
+    protected void visitStatement(Statement statement) {
+    }
+
+    public void visitAssertStatement(AssertStatement statement) {
+        visitStatement(statement);
+        super.visitAssertStatement(statement);
+    }
+
+    public void visitBreakStatement(BreakStatement statement) {
+        visitStatement(statement);
+        super.visitBreakStatement(statement);
+    }
+
+    public void visitCaseStatement(CaseStatement statement) {
+        visitStatement(statement);
+        super.visitCaseStatement(statement);
+    }
+
+    public void visitCatchStatement(CatchStatement statement) {
+        visitStatement(statement);
+        super.visitCatchStatement(statement);
+    }
+
+    public void visitContinueStatement(ContinueStatement statement) {
+        visitStatement(statement);
+        super.visitContinueStatement(statement);
+    }
+
+    public void visitDoWhileLoop(DoWhileStatement loop) {
+        visitStatement(loop);
+        super.visitDoWhileLoop(loop);
+    }
+
+    public void visitExpressionStatement(ExpressionStatement statement) {
+        visitStatement(statement);
+        super.visitExpressionStatement(statement);
+    }
+
+    public void visitForLoop(ForStatement forLoop) {
+        visitStatement(forLoop);
+        super.visitForLoop(forLoop);
+    }
+
+    public void visitIfElse(IfStatement ifElse) {
+        visitStatement(ifElse);
+        super.visitIfElse(ifElse);
+    }
+
+    public void visitReturnStatement(ReturnStatement statement) {
+        visitStatement(statement);
+        super.visitReturnStatement(statement);
+    }
+
+    public void visitSwitch(SwitchStatement statement) {
+        visitStatement(statement);
+        super.visitSwitch(statement);
+    }
+
+    public void visitSynchronizedStatement(SynchronizedStatement statement) {
+        visitStatement(statement);
+        super.visitSynchronizedStatement(statement);
+    }
+
+    public void visitThrowStatement(ThrowStatement statement) {
+        visitStatement(statement);
+        super.visitThrowStatement(statement);
+    }
+
+    public void visitTryCatchFinally(TryCatchStatement statement) {
+        visitStatement(statement);
+        super.visitTryCatchFinally(statement);
+    }
+
+    public void visitWhileLoop(WhileStatement loop) {
+        visitStatement(loop);
+        super.visitWhileLoop(loop);
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/b25d0e55/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
new file mode 100644
index 0000000..60eaa47
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
@@ -0,0 +1,481 @@
+/*
+ *  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.ast;
+
+import groovy.lang.Binding;
+import groovy.lang.Closure;
+import groovy.lang.GString;
+import groovy.lang.GroovyInterceptable;
+import groovy.lang.GroovyObject;
+import groovy.lang.GroovyObjectSupport;
+import groovy.lang.MetaClass;
+import groovy.lang.Range;
+import groovy.lang.Reference;
+import groovy.lang.Script;
+import org.codehaus.groovy.runtime.GeneratedClosure;
+import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
+import org.codehaus.groovy.transform.trait.Traits;
+import org.codehaus.groovy.util.ManagedConcurrentMap;
+import org.codehaus.groovy.util.ReferenceBundle;
+import org.codehaus.groovy.vmplugin.VMPluginFactory;
+import org.objectweb.asm.Opcodes;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * This class is a Helper for ClassNode and classes handling ClassNodes.
+ * It does contain a set of predefined ClassNodes for the most used
+ * types and some code for cached ClassNode creation and basic
+ * ClassNode handling
+ */
+public class ClassHelper {
+
+    private static final Class[] classes = new Class[]{
+            Object.class, Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE,
+            Integer.TYPE, Long.TYPE, Double.TYPE, Float.TYPE, Void.TYPE,
+            Closure.class, GString.class, List.class, Map.class, Range.class,
+            Pattern.class, Script.class, String.class, Boolean.class,
+            Character.class, Byte.class, Short.class, Integer.class, Long.class,
+            Double.class, Float.class, BigDecimal.class, BigInteger.class,
+            Number.class, Void.class, Reference.class, Class.class, MetaClass.class,
+            Iterator.class, GeneratedClosure.class, GroovyObjectSupport.class
+    };
+
+    private static final String[] primitiveClassNames = new String[]{
+            "", "boolean", "char", "byte", "short",
+            "int", "long", "double", "float", "void"
+    };
+
+    public static final ClassNode
+            DYNAMIC_TYPE = makeCached(Object.class), OBJECT_TYPE = DYNAMIC_TYPE,
+            VOID_TYPE = makeCached(Void.TYPE), CLOSURE_TYPE = makeCached(Closure.class),
+            GSTRING_TYPE = makeCached(GString.class), LIST_TYPE = makeWithoutCaching(List.class),
+            MAP_TYPE = makeWithoutCaching(Map.class), RANGE_TYPE = makeCached(Range.class),
+            PATTERN_TYPE = makeCached(Pattern.class), STRING_TYPE = makeCached(String.class),
+            SCRIPT_TYPE = makeCached(Script.class), REFERENCE_TYPE = makeWithoutCaching(Reference.class),
+            BINDING_TYPE = makeCached(Binding.class),
+
+    boolean_TYPE = makeCached(boolean.class), char_TYPE = makeCached(char.class),
+            byte_TYPE = makeCached(byte.class), int_TYPE = makeCached(int.class),
+            long_TYPE = makeCached(long.class), short_TYPE = makeCached(short.class),
+            double_TYPE = makeCached(double.class), float_TYPE = makeCached(float.class),
+            Byte_TYPE = makeCached(Byte.class), Short_TYPE = makeCached(Short.class),
+            Integer_TYPE = makeCached(Integer.class), Long_TYPE = makeCached(Long.class),
+            Character_TYPE = makeCached(Character.class), Float_TYPE = makeCached(Float.class),
+            Double_TYPE = makeCached(Double.class), Boolean_TYPE = makeCached(Boolean.class),
+            BigInteger_TYPE = makeCached(java.math.BigInteger.class),
+            BigDecimal_TYPE = makeCached(java.math.BigDecimal.class),
+            Number_TYPE = makeCached(Number.class),
+
+    void_WRAPPER_TYPE = makeCached(Void.class), METACLASS_TYPE = makeCached(MetaClass.class),
+            Iterator_TYPE = makeCached(Iterator.class),
+
+    Enum_Type = makeWithoutCaching(Enum.class),
+            Annotation_TYPE = makeCached(Annotation.class),
+            ELEMENT_TYPE_TYPE = makeCached(ElementType.class),
+
+    // uncached constants.
+    CLASS_Type = makeWithoutCaching(Class.class), COMPARABLE_TYPE = makeWithoutCaching(Comparable.class),
+            GENERATED_CLOSURE_Type = makeWithoutCaching(GeneratedClosure.class),
+            GROOVY_OBJECT_SUPPORT_TYPE = makeWithoutCaching(GroovyObjectSupport.class),
+            GROOVY_OBJECT_TYPE = makeWithoutCaching(GroovyObject.class),
+            GROOVY_INTERCEPTABLE_TYPE = makeWithoutCaching(GroovyInterceptable.class);
+
+    private static final ClassNode[] types = new ClassNode[]{
+            OBJECT_TYPE,
+            boolean_TYPE, char_TYPE, byte_TYPE, short_TYPE,
+            int_TYPE, long_TYPE, double_TYPE, float_TYPE,
+            VOID_TYPE, CLOSURE_TYPE, GSTRING_TYPE,
+            LIST_TYPE, MAP_TYPE, RANGE_TYPE, PATTERN_TYPE,
+            SCRIPT_TYPE, STRING_TYPE, Boolean_TYPE, Character_TYPE,
+            Byte_TYPE, Short_TYPE, Integer_TYPE, Long_TYPE,
+            Double_TYPE, Float_TYPE, BigDecimal_TYPE, BigInteger_TYPE,
+            Number_TYPE,
+            void_WRAPPER_TYPE, REFERENCE_TYPE, CLASS_Type, METACLASS_TYPE,
+            Iterator_TYPE, GENERATED_CLOSURE_Type, GROOVY_OBJECT_SUPPORT_TYPE,
+            GROOVY_OBJECT_TYPE, GROOVY_INTERCEPTABLE_TYPE, Enum_Type, Annotation_TYPE
+    };
+
+    private static final int ABSTRACT_STATIC_PRIVATE =
+            Modifier.ABSTRACT | Modifier.PRIVATE | Modifier.STATIC;
+    private static final int VISIBILITY = 5; // public|protected
+
+    protected static final ClassNode[] EMPTY_TYPE_ARRAY = {};
+
+    public static final String OBJECT = "java.lang.Object";
+
+    public static ClassNode makeCached(Class c) {
+        final SoftReference<ClassNode> classNodeSoftReference = ClassHelperCache.classCache.get(c);
+        ClassNode classNode;
+        if (classNodeSoftReference == null || (classNode = classNodeSoftReference.get()) == null) {
+            classNode = new ClassNode(c);
+            ClassHelperCache.classCache.put(c, new SoftReference<ClassNode>(classNode));
+
+            VMPluginFactory.getPlugin().setAdditionalClassInformation(classNode);
+        }
+
+        return classNode;
+    }
+
+    /**
+     * Creates an array of ClassNodes using an array of classes.
+     * For each of the given classes a new ClassNode will be
+     * created
+     *
+     * @param classes an array of classes used to create the ClassNodes
+     * @return an array of ClassNodes
+     * @see #make(Class)
+     */
+    public static ClassNode[] make(Class[] classes) {
+        ClassNode[] cns = new ClassNode[classes.length];
+        for (int i = 0; i < cns.length; i++) {
+            cns[i] = make(classes[i]);
+        }
+
+        return cns;
+    }
+
+    /**
+     * Creates a ClassNode using a given class.
+     * A new ClassNode object is only created if the class
+     * is not one of the predefined ones
+     *
+     * @param c class used to created the ClassNode
+     * @return ClassNode instance created from the given class
+     */
+    public static ClassNode make(Class c) {
+        return make(c, true);
+    }
+
+    public static ClassNode make(Class c, boolean includeGenerics) {
+        for (int i = 0; i < classes.length; i++) {
+            if (c == classes[i]) return types[i];
+        }
+        if (c.isArray()) {
+            ClassNode cn = make(c.getComponentType(), includeGenerics);
+            return cn.makeArray();
+        }
+        return makeWithoutCaching(c, includeGenerics);
+    }
+
+    public static ClassNode makeWithoutCaching(Class c) {
+        return makeWithoutCaching(c, true);
+    }
+
+    public static ClassNode makeWithoutCaching(Class c, boolean includeGenerics) {
+        if (c.isArray()) {
+            ClassNode cn = makeWithoutCaching(c.getComponentType(), includeGenerics);
+            return cn.makeArray();
+        }
+
+        final ClassNode cached = makeCached(c);
+        if (includeGenerics) {
+            return cached;
+        } else {
+            ClassNode t = makeWithoutCaching(c.getName());
+            t.setRedirect(cached);
+            return t;
+        }
+    }
+
+
+    /**
+     * Creates a ClassNode using a given class.
+     * Unlike make(String) this method will not use the cache
+     * to create the ClassNode. This means the ClassNode created
+     * from this method using the same name will have a different
+     * reference
+     *
+     * @param name of the class the ClassNode is representing
+     * @see #make(String)
+     */
+    public static ClassNode makeWithoutCaching(String name) {
+        ClassNode cn = new ClassNode(name, Opcodes.ACC_PUBLIC, OBJECT_TYPE);
+        cn.isPrimaryNode = false;
+        return cn;
+    }
+
+    /**
+     * Creates a ClassNode using a given class.
+     * If the name is one of the predefined ClassNodes then the
+     * corresponding ClassNode instance will be returned. If the
+     * name is null or of length 0 the dynamic type is returned
+     *
+     * @param name of the class the ClassNode is representing
+     */
+    public static ClassNode make(String name) {
+        if (name == null || name.length() == 0) return DYNAMIC_TYPE;
+
+        for (int i = 0; i < primitiveClassNames.length; i++) {
+            if (primitiveClassNames[i].equals(name)) return types[i];
+        }
+
+        for (int i = 0; i < classes.length; i++) {
+            String cname = classes[i].getName();
+            if (name.equals(cname)) return types[i];
+        }
+        return makeWithoutCaching(name);
+    }
+
+    /**
+     * Creates a ClassNode containing the wrapper of a ClassNode
+     * of primitive type. Any ClassNode representing a primitive
+     * type should be created using the predefined types used in
+     * class. The method will check the parameter for known
+     * references of ClassNode representing a primitive type. If
+     * Reference is found, then a ClassNode will be contained that
+     * represents the wrapper class. For example for boolean, the
+     * wrapper class is java.lang.Boolean.
+     * <p>
+     * If the parameter is no primitive type, the redirected
+     * ClassNode will be returned
+     *
+     * @param cn the ClassNode containing a possible primitive type
+     * @see #make(Class)
+     * @see #make(String)
+     */
+    public static ClassNode getWrapper(ClassNode cn) {
+        cn = cn.redirect();
+        if (!isPrimitiveType(cn)) return cn;
+        if (cn == boolean_TYPE) {
+            return Boolean_TYPE;
+        } else if (cn == byte_TYPE) {
+            return Byte_TYPE;
+        } else if (cn == char_TYPE) {
+            return Character_TYPE;
+        } else if (cn == short_TYPE) {
+            return Short_TYPE;
+        } else if (cn == int_TYPE) {
+            return Integer_TYPE;
+        } else if (cn == long_TYPE) {
+            return Long_TYPE;
+        } else if (cn == float_TYPE) {
+            return Float_TYPE;
+        } else if (cn == double_TYPE) {
+            return Double_TYPE;
+        } else if (cn == VOID_TYPE) {
+            return void_WRAPPER_TYPE;
+        } else {
+            return cn;
+        }
+    }
+
+    public static ClassNode getUnwrapper(ClassNode cn) {
+        cn = cn.redirect();
+        if (isPrimitiveType(cn)) return cn;
+        if (cn == Boolean_TYPE) {
+            return boolean_TYPE;
+        } else if (cn == Byte_TYPE) {
+            return byte_TYPE;
+        } else if (cn == Character_TYPE) {
+            return char_TYPE;
+        } else if (cn == Short_TYPE) {
+            return short_TYPE;
+        } else if (cn == Integer_TYPE) {
+            return int_TYPE;
+        } else if (cn == Long_TYPE) {
+            return long_TYPE;
+        } else if (cn == Float_TYPE) {
+            return float_TYPE;
+        } else if (cn == Double_TYPE) {
+            return double_TYPE;
+        } else {
+            return cn;
+        }
+    }
+
+
+    /**
+     * Test to determine if a ClassNode is a primitive type.
+     * Note: this only works for ClassNodes created using a
+     * predefined ClassNode
+     *
+     * @param cn the ClassNode containing a possible primitive type
+     * @return true if the ClassNode is a primitive type
+     * @see #make(Class)
+     * @see #make(String)
+     */
+    public static boolean isPrimitiveType(ClassNode cn) {
+        return cn == boolean_TYPE ||
+                cn == char_TYPE ||
+                cn == byte_TYPE ||
+                cn == short_TYPE ||
+                cn == int_TYPE ||
+                cn == long_TYPE ||
+                cn == float_TYPE ||
+                cn == double_TYPE ||
+                cn == VOID_TYPE;
+    }
+
+    /**
+     * Test to determine if a ClassNode is a type belongs to the list of types which
+     * are allowed to initialize constants directly in bytecode instead of using &lt;cinit&gt;
+     * <p>
+     * Note: this only works for ClassNodes created using a
+     * predefined ClassNode
+     *
+     * @param cn the ClassNode to be tested
+     * @return true if the ClassNode is of int, float, long, double or String type
+     * @see #make(Class)
+     * @see #make(String)
+     */
+    public static boolean isStaticConstantInitializerType(ClassNode cn) {
+        return cn == int_TYPE ||
+                cn == float_TYPE ||
+                cn == long_TYPE ||
+                cn == double_TYPE ||
+                cn == STRING_TYPE ||
+                // the next items require conversion to int when initializing
+                cn == byte_TYPE ||
+                cn == char_TYPE ||
+                cn == short_TYPE;
+    }
+
+    public static boolean isNumberType(ClassNode cn) {
+        return cn == Byte_TYPE ||
+                cn == Short_TYPE ||
+                cn == Integer_TYPE ||
+                cn == Long_TYPE ||
+                cn == Float_TYPE ||
+                cn == Double_TYPE ||
+                cn == byte_TYPE ||
+                cn == short_TYPE ||
+                cn == int_TYPE ||
+                cn == long_TYPE ||
+                cn == float_TYPE ||
+                cn == double_TYPE;
+    }
+
+    public static ClassNode makeReference() {
+        return REFERENCE_TYPE.getPlainNodeReference();
+    }
+
+    public static boolean isCachedType(ClassNode type) {
+        for (ClassNode cachedType : types) {
+            if (cachedType == type) return true;
+        }
+        return false;
+    }
+
+    static class ClassHelperCache {
+        static ManagedConcurrentMap<Class, SoftReference<ClassNode>> classCache = new ManagedConcurrentMap<Class, SoftReference<ClassNode>>(ReferenceBundle.getWeakBundle());
+    }
+
+    public static boolean isSAMType(ClassNode type) {
+        return findSAM(type) != null;
+    }
+
+    /**
+     * Returns the single abstract method of a class node, if it is a SAM type, or null otherwise.
+     *
+     * @param type a type for which to search for a single abstract method
+     * @return the method node if type is a SAM type, null otherwise
+     */
+    public static MethodNode findSAM(ClassNode type) {
+        if (!Modifier.isAbstract(type.getModifiers())) return null;
+        if (type.isInterface()) {
+            List<MethodNode> methods = type.getMethods();
+            MethodNode found = null;
+            for (MethodNode mi : methods) {
+                // ignore methods, that are not abstract and from Object
+                if (!Modifier.isAbstract(mi.getModifiers())) continue;
+                // ignore trait methods which have a default implementation
+                if (Traits.hasDefaultImplementation(mi)) continue;
+                if (mi.getDeclaringClass().equals(OBJECT_TYPE)) continue;
+                if (OBJECT_TYPE.getDeclaredMethod(mi.getName(), mi.getParameters()) != null) continue;
+
+                // we have two methods, so no SAM
+                if (found != null) return null;
+                found = mi;
+            }
+            return found;
+
+        } else {
+
+            List<MethodNode> methods = type.getAbstractMethods();
+            MethodNode found = null;
+            if (methods != null) {
+                for (MethodNode mi : methods) {
+                    if (!hasUsableImplementation(type, mi)) {
+                        if (found != null) return null;
+                        found = mi;
+                    }
+                }
+            }
+            return found;
+        }
+    }
+
+    private static boolean hasUsableImplementation(ClassNode c, MethodNode m) {
+        if (c == m.getDeclaringClass()) return false;
+        MethodNode found = c.getDeclaredMethod(m.getName(), m.getParameters());
+        if (found == null) return false;
+        int asp = found.getModifiers() & ABSTRACT_STATIC_PRIVATE;
+        int visible = found.getModifiers() & VISIBILITY;
+        if (visible != 0 && asp == 0) return true;
+        if (c.equals(OBJECT_TYPE)) return false;
+        return hasUsableImplementation(c.getSuperClass(), m);
+    }
+
+    /**
+     * Returns a super class or interface for a given class depending on a given target.
+     * If the target is no super class or interface, then null will be returned.
+     * For a non-primitive array type, returns an array of the componentType's super class
+     * or interface if the target is also an array.
+     *
+     * @param clazz     the start class
+     * @param goalClazz the goal class
+     * @return the next super class or interface
+     */
+    public static ClassNode getNextSuperClass(ClassNode clazz, ClassNode goalClazz) {
+        if (clazz.isArray()) {
+            if (!goalClazz.isArray()) return null;
+            ClassNode cn = getNextSuperClass(clazz.getComponentType(), goalClazz.getComponentType());
+            if (cn != null) cn = cn.makeArray();
+            return cn;
+        }
+
+        if (!goalClazz.isInterface()) {
+            if (clazz.isInterface()) {
+                if (OBJECT_TYPE.equals(clazz)) return null;
+                return OBJECT_TYPE;
+            } else {
+                return clazz.getUnresolvedSuperClass();
+            }
+        }
+
+        ClassNode[] interfaces = clazz.getUnresolvedInterfaces();
+        for (ClassNode anInterface : interfaces) {
+            if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(anInterface, goalClazz)) {
+                return anInterface;
+            }
+        }
+        //none of the interfaces here match, so continue with super class
+        return clazz.getUnresolvedSuperClass();
+    }
+}