diff --git a/src/main/java/org/mapstruct/intellij/codeinsight/references/BaseValueMappingReference.java b/src/main/java/org/mapstruct/intellij/codeinsight/references/BaseValueMappingReference.java index 64f749d..2ac4ae8 100644 --- a/src/main/java/org/mapstruct/intellij/codeinsight/references/BaseValueMappingReference.java +++ b/src/main/java/org/mapstruct/intellij/codeinsight/references/BaseValueMappingReference.java @@ -6,7 +6,10 @@ package org.mapstruct.intellij.codeinsight.references; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiEnumConstant; +import com.intellij.psi.PsiField; import com.intellij.psi.PsiMethod; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,7 +19,7 @@ * * @author Filip Hrisafov */ -abstract class BaseValueMappingReference extends BaseReference { +public abstract class BaseValueMappingReference extends BaseReference { /** * @param element the element for which a reference should be found @@ -33,29 +36,77 @@ public final PsiElement resolve() { return null; } - PsiMethod mappingMethod = getMappingMethod(); + PsiClass enumClass = getEnumClass(); + if ( enumClass == null ) { + return null; + } + + return resolveInternal( value, enumClass ); + } + + @Override + @Nullable + PsiMethod getMappingMethod() { + PsiMethod mappingMethod = super.getMappingMethod(); if ( isNotValueMapping( mappingMethod ) ) { return null; } + return mappingMethod; + } + + public PsiClass getEnumClass() { + PsiMethod mappingMethod = getMappingMethod(); + if ( mappingMethod == null ) { + return null; + } + + PsiClass enumClass = getEnumClass( mappingMethod ); + + if ( enumClass == null || !enumClass.isEnum() ) { + return null; + } - return resolveInternal( value, mappingMethod ); + return enumClass; } @Nullable - abstract PsiElement resolveInternal(@NotNull String value, @NotNull PsiMethod mappingMethod); + PsiElement resolveInternal(@NotNull String value, @NotNull PsiClass enumClass) { + PsiField field = enumClass.findFieldByName( value, false ); + + if ( field instanceof PsiEnumConstant ) { + return field; + } + + return null; + } + + PsiClass getEnumClass(@NotNull PsiMethod mappingMethod) { + PsiClass enumClass = determineEnumClass( mappingMethod ); + + if ( enumClass == null || !enumClass.isEnum() ) { + return null; + } + return enumClass; + } + + abstract PsiClass determineEnumClass(@NotNull PsiMethod mappingMethod); @NotNull @Override public final Object[] getVariants() { PsiMethod mappingMethod = getMappingMethod(); - if ( isNotValueMapping( mappingMethod ) ) { + if ( mappingMethod == null ) { + return LookupElement.EMPTY_ARRAY; + } + PsiClass enumClass = getEnumClass( mappingMethod ); + if ( enumClass == null ) { return LookupElement.EMPTY_ARRAY; } - return getVariantsInternal( mappingMethod ); + return getVariantsInternal( mappingMethod, enumClass ); } @NotNull - abstract Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod); + abstract Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod, @NotNull PsiClass enumClass); private static boolean isNotValueMapping(@Nullable PsiMethod mappingMethod) { return mappingMethod == null || mappingMethod.getParameterList().getParametersCount() != 1; diff --git a/src/main/java/org/mapstruct/intellij/codeinsight/references/ValueMappingSourceReference.java b/src/main/java/org/mapstruct/intellij/codeinsight/references/ValueMappingSourceReference.java index 228c723..46c9529 100644 --- a/src/main/java/org/mapstruct/intellij/codeinsight/references/ValueMappingSourceReference.java +++ b/src/main/java/org/mapstruct/intellij/codeinsight/references/ValueMappingSourceReference.java @@ -13,11 +13,9 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiEnumConstant; -import com.intellij.psi.PsiField; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReference; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.mapstruct.intellij.util.MapstructUtil; import org.mapstruct.intellij.util.ValueMappingUtils; @@ -37,31 +35,14 @@ private ValueMappingSourceReference(@NotNull PsiElement element) { super( element ); } - @Nullable @Override - PsiElement resolveInternal(@NotNull String value, @NotNull PsiMethod mappingMethod) { - //TODO should we resolve and suggest MappingConstants as well? - PsiClass sourceClass = getParameterClass( mappingMethod.getParameterList().getParameters()[0] ); - if ( sourceClass == null || !sourceClass.isEnum() ) { - return null; - } - PsiField field = sourceClass.findFieldByName( value, false ); - - if ( field instanceof PsiEnumConstant ) { - return field; - } - - return null; + PsiClass determineEnumClass(@NotNull PsiMethod mappingMethod) { + return getParameterClass( mappingMethod.getParameterList().getParameters()[0] ); } @NotNull @Override - Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod) { - PsiClass sourceClass = getParameterClass( mappingMethod.getParameterList().getParameters()[0] ); - if ( sourceClass == null || !sourceClass.isEnum() ) { - return LookupElement.EMPTY_ARRAY; - } - + Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod, @NotNull PsiClass sourceClass) { Set alreadyDefinedValues = ValueMappingUtils.findAllDefinedValueMappingSources( mappingMethod ) .collect( Collectors.toSet() ); diff --git a/src/main/java/org/mapstruct/intellij/codeinsight/references/ValueMappingTargetReference.java b/src/main/java/org/mapstruct/intellij/codeinsight/references/ValueMappingTargetReference.java index cc432a4..13a6656 100644 --- a/src/main/java/org/mapstruct/intellij/codeinsight/references/ValueMappingTargetReference.java +++ b/src/main/java/org/mapstruct/intellij/codeinsight/references/ValueMappingTargetReference.java @@ -11,7 +11,6 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiEnumConstant; -import com.intellij.psi.PsiField; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiUtil; @@ -34,31 +33,14 @@ private ValueMappingTargetReference(@NotNull PsiElement element) { super( element ); } - @Nullable @Override - PsiElement resolveInternal(@NotNull String value, @NotNull PsiMethod mappingMethod) { - //TODO should we resolve and suggest MappingConstants as well? - PsiClass targetClass = methodReturnClass( mappingMethod ); - if ( targetClass == null || !targetClass.isEnum() ) { - return null; - } - PsiField field = targetClass.findFieldByName( value, false ); - - if ( field instanceof PsiEnumConstant ) { - return field; - } - - return null; + PsiClass determineEnumClass(@NotNull PsiMethod mappingMethod) { + return methodReturnClass( mappingMethod ); } @NotNull @Override - Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod) { - PsiClass targetClass = methodReturnClass( mappingMethod ); - if ( targetClass == null || !targetClass.isEnum() ) { - return LookupElement.EMPTY_ARRAY; - } - + Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod, @NotNull PsiClass targetClass) { return Stream.of( targetClass.getFields() ) .filter( psiField -> psiField instanceof PsiEnumConstant ) .map( psiEnumConstant -> asLookup( (PsiEnumConstant) psiEnumConstant ) ) diff --git a/src/main/java/org/mapstruct/intellij/inspection/MapstructReferenceInspection.java b/src/main/java/org/mapstruct/intellij/inspection/MapstructReferenceInspection.java index 8e5b43e..bf0c332 100644 --- a/src/main/java/org/mapstruct/intellij/inspection/MapstructReferenceInspection.java +++ b/src/main/java/org/mapstruct/intellij/inspection/MapstructReferenceInspection.java @@ -15,6 +15,7 @@ import com.intellij.psi.PsiReference; import org.jetbrains.annotations.NotNull; import org.mapstruct.intellij.codeinsight.references.BaseReference; +import org.mapstruct.intellij.codeinsight.references.BaseValueMappingReference; /** * Inspection that checks if mapstruct references can be resolved. @@ -43,14 +44,14 @@ private MapstructReferenceVisitor(ProblemsHolder holder) { public void visitElement(@NotNull PsiElement element) { if (element instanceof ContributedReferenceHost r && element instanceof PsiLanguageInjectionHost) { for (PsiReference psiReference : r.getReferences()) { - if (psiReference instanceof BaseReference && psiReference.resolve() == null) { + if ( psiReference instanceof BaseReference baseReference && psiReference.resolve() == null ) { TextRange range = psiReference.getRangeInElement(); if (range.isEmpty() && range.getStartOffset() == 1 && "\"\"".equals( element.getText() ) ) { String message = ProblemsHolder.unresolvedReferenceMessage( psiReference ); holder.registerProblem( element, message, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, TextRange.create( 0, 2 ) ); } - else { + else if ( shouldRegisterProblem( baseReference ) ) { holder.registerProblem( psiReference ); } } @@ -58,5 +59,12 @@ public void visitElement(@NotNull PsiElement element) { } super.visitElement( element ); } + + private boolean shouldRegisterProblem(BaseReference reference) { + if ( reference instanceof BaseValueMappingReference valueMappingReference ) { + return valueMappingReference.getEnumClass() != null; + } + return true; + } } } diff --git a/testData/inspection/UnknownValueMappingSourceReference.java b/testData/inspection/UnknownValueMappingSourceReference.java index edd2368..c166f85 100644 --- a/testData/inspection/UnknownValueMappingSourceReference.java +++ b/testData/inspection/UnknownValueMappingSourceReference.java @@ -36,3 +36,10 @@ interface SingleValueMappingsMapper { Target map(Source source); } +@Mapper +interface StringToEnumMapper { + + @ValueMapping(target = "FIST", source = "OTHER") + Target map(String source); +} + diff --git a/testData/inspection/UnknownValueMappingTargetReference.java b/testData/inspection/UnknownValueMappingTargetReference.java index de25e12..1afe3d2 100644 --- a/testData/inspection/UnknownValueMappingTargetReference.java +++ b/testData/inspection/UnknownValueMappingTargetReference.java @@ -36,3 +36,9 @@ interface SingleValueMappingsMapper { Target map(Source source); } +@Mapper +interface EnumToStringMapper { + + @ValueMapping(target = "OTHER", source = "FIST") + String map(Source source); +} \ No newline at end of file