Skip to content

Commit

Permalink
#124 Add custom Immutables and FreeBuilder fluent setter MapstructUtils
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephan Leicht Vogt (C803964) committed Apr 14, 2023
1 parent 451f63e commit be54e14
Show file tree
Hide file tree
Showing 14 changed files with 866 additions and 524 deletions.
11 changes: 9 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ dependencies {
testRuntimeOnly('org.junit.vintage:junit-vintage-engine')
testImplementation('org.assertj:assertj-core:3.11.1')
testImplementation('org.apache.commons:commons-text:1.9')
testRuntimeOnly('org.immutables:value:2.5.6')
}

task libs(type: Sync) {
Expand All @@ -110,6 +111,12 @@ task libs(type: Sync) {
rename 'mapstruct-1.5.3.Final.jar', 'mapstruct.jar'
}

task testLibs(type: Sync) {
from configurations.testRuntimeClasspath
into "$buildDir/test-libs"
rename 'value-2.5.6.jar', 'immutables.jar'
}

def mockJdkLocation = "https://github.com/JetBrains/intellij-community/raw/master/java/mock"
def mockJdkDest = "$buildDir/mock"
def downloadMockJdk(mockJdkLocation, mockJdkDest, mockJdkVersion) {
Expand Down Expand Up @@ -149,8 +156,8 @@ task downloadMockJdk11() {
downloadMockJdk(mockJdkLocation, mockJdkDest, "JDK-11")
}

test.dependsOn( libs, downloadMockJdk7, downloadMockJdk8, downloadMockJdk11 )
prepareTestingSandbox.dependsOn( libs )
test.dependsOn( libs, testLibs, downloadMockJdk7, downloadMockJdk8, downloadMockJdk11 )
prepareTestingSandbox.dependsOn( libs, testLibs )
prepareSandbox.dependsOn( libs )

test {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ abstract class MapstructBaseReference extends BaseReference {

private final MapstructBaseReference previous;
private final String value;
protected final MapstructUtil mapstructUtil;

/**
* Create a reference.
Expand All @@ -47,6 +48,7 @@ abstract class MapstructBaseReference extends BaseReference {
super( element, rangeInElement );
this.previous = previous;
this.value = value;
this.mapstructUtil = MapstructUtil.getInstance(element.getContainingFile());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ builderSupportPresent && isBuilderEnabled( getMappingMethod() )
if ( builderSupportPresent ) {
for ( PsiMethod method : psiClass.findMethodsByName( value, true ) ) {
if ( method.getParameterList().getParametersCount() == 1 &&
MapstructUtil.isFluentSetter( method, typeToUse ) ) {
mapstructUtil.isFluentSetter( method, typeToUse ) ) {
return method;
}
}
Expand Down Expand Up @@ -140,7 +140,7 @@ PsiElement resolveInternal(@NotNull String value, @NotNull PsiMethod mappingMeth
@Override
Object[] getVariantsInternal(@NotNull PsiType psiType) {
return asLookup(
publicWriteAccessors( psiType, mapStructVersion, getMappingMethod() ),
publicWriteAccessors( psiType, mapStructVersion, mapstructUtil, getMappingMethod() ),
MapstructTargetReference::memberPsiType
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,19 @@ 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() ), MapstructUtil.getInstance( holder.getFile() ) );
}

private static class MyJavaElementVisitor extends JavaElementVisitor {
private final ProblemsHolder holder;
private final MapStructVersion mapStructVersion;
private final MapstructUtil mapstructUtil;

private MyJavaElementVisitor(ProblemsHolder holder, MapStructVersion mapStructVersion) {
private MyJavaElementVisitor(ProblemsHolder holder, MapStructVersion mapStructVersion, MapstructUtil mapstructUtil) {
this.holder = holder;
this.mapStructVersion = mapStructVersion;
}
this.mapstructUtil = mapstructUtil;
}

@Override
public void visitMethod(PsiMethod method) {
Expand All @@ -82,7 +84,7 @@ public void visitMethod(PsiMethod method) {
return;
}

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

// find and remove all defined mapping targets
Set<String> definedTargets = TargetUtils.findAllDefinedMappingTargets( method, mapStructVersion )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.intellij.util;

public class DefaultMapstructUtil implements MapstructUtil {
/**
* Hide constructor.
*/
protected DefaultMapstructUtil() {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.intellij.util;

import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;

/**
* Mapstruct util for FreeBuilder.
* FreeBuilder adds a lot of other methods that can be considered as fluent setters. Such as:
* <ul>
* <li>{@code from(Target)}</li>
* <li>{@code mapXXX(UnaryOperator)}</li>
* <li>{@code mutateXXX(Consumer)}</li>
* <li>{@code mergeFrom(Target)}</li>
* <li>{@code mergeFrom(Target.Builder)}</li>
* </ul>
* <p>
* When the JavaBean convention is not used with FreeBuilder then the getters are non-standard and MapStruct
* won't recognize them. Therefore, one needs to use the JavaBean convention in which the fluent setters
* start with {@code set}.
*/
public class FreeBuildersMapstructUtil implements MapstructUtil {
/**
* Hide constructor.
*/
protected FreeBuildersMapstructUtil() {
}

@Override
public boolean isFluentSetter(@NotNull PsiMethod method, PsiType psiType) {
// When using FreeBuilder one needs to use the JavaBean convention, which means that all setters will start
// with set
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.intellij.util;

import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;

/**
* Mapstruct util for Immutables.
* The generated Immutables also have a from that works as a copy. Our default strategy considers this method
* as a setter with a name {@code from}. Therefore, we are ignoring it.
*/
public class ImmutablesMapstructUtil implements MapstructUtil {
/**
* Hide constructor.
*/
protected ImmutablesMapstructUtil() {
}

@Override
public boolean isFluentSetter(@NotNull PsiMethod method, PsiType psiType) {
return MapstructUtil.super.isFluentSetter( method, psiType ) && !method.getName().equals( "from" );
}
}
Loading

0 comments on commit be54e14

Please sign in to comment.