Skip to content

Commit

Permalink
Use correct type for the Record component read accessors
Browse files Browse the repository at this point in the history
  • Loading branch information
filiphr committed Sep 1, 2024
1 parent c6010c9 commit 478648f
Show file tree
Hide file tree
Showing 18 changed files with 265 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ void recordsTest() {
void recordsCrossModuleTest() {
}

@ProcessorTest(baseDir = "recordsCrossModuleInterfaceTest", processorTypes = {
ProcessorTest.ProcessorType.JAVAC
})
@EnabledForJreRange(min = JRE.JAVA_17)
void recordsCrossModuleInterfaceTest() {
}

@ProcessorTest(baseDir = "expressionTextBlocksTest", processorTypes = {
ProcessorTest.ProcessorType.JAVAC
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright MapStruct Authors.
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>recordsCrossModuleInterfaceTest</artifactId>
<groupId>org.mapstruct</groupId>
<version>1.0.0</version>
</parent>

<artifactId>records-cross-module-1</artifactId>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.itest.records.module1;

public interface NestedInterface {
String field();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.itest.records.module1;

public interface RootInterface {
NestedInterface nested();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.itest.records.module1;

public record SourceNestedRecord(
String field
) implements NestedInterface {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.itest.records.module1;

public record SourceRootRecord(
SourceNestedRecord nested
) implements RootInterface {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright MapStruct Authors.
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>recordsCrossModuleInterfaceTest</artifactId>
<groupId>org.mapstruct</groupId>
<version>1.0.0</version>
</parent>

<artifactId>records-cross-module-2</artifactId>


<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>records-cross-module-1</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.itest.records.module2;

import org.mapstruct.itest.records.module1.SourceRootRecord;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface RecordInterfaceIssueMapper {

RecordInterfaceIssueMapper INSTANCE = Mappers.getMapper(RecordInterfaceIssueMapper.class);

TargetRootRecord map(SourceRootRecord source);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.itest.records.module2;

public record TargetNestedRecord(
String field
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.itest.records.module2;

public record TargetRootRecord(
TargetNestedRecord nested
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.itest.records.module2;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;
import org.mapstruct.itest.records.module1.SourceRootRecord;
import org.mapstruct.itest.records.module1.SourceNestedRecord;

public class RecordsTest {

@Test
public void shouldMap() {
SourceRootRecord source = new SourceRootRecord( new SourceNestedRecord( "test" ) );
TargetRootRecord target = RecordInterfaceIssueMapper.INSTANCE.map( source );

assertThat( target ).isNotNull();
assertThat( target.nested() ).isNotNull();
assertThat( target.nested().field() ).isEqualTo( "test" );
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright MapStruct Authors.
Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-it-parent</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>recordsCrossModuleInterfaceTest</artifactId>
<packaging>pom</packaging>

<modules>
<module>module-1</module>
<module>module-2</module>
</modules>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
import org.mapstruct.ap.internal.util.TypeUtils;
import org.mapstruct.ap.internal.util.accessor.Accessor;
import org.mapstruct.ap.internal.util.accessor.AccessorType;
import org.mapstruct.ap.internal.util.accessor.FieldElementAccessor;
import org.mapstruct.ap.internal.util.accessor.ElementAccessor;
import org.mapstruct.ap.internal.util.accessor.MapValueAccessor;
import org.mapstruct.ap.internal.util.accessor.PresenceCheckAccessor;
import org.mapstruct.ap.internal.util.accessor.ReadAccessor;
Expand Down Expand Up @@ -1047,7 +1047,7 @@ private List<Accessor> getAlternativeTargetAccessors() {
List<Accessor> setterMethods = getSetters();
List<Accessor> readAccessors = new ArrayList<>( getPropertyReadAccessors().values() );
// All the fields are also alternative accessors
readAccessors.addAll( filters.fieldsIn( getAllFields(), FieldElementAccessor::new ) );
readAccessors.addAll( filters.fieldsIn( getAllFields(), ElementAccessor::new ) );

// there could be a read accessor (field or method) for a list/map that is not present as setter.
// an accessor could substitute the setter in that case and act as setter.
Expand Down
33 changes: 10 additions & 23 deletions processor/src/main/java/org/mapstruct/ap/internal/util/Filters.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,16 @@
public class Filters {

private static final Method RECORD_COMPONENTS_METHOD;
private static final Method RECORD_COMPONENT_ACCESSOR_METHOD;

static {
Method recordComponentsMethod;
Method recordComponentAccessorMethod;
try {
recordComponentsMethod = TypeElement.class.getMethod( "getRecordComponents" );
recordComponentAccessorMethod = Class.forName( "javax.lang.model.element.RecordComponentElement" )
.getMethod( "getAccessor" );
}
catch ( NoSuchMethodException | ClassNotFoundException e ) {
catch ( NoSuchMethodException e ) {
recordComponentsMethod = null;
recordComponentAccessorMethod = null;
}
RECORD_COMPONENTS_METHOD = recordComponentsMethod;
RECORD_COMPONENT_ACCESSOR_METHOD = recordComponentAccessorMethod;
}

private final AccessorNamingUtils accessorNaming;
Expand Down Expand Up @@ -89,25 +83,18 @@ public List<Element> recordComponentsIn(TypeElement typeElement) {
}

public Map<String, ReadAccessor> recordAccessorsIn(Collection<Element> recordComponents) {
if ( RECORD_COMPONENT_ACCESSOR_METHOD == null ) {
if ( recordComponents.isEmpty() ) {
return java.util.Collections.emptyMap();
}
try {
Map<String, ReadAccessor> recordAccessors = new LinkedHashMap<>();
for ( Element recordComponent : recordComponents ) {
ExecutableElement recordExecutableElement =
(ExecutableElement) RECORD_COMPONENT_ACCESSOR_METHOD.invoke( recordComponent );
recordAccessors.put(
recordComponent.getSimpleName().toString(),
ReadAccessor.fromGetter( recordExecutableElement, getReturnType( recordExecutableElement ) )
);
}

return recordAccessors;
}
catch ( IllegalAccessException | InvocationTargetException e ) {
return java.util.Collections.emptyMap();
Map<String, ReadAccessor> recordAccessors = new LinkedHashMap<>();
for ( Element recordComponent : recordComponents ) {
recordAccessors.put(
recordComponent.getSimpleName().toString(),
ReadAccessor.fromRecordComponent( recordComponent )
);
}

return recordAccessors;
}

private TypeMirror getReturnType(ExecutableElement executableElement) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.internal.util.accessor;

import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;

/**
* An {@link Accessor} that wraps a {@link VariableElement}.
*
* @author Filip Hrisafov
*/
public class ElementAccessor extends AbstractAccessor<Element> {

private final AccessorType accessorType;

public ElementAccessor(VariableElement variableElement) {
this( variableElement, AccessorType.FIELD );
}

public ElementAccessor(Element element, AccessorType accessorType) {
super( element );
this.accessorType = accessorType;
}

@Override
public TypeMirror getAccessedType() {
return element.asType();
}

@Override
public String toString() {
return element.toString();
}

@Override
public AccessorType getAccessorType() {
return accessorType;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
package org.mapstruct.ap.internal.util.accessor;

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
Expand All @@ -17,14 +18,23 @@ public interface ReadAccessor extends Accessor {
String getReadValueSource();

static ReadAccessor fromField(VariableElement variableElement) {
return new ReadDelegateAccessor( new FieldElementAccessor( variableElement ) ) {
return new ReadDelegateAccessor( new ElementAccessor( variableElement ) ) {
@Override
public String getReadValueSource() {
return getSimpleName();
}
};
}

static ReadAccessor fromRecordComponent(Element element) {
return new ReadDelegateAccessor( new ElementAccessor( element, AccessorType.GETTER ) ) {
@Override
public String getReadValueSource() {
return getSimpleName() + "()";
}
};
}

static ReadAccessor fromGetter(ExecutableElement element, TypeMirror accessedType) {
return new ReadDelegateAccessor( new ExecutableElementAccessor( element, accessedType, AccessorType.GETTER ) ) {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
package org.mapstruct.ap.internal.util.accessor;

import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;

Expand All @@ -13,9 +14,9 @@
*
* @author Filip Hrisafov
*/
public class FieldElementAccessor extends AbstractAccessor<VariableElement> {
public class RecordElementAccessor extends AbstractAccessor<Element> {

public FieldElementAccessor(VariableElement element) {
public RecordElementAccessor(Element element) {
super( element );
}

Expand All @@ -31,7 +32,7 @@ public String toString() {

@Override
public AccessorType getAccessorType() {
return AccessorType.FIELD;
return AccessorType.GETTER;
}

}

0 comments on commit 478648f

Please sign in to comment.