From e979f506fac6aeabfa3a1993b3b986449fcb7b3a Mon Sep 17 00:00:00 2001
From: Orange Add <48479242+chenzijia12300@users.noreply.github.com>
Date: Thu, 29 Sep 2022 04:17:59 +0800
Subject: [PATCH] #2773 Copy `@Deprecated` annotation from method or mapper to
implementation
---
...eatureCompilationExclusionCliEnhancer.java | 1 +
.../test/resources/fullFeatureTest/pom.xml | 2 +
.../ap/internal/gem/GemGenerator.java | 1 +
.../model/AdditionalAnnotationsBuilder.java | 42 ++++++++++++-
.../test/annotatewith/AnnotateWithTest.java | 1 -
.../deprecated/DeprecatedMapperWithClass.java | 13 ++++
.../DeprecatedMapperWithMethod.java | 44 +++++++++++++
.../deprecated/DeprecatedTest.java | 56 +++++++++++++++++
.../deprecated/RepeatDeprecatedMapper.java | 15 +++++
.../jdk11/DeprecatedMapperWithClass.java | 13 ++++
.../jdk11/DeprecatedMapperWithMethod.java | 44 +++++++++++++
.../deprecated/jdk11/DeprecatedTest.java | 63 +++++++++++++++++++
.../RepeatDeprecatedMapperWithParams.java | 21 +++++++
13 files changed, 314 insertions(+), 2 deletions(-)
create mode 100644 processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedMapperWithClass.java
create mode 100644 processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedMapperWithMethod.java
create mode 100644 processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedTest.java
create mode 100644 processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/RepeatDeprecatedMapper.java
create mode 100644 processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedMapperWithClass.java
create mode 100644 processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedMapperWithMethod.java
create mode 100644 processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedTest.java
create mode 100644 processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/RepeatDeprecatedMapperWithParams.java
diff --git a/integrationtest/src/test/java/org/mapstruct/itest/tests/FullFeatureCompilationExclusionCliEnhancer.java b/integrationtest/src/test/java/org/mapstruct/itest/tests/FullFeatureCompilationExclusionCliEnhancer.java
index 0f261d656..e017d1b00 100644
--- a/integrationtest/src/test/java/org/mapstruct/itest/tests/FullFeatureCompilationExclusionCliEnhancer.java
+++ b/integrationtest/src/test/java/org/mapstruct/itest/tests/FullFeatureCompilationExclusionCliEnhancer.java
@@ -31,6 +31,7 @@ public final class FullFeatureCompilationExclusionCliEnhancer implements Process
case JAVA_8:
additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/cdi/**/*.java" );
additionalExcludes.add( "org/mapstruct/ap/test/injectionstrategy/jakarta_cdi/**/*.java" );
+ additionalExcludes.add( "org/mapstruct/ap/test/annotatewith/deprecated/jdk11/*.java" );
break;
case JAVA_9:
// TODO find out why this fails:
diff --git a/integrationtest/src/test/resources/fullFeatureTest/pom.xml b/integrationtest/src/test/resources/fullFeatureTest/pom.xml
index ac69114bd..8a62f4858 100644
--- a/integrationtest/src/test/resources/fullFeatureTest/pom.xml
+++ b/integrationtest/src/test/resources/fullFeatureTest/pom.xml
@@ -25,6 +25,7 @@
x
x
x
+ x
@@ -45,6 +46,7 @@
${additionalExclude2}
${additionalExclude3}
${additionalExclude4}
+ ${additionalExclude5}
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/gem/GemGenerator.java b/processor/src/main/java/org/mapstruct/ap/internal/gem/GemGenerator.java
index cbb59f4e5..5caea8a00 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/gem/GemGenerator.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/gem/GemGenerator.java
@@ -45,6 +45,7 @@ import org.mapstruct.tools.gem.GemDefinition;
*
* @author Gunnar Morling
*/
+@GemDefinition(Deprecated.class)
@GemDefinition(AnnotateWith.class)
@GemDefinition(AnnotateWith.Element.class)
@GemDefinition(AnnotateWiths.class)
diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/AdditionalAnnotationsBuilder.java b/processor/src/main/java/org/mapstruct/ap/internal/model/AdditionalAnnotationsBuilder.java
index f28cdfef9..3f0b2123a 100644
--- a/processor/src/main/java/org/mapstruct/ap/internal/model/AdditionalAnnotationsBuilder.java
+++ b/processor/src/main/java/org/mapstruct/ap/internal/model/AdditionalAnnotationsBuilder.java
@@ -10,6 +10,7 @@ import java.lang.annotation.Repeatable;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
@@ -31,6 +32,7 @@ import javax.lang.model.type.TypeMirror;
import org.mapstruct.ap.internal.gem.AnnotateWithGem;
import org.mapstruct.ap.internal.gem.AnnotateWithsGem;
+import org.mapstruct.ap.internal.gem.DeprecatedGem;
import org.mapstruct.ap.internal.gem.ElementGem;
import org.mapstruct.ap.internal.model.annotation.AnnotationElement;
import org.mapstruct.ap.internal.model.annotation.AnnotationElement.AnnotationElementType;
@@ -55,7 +57,6 @@ public class AdditionalAnnotationsBuilder
extends RepeatableAnnotations {
private static final String ANNOTATE_WITH_FQN = "org.mapstruct.AnnotateWith";
private static final String ANNOTATE_WITHS_FQN = "org.mapstruct.AnnotateWiths";
-
private TypeFactory typeFactory;
private FormattingMessager messager;
@@ -90,6 +91,45 @@ public class AdditionalAnnotationsBuilder
}
}
+ @Override
+ public Set getProcessedAnnotations(Element source) {
+ Set processedAnnotations = super.getProcessedAnnotations( source );
+ return addDeprecatedAnnotation( source, processedAnnotations );
+ }
+
+ private Set addDeprecatedAnnotation(Element source, Set annotations) {
+ DeprecatedGem deprecatedGem = DeprecatedGem.instanceOn( source );
+ if ( deprecatedGem == null ) {
+ return annotations;
+ }
+ Type deprecatedType = typeFactory.getType( Deprecated.class );
+ if ( annotations.stream().anyMatch( annotation -> annotation.getType().equals( deprecatedType ) ) ) {
+ messager.printMessage(
+ source,
+ deprecatedGem.mirror(),
+ Message.ANNOTATE_WITH_DUPLICATE,
+ deprecatedType.describe() );
+ return annotations;
+ }
+ List annotationElements = new ArrayList<>();
+ if ( deprecatedGem.since() != null && deprecatedGem.since().hasValue() ) {
+ annotationElements.add( new AnnotationElement(
+ AnnotationElementType.STRING,
+ "since",
+ Collections.singletonList( deprecatedGem.since().getValue() )
+ ) );
+ }
+ if ( deprecatedGem.forRemoval() != null && deprecatedGem.forRemoval().hasValue() ) {
+ annotationElements.add( new AnnotationElement(
+ AnnotationElementType.BOOLEAN,
+ "forRemoval",
+ Collections.singletonList( deprecatedGem.forRemoval().getValue() )
+ ) );
+ }
+ annotations.add( new Annotation(deprecatedType, annotationElements ) );
+ return annotations;
+ }
+
private void addAndValidateMapping(Set mappings, Element source, AnnotateWithGem gem, Annotation anno) {
if ( anno.getType().getTypeElement().getAnnotation( Repeatable.class ) == null ) {
if ( mappings.stream().anyMatch( existing -> existing.getType().equals( anno.getType() ) ) ) {
diff --git a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/AnnotateWithTest.java b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/AnnotateWithTest.java
index e3b20f547..3687fe2bc 100644
--- a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/AnnotateWithTest.java
+++ b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/AnnotateWithTest.java
@@ -593,5 +593,4 @@ public class AnnotateWithTest {
Method method = mapper.getClass().getMethod( "map", String.class );
assertThat( method.getAnnotation( CustomMethodOnlyAnnotation.class ) ).isNotNull();
}
-
}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedMapperWithClass.java b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedMapperWithClass.java
new file mode 100644
index 000000000..d0164e8be
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedMapperWithClass.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.test.annotatewith.deprecated;
+
+import org.mapstruct.Mapper;
+
+@Mapper
+@Deprecated
+public class DeprecatedMapperWithClass {
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedMapperWithMethod.java b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedMapperWithMethod.java
new file mode 100644
index 000000000..b6c2c8eb6
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedMapperWithMethod.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.test.annotatewith.deprecated;
+
+import org.mapstruct.AnnotateWith;
+import org.mapstruct.Mapper;
+import org.mapstruct.ap.test.annotatewith.CustomMethodOnlyAnnotation;
+
+@Mapper
+public interface DeprecatedMapperWithMethod {
+
+ @AnnotateWith(CustomMethodOnlyAnnotation.class)
+ @Deprecated
+ Target map(Source source);
+
+ class Source {
+
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+ }
+
+ class Target {
+
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedTest.java b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedTest.java
new file mode 100644
index 000000000..5abca7171
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/DeprecatedTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.test.annotatewith.deprecated;
+
+import java.lang.reflect.Method;
+import org.mapstruct.ap.test.annotatewith.CustomMethodOnlyAnnotation;
+import org.mapstruct.ap.testutil.ProcessorTest;
+import org.mapstruct.ap.testutil.WithClasses;
+import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
+import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
+import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
+import org.mapstruct.factory.Mappers;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author orange add
+ */
+public class DeprecatedTest {
+
+ @ProcessorTest
+ @WithClasses( { DeprecatedMapperWithMethod.class, CustomMethodOnlyAnnotation.class} )
+ public void deprecatedWithMethodCorrectCopy() throws NoSuchMethodException {
+ DeprecatedMapperWithMethod mapper = Mappers.getMapper( DeprecatedMapperWithMethod.class );
+ Method method = mapper.getClass().getMethod( "map", DeprecatedMapperWithMethod.Source.class );
+ Deprecated annotation = method.getAnnotation( Deprecated.class );
+ assertThat( annotation ).isNotNull();
+ }
+
+ @ProcessorTest
+ @WithClasses(DeprecatedMapperWithClass.class)
+ public void deprecatedWithClassCorrectCopy() {
+ DeprecatedMapperWithClass mapper = Mappers.getMapper( DeprecatedMapperWithClass.class );
+ Deprecated annotation = mapper.getClass().getAnnotation( Deprecated.class );
+ assertThat( annotation ).isNotNull();
+ }
+
+ @ProcessorTest
+ @WithClasses(RepeatDeprecatedMapper.class)
+ @ExpectedCompilationOutcome(
+ value = CompilationResult.SUCCEEDED,
+ diagnostics = {
+ @Diagnostic(
+ kind = javax.tools.Diagnostic.Kind.WARNING,
+ type = RepeatDeprecatedMapper.class,
+ message = "Annotation \"Deprecated\" is already present with the " +
+ "same elements configuration."
+ )
+ }
+ )
+ public void deprecatedWithRepeat() {
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/RepeatDeprecatedMapper.java b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/RepeatDeprecatedMapper.java
new file mode 100644
index 000000000..dd085f101
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/RepeatDeprecatedMapper.java
@@ -0,0 +1,15 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.test.annotatewith.deprecated;
+
+import org.mapstruct.AnnotateWith;
+import org.mapstruct.Mapper;
+
+@Mapper
+@Deprecated
+@AnnotateWith(Deprecated.class)
+public class RepeatDeprecatedMapper {
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedMapperWithClass.java b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedMapperWithClass.java
new file mode 100644
index 000000000..2e0507f5a
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedMapperWithClass.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.test.annotatewith.deprecated.jdk11;
+
+import org.mapstruct.Mapper;
+
+@Mapper
+@Deprecated(since = "11")
+public class DeprecatedMapperWithClass {
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedMapperWithMethod.java b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedMapperWithMethod.java
new file mode 100644
index 000000000..bf898e204
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedMapperWithMethod.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.test.annotatewith.deprecated.jdk11;
+
+import org.mapstruct.AnnotateWith;
+import org.mapstruct.Mapper;
+import org.mapstruct.ap.test.annotatewith.CustomMethodOnlyAnnotation;
+
+@Mapper
+public interface DeprecatedMapperWithMethod {
+
+ @AnnotateWith(CustomMethodOnlyAnnotation.class)
+ @Deprecated(since = "18", forRemoval = false)
+ Target map(Source source);
+
+ class Source {
+
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+ }
+
+ class Target {
+
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedTest.java b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedTest.java
new file mode 100644
index 000000000..4e10b6ded
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/DeprecatedTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.test.annotatewith.deprecated.jdk11;
+
+import java.lang.reflect.Method;
+import org.mapstruct.ap.test.annotatewith.CustomMethodOnlyAnnotation;
+import org.mapstruct.ap.testutil.ProcessorTest;
+import org.mapstruct.ap.testutil.WithClasses;
+import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
+import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
+import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
+import org.mapstruct.factory.Mappers;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author orange add
+ */
+public class DeprecatedTest {
+ @ProcessorTest
+ @WithClasses({ DeprecatedMapperWithMethod.class, CustomMethodOnlyAnnotation.class})
+ public void deprecatedWithMethodCorrectCopyForJdk11() throws NoSuchMethodException {
+ DeprecatedMapperWithMethod mapper = Mappers.getMapper( DeprecatedMapperWithMethod.class );
+ Method method = mapper.getClass().getMethod( "map", DeprecatedMapperWithMethod.Source.class );
+ Deprecated annotation = method.getAnnotation( Deprecated.class );
+ assertThat( annotation ).isNotNull();
+ assertThat( annotation.since() ).isEqualTo( "18" );
+ assertThat( annotation.forRemoval() ).isEqualTo( false );
+ }
+
+ @ProcessorTest
+ @WithClasses(DeprecatedMapperWithClass.class)
+ public void deprecatedWithClassCorrectCopyForJdk11() {
+ DeprecatedMapperWithClass mapper = Mappers.getMapper( DeprecatedMapperWithClass.class );
+ Deprecated annotation = mapper.getClass().getAnnotation( Deprecated.class );
+ assertThat( annotation ).isNotNull();
+ assertThat( annotation.since() ).isEqualTo( "11" );
+ }
+
+ @ProcessorTest
+ @WithClasses( { RepeatDeprecatedMapperWithParams.class})
+ @ExpectedCompilationOutcome(
+ value = CompilationResult.SUCCEEDED,
+ diagnostics = {
+ @Diagnostic(
+ kind = javax.tools.Diagnostic.Kind.WARNING,
+ type = RepeatDeprecatedMapperWithParams.class,
+ message = "Annotation \"Deprecated\" is already present with the " +
+ "same elements configuration."
+ )
+ }
+ )
+ public void bothExistPriorityAnnotateWithForJdk11() {
+ RepeatDeprecatedMapperWithParams mapper = Mappers.getMapper( RepeatDeprecatedMapperWithParams.class );
+ Deprecated deprecated = mapper.getClass().getAnnotation( Deprecated.class );
+ assertThat( deprecated ).isNotNull();
+ assertThat( deprecated.since() ).isEqualTo( "1.5" );
+ assertThat( deprecated.forRemoval() ).isEqualTo( false );
+ }
+}
diff --git a/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/RepeatDeprecatedMapperWithParams.java b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/RepeatDeprecatedMapperWithParams.java
new file mode 100644
index 000000000..971791bfd
--- /dev/null
+++ b/processor/src/test/java/org/mapstruct/ap/test/annotatewith/deprecated/jdk11/RepeatDeprecatedMapperWithParams.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright MapStruct Authors.
+ *
+ * Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
+ */
+package org.mapstruct.ap.test.annotatewith.deprecated.jdk11;
+
+import org.mapstruct.AnnotateWith;
+import org.mapstruct.Mapper;
+
+@Mapper
+@Deprecated( since = "1.8" )
+@AnnotateWith(
+ value = Deprecated.class,
+ elements = {
+ @AnnotateWith.Element( name = "forRemoval", booleans = false),
+ @AnnotateWith.Element( name = "since", strings = "1.5")
+ }
+)
+public class RepeatDeprecatedMapperWithParams {
+}