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 2018/04/25 13:56:25 UTC
groovy git commit: GROOVY-8559: CLONE - Add @Repeatable java8
annotation support (handle pre-compiled annotations)
Repository: groovy
Updated Branches:
refs/heads/master 9bcdd74df -> ebebbb31f
GROOVY-8559: CLONE - Add @Repeatable java8 annotation support (handle pre-compiled annotations)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/ebebbb31
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/ebebbb31
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/ebebbb31
Branch: refs/heads/master
Commit: ebebbb31fb949ffbe515edc8bf5810aa2ae9a3b2
Parents: 9bcdd74
Author: Paul King <pa...@asert.com.au>
Authored: Wed Apr 25 23:55:12 2018 +1000
Committer: Paul King <pa...@asert.com.au>
Committed: Wed Apr 25 23:56:19 2018 +1000
----------------------------------------------------------------------
.../java/org/codehaus/groovy/ast/ClassNode.java | 5 +--
.../codehaus/groovy/control/ResolveVisitor.java | 18 +++++++--
src/test/gls/annotations/AnnotationTest.groovy | 39 ++++++++++++++++++++
src/test/gls/annotations/Require.java | 32 ++++++++++++++++
src/test/gls/annotations/Requires.java | 30 +++++++++++++++
5 files changed, 118 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/ebebbb31/src/main/java/org/codehaus/groovy/ast/ClassNode.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/ClassNode.java b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
index e5d1f03..565e2f9 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
@@ -1440,9 +1440,8 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
}
public boolean isAnnotationDefinition() {
- return redirect().isPrimaryNode &&
- isInterface() &&
- (getModifiers() & Opcodes.ACC_ANNOTATION)!=0;
+ return /* redirect().isPrimaryNode && */
+ isInterface() && (getModifiers() & Opcodes.ACC_ANNOTATION) != 0;
}
public List<AnnotationNode> getAnnotations() {
http://git-wip-us.apache.org/repos/asf/groovy/blob/ebebbb31/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
index 1bdf9b8..d5d0bf9 100644
--- a/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/ResolveVisitor.java
@@ -63,6 +63,7 @@ import org.codehaus.groovy.syntax.Types;
import org.codehaus.groovy.transform.trait.Traits;
import org.objectweb.asm.Opcodes;
+import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Modifier;
@@ -1222,12 +1223,13 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
member.setValue(newValue);
checkAnnotationMemberValue(newValue);
}
- if(annType.isResolved()) {
+ if (annType.isResolved()) {
Class annTypeClass = annType.getTypeClass();
Retention retAnn = (Retention) annTypeClass.getAnnotation(Retention.class);
- if (retAnn != null && retAnn.value().equals(RetentionPolicy.RUNTIME)) {
+ if (retAnn != null && retAnn.value().equals(RetentionPolicy.RUNTIME) && !isRepeatable(annTypeClass)) {
+ // remember runtime/non-repeatable annos (auto collecting of Repeatable annotations is handled elsewhere)
AnnotationNode anyPrevAnnNode = tmpAnnotations.put(annTypeClass.getName(), an);
- if(anyPrevAnnNode != null) {
+ if (anyPrevAnnNode != null) {
addError("Cannot specify duplicate annotation on the same member : " + annType.getName(), an);
}
}
@@ -1235,6 +1237,16 @@ public class ResolveVisitor extends ClassCodeExpressionTransformer {
}
}
+ private boolean isRepeatable(Class annTypeClass) {
+ Annotation[] annTypeAnnotations = annTypeClass.getAnnotations();
+ for (Annotation annTypeAnnotation : annTypeAnnotations) {
+ if (annTypeAnnotation.annotationType().getName().equals("java.lang.annotation.Repeatable")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
// resolve constant-looking expressions statically (do here as gets transformed away later)
private Expression transformInlineConstants(Expression exp) {
if (exp instanceof PropertyExpression) {
http://git-wip-us.apache.org/repos/asf/groovy/blob/ebebbb31/src/test/gls/annotations/AnnotationTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/gls/annotations/AnnotationTest.groovy b/src/test/gls/annotations/AnnotationTest.groovy
index be77a16..78aa260 100644
--- a/src/test/gls/annotations/AnnotationTest.groovy
+++ b/src/test/gls/annotations/AnnotationTest.groovy
@@ -755,6 +755,45 @@ class AnnotationTest extends CompilableTestSupport {
'''
}
+ void testAnnotationWithRepeatableSupportedPrecompiledJava() {
+ assertScript '''
+ import java.lang.annotation.*
+ import gls.annotations.*
+
+ class MyClass {
+ // TODO confirm the JDK9 behavior is what we expect
+ private static final List<String> expected = [
+ '@gls.annotations.Requires(value=[@gls.annotations.Require(value=val1), @gls.annotations.Require(value=val2)])', // JDK5-8
+ '@gls.annotations.Requires(value={@gls.annotations.Require(value="val1"), @gls.annotations.Require(value="val2")})' // JDK9
+ ]
+
+ // control
+ @Requires([@Require("val1"), @Require("val2")])
+ String method1() { 'method1' }
+
+ // duplicate candidate for auto collection
+ @Require(value = "val1")
+ @Require(value = "val2")
+ String method2() { 'method2' }
+
+ static void main(String... args) {
+ MyClass myc = new MyClass()
+ assert 'method1' == myc.method1()
+ assert 'method2' == myc.method2()
+ assert expected.contains(checkAnnos(myc, "method1"))
+ assert expected.contains(checkAnnos(myc, "method2"))
+ }
+
+ private static String checkAnnos(MyClass myc, String name) {
+ def m = myc.getClass().getMethod(name)
+ List annos = m.getAnnotations()
+ assert annos.size() == 1
+ annos[0].toString()
+ }
+ }
+ '''
+ }
+
//Parametrized tests in Spock would allow to make it much more readable
private static String codeWithMetaAnnotationWithTarget(String targetElementTypeName) {
"""
http://git-wip-us.apache.org/repos/asf/groovy/blob/ebebbb31/src/test/gls/annotations/Require.java
----------------------------------------------------------------------
diff --git a/src/test/gls/annotations/Require.java b/src/test/gls/annotations/Require.java
new file mode 100644
index 0000000..7d51cf2
--- /dev/null
+++ b/src/test/gls/annotations/Require.java
@@ -0,0 +1,32 @@
+/*
+ * 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 gls.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+@Repeatable(Requires.class)
+public @interface Require {
+ String value() default "";
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/ebebbb31/src/test/gls/annotations/Requires.java
----------------------------------------------------------------------
diff --git a/src/test/gls/annotations/Requires.java b/src/test/gls/annotations/Requires.java
new file mode 100644
index 0000000..b828a59
--- /dev/null
+++ b/src/test/gls/annotations/Requires.java
@@ -0,0 +1,30 @@
+/*
+ * 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 gls.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface Requires {
+ Require[] value();
+}