Skip to content

Conversation

@chenzijia12300
Copy link
Contributor

@chenzijia12300 chenzijia12300 commented Aug 29, 2022

Fixes #2773

Copy link
Member

@filiphr filiphr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for your patience @chenzijia12300. This PR now looks really clean 😄. I've left one comment about the error, which I think that we should not be that strict.

In addition to the comment, can you please revert the changes you've done with the imports in the AdditionalAnnotationsBuilder and try to keep the same order as it was before. We do have some IDE specific settings in https://github.com/mapstruct/mapstruct/blob/main/etc that you can use to have the right formatting and import order. If you are using IntelliJ then you can import https://github.com/mapstruct/mapstruct/blob/main/etc/mapstruct.xml as a code style.

annotationMirror.getAnnotationType().asElement().toString() ) ).findFirst();
if (optionalAnnotationMirror.isPresent() &&
annotations.stream().anyMatch( annotation -> annotation.getType().equals( deprecatedType ) ) ) {
messager.printMessage(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that for this particular case we don't have to add an error. We can have a warning that is saying that the method is already using @AnnotateWith(Deprecated.class) and that doing it twice is obsolete.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@filiphr , should the warning take into account the situation where the @Deprecation and the @AnnotateWith don't match?

for example:

@Deprecated( since = "1.5" )
@AnnotateWith(
    value = Deprecated.class,
    elements = {
        @Element( name = "forRemoval", boolean = true ),
        @Element( name = "since", string = "1.5.0" )
    }
)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so when there is a duplicate definition, a warning is raised and the type defined in @AnnotateWith(Deprecated.class) is returned

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so when there is a duplicate definition, a warning is raised and the type defined in @AnnotateWith(Deprecated.class) is returned

@filiphr filiphr mentioned this pull request Aug 29, 2022
@Zegveld
Copy link
Contributor

Zegveld commented Aug 29, 2022

I'm missing the 2 annotation elements of @Deprecated: since and forRemoval.

Using a Gem for the annotation will allow you to find the values of these.
You will need to add Deprecated to the GemGenerator class so that it becomes available for usage.
Another advantage of using Gem is that you do not need to search for the deprecation annotation yourself but the generated Gem has methods that do this for you.

@chenzijia12300
Copy link
Contributor Author

Thank you for your guidance😊

@Zegveld
Copy link
Contributor

Zegveld commented Aug 30, 2022

Just looked at the reason the JDK 8 tests failed.
I totally missed this, but the since and forRemoval annotation elements are only available since java 9.
So some of the tests must be annotated that they require at least java 11, while the others also work with java 8.
@EnabledForJreRange(min = JRE.JAVA_11)
This might also require some tests to be near duplicates, one without the annotation elements for java 8+ and one with for java 11+.

@chenzijia12300
Copy link
Contributor Author

chenzijia12300 commented Aug 31, 2022

Just looked at the reason the JDK 8 tests failed. I totally missed this, but the since and forRemoval annotation elements are only available since java 9. So some of the tests must be annotated that they require at least java 11, while the others also work with java 8. @EnabledForJreRange(min = JRE.JAVA_11) This might also require some tests to be near duplicates, one without the annotation elements for java 8+ and one with for java 11+.

Thanks for the suggestion, I'm having a problem with how to exclude certain classes from compiling in a particular JDK version. I think @EnabledForJreRange only prevents the execution of the test class or test method, it does not prevent the compilation of the class.
I see a FullFeatureCompilationExclusionCliEnhancer class, please can be here for the specific class compilation exclusion?

@filiphr
Copy link
Member

filiphr commented Aug 31, 2022

I think @EnabledForJreRange only prevents the execution of the test class or test method, it does not prevent the compilation of the class.

Indeed that prevents the execution of a specific test class or test method. The processors tests are not run with Java 8, they are only run with Java 11 and later.

I see a FullFeatureCompilationExclusionCliEnhancer class, please can be here for the specific class compilation exclusion?

Spot on @chenzijia12300. That class is the one that can add additional excludes for the full feature integration test. Keep in mind that you most likely will also need to add an additionalExclude in

<properties>
<additionalExclude0>x</additionalExclude0>
<additionalExclude1>x</additionalExclude1>
<additionalExclude2>x</additionalExclude2>
<additionalExclude3>x</additionalExclude3>
<additionalExclude4>x</additionalExclude4>
</properties>

and

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/erroneous/**/*.java</exclude>
<exclude>**/*Erroneous*.java</exclude>
<exclude>**/*Test.java</exclude>
<exclude>**/testutil/**/*.java</exclude>
<exclude>**/spi/**/*.java</exclude>
<exclude>${additionalExclude0}</exclude>
<exclude>${additionalExclude1}</exclude>
<exclude>${additionalExclude2}</exclude>
<exclude>${additionalExclude3}</exclude>
<exclude>${additionalExclude4}</exclude>
</excludes>
</configuration>
</plugin>

@chenzijia12300
Copy link
Contributor Author

Spot on @chenzijia12300. That class is the one that can add additional excludes for the full feature integration test. Keep in mind that you most likely will also need to add an additionalExclude in

Thank you for the tip 😊

Copy link
Member

@filiphr filiphr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes @chenzijia12300. Few more tiny changes and we are ready to merge this.

/**
* @author orange add
*/
public class DeprecatedTest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that there is some small misunderstanding of the use of the integration fullFeatureTest.

The full feature integration test does nothing more than compiling all the mappers that are in our processor test module. However, it doesn't run any tests on its own.

In addition to that, our processor tests are currently only running with Java 11 and later. Which means that we can easily move this test to the package above org.mapstruct.ap.test.annotatewith.deprecated and remove the one from org.mapstruct.ap.test.annotatewith.deprecated.older. I would also remove the @EnabledForJreRange from this tests, since it is not needed.

Can we also please change the names of the mappers a bit. e.g. everything from the older package can just be moved to the package above org.mapstruct.ap.test.annotatewith.deprecated and the prefix Older can be removed. Everything in the newer package can be moved to a different package called java11, remove the prefix Newer and do things like DeprecatedWithAttributesMapper, etc.

I am asking for this in order to reduce some of the additional test complexity and to be immediately clear when someone reads the names of the classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your patient guidance, I will correct it

return annotations;
}
List<AnnotationElement> annotationElements = new ArrayList<>();
for ( Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : deprecatedGem.mirror()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't really need to use the mirror and strings for this. The DeprecatedGem should have methods that allow to have access to the values. You can rewrite the loop to:

if ( deprecatedGem.since().hasValue() ) {
    annotationElements.add( new AnnotationElement(
        AnnotationElementType.STRING,
        "since",
        Collections.singletonList( deprecatedGem.since().getValue() )
    ) );
}
        
if ( deprecatedGem.forRemoval().hasValue() ) {
    annotationElements.add( new AnnotationElement(
        AnnotationElementType.BOOLEAN,
        "forRemoval",
        Collections.singletonList( deprecatedGem.forRemoval().getValue() )
    ) );
}

Copy link
Member

@filiphr filiphr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks for all the changes @chenzijia12300. @Zegveld do you have anything extra to add or can I merge this?

@filiphr filiphr merged commit e979f50 into mapstruct:main Sep 28, 2022
@filiphr
Copy link
Member

filiphr commented Sep 28, 2022

Thanks @chenzijia12300. We've integrated this into main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Copy @Deprecated annotation from method or mapper to implementation

3 participants