From 27aa40c0ec4f475e7300e6a7726a09e4a6800198 Mon Sep 17 00:00:00 2001 From: Gunnar Morling Date: Mon, 7 Mar 2016 19:14:00 +0100 Subject: [PATCH] #768 Consistently using Type#getImportTypes() for determining imported types --- .../ap/internal/model/Decorator.java | 2 +- .../ap/internal/model/GeneratedType.java | 38 ++++------ .../internal/model/IterableMappingMethod.java | 1 - .../ap/internal/model/MappingMethod.java | 10 ++- .../ap/internal/model/MethodReference.java | 12 ++- .../ap/internal/model/common/Type.java | 8 +- ...ontainsCollectionWithExtendsBoundTest.java | 76 +++++++++++++++++++ .../SpaceshipMapper.java | 33 ++++++++ .../astronautmapper/AstronautMapper.java | 32 ++++++++ .../dto/AstronautDto.java | 32 ++++++++ .../dto/SpaceshipDto.java | 34 +++++++++ .../entity/Astronaut.java | 32 ++++++++ .../entity/Spaceship.java | 34 +++++++++ 13 files changed, 313 insertions(+), 31 deletions(-) create mode 100644 processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/SourceTypeContainsCollectionWithExtendsBoundTest.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/SpaceshipMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/astronautmapper/AstronautMapper.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/dto/AstronautDto.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/dto/SpaceshipDto.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/entity/Astronaut.java create mode 100644 processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/entity/Spaceship.java diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/Decorator.java b/processor/src/main/java/org/mapstruct/ap/internal/model/Decorator.java index 6874f46cb..b3dd25620 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/Decorator.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/Decorator.java @@ -171,7 +171,7 @@ public class Decorator extends GeneratedType { @Override public SortedSet getImportTypes() { SortedSet importTypes = super.getImportTypes(); - addWithDependents( importTypes, decoratorType ); + addIfImportRequired( importTypes, decoratorType ); return importTypes; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java b/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java index aab045654..3e28fc8f1 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/GeneratedType.java @@ -25,6 +25,7 @@ import java.util.SortedSet; import java.util.TreeSet; import javax.annotation.Generated; +import javax.lang.model.type.TypeKind; import org.mapstruct.ap.internal.model.common.Accessibility; import org.mapstruct.ap.internal.model.common.ModelElement; @@ -159,24 +160,24 @@ public abstract class GeneratedType extends ModelElement { for ( MappingMethod mappingMethod : methods ) { for ( Type type : mappingMethod.getImportTypes() ) { - addWithDependents( importedTypes, type ); + addIfImportRequired( importedTypes, type ); } } for ( Field field : fields ) { if ( field.isTypeRequiresImport() ) { for ( Type type : field.getImportTypes() ) { - addWithDependents( importedTypes, type ); + addIfImportRequired( importedTypes, type ); } } } for ( Annotation annotation : annotations ) { - addWithDependents( importedTypes, annotation.getType() ); + addIfImportRequired( importedTypes, annotation.getType() ); } for ( Type extraImport : extraImportedTypes ) { - addWithDependents( importedTypes, extraImport ); + addIfImportRequired( importedTypes, extraImport ); } return importedTypes; @@ -190,22 +191,13 @@ public abstract class GeneratedType extends ModelElement { constructor = null; } - protected void addWithDependents(Collection collection, Type typeToAdd) { + protected void addIfImportRequired(Collection collection, Type typeToAdd) { if ( typeToAdd == null ) { return; } if ( needsImportDeclaration( typeToAdd ) ) { - if ( typeToAdd.isArrayType() ) { - collection.add( typeToAdd.getComponentType() ); - } - else { - collection.add( typeToAdd ); - } - } - - for ( Type type : typeToAdd.getTypeParameters() ) { - addWithDependents( collection, type ); + collection.add( typeToAdd ); } } @@ -214,18 +206,20 @@ public abstract class GeneratedType extends ModelElement { return false; } - if ( typeToAdd.getPackageName() == null ) { + if ( typeToAdd.getTypeMirror().getKind() != TypeKind.DECLARED ) { return false; } - if ( typeToAdd.getPackageName().startsWith( JAVA_LANG_PACKAGE ) ) { - return false; - } - - if ( typeToAdd.getPackageName().equals( packageName ) ) { - if ( !typeToAdd.getTypeElement().getNestingKind().isNested() ) { + if ( typeToAdd.getPackageName() != null ) { + if ( typeToAdd.getPackageName().startsWith( JAVA_LANG_PACKAGE ) ) { return false; } + + if ( typeToAdd.getPackageName().equals( packageName ) ) { + if ( !typeToAdd.getTypeElement().getNestingKind().isNested() ) { + return false; + } + } } return true; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/IterableMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/IterableMappingMethod.java index 14fe95188..57725e084 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/IterableMappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/IterableMappingMethod.java @@ -194,7 +194,6 @@ public class IterableMappingMethod extends MappingMethod { types.addAll( elementAssignment.getImportTypes() ); } if ( ( factoryMethod == null ) && ( !isExistingInstanceMapping() ) ) { - types.addAll( getReturnType().getImportTypes() ); if ( getReturnType().getImplementationType() != null ) { types.addAll( getReturnType().getImplementationType().getImportTypes() ); } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/MappingMethod.java b/processor/src/main/java/org/mapstruct/ap/internal/model/MappingMethod.java index ba508706a..ab5026fb7 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/MappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/MappingMethod.java @@ -151,11 +151,15 @@ public abstract class MappingMethod extends ModelElement { Set types = new HashSet(); for ( Parameter param : parameters ) { - types.add( param.getType() ); + types.addAll( param.getType().getImportTypes() ); + } + + types.addAll( getReturnType().getImportTypes() ); + + for ( Type type : thrownTypes ) { + types.addAll( type.getImportTypes() ); } - types.add( getReturnType() ); - types.addAll( thrownTypes ); return types; } diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/MethodReference.java b/processor/src/main/java/org/mapstruct/ap/internal/model/MethodReference.java index dc9d8bf21..4a0a636d6 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/MethodReference.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/MethodReference.java @@ -76,10 +76,16 @@ public class MethodReference extends MappingMethod implements Assignment { super( method ); this.declaringMapper = declaringMapper; this.contextParam = null; - Set imported = new HashSet( method.getThrownTypes() ); - if ( targetType != null ) { - imported.add( targetType ); + Set imported = new HashSet(); + + for ( Type type : method.getThrownTypes() ) { + imported.addAll( type.getImportTypes() ); } + + if ( targetType != null ) { + imported.addAll( targetType.getImportTypes() ); + } + this.importTypes = Collections.unmodifiableSet( imported ); this.thrownTypes = method.getThrownTypes(); this.isUpdateMethod = method.getMappingTargetParameter() != null; diff --git a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java index 4f0d98db6..fc9f45510 100644 --- a/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/internal/model/common/Type.java @@ -265,7 +265,9 @@ public class Type extends ModelElement implements Comparable { public Set getImportTypes() { Set result = new HashSet(); - result.add( this ); + if ( getTypeMirror().getKind() == TypeKind.DECLARED ) { + result.add( this ); + } if ( componentType != null ) { result.addAll( componentType.getImportTypes() ); @@ -275,6 +277,10 @@ public class Type extends ModelElement implements Comparable { result.addAll( parameter.getImportTypes() ); } + if ( boundingBase != null ) { + result.addAll( boundingBase.getImportTypes() ); + } + return result; } diff --git a/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/SourceTypeContainsCollectionWithExtendsBoundTest.java b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/SourceTypeContainsCollectionWithExtendsBoundTest.java new file mode 100644 index 000000000..3b2c485ac --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/SourceTypeContainsCollectionWithExtendsBoundTest.java @@ -0,0 +1,76 @@ +/** + * Copyright 2012-2016 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.test.imports.sourcewithextendsbound; + +import static org.fest.assertions.Assertions.assertThat; + +import java.util.Collections; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.astronautmapper.AstronautMapper; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.dto.AstronautDto; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.dto.SpaceshipDto; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.entity.Astronaut; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.entity.Spaceship; +import org.mapstruct.ap.testutil.IssueKey; +import org.mapstruct.ap.testutil.WithClasses; +import org.mapstruct.ap.testutil.runner.AnnotationProcessorTestRunner; +import org.mapstruct.ap.testutil.runner.GeneratedSource; + +/** + * Test for generating a mapper which references nested types (static inner classes). + * + * @author Gunnar Morling + */ +@WithClasses({ + Astronaut.class, Spaceship.class, AstronautDto.class, SpaceshipDto.class, SpaceshipMapper.class, + AstronautMapper.class +}) +@RunWith(AnnotationProcessorTestRunner.class) +public class SourceTypeContainsCollectionWithExtendsBoundTest { + + private final GeneratedSource generatedSource = new GeneratedSource(); + + @Rule + public GeneratedSource getGeneratedSource() { + return generatedSource; + } + + @Test + @IssueKey("768") + public void generatesImportsForCollectionWithExtendsBoundInSourceType() { + Astronaut astronaut = new Astronaut(); + astronaut.setName( "Bob" ); + + Spaceship spaceship = new Spaceship(); + spaceship.setAstronauts( Collections.singleton( astronaut ) ); + + SpaceshipDto spaceshipDto = SpaceshipMapper.INSTANCE.spaceshipToDto( spaceship ); + + assertThat( spaceshipDto ).isNotNull(); + assertThat( spaceshipDto.getAstronauts() ).onProperty( "name" ).containsOnly( "Bob" ); + + generatedSource.forMapper( SpaceshipMapper.class ).containsImportFor( Astronaut.class ); + generatedSource.forMapper( SpaceshipMapper.class ).containsImportFor( Spaceship.class ); + generatedSource.forMapper( SpaceshipMapper.class ).containsImportFor( AstronautDto.class ); + generatedSource.forMapper( SpaceshipMapper.class ).containsImportFor( SpaceshipDto.class ); + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/SpaceshipMapper.java b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/SpaceshipMapper.java new file mode 100644 index 000000000..50f15b8d6 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/SpaceshipMapper.java @@ -0,0 +1,33 @@ +/** + * Copyright 2012-2016 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.test.imports.sourcewithextendsbound; + +import org.mapstruct.Mapper; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.astronautmapper.AstronautMapper; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.dto.SpaceshipDto; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.entity.Spaceship; +import org.mapstruct.factory.Mappers; + +@Mapper(uses = AstronautMapper.class) +public interface SpaceshipMapper { + + SpaceshipMapper INSTANCE = Mappers.getMapper( SpaceshipMapper.class ); + + SpaceshipDto spaceshipToDto(Spaceship spaceship); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/astronautmapper/AstronautMapper.java b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/astronautmapper/AstronautMapper.java new file mode 100644 index 000000000..401728d02 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/astronautmapper/AstronautMapper.java @@ -0,0 +1,32 @@ +/** + * Copyright 2012-2016 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.test.imports.sourcewithextendsbound.astronautmapper; + +import org.mapstruct.Mapper; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.dto.AstronautDto; +import org.mapstruct.ap.test.imports.sourcewithextendsbound.entity.Astronaut; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface AstronautMapper { + + AstronautMapper INSTANCE = Mappers.getMapper( AstronautMapper.class ); + + AstronautDto astronautToDto(Astronaut astronaut); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/dto/AstronautDto.java b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/dto/AstronautDto.java new file mode 100644 index 000000000..5d7008e72 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/dto/AstronautDto.java @@ -0,0 +1,32 @@ +/** + * Copyright 2012-2016 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.test.imports.sourcewithextendsbound.dto; + +public class AstronautDto { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/dto/SpaceshipDto.java b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/dto/SpaceshipDto.java new file mode 100644 index 000000000..40c4c0355 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/dto/SpaceshipDto.java @@ -0,0 +1,34 @@ +/** + * Copyright 2012-2016 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.test.imports.sourcewithextendsbound.dto; + +import java.util.Collection; + +public class SpaceshipDto { + + private Collection astronauts; + + public Collection getAstronauts() { + return astronauts; + } + + public void setAstronauts(Collection astronauts) { + this.astronauts = astronauts; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/entity/Astronaut.java b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/entity/Astronaut.java new file mode 100644 index 000000000..b723f415f --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/entity/Astronaut.java @@ -0,0 +1,32 @@ +/** + * Copyright 2012-2016 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.test.imports.sourcewithextendsbound.entity; + +public class Astronaut { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/entity/Spaceship.java b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/entity/Spaceship.java new file mode 100644 index 000000000..c147c8275 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/imports/sourcewithextendsbound/entity/Spaceship.java @@ -0,0 +1,34 @@ +/** + * Copyright 2012-2016 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.test.imports.sourcewithextendsbound.entity; + +import java.util.Collection; + +public class Spaceship { + + private Collection astronauts; + + public Collection getAstronauts() { + return astronauts; + } + + public void setAstronauts(Collection astronauts) { + this.astronauts = astronauts; + } +}