You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2019/12/22 08:57:19 UTC
[groovy] branch GROOVY_2_5_X updated: GROOVY-9352: Static
compilation fails with NoClassDefFoundError
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push:
new dc4678d GROOVY-9352: Static compilation fails with NoClassDefFoundError
dc4678d is described below
commit dc4678dbf8ab11a0f4487c594fb17a488466df5d
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Dec 22 16:56:11 2019 +0800
GROOVY-9352: Static compilation fails with NoClassDefFoundError
---
.../org/codehaus/groovy/ast/ConstructorNode.java | 1 +
.../java/org/codehaus/groovy/ast/FieldNode.java | 2 +
.../java/org/codehaus/groovy/ast/MethodNode.java | 8 +-
.../groovy/ast/decompiled/DecompiledClassNode.java | 60 ++-
.../groovy/ast/decompiled/LazyConstructorNode.java | 448 +++++++++++++++++++++
.../groovy/ast/decompiled/LazyFieldNode.java | 403 ++++++++++++++++++
.../groovy/ast/decompiled/LazyMethodNode.java | 444 ++++++++++++++++++++
.../test/groovy/groovy/ant/Groovy9352Test.groovy | 99 +++++
8 files changed, 1457 insertions(+), 8 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/ast/ConstructorNode.java b/src/main/java/org/codehaus/groovy/ast/ConstructorNode.java
index da9a87f..af1eef9 100644
--- a/src/main/java/org/codehaus/groovy/ast/ConstructorNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ConstructorNode.java
@@ -27,6 +27,7 @@ import org.codehaus.groovy.ast.stmt.Statement;
* Represents a constructor declaration
*/
public class ConstructorNode extends MethodNode {
+ protected ConstructorNode() {}
public ConstructorNode(int modifiers, Statement code) {
this(modifiers, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, code);
diff --git a/src/main/java/org/codehaus/groovy/ast/FieldNode.java b/src/main/java/org/codehaus/groovy/ast/FieldNode.java
index cae3dcf..db29623 100644
--- a/src/main/java/org/codehaus/groovy/ast/FieldNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/FieldNode.java
@@ -43,6 +43,8 @@ public class FieldNode extends AnnotatedNode implements Opcodes, Variable {
return new FieldNode(name, ACC_PUBLIC | ACC_STATIC, fldType, ClassHelper.make(theClass), null);
}
+ protected FieldNode() {}
+
public FieldNode(String name, int modifiers, ClassNode type, ClassNode owner, Expression initialValueExpression) {
this.name = name;
this.modifiers = modifiers;
diff --git a/src/main/java/org/codehaus/groovy/ast/MethodNode.java b/src/main/java/org/codehaus/groovy/ast/MethodNode.java
index fc1c05e..534057f 100644
--- a/src/main/java/org/codehaus/groovy/ast/MethodNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/MethodNode.java
@@ -31,7 +31,7 @@ import java.util.List;
public class MethodNode extends AnnotatedNode implements Opcodes {
public static final String SCRIPT_BODY_METHOD_KEY = "org.codehaus.groovy.ast.MethodNode.isScriptBody";
- private final String name;
+ private String name;
private int modifiers;
private boolean syntheticPublic;
private ClassNode returnType;
@@ -40,8 +40,8 @@ public class MethodNode extends AnnotatedNode implements Opcodes {
private Statement code;
private boolean dynamicReturnType;
private VariableScope variableScope;
- private final ClassNode[] exceptions;
- private final boolean staticConstructor;
+ private ClassNode[] exceptions;
+ private boolean staticConstructor;
// type spec for generics
private GenericsType[] genericsTypes = null;
@@ -50,6 +50,8 @@ public class MethodNode extends AnnotatedNode implements Opcodes {
// cached data
String typeDescriptor;
+ protected MethodNode() {}
+
public MethodNode(String name, int modifiers, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
this.name = name;
this.modifiers = modifiers;
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/DecompiledClassNode.java b/src/main/java/org/codehaus/groovy/ast/decompiled/DecompiledClassNode.java
index 8207070..c18f0d0 100644
--- a/src/main/java/org/codehaus/groovy/ast/decompiled/DecompiledClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/DecompiledClassNode.java
@@ -18,6 +18,7 @@
*/
package org.codehaus.groovy.ast.decompiled;
+import org.apache.groovy.internal.util.Supplier;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassNode;
@@ -27,6 +28,7 @@ import org.codehaus.groovy.ast.GenericsType;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.MixinNode;
import org.codehaus.groovy.classgen.Verifier;
+import org.objectweb.asm.Opcodes;
import java.lang.reflect.Modifier;
import java.util.List;
@@ -191,18 +193,17 @@ public class DecompiledClassNode extends ClassNode {
if (!membersInitialized) {
if (classData.methods != null) {
for (MethodStub method : classData.methods) {
- MethodNode node = addAnnotations(method, MemberSignatureParser.createMethodNode(resolver, method));
- if (node instanceof ConstructorNode) {
- addConstructor((ConstructorNode) node);
+ if (isConstructor(method)) {
+ addConstructor(createConstructor(method));
} else {
- addMethod(node);
+ addMethod(createMethodNode(method));
}
}
}
if (classData.fields != null) {
for (FieldStub field : classData.fields) {
- addField(addAnnotations(field, MemberSignatureParser.createFieldNode(field, resolver, this)));
+ addField(createFieldNode(field));
}
}
@@ -211,6 +212,55 @@ public class DecompiledClassNode extends ClassNode {
}
}
+ private FieldNode createFieldNode(final FieldStub field) {
+ Supplier<FieldNode> fieldNodeSupplier = new Supplier<FieldNode>() {
+ @Override
+ public FieldNode get() {
+ return addAnnotations(field, MemberSignatureParser.createFieldNode(field, resolver, DecompiledClassNode.this));
+ }
+ };
+
+ if ((field.accessModifiers & Opcodes.ACC_PRIVATE) != 0) {
+ return new LazyFieldNode(fieldNodeSupplier, field.fieldName);
+ }
+
+ return fieldNodeSupplier.get();
+ }
+
+ private MethodNode createMethodNode(final MethodStub method) {
+ Supplier<MethodNode> methodNodeSupplier = new Supplier<MethodNode>() {
+ @Override
+ public MethodNode get() {
+ return addAnnotations(method, MemberSignatureParser.createMethodNode(resolver, method));
+ }
+ };
+
+ if ((method.accessModifiers & Opcodes.ACC_PRIVATE) != 0) {
+ return new LazyMethodNode(methodNodeSupplier, method.methodName);
+ }
+
+ return methodNodeSupplier.get();
+ }
+
+ private ConstructorNode createConstructor(final MethodStub method) {
+ Supplier<ConstructorNode> constructorNodeSupplier = new Supplier<ConstructorNode>() {
+ @Override
+ public ConstructorNode get() {
+ return (ConstructorNode) addAnnotations(method, MemberSignatureParser.createMethodNode(resolver, method));
+ }
+ };
+
+ if ((method.accessModifiers & Opcodes.ACC_PRIVATE) != 0) {
+ return new LazyConstructorNode(constructorNodeSupplier);
+ }
+
+ return constructorNodeSupplier.get();
+ }
+
+ private boolean isConstructor(MethodStub method) {
+ return "<init>".equals(method.methodName);
+ }
+
private <T extends AnnotatedNode> T addAnnotations(MemberStub stub, T node) {
List<AnnotationStub> annotations = stub.annotations;
if (annotations != null) {
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/LazyConstructorNode.java b/src/main/java/org/codehaus/groovy/ast/decompiled/LazyConstructorNode.java
new file mode 100644
index 0000000..62418ce
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/LazyConstructorNode.java
@@ -0,0 +1,448 @@
+/*
+ * 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.decompiled;
+
+import org.apache.groovy.internal.util.Supplier;
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ConstructorNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.VariableScope;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.util.ListHashMap;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents lazy constructor node, which will be initialized only when accessed
+ *
+ * @since 2.5.9
+ */
+public class LazyConstructorNode extends ConstructorNode {
+ private final Supplier<ConstructorNode> constructorNodeSupplier;
+ private ConstructorNode delegate;
+ private boolean initialized;
+
+ public LazyConstructorNode(Supplier<ConstructorNode> constructorNodeSupplier) {
+ this.constructorNodeSupplier = constructorNodeSupplier;
+ }
+
+ private void init() {
+ if (initialized) return;
+ delegate = constructorNodeSupplier.get();
+
+ ClassNode declaringClass = super.getDeclaringClass();
+ if (null != declaringClass) delegate.setDeclaringClass(declaringClass);
+
+ initialized = true;
+ }
+
+ @Override
+ public boolean firstStatementIsSpecialConstructorCall() {
+ init();
+ return delegate.firstStatementIsSpecialConstructorCall();
+ }
+
+ @Override
+ public String getTypeDescriptor() {
+ init();
+ return delegate.getTypeDescriptor();
+ }
+
+ @Override
+ public boolean isVoidMethod() {
+ init();
+ return delegate.isVoidMethod();
+ }
+
+ @Override
+ public Statement getCode() {
+ init();
+ return delegate.getCode();
+ }
+
+ @Override
+ public void setCode(Statement code) {
+ init();
+ delegate.setCode(code);
+ }
+
+ @Override
+ public int getModifiers() {
+ init();
+ return delegate.getModifiers();
+ }
+
+ @Override
+ public void setModifiers(int modifiers) {
+ init();
+ delegate.setModifiers(modifiers);
+ }
+
+ @Override
+ public String getName() {
+ init();
+ return delegate.getName();
+ }
+
+ @Override
+ public Parameter[] getParameters() {
+ init();
+ return delegate.getParameters();
+ }
+
+ @Override
+ public void setParameters(Parameter[] parameters) {
+ init();
+ delegate.setParameters(parameters);
+ }
+
+ @Override
+ public ClassNode getReturnType() {
+ init();
+ return delegate.getReturnType();
+ }
+
+ @Override
+ public VariableScope getVariableScope() {
+ init();
+ return delegate.getVariableScope();
+ }
+
+ @Override
+ public void setVariableScope(VariableScope variableScope) {
+ init();
+ delegate.setVariableScope(variableScope);
+ }
+
+ @Override
+ public boolean isDynamicReturnType() {
+ init();
+ return delegate.isDynamicReturnType();
+ }
+
+ @Override
+ public boolean isAbstract() {
+ init();
+ return delegate.isAbstract();
+ }
+
+ @Override
+ public boolean isStatic() {
+ init();
+ return delegate.isStatic();
+ }
+
+ @Override
+ public boolean isPublic() {
+ init();
+ return delegate.isPublic();
+ }
+
+ @Override
+ public boolean isPrivate() {
+ init();
+ return delegate.isPrivate();
+ }
+
+ @Override
+ public boolean isFinal() {
+ init();
+ return delegate.isFinal();
+ }
+
+ @Override
+ public boolean isProtected() {
+ init();
+ return delegate.isProtected();
+ }
+
+ @Override
+ public boolean isPackageScope() {
+ init();
+ return delegate.isPackageScope();
+ }
+
+ @Override
+ public boolean hasDefaultValue() {
+ init();
+ return delegate.hasDefaultValue();
+ }
+
+ @Override
+ public boolean isScriptBody() {
+ init();
+ return delegate.isScriptBody();
+ }
+
+ @Override
+ public void setIsScriptBody() {
+ init();
+ delegate.setIsScriptBody();
+ }
+
+ @Override
+ public String toString() {
+ init();
+ return delegate.toString();
+ }
+
+ @Override
+ public void setReturnType(ClassNode returnType) {
+ init();
+ delegate.setReturnType(returnType);
+ }
+
+ @Override
+ public ClassNode[] getExceptions() {
+ init();
+ return delegate.getExceptions();
+ }
+
+ @Override
+ public Statement getFirstStatement() {
+ init();
+ return delegate.getFirstStatement();
+ }
+
+ @Override
+ public GenericsType[] getGenericsTypes() {
+ init();
+ return delegate.getGenericsTypes();
+ }
+
+ @Override
+ public void setGenericsTypes(GenericsType[] genericsTypes) {
+ init();
+ delegate.setGenericsTypes(genericsTypes);
+ }
+
+ @Override
+ public void setAnnotationDefault(boolean b) {
+ init();
+ delegate.setAnnotationDefault(b);
+ }
+
+ @Override
+ public boolean hasAnnotationDefault() {
+ init();
+ return delegate.hasAnnotationDefault();
+ }
+
+ @Override
+ public boolean isStaticConstructor() {
+ init();
+ return delegate.isStaticConstructor();
+ }
+
+ @Override
+ public boolean isSyntheticPublic() {
+ init();
+ return delegate.isSyntheticPublic();
+ }
+
+ @Override
+ public void setSyntheticPublic(boolean syntheticPublic) {
+ init();
+ delegate.setSyntheticPublic(syntheticPublic);
+ }
+
+ @Override
+ public String getText() {
+ init();
+ return delegate.getText();
+ }
+
+ @Override
+ public List<AnnotationNode> getAnnotations() {
+ init();
+ return delegate.getAnnotations();
+ }
+
+ @Override
+ public List<AnnotationNode> getAnnotations(ClassNode type) {
+ init();
+ return delegate.getAnnotations(type);
+ }
+
+ @Override
+ public void addAnnotation(AnnotationNode value) {
+ init();
+ delegate.addAnnotation(value);
+ }
+
+ @Override
+ public void addAnnotations(List<AnnotationNode> annotations) {
+ init();
+ delegate.addAnnotations(annotations);
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ init();
+ return delegate.isSynthetic();
+ }
+
+ @Override
+ public void setSynthetic(boolean synthetic) {
+ init();
+ delegate.setSynthetic(synthetic);
+ }
+
+ @Override
+ public ClassNode getDeclaringClass() {
+ init();
+ return delegate.getDeclaringClass();
+ }
+
+ @Override
+ public void setDeclaringClass(ClassNode declaringClass) {
+ super.setDeclaringClass(declaringClass);
+ }
+
+ @Override
+ public boolean hasNoRealSourcePosition() {
+ init();
+ return delegate.hasNoRealSourcePosition();
+ }
+
+ @Override
+ public void setHasNoRealSourcePosition(boolean value) {
+ init();
+ delegate.setHasNoRealSourcePosition(value);
+ }
+
+ @Override
+ public void visit(GroovyCodeVisitor visitor) {
+ init();
+ delegate.visit(visitor);
+ }
+
+ @Override
+ public int getLineNumber() {
+ init();
+ return delegate.getLineNumber();
+ }
+
+ @Override
+ public void setLineNumber(int lineNumber) {
+ init();
+ delegate.setLineNumber(lineNumber);
+ }
+
+ @Override
+ public int getColumnNumber() {
+ init();
+ return delegate.getColumnNumber();
+ }
+
+ @Override
+ public void setColumnNumber(int columnNumber) {
+ init();
+ delegate.setColumnNumber(columnNumber);
+ }
+
+ @Override
+ public int getLastLineNumber() {
+ init();
+ return delegate.getLastLineNumber();
+ }
+
+ @Override
+ public void setLastLineNumber(int lastLineNumber) {
+ init();
+ delegate.setLastLineNumber(lastLineNumber);
+ }
+
+ @Override
+ public int getLastColumnNumber() {
+ init();
+ return delegate.getLastColumnNumber();
+ }
+
+ @Override
+ public void setLastColumnNumber(int lastColumnNumber) {
+ init();
+ delegate.setLastColumnNumber(lastColumnNumber);
+ }
+
+ @Override
+ public void setSourcePosition(ASTNode node) {
+ init();
+ delegate.setSourcePosition(node);
+ }
+
+ @Override
+ public <T> T getNodeMetaData(Object key) {
+ init();
+ return delegate.getNodeMetaData(key);
+ }
+
+ @Override
+ public void copyNodeMetaData(ASTNode other) {
+ init();
+ delegate.copyNodeMetaData(other);
+ }
+
+ @Override
+ public void setNodeMetaData(Object key, Object value) {
+ init();
+ delegate.setNodeMetaData(key, value);
+ }
+
+ @Override
+ public Object putNodeMetaData(Object key, Object value) {
+ init();
+ return delegate.putNodeMetaData(key, value);
+ }
+
+ @Override
+ public void removeNodeMetaData(Object key) {
+ init();
+ delegate.removeNodeMetaData(key);
+ }
+
+ @Override
+ public Map<?, ?> getNodeMetaData() {
+ init();
+ return delegate.getNodeMetaData();
+ }
+
+ @Override
+ public ListHashMap getMetaDataMap() {
+ init();
+ return delegate.getMetaDataMap();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ init();
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ init();
+ return delegate.hashCode();
+ }
+}
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/LazyFieldNode.java b/src/main/java/org/codehaus/groovy/ast/decompiled/LazyFieldNode.java
new file mode 100644
index 0000000..d279c14
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/LazyFieldNode.java
@@ -0,0 +1,403 @@
+/*
+ * 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.decompiled;
+
+import org.apache.groovy.internal.util.Supplier;
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.util.ListHashMap;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents lazy field node, which will be initialized only when accessed
+ *
+ * @since 2.5.9
+ */
+public class LazyFieldNode extends FieldNode {
+ private final Supplier<FieldNode> fieldNodeSupplier;
+ private FieldNode delegate;
+ private boolean initialized;
+
+ private String name;
+
+ public LazyFieldNode(Supplier<FieldNode> fieldNodeSupplier, String name) {
+ this.fieldNodeSupplier = fieldNodeSupplier;
+ this.name = name;
+ }
+
+ private void init() {
+ if (initialized) return;
+ delegate = fieldNodeSupplier.get();
+
+ ClassNode declaringClass = super.getDeclaringClass();
+ if (null != declaringClass) delegate.setDeclaringClass(declaringClass);
+
+ ClassNode owner = super.getOwner();
+ if (null != owner) delegate.setOwner(owner);
+
+ initialized = true;
+ }
+
+ @Override
+ public Expression getInitialExpression() {
+ init();
+ return delegate.getInitialExpression();
+ }
+
+ @Override
+ public int getModifiers() {
+ init();
+ return delegate.getModifiers();
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public ClassNode getType() {
+ init();
+ return delegate.getType();
+ }
+
+ @Override
+ public void setType(ClassNode type) {
+ init();
+ delegate.setType(type);
+ }
+
+ @Override
+ public ClassNode getOwner() {
+ init();
+ return delegate.getOwner();
+ }
+
+ @Override
+ public boolean isHolder() {
+ init();
+ return delegate.isHolder();
+ }
+
+ @Override
+ public void setHolder(boolean holder) {
+ init();
+ delegate.setHolder(holder);
+ }
+
+ @Override
+ public boolean isDynamicTyped() {
+ init();
+ return delegate.isDynamicTyped();
+ }
+
+ @Override
+ public void setModifiers(int modifiers) {
+ init();
+ delegate.setModifiers(modifiers);
+ }
+
+ @Override
+ public boolean isStatic() {
+ init();
+ return delegate.isStatic();
+ }
+
+ @Override
+ public boolean isEnum() {
+ init();
+ return delegate.isEnum();
+ }
+
+ @Override
+ public boolean isFinal() {
+ init();
+ return delegate.isFinal();
+ }
+
+ @Override
+ public boolean isVolatile() {
+ init();
+ return delegate.isVolatile();
+ }
+
+ @Override
+ public boolean isPublic() {
+ init();
+ return delegate.isPublic();
+ }
+
+ @Override
+ public boolean isProtected() {
+ init();
+ return delegate.isProtected();
+ }
+
+ @Override
+ public boolean isPrivate() {
+ init();
+ return delegate.isPrivate();
+ }
+
+ @Override
+ public void setOwner(ClassNode owner) {
+ super.setOwner(owner);
+ }
+
+ @Override
+ public boolean hasInitialExpression() {
+ init();
+ return delegate.hasInitialExpression();
+ }
+
+ @Override
+ public boolean isInStaticContext() {
+ init();
+ return delegate.isInStaticContext();
+ }
+
+ @Override
+ public Expression getInitialValueExpression() {
+ init();
+ return delegate.getInitialValueExpression();
+ }
+
+ @Override
+ public void setInitialValueExpression(Expression initialValueExpression) {
+ init();
+ delegate.setInitialValueExpression(initialValueExpression);
+ }
+
+ @Override
+ @Deprecated
+ public boolean isClosureSharedVariable() {
+ init();
+ return delegate.isClosureSharedVariable();
+ }
+
+ @Override
+ @Deprecated
+ public void setClosureSharedVariable(boolean inClosure) {
+ init();
+ delegate.setClosureSharedVariable(inClosure);
+ }
+
+ @Override
+ public ClassNode getOriginType() {
+ init();
+ return delegate.getOriginType();
+ }
+
+ @Override
+ public void setOriginType(ClassNode cn) {
+ init();
+ delegate.setOriginType(cn);
+ }
+
+ @Override
+ public void rename(String name) {
+ init();
+ delegate.rename(name);
+ }
+
+ @Override
+ public List<AnnotationNode> getAnnotations() {
+ init();
+ return delegate.getAnnotations();
+ }
+
+ @Override
+ public List<AnnotationNode> getAnnotations(ClassNode type) {
+ init();
+ return delegate.getAnnotations(type);
+ }
+
+ @Override
+ public void addAnnotation(AnnotationNode value) {
+ init();
+ delegate.addAnnotation(value);
+ }
+
+ @Override
+ public void addAnnotations(List<AnnotationNode> annotations) {
+ init();
+ delegate.addAnnotations(annotations);
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ init();
+ return delegate.isSynthetic();
+ }
+
+ @Override
+ public void setSynthetic(boolean synthetic) {
+ init();
+ delegate.setSynthetic(synthetic);
+ }
+
+ @Override
+ public ClassNode getDeclaringClass() {
+ init();
+ return delegate.getDeclaringClass();
+ }
+
+ @Override
+ public void setDeclaringClass(ClassNode declaringClass) {
+ super.setDeclaringClass(declaringClass);
+ }
+
+ @Override
+ public boolean hasNoRealSourcePosition() {
+ init();
+ return delegate.hasNoRealSourcePosition();
+ }
+
+ @Override
+ public void setHasNoRealSourcePosition(boolean value) {
+ init();
+ delegate.setHasNoRealSourcePosition(value);
+ }
+
+ @Override
+ public void visit(GroovyCodeVisitor visitor) {
+ init();
+ delegate.visit(visitor);
+ }
+
+ @Override
+ public String getText() {
+ init();
+ return delegate.getText();
+ }
+
+ @Override
+ public int getLineNumber() {
+ init();
+ return delegate.getLineNumber();
+ }
+
+ @Override
+ public void setLineNumber(int lineNumber) {
+ init();
+ delegate.setLineNumber(lineNumber);
+ }
+
+ @Override
+ public int getColumnNumber() {
+ init();
+ return delegate.getColumnNumber();
+ }
+
+ @Override
+ public void setColumnNumber(int columnNumber) {
+ init();
+ delegate.setColumnNumber(columnNumber);
+ }
+
+ @Override
+ public int getLastLineNumber() {
+ init();
+ return delegate.getLastLineNumber();
+ }
+
+ @Override
+ public void setLastLineNumber(int lastLineNumber) {
+ init();
+ delegate.setLastLineNumber(lastLineNumber);
+ }
+
+ @Override
+ public int getLastColumnNumber() {
+ init();
+ return delegate.getLastColumnNumber();
+ }
+
+ @Override
+ public void setLastColumnNumber(int lastColumnNumber) {
+ init();
+ delegate.setLastColumnNumber(lastColumnNumber);
+ }
+
+ @Override
+ public void setSourcePosition(ASTNode node) {
+ init();
+ delegate.setSourcePosition(node);
+ }
+
+ @Override
+ public <T> T getNodeMetaData(Object key) {
+ init();
+ return delegate.getNodeMetaData(key);
+ }
+
+ @Override
+ public void copyNodeMetaData(ASTNode other) {
+ init();
+ delegate.copyNodeMetaData(other);
+ }
+
+ @Override
+ public void setNodeMetaData(Object key, Object value) {
+ init();
+ delegate.setNodeMetaData(key, value);
+ }
+
+ @Override
+ public Object putNodeMetaData(Object key, Object value) {
+ init();
+ return delegate.putNodeMetaData(key, value);
+ }
+
+ @Override
+ public void removeNodeMetaData(Object key) {
+ init();
+ delegate.removeNodeMetaData(key);
+ }
+
+ @Override
+ public Map<?, ?> getNodeMetaData() {
+ init();
+ return delegate.getNodeMetaData();
+ }
+
+ @Override
+ public ListHashMap getMetaDataMap() {
+ init();
+ return delegate.getMetaDataMap();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ init();
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ init();
+ return delegate.hashCode();
+ }
+}
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/LazyMethodNode.java b/src/main/java/org/codehaus/groovy/ast/decompiled/LazyMethodNode.java
new file mode 100644
index 0000000..1da3e94
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/LazyMethodNode.java
@@ -0,0 +1,444 @@
+/*
+ * 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.decompiled;
+
+import org.apache.groovy.internal.util.Supplier;
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.VariableScope;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.util.ListHashMap;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Represents lazy method node, which will be initialized only when accessed
+ *
+ * @since 2.5.9
+ */
+public class LazyMethodNode extends MethodNode {
+ private final Supplier<MethodNode> methodNodeSupplier;
+ private MethodNode delegate;
+ private boolean initialized;
+
+ private String name;
+
+ public LazyMethodNode(Supplier<MethodNode> methodNodeSupplier, String name) {
+ this.methodNodeSupplier = methodNodeSupplier;
+ this.name = name;
+ }
+
+ private void init() {
+ if (initialized) return;
+ delegate = methodNodeSupplier.get();
+
+ ClassNode declaringClass = super.getDeclaringClass();
+ if (null != declaringClass) delegate.setDeclaringClass(declaringClass);
+
+ initialized = true;
+ }
+
+ @Override
+ public String getTypeDescriptor() {
+ init();
+ return delegate.getTypeDescriptor();
+ }
+
+ @Override
+ public boolean isVoidMethod() {
+ init();
+ return delegate.isVoidMethod();
+ }
+
+ @Override
+ public Statement getCode() {
+ init();
+ return delegate.getCode();
+ }
+
+ @Override
+ public void setCode(Statement code) {
+ init();
+ delegate.setCode(code);
+ }
+
+ @Override
+ public int getModifiers() {
+ init();
+ return delegate.getModifiers();
+ }
+
+ @Override
+ public void setModifiers(int modifiers) {
+ init();
+ delegate.setModifiers(modifiers);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Parameter[] getParameters() {
+ init();
+ return delegate.getParameters();
+ }
+
+ @Override
+ public void setParameters(Parameter[] parameters) {
+ init();
+ delegate.setParameters(parameters);
+ }
+
+ @Override
+ public ClassNode getReturnType() {
+ init();
+ return delegate.getReturnType();
+ }
+
+ @Override
+ public VariableScope getVariableScope() {
+ init();
+ return delegate.getVariableScope();
+ }
+
+ @Override
+ public void setVariableScope(VariableScope variableScope) {
+ init();
+ delegate.setVariableScope(variableScope);
+ }
+
+ @Override
+ public boolean isDynamicReturnType() {
+ init();
+ return delegate.isDynamicReturnType();
+ }
+
+ @Override
+ public boolean isAbstract() {
+ init();
+ return delegate.isAbstract();
+ }
+
+ @Override
+ public boolean isStatic() {
+ init();
+ return delegate.isStatic();
+ }
+
+ @Override
+ public boolean isPublic() {
+ init();
+ return delegate.isPublic();
+ }
+
+ @Override
+ public boolean isPrivate() {
+ init();
+ return delegate.isPrivate();
+ }
+
+ @Override
+ public boolean isFinal() {
+ init();
+ return delegate.isFinal();
+ }
+
+ @Override
+ public boolean isProtected() {
+ init();
+ return delegate.isProtected();
+ }
+
+ @Override
+ public boolean isPackageScope() {
+ init();
+ return delegate.isPackageScope();
+ }
+
+ @Override
+ public boolean hasDefaultValue() {
+ init();
+ return delegate.hasDefaultValue();
+ }
+
+ @Override
+ public boolean isScriptBody() {
+ init();
+ return delegate.isScriptBody();
+ }
+
+ @Override
+ public void setIsScriptBody() {
+ init();
+ delegate.setIsScriptBody();
+ }
+
+ @Override
+ public String toString() {
+ init();
+ return delegate.toString();
+ }
+
+ @Override
+ public void setReturnType(ClassNode returnType) {
+ init();
+ delegate.setReturnType(returnType);
+ }
+
+ @Override
+ public ClassNode[] getExceptions() {
+ init();
+ return delegate.getExceptions();
+ }
+
+ @Override
+ public Statement getFirstStatement() {
+ init();
+ return delegate.getFirstStatement();
+ }
+
+ @Override
+ public GenericsType[] getGenericsTypes() {
+ init();
+ return delegate.getGenericsTypes();
+ }
+
+ @Override
+ public void setGenericsTypes(GenericsType[] genericsTypes) {
+ init();
+ delegate.setGenericsTypes(genericsTypes);
+ }
+
+ @Override
+ public void setAnnotationDefault(boolean b) {
+ init();
+ delegate.setAnnotationDefault(b);
+ }
+
+ @Override
+ public boolean hasAnnotationDefault() {
+ init();
+ return delegate.hasAnnotationDefault();
+ }
+
+ @Override
+ public boolean isStaticConstructor() {
+ init();
+ return delegate.isStaticConstructor();
+ }
+
+ @Override
+ public boolean isSyntheticPublic() {
+ init();
+ return delegate.isSyntheticPublic();
+ }
+
+ @Override
+ public void setSyntheticPublic(boolean syntheticPublic) {
+ init();
+ delegate.setSyntheticPublic(syntheticPublic);
+ }
+
+ @Override
+ public String getText() {
+ init();
+ return delegate.getText();
+ }
+
+ @Override
+ public List<AnnotationNode> getAnnotations() {
+ init();
+ return delegate.getAnnotations();
+ }
+
+ @Override
+ public List<AnnotationNode> getAnnotations(ClassNode type) {
+ init();
+ return delegate.getAnnotations(type);
+ }
+
+ @Override
+ public void addAnnotation(AnnotationNode value) {
+ init();
+ delegate.addAnnotation(value);
+ }
+
+ @Override
+ public void addAnnotations(List<AnnotationNode> annotations) {
+ init();
+ delegate.addAnnotations(annotations);
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ init();
+ return delegate.isSynthetic();
+ }
+
+ @Override
+ public void setSynthetic(boolean synthetic) {
+ init();
+ delegate.setSynthetic(synthetic);
+ }
+
+ @Override
+ public ClassNode getDeclaringClass() {
+ init();
+ return delegate.getDeclaringClass();
+ }
+
+ @Override
+ public void setDeclaringClass(ClassNode declaringClass) {
+ super.setDeclaringClass(declaringClass);
+ }
+
+ @Override
+ public boolean hasNoRealSourcePosition() {
+ init();
+ return delegate.hasNoRealSourcePosition();
+ }
+
+ @Override
+ public void setHasNoRealSourcePosition(boolean value) {
+ init();
+ delegate.setHasNoRealSourcePosition(value);
+ }
+
+ @Override
+ public void visit(GroovyCodeVisitor visitor) {
+ init();
+ delegate.visit(visitor);
+ }
+
+ @Override
+ public int getLineNumber() {
+ init();
+ return delegate.getLineNumber();
+ }
+
+ @Override
+ public void setLineNumber(int lineNumber) {
+ init();
+ delegate.setLineNumber(lineNumber);
+ }
+
+ @Override
+ public int getColumnNumber() {
+ init();
+ return delegate.getColumnNumber();
+ }
+
+ @Override
+ public void setColumnNumber(int columnNumber) {
+ init();
+ delegate.setColumnNumber(columnNumber);
+ }
+
+ @Override
+ public int getLastLineNumber() {
+ init();
+ return delegate.getLastLineNumber();
+ }
+
+ @Override
+ public void setLastLineNumber(int lastLineNumber) {
+ init();
+ delegate.setLastLineNumber(lastLineNumber);
+ }
+
+ @Override
+ public int getLastColumnNumber() {
+ init();
+ return delegate.getLastColumnNumber();
+ }
+
+ @Override
+ public void setLastColumnNumber(int lastColumnNumber) {
+ init();
+ delegate.setLastColumnNumber(lastColumnNumber);
+ }
+
+ @Override
+ public void setSourcePosition(ASTNode node) {
+ init();
+ delegate.setSourcePosition(node);
+ }
+
+ @Override
+ public <T> T getNodeMetaData(Object key) {
+ init();
+ return delegate.getNodeMetaData(key);
+ }
+
+ @Override
+ public void copyNodeMetaData(ASTNode other) {
+ init();
+ delegate.copyNodeMetaData(other);
+ }
+
+ @Override
+ public void setNodeMetaData(Object key, Object value) {
+ init();
+ delegate.setNodeMetaData(key, value);
+ }
+
+ @Override
+ public Object putNodeMetaData(Object key, Object value) {
+ init();
+ return delegate.putNodeMetaData(key, value);
+ }
+
+ @Override
+ public void removeNodeMetaData(Object key) {
+ init();
+ delegate.removeNodeMetaData(key);
+ }
+
+ @Override
+ public Map<?, ?> getNodeMetaData() {
+ init();
+ return delegate.getNodeMetaData();
+ }
+
+ @Override
+ public ListHashMap getMetaDataMap() {
+ init();
+ return delegate.getMetaDataMap();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ init();
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ init();
+ return delegate.hashCode();
+ }
+}
diff --git a/subprojects/groovy-ant/src/test/groovy/groovy/ant/Groovy9352Test.groovy b/subprojects/groovy-ant/src/test/groovy/groovy/ant/Groovy9352Test.groovy
new file mode 100644
index 0000000..4eddd70
--- /dev/null
+++ b/subprojects/groovy-ant/src/test/groovy/groovy/ant/Groovy9352Test.groovy
@@ -0,0 +1,99 @@
+/*
+ * 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 groovy.ant
+
+class Groovy9352Test extends AntTestCase {
+ void test() {
+ doInTmpDir { ant, baseDir ->
+ baseDir.src {
+ p1 {
+ 'Consumer.groovy'('''
+ package p1
+ import groovy.transform.CompileStatic
+ import p2.Producer
+
+ @CompileStatic
+ class Consumer {
+ void doSomething(Producer producer) {
+ // this shouldn't trigger a compile error
+ producer.foo()
+ }
+
+ }
+ ''')
+ }
+ p2 {
+ 'Producer.java'('''
+ package p2;
+ import java.util.List;
+ import java.util.ArrayList;
+
+ public class Producer {
+ public void foo() {}
+
+ // the following members are private, they shouldn't leak into the public API
+ private Gson gson;
+ private Gson gson2 = new SubGson();
+ private List<Gson> gsonList;
+ private List<? extends Gson> gsonList2 = new ArrayList<SubGson>();
+
+ private Producer(Gson p) {}
+ private Producer(int p) throws Gson {}
+ private Producer() { gson = new Gson(); }
+
+ private void bar(Gson p) {}
+ private Gson bar() { return null;}
+ private void bar(int p) throws Gson {}
+ private Object bar(float p) { return new Gson(); }
+ }
+ ''')
+ 'Gson.java'('''
+ package p2;
+ class Gson extends Exception {
+ }
+ ''')
+ 'SubGson.java'('''
+ package p2;
+ class SubGson extends Gson {
+ }
+ ''')
+ }
+ }
+
+ ant.mkdir(dir: 'build')
+ ant.taskdef(name: 'groovyc', classname: 'org.codehaus.groovy.ant.Groovyc')
+
+ // 1) compile the Java source code only
+ ant.groovyc(srcdir: 'src', destdir: 'build', includes: 'p2/*' /*, keepStubs: true*/) {
+ javac()
+ }
+
+ // 2) delete `Gson` and `SubGson` related files: "Gson.java", "Gson.class", "SubGson.java" and "SubGson.class"
+ assert new File(ant.project.baseDir,"src/p2/Gson.java").delete()
+ assert new File(ant.project.baseDir,"build/p2/Gson.class").delete()
+ assert new File(ant.project.baseDir,"src/p2/SubGson.java").delete()
+ assert new File(ant.project.baseDir,"build/p2/SubGson.class").delete()
+
+ // 3) compile the Groovy source code
+ ant.groovyc(srcdir: 'src', destdir: 'build', includes: 'p1/*'){
+ classpath { pathelement(path: 'build') }
+ }
+ }
+ }
+}