mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#11 Raising an error when referencing unknown attribute in @Mapping
This commit is contained in:
parent
f5f448ab08
commit
b3b90f7969
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@
|
|||||||
.classpath
|
.classpath
|
||||||
.project
|
.project
|
||||||
.settings
|
.settings
|
||||||
|
.factorypath
|
||||||
|
|
||||||
# IntelliJ
|
# IntelliJ
|
||||||
*.iml
|
*.iml
|
||||||
|
@ -29,6 +29,8 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
|
import javax.lang.model.element.AnnotationValue;
|
||||||
import javax.lang.model.element.Element;
|
import javax.lang.model.element.Element;
|
||||||
import javax.lang.model.element.ExecutableElement;
|
import javax.lang.model.element.ExecutableElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
@ -358,19 +360,24 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
for ( ExecutableElement method : methodsIn( element.getEnclosedElements() ) ) {
|
for ( ExecutableElement method : methodsIn( element.getEnclosedElements() ) ) {
|
||||||
Parameter parameter = retrieveParameter( method );
|
Parameter parameter = retrieveParameter( method );
|
||||||
Type returnType = retrieveReturnType( method );
|
Type returnType = retrieveReturnType( method );
|
||||||
|
boolean mappingErroneous = false;
|
||||||
|
|
||||||
if ( declaringMapper == null ) {
|
if ( declaringMapper == null ) {
|
||||||
if ( parameter.getType().isIterableType() && !returnType.isIterableType() ) {
|
if ( parameter.getType().isIterableType() && !returnType.isIterableType() ) {
|
||||||
reportError( "Can't generate mapping method from iterable type to non-iterable ype.", method );
|
reportError( "Can't generate mapping method from iterable type to non-iterable ype.", method );
|
||||||
|
mappingErroneous = true;
|
||||||
}
|
}
|
||||||
if ( !parameter.getType().isIterableType() && returnType.isIterableType() ) {
|
if ( !parameter.getType().isIterableType() && returnType.isIterableType() ) {
|
||||||
reportError( "Can't generate mapping method from non-iterable type to iterable ype.", method );
|
reportError( "Can't generate mapping method from non-iterable type to iterable ype.", method );
|
||||||
|
mappingErroneous = true;
|
||||||
}
|
}
|
||||||
if ( parameter.getType().isPrimitive() ) {
|
if ( parameter.getType().isPrimitive() ) {
|
||||||
reportError( "Can't generate mapping method with primitive parameter type.", method );
|
reportError( "Can't generate mapping method with primitive parameter type.", method );
|
||||||
|
mappingErroneous = true;
|
||||||
}
|
}
|
||||||
if ( returnType.isPrimitive() ) {
|
if ( returnType.isPrimitive() ) {
|
||||||
reportError( "Can't generate mapping method with primitive return type.", method );
|
reportError( "Can't generate mapping method with primitive return type.", method );
|
||||||
|
mappingErroneous = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mappingErroneous ) {
|
if ( mappingErroneous ) {
|
||||||
@ -432,15 +439,16 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
Element parameterElement = typeUtils.asElement( method.getParameters().get( 0 ).asType() );
|
Element parameterElement = typeUtils.asElement( method.getParameters().get( 0 ).asType() );
|
||||||
|
|
||||||
List<MappedProperty> properties = new ArrayList<MappedProperty>();
|
List<MappedProperty> properties = new ArrayList<MappedProperty>();
|
||||||
|
List<ExecutableElement> sourceGetters = Filters.getterMethodsIn( parameterElement.getEnclosedElements() );
|
||||||
|
List<ExecutableElement> targetSetters = Filters.setterMethodsIn( returnTypeElement.getEnclosedElements() );
|
||||||
|
|
||||||
for ( ExecutableElement getterMethod : Filters.getterMethodsIn( parameterElement.getEnclosedElements() ) ) {
|
reportErrorIfMappedPropertiesDontExist( method, mappings, sourceGetters, targetSetters );
|
||||||
|
|
||||||
|
for ( ExecutableElement getterMethod : sourceGetters ) {
|
||||||
String sourcePropertyName = Executables.getPropertyName( getterMethod );
|
String sourcePropertyName = Executables.getPropertyName( getterMethod );
|
||||||
Mapping mapping = mappings.get( sourcePropertyName );
|
Mapping mapping = mappings.get( sourcePropertyName );
|
||||||
|
|
||||||
for ( ExecutableElement setterMethod :Filters.setterMethodsIn( returnTypeElement
|
for ( ExecutableElement setterMethod : targetSetters ) {
|
||||||
.getEnclosedElements() ) ) {
|
|
||||||
|
|
||||||
String targetPropertyName = Executables.getPropertyName( setterMethod );
|
String targetPropertyName = Executables.getPropertyName( setterMethod );
|
||||||
|
|
||||||
if ( targetPropertyName.equals( mapping != null ? mapping.getTargetName() : sourcePropertyName ) ) {
|
if ( targetPropertyName.equals( mapping != null ? mapping.getTargetName() : sourcePropertyName ) ) {
|
||||||
@ -467,6 +475,45 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reportErrorIfMappedPropertiesDontExist(ExecutableElement method, Map<String, Mapping> mappings,
|
||||||
|
List<ExecutableElement> sourceGetters,
|
||||||
|
List<ExecutableElement> targetSetters) {
|
||||||
|
|
||||||
|
Set<String> sourcePropertyNames = getPropertyNames( sourceGetters );
|
||||||
|
Set<String> targetPropertyNames = getPropertyNames( targetSetters );
|
||||||
|
|
||||||
|
for ( Mapping mappedProperty : mappings.values() ) {
|
||||||
|
if ( !sourcePropertyNames.contains( mappedProperty.getSourceName() ) ) {
|
||||||
|
reportError(
|
||||||
|
String.format(
|
||||||
|
"Unknown property \"%s\" in parameter type %s.",
|
||||||
|
mappedProperty.getSourceName(),
|
||||||
|
retrieveParameter( method ).getType()
|
||||||
|
), method, mappedProperty.getMirror(), mappedProperty.getSourceAnnotationValue()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ( !targetPropertyNames.contains( mappedProperty.getTargetName() ) ) {
|
||||||
|
reportError(
|
||||||
|
String.format(
|
||||||
|
"Unknown property \"%s\" in return type %s.",
|
||||||
|
mappedProperty.getTargetName(),
|
||||||
|
retrieveReturnType( method )
|
||||||
|
), method, mappedProperty.getMirror(), mappedProperty.getTargetAnnotationValue()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getPropertyNames(List<ExecutableElement> propertyAccessors) {
|
||||||
|
Set<String> propertyNames = new HashSet<String>();
|
||||||
|
|
||||||
|
for ( ExecutableElement executableElement : propertyAccessors ) {
|
||||||
|
propertyNames.add( Executables.getPropertyName( executableElement ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return propertyNames;
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, Mapping> getMappings(MappingsPrism mappingsAnnotation) {
|
private Map<String, Mapping> getMappings(MappingsPrism mappingsAnnotation) {
|
||||||
Map<String, Mapping> mappings = new HashMap<String, Mapping>();
|
Map<String, Mapping> mappings = new HashMap<String, Mapping>();
|
||||||
|
|
||||||
@ -478,7 +525,13 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Mapping getMapping(MappingPrism mapping) {
|
private Mapping getMapping(MappingPrism mapping) {
|
||||||
return new Mapping( mapping.source(), mapping.target() );
|
return new Mapping(
|
||||||
|
mapping.source(),
|
||||||
|
mapping.target(),
|
||||||
|
mapping.mirror,
|
||||||
|
mapping.values.source(),
|
||||||
|
mapping.values.target()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Parameter retrieveParameter(ExecutableElement method) {
|
private Parameter retrieveParameter(ExecutableElement method) {
|
||||||
@ -505,4 +558,11 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
processingEnvironment.getMessager().printMessage( Kind.ERROR, message, element );
|
processingEnvironment.getMessager().printMessage( Kind.ERROR, message, element );
|
||||||
mappingErroneous = true;
|
mappingErroneous = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reportError(String message, Element element, AnnotationMirror annotationMirror,
|
||||||
|
AnnotationValue annotationValue) {
|
||||||
|
processingEnvironment.getMessager()
|
||||||
|
.printMessage( Kind.ERROR, message, element, annotationMirror, annotationValue );
|
||||||
|
mappingErroneous = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,24 @@
|
|||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.model.source;
|
package org.mapstruct.ap.model.source;
|
||||||
|
|
||||||
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
|
import javax.lang.model.element.AnnotationValue;
|
||||||
|
|
||||||
public class Mapping {
|
public class Mapping {
|
||||||
|
|
||||||
private final String sourceName;
|
private final String sourceName;
|
||||||
private final String targetName;
|
private final String targetName;
|
||||||
|
private final AnnotationMirror mirror;
|
||||||
|
private final AnnotationValue sourceAnnotationValue;
|
||||||
|
private final AnnotationValue targetAnnotationValue;
|
||||||
|
|
||||||
public Mapping(String sourceName, String targetName) {
|
public Mapping(String sourceName, String targetName, AnnotationMirror mirror, AnnotationValue sourceAnnotationValue,
|
||||||
|
AnnotationValue targetAnnotationValue) {
|
||||||
this.sourceName = sourceName;
|
this.sourceName = sourceName;
|
||||||
this.targetName = targetName;
|
this.targetName = targetName;
|
||||||
|
this.mirror = mirror;
|
||||||
|
this.sourceAnnotationValue = sourceAnnotationValue;
|
||||||
|
this.targetAnnotationValue = targetAnnotationValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSourceName() {
|
public String getSourceName() {
|
||||||
@ -36,6 +46,18 @@ public class Mapping {
|
|||||||
return targetName;
|
return targetName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AnnotationMirror getMirror() {
|
||||||
|
return mirror;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnnotationValue getSourceAnnotationValue() {
|
||||||
|
return sourceAnnotationValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnnotationValue getTargetAnnotationValue() {
|
||||||
|
return targetAnnotationValue;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Mapping {" +
|
return "Mapping {" +
|
||||||
|
@ -37,4 +37,9 @@ public class Parameter {
|
|||||||
public Type getType() {
|
public Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return type.toString() + " " + name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2013 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.erroneous.attributereference;
|
||||||
|
|
||||||
|
public class AnotherTarget {
|
||||||
|
|
||||||
|
private int foo;
|
||||||
|
|
||||||
|
public int getFoo() {
|
||||||
|
return foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFoo(int foo) {
|
||||||
|
this.foo = foo;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2013 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.erroneous.attributereference;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ErroneousMapper {
|
||||||
|
|
||||||
|
@Mapping(source = "foo", target = "bar")
|
||||||
|
Target sourceToTarget(Source source);
|
||||||
|
|
||||||
|
@Mapping(source = "bar", target = "foo")
|
||||||
|
AnotherTarget sourceToAnotherTarget(Source source);
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2013 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.erroneous.attributereference;
|
||||||
|
|
||||||
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.MapperTestBase;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.CompilationResult;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.Diagnostic;
|
||||||
|
import org.mapstruct.ap.testutil.compilation.annotation.ExpectedCompilationOutcome;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@WithClasses({ ErroneousMapper.class, Source.class, Target.class, AnotherTarget.class })
|
||||||
|
public class ErroneousMappingsTest extends MapperTestBase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IssueKey("11")
|
||||||
|
@ExpectedCompilationOutcome(
|
||||||
|
value = CompilationResult.FAILED,
|
||||||
|
diagnostics = {
|
||||||
|
@Diagnostic(type = ErroneousMapper.class, kind = Kind.ERROR, line = 27),
|
||||||
|
@Diagnostic(type = ErroneousMapper.class, kind = Kind.ERROR, line = 30)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public void shouldFailToGenerateMappings() {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2013 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.erroneous.attributereference;
|
||||||
|
|
||||||
|
public class Source {
|
||||||
|
|
||||||
|
private int foo;
|
||||||
|
|
||||||
|
public int getFoo() {
|
||||||
|
return foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFoo(int foo) {
|
||||||
|
this.foo = foo;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2013 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.erroneous.attributereference;
|
||||||
|
|
||||||
|
public class Target {
|
||||||
|
|
||||||
|
private int foo;
|
||||||
|
|
||||||
|
public int getFoo() {
|
||||||
|
return foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFoo(int foo) {
|
||||||
|
this.foo = foo;
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.erroneous;
|
package org.mapstruct.ap.test.erroneous.typemismatch;
|
||||||
|
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.erroneous;
|
package org.mapstruct.ap.test.erroneous.typemismatch;
|
||||||
|
|
||||||
import javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.erroneous;
|
package org.mapstruct.ap.test.erroneous.typemismatch;
|
||||||
|
|
||||||
public class Source {
|
public class Source {
|
||||||
|
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.mapstruct.ap.test.erroneous;
|
package org.mapstruct.ap.test.erroneous.typemismatch;
|
||||||
|
|
||||||
public class Target {
|
public class Target {
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user