From 33a2ceeb29e15d57fb193ee8214cfb98008340b7 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Mon, 8 Oct 2018 11:12:50 +0200 Subject: [PATCH] Reduce use of javax.annotation annotations The annotations in use have runtime retention, which triggers generation of import-package for javax.annotation, which is no longer satisfied with newer JDKs. Use JDT @Nullable annotation instead. Since @Nullable is TYPE_USE annotation, this also requires a bit of juggling in JavaFileTemplate to make it work correctly with types which end up being referenced via their FQCN. This still retains javax.annotation.CheckReturnValue, but marks it for replacement once we decide where to go annotation-wise. JIRA: MDSAL-372 Change-Id: I792094d3c07162a5f8e6ca82ceea3a75b48c7b6e Signed-off-by: Robert Varga --- .../generator/impl/AbstractTypeGenerator.java | 5 +--- .../generator/AbstractJavaGeneratedType.java | 27 +++++++++++++++---- .../api/generator/InterfaceTemplate.xtend | 27 ++++++++++++++----- .../java/api/generator/JavaFileTemplate.java | 4 +-- .../api/generator/test/CompilationTest.java | 3 +-- 5 files changed, 47 insertions(+), 19 deletions(-) diff --git a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java index 47b4adaa08..f2a0cbe71d 100644 --- a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java +++ b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java @@ -503,6 +503,7 @@ abstract class AbstractTypeGenerator { final MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName); // Do not refer to annotation class, as it may not be available at runtime + // FIXME: migrate this to some other annotation type method.addAnnotation("javax.annotation", "CheckReturnValue"); addComment(method, rpc); method.addParameter( @@ -1681,10 +1682,6 @@ abstract class AbstractTypeGenerator { getMethod.setReturnType(returnType); annotateDeprecatedIfNecessary(node.getStatus(), getMethod); - if (!returnType.getPackageName().isEmpty()) { - // The return type has a package, so it's not a primitive type - getMethod.addAnnotation("javax.annotation", "Nullable"); - } addComment(getMethod, node); return getMethod; diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/AbstractJavaGeneratedType.java b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/AbstractJavaGeneratedType.java index 0d368f0252..75461fa843 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/AbstractJavaGeneratedType.java +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/AbstractJavaGeneratedType.java @@ -61,7 +61,7 @@ abstract class AbstractJavaGeneratedType { conflictingNames = ImmutableSet.copyOf(cb); } - private void collectAccessibleTypes(Set set, GeneratedType type) { + private void collectAccessibleTypes(final Set set, final GeneratedType type) { for (Type impl : type.getImplements()) { if (impl instanceof GeneratedType) { final GeneratedType genType = (GeneratedType) impl; @@ -81,13 +81,13 @@ abstract class AbstractJavaGeneratedType { return name.simpleName(); } - final String getReferenceString(final Type type) { + final String getReferenceString(final Type type, final String... annotations) { + final String ref = getReferenceString(type.getIdentifier()); if (!(type instanceof ParameterizedType)) { - return getReferenceString(type.getIdentifier()); + return annotations.length == 0 ? ref : annotate(ref, annotations).toString(); } - final StringBuilder sb = new StringBuilder(); - sb.append(getReferenceString(type.getIdentifier())).append('<'); + final StringBuilder sb = annotate(ref, annotations).append('<'); final Type[] types = ((ParameterizedType) type).getActualTypeArguments(); if (types.length == 0) { return sb.append("?>").toString(); @@ -161,4 +161,21 @@ abstract class AbstractJavaGeneratedType { // Try to anchor the top-level type and use a local reference return checkAndImportType(type.topLevelClass()) ? type.localName() : type.toString(); } + + private static StringBuilder annotate(final String ref, final String... annotations) { + final StringBuilder sb = new StringBuilder(); + if (annotations.length == 0) { + return sb.append(ref); + } + + final int dot = ref.lastIndexOf('.'); + if (dot != -1) { + sb.append(ref, 0, dot + 1); + } + for (String annotation : annotations) { + sb.append('@').append(annotation).append(' '); + } + + return sb.append(ref, dot + 1, ref.length()); + } } diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend index ba99afceaa..6b95436143 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend @@ -12,13 +12,16 @@ import org.opendaylight.mdsal.binding.model.api.AnnotationType import org.opendaylight.mdsal.binding.model.api.Constant import org.opendaylight.mdsal.binding.model.api.Enumeration import org.opendaylight.mdsal.binding.model.api.GeneratedType +import org.opendaylight.mdsal.binding.model.api.JavaTypeName import org.opendaylight.mdsal.binding.model.api.MethodSignature +import org.opendaylight.mdsal.binding.model.api.Type import org.opendaylight.mdsal.binding.model.util.TypeConstants /** * Template for generating JAVA interfaces. */ class InterfaceTemplate extends BaseTemplate { + static val JavaTypeName NULLABLE = JavaTypeName.create("org.eclipse.jdt.annotation", "Nullable") /** * List of constant instances which are generated as JAVA public static final attributes. @@ -163,17 +166,29 @@ class InterfaceTemplate extends BaseTemplate { def private generateMethods() ''' «IF !methods.empty» «FOR m : methods SEPARATOR "\n"» - «IF !m.isAccessor» - «m.comment.asJavadoc» - «ELSE» - «formatDataForJavaDoc(m, "@return " + asCode(m.returnType.fullyQualifiedName) + " " + «val accessor = m.isAccessor» + «val ret = m.returnType» + «IF accessor» + «formatDataForJavaDoc(m, "@return " + asCode(ret.fullyQualifiedName) + " " + asCode(propertyNameFromGetter(m)) + ", or " + asCode("null") + " if not present")» + «ELSE» + «m.comment.asJavadoc» «ENDIF» «m.annotations.generateAnnotations» - «m.returnType.importedName» «m.name»(«m.parameters.generateParameters»); + «nullableType(ret, accessor)» «m.name»(«m.parameters.generateParameters»); «ENDFOR» «ENDIF» ''' -} + def private String nullableType(Type type, boolean accessor) { + if (accessor && type.isObject) { + return importedName(type, NULLABLE.importedName) + } + return type.importedName + } + def private static boolean isObject(Type type) { + // The return type has a package, so it's not a primitive type + return !type.getPackageName().isEmpty() + } +} diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java index 5387a82c53..a414f707bd 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/JavaFileTemplate.java @@ -62,8 +62,8 @@ class JavaFileTemplate { .collect(Collectors.joining()); } - final String importedName(final Type intype) { - return javaType.getReferenceString(intype); + final String importedName(final Type intype, final String... annotations) { + return javaType.getReferenceString(intype, annotations); } final String importedName(final Class cls) { diff --git a/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/CompilationTest.java b/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/CompilationTest.java index 794ad9d3a7..2033d6dc2b 100644 --- a/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/CompilationTest.java +++ b/binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/CompilationTest.java @@ -33,7 +33,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; -import javax.annotation.Nullable; import org.junit.Test; import org.opendaylight.yangtools.yang.binding.ChildOf; import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext; @@ -470,7 +469,7 @@ public class CompilationTest extends BaseCompilationTest { throw new AssertionError("Method getId() not found", e); } - assertEquals(ImmutableSet.of(RoutingContext.class, Nullable.class), Arrays.stream(getId.getAnnotations()) + assertEquals(ImmutableSet.of(RoutingContext.class), Arrays.stream(getId.getAnnotations()) .map(Annotation::annotationType).collect(Collectors.toSet())); CompilationTestUtils.cleanUp(sourcesOutputDir, compiledOutputDir); } -- 2.36.6