mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#1566, #1253 Add support for initializing the AccessorNamingStrategy with Elements and Types and use Types for determining fluent setters
* This allows using generic builders
This commit is contained in:
parent
e69647f756
commit
6f19d56155
@ -114,7 +114,10 @@ public class MappingProcessor extends AbstractProcessor {
|
||||
super.init( processingEnv );
|
||||
|
||||
options = createOptions();
|
||||
annotationProcessorContext = new AnnotationProcessorContext( processingEnv.getElementUtils() );
|
||||
annotationProcessorContext = new AnnotationProcessorContext(
|
||||
processingEnv.getElementUtils(),
|
||||
processingEnv.getTypeUtils()
|
||||
);
|
||||
}
|
||||
|
||||
private Options createOptions() {
|
||||
|
@ -12,6 +12,7 @@ import java.util.ServiceLoader;
|
||||
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.spi.AccessorNamingStrategy;
|
||||
import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
|
||||
@ -20,13 +21,14 @@ import org.mapstruct.ap.spi.DefaultAccessorNamingStrategy;
|
||||
import org.mapstruct.ap.spi.DefaultBuilderProvider;
|
||||
import org.mapstruct.ap.spi.ImmutablesAccessorNamingStrategy;
|
||||
import org.mapstruct.ap.spi.ImmutablesBuilderProvider;
|
||||
import org.mapstruct.ap.spi.MapStructProcessingEnvironment;
|
||||
|
||||
/**
|
||||
* Keeps contextual data in the scope of the entire annotation processor ("application scope").
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class AnnotationProcessorContext {
|
||||
public class AnnotationProcessorContext implements MapStructProcessingEnvironment {
|
||||
|
||||
private List<AstModifyingAnnotationProcessor> astModifyingAnnotationProcessors;
|
||||
|
||||
@ -36,11 +38,13 @@ public class AnnotationProcessorContext {
|
||||
|
||||
private AccessorNamingUtils accessorNaming;
|
||||
private Elements elementUtils;
|
||||
private Types typeUtils;
|
||||
|
||||
public AnnotationProcessorContext(Elements elementUtils) {
|
||||
public AnnotationProcessorContext(Elements elementUtils, Types typeUtils) {
|
||||
astModifyingAnnotationProcessors = java.util.Collections.unmodifiableList(
|
||||
findAstModifyingAnnotationProcessors() );
|
||||
this.elementUtils = elementUtils;
|
||||
this.typeUtils = typeUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,6 +71,7 @@ public class AnnotationProcessorContext {
|
||||
defaultBuilderProvider = new ImmutablesBuilderProvider();
|
||||
}
|
||||
this.accessorNamingStrategy = Services.get( AccessorNamingStrategy.class, defaultAccessorNamingStrategy );
|
||||
this.accessorNamingStrategy.init( this );
|
||||
this.builderProvider = Services.get( BuilderProvider.class, defaultBuilderProvider );
|
||||
this.accessorNaming = new AccessorNamingUtils( this.accessorNamingStrategy );
|
||||
this.initialized = true;
|
||||
@ -86,6 +91,16 @@ public class AnnotationProcessorContext {
|
||||
return processors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Elements getElementUtils() {
|
||||
return elementUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Types getTypeUtils() {
|
||||
return typeUtils;
|
||||
}
|
||||
|
||||
public List<AstModifyingAnnotationProcessor> getAstModifyingAnnotationProcessors() {
|
||||
return astModifyingAnnotationProcessors;
|
||||
}
|
||||
|
@ -15,6 +15,15 @@ import javax.lang.model.element.ExecutableElement;
|
||||
*/
|
||||
public interface AccessorNamingStrategy {
|
||||
|
||||
/**
|
||||
* Initializes the accessor naming strategy with the MapStruct processing environment.
|
||||
*
|
||||
* @param processingEnvironment environment for facilities
|
||||
*/
|
||||
default void init(MapStructProcessingEnvironment processingEnvironment) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the given method.
|
||||
*
|
||||
|
@ -12,8 +12,10 @@ import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.SimpleElementVisitor6;
|
||||
import javax.lang.model.util.SimpleTypeVisitor6;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
import org.mapstruct.ap.spi.util.IntrospectorUtils;
|
||||
|
||||
@ -26,6 +28,15 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
||||
|
||||
private static final Pattern JAVA_JAVAX_PACKAGE = Pattern.compile( "^javax?\\..*" );
|
||||
|
||||
protected Elements elementUtils;
|
||||
protected Types typeUtils;
|
||||
|
||||
@Override
|
||||
public void init(MapStructProcessingEnvironment processingEnvironment) {
|
||||
this.elementUtils = processingEnvironment.getElementUtils();
|
||||
this.typeUtils = processingEnvironment.getTypeUtils();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodType getMethodType(ExecutableElement method) {
|
||||
if ( isGetterMethod( method ) ) {
|
||||
@ -90,8 +101,7 @@ public class DefaultAccessorNamingStrategy implements AccessorNamingStrategy {
|
||||
return method.getParameters().size() == 1 &&
|
||||
!JAVA_JAVAX_PACKAGE.matcher( method.getEnclosingElement().asType().toString() ).matches() &&
|
||||
!isAdderWithUpperCase4thCharacter( method ) &&
|
||||
//TODO The Types need to be compared with Types#isSameType(TypeMirror, TypeMirror)
|
||||
method.getReturnType().toString().equals( method.getEnclosingElement().asType().toString() );
|
||||
typeUtils.isAssignable( method.getReturnType(), method.getEnclosingElement().asType() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.spi;
|
||||
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.lang.model.util.Types;
|
||||
|
||||
/**
|
||||
* MapStruct will provide the implementations of its SPIs with on object implementing this interface so they can use
|
||||
* facilities provided by it. It is a subset of {@link javax.annotation.processing.ProcessingEnvironment
|
||||
* ProcessingEnvironment}.
|
||||
*
|
||||
* @author Filip Hrisafov
|
||||
* @see javax.annotation.processing.ProcessingEnvironment
|
||||
*/
|
||||
public interface MapStructProcessingEnvironment {
|
||||
|
||||
/**
|
||||
* Returns an implementation of some utility methods for
|
||||
* operating on elements
|
||||
*
|
||||
* @return element utilities
|
||||
*/
|
||||
Elements getElementUtils();
|
||||
|
||||
/**
|
||||
* Returns an implementation of some utility methods for
|
||||
* operating on types.
|
||||
*
|
||||
* @return type utilities
|
||||
*/
|
||||
Types getTypeUtils();
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.test.bugs._1566;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public abstract class AbstractBuilder<T extends AbstractBuilder<T>> {
|
||||
String id;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T id(final String id) {
|
||||
this.id = id;
|
||||
return (T) this;
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.test.bugs._1566;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@Mapper
|
||||
public interface Issue1566Mapper {
|
||||
|
||||
Issue1566Mapper INSTANCE = Mappers.getMapper( Issue1566Mapper.class );
|
||||
|
||||
Target map(Source source);
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.test.bugs._1566;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.ap.testutil.IssueKey;
|
||||
import org.mapstruct.ap.testutil.WithClasses;
|
||||
import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@WithClasses({
|
||||
AbstractBuilder.class,
|
||||
Issue1566Mapper.class,
|
||||
Source.class,
|
||||
Target.class
|
||||
})
|
||||
@IssueKey("1566")
|
||||
@RunWith(AnnotationProcessorTestRunner.class)
|
||||
public class Issue1566Test {
|
||||
|
||||
@Test
|
||||
public void genericMapperIsCorrectlyUsed() {
|
||||
Source source = new Source();
|
||||
source.setId( "id-123" );
|
||||
source.setName( "Source" );
|
||||
|
||||
Target target = Issue1566Mapper.INSTANCE.map( source );
|
||||
|
||||
assertThat( target ).isNotNull();
|
||||
assertThat( target.getId() ).isEqualTo( "id-123" );
|
||||
assertThat( target.getName() ).isEqualTo( "Source" );
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.test.bugs._1566;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class Source {
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
@ -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.test.bugs._1566;
|
||||
|
||||
/**
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
public class Target {
|
||||
|
||||
private final String id;
|
||||
private final String name;
|
||||
|
||||
private Target(String id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder extends AbstractBuilder<Builder> {
|
||||
private String name;
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Target build() {
|
||||
return new Target( id, name );
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user