Browse Source

Polishing.

Split tests into parametrized tests.

Original Pull Request: #3378
pull/3386/head
Mark Paluch 2 months ago committed by Christoph Strobl
parent
commit
cd44725b2d
No known key found for this signature in database
GPG Key ID: E6054036D0C37A4B
  1. 18
      src/main/java/org/springframework/data/javapoet/TypeNames.java
  2. 46
      src/main/java/org/springframework/data/repository/aot/generate/AotRepositoryCreator.java
  3. 28
      src/test/java/example/BaseRepository.java
  4. 2
      src/test/java/example/UserRepository.java
  5. 62
      src/test/java/org/springframework/data/javapoet/TypeNamesUnitTests.java

18
src/main/java/org/springframework/data/javapoet/TypeNames.java

@ -84,24 +84,24 @@ public abstract class TypeNames { @@ -84,24 +84,24 @@ public abstract class TypeNames {
return TypeName.get(Object.class);
}
if (resolvableType.hasResolvableGenerics()) {
return ParameterizedTypeName.get(ClassName.get(resolvableType.toClass()),
Arrays.stream(resolvableType.getGenerics()).map(TypeNames::resolvedTypeName).toArray(TypeName[]::new));
}
if (!resolvableType.hasGenerics()) {
Class<?> resolvedType = resolvableType.toClass();
if (!resolvableType.isArray()) {
return TypeName.get(resolvedType);
}
if (resolvedType.isArray()) {
if (!resolvableType.isArray() || resolvedType.isArray()) {
return TypeName.get(resolvedType);
}
if (resolvableType.isArray()) {
return ArrayTypeName.of(resolvedType);
}
return TypeName.get(resolvedType);
}
if (resolvableType.hasResolvableGenerics()) {
return ParameterizedTypeName.get(ClassName.get(resolvableType.toClass()),
Arrays.stream(resolvableType.getGenerics()).map(TypeNames::resolvedTypeName).toArray(TypeName[]::new));
return TypeName.get(resolvedType);
}
return ClassName.get(resolvableType.toClass());

46
src/main/java/org/springframework/data/repository/aot/generate/AotRepositoryCreator.java

@ -290,6 +290,7 @@ class AotRepositoryCreator { @@ -290,6 +290,7 @@ class AotRepositoryCreator {
MethodContributor<? extends QueryMethod> contributor = contributorFactory.create(method);
if (contributor == null) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping method [%s.%s] contribution, no MethodContributor available"
.formatted(repositoryInformation.getRepositoryInterface().getName(), method.getName()));
@ -298,12 +299,11 @@ class AotRepositoryCreator { @@ -298,12 +299,11 @@ class AotRepositoryCreator {
return;
}
// TODO: should we do this even before we do something with the method to protect the modules?
if (ResolvableType.forMethodReturnType(method, repositoryInformation.getRepositoryInterface())
.hasUnresolvableGenerics()) {
if (hasUnresolvableGenerics(method)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping method [%s.%s] contribution, unresolvable generic return"
logger.trace(
"Skipping implementation method [%s.%s] contribution. Method uses generics that currently cannot be resolved."
.formatted(repositoryInformation.getRepositoryInterface().getName(), method.getName()));
}
@ -311,11 +311,43 @@ class AotRepositoryCreator { @@ -311,11 +311,43 @@ class AotRepositoryCreator {
return;
}
if (contributor.contributesMethodSpec() && !repositoryInformation.isReactiveRepository()) {
generationMetadata.addRepositoryMethod(method, contributor);
} else {
if (!contributor.contributesMethodSpec() || repositoryInformation.isReactiveRepository()) {
if (repositoryInformation.isReactiveRepository() && logger.isTraceEnabled()) {
logger.trace(
"Skipping implementation method [%s.%s] contribution. AOT repositories are not supported for reactive repositories."
.formatted(repositoryInformation.getRepositoryInterface().getName(), method.getName()));
}
if (!contributor.contributesMethodSpec() && logger.isTraceEnabled()) {
logger.trace(
"Skipping implementation method [%s.%s] contribution. Spring Data %s did not provide a method implementation."
.formatted(repositoryInformation.getRepositoryInterface().getName(), method.getName(), moduleName));
}
generationMetadata.addDelegateMethod(method, contributor);
return;
}
generationMetadata.addRepositoryMethod(method, contributor);
}
private boolean hasUnresolvableGenerics(Method method) {
if (ResolvableType.forMethodReturnType(method, repositoryInformation.getRepositoryInterface())
.hasUnresolvableGenerics()) {
return true;
}
for (int i = 0; i < method.getParameterCount(); i++) {
if (ResolvableType.forMethodParameter(method, i, repositoryInformation.getRepositoryInterface())
.hasUnresolvableGenerics()) {
return true;
}
}
return false;
}
/**

28
src/test/java/example/BaseRepository.java

@ -1,28 +0,0 @@ @@ -1,28 +0,0 @@
/*
* Copyright 2025-present the original author or authors.
*
* 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 example;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
/**
* @author Christoph Strobl
*/
@NoRepositoryBean
public interface BaseRepository<T, ID> extends CrudRepository<T, ID> {
T findInBaseRepository(ID id);
}

2
src/test/java/example/UserRepository.java

@ -24,7 +24,7 @@ import org.springframework.data.repository.CrudRepository; @@ -24,7 +24,7 @@ import org.springframework.data.repository.CrudRepository;
/**
* @author Christoph Strobl
*/
public interface UserRepository extends BaseRepository<User, Long>, UserRepositoryExtension {
public interface UserRepository extends CrudRepository<User, Long>, UserRepositoryExtension {
User findByFirstname(String firstname);

62
src/test/java/org/springframework/data/javapoet/TypeNamesUnitTests.java

@ -15,8 +15,10 @@ @@ -15,8 +15,10 @@
*/
package org.springframework.data.javapoet;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import static org.assertj.core.api.AssertionsForInterfaceTypes.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
@ -25,6 +27,7 @@ import org.junit.jupiter.api.Test; @@ -25,6 +27,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.data.geo.Distance;
@ -37,7 +40,10 @@ import org.springframework.javapoet.TypeVariableName; @@ -37,7 +40,10 @@ import org.springframework.javapoet.TypeVariableName;
import org.springframework.util.ReflectionUtils;
/**
* Tests for {@link TypeNames}.
*
* @author Christoph Strobl
* @author Mark Paluch
*/
class TypeNamesUnitTests {
@ -75,13 +81,37 @@ class TypeNamesUnitTests { @@ -75,13 +81,37 @@ class TypeNamesUnitTests {
assertThat(TypeNames.resolvedTypeName(resolvableType)).extracting(TypeName::toString).isEqualTo("java.util.List");
}
@Test // GH-3374
void resolvedTypeNamesForMethodParameters() {
static List<Method> concreteMethods() {
List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(Concrete.class, method -> {
if (!method.getName().contains("baseMethod")) {
return;
}
methods.add(method);
});
return methods;
}
static List<Method> otherMethods() {
List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(Concrete.class, method -> {
if (!method.getName().contains("otherMethod")) {
return;
}
methods.add(method);
});
return methods;
}
@ParameterizedTest // GH-3374
@MethodSource("concreteMethods")
void resolvedTypeNamesForMethodParameters(Method method) {
MethodParameter refiedObjectMethodParameter = new MethodParameter(method, 0).withContainingClass(Concrete.class);
ResolvableType resolvedObjectParameterType = ResolvableType.forMethodParameter(refiedObjectMethodParameter);
@ -90,8 +120,7 @@ class TypeNamesUnitTests { @@ -90,8 +120,7 @@ class TypeNamesUnitTests {
MethodParameter refiedCollectionMethodParameter = new MethodParameter(method, 1)
.withContainingClass(Concrete.class);
ResolvableType resolvedCollectionParameterType = ResolvableType
.forMethodParameter(refiedCollectionMethodParameter);
ResolvableType resolvedCollectionParameterType = ResolvableType.forMethodParameter(refiedCollectionMethodParameter);
assertThat(TypeNames.typeName(resolvedCollectionParameterType))
.isEqualTo(ParameterizedTypeName.get(ClassName.get(java.util.List.class), TypeVariableName.get("T")));
assertThat(TypeNames.resolvedTypeName(resolvedCollectionParameterType))
@ -108,13 +137,13 @@ class TypeNamesUnitTests { @@ -108,13 +137,13 @@ class TypeNamesUnitTests {
.isEqualTo(ParameterizedTypeName.get(ClassName.get(java.util.List.class), TypeVariableName.get("T")));
assertThat(TypeNames.resolvedTypeName(resolvedReturnType))
.isEqualTo(ParameterizedTypeName.get(java.util.List.class, MyType.class));
});
ReflectionUtils.doWithMethods(Concrete.class, method -> {
if (!method.getName().contains("otherMethod")) {
return;
}
@ParameterizedTest // GH-3374
@MethodSource("otherMethods")
void resolvedTypeNamesForOtherMethodParameters(Method method) {
MethodParameter refiedObjectMethodParameter = new MethodParameter(method, 0).withContainingClass(Concrete.class);
ResolvableType resolvedObjectParameterType = ResolvableType.forMethodParameter(refiedObjectMethodParameter);
assertThat(TypeNames.typeName(resolvedObjectParameterType)).isEqualTo(TypeVariableName.get("RT"));
@ -122,8 +151,7 @@ class TypeNamesUnitTests { @@ -122,8 +151,7 @@ class TypeNamesUnitTests {
MethodParameter refiedCollectionMethodParameter = new MethodParameter(method, 1)
.withContainingClass(Concrete.class);
ResolvableType resolvedCollectionParameterType = ResolvableType
.forMethodParameter(refiedCollectionMethodParameter);
ResolvableType resolvedCollectionParameterType = ResolvableType.forMethodParameter(refiedCollectionMethodParameter);
assertThat(TypeNames.typeName(resolvedCollectionParameterType))
.isEqualTo(ParameterizedTypeName.get(ClassName.get(java.util.List.class), TypeVariableName.get("RT")));
assertThat(TypeNames.resolvedTypeName(resolvedCollectionParameterType))
@ -138,21 +166,19 @@ class TypeNamesUnitTests { @@ -138,21 +166,19 @@ class TypeNamesUnitTests {
ResolvableType resolvedReturnType = ResolvableType.forMethodReturnType(method, Concrete.class);
assertThat(TypeNames.typeName(resolvedReturnType)).extracting(TypeName::toString).isEqualTo("RT");
assertThat(TypeNames.resolvedTypeName(resolvedReturnType)).isEqualTo(TypeName.get(Object.class));
});
ReflectionUtils.doWithMethods(Concrete.class, method -> {
if (!method.getName().contains("findByLocationNear")) {
return;
}
@Test // GH-3374
void resolvesTypeNamesForMethodParameters() throws NoSuchMethodException {
Method method = Concrete.class.getDeclaredMethod("findByLocationNear", Point.class, Distance.class);
ResolvableType resolvedReturnType = ResolvableType.forMethodReturnType(method, Concrete.class);
assertThat(TypeNames.typeName(resolvedReturnType)).extracting(TypeName::toString).isEqualTo(
"java.util.List<org.springframework.data.geo.GeoResult<org.springframework.data.javapoet.TypeNamesUnitTests.MyType>>");
assertThat(TypeNames.resolvedTypeName(resolvedReturnType)).isEqualTo(ParameterizedTypeName
.get(ClassName.get(java.util.List.class), ParameterizedTypeName.get(GeoResult.class, MyType.class)));
});
}
interface GenericBase<T> {

Loading…
Cancel
Save