Skip to content

Commit 82f90d5

Browse files
committed
add type parameter dependencies to self
I decided to make `JavaTypeParameters.getDependenciesFromSelf()` and `JavaTypeVariable.getDependenciesFromSelf()` public API as it might be useful in general and we need it now to register the dependencies to self within the import context. The alternative would have been some workaround to keep the visibility package private, but I didn't consider it worth the effort, since it makes a nice addition to the public API. Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
1 parent 7e7819d commit 82f90d5

File tree

8 files changed

+68
-4
lines changed

8 files changed

+68
-4
lines changed

archunit-integration-test/src/test/java/com/tngtech/archunit/integration/ExamplesIntegrationTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -857,8 +857,10 @@ Stream<DynamicTest> LayeredArchitectureTest() {
857857
.inLine(27)
858858
.asDependency())
859859

860-
.by(method(ServiceViolatingLayerRules.class, dependentMethod).withParameter(UseCaseTwoController.class))
860+
.by(typeParameter(ServiceHelper.class, "TYPE_PARAMETER_VIOLATING_LAYER_RULE").dependingOn(SomeUtility.class))
861+
.by(typeParameter(ServiceHelper.class, "ANOTHER_TYPE_PARAMETER_VIOLATING_LAYER_RULE").dependingOn(SomeEnum.class))
861862

863+
.by(method(ServiceViolatingLayerRules.class, dependentMethod).withParameter(UseCaseTwoController.class))
862864
.by(method(ServiceViolatingLayerRules.class, dependentMethod).withReturnType(SomeGuiController.class))
863865

864866
.by(annotatedClass(ServiceViolatingLayerRules.class).withAnnotationParameterType(ComplexControllerAnnotation.class))

archunit/src/main/java/com/tngtech/archunit/core/domain/ImportContext.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ public interface ImportContext {
6767

6868
Set<InstanceofCheck> getInstanceofChecksOfType(JavaClass javaClass);
6969

70+
Set<Dependency> getTypeParameterDependenciesWithTargetClass(JavaClass javaClass);
71+
7072
JavaClass resolveClass(String fullyQualifiedClassName);
7173

7274
Optional<JavaClass> getMethodReturnType(String declaringClassName, String methodName);

archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassDependencies.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class JavaClassDependencies {
3939
private final Set<JavaAnnotation<?>> annotationsWithTypeOfClass;
4040
private final Set<JavaAnnotation<?>> annotationsWithParameterTypeOfClass;
4141
private final Set<InstanceofCheck> instanceofChecksWithTypeOfClass;
42+
private final Set<Dependency> typeParameterDependenciesWithTargetClass;
4243
private final Supplier<Set<Dependency>> directDependenciesFromClass;
4344
private final Supplier<Set<Dependency>> directDependenciesToClass;
4445

@@ -53,6 +54,7 @@ class JavaClassDependencies {
5354
this.annotationsWithTypeOfClass = context.getAnnotationsOfType(javaClass);
5455
this.annotationsWithParameterTypeOfClass = context.getAnnotationsWithParameterOfType(javaClass);
5556
this.instanceofChecksWithTypeOfClass = context.getInstanceofChecksOfType(javaClass);
57+
this.typeParameterDependenciesWithTargetClass = context.getTypeParameterDependenciesWithTargetClass(javaClass);
5658
this.directDependenciesFromClass = getDirectDependenciesFromClassSupplier();
5759
this.directDependenciesToClass = getDirectDependenciesToClassSupplier();
5860
}
@@ -91,6 +93,7 @@ public Set<Dependency> get() {
9193
result.addAll(constructorParameterDependenciesToSelf());
9294
result.addAll(annotationDependenciesToSelf());
9395
result.addAll(instanceofCheckDependenciesToSelf());
96+
result.addAll(typeParameterDependenciesWithTargetClass);
9497
return result.build();
9598
}
9699
});

archunit/src/main/java/com/tngtech/archunit/core/domain/JavaTypeParameters.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ protected List<JavaTypeVariable<OWNER>> delegate() {
4343
return typeParameters;
4444
}
4545

46-
Set<Dependency> getDependenciesFromSelf() {
46+
@PublicAPI(usage = ACCESS)
47+
public Set<Dependency> getDependenciesFromSelf() {
4748
ImmutableSet.Builder<Dependency> result = ImmutableSet.builder();
4849
for (JavaTypeVariable<?> typeVariable : typeParameters) {
4950
result.addAll(typeVariable.getDependenciesFromSelf());

archunit/src/main/java/com/tngtech/archunit/core/domain/JavaTypeVariable.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ public JavaClass toErasure() {
157157
return erasure;
158158
}
159159

160-
Set<Dependency> getDependenciesFromSelf() {
160+
@PublicAPI(usage = ACCESS)
161+
public Set<Dependency> getDependenciesFromSelf() {
161162
return dependencies;
162163
}
163164

archunit/src/main/java/com/tngtech/archunit/core/importer/ClassGraphCreator.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.tngtech.archunit.core.domain.AccessTarget;
3131
import com.tngtech.archunit.core.domain.AccessTarget.ConstructorCallTarget;
3232
import com.tngtech.archunit.core.domain.AccessTarget.MethodCallTarget;
33+
import com.tngtech.archunit.core.domain.Dependency;
3334
import com.tngtech.archunit.core.domain.DomainObjectCreationContext;
3435
import com.tngtech.archunit.core.domain.ImportContext;
3536
import com.tngtech.archunit.core.domain.InstanceofCheck;
@@ -264,6 +265,11 @@ public Set<InstanceofCheck> getInstanceofChecksOfType(JavaClass javaClass) {
264265
return memberDependenciesByTarget.getInstanceofChecksOfType(javaClass);
265266
}
266267

268+
@Override
269+
public Set<Dependency> getTypeParameterDependenciesWithTargetClass(JavaClass javaClass) {
270+
return memberDependenciesByTarget.getTypeParameterDependenciesWithTargetClass(javaClass);
271+
}
272+
267273
private <T extends AccessTarget, B extends DomainBuilders.JavaAccessBuilder<T, B>>
268274
B accessBuilderFrom(B builder, AccessRecord<T> record) {
269275
return builder
@@ -293,7 +299,9 @@ public Set<JavaClass> createInterfaces(JavaClass owner) {
293299
public JavaTypeParameters<JavaClass> createTypeParameters(JavaClass owner) {
294300
TypeParametersBuilder typeParametersBuilder = importRecord.getTypeParameterBuildersFor(owner.getName());
295301
List<JavaTypeVariable<JavaClass>> typeParameters = typeParametersBuilder.build(owner, classes.byTypeName());
296-
return DomainObjectCreationContext.createTypeParameters(typeParameters);
302+
JavaTypeParameters<JavaClass> result = DomainObjectCreationContext.createTypeParameters(typeParameters);
303+
memberDependenciesByTarget.registerTypeParameters(result);
304+
return result;
297305
}
298306

299307
@Override
@@ -389,6 +397,7 @@ private static class MemberDependenciesByTarget {
389397
private final SetMultimap<JavaClass, JavaAnnotation<?>> annotationTypeDependencies = HashMultimap.create();
390398
private final SetMultimap<JavaClass, JavaAnnotation<?>> annotationParameterTypeDependencies = HashMultimap.create();
391399
private final SetMultimap<JavaClass, InstanceofCheck> instanceofCheckDependencies = HashMultimap.create();
400+
private final SetMultimap<JavaClass, Dependency> typeParameterDependencies = HashMultimap.create();
392401

393402
void registerFields(Set<JavaField> fields) {
394403
for (JavaField field : fields) {
@@ -454,6 +463,14 @@ void registerStaticInitializer(JavaStaticInitializer staticInitializer) {
454463
}
455464
}
456465

466+
void registerTypeParameters(JavaTypeParameters<JavaClass> typeParameters) {
467+
for (JavaTypeVariable<JavaClass> typeParameter : typeParameters) {
468+
for (Dependency dependency : typeParameter.getDependenciesFromSelf()) {
469+
typeParameterDependencies.put(dependency.getTargetClass(), dependency);
470+
}
471+
}
472+
}
473+
457474
Set<JavaField> getFieldsOfType(JavaClass javaClass) {
458475
return fieldTypeDependencies.get(javaClass);
459476
}
@@ -489,5 +506,9 @@ Set<JavaAnnotation<?>> getAnnotationsWithParameterOfType(JavaClass javaClass) {
489506
Set<InstanceofCheck> getInstanceofChecksOfType(JavaClass javaClass) {
490507
return instanceofCheckDependencies.get(javaClass);
491508
}
509+
510+
Set<Dependency> getTypeParameterDependenciesWithTargetClass(JavaClass javaClass) {
511+
return typeParameterDependencies.get(javaClass);
512+
}
492513
}
493514
}

archunit/src/test/java/com/tngtech/archunit/core/domain/JavaClassTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,34 @@ public void direct_dependencies_to_self_by_annotation() {
700700
.inLineNumber(0));
701701
}
702702

703+
@Test
704+
public void direct_dependencies_to_self_by_type_parameter() {
705+
class ClassOtherTypeSignaturesDependOn {
706+
}
707+
@SuppressWarnings("unused")
708+
class FirstDependingOnOtherThroughTypeParameter<T extends ClassOtherTypeSignaturesDependOn> {
709+
}
710+
@SuppressWarnings("unused")
711+
class SecondDependingOnOtherThroughTypeParameter<
712+
U extends Map<?, List<? super Set<? extends ClassOtherTypeSignaturesDependOn>>>,
713+
V extends Map<ClassOtherTypeSignaturesDependOn, ClassOtherTypeSignaturesDependOn>> {
714+
}
715+
716+
JavaClass someClass = importClasses(ClassOtherTypeSignaturesDependOn.class, FirstDependingOnOtherThroughTypeParameter.class, SecondDependingOnOtherThroughTypeParameter.class)
717+
.get(ClassOtherTypeSignaturesDependOn.class);
718+
719+
assertThatDependencies(someClass.getDirectDependenciesToSelf())
720+
.contain(from(FirstDependingOnOtherThroughTypeParameter.class).to(ClassOtherTypeSignaturesDependOn.class).inLocation(getClass(), 0)
721+
.withDescriptionContaining("type parameter 'T' depending on")
722+
723+
.from(SecondDependingOnOtherThroughTypeParameter.class).to(ClassOtherTypeSignaturesDependOn.class).inLocation(getClass(), 0)
724+
.withDescriptionContaining("type parameter 'U' depending on")
725+
726+
.from(SecondDependingOnOtherThroughTypeParameter.class).to(ClassOtherTypeSignaturesDependOn.class).inLocation(getClass(), 0)
727+
.withDescriptionContaining("type parameter 'V' depending on")
728+
);
729+
}
730+
703731
@Test
704732
public void direct_dependencies_to_self_finds_correct_set_of_origin_types() {
705733
JavaClasses classes = importPackagesOf(getClass());

archunit/src/test/java/com/tngtech/archunit/core/importer/ImportTestUtils.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.tngtech.archunit.base.Optional;
2323
import com.tngtech.archunit.core.domain.AccessTarget;
2424
import com.tngtech.archunit.core.domain.AccessTarget.MethodCallTarget;
25+
import com.tngtech.archunit.core.domain.Dependency;
2526
import com.tngtech.archunit.core.domain.DomainObjectCreationContext;
2627
import com.tngtech.archunit.core.domain.ImportContext;
2728
import com.tngtech.archunit.core.domain.InstanceofCheck;
@@ -444,6 +445,11 @@ public Set<InstanceofCheck> getInstanceofChecksOfType(JavaClass javaClass) {
444445
return Collections.emptySet();
445446
}
446447

448+
@Override
449+
public Set<Dependency> getTypeParameterDependenciesWithTargetClass(JavaClass javaClass) {
450+
return Collections.emptySet();
451+
}
452+
447453
@Override
448454
public JavaClass resolveClass(String fullyQualifiedClassName) {
449455
throw new UnsupportedOperationException("Override me where necessary");

0 commit comments

Comments
 (0)