From b10dde649f2cda04c8f567da70fdb97c8bbe573b Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Sun, 3 Nov 2019 15:20:39 +0100 Subject: [PATCH] Review: We have to always ensure the whole component type chain is present. Background is, that if those component types are not referenced in another place (e.g. the two-dim component type is not also a field type somewhere, etc.), we will otherwise create a "simple" class stub here on the fly, and that simple stub will not get processed anymore and thus will not get any component type. In other words, the component type chain would then be broken. Issue: #187 Signed-off-by: Peter Gafert --- .../archunit/core/domain/ImportContext.java | 2 +- .../archunit/core/domain/JavaClass.java | 11 +++++++++- .../core/importer/ClassGraphCreator.java | 12 +++-------- .../archunit/core/domain/JavaClassTest.java | 21 +++++++++++++++++++ .../core/importer/ImportTestUtils.java | 6 +++--- 5 files changed, 38 insertions(+), 14 deletions(-) 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 44d33e13fc..418b474a23 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 @@ -57,5 +57,5 @@ public interface ImportContext { Set> getConstructorThrowsDeclarationsOfType(JavaClass javaClass); - Optional resolveComponentType(JavaType type); + JavaClass resolveClass(String fullyQualifiedClassName); } 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 1a359c4458..764827453e 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 @@ -847,7 +847,7 @@ public Map get() { } CompletionProcess completeFrom(ImportContext context) { - componentType = context.resolveComponentType(javaType); + completeComponentType(context); enclosingClass = context.createEnclosingClass(this); memberDependenciesOnClass = new MemberDependenciesOnClass( context.getFieldsOfType(this), @@ -859,6 +859,15 @@ CompletionProcess completeFrom(ImportContext context) { return new CompletionProcess(); } + private void completeComponentType(ImportContext context) { + JavaClass current = this; + while (current.isArray() && !current.componentType.isPresent()) { + JavaClass componentType = context.resolveClass(current.javaType.tryGetComponentType().get().getName()); + current.componentType = Optional.of(componentType); + current = componentType; + } + } + @Override public String toString() { return "JavaClass{name='" + javaType.getName() + "\'}"; 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 6373ebaced..f9438ca636 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,7 +40,6 @@ 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; @@ -277,13 +276,8 @@ public Optional createEnclosingClass(JavaClass owner) { } @Override - public Optional resolveComponentType(JavaType array) { - return array.tryGetComponentType().transform(new Function() { - @Override - public JavaClass apply(JavaType input) { - return classes.getOrResolve(input.getName()); - } - }); + public JavaClass resolveClass(String fullyQualifiedClassName) { + return classes.getOrResolve(fullyQualifiedClassName); } private static class MemberDependenciesByTarget { @@ -347,4 +341,4 @@ Set> getConstructorThrowsDeclarationsOfType(J return constructorThrowsDeclarationDependencies.get(javaClass); } } -} \ No newline at end of file +} 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 763d52c8d8..b54552cb6f 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 @@ -105,6 +105,27 @@ public void finds_multidimensional_array_type() { assertThat(oneDimArray.tryGetComponentType().get()).isEqualTo(type); assertThat(twoDimArray.isArray()).isTrue(); assertThat(twoDimArray.tryGetComponentType().get()).isEqualTo(oneDimArray); + assertThat(twoDimArray.tryGetComponentType().get().tryGetComponentType().get()).isEqualTo(type); + } + + @Test + public void finds_component_type_chain_of_otherwise_unreferenced_component_type() { + class OnlyReferencingMultiDimArray { + OnlyReferencingMultiDimArray[][][] field; + } + + JavaClass javaClass = importClassesWithContext(OnlyReferencingMultiDimArray.class) + .get(OnlyReferencingMultiDimArray.class); + + JavaClass arrayType = javaClass.getField("field").getRawType(); + JavaClass twoDim = arrayType.tryGetComponentType().get(); + assertThat(twoDim.getName()).isEqualTo(OnlyReferencingMultiDimArray[][].class.getName()); + + JavaClass oneDim = twoDim.tryGetComponentType().get(); + assertThat(oneDim.getName()).isEqualTo(OnlyReferencingMultiDimArray[].class.getName()); + + JavaClass original = oneDim.tryGetComponentType().get(); + assertThat(original).isEqualTo(javaClass); } @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 6d5cdeef33..c48fbd4657 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 @@ -430,8 +430,8 @@ public Set> getConstructorThrowsDeclarationsO } @Override - public Optional resolveComponentType(JavaType type) { - return Optional.absent(); + public JavaClass resolveClass(String fullyQualifiedClassName) { + throw new UnsupportedOperationException("Override me where necessary"); } } -} \ No newline at end of file +}