From 705bf8ca37423f082c920a5aa3447577d555ab59 Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Tue, 5 Jan 2021 23:15:13 +0100 Subject: [PATCH 01/11] remove obsolete `public` from method of `ClassFileImportRecord` Signed-off-by: Peter Gafert --- .../tngtech/archunit/core/importer/ClassFileImportRecord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java index c838527351..914062061f 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java @@ -71,7 +71,7 @@ void addInterfaces(String ownerName, Set interfaceNames) { interfaceNamesByOwner.putAll(ownerName, interfaceNames); } - public void addTypeParameters(String ownerName, TypeParametersBuilder builder) { + void addTypeParameters(String ownerName, TypeParametersBuilder builder) { typeParametersBuilderByOwner.put(ownerName, builder); } From a7713668bab04a02c3feafc60470fddaaf0c076d Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Sat, 19 Dec 2020 20:38:56 +0100 Subject: [PATCH 02/11] ensure ArchConfiguration is reset after data point generation Adjusting `ArchConfiguration` in a static context without resetting it afterwards is a bad idea. Together with `ArchConfigurationRule` it then depends on the order which default value for `resolveMissingDependenciesFromClasspath` is stored within `ArchConfigurationRule`. This is a recipe for flaky tests, e.g. on master `ClassFileImporterTest` succeeds, while on this branch it fails, even though there have been no relevant changes there. To make it easier to execute little snippets and correctly ensure the configuration is reset before the snippet as well as after the snippet, I have introduced a new utility method `ArchConfigurationRule.resetConfigurationAround(callable)`. Signed-off-by: Peter Gafert --- .../core/importer/ClassFileImporterTest.java | 29 ++++++++++++------- .../testutil/ArchConfigurationRule.java | 13 +++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterTest.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterTest.java index 75f59c74a0..425a99e171 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterTest.java @@ -22,6 +22,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.Callable; import java.util.jar.JarFile; import com.google.common.base.Predicate; @@ -1722,18 +1723,24 @@ class Element { class DependsOnArray { Element[] array; } - ArchConfiguration.get().setResolveMissingDependenciesFromClassPath(true); - JavaClass resolvedFromClasspath = new ClassFileImporter().importClasses(DependsOnArray.class) - .get(DependsOnArray.class).getField("array").getRawType().getComponentType(); - - ArchConfiguration.get().setResolveMissingDependenciesFromClassPath(false); - JavaClass stub = new ClassFileImporter().importClasses(DependsOnArray.class) - .get(DependsOnArray.class).getField("array").getRawType().getComponentType(); - return $$( - $("Resolved from classpath", resolvedFromClasspath), - $("Stub class", stub) - ); + return ArchConfigurationRule.resetConfigurationAround(new Callable() { + @Override + public Object[][] call() { + ArchConfiguration.get().setResolveMissingDependenciesFromClassPath(true); + JavaClass resolvedFromClasspath = new ClassFileImporter().importClasses(DependsOnArray.class) + .get(DependsOnArray.class).getField("array").getRawType().getComponentType(); + + ArchConfiguration.get().setResolveMissingDependenciesFromClassPath(false); + JavaClass stub = new ClassFileImporter().importClasses(DependsOnArray.class) + .get(DependsOnArray.class).getField("array").getRawType().getComponentType(); + + return $$( + $("Resolved from classpath", resolvedFromClasspath), + $("Stub class", stub) + ); + } + }); } @Test diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/ArchConfigurationRule.java b/archunit/src/test/java/com/tngtech/archunit/testutil/ArchConfigurationRule.java index c283edae33..ccc67c7f29 100644 --- a/archunit/src/test/java/com/tngtech/archunit/testutil/ArchConfigurationRule.java +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/ArchConfigurationRule.java @@ -1,11 +1,24 @@ package com.tngtech.archunit.testutil; +import java.util.concurrent.Callable; + import com.tngtech.archunit.ArchConfiguration; import org.junit.rules.ExternalResource; public class ArchConfigurationRule extends ExternalResource { private boolean resolveMissingDependenciesFromClassPath = ArchConfiguration.get().resolveMissingDependenciesFromClassPath(); + public static T resetConfigurationAround(Callable callable) { + ArchConfiguration.get().reset(); + try { + return callable.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + ArchConfiguration.get().reset(); + } + } + public ArchConfigurationRule resolveAdditionalDependenciesFromClassPath(boolean enabled) { resolveMissingDependenciesFromClassPath = enabled; return this; From f86b800631068c56b16721e5fdd1cf929dd4a8df Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Wed, 6 Jan 2021 20:01:14 +0100 Subject: [PATCH 03/11] make `DependencyTest` resilient against line number changes While it is generally nice to have classes as test input defined as local classes within the test method itself, this does not hold for tests that depend on line numbers. To avoid having to continuously change this test method for unrelated changes, just because the line numbers change, I have extracted the test class from the test method. Signed-off-by: Peter Gafert --- .../archunit/core/domain/DependencyTest.java | 24 +++++++------------ .../ClassWithArrayDependencies.java | 12 ++++++++++ 2 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/ClassWithArrayDependencies.java diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java index 112b1c29c5..994d6c94e5 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java @@ -9,6 +9,7 @@ import com.google.common.base.MoreObjects; import com.tngtech.archunit.base.DescribedPredicate; +import com.tngtech.archunit.core.domain.testobjects.ClassWithArrayDependencies; import com.tngtech.archunit.core.domain.testobjects.ClassWithDependencyOnInstanceofCheck; import com.tngtech.archunit.core.domain.testobjects.ClassWithDependencyOnInstanceofCheck.InstanceOfCheckTarget; import com.tngtech.archunit.core.importer.ClassFileImporter; @@ -86,26 +87,17 @@ public void Dependency_from_access() { } @DataProvider - public static Object[][] method_calls_to_array_types() throws NoSuchMethodException { - @SuppressWarnings("unused") - class ClassWithArrayDependencies { - private void oneDimArray() { - new String[0].clone(); - } - - private void multiDimArray() { - new String[0][0].clone(); - } - } + public static Object[][] method_calls_to_array_types() { return $$( - $(ClassWithArrayDependencies.class.getDeclaredMethod("oneDimArray"), String[].class, 93), - $(ClassWithArrayDependencies.class.getDeclaredMethod("multiDimArray"), String[][].class, 97) + $(ClassWithArrayDependencies.class, "oneDimArray", String[].class, 6), + $(ClassWithArrayDependencies.class, "multiDimArray", String[][].class, 10) ); } @Test @UseDataProvider("method_calls_to_array_types") - public void Dependency_from_access_with_component_type(Method reflectionMethodWithArrayMethodCall, Class arrayType, int expectedLineNumber) { + public void Dependency_from_access_with_component_type(Class classDependingOnArray, String nameOfMethodWithArrayMethodCall, Class arrayType, int expectedLineNumber) throws NoSuchMethodException { + Method reflectionMethodWithArrayMethodCall = classDependingOnArray.getDeclaredMethod(nameOfMethodWithArrayMethodCall); Class reflectionDeclaringClass = reflectionMethodWithArrayMethodCall.getDeclaringClass(); JavaMethod method = new ClassFileImporter().importClasses(reflectionDeclaringClass) .get(reflectionDeclaringClass).getMethod(reflectionMethodWithArrayMethodCall.getName()); @@ -115,12 +107,12 @@ public void Dependency_from_access_with_component_type(Method reflectionMethodWi DependenciesAssertion.ExpectedDependencies expectedDependencies = from(reflectionDeclaringClass).to(arrayType) .withDescriptionContaining("Method <%s> calls method <%s>", method.getFullName(), arrayType.getName() + ".clone()") - .inLocation(DependencyTest.class, expectedLineNumber); + .inLocation(classDependingOnArray, expectedLineNumber); Class expectedComponentType = arrayType.getComponentType(); while (expectedComponentType != null) { expectedDependencies.from(reflectionDeclaringClass).to(expectedComponentType) .withDescriptionContaining("Method <%s> depends on component type <%s>", method.getFullName(), expectedComponentType.getName()) - .inLocation(DependencyTest.class, expectedLineNumber); + .inLocation(classDependingOnArray, expectedLineNumber); expectedComponentType = expectedComponentType.getComponentType(); } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/ClassWithArrayDependencies.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/ClassWithArrayDependencies.java new file mode 100644 index 0000000000..9e0d913ac0 --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/ClassWithArrayDependencies.java @@ -0,0 +1,12 @@ +package com.tngtech.archunit.core.domain.testobjects; + +@SuppressWarnings("unused") +public class ClassWithArrayDependencies { + private void oneDimArray() { + new String[0].clone(); + } + + private void multiDimArray() { + new String[0][0].clone(); + } +} From 26bb44b0bcd493ee4bb519506c606a5f5e7608c3 Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Tue, 5 Jan 2021 20:36:21 +0100 Subject: [PATCH 04/11] fix signature of `Optional.or(Optional<..> value)` Since `Optional` is covariant, it is a perfectly valid use case to have `Optional.of(parent).or(optionalChild)`, since an `Optional.of(child)` is always also an `Optional.of(parent)` (for an inheritance relation `Child extends Parent`). Unfortunately the signature so far did not reflect that, because `Optional.of(parent)` only allowed another `Optional` to be passed to `Optional.or(..)`. This commit fixes this to allow any optional of a subtype of the type parameter to be passed into `Optional.or(..)`. Signed-off-by: Peter Gafert --- .../main/java/com/tngtech/archunit/base/Optional.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/archunit/src/main/java/com/tngtech/archunit/base/Optional.java b/archunit/src/main/java/com/tngtech/archunit/base/Optional.java index 3a59e8fbc3..b05b4c3f75 100644 --- a/archunit/src/main/java/com/tngtech/archunit/base/Optional.java +++ b/archunit/src/main/java/com/tngtech/archunit/base/Optional.java @@ -72,7 +72,7 @@ public static Optional absent() { public abstract T or(T value); @PublicAPI(usage = ACCESS) - public abstract Optional or(Optional value); + public abstract Optional or(Optional value); @PublicAPI(usage = ACCESS) public abstract Set asSet(); @@ -106,8 +106,9 @@ public T or(T value) { } @Override - public Optional or(Optional value) { - return value; + @SuppressWarnings("unchecked") // cast is safe because Optional is covariant + public Optional or(Optional value) { + return (Optional) value; } @Override @@ -169,7 +170,7 @@ public T or(T value) { } @Override - public Optional or(Optional value) { + public Optional or(Optional value) { return this; } From 1069d42d0e40962c379d1bbec4ef80f85ab52203 Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Sat, 18 Jul 2020 20:52:44 +0200 Subject: [PATCH 05/11] consistently use {super-/sub-}{class/interface/type/package} The Oracle documentation as well as the Reflection API use `superclass`, `subclass`, `supertype`, `subtype`. For `interface` this is not completely consistent, even within the JDK classes themselves, but I've decided to go for the same camel case convention as for `class`. In general the prefixes `super-` and `sub-` are used to form new words by concatenation in all cases I could find, `supernatural`, `superintendent`, `superpower`, `substandard`, `subconscious`, `subcommittee`, ... Thus I think it is worth it to adjust ArchUnit's spelling consistently and adjust to the Reflection API conventions, even though this will introduce some deprecated public API methods. Signed-off-by: Peter Gafert --- .../junit4/SessionBeanRulesTest.java | 8 +- .../junit4/ThirdPartyRulesTest.java | 4 +- .../junit5/SessionBeanRulesTest.java | 8 +- .../junit5/ThirdPartyRulesTest.java | 4 +- .../layers/ClassViolatingThirdPartyRules.java | 10 +- .../ThirdPartyClassWorkaroundFactory.java | 4 +- ...ava => ThirdPartySubclassWithProblem.java} | 2 +- .../exampletest/SessionBeanRulesTest.java | 8 +- .../exampletest/ThirdPartyRulesTest.java | 4 +- .../archunit/ArchUnitArchitectureTest.java | 4 +- .../com/tngtech/archunit/PublicAPIRules.java | 12 +- .../integration/ExamplesIntegrationTest.java | 6 +- .../testutils/ExpectedDependency.java | 6 +- .../archunit/junit/ReflectionUtils.java | 8 +- .../archunit/junit/ReflectionUtilsTest.java | 10 +- .../archunit/base/DescribedPredicate.java | 22 +- .../archunit/core/domain/AccessTarget.java | 2 +- .../archunit/core/domain/Dependency.java | 12 +- .../archunit/core/domain/ImportContext.java | 2 +- .../archunit/core/domain/JavaClass.java | 88 +++++-- .../core/domain/JavaClassDependencies.java | 4 +- .../archunit/core/domain/JavaMember.java | 2 +- .../archunit/core/domain/JavaPackage.java | 76 +++--- .../core/domain/ReverseDependencies.java | 2 +- .../domain/properties/HasThrowsClause.java | 2 +- .../archunit/core/importer/AccessRecord.java | 6 +- .../core/importer/ClassFileImportRecord.java | 20 +- .../core/importer/ClassFileProcessor.java | 6 +- .../core/importer/ClassGraphCreator.java | 24 +- .../core/importer/JavaClassProcessor.java | 12 +- .../tngtech/archunit/lang/ArchCondition.java | 14 +- .../lang/conditions/ArchConditions.java | 32 +-- .../lang/conditions/ArchPredicates.java | 10 +- .../lang/conditions/FieldAccessCondition.java | 4 +- .../AbstractGivenCodeUnitsInternal.java | 2 +- .../syntax/AbstractGivenMembersInternal.java | 2 +- .../syntax/AbstractMembersShouldInternal.java | 2 +- .../lang/syntax/GivenClassInternal.java | 2 +- .../lang/syntax/GivenClassesInternal.java | 2 +- .../syntax/GivenConstructorsInternal.java | 2 +- .../lang/syntax/GivenFieldsInternal.java | 2 +- .../lang/syntax/GivenMethodsInternal.java | 2 +- .../lang/syntax/GivenObjectsInternal.java | 2 +- .../lang/syntax/ObjectsShouldInternal.java | 4 +- .../lang/syntax/PredicateAggregator.java | 4 +- .../lang/syntax/elements/MembersShould.java | 2 +- .../lang/syntax/elements/MembersThat.java | 2 +- .../archunit/library/Architectures.java | 2 +- .../dependencies/GivenSlicesInternal.java | 2 +- .../archunit/core/domain/DependencyTest.java | 4 +- .../archunit/core/domain/JavaClassTest.java | 74 +++--- .../archunit/core/domain/JavaPackageTest.java | 10 +- .../domain/testobjects/InterfaceForA.java | 2 +- ...uperInterface.java => Superinterface.java} | 2 +- .../ClassFileImporterAnnotationsTest.java | 2 +- .../core/importer/ClassFileImporterTest.java | 223 +++++++++--------- .../core/importer/ImportTestUtils.java | 2 +- .../importer/IndependentClasspathRule.java | 2 +- .../archunit/core/importer/UrlSourceTest.java | 14 +- ...electedClassResolverFromClasspathTest.java | 6 +- ...va => ExternalSubtypeConstructorCall.java} | 2 +- ...{OtherSubClass.java => OtherSubclass.java} | 2 +- .../classhierarchyimport/SomeCollection.java | 2 +- ...ubSubClass.java => SubSubSubSubclass.java} | 2 +- ...ubSubSubClass.java => SubSubSubclass.java} | 2 +- .../{SubSubClass.java => SubSubclass.java} | 2 +- .../{SubClass.java => Subclass.java} | 14 +- .../{SubInterface.java => Subinterface.java} | 2 +- .../AccessToSuperAndSubClassField.java | 11 - .../AccessToSuperAndSubclassField.java | 11 + ...ld.java => SubclassWithAccessedField.java} | 2 +- ....java => SuperclassWithAccessedField.java} | 2 +- .../CallOfSuperAndSubClassMethod.java | 16 -- .../CallOfSuperAndSubclassMethod.java | 16 ++ ...hod.java => SubclassWithCalledMethod.java} | 2 +- ...d.java => SuperclassWithCalledMethod.java} | 2 +- ...lassCDependingOnClassB_SuperclassOfX.java} | 4 +- .../ClassXDependingOnClassesABCD.java | 2 +- .../outsideofclasspath/MiddleClass.java | 2 +- ...SuperClass.java => MissingSuperclass.java} | 4 +- .../archunit/lang/ConditionEventsTest.java | 12 +- .../lang/conditions/ArchConditionsTest.java | 10 +- .../archunit/library/ArchitecturesTest.java | 20 +- .../library/dependencies/SliceTest.java | 8 +- .../dependencies/SlicesShouldTest.java | 14 +- .../first/any/pkg/FirstAnyPkgClass.java | 4 +- .../testclasses/some/pkg/SomePkgClass.java | 4 +- ...ePkgSubClass.java => SomePkgSubclass.java} | 2 +- docs/userguide/006_The_Core_API.adoc | 6 +- docs/userguide/007_The_Lang_API.adoc | 4 +- 90 files changed, 540 insertions(+), 459 deletions(-) rename archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/{ThirdPartySubClassWithProblem.java => ThirdPartySubclassWithProblem.java} (53%) rename archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/{SuperInterface.java => Superinterface.java} (62%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/callimport/{ExternalSubTypeConstructorCall.java => ExternalSubtypeConstructorCall.java} (87%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/{OtherSubClass.java => OtherSubclass.java} (78%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/{SubSubSubSubClass.java => SubSubSubSubclass.java} (59%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/{SubSubSubClass.java => SubSubSubclass.java} (61%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/{SubSubClass.java => SubSubclass.java} (77%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/{SubClass.java => Subclass.java} (59%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/{SubInterface.java => Subinterface.java} (59%) delete mode 100644 archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/AccessToSuperAndSubClassField.java create mode 100644 archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/AccessToSuperAndSubclassField.java rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/{SubClassWithAccessedField.java => SubclassWithAccessedField.java} (64%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/{SuperClassWithAccessedField.java => SuperclassWithAccessedField.java} (74%) delete mode 100644 archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/CallOfSuperAndSubClassMethod.java create mode 100644 archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/CallOfSuperAndSubclassMethod.java rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/{SubClassWithCalledMethod.java => SubclassWithCalledMethod.java} (77%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/{SuperClassWithCalledMethod.java => SuperclassWithCalledMethod.java} (84%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/{ClassCDependingOnClassB_SuperClassOfX.java => ClassCDependingOnClassB_SuperclassOfX.java} (78%) rename archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/{MissingSuperClass.java => MissingSuperclass.java} (70%) rename archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/sub/{SomePkgSubClass.java => SomePkgSubclass.java} (89%) diff --git a/archunit-example/example-junit4/src/test/java/com/tngtech/archunit/exampletest/junit4/SessionBeanRulesTest.java b/archunit-example/example-junit4/src/test/java/com/tngtech/archunit/exampletest/junit4/SessionBeanRulesTest.java index bf95c83497..cfc680d8dc 100644 --- a/archunit-example/example-junit4/src/test/java/com/tngtech/archunit/exampletest/junit4/SessionBeanRulesTest.java +++ b/archunit-example/example-junit4/src/test/java/com/tngtech/archunit/exampletest/junit4/SessionBeanRulesTest.java @@ -66,8 +66,8 @@ private static DescribedPredicate haveLocalBeanSubclass() { return new DescribedPredicate("have subclass that is a local bean") { @Override public boolean apply(JavaClass input) { - for (JavaClass subClass : input.getAllSubClasses()) { - if (isLocalBeanImplementation(subClass, input)) { + for (JavaClass subclass : input.getAllSubclasses()) { + if (isLocalBeanImplementation(subclass, input)) { return true; } } @@ -93,13 +93,13 @@ private static ArchCondition haveAUniqueImplementation() { @Override public void check(JavaClass businessInterface, ConditionEvents events) { events.add(new SimpleConditionEvent(businessInterface, - businessInterface.getAllSubClasses().size() <= 1, + businessInterface.getAllSubclasses().size() <= 1, describe(businessInterface))); } private String describe(JavaClass businessInterface) { return String.format("%s is implemented by %s", - businessInterface.getSimpleName(), joinNamesOf(businessInterface.getAllSubClasses())); + businessInterface.getSimpleName(), joinNamesOf(businessInterface.getAllSubclasses())); } private String joinNamesOf(Set implementations) { diff --git a/archunit-example/example-junit4/src/test/java/com/tngtech/archunit/exampletest/junit4/ThirdPartyRulesTest.java b/archunit-example/example-junit4/src/test/java/com/tngtech/archunit/exampletest/junit4/ThirdPartyRulesTest.java index a1811b3b02..3568cebb29 100644 --- a/archunit-example/example-junit4/src/test/java/com/tngtech/archunit/exampletest/junit4/ThirdPartyRulesTest.java +++ b/archunit-example/example-junit4/src/test/java/com/tngtech/archunit/exampletest/junit4/ThirdPartyRulesTest.java @@ -42,10 +42,10 @@ private static ArchCondition notCreateProblematicClassesOutsideOfWork target(is(constructor())).and(targetOwner(is(assignableTo(ThirdPartyClassWithProblem.class)))); DescribedPredicate> notFromWithinThirdPartyClass = - originOwner(is(not(assignableTo(ThirdPartyClassWithProblem.class)))).forSubType(); + originOwner(is(not(assignableTo(ThirdPartyClassWithProblem.class)))).forSubtype(); DescribedPredicate> notFromWorkaroundFactory = - originOwner(is(not(equivalentTo(ThirdPartyClassWorkaroundFactory.class)))).forSubType(); + originOwner(is(not(equivalentTo(ThirdPartyClassWorkaroundFactory.class)))).forSubtype(); DescribedPredicate> targetIsIllegalConstructorOfThirdPartyClass = constructorCallOfThirdPartyClass. diff --git a/archunit-example/example-junit5/src/test/java/com/tngtech/archunit/exampletest/junit5/SessionBeanRulesTest.java b/archunit-example/example-junit5/src/test/java/com/tngtech/archunit/exampletest/junit5/SessionBeanRulesTest.java index a8b1095d55..30acfacaaa 100644 --- a/archunit-example/example-junit5/src/test/java/com/tngtech/archunit/exampletest/junit5/SessionBeanRulesTest.java +++ b/archunit-example/example-junit5/src/test/java/com/tngtech/archunit/exampletest/junit5/SessionBeanRulesTest.java @@ -63,8 +63,8 @@ private static DescribedPredicate haveLocalBeanSubclass() { return new DescribedPredicate("have subclass that is a local bean") { @Override public boolean apply(JavaClass input) { - for (JavaClass subClass : input.getAllSubClasses()) { - if (isLocalBeanImplementation(subClass, input)) { + for (JavaClass subclass : input.getAllSubclasses()) { + if (isLocalBeanImplementation(subclass, input)) { return true; } } @@ -90,13 +90,13 @@ private static ArchCondition haveAUniqueImplementation() { @Override public void check(JavaClass businessInterface, ConditionEvents events) { events.add(new SimpleConditionEvent(businessInterface, - businessInterface.getAllSubClasses().size() <= 1, + businessInterface.getAllSubclasses().size() <= 1, describe(businessInterface))); } private String describe(JavaClass businessInterface) { return String.format("%s is implemented by %s", - businessInterface.getSimpleName(), joinNamesOf(businessInterface.getAllSubClasses())); + businessInterface.getSimpleName(), joinNamesOf(businessInterface.getAllSubclasses())); } private String joinNamesOf(Set implementations) { diff --git a/archunit-example/example-junit5/src/test/java/com/tngtech/archunit/exampletest/junit5/ThirdPartyRulesTest.java b/archunit-example/example-junit5/src/test/java/com/tngtech/archunit/exampletest/junit5/ThirdPartyRulesTest.java index 5394969f59..fc0951cf6c 100644 --- a/archunit-example/example-junit5/src/test/java/com/tngtech/archunit/exampletest/junit5/ThirdPartyRulesTest.java +++ b/archunit-example/example-junit5/src/test/java/com/tngtech/archunit/exampletest/junit5/ThirdPartyRulesTest.java @@ -39,10 +39,10 @@ private static ArchCondition notCreateProblematicClassesOutsideOfWork target(is(constructor())).and(targetOwner(is(assignableTo(ThirdPartyClassWithProblem.class)))); DescribedPredicate> notFromWithinThirdPartyClass = - originOwner(is(not(assignableTo(ThirdPartyClassWithProblem.class)))).forSubType(); + originOwner(is(not(assignableTo(ThirdPartyClassWithProblem.class)))).forSubtype(); DescribedPredicate> notFromWorkaroundFactory = - originOwner(is(not(equivalentTo(ThirdPartyClassWorkaroundFactory.class)))).forSubType(); + originOwner(is(not(equivalentTo(ThirdPartyClassWorkaroundFactory.class)))).forSubtype(); DescribedPredicate> targetIsIllegalConstructorOfThirdPartyClass = constructorCallOfThirdPartyClass. diff --git a/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/ClassViolatingThirdPartyRules.java b/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/ClassViolatingThirdPartyRules.java index 36cb21c5bb..56d88411b2 100644 --- a/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/ClassViolatingThirdPartyRules.java +++ b/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/ClassViolatingThirdPartyRules.java @@ -2,7 +2,7 @@ import com.tngtech.archunit.example.layers.thirdparty.ThirdPartyClassWithProblem; import com.tngtech.archunit.example.layers.thirdparty.ThirdPartyClassWorkaroundFactory; -import com.tngtech.archunit.example.layers.thirdparty.ThirdPartySubClassWithProblem; +import com.tngtech.archunit.example.layers.thirdparty.ThirdPartySubclassWithProblem; public class ClassViolatingThirdPartyRules { ThirdPartyClassWithProblem illegallyInstantiateThirdPartyClass() { @@ -13,11 +13,11 @@ ThirdPartyClassWithProblem correctlyInstantiateThirdPartyClass() { return new ThirdPartyClassWorkaroundFactory().create(); } - ThirdPartySubClassWithProblem illegallyInstantiateThirdPartySubClass() { - return new ThirdPartySubClassWithProblem(); + ThirdPartySubclassWithProblem illegallyInstantiateThirdPartySubclass() { + return new ThirdPartySubclassWithProblem(); } - ThirdPartySubClassWithProblem correctlyInstantiateThirdPartySubClass() { - return new ThirdPartyClassWorkaroundFactory().createSubClass(); + ThirdPartySubclassWithProblem correctlyInstantiateThirdPartySubclass() { + return new ThirdPartyClassWorkaroundFactory().createSubclass(); } } diff --git a/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartyClassWorkaroundFactory.java b/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartyClassWorkaroundFactory.java index 5a123cec06..c30a9ea8c0 100644 --- a/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartyClassWorkaroundFactory.java +++ b/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartyClassWorkaroundFactory.java @@ -9,8 +9,8 @@ public ThirdPartyClassWithProblem create() { return new ThirdPartyClassWithProblem(); } - public ThirdPartySubClassWithProblem createSubClass() { + public ThirdPartySubclassWithProblem createSubclass() { // some workaround here - return new ThirdPartySubClassWithProblem(); + return new ThirdPartySubclassWithProblem(); } } diff --git a/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartySubClassWithProblem.java b/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartySubclassWithProblem.java similarity index 53% rename from archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartySubClassWithProblem.java rename to archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartySubclassWithProblem.java index 435b517a0a..b994c401c6 100644 --- a/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartySubClassWithProblem.java +++ b/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/thirdparty/ThirdPartySubclassWithProblem.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.example.layers.thirdparty; -public class ThirdPartySubClassWithProblem extends ThirdPartyClassWithProblem { +public class ThirdPartySubclassWithProblem extends ThirdPartyClassWithProblem { } diff --git a/archunit-example/example-plain/src/test/java/com/tngtech/archunit/exampletest/SessionBeanRulesTest.java b/archunit-example/example-plain/src/test/java/com/tngtech/archunit/exampletest/SessionBeanRulesTest.java index 2257e7117d..c903b9f96d 100644 --- a/archunit-example/example-plain/src/test/java/com/tngtech/archunit/exampletest/SessionBeanRulesTest.java +++ b/archunit-example/example-plain/src/test/java/com/tngtech/archunit/exampletest/SessionBeanRulesTest.java @@ -65,8 +65,8 @@ private static DescribedPredicate> originNeitherConstructorNorPost new DescribedPredicate("have subclass that is a local bean") { @Override public boolean apply(JavaClass input) { - for (JavaClass subClass : input.getAllSubClasses()) { - if (isLocalBeanImplementation(subClass, input)) { + for (JavaClass subclass : input.getAllSubclasses()) { + if (isLocalBeanImplementation(subclass, input)) { return true; } } @@ -90,13 +90,13 @@ private boolean isLocalBeanImplementation(JavaClass bean, JavaClass businessInte @Override public void check(JavaClass businessInterface, ConditionEvents events) { events.add(new SimpleConditionEvent(businessInterface, - businessInterface.getAllSubClasses().size() <= 1, + businessInterface.getAllSubclasses().size() <= 1, describe(businessInterface))); } private String describe(JavaClass businessInterface) { return String.format("%s is implemented by %s", - businessInterface.getSimpleName(), joinNamesOf(businessInterface.getAllSubClasses())); + businessInterface.getSimpleName(), joinNamesOf(businessInterface.getAllSubclasses())); } private String joinNamesOf(Set implementations) { diff --git a/archunit-example/example-plain/src/test/java/com/tngtech/archunit/exampletest/ThirdPartyRulesTest.java b/archunit-example/example-plain/src/test/java/com/tngtech/archunit/exampletest/ThirdPartyRulesTest.java index 8a5c3b6cda..dd8e3049bd 100644 --- a/archunit-example/example-plain/src/test/java/com/tngtech/archunit/exampletest/ThirdPartyRulesTest.java +++ b/archunit-example/example-plain/src/test/java/com/tngtech/archunit/exampletest/ThirdPartyRulesTest.java @@ -43,10 +43,10 @@ private ArchCondition notCreateProblematicClassesOutsideOfWorkaroundF target(is(constructor())).and(targetOwner(is(assignableTo(ThirdPartyClassWithProblem.class)))); DescribedPredicate> notFromWithinThirdPartyClass = - originOwner(is(not(assignableTo(ThirdPartyClassWithProblem.class)))).forSubType(); + originOwner(is(not(assignableTo(ThirdPartyClassWithProblem.class)))).forSubtype(); DescribedPredicate> notFromWorkaroundFactory = - originOwner(is(not(equivalentTo(ThirdPartyClassWorkaroundFactory.class)))).forSubType(); + originOwner(is(not(equivalentTo(ThirdPartyClassWorkaroundFactory.class)))).forSubtype(); DescribedPredicate> targetIsIllegalConstructorOfThirdPartyClass = constructorCallOfThirdPartyClass. diff --git a/archunit-integration-test/src/test/java/com/tngtech/archunit/ArchUnitArchitectureTest.java b/archunit-integration-test/src/test/java/com/tngtech/archunit/ArchUnitArchitectureTest.java index c856ccfb36..b99bf0fc97 100644 --- a/archunit-integration-test/src/test/java/com/tngtech/archunit/ArchUnitArchitectureTest.java +++ b/archunit-integration-test/src/test/java/com/tngtech/archunit/ArchUnitArchitectureTest.java @@ -71,7 +71,7 @@ public class ArchUnitArchitectureTest { private static DescribedPredicate> typeIsIllegallyResolvedViaReflection() { DescribedPredicate> explicitlyAllowedUsage = origin(is(annotatedWith(MayResolveTypesViaReflection.class))) - .or(contextIsAnnotatedWith(MayResolveTypesViaReflection.class)).forSubType(); + .or(contextIsAnnotatedWith(MayResolveTypesViaReflection.class)).forSubtype(); return classIsResolvedViaReflection().and(not(explicitlyAllowedUsage)); } @@ -100,7 +100,7 @@ private static DescribedPredicate> classIsResolvedViaReflection() { target(HasOwner.Functions.Get.owner() .is(equivalentTo(Class.class))) .and(target(has(name("forName")))) - .forSubType(); + .forSubtype(); DescribedPredicate> targetIsMarked = annotatedWith(ResolvesTypesViaReflection.class).onResultOf(Get.target()); diff --git a/archunit-integration-test/src/test/java/com/tngtech/archunit/PublicAPIRules.java b/archunit-integration-test/src/test/java/com/tngtech/archunit/PublicAPIRules.java index 8924f532a1..298f888179 100644 --- a/archunit-integration-test/src/test/java/com/tngtech/archunit/PublicAPIRules.java +++ b/archunit-integration-test/src/test/java/com/tngtech/archunit/PublicAPIRules.java @@ -136,13 +136,13 @@ public class PublicAPIRules { .andShould().haveRawReturnType(not(guavaClass()).as("that are no Guava types"))); private static DescribedPredicate publicAPI() { - return annotatedWith(PublicAPI.class).forSubType() + return annotatedWith(PublicAPI.class).forSubtype() .or(haveMemberThatBelongsToPublicApi()) .or(markedAsPublicAPIForInheritance()); } private static DescribedPredicate internal() { - return annotatedWith(Internal.class).forSubType() + return annotatedWith(Internal.class).forSubtype() .or(equivalentTo(Internal.class)); } @@ -215,8 +215,8 @@ public boolean apply(JavaClass input) { } } return input.getConstructors().isEmpty() && - input.getSuperClass().isPresent() && - haveAPublicConstructor().apply(input.getSuperClass().get()); + input.getRawSuperclass().isPresent() && + haveAPublicConstructor().apply(input.getRawSuperclass().get()); } }; } @@ -236,8 +236,8 @@ public boolean apply(JavaClass input) { } private static DescribedPredicate withoutAPIMarking() { - return not(annotatedWith(PublicAPI.class)).forSubType() - .and(not(annotatedWith(Internal.class)).forSubType()) + return not(annotatedWith(PublicAPI.class)).forSubtype() + .and(not(annotatedWith(Internal.class)).forSubtype()) .and(declaredIn(modifier(PUBLIC))) .as("without API marking"); } diff --git a/archunit-integration-test/src/test/java/com/tngtech/archunit/integration/ExamplesIntegrationTest.java b/archunit-integration-test/src/test/java/com/tngtech/archunit/integration/ExamplesIntegrationTest.java index 797252a007..735e9d4675 100644 --- a/archunit-integration-test/src/test/java/com/tngtech/archunit/integration/ExamplesIntegrationTest.java +++ b/archunit-integration-test/src/test/java/com/tngtech/archunit/integration/ExamplesIntegrationTest.java @@ -108,7 +108,7 @@ import com.tngtech.archunit.example.layers.service.impl.WronglyNamedSvc; import com.tngtech.archunit.example.layers.thirdparty.ThirdPartyClassWithProblem; import com.tngtech.archunit.example.layers.thirdparty.ThirdPartyClassWorkaroundFactory; -import com.tngtech.archunit.example.layers.thirdparty.ThirdPartySubClassWithProblem; +import com.tngtech.archunit.example.layers.thirdparty.ThirdPartySubclassWithProblem; import com.tngtech.archunit.example.layers.web.AnnotatedController; import com.tngtech.archunit.example.layers.web.InheritedControllerImpl; import com.tngtech.archunit.example.onionarchitecture.adapter.cli.AdministrationCLI; @@ -1370,8 +1370,8 @@ Stream ThirdPartyRulesTest() { .by(callFromMethod(ClassViolatingThirdPartyRules.class, "illegallyInstantiateThirdPartyClass") .toConstructor(ThirdPartyClassWithProblem.class) .inLine(9)) - .by(callFromMethod(ClassViolatingThirdPartyRules.class, "illegallyInstantiateThirdPartySubClass") - .toConstructor(ThirdPartySubClassWithProblem.class) + .by(callFromMethod(ClassViolatingThirdPartyRules.class, "illegallyInstantiateThirdPartySubclass") + .toConstructor(ThirdPartySubclassWithProblem.class) .inLine(17)) .toDynamicTests(); diff --git a/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedDependency.java b/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedDependency.java index 7a19fce21d..b5a7ae5131 100644 --- a/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedDependency.java +++ b/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedDependency.java @@ -78,9 +78,9 @@ private InheritanceCreator(Class clazz) { this.clazz = clazz; } - public ExpectedDependency extending(Class superClass) { - return new ExpectedDependency(clazz, superClass, - getDependencyPattern(clazz.getName(), "extends", superClass.getName(), 0)); + public ExpectedDependency extending(Class superclass) { + return new ExpectedDependency(clazz, superclass, + getDependencyPattern(clazz.getName(), "extends", superclass.getName(), 0)); } public ExpectedDependency implementing(Class anInterface) { diff --git a/archunit-junit/src/main/java/com/tngtech/archunit/junit/ReflectionUtils.java b/archunit-junit/src/main/java/com/tngtech/archunit/junit/ReflectionUtils.java index 828789ad76..ec20792280 100644 --- a/archunit-junit/src/main/java/com/tngtech/archunit/junit/ReflectionUtils.java +++ b/archunit-junit/src/main/java/com/tngtech/archunit/junit/ReflectionUtils.java @@ -38,16 +38,16 @@ class ReflectionUtils { private ReflectionUtils() { } - static Set> getAllSuperTypes(Class type) { + static Set> getAllSupertypes(Class type) { if (type == null) { return Collections.emptySet(); } ImmutableSet.Builder> result = ImmutableSet.>builder() .add(type) - .addAll(getAllSuperTypes(type.getSuperclass())); + .addAll(getAllSupertypes(type.getSuperclass())); for (Class c : type.getInterfaces()) { - result.addAll(getAllSuperTypes(c)); + result.addAll(getAllSupertypes(c)); } return result.build(); } @@ -71,7 +71,7 @@ protected Collection extractFrom(Class type) { } private static List getAll(Class type, Collector collector) { - for (Class t : getAllSuperTypes(type)) { + for (Class t : getAllSupertypes(type)) { collector.collectFrom(t); } return collector.collected; diff --git a/archunit-junit/src/test/java/com/tngtech/archunit/junit/ReflectionUtilsTest.java b/archunit-junit/src/test/java/com/tngtech/archunit/junit/ReflectionUtilsTest.java index bb540c38fe..0772fb69ed 100644 --- a/archunit-junit/src/test/java/com/tngtech/archunit/junit/ReflectionUtilsTest.java +++ b/archunit-junit/src/test/java/com/tngtech/archunit/junit/ReflectionUtilsTest.java @@ -39,7 +39,7 @@ public void getAllMethods() { @Test public void getAllSupertypes() { - assertThat(ReflectionUtils.getAllSuperTypes(Child.class)).containsOnly( + assertThat(ReflectionUtils.getAllSupertypes(Child.class)).containsOnly( Child.class, ChildInterface.class, UpperMiddle.class, LowerMiddle.class, Parent.class, SomeInterface.class, OtherInterface.class, Object.class ); @@ -47,7 +47,7 @@ public void getAllSupertypes() { @Test public void getAllMethods_of_interface() { - assertThat(ReflectionUtils.getAllMethods(SubInterface.class, always(true))) + assertThat(ReflectionUtils.getAllMethods(Subinterface.class, always(true))) .containsOnly( method(SomeInterface.class, "foo"), method(OtherInterface.class, "bar")); @@ -64,7 +64,7 @@ public boolean apply(T input) { @Test public void getAllFields_of_interface() { - assertThat(ReflectionUtils.getAllFields(SubInterface.class, always(true))) + assertThat(ReflectionUtils.getAllFields(Subinterface.class, always(true))) .containsOnly( field(SomeInterface.class, "SOME_CONSTANT"), field(OtherInterface.class, "OTHER_CONSTANT")); @@ -162,6 +162,6 @@ private interface OtherInterface { void bar(); } - private interface SubInterface extends SomeInterface, OtherInterface { + private interface Subinterface extends SomeInterface, OtherInterface { } -} \ No newline at end of file +} diff --git a/archunit/src/main/java/com/tngtech/archunit/base/DescribedPredicate.java b/archunit/src/main/java/com/tngtech/archunit/base/DescribedPredicate.java index a8139caac4..0e66297c6e 100644 --- a/archunit/src/main/java/com/tngtech/archunit/base/DescribedPredicate.java +++ b/archunit/src/main/java/com/tngtech/archunit/base/DescribedPredicate.java @@ -60,10 +60,18 @@ public DescribedPredicate onResultOf(final Function} Can't specify this contravariant type at the language level */ @SuppressWarnings("unchecked") // DescribedPredicate is contravariant - public DescribedPredicate forSubType() { + public final DescribedPredicate forSubtype() { return (DescribedPredicate) this; } + /** + * @deprecated Use {@link #forSubtype()} instead. + */ + @Deprecated + public final DescribedPredicate forSubType() { + return forSubtype(); + } + @Override public String toString() { return getDescription(); @@ -114,15 +122,15 @@ public static > DescribedPredicate greaterThanOrEqual } public static DescribedPredicate describe(String description, Predicate predicate) { - return new DescribePredicate<>(description, predicate).forSubType(); + return new DescribePredicate<>(description, predicate).forSubtype(); } public static DescribedPredicate doesNot(final DescribedPredicate predicate) { - return not(predicate).as("does not %s", predicate.getDescription()).forSubType(); + return not(predicate).as("does not %s", predicate.getDescription()).forSubtype(); } public static DescribedPredicate doNot(final DescribedPredicate predicate) { - return not(predicate).as("do not %s", predicate.getDescription()).forSubType(); + return not(predicate).as("do not %s", predicate.getDescription()).forSubtype(); } public static DescribedPredicate not(final DescribedPredicate predicate) { @@ -208,7 +216,7 @@ private static class NotPredicate extends DescribedPredicate { NotPredicate(DescribedPredicate predicate) { super("not " + predicate.getDescription()); - this.predicate = checkNotNull(predicate).forSubType(); + this.predicate = checkNotNull(predicate).forSubtype(); } @Override @@ -317,7 +325,7 @@ private static class AnyElementPredicate extends DescribedPredicate predicate) { super("any element that " + predicate.getDescription()); - this.predicate = predicate.forSubType(); + this.predicate = predicate.forSubtype(); } @Override @@ -336,7 +344,7 @@ private static class AllElementsPredicate extends DescribedPredicate predicate) { super("all elements " + predicate.getDescription()); - this.predicate = predicate.forSubType(); + this.predicate = predicate.forSubtype(); } @Override diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/AccessTarget.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/AccessTarget.java index 6cef6a01ac..2e87b75b45 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/AccessTarget.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/AccessTarget.java @@ -522,7 +522,7 @@ public static DescribedPredicate declaredIn(String className) { public static DescribedPredicate declaredIn(DescribedPredicate predicate) { return Get.owner().is(predicate) .as("declared in %s", predicate.getDescription()) - .forSubType(); + .forSubtype(); } @PublicAPI(usage = ACCESS) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java index 346bf0029a..ce8e09d0eb 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java @@ -78,23 +78,23 @@ static Set tryCreateFromAccess(JavaAccess access) { return dependencies.build(); } - static Dependency fromInheritance(JavaClass origin, JavaClass targetSuperType) { + static Dependency fromInheritance(JavaClass origin, JavaClass targetSupertype) { String originType = origin.isInterface() ? "Interface" : "Class"; String originDescription = originType + " " + bracketFormat(origin.getName()); - String dependencyType = !origin.isInterface() && targetSuperType.isInterface() ? "implements" : "extends"; + String dependencyType = !origin.isInterface() && targetSupertype.isInterface() ? "implements" : "extends"; - String targetType = targetSuperType.isInterface() ? "interface" : "class"; - String targetDescription = bracketFormat(targetSuperType.getName()); + String targetType = targetSupertype.isInterface() ? "interface" : "class"; + String targetDescription = bracketFormat(targetSupertype.getName()); String dependencyDescription = originDescription + " " + dependencyType + " " + targetType + " " + targetDescription; String description = dependencyDescription + " in " + origin.getSourceCodeLocation(); - Optional result = tryCreateDependency(origin, targetSuperType, description, 0); + Optional result = tryCreateDependency(origin, targetSupertype, description, 0); if (!result.isPresent()) { throw new IllegalStateException(String.format("Tried to create illegal inheritance dependency '%s' (%s -> %s), this is likely a bug!", - description, origin.getSimpleName(), targetSuperType.getSimpleName())); + description, origin.getSimpleName(), targetSupertype.getSimpleName())); } return result.get(); } 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 c4ec07c65e..3f123246e4 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 @@ -24,7 +24,7 @@ @Internal public interface ImportContext { - Optional createSuperClass(JavaClass owner); + Optional createSuperclass(JavaClass owner); Set createInterfaces(JavaClass owner); 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 4a0d7dd55a..c80aa3b569 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 @@ -80,14 +80,14 @@ public class JavaClass implements JavaType, HasName.AndFullName, HasAnnotations< private Set members = emptySet(); private Set constructors = emptySet(); private Optional staticInitializer = Optional.absent(); - private Optional superClass = Optional.absent(); - private final Supplier> allSuperClasses = Suppliers.memoize(new Supplier>() { + private Optional superclass = Optional.absent(); + private final Supplier> allRawSuperclasses = Suppliers.memoize(new Supplier>() { @Override public List get() { ImmutableList.Builder result = ImmutableList.builder(); JavaClass current = JavaClass.this; - while (current.getSuperClass().isPresent()) { - current = current.getSuperClass().get(); + while (current.getRawSuperclass().isPresent()) { + current = current.getRawSuperclass().get(); result.add(current); } return result.build(); @@ -102,8 +102,8 @@ public Set get() { result.add(i); result.addAll(i.getAllInterfaces()); } - if (superClass.isPresent()) { - result.addAll(superClass.get().getAllInterfaces()); + if (superclass.isPresent()) { + result.addAll(superclass.get().getAllInterfaces()); } return result.build(); } @@ -113,18 +113,18 @@ public Set get() { public List get() { ImmutableList.Builder result = ImmutableList.builder(); result.add(JavaClass.this); - result.addAll(getAllSuperClasses()); + result.addAll(getAllRawSuperclasses()); return result.build(); } }); - private final Set subClasses = new HashSet<>(); - private final Supplier> allSubClasses = Suppliers.memoize(new Supplier>() { + private final Set subclasses = new HashSet<>(); + private final Supplier> allSubclasses = Suppliers.memoize(new Supplier>() { @Override public Set get() { Set result = new HashSet<>(); - for (JavaClass subClass : subClasses) { - result.add(subClass); - result.addAll(subClass.getAllSubClasses()); + for (JavaClass subclass : subclasses) { + result.add(subclass); + result.addAll(subclass.getAllSubclasses()); } return result; } @@ -655,13 +655,22 @@ public JavaClass toErasure() { return this; } + @PublicAPI(usage = ACCESS) + public Optional getRawSuperclass() { + return superclass; + } + + /** + * @deprecated Use {@link #getRawSuperclass()} instead + */ + @Deprecated @PublicAPI(usage = ACCESS) public Optional getSuperClass() { - return superClass; + return getRawSuperclass(); } /** - * @return The complete class hierarchy, i.e. the class itself and the result of {@link #getAllSuperClasses()} + * @return The complete class hierarchy, i.e. the class itself and the result of {@link #getAllRawSuperclasses()} */ @PublicAPI(usage = ACCESS) public List getClassHierarchy() { @@ -673,13 +682,31 @@ public List getClassHierarchy() { * then the super class of the super class and so on. Includes Object.class in the result. */ @PublicAPI(usage = ACCESS) + public List getAllRawSuperclasses() { + return allRawSuperclasses.get(); + } + + /** + * @deprecated Use {@link #getAllRawSuperclasses()} instead. + */ + @Deprecated + @PublicAPI(usage = ACCESS) public List getAllSuperClasses() { - return allSuperClasses.get(); + return getAllRawSuperclasses(); } + @PublicAPI(usage = ACCESS) + public Set getSubclasses() { + return subclasses; + } + + /** + * @deprecated Use {@link #getSubclasses()} instead. + */ + @Deprecated @PublicAPI(usage = ACCESS) public Set getSubClasses() { - return subClasses; + return getSubclasses(); } @PublicAPI(usage = ACCESS) @@ -704,7 +731,7 @@ public Set getAllInterfaces() { public Set getAllClassesSelfIsAssignableTo() { return ImmutableSet.builder() .add(this) - .addAll(getAllSuperClasses()) + .addAll(getAllRawSuperclasses()) .addAll(getAllInterfaces()) .build(); } @@ -714,9 +741,18 @@ public Optional getEnclosingClass() { return enclosingClass; } + @PublicAPI(usage = ACCESS) + public Set getAllSubclasses() { + return allSubclasses.get(); + } + + /** + * @deprecated Use {@link #getAllSubclasses()} instead. + */ + @Deprecated @PublicAPI(usage = ACCESS) public Set getAllSubClasses() { - return allSubClasses.get(); + return getAllSubclasses(); } @PublicAPI(usage = ACCESS) @@ -1194,7 +1230,7 @@ public boolean isAssignableFrom(String typeName) { @PublicAPI(usage = ACCESS) public boolean isAssignableFrom(DescribedPredicate predicate) { List possibleTargets = ImmutableList.builder() - .add(this).addAll(getAllSubClasses()).build(); + .add(this).addAll(getAllSubclasses()).build(); return anyMatches(possibleTargets, predicate); } @@ -1240,7 +1276,7 @@ public Class reflect() { } void completeClassHierarchyFrom(ImportContext context) { - completeSuperClassFrom(context); + completeSuperclassFrom(context); completeInterfacesFrom(context); allFields = Suppliers.memoize(new Supplier>() { @Override @@ -1274,17 +1310,17 @@ public Set get() { }); } - private void completeSuperClassFrom(ImportContext context) { - superClass = context.createSuperClass(this); - if (superClass.isPresent()) { - superClass.get().subClasses.add(this); + private void completeSuperclassFrom(ImportContext context) { + superclass = context.createSuperclass(this); + if (superclass.isPresent()) { + superclass.get().subclasses.add(this); } } private void completeInterfacesFrom(ImportContext context) { interfaces.addAll(context.createInterfaces(this)); for (JavaClass i : interfaces) { - i.subClasses.add(this); + i.subclasses.add(this); } } @@ -1663,7 +1699,7 @@ public static DescribedPredicate implement(final String typeName) { @PublicAPI(usage = ACCESS) public static DescribedPredicate implement(final DescribedPredicate predicate) { DescribedPredicate selfIsImplementation = not(INTERFACES); - DescribedPredicate interfacePredicate = predicate.forSubType().and(INTERFACES); + DescribedPredicate interfacePredicate = predicate.forSubtype().and(INTERFACES); return selfIsImplementation.and(assignableTo(interfacePredicate)) .as("implement " + predicate.getDescription()); } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassDependencies.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassDependencies.java index 9e24e2e197..7d79e8afbd 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassDependencies.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassDependencies.java @@ -70,8 +70,8 @@ private Set dependenciesFromAccesses(Set> accesses) { private Set inheritanceDependenciesFromSelf() { ImmutableSet.Builder result = ImmutableSet.builder(); - for (JavaClass superType : FluentIterable.from(javaClass.getInterfaces()).append(javaClass.getSuperClass().asSet())) { - result.add(Dependency.fromInheritance(javaClass, superType)); + for (JavaClass supertype : FluentIterable.from(javaClass.getInterfaces()).append(javaClass.getRawSuperclass().asSet())) { + result.add(Dependency.fromInheritance(javaClass, supertype)); } return result.build(); } 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 7164cb4ccd..b3bb27eda6 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 @@ -215,7 +215,7 @@ public static DescribedPredicate declaredIn(String className) { public static DescribedPredicate declaredIn(DescribedPredicate predicate) { return Get.owner().is(predicate) .as("declared in %s", predicate.getDescription()) - .forSubType(); + .forSubtype(); } } } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaPackage.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaPackage.java index e8c449b8a7..3fbff1e921 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaPackage.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaPackage.java @@ -56,15 +56,15 @@ public final class JavaPackage implements HasName, HasAnnotations { private final String relativeName; private final Set classes; private final Optional packageInfo; - private final Map subPackages; + private final Map subpackages; private Optional parent = Optional.absent(); - private JavaPackage(String name, Set classes, Map subPackages) { + private JavaPackage(String name, Set classes, Map subpackages) { this.name = checkNotNull(name); relativeName = name.substring(name.lastIndexOf(".") + 1); this.classes = ImmutableSet.copyOf(classes); this.packageInfo = tryGetClassWithSimpleName("package-info"); - this.subPackages = ImmutableMap.copyOf(subPackages); + this.subpackages = ImmutableMap.copyOf(subpackages); } /** @@ -221,36 +221,52 @@ public Set getClasses() { @PublicAPI(usage = ACCESS) public Set getAllClasses() { ImmutableSet.Builder result = ImmutableSet.builder().addAll(classes); - for (JavaPackage subPackage : getSubPackages()) { - result.addAll(subPackage.getAllClasses()); + for (JavaPackage subpackage : getSubpackages()) { + result.addAll(subpackage.getAllClasses()); } return result.build(); } /** * @return all (direct) sub-packages contained in this package, e.g. {@code [java.lang, java.io, ...]} for package {@code java} - * (compare {@link #getAllSubPackages()}) + * (compare {@link #getAllSubpackages()}) + */ + @PublicAPI(usage = ACCESS) + public Set getSubpackages() { + return ImmutableSet.copyOf(subpackages.values()); + } + + /** + * @deprecated Use {@link #getSubpackages()} instead. */ @PublicAPI(usage = ACCESS) public Set getSubPackages() { - return ImmutableSet.copyOf(subPackages.values()); + return getSubpackages(); } /** * @return all sub-packages including nested sub-packages contained in this package, * e.g. {@code [java.lang, java.lang.annotation, java.util, java.util.concurrent, ...]} for package {@code java} - * (compare {@link #getSubPackages()}) + * (compare {@link #getSubpackages()}) */ @PublicAPI(usage = ACCESS) - public Set getAllSubPackages() { + public Set getAllSubpackages() { ImmutableSet.Builder result = ImmutableSet.builder(); - for (JavaPackage subPackage : getSubPackages()) { - result.add(subPackage); - result.addAll(subPackage.getAllSubPackages()); + for (JavaPackage subpackage : getSubpackages()) { + result.add(subpackage); + result.addAll(subpackage.getAllSubpackages()); } return result.build(); } + /** + * @deprecated Use {@link #getAllSubpackages()} instead. + */ + @PublicAPI(usage = ACCESS) + public Set getAllSubPackages() { + return getAllSubpackages(); + } + /** * @param clazz a {@link JavaClass} * @return true if this package (directly) contains this {@link JavaClass} @@ -388,10 +404,10 @@ private Optional tryGetPackage(JavaPackage currentPackage, Deque predicate, ClassVisitor visitor) for (JavaClass javaClass : getClassesWith(predicate)) { visitor.visit(javaClass); } - for (JavaPackage subPackage : getSubPackages()) { - subPackage.accept(predicate, visitor); + for (JavaPackage subpackage : getSubpackages()) { + subpackage.accept(predicate, visitor); } } @@ -487,8 +503,8 @@ public void accept(Predicate predicate, PackageVisitor visi if (predicate.apply(this)) { visitor.visit(this); } - for (JavaPackage subPackage : getSubPackages()) { - subPackage.accept(predicate, visitor); + for (JavaPackage subpackage : getSubpackages()) { + subpackage.accept(predicate, visitor); } } @@ -522,7 +538,7 @@ static JavaPackage from(Iterable classes) { private static class Tree { private final String packageName; - private final Map subPackageTrees; + private final Map subpackageTrees; private final Set classes = new HashSet<>(); Tree(Iterable classes) { @@ -537,14 +553,14 @@ private Tree(String packageName, Iterable classes) { if (clazz.getPackageName().equals(packageName)) { this.classes.add(clazz); } else { - String subPackageName = findSubPackageName(packageName, clazz); - childPackages.put(subPackageName, clazz); + String subpackageName = findSubpackageName(packageName, clazz); + childPackages.put(subpackageName, clazz); } } - this.subPackageTrees = createSubTrees(packageName, childPackages); + this.subpackageTrees = createSubTrees(packageName, childPackages); } - private String findSubPackageName(String packageName, JavaClass clazz) { + private String findSubpackageName(String packageName, JavaClass clazz) { String packageRest = !packageName.isEmpty() ? clazz.getPackageName().substring(packageName.length() + 1) : clazz.getPackageName(); @@ -567,18 +583,18 @@ private String joinSkippingEmpty(String first, String second) { JavaPackage toJavaPackage() { JavaPackage result = createJavaPackage(); - for (JavaPackage subPackage : result.getSubPackages()) { - subPackage.setParent(result); + for (JavaPackage subpackage : result.getSubpackages()) { + subpackage.setParent(result); } return result; } private JavaPackage createJavaPackage() { - ImmutableMap.Builder subPackages = ImmutableMap.builder(); - for (Map.Entry entry : subPackageTrees.entrySet()) { - subPackages.put(entry.getKey(), entry.getValue().toJavaPackage()); + ImmutableMap.Builder subpackages = ImmutableMap.builder(); + for (Map.Entry entry : subpackageTrees.entrySet()) { + subpackages.put(entry.getKey(), entry.getValue().toJavaPackage()); } - return new JavaPackage(packageName, classes, subPackages.build()); + return new JavaPackage(packageName, classes, subpackages.build()); } } @@ -619,7 +635,7 @@ public Set apply(JavaPackage javaPackage) { new ChainableFunction>() { @Override public Set apply(JavaPackage javaPackage) { - return javaPackage.getSubPackages(); + return javaPackage.getSubpackages(); } }; } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/ReverseDependencies.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/ReverseDependencies.java index d0135c96ba..a88fc1b898 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/ReverseDependencies.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/ReverseDependencies.java @@ -272,7 +272,7 @@ public Set load(MEMBER member) { private Set getPossibleTargetClassesForAccess(JavaClass owner) { return ImmutableSet.builder() .add(owner) - .addAll(owner.getAllSubClasses()) + .addAll(owner.getAllSubclasses()) .build(); } } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasThrowsClause.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasThrowsClause.java index 771566db89..ca74114463 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasThrowsClause.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasThrowsClause.java @@ -70,7 +70,7 @@ public static DescribedPredicate> throwsClauseContainingType( @PublicAPI(usage = ACCESS) public static DescribedPredicate> throwsClauseContainingType(DescribedPredicate predicate) { - DescribedPredicate> declarationPredicate = GET_RAW_TYPE.is(predicate).forSubType(); + DescribedPredicate> declarationPredicate = GET_RAW_TYPE.is(predicate).forSubtype(); return throwsClause(anyElementThat(declarationPredicate)).as("throws clause containing type " + predicate.getDescription()); } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/AccessRecord.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/AccessRecord.java index f372a776d9..8a0dc24e99 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/AccessRecord.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/AccessRecord.java @@ -356,7 +356,7 @@ public ClassHierarchyPath(JavaClassDescriptor childType, JavaClass parent) { } private Optional tryFindChildInHierarchy(JavaClassDescriptor childType, JavaClass parent) { - for (JavaClass subclass : parent.getAllSubClasses()) { + for (JavaClass subclass : parent.getAllSubclasses()) { if (subclass.getName().equals(childType.getFullyQualifiedClassName())) { return Optional.of(subclass); } @@ -413,12 +413,12 @@ private ClassHierarchyResolutionStrategy(JavaClass child, JavaClass parent) { @Override public boolean hasNext() { - return !current.equals(parent) && current.getSuperClass().isPresent(); + return !current.equals(parent) && current.getRawSuperclass().isPresent(); } @Override public JavaClass next() { - current = current.getSuperClass().get(); + current = current.getRawSuperclass().get(); return current; } } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java index 914062061f..9d19ab6c86 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java @@ -45,7 +45,7 @@ class ClassFileImportRecord { private final Map classes = new HashMap<>(); - private final Map superClassNamesByOwner = new HashMap<>(); + private final Map superclassNamesByOwner = new HashMap<>(); private final SetMultimap interfaceNamesByOwner = HashMultimap.create(); private final Map typeParametersBuilderByOwner = new HashMap<>(); private final SetMultimap fieldBuildersByOwner = HashMultimap.create(); @@ -60,11 +60,11 @@ class ClassFileImportRecord { private final Set rawMethodCallRecords = new HashSet<>(); private final Set rawConstructorCallRecords = new HashSet<>(); - void setSuperClass(String ownerName, String superClassName) { - checkState(!superClassNamesByOwner.containsKey(ownerName), + void setSuperclass(String ownerName, String superclassName) { + checkState(!superclassNamesByOwner.containsKey(ownerName), "Attempted to add %s as a second superclass to %s, this is most likely a bug", - superClassName, ownerName); - superClassNamesByOwner.put(ownerName, superClassName); + superclassName, ownerName); + superclassNamesByOwner.put(ownerName, superclassName); } void addInterfaces(String ownerName, Set interfaceNames) { @@ -110,8 +110,8 @@ void setEnclosingClass(String ownerName, String enclosingClassName) { enclosingClassNamesByOwner.register(ownerName, enclosingClassName); } - Optional getSuperClassFor(String name) { - return Optional.fromNullable(superClassNamesByOwner.get(name)); + Optional getSuperclassFor(String name) { + return Optional.fromNullable(superclassNamesByOwner.get(name)); } Set getInterfaceNamesFor(String ownerName) { @@ -229,11 +229,11 @@ Set getAccessRecords() { .build(); } - Set getAllSuperClassNames() { - return ImmutableSet.copyOf(superClassNamesByOwner.values()); + Set getAllSuperclassNames() { + return ImmutableSet.copyOf(superclassNamesByOwner.values()); } - Set getAllSuperInterfaceNames() { + Set getAllSuperinterfaceNames() { return ImmutableSet.copyOf(interfaceNamesByOwner.values()); } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileProcessor.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileProcessor.java index 8b8d9ec0d6..32082311ce 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileProcessor.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileProcessor.java @@ -77,10 +77,10 @@ public boolean isNew(String className) { } @Override - public void onNewClass(String className, Optional superClassName, Set interfaceNames) { + public void onNewClass(String className, Optional superclassName, Set interfaceNames) { ownerName = className; - if (superClassName.isPresent()) { - importRecord.setSuperClass(ownerName, superClassName.get()); + if (superclassName.isPresent()) { + importRecord.setSuperclass(ownerName, superclassName.get()); } importRecord.addInterfaces(ownerName, interfaceNames); } 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 68cf36cf4e..a0a2297ea3 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 @@ -68,21 +68,21 @@ class ClassGraphCreator implements ImportContext { private final SetMultimap processedFieldAccessRecords = HashMultimap.create(); private final SetMultimap> processedMethodCallRecords = HashMultimap.create(); private final SetMultimap> processedConstructorCallRecords = HashMultimap.create(); - private final Function> superClassStrategy; + private final Function> superclassStrategy; private final Function> interfaceStrategy; ClassGraphCreator(ClassFileImportRecord importRecord, ClassResolver classResolver) { this.importRecord = importRecord; classes = new ImportedClasses(importRecord.getClasses(), classResolver); - superClassStrategy = createSuperClassStrategy(); + superclassStrategy = createSuperclassStrategy(); interfaceStrategy = createInterfaceStrategy(); } - private Function> createSuperClassStrategy() { + private Function> createSuperclassStrategy() { return new Function>() { @Override public Set apply(JavaClass input) { - return importRecord.getSuperClassFor(input.getName()).asSet(); + return importRecord.getSuperclassFor(input.getName()).asSet(); } }; } @@ -112,12 +112,12 @@ private void ensureCallTargetsArePresent() { } private void ensureClassesOfInheritanceHierarchiesArePresent() { - for (String superClassName : importRecord.getAllSuperClassNames()) { - resolveInheritance(superClassName, superClassStrategy); + for (String superclassName : importRecord.getAllSuperclassNames()) { + resolveInheritance(superclassName, superclassStrategy); } - for (String superInterfaceName : importRecord.getAllSuperInterfaceNames()) { - resolveInheritance(superInterfaceName, interfaceStrategy); + for (String superinterfaceName : importRecord.getAllSuperinterfaceNames()) { + resolveInheritance(superinterfaceName, interfaceStrategy); } } @@ -220,10 +220,10 @@ B accessBuilderFrom(B builder, AccessRecord record) { } @Override - public Optional createSuperClass(JavaClass owner) { - Optional superClassName = importRecord.getSuperClassFor(owner.getName()); - return superClassName.isPresent() ? - Optional.of(classes.getOrResolve(superClassName.get())) : + public Optional createSuperclass(JavaClass owner) { + Optional superclassName = importRecord.getSuperclassFor(owner.getName()); + return superclassName.isPresent() ? + Optional.of(classes.getOrResolve(superclassName.get())) : Optional.absent(); } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java index f01f3c4083..ea5e973e90 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java @@ -101,8 +101,8 @@ public void visit(int version, int access, String name, String signature, String boolean opCodeForInterfaceIsPresent = (access & Opcodes.ACC_INTERFACE) != 0; boolean opCodeForEnumIsPresent = (access & Opcodes.ACC_ENUM) != 0; boolean opCodeForAnnotationIsPresent = (access & Opcodes.ACC_ANNOTATION) != 0; - Optional superClassName = getSuperClassName(superName, opCodeForInterfaceIsPresent); - LOG.trace("Found superclass {} on class '{}'", superClassName.orNull(), name); + Optional superclassName = getSuperclassName(superName, opCodeForInterfaceIsPresent); + LOG.trace("Found superclass {} on class '{}'", superclassName.orNull(), name); javaClassBuilder = new DomainBuilders.JavaClassBuilder() .withSourceDescriptor(sourceDescriptor) @@ -113,7 +113,7 @@ public void visit(int version, int access, String name, String signature, String .withModifiers(JavaModifier.getModifiersForClass(access)); className = descriptor.getFullyQualifiedClassName(); - declarationHandler.onNewClass(className, superClassName, interfaceNames); + declarationHandler.onNewClass(className, superclassName, interfaceNames); JavaGenericTypeImporter.parseAsmTypeSignature(signature, declarationHandler); } @@ -122,8 +122,8 @@ private boolean alreadyImported(JavaClassDescriptor descriptor) { } // NOTE: For some reason ASM claims superName == java/lang/Object for Interfaces??? - // This is inconsistent with the behavior of Class.getSuperClass() - private Optional getSuperClassName(String superName, boolean isInterface) { + // This is inconsistent with the behavior of Class.getSuperclass() + private Optional getSuperclassName(String superName, boolean isInterface) { return superName != null && !isInterface ? Optional.of(createTypeName(superName)) : Optional.absent(); @@ -424,7 +424,7 @@ public void setArrayResult(ValueBuilder valueBuilder) { interface DeclarationHandler { boolean isNew(String className); - void onNewClass(String className, Optional superClassName, Set interfaceNames); + void onNewClass(String className, Optional superclassName, Set interfaceNames); void onDeclaredTypeParameters(DomainBuilders.TypeParametersBuilder typeParametersBuilder); diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/ArchCondition.java b/archunit/src/main/java/com/tngtech/archunit/lang/ArchCondition.java index 45fb6c06b7..4255518cf6 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/ArchCondition.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/ArchCondition.java @@ -59,11 +59,11 @@ public void finish(ConditionEvents events) { } public ArchCondition and(ArchCondition condition) { - return new AndCondition<>(this, condition.forSubType()); + return new AndCondition<>(this, condition.forSubtype()); } public ArchCondition or(ArchCondition condition) { - return new OrCondition<>(this, condition.forSubType()); + return new OrCondition<>(this, condition.forSubtype()); } public String getDescription() { @@ -95,10 +95,18 @@ public String toString() { } @SuppressWarnings("unchecked") // Cast is safe since input parameter is contravariant - public ArchCondition forSubType() { + public ArchCondition forSubtype() { return (ArchCondition) this; } + /** + * @deprecated Use {@link #forSubtype()} instead. + */ + @Deprecated + public ArchCondition forSubType() { + return forSubtype(); + } + private abstract static class JoinCondition extends ArchCondition { private final Collection> conditions; diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchConditions.java b/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchConditions.java index c6d9682255..6ed6e00983 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchConditions.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchConditions.java @@ -173,7 +173,7 @@ public static ArchCondition accessFieldWhere(DescribedPredicate onlyAccessFieldsThat(final DescribedPredicate predicate) { ChainableFunction getTarget = JavaAccess.Functions.Get.target(); DescribedPredicate accessPredicate = getTarget.then(FieldAccessTarget.Functions.RESOLVE) - .is(anyElementThat(predicate.forSubType()).or(empty())); + .is(anyElementThat(predicate.forSubtype()).or(empty())); return new ClassOnlyAccessesCondition<>(accessPredicate, GET_FIELD_ACCESSES_FROM_SELF) .as("only access fields that " + predicate.getDescription()); } @@ -206,7 +206,7 @@ public static ArchCondition callMethodWhere(final DescribedPredicate< public static ArchCondition onlyCallMethodsThat(final DescribedPredicate predicate) { ChainableFunction getTarget = JavaAccess.Functions.Get.target(); DescribedPredicate callPredicate = getTarget.then(MethodCallTarget.Functions.RESOLVE) - .is(anyElementThat(predicate.forSubType()).or(empty())); + .is(anyElementThat(predicate.forSubtype()).or(empty())); return new ClassOnlyAccessesCondition<>(callPredicate, GET_METHOD_CALLS_FROM_SELF) .as("only call methods that " + predicate.getDescription()); } @@ -239,7 +239,7 @@ public static ArchCondition callConstructorWhere(final DescribedPredi public static ArchCondition onlyCallConstructorsThat(final DescribedPredicate predicate) { ChainableFunction getTarget = JavaAccess.Functions.Get.target(); DescribedPredicate callPredicate = getTarget.then(ConstructorCallTarget.Functions.RESOLVE) - .is(anyElementThat(predicate.forSubType()).or(empty())); + .is(anyElementThat(predicate.forSubtype()).or(empty())); return new ClassOnlyAccessesCondition<>(callPredicate, GET_CONSTRUCTOR_CALLS_FROM_SELF) .as("only call constructors that " + predicate.getDescription()); } @@ -254,7 +254,7 @@ public static ArchCondition callCodeUnitWhere(DescribedPredicate onlyCallCodeUnitsThat(final DescribedPredicate predicate) { ChainableFunction, CodeUnitCallTarget> getTarget = JavaAccess.Functions.Get.target(); DescribedPredicate> callPredicate = getTarget.then(CodeUnitCallTarget.Functions.RESOLVE) - .is(anyElementThat(predicate.forSubType()).or(empty())); + .is(anyElementThat(predicate.forSubtype()).or(empty())); return new ClassOnlyAccessesCondition<>(callPredicate, GET_CALLS_FROM_SELF) .as("only call code units that " + predicate.getDescription()); } @@ -263,7 +263,7 @@ public static ArchCondition onlyCallCodeUnitsThat(final DescribedPred public static ArchCondition onlyAccessMembersThat(final DescribedPredicate predicate) { ChainableFunction, AccessTarget> getTarget = JavaAccess.Functions.Get.target(); DescribedPredicate> accessPredicate = getTarget.then(AccessTarget.Functions.RESOLVE) - .is(anyElementThat(predicate.forSubType()).or(empty())); + .is(anyElementThat(predicate.forSubtype()).or(empty())); return new ClassOnlyAccessesCondition<>(accessPredicate, GET_ACCESSES_FROM_SELF) .as("only access members that " + predicate.getDescription()); } @@ -534,7 +534,7 @@ public static ArchCondition haveSimpleNameNotEndingWith(String suffix @PublicAPI(usage = ACCESS) public static ArchCondition haveNameMatching(final String regex) { - final DescribedPredicate haveNameMatching = have(nameMatching(regex)).forSubType(); + final DescribedPredicate haveNameMatching = have(nameMatching(regex)).forSubtype(); return new MatchingCondition<>(haveNameMatching, regex); } @@ -546,7 +546,7 @@ public static ArchCondition haveFullNameMatching(String regex) { - final DescribedPredicate haveFullNameMatching = have(fullNameMatching(regex)).forSubType(); + final DescribedPredicate haveFullNameMatching = have(fullNameMatching(regex)).forSubtype(); return new MatchingCondition<>(haveFullNameMatching, regex); } @@ -559,42 +559,42 @@ ArchCondition haveFullNameMatching(String regex) { @PublicAPI(usage = ACCESS) public static ArchCondition haveNameStartingWith(String prefix) { - final DescribedPredicate haveNameStartingWith = have(nameStartingWith(prefix)).forSubType(); + final DescribedPredicate haveNameStartingWith = have(nameStartingWith(prefix)).forSubtype(); return new StartingCondition<>(haveNameStartingWith, prefix); } @PublicAPI(usage = ACCESS) public static ArchCondition haveNameNotStartingWith(String prefix) { - final DescribedPredicate haveNameStartingWith = have(nameStartingWith(prefix)).forSubType(); + final DescribedPredicate haveNameStartingWith = have(nameStartingWith(prefix)).forSubtype(); return not(new StartingCondition<>(haveNameStartingWith, prefix)).as("have name not starting with '%s'", prefix); } @PublicAPI(usage = ACCESS) public static ArchCondition haveNameContaining(String infix) { - final DescribedPredicate haveNameContaining = have(nameContaining(infix)).forSubType(); + final DescribedPredicate haveNameContaining = have(nameContaining(infix)).forSubtype(); return new ContainingCondition<>(haveNameContaining, infix); } @PublicAPI(usage = ACCESS) public static ArchCondition haveNameNotContaining(String infix) { - final DescribedPredicate haveNameContaining = have(nameContaining(infix)).forSubType(); + final DescribedPredicate haveNameContaining = have(nameContaining(infix)).forSubtype(); return not(new ContainingCondition<>(haveNameContaining, infix)).as("have name not containing '%s'", infix); } @PublicAPI(usage = ACCESS) public static ArchCondition haveNameEndingWith(String suffix) { - final DescribedPredicate haveNameEndingWith = have(nameEndingWith(suffix)).forSubType(); + final DescribedPredicate haveNameEndingWith = have(nameEndingWith(suffix)).forSubtype(); return new EndingCondition<>(haveNameEndingWith, suffix); } @PublicAPI(usage = ACCESS) public static ArchCondition haveNameNotEndingWith(String suffix) { - final DescribedPredicate haveNameEndingWith = have(nameEndingWith(suffix)).forSubType(); + final DescribedPredicate haveNameEndingWith = have(nameEndingWith(suffix)).forSubtype(); return not(new EndingCondition<>(haveNameEndingWith, suffix)).as("have name not ending with '%s'", suffix); } @@ -1145,7 +1145,7 @@ private static class NumberOfElementsCondition extends ArchCondition NumberOfElementsCondition(DescribedPredicate predicate) { super("contain number of elements " + predicate.getDescription()); - this.predicate = predicate.forSubType(); + this.predicate = predicate.forSubtype(); allClassNames = new TreeSet<>(); } @@ -1374,7 +1374,7 @@ private static class IsConditionByPredicate predicate) { super(ArchPredicates.be(predicate).getDescription()); this.eventDescription = eventDescription; - this.predicate = predicate.forSubType(); + this.predicate = predicate.forSubtype(); } @Override @@ -1391,7 +1391,7 @@ private static class HaveConditionByPredicate rawType) { super(ArchPredicates.have(rawType).getDescription()); - this.rawType = rawType.forSubType(); + this.rawType = rawType.forSubtype(); } @Override diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchPredicates.java b/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchPredicates.java index 11c00b3082..871313b646 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchPredicates.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/conditions/ArchPredicates.java @@ -33,7 +33,7 @@ private ArchPredicates() { */ @PublicAPI(usage = ACCESS) public static DescribedPredicate is(DescribedPredicate predicate) { - return predicate.as("is " + predicate.getDescription()).forSubType(); + return predicate.as("is " + predicate.getDescription()).forSubtype(); } /** @@ -45,7 +45,7 @@ public static DescribedPredicate is(DescribedPredicate predica */ @PublicAPI(usage = ACCESS) public static DescribedPredicate are(DescribedPredicate predicate) { - return predicate.as("are " + predicate.getDescription()).forSubType(); + return predicate.as("are " + predicate.getDescription()).forSubtype(); } /** @@ -57,7 +57,7 @@ public static DescribedPredicate are(DescribedPredicate predic */ @PublicAPI(usage = ACCESS) public static DescribedPredicate has(DescribedPredicate predicate) { - return predicate.as("has " + predicate.getDescription()).forSubType(); + return predicate.as("has " + predicate.getDescription()).forSubtype(); } /** @@ -69,7 +69,7 @@ public static DescribedPredicate has(DescribedPredicate predic */ @PublicAPI(usage = ACCESS) public static DescribedPredicate have(DescribedPredicate predicate) { - return predicate.as("have " + predicate.getDescription()).forSubType(); + return predicate.as("have " + predicate.getDescription()).forSubtype(); } /** @@ -81,6 +81,6 @@ public static DescribedPredicate have(DescribedPredicate predi */ @PublicAPI(usage = ACCESS) public static DescribedPredicate be(DescribedPredicate predicate) { - return predicate.as("be " + predicate.getDescription()).forSubType(); + return predicate.as("be " + predicate.getDescription()).forSubtype(); } } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/conditions/FieldAccessCondition.java b/archunit/src/main/java/com/tngtech/archunit/lang/conditions/FieldAccessCondition.java index b4d294907f..a9b1854e23 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/conditions/FieldAccessCondition.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/conditions/FieldAccessCondition.java @@ -41,13 +41,13 @@ public void check(JavaFieldAccess item, ConditionEvents events) { static class FieldGetAccessCondition extends FieldAccessCondition { FieldGetAccessCondition(DescribedPredicate predicate) { - super(predicate.forSubType().and(accessType(GET))); + super(predicate.forSubtype().and(accessType(GET))); } } static class FieldSetAccessCondition extends FieldAccessCondition { FieldSetAccessCondition(DescribedPredicate predicate) { - super(predicate.forSubType().and(accessType(SET))); + super(predicate.forSubtype().and(accessType(SET))); } } } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractGivenCodeUnitsInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractGivenCodeUnitsInternal.java index 1d11b4fa72..fe9e03dd10 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractGivenCodeUnitsInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractGivenCodeUnitsInternal.java @@ -93,7 +93,7 @@ public CodeUnitsShouldInternal should() { @Override public CodeUnitsShouldInternal should(ArchCondition condition) { - return new CodeUnitsShouldInternal(finishedClassesTransformer(), priority, condition.forSubType(), prepareCondition); + return new CodeUnitsShouldInternal(finishedClassesTransformer(), priority, condition.forSubtype(), prepareCondition); } private static class GivenCodeUnitsFactory implements Factory { diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractGivenMembersInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractGivenMembersInternal.java index f8cb219b2a..a169b9d72e 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractGivenMembersInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractGivenMembersInternal.java @@ -90,7 +90,7 @@ private GivenMembersInternal( @Override public MembersShouldConjunction should(ArchCondition condition) { - return new MembersShouldInternal(finishedClassesTransformer(), priority, condition.forSubType(), prepareCondition); + return new MembersShouldInternal(finishedClassesTransformer(), priority, condition.forSubtype(), prepareCondition); } @Override diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractMembersShouldInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractMembersShouldInternal.java index de347f138b..e711302953 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractMembersShouldInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/AbstractMembersShouldInternal.java @@ -295,7 +295,7 @@ public SELF apply(DescribedPredicate predicate) { } private SELF copyWithNewCondition(ArchCondition newCondition) { - return copyWithNewCondition(new ConditionAggregator<>(newCondition.forSubType())); + return copyWithNewCondition(new ConditionAggregator<>(newCondition.forSubtype())); } abstract SELF copyWithNewCondition(ConditionAggregator newCondition); diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenClassInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenClassInternal.java index 0d7e7f355d..baab9b316e 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenClassInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenClassInternal.java @@ -43,6 +43,6 @@ public ClassesShould should() { @Override public ClassesShouldConjunction should(ArchCondition condition) { - return new ClassesShouldInternal(classesTransformer, priority, condition.forSubType(), prepareCondition); + return new ClassesShouldInternal(classesTransformer, priority, condition.forSubtype(), prepareCondition); } } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenClassesInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenClassesInternal.java index 82fbc5dfd5..69604675bf 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenClassesInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenClassesInternal.java @@ -90,7 +90,7 @@ public GivenClassesConjunction apply(DescribedPredicate input @Override public ClassesShouldConjunction should(ArchCondition condition) { - return new ClassesShouldInternal(finishedClassesTransformer(), priority, condition.forSubType(), prepareCondition); + return new ClassesShouldInternal(finishedClassesTransformer(), priority, condition.forSubtype(), prepareCondition); } private static class GivenClassesFactory implements Factory { diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenConstructorsInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenConstructorsInternal.java index 2e2e7c4560..4fc0d526b5 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenConstructorsInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenConstructorsInternal.java @@ -63,7 +63,7 @@ public ConstructorsShouldInternal should() { @Override public ConstructorsShouldInternal should(ArchCondition condition) { - return new ConstructorsShouldInternal(finishedClassesTransformer(), priority, condition.forSubType(), prepareCondition); + return new ConstructorsShouldInternal(finishedClassesTransformer(), priority, condition.forSubtype(), prepareCondition); } private static class GivenConstructorsFactory implements Factory { diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenFieldsInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenFieldsInternal.java index 2efb4b2883..2ad0cfdbd2 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenFieldsInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenFieldsInternal.java @@ -64,7 +64,7 @@ public FieldsShouldInternal should() { @Override public FieldsShouldInternal should(ArchCondition condition) { - return new FieldsShouldInternal(finishedClassesTransformer(), priority, condition.forSubType(), prepareCondition); + return new FieldsShouldInternal(finishedClassesTransformer(), priority, condition.forSubtype(), prepareCondition); } @Override diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenMethodsInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenMethodsInternal.java index 3615e138e9..97af4163b7 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenMethodsInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenMethodsInternal.java @@ -79,7 +79,7 @@ public MethodsShouldInternal should() { @Override public MethodsShouldInternal should(ArchCondition condition) { - return new MethodsShouldInternal(finishedClassesTransformer(), priority, condition.forSubType(), prepareCondition); + return new MethodsShouldInternal(finishedClassesTransformer(), priority, condition.forSubtype(), prepareCondition); } private static class GivenMethodsFactory implements Factory { diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenObjectsInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenObjectsInternal.java index afd85e612b..43af9d840c 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenObjectsInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/GivenObjectsInternal.java @@ -49,7 +49,7 @@ private GivenObjectsInternal( @Override public ArchRule should(ArchCondition condition) { - return new ObjectsShouldInternal<>(finishedClassesTransformer(), priority, condition.forSubType(), prepareCondition); + return new ObjectsShouldInternal<>(finishedClassesTransformer(), priority, condition.forSubtype(), prepareCondition); } private static class GivenObjectsFactory implements AbstractGivenObjects.Factory> { diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/ObjectsShouldInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/ObjectsShouldInternal.java index 22b5d38ac0..705622abbe 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/ObjectsShouldInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/ObjectsShouldInternal.java @@ -152,7 +152,7 @@ static AddMode and(final Function, ArchCondition> pre return new AddMode() { @Override ArchCondition apply(Optional> first, ArchCondition other) { - ArchCondition second = prepareCondition.apply(other.forSubType()); + ArchCondition second = prepareCondition.apply(other.forSubtype()); return first.isPresent() ? first.get().and(second) : second; } }; @@ -162,7 +162,7 @@ static AddMode or(final Function, ArchCondition> prep return new AddMode() { @Override ArchCondition apply(Optional> first, ArchCondition other) { - ArchCondition second = prepareCondition.apply(other.forSubType()); + ArchCondition second = prepareCondition.apply(other.forSubtype()); return first.isPresent() ? first.get().or(second) : second; } }; diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/PredicateAggregator.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/PredicateAggregator.java index ce98b0226d..309750b881 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/PredicateAggregator.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/PredicateAggregator.java @@ -58,7 +58,7 @@ static AddMode and() { return new AddMode() { @Override DescribedPredicate apply(Optional> first, DescribedPredicate other) { - DescribedPredicate second = other.forSubType(); + DescribedPredicate second = other.forSubtype(); return first.isPresent() ? first.get().and(second) : second; } }; @@ -68,7 +68,7 @@ static AddMode or() { return new AddMode() { @Override DescribedPredicate apply(Optional> first, DescribedPredicate other) { - DescribedPredicate second = other.forSubType(); + DescribedPredicate second = other.forSubtype(); return first.isPresent() ? first.get().or(second) : second; } }; diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MembersShould.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MembersShould.java index 01a1b323cb..8d94cb97c1 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MembersShould.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MembersShould.java @@ -440,7 +440,7 @@ public interface MembersShould> *

* E.g. *

-     * {@link ArchRuleDefinition#members() members()}.{@link GivenMembers#should() should()}.{@link MembersShould#beDeclaredInClassesThat(DescribedPredicate) beDeclaredInClassesThat(areSubTypeOf(Example.class))}
+     * {@link ArchRuleDefinition#members() members()}.{@link GivenMembers#should() should()}.{@link MembersShould#beDeclaredInClassesThat(DescribedPredicate) beDeclaredInClassesThat(areSubtypeOf(Example.class))}
      * 
* would be violated by someField in * diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MembersThat.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MembersThat.java index f863cc6e5d..48d5dd37ba 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MembersThat.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/MembersThat.java @@ -451,7 +451,7 @@ public interface MembersThat> { * * will be matched by *

-     * {@link ArchRuleDefinition#members() members()}.{@link GivenMembers#that() that()}.{@link MembersThat#areDeclaredInClassesThat(DescribedPredicate) areDeclaredInClassesThat(areSubTypeOf(Object.class))}
+     * {@link ArchRuleDefinition#members() members()}.{@link GivenMembers#that() that()}.{@link MembersThat#areDeclaredInClassesThat(DescribedPredicate) areDeclaredInClassesThat(areSubtypeOf(Object.class))}
      * 
* * @param predicate A predicate which matches classes where members have to be declared in diff --git a/archunit/src/main/java/com/tngtech/archunit/library/Architectures.java b/archunit/src/main/java/com/tngtech/archunit/library/Architectures.java index 7f14d84474..edb564febd 100644 --- a/archunit/src/main/java/com/tngtech/archunit/library/Architectures.java +++ b/archunit/src/main/java/com/tngtech/archunit/library/Architectures.java @@ -362,7 +362,7 @@ private LayerDefinition(String name, boolean optional) { @PublicAPI(usage = ACCESS) public LayeredArchitecture definedBy(DescribedPredicate predicate) { checkNotNull(predicate, "Supplied predicate must not be null"); - this.containsPredicate = predicate.forSubType(); + this.containsPredicate = predicate.forSubtype(); return LayeredArchitecture.this.addLayerDefinition(this); } diff --git a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/GivenSlicesInternal.java b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/GivenSlicesInternal.java index 5e15e845a6..d2072244c1 100644 --- a/archunit/src/main/java/com/tngtech/archunit/library/dependencies/GivenSlicesInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/library/dependencies/GivenSlicesInternal.java @@ -43,7 +43,7 @@ class GivenSlicesInternal implements GivenSlices, SlicesShould, GivenSlicesConju @Override public ArchRule should(ArchCondition condition) { - return ArchRule.Factory.create(classesTransformer, condition.forSubType(), priority); + return ArchRule.Factory.create(classesTransformer, condition.forSubtype(), priority); } @Override diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java index 994d6c94e5..a4989b0a2b 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java @@ -132,7 +132,7 @@ public void Dependency_from_origin_and_target() { assertThat(dependency.getDescription()).as("description") .contains("Class <" + origin.getName() + "> implements interface <" + target.getName() + ">"); - origin = importClassWithContext(DependencySubInterface.class); + origin = importClassWithContext(DependencySubinterface.class); dependency = createDependency(origin, target); assertThat(dependency.getDescription()).as("description") .contains("Interface <" + origin.getName() + "> extends interface <" + target.getName() + ">"); @@ -353,7 +353,7 @@ public String toString() { private static class DependencyClass { } - private interface DependencySubInterface extends DependencyInterface { + private interface DependencySubinterface extends DependencyInterface { } private interface DependencyInterface { 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 bfb0c160df..9a1357e934 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 @@ -244,23 +244,27 @@ public void inner_class_has_package_of_declaring_class() { @Test public void superclasses_are_found() { - JavaClass clazz = importClassesWithContext(ClassWithTwoFieldsAndTwoMethods.class, SuperClassWithFieldAndMethod.class, Parent.class) + JavaClass clazz = importClassesWithContext(ClassWithTwoFieldsAndTwoMethods.class, SuperclassWithFieldAndMethod.class, Parent.class) .get(ClassWithTwoFieldsAndTwoMethods.class); - assertThat(clazz.getAllSuperClasses()).extracting("name").containsExactly( - SuperClassWithFieldAndMethod.class.getName(), + assertThat(clazz.getAllRawSuperclasses()).extracting("name").containsExactly( + SuperclassWithFieldAndMethod.class.getName(), + Parent.class.getName(), + Object.class.getName()); + assertThat(clazz.getAllRawSuperclasses()).extracting("name").containsExactly( + SuperclassWithFieldAndMethod.class.getName(), Parent.class.getName(), Object.class.getName()); } @Test public void hierarchy_is_found() { - JavaClass clazz = importClassesWithContext(ClassWithTwoFieldsAndTwoMethods.class, SuperClassWithFieldAndMethod.class, Parent.class) + JavaClass clazz = importClassesWithContext(ClassWithTwoFieldsAndTwoMethods.class, SuperclassWithFieldAndMethod.class, Parent.class) .get(ClassWithTwoFieldsAndTwoMethods.class); assertThat(clazz.getClassHierarchy()).extracting("name").containsExactly( clazz.getName(), - SuperClassWithFieldAndMethod.class.getName(), + SuperclassWithFieldAndMethod.class.getName(), Parent.class.getName(), Object.class.getName()); } @@ -350,15 +354,15 @@ public void isMetaAnnotatedWith_correctly_resolves_cyclic_annotations() { @Test public void allAccesses_contains_accesses_from_superclass() { - JavaClass javaClass = importClasses(ClassWithTwoFieldsAndTwoMethods.class, SuperClassWithFieldAndMethod.class, Parent.class) + JavaClass javaClass = importClasses(ClassWithTwoFieldsAndTwoMethods.class, SuperclassWithFieldAndMethod.class, Parent.class) .get(ClassWithTwoFieldsAndTwoMethods.class); JavaClass anotherClass = importClassWithContext(Object.class); simulateCall().from(javaClass.getMethod("stringMethod"), 8).to(anotherClass.getMethod("toString")); - simulateCall().from(javaClass.getSuperClass().get().getMethod("objectMethod"), 8).to(anotherClass.getMethod("toString")); + simulateCall().from(javaClass.getRawSuperclass().get().getMethod("objectMethod"), 8).to(anotherClass.getMethod("toString")); assertThat(javaClass.getAccessesFromSelf()).extractingResultOf("getOriginOwner").containsOnly(javaClass); assertThat(javaClass.getAllAccessesFromSelf()).extractingResultOf("getOriginOwner") - .contains(javaClass, javaClass.getSuperClass().get()); + .contains(javaClass, javaClass.getRawSuperclass().get()); } @Test @@ -639,7 +643,7 @@ public void direct_dependencies_from_self_finds_correct_set_of_target_types() { assertThatTypes(targets).matchInAnyOrder( B.class, AhavingMembersOfTypeB.class, Object.class, String.class, - List.class, Serializable.class, SomeSuperClass.class, + List.class, Serializable.class, SomeSuperclass.class, WithType.class, WithNestedAnnotations.class, OnClass.class, OnMethod.class, OnConstructor.class, OnField.class, MetaAnnotated.class, WithEnum.class, WithPrimitive.class, WithOtherEnum.class, WithOtherType.class, @@ -671,9 +675,9 @@ public void direct_dependencies_to_self_by_accesses() { @Test public void direct_dependencies_to_self_by_inheritance() { - JavaClass superClass = importClassesWithContext(SuperA.class, AExtendingSuperAImplementingInterfaceForA.class).get(SuperA.class); + JavaClass superclass = importClassesWithContext(SuperA.class, AExtendingSuperAImplementingInterfaceForA.class).get(SuperA.class); - assertThat(superClass.getDirectDependenciesToSelf()) + assertThat(superclass.getDirectDependenciesToSelf()) .areAtLeastOne(extendsDependency() .from(AExtendingSuperAImplementingInterfaceForA.class) .to(SuperA.class) @@ -886,7 +890,7 @@ public void functions_get_members() { public void predicate_withType() { assertThat(type(Parent.class)) .accepts(importClassWithContext(Parent.class)) - .rejects(importClassWithContext(SuperClassWithFieldAndMethod.class)); + .rejects(importClassWithContext(SuperclassWithFieldAndMethod.class)); assertThat(type(System.class)).hasDescription("type java.lang.System"); } @@ -895,7 +899,7 @@ public void predicate_withType() { public void predicate_simpleName() { assertThat(simpleName(Parent.class.getSimpleName())) .accepts(importClassWithContext(Parent.class)) - .rejects(importClassWithContext(SuperClassWithFieldAndMethod.class)); + .rejects(importClassWithContext(SuperclassWithFieldAndMethod.class)); assertThat(simpleName("Simple")).hasDescription("simple name 'Simple'"); } @@ -962,17 +966,17 @@ public void predicate_simpleNameEndingWith() { @Test public void predicate_assignableFrom() { - assertThatAssignable().from(SuperClassWithFieldAndMethod.class) - .to(SuperClassWithFieldAndMethod.class) + assertThatAssignable().from(SuperclassWithFieldAndMethod.class) + .to(SuperclassWithFieldAndMethod.class) .isTrue(); assertThatAssignable().from(ClassWithTwoFieldsAndTwoMethods.class) - .to(SuperClassWithFieldAndMethod.class) + .to(SuperclassWithFieldAndMethod.class) .isTrue(); - assertThatAssignable().from(SuperClassWithFieldAndMethod.class) + assertThatAssignable().from(SuperclassWithFieldAndMethod.class) .to(InterfaceWithMethod.class) .isTrue(); assertThatAssignable().from(ClassWithTwoFieldsAndTwoMethods.class) - .via(SuperClassWithFieldAndMethod.class) + .via(SuperclassWithFieldAndMethod.class) .to(InterfaceWithMethod.class) .isTrue(); assertThatAssignable().from(InterfaceWithMethod.class) @@ -981,14 +985,14 @@ public void predicate_assignableFrom() { assertThatAssignable().from(Parent.class) .to(InterfaceWithMethod.class) .isFalse(); - assertThatAssignable().from(SuperClassWithFieldAndMethod.class) + assertThatAssignable().from(SuperclassWithFieldAndMethod.class) .to(Parent.class) .isTrue(); - assertThatAssignable().from(SuperClassWithFieldAndMethod.class) + assertThatAssignable().from(SuperclassWithFieldAndMethod.class) .to(ClassWithTwoFieldsAndTwoMethods.class) .isFalse(); assertThatAssignable().from(Parent.class) - .to(SuperClassWithFieldAndMethod.class) + .to(SuperclassWithFieldAndMethod.class) .isFalse(); assertThat(assignableFrom(System.class)).hasDescription("assignable from java.lang.System"); @@ -996,33 +1000,33 @@ public void predicate_assignableFrom() { @Test public void predicate_assignableTo() { - assertThatAssignable().to(SuperClassWithFieldAndMethod.class) - .from(SuperClassWithFieldAndMethod.class) + assertThatAssignable().to(SuperclassWithFieldAndMethod.class) + .from(SuperclassWithFieldAndMethod.class) .isTrue(); assertThatAssignable().to(ClassWithTwoFieldsAndTwoMethods.class) - .from(SuperClassWithFieldAndMethod.class) + .from(SuperclassWithFieldAndMethod.class) .isFalse(); assertThatAssignable().to(InterfaceWithMethod.class) .from(InterfaceWithMethod.class) .isTrue(); assertThatAssignable().to(InterfaceWithMethod.class) - .from(SuperClassWithFieldAndMethod.class) + .from(SuperclassWithFieldAndMethod.class) .isTrue(); assertThatAssignable().to(InterfaceWithMethod.class) - .via(SuperClassWithFieldAndMethod.class) + .via(SuperclassWithFieldAndMethod.class) .from(ClassWithTwoFieldsAndTwoMethods.class) .isTrue(); assertThatAssignable().to(InterfaceWithMethod.class) .from(Parent.class) .isFalse(); - assertThatAssignable().to(SuperClassWithFieldAndMethod.class) + assertThatAssignable().to(SuperclassWithFieldAndMethod.class) .from(Parent.class) .isFalse(); - assertThatAssignable().to(SuperClassWithFieldAndMethod.class) + assertThatAssignable().to(SuperclassWithFieldAndMethod.class) .from(ClassWithTwoFieldsAndTwoMethods.class) .isTrue(); assertThatAssignable().to(Parent.class) - .from(SuperClassWithFieldAndMethod.class) + .from(SuperclassWithFieldAndMethod.class) .isTrue(); assertThat(assignableTo(System.class)).hasDescription("assignable to java.lang.System"); @@ -1124,9 +1128,9 @@ public void predicate_reside_in_any_package() { @Test public void predicate_equivalentTo() { - JavaClass javaClass = importClasses(SuperClassWithFieldAndMethod.class, Parent.class).get(SuperClassWithFieldAndMethod.class); + JavaClass javaClass = importClasses(SuperclassWithFieldAndMethod.class, Parent.class).get(SuperclassWithFieldAndMethod.class); - assertThat(equivalentTo(SuperClassWithFieldAndMethod.class)) + assertThat(equivalentTo(SuperclassWithFieldAndMethod.class)) .accepts(javaClass); assertThat(equivalentTo(Parent.class)) .rejects(javaClass) @@ -1429,7 +1433,7 @@ public void isFalse() { } @SuppressWarnings("unused") - static class ClassWithTwoFieldsAndTwoMethods extends SuperClassWithFieldAndMethod { + static class ClassWithTwoFieldsAndTwoMethods extends SuperclassWithFieldAndMethod { String stringField; private int intField; @@ -1442,7 +1446,7 @@ protected String stringMethod() { } @SuppressWarnings("unused") - abstract static class SuperClassWithFieldAndMethod extends Parent implements InterfaceWithMethod { + abstract static class SuperclassWithFieldAndMethod extends Parent implements InterfaceWithMethod { private Object objectField; @Override @@ -1577,7 +1581,7 @@ private class NestedNamedInnerClass { } } - private static class SomeSuperClass { + private static class SomeSuperclass { } @OnClass @@ -1595,7 +1599,7 @@ private static class SomeSuperClass { ) @MetaAnnotated @SuppressWarnings("unused") - private static class ClassWithAnnotationDependencies extends SomeSuperClass { + private static class ClassWithAnnotationDependencies extends SomeSuperclass { @OnField(SomeEnumAsAnnotationParameter.ANNOTATION_PARAMETER) Object field; diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaPackageTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaPackageTest.java index 70dd924535..f574f72a42 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaPackageTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaPackageTest.java @@ -191,6 +191,9 @@ public void iterates_sub_packages() { JavaPackage java = defaultPackage.getPackage("java"); + assertThatPackages(java.getSubpackages()).containRelativeNames("lang", "util", "io", "security"); + assertThatPackages(java.getSubpackages()).containNames("java.lang", "java.util", "java.io", "java.security"); + assertThatPackages(java.getSubPackages()).containRelativeNames("lang", "util", "io", "security"); assertThatPackages(java.getSubPackages()).containNames("java.lang", "java.util", "java.io", "java.security"); } @@ -211,6 +214,9 @@ public void iterates_all_sub_packages() { JavaPackage java = defaultPackage.getPackage("java"); + assertThatPackages(java.getAllSubpackages()).containPackagesOf( + Object.class, Annotation.class, Collection.class, BlockingQueue.class, Security.class); + assertThatPackages(java.getAllSubPackages()).containPackagesOf( Object.class, Annotation.class, Collection.class, BlockingQueue.class, Security.class); } @@ -522,8 +528,8 @@ private JavaPackage importDefaultPackage(Class... classes) { return new ClassFileImporter().importClasses(classes).getDefaultPackage(); } - private JavaPackage importPackage(String subPackageName) { - String packageName = getClass().getPackage().getName() + "." + subPackageName; + private JavaPackage importPackage(String subpackageName) { + String packageName = getClass().getPackage().getName() + "." + subpackageName; JavaClasses classes = new ClassFileImporter().importPackages(packageName); return classes.getPackage(packageName); } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/InterfaceForA.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/InterfaceForA.java index a04ddf7e1d..eed23febde 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/InterfaceForA.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/InterfaceForA.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.core.domain.testobjects; -public interface InterfaceForA extends SuperInterface { +public interface InterfaceForA extends Superinterface { } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/SuperInterface.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/Superinterface.java similarity index 62% rename from archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/SuperInterface.java rename to archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/Superinterface.java index 3a85718559..5cf8da74de 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/SuperInterface.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/testobjects/Superinterface.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.core.domain.testobjects; -public interface SuperInterface { +public interface Superinterface { } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterAnnotationsTest.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterAnnotationsTest.java index 3e38e19336..278cbba2c7 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterAnnotationsTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterAnnotationsTest.java @@ -66,7 +66,7 @@ public void imports_simple_annotation() { assertThat(javaClass.getSimpleName()).as("simple name").isEqualTo(AnnotationToImport.class.getSimpleName()); assertThat(javaClass.getPackageName()).as("package name").isEqualTo(AnnotationToImport.class.getPackage().getName()); assertThat(javaClass.getModifiers()).as("modifiers").containsOnly(JavaModifier.PUBLIC, JavaModifier.ABSTRACT); - assertThat(javaClass.getSuperClass()).as("super class").isAbsent(); + assertThat(javaClass.getRawSuperclass()).as("super class").isAbsent(); assertThatTypes(javaClass.getInterfaces()).as("interfaces").matchInAnyOrder(Annotation.class); assertThat(javaClass.isInterface()).as("is interface").isTrue(); assertThat(javaClass.isEnum()).as("is enum").isFalse(); diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterTest.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterTest.java index 425a99e171..de795b987f 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterTest.java @@ -77,19 +77,19 @@ import com.tngtech.archunit.core.importer.testexamples.callimport.CallsOwnMethod; import com.tngtech.archunit.core.importer.testexamples.callimport.ExternalInterfaceMethodCall; import com.tngtech.archunit.core.importer.testexamples.callimport.ExternalOverriddenMethodCall; -import com.tngtech.archunit.core.importer.testexamples.callimport.ExternalSubTypeConstructorCall; +import com.tngtech.archunit.core.importer.testexamples.callimport.ExternalSubtypeConstructorCall; import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.BaseClass; import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.CollectionInterface; import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.GrandParentInterface; import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.OtherInterface; -import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.OtherSubClass; +import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.OtherSubclass; import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.ParentInterface; import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.SomeCollection; -import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.SubClass; -import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.SubInterface; -import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.SubSubClass; -import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.SubSubSubClass; -import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.SubSubSubSubClass; +import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.SubSubSubSubclass; +import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.SubSubSubclass; +import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.SubSubclass; +import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.Subclass; +import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.Subinterface; import com.tngtech.archunit.core.importer.testexamples.classhierarchyimport.YetAnotherInterface; import com.tngtech.archunit.core.importer.testexamples.complexexternal.ChildClass; import com.tngtech.archunit.core.importer.testexamples.complexexternal.ParentClass; @@ -120,12 +120,12 @@ import com.tngtech.archunit.core.importer.testexamples.fieldaccesstointerfaces.ParentInterfaceWithFields; import com.tngtech.archunit.core.importer.testexamples.fieldimport.ClassWithIntAndObjectFields; import com.tngtech.archunit.core.importer.testexamples.fieldimport.ClassWithStringField; -import com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess.AccessToSuperAndSubClassField; -import com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess.SubClassWithAccessedField; -import com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess.SuperClassWithAccessedField; -import com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall.CallOfSuperAndSubClassMethod; -import com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall.SubClassWithCalledMethod; -import com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall.SuperClassWithCalledMethod; +import com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess.AccessToSuperAndSubclassField; +import com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess.SubclassWithAccessedField; +import com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess.SuperclassWithAccessedField; +import com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall.CallOfSuperAndSubclassMethod; +import com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall.SubclassWithCalledMethod; +import com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall.SuperclassWithCalledMethod; import com.tngtech.archunit.core.importer.testexamples.innerclassimport.CalledClass; import com.tngtech.archunit.core.importer.testexamples.innerclassimport.ClassWithInnerClass; import com.tngtech.archunit.core.importer.testexamples.instanceofcheck.ChecksInstanceofInConstructor; @@ -134,7 +134,7 @@ import com.tngtech.archunit.core.importer.testexamples.instanceofcheck.InstanceofChecked; import com.tngtech.archunit.core.importer.testexamples.integration.ClassA; import com.tngtech.archunit.core.importer.testexamples.integration.ClassBDependingOnClassA; -import com.tngtech.archunit.core.importer.testexamples.integration.ClassCDependingOnClassB_SuperClassOfX; +import com.tngtech.archunit.core.importer.testexamples.integration.ClassCDependingOnClassB_SuperclassOfX; import com.tngtech.archunit.core.importer.testexamples.integration.ClassD; import com.tngtech.archunit.core.importer.testexamples.integration.ClassXDependingOnClassesABCD; import com.tngtech.archunit.core.importer.testexamples.integration.InterfaceOfClassX; @@ -250,7 +250,7 @@ public void imports_simple_class_details() throws Exception { assertThat(javaClass.getSimpleName()).as("simple name").isEqualTo(ClassToImportOne.class.getSimpleName()); assertThat(javaClass.getPackageName()).as("package name").isEqualTo(ClassToImportOne.class.getPackage().getName()); assertThat(javaClass.getModifiers()).as("modifiers").containsOnly(JavaModifier.PUBLIC); - assertThatType(javaClass.getSuperClass().get()).as("super class").matches(Object.class); + assertThatType(javaClass.getRawSuperclass().get()).as("super class").matches(Object.class); assertThat(javaClass.getInterfaces()).as("interfaces").isEmpty(); assertThat(javaClass.isInterface()).as("is interface").isFalse(); assertThat(javaClass.isEnum()).as("is enum").isFalse(); @@ -274,7 +274,7 @@ public void imports_simple_enum() throws Exception { assertThat(javaClass.getSimpleName()).as("simple name").isEqualTo(EnumToImport.class.getSimpleName()); assertThat(javaClass.getPackageName()).as("package name").isEqualTo(EnumToImport.class.getPackage().getName()); assertThat(javaClass.getModifiers()).as("modifiers").containsOnly(JavaModifier.PUBLIC, JavaModifier.FINAL); - assertThatType(javaClass.getSuperClass().get()).as("super class").matches(Enum.class); + assertThatType(javaClass.getRawSuperclass().get()).as("super class").matches(Enum.class); assertThat(javaClass.getInterfaces()).as("interfaces").isEmpty(); assertThatTypes(javaClass.getAllInterfaces()).matchInAnyOrder(Enum.class.getInterfaces()); assertThat(javaClass.isInterface()).as("is interface").isFalse(); @@ -373,7 +373,7 @@ public void imports_interfaces() throws Exception { assertThat(simpleInterface.getName()).as("full name").isEqualTo(InterfaceToImport.class.getName()); assertThat(simpleInterface.getSimpleName()).as("simple name").isEqualTo(InterfaceToImport.class.getSimpleName()); assertThat(simpleInterface.getPackageName()).as("package name").isEqualTo(InterfaceToImport.class.getPackage().getName()); - assertThat(simpleInterface.getSuperClass()).as("super class").isAbsent(); + assertThat(simpleInterface.getRawSuperclass()).as("super class").isAbsent(); assertThat(simpleInterface.getInterfaces()).as("interfaces").isEmpty(); assertThat(simpleInterface.isInterface()).as("is interface").isTrue(); assertThat(simpleInterface.isEnum()).as("is enum").isFalse(); @@ -682,31 +682,34 @@ public void imports_base_class_in_class_hierarchy_correctly() throws Exception { } @Test - public void imports_sub_class_in_class_hierarchy_correctly() throws Exception { - JavaClass subClass = classesIn("testexamples/classhierarchyimport").get(SubClass.class); + public void imports_subclass_in_class_hierarchy_correctly() throws Exception { + JavaClass subclass = classesIn("testexamples/classhierarchyimport").get(Subclass.class); - assertThat(subClass.getConstructors()).hasSize(3); - assertThat(subClass.getFields()).hasSize(1); - assertThat(subClass.getMethods()).hasSize(3); - assertThat(subClass.getStaticInitializer().get().getMethodCallsFromSelf().size()).isGreaterThan(0); + assertThat(subclass.getConstructors()).hasSize(3); + assertThat(subclass.getFields()).hasSize(1); + assertThat(subclass.getMethods()).hasSize(3); + assertThat(subclass.getStaticInitializer().get().getMethodCallsFromSelf().size()).isGreaterThan(0); } @Test - public void creates_relations_between_super_and_sub_classes() throws Exception { + public void creates_relations_between_super_and_subclasses() throws Exception { ImportedClasses classes = classesIn("testexamples/classhierarchyimport"); JavaClass baseClass = classes.get(BaseClass.class); - JavaClass subClass = classes.get(SubClass.class); - JavaClass otherSubClass = classes.get(OtherSubClass.class); - JavaClass subSubClass = classes.get(SubSubClass.class); - JavaClass subSubSubClass = classes.get(SubSubSubClass.class); - JavaClass subSubSubSubClass = classes.get(SubSubSubSubClass.class); + JavaClass subclass = classes.get(Subclass.class); + JavaClass otherSubclass = classes.get(OtherSubclass.class); + JavaClass subSubclass = classes.get(SubSubclass.class); + JavaClass subSubSubclass = classes.get(SubSubSubclass.class); + JavaClass subSubSubSubclass = classes.get(SubSubSubSubclass.class); - assertThat(baseClass.getSuperClass().get().reflect()).isEqualTo(Object.class); - assertThat(baseClass.getSubClasses()).containsOnly(subClass, otherSubClass); - assertThat(baseClass.getAllSubClasses()).containsOnly(subClass, otherSubClass, subSubClass, subSubSubClass, subSubSubSubClass); - assertThat(subClass.getSuperClass()).contains(baseClass); - assertThat(subClass.getAllSubClasses()).containsOnly(subSubClass, subSubSubClass, subSubSubSubClass); - assertThat(subSubClass.getSuperClass()).contains(subClass); + assertThat(baseClass.getRawSuperclass().get().reflect()).isEqualTo(Object.class); + assertThat(baseClass.getSubclasses()).containsOnly(subclass, otherSubclass); + assertThat(baseClass.getSubclasses()).containsOnly(subclass, otherSubclass); + assertThat(baseClass.getAllSubclasses()).containsOnly(subclass, otherSubclass, subSubclass, subSubSubclass, subSubSubSubclass); + assertThat(baseClass.getAllSubclasses()).containsOnly(subclass, otherSubclass, subSubclass, subSubSubclass, subSubSubSubclass); + assertThat(subclass.getRawSuperclass()).contains(baseClass); + assertThat(subclass.getRawSuperclass()).contains(baseClass); + assertThat(subclass.getAllSubclasses()).containsOnly(subSubclass, subSubSubclass, subSubSubSubclass); + assertThat(subSubclass.getRawSuperclass()).contains(subclass); } @Test @@ -714,9 +717,9 @@ public void creates_relations_between_classes_and_interfaces() throws Exception ImportedClasses classes = classesIn("testexamples/classhierarchyimport"); JavaClass baseClass = classes.get(BaseClass.class); JavaClass otherInterface = classes.get(OtherInterface.class); - JavaClass subClass = classes.get(SubClass.class); - JavaClass subInterface = classes.get(SubInterface.class); - JavaClass otherSubClass = classes.get(OtherSubClass.class); + JavaClass subclass = classes.get(Subclass.class); + JavaClass subinterface = classes.get(Subinterface.class); + JavaClass otherSubclass = classes.get(OtherSubclass.class); JavaClass parentInterface = classes.get(ParentInterface.class); JavaClass grandParentInterface = classes.get(GrandParentInterface.class); JavaClass someCollection = classes.get(SomeCollection.class); @@ -724,21 +727,21 @@ public void creates_relations_between_classes_and_interfaces() throws Exception assertThat(baseClass.getInterfaces()).containsOnly(otherInterface); assertThat(baseClass.getAllInterfaces()).containsOnly(otherInterface, grandParentInterface); - assertThat(subClass.getInterfaces()).containsOnly(subInterface); - assertThat(subClass.getAllInterfaces()).containsOnly( - subInterface, otherInterface, parentInterface, grandParentInterface); - assertThat(otherSubClass.getInterfaces()).containsOnly(parentInterface); - assertThat(otherSubClass.getAllInterfaces()).containsOnly(parentInterface, grandParentInterface, otherInterface); - assertThat(someCollection.getInterfaces()).containsOnly(collectionInterface, otherInterface, subInterface); + assertThat(subclass.getInterfaces()).containsOnly(subinterface); + assertThat(subclass.getAllInterfaces()).containsOnly( + subinterface, otherInterface, parentInterface, grandParentInterface); + assertThat(otherSubclass.getInterfaces()).containsOnly(parentInterface); + assertThat(otherSubclass.getAllInterfaces()).containsOnly(parentInterface, grandParentInterface, otherInterface); + assertThat(someCollection.getInterfaces()).containsOnly(collectionInterface, otherInterface, subinterface); assertThat(someCollection.getAllInterfaces()).extractingResultOf("reflect").containsOnly( - CollectionInterface.class, OtherInterface.class, SubInterface.class, ParentInterface.class, + CollectionInterface.class, OtherInterface.class, Subinterface.class, ParentInterface.class, GrandParentInterface.class, Collection.class, Iterable.class); } @Test public void creates_relations_between_interfaces_and_interfaces() throws Exception { ImportedClasses classes = classesIn("testexamples/classhierarchyimport"); - JavaClass subInterface = classes.get(SubInterface.class); + JavaClass subinterface = classes.get(Subinterface.class); JavaClass parentInterface = classes.get(ParentInterface.class); JavaClass grandParentInterface = classes.get(GrandParentInterface.class); JavaClass collectionInterface = classes.get(CollectionInterface.class); @@ -746,54 +749,54 @@ public void creates_relations_between_interfaces_and_interfaces() throws Excepti assertThat(grandParentInterface.getAllInterfaces()).isEmpty(); assertThat(parentInterface.getInterfaces()).containsOnly(grandParentInterface); assertThat(parentInterface.getAllInterfaces()).containsOnly(grandParentInterface); - assertThat(subInterface.getInterfaces()).containsOnly(parentInterface); - assertThat(subInterface.getAllInterfaces()).containsOnly(parentInterface, grandParentInterface); + assertThat(subinterface.getInterfaces()).containsOnly(parentInterface); + assertThat(subinterface.getAllInterfaces()).containsOnly(parentInterface, grandParentInterface); assertThat(collectionInterface.getInterfaces()).extractingResultOf("reflect").containsOnly(Collection.class); } @Test - public void creates_relations_between_interfaces_and_sub_classes() throws Exception { + public void creates_relations_between_interfaces_and_subclasses() throws Exception { ImportedClasses classes = classesIn("testexamples/classhierarchyimport"); JavaClass baseClass = classes.get(BaseClass.class); JavaClass otherInterface = classes.get(OtherInterface.class); - JavaClass subClass = classes.get(SubClass.class); - JavaClass subSubClass = classes.get(SubSubClass.class); - JavaClass subSubSubClass = classes.get(SubSubSubClass.class); - JavaClass subSubSubSubClass = classes.get(SubSubSubSubClass.class); - JavaClass subInterface = classes.get(SubInterface.class); - JavaClass otherSubClass = classes.get(OtherSubClass.class); + JavaClass subclass = classes.get(Subclass.class); + JavaClass subSubclass = classes.get(SubSubclass.class); + JavaClass subSubSubclass = classes.get(SubSubSubclass.class); + JavaClass subSubSubSubclass = classes.get(SubSubSubSubclass.class); + JavaClass subinterface = classes.get(Subinterface.class); + JavaClass otherSubclass = classes.get(OtherSubclass.class); JavaClass parentInterface = classes.get(ParentInterface.class); JavaClass grandParentInterface = classes.get(GrandParentInterface.class); JavaClass someCollection = classes.get(SomeCollection.class); JavaClass collectionInterface = classes.get(CollectionInterface.class); - assertThat(grandParentInterface.getSubClasses()).containsOnly(parentInterface, otherInterface); - assertThat(grandParentInterface.getAllSubClasses()).containsOnly( - parentInterface, subInterface, otherInterface, - baseClass, subClass, otherSubClass, subSubClass, subSubSubClass, subSubSubSubClass, someCollection + assertThat(grandParentInterface.getSubclasses()).containsOnly(parentInterface, otherInterface); + assertThat(grandParentInterface.getAllSubclasses()).containsOnly( + parentInterface, subinterface, otherInterface, + baseClass, subclass, otherSubclass, subSubclass, subSubSubclass, subSubSubSubclass, someCollection ); - assertThat(parentInterface.getSubClasses()).containsOnly(subInterface, otherSubClass); - assertThat(parentInterface.getAllSubClasses()).containsOnly( - subInterface, subClass, subSubClass, subSubSubClass, subSubSubSubClass, someCollection, otherSubClass); + assertThat(parentInterface.getSubclasses()).containsOnly(subinterface, otherSubclass); + assertThat(parentInterface.getAllSubclasses()).containsOnly( + subinterface, subclass, subSubclass, subSubSubclass, subSubSubSubclass, someCollection, otherSubclass); JavaClass collection = getOnlyElement(collectionInterface.getInterfaces()); - assertThat(collection.getAllSubClasses()).containsOnly(collectionInterface, someCollection); + assertThat(collection.getAllSubclasses()).containsOnly(collectionInterface, someCollection); } @Test public void creates_superclass_and_interface_relations_missing_from_context() { - JavaClass javaClass = new ClassFileImporter().importClass(SubSubSubSubClass.class); + JavaClass javaClass = new ClassFileImporter().importClass(SubSubSubSubclass.class); - assertThat(javaClass.getAllSuperClasses()).extracting("name") + assertThat(javaClass.getAllRawSuperclasses()).extracting("name") .containsExactly( - SubSubSubClass.class.getName(), - SubSubClass.class.getName(), - SubClass.class.getName(), + SubSubSubclass.class.getName(), + SubSubclass.class.getName(), + Subclass.class.getName(), BaseClass.class.getName(), Object.class.getName()); assertThat(javaClass.getAllInterfaces()).extracting("name") .containsOnly( - SubInterface.class.getName(), + Subinterface.class.getName(), YetAnotherInterface.class.getName(), ParentInterface.class.getName(), GrandParentInterface.class.getName(), @@ -827,10 +830,10 @@ public void imports_enclosing_classes() throws Exception { public void imports_overridden_methods_correctly() throws Exception { ImportedClasses classes = classesIn("testexamples/classhierarchyimport"); JavaClass baseClass = classes.get(BaseClass.class); - JavaClass subClass = classes.get(SubClass.class); + JavaClass subclass = classes.get(Subclass.class); assertThat(baseClass.getCodeUnitWithParameterTypes("getSomeField").getModifiers()).containsOnly(PROTECTED); - assertThat(subClass.getCodeUnitWithParameterTypes("getSomeField").getModifiers()).containsOnly(PUBLIC); + assertThat(subclass.getCodeUnitWithParameterTypes("getSomeField").getModifiers()).containsOnly(PUBLIC); } @Test @@ -1060,27 +1063,27 @@ public void imports_external_field_access_with_shadowed_field() throws Exception @Test public void imports_shadowed_and_superclass_field_access() throws Exception { ImportedClasses classes = classesIn("testexamples/hierarchicalfieldaccess"); - JavaClass classThatAccessesFieldOfSuperClass = classes.get(AccessToSuperAndSubClassField.class); - JavaClass superClassWithAccessedField = classes.get(SuperClassWithAccessedField.class); - JavaClass subClassWithAccessedField = classes.get(SubClassWithAccessedField.class); + JavaClass classThatAccessesFieldOfSuperclass = classes.get(AccessToSuperAndSubclassField.class); + JavaClass superclassWithAccessedField = classes.get(SuperclassWithAccessedField.class); + JavaClass subclassWithAccessedField = classes.get(SubclassWithAccessedField.class); - Set accesses = classThatAccessesFieldOfSuperClass.getFieldAccessesFromSelf(); + Set accesses = classThatAccessesFieldOfSuperclass.getFieldAccessesFromSelf(); assertThat(accesses).hasSize(2); - JavaField field = superClassWithAccessedField.getField("field"); - FieldAccessTarget expectedSuperClassFieldAccess = new FieldAccessTargetBuilder() - .withOwner(subClassWithAccessedField) + JavaField field = superclassWithAccessedField.getField("field"); + FieldAccessTarget expectedSuperclassFieldAccess = new FieldAccessTargetBuilder() + .withOwner(subclassWithAccessedField) .withName(field.getName()) .withType(field.getRawType()) .withField(Suppliers.ofInstance(Optional.of(field))) .build(); assertThatAccess(getOnly(accesses, "field", GET)) - .isFrom("accessSuperClassField") - .isTo(expectedSuperClassFieldAccess) + .isFrom("accessSuperclassField") + .isTo(expectedSuperclassFieldAccess) .inLineNumber(5); assertThatAccess(getOnly(accesses, "maskedField", GET)) - .isFrom("accessSubClassField") - .isTo(subClassWithAccessedField.getField("maskedField")) + .isFrom("accessSubclassField") + .isTo(subclassWithAccessedField.getField("maskedField")) .inLineNumber(9); } @@ -1106,35 +1109,35 @@ public void imports_field_accesses_to_fields_from_interfaces() throws Exception @Test public void imports_shadowed_and_superclass_method_calls() throws Exception { ImportedClasses classes = classesIn("testexamples/hierarchicalmethodcall"); - JavaClass classThatCallsMethodOfSuperClass = classes.get(CallOfSuperAndSubClassMethod.class); - JavaClass superClassWithCalledMethod = classes.get(SuperClassWithCalledMethod.class); - JavaClass subClassWithCalledMethod = classes.get(SubClassWithCalledMethod.class); + JavaClass classThatCallsMethodOfSuperclass = classes.get(CallOfSuperAndSubclassMethod.class); + JavaClass superclassWithCalledMethod = classes.get(SuperclassWithCalledMethod.class); + JavaClass subclassWithCalledMethod = classes.get(SubclassWithCalledMethod.class); - Set calls = classThatCallsMethodOfSuperClass.getMethodCallsFromSelf(); + Set calls = classThatCallsMethodOfSuperclass.getMethodCallsFromSelf(); assertThat(calls).hasSize(2); - JavaCodeUnit callSuperClassMethod = classThatCallsMethodOfSuperClass - .getCodeUnitWithParameterTypes(CallOfSuperAndSubClassMethod.callSuperClassMethod); - JavaMethod expectedSuperClassMethod = superClassWithCalledMethod.getMethod(SuperClassWithCalledMethod.method); - MethodCallTarget expectedSuperClassCall = new MethodCallTargetBuilder() - .withOwner(subClassWithCalledMethod) - .withName(expectedSuperClassMethod.getName()) - .withParameters(expectedSuperClassMethod.getRawParameterTypes()) - .withReturnType(expectedSuperClassMethod.getRawReturnType()) - .withMethods(Suppliers.ofInstance(Collections.singleton(expectedSuperClassMethod))) + JavaCodeUnit callSuperclassMethod = classThatCallsMethodOfSuperclass + .getCodeUnitWithParameterTypes(CallOfSuperAndSubclassMethod.callSuperclassMethod); + JavaMethod expectedSuperclassMethod = superclassWithCalledMethod.getMethod(SuperclassWithCalledMethod.method); + MethodCallTarget expectedSuperclassCall = new MethodCallTargetBuilder() + .withOwner(subclassWithCalledMethod) + .withName(expectedSuperclassMethod.getName()) + .withParameters(expectedSuperclassMethod.getRawParameterTypes()) + .withReturnType(expectedSuperclassMethod.getRawReturnType()) + .withMethods(Suppliers.ofInstance(Collections.singleton(expectedSuperclassMethod))) .build(); - assertThatCall(getOnlyByCaller(calls, callSuperClassMethod)) - .isFrom(callSuperClassMethod) - .isTo(expectedSuperClassCall) - .inLineNumber(CallOfSuperAndSubClassMethod.callSuperClassLineNumber); + assertThatCall(getOnlyByCaller(calls, callSuperclassMethod)) + .isFrom(callSuperclassMethod) + .isTo(expectedSuperclassCall) + .inLineNumber(CallOfSuperAndSubclassMethod.callSuperclassLineNumber); - JavaCodeUnit callSubClassMethod = classThatCallsMethodOfSuperClass - .getCodeUnitWithParameterTypes(CallOfSuperAndSubClassMethod.callSubClassMethod); - assertThatCall(getOnlyByCaller(calls, callSubClassMethod)) - .isFrom(callSubClassMethod) - .isTo(subClassWithCalledMethod.getMethod(SubClassWithCalledMethod.maskedMethod)) - .inLineNumber(CallOfSuperAndSubClassMethod.callSubClassLineNumber); + JavaCodeUnit callSubclassMethod = classThatCallsMethodOfSuperclass + .getCodeUnitWithParameterTypes(CallOfSuperAndSubclassMethod.callSubclassMethod); + assertThatCall(getOnlyByCaller(calls, callSubclassMethod)) + .isFrom(callSubclassMethod) + .isTo(subclassWithCalledMethod.getMethod(SubclassWithCalledMethod.maskedMethod)) + .inLineNumber(CallOfSuperAndSubclassMethod.callSubclassLineNumber); } @Test @@ -1209,7 +1212,7 @@ public void imports_constructor_calls_on_external_class() throws Exception { @Test public void imports_constructor_calls_to_sub_type_constructor_on_external_class() throws Exception { - JavaClass classWithExternalConstructorCall = classesIn("testexamples/callimport").get(ExternalSubTypeConstructorCall.class); + JavaClass classWithExternalConstructorCall = classesIn("testexamples/callimport").get(ExternalSubtypeConstructorCall.class); assertConstructorCall(classWithExternalConstructorCall.getCodeUnitWithParameterTypes("call"), ChildClass.class, 9); assertConstructorCall(classWithExternalConstructorCall.getCodeUnitWithParameterTypes("newHashMap"), HashMap.class, 13); @@ -1325,7 +1328,7 @@ public void dependency_target_classes_are_derived_correctly() throws Exception { Set expectedTargetClasses = ImmutableSet.of( classes.get(ClassA.class), classes.get(ClassBDependingOnClassA.class), - classes.get(ClassCDependingOnClassB_SuperClassOfX.class), + classes.get(ClassCDependingOnClassB_SuperclassOfX.class), classes.get(ClassD.class), classes.get(InterfaceOfClassX.class) ); @@ -1341,7 +1344,7 @@ public void dependency_target_classes_are_derived_correctly() throws Exception { @Test public void getDirectDependencies_does_not_return_transitive_dependencies() throws Exception { ImportedClasses classes = classesIn("testexamples/integration"); - JavaClass javaClass = classes.get(ClassCDependingOnClassB_SuperClassOfX.class); + JavaClass javaClass = classes.get(ClassCDependingOnClassB_SuperclassOfX.class); JavaClass expectedTargetClass = classes.get(ClassBDependingOnClassA.class); Set targetClasses = new HashSet<>(); @@ -1707,12 +1710,12 @@ public void resolve_missing_dependencies_from_classpath_can_be_toogled() throws ArchConfiguration.get().setResolveMissingDependenciesFromClassPath(true); JavaClass clazz = classesIn("testexamples/simpleimport").get(ClassToImportOne.class); - assertThat(clazz.getSuperClass().get().getMethods()).isNotEmpty(); + assertThat(clazz.getRawSuperclass().get().getMethods()).isNotEmpty(); ArchConfiguration.get().setResolveMissingDependenciesFromClassPath(false); clazz = classesIn("testexamples/simpleimport").get(ClassToImportOne.class); - assertThat(clazz.getSuperClass().get().getMethods()).isEmpty(); + assertThat(clazz.getRawSuperclass().get().getMethods()).isEmpty(); } @DataProvider 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 09a535b671..f68e42e2bf 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 @@ -332,7 +332,7 @@ private JavaClass importNew(Class owner) { private static class ImportContextStub implements ImportContext { @Override - public Optional createSuperClass(JavaClass owner) { + public Optional createSuperclass(JavaClass owner) { return Optional.absent(); } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/IndependentClasspathRule.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/IndependentClasspathRule.java index dd9779abfa..f86303de9d 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/IndependentClasspathRule.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/IndependentClasspathRule.java @@ -21,7 +21,7 @@ class IndependentClasspathRule extends ExternalResource { private final SystemPropertiesRule systemPropertiesRule = new SystemPropertiesRule(); @Override - protected void before() throws Throwable { + protected void before() { systemPropertiesRule.before(); } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/UrlSourceTest.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/UrlSourceTest.java index 8be6c2ba1d..b7e2df85aa 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/UrlSourceTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/UrlSourceTest.java @@ -125,11 +125,11 @@ public void handles_jar_uri_with_spaces() throws Exception { @Test public void recursively_resolves_classpath_attributes_in_manifests() throws Exception { File folder = temporaryFolder.newFolder(); - WrittenJarFile grandChildOne = writeJarWithManifestClasspathAttribute(folder, subPath("grandchild", "one")); - WrittenJarFile grandChildTwo = writeJarWithManifestClasspathAttribute(folder, subPath("grandchild", "two")); - WrittenJarFile grandChildThree = writeJarWithManifestClasspathAttribute(folder, subPath("grandchild", "three")); - WrittenJarFile childOne = writeJarWithManifestClasspathAttribute(folder, subPath("child", "one"), grandChildOne.getPathAsAbsoluteUrl(), ManifestClasspathEntry.relativeUrl(grandChildTwo.path)); - WrittenJarFile childTwo = writeJarWithManifestClasspathAttribute(folder, subPath("child", "two"), ManifestClasspathEntry.absoluteUrl(grandChildThree.path)); + WrittenJarFile grandChildOne = writeJarWithManifestClasspathAttribute(folder, subpath("grandchild", "one")); + WrittenJarFile grandChildTwo = writeJarWithManifestClasspathAttribute(folder, subpath("grandchild", "two")); + WrittenJarFile grandChildThree = writeJarWithManifestClasspathAttribute(folder, subpath("grandchild", "three")); + WrittenJarFile childOne = writeJarWithManifestClasspathAttribute(folder, subpath("child", "one"), grandChildOne.getPathAsAbsoluteUrl(), ManifestClasspathEntry.relativeUrl(grandChildTwo.path)); + WrittenJarFile childTwo = writeJarWithManifestClasspathAttribute(folder, subpath("child", "two"), ManifestClasspathEntry.absoluteUrl(grandChildThree.path)); WrittenJarFile parent = writeJarWithManifestClasspathAttribute(folder, "parent", ManifestClasspathEntry.relativePath(childOne.path), ManifestClasspathEntry.absoluteUrl(childTwo.path)); System.setProperty(JAVA_CLASS_PATH_PROP, parent.path.toString()); @@ -163,7 +163,7 @@ public void terminates_recursively_resolving_manifest_classpaths_if_manifests_ha assertThat(urls).containsOnly(toUrl(Paths.get(jarOne.getName())), toUrl(Paths.get(jarTwo.getName()))); } - private String subPath(String... parts) { + private String subpath(String... parts) { return Joiner.on(File.separator).join(parts); } @@ -188,7 +188,7 @@ private Set createManifestClasspathEntries(String infix) Set result = new HashSet<>(); for (int i = 0; i < 10; i++) { result.add(ManifestClasspathEntry - .absolutePath(Paths.get(File.separator + subPath("some", "path", "parent", infix + i, "")).toAbsolutePath())); + .absolutePath(Paths.get(File.separator + subpath("some", "path", "parent", infix + i, "")).toAbsolutePath())); } return result; } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/resolvers/SelectedClassResolverFromClasspathTest.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/resolvers/SelectedClassResolverFromClasspathTest.java index 9b1ae51f5b..8863700bd1 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/resolvers/SelectedClassResolverFromClasspathTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/resolvers/SelectedClassResolverFromClasspathTest.java @@ -68,11 +68,11 @@ public boolean matches(URI argument) { }); } - private ImmutableList packages(String... subPackages) { + private ImmutableList packages(String... subpackages) { ImmutableList.Builder result = ImmutableList.builder(); - for (String pkg : subPackages) { + for (String pkg : subpackages) { result.add(getClass().getPackage().getName() + ".testclasses." + pkg); } return result.build(); } -} \ No newline at end of file +} diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/callimport/ExternalSubTypeConstructorCall.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/callimport/ExternalSubtypeConstructorCall.java similarity index 87% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/callimport/ExternalSubTypeConstructorCall.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/callimport/ExternalSubtypeConstructorCall.java index ede53b5ce7..3a55b09b22 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/callimport/ExternalSubTypeConstructorCall.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/callimport/ExternalSubtypeConstructorCall.java @@ -4,7 +4,7 @@ import com.tngtech.archunit.core.importer.testexamples.complexexternal.ChildClass; -public class ExternalSubTypeConstructorCall { +public class ExternalSubtypeConstructorCall { void call() { new ChildClass(); } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/OtherSubClass.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/OtherSubclass.java similarity index 78% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/OtherSubClass.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/OtherSubclass.java index 269a8b1874..c0a43a70d2 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/OtherSubClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/OtherSubclass.java @@ -1,6 +1,6 @@ package com.tngtech.archunit.core.importer.testexamples.classhierarchyimport; -public class OtherSubClass extends BaseClass implements ParentInterface { +public class OtherSubclass extends BaseClass implements ParentInterface { private int foo = 5; void soSthOtherSub() { diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SomeCollection.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SomeCollection.java index 8424ce8ed4..c313b97a8e 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SomeCollection.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SomeCollection.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.core.importer.testexamples.classhierarchyimport; -public abstract class SomeCollection implements CollectionInterface, OtherInterface, SubInterface { +public abstract class SomeCollection implements CollectionInterface, OtherInterface, Subinterface { } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubSubClass.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubSubclass.java similarity index 59% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubSubClass.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubSubclass.java index 1ac7fb59e5..c8bbda94c8 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubSubClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubSubclass.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.core.importer.testexamples.classhierarchyimport; -public class SubSubSubSubClass extends SubSubSubClass { +public class SubSubSubSubclass extends SubSubSubclass { } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubClass.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubclass.java similarity index 61% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubClass.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubclass.java index 902991f6a4..b8425a3330 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubSubclass.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.core.importer.testexamples.classhierarchyimport; -public class SubSubSubClass extends SubSubClass { +public class SubSubSubclass extends SubSubclass { } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubClass.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubclass.java similarity index 77% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubClass.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubclass.java index 6415fbbd1a..6dae2a57fe 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubSubclass.java @@ -1,6 +1,6 @@ package com.tngtech.archunit.core.importer.testexamples.classhierarchyimport; -public class SubSubClass extends SubClass implements SubInterface, YetAnotherInterface { +public class SubSubclass extends Subclass implements Subinterface, YetAnotherInterface { private String printMe = "NoOp"; void doSomethingSubSub() { diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubClass.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/Subclass.java similarity index 59% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubClass.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/Subclass.java index 13a3ccfc4f..1366f123bc 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/Subclass.java @@ -1,22 +1,22 @@ package com.tngtech.archunit.core.importer.testexamples.classhierarchyimport; -public class SubClass extends BaseClass implements SubInterface { +public class Subclass extends BaseClass implements Subinterface { static { - System.out.println(SubClass.class.getSimpleName() + " initializing"); + System.out.println(Subclass.class.getSimpleName() + " initializing"); } private int intField; - public SubClass() { + public Subclass() { intField = 1; } - public SubClass(String someField) { - super(someField + "by" + SubClass.class.getSimpleName()); + public Subclass(String someField) { + super(someField + "by" + Subclass.class.getSimpleName()); intField = 1; } - public SubClass(String someField, int addition) { + public Subclass(String someField, int addition) { this(someField + addition); this.intField = addition; } @@ -26,7 +26,7 @@ public String getSomeField() { return super.getSomeField(); } - public void subClassSay() { + public void subclassSay() { System.out.println(getSomeField()); } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubInterface.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/Subinterface.java similarity index 59% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubInterface.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/Subinterface.java index 93a0e23b13..0f3208f6f4 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/SubInterface.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/classhierarchyimport/Subinterface.java @@ -1,4 +1,4 @@ package com.tngtech.archunit.core.importer.testexamples.classhierarchyimport; -public interface SubInterface extends ParentInterface { +public interface Subinterface extends ParentInterface { } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/AccessToSuperAndSubClassField.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/AccessToSuperAndSubClassField.java deleted file mode 100644 index 8d44a095b2..0000000000 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/AccessToSuperAndSubClassField.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess; - -public class AccessToSuperAndSubClassField { - String accessSuperClassField() { - return new SubClassWithAccessedField().field; - } - - int accessSubClassField() { - return new SubClassWithAccessedField().maskedField; - } -} diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/AccessToSuperAndSubclassField.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/AccessToSuperAndSubclassField.java new file mode 100644 index 0000000000..fa34bcf32b --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/AccessToSuperAndSubclassField.java @@ -0,0 +1,11 @@ +package com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess; + +public class AccessToSuperAndSubclassField { + String accessSuperclassField() { + return new SubclassWithAccessedField().field; + } + + int accessSubclassField() { + return new SubclassWithAccessedField().maskedField; + } +} diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SubClassWithAccessedField.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SubclassWithAccessedField.java similarity index 64% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SubClassWithAccessedField.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SubclassWithAccessedField.java index 358899dcf4..2bef681d1d 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SubClassWithAccessedField.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SubclassWithAccessedField.java @@ -1,5 +1,5 @@ package com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess; -public class SubClassWithAccessedField extends SuperClassWithAccessedField { +public class SubclassWithAccessedField extends SuperclassWithAccessedField { int maskedField; } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SuperClassWithAccessedField.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SuperclassWithAccessedField.java similarity index 74% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SuperClassWithAccessedField.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SuperclassWithAccessedField.java index efa9c7cd90..d7a68ab991 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SuperClassWithAccessedField.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalfieldaccess/SuperclassWithAccessedField.java @@ -1,6 +1,6 @@ package com.tngtech.archunit.core.importer.testexamples.hierarchicalfieldaccess; -public class SuperClassWithAccessedField { +public class SuperclassWithAccessedField { String field; int maskedField; } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/CallOfSuperAndSubClassMethod.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/CallOfSuperAndSubClassMethod.java deleted file mode 100644 index cf12591354..0000000000 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/CallOfSuperAndSubClassMethod.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall; - -public class CallOfSuperAndSubClassMethod { - public static final String callSuperClassMethod = "callSuperClassMethod"; - public static final int callSuperClassLineNumber = 10; - public static final String callSubClassMethod = "callSubClassMethod"; - public static final int callSubClassLineNumber = 14; - - String callSuperClassMethod() { - return new SubClassWithCalledMethod().method(); - } - - int callSubClassMethod() { - return new SubClassWithCalledMethod().maskedMethod(); - } -} diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/CallOfSuperAndSubclassMethod.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/CallOfSuperAndSubclassMethod.java new file mode 100644 index 0000000000..7eb063b0e1 --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/CallOfSuperAndSubclassMethod.java @@ -0,0 +1,16 @@ +package com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall; + +public class CallOfSuperAndSubclassMethod { + public static final String callSuperclassMethod = "callSuperclassMethod"; + public static final int callSuperclassLineNumber = 10; + public static final String callSubclassMethod = "callSubclassMethod"; + public static final int callSubclassLineNumber = 14; + + String callSuperclassMethod() { + return new SubclassWithCalledMethod().method(); + } + + int callSubclassMethod() { + return new SubclassWithCalledMethod().maskedMethod(); + } +} diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SubClassWithCalledMethod.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SubclassWithCalledMethod.java similarity index 77% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SubClassWithCalledMethod.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SubclassWithCalledMethod.java index c04864e32c..8622fc7b62 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SubClassWithCalledMethod.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SubclassWithCalledMethod.java @@ -1,6 +1,6 @@ package com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall; -public class SubClassWithCalledMethod extends SuperClassWithCalledMethod { +public class SubclassWithCalledMethod extends SuperclassWithCalledMethod { public static final String maskedMethod = "maskedMethod"; @Override diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SuperClassWithCalledMethod.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SuperclassWithCalledMethod.java similarity index 84% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SuperClassWithCalledMethod.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SuperclassWithCalledMethod.java index 060c0cd52f..7b6b48941d 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SuperClassWithCalledMethod.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/hierarchicalmethodcall/SuperclassWithCalledMethod.java @@ -1,6 +1,6 @@ package com.tngtech.archunit.core.importer.testexamples.hierarchicalmethodcall; -public class SuperClassWithCalledMethod { +public class SuperclassWithCalledMethod { public static final String method = "method"; String method() { diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassCDependingOnClassB_SuperClassOfX.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassCDependingOnClassB_SuperclassOfX.java similarity index 78% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassCDependingOnClassB_SuperClassOfX.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassCDependingOnClassB_SuperclassOfX.java index 94e7455c65..ee4e2526e2 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassCDependingOnClassB_SuperClassOfX.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassCDependingOnClassB_SuperclassOfX.java @@ -1,10 +1,10 @@ package com.tngtech.archunit.core.importer.testexamples.integration; -public class ClassCDependingOnClassB_SuperClassOfX { +public class ClassCDependingOnClassB_SuperclassOfX { private ClassBDependingOnClassA classB; private int cState; - public ClassCDependingOnClassB_SuperClassOfX(int a, int b, int c) { + public ClassCDependingOnClassB_SuperclassOfX(int a, int b, int c) { this.cState = a + b + c; } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassXDependingOnClassesABCD.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassXDependingOnClassesABCD.java index d819a99ebb..0034f35b42 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassXDependingOnClassesABCD.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/integration/ClassXDependingOnClassesABCD.java @@ -1,6 +1,6 @@ package com.tngtech.archunit.core.importer.testexamples.integration; -public class ClassXDependingOnClassesABCD extends ClassCDependingOnClassB_SuperClassOfX implements InterfaceOfClassX { +public class ClassXDependingOnClassesABCD extends ClassCDependingOnClassB_SuperclassOfX implements InterfaceOfClassX { private ClassA classA; private ClassBDependingOnClassA classB; diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MiddleClass.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MiddleClass.java index ef61fd2ed6..9e9bdcea1d 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MiddleClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MiddleClass.java @@ -1,6 +1,6 @@ package com.tngtech.archunit.core.importer.testexamples.outsideofclasspath; -public class MiddleClass extends MissingSuperClass { +public class MiddleClass extends MissingSuperclass { public String someField; private MissingDependency missingDependency = new MissingDependency(); diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MissingSuperClass.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MissingSuperclass.java similarity index 70% rename from archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MissingSuperClass.java rename to archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MissingSuperclass.java index 5183e04b74..6d1fb1ad0e 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MissingSuperClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/testexamples/outsideofclasspath/MissingSuperclass.java @@ -1,9 +1,9 @@ package com.tngtech.archunit.core.importer.testexamples.outsideofclasspath; -public class MissingSuperClass { +public class MissingSuperclass { public String parentField; - public MissingSuperClass() { + public MissingSuperclass() { } public void overrideMe() { diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/ConditionEventsTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/ConditionEventsTest.java index b7ae5f37e6..cb3a4c981b 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/ConditionEventsTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/ConditionEventsTest.java @@ -39,9 +39,9 @@ public void handleViolations_reports_only_violations_referring_to_the_correct_ty ConditionEvents events = events( SimpleConditionEvent.satisfied(new CorrectType("do not handle"), "I'm not violated"), SimpleConditionEvent.violated(new WrongType(), "I'm violated, but wrong type"), - SimpleConditionEvent.violated(new WrongSuperType(), "I'm violated, but wrong type"), + SimpleConditionEvent.violated(new WrongSupertype(), "I'm violated, but wrong type"), SimpleConditionEvent.violated(new CorrectType("handle type"), "I'm violated and correct type"), - SimpleConditionEvent.violated(new CorrectSubType("handle sub type"), "I'm violated and correct sub type")); + SimpleConditionEvent.violated(new CorrectSubtype("handle sub type"), "I'm violated and correct sub type")); final Set handledFailures = new HashSet<>(); events.handleViolations(new ObjectToStringAndMessageJoiningTestHandler(handledFailures)); @@ -145,13 +145,13 @@ private static ConditionEvents events(ConditionEvent... events) { return result; } - private static class CorrectSubType extends CorrectType { - CorrectSubType(String message) { + private static class CorrectSubtype extends CorrectType { + CorrectSubtype(String message) { super(message); } } - static class CorrectType extends WrongSuperType { + static class CorrectType extends WrongSupertype { String message; CorrectType(String message) { @@ -167,7 +167,7 @@ public String toString() { private static class WrongType { } - private static class WrongSuperType { + private static class WrongSupertype { } } diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/conditions/ArchConditionsTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/conditions/ArchConditionsTest.java index d3df43ef62..79f96971f2 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/conditions/ArchConditionsTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/conditions/ArchConditionsTest.java @@ -50,11 +50,11 @@ public void never_call_method_where_target_owner_is_assignable_to() { JavaMethodCall callTodoNotCallMe = simulateCall.from(callingClass.getMethod("call"), 0).to(doNotCallMe); ArchCondition condition = never(callMethodWhere(target(name("doNotCallMe")) - .and(target(owner(assignableTo(SomeSuperClass.class)))))); + .and(target(owner(assignableTo(SomeSuperclass.class)))))); assertThat(condition).checking(callingClass) .containViolations(callTodoNotCallMe.getDescription()); - condition = never(callMethodWhere(target(name("doNotCallMe")).and(target(owner(type(SomeSuperClass.class)))))); + condition = never(callMethodWhere(target(name("doNotCallMe")).and(target(owner(type(SomeSuperclass.class)))))); assertThat(condition).checking(callingClass) .containNoViolation(); } @@ -145,7 +145,7 @@ void call() { } } - private static class SomeClass extends SomeSuperClass { + private static class SomeClass extends SomeSuperclass { void doNotCallMe() { } @@ -153,6 +153,6 @@ void callMe() { } } - private static class SomeSuperClass { + private static class SomeSuperclass { } -} \ No newline at end of file +} diff --git a/archunit/src/test/java/com/tngtech/archunit/library/ArchitecturesTest.java b/archunit/src/test/java/com/tngtech/archunit/library/ArchitecturesTest.java index 9fe271d8aa..883410c50d 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/ArchitecturesTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/ArchitecturesTest.java @@ -24,7 +24,7 @@ import com.tngtech.archunit.library.testclasses.onionarchitecture.domain.service.DomainServiceLayerClass; import com.tngtech.archunit.library.testclasses.second.three.any.SecondThreeAnyClass; import com.tngtech.archunit.library.testclasses.some.pkg.SomePkgClass; -import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubClass; +import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubclass; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.DataProviders; @@ -201,10 +201,10 @@ public void layered_architecture_gathers_all_layer_violations(LayeredArchitectur assertPatternMatches(result.getFailureReport().getDetails(), ImmutableSet.of( - expectedAccessViolationPattern(FirstAnyPkgClass.class, "call", SomePkgSubClass.class, "callMe"), + expectedAccessViolationPattern(FirstAnyPkgClass.class, "call", SomePkgSubclass.class, "callMe"), expectedAccessViolationPattern(SecondThreeAnyClass.class, "call", SomePkgClass.class, "callMe"), expectedAccessViolationPattern(FirstThreeAnyClass.class, "call", FirstAnyPkgClass.class, "callMe"), - fieldTypePattern(FirstAnyPkgClass.class, "illegalTarget", SomePkgSubClass.class), + fieldTypePattern(FirstAnyPkgClass.class, "illegalTarget", SomePkgSubclass.class), fieldTypePattern(FirstThreeAnyClass.class, "illegalTarget", FirstAnyPkgClass.class), fieldTypePattern(SecondThreeAnyClass.class, "illegalTarget", SomePkgClass.class))); } @@ -217,13 +217,13 @@ public static Object[][] toIgnore() { return DataProviders.testForEach( new RuleWithIgnore( - layeredArchitecture.ignoreDependency(FirstAnyPkgClass.class, SomePkgSubClass.class), + layeredArchitecture.ignoreDependency(FirstAnyPkgClass.class, SomePkgSubclass.class), "rule with ignore specified as class objects"), new RuleWithIgnore( - layeredArchitecture.ignoreDependency(FirstAnyPkgClass.class.getName(), SomePkgSubClass.class.getName()), + layeredArchitecture.ignoreDependency(FirstAnyPkgClass.class.getName(), SomePkgSubclass.class.getName()), "rule with ignore specified as class names"), new RuleWithIgnore( - layeredArchitecture.ignoreDependency(name(FirstAnyPkgClass.class.getName()), name(SomePkgSubClass.class.getName())), + layeredArchitecture.ignoreDependency(name(FirstAnyPkgClass.class.getName()), name(SomePkgSubclass.class.getName())), "rule with ignore specified as predicates")); } @@ -231,14 +231,14 @@ public static Object[][] toIgnore() { @UseDataProvider("toIgnore") public void layered_architecture_ignores_specified_violations(RuleWithIgnore layeredArchitectureWithIgnore) { JavaClasses classes = new ClassFileImporter().importClasses( - FirstAnyPkgClass.class, SomePkgSubClass.class, + FirstAnyPkgClass.class, SomePkgSubclass.class, SecondThreeAnyClass.class, SomePkgClass.class); EvaluationResult result = layeredArchitectureWithIgnore.rule.evaluate(classes); assertThat(singleLine(result)) .doesNotMatch(String.format(".*%s[^%s]*%s.*", - quote(FirstAnyPkgClass.class.getName()), NEW_LINE_REPLACE, quote(SomePkgSubClass.class.getName()))) + quote(FirstAnyPkgClass.class.getName()), NEW_LINE_REPLACE, quote(SomePkgSubclass.class.getName()))) .matches(String.format(".*%s[^%s]*%s.*", quote(SecondThreeAnyClass.class.getName()), NEW_LINE_REPLACE, quote(SomePkgClass.class.getName()))); } @@ -246,13 +246,13 @@ public void layered_architecture_ignores_specified_violations(RuleWithIgnore lay @Test public void layered_architecture_combines_multiple_ignores() { JavaClasses classes = new ClassFileImporter().importClasses( - FirstAnyPkgClass.class, SomePkgSubClass.class, + FirstAnyPkgClass.class, SomePkgSubclass.class, SecondThreeAnyClass.class, SomePkgClass.class); LayeredArchitecture layeredArchitecture = layeredArchitecture() .layer("One").definedBy(absolute("some.pkg..")) .whereLayer("One").mayNotBeAccessedByAnyLayer() - .ignoreDependency(FirstAnyPkgClass.class, SomePkgSubClass.class); + .ignoreDependency(FirstAnyPkgClass.class, SomePkgSubclass.class); assertThat(layeredArchitecture.evaluate(classes).hasViolation()).as("result has violation").isTrue(); diff --git a/archunit/src/test/java/com/tngtech/archunit/library/dependencies/SliceTest.java b/archunit/src/test/java/com/tngtech/archunit/library/dependencies/SliceTest.java index e8ce98e89f..13b953b45d 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/dependencies/SliceTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/dependencies/SliceTest.java @@ -7,7 +7,7 @@ import com.tngtech.archunit.library.testclasses.first.three.any.FirstThreeAnyClass; import com.tngtech.archunit.library.testclasses.second.any.pkg.SecondAnyClass; import com.tngtech.archunit.library.testclasses.second.three.any.SecondThreeAnyClass; -import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubClass; +import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubclass; import org.junit.Test; import static com.tngtech.archunit.testutil.Assertions.assertThatDependencies; @@ -21,7 +21,7 @@ public void dependencies_from_self() { assertThatDependencies(slice.getDependenciesFromSelf()).containOnly( from(FirstAnyPkgClass.class).to(Object.class) - .from(FirstAnyPkgClass.class).to(SomePkgSubClass.class) + .from(FirstAnyPkgClass.class).to(SomePkgSubclass.class) .from(FirstAnyPkgClass.class).to(SecondThreeAnyClass.class) .from(ClassOnlyDependentOnOwnPackageAndObject.class).to(Object.class) .from(FirstThreeAnyClass.class).to(Object.class) @@ -35,7 +35,7 @@ public void dependencies_to_self() { assertThatDependencies(slice.getDependenciesToSelf()).containOnly( from(SecondAnyClass.class).to(FirstAnyPkgClass.class) - .from(SomePkgSubClass.class).to(FirstAnyPkgClass.class) + .from(SomePkgSubclass.class).to(FirstAnyPkgClass.class) ); } @@ -52,4 +52,4 @@ private Slices slicesOfTestClasses() { JavaClasses testClasses = new ClassFileImporter().importPackages("com.tngtech.archunit.library.testclasses"); return Slices.matching("..testclasses.(*)..").transform(testClasses); } -} \ No newline at end of file +} diff --git a/archunit/src/test/java/com/tngtech/archunit/library/dependencies/SlicesShouldTest.java b/archunit/src/test/java/com/tngtech/archunit/library/dependencies/SlicesShouldTest.java index 47d1c9abf3..a97611ed9e 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/dependencies/SlicesShouldTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/dependencies/SlicesShouldTest.java @@ -13,7 +13,7 @@ import com.tngtech.archunit.library.testclasses.second.any.pkg.SecondAnyClass; import com.tngtech.archunit.library.testclasses.second.three.any.SecondThreeAnyClass; import com.tngtech.archunit.library.testclasses.some.pkg.SomePkgClass; -import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubClass; +import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubclass; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; @@ -45,35 +45,35 @@ public void slice_rules_should_ignore_configured_dependencies(SliceRule rule) { assertViolations(classes, rule) .contain(FirstThreeAnyClass.class, SecondThreeAnyClass.class) - .contain(FirstAnyPkgClass.class, SomePkgSubClass.class) + .contain(FirstAnyPkgClass.class, SomePkgSubclass.class) .contain(SecondAnyClass.class, FirstAnyPkgClass.class) .contain(SecondThreeAnyClass.class, SomePkgClass.class); rule = rule.ignoreDependency(classIn(".*\\.first\\.three\\..*"), DescribedPredicate.alwaysTrue()); assertViolations(classes, rule) .doNotContain(FirstThreeAnyClass.class, SecondThreeAnyClass.class) - .contain(FirstAnyPkgClass.class, SomePkgSubClass.class) + .contain(FirstAnyPkgClass.class, SomePkgSubclass.class) .contain(SecondAnyClass.class, FirstAnyPkgClass.class) .contain(SecondThreeAnyClass.class, SomePkgClass.class); - rule = rule.ignoreDependency(FirstAnyPkgClass.class.getName(), SomePkgSubClass.class.getName()); + rule = rule.ignoreDependency(FirstAnyPkgClass.class.getName(), SomePkgSubclass.class.getName()); assertViolations(classes, rule) .doNotContain(FirstThreeAnyClass.class, SecondThreeAnyClass.class) - .doNotContain(FirstAnyPkgClass.class, SomePkgSubClass.class) + .doNotContain(FirstAnyPkgClass.class, SomePkgSubclass.class) .contain(SecondAnyClass.class, FirstAnyPkgClass.class) .contain(SecondThreeAnyClass.class, SomePkgClass.class); rule = rule.ignoreDependency(SecondAnyClass.class, FirstAnyPkgClass.class); assertViolations(classes, rule) .doNotContain(FirstThreeAnyClass.class, SecondThreeAnyClass.class) - .doNotContain(FirstAnyPkgClass.class, SomePkgSubClass.class) + .doNotContain(FirstAnyPkgClass.class, SomePkgSubclass.class) .doNotContain(SecondAnyClass.class, FirstAnyPkgClass.class) .contain(SecondThreeAnyClass.class, SomePkgClass.class); rule = rule.ignoreDependency(DescribedPredicate.alwaysTrue(), classIn(".*\\.some\\.pkg\\..*")); assertViolations(classes, rule) .doNotContain(FirstThreeAnyClass.class, SecondThreeAnyClass.class) - .doNotContain(FirstAnyPkgClass.class, SomePkgSubClass.class) + .doNotContain(FirstAnyPkgClass.class, SomePkgSubclass.class) .doNotContain(SecondAnyClass.class, FirstAnyPkgClass.class) .doNotContain(SecondThreeAnyClass.class, SomePkgClass.class); } diff --git a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/first/any/pkg/FirstAnyPkgClass.java b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/first/any/pkg/FirstAnyPkgClass.java index 5d13837a14..12681fac02 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/first/any/pkg/FirstAnyPkgClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/first/any/pkg/FirstAnyPkgClass.java @@ -1,11 +1,11 @@ package com.tngtech.archunit.library.testclasses.first.any.pkg; import com.tngtech.archunit.library.testclasses.second.three.any.SecondThreeAnyClass; -import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubClass; +import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubclass; @SuppressWarnings("WeakerAccess") public class FirstAnyPkgClass { - SomePkgSubClass illegalTarget; + SomePkgSubclass illegalTarget; SecondThreeAnyClass legalTarget; // The importer will never find the bytecode of FirstAnyPkgClass[].class, thus it will always be a stub in the same package FirstAnyPkgClass[] evilArrayToCauseOriginallyUnimportedClass; diff --git a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/SomePkgClass.java b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/SomePkgClass.java index 7d91117812..21d270298e 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/SomePkgClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/SomePkgClass.java @@ -1,9 +1,9 @@ package com.tngtech.archunit.library.testclasses.some.pkg; -import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubClass; +import com.tngtech.archunit.library.testclasses.some.pkg.sub.SomePkgSubclass; public class SomePkgClass { - SomePkgSubClass legalTarget; + SomePkgSubclass legalTarget; void call() { legalTarget.callMe(); diff --git a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/sub/SomePkgSubClass.java b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/sub/SomePkgSubclass.java similarity index 89% rename from archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/sub/SomePkgSubClass.java rename to archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/sub/SomePkgSubclass.java index 70b2efec96..27964632f7 100644 --- a/archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/sub/SomePkgSubClass.java +++ b/archunit/src/test/java/com/tngtech/archunit/library/testclasses/some/pkg/sub/SomePkgSubclass.java @@ -2,7 +2,7 @@ import com.tngtech.archunit.library.testclasses.first.any.pkg.FirstAnyPkgClass; -public class SomePkgSubClass { +public class SomePkgSubclass { FirstAnyPkgClass legalTarget; void call() { diff --git a/docs/userguide/006_The_Core_API.adoc b/docs/userguide/006_The_Core_API.adoc index d63509733b..9b48fadafd 100644 --- a/docs/userguide/006_The_Core_API.adoc +++ b/docs/userguide/006_The_Core_API.adoc @@ -170,11 +170,11 @@ class ClassAccessing { } class ClassBeingAccessed -class SuperClassBeingAccessed { +class SuperclassBeingAccessed { Object accessedField } -SuperClassBeingAccessed <|-- ClassBeingAccessed +SuperclassBeingAccessed <|-- ClassBeingAccessed ClassAccessing o-- ClassBeingAccessed ---- @@ -226,7 +226,7 @@ Two things might seem strange at the first look. First, why can a target resolve to zero matching members? The reason is that the set of classes that was imported does not need to have all classes involved within this resolution process. -Consider the above example, if `SuperClassBeingAccessed` would not be imported, ArchUnit would +Consider the above example, if `SuperclassBeingAccessed` would not be imported, ArchUnit would have no way of knowing where the actual targeted field resides. Thus in this case the resolution would return zero elements. diff --git a/docs/userguide/007_The_Lang_API.adoc b/docs/userguide/007_The_Lang_API.adoc index 2102b13b2e..a8870d7993 100644 --- a/docs/userguide/007_The_Lang_API.adoc +++ b/docs/userguide/007_The_Lang_API.adoc @@ -210,7 +210,7 @@ HasName.Predicates.name("").and(JavaClass.Predicates.type(Serializable.class)) JavaClass.Predicates.type(Serializable.class).and(HasName.Predicates.name("")) // Does compile, because the compiler now sees name(..) as a predicate for JavaClass -DescribedPredicate name = HasName.Predicates.name("").forSubType(); +DescribedPredicate name = HasName.Predicates.name("").forSubtype(); name.and(JavaClass.Predicates.type(Serializable.class)); ---- @@ -361,4 +361,4 @@ It is possible to add comments to ignore patterns by prefixing the line with a ' ---- # There are many known violations where LegacyService is involved; we'll ignore them all .*some\.pkg\.LegacyService.* ----- \ No newline at end of file +---- From 96dc8569a7f3867e8c00525a123735fac10bb93e Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Wed, 23 Dec 2020 22:25:12 +0100 Subject: [PATCH 06/11] force use of list in `TypeParametersBuilder` Since the order of type parameters matters we should not allow a generic `Collection` to be passed to the `TypeParametersBuilder` and then convert it to a list, but instead force a list to be passed right away. The only other type ever used was an empty set, so this has not caused any problems so far, but for future maintenance I have fixed this now. Signed-off-by: Peter Gafert --- .../archunit/core/importer/ClassFileImportRecord.java | 2 +- .../com/tngtech/archunit/core/importer/DomainBuilders.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java index 9d19ab6c86..86fe30ea4d 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java @@ -41,7 +41,7 @@ class ClassFileImportRecord { private static final Logger LOG = LoggerFactory.getLogger(ClassFileImportRecord.class); private static final TypeParametersBuilder NO_TYPE_PARAMETERS = - new TypeParametersBuilder(Collections.>emptySet()); + new TypeParametersBuilder(Collections.>emptyList()); private final Map classes = new HashMap<>(); diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java index 7568944c65..3643afde5d 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java @@ -16,7 +16,6 @@ package com.tngtech.archunit.core.importer; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashMap; @@ -541,9 +540,9 @@ public List getUpperBounds(Iterable> all } static class TypeParametersBuilder { - private final Collection> typeParameterBuilders; + private final List> typeParameterBuilders; - TypeParametersBuilder(Collection> typeParameterBuilders) { + TypeParametersBuilder(List> typeParameterBuilders) { this.typeParameterBuilders = typeParameterBuilders; } From 00bbcb2ad8ec42e54533c4ee93379b02b0e015f2 Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Wed, 6 Jan 2021 15:56:36 +0100 Subject: [PATCH 07/11] prevent creation of parameterized types without type arguments To be consistent with the Reflection API we should not create a `JavaParameterizedType` with an empty list of type arguments for generic type signatures. So far for `List` we would e.g. create a `JavaParameterizedType{String}` as upper wildcard bound, even though `String` obviously has no type parameters. The Reflection API would return the `Class` directly as upper bound in this case, so we should return the `JavaClass{String}` directly here. It feels a little fishy to have `JavaParameterizedTypeBuilder` return a `JavaClass`, if there are no type arguments (inconsistent pattern, if `FooBuilder` always returns `Foo` in all other cases), but due to the visitor pattern it is not trivial to know ahead of time which builder is the correct one to use. Since `JavaParameterizedTypeBuilder` is an implementation detail and usually encapsulated by referring to a generic `JavaTypeBuilder`, I still decided to go this simple way. It would be fair to simply give `JavaParameterizedTypeBuilder` a name that would reflect that both `JavaParameterizedType` and `JavaClass` could be created, but I could not come up with a good name. Signed-off-by: Peter Gafert --- .../core/importer/DomainBuilders.java | 6 +- .../core/domain/JavaTypeVariableTest.java | 6 +- .../ClassFileImporterGenericClassesTest.java | 7 ++- .../tngtech/archunit/testutil/Assertions.java | 9 +++ .../testutil/assertion/JavaTypeAssertion.java | 3 +- .../assertion/JavaTypeVariableAssertion.java | 61 +++++++++++++------ 6 files changed, 63 insertions(+), 29 deletions(-) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java index 3643afde5d..f257a6de89 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java @@ -632,9 +632,11 @@ void addTypeArgument(JavaTypeCreationProcess typeCreationProcess) { } @Override - public JavaParameterizedType build(OWNER owner, Iterable> allTypeParametersInContext, ClassesByTypeName classes) { + public JavaType build(OWNER owner, Iterable> allTypeParametersInContext, ClassesByTypeName classes) { List typeArguments = buildJavaTypes(typeArgumentCreationProcesses, owner, allTypeParametersInContext, classes); - return new ImportedParameterizedType(classes.get(type.getFullyQualifiedClassName()), typeArguments); + return typeArguments.isEmpty() + ? classes.get(type.getFullyQualifiedClassName()) + : new ImportedParameterizedType(classes.get(type.getFullyQualifiedClassName()), typeArguments); } String getTypeName() { diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaTypeVariableTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaTypeVariableTest.java index 1ce12894cc..88e8bd8c19 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaTypeVariableTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaTypeVariableTest.java @@ -9,7 +9,7 @@ import static com.tngtech.archunit.testutil.Assertions.assertThat; import static com.tngtech.archunit.testutil.Assertions.assertThatType; -import static com.tngtech.archunit.testutil.Assertions.assertThatTypes; +import static com.tngtech.archunit.testutil.Assertions.assertThatTypeErasuresOf; public class JavaTypeVariableTest { @@ -45,8 +45,8 @@ class ClassWithUnboundTypeParameter & Serializ JavaTypeVariable type = new ClassFileImporter().importClass(ClassWithUnboundTypeParameter.class).getTypeParameters().get(0); - assertThatTypes(type.getBounds()).matchExactly(HashMap.class, Serializable.class); - assertThatTypes(type.getUpperBounds()).matchExactly(HashMap.class, Serializable.class); + assertThatTypeErasuresOf(type.getBounds()).matchExactly(HashMap.class, Serializable.class); + assertThatTypeErasuresOf(type.getUpperBounds()).matchExactly(HashMap.class, Serializable.class); } @Test diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericClassesTest.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericClassesTest.java index 7fd6dc6935..c2f1c9ee78 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericClassesTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericClassesTest.java @@ -24,6 +24,7 @@ import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.ExpectedConcreteTypeVariable.typeVariable; import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.ExpectedConcreteTypeVariableArray.typeVariableArray; import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.ExpectedConcreteWildcardType.wildcardType; +import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.concreteClass; import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.parameterizedType; import static com.tngtech.java.junit.dataprovider.DataProviders.$; import static com.tngtech.java.junit.dataprovider.DataProviders.$$; @@ -492,7 +493,7 @@ class ClassWithComplexTypeParameters< .hasTypeParameter("A") .withBoundsMatching( parameterizedType(List.class).withWildcardTypeParameter(), - parameterizedType(Serializable.class), + concreteClass(Serializable.class), parameterizedType(Comparable.class).withTypeArguments(typeVariable("A"))) .hasTypeParameter("B") .withBoundsMatching(typeVariable("A")) @@ -502,7 +503,7 @@ class ClassWithComplexTypeParameters< parameterizedType(Map.Entry.class).withTypeArguments( typeVariable("A"), parameterizedType(Map.Entry.class).withTypeArguments( - parameterizedType(String.class), typeVariable("B"))), + concreteClass(String.class), typeVariable("B"))), parameterizedType(Map.class).withTypeArguments( wildcardType().withUpperBound(String.class), parameterizedType(Map.class).withTypeArguments( @@ -558,7 +559,7 @@ class ClassWithComplexTypeParametersWithConcreteArrayBounds< parameterizedType(Map.class).withTypeArguments( wildcardType().withLowerBound(String[][][].class), wildcardType()), - parameterizedType(Serializable[][].class))) + concreteClass(Serializable[][].class))) ); } diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/Assertions.java b/archunit/src/test/java/com/tngtech/archunit/testutil/Assertions.java index a27b573443..adee9f10c9 100644 --- a/archunit/src/test/java/com/tngtech/archunit/testutil/Assertions.java +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/Assertions.java @@ -7,6 +7,7 @@ import java.util.Set; import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.tngtech.archunit.base.DescribedPredicate; import com.tngtech.archunit.base.Optional; @@ -104,6 +105,14 @@ public static JavaTypesAssertion assertThatTypes(Iterable ja return new JavaTypesAssertion(javaTypes); } + public static JavaTypesAssertion assertThatTypeErasuresOf(Iterable javaTypes) { + ImmutableList.Builder erasures = ImmutableList.builder(); + for (JavaType javaType : javaTypes) { + erasures.add(javaType.toErasure()); + } + return new JavaTypesAssertion(erasures.build()); + } + public static JavaPackagesAssertion assertThatPackages(Iterable javaPackages) { return new JavaPackagesAssertion(javaPackages); } diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeAssertion.java b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeAssertion.java index 2bd4a81ec7..408549b09e 100644 --- a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeAssertion.java +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeAssertion.java @@ -89,7 +89,8 @@ public JavaTypeVariableOfClassAssertion hasOnlyTypeParameter(String name) { } private JavaClass actualClass() { - return actual instanceof JavaClass ? (JavaClass) actual : actual.toErasure(); + assertThat(actual).as(describeAssertion(actual.getName())).isInstanceOf(JavaClass.class); + return (JavaClass) actual; } private String ensureArrayName(String name) { diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeVariableAssertion.java b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeVariableAssertion.java index 820227e0c4..85fa45df50 100644 --- a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeVariableAssertion.java +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeVariableAssertion.java @@ -7,6 +7,7 @@ import com.google.common.base.Joiner; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; +import com.tngtech.archunit.core.domain.JavaClass; import com.tngtech.archunit.core.domain.JavaGenericArrayType; import com.tngtech.archunit.core.domain.JavaParameterizedType; import com.tngtech.archunit.core.domain.JavaType; @@ -29,7 +30,7 @@ public JavaTypeVariableAssertion(JavaTypeVariable actual) { } public void hasBoundsMatching(Class... bounds) { - hasBoundsMatching(ExpectedConcreteParameterizedType.wrap(bounds)); + hasBoundsMatching(ExpectedConcreteClass.wrap(bounds)); } public void hasBoundsMatching(ExpectedConcreteType... bounds) { @@ -45,6 +46,10 @@ private static void assertConcreteTypesMatch(DescriptionContext context, List expectedType) { + return new ExpectedConcreteClass(expectedType); + } + public static ExpectedConcreteParameterizedType parameterizedType(Class expectedType) { return new ExpectedConcreteParameterizedType(expectedType); } @@ -53,16 +58,39 @@ public interface ExpectedConcreteType { void assertMatchWith(JavaType actual, DescriptionContext context); } + public static class ExpectedConcreteClass implements ExpectedConcreteType { + private final Class clazz; + + private ExpectedConcreteClass(Class clazz) { + this.clazz = clazz; + } + + @Override + public void assertMatchWith(JavaType actual, DescriptionContext context) { + DescriptionContext newContext = context.describe(ensureSimpleName(actual.getName())); + assertThat(actual).as(newContext.toString()).isInstanceOf(JavaClass.class); + assertThatType(actual).as(newContext.toString()).matches(clazz); + } + + static ExpectedConcreteType[] wrap(Class[] classes) { + ExpectedConcreteType[] result = new ExpectedConcreteType[classes.length]; + for (int i = 0; i < classes.length; i++) { + result[i] = new ExpectedConcreteClass(classes[i]); + } + return result; + } + } + public static class ExpectedConcreteParameterizedType implements ExpectedConcreteType { - private Type type; + private final Type type; private final List typeParameters = new ArrayList<>(); private ExpectedConcreteParameterizedType(Type type) { this.type = type; } - public ExpectedConcreteType withTypeArguments(Type... type) { - return withTypeArguments(ExpectedConcreteParameterizedType.wrap(type)); + public ExpectedConcreteType withTypeArguments(Class... type) { + return withTypeArguments(ExpectedConcreteClass.wrap(type)); } public ExpectedConcreteType withTypeArguments(ExpectedConcreteType... type) { @@ -75,7 +103,7 @@ public ExpectedConcreteType withWildcardTypeParameter() { } public ExpectedConcreteType withWildcardTypeParameterWithUpperBound(Class bound) { - return withWildcardTypeParameterWithUpperBound(new ExpectedConcreteParameterizedType(bound)); + return withWildcardTypeParameterWithUpperBound(new ExpectedConcreteClass(bound)); } public ExpectedConcreteType withWildcardTypeParameterWithUpperBound(ExpectedConcreteType bound) { @@ -83,7 +111,7 @@ public ExpectedConcreteType withWildcardTypeParameterWithUpperBound(ExpectedConc } public ExpectedConcreteType withWildcardTypeParameterWithLowerBound(Class bound) { - return withWildcardTypeParameterWithLowerBound(new ExpectedConcreteParameterizedType(bound)); + return withWildcardTypeParameterWithLowerBound(new ExpectedConcreteClass(bound)); } public ExpectedConcreteType withWildcardTypeParameterWithLowerBound(ExpectedConcreteType bound) { @@ -97,14 +125,15 @@ public ExpectedConcreteType withWildcardTypeParameters(ExpectedConcreteWildcardT @Override public void assertMatchWith(JavaType actual, DescriptionContext context) { DescriptionContext newContext = context.describe(ensureSimpleName(actual.getName())); - assertThatType(actual).as(newContext.toString()).matches(type); + assertThatType(actual.toErasure()).as(newContext.toString()).matches(type); assertTypeParametersMatch(actual, newContext); } private void assertTypeParametersMatch(JavaType actual, DescriptionContext context) { DescriptionContext parameterContext = context.step("type parameters").describeTypeParameters(); - if (!typeParameters.isEmpty() && !(actual instanceof JavaParameterizedType)) { - Assert.fail(String.format("%s: Not parameterized, but expected to have type parameters %s", parameterContext, typeParameters)); + if (!(actual instanceof JavaParameterizedType)) { + Assert.fail(String.format( + "%s: Actual type is not parameterized, but expected to be parameterized with type parameters %s", parameterContext, typeParameters)); } List actualTypeParameters = ((JavaParameterizedType) actual).getActualTypeArguments(); assertConcreteTypesMatch(parameterContext, actualTypeParameters, typeParameters); @@ -118,14 +147,6 @@ public String toString() { private String formatTypeParameters() { return !typeParameters.isEmpty() ? "<" + Joiner.on(", ").join(typeParameters) + ">" : ""; } - - static ExpectedConcreteType[] wrap(Type... types) { - ExpectedConcreteType[] result = new ExpectedConcreteType[types.length]; - for (int i = 0; i < types.length; i++) { - result[i] = new ExpectedConcreteParameterizedType(types[i]); - } - return result; - } } public static class ExpectedConcreteWildcardType implements ExpectedConcreteType { @@ -168,7 +189,7 @@ private void assertBoundsMatch(List actualBounds, List bound) { - return withUpperBound(new ExpectedConcreteParameterizedType(bound)); + return withUpperBound(new ExpectedConcreteClass(bound)); } public ExpectedConcreteWildcardType withUpperBound(ExpectedConcreteType bound) { @@ -177,7 +198,7 @@ public ExpectedConcreteWildcardType withUpperBound(ExpectedConcreteType bound) { } public ExpectedConcreteWildcardType withLowerBound(Class bound) { - return withLowerBound(new ExpectedConcreteParameterizedType(bound)); + return withLowerBound(new ExpectedConcreteClass(bound)); } public ExpectedConcreteWildcardType withLowerBound(ExpectedConcreteType bound) { @@ -199,7 +220,7 @@ private ExpectedConcreteTypeVariable(String name) { } public ExpectedConcreteTypeVariable withUpperBounds(Class... bounds) { - return withUpperBounds(ExpectedConcreteParameterizedType.wrap(bounds)); + return withUpperBounds(ExpectedConcreteClass.wrap(bounds)); } public ExpectedConcreteTypeVariable withUpperBounds(ExpectedConcreteType... bounds) { From cf704846942e18660f872c58fefd3ce980f584fe Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Wed, 23 Dec 2020 21:59:39 +0100 Subject: [PATCH 08/11] use instance scoped `BoundProcessors` instead of a single static one This was a little premature optimization. I assumed creating a new `BoundProcessor` for every `JavaClass` would be an unnecessary overhead. On the other hand having a single shared instance has downsides for maintainability and a higher danger to introduce bugs. When I tried to measure performance I could not detect any difference between having a single static `BoundProcessor` and instantiating one for every class, so we should go for the instance scoped one. Also the instance scoped pattern is easier to apply to the superclass case, so it makes sense to refactor this first. Signed-off-by: Peter Gafert --- .../importer/JavaGenericTypeImporter.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaGenericTypeImporter.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaGenericTypeImporter.java index ba0b7e4b74..505fbf32cf 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaGenericTypeImporter.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaGenericTypeImporter.java @@ -53,24 +53,24 @@ static void parseAsmTypeSignature(String signature, DeclarationHandler declarati JavaTypeVariableProcessor typeVariableProcessor = new JavaTypeVariableProcessor(); new SignatureReader(signature).accept(typeVariableProcessor); - declarationHandler.onDeclaredTypeParameters(new TypeParametersBuilder(typeVariableProcessor.typeParameterBuilders)); + declarationHandler.onDeclaredTypeParameters(new TypeParametersBuilder(typeVariableProcessor.getTypeParameterBuilders())); } private static class JavaTypeVariableProcessor extends SignatureVisitor { - private static final BoundProcessor boundProcessor = new BoundProcessor(); - - private final List> typeParameterBuilders = new ArrayList<>(); + private final BoundProcessor boundProcessor = new BoundProcessor(); JavaTypeVariableProcessor() { super(ASM_API_VERSION); } + List> getTypeParameterBuilders() { + return boundProcessor.typeParameterBuilders; + } + @Override public void visitFormalTypeParameter(String name) { log.trace("Encountered type parameter {}", name); - JavaTypeParameterBuilder type = new JavaTypeParameterBuilder<>(name); - boundProcessor.setCurrentType(type); - typeParameterBuilders.add(type); + boundProcessor.addTypeParameter(name); } @Override @@ -84,6 +84,8 @@ public SignatureVisitor visitInterfaceBound() { } private static class BoundProcessor extends SignatureVisitor { + private final List> typeParameterBuilders = new ArrayList<>(); + private JavaTypeParameterBuilder currentType; private JavaParameterizedTypeBuilder currentBound; @@ -91,8 +93,10 @@ private static class BoundProcessor extends SignatureVisitor { super(ASM_API_VERSION); } - void setCurrentType(JavaTypeParameterBuilder type) { - this.currentType = type; + void addTypeParameter(String typeName) { + currentType = new JavaTypeParameterBuilder<>(typeName); + currentBound = null; + typeParameterBuilders.add(currentType); } @Override From 06f1ac4e214a4e23ad89c9ad8083c13f4115511a Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Tue, 22 Sep 2020 23:39:19 +0200 Subject: [PATCH 09/11] rename `JavaGenericTypeImporter` -> `JavaClassSignatureImporter` We should separate importing the signature of fields or methods in the future, but it makes sense to also integrate generic superclass and interface handling here, because the scope is very similar. I have thus renamed the class to be a "class signature importer", which is less generic than "generic type importer", but leaves room to handle other class signature related parsing. For now it continues to only handle type parameters, but in the next step we can extend this to generic superclass parsing. Signed-off-by: Peter Gafert --- .../core/importer/JavaClassProcessor.java | 2 +- ...orter.java => JavaClassSignatureImporter.java} | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) rename archunit/src/main/java/com/tngtech/archunit/core/importer/{JavaGenericTypeImporter.java => JavaClassSignatureImporter.java} (96%) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java index ea5e973e90..1dc836c730 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java @@ -114,7 +114,7 @@ public void visit(int version, int access, String name, String signature, String className = descriptor.getFullyQualifiedClassName(); declarationHandler.onNewClass(className, superclassName, interfaceNames); - JavaGenericTypeImporter.parseAsmTypeSignature(signature, declarationHandler); + JavaClassSignatureImporter.parseAsmTypeSignature(signature, declarationHandler); } private boolean alreadyImported(JavaClassDescriptor descriptor) { diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaGenericTypeImporter.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassSignatureImporter.java similarity index 96% rename from archunit/src/main/java/com/tngtech/archunit/core/importer/JavaGenericTypeImporter.java rename to archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassSignatureImporter.java index 505fbf32cf..fe46c16bc3 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaGenericTypeImporter.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassSignatureImporter.java @@ -41,8 +41,8 @@ import static com.tngtech.archunit.core.domain.DomainObjectCreationContext.createGenericArrayType; import static com.tngtech.archunit.core.importer.ClassFileProcessor.ASM_API_VERSION; -class JavaGenericTypeImporter { - private static final Logger log = LoggerFactory.getLogger(JavaGenericTypeImporter.class); +class JavaClassSignatureImporter { + private static final Logger log = LoggerFactory.getLogger(JavaClassSignatureImporter.class); static void parseAsmTypeSignature(String signature, DeclarationHandler declarationHandler) { if (signature == null) { @@ -51,15 +51,15 @@ static void parseAsmTypeSignature(String signature, DeclarationHandler declarati log.trace("Analyzing signature: {}", signature); - JavaTypeVariableProcessor typeVariableProcessor = new JavaTypeVariableProcessor(); - new SignatureReader(signature).accept(typeVariableProcessor); - declarationHandler.onDeclaredTypeParameters(new TypeParametersBuilder(typeVariableProcessor.getTypeParameterBuilders())); + SignatureProcessor signatureProcessor = new SignatureProcessor(); + new SignatureReader(signature).accept(signatureProcessor); + declarationHandler.onDeclaredTypeParameters(new TypeParametersBuilder(signatureProcessor.getTypeParameterBuilders())); } - private static class JavaTypeVariableProcessor extends SignatureVisitor { + private static class SignatureProcessor extends SignatureVisitor { private final BoundProcessor boundProcessor = new BoundProcessor(); - JavaTypeVariableProcessor() { + SignatureProcessor() { super(ASM_API_VERSION); } @@ -238,7 +238,6 @@ String getFinishedName(String name) { } @Override - @SuppressWarnings("ConstantConditions") // we never return null by convention public void visitClassType(String internalObjectName) { JavaClassDescriptor type = typeMapping.apply(JavaClassDescriptorImporter.createFromAsmObjectTypeName(internalObjectName)); log.trace("Encountered {} for {}: Class type {}", typeArgumentType.description, parameterizedType.getTypeName(), type.getFullyQualifiedClassName()); From d92e8ffd5f5df194fec14981530df739e4ef45d6 Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Tue, 5 Jan 2021 23:20:17 +0100 Subject: [PATCH 10/11] add generic superclass to `JavaClass` Unfortunately signature handling is a little bit inconsistent. If the type is not generic the signature is `null` and we need to rely on the superclass name passed to `visit(..)`. If the type is generic we will now derive the raw superclass from the erasure of the generic superclass. This seems logically consistent. It could however break existing behavior, if for some reason our assumption is wrong and the erasure of the generic superclass is not always equivalent to the raw superclass whose type name is passed as `superclass` string to `visit(..)`. To be consistent with `HasType`, which offers `getType()` and `getRawType()` we have decided to name the methods `JavaClass.getRawSuperclass()` for the raw superclass and `JavaClass.getSuperclass()` for the generic superclass (i.e. the generic case will be the "default" case as opposed to the reflection API where this is always named explicitly as "generic type"). Signed-off-by: Peter Gafert --- .../domain/DomainObjectCreationContext.java | 4 + .../archunit/core/domain/ImportContext.java | 2 + .../archunit/core/domain/JavaClass.java | 64 ++- .../archunit/core/domain/JavaType.java | 14 + .../core/importer/ClassFileImportRecord.java | 10 + .../core/importer/ClassFileProcessor.java | 5 + .../core/importer/ClassGraphCreator.java | 22 + .../core/importer/DomainBuilders.java | 5 + .../core/importer/JavaClassProcessor.java | 2 + .../importer/JavaClassSignatureImporter.java | 45 +- .../archunit/core/domain/JavaTypeTest.java | 21 + .../ClassFileImporterGenericClassesTest.java | 10 +- ...lassFileImporterGenericSuperclassTest.java | 423 ++++++++++++++++++ .../core/importer/ImportTestUtils.java | 6 + .../assertion/DescriptionContext.java | 81 ++++ .../assertion/ExpectedConcreteType.java | 255 +++++++++++ .../testutil/assertion/JavaTypeAssertion.java | 24 +- .../assertion/JavaTypeVariableAssertion.java | 340 +------------- .../assertion/JavaTypesAssertion.java | 13 + 19 files changed, 993 insertions(+), 353 deletions(-) create mode 100644 archunit/src/test/java/com/tngtech/archunit/core/domain/JavaTypeTest.java create mode 100644 archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericSuperclassTest.java create mode 100644 archunit/src/test/java/com/tngtech/archunit/testutil/assertion/DescriptionContext.java create mode 100644 archunit/src/test/java/com/tngtech/archunit/testutil/assertion/ExpectedConcreteType.java diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/DomainObjectCreationContext.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/DomainObjectCreationContext.java index 8486545f08..9ba42f6ec7 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/DomainObjectCreationContext.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/DomainObjectCreationContext.java @@ -78,6 +78,10 @@ public static void completeTypeParameters(JavaClass javaClass, ImportContext imp javaClass.completeTypeParametersFrom(importContext); } + public static void completeGenericSuperclass(JavaClass javaClass, ImportContext importContext) { + javaClass.completeGenericSuperclassFrom(importContext); + } + public static void completeMembers(JavaClass javaClass, ImportContext importContext) { javaClass.completeMembers(importContext); } 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 3f123246e4..0a5f505f5f 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 @@ -26,6 +26,8 @@ public interface ImportContext { Optional createSuperclass(JavaClass owner); + Optional createGenericSuperclass(JavaClass owner); + Set createInterfaces(JavaClass owner); List> createTypeParameters(JavaClass owner); 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 c80aa3b569..d48fed6bd7 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 @@ -54,6 +54,7 @@ import static com.tngtech.archunit.core.domain.JavaClass.Functions.GET_SIMPLE_NAME; import static com.tngtech.archunit.core.domain.JavaConstructor.CONSTRUCTOR_NAME; import static com.tngtech.archunit.core.domain.JavaModifier.ENUM; +import static com.tngtech.archunit.core.domain.JavaType.Functions.TO_ERASURE; import static com.tngtech.archunit.core.domain.properties.CanBeAnnotated.Utils.toAnnotationOfType; import static com.tngtech.archunit.core.domain.properties.HasName.Functions.GET_NAME; import static com.tngtech.archunit.core.domain.properties.HasType.Functions.GET_RAW_TYPE; @@ -80,7 +81,7 @@ public class JavaClass implements JavaType, HasName.AndFullName, HasAnnotations< private Set members = emptySet(); private Set constructors = emptySet(); private Optional staticInitializer = Optional.absent(); - private Optional superclass = Optional.absent(); + private Superclass superclass = Superclass.ABSENT; private final Supplier> allRawSuperclasses = Suppliers.memoize(new Supplier>() { @Override public List get() { @@ -102,9 +103,7 @@ public Set get() { result.add(i); result.addAll(i.getAllInterfaces()); } - if (superclass.isPresent()) { - result.addAll(superclass.get().getAllInterfaces()); - } + result.addAll(superclass.getAllInterfaces()); return result.build(); } }); @@ -657,7 +656,12 @@ public JavaClass toErasure() { @PublicAPI(usage = ACCESS) public Optional getRawSuperclass() { - return superclass; + return superclass.getRaw(); + } + + @PublicAPI(usage = ACCESS) + public Optional getSuperclass() { + return superclass.get(); } /** @@ -1311,9 +1315,10 @@ public Set get() { } private void completeSuperclassFrom(ImportContext context) { - superclass = context.createSuperclass(this); - if (superclass.isPresent()) { - superclass.get().subclasses.add(this); + Optional rawSuperclass = context.createSuperclass(this); + if (rawSuperclass.isPresent()) { + rawSuperclass.get().subclasses.add(this); + this.superclass = this.superclass.withRawType(rawSuperclass.get()); } } @@ -1332,6 +1337,13 @@ void completeTypeParametersFrom(ImportContext context) { typeParameters = context.createTypeParameters(this); } + void completeGenericSuperclassFrom(ImportContext context) { + Optional genericSuperclass = context.createGenericSuperclass(this); + if (genericSuperclass.isPresent()) { + superclass = superclass.withGenericType(genericSuperclass.get()); + } + } + void completeMembers(final ImportContext context) { fields = context.createFields(this); methods = context.createMethods(this); @@ -1408,6 +1420,42 @@ public boolean isAnonymous() { return isAnonymousClass(); } + private static class Superclass { + private static final Superclass ABSENT = new Superclass(Optional.absent()); + + private final Optional rawType; + private final Optional type; + + private Superclass(JavaType type) { + this(Optional.of(type)); + } + + private Superclass(Optional type) { + this.rawType = type.transform(TO_ERASURE); + this.type = type; + } + + Optional getRaw() { + return rawType; + } + + Optional get() { + return type.or(rawType); + } + + Set getAllInterfaces() { + return rawType.isPresent() ? rawType.get().getAllInterfaces() : Collections.emptySet(); + } + + Superclass withRawType(JavaClass newRawType) { + return new Superclass(newRawType); + } + + Superclass withGenericType(JavaType newGenericType) { + return new Superclass(newGenericType); + } + } + public static final class Functions { private Functions() { } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaType.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaType.java index 7aebefea55..7b386eed85 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaType.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaType.java @@ -16,6 +16,7 @@ package com.tngtech.archunit.core.domain; import com.tngtech.archunit.PublicAPI; +import com.tngtech.archunit.base.ChainableFunction; import com.tngtech.archunit.core.domain.properties.HasName; import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; @@ -37,4 +38,17 @@ public interface JavaType extends HasName { */ @PublicAPI(usage = ACCESS) JavaClass toErasure(); + + final class Functions { + private Functions() { + } + + @PublicAPI(usage = ACCESS) + public static final ChainableFunction TO_ERASURE = new ChainableFunction() { + @Override + public JavaClass apply(JavaType input) { + return input.toErasure(); + } + }; + } } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java index 86fe30ea4d..7cacf48340 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileImportRecord.java @@ -30,6 +30,7 @@ import com.tngtech.archunit.core.domain.JavaClass; import com.tngtech.archunit.core.domain.JavaMember; import com.tngtech.archunit.core.domain.JavaMethod; +import com.tngtech.archunit.core.importer.DomainBuilders.JavaParameterizedTypeBuilder; import com.tngtech.archunit.core.importer.DomainBuilders.JavaTypeParameterBuilder; import com.tngtech.archunit.core.importer.DomainBuilders.TypeParametersBuilder; import org.slf4j.Logger; @@ -48,6 +49,7 @@ class ClassFileImportRecord { private final Map superclassNamesByOwner = new HashMap<>(); private final SetMultimap interfaceNamesByOwner = HashMultimap.create(); private final Map typeParametersBuilderByOwner = new HashMap<>(); + private final Map> genericSuperclassBuilderByOwner = new HashMap<>(); private final SetMultimap fieldBuildersByOwner = HashMultimap.create(); private final SetMultimap methodBuildersByOwner = HashMultimap.create(); private final SetMultimap constructorBuildersByOwner = HashMultimap.create(); @@ -75,6 +77,10 @@ void addTypeParameters(String ownerName, TypeParametersBuilder builder) { typeParametersBuilderByOwner.put(ownerName, builder); } + void addGenericSuperclass(String ownerName, JavaParameterizedTypeBuilder genericSuperclassBuilder) { + genericSuperclassBuilderByOwner.put(ownerName, genericSuperclassBuilder); + } + void addField(String ownerName, DomainBuilders.JavaFieldBuilder fieldBuilder) { fieldBuildersByOwner.put(ownerName, fieldBuilder); } @@ -125,6 +131,10 @@ TypeParametersBuilder getTypeParameterBuildersFor(String ownerName) { return typeParametersBuilderByOwner.get(ownerName); } + Optional> getGenericSuperclassFor(JavaClass owner) { + return Optional.fromNullable(genericSuperclassBuilderByOwner.get(owner.getName())); + } + Set getFieldBuildersFor(String ownerName) { return fieldBuildersByOwner.get(ownerName); } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileProcessor.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileProcessor.java index 32082311ce..a9c93fe465 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileProcessor.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/ClassFileProcessor.java @@ -90,6 +90,11 @@ public void onDeclaredTypeParameters(TypeParametersBuilder typeParametersBuilder importRecord.addTypeParameters(ownerName, typeParametersBuilder); } + @Override + public void onGenericSuperclass(DomainBuilders.JavaParameterizedTypeBuilder genericSuperclassBuilder) { + importRecord.addGenericSuperclass(ownerName, genericSuperclassBuilder); + } + @Override public void onDeclaredField(DomainBuilders.JavaFieldBuilder fieldBuilder) { importRecord.addField(ownerName, fieldBuilder); 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 a0a2297ea3..8e93dcd7ea 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 @@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import com.google.common.collect.SetMultimap; +import com.google.common.collect.Sets; import com.tngtech.archunit.base.Function; import com.tngtech.archunit.base.HasDescription; import com.tngtech.archunit.base.Optional; @@ -42,18 +43,21 @@ 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.JavaTypeVariable; import com.tngtech.archunit.core.importer.AccessRecord.FieldAccessRecord; import com.tngtech.archunit.core.importer.DomainBuilders.JavaAnnotationBuilder.ValueBuilder; import com.tngtech.archunit.core.importer.DomainBuilders.JavaConstructorCallBuilder; import com.tngtech.archunit.core.importer.DomainBuilders.JavaFieldAccessBuilder; import com.tngtech.archunit.core.importer.DomainBuilders.JavaMethodCallBuilder; +import com.tngtech.archunit.core.importer.DomainBuilders.JavaParameterizedTypeBuilder; import com.tngtech.archunit.core.importer.DomainBuilders.TypeParametersBuilder; import com.tngtech.archunit.core.importer.resolvers.ClassResolver; import static com.tngtech.archunit.core.domain.DomainObjectCreationContext.completeAnnotations; import static com.tngtech.archunit.core.domain.DomainObjectCreationContext.completeClassHierarchy; import static com.tngtech.archunit.core.domain.DomainObjectCreationContext.completeEnclosingClass; +import static com.tngtech.archunit.core.domain.DomainObjectCreationContext.completeGenericSuperclass; import static com.tngtech.archunit.core.domain.DomainObjectCreationContext.completeMembers; import static com.tngtech.archunit.core.domain.DomainObjectCreationContext.completeTypeParameters; import static com.tngtech.archunit.core.domain.DomainObjectCreationContext.createJavaClasses; @@ -132,6 +136,7 @@ private void completeClasses() { completeClassHierarchy(javaClass, this); completeEnclosingClass(javaClass, this); completeTypeParameters(javaClass, this); + completeGenericSuperclass(javaClass, this); completeMembers(javaClass, this); completeAnnotations(javaClass, this); } @@ -227,6 +232,23 @@ public Optional createSuperclass(JavaClass owner) { Optional.absent(); } + @Override + public Optional createGenericSuperclass(JavaClass owner) { + Optional> genericSuperclassBuilder = importRecord.getGenericSuperclassFor(owner); + return genericSuperclassBuilder.isPresent() + ? Optional.of(genericSuperclassBuilder.get().build(owner, getTypeParametersInContextOf(owner), classes.byTypeName())) + : Optional.absent(); + } + + private static Iterable> getTypeParametersInContextOf(JavaClass javaClass) { + Set> result = Sets.>newHashSet(javaClass.getTypeParameters()); + while (javaClass.getEnclosingClass().isPresent()) { + javaClass = javaClass.getEnclosingClass().get(); + result.addAll(javaClass.getTypeParameters()); + } + return result; + } + @Override public Set createInterfaces(JavaClass owner) { ImmutableSet.Builder result = ImmutableSet.builder(); diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java index f257a6de89..a50f751d12 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/DomainBuilders.java @@ -642,6 +642,11 @@ public JavaType build(OWNER owner, Iterable> allTypeParamete String getTypeName() { return type.getFullyQualifiedClassName(); } + + JavaParameterizedTypeBuilder forInnerClass(String simpleInnerClassName) { + return new JavaParameterizedTypeBuilder<>(JavaClassDescriptorImporter.createFromAsmObjectTypeName( + type.getFullyQualifiedClassName() + '$' + simpleInnerClassName)); + } } private static List buildJavaTypes(List> typeCreationProcesses, OWNER owner, Iterable> allGenericParametersInContext, ClassesByTypeName classes) { diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java index 1dc836c730..a578d7b568 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassProcessor.java @@ -428,6 +428,8 @@ interface DeclarationHandler { void onDeclaredTypeParameters(DomainBuilders.TypeParametersBuilder typeParametersBuilder); + void onGenericSuperclass(DomainBuilders.JavaParameterizedTypeBuilder genericSuperclassBuilder); + void onDeclaredField(DomainBuilders.JavaFieldBuilder fieldBuilder); void onDeclaredConstructor(DomainBuilders.JavaConstructorBuilder constructorBuilder); diff --git a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassSignatureImporter.java b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassSignatureImporter.java index fe46c16bc3..97185ee53f 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassSignatureImporter.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/importer/JavaClassSignatureImporter.java @@ -21,6 +21,7 @@ import com.google.common.base.Function; import com.google.common.base.Functions; import com.tngtech.archunit.base.HasDescription; +import com.tngtech.archunit.base.Optional; import com.tngtech.archunit.core.domain.JavaClass; import com.tngtech.archunit.core.domain.JavaClassDescriptor; import com.tngtech.archunit.core.domain.JavaType; @@ -54,10 +55,16 @@ static void parseAsmTypeSignature(String signature, DeclarationHandler declarati SignatureProcessor signatureProcessor = new SignatureProcessor(); new SignatureReader(signature).accept(signatureProcessor); declarationHandler.onDeclaredTypeParameters(new TypeParametersBuilder(signatureProcessor.getTypeParameterBuilders())); + + Optional> genericSuperclass = signatureProcessor.getGenericSuperclass(); + if (genericSuperclass.isPresent()) { + declarationHandler.onGenericSuperclass(genericSuperclass.get()); + } } private static class SignatureProcessor extends SignatureVisitor { private final BoundProcessor boundProcessor = new BoundProcessor(); + private final GenericSuperclassProcessor superclassProcessor = new GenericSuperclassProcessor(); SignatureProcessor() { super(ASM_API_VERSION); @@ -67,12 +74,21 @@ List> getTypeParameterBuilders() { return boundProcessor.typeParameterBuilders; } + public Optional> getGenericSuperclass() { + return Optional.fromNullable(superclassProcessor.superclass); + } + @Override public void visitFormalTypeParameter(String name) { log.trace("Encountered type parameter {}", name); boundProcessor.addTypeParameter(name); } + @Override + public SignatureVisitor visitSuperclass() { + return superclassProcessor; + } + @Override public SignatureVisitor visitClassBound() { return boundProcessor; @@ -121,7 +137,30 @@ public void visitTypeVariable(String name) { @Override public SignatureVisitor visitTypeArgument(char wildcard) { - return TypeArgumentProcessor.create(wildcard, currentBound, Functions.identity(), ReferenceCreationProcess.JavaTypeVariableFinisher.IDENTITY); + return TypeArgumentProcessor.create(wildcard, currentBound); + } + } + + private static class GenericSuperclassProcessor extends SignatureVisitor { + private JavaParameterizedTypeBuilder superclass; + + GenericSuperclassProcessor() { + super(ASM_API_VERSION); + } + + @Override + public void visitClassType(String internalObjectName) { + superclass = new JavaParameterizedTypeBuilder<>(JavaClassDescriptorImporter.createFromAsmObjectTypeName(internalObjectName)); + } + + @Override + public void visitInnerClassType(String name) { + superclass = superclass.forInnerClass(name); + } + + @Override + public SignatureVisitor visitTypeArgument(char wildcard) { + return TypeArgumentProcessor.create(wildcard, superclass); } } } @@ -269,6 +308,10 @@ public SignatureVisitor visitArrayType() { return new TypeArgumentProcessor(typeArgumentType, parameterizedType, compose(typeMapping, TO_ARRAY_TYPE), typeVariableFinisher.after(GENERIC_ARRAY_CREATOR)); } + static TypeArgumentProcessor create(char identifier, JavaParameterizedTypeBuilder parameterizedType) { + return create(identifier, parameterizedType, Functions.identity(), ReferenceCreationProcess.JavaTypeVariableFinisher.IDENTITY); + } + static TypeArgumentProcessor create( char identifier, JavaParameterizedTypeBuilder parameterizedType, diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaTypeTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaTypeTest.java new file mode 100644 index 0000000000..f355ffeb57 --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaTypeTest.java @@ -0,0 +1,21 @@ +package com.tngtech.archunit.core.domain; + +import com.tngtech.archunit.core.importer.ClassFileImporter; +import org.junit.Test; + +import static com.tngtech.archunit.core.domain.JavaType.Functions.TO_ERASURE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class JavaTypeTest { + + @Test + public void function_TO_ERASURE() { + JavaType javaType = mock(JavaType.class); + JavaClass erasure = new ClassFileImporter().importClass(getClass()); + when(javaType.toErasure()).thenReturn(erasure); + + assertThat(TO_ERASURE.apply(javaType)).isEqualTo(erasure); + } +} diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericClassesTest.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericClassesTest.java index c2f1c9ee78..e02c19017a 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericClassesTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericClassesTest.java @@ -21,11 +21,11 @@ import static com.tngtech.archunit.testutil.Assertions.assertThat; import static com.tngtech.archunit.testutil.Assertions.assertThatType; -import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.ExpectedConcreteTypeVariable.typeVariable; -import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.ExpectedConcreteTypeVariableArray.typeVariableArray; -import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.ExpectedConcreteWildcardType.wildcardType; -import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.concreteClass; -import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.parameterizedType; +import static com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteClass.concreteClass; +import static com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteParameterizedType.parameterizedType; +import static com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteTypeVariable.typeVariable; +import static com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteTypeVariableArray.typeVariableArray; +import static com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteWildcardType.wildcardType; import static com.tngtech.java.junit.dataprovider.DataProviders.$; import static com.tngtech.java.junit.dataprovider.DataProviders.$$; diff --git a/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericSuperclassTest.java b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericSuperclassTest.java new file mode 100644 index 0000000000..f4bcbe4c16 --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/core/importer/ClassFileImporterGenericSuperclassTest.java @@ -0,0 +1,423 @@ +package com.tngtech.archunit.core.importer; + +import java.io.File; +import java.io.Serializable; +import java.lang.ref.Reference; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.tngtech.archunit.core.domain.JavaType; +import com.tngtech.archunit.testutil.ArchConfigurationRule; +import com.tngtech.java.junit.dataprovider.DataProviderRunner; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static com.tngtech.archunit.testutil.Assertions.assertThatType; +import static com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteClass.concreteClass; +import static com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteParameterizedType.parameterizedType; +import static com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteTypeVariable.typeVariable; +import static com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteWildcardType.wildcardType; + +@RunWith(DataProviderRunner.class) +public class ClassFileImporterGenericSuperclassTest { + + @Rule + public final ArchConfigurationRule configurationRule = new ArchConfigurationRule().resolveAdditionalDependenciesFromClassPath(false); + + @Test + public void imports_non_generic_superclass() { + class BaseClass { + } + class Child extends BaseClass { + } + + JavaType genericSuperClass = new ClassFileImporter().importClass(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").matches(BaseClass.class); + } + + @Test + public void imports_generic_superclass_with_one_type_argument() { + @SuppressWarnings("unused") + class BaseClass { + } + class Child extends BaseClass { + } + + JavaType genericSuperClass = new ClassFileImporter().importClasses(Child.class, String.class).get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass") + .hasErasure(BaseClass.class) + .hasActualTypeArguments(String.class); + } + + @Test + public void imports_generic_superclass_with_multiple_type_arguments() { + @SuppressWarnings("unused") + class BaseClass { + } + @SuppressWarnings("unused") + class Child extends BaseClass { + } + + JavaType genericSuperClass = new ClassFileImporter().importClasses(Child.class, String.class, Serializable.class, File.class) + .get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass") + .hasErasure(BaseClass.class) + .hasActualTypeArguments(String.class, Serializable.class, File.class); + } + + @Test + public void imports_generic_superclass_with_single_actual_type_argument_parameterized_with_concrete_class() { + @SuppressWarnings("unused") + class BaseClass { + } + class Child extends BaseClass> { + } + + JavaType genericSuperClass = new ClassFileImporter().importClasses(Child.class, ClassParameterWithSingleTypeParameter.class, String.class) + .get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withTypeArguments(String.class) + ); + } + + @Test + public void imports_generic_superclass_with_multiple_actual_type_arguments_parameterized_with_concrete_classes() { + @SuppressWarnings("unused") + class BaseClass { + } + class Child extends BaseClass< + ClassParameterWithSingleTypeParameter, + InterfaceParameterWithSingleTypeParameter, + InterfaceParameterWithSingleTypeParameter> { + } + + JavaType genericSuperClass = new ClassFileImporter() + .importClasses( + Child.class, ClassParameterWithSingleTypeParameter.class, InterfaceParameterWithSingleTypeParameter.class, + File.class, Serializable.class, String.class) + .get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withTypeArguments(File.class), + parameterizedType(InterfaceParameterWithSingleTypeParameter.class) + .withTypeArguments(Serializable.class), + parameterizedType(InterfaceParameterWithSingleTypeParameter.class) + .withTypeArguments(String.class) + ); + } + + @Test + public void imports_generic_superclass_with_single_actual_type_argument_parameterized_with_unbound_wildcard() { + @SuppressWarnings("unused") + class BaseClass { + } + class Child extends BaseClass> { + } + + JavaType genericSuperClass = new ClassFileImporter().importClasses(Child.class, ClassParameterWithSingleTypeParameter.class) + .get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withWildcardTypeParameter() + ); + } + + @Test + public void imports_generic_superclass_with_actual_type_arguments_parameterized_with_bounded_wildcards() { + @SuppressWarnings("unused") + class BaseClass { + } + class Child extends BaseClass< + ClassParameterWithSingleTypeParameter, + ClassParameterWithSingleTypeParameter> { + } + + JavaType genericSuperClass = new ClassFileImporter().importClasses(Child.class, ClassParameterWithSingleTypeParameter.class, String.class, File.class) + .get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withWildcardTypeParameterWithUpperBound(String.class), + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withWildcardTypeParameterWithLowerBound(File.class) + ); + } + + @Test + public void imports_generic_superclass_with_actual_type_arguments_with_multiple_wildcards_with_various_bounds() { + @SuppressWarnings("unused") + class BaseClass { + } + class Child extends BaseClass< + ClassParameterWithSingleTypeParameter>, + ClassParameterWithSingleTypeParameter>> { + } + + JavaType genericSuperClass = new ClassFileImporter() + .importClasses( + Child.class, ClassParameterWithSingleTypeParameter.class, + Map.class, Serializable.class, File.class, Reference.class, String.class) + .get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withTypeArguments(parameterizedType(Map.class) + .withWildcardTypeParameters( + wildcardType().withUpperBound(Serializable.class), + wildcardType().withLowerBound(File.class))), + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withTypeArguments(parameterizedType(Reference.class) + .withWildcardTypeParameterWithLowerBound(String.class)) + ); + } + + @Test + public void imports_generic_superclass_with_actual_type_argument_parameterized_with_type_variable() { + @SuppressWarnings("unused") + class BaseClass { + } + class Child extends BaseClass> { + } + + JavaType genericSuperClass = new ClassFileImporter().importClasses(Child.class, ClassParameterWithSingleTypeParameter.class) + .get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withTypeArguments(typeVariable("SUB")) + ); + } + + @Test + public void references_type_variable_assigned_to_actual_type_argument_of_generic_superclass() { + @SuppressWarnings("unused") + class BaseClass { + } + class Child extends BaseClass> { + } + + JavaType genericSuperClass = new ClassFileImporter().importClasses(Child.class, ClassParameterWithSingleTypeParameter.class, String.class) + .get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withTypeArguments(typeVariable("SUB").withUpperBounds(String.class)) + ); + } + + @Test + public void references_outer_type_variable_assigned_to_actual_type_argument_of_generic_superclass_of_inner_class() { + @SuppressWarnings("unused") + class OuterWithTypeParameter { + class SomeInner { + @SuppressWarnings("unused") + class BaseClass { + } + + class Child extends BaseClass { + } + } + } + + JavaType genericSuperClass = new ClassFileImporter() + .importClasses( + OuterWithTypeParameter.class, + OuterWithTypeParameter.SomeInner.class, + OuterWithTypeParameter.SomeInner.Child.class, + String.class) + .get(OuterWithTypeParameter.SomeInner.Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + typeVariable("OUTER").withUpperBounds(String.class) + ); + } + + @Test + public void creates_new_stub_type_variables_for_type_variables_of_enclosing_classes_that_are_out_of_context_for_generic_superclass_of_inner_class() { + @SuppressWarnings("unused") + class OuterWithTypeParameter { + class SomeInner { + @SuppressWarnings("unused") + class BaseClass { + } + + class Child extends BaseClass { + } + } + } + + JavaType genericSuperClass = new ClassFileImporter() + .importClasses(OuterWithTypeParameter.SomeInner.Child.class, String.class) + .get(OuterWithTypeParameter.SomeInner.Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + typeVariable("OUTER").withoutUpperBounds() + ); + } + + @Test + public void imports_wildcards_of_generic_superclass_bound_by_type_variables() { + @SuppressWarnings("unused") + class BaseClass { + } + + class Child extends BaseClass< + ClassParameterWithSingleTypeParameter, + ClassParameterWithSingleTypeParameter> { + } + + JavaType genericSuperClass = new ClassFileImporter() + .importClasses(Child.class, ClassParameterWithSingleTypeParameter.class, String.class, Serializable.class) + .get(Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withWildcardTypeParameterWithUpperBound( + typeVariable("FIRST").withUpperBounds(String.class)), + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withWildcardTypeParameterWithLowerBound( + typeVariable("SECOND").withUpperBounds(Serializable.class)) + ); + } + + @Test + public void imports_wildcards_of_generic_superclass_bound_by_type_variables_of_enclosing_classes() { + @SuppressWarnings("unused") + class OuterWithTypeParameter { + class SomeInner { + @SuppressWarnings("unused") + class BaseClass { + } + + class Child extends BaseClass< + ClassParameterWithSingleTypeParameter, + ClassParameterWithSingleTypeParameter> { + } + } + } + + JavaType genericSuperClass = new ClassFileImporter() + .importClasses( + OuterWithTypeParameter.class, + OuterWithTypeParameter.SomeInner.class, + OuterWithTypeParameter.SomeInner.Child.class, + ClassParameterWithSingleTypeParameter.class, String.class, Serializable.class) + .get(OuterWithTypeParameter.SomeInner.Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withWildcardTypeParameterWithUpperBound( + typeVariable("OUTER_ONE").withUpperBounds(String.class)), + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withWildcardTypeParameterWithLowerBound( + typeVariable("OUTER_TWO").withUpperBounds(Serializable.class)) + ); + } + + @Test + public void creates_new_stub_type_variables_for_wildcards_bound_by_type_variables_of_enclosing_classes_that_are_out_of_context() { + @SuppressWarnings("unused") + class OuterWithTypeParameter { + class SomeInner { + @SuppressWarnings("unused") + class BaseClass { + } + + class Child extends BaseClass< + ClassParameterWithSingleTypeParameter, + ClassParameterWithSingleTypeParameter> { + } + } + } + + JavaType genericSuperClass = new ClassFileImporter() + .importClasses( + OuterWithTypeParameter.SomeInner.Child.class, + ClassParameterWithSingleTypeParameter.class, String.class, Serializable.class) + .get(OuterWithTypeParameter.SomeInner.Child.class).getSuperclass().get(); + + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withWildcardTypeParameterWithUpperBound( + typeVariable("OUTER_ONE").withoutUpperBounds()), + parameterizedType(ClassParameterWithSingleTypeParameter.class) + .withWildcardTypeParameterWithLowerBound( + typeVariable("OUTER_TWO").withoutUpperBounds()) + ); + } + + @Test + public void imports_complex_type_with_multiple_nested_actual_type_arguments_of_generic_superclass_with_self_referencing_type_definitions() { + @SuppressWarnings("unused") + class BaseClass { + } + + class Child extends BaseClass< + // assigned to BaseClass + List, + // assigned to BaseClass<_,B,_> + Map< + Map.Entry>, + Map>>>>>>>, + // assigned to BaseClass<_,_,C> + Comparable>> { + } + + JavaType genericSuperClass = new ClassFileImporter() + .importClasses(Child.class, String.class, Serializable.class, Cloneable.class, + List.class, Map.class, Map.Entry.class, Set.class, Iterable.class, Comparable.class) + .get(Child.class).getSuperclass().get(); + + // @formatter:off + assertThatType(genericSuperClass).as("generic superclass").hasActualTypeArguments( + // assigned to BaseClass + parameterizedType(List.class) + .withWildcardTypeParameterWithUpperBound( + typeVariable("FIRST").withUpperBounds(String.class, Serializable.class)), + // assigned to BaseClass<_,B,_> + parameterizedType(Map.class).withTypeArguments( + parameterizedType(Map.Entry.class).withTypeArguments( + typeVariable("FIRST").withUpperBounds(String.class, Serializable.class), + parameterizedType(Map.Entry.class).withTypeArguments( + concreteClass(String.class), + typeVariable("SECOND").withUpperBounds(Serializable.class, Cloneable.class))), + parameterizedType(Map.class).withTypeArguments( + wildcardType().withUpperBound(String.class), + parameterizedType(Map.class).withTypeArguments( + wildcardType().withUpperBound(Serializable.class), + parameterizedType(List.class).withTypeArguments( + parameterizedType(List.class).withTypeArguments( + wildcardType().withUpperBound( + parameterizedType(Set.class).withTypeArguments( + wildcardType().withLowerBound( + parameterizedType(Iterable.class).withTypeArguments( + wildcardType().withLowerBound( + parameterizedType(Map.class).withTypeArguments( + typeVariable("SECOND").withUpperBounds(Serializable.class, Cloneable.class), + wildcardType()))))))))))), + // assigned to BaseClass<_,_,C> + parameterizedType(Comparable.class).withTypeArguments( + parameterizedType(Child.class).withTypeArguments( + typeVariable("FIRST").withUpperBounds(String.class, Serializable.class), + typeVariable("SECOND").withUpperBounds(Serializable.class, Cloneable.class)))); + // @formatter:on + } + + @SuppressWarnings("unused") + public static class ClassParameterWithSingleTypeParameter { + } + + @SuppressWarnings("unused") + public interface InterfaceParameterWithSingleTypeParameter { + } +} 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 f68e42e2bf..c9fecf109c 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 @@ -38,6 +38,7 @@ import com.tngtech.archunit.core.domain.JavaMethodCall; import com.tngtech.archunit.core.domain.JavaModifier; import com.tngtech.archunit.core.domain.JavaStaticInitializer; +import com.tngtech.archunit.core.domain.JavaType; import com.tngtech.archunit.core.domain.JavaTypeVariable; import com.tngtech.archunit.core.importer.DomainBuilders.JavaMethodCallBuilder; import org.objectweb.asm.Type; @@ -336,6 +337,11 @@ public Optional createSuperclass(JavaClass owner) { return Optional.absent(); } + @Override + public Optional createGenericSuperclass(JavaClass owner) { + return Optional.absent(); + } + @Override public Set createInterfaces(JavaClass owner) { return Collections.emptySet(); diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/DescriptionContext.java b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/DescriptionContext.java new file mode 100644 index 0000000000..ed578350fd --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/DescriptionContext.java @@ -0,0 +1,81 @@ +package com.tngtech.archunit.testutil.assertion; + +import com.google.common.base.Joiner; +import com.google.common.collect.FluentIterable; + +import static com.google.common.collect.Iterables.cycle; +import static com.google.common.collect.Iterables.limit; + +class DescriptionContext { + private static final String MARKER = "##MARKER##"; + private static final String PLACEHOLDER = "_"; + + private final String context; + private final String description; + private final String currentElement; + private final String joinString; + + DescriptionContext(String context) { + this(context + MARKER, "assertion", "", ", "); + } + + private DescriptionContext(String context, String description, String currentElement, String joinString) { + this.context = context; + this.description = description; + this.currentElement = currentElement; + this.joinString = joinString; + } + + public DescriptionContext describe(String part) { + return new DescriptionContext(context.replace(MARKER, part + MARKER), description, part, joinString); + } + + public DescriptionContext describeUpperBounds() { + String newContext = context.replace(MARKER, " extends " + MARKER); + return new DescriptionContext(newContext, description, currentElement, " & "); + } + + public DescriptionContext describeLowerBounds() { + String newContext = context.replace(MARKER, " super " + MARKER); + return new DescriptionContext(newContext, description, currentElement, " & "); + } + + public DescriptionContext describeElements(int number) { + String elementsPlaceHolder = number > 0 ? joinedPlaceHolders(number) : "[]"; + return new DescriptionContext(context.replace(MARKER, elementsPlaceHolder), description, currentElement, joinString); + } + + public DescriptionContext describeElement(int index, int totalSize) { + int maxIndex = totalSize - 1; + String prefix = index > 0 ? joinedPlaceHolders(index) + joinString : ""; + String suffix = index < maxIndex ? joinString + joinedPlaceHolders(maxIndex - index) : ""; + String newContext = context.replace(MARKER, prefix + MARKER + suffix); + String newCurrentElement = this.currentElement + "[" + index + "]"; + return new DescriptionContext(newContext, description, newCurrentElement, joinString); + } + + private String joinedPlaceHolders(int number) { + return FluentIterable.from(limit(cycle(PLACEHOLDER), number)).join(Joiner.on(joinString)); + } + + public DescriptionContext step(String description) { + return new DescriptionContext(context, description, currentElement, joinString); + } + + public DescriptionContext metaInfo() { + String newContext = context.replace(MARKER, "{" + MARKER + "}"); + return new DescriptionContext(newContext, description, currentElement, joinString); + } + + public DescriptionContext describeTypeParameters() { + String newContext = context.replace(MARKER, "<" + MARKER + ">"); + String newJoinString = ", "; + return new DescriptionContext(newContext, description, currentElement, newJoinString); + } + + @Override + public String toString() { + String currentElementInfix = currentElement.isEmpty() ? "" : "[" + currentElement + "]"; + return "\"" + description + "\"" + currentElementInfix + " -> " + context.replace(MARKER, ""); + } +} diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/ExpectedConcreteType.java b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/ExpectedConcreteType.java new file mode 100644 index 0000000000..7c5de8fa1e --- /dev/null +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/ExpectedConcreteType.java @@ -0,0 +1,255 @@ +package com.tngtech.archunit.testutil.assertion; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.tngtech.archunit.core.domain.JavaClass; +import com.tngtech.archunit.core.domain.JavaGenericArrayType; +import com.tngtech.archunit.core.domain.JavaParameterizedType; +import com.tngtech.archunit.core.domain.JavaType; +import com.tngtech.archunit.core.domain.JavaTypeVariable; +import com.tngtech.archunit.core.domain.JavaWildcardType; +import org.junit.Assert; + +import static com.tngtech.archunit.core.domain.Formatters.ensureSimpleName; +import static com.tngtech.archunit.testutil.Assertions.assertThatType; +import static com.tngtech.archunit.testutil.Assertions.assertThatTypes; +import static java.util.Collections.emptyList; +import static org.assertj.core.api.Assertions.assertThat; + +public interface ExpectedConcreteType { + void assertMatchWith(JavaType actual, DescriptionContext context); + + class ExpectedConcreteClass implements ExpectedConcreteType { + private final Class clazz; + + private ExpectedConcreteClass(Class clazz) { + this.clazz = clazz; + } + + @Override + public void assertMatchWith(JavaType actual, DescriptionContext context) { + DescriptionContext newContext = context.describe(ensureSimpleName(actual.getName())); + assertThat(actual).as(newContext.toString()).isInstanceOf(JavaClass.class); + assertThatType(actual).as(newContext.toString()).matches(clazz); + } + + static ExpectedConcreteType[] wrap(Class[] classes) { + ExpectedConcreteType[] result = new ExpectedConcreteType[classes.length]; + for (int i = 0; i < classes.length; i++) { + result[i] = new ExpectedConcreteClass(classes[i]); + } + return result; + } + + public static ExpectedConcreteClass concreteClass(Class expectedType) { + return new ExpectedConcreteClass(expectedType); + } + } + + class ExpectedConcreteParameterizedType implements ExpectedConcreteType { + private final Type type; + private final List typeParameters = new ArrayList<>(); + + private ExpectedConcreteParameterizedType(Type type) { + this.type = type; + } + + public static ExpectedConcreteParameterizedType parameterizedType(Class expectedType) { + return new ExpectedConcreteParameterizedType(expectedType); + } + + public ExpectedConcreteType withTypeArguments(Class... type) { + return withTypeArguments(ExpectedConcreteClass.wrap(type)); + } + + public ExpectedConcreteType withTypeArguments(ExpectedConcreteType... type) { + typeParameters.addAll(ImmutableList.copyOf(type)); + return this; + } + + public ExpectedConcreteType withWildcardTypeParameter() { + return withTypeArguments(new ExpectedConcreteWildcardType()); + } + + public ExpectedConcreteType withWildcardTypeParameterWithUpperBound(Class bound) { + return withWildcardTypeParameterWithUpperBound(new ExpectedConcreteClass(bound)); + } + + public ExpectedConcreteType withWildcardTypeParameterWithUpperBound(ExpectedConcreteType bound) { + return withTypeArguments(ExpectedConcreteWildcardType.wildcardType().withUpperBound(bound)); + } + + public ExpectedConcreteType withWildcardTypeParameterWithLowerBound(Class bound) { + return withWildcardTypeParameterWithLowerBound(new ExpectedConcreteClass(bound)); + } + + public ExpectedConcreteType withWildcardTypeParameterWithLowerBound(ExpectedConcreteType bound) { + return withTypeArguments(ExpectedConcreteWildcardType.wildcardType().withLowerBound(bound)); + } + + public ExpectedConcreteType withWildcardTypeParameters(ExpectedConcreteWildcardType... wildcardTypes) { + return withTypeArguments(wildcardTypes); + } + + @Override + public void assertMatchWith(JavaType actual, DescriptionContext context) { + DescriptionContext newContext = context.describe(ensureSimpleName(actual.getName())); + assertThatType(actual.toErasure()).as(newContext.toString()).matches(type); + assertTypeParametersMatch(actual, newContext); + } + + private void assertTypeParametersMatch(JavaType actual, DescriptionContext context) { + DescriptionContext parameterContext = context.step("type parameters").describeTypeParameters(); + if (!(actual instanceof JavaParameterizedType)) { + Assert.fail(String.format( + "%s: Actual type is not parameterized, but expected to be parameterized with type parameters %s", parameterContext, typeParameters)); + } + List actualTypeParameters = ((JavaParameterizedType) actual).getActualTypeArguments(); + assertThatTypes(actualTypeParameters).matchExactly(typeParameters, parameterContext); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "{" + type + formatTypeParameters() + '}'; + } + + private String formatTypeParameters() { + return !typeParameters.isEmpty() ? "<" + Joiner.on(", ").join(typeParameters) + ">" : ""; + } + } + + class ExpectedConcreteWildcardType implements ExpectedConcreteType { + private final List upperBounds = new ArrayList<>(); + private final List lowerBounds = new ArrayList<>(); + + private ExpectedConcreteWildcardType() { + } + + @Override + public void assertMatchWith(JavaType actual, DescriptionContext context) { + context = context.describe(actual.getName()); + + assertThat(actual).as(context.toString()).isInstanceOf(JavaWildcardType.class); + JavaWildcardType wildcardType = (JavaWildcardType) actual; + assertThat(wildcardType.getName()).as(context.toString()).isEqualTo("?"); + + assertUpperBoundsMatch(wildcardType, context); + assertLowerBoundMatch(wildcardType, context); + } + + private void assertUpperBoundsMatch(JavaWildcardType actual, DescriptionContext context) { + context = context.step("upper bounds"); + assertThat(actual.getUpperBounds()).as(context.toString()).hasSameSizeAs(upperBounds); + context = context.describeUpperBounds(); + assertBoundsMatch(actual.getUpperBounds(), upperBounds, context); + } + + private void assertLowerBoundMatch(JavaWildcardType actual, DescriptionContext context) { + context = context.step("lower bounds"); + assertThat(actual.getLowerBounds()).as(context.toString()).hasSameSizeAs(lowerBounds); + context = context.describeLowerBounds(); + assertBoundsMatch(actual.getLowerBounds(), lowerBounds, context); + } + + private void assertBoundsMatch(List actualBounds, List expectedBounds, DescriptionContext context) { + for (int i = 0; i < expectedBounds.size(); i++) { + expectedBounds.get(i).assertMatchWith(actualBounds.get(i), context); + } + } + + public ExpectedConcreteWildcardType withUpperBound(Class bound) { + return withUpperBound(new ExpectedConcreteClass(bound)); + } + + public ExpectedConcreteWildcardType withUpperBound(ExpectedConcreteType bound) { + upperBounds.add(bound); + return this; + } + + public ExpectedConcreteWildcardType withLowerBound(Class bound) { + return withLowerBound(new ExpectedConcreteClass(bound)); + } + + public ExpectedConcreteWildcardType withLowerBound(ExpectedConcreteType bound) { + lowerBounds.add(bound); + return this; + } + + public static ExpectedConcreteWildcardType wildcardType() { + return new ExpectedConcreteWildcardType(); + } + } + + class ExpectedConcreteTypeVariable implements ExpectedConcreteType { + private final String name; + private List upperBounds; + + private ExpectedConcreteTypeVariable(String name) { + this.name = name; + } + + public ExpectedConcreteTypeVariable withUpperBounds(Class... bounds) { + return withUpperBounds(ExpectedConcreteClass.wrap(bounds)); + } + + public ExpectedConcreteTypeVariable withUpperBounds(ExpectedConcreteType... bounds) { + upperBounds = ImmutableList.copyOf(bounds); + return this; + } + + public ExpectedConcreteTypeVariable withoutUpperBounds() { + upperBounds = emptyList(); + return this; + } + + @Override + public void assertMatchWith(JavaType actual, DescriptionContext context) { + assertThat(actual).as(context.step("JavaType").toString()).isInstanceOf(JavaTypeVariable.class); + JavaTypeVariable actualTypeVariable = (JavaTypeVariable) actual; + assertThat(actualTypeVariable.getName()).as(context.step("type variable name").toString()).isEqualTo(name); + + if (upperBounds != null) { + DescriptionContext newContext = context.describe(actual.getName()).step("bounds").metaInfo().describeUpperBounds(); + assertThatTypes(actualTypeVariable.getUpperBounds()).matchExactly(upperBounds, newContext); + } + } + + public static ExpectedConcreteTypeVariable typeVariable(String name) { + return new ExpectedConcreteTypeVariable(name); + } + } + + class ExpectedConcreteTypeVariableArray implements ExpectedConcreteType { + private final String name; + private ExpectedConcreteType componentType; + + private ExpectedConcreteTypeVariableArray(String name) { + this.name = name; + } + + public ExpectedConcreteTypeVariableArray withComponentType(ExpectedConcreteType componentType) { + this.componentType = componentType; + return this; + } + + @Override + public void assertMatchWith(JavaType actual, DescriptionContext context) { + assertThat(actual).as(context.step("JavaType").toString()).isInstanceOf(JavaGenericArrayType.class); + JavaGenericArrayType actualArrayType = (JavaGenericArrayType) actual; + assertThat(actualArrayType.getName()).as(context.step("type variable name").toString()).isEqualTo(name); + + if (componentType != null) { + DescriptionContext newContext = context.describe(actual.getName()).step("component type").metaInfo(); + componentType.assertMatchWith(actualArrayType.getComponentType(), newContext); + } + } + + public static ExpectedConcreteTypeVariableArray typeVariableArray(String typeVariableArrayString) { + return new ExpectedConcreteTypeVariableArray(typeVariableArrayString); + } + } +} diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeAssertion.java b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeAssertion.java index 408549b09e..fb292407fe 100644 --- a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeAssertion.java +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeAssertion.java @@ -9,9 +9,10 @@ import com.google.common.collect.FluentIterable; import com.tngtech.archunit.core.domain.JavaClass; import com.tngtech.archunit.core.domain.JavaModifier; +import com.tngtech.archunit.core.domain.JavaParameterizedType; import com.tngtech.archunit.core.domain.JavaType; import com.tngtech.archunit.core.domain.JavaTypeVariable; -import com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.ExpectedConcreteType; +import com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteClass; import org.assertj.core.api.AbstractObjectAssert; import org.objectweb.asm.Type; @@ -88,6 +89,27 @@ public JavaTypeVariableOfClassAssertion hasOnlyTypeParameter(String name) { return hasTypeParameter(name); } + public JavaTypeAssertion hasErasure(Class rawType) { + new JavaTypeAssertion(actual.toErasure()).as("Erasure of %s", actual.getName()).matches(rawType); + return this; + } + + public void hasActualTypeArguments(Class... typeArguments) { + hasActualTypeArguments(ExpectedConcreteClass.wrap(typeArguments)); + } + + public void hasActualTypeArguments(ExpectedConcreteType... typeArguments) { + assertThat(actual).isInstanceOf(JavaParameterizedType.class); + JavaParameterizedType parameterizedType = (JavaParameterizedType) this.actual; + + List actualTypeArguments = parameterizedType.getActualTypeArguments(); + DescriptionContext context = new DescriptionContext(actual.getName()).describeTypeParameters().step("actual type arguments"); + assertThat(actualTypeArguments).as(context.toString()).hasSameSizeAs(typeArguments); + for (int i = 0; i < actualTypeArguments.size(); i++) { + typeArguments[i].assertMatchWith(actualTypeArguments.get(i), context.describeElement(i, actualTypeArguments.size())); + } + } + private JavaClass actualClass() { assertThat(actual).as(describeAssertion(actual.getName())).isInstanceOf(JavaClass.class); return (JavaClass) actual; diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeVariableAssertion.java b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeVariableAssertion.java index 85fa45df50..8ef0d8e9fe 100644 --- a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeVariableAssertion.java +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypeVariableAssertion.java @@ -1,28 +1,8 @@ package com.tngtech.archunit.testutil.assertion; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; - -import com.google.common.base.Joiner; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; -import com.tngtech.archunit.core.domain.JavaClass; -import com.tngtech.archunit.core.domain.JavaGenericArrayType; -import com.tngtech.archunit.core.domain.JavaParameterizedType; -import com.tngtech.archunit.core.domain.JavaType; import com.tngtech.archunit.core.domain.JavaTypeVariable; -import com.tngtech.archunit.core.domain.JavaWildcardType; +import com.tngtech.archunit.testutil.assertion.ExpectedConcreteType.ExpectedConcreteClass; import org.assertj.core.api.AbstractObjectAssert; -import org.junit.Assert; - -import static com.google.common.collect.Iterables.cycle; -import static com.google.common.collect.Iterables.limit; -import static com.tngtech.archunit.core.domain.Formatters.ensureSimpleName; -import static com.tngtech.archunit.testutil.Assertions.assertThat; -import static com.tngtech.archunit.testutil.Assertions.assertThatType; -import static com.tngtech.archunit.testutil.assertion.JavaTypeVariableAssertion.ExpectedConcreteWildcardType.wildcardType; -import static java.util.Collections.emptyList; public class JavaTypeVariableAssertion extends AbstractObjectAssert> { public JavaTypeVariableAssertion(JavaTypeVariable actual) { @@ -35,322 +15,6 @@ public void hasBoundsMatching(Class... bounds) { public void hasBoundsMatching(ExpectedConcreteType... bounds) { DescriptionContext context = new DescriptionContext(actual.getName()).step("bounds").describeUpperBounds(); - assertConcreteTypesMatch(context, actual.getBounds(), ImmutableList.copyOf(bounds)); - } - - private static void assertConcreteTypesMatch(DescriptionContext context, List actual, List expected) { - assertThat(actual).as(context.describeElements(actual.size()).toString()).hasSize(expected.size()); - for (int i = 0; i < actual.size(); i++) { - DescriptionContext elementContext = context.describeElement(i, actual.size()); - expected.get(i).assertMatchWith(actual.get(i), elementContext); - } - } - - public static ExpectedConcreteClass concreteClass(Class expectedType) { - return new ExpectedConcreteClass(expectedType); - } - - public static ExpectedConcreteParameterizedType parameterizedType(Class expectedType) { - return new ExpectedConcreteParameterizedType(expectedType); - } - - public interface ExpectedConcreteType { - void assertMatchWith(JavaType actual, DescriptionContext context); - } - - public static class ExpectedConcreteClass implements ExpectedConcreteType { - private final Class clazz; - - private ExpectedConcreteClass(Class clazz) { - this.clazz = clazz; - } - - @Override - public void assertMatchWith(JavaType actual, DescriptionContext context) { - DescriptionContext newContext = context.describe(ensureSimpleName(actual.getName())); - assertThat(actual).as(newContext.toString()).isInstanceOf(JavaClass.class); - assertThatType(actual).as(newContext.toString()).matches(clazz); - } - - static ExpectedConcreteType[] wrap(Class[] classes) { - ExpectedConcreteType[] result = new ExpectedConcreteType[classes.length]; - for (int i = 0; i < classes.length; i++) { - result[i] = new ExpectedConcreteClass(classes[i]); - } - return result; - } - } - - public static class ExpectedConcreteParameterizedType implements ExpectedConcreteType { - private final Type type; - private final List typeParameters = new ArrayList<>(); - - private ExpectedConcreteParameterizedType(Type type) { - this.type = type; - } - - public ExpectedConcreteType withTypeArguments(Class... type) { - return withTypeArguments(ExpectedConcreteClass.wrap(type)); - } - - public ExpectedConcreteType withTypeArguments(ExpectedConcreteType... type) { - typeParameters.addAll(ImmutableList.copyOf(type)); - return this; - } - - public ExpectedConcreteType withWildcardTypeParameter() { - return withTypeArguments(new ExpectedConcreteWildcardType()); - } - - public ExpectedConcreteType withWildcardTypeParameterWithUpperBound(Class bound) { - return withWildcardTypeParameterWithUpperBound(new ExpectedConcreteClass(bound)); - } - - public ExpectedConcreteType withWildcardTypeParameterWithUpperBound(ExpectedConcreteType bound) { - return withTypeArguments(wildcardType().withUpperBound(bound)); - } - - public ExpectedConcreteType withWildcardTypeParameterWithLowerBound(Class bound) { - return withWildcardTypeParameterWithLowerBound(new ExpectedConcreteClass(bound)); - } - - public ExpectedConcreteType withWildcardTypeParameterWithLowerBound(ExpectedConcreteType bound) { - return withTypeArguments(wildcardType().withLowerBound(bound)); - } - - public ExpectedConcreteType withWildcardTypeParameters(ExpectedConcreteWildcardType... wildcardTypes) { - return withTypeArguments(wildcardTypes); - } - - @Override - public void assertMatchWith(JavaType actual, DescriptionContext context) { - DescriptionContext newContext = context.describe(ensureSimpleName(actual.getName())); - assertThatType(actual.toErasure()).as(newContext.toString()).matches(type); - assertTypeParametersMatch(actual, newContext); - } - - private void assertTypeParametersMatch(JavaType actual, DescriptionContext context) { - DescriptionContext parameterContext = context.step("type parameters").describeTypeParameters(); - if (!(actual instanceof JavaParameterizedType)) { - Assert.fail(String.format( - "%s: Actual type is not parameterized, but expected to be parameterized with type parameters %s", parameterContext, typeParameters)); - } - List actualTypeParameters = ((JavaParameterizedType) actual).getActualTypeArguments(); - assertConcreteTypesMatch(parameterContext, actualTypeParameters, typeParameters); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "{" + type + formatTypeParameters() + '}'; - } - - private String formatTypeParameters() { - return !typeParameters.isEmpty() ? "<" + Joiner.on(", ").join(typeParameters) + ">" : ""; - } - } - - public static class ExpectedConcreteWildcardType implements ExpectedConcreteType { - private final List upperBounds = new ArrayList<>(); - private final List lowerBounds = new ArrayList<>(); - - private ExpectedConcreteWildcardType() { - } - - @Override - public void assertMatchWith(JavaType actual, DescriptionContext context) { - context = context.describe(actual.getName()); - - assertThat(actual).as(context.toString()).isInstanceOf(JavaWildcardType.class); - JavaWildcardType wildcardType = (JavaWildcardType) actual; - assertThat(wildcardType.getName()).as(context.toString()).isEqualTo("?"); - - assertUpperBoundsMatch(wildcardType, context); - assertLowerBoundMatch(wildcardType, context); - } - - private void assertUpperBoundsMatch(JavaWildcardType actual, DescriptionContext context) { - context = context.step("upper bounds"); - assertThat(actual.getUpperBounds()).as(context.toString()).hasSameSizeAs(upperBounds); - context = context.describeUpperBounds(); - assertBoundsMatch(actual.getUpperBounds(), upperBounds, context); - } - - private void assertLowerBoundMatch(JavaWildcardType actual, DescriptionContext context) { - context = context.step("lower bounds"); - assertThat(actual.getLowerBounds()).as(context.toString()).hasSameSizeAs(lowerBounds); - context = context.describeLowerBounds(); - assertBoundsMatch(actual.getLowerBounds(), lowerBounds, context); - } - - private void assertBoundsMatch(List actualBounds, List expectedBounds, DescriptionContext context) { - for (int i = 0; i < expectedBounds.size(); i++) { - expectedBounds.get(i).assertMatchWith(actualBounds.get(i), context); - } - } - - public ExpectedConcreteWildcardType withUpperBound(Class bound) { - return withUpperBound(new ExpectedConcreteClass(bound)); - } - - public ExpectedConcreteWildcardType withUpperBound(ExpectedConcreteType bound) { - upperBounds.add(bound); - return this; - } - - public ExpectedConcreteWildcardType withLowerBound(Class bound) { - return withLowerBound(new ExpectedConcreteClass(bound)); - } - - public ExpectedConcreteWildcardType withLowerBound(ExpectedConcreteType bound) { - lowerBounds.add(bound); - return this; - } - - public static ExpectedConcreteWildcardType wildcardType() { - return new ExpectedConcreteWildcardType(); - } - } - - public static class ExpectedConcreteTypeVariable implements ExpectedConcreteType { - private final String name; - private List upperBounds; - - private ExpectedConcreteTypeVariable(String name) { - this.name = name; - } - - public ExpectedConcreteTypeVariable withUpperBounds(Class... bounds) { - return withUpperBounds(ExpectedConcreteClass.wrap(bounds)); - } - - public ExpectedConcreteTypeVariable withUpperBounds(ExpectedConcreteType... bounds) { - upperBounds = ImmutableList.copyOf(bounds); - return this; - } - - public ExpectedConcreteTypeVariable withoutUpperBounds() { - upperBounds = emptyList(); - return this; - } - - @Override - public void assertMatchWith(JavaType actual, DescriptionContext context) { - assertThat(actual).as(context.step("JavaType").toString()).isInstanceOf(JavaTypeVariable.class); - JavaTypeVariable actualTypeVariable = (JavaTypeVariable) actual; - assertThat(actualTypeVariable.getName()).as(context.step("type variable name").toString()).isEqualTo(name); - - if (upperBounds != null) { - DescriptionContext newContext = context.describe(actual.getName()).step("bounds").metaInfo().describeUpperBounds(); - assertConcreteTypesMatch(newContext, actualTypeVariable.getUpperBounds(), upperBounds); - } - } - - public static ExpectedConcreteTypeVariable typeVariable(String name) { - return new ExpectedConcreteTypeVariable(name); - } - } - - public static class ExpectedConcreteTypeVariableArray implements ExpectedConcreteType { - private final String name; - private ExpectedConcreteType componentType; - - private ExpectedConcreteTypeVariableArray(String name) { - this.name = name; - } - - public ExpectedConcreteTypeVariableArray withComponentType(ExpectedConcreteType componentType) { - this.componentType = componentType; - return this; - } - - @Override - public void assertMatchWith(JavaType actual, DescriptionContext context) { - assertThat(actual).as(context.step("JavaType").toString()).isInstanceOf(JavaGenericArrayType.class); - JavaGenericArrayType actualArrayType = (JavaGenericArrayType) actual; - assertThat(actualArrayType.getName()).as(context.step("type variable name").toString()).isEqualTo(name); - - if (componentType != null) { - DescriptionContext newContext = context.describe(actual.getName()).step("component type").metaInfo(); - componentType.assertMatchWith(actualArrayType.getComponentType(), newContext); - } - } - - public static ExpectedConcreteTypeVariableArray typeVariableArray(String typeVariableArrayString) { - return new ExpectedConcreteTypeVariableArray(typeVariableArrayString); - } - } - - private static class DescriptionContext { - private static final String MARKER = "##MARKER##"; - private static final String PLACEHOLDER = "_"; - - private final String context; - private final String description; - private final String currentElement; - private final String joinString; - - DescriptionContext(String context) { - this(context + MARKER, "assertion", "", ", "); - } - - private DescriptionContext(String context, String description, String currentElement, String joinString) { - this.context = context; - this.description = description; - this.currentElement = currentElement; - this.joinString = joinString; - } - - public DescriptionContext describe(String part) { - return new DescriptionContext(context.replace(MARKER, part + MARKER), description, part, joinString); - } - - public DescriptionContext describeUpperBounds() { - String newContext = context.replace(MARKER, " extends " + MARKER); - return new DescriptionContext(newContext, description, currentElement, " & "); - } - - public DescriptionContext describeLowerBounds() { - String newContext = context.replace(MARKER, " super " + MARKER); - return new DescriptionContext(newContext, description, currentElement, " & "); - } - - public DescriptionContext describeElements(int number) { - String elementsPlaceHolder = number > 0 ? joinedPlaceHolders(number) : "[]"; - return new DescriptionContext(context.replace(MARKER, elementsPlaceHolder), description, currentElement, joinString); - } - - public DescriptionContext describeElement(int index, int totalSize) { - int maxIndex = totalSize - 1; - String prefix = index > 0 ? joinedPlaceHolders(index) + joinString : ""; - String suffix = index < maxIndex ? joinString + joinedPlaceHolders(maxIndex - index) : ""; - String newContext = context.replace(MARKER, prefix + MARKER + suffix); - String newCurrentElement = this.currentElement + "[" + index + "]"; - return new DescriptionContext(newContext, description, newCurrentElement, joinString); - } - - private String joinedPlaceHolders(int number) { - return FluentIterable.from(limit(cycle(PLACEHOLDER), number)).join(Joiner.on(joinString)); - } - - public DescriptionContext step(String description) { - return new DescriptionContext(context, description, currentElement, joinString); - } - - public DescriptionContext metaInfo() { - String newContext = context.replace(MARKER, "{" + MARKER + "}"); - return new DescriptionContext(newContext, description, currentElement, joinString); - } - - public DescriptionContext describeTypeParameters() { - String newContext = context.replace(MARKER, "<" + MARKER + ">"); - String newJoinString = ", "; - return new DescriptionContext(newContext, description, currentElement, newJoinString); - } - - @Override - public String toString() { - String currentElementInfix = currentElement.isEmpty() ? "" : "[" + currentElement + "]"; - return "\"" + description + "\"" + currentElementInfix + " -> " + context.replace(MARKER, ""); - } + new JavaTypesAssertion(actual.getBounds()).matchExactly(bounds, context); } } diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypesAssertion.java b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypesAssertion.java index c0c108eb83..3d8784aab1 100644 --- a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypesAssertion.java +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/JavaTypesAssertion.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Set; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.tngtech.archunit.core.domain.JavaClass; @@ -43,6 +44,18 @@ public void matchInAnyOrder(Class... classes) { matchInAnyOrder(ImmutableSet.copyOf(classes)); } + public void matchExactly(ExpectedConcreteType[] expected, DescriptionContext context) { + matchExactly(ImmutableList.copyOf(expected), context); + } + + public void matchExactly(List expected, DescriptionContext context) { + assertThat(actual).as(context.describeElements(actual.length).toString()).hasSize(expected.size()); + for (int i = 0; i < actual.length; i++) { + DescriptionContext elementContext = context.describeElement(i, actual.length); + expected.get(i).assertMatchWith(actual[i], elementContext); + } + } + public void matchExactly(Class... classes) { assertThat(TestUtils.namesOf(actual)).as("classes").containsExactlyElementsOf(namesOf(classes)); matchInAnyOrder(classes); From 0f45abd3e5d3490c547279502391c4c98e9b54eb Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Wed, 6 Jan 2021 18:26:20 +0100 Subject: [PATCH 11/11] add generic superclass type argument dependencies from and to self Signed-off-by: Peter Gafert --- .../a81a2b54-5a18-4145-b544-7a580aba0425 | 2 + .../a81a2b54-5a18-4145-b544-7a580aba0425 | 2 + .../layers/service/SpecialServiceHelper.java | 10 ++ .../a81a2b54-5a18-4145-b544-7a580aba0425 | 2 + .../integration/ExamplesIntegrationTest.java | 8 ++ .../testutils/ExpectedDependency.java | 22 ++++ .../archunit/core/domain/Dependency.java | 5 + .../core/domain/JavaClassDependencies.java | 33 +++++- .../archunit/core/domain/DependencyTest.java | 22 ++++ .../archunit/core/domain/JavaClassTest.java | 111 ++++++++++++------ .../assertion/DependenciesAssertion.java | 38 ++++-- 11 files changed, 208 insertions(+), 47 deletions(-) create mode 100644 archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/service/SpecialServiceHelper.java diff --git a/archunit-example/example-junit4/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 b/archunit-example/example-junit4/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 index b3440d5d81..5f85d78b3e 100644 --- a/archunit-example/example-junit4/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 +++ b/archunit-example/example-junit4/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 @@ -2,8 +2,10 @@ Class has annotation member of type in (ServiceViolatingLayerRules.java:0) Class has annotation member of type in (ServiceViolatingLayerRules.java:0) Class is annotated with in (ServiceViolatingLayerRules.java:0) +Class extends class in (SpecialServiceHelper.java:0) Class implements interface in (ServiceImplementation.java:0) Constructor (com.tngtech.archunit.example.layers.service.ServiceViolatingLayerRules)> has parameter of type in (SomeMediator.java:0) +Constructor ()> calls constructor ()> in (SpecialServiceHelper.java:9) Field has type in (SomeMediator.java:0) Field has type in (SomeController.java:0) Field has type in (SomeController.java:0) diff --git a/archunit-example/example-junit5/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 b/archunit-example/example-junit5/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 index b3440d5d81..5f85d78b3e 100644 --- a/archunit-example/example-junit5/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 +++ b/archunit-example/example-junit5/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 @@ -2,8 +2,10 @@ Class has annotation member of type in (ServiceViolatingLayerRules.java:0) Class has annotation member of type in (ServiceViolatingLayerRules.java:0) Class is annotated with in (ServiceViolatingLayerRules.java:0) +Class extends class in (SpecialServiceHelper.java:0) Class implements interface in (ServiceImplementation.java:0) Constructor (com.tngtech.archunit.example.layers.service.ServiceViolatingLayerRules)> has parameter of type in (SomeMediator.java:0) +Constructor ()> calls constructor ()> in (SpecialServiceHelper.java:9) Field has type in (SomeMediator.java:0) Field has type in (SomeController.java:0) Field has type in (SomeController.java:0) diff --git a/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/service/SpecialServiceHelper.java b/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/service/SpecialServiceHelper.java new file mode 100644 index 0000000000..09e70824eb --- /dev/null +++ b/archunit-example/example-plain/src/main/java/com/tngtech/archunit/example/layers/service/SpecialServiceHelper.java @@ -0,0 +1,10 @@ +package com.tngtech.archunit.example.layers.service; + +import java.util.HashMap; +import java.util.Set; + +import com.tngtech.archunit.example.layers.controller.SomeUtility; +import com.tngtech.archunit.example.layers.controller.one.SomeEnum; + +public class SpecialServiceHelper extends ServiceHelper>> { +} diff --git a/archunit-example/example-plain/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 b/archunit-example/example-plain/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 index b3440d5d81..5f85d78b3e 100644 --- a/archunit-example/example-plain/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 +++ b/archunit-example/example-plain/src/test/resources/frozen/a81a2b54-5a18-4145-b544-7a580aba0425 @@ -2,8 +2,10 @@ Class has annotation member of type in (ServiceViolatingLayerRules.java:0) Class has annotation member of type in (ServiceViolatingLayerRules.java:0) Class is annotated with in (ServiceViolatingLayerRules.java:0) +Class extends class in (SpecialServiceHelper.java:0) Class implements interface in (ServiceImplementation.java:0) Constructor (com.tngtech.archunit.example.layers.service.ServiceViolatingLayerRules)> has parameter of type in (SomeMediator.java:0) +Constructor ()> calls constructor ()> in (SpecialServiceHelper.java:9) Field has type in (SomeMediator.java:0) Field has type in (SomeController.java:0) Field has type in (SomeController.java:0) diff --git a/archunit-integration-test/src/test/java/com/tngtech/archunit/integration/ExamplesIntegrationTest.java b/archunit-integration-test/src/test/java/com/tngtech/archunit/integration/ExamplesIntegrationTest.java index 735e9d4675..9a672db5f9 100644 --- a/archunit-integration-test/src/test/java/com/tngtech/archunit/integration/ExamplesIntegrationTest.java +++ b/archunit-integration-test/src/test/java/com/tngtech/archunit/integration/ExamplesIntegrationTest.java @@ -103,6 +103,7 @@ import com.tngtech.archunit.example.layers.service.ServiceInterface; import com.tngtech.archunit.example.layers.service.ServiceViolatingDaoRules; import com.tngtech.archunit.example.layers.service.ServiceViolatingLayerRules; +import com.tngtech.archunit.example.layers.service.SpecialServiceHelper; import com.tngtech.archunit.example.layers.service.impl.ServiceImplementation; import com.tngtech.archunit.example.layers.service.impl.SomeInterfacePlacedInTheWrongPackage; import com.tngtech.archunit.example.layers.service.impl.WronglyNamedSvc; @@ -172,6 +173,7 @@ import static com.tngtech.archunit.testutils.ExpectedDependency.annotatedClass; import static com.tngtech.archunit.testutils.ExpectedDependency.constructor; import static com.tngtech.archunit.testutils.ExpectedDependency.field; +import static com.tngtech.archunit.testutils.ExpectedDependency.genericSuperclass; import static com.tngtech.archunit.testutils.ExpectedDependency.inheritanceFrom; import static com.tngtech.archunit.testutils.ExpectedDependency.method; import static com.tngtech.archunit.testutils.ExpectedDependency.typeParameter; @@ -775,6 +777,8 @@ Stream LayerDependencyRulesTest() { .inLine(25).asDependency()) .by(typeParameter(ServiceHelper.class, "TYPE_PARAMETER_VIOLATING_LAYER_RULE").dependingOn(SomeUtility.class)) .by(typeParameter(ServiceHelper.class, "ANOTHER_TYPE_PARAMETER_VIOLATING_LAYER_RULE").dependingOn(SomeEnum.class)) + .by(genericSuperclass(SpecialServiceHelper.class, ServiceHelper.class).dependingOn(SomeUtility.class)) + .by(genericSuperclass(SpecialServiceHelper.class, ServiceHelper.class).dependingOn(SomeEnum.class)) .by(method(ServiceViolatingLayerRules.class, dependentMethod).withParameter(UseCaseTwoController.class)) .by(method(ServiceViolatingLayerRules.class, dependentMethod).withReturnType(SomeGuiController.class)) .by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).withParameter(UseCaseTwoController[].class)) @@ -834,6 +838,8 @@ Stream LayerDependencyRulesTest() { .inLine(25).asDependency()) .by(typeParameter(ServiceHelper.class, "TYPE_PARAMETER_VIOLATING_LAYER_RULE").dependingOn(SomeUtility.class)) .by(typeParameter(ServiceHelper.class, "ANOTHER_TYPE_PARAMETER_VIOLATING_LAYER_RULE").dependingOn(SomeEnum.class)) + .by(genericSuperclass(SpecialServiceHelper.class, ServiceHelper.class).dependingOn(SomeUtility.class)) + .by(genericSuperclass(SpecialServiceHelper.class, ServiceHelper.class).dependingOn(SomeEnum.class)) .by(method(ServiceViolatingLayerRules.class, dependentMethod).withParameter(UseCaseTwoController.class)) .by(method(ServiceViolatingLayerRules.class, dependentMethod).withReturnType(SomeGuiController.class)) .by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod).withParameter(UseCaseTwoController[].class)) @@ -903,6 +909,8 @@ Stream LayeredArchitectureTest() { .by(typeParameter(ServiceHelper.class, "TYPE_PARAMETER_VIOLATING_LAYER_RULE").dependingOn(SomeUtility.class)) .by(typeParameter(ServiceHelper.class, "ANOTHER_TYPE_PARAMETER_VIOLATING_LAYER_RULE").dependingOn(SomeEnum.class)) + .by(genericSuperclass(SpecialServiceHelper.class, ServiceHelper.class).dependingOn(SomeUtility.class)) + .by(genericSuperclass(SpecialServiceHelper.class, ServiceHelper.class).dependingOn(SomeEnum.class)) .by(method(ServiceViolatingLayerRules.class, dependentMethod).withParameter(UseCaseTwoController.class)) .by(method(ServiceViolatingLayerRules.class, dependentMethod).withReturnType(SomeGuiController.class)) .by(method(ServiceViolatingLayerRules.class, dependentOnComponentTypeMethod) diff --git a/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedDependency.java b/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedDependency.java index b5a7ae5131..4a2a19b5dd 100644 --- a/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedDependency.java +++ b/archunit-integration-test/src/test/java/com/tngtech/archunit/testutils/ExpectedDependency.java @@ -29,6 +29,10 @@ public static TypeParameterCreator typeParameter(Class clazz, String typePara return new TypeParameterCreator(clazz, typeParameterName); } + public static GenericSuperclassTypeArgumentCreator genericSuperclass(Class clazz, Class genericSuperclassErasure) { + return new GenericSuperclassTypeArgumentCreator(clazz, genericSuperclassErasure); + } + public static AnnotationDependencyCreator annotatedClass(Class clazz) { return new AnnotationDependencyCreator(clazz); } @@ -104,6 +108,24 @@ public ExpectedDependency dependingOn(Class typeParameterDependency) { } } + public static class GenericSuperclassTypeArgumentCreator { + private final Class childClass; + private final Class genericSuperclassErasure; + + private GenericSuperclassTypeArgumentCreator(Class childClass, Class genericSuperclassErasure) { + this.childClass = childClass; + this.genericSuperclassErasure = genericSuperclassErasure; + } + + public ExpectedDependency dependingOn(Class superclassTypeArgumentDependency) { + return new ExpectedDependency(childClass, superclassTypeArgumentDependency, + getDependencyPattern(childClass.getName(), + "has generic superclass <" + genericSuperclassErasure.getName() + "> with type argument depending on", + superclassTypeArgumentDependency.getName(), + 0)); + } + } + public static class AccessCreator { private final Class originClass; diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java index ce8e09d0eb..120c2c8c55 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/Dependency.java @@ -135,6 +135,11 @@ static Set tryCreateFromTypeParameter(JavaTypeVariable typeParame return tryCreateDependency(origin.originClass, origin.originDescription, dependencyType, typeParameterDependency); } + static Set tryCreateFromGenericSuperclassTypeArguments(JavaClass originClass, JavaType superclass, JavaClass typeArgumentDependency) { + String dependencyType = "has generic superclass " + bracketFormat(superclass.getName()) + " with type argument depending on"; + return tryCreateDependency(originClass, originClass.getDescription(), dependencyType, typeArgumentDependency); + } + private static Origin findSuitableOrigin(Object dependencyCause, Object originCandidate) { if (originCandidate instanceof JavaMember) { JavaMember member = (JavaMember) originCandidate; diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassDependencies.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassDependencies.java index 7d79e8afbd..c08dfd60e4 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassDependencies.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaClassDependencies.java @@ -15,6 +15,7 @@ */ package com.tngtech.archunit.core.domain; +import java.util.List; import java.util.Set; import com.google.common.base.Supplier; @@ -26,6 +27,7 @@ import static com.google.common.base.Suppliers.memoize; import static com.google.common.collect.Iterables.concat; +import static java.util.Collections.emptySet; class JavaClassDependencies { private final JavaClass javaClass; @@ -73,6 +75,21 @@ private Set inheritanceDependenciesFromSelf() { for (JavaClass supertype : FluentIterable.from(javaClass.getInterfaces()).append(javaClass.getRawSuperclass().asSet())) { result.add(Dependency.fromInheritance(javaClass, supertype)); } + result.addAll(genericSuperclassTypeArgumentDependencies()); + return result.build(); + } + + private Set genericSuperclassTypeArgumentDependencies() { + if (!javaClass.getSuperclass().isPresent() || !(javaClass.getSuperclass().get() instanceof JavaParameterizedType)) { + return emptySet(); + } + JavaParameterizedType genericSuperclass = (JavaParameterizedType) javaClass.getSuperclass().get(); + + List actualTypeArguments = genericSuperclass.getActualTypeArguments(); + ImmutableSet.Builder result = ImmutableSet.builder(); + for (JavaClass superclassTypeArgumentDependency : dependenciesOfTypes(actualTypeArguments)) { + result.addAll(Dependency.tryCreateFromGenericSuperclassTypeArguments(javaClass, genericSuperclass, superclassTypeArgumentDependency)); + } return result.build(); } @@ -151,14 +168,22 @@ private Set typeParameterDependenciesFromSelf() { private Set getDependenciesFromTypeParameter(JavaTypeVariable typeVariable) { ImmutableSet.Builder dependenciesBuilder = ImmutableSet.builder(); - for (JavaType bound : typeVariable.getUpperBounds()) { - for (JavaClass typeParameterDependency : dependenciesOfType(bound)) { - dependenciesBuilder.addAll(Dependency.tryCreateFromTypeParameter(typeVariable, typeParameterDependency)); - } + for (JavaClass typeParameterDependency : dependenciesOfTypes(typeVariable.getUpperBounds())) { + dependenciesBuilder.addAll(Dependency.tryCreateFromTypeParameter(typeVariable, typeParameterDependency)); } return dependenciesBuilder.build(); } + private Set dependenciesOfTypes(Iterable types) { + ImmutableSet.Builder result = ImmutableSet.builder(); + for (JavaType type : types) { + for (JavaClass typeParameterDependency : dependenciesOfType(type)) { + result.add(typeParameterDependency); + } + } + return result.build(); + } + private static Iterable dependenciesOfType(JavaType javaType) { ImmutableSet.Builder result = ImmutableSet.builder(); if (javaType instanceof JavaClass) { diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java index a4989b0a2b..3d7aed0736 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/DependencyTest.java @@ -1,6 +1,7 @@ package com.tngtech.archunit.core.domain; import java.io.IOException; +import java.io.Serializable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Field; @@ -267,6 +268,27 @@ class ClassWithTypeParameters { ClassWithTypeParameters.class.getName(), typeParameter.getName(), String.class.getName(), getClass().getSimpleName())); } + @Test + public void Dependency_from_generic_superclass_type_arguments() { + @SuppressWarnings("unused") + class Base { + } + @SuppressWarnings("unused") + class ClassWithTypeParameters extends Base { + } + + JavaClass javaClass = importClassesWithContext(ClassWithTypeParameters.class, String.class, Serializable.class).get(ClassWithTypeParameters.class); + JavaParameterizedType genericSuperClass = (JavaParameterizedType) javaClass.getSuperclass().get(); + + Dependency dependency = getOnlyElement(Dependency.tryCreateFromGenericSuperclassTypeArguments(javaClass, genericSuperClass, (JavaClass) genericSuperClass.getActualTypeArguments().get(0))); + + assertThatType(dependency.getOriginClass()).matches(ClassWithTypeParameters.class); + assertThatType(dependency.getTargetClass()).matches(String.class); + assertThat(dependency.getDescription()).as("description").contains(String.format( + "Class <%s> has generic superclass <%s> with type argument depending on <%s> in (%s.java:0)", + ClassWithTypeParameters.class.getName(), Base.class.getName(), String.class.getName(), getClass().getSimpleName())); + } + @Test public void origin_predicates_match() { assertThatDependency(Origin.class, Target.class) 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 9a1357e934..ca7c62f975 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 @@ -486,6 +486,34 @@ public void direct_dependencies_from_self_by_inheritance() { .inLineNumber(0)); } + @Test + public void direct_dependencies_from_self_by_inheritance_through_generic_superclass_parameters() { + @SuppressWarnings("unused") + class Base { + } + class Child extends Base< + Comparable>, + Map< + Map.Entry>, + Map>>>>>>>> { + } + + JavaClass javaClass = importClassWithContext(Child.class); + + assertThatDependencies(javaClass.getDirectDependenciesFromSelf()) + .contain(from(Child.class).to(Base.class).inLocation(getClass(), 0) + .withDescriptionContaining("extends") + + .from(Child.class) + .withExpectedDescriptionTemplate("has generic superclass <" + Base.class.getName() + "> with type argument depending on <#target>") + .to(Comparable.class, Map.class, Map.Entry.class, String.class, BufferedInputStream[][].class, Serializable.class, List.class, Set.class, Iterable.class, File.class) + + .from(Child.class).to(BufferedInputStream.class).inLocation(getClass(), 0) + .withDescriptionContaining("depends on component type <%s>", BufferedInputStream.class.getName()) + ); + } + @Test public void direct_dependencies_from_self_by_member_declarations() { JavaClass javaClass = importClasses(AhavingMembersOfTypeB.class, B.class).get(AhavingMembersOfTypeB.class); @@ -596,41 +624,18 @@ class ClassWithTypeParameters< JavaClass javaClass = importClasses(ClassWithTypeParameters.class).get(ClassWithTypeParameters.class); assertThatDependencies(javaClass.getDirectDependenciesFromSelf()) - .contain(from(ClassWithTypeParameters.class).to(List.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'FIRST' depending on") - - .from(ClassWithTypeParameters.class).to(Serializable.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'FIRST' depending on") - - .from(ClassWithTypeParameters.class).to(Comparable.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'FIRST' depending on") - - .from(ClassWithTypeParameters.class).to(Map.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'SECOND' depending on") - - .from(ClassWithTypeParameters.class).to(Map.Entry.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'SECOND' depending on") - - .from(ClassWithTypeParameters.class).to(String.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'SECOND' depending on") - - .from(ClassWithTypeParameters.class).to(BufferedInputStream[][].class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'SECOND' depending on") - - .from(ClassWithTypeParameters.class).to(Serializable.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'SECOND' depending on") - - .from(ClassWithTypeParameters.class).to(List.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'SECOND' depending on") - - .from(ClassWithTypeParameters.class).to(Set.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'SECOND' depending on") - - .from(ClassWithTypeParameters.class).to(Iterable.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'SECOND' depending on") - - .from(ClassWithTypeParameters.class).to(File.class).inLocation(getClass(), 0) - .withDescriptionContaining("type parameter 'SECOND' depending on") + .contain(from(ClassWithTypeParameters.class) + .withExpectedDescriptionTemplate("type parameter 'FIRST' depending on") + .to(List.class, Serializable.class, Comparable.class) + .inLocation(getClass(), 0) + + .from(ClassWithTypeParameters.class) + .withExpectedDescriptionTemplate("type parameter 'SECOND' depending on") + .to(Map.class, Map.Entry.class, String.class, BufferedInputStream[][].class, Serializable.class, List.class, Set.class, Iterable.class, File.class) + .inLocation(getClass(), 0) + + .from(ClassWithTypeParameters.class).to(BufferedInputStream.class).inLocation(getClass(), 0) + .withDescriptionContaining("depends on component type <%s>", BufferedInputStream.class.getName()) ); } @@ -693,6 +698,42 @@ public void direct_dependencies_to_self_by_inheritance() { .inLineNumber(0)); } + @Test + public void direct_dependencies_to_self_by_inheritance_through_generic_superclass_parameters() { + @SuppressWarnings("unused") + class FirstBase { + } + class FirstChild extends FirstBase< + Comparable, + Map< + Map.Entry>, + Map>>>>>>>> { + } + @SuppressWarnings("unused") + class SecondBase { + } + class SecondChild extends SecondBase> { + } + + JavaClasses javaClasses = importClassesWithContext(FirstChild.class, SecondChild.class, BufferedInputStream.class, File.class); + + assertThatDependencies(javaClasses.get(File.class).getDirectDependenciesToSelf()) + .contain(from(FirstChild.class).to(File.class).inLocation(getClass(), 0) + .withDescriptionContaining("Class <%s> has generic superclass <%s> with type argument depending on <%s>", + FirstChild.class.getName(), FirstBase.class.getName(), File.class.getName()) + + .from(SecondChild.class).to(File.class).inLocation(getClass(), 0) + .withDescriptionContaining("Class <%s> has generic superclass <%s> with type argument depending on <%s>", + SecondChild.class.getName(), SecondBase.class.getName(), File.class.getName()) + ); + + assertThatDependencies(javaClasses.get(BufferedInputStream.class).getDirectDependenciesToSelf()) + .contain(from(FirstChild.class).to(BufferedInputStream.class).inLocation(getClass(), 0) + .withDescriptionContaining("depends on component type <%s>", BufferedInputStream.class.getName()) + ); + } + @Test public void direct_dependencies_to_self_by_member_declarations() { JavaClass javaClass = importClassesWithContext(AhavingMembersOfTypeB.class, B.class).get(B.class); diff --git a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/DependenciesAssertion.java b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/DependenciesAssertion.java index 629e972830..09eaf10c32 100644 --- a/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/DependenciesAssertion.java +++ b/archunit/src/test/java/com/tngtech/archunit/testutil/assertion/DependenciesAssertion.java @@ -10,6 +10,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; import com.google.common.collect.Iterables; +import com.tngtech.archunit.base.HasDescription; import com.tngtech.archunit.core.domain.Dependency; import org.assertj.core.api.AbstractIterableAssert; @@ -111,6 +112,7 @@ public static ExpectedDependenciesCreator from(Class origin) { public static class ExpectedDependenciesCreator { private final ExpectedDependencies expectedDependencies; + private Optional descriptionTemplate = Optional.absent(); private final Class origin; private ExpectedDependenciesCreator(ExpectedDependencies expectedDependencies, Class origin) { @@ -118,8 +120,16 @@ private ExpectedDependenciesCreator(ExpectedDependencies expectedDependencies, C this.origin = origin; } - public ExpectedDependencies to(Class target) { - return expectedDependencies.add(origin, target); + public ExpectedDependenciesCreator withExpectedDescriptionTemplate(String descriptionTemplate) { + this.descriptionTemplate = Optional.of(descriptionTemplate); + return this; + } + + public ExpectedDependencies to(Class... targets) { + for (Class target : targets) { + expectedDependencies.add(origin, target, descriptionTemplate); + } + return expectedDependencies; } } @@ -138,9 +148,12 @@ public ExpectedDependenciesCreator from(Class origin) { return new ExpectedDependenciesCreator(this, origin); } - ExpectedDependencies add(Class origin, Class target) { - expectedDependencies.add(new ExpectedDependency(origin, target)); - return this; + void add(Class origin, Class target, Optional descriptionTemplate) { + ExpectedDependency expectedDependency = new ExpectedDependency(origin, target); + if (descriptionTemplate.isPresent()) { + expectedDependency.descriptionContaining(descriptionTemplate.get().replace("#target", target.getName())); + } + expectedDependencies.add(expectedDependency); } public ExpectedDependencies withDescriptionContaining(String descriptionTemplate, Object... args) { @@ -172,7 +185,7 @@ boolean matches(Dependency dependency) { && (!locationPart.isPresent() || dependency.getDescription().endsWith(locationPart.get())); } - public void descriptionContaining(String descriptionTemplate, Object[] args) { + public void descriptionContaining(String descriptionTemplate, Object... args) { String descriptionPart = String.format(descriptionTemplate, args); descriptionPattern = Optional.of(Pattern.compile(".*" + quote(descriptionPart) + ".*")); } @@ -190,7 +203,7 @@ public String toString() { } } - private static class ExpectedDependenciesMatchResult { + private class ExpectedDependenciesMatchResult { private final Iterable missingDependencies; private final Iterable unexpectedDependencies; @@ -201,8 +214,17 @@ private ExpectedDependenciesMatchResult(Iterable missingDepe void assertNoMissingDependencies() { if (!Iterables.isEmpty(missingDependencies)) { - throw new AssertionError("Could not find expected dependencies:" + lineSeparator() + Joiner.on(lineSeparator()).join(missingDependencies)); + throw new AssertionError("Could not find expected dependencies:" + lineSeparator() + Joiner.on(lineSeparator()).join(missingDependencies) + + lineSeparator() + "within: " + lineSeparator() + Joiner.on(lineSeparator()).join(descriptionsOf(actual))); + } + } + + private List descriptionsOf(Iterable haveDescriptions) { + List result = new ArrayList<>(); + for (HasDescription hasDescription : haveDescriptions) { + result.add(hasDescription.getDescription()); } + return result; } public void assertAllDependenciesMatched() {