Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<String> alreadyDefinedValues = ValueMappingUtils.findAllDefinedValueMappingSources( mappingMethod )
.collect( Collectors.toSet() );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 ) )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -43,20 +44,27 @@ 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 );
}
}
}
}
super.visitElement( element );
}

private boolean shouldRegisterProblem(BaseReference reference) {
if ( reference instanceof BaseValueMappingReference valueMappingReference ) {
return valueMappingReference.getEnumClass() != null;
}
return true;
}
}
}
7 changes: 7 additions & 0 deletions testData/inspection/UnknownValueMappingSourceReference.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,10 @@ interface SingleValueMappingsMapper {
Target map(Source source);
}

@Mapper
interface StringToEnumMapper {

@ValueMapping(target = "FIST", source = "OTHER")
Target map(String source);
}

6 changes: 6 additions & 0 deletions testData/inspection/UnknownValueMappingTargetReference.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ interface SingleValueMappingsMapper {
Target map(Source source);
}

@Mapper
interface EnumToStringMapper {

@ValueMapping(target = "OTHER", source = "FIST")
String map(Source source);
}