From 75071805f74b9989711d4a7f59a42ee7136d7595 Mon Sep 17 00:00:00 2001 From: Alexander Fedorenchik Date: Sat, 5 Oct 2019 13:42:35 +0300 Subject: [PATCH] Offer a way to retrieve the component type of a `JavaClass` that is an array. Issue: #187 Signed-off-by: Alexander Fedorenchik --- .../archunit/core/domain/ImportContext.java | 2 ++ .../archunit/core/domain/JavaClass.java | 7 +++++++ .../core/importer/ClassGraphCreator.java | 11 +++++++++++ .../archunit/core/domain/JavaClassTest.java | 18 ++++++++++++++++++ .../core/importer/ImportTestUtils.java | 5 +++++ 5 files changed, 43 insertions(+) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/ImportContext.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/ImportContext.java index 20a625012d..44d33e13fc 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/ImportContext.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/ImportContext.java @@ -56,4 +56,6 @@ public interface ImportContext { Set getConstructorsWithParameterOfType(JavaClass javaClass); Set> getConstructorThrowsDeclarationsOfType(JavaClass javaClass); + + Optional resolveComponentType(JavaType type); } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java index e11cfac8af..1a359c4458 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClass.java @@ -81,6 +81,7 @@ public class JavaClass implements HasName.AndFullName, HasAnnotations, HasModifi private final Set interfaces = new HashSet<>(); private final Set subClasses = new HashSet<>(); private Optional enclosingClass = Optional.absent(); + private Optional componentType = Optional.absent(); private Supplier> annotations = Suppliers.ofInstance(Collections.emptyMap()); private Supplier> allMethods; @@ -186,6 +187,11 @@ public boolean isArray() { return javaType.isArray(); } + @PublicAPI(usage = ACCESS) + Optional tryGetComponentType() { + return componentType; + } + /** * @return Returns true if this class is declared within another class. * Returns false for top-level classes. @@ -841,6 +847,7 @@ public Map get() { } CompletionProcess completeFrom(ImportContext context) { + componentType = context.resolveComponentType(javaType); enclosingClass = context.createEnclosingClass(this); memberDependenciesOnClass = new MemberDependenciesOnClass( context.getFieldsOfType(this), diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassGraphCreator.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassGraphCreator.java index f26f84428e..6373ebaced 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassGraphCreator.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassGraphCreator.java @@ -40,6 +40,7 @@ import com.tngtech.archunit.core.domain.JavaMethod; import com.tngtech.archunit.core.domain.JavaMethodCall; import com.tngtech.archunit.core.domain.JavaStaticInitializer; +import com.tngtech.archunit.core.domain.JavaType; import com.tngtech.archunit.core.domain.ThrowsDeclaration; import com.tngtech.archunit.core.importer.AccessRecord.FieldAccessRecord; import com.tngtech.archunit.core.importer.DomainBuilders.JavaConstructorCallBuilder; @@ -275,6 +276,16 @@ public Optional createEnclosingClass(JavaClass owner) { Optional.absent(); } + @Override + public Optional resolveComponentType(JavaType array) { + return array.tryGetComponentType().transform(new Function() { + @Override + public JavaClass apply(JavaType input) { + return classes.getOrResolve(input.getName()); + } + }); + } + private static class MemberDependenciesByTarget { private final SetMultimap fieldTypeDependencies = HashMultimap.create(); private final SetMultimap methodParameterTypeDependencies = HashMultimap.create(); diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaClassTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaClassTest.java index ebe85f8805..a01ea21a2e 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaClassTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaClassTest.java @@ -23,6 +23,9 @@ import com.tngtech.archunit.core.domain.testobjects.IsArrayTestClass; import com.tngtech.archunit.core.domain.testobjects.SuperA; import com.tngtech.archunit.core.importer.ClassFileImporter; +import com.tngtech.archunit.core.importer.testexamples.arrays.ClassAccessingOneDimensionalArray; +import com.tngtech.archunit.core.importer.testexamples.arrays.ClassAccessingTwoDimensionalArray; +import com.tngtech.archunit.core.importer.testexamples.arrays.ClassUsedInArray; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; @@ -80,6 +83,7 @@ public void finds_array_type() { JavaMethod method = importClassWithContext(IsArrayTestClass.class).getMethod("anArray"); assertThat(method.getRawReturnType().isArray()).isTrue(); + assertThat(method.getRawReturnType().tryGetComponentType().get().getName()).isEqualTo("java.lang.Object"); } @Test @@ -87,6 +91,20 @@ public void finds_non_array_type() { JavaMethod method = importClassWithContext(IsArrayTestClass.class).getMethod("notAnArray"); assertThat(method.getRawReturnType().isArray()).isFalse(); + assertThat(method.getRawReturnType().tryGetComponentType().isPresent()).isFalse(); + } + + @Test + public void finds_multidimensional_array_type() { + JavaClasses classes = importClassesWithContext(ClassUsedInArray.class, ClassAccessingOneDimensionalArray.class, ClassAccessingTwoDimensionalArray.class); + JavaClass type = classes.get(ClassUsedInArray.class); + JavaClass oneDimArray = classes.get(ClassAccessingOneDimensionalArray.class).getField("array").getRawType(); + JavaClass twoDimArray = classes.get(ClassAccessingTwoDimensionalArray.class).getField("array").getRawType(); + + assertThat(oneDimArray.isArray()).isTrue(); + assertThat(oneDimArray.tryGetComponentType().get()).isEqualTo(type); + assertThat(twoDimArray.isArray()).isTrue(); + assertThat(twoDimArray.tryGetComponentType().get()).isEqualTo(oneDimArray); } @Test diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/ImportTestUtils.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/ImportTestUtils.java index a8a6c71e93..6d5cdeef33 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/ImportTestUtils.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/ImportTestUtils.java @@ -428,5 +428,10 @@ public Set getConstructorsWithParameterOfType(JavaClass javaCla public Set> getConstructorThrowsDeclarationsOfType(JavaClass javaClass) { return Collections.emptySet(); } + + @Override + public Optional resolveComponentType(JavaType type) { + return Optional.absent(); + } } } \ No newline at end of file