mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#2437 Do not visit the same type element twice when retrieving methods
When using the diamond inheritance a TypeElement might be visited twice. This is however, incorrect. We need to visit a TypeElement exactly once.
This commit is contained in:
parent
a6ac4f3fd6
commit
70ea65f7aa
@ -7,6 +7,8 @@ package org.mapstruct.ap.internal.util;
|
|||||||
|
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -118,7 +120,7 @@ public abstract class AbstractElementUtilsDecorator implements ElementUtils {
|
|||||||
public List<ExecutableElement> getAllEnclosedExecutableElements(TypeElement element) {
|
public List<ExecutableElement> getAllEnclosedExecutableElements(TypeElement element) {
|
||||||
List<ExecutableElement> enclosedElements = new ArrayList<>();
|
List<ExecutableElement> enclosedElements = new ArrayList<>();
|
||||||
element = replaceTypeElementIfNecessary( element );
|
element = replaceTypeElementIfNecessary( element );
|
||||||
addEnclosedMethodsInHierarchy( enclosedElements, element, element );
|
addEnclosedMethodsInHierarchy( enclosedElements, new HashSet<>(), element, element );
|
||||||
|
|
||||||
return enclosedElements;
|
return enclosedElements;
|
||||||
}
|
}
|
||||||
@ -132,7 +134,9 @@ public abstract class AbstractElementUtilsDecorator implements ElementUtils {
|
|||||||
return enclosedElements;
|
return enclosedElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addEnclosedMethodsInHierarchy(List<ExecutableElement> alreadyAdded, TypeElement element,
|
private void addEnclosedMethodsInHierarchy(List<ExecutableElement> alreadyAdded,
|
||||||
|
Collection<String> alreadyVisitedElements,
|
||||||
|
TypeElement element,
|
||||||
TypeElement parentType) {
|
TypeElement parentType) {
|
||||||
if ( element != parentType ) { // otherwise the element was already checked for replacement
|
if ( element != parentType ) { // otherwise the element was already checked for replacement
|
||||||
element = replaceTypeElementIfNecessary( element );
|
element = replaceTypeElementIfNecessary( element );
|
||||||
@ -142,11 +146,17 @@ public abstract class AbstractElementUtilsDecorator implements ElementUtils {
|
|||||||
throw new TypeHierarchyErroneousException( element );
|
throw new TypeHierarchyErroneousException( element );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !alreadyVisitedElements.add( element.getQualifiedName().toString() ) ) {
|
||||||
|
// If we already visited the element we should not go into it again.
|
||||||
|
// This can happen when diamond inheritance is used with interfaces
|
||||||
|
return;
|
||||||
|
}
|
||||||
addMethodNotYetOverridden( alreadyAdded, methodsIn( element.getEnclosedElements() ), parentType );
|
addMethodNotYetOverridden( alreadyAdded, methodsIn( element.getEnclosedElements() ), parentType );
|
||||||
|
|
||||||
if ( hasNonObjectSuperclass( element ) ) {
|
if ( hasNonObjectSuperclass( element ) ) {
|
||||||
addEnclosedMethodsInHierarchy(
|
addEnclosedMethodsInHierarchy(
|
||||||
alreadyAdded,
|
alreadyAdded,
|
||||||
|
alreadyVisitedElements,
|
||||||
asTypeElement( element.getSuperclass() ),
|
asTypeElement( element.getSuperclass() ),
|
||||||
parentType
|
parentType
|
||||||
);
|
);
|
||||||
@ -155,6 +165,7 @@ public abstract class AbstractElementUtilsDecorator implements ElementUtils {
|
|||||||
for ( TypeMirror interfaceType : element.getInterfaces() ) {
|
for ( TypeMirror interfaceType : element.getInterfaces() ) {
|
||||||
addEnclosedMethodsInHierarchy(
|
addEnclosedMethodsInHierarchy(
|
||||||
alreadyAdded,
|
alreadyAdded,
|
||||||
|
alreadyVisitedElements,
|
||||||
asTypeElement( interfaceType ),
|
asTypeElement( interfaceType ),
|
||||||
parentType
|
parentType
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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._2437;
|
||||||
|
|
||||||
|
import org.mapstruct.ap.testutil.IssueKey;
|
||||||
|
import org.mapstruct.ap.testutil.ProcessorTest;
|
||||||
|
import org.mapstruct.ap.testutil.WithClasses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@IssueKey("2437")
|
||||||
|
@WithClasses({
|
||||||
|
Phone.class,
|
||||||
|
PhoneDto.class,
|
||||||
|
PhoneMapper.class,
|
||||||
|
PhoneParent1Mapper.class,
|
||||||
|
PhoneParent2Mapper.class,
|
||||||
|
PhoneSuperMapper.class,
|
||||||
|
})
|
||||||
|
class Issue2437Test {
|
||||||
|
|
||||||
|
@ProcessorTest
|
||||||
|
void shouldGenerateValidCode() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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._2437;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public class Phone {
|
||||||
|
|
||||||
|
private final String number;
|
||||||
|
|
||||||
|
public Phone(String number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNumber() {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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._2437;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public class PhoneDto {
|
||||||
|
|
||||||
|
private final String number;
|
||||||
|
|
||||||
|
public PhoneDto(String number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNumber() {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* 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._2437;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface PhoneMapper extends PhoneParent1Mapper, PhoneParent2Mapper {
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* 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._2437;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public interface PhoneParent1Mapper extends PhoneSuperMapper {
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* 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._2437;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public interface PhoneParent2Mapper extends PhoneSuperMapper {
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* 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._2437;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Filip Hrisafov
|
||||||
|
*/
|
||||||
|
public interface PhoneSuperMapper {
|
||||||
|
|
||||||
|
Phone map(PhoneDto dto);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user