From f065d95a56f4755047ceacd79a2b91d86a7551d5 Mon Sep 17 00:00:00 2001 From: Joern Muehlencord Date: Sat, 26 Aug 2023 00:21:46 +0200 Subject: [PATCH] ignore withXZY fluent setter --- .../references/MapstructTargetReference.java | 19 +++++++++------ .../UnmappedTargetPropertiesInspection.java | 11 ++++++--- .../intellij/settings/ProjectSettings.java | 11 +++++++++ .../settings/ProjectSettingsComponent.java | 12 ++++++++++ .../settings/ProjectSettingsPage.java | 6 ++++- .../mapstruct/intellij/util/TargetUtils.java | 23 +++++++++++-------- .../messages/MapStructBundle.properties | 1 + 7 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/mapstruct/intellij/codeinsight/references/MapstructTargetReference.java b/src/main/java/org/mapstruct/intellij/codeinsight/references/MapstructTargetReference.java index 30c81134..0e1a8824 100644 --- a/src/main/java/org/mapstruct/intellij/codeinsight/references/MapstructTargetReference.java +++ b/src/main/java/org/mapstruct/intellij/codeinsight/references/MapstructTargetReference.java @@ -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; @@ -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; @@ -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 @@ -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 @@ -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; } @@ -150,7 +154,8 @@ Object[] getVariantsInternal(@NotNull PsiType psiType) { Map> accessors = publicWriteAccessors( psiType, mapStructVersion, - mappingMethod + mappingMethod, + ignoreWither ); if (mappingMethod != null) { @@ -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) { diff --git a/src/main/java/org/mapstruct/intellij/inspection/UnmappedTargetPropertiesInspection.java b/src/main/java/org/mapstruct/intellij/inspection/UnmappedTargetPropertiesInspection.java index a85796a6..bc9d3908 100644 --- a/src/main/java/org/mapstruct/intellij/inspection/UnmappedTargetPropertiesInspection.java +++ b/src/main/java/org/mapstruct/intellij/inspection/UnmappedTargetPropertiesInspection.java @@ -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 @@ -92,7 +97,7 @@ public void visitMethod(PsiMethod method) { } - Set allTargetProperties = findAllTargetProperties( targetType, mapStructVersion, method ); + Set allTargetProperties = findAllTargetProperties( targetType, mapStructVersion, method, ignoreWither ); // find and remove all defined mapping targets Set definedTargets = findAllDefinedMappingTargets( method, mapStructVersion ) diff --git a/src/main/java/org/mapstruct/intellij/settings/ProjectSettings.java b/src/main/java/org/mapstruct/intellij/settings/ProjectSettings.java index 19f7287c..7e1f12fc 100644 --- a/src/main/java/org/mapstruct/intellij/settings/ProjectSettings.java +++ b/src/main/java/org/mapstruct/intellij/settings/ProjectSettings.java @@ -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 ); } @@ -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" ); + } } diff --git a/src/main/java/org/mapstruct/intellij/settings/ProjectSettingsComponent.java b/src/main/java/org/mapstruct/intellij/settings/ProjectSettingsComponent.java index 36056b6b..8ca334f8 100644 --- a/src/main/java/org/mapstruct/intellij/settings/ProjectSettingsComponent.java +++ b/src/main/java/org/mapstruct/intellij/settings/ProjectSettingsComponent.java @@ -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 ) @@ -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 ); + } + } diff --git a/src/main/java/org/mapstruct/intellij/settings/ProjectSettingsPage.java b/src/main/java/org/mapstruct/intellij/settings/ProjectSettingsPage.java index 08629d7e..3c426360 100644 --- a/src/main/java/org/mapstruct/intellij/settings/ProjectSettingsPage.java +++ b/src/main/java/org/mapstruct/intellij/settings/ProjectSettingsPage.java @@ -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; /** @@ -47,7 +48,8 @@ public JComponent getPreferredFocusedComponent() { @Override public boolean isModified() { return settingsComponent.getPreferSourceBeforeTargetInMapping() != - isPreferSourceBeforeTargetInMapping( myProject ); + isPreferSourceBeforeTargetInMapping( myProject ) || + settingsComponent.getIgnoreWitherInMapping() != isIgnoreWitherInMapping(myProject); } @Override @@ -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 diff --git a/src/main/java/org/mapstruct/intellij/util/TargetUtils.java b/src/main/java/org/mapstruct/intellij/util/TargetUtils.java index 51979500..0c746c29 100644 --- a/src/main/java/org/mapstruct/intellij/util/TargetUtils.java +++ b/src/main/java/org/mapstruct/intellij/util/TargetUtils.java @@ -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; @@ -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> publicWriteAccessors(@NotNull PsiType psiType, - MapStructVersion mapStructVersion, PsiMethod mappingMethod) { + MapStructVersion mapStructVersion, PsiMethod mappingMethod, boolean ignoreWither) { boolean builderSupportPresent = mapStructVersion.isBuilderSupported(); Pair classAndType = resolveBuilderOrSelfClass( psiType, @@ -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() ) { @@ -267,7 +268,8 @@ public static PsiMethod resolveMappingConstructor(@NotNull PsiClass psiClass) { */ private static Map> publicSetters(@NotNull PsiClass psiClass, @NotNull PsiType typeToUse, - boolean builderSupportPresent) { + boolean builderSupportPresent, boolean ignoreWither + ) { Set overriddenMethods = new HashSet<>(); Map> publicSetters = new LinkedHashMap<>(); for ( Pair pair : psiClass.getAllMethodsAndTheirSubstitutors() ) { @@ -275,7 +277,7 @@ private static Map> publicSett if ( method.isConstructor() ) { continue; } - String propertyName = extractPublicSetterPropertyName( method, typeToUse, builderSupportPresent ); + String propertyName = extractPublicSetterPropertyName( method, typeToUse, builderSupportPresent, ignoreWither ); if ( propertyName != null && !overriddenMethods.contains( method ) ) { @@ -290,7 +292,7 @@ private static Map> 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; @@ -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" ) ) { @@ -343,7 +348,7 @@ public static Pair 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; } @@ -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; } } @@ -432,8 +437,8 @@ public static Stream findAllSourcePropertiesForCurrentTarget(@NotNull Ps * @return all target properties for the given {@code targetClass} */ public static Set 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(); } /** diff --git a/src/main/resources/org/mapstruct/intellij/messages/MapStructBundle.properties b/src/main/resources/org/mapstruct/intellij/messages/MapStructBundle.properties index ee2a02ac..b413ce34 100644 --- a/src/main/resources/org/mapstruct/intellij/messages/MapStructBundle.properties +++ b/src/main/resources/org/mapstruct/intellij/messages/MapStructBundle.properties @@ -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