Skip to content

Commit 6b04bbc

Browse files
authored
Add support for collection targets from getter (#149)
1 parent 227371f commit 6b04bbc

File tree

4 files changed

+168
-23
lines changed

4 files changed

+168
-23
lines changed

src/main/java/org/mapstruct/intellij/util/TargetUtils.java

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -291,38 +291,37 @@ private static Map<String, Pair<? extends PsiMember, PsiSubstitutor>> publicSett
291291
@Nullable
292292
private static String extractPublicSetterPropertyName(PsiMethod method, @NotNull PsiType typeToUse,
293293
boolean builderSupportPresent) {
294-
if ( method.getParameterList().getParametersCount() != 1 || !MapstructUtil.isPublicNonStatic( method ) ) {
295-
// If the method does not have 1 parameter or is not public then there is no property
294+
if (!MapstructUtil.isPublicNonStatic( method )) {
295+
// If the method is not public then there is no property
296+
return null;
297+
}
298+
String methodName = method.getName();
299+
int parametersCount = method.getParameterList().getParametersCount();
300+
PsiType returnType = method.getReturnType();
301+
if (parametersCount == 0 && methodName.startsWith( "get" ) && returnType != null &&
302+
returnType.isConvertibleFrom( PsiType.getTypeByName( "java.util.Collection",
303+
method.getProject(), method.getResolveScope() ) )) {
304+
// If the methode returns a collection
305+
return Introspector.decapitalize( methodName.substring( 3 ) );
306+
}
307+
if (parametersCount != 1) {
308+
// If the method does not have 1 parameter
296309
return null;
297310
}
298311

299312
// This logic is aligned with the DefaultAccessorNamingStrategy
300-
String methodName = method.getName();
301-
if ( builderSupportPresent ) {
302-
if ( isFluentSetter( method, typeToUse ) ) {
303-
if ( methodName.startsWith( "set" )
304-
&& methodName.length() > 3
305-
&& Character.isUpperCase( methodName.charAt( 3 ) ) ) {
306-
return Introspector.decapitalize( methodName.substring( 3 ) );
307-
}
308-
else {
309-
return methodName;
310-
}
311-
}
312-
else if ( methodName.startsWith( "set" ) ) {
313+
if ( builderSupportPresent && isFluentSetter( method, typeToUse )) {
314+
if ( methodName.startsWith( "set" )
315+
&& methodName.length() > 3
316+
&& Character.isUpperCase( methodName.charAt( 3 ) ) ) {
313317
return Introspector.decapitalize( methodName.substring( 3 ) );
314318
}
315-
else {
316-
return null;
317-
}
319+
return methodName;
318320
}
319-
else if ( methodName.startsWith( "set" ) ) {
321+
if ( methodName.startsWith( "set" ) ) {
320322
return Introspector.decapitalize( methodName.substring( 3 ) );
321323
}
322-
else {
323-
return null;
324-
}
325-
324+
return null;
326325
}
327326

328327
/**
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright MapStruct Authors.
3+
*
4+
* Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0
5+
*/
6+
package org.mapstruct.intellij.inspection;
7+
8+
import com.intellij.codeInsight.intention.IntentionAction;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
import java.util.List;
12+
13+
import static org.assertj.core.api.Assertions.assertThat;
14+
15+
/**
16+
* @author Filip Hrisafov
17+
*/
18+
public class UnmappedCollectionGetterPropertiesInspectionTest extends BaseInspectionTest {
19+
20+
@NotNull
21+
@Override
22+
protected Class<UnmappedTargetPropertiesInspection> getInspection() {
23+
return UnmappedTargetPropertiesInspection.class;
24+
}
25+
26+
@Override
27+
protected void setUp() throws Exception {
28+
super.setUp();
29+
myFixture.copyFileToProject(
30+
"UnmappedCollectionGetterPropertiesData.java",
31+
"org/example/data/UnmappedCollectionGetterPropertiesData.java"
32+
);
33+
}
34+
35+
public void testUnmappedCollectionGetterProperties() {
36+
doTest();
37+
List<IntentionAction> allQuickFixes = myFixture.getAllQuickFixes();
38+
39+
assertThat( allQuickFixes )
40+
.extracting( IntentionAction::getText )
41+
.as( "Intent Text" )
42+
.containsExactlyInAnyOrder(
43+
"Ignore unmapped target property: 'listTarget'",
44+
"Add unmapped target property: 'listTarget'",
45+
"Ignore unmapped target property: 'setTarget'",
46+
"Add unmapped target property: 'setTarget'",
47+
"Ignore unmapped target property: 'mapTarget'",
48+
"Add unmapped target property: 'mapTarget'",
49+
"Ignore all unmapped target properties"
50+
);
51+
52+
allQuickFixes.forEach( myFixture::launchAction );
53+
}
54+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright MapStruct Authors.
3+
*
4+
* Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0
5+
*/
6+
7+
import org.mapstruct.Context;
8+
import org.mapstruct.Mapper;
9+
import org.mapstruct.Mapping;
10+
import org.mapstruct.MappingTarget;
11+
import org.mapstruct.Mappings;
12+
import org.example.data.UnmappedCollectionGetterPropertiesData.Target;
13+
import org.example.data.UnmappedCollectionGetterPropertiesData.Source;
14+
15+
interface NotMapStructMapper {
16+
17+
Target map(Source source);
18+
}
19+
20+
@Mapper
21+
interface NoMappingMapper {
22+
23+
Target <warning descr="Unmapped target properties: listTarget, mapTarget, setTarget">map</warning>(Source source);
24+
25+
@org.mapstruct.InheritInverseConfiguration
26+
Source reverse(Target target);
27+
}
28+
29+
@Mapper
30+
interface AllMappingMapper {
31+
32+
@Mapping(target = "listTarget", source = "listSource")
33+
@Mapping(target = "setTarget", source = "setSource")
34+
@Mapping(target = "mapTarget", source = "mapSource")
35+
Target mapWithAllMapping(Source source);
36+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright MapStruct Authors.
3+
*
4+
* Licensed under the Apache License version 2.0, available at https://www.apache.org/licenses/LICENSE-2.0
5+
*/
6+
package org.example.data;
7+
8+
import java.util.List;
9+
import java.util.Map;
10+
import java.util.Set;
11+
12+
public class UnmappedCollectionGetterPropertiesData {
13+
public static class Source {
14+
15+
private List<String> listSource;
16+
private Set<Strinf> setSource;
17+
private Map<String, String> mapSource;
18+
19+
public List<String> getListSource() {
20+
return listSource;
21+
}
22+
23+
public Set<Strinf> getSetSource() {
24+
return setSource;
25+
}
26+
27+
public Map<String, String> getMapSource() {
28+
return mapSource;
29+
}
30+
}
31+
32+
public static class Target {
33+
34+
private List<String> listTarget;
35+
private Set<Strinf> setTarget;
36+
private Map<String, String> mapTarget;
37+
private String stringTarget;
38+
39+
public List<String> getListTarget() {
40+
return listTarget;
41+
}
42+
43+
public Set<Strinf> getSetTarget() {
44+
return setTarget;
45+
}
46+
47+
public Map<String, String> getMapTarget() {
48+
return mapTarget;
49+
}
50+
51+
public String getStringTarget() {
52+
return stringTarget;
53+
}
54+
}
55+
56+
}

0 commit comments

Comments
 (0)