Skip to content

Commit

Permalink
#163 Reference support for @InheritConfiguration and @InheritInverseC…
Browse files Browse the repository at this point in the history
…onfiguration
  • Loading branch information
thunderhook committed Jun 1, 2024
1 parent 4b48a62 commit 88ebd38
Show file tree
Hide file tree
Showing 13 changed files with 512 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import static org.mapstruct.intellij.util.MapstructUtil.canDescendIntoType;

/**
* A base reference to target / source annotation.
* A base reference to annotations holding a reference and possibly nested types.
*
* @author Filip Hrisafov
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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.Objects;

import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull;
import org.mapstruct.InheritConfiguration;
import org.mapstruct.intellij.util.MapStructVersion;
import org.mapstruct.intellij.util.MapstructUtil;

import static org.mapstruct.intellij.inspection.inheritance.InheritConfigurationUtils.findInheritConfigurationMethods;

/**
* Reference for {@link InheritConfiguration#name()}.
*
* @author Oliver Erhart
*/
class MapstructMappingInheritConfigurationReference extends MapstructNonNestedBaseReference {

private final MapStructVersion mapStructVersion;

/**
* Create a new {@link MapstructMappingInheritConfigurationReference} 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)
*/
private MapstructMappingInheritConfigurationReference(
PsiElement element,
MapstructMappingInheritConfigurationReference previousReference,
TextRange rangeInElement, String value
) {
super( element, previousReference, rangeInElement, value );
mapStructVersion = MapstructUtil.resolveMapStructProjectVersion( element.getContainingFile()
.getOriginalFile() );
}

@Override
PsiElement resolveInternal(@NotNull String value, @NotNull PsiMethod mappingMethod) {

return findInheritConfigurationMethods( mappingMethod, mapStructVersion )
.filter( a -> Objects.equals( a.getName(), value ) )
.findAny()
.orElse( null );
}

@NotNull
@Override
Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod) {

return findInheritConfigurationMethods( mappingMethod, mapStructVersion )
.map( method -> MapstructUtil.asLookup( method, method.getName(), method.getName() ) )
.filter( Objects::nonNull )
.toArray();
}

/**
* @param psiElement the literal for which references need to be created
* @return the references for the given {@code psiLiteral}
*/
static PsiReference[] create(PsiElement psiElement) {
return MapstructBaseReference.create( psiElement, MapstructMappingInheritConfigurationReference::new, false );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* 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.Objects;

import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.intellij.util.MapStructVersion;
import org.mapstruct.intellij.util.MapstructUtil;

import static org.mapstruct.intellij.inspection.inheritance.InheritConfigurationUtils.findInheritInverseConfigurationMethods;

/**
* Reference for {@link InheritInverseConfiguration#name()}.
*
* @author Oliver Erhart
*/
class MapstructMappingInheritInverseConfigurationReference extends MapstructNonNestedBaseReference {

private final MapStructVersion mapStructVersion;

/**
* Create a new {@link MapstructMappingInheritInverseConfigurationReference} 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)
*/
private MapstructMappingInheritInverseConfigurationReference(
PsiElement element,
MapstructMappingInheritInverseConfigurationReference previousReference,
TextRange rangeInElement,
String value
) {

super( element, previousReference, rangeInElement, value );
mapStructVersion = MapstructUtil.resolveMapStructProjectVersion( element.getContainingFile()
.getOriginalFile() );
}

@Override
PsiElement resolveInternal(@NotNull String value, @NotNull PsiMethod mappingMethod) {

return findInheritInverseConfigurationMethods( mappingMethod, mapStructVersion )
.filter( a -> Objects.equals( a.getName(), value ) )
.findAny()
.orElse( null );
}

@NotNull
@Override
Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod) {

return findInheritInverseConfigurationMethods( mappingMethod, mapStructVersion )
.map( method -> MapstructUtil.asLookup( method, method.getName(), method.getName() ) )
.filter( Objects::nonNull )
.toArray();
}

/**
* @param psiElement the literal for which references need to be created
* @return the references for the given {@code psiLiteral}
*/
static PsiReference[] create(PsiElement psiElement) {
return MapstructBaseReference.create(
psiElement,
MapstructMappingInheritInverseConfigurationReference::new,
false
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.intellij.codeInsight.lookup.LookupElement;
Expand All @@ -18,7 +17,6 @@
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;
Expand All @@ -31,14 +29,13 @@
import static org.mapstruct.intellij.util.MapstructUtil.NAMED_ANNOTATION_FQN;
import static org.mapstruct.intellij.util.MapstructUtil.MAPPER_ANNOTATION_FQN;
import static org.mapstruct.intellij.util.MapstructUtil.MAPPER_CONFIG_ANNOTATION_FQN;
import static org.mapstruct.intellij.util.MapstructUtil.asLookupWithRepresentableText;

/**
* Reference for {@link org.mapstruct.Mapping#qualifiedByName()}.
*
* @author Oliver Erhart
*/
class MapstructMappingQualifiedByNameReference extends MapstructBaseReference {
class MapstructMappingQualifiedByNameReference extends MapstructNonNestedBaseReference {

/**
* Create a new {@link MapstructMappingQualifiedByNameReference} with the provided parameters
Expand All @@ -54,11 +51,6 @@ private MapstructMappingQualifiedByNameReference(PsiElement element,
super( element, previousReference, rangeInElement, value );
}

@Override
PsiElement resolveInternal(@NotNull String value, @NotNull PsiType psiType) {
return null; // not needed
}

@Override
PsiElement resolveInternal(@NotNull String value, @NotNull PsiMethod mappingMethod) {

Expand All @@ -80,12 +72,6 @@ private String getNamedValue(PsiMethod method) {
return getStringAttributeValue( namedAnnotation, "value" );
}

@NotNull
@Override
Object[] getVariantsInternal(@NotNull PsiType psiType) {
return LookupElement.EMPTY_ARRAY; // not needed
}

@NotNull
@Override
Object[] getVariantsInternal(@NotNull PsiMethod mappingMethod) {
Expand Down Expand Up @@ -139,31 +125,7 @@ private LookupElement methodAsLookup(@NotNull PsiMethod method) {
return null;
}

return asLookupWithRepresentableText(
method,
lookupString,
lookupString,
String.format(
" %s#%s(%s)",
Objects.requireNonNull( method.getContainingClass() ).getName(),
method.getName(),
formatParameters( method )
)
);
}

@NotNull
private static String formatParameters(@NotNull PsiMethod method) {
return Arrays.stream( method.getParameterList().getParameters() )
.map( PsiParameter::getType )
.map( PsiType::getPresentableText )
.collect( Collectors.joining( ", " ) );
}

@Nullable
@Override
PsiType resolvedType() {
return null;
return MapstructUtil.asLookup( method, lookupString, lookupString );
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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 com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* A base reference to mapstruct annotations without nested types.
*
* @author Oliver Erhart
*/
public abstract class MapstructNonNestedBaseReference extends MapstructBaseReference {

/**
* Create a reference.
*
* @param element the literal where the text is
* @param previous the previous reference ({@code null} if there is no previous reference)
* @param rangeInElement the range in the {@code element} for which this reference is valid
*/
MapstructNonNestedBaseReference(@NotNull PsiElement element,
@Nullable MapstructBaseReference previous,
TextRange rangeInElement, String value) {
super( element, previous, rangeInElement, value );
}

@Override
final PsiElement resolveInternal(@NotNull String value, @NotNull PsiType psiType) {
return null; // not needed
}

@NotNull
@Override
final Object[] getVariantsInternal(@NotNull PsiType psiType) {
return LookupElement.EMPTY_ARRAY; // not needed
}

@Override
@Nullable
final PsiType resolvedType() {
return null; // not needed
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -48,6 +50,16 @@ public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar)
valueMappingElementPattern( "target" ),
new MappingTargetReferenceProvider( ValueMappingTargetReference::create )
);

registrar.registerReferenceProvider(
inheritConfigurationElementPattern( "name" ),
new MappingTargetReferenceProvider( MapstructMappingInheritConfigurationReference::create )
);
registrar.registerReferenceProvider(
inheritInverseConfigurationElementPattern( "name" ),
new MappingTargetReferenceProvider( MapstructMappingInheritInverseConfigurationReference::create )
);

}

}
Loading

0 comments on commit 88ebd38

Please sign in to comment.