From 22bbff5bb474865b4bd6780d8bc1b885caf015c0 Mon Sep 17 00:00:00 2001 From: hduelme Date: Mon, 12 Oct 2026 23:10:57 +0200 Subject: [PATCH] add InheritConfigurationNameReference --- README.md | 3 + description.html | 3 + .../InheritConfigurationNameReference.java | 209 ++++++++++++++++++ .../MapstructReferenceContributor.java | 11 + .../MapstructReferenceInspection.java | 6 + .../InheritConfigurationUtils.java | 2 +- .../intellij/util/MapstructElementUtils.java | 19 ++ .../messages/MapStructBundle.properties | 2 + ...nheritConfigurationCompletionTestCase.java | 98 ++++++++ .../MapstructReferenceInspectionTest.java | 16 ++ .../InheritConfigurationByNameCompletion.java | 33 +++ ...nfigurationWithMapperConfigCompletion.java | 36 +++ ...tInverseConfigurationByNameCompletion.java | 29 +++ ...onfigurationWithMapperConfigReference.java | 58 +++++ ...nownInheritConfigurationNameReference.java | 52 +++++ ...nfigurationNameReferenceWithMapSource.java | 52 +++++ ...eritInverseConfigurationNameReference.java | 50 +++++ 17 files changed, 678 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/mapstruct/intellij/codeinsight/references/InheritConfigurationNameReference.java create mode 100644 src/test/java/org/mapstruct/intellij/completion/InheritConfigurationCompletionTestCase.java create mode 100644 testData/completion/inheritconfiguration/InheritConfigurationByNameCompletion.java create mode 100644 testData/completion/inheritconfiguration/InheritConfigurationWithMapperConfigCompletion.java create mode 100644 testData/completion/inheritconfiguration/InheritInverseConfigurationByNameCompletion.java create mode 100644 testData/inspection/InheritConfigurationWithMapperConfigReference.java create mode 100644 testData/inspection/UnknownInheritConfigurationNameReference.java create mode 100644 testData/inspection/UnknownInheritConfigurationNameReferenceWithMapSource.java create mode 100644 testData/inspection/UnknownInheritInverseConfigurationNameReference.java diff --git a/README.md b/README.md index 000ea87d..c1c16d24 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,10 @@ To learn more about MapStruct have a look at the [mapstruct](https://github.com/ * Completion of `target` and `source` properties in `@ValueMapping` annotation * Completion of `componentModel` in `@Mapper` and `@MapperConfig` annotations * Completion of `qualifiedByName` in `@Mapping` annotation + * Completion of `name` in `@InheritConfiguration` and `@InheritInverseConfiguration` annotations * Go To Declaration for properties in `target` and `source` to setters / getters * Go To Declaration for `Mapping#qualifiedByName` +* Go To Declaration for `name` in `@InheritConfiguration` and `@InheritInverseConfiguration` annotations * Find usages of properties in `target` and `source` and find usages of setters / getters in `@Mapping` annotations * Highlighting properties in `target` and `source` * Errors and Quick fixes: @@ -41,6 +43,7 @@ To learn more about MapStruct have a look at the [mapstruct](https://github.com/ * `*` used as a source in `@Mapping` annotation with quick fixes: Replace `*` with method parameter name. * Unknown reference inspection for `source` and `target` in `@Mapping` and `@ValueMapping` annotation. * Unknown reference inspection for `qualifiedByName` in `@Mapping` annotation + * Unknown reference inspection for `name` in `@InheritConfiguration` and `@InheritInverseConfiguration` annotations ## Requirements diff --git a/description.html b/description.html index 7c30808c..efc133c7 100644 --- a/description.html +++ b/description.html @@ -25,11 +25,13 @@
  • Completion of target and source properties in @ValueMapping annotation
  • Completion of componentModel in @Mapper and @MapperConfig annotations
  • Completion of qualifiedByName in @Mapping annotation
  • +
  • Completion of name in @InheritConfiguration and @InheritInverseConfiguration annotations
  • Go To Declaration for properties in target and source to setters / getters
  • Find usages of properties in target and source and find usages of setters / getters in @Mapping annotations
  • Go To Declaration for Mapping#qualifiedByName
  • +
  • Go To Declaration for name in @InheritConfiguration and @InheritInverseConfiguration annotations
  • Highlighting properties in target and source
  • Refactoring support for properties and methods renaming
  • Errors and Quick Fixes:
  • @@ -45,6 +47,7 @@
  • * used as a source in @Mapping annotations with quick fixes: Replace * with method parameter name.
  • Unknown reference inspection for source and target in @Mapping and @ValueMapping annotation.
  • Unknown reference inspection for qualifiedByName in @Mapping annotation.
  • +
  • Unknown reference inspection for name in @InheritConfiguration and @InheritInverseConfiguration annotations.
  • diff --git a/src/main/java/org/mapstruct/intellij/codeinsight/references/InheritConfigurationNameReference.java b/src/main/java/org/mapstruct/intellij/codeinsight/references/InheritConfigurationNameReference.java new file mode 100644 index 00000000..734c9b36 --- /dev/null +++ b/src/main/java/org/mapstruct/intellij/codeinsight/references/InheritConfigurationNameReference.java @@ -0,0 +1,209 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.intellij.codeinsight.references; + +import java.util.Arrays; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiParameter; +import com.intellij.psi.PsiReference; +import com.intellij.psi.PsiType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.mapstruct.intellij.MapStructBundle; +import org.mapstruct.intellij.inspection.inheritance.SourceMethod; + +import static org.mapstruct.intellij.inspection.inheritance.InheritConfigurationUtils.findMappingMethodsFromInheritScope; +import static org.mapstruct.intellij.util.MapstructUtil.MAPPER_ANNOTATION_FQN; +import static org.mapstruct.intellij.util.MapstructUtil.asLookupWithRepresentableText; +import static org.mapstruct.intellij.util.TargetUtils.getRelevantType; + +/** + * Reference for {@link org.mapstruct.InheritConfiguration#name()} and + * {@link org.mapstruct.InheritInverseConfiguration#name()}. + * + * @author hduelme + */ +public class InheritConfigurationNameReference extends MapstructBaseReference { + + private final boolean inverse; + + /** + * Create a new {@link InheritConfigurationNameReference} with the provided parameters + * + * @param element the element that the reference belongs to + * @param previousReference the previous reference if there is one (in nested properties for example) + * @param rangeInElement the range that the reference represent in the {@code element} + * @param value the matched value (useful when {@code rangeInElement} is empty) + * @param inverse whether this is the inverse variant ({@link org.mapstruct.InheritInverseConfiguration}) + */ + private InheritConfigurationNameReference(PsiElement element, + InheritConfigurationNameReference previousReference, + TextRange rangeInElement, + String value, + boolean inverse) { + super( element, previousReference, rangeInElement, value ); + this.inverse = inverse; + } + + @Override + PsiElement resolveInternal(@NotNull String value, @NotNull PsiType psiType) { + return null; // not needed + } + + @Override + PsiElement resolveInternal(@NotNull String value, @NotNull PsiMethod mappingMethod) { + + java.util.List namedCandidates = candidatesInScope( mappingMethod ) + .filter( candidate -> value.equals( candidate.getName() ) ) + .distinct() + .toList(); + + // Match the disambiguation rule of InheritConfigurationUtils#getResultMethod: + // a name value is only valid if it identifies exactly one in-scope candidate. + if ( namedCandidates.size() != 1 ) { + return null; + } + + return namedCandidates.getFirst().getNameIdentifier(); + } + + @NotNull + private Stream candidatesInScope(@NotNull PsiMethod mappingMethod) { + return inScopeMethods( mappingMethod ) + .filter( candidateFilter( mappingMethod ) ) + .filter( m -> !m.equals( mappingMethod ) ) + .distinct(); + } + + @NotNull + @Override + Object[] getVariantsInternal(@NotNull PsiType psiType) { + return LookupElement.EMPTY_ARRAY; // not needed + } + + @NotNull + @Override + Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod) { + return candidatesInScope( mappingMethod ) + .map( this::methodAsLookup ) + .filter( Objects::nonNull ) + .toArray(); + } + + @Nullable + private LookupElement methodAsLookup(@NotNull PsiMethod method) { + String lookupString = method.getName(); + if ( lookupString.isEmpty() ) { + return null; + } + + PsiClass containingClass = method.getContainingClass(); + String classSimpleName = containingClass != null ? containingClass.getName() : "?"; + + return asLookupWithRepresentableText( + method, + lookupString, + lookupString, + String.format( + " %s#%s(%s)", + classSimpleName, + method.getName(), + formatParameters( method ) + ) + ); + } + + @NotNull + private Stream inScopeMethods(@NotNull PsiMethod mappingMethod) { + PsiClass containingClass = mappingMethod.getContainingClass(); + if ( containingClass == null ) { + return Stream.empty(); + } + + PsiAnnotation mapperAnnotation = containingClass.getAnnotation( MAPPER_ANNOTATION_FQN ); + if ( mapperAnnotation == null ) { + return Stream.empty(); + } + + return findMappingMethodsFromInheritScope( containingClass, mapperAnnotation ); + } + + @NotNull + private Predicate candidateFilter(@NotNull PsiMethod mappingMethod) { + PsiType targetType = getRelevantType( mappingMethod ); + SourceMethod sourceMethod = new SourceMethod( mappingMethod ); + if ( inverse ) { + return candidate -> candidate.getBody() == null && sourceMethod.inverses( candidate, targetType ); + } + return candidate -> candidate.getBody() == null && sourceMethod.canInheritFrom( candidate, targetType ); + } + + @NotNull + private static String formatParameters(@NotNull PsiMethod method) { + return Arrays.stream( method.getParameterList().getParameters() ) + .map( PsiParameter::getType ) + .map( PsiType::getPresentableText ) + .collect( java.util.stream.Collectors.joining( ", " ) ); + } + + @Nullable + @Override + PsiType resolvedType() { + return null; + } + + @NotNull + @Override + public String getUnresolvedMessagePattern() { + return MapStructBundle.message( + inverse ? "unknown.inheritInverseConfiguration.reference" : "unknown.inheritConfiguration.reference" + ); + } + + /** + * @param psiElement the literal for which references need to be created + * @return the references for the given {@code psiLiteral} + */ + static PsiReference[] createForward(PsiElement psiElement) { + return MapstructBaseReference.create( psiElement, + InheritConfigurationNameReference::newForward, + false ); + } + + /** + * @param psiElement the literal for which references need to be created + * @return the references for the given {@code psiLiteral} + */ + static PsiReference[] createInverse(PsiElement psiElement) { + return MapstructBaseReference.create( psiElement, + InheritConfigurationNameReference::newInverse, + false ); + } + + private static InheritConfigurationNameReference newForward(PsiElement element, + InheritConfigurationNameReference previous, + TextRange range, + String value) { + return new InheritConfigurationNameReference( element, previous, range, value, false ); + } + + private static InheritConfigurationNameReference newInverse(PsiElement element, + InheritConfigurationNameReference previous, + TextRange range, + String value) { + return new InheritConfigurationNameReference( element, previous, range, value, true ); + } + +} diff --git a/src/main/java/org/mapstruct/intellij/codeinsight/references/MapstructReferenceContributor.java b/src/main/java/org/mapstruct/intellij/codeinsight/references/MapstructReferenceContributor.java index f2edb1fc..96d25e85 100644 --- a/src/main/java/org/mapstruct/intellij/codeinsight/references/MapstructReferenceContributor.java +++ b/src/main/java/org/mapstruct/intellij/codeinsight/references/MapstructReferenceContributor.java @@ -10,6 +10,8 @@ import org.jetbrains.annotations.NotNull; import static org.mapstruct.intellij.util.MapstructElementUtils.beanMappingElementPattern; +import static org.mapstruct.intellij.util.MapstructElementUtils.inheritConfigurationElementPattern; +import static org.mapstruct.intellij.util.MapstructElementUtils.inheritInverseConfigurationElementPattern; import static org.mapstruct.intellij.util.MapstructElementUtils.mappingElementPattern; import static org.mapstruct.intellij.util.MapstructElementUtils.valueMappingElementPattern; @@ -48,6 +50,15 @@ public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) valueMappingElementPattern( "target" ), new MappingTargetReferenceProvider( ValueMappingTargetReference::create ) ); + + registrar.registerReferenceProvider( + inheritConfigurationElementPattern( "name" ), + new MappingTargetReferenceProvider( InheritConfigurationNameReference::createForward ) + ); + registrar.registerReferenceProvider( + inheritInverseConfigurationElementPattern( "name" ), + new MappingTargetReferenceProvider( InheritConfigurationNameReference::createInverse ) + ); } } diff --git a/src/main/java/org/mapstruct/intellij/inspection/MapstructReferenceInspection.java b/src/main/java/org/mapstruct/intellij/inspection/MapstructReferenceInspection.java index d96ecf2c..364d5e23 100644 --- a/src/main/java/org/mapstruct/intellij/inspection/MapstructReferenceInspection.java +++ b/src/main/java/org/mapstruct/intellij/inspection/MapstructReferenceInspection.java @@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nullable; import org.mapstruct.intellij.codeinsight.references.BaseReference; import org.mapstruct.intellij.codeinsight.references.BaseValueMappingReference; +import org.mapstruct.intellij.codeinsight.references.InheritConfigurationNameReference; import org.mapstruct.intellij.util.MapstructUtil; /** @@ -75,6 +76,11 @@ private boolean shouldRegisterProblem(BaseReference reference) { return valueMappingReference.getEnumClass() != null; } + if ( reference instanceof InheritConfigurationNameReference ) { + // The name attribute references a method name, not a property that could be a map key. + return true; + } + if ( hasSingleStringKeyMapSourceParameter( reference.getMappingMethod() ) ) { // MapStruct allows source values as map keys, even if they are not resolvable as Java properties. // Therefore, we don't report an unresolved reference problem here. diff --git a/src/main/java/org/mapstruct/intellij/inspection/inheritance/InheritConfigurationUtils.java b/src/main/java/org/mapstruct/intellij/inspection/inheritance/InheritConfigurationUtils.java index 06f8e146..84f1573f 100644 --- a/src/main/java/org/mapstruct/intellij/inspection/inheritance/InheritConfigurationUtils.java +++ b/src/main/java/org/mapstruct/intellij/inspection/inheritance/InheritConfigurationUtils.java @@ -294,7 +294,7 @@ private static Set getApplicablePrototypeMethods(SourceMethod mapp * @param mapperAnnotation the mapper annotation of the containing class * @return possible mapping methods to be inherited from */ - private static Stream findMappingMethodsFromInheritScope(@NotNull PsiClass containingClass, + public static Stream findMappingMethodsFromInheritScope(@NotNull PsiClass containingClass, @NotNull PsiAnnotation mapperAnnotation) { Stream localAndParentMethods = Arrays.stream( containingClass.getAllMethods() ); diff --git a/src/main/java/org/mapstruct/intellij/util/MapstructElementUtils.java b/src/main/java/org/mapstruct/intellij/util/MapstructElementUtils.java index 7d041c20..ac0c5cdc 100644 --- a/src/main/java/org/mapstruct/intellij/util/MapstructElementUtils.java +++ b/src/main/java/org/mapstruct/intellij/util/MapstructElementUtils.java @@ -69,6 +69,25 @@ public static PsiJavaElementPattern.Capture beanMappingElementPatter return elementPattern( parameterName, MapstructUtil.BEAN_MAPPING_FQN ); } + /** + * @param parameterName the name of the parameter in the {@code @InheritConfiguration} annotation + * + * @return an element pattern for a parameter in the {@code @InheritConfiguration} annotation + */ + public static PsiJavaElementPattern.Capture inheritConfigurationElementPattern(String parameterName) { + return elementPattern( parameterName, MapstructUtil.INHERIT_CONFIGURATION_FQN ); + } + + /** + * @param parameterName the name of the parameter in the {@code @InheritInverseConfiguration} annotation + * + * @return an element pattern for a parameter in the {@code @InheritInverseConfiguration} annotation + */ + public static PsiJavaElementPattern.Capture inheritInverseConfigurationElementPattern( + String parameterName) { + return elementPattern( parameterName, MapstructUtil.INHERIT_INVERSE_CONFIGURATION_FQN ); + } + private static PsiJavaElementPattern.Capture elementPattern(String parameterName, String annotationFQN) { return psiElement() diff --git a/src/main/resources/org/mapstruct/intellij/messages/MapStructBundle.properties b/src/main/resources/org/mapstruct/intellij/messages/MapStructBundle.properties index 9a5608bd..7b51e5f4 100644 --- a/src/main/resources/org/mapstruct/intellij/messages/MapStructBundle.properties +++ b/src/main/resources/org/mapstruct/intellij/messages/MapStructBundle.properties @@ -47,3 +47,5 @@ plugin.settings.quickFix.preferSourceBeforeTargetInMapping=Prefer source before unknown.property=Unknown property ''{0}'' unknown.enum.constant=Unknown enum constant ''{0}'' unknown.qualifiedByName.reference=Unknown @Named reference ''{0}'' +unknown.inheritConfiguration.reference=Unknown @InheritConfiguration method ''{0}'' +unknown.inheritInverseConfiguration.reference=Unknown @InheritInverseConfiguration method ''{0}'' diff --git a/src/test/java/org/mapstruct/intellij/completion/InheritConfigurationCompletionTestCase.java b/src/test/java/org/mapstruct/intellij/completion/InheritConfigurationCompletionTestCase.java new file mode 100644 index 00000000..3bbc7206 --- /dev/null +++ b/src/test/java/org/mapstruct/intellij/completion/InheritConfigurationCompletionTestCase.java @@ -0,0 +1,98 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.intellij.completion; + +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementPresentation; +import org.mapstruct.intellij.MapstructBaseCompletionTestCase; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mapstruct.intellij.testutil.TestUtils.createMethod; + +public class InheritConfigurationCompletionTestCase extends MapstructBaseCompletionTestCase { + + @Override + protected String getTestDataPath() { + return "testData/completion/inheritconfiguration"; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + addDirectoryToProject( "../../mapping/dto" ); + } + + public void testInheritConfigurationByNameCompletion() { + configureByTestName(); + assertThat( myItems ) + .extracting( LookupElement::getLookupString ) + .containsExactlyInAnyOrder( "carDtoToCarIgnoringSeatCount", "carDtoToCarIgnoringManufacturingDate" ); + + assertThat( myItems ) + .extracting( LookupElementPresentation::renderElement ) + .usingRecursiveFieldByFieldElementComparator() + .containsExactlyInAnyOrder( + createMethod( + "carDtoToCarIgnoringSeatCount", + "Car", + " InheritConfigurationCompletion#carDtoToCarIgnoringSeatCount(CarDto)" + ), + createMethod( + "carDtoToCarIgnoringManufacturingDate", + "Car", + " InheritConfigurationCompletion#carDtoToCarIgnoringManufacturingDate(CarDto)" + ) + ); + } + + public void testInheritConfigurationWithMapperConfigCompletion() { + configureByTestName(); + assertThat( myItems ) + .extracting( LookupElement::getLookupString ) + .containsExactlyInAnyOrder( "configSourceToTarget", "configSourceToTargetIgnoringSeats" ); + + assertThat( myItems ) + .extracting( LookupElementPresentation::renderElement ) + .usingRecursiveFieldByFieldElementComparator() + .containsExactlyInAnyOrder( + createMethod( + "configSourceToTarget", + "Car", + " ConfigCompleteMapperConfig#configSourceToTarget(CarDto)" + ), + createMethod( + "configSourceToTargetIgnoringSeats", + "Car", + " ConfigCompleteMapperConfig#configSourceToTargetIgnoringSeats(CarDto)" + ) + ); + } + + public void testInheritInverseConfigurationByNameCompletion() { + configureByTestName(); + assertThat( myItems ) + .extracting( LookupElement::getLookupString ) + .containsExactlyInAnyOrder( "carToCarDto", "carToCarDtoIgnoringDriver" ); + + assertThat( myItems ) + .extracting( LookupElementPresentation::renderElement ) + .usingRecursiveFieldByFieldElementComparator() + .containsExactlyInAnyOrder( + createMethod( + "carToCarDto", + "CarDto", + " InheritInverseConfigurationByNameCompletion#carToCarDto(Car)" + ), + createMethod( + "carToCarDtoIgnoringDriver", + "CarDto", + " InheritInverseConfigurationByNameCompletion#carToCarDtoIgnoringDriver(Car)" + ) + ); + } + +} diff --git a/src/test/java/org/mapstruct/intellij/inspection/MapstructReferenceInspectionTest.java b/src/test/java/org/mapstruct/intellij/inspection/MapstructReferenceInspectionTest.java index 97703559..67c2ec1f 100644 --- a/src/test/java/org/mapstruct/intellij/inspection/MapstructReferenceInspectionTest.java +++ b/src/test/java/org/mapstruct/intellij/inspection/MapstructReferenceInspectionTest.java @@ -49,4 +49,20 @@ public void testUnknownIgnoreUnmappedSourceReference() { public void testUnknownQualifiedByNameReferenceReference() { doTest(); } + + public void testUnknownInheritConfigurationNameReference() { + doTest(); + } + + public void testUnknownInheritConfigurationNameReferenceWithMapSource() { + doTest(); + } + + public void testUnknownInheritInverseConfigurationNameReference() { + doTest(); + } + + public void testInheritConfigurationWithMapperConfigReference() { + doTest(); + } } diff --git a/testData/completion/inheritconfiguration/InheritConfigurationByNameCompletion.java b/testData/completion/inheritconfiguration/InheritConfigurationByNameCompletion.java new file mode 100644 index 00000000..819d8b5c --- /dev/null +++ b/testData/completion/inheritconfiguration/InheritConfigurationByNameCompletion.java @@ -0,0 +1,33 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.complex; + +import org.example.dto.Car; +import org.example.dto.CarDto; +import org.mapstruct.InheritConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.ReportingPolicy; + +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN) +public interface InheritConfigurationCompletion { + + @Mapping(target = "numberOfSeats", ignore = true) + @Mapping(target = "manufacturingDate", source = "manufacturingYear") + @Mapping(target = "free", source = "available") + Car carDtoToCarIgnoringSeatCount(CarDto car); + + @Mapping(target = "manufacturingDate", ignore = true) + @Mapping(target = "free", source = "available") + @Mapping(target = "driver", source = "myDriver") + @Mapping(target = "numberOfSeats", source = "seatCount") + Car carDtoToCarIgnoringManufacturingDate(CarDto car); + + @InheritConfiguration(name = "") + void carDtoIntoCar(CarDto carDto, @MappingTarget Car car); + +} diff --git a/testData/completion/inheritconfiguration/InheritConfigurationWithMapperConfigCompletion.java b/testData/completion/inheritconfiguration/InheritConfigurationWithMapperConfigCompletion.java new file mode 100644 index 00000000..6d397aea --- /dev/null +++ b/testData/completion/inheritconfiguration/InheritConfigurationWithMapperConfigCompletion.java @@ -0,0 +1,36 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.complex; + +import org.example.dto.Car; +import org.example.dto.CarDto; +import org.mapstruct.InheritConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.MapperConfig; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; + +@MapperConfig +interface ConfigCompleteMapperConfig { + + @Mapping(target = "manufacturingDate", source = "manufacturingYear") + @Mapping(target = "free", source = "available") + Car configSourceToTarget(CarDto carDto); + + @Mapping(target = "numberOfSeats", source = "seatCount") + @Mapping(target = "free", source = "available") + @Mapping(target = "driver", source = "myDriver") + Car configSourceToTargetIgnoringSeats(CarDto carDto); + +} + +@Mapper(config = ConfigCompleteMapperConfig.class) +interface InheritConfigurationWithMapperConfigCompletion { + + @InheritConfiguration(name = "") + void carDtoIntoCar(CarDto carDto, @MappingTarget Car car); + +} diff --git a/testData/completion/inheritconfiguration/InheritInverseConfigurationByNameCompletion.java b/testData/completion/inheritconfiguration/InheritInverseConfigurationByNameCompletion.java new file mode 100644 index 00000000..65e54bb4 --- /dev/null +++ b/testData/completion/inheritconfiguration/InheritInverseConfigurationByNameCompletion.java @@ -0,0 +1,29 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ +package org.mapstruct.ap.test.complex; + +import org.example.dto.Car; +import org.example.dto.CarDto; +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.ReportingPolicy; + +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN) +public interface InheritInverseConfigurationByNameCompletion { + + @Mapping(target = "numberOfSeats", ignore = true) + @Mapping(target = "manufacturingDate", source = "manufacturingYear") + CarDto carToCarDto(Car car); + + @Mapping(target = "driver", ignore = true) + CarDto carToCarDtoIgnoringDriver(Car car); + + @InheritInverseConfiguration(name = "") + Car carDtoToCar(CarDto carDto, @MappingTarget Car car); + +} diff --git a/testData/inspection/InheritConfigurationWithMapperConfigReference.java b/testData/inspection/InheritConfigurationWithMapperConfigReference.java new file mode 100644 index 00000000..f8a91d8b --- /dev/null +++ b/testData/inspection/InheritConfigurationWithMapperConfigReference.java @@ -0,0 +1,58 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ + +import org.mapstruct.InheritConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.MapperConfig; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.ReportingPolicy; + +class SourceForConfig { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + +class TargetForConfig { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + +@MapperConfig +interface InheritConfigurationWithMapperConfig { + + @Mapping(target = "name", source = "name") + TargetForConfig configSourceToTarget(SourceForConfig source); + +} + +@Mapper(config = InheritConfigurationWithMapperConfig.class, + unmappedTargetPolicy = ReportingPolicy.WARN) +interface MapperThatReferencesConfig { + + @InheritConfiguration(name = "configSourceToTarget") + void sourceIntoTarget(SourceForConfig source, @MappingTarget TargetForConfig target); + + @InheritConfiguration(name = "doesNotExist") + void sourceIntoAnotherTarget(SourceForConfig source, @MappingTarget TargetForConfig target); + +} diff --git a/testData/inspection/UnknownInheritConfigurationNameReference.java b/testData/inspection/UnknownInheritConfigurationNameReference.java new file mode 100644 index 00000000..4aab48d3 --- /dev/null +++ b/testData/inspection/UnknownInheritConfigurationNameReference.java @@ -0,0 +1,52 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ + +import org.mapstruct.InheritConfiguration; +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.ReportingPolicy; + +class Source { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + +class Target { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN) +interface InheritConfigurationUnknownNameMapper { + + @Mapping(target = "name", source = "name") + Target sourceToTarget(Source source); + + @InheritConfiguration(name = "doesNotExist") + void sourceIntoTarget(Source source, @MappingTarget Target target); + + @InheritConfiguration(name ="") + void sourceIntoAnotherTarget(Source source, @MappingTarget Target target); + +} diff --git a/testData/inspection/UnknownInheritConfigurationNameReferenceWithMapSource.java b/testData/inspection/UnknownInheritConfigurationNameReferenceWithMapSource.java new file mode 100644 index 00000000..778d14e7 --- /dev/null +++ b/testData/inspection/UnknownInheritConfigurationNameReferenceWithMapSource.java @@ -0,0 +1,52 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ + +import java.util.Map; +import org.mapstruct.InheritConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import org.mapstruct.ReportingPolicy; + +interface InheritConfigurationMapSource { + + 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; + } + } +} + +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN) +interface InheritConfigurationMapSourceMapper { + + @Mapping(target = "value", source = "source.value") + InheritConfigurationMapSource.Target mapToTarget(Map source); + + @InheritConfiguration(name = "doesNotExist") + void copyIntoTarget(Map source, @MappingTarget InheritConfigurationMapSource.Target target); + +} diff --git a/testData/inspection/UnknownInheritInverseConfigurationNameReference.java b/testData/inspection/UnknownInheritInverseConfigurationNameReference.java new file mode 100644 index 00000000..7783f3ea --- /dev/null +++ b/testData/inspection/UnknownInheritInverseConfigurationNameReference.java @@ -0,0 +1,50 @@ +/* + * Copyright MapStruct Authors. + * + * Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0 + */ + +import org.mapstruct.InheritInverseConfiguration; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.ReportingPolicy; + +class Source { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + +class Target { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} + +@Mapper(unmappedTargetPolicy = ReportingPolicy.WARN) +interface InheritInverseConfigurationUnknownNameMapper { + + @Mapping(target = "name", source = "name") + Source targetToSource(Target target); + + @InheritInverseConfiguration(name = "doesNotExist") + Target inverse(Source source); + + @InheritInverseConfiguration(name ="") + Target inverseAnother(Source source); + +}