mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#710 Deferring processing of mappers with incomplete source/target types to a later processing round
This commit is contained in:
parent
03bf027858
commit
55b74ae384
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.itest.tests;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.itest.testutil.runner.ProcessorSuite;
|
||||
import org.mapstruct.itest.testutil.runner.ProcessorSuite.ProcessorType;
|
||||
import org.mapstruct.itest.testutil.runner.ProcessorSuiteRunner;
|
||||
|
||||
/**
|
||||
* Tests usage of MapStruct with another processor that generates supertypes of mapping source/target types.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
@RunWith( ProcessorSuiteRunner.class )
|
||||
@ProcessorSuite(baseDir = "superTypeGenerationTest", processorTypes = ProcessorType.ORACLE_JAVA_8)
|
||||
public class SuperTypeGenerationTest {
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<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.itest</groupId>
|
||||
<artifactId>itest-supertypegeneration-aggregator</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>itest-supertypegeneration-generator</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<compilerArgs>
|
||||
<compilerArg>-proc:none</compilerArg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.itest.supertypegeneration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
/**
|
||||
* Generates base classes.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*
|
||||
*/
|
||||
@SupportedAnnotationTypes("org.mapstruct.itest.supertypegeneration.GenBase")
|
||||
public class BaseGenerationProcessor extends AbstractProcessor {
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
for (TypeElement annotation : annotations) {
|
||||
Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith( annotation );
|
||||
for (Element element : annotated) {
|
||||
AnnotationMirror annotationMirror = element.getAnnotationMirrors().get(0);
|
||||
Integer level = (Integer) annotationMirror.getElementValues().values().iterator().next().getValue();
|
||||
|
||||
if ( level >= 1 ) {
|
||||
try {
|
||||
PackageElement packageElement = processingEnv.getElementUtils().getPackageOf( element );
|
||||
Name name = element.getSimpleName();
|
||||
String baseName = name.toString() + "Base";
|
||||
String baseBaseName = level > 1 ? baseName + "Base" : null;
|
||||
|
||||
JavaFileObject baseGen = processingEnv.getFiler().createSourceFile( packageElement.getQualifiedName() + "." + baseName );
|
||||
Writer writer = baseGen.openWriter();
|
||||
writer.append( "package " + packageElement.getQualifiedName() + ";\n" );
|
||||
writer.append( "\n" );
|
||||
writer.append( "import org.mapstruct.itest.supertypegeneration.GenBase;\n" );
|
||||
writer.append( "\n" );
|
||||
if ( level > 1 ) {
|
||||
writer.append( "@GenBase( " + (level - 1) + " )\n" );
|
||||
writer.append( "public class " + baseName + " extends " + baseBaseName + " {\n" );
|
||||
}
|
||||
else {
|
||||
writer.append( "public class " + baseName + " {\n" );
|
||||
}
|
||||
writer.append( " private String baseName" + level + ";\n" );
|
||||
writer.append( " public String getBaseName" + level + "() { return baseName" + level + "; }\n" );
|
||||
writer.append( " public void setBaseName" + level + "(String baseName" + level + ") { this.baseName" + level + " = baseName" + level + ";}\n" );
|
||||
writer.append( "}\n" );
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.itest.supertypegeneration;
|
||||
|
||||
/**
|
||||
* Triggers generation of base-classes.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*
|
||||
*/
|
||||
public @interface GenBase {
|
||||
|
||||
int value();
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
# Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
# and/or other contributors as indicated by the @authors tag. See the
|
||||
# copyright.txt file in the distribution for a full listing of all
|
||||
# contributors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
org.mapstruct.itest.supertypegeneration.BaseGenerationProcessor
|
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
and/or other contributors as indicated by the @authors tag. See the
|
||||
copyright.txt file in the distribution for a full listing of all
|
||||
contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-->
|
||||
<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>
|
||||
|
||||
<groupId>org.mapstruct.itest</groupId>
|
||||
<artifactId>itest-supertypegeneration-aggregator</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>generator</module>
|
||||
<module>usage</module>
|
||||
</modules>
|
||||
</project>
|
@ -0,0 +1,47 @@
|
||||
<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.itest</groupId>
|
||||
<artifactId>itest-supertypegeneration-aggregator</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>itest-supertypegeneration-usage</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct.itest</groupId>
|
||||
<artifactId>itest-supertypegeneration-generator</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<compilerArgs>
|
||||
<compilerArg>-XprintProcessorInfo</compilerArg>
|
||||
<compilerArg>-XprintRounds</compilerArg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.itest.supertypegeneration.usage;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*
|
||||
*/
|
||||
@Mapper
|
||||
public abstract class AnotherOrderMapper {
|
||||
|
||||
public static final AnotherOrderMapper INSTANCE = Mappers.getMapper( AnotherOrderMapper.class );
|
||||
|
||||
public abstract OrderDto orderToDto(Order order);
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.itest.supertypegeneration.usage;
|
||||
|
||||
import org.mapstruct.itest.supertypegeneration.GenBase;
|
||||
|
||||
/**
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
@GenBase(2)
|
||||
public class Order extends OrderBase {
|
||||
|
||||
private String item;
|
||||
|
||||
public String getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public void setItem(String item) {
|
||||
this.item = item;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.itest.supertypegeneration.usage;
|
||||
|
||||
import org.mapstruct.itest.supertypegeneration.GenBase;
|
||||
|
||||
/**
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
@GenBase(2)
|
||||
public class OrderDto extends OrderDtoBase {
|
||||
|
||||
private String item;
|
||||
|
||||
public String getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public void setItem(String item) {
|
||||
this.item = item;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.itest.supertypegeneration.usage;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*
|
||||
*/
|
||||
@Mapper
|
||||
public abstract class OrderMapper {
|
||||
|
||||
public static final OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class );
|
||||
|
||||
public abstract OrderDto orderToDto(Order order);
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.itest.supertypegeneration.usage;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mapstruct.itest.supertypegeneration.usage.Order;
|
||||
import org.mapstruct.itest.supertypegeneration.usage.OrderDto;
|
||||
import org.mapstruct.itest.supertypegeneration.usage.OrderMapper;
|
||||
|
||||
/**
|
||||
* Integration test for using MapStruct with another annotation processor that generates super-types of mapping source
|
||||
* and target types.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*/
|
||||
public class GeneratedBasesTest {
|
||||
|
||||
@Test
|
||||
public void considersPropertiesOnGeneratedSourceAndTargetTypes() {
|
||||
Order order = new Order();
|
||||
order.setItem( "my item" );
|
||||
order.setBaseName2( "my base name 2" );
|
||||
order.setBaseName1( "my base name 1" );
|
||||
|
||||
OrderDto dto = OrderMapper.INSTANCE.orderToDto( order );
|
||||
assertEquals( order.getItem(), dto.getItem() );
|
||||
assertEquals( order.getBaseName2(), dto.getBaseName2() );
|
||||
assertEquals( order.getBaseName1(), dto.getBaseName1() );
|
||||
|
||||
// Let's make sure several mappers can be generated
|
||||
dto = AnotherOrderMapper.INSTANCE.orderToDto( order );
|
||||
assertEquals( order.getItem(), dto.getItem() );
|
||||
assertEquals( order.getBaseName2(), dto.getBaseName2() );
|
||||
assertEquals( order.getBaseName1(), dto.getBaseName1() );
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
@ -49,6 +50,7 @@ import org.mapstruct.ap.internal.processor.DefaultModelElementProcessorContext;
|
||||
import org.mapstruct.ap.internal.processor.ModelElementProcessor;
|
||||
import org.mapstruct.ap.internal.processor.ModelElementProcessor.ProcessorContext;
|
||||
import org.mapstruct.ap.internal.util.AnnotationProcessingException;
|
||||
import org.mapstruct.ap.internal.util.TypeHierarchyErroneousException;
|
||||
|
||||
/**
|
||||
* A JSR 269 annotation {@link Processor} which generates the implementations for mapper interfaces (interfaces
|
||||
@ -105,6 +107,17 @@ public class MappingProcessor extends AbstractProcessor {
|
||||
|
||||
private Options options;
|
||||
|
||||
/**
|
||||
* Any mappers for which an implementation cannot be generated in the current round because they have source/target
|
||||
* types with incomplete hierarchies (as super-types are to be generated by other processors). They will be
|
||||
* processed in subsequent rounds.
|
||||
* <p>
|
||||
* If the hierarchy of a mapper's source/target types is never completed (i.e. the missing super-types are not
|
||||
* generated by other processors), this mapper will not be generated; That's fine, the compiler will raise an error
|
||||
* due to the inconsistent Java types used as source or target anyways.
|
||||
*/
|
||||
private Set<TypeElement> deferredMappers = new HashSet<TypeElement>();
|
||||
|
||||
@Override
|
||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||
super.init( processingEnv );
|
||||
@ -132,50 +145,85 @@ public class MappingProcessor extends AbstractProcessor {
|
||||
|
||||
@Override
|
||||
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnvironment) {
|
||||
// nothing to do in the last round
|
||||
if ( !roundEnvironment.processingOver() ) {
|
||||
// process any mappers left over from previous rounds
|
||||
Set<TypeElement> deferredMappers = getAndResetDeferredMappers();
|
||||
processMapperElements( deferredMappers );
|
||||
|
||||
// get and process any mappers from this round
|
||||
Set<TypeElement> mappers = getMappers( annotations, roundEnvironment );
|
||||
processMapperElements( mappers );
|
||||
}
|
||||
|
||||
return ANNOTATIONS_CLAIMED_EXCLUSIVELY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets fresh copies of all mappers deferred from previous rounds (the originals may contain references to
|
||||
* erroneous source/target type elements).
|
||||
*/
|
||||
private Set<TypeElement> getAndResetDeferredMappers() {
|
||||
Set<TypeElement> deferred = new HashSet<TypeElement>( deferredMappers.size() );
|
||||
|
||||
for (TypeElement element : deferredMappers ) {
|
||||
deferred.add( processingEnv.getElementUtils().getTypeElement( element.getQualifiedName() ) );
|
||||
}
|
||||
|
||||
deferredMappers.clear();
|
||||
return deferred;
|
||||
}
|
||||
|
||||
private Set<TypeElement> getMappers(final Set<? extends TypeElement> annotations,
|
||||
final RoundEnvironment roundEnvironment) {
|
||||
Set<TypeElement> mapperTypes = new HashSet<TypeElement>();
|
||||
|
||||
for ( TypeElement annotation : annotations ) {
|
||||
|
||||
//Indicates that the annotation's type isn't on the class path of the compiled
|
||||
//project. Let the compiler deal with that and print an appropriate error.
|
||||
if ( annotation.getKind() != ElementKind.ANNOTATION_TYPE ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Set<? extends Element> elementsWithAnnotation;
|
||||
try {
|
||||
elementsWithAnnotation = roundEnvironment.getElementsAnnotatedWith( annotation );
|
||||
Set<? extends Element> annotatedMappers = roundEnvironment.getElementsAnnotatedWith( annotation );
|
||||
for (Element mapperElement : annotatedMappers) {
|
||||
TypeElement mapperTypeElement = asTypeElement( mapperElement );
|
||||
|
||||
// on some JDKs, RoundEnvironment.getElementsAnnotatedWith( ... ) returns types with
|
||||
// annotations unknown to the compiler, even though they are not declared Mappers
|
||||
if ( mapperTypeElement != null && MapperPrism.getInstanceOn( mapperTypeElement ) != null ) {
|
||||
mapperTypes.add( mapperTypeElement );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( Throwable t ) { // whenever that may happen, but just to stay on the save side
|
||||
handleUncaughtError( annotation, t );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return mapperTypes;
|
||||
}
|
||||
|
||||
for ( Element mapperElement : elementsWithAnnotation ) {
|
||||
try {
|
||||
TypeElement mapperTypeElement = asTypeElement( mapperElement );
|
||||
|
||||
// on some JDKs, RoundEnvironment.getElementsAnnotatedWith( ... ) returns types with
|
||||
// annotations unknown to the compiler, even though they are not declared Mappers
|
||||
if ( mapperTypeElement == null || MapperPrism.getInstanceOn( mapperTypeElement ) == null ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// create a new context for each generated mapper in order to have imports of referenced types
|
||||
// correctly managed;
|
||||
// note that this assumes that a new source file is created for each mapper which must not
|
||||
// necessarily be the case, e.g. in case of several mapper interfaces declared as inner types
|
||||
// of one outer interface
|
||||
ProcessorContext context = new DefaultModelElementProcessorContext( processingEnv, options );
|
||||
processMapperTypeElement( context, mapperTypeElement );
|
||||
}
|
||||
catch ( Throwable t ) {
|
||||
handleUncaughtError( mapperElement, t );
|
||||
break;
|
||||
}
|
||||
private void processMapperElements(Set<TypeElement> mapperElements) {
|
||||
for ( TypeElement mapperElement : mapperElements ) {
|
||||
try {
|
||||
// create a new context for each generated mapper in order to have imports of referenced types
|
||||
// correctly managed;
|
||||
// note that this assumes that a new source file is created for each mapper which must not
|
||||
// necessarily be the case, e.g. in case of several mapper interfaces declared as inner types
|
||||
// of one outer interface
|
||||
ProcessorContext context = new DefaultModelElementProcessorContext( processingEnv, options );
|
||||
processMapperTypeElement( context, mapperElement );
|
||||
}
|
||||
catch ( TypeHierarchyErroneousException thie ) {
|
||||
deferredMappers.add( mapperElement );
|
||||
}
|
||||
catch ( Throwable t ) {
|
||||
handleUncaughtError( mapperElement, t );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ANNOTATIONS_CLAIMED_EXCLUSIVELY;
|
||||
}
|
||||
|
||||
private void handleUncaughtError(Element element, Throwable thrown) {
|
||||
|
@ -155,6 +155,10 @@ public class Executables {
|
||||
element = replaceTypeElementIfNecessary( elementUtils, element );
|
||||
}
|
||||
|
||||
if ( element.asType().getKind() == TypeKind.ERROR ) {
|
||||
throw new TypeHierarchyErroneousException( element );
|
||||
}
|
||||
|
||||
addNotYetOverridden( elementUtils, alreadyAdded, methodsIn( element.getEnclosedElements() ), parentType );
|
||||
|
||||
if ( hasNonObjectSuperclass( element ) ) {
|
||||
@ -244,8 +248,12 @@ public class Executables {
|
||||
* @return {@code true}, iff the type has a super-class that is not java.lang.Object
|
||||
*/
|
||||
private static boolean hasNonObjectSuperclass(TypeElement element) {
|
||||
if ( element.getSuperclass().getKind() == TypeKind.ERROR ) {
|
||||
throw new TypeHierarchyErroneousException( element );
|
||||
}
|
||||
|
||||
return element.getSuperclass().getKind() == TypeKind.DECLARED
|
||||
&& asTypeElement( element.getSuperclass() ).getSuperclass().getKind() == TypeKind.DECLARED;
|
||||
&& !asTypeElement( element.getSuperclass() ).getQualifiedName().toString().equals( "java.lang.Object" );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright 2012-2015 Gunnar Morling (http://www.gunnarmorling.de/)
|
||||
* and/or other contributors as indicated by the @authors tag. See the
|
||||
* copyright.txt file in the distribution for a full listing of all
|
||||
* contributors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.mapstruct.ap.internal.util;
|
||||
|
||||
import javax.lang.model.element.TypeElement;
|
||||
|
||||
/**
|
||||
* Indicates a type element was visited whose hierarchy was erroneous, because it has a non-existing super-type.
|
||||
*
|
||||
* @author Gunnar Morling
|
||||
*
|
||||
*/
|
||||
public class TypeHierarchyErroneousException extends RuntimeException {
|
||||
|
||||
private TypeElement element;
|
||||
|
||||
public TypeHierarchyErroneousException(TypeElement element) {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
public TypeElement getElement() {
|
||||
return element;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user