Use enclosing class constructor parameter only for non-static inner classes.

Closes #3038
Original pull request: #3039
This commit is contained in:
Christoph Strobl
2024-02-07 12:32:43 +01:00
committed by Mark Paluch
parent 25f87d251a
commit d333dc612b
2 changed files with 88 additions and 1 deletions

View File

@@ -24,6 +24,7 @@ import org.springframework.data.util.Lazy;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
@@ -31,6 +32,7 @@ import org.springframework.util.StringUtils;
*
* @param <T> the type of the parameter
* @author Oliver Gierke
* @author Christoph Strobl
*/
public class Parameter<T, P extends PersistentProperty<P>> {
@@ -72,7 +74,7 @@ public class Parameter<T, P extends PersistentProperty<P>> {
}
Class<T> owningType = entity.getType();
return owningType.isMemberClass() && type.getType().equals(owningType.getEnclosingClass());
return ClassUtils.isInnerClass(owningType) && type.getType().equals(owningType.getEnclosingClass());
});
this.hasSpelExpression = Lazy.of(() -> StringUtils.hasText(getSpelExpression()));

View File

@@ -16,19 +16,27 @@
package org.springframework.data.mapping;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.lang.annotation.Annotation;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.mapping.ParameterUnitTests.IFace.ClassMember;
import org.springframework.data.mapping.ParameterUnitTests.IFace.RecordMember;
import org.springframework.data.mapping.ParameterUnitTests.StaticType.NonStaticInner;
import org.springframework.data.mapping.ParameterUnitTests.StaticType.RecordInner;
import org.springframework.data.mapping.ParameterUnitTests.StaticType.StaticInner;
import org.springframework.data.util.TypeInformation;
/**
* Unit tests for {@link Parameter}.
*
* @author Oliver Gierke
* @author Christoph Strobl
*/
@ExtendWith(MockitoExtension.class)
class ParameterUnitTests<P extends PersistentProperty<P>> {
@@ -87,4 +95,81 @@ class ParameterUnitTests<P extends PersistentProperty<P>> {
assertThat(left).isNotEqualTo(right);
}
@Test // GH-3038
void shouldNotConsiderRecordTypeOfInterfaceEnclosingClassParameter() {
PersistentEntity pe = Mockito.mock(PersistentEntity.class);
when(pe.getType()).thenReturn(RecordMember.class);
Parameter<IFace, P> iFace = new Parameter<IFace, P>("iFace", TypeInformation.of(IFace.class), annotations, pe);
assertThat(iFace.isEnclosingClassParameter()).isFalse();
}
@Test // GH-3038
void shouldNotConsiderMemberTypeOfInterfaceEnclosingClassParameter() {
PersistentEntity pe = Mockito.mock(PersistentEntity.class);
when(pe.getType()).thenReturn(ClassMember.class);
Parameter<IFace, P> iFace = new Parameter<IFace, P>("iFace", TypeInformation.of(IFace.class), annotations, pe);
assertThat(iFace.isEnclosingClassParameter()).isFalse();
}
@Test // GH-3038
void shouldConsiderMemberTypeOfClassEnclosingClassParameter() {
PersistentEntity pe = Mockito.mock(PersistentEntity.class);
when(pe.getType()).thenReturn(NonStaticInner.class);
Parameter<StaticType, P> iFace = new Parameter<StaticType, P>("outer", TypeInformation.of(StaticType.class),
annotations, pe);
assertThat(iFace.isEnclosingClassParameter()).isTrue();
}
@Test // GH-3038
void shouldNotConsiderStaticMemberTypeOfClassEnclosingClassParameter() {
PersistentEntity pe = Mockito.mock(PersistentEntity.class);
when(pe.getType()).thenReturn(StaticInner.class);
Parameter<StaticType, P> iFace = new Parameter<StaticType, P>("outer", TypeInformation.of(StaticType.class),
annotations, pe);
assertThat(iFace.isEnclosingClassParameter()).isFalse();
}
@Test // GH-3038
void shouldNotConsiderRecordMemberTypeOfClassEnclosingClassParameter() {
PersistentEntity pe = Mockito.mock(PersistentEntity.class);
when(pe.getType()).thenReturn(RecordInner.class);
Parameter<StaticType, P> iFace = new Parameter<StaticType, P>("outer", TypeInformation.of(StaticType.class),
annotations, pe);
assertThat(iFace.isEnclosingClassParameter()).isFalse();
}
interface IFace {
record RecordMember(IFace iFace) {
}
class ClassMember {
ClassMember(IFace iface) {}
}
}
static class StaticType {
class NonStaticInner {
NonStaticInner(StaticType outer) {}
}
static class StaticInner {
StaticInner(StaticType outer) {}
}
record RecordInner(StaticType outer) {
}
}
}