You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2016/05/24 12:06:04 UTC
groovy git commit: GROOVY-7750: @Lazy allows instantiation of
abstract class
Repository: groovy
Updated Branches:
refs/heads/master 7d9a54bb1 -> a2565bebb
GROOVY-7750: @Lazy allows instantiation of abstract class
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/a2565beb
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/a2565beb
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/a2565beb
Branch: refs/heads/master
Commit: a2565bebba790545a062525cb1f471dc62117225
Parents: 7d9a54b
Author: paulk <pa...@asert.com.au>
Authored: Tue May 17 21:06:50 2016 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Tue May 24 22:05:24 2016 +1000
----------------------------------------------------------------------
.../groovy/ast/ClassCodeVisitorSupport.java | 5 +--
src/main/org/codehaus/groovy/ast/ClassNode.java | 4 +++
.../groovy/ast/tools/GenericsUtils.java | 2 +-
.../groovy/classgen/ExtendedVerifier.java | 2 +-
.../tools/javac/JavaAwareResolveVisitor.java | 2 +-
.../transform/AbstractASTTransformation.java | 32 ++++++++++----------
.../groovy/transform/ErrorCollecting.java | 31 +++++++++++++++++++
.../transform/FieldASTTransformation.java | 2 +-
.../groovy/transform/LazyASTTransformation.java | 19 +++++++-----
.../stc/StaticTypeCheckingVisitor.java | 2 +-
.../groovy/transform/LazyTransformTest.groovy | 14 +++++++++
.../MarkupTemplateTypeCheckingExtension.groovy | 2 +-
12 files changed, 85 insertions(+), 32 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java b/src/main/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
index 7cd5807..bfabea9 100644
--- a/src/main/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
+++ b/src/main/org/codehaus/groovy/ast/ClassCodeVisitorSupport.java
@@ -43,8 +43,9 @@ 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;
-public abstract class ClassCodeVisitorSupport extends CodeVisitorSupport implements GroovyClassVisitor {
+public abstract class ClassCodeVisitorSupport extends CodeVisitorSupport implements ErrorCollecting, GroovyClassVisitor {
public void visitClass(ClassNode node) {
visitAnnotations(node);
@@ -149,7 +150,7 @@ public abstract class ClassCodeVisitorSupport extends CodeVisitorSupport impleme
if (init != null) init.visit(this);
}
- protected void addError(String msg, ASTNode expr) {
+ 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)
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/ast/ClassNode.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/ClassNode.java b/src/main/org/codehaus/groovy/ast/ClassNode.java
index 2cde68c..6601ac7 100644
--- a/src/main/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/org/codehaus/groovy/ast/ClassNode.java
@@ -1345,6 +1345,10 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
return (getModifiers() & Opcodes.ACC_INTERFACE) > 0;
}
+ public boolean isAbstract(){
+ return (getModifiers() & Opcodes.ACC_ABSTRACT) > 0;
+ }
+
public boolean isResolved() {
if (clazz != null) return true;
if (redirect != null) return redirect.isResolved();
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 53b7c1d..79449e4 100644
--- a/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -554,7 +554,7 @@ public class GenericsUtils {
dummyClass.addMethod(dummyMN);
ResolveVisitor visitor = new ResolveVisitor(compilationUnit) {
@Override
- protected void addError(final String msg, final ASTNode expr) {
+ public void addError(final String msg, final ASTNode expr) {
sourceUnit.addError(new IncorrectTypeHintException(mn, msg, usage.getLineNumber(), usage.getColumnNumber()));
}
};
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/classgen/ExtendedVerifier.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/ExtendedVerifier.java b/src/main/org/codehaus/groovy/classgen/ExtendedVerifier.java
index 14697e6..57cfbfa 100644
--- a/src/main/org/codehaus/groovy/classgen/ExtendedVerifier.java
+++ b/src/main/org/codehaus/groovy/classgen/ExtendedVerifier.java
@@ -278,7 +278,7 @@ public class ExtendedVerifier extends ClassCodeVisitorSupport {
return CompilerConfiguration.isPostJDK5(this.source.getConfiguration().getTargetBytecode());
}
- protected void addError(String msg, ASTNode expr) {
+ public void addError(String msg, ASTNode expr) {
this.source.getErrorCollector().addErrorAndContinue(
new SyntaxErrorMessage(
new SyntaxException(msg + '\n', expr.getLineNumber(), expr.getColumnNumber(), expr.getLastLineNumber(), expr.getLastColumnNumber()), this.source)
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/tools/javac/JavaAwareResolveVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/tools/javac/JavaAwareResolveVisitor.java b/src/main/org/codehaus/groovy/tools/javac/JavaAwareResolveVisitor.java
index aca9544..4291ac4 100644
--- a/src/main/org/codehaus/groovy/tools/javac/JavaAwareResolveVisitor.java
+++ b/src/main/org/codehaus/groovy/tools/javac/JavaAwareResolveVisitor.java
@@ -63,7 +63,7 @@ public class JavaAwareResolveVisitor extends ResolveVisitor {
// do nothing here, leave it to the normal resolving
}
- protected void addError(String msg, ASTNode expr) {
+ public void addError(String msg, ASTNode expr) {
// do nothing here, leave it to the normal resolving
}
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/transform/AbstractASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/AbstractASTTransformation.java b/src/main/org/codehaus/groovy/transform/AbstractASTTransformation.java
index b762153..17eef57 100644
--- a/src/main/org/codehaus/groovy/transform/AbstractASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/AbstractASTTransformation.java
@@ -50,7 +50,7 @@ import static groovy.transform.Undefined.isUndefined;
import static org.codehaus.groovy.ast.tools.GeneralUtils.getInstanceNonPropertyFieldNames;
import static org.codehaus.groovy.ast.tools.GeneralUtils.getInstancePropertyNames;
-public abstract class AbstractASTTransformation implements Opcodes, ASTTransformation {
+public abstract class AbstractASTTransformation implements Opcodes, ASTTransformation, ErrorCollecting {
public static final ClassNode RETENTION_CLASSNODE = ClassHelper.makeWithoutCaching(Retention.class);
protected SourceUnit sourceUnit;
@@ -248,7 +248,7 @@ public abstract class AbstractASTTransformation implements Opcodes, ASTTransform
public boolean hasAnnotation(ClassNode cNode, ClassNode annotation) {
List annots = cNode.getAnnotations(annotation);
- return (annots != null && !annots.isEmpty());
+ return (annots != null && !annots.isEmpty());
}
public static List<String> tokenize(String rawExcludes) {
@@ -260,23 +260,23 @@ public abstract class AbstractASTTransformation implements Opcodes, ASTTransform
}
public static boolean shouldSkipUndefinedAware(String name, List<String> excludes, List<String> includes) {
- return shouldSkipUndefinedAware(name, excludes, includes, false);
- }
-
- public static boolean shouldSkipUndefinedAware(String name, List<String> excludes, List<String> includes, boolean allNames) {
- return (excludes != null && excludes.contains(name)) ||
- (!allNames && deemedInternalName(name)) ||
- (includes != null && !includes.contains(name));
+ return shouldSkipUndefinedAware(name, excludes, includes, false);
+ }
+
+ public static boolean shouldSkipUndefinedAware(String name, List<String> excludes, List<String> includes, boolean allNames) {
+ return (excludes != null && excludes.contains(name)) ||
+ (!allNames && deemedInternalName(name)) ||
+ (includes != null && !includes.contains(name));
}
public static boolean shouldSkip(String name, List<String> excludes, List<String> includes) {
- return shouldSkip(name, excludes, includes, false);
- }
-
- public static boolean shouldSkip(String name, List<String> excludes, List<String> includes, boolean allNames) {
- return (excludes != null && excludes.contains(name)) ||
- (!allNames && deemedInternalName(name)) ||
- (includes != null && !includes.isEmpty() && !includes.contains(name));
+ return shouldSkip(name, excludes, includes, false);
+ }
+
+ public static boolean shouldSkip(String name, List<String> excludes, List<String> includes, boolean allNames) {
+ return (excludes != null && excludes.contains(name)) ||
+ (!allNames && deemedInternalName(name)) ||
+ (includes != null && !includes.isEmpty() && !includes.contains(name));
}
@Deprecated
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/transform/ErrorCollecting.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/ErrorCollecting.java b/src/main/org/codehaus/groovy/transform/ErrorCollecting.java
new file mode 100644
index 0000000..18d6008
--- /dev/null
+++ b/src/main/org/codehaus/groovy/transform/ErrorCollecting.java
@@ -0,0 +1,31 @@
+/*
+ * 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.transform;
+
+import org.codehaus.groovy.ast.ASTNode;
+
+/**
+ * An AST transform with the ability to report errors.
+ *
+ * @see ASTTransformation
+ */
+public interface ErrorCollecting {
+ void addError(String msg, ASTNode expr);
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java b/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
index d0fee21..52b4406 100644
--- a/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/FieldASTTransformation.java
@@ -118,7 +118,7 @@ public class FieldASTTransformation extends ClassCodeExpressionTransformer imple
for (AnnotationNode annotation : annotations) {
// GROOVY-6337 HACK: in case newly created field is @Lazy
if (annotation.getClassNode().equals(LAZY_TYPE)) {
- LazyASTTransformation.visitField(annotation, fieldNode);
+ LazyASTTransformation.visitField(this, annotation, fieldNode);
}
final ClassNode annotationClassNode = annotation.getClassNode();
if (notTransform(annotationClassNode) || acceptableTransform(annotation)) {
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/transform/LazyASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/LazyASTTransformation.java b/src/main/org/codehaus/groovy/transform/LazyASTTransformation.java
index 5e25a3c..0216c47 100644
--- a/src/main/org/codehaus/groovy/transform/LazyASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/LazyASTTransformation.java
@@ -23,10 +23,12 @@ import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.CodeVisitorSupport;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.InnerClassNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.EmptyExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
@@ -58,9 +60,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
/**
* Handles generation of code for the @Lazy annotation
- *
- * @author Alex Tkachman
- * @author Paul King
*/
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class LazyASTTransformation extends AbstractASTTransformation {
@@ -75,13 +74,13 @@ public class LazyASTTransformation extends AbstractASTTransformation {
if (parent instanceof FieldNode) {
final FieldNode fieldNode = (FieldNode) parent;
- visitField(node, fieldNode);
+ visitField(this, node, fieldNode);
}
}
- static void visitField(AnnotationNode node, FieldNode fieldNode) {
+ static void visitField(ErrorCollecting xform, AnnotationNode node, FieldNode fieldNode) {
final Expression soft = node.getMember("soft");
- final Expression init = getInitExpr(fieldNode);
+ final Expression init = getInitExpr(xform, fieldNode);
fieldNode.rename("$" + fieldNode.getName());
fieldNode.setModifiers(ACC_PRIVATE | (fieldNode.getModifiers() & (~(ACC_PUBLIC | ACC_PROTECTED))));
@@ -207,11 +206,15 @@ public class LazyASTTransformation extends AbstractASTTransformation {
return fieldNode.isStatic() ? classX(fieldNode.getDeclaringClass()) : varX("this");
}
- private static Expression getInitExpr(FieldNode fieldNode) {
+ private static Expression getInitExpr(ErrorCollecting xform, FieldNode fieldNode) {
Expression initExpr = fieldNode.getInitialValueExpression();
fieldNode.setInitialValueExpression(null);
- if (initExpr == null) {
+ if (initExpr == null || initExpr instanceof EmptyExpression) {
+ if (fieldNode.getType().isAbstract()) {
+ xform.addError("You cannot lazily initialize '" + fieldNode.getName() + "' from the abstract class '" +
+ fieldNode.getType().getName() + "'", fieldNode);
+ }
initExpr = ctorX(fieldNode.getType());
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 6d3afb7..76d4249 100644
--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4603,7 +4603,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
@Override
- protected void addError(final String msg, final ASTNode expr) {
+ public void addError(final String msg, final ASTNode expr) {
Long err = ((long) expr.getLineNumber()) << 16 + expr.getColumnNumber();
if ((DEBUG_GENERATED_CODE && expr.getLineNumber()<0) || !typeCheckingContext.reportedErrors.contains(err)) {
typeCheckingContext.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/src/test/org/codehaus/groovy/transform/LazyTransformTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/transform/LazyTransformTest.groovy b/src/test/org/codehaus/groovy/transform/LazyTransformTest.groovy
index 7ef7c1d..08a0b19 100644
--- a/src/test/org/codehaus/groovy/transform/LazyTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/LazyTransformTest.groovy
@@ -149,6 +149,20 @@ class LazyTransformTest extends GroovyShellTestCase {
assert Modifier.isVolatile(res.class.getDeclaredField('$val2').modifiers)
}
+ void testAbstractClassShouldNotCompile() {
+ def message = shouldFail {
+ new GroovyShell().run('''
+ abstract class Foo {}
+ class Demo {
+ @Lazy Foo foo
+ }
+
+ new Demo().foo
+ ''', 'dummyFileName', [])
+ }
+ assert message.contains("You cannot lazily initialize 'foo' from the abstract class 'Foo'")
+ }
+
void testSoft() {
def res = evaluate("""
class X {
http://git-wip-us.apache.org/repos/asf/groovy/blob/a2565beb/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
index 57cf170..db66f29 100644
--- a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
+++ b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
@@ -194,7 +194,7 @@ class MarkupTemplateTypeCheckingExtension extends GroovyTypeCheckingExtensionSup
dummyClass.addMethod(dummyMN);
ResolveVisitor visitor = new ResolveVisitor(ctx.compilationUnit) {
@Override
- protected void addError(final String msg, final ASTNode expr) {
+ public void addError(final String msg, final ASTNode expr) {
ctx.errorCollector.addErrorAndContinue(new SyntaxErrorMessage(
new SyntaxException(msg + '\n', expr.getLineNumber(), expr.getColumnNumber(), expr.getLastLineNumber(), expr.getLastColumnNumber()),
ctx.source)