GH-598 - Invalid dependency into named interface now gets reported properly.
This commit is contained in:
@@ -579,6 +579,10 @@ public class ApplicationModule {
|
||||
.collect(Classes.toClasses());
|
||||
}
|
||||
|
||||
private String getQualifiedName(NamedInterface namedInterface) {
|
||||
return namedInterface.getQualifiedName(getName());
|
||||
}
|
||||
|
||||
private static Classes filterSpringBeans(JavaPackage source) {
|
||||
|
||||
Map<Boolean, List<JavaClass>> collect = source.that(isConfiguration()).stream() //
|
||||
@@ -971,8 +975,20 @@ public class ApplicationModule {
|
||||
// Check explicitly defined allowed targets
|
||||
if (!declaredDependencies.isAllowedDependency(target)) {
|
||||
|
||||
var message = "Module '%s' depends on module '%s' via %s -> %s. Allowed targets: %s." //
|
||||
.formatted(originModule.getName(), targetModule.getName(), source.getName(), target.getName(),
|
||||
var targetNamedInterfaces = targetModule.getNamedInterfaces()
|
||||
.getNamedInterfacesContaining(target)
|
||||
.filter(NamedInterface::isNamed)
|
||||
.toList();
|
||||
|
||||
var targetString = targetNamedInterfaces.isEmpty()
|
||||
? "module '%s'".formatted(targetModule.getName())
|
||||
: "named interface(s) '%s'".formatted(
|
||||
targetNamedInterfaces.stream()
|
||||
.map(targetModule::getQualifiedName)
|
||||
.collect(Collectors.joining(", ")));
|
||||
|
||||
var message = "Module '%s' depends on %s via %s -> %s. Allowed targets: %s." //
|
||||
.formatted(originModule.getName(), targetString, source.getName(), target.getName(),
|
||||
declaredDependencies.toString());
|
||||
|
||||
return violations.and(new Violation(message));
|
||||
|
||||
@@ -125,6 +125,10 @@ public class NamedInterface implements Iterable<JavaClass> {
|
||||
return name;
|
||||
}
|
||||
|
||||
String getQualifiedName(String qualifier) {
|
||||
return qualifier + " :: " + name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this is the unnamed (implicit) {@link NamedInterface}.
|
||||
*/
|
||||
@@ -132,6 +136,13 @@ public class NamedInterface implements Iterable<JavaClass> {
|
||||
return name.equals(UNNAMED_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this {@link NamedInterface} has an explicit name.
|
||||
*/
|
||||
public boolean isNamed() {
|
||||
return !isUnnamed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the {@link NamedInterface} contains the given {@link JavaClass}.
|
||||
*
|
||||
|
||||
@@ -138,6 +138,20 @@ public class NamedInterfaces implements Iterable<NamedInterface> {
|
||||
.orElseThrow(() -> new IllegalStateException("No unnamed interface found!"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all named interfaces that contain the given type.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public Stream<NamedInterface> getNamedInterfacesContaining(JavaClass type) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
|
||||
return namedInterfaces.stream()
|
||||
.filter(it -> it.contains(type));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Iterable#iterator()
|
||||
@@ -183,6 +197,12 @@ public class NamedInterfaces implements Iterable<NamedInterface> {
|
||||
return new NamedInterfaces(namedInterfaces);
|
||||
}
|
||||
|
||||
Stream<NamedInterface> getNamedInterfacesContaining(Class<?> type) {
|
||||
|
||||
return namedInterfaces.stream()
|
||||
.filter(it -> it.contains(type));
|
||||
}
|
||||
|
||||
private static NamedInterfaces of(NamedInterface interfaces) {
|
||||
return new NamedInterfaces(List.of(interfaces));
|
||||
}
|
||||
|
||||
@@ -64,6 +64,17 @@ class NamedInterfacesUnitTests {
|
||||
.withMessageContaining(InvalidDefaultNamedInterface.class.getSimpleName());
|
||||
}
|
||||
|
||||
@Test // GH-595
|
||||
void detectsNamedInterfacesATypeIsContainedIn() {
|
||||
|
||||
var javaPackage = TestUtils.getPackage(RootType.class);
|
||||
var interfaces = NamedInterfaces.discoverNamedInterfaces(javaPackage);
|
||||
|
||||
assertThat(interfaces.getNamedInterfacesContaining(AdditionalSpiType.class))
|
||||
.extracting(NamedInterface::getName)
|
||||
.containsExactlyInAnyOrder("spi", "kpi");
|
||||
}
|
||||
|
||||
private static void assertInterfaceContains(NamedInterfaces interfaces, String name, Class<?>... types) {
|
||||
|
||||
var classNames = Arrays.stream(types).map(Class::getName).toArray(String[]::new);
|
||||
|
||||
Reference in New Issue
Block a user