diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java index efe43febb..f0473a199 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.stream.Stream; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -43,6 +44,7 @@ import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; import static com.tngtech.archunit.core.domain.Formatters.formatMethod; import static com.tngtech.archunit.core.domain.properties.HasName.Utils.namesOf; +import static java.util.stream.Collectors.toSet; /** * Represents a unit of code containing accesses to other units of code. A unit of code can be @@ -169,6 +171,22 @@ public JavaClass getRawReturnType() { return returnType.getRaw(); } + /** + * @return All raw types involved in this code unit's signature, + * which is the union of all raw types involved in the {@link #getReturnType() return type}, + * the {@link #getParameterTypes() parameter types} and the {@link #getTypeParameters() type parameters} of this code unit. + * For a definition of "all raw types involved" consult {@link JavaType#getAllInvolvedRawTypes()}. + */ + @Override + @PublicAPI(usage = ACCESS) + public Set getAllInvolvedRawTypes() { + return Stream.of( + Stream.of(this.returnType.get()), + this.parameters.getParameterTypes().stream(), + this.typeParameters.stream() + ).flatMap(s -> s).map(JavaType::getAllInvolvedRawTypes).flatMap(Set::stream).collect(toSet()); + } + @PublicAPI(usage = ACCESS) public Set getFieldAccesses() { return fieldAccesses; diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java index 335f0e93b..2022429a2 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java @@ -62,6 +62,15 @@ public JavaClass getRawType() { return type.toErasure(); } + /** + * @return All raw types involved in this field's signature, which is equivalent to {@link #getType()}.{@link JavaType#getAllInvolvedRawTypes() getAllInvolvedRawTypes()}. + */ + @Override + @PublicAPI(usage = ACCESS) + public Set getAllInvolvedRawTypes() { + return getType().getAllInvolvedRawTypes(); + } + @Override @PublicAPI(usage = ACCESS) public Set getAccessesToSelf() { diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java index ae0213b2f..4b7f0e57b 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaMember.java @@ -63,6 +63,15 @@ public abstract class JavaMember implements this.modifiers = checkNotNull(builder.getModifiers()); } + /** + * Similar to {@link JavaType#getAllInvolvedRawTypes()}, this method returns all raw types involved in this {@link JavaMember member's} signature. + * For more concrete details refer to {@link JavaField#getAllInvolvedRawTypes()} and {@link JavaCodeUnit#getAllInvolvedRawTypes()}. + * + * @return All raw types involved in the signature of this member + */ + @PublicAPI(usage = ACCESS) + public abstract Set getAllInvolvedRawTypes(); + @Override @PublicAPI(usage = ACCESS) public Set> getAnnotations() { diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaCodeUnitTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaCodeUnitTest.java index e2b61efd4..726c56230 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaCodeUnitTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaCodeUnitTest.java @@ -1,8 +1,11 @@ package com.tngtech.archunit.core.domain; import java.io.File; +import java.io.Serializable; +import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import com.google.common.collect.ImmutableList; import com.tngtech.archunit.core.importer.ClassFileImporter; @@ -20,12 +23,28 @@ import static com.tngtech.archunit.core.domain.properties.HasType.Functions.GET_RAW_TYPE; import static com.tngtech.archunit.testutil.Assertions.assertThat; import static com.tngtech.archunit.testutil.Assertions.assertThatAnnotation; +import static com.tngtech.archunit.testutil.Assertions.assertThatTypes; import static com.tngtech.java.junit.dataprovider.DataProviders.testForEach; import static org.assertj.core.api.Assertions.assertThatThrownBy; @RunWith(DataProviderRunner.class) public class JavaCodeUnitTest { + @Test + public void offers_all_involved_raw_types() { + class SampleClass & Serializable> { + @SuppressWarnings("unused") + T method(List>> input) { + return null; + } + } + + JavaMethod method = new ClassFileImporter().importClass(SampleClass.class).getMethod("method", List.class); + + assertThatTypes(method.getAllInvolvedRawTypes()) + .matchInAnyOrder(Collection.class, File.class, Serializable.class, List.class, Map.class, Number.class, Set.class, String.class); + } + @Test public void offers_all_calls_from_Self() { JavaMethod method = importClassWithContext(ClassAccessingOtherClass.class).getMethod("access", ClassBeingAccessed.class); diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaFieldTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaFieldTest.java new file mode 100644 index 000000000..2d93d7e87 --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaFieldTest.java @@ -0,0 +1,25 @@ +package com.tngtech.archunit.core.domain; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.tngtech.archunit.core.importer.ClassFileImporter; +import org.junit.Test; + +import static com.tngtech.archunit.testutil.Assertions.assertThatTypes; + +public class JavaFieldTest { + @Test + public void offers_all_involved_raw_types() { + class SomeClass { + @SuppressWarnings("unused") + List>> field; + } + + JavaField field = new ClassFileImporter().importClass(SomeClass.class).getField("field"); + + assertThatTypes(field.getAllInvolvedRawTypes()).matchInAnyOrder(List.class, Map.class, Serializable.class, Set.class, Number.class); + } +} \ No newline at end of file