Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ignore withXZY fluent setter #150

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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 @@ -5,12 +5,9 @@
*/
package org.mapstruct.intellij.codeinsight.references;

import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiClass;
Expand All @@ -27,11 +24,16 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mapstruct.Mapping;
import org.mapstruct.intellij.settings.ProjectSettings;
import org.mapstruct.intellij.util.MapStructVersion;
import org.mapstruct.intellij.util.MapstructUtil;
import org.mapstruct.intellij.util.TargetType;
import org.mapstruct.intellij.util.TargetUtils;

import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

import static org.mapstruct.intellij.util.MapstructAnnotationUtils.findAllDefinedMappingAnnotations;
import static org.mapstruct.intellij.util.MapstructUtil.asLookup;
import static org.mapstruct.intellij.util.MapstructUtil.findRecordComponent;
Expand All @@ -50,6 +52,7 @@
class MapstructTargetReference extends MapstructBaseReference {

private final MapStructVersion mapStructVersion;
private final boolean ignoreWither;

/**
* Create a new {@link MapstructTargetReference} with the provided parameters
Expand All @@ -64,6 +67,7 @@ private MapstructTargetReference(PsiElement element, MapstructTargetReference pr
super( element, previousReference, rangeInElement, value );
mapStructVersion = MapstructUtil.resolveMapStructProjectVersion( element.getContainingFile()
.getOriginalFile() );
ignoreWither = ProjectSettings.isIgnoreWitherInMapping(element.getContainingFile().getOriginalFile().getProject());
}

@Override
Expand Down Expand Up @@ -104,7 +108,7 @@ builderSupportPresent && isBuilderEnabled( getMappingMethod() )

if ( builderSupportPresent ) {
for ( PsiMethod method : psiClass.findMethodsByName( value, true ) ) {
if ( method.getParameterList().getParametersCount() == 1 &&
if ( method.getParameterList().getParametersCount() == 1 && // !ignoreWither &&
MapstructUtil.isFluentSetter( method, typeToUse ) ) {
return method;
}
Expand Down Expand Up @@ -150,7 +154,8 @@ Object[] getVariantsInternal(@NotNull PsiType psiType) {
Map<String, Pair<? extends PsiElement, PsiSubstitutor>> accessors = publicWriteAccessors(
psiType,
mapStructVersion,
mappingMethod
mappingMethod,
ignoreWither
);

if (mappingMethod != null) {
Expand Down Expand Up @@ -212,7 +217,7 @@ else if ( element instanceof PsiField ) {
* @return the references for the given {@code psiLiteral}
*/
static PsiReference[] create(PsiElement psiElement) {
return MapstructBaseReference.create( psiElement, MapstructTargetReference::new, true );
return MapstructBaseReference.create( psiElement, MapstructTargetReference::new, true);
}

private static PsiType memberPsiType(PsiElement psiMember) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,21 @@ public class UnmappedTargetPropertiesInspection extends InspectionBase {
@NotNull
@Override
PsiElementVisitor buildVisitorInternal(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
return new MyJavaElementVisitor( holder, MapstructUtil.resolveMapStructProjectVersion( holder.getFile() ) );
return new MyJavaElementVisitor( holder,
MapstructUtil.resolveMapStructProjectVersion( holder.getFile() ),
ProjectSettings.isIgnoreWitherInMapping(holder.getProject() )
);
}

private static class MyJavaElementVisitor extends JavaElementVisitor {
private final ProblemsHolder holder;
private final MapStructVersion mapStructVersion;
private final boolean ignoreWither;

private MyJavaElementVisitor(ProblemsHolder holder, MapStructVersion mapStructVersion) {
private MyJavaElementVisitor(ProblemsHolder holder, MapStructVersion mapStructVersion, boolean ignoreWither) {
this.holder = holder;
this.mapStructVersion = mapStructVersion;
this.ignoreWither = ignoreWither;
}

@Override
Expand All @@ -92,7 +97,7 @@ public void visitMethod(PsiMethod method) {
}


Set<String> allTargetProperties = findAllTargetProperties( targetType, mapStructVersion, method );
Set<String> allTargetProperties = findAllTargetProperties( targetType, mapStructVersion, method, ignoreWither );

// find and remove all defined mapping targets
Set<String> definedTargets = findAllDefinedMappingTargets( method, mapStructVersion )
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/mapstruct/intellij/settings/ProjectSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public interface ProjectSettings {
String PREFER_SOURCE_BEFORE_TARGET_IN_MAPPING =
PREFIX + "PREFER_SOURCE_BEFORE_TARGET_IN_MAPPING";

String IGNORE_WITHER_IN_MAPPING = PREFIX + "IGNORE_WITHER_IN_MAPPING";

static boolean isPreferSourceBeforeTargetInMapping(@NotNull Project project) {
return PropertiesComponent.getInstance( project ).getBoolean( PREFER_SOURCE_BEFORE_TARGET_IN_MAPPING, false );
}
Expand All @@ -27,4 +29,13 @@ static void setPreferSourceBeforeTargetInMapping(@NotNull Project project, boole
PropertiesComponent.getInstance( project )
.setValue( PREFER_SOURCE_BEFORE_TARGET_IN_MAPPING, String.valueOf( value ), "false" );
}

static boolean isIgnoreWitherInMapping(@NotNull Project project) {
return PropertiesComponent.getInstance( project ).getBoolean( IGNORE_WITHER_IN_MAPPING, false );
}

static void setIgnoreWitherInMapping(@NotNull Project project, boolean value) {
PropertiesComponent.getInstance( project )
.setValue( IGNORE_WITHER_IN_MAPPING, String.valueOf( value ), "false" );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,19 @@ public class ProjectSettingsComponent {

private final JPanel mainPanel;
private final JBCheckBox preferSourceBeforeTargetInMapping;
private final JBCheckBox ignoreWitherInMapping;

public ProjectSettingsComponent() {
this.preferSourceBeforeTargetInMapping = new JBCheckBox( MapStructBundle.message(
"plugin.settings.quickFix.preferSourceBeforeTargetInMapping" ), false );
this.ignoreWitherInMapping = new JBCheckBox( MapStructBundle.message(
"plugin.settings.quickFix.ignoreWitherInMapping" ), false );
JPanel quickFixProperties = new JPanel( new BorderLayout() );
quickFixProperties.setBorder( IdeBorderFactory.createTitledBorder( MapStructBundle.message(
"plugin.settings.quickFix.title" ), false ) );

quickFixProperties.add( this.preferSourceBeforeTargetInMapping, BorderLayout.NORTH );
quickFixProperties.add( this.ignoreWitherInMapping, BorderLayout.SOUTH );
this.mainPanel = FormBuilder.createFormBuilder()
.addComponent( quickFixProperties )
.addComponentFillVertically( new JPanel(), 0 )
Expand All @@ -52,4 +56,12 @@ public void setPreferSourceBeforeTargetInMapping(boolean newState) {
preferSourceBeforeTargetInMapping.setSelected( newState );
}

public boolean getIgnoreWitherInMapping() {
return ignoreWitherInMapping.isSelected();
}

public void setIgnoreWitherInMapping(boolean newState) {
ignoreWitherInMapping.setSelected( newState );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.jetbrains.annotations.Nls;
import org.mapstruct.intellij.MapStructBundle;

import static org.mapstruct.intellij.settings.ProjectSettings.isIgnoreWitherInMapping;
import static org.mapstruct.intellij.settings.ProjectSettings.isPreferSourceBeforeTargetInMapping;

/**
Expand Down Expand Up @@ -47,7 +48,8 @@ public JComponent getPreferredFocusedComponent() {
@Override
public boolean isModified() {
return settingsComponent.getPreferSourceBeforeTargetInMapping() !=
isPreferSourceBeforeTargetInMapping( myProject );
isPreferSourceBeforeTargetInMapping( myProject ) ||
settingsComponent.getIgnoreWitherInMapping() != isIgnoreWitherInMapping(myProject);
}

@Override
Expand All @@ -56,11 +58,13 @@ public void apply() {
myProject,
settingsComponent.getPreferSourceBeforeTargetInMapping()
);
ProjectSettings.setIgnoreWitherInMapping(myProject, settingsComponent.getIgnoreWitherInMapping());
}

@Override
public void reset() {
settingsComponent.setPreferSourceBeforeTargetInMapping( isPreferSourceBeforeTargetInMapping( myProject ) );
settingsComponent.setIgnoreWitherInMapping( isIgnoreWitherInMapping( myProject ) );
}

@Override
Expand Down
23 changes: 14 additions & 9 deletions src/main/java/org/mapstruct/intellij/util/TargetUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.lang.jvm.JvmModifier;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiAnnotationMemberValue;
Expand Down Expand Up @@ -98,7 +99,7 @@ public static PsiType getRelevantType(@NotNull PsiMethod mappingMethod) {
* @return a stream that holds all public write accessors for the given {@code psiType}
*/
public static Map<String, Pair<? extends PsiElement, PsiSubstitutor>> publicWriteAccessors(@NotNull PsiType psiType,
MapStructVersion mapStructVersion, PsiMethod mappingMethod) {
MapStructVersion mapStructVersion, PsiMethod mappingMethod, boolean ignoreWither) {
boolean builderSupportPresent = mapStructVersion.isBuilderSupported();
Pair<PsiClass, TargetType> classAndType = resolveBuilderOrSelfClass(
psiType,
Expand All @@ -114,7 +115,7 @@ builderSupportPresent && isBuilderEnabled( mappingMethod )
TargetType targetType = classAndType.getSecond();
PsiType typeToUse = targetType.type();

publicWriteAccessors.putAll( publicSetters( psiClass, typeToUse, builderSupportPresent ) );
publicWriteAccessors.putAll( publicSetters( psiClass, typeToUse, builderSupportPresent, ignoreWither ) );
publicWriteAccessors.putAll( publicFields( psiClass ) );

if ( mapStructVersion.isConstructorSupported() && !targetType.builder() ) {
Expand Down Expand Up @@ -267,15 +268,16 @@ public static PsiMethod resolveMappingConstructor(@NotNull PsiClass psiClass) {
*/
private static Map<String, Pair<? extends PsiMember, PsiSubstitutor>> publicSetters(@NotNull PsiClass psiClass,
@NotNull PsiType typeToUse,
boolean builderSupportPresent) {
boolean builderSupportPresent, boolean ignoreWither
) {
Set<PsiMethod> overriddenMethods = new HashSet<>();
Map<String, Pair<? extends PsiMember, PsiSubstitutor>> publicSetters = new LinkedHashMap<>();
for ( Pair<PsiMethod, PsiSubstitutor> pair : psiClass.getAllMethodsAndTheirSubstitutors() ) {
PsiMethod method = pair.getFirst();
if ( method.isConstructor() ) {
continue;
}
String propertyName = extractPublicSetterPropertyName( method, typeToUse, builderSupportPresent );
String propertyName = extractPublicSetterPropertyName( method, typeToUse, builderSupportPresent, ignoreWither );

if ( propertyName != null &&
!overriddenMethods.contains( method ) ) {
Expand All @@ -290,7 +292,7 @@ private static Map<String, Pair<? extends PsiMember, PsiSubstitutor>> publicSett

@Nullable
private static String extractPublicSetterPropertyName(PsiMethod method, @NotNull PsiType typeToUse,
boolean builderSupportPresent) {
boolean builderSupportPresent, boolean ignoreWither) {
if (!MapstructUtil.isPublicNonStatic( method )) {
// If the method is not public then there is no property
return null;
Expand All @@ -316,6 +318,9 @@ private static String extractPublicSetterPropertyName(PsiMethod method, @NotNull
&& Character.isUpperCase( methodName.charAt( 3 ) ) ) {
return Introspector.decapitalize( methodName.substring( 3 ) );
}
if (ignoreWither) {
return null;
}
return methodName;
}
if ( methodName.startsWith( "set" ) ) {
Expand Down Expand Up @@ -343,7 +348,7 @@ public static Pair<PsiClass, TargetType> resolveBuilderOrSelfClass(@NotNull PsiT
if ( builderEnabled ) {
for ( PsiMethod classMethod : psiClass.getMethods() ) {
if ( MapstructUtil.isPossibleBuilderCreationMethod( classMethod, targetType.type() ) &&
hasBuildMethod( classMethod.getReturnType(), psiType ) ) {
hasBuildMethod( classMethod.getReturnType(), psiType) ) {
targetType = TargetType.builder( classMethod.getReturnType() );
break;
}
Expand Down Expand Up @@ -375,7 +380,7 @@ private static boolean hasBuildMethod(@Nullable PsiType builderType, @NotNull Ps
}

for ( PsiMethod buildMethod : builderClass.getAllMethods() ) {
if ( MapstructUtil.isBuildMethod( buildMethod, type ) ) {
if ( MapstructUtil.isBuildMethod( buildMethod, type) ) {
return true;
}
}
Expand Down Expand Up @@ -432,8 +437,8 @@ public static Stream<String> findAllSourcePropertiesForCurrentTarget(@NotNull Ps
* @return all target properties for the given {@code targetClass}
*/
public static Set<String> findAllTargetProperties(@NotNull PsiType targetType, MapStructVersion mapStructVersion,
PsiMethod mappingMethod) {
return publicWriteAccessors( targetType, mapStructVersion, mappingMethod ).keySet();
PsiMethod mappingMethod, boolean ignoreWither) {
return publicWriteAccessors( targetType, mapStructVersion, mappingMethod, ignoreWither ).keySet();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ intention.add.unmapped.target.property=Add unmapped target property
plugin.settings.title=MapStruct
plugin.settings.quickFix.title=Quick fix properties
plugin.settings.quickFix.preferSourceBeforeTargetInMapping=Prefer source before target in @Mapping
plugin.settings.quickFix.ignoreWitherInMapping=Ignore fluent API methods like withXYZ