diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java b/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java index ba00d7f77..73e6b557d 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java +++ b/processor/src/main/java/org/mapstruct/ap/model/common/TypeFactory.java @@ -123,16 +123,16 @@ public class TypeFactory { Type implementationType = getImplementationType( mirror ); boolean isIterableType = typeUtils.isSubtype( - mirror, - iterableType + typeUtils.erasure( mirror ), + typeUtils.erasure( iterableType ) ); boolean isCollectionType = typeUtils.isSubtype( - mirror, - collectionType + typeUtils.erasure( mirror ), + typeUtils.erasure( collectionType ) ); boolean isMapType = typeUtils.isSubtype( - mirror, - mapType + typeUtils.erasure( mirror ), + typeUtils.erasure( mapType ) ); boolean isEnumType; diff --git a/processor/src/main/java/org/mapstruct/ap/model/source/MethodMatcher.java b/processor/src/main/java/org/mapstruct/ap/model/source/MethodMatcher.java index 30f1e48eb..51adbd9b5 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/source/MethodMatcher.java +++ b/processor/src/main/java/org/mapstruct/ap/model/source/MethodMatcher.java @@ -207,7 +207,8 @@ public class MethodMatcher { } else { // check if types are in bound - if ( typeUtils.isSubtype( t.getLowerBound(), p ) && typeUtils.isSubtype( p, t.getUpperBound() ) ) { + if ( typeUtils.isSubtype( typeUtils.erasure( t.getLowerBound() ), typeUtils.erasure( p ) ) && + typeUtils.isSubtype( typeUtils.erasure( p ), typeUtils.erasure( t.getUpperBound() ) ) ) { genericTypesMap.put( t, p ); return Boolean.TRUE; } @@ -227,7 +228,7 @@ public class MethodMatcher { case DECLARED: // for example method: String method(? extends String) // isSubType checks range [subtype, type], e.g. isSubtype [Object, String]==true - return typeUtils.isSubtype( p, extendsBound ); + return typeUtils.isSubtype( typeUtils.erasure( p ), extendsBound ); case TYPEVAR: // for example method: T method(? extends T) @@ -249,7 +250,8 @@ public class MethodMatcher { // for example method: String method(? super String) // to check super type, we can simply reverse the argument, but that would initially yield // a result: bounds = tpe.getBounds(); if ( t != null && bounds != null ) { for ( TypeMirror bound : bounds ) { - if ( !( bound.getKind().equals( TypeKind.DECLARED ) && typeUtils.isSubtype( t, bound ) ) ) { + if ( !( bound.getKind().equals( TypeKind.DECLARED ) && + typeUtils.isSubtype( typeUtils.erasure( t ), typeUtils.erasure( bound ) ) ) ) { return false; } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ConversionTest.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ConversionTest.java index 0bcdee1c9..db15090a2 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ConversionTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ConversionTest.java @@ -158,4 +158,18 @@ public class ConversionTest extends MapperTestBase { }) public void shouldFailOnSuperBounds2() { } + + @Test + @WithClasses({ ErroneousSource6.class, ErroneousTarget6.class, ErroneousSourceTargetMapper6.class }) + @ExpectedCompilationOutcome(value = CompilationResult.FAILED, + diagnostics = { + @Diagnostic(type = ErroneousSourceTargetMapper6.class, + kind = javax.tools.Diagnostic.Kind.ERROR, + line = 29, + messageRegExp = "Can't map property \"org.mapstruct.ap.test.conversion.generics.WildCardSuperWrapper" + + " foo\" to" + + " \"org.mapstruct.ap.test.conversion.generics.WildCardSuperWrapper foo\"") + }) + public void shouldFailOnNonMatchingWildCards() { + } } diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ErroneousSource6.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ErroneousSource6.java new file mode 100644 index 000000000..79240f9d9 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ErroneousSource6.java @@ -0,0 +1,35 @@ +/** + * Copyright 2012-2014 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.conversion.generics; + +public class ErroneousSource6 { + + private WildCardSuperWrapper foo; + + public WildCardSuperWrapper getFoo() { + return foo; + } + + public void setFoo(WildCardSuperWrapper foo) { + this.foo = foo; + } + + + +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ErroneousSourceTargetMapper6.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ErroneousSourceTargetMapper6.java new file mode 100644 index 000000000..88655afe2 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ErroneousSourceTargetMapper6.java @@ -0,0 +1,30 @@ +/** + * Copyright 2012-2014 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.conversion.generics; + +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +@Mapper( uses = GenericTypeMapper.class ) +public interface ErroneousSourceTargetMapper6 { + + ErroneousSourceTargetMapper6 INSTANCE = Mappers.getMapper( ErroneousSourceTargetMapper6.class ); + + ErroneousTarget6 sourceToTarget(ErroneousSource6 source); +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ErroneousTarget6.java b/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ErroneousTarget6.java new file mode 100644 index 000000000..cc1c06ec8 --- /dev/null +++ b/processor/src/test/java/org/mapstruct/ap/test/conversion/generics/ErroneousTarget6.java @@ -0,0 +1,32 @@ +/** + * Copyright 2012-2014 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.conversion.generics; + +public class ErroneousTarget6 { + + private WildCardSuperWrapper foo; + + public WildCardSuperWrapper getFoo() { + return foo; + } + + public void setFoo(WildCardSuperWrapper foo) { + this.foo = foo; + } +} diff --git a/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousfactorymethod/FactoryTest.java b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousfactorymethod/FactoryTest.java index 239170280..bcb63ddd4 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousfactorymethod/FactoryTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/erroneous/ambiguousfactorymethod/FactoryTest.java @@ -45,11 +45,11 @@ public class FactoryTest extends MapperTestBase { @Diagnostic(type = BarFactory.class, kind = javax.tools.Diagnostic.Kind.ERROR, line = 29, - messageRegExp = "^Ambiguous factory methods: \"org\\.mapstruct\\.ap\\.test\\.erroneous\\." + messageRegExp = "Ambiguous factory methods: \"org\\.mapstruct\\.ap\\.test\\.erroneous\\." + "ambiguousfactorymethod\\.Bar createBar\\(\\)\" conflicts with " + "\"org\\.mapstruct\\.ap\\.test\\.erroneous\\.ambiguousfactorymethod\\.Bar " + "org\\.mapstruct\\.ap\\.test\\.erroneous\\.ambiguousfactorymethod" - + "\\.a\\.BarFactory\\.createBar\\(\\)\"\\.$") + + "\\.a\\.BarFactory\\.createBar\\(\\)\"\\") } ) public void shouldUseTwoFactoryMethods() { diff --git a/processor/src/test/java/org/mapstruct/ap/test/severalsources/SeveralSourceParametersTest.java b/processor/src/test/java/org/mapstruct/ap/test/severalsources/SeveralSourceParametersTest.java index 0983775e6..345e09021 100644 --- a/processor/src/test/java/org/mapstruct/ap/test/severalsources/SeveralSourceParametersTest.java +++ b/processor/src/test/java/org/mapstruct/ap/test/severalsources/SeveralSourceParametersTest.java @@ -18,6 +18,7 @@ */ package org.mapstruct.ap.test.severalsources; +import javax.lang.model.SourceVersion; import javax.tools.Diagnostic.Kind; import org.mapstruct.ap.testutil.IssueKey; @@ -101,12 +102,22 @@ public class SeveralSourceParametersTest extends MapperTestBase { @ExpectedCompilationOutcome( value = CompilationResult.FAILED, diagnostics = { + @Diagnostic(type = ErroneousSourceTargetMapper.class, + kind = Kind.ERROR, + line = 29, + messageRegExp = "Several possible source properties for target property \"description\".", + javaVersions = { SourceVersion.RELEASE_6 } ), + @Diagnostic(type = ErroneousSourceTargetMapper.class, + kind = Kind.ERROR, + line = 29, + messageRegExp = "Several possible source properties for target property \"zipCode\".", + javaVersions = { SourceVersion.RELEASE_6 } ), @Diagnostic(type = ErroneousSourceTargetMapper.class, kind = Kind.ERROR, line = 29, messageRegExp = "Several possible source properties for target property \"street\".") - } - ) + }) + public void shouldFailToGenerateMappingsForAmbigiousSourceProperty() { } } diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/MapperTestBase.java b/processor/src/test/java/org/mapstruct/ap/testutil/MapperTestBase.java index 7358be399..4e951d037 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/MapperTestBase.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/MapperTestBase.java @@ -132,7 +132,7 @@ public abstract class MapperTestBase { diagnostics.getDiagnostics() ); CompilationOutcomeDescriptor expectedResult = CompilationOutcomeDescriptor.forExpectedCompilationResult( - testMethod.getAnnotation( ExpectedCompilationOutcome.class ) + testMethod.getAnnotation( ExpectedCompilationOutcome.class ) ); if ( expectedResult.getCompilationResult() == CompilationResult.SUCCEEDED ) { @@ -344,4 +344,8 @@ public abstract class MapperTestBase { return o1.getMessage().compareTo( o2.getMessage() ); } } + + private boolean isJdk6() { + return ( Integer.parseInt( System.getProperty( "java.version" ).split( "\\." )[1]) == 6 ); + } } diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/Diagnostic.java b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/Diagnostic.java index 1efe72c22..b09573577 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/Diagnostic.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/annotation/Diagnostic.java @@ -19,6 +19,7 @@ package org.mapstruct.ap.testutil.compilation.annotation; import javax.tools.Diagnostic.Kind; +import javax.lang.model.SourceVersion; /** * An expected diagnostic of a compilation. @@ -57,4 +58,11 @@ public @interface Diagnostic { * diagnostic. */ String messageRegExp() default ".*"; + + /** + * The java version for which this this diagnostic is valid. + * + * @return versions for which this Diagnostic should be evaluated. Default it evaluates for all + */ + SourceVersion[] javaVersions() default { }; } diff --git a/processor/src/test/java/org/mapstruct/ap/testutil/compilation/model/CompilationOutcomeDescriptor.java b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/model/CompilationOutcomeDescriptor.java index a148213d7..5f87a4e04 100644 --- a/processor/src/test/java/org/mapstruct/ap/testutil/compilation/model/CompilationOutcomeDescriptor.java +++ b/processor/src/test/java/org/mapstruct/ap/testutil/compilation/model/CompilationOutcomeDescriptor.java @@ -21,6 +21,7 @@ package org.mapstruct.ap.testutil.compilation.model; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import javax.lang.model.SourceVersion; import javax.tools.Diagnostic; import javax.tools.Diagnostic.Kind; import javax.tools.JavaFileObject; @@ -56,13 +57,27 @@ public class CompilationOutcomeDescriptor { List diagnosticDescriptors = new ArrayList(); for ( org.mapstruct.ap.testutil.compilation.annotation.Diagnostic diagnostic : expectedCompilationResult.diagnostics() ) { - diagnosticDescriptors.add( DiagnosticDescriptor.forDiagnostic( diagnostic ) ); + if ( requiresEvaluation( diagnostic.javaVersions() ) ) { + diagnosticDescriptors.add( DiagnosticDescriptor.forDiagnostic( diagnostic ) ); + } } return new CompilationOutcomeDescriptor( expectedCompilationResult.value(), diagnosticDescriptors ); } } + private static boolean requiresEvaluation(SourceVersion[] sourceVersions) { + if ( sourceVersions.length == 0 ) { + return true; + } + for (SourceVersion sourceVersion : sourceVersions) { + if (SourceVersion.latestSupported().equals( sourceVersion ) ) { + return true; + } + } + return false; + } + public static CompilationOutcomeDescriptor forResult(String sourceDir, boolean compilationSuccessful, List> diagnostics) { CompilationResult compilationResult =