Skip to content

Commit

Permalink
move all reverse dependency registering into ReverseDependencies
Browse files Browse the repository at this point in the history
This will make it easier to understand how reverse dependencies work, because now there is one uniform place, in the very end, where we register all reverse dependencies of a class. I have thought about encapsulating `ReverseDependencies` into `JavaClassDependencies` to have an API similar to earlier, but since `JavaMember` meanwhile also uses `ReverseDependencies` directly, I refrained from it. I think it is still acceptable to have these two objects and another level of indirection (`JavaClassDependencies` delegating to `ReverseDependencies`) will certainly not make dependency resolution any faster either.
In any case the `ImportContext` is now simpler and I measured performance and could not detect any significant degradation (even though we now have additional loops to register the reverse dependencies that we did not have before).

Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
  • Loading branch information
codecholeric committed Dec 15, 2020
1 parent 61037e2 commit 90daf52
Show file tree
Hide file tree
Showing 13 changed files with 315 additions and 418 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,6 @@ public interface ImportContext {

Set<JavaConstructorCall> createConstructorCallsFor(JavaCodeUnit codeUnit);

Set<JavaField> getFieldsOfType(JavaClass javaClass);

Set<JavaMethod> getMethodsWithParameterOfType(JavaClass javaClass);

Set<JavaMethod> getMethodsWithReturnType(JavaClass javaClass);

Set<ThrowsDeclaration<JavaMethod>> getMethodThrowsDeclarationsOfType(JavaClass javaClass);

Set<JavaConstructor> getConstructorsWithParameterOfType(JavaClass javaClass);

Set<ThrowsDeclaration<JavaConstructor>> getConstructorThrowsDeclarationsOfType(JavaClass javaClass);

Set<JavaAnnotation<?>> getAnnotationsOfType(JavaClass javaClass);

Set<JavaAnnotation<?>> getAnnotationsWithParameterOfType(JavaClass javaClass);

Set<InstanceofCheck> getInstanceofChecksOfType(JavaClass javaClass);

JavaClass resolveClass(String fullyQualifiedClassName);

Optional<JavaClass> getMethodReturnType(String declaringClassName, String methodName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ public Set<JavaMember> get() {
}
});
private JavaClassDependencies javaClassDependencies;
private ReverseDependencies reverseDependencies;

JavaClass(JavaClassBuilder builder) {
source = checkNotNull(builder.getSource());
Expand Down Expand Up @@ -1037,7 +1038,7 @@ public Set<Dependency> getDirectDependenciesFromSelf() {
*/
@PublicAPI(usage = ACCESS)
public Set<Dependency> getDirectDependenciesToSelf() {
return javaClassDependencies.getDirectDependenciesToClass();
return reverseDependencies.getDirectDependenciesTo(this);
}

@PublicAPI(usage = ACCESS)
Expand Down Expand Up @@ -1081,55 +1082,71 @@ public Set<JavaAccess<?>> getAccessesToSelf() {
*/
@PublicAPI(usage = ACCESS)
public Set<JavaField> getFieldsWithTypeOfSelf() {
return javaClassDependencies.getFieldsWithTypeOfClass();
return reverseDependencies.getFieldsWithTypeOf(this);
}

/**
* @return Methods of all imported classes that have a parameter type of this class.
*/
@PublicAPI(usage = ACCESS)
public Set<JavaMethod> getMethodsWithParameterTypeOfSelf() {
return javaClassDependencies.getMethodsWithParameterTypeOfClass();
return reverseDependencies.getMethodsWithParameterTypeOf(this);
}

/**
* @return Methods of all imported classes that have a return type of this class.
*/
@PublicAPI(usage = ACCESS)
public Set<JavaMethod> getMethodsWithReturnTypeOfSelf() {
return javaClassDependencies.getMethodsWithReturnTypeOfClass();
return reverseDependencies.getMethodsWithReturnTypeOf(this);
}

/**
* @return {@link ThrowsDeclaration ThrowsDeclarations} of all imported classes that have the type of this class.
*/
@PublicAPI(usage = ACCESS)
public Set<ThrowsDeclaration<JavaMethod>> getMethodThrowsDeclarationsWithTypeOfSelf() {
return javaClassDependencies.getMethodThrowsDeclarationsWithTypeOfClass();
return reverseDependencies.getMethodThrowsDeclarationsWithTypeOf(this);
}

/**
* @return Constructors of all imported classes that have a parameter type of this class.
*/
@PublicAPI(usage = ACCESS)
public Set<JavaConstructor> getConstructorsWithParameterTypeOfSelf() {
return javaClassDependencies.getConstructorsWithParameterTypeOfClass();
return reverseDependencies.getConstructorsWithParameterTypeOf(this);
}

/**
* @return {@link ThrowsDeclaration ThrowsDeclarations} of all imported classes that have the type of this class.
*/
@PublicAPI(usage = ACCESS)
public Set<ThrowsDeclaration<JavaConstructor>> getConstructorsWithThrowsDeclarationTypeOfSelf() {
return javaClassDependencies.getConstructorsWithThrowsDeclarationTypeOfClass();
return reverseDependencies.getConstructorsWithThrowsDeclarationTypeOf(this);
}

/**
* @return All imported {@link JavaAnnotation JavaAnnotations} that have the annotation type of this class.
*/
@PublicAPI(usage = ACCESS)
public Set<JavaAnnotation<?>> getAnnotationsWithTypeOfSelf() {
return javaClassDependencies.getAnnotationsWithTypeOfClass();
return reverseDependencies.getAnnotationsWithTypeOf(this);
}

/**
* @return All imported {@link JavaAnnotation JavaAnnotations} that have a parameter with type of this class.
*/
@PublicAPI(usage = ACCESS)
public Set<JavaAnnotation<?>> getAnnotationsWithParameterTypeOfSelf() {
return reverseDependencies.getAnnotationsWithParameterTypeOf(this);
}

/**
* @return All imported {@link InstanceofCheck InstanceofChecks} that check if another class is an instance of this class.
*/
@PublicAPI(usage = ACCESS)
public Set<InstanceofCheck> getInstanceofChecksWithTypeOfSelf() {
return reverseDependencies.getInstanceofChecksWithTypeOf(this);
}

/**
Expand Down Expand Up @@ -1280,10 +1297,10 @@ void completeAnnotations(final ImportContext context) {

void completeFrom(ImportContext context) {
completeComponentType(context);
javaClassDependencies = new JavaClassDependencies(this, context);
for (JavaCodeUnit codeUnit : codeUnits) {
codeUnit.completeFrom(context);
}
javaClassDependencies = new JavaClassDependencies(this);
}

private void completeComponentType(ImportContext context) {
Expand All @@ -1296,6 +1313,7 @@ private void completeComponentType(ImportContext context) {
}

void setReverseDependencies(ReverseDependencies reverseDependencies) {
this.reverseDependencies = reverseDependencies;
for (JavaMember member : members) {
member.setReverseDependencies(reverseDependencies);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package com.tngtech.archunit.core.domain;

import java.util.HashSet;
import java.util.Set;

import com.google.common.base.Supplier;
Expand All @@ -26,38 +25,17 @@
import com.tngtech.archunit.core.domain.properties.HasAnnotations;

import static com.google.common.base.Suppliers.memoize;
import static com.google.common.collect.Sets.union;

class JavaClassDependencies {
private final JavaClass javaClass;
private final Set<JavaField> fieldsWithTypeOfClass;
private final Set<JavaMethod> methodsWithParameterTypeOfClass;
private final Set<JavaMethod> methodsWithReturnTypeOfClass;
private final Set<ThrowsDeclaration<JavaMethod>> methodsWithThrowsDeclarationTypeOfClass;
private final Set<JavaConstructor> constructorsWithParameterTypeOfClass;
private final Set<ThrowsDeclaration<JavaConstructor>> constructorsWithThrowsDeclarationTypeOfClass;
private final Set<JavaAnnotation<?>> annotationsWithTypeOfClass;
private final Set<JavaAnnotation<?>> annotationsWithParameterTypeOfClass;
private final Set<InstanceofCheck> instanceofChecksWithTypeOfClass;
private final Supplier<Set<Dependency>> directDependenciesFromClass;
private final Supplier<Set<Dependency>> directDependenciesToClass;

JavaClassDependencies(JavaClass javaClass, ImportContext context) {
JavaClassDependencies(JavaClass javaClass) {
this.javaClass = javaClass;
this.fieldsWithTypeOfClass = context.getFieldsOfType(javaClass);
this.methodsWithParameterTypeOfClass = context.getMethodsWithParameterOfType(javaClass);
this.methodsWithReturnTypeOfClass = context.getMethodsWithReturnType(javaClass);
this.methodsWithThrowsDeclarationTypeOfClass = context.getMethodThrowsDeclarationsOfType(javaClass);
this.constructorsWithParameterTypeOfClass = context.getConstructorsWithParameterOfType(javaClass);
this.constructorsWithThrowsDeclarationTypeOfClass = context.getConstructorThrowsDeclarationsOfType(javaClass);
this.annotationsWithTypeOfClass = context.getAnnotationsOfType(javaClass);
this.annotationsWithParameterTypeOfClass = context.getAnnotationsWithParameterOfType(javaClass);
this.instanceofChecksWithTypeOfClass = context.getInstanceofChecksOfType(javaClass);
this.directDependenciesFromClass = getDirectDependenciesFromClassSupplier();
this.directDependenciesToClass = getDirectDependenciesToClassSupplier();
this.directDependenciesFromClass = createDirectDependenciesFromClassSupplier();
}

private Supplier<Set<Dependency>> getDirectDependenciesFromClassSupplier() {
private Supplier<Set<Dependency>> createDirectDependenciesFromClassSupplier() {
return memoize(new Supplier<Set<Dependency>>() {
@Override
public Set<Dependency> get() {
Expand All @@ -76,69 +54,10 @@ public Set<Dependency> get() {
});
}

private Supplier<Set<Dependency>> getDirectDependenciesToClassSupplier() {
return memoize(new Supplier<Set<Dependency>>() {
@Override
public Set<Dependency> get() {
ImmutableSet.Builder<Dependency> result = ImmutableSet.builder();
result.addAll(dependenciesFromAccesses(javaClass.getAccessesToSelf()));
result.addAll(inheritanceDependenciesToSelf());
result.addAll(fieldDependenciesToSelf());
result.addAll(returnTypeDependenciesToSelf());
result.addAll(methodParameterDependenciesToSelf());
result.addAll(throwsDeclarationDependenciesToSelf());
result.addAll(constructorParameterDependenciesToSelf());
result.addAll(annotationDependenciesToSelf());
result.addAll(instanceofCheckDependenciesToSelf());
return result.build();
}
});
}

Set<Dependency> getDirectDependenciesFromClass() {
return directDependenciesFromClass.get();
}

Set<Dependency> getDirectDependenciesToClass() {
return directDependenciesToClass.get();
}

Set<JavaField> getFieldsWithTypeOfClass() {
return fieldsWithTypeOfClass;
}

Set<JavaMethod> getMethodsWithParameterTypeOfClass() {
return methodsWithParameterTypeOfClass;
}

Set<JavaMethod> getMethodsWithReturnTypeOfClass() {
return methodsWithReturnTypeOfClass;
}

Set<ThrowsDeclaration<JavaMethod>> getMethodThrowsDeclarationsWithTypeOfClass() {
return methodsWithThrowsDeclarationTypeOfClass;
}

Set<JavaConstructor> getConstructorsWithParameterTypeOfClass() {
return constructorsWithParameterTypeOfClass;
}

Set<ThrowsDeclaration<JavaConstructor>> getConstructorsWithThrowsDeclarationTypeOfClass() {
return constructorsWithThrowsDeclarationTypeOfClass;
}

private Set<ThrowsDeclaration<? extends JavaCodeUnit>> getThrowsDeclarationsWithTypeOfClass() {
return union(methodsWithThrowsDeclarationTypeOfClass, constructorsWithThrowsDeclarationTypeOfClass);
}

Set<JavaAnnotation<?>> getAnnotationsWithTypeOfClass() {
return annotationsWithTypeOfClass;
}

Set<InstanceofCheck> getInstanceofChecksWithTypeOfClass() {
return instanceofChecksWithTypeOfClass;
}

private Set<Dependency> dependenciesFromAccesses(Set<JavaAccess<?>> accesses) {
ImmutableSet.Builder<Dependency> result = ImmutableSet.builder();
for (JavaAccess<?> access : accesses) {
Expand Down Expand Up @@ -252,71 +171,4 @@ public void visitAnnotation(String propertyName, JavaAnnotation<?> memberAnnotat
}
return result.build();
}

private Set<Dependency> inheritanceDependenciesToSelf() {
Set<Dependency> result = new HashSet<>();
for (JavaClass subClass : javaClass.getSubClasses()) {
result.add(Dependency.fromInheritance(subClass, javaClass));
}
return result;
}

private Set<Dependency> fieldDependenciesToSelf() {
Set<Dependency> result = new HashSet<>();
for (JavaField field : javaClass.getFieldsWithTypeOfSelf()) {
result.addAll(Dependency.tryCreateFromField(field));
}
return result;
}

private Set<Dependency> returnTypeDependenciesToSelf() {
Set<Dependency> result = new HashSet<>();
for (JavaMethod method : javaClass.getMethodsWithReturnTypeOfSelf()) {
result.addAll(Dependency.tryCreateFromReturnType(method));
}
return result;
}

private Set<Dependency> methodParameterDependenciesToSelf() {
Set<Dependency> result = new HashSet<>();
for (JavaMethod method : javaClass.getMethodsWithParameterTypeOfSelf()) {
result.addAll(Dependency.tryCreateFromParameter(method, javaClass));
}
return result;
}

private Set<Dependency> throwsDeclarationDependenciesToSelf() {
Set<Dependency> result = new HashSet<>();
for (ThrowsDeclaration<? extends JavaCodeUnit> throwsDeclaration : getThrowsDeclarationsWithTypeOfClass()) {
result.addAll(Dependency.tryCreateFromThrowsDeclaration(throwsDeclaration));
}
return result;
}

private Set<Dependency> constructorParameterDependenciesToSelf() {
Set<Dependency> result = new HashSet<>();
for (JavaConstructor constructor : javaClass.getConstructorsWithParameterTypeOfSelf()) {
result.addAll(Dependency.tryCreateFromParameter(constructor, javaClass));
}
return result;
}

private Iterable<? extends Dependency> annotationDependenciesToSelf() {
Set<Dependency> result = new HashSet<>();
for (JavaAnnotation<?> annotation : annotationsWithTypeOfClass) {
result.addAll(Dependency.tryCreateFromAnnotation(annotation));
}
for (JavaAnnotation<?> annotation : annotationsWithParameterTypeOfClass) {
result.addAll(Dependency.tryCreateFromAnnotationMember(annotation, javaClass));
}
return result;
}

private Set<Dependency> instanceofCheckDependenciesToSelf() {
Set<Dependency> result = new HashSet<>();
for (InstanceofCheck instanceofCheck : getInstanceofChecksWithTypeOfClass()) {
result.addAll(Dependency.tryCreateFromInstanceofCheck(instanceofCheck));
}
return result;
}
}
Loading

0 comments on commit 90daf52

Please sign in to comment.