From c45ffe166a1b0d22ed4d0ac55e993512d73f1d69 Mon Sep 17 00:00:00 2001 From: Manfred Hanke Date: Thu, 4 Apr 2019 18:41:18 +0200 Subject: [PATCH 1/4] remove duplicate import introduced with efbbc3255c9505a050488d25bf7fbb1c0ad5c679 after rebase Signed-off-by: Manfred Hanke --- .../tngtech/archunit/lang/syntax/elements/FieldsShouldTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/FieldsShouldTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/FieldsShouldTest.java index 89093112a0..8e4d38b15b 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/FieldsShouldTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/FieldsShouldTest.java @@ -5,7 +5,6 @@ import java.util.Map; import java.util.Set; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList; import com.tngtech.archunit.lang.ArchRule; import com.tngtech.archunit.lang.EvaluationResult; From 291d1d5c10e551928b130d2c7bef78ca955790af Mon Sep 17 00:00:00 2001 From: Manfred Hanke Date: Thu, 28 Mar 2019 22:36:24 +0100 Subject: [PATCH 2/4] add members().that().{have,doNotHave}FullName[Not][Matching] syntax Signed-off-by: Manfred Hanke --- .../core/domain/properties/HasName.java | 46 +++++++++++++++ .../lang/syntax/MembersThatInternal.java | 22 ++++++++ .../lang/syntax/elements/MembersThat.java | 36 ++++++++++++ .../core/domain/properties/HasNameTest.java | 56 ++++++++++++++----- .../syntax/elements/GivenMembersTest.java | 27 +++++++++ 5 files changed, 174 insertions(+), 13 deletions(-) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java index 481a370977..796db3d7b4 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java @@ -30,6 +30,52 @@ public interface HasName { interface AndFullName extends HasName { @PublicAPI(usage = ACCESS) String getFullName(); + + final class Predicates { + private Predicates() { + } + + @PublicAPI(usage = ACCESS) + public static DescribedPredicate fullName(String fullName) { + return new FullNameEqualsPredicate(fullName); + } + + /** + * Matches full names against a regular expression. + */ + @PublicAPI(usage = ACCESS) + public static DescribedPredicate fullNameMatching(String regex) { + return new FullNameMatchingPredicate(regex); + } + + private static class FullNameEqualsPredicate extends DescribedPredicate { + private final String fullName; + + FullNameEqualsPredicate(String fullName) { + super(String.format("full name '%s'", fullName)); + this.fullName = fullName; + } + + @Override + public boolean apply(HasName.AndFullName input) { + return input.getFullName().equals(fullName); + } + } + + private static class FullNameMatchingPredicate extends DescribedPredicate { + private final Pattern pattern; + + FullNameMatchingPredicate(String regex) { + super(String.format("full name matching '%s'", regex)); + this.pattern = Pattern.compile(regex); + } + + @Override + public boolean apply(HasName.AndFullName input) { + return pattern.matcher(input.getFullName()).matches(); + } + } + } } final class Predicates { diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/MembersThatInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/MembersThatInternal.java index d4a35062f7..68368ec679 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/MembersThatInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/MembersThatInternal.java @@ -31,6 +31,8 @@ import static com.tngtech.archunit.core.domain.JavaMember.Predicates.declaredIn; import static com.tngtech.archunit.core.domain.properties.CanBeAnnotated.Predicates.annotatedWith; import static com.tngtech.archunit.core.domain.properties.CanBeAnnotated.Predicates.metaAnnotatedWith; +import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullName; +import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullNameMatching; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching; import static com.tngtech.archunit.lang.conditions.ArchPredicates.are; @@ -71,6 +73,26 @@ public CONJUNCTION haveNameNotMatching(String regex) { return givenWith(SyntaxPredicates.haveNameNotMatching(regex)); } + @Override + public CONJUNCTION haveFullName(String fullName) { + return givenWith(have(fullName(fullName))); + } + + @Override + public CONJUNCTION doNotHaveFullName(String fullName) { + return givenWith(doNot(have(fullName(fullName)))); + } + + @Override + public CONJUNCTION haveFullNameMatching(String regex) { + return givenWith(have(fullNameMatching(regex))); + } + + @Override + public CONJUNCTION haveFullNameNotMatching(String regex) { + return givenWith(have(not(fullNameMatching(regex)).as("full name not matching '%s'", regex))); + } + @Override public CONJUNCTION arePublic() { return givenWith(SyntaxPredicates.arePublic()); 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 70e3d60cb1..6cbfe2a35d 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 @@ -67,6 +67,42 @@ public interface MembersThat> { @PublicAPI(usage = ACCESS) CONJUNCTION haveNameNotMatching(String regex); + /** + * Matches members by their full name. + * + * @param fullName The member's full name + * @return A syntax conjunction element, which can be completed to form a full rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION haveFullName(String fullName); + + /** + * Matches members that do not have a certain full name. + * + * @param fullName The member's full name + * @return A syntax conjunction element, which can be completed to form a full rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION doNotHaveFullName(String fullName); + + /** + * Matches members with a full name matching a given regular expression. + * + * @param regex A regular expression + * @return A syntax conjunction element, which can be completed to form a full rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION haveFullNameMatching(String regex); + + /** + * Matches members with a full name not matching a given regular expression. + * + * @param regex A regular expression + * @return A syntax conjunction element, which can be completed to form a full rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION haveFullNameNotMatching(String regex); + /** * Matches public members. * diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/properties/HasNameTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/properties/HasNameTest.java index 0c8aa8209c..4d13d23671 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/properties/HasNameTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/properties/HasNameTest.java @@ -3,28 +3,30 @@ import org.assertj.core.api.AbstractBooleanAssert; import org.junit.Test; +import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullName; +import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullNameMatching; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching; import static com.tngtech.archunit.testutil.Assertions.assertThat; public class HasNameTest { @Test - public void match_against_regex() { - assertMatches("Some.foobar", ".*foo.*").isTrue(); - assertMatches("Some.fobar", ".*foo.*").isFalse(); - assertMatches("Some.foobar", ".*fob?o*.*").isTrue(); - assertMatches("com.tngtech.SomeClass", ".*W.*").isFalse(); - assertMatches("com.tngtech.SomeClass", "com.*").isTrue(); - assertMatches("com.tngtech.SomeClass", "co\\..*").isFalse(); - assertMatches("com.tngtech.SomeClass", ".*Class").isTrue(); - assertMatches("com.tngtech.SomeClass", ".*Clas").isFalse(); - assertMatches("com.tngtech.SomeClass", ".*\\.S.*s").isTrue(); + public void nameMatching_predicate() { + assertNameMatches("Some.foobar", ".*foo.*").isTrue(); + assertNameMatches("Some.fobar", ".*foo.*").isFalse(); + assertNameMatches("Some.foobar", ".*fob?o*.*").isTrue(); + assertNameMatches("com.tngtech.SomeClass", ".*W.*").isFalse(); + assertNameMatches("com.tngtech.SomeClass", "com.*").isTrue(); + assertNameMatches("com.tngtech.SomeClass", "co\\..*").isFalse(); + assertNameMatches("com.tngtech.SomeClass", ".*Class").isTrue(); + assertNameMatches("com.tngtech.SomeClass", ".*Clas").isFalse(); + assertNameMatches("com.tngtech.SomeClass", ".*\\.S.*s").isTrue(); assertThat(nameMatching(".*foo")).hasDescription("name matching '.*foo'"); } @Test - public void match_against_name() { + public void name_predicate() { assertThat(name("some.Foo")) .accepts(newHasName("some.Foo")) .rejects(newHasName("some.Fo")) @@ -32,17 +34,45 @@ public void match_against_name() { assertThat(name("Foo")).rejects(newHasName("some.Foo")); } - private AbstractBooleanAssert assertMatches(String input, String regex) { + @Test + public void fullName_predicate() { + assertThat(fullName("some.Foo.field1")) + .accepts(newHasNameAndFullName("field1", "some.Foo.field1")) + .rejects(newHasNameAndFullName("field", "some.Foo.field")) + .rejects(newHasNameAndFullName("field12", "some.Foo.field12")) + .rejects(newHasNameAndFullName("some.Foo.field1", "some.Foo.field1.property")) + .hasDescription("full name 'some.Foo.field1'"); + } + + @Test + public void fullNameMatching_predicate() { + assertThat(fullNameMatching(".*method\\(.*\\)")) + .accepts(newHasNameAndFullName("method", "some.Foo.method(int)")) + .accepts(newHasNameAndFullName("method", "some.Foo.method()")) + .rejects(newHasNameAndFullName("method", "some.Foo.method")) + .hasDescription("full name matching '.*method\\(.*\\)'"); + } + + private AbstractBooleanAssert assertNameMatches(String input, String regex) { return assertThat(nameMatching(regex).apply(newHasName(input))) .as(input + " =~ " + regex); } private HasName newHasName(final String name) { - return new HasName() { + return newHasNameAndFullName(name, "full " + name); + } + + private HasName.AndFullName newHasNameAndFullName(final String name, final String fullName) { + return new HasName.AndFullName() { @Override public String getName() { return name; } + + @Override + public String getFullName() { + return fullName; + } }; } } \ No newline at end of file diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersTest.java index 3d1c76e1a5..42db09e141 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersTest.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; @@ -52,6 +53,7 @@ import static com.tngtech.java.junit.dataprovider.DataProviders.$$; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; +import static java.util.regex.Pattern.quote; import static org.assertj.core.api.Assertions.assertThat; @RunWith(DataProviderRunner.class) @@ -147,6 +149,7 @@ public void complex_members_syntax() { @DataProvider public static Object[][] restricted_property_rule_starts() { + String classNameDot = ClassWithVariousMembers.class.getName() + "."; ImmutableList.Builder data = ImmutableList.builder().add( $(described(members().that().haveName(FIELD_A)), ImmutableSet.of(FIELD_A)), $(described(codeUnits().that().haveName(FIELD_A)), ImmutableSet.of()), @@ -186,6 +189,30 @@ public static Object[][] restricted_property_rule_starts() { $(described(codeUnits().that().haveNameNotMatching(".*init.*")), ALL_METHOD_DESCRIPTIONS), $(described(constructors().that().haveNameNotMatching(".*init.*")), emptySet()), + $(described(members().that().haveFullName(classNameDot + FIELD_A)), ImmutableSet.of(FIELD_A)), + $(described(codeUnits().that().haveFullName(classNameDot + METHOD_A)), ImmutableSet.of(METHOD_A)), + $(described(methods().that().haveFullName(classNameDot + METHOD_A)), ImmutableSet.of(METHOD_A)), + $(described(constructors().that().haveFullName(classNameDot + CONSTRUCTOR_ONE_ARG)), ImmutableSet.of(CONSTRUCTOR_ONE_ARG)), + $(described(fields().that().haveFullName(classNameDot + FIELD_A)), ImmutableSet.of(FIELD_A)), + $(described(members().that().doNotHaveFullName(classNameDot + FIELD_A)), union(allFieldsExcept(FIELD_A), ALL_CODE_UNIT_DESCRIPTIONS)), + $(described(codeUnits().that().doNotHaveFullName(classNameDot + FIELD_A)), ALL_CODE_UNIT_DESCRIPTIONS), + $(described(methods().that().doNotHaveFullName(classNameDot + METHOD_A)), allMethodsExcept(METHOD_A)), + $(described(constructors().that().doNotHaveFullName(classNameDot + CONSTRUCTOR_ONE_ARG)), allConstructorsExcept(CONSTRUCTOR_ONE_ARG)), + $(described(fields().that().doNotHaveFullName(classNameDot + FIELD_A)), allFieldsExcept(FIELD_A)), + + $(described(members().that().haveFullNameMatching(quote(classNameDot) + ".*A.*")), ImmutableSet.of(FIELD_A, METHOD_A)), + $(described(codeUnits().that().haveFullNameMatching(quote(classNameDot) + ".*A.*")), ImmutableSet.of(METHOD_A)), + $(described(methods().that().haveFullNameMatching(quote(classNameDot) + ".*A.*")), ImmutableSet.of(METHOD_A)), + $(described(constructors().that().haveFullNameMatching(".*init.*")), ALL_CONSTRUCTOR_DESCRIPTIONS), + $(described(fields().that().haveFullNameMatching(quote(classNameDot) + ".*A.*")), ImmutableSet.of(FIELD_A)), + $(described(members().that().haveFullNameNotMatching(quote(classNameDot) + "f.*A.*")), union( + allFieldsExcept(FIELD_A), + ALL_CODE_UNIT_DESCRIPTIONS)), + $(described(codeUnits().that().haveFullNameNotMatching(quote(classNameDot) + "f.*A.*")), ALL_CODE_UNIT_DESCRIPTIONS), + $(described(methods().that().haveFullNameNotMatching(quote(classNameDot) + ".*A.*")), allMethodsExcept(METHOD_A)), + $(described(constructors().that().haveFullNameNotMatching(".*init.*")), emptySet()), + $(described(fields().that().haveFullNameNotMatching(quote(classNameDot) + ".*A.*")), allFieldsExcept(FIELD_A)), + $(described(members().that().arePublic()), ImmutableSet.of( FIELD_PUBLIC, METHOD_PUBLIC, CONSTRUCTOR_PUBLIC)), $(described(fields().that().arePublic()), ImmutableSet.of(FIELD_C)), From 5879c48909dc1f3e3b8212ba7ca8fdd1b1265cf3 Mon Sep 17 00:00:00 2001 From: Manfred Hanke Date: Mon, 22 Jul 2019 12:18:41 +0200 Subject: [PATCH 3/4] add members().should().{have,notHave}FullName[Not][Matching] syntax Signed-off-by: Manfred Hanke --- .../core/domain/properties/HasName.java | 12 ++--- .../lang/conditions/ArchConditions.java | 45 ++++++++++++++----- .../syntax/AbstractMembersShouldInternal.java | 19 ++++++++ .../lang/syntax/elements/MembersShould.java | 36 +++++++++++++++ .../syntax/elements/MembersShouldTest.java | 27 +++++++++++ 5 files changed, 121 insertions(+), 18 deletions(-) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java index 796db3d7b4..fba3042730 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java @@ -44,8 +44,8 @@ public static DescribedPredicate fullName(String fullName) * Matches full names against a regular expression. */ @PublicAPI(usage = ACCESS) - public static DescribedPredicate fullNameMatching(String regex) { - return new FullNameMatchingPredicate(regex); + public static DescribedPredicate fullNameMatching(String regex) { + return new FullNameMatchingPredicate<>(regex); } private static class FullNameEqualsPredicate extends DescribedPredicate { @@ -62,7 +62,7 @@ public boolean apply(HasName.AndFullName input) { } } - private static class FullNameMatchingPredicate extends DescribedPredicate { + private static class FullNameMatchingPredicate extends DescribedPredicate { private final Pattern pattern; FullNameMatchingPredicate(String regex) { @@ -86,8 +86,8 @@ private Predicates() { * Matches names against a regular expression. */ @PublicAPI(usage = ACCESS) - public static DescribedPredicate nameMatching(final String regex) { - return new NameMatchingPredicate(regex); + public static DescribedPredicate nameMatching(final String regex) { + return new NameMatchingPredicate<>(regex); } @PublicAPI(usage = ACCESS) @@ -95,7 +95,7 @@ public static DescribedPredicate name(final String name) { return new NameEqualsPredicate(name); } - private static class NameMatchingPredicate extends DescribedPredicate { + private static class NameMatchingPredicate extends DescribedPredicate { private final Pattern pattern; NameMatchingPredicate(String regex) { 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 b5899b877b..a5cb97159a 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 @@ -98,8 +98,8 @@ import static com.tngtech.archunit.core.domain.properties.CanBeAnnotated.Predicates.annotatedWith; import static com.tngtech.archunit.core.domain.properties.CanBeAnnotated.Predicates.metaAnnotatedWith; import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier; +import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullName; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name; -import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching; import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner; import static com.tngtech.archunit.core.domain.properties.HasParameterTypes.Predicates.rawParameterTypes; import static com.tngtech.archunit.core.domain.properties.HasReturnType.Predicates.rawReturnType; @@ -451,6 +451,16 @@ public static haveName(name)); } + @PublicAPI(usage = ACCESS) + public static ArchCondition haveFullName(String fullName) { + return new HaveConditionByPredicate<>(fullName(fullName)); + } + + @PublicAPI(usage = ACCESS) + public static ArchCondition notHaveFullName(String fullName) { + return not(new HaveConditionByPredicate(fullName(fullName))); + } + @PublicAPI(usage = ACCESS) public static ArchCondition haveFullyQualifiedName(final String name) { return new HaveConditionByPredicate<>(fullyQualifiedName(name)); @@ -516,8 +526,8 @@ public static ArchCondition haveSimpleNameNotEndingWith(String suffix @PublicAPI(usage = ACCESS) public static ArchCondition haveNameMatching(final String regex) { - final DescribedPredicate haveNameMatching = have(nameMatching(regex)); - return new NameMatchingCondition<>(haveNameMatching, regex); + final DescribedPredicate haveNameMatching = have(HasName.Predicates.nameMatching(regex)); + return new MatchingCondition<>(haveNameMatching, regex); } @PublicAPI(usage = ACCESS) @@ -525,6 +535,17 @@ public static haveNameMatching(regex)).as("have name not matching '%s'", regex); } + @PublicAPI(usage = ACCESS) + public static ArchCondition haveFullNameMatching(String regex) { + final DescribedPredicate haveFullNameMatching = have(HasName.AndFullName.Predicates.fullNameMatching(regex)); + return new MatchingCondition(haveFullNameMatching, regex); + } + + @PublicAPI(usage = ACCESS) + public static ArchCondition haveFullNameNotMatching(String regex) { + return not(ArchConditions.haveFullNameMatching(regex)).as("have full name not matching '%s'", regex); + } + @PublicAPI(usage = ACCESS) public static ArchCondition resideInAPackage(final String packageIdentifier) { return new DoesConditionByPredicate<>(JavaClass.Predicates.resideInAPackage(packageIdentifier)); @@ -1095,22 +1116,22 @@ public void check(JavaClass javaClass, ConditionEvents events) { } } - private static class NameMatchingCondition extends ArchCondition { - private final DescribedPredicate haveNameMatching; + private static class MatchingCondition extends ArchCondition { + private final DescribedPredicate matcher; private final String regex; - NameMatchingCondition(DescribedPredicate haveNameMatching, String regex) { - super(haveNameMatching.getDescription()); - this.haveNameMatching = haveNameMatching; + MatchingCondition(DescribedPredicate matcher, String regex) { + super(matcher.getDescription()); + this.matcher = matcher; this.regex = regex; } @Override - public void check(HAS_NAME hasName, ConditionEvents events) { - boolean satisfied = haveNameMatching.apply(hasName); - String message = createMessage(hasName, + public void check(T item, ConditionEvents events) { + boolean satisfied = matcher.apply(item); + String message = createMessage(item, String.format("%s '%s'", satisfied ? "matches" : "does not match", regex)); - events.add(new SimpleConditionEvent(hasName, satisfied, message)); + events.add(new SimpleConditionEvent(item, satisfied, message)); } } 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 0b5e6bb313..253fb94908 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 @@ -79,6 +79,25 @@ public SELF haveNameNotMatching(String regex) { return addCondition(ArchConditions.haveNameNotMatching(regex)); } + @Override + public SELF haveFullName(String fullName) { + return addCondition(ArchConditions.haveFullName(fullName)); + } + + @Override + public SELF notHaveFullName(String fullName) { + return addCondition(ArchConditions.notHaveFullName(fullName)); + } + + @Override + public SELF haveFullNameMatching(String regex) { + return addCondition(ArchConditions.haveFullNameMatching(regex)); + } + + @Override + public SELF haveFullNameNotMatching(String regex) { + return addCondition(ArchConditions.haveFullNameNotMatching(regex)); + } @Override public SELF bePublic() { return addCondition(ArchConditions.bePublic()); 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 065fd4fa36..5aca2f0fcf 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 @@ -67,6 +67,42 @@ public interface MembersShould> @PublicAPI(usage = ACCESS) CONJUNCTION haveNameNotMatching(String regex); + /** + * Asserts that members have a certain full name. + * + * @param fullName The member's full name + * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION haveFullName(String fullName); + + /** + * Asserts that members do not have a certain full name. + * + * @param fullName The member's full name + * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION notHaveFullName(String fullName); + + /** + * Asserts that members have a full name matching a given regular expression. + * + * @param regex A regular expression + * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION haveFullNameMatching(String regex); + + /** + * Asserts that members have a full name not matching a given regular expression. + * + * @param regex A regular expression + * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION haveFullNameNotMatching(String regex); + /** * Asserts that members are public. * diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MembersShouldTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MembersShouldTest.java index 54d8a9a8ef..235f782806 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MembersShouldTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MembersShouldTest.java @@ -100,6 +100,7 @@ public void complex_members_syntax() { @DataProvider public static Object[][] restricted_property_rule_ends() { + String classNameDot = ClassWithVariousMembers.class.getName() + "."; ImmutableList.Builder data = ImmutableList.builder().add( $(members().should().haveName(FIELD_A), allMembersExcept(FIELD_A)), $(codeUnits().should().haveName(FIELD_A), ALL_CODE_UNIT_DESCRIPTIONS), @@ -131,6 +132,32 @@ public static Object[][] restricted_property_rule_ends() { $(codeUnits().should().haveNameNotMatching(".*init.*"), ALL_CONSTRUCTOR_DESCRIPTIONS), $(constructors().should().haveNameNotMatching(".*init.*"), ALL_CONSTRUCTOR_DESCRIPTIONS), + $(members().should().haveFullName(classNameDot + FIELD_A), allMembersExcept(FIELD_A)), + $(fields().should().haveFullName(classNameDot + FIELD_A), allFieldsExcept(FIELD_A)), + $(codeUnits().should().haveFullName(classNameDot + FIELD_A), ALL_CODE_UNIT_DESCRIPTIONS), + $(methods().should().haveFullName(classNameDot + METHOD_A), allMethodsExcept(METHOD_A)), + $(codeUnits().should().haveFullName(classNameDot + METHOD_A), allCodeUnitsExcept(METHOD_A)), + $(members().should().notHaveFullName(classNameDot + FIELD_A), ImmutableSet.of(FIELD_A)), + $(fields().should().notHaveFullName(classNameDot + FIELD_A), ImmutableSet.of(FIELD_A)), + $(codeUnits().should().notHaveFullName(classNameDot + FIELD_A), emptySet()), + $(methods().should().notHaveFullName(classNameDot + METHOD_A), ImmutableSet.of(METHOD_A)), + $(codeUnits().should().notHaveFullName(classNameDot + METHOD_A), ImmutableSet.of(METHOD_A)), + + $(members().should().haveFullNameMatching(quote(classNameDot) + ".*A\\(?\\)?"), allMembersExcept(FIELD_A, METHOD_A)), + $(codeUnits().should().haveFullNameMatching(quote(classNameDot) + ".*A"), ALL_CODE_UNIT_DESCRIPTIONS), + $(fields().should().haveFullNameMatching(quote(classNameDot) + ".*A"), allFieldsExcept(FIELD_A)), + $(codeUnits().should().haveFullNameMatching(quote(classNameDot) + ".*A" + quote("()")), allCodeUnitsExcept(METHOD_A)), + $(methods().should().haveFullNameMatching(quote(classNameDot) + ".*A" + quote("()")), allMethodsExcept(METHOD_A)), + $(codeUnits().should().haveFullNameMatching(quote(classNameDot) + "..*init.*"), ALL_METHOD_DESCRIPTIONS), + $(constructors().should().haveFullNameMatching(quote(classNameDot) + ".*init.*"), emptySet()), + $(members().should().haveFullNameNotMatching(quote(classNameDot) + ".*A\\(?\\)?"), ImmutableSet.of(FIELD_A, METHOD_A)), + $(codeUnits().should().haveFullNameNotMatching(quote(classNameDot) + ".*A"), emptySet()), + $(fields().should().haveFullNameNotMatching(quote(classNameDot) + ".*A"), ImmutableSet.of(FIELD_A)), + $(codeUnits().should().haveFullNameNotMatching(quote(classNameDot) + ".*A" + quote("()")), ImmutableSet.of(METHOD_A)), + $(methods().should().haveFullNameNotMatching(quote(classNameDot) + ".*A" + quote("()")), ImmutableSet.of(METHOD_A)), + $(codeUnits().should().haveFullNameNotMatching(quote(classNameDot) + ".*init.*"), ALL_CONSTRUCTOR_DESCRIPTIONS), + $(constructors().should().haveFullNameNotMatching(quote(classNameDot) + ".*init.*"), ALL_CONSTRUCTOR_DESCRIPTIONS), + $(members().should().bePublic(), allMembersExcept( FIELD_PUBLIC, METHOD_PUBLIC, CONSTRUCTOR_PUBLIC)), $(fields().should().bePublic(), allFieldsExcept(FIELD_PUBLIC)), From 71a524e07d1045747264bcfd1b8f0a6e0a5cce7f Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Mon, 29 Jul 2019 01:07:59 +0200 Subject: [PATCH 4/4] Review: - Added some Javadoc (since I'm not sure if 'full name' can be immediately understood by every user) - Removed the generic return type from the predicates in HasName and HasName.AndFullName since the caller should be responsible to map to the subtype (or it would have to be consistently changed in many other places) - Tried to make some tests more decisive by matching at least some element of the passed collection - Unrelated: Added HasName.AndFullName.Functions.GET_FULL_NAME to be consistent with HasName Signed-off-by: Peter Gafert --- .../archunit/core/domain/AccessTarget.java | 4 ++ .../archunit/core/domain/JavaClass.java | 9 +++ .../archunit/core/domain/JavaCodeUnit.java | 3 + .../archunit/core/domain/JavaField.java | 3 + .../core/domain/properties/HasName.java | 60 ++++++++++++------- .../properties/HasSourceCodeLocation.java | 3 + .../lang/conditions/ArchConditions.java | 20 ++++--- .../lang/syntax/elements/MembersShould.java | 12 ++-- .../core/domain/properties/HasNameTest.java | 9 +++ .../syntax/elements/GivenMembersTest.java | 9 +-- .../syntax/elements/MembersShouldTest.java | 6 +- 11 files changed, 99 insertions(+), 39 deletions(-) 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 7e2a3edb25..a3f1871f97 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 @@ -91,6 +91,10 @@ public JavaClass getOwner() { return owner; } + /** + * @return The full name of this {@link AccessTarget}, i.e. a string containing {@code ${declaringClass}.${name}} for a field and + * {@code ${declaringClass}.${name}(${parameterTypes})} for a code unit + */ @Override @PublicAPI(usage = ACCESS) public String getFullName() { 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 25c4609b97..7cf2cdad97 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 @@ -109,6 +109,9 @@ public Set get() { javaPackage = JavaPackage.simple(this); } + /** + * @return The {@link Source} of this {@link JavaClass}, i.e. where this class has been imported from + */ @PublicAPI(usage = ACCESS) public Optional getSource() { return source; @@ -126,12 +129,18 @@ public String getDescription() { return "Class <" + getName() + ">"; } + /** + * @return The fully qualified name of this {@link JavaClass}, compare {@link Class#getName()} of the Reflection API + */ @Override @PublicAPI(usage = ACCESS) public String getName() { return javaType.getName(); } + /** + * @return The fully qualified name of this {@link JavaClass}, i.e. the result is the same as invoking {@link #getName()} + */ @Override @PublicAPI(usage = ACCESS) public String getFullName() { diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java index f6441f4358..db00df07ad 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaCodeUnit.java @@ -62,6 +62,9 @@ public abstract class JavaCodeUnit extends JavaMember implements HasParameterTyp fullName = formatMethod(getOwner().getName(), getName(), getRawParameterTypes()); } + /** + * @return The full name of this {@link JavaCodeUnit}, i.e. a string containing {@code ${declaringClass}.${name}(${parameterTypes})} + */ @Override @PublicAPI(usage = ACCESS) public String getFullName() { diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java index d4ec5b65a2..c64cd3306a 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/JavaField.java @@ -42,6 +42,9 @@ public class JavaField extends JavaMember implements HasType { fieldSupplier = Suppliers.memoize(new ReflectFieldSupplier()); } + /** + * @return The full name of this {@link JavaField}, i.e. a string containing {@code ${declaringClass}.${name}} + */ @Override @PublicAPI(usage = ACCESS) public String getFullName() { diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java index fba3042730..fb152f9d4a 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasName.java @@ -28,6 +28,9 @@ public interface HasName { String getName(); interface AndFullName extends HasName { + /** + * @return The full name of the given object. Varies by context, for details consult Javadoc of the concrete subclass. + */ @PublicAPI(usage = ACCESS) String getFullName(); @@ -44,8 +47,8 @@ public static DescribedPredicate fullName(String fullName) * Matches full names against a regular expression. */ @PublicAPI(usage = ACCESS) - public static DescribedPredicate fullNameMatching(String regex) { - return new FullNameMatchingPredicate<>(regex); + public static DescribedPredicate fullNameMatching(String regex) { + return new FullNameMatchingPredicate(regex); } private static class FullNameEqualsPredicate extends DescribedPredicate { @@ -62,7 +65,7 @@ public boolean apply(HasName.AndFullName input) { } } - private static class FullNameMatchingPredicate extends DescribedPredicate { + private static class FullNameMatchingPredicate extends DescribedPredicate { private final Pattern pattern; FullNameMatchingPredicate(String regex) { @@ -76,50 +79,63 @@ public boolean apply(HasName.AndFullName input) { } } } + + final class Functions { + private Functions() { + } + + @PublicAPI(usage = ACCESS) + public static final ChainableFunction GET_FULL_NAME = new ChainableFunction() { + @Override + public String apply(HasName.AndFullName input) { + return input.getFullName(); + } + }; + } } final class Predicates { private Predicates() { } - /** - * Matches names against a regular expression. - */ @PublicAPI(usage = ACCESS) - public static DescribedPredicate nameMatching(final String regex) { - return new NameMatchingPredicate<>(regex); + public static DescribedPredicate name(final String name) { + return new NameEqualsPredicate(name); } + /** + * Matches names against a regular expression. + */ @PublicAPI(usage = ACCESS) - public static DescribedPredicate name(final String name) { - return new NameEqualsPredicate(name); + public static DescribedPredicate nameMatching(final String regex) { + return new NameMatchingPredicate(regex); } - private static class NameMatchingPredicate extends DescribedPredicate { - private final Pattern pattern; + private static class NameEqualsPredicate extends DescribedPredicate { + private final String name; - NameMatchingPredicate(String regex) { - super(String.format("name matching '%s'", regex)); - this.pattern = Pattern.compile(regex); + NameEqualsPredicate(String name) { + super(String.format("name '%s'", name)); + this.name = name; } @Override public boolean apply(HasName input) { - return pattern.matcher(input.getName()).matches(); + return input.getName().equals(name); } } - private static class NameEqualsPredicate extends DescribedPredicate { - private final String name; + private static class NameMatchingPredicate extends DescribedPredicate { + private final Pattern pattern; - NameEqualsPredicate(String name) { - super(String.format("name '%s'", name)); - this.name = name; + NameMatchingPredicate(String regex) { + super(String.format("name matching '%s'", regex)); + this.pattern = Pattern.compile(regex); } @Override public boolean apply(HasName input) { - return input.getName().equals(name); + return pattern.matcher(input.getName()).matches(); } } } diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasSourceCodeLocation.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasSourceCodeLocation.java index 8b242994e1..5547d93ce2 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasSourceCodeLocation.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/HasSourceCodeLocation.java @@ -21,6 +21,9 @@ import static com.tngtech.archunit.PublicAPI.Usage.ACCESS; public interface HasSourceCodeLocation { + /** + * @return The {@link SourceCodeLocation} of this object, i.e. how to locate the respective object within the set of source files. + */ @PublicAPI(usage = ACCESS) SourceCodeLocation getSourceCodeLocation(); } 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 a5cb97159a..d699fbdb0e 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 @@ -99,7 +99,9 @@ import static com.tngtech.archunit.core.domain.properties.CanBeAnnotated.Predicates.metaAnnotatedWith; import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier; import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullName; +import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullNameMatching; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name; +import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching; import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner; import static com.tngtech.archunit.core.domain.properties.HasParameterTypes.Predicates.rawParameterTypes; import static com.tngtech.archunit.core.domain.properties.HasReturnType.Predicates.rawReturnType; @@ -452,12 +454,14 @@ public static ArchCondition haveFullName(String fullName) { + public static + ArchCondition haveFullName(String fullName) { return new HaveConditionByPredicate<>(fullName(fullName)); } @PublicAPI(usage = ACCESS) - public static ArchCondition notHaveFullName(String fullName) { + public static + ArchCondition notHaveFullName(String fullName) { return not(new HaveConditionByPredicate(fullName(fullName))); } @@ -526,7 +530,7 @@ public static ArchCondition haveSimpleNameNotEndingWith(String suffix @PublicAPI(usage = ACCESS) public static ArchCondition haveNameMatching(final String regex) { - final DescribedPredicate haveNameMatching = have(HasName.Predicates.nameMatching(regex)); + final DescribedPredicate haveNameMatching = have(nameMatching(regex)).forSubType(); return new MatchingCondition<>(haveNameMatching, regex); } @@ -536,13 +540,15 @@ public static ArchCondition haveFullNameMatching(String regex) { - final DescribedPredicate haveFullNameMatching = have(HasName.AndFullName.Predicates.fullNameMatching(regex)); - return new MatchingCondition(haveFullNameMatching, regex); + public static + ArchCondition haveFullNameMatching(String regex) { + final DescribedPredicate haveFullNameMatching = have(fullNameMatching(regex)).forSubType(); + return new MatchingCondition<>(haveFullNameMatching, regex); } @PublicAPI(usage = ACCESS) - public static ArchCondition haveFullNameNotMatching(String regex) { + public static ArchCondition + haveFullNameNotMatching(String regex) { return not(ArchConditions.haveFullNameMatching(regex)).as("have full name not matching '%s'", regex); } 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 5aca2f0fcf..74ce1e7ffd 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 @@ -21,7 +21,9 @@ import com.tngtech.archunit.base.DescribedPredicate; import com.tngtech.archunit.core.domain.JavaAnnotation; import com.tngtech.archunit.core.domain.JavaClass; +import com.tngtech.archunit.core.domain.JavaCodeUnit; import com.tngtech.archunit.core.domain.JavaConstructor; +import com.tngtech.archunit.core.domain.JavaField; import com.tngtech.archunit.core.domain.JavaModifier; import com.tngtech.archunit.lang.syntax.ArchRuleDefinition; @@ -68,7 +70,7 @@ public interface MembersShould> CONJUNCTION haveNameNotMatching(String regex); /** - * Asserts that members have a certain full name. + * Asserts that members have a certain full name (compare {@link JavaField#getFullName()} and {@link JavaCodeUnit#getFullName()}). * * @param fullName The member's full name * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule @@ -77,7 +79,7 @@ public interface MembersShould> CONJUNCTION haveFullName(String fullName); /** - * Asserts that members do not have a certain full name. + * Asserts that members do not have a certain full name (compare {@link JavaField#getFullName()} and {@link JavaCodeUnit#getFullName()}). * * @param fullName The member's full name * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule @@ -86,7 +88,8 @@ public interface MembersShould> CONJUNCTION notHaveFullName(String fullName); /** - * Asserts that members have a full name matching a given regular expression. + * Asserts that members have a full name matching a given regular expression (compare {@link JavaField#getFullName()} + * and {@link JavaCodeUnit#getFullName()}). * * @param regex A regular expression * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule @@ -95,7 +98,8 @@ public interface MembersShould> CONJUNCTION haveFullNameMatching(String regex); /** - * Asserts that members have a full name not matching a given regular expression. + * Asserts that members have a full name not matching a given regular expression (compare {@link JavaField#getFullName()} + * and {@link JavaCodeUnit#getFullName()}). * * @param regex A regular expression * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/properties/HasNameTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/properties/HasNameTest.java index 4d13d23671..ed9bc1d773 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/properties/HasNameTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/properties/HasNameTest.java @@ -3,8 +3,10 @@ import org.assertj.core.api.AbstractBooleanAssert; import org.junit.Test; +import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Functions.GET_FULL_NAME; import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullName; import static com.tngtech.archunit.core.domain.properties.HasName.AndFullName.Predicates.fullNameMatching; +import static com.tngtech.archunit.core.domain.properties.HasName.Functions.GET_NAME; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameMatching; import static com.tngtech.archunit.testutil.Assertions.assertThat; @@ -53,6 +55,13 @@ public void fullNameMatching_predicate() { .hasDescription("full name matching '.*method\\(.*\\)'"); } + @Test + public void functions() { + HasName.AndFullName test = newHasNameAndFullName("simple", "full"); + assertThat(GET_NAME.apply(test)).isEqualTo("simple"); + assertThat(GET_FULL_NAME.apply(test)).isEqualTo("full"); + } + private AbstractBooleanAssert assertNameMatches(String input, String regex) { return assertThat(nameMatching(regex).apply(newHasName(input))) .as(input + " =~ " + regex); diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersTest.java index 42db09e141..e83e127d72 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersTest.java @@ -5,7 +5,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.regex.Pattern; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; @@ -195,7 +194,7 @@ public static Object[][] restricted_property_rule_starts() { $(described(constructors().that().haveFullName(classNameDot + CONSTRUCTOR_ONE_ARG)), ImmutableSet.of(CONSTRUCTOR_ONE_ARG)), $(described(fields().that().haveFullName(classNameDot + FIELD_A)), ImmutableSet.of(FIELD_A)), $(described(members().that().doNotHaveFullName(classNameDot + FIELD_A)), union(allFieldsExcept(FIELD_A), ALL_CODE_UNIT_DESCRIPTIONS)), - $(described(codeUnits().that().doNotHaveFullName(classNameDot + FIELD_A)), ALL_CODE_UNIT_DESCRIPTIONS), + $(described(codeUnits().that().doNotHaveFullName(classNameDot + METHOD_A)), allCodeUnitsExcept(METHOD_A)), $(described(methods().that().doNotHaveFullName(classNameDot + METHOD_A)), allMethodsExcept(METHOD_A)), $(described(constructors().that().doNotHaveFullName(classNameDot + CONSTRUCTOR_ONE_ARG)), allConstructorsExcept(CONSTRUCTOR_ONE_ARG)), $(described(fields().that().doNotHaveFullName(classNameDot + FIELD_A)), allFieldsExcept(FIELD_A)), @@ -203,14 +202,16 @@ public static Object[][] restricted_property_rule_starts() { $(described(members().that().haveFullNameMatching(quote(classNameDot) + ".*A.*")), ImmutableSet.of(FIELD_A, METHOD_A)), $(described(codeUnits().that().haveFullNameMatching(quote(classNameDot) + ".*A.*")), ImmutableSet.of(METHOD_A)), $(described(methods().that().haveFullNameMatching(quote(classNameDot) + ".*A.*")), ImmutableSet.of(METHOD_A)), - $(described(constructors().that().haveFullNameMatching(".*init.*")), ALL_CONSTRUCTOR_DESCRIPTIONS), + $(described(constructors().that().haveFullNameMatching(quote(classNameDot) + ".*init.*String\\)")), + ImmutableSet.of(CONSTRUCTOR_ONE_ARG)), $(described(fields().that().haveFullNameMatching(quote(classNameDot) + ".*A.*")), ImmutableSet.of(FIELD_A)), $(described(members().that().haveFullNameNotMatching(quote(classNameDot) + "f.*A.*")), union( allFieldsExcept(FIELD_A), ALL_CODE_UNIT_DESCRIPTIONS)), $(described(codeUnits().that().haveFullNameNotMatching(quote(classNameDot) + "f.*A.*")), ALL_CODE_UNIT_DESCRIPTIONS), $(described(methods().that().haveFullNameNotMatching(quote(classNameDot) + ".*A.*")), allMethodsExcept(METHOD_A)), - $(described(constructors().that().haveFullNameNotMatching(".*init.*")), emptySet()), + $(described(constructors().that().haveFullNameNotMatching(quote(classNameDot) + ".*init.*String\\)")), + allConstructorsExcept(CONSTRUCTOR_ONE_ARG)), $(described(fields().that().haveFullNameNotMatching(quote(classNameDot) + ".*A.*")), allFieldsExcept(FIELD_A)), $(described(members().that().arePublic()), ImmutableSet.of( diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MembersShouldTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MembersShouldTest.java index 235f782806..3725b15664 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MembersShouldTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/MembersShouldTest.java @@ -46,6 +46,7 @@ import static com.tngtech.archunit.lang.syntax.elements.GivenMembersTest.ALL_OTHER_MEMBER_DESCRIPTIONS; import static com.tngtech.archunit.lang.syntax.elements.GivenMembersTest.ALL_OTHER_METHOD_DESCRIPTIONS; import static com.tngtech.archunit.lang.syntax.elements.GivenMembersTest.CONSTRUCTOR_ANNOTATED_WITH_A; +import static com.tngtech.archunit.lang.syntax.elements.GivenMembersTest.CONSTRUCTOR_ONE_ARG; import static com.tngtech.archunit.lang.syntax.elements.GivenMembersTest.CONSTRUCTOR_PACKAGE_PRIVATE; import static com.tngtech.archunit.lang.syntax.elements.GivenMembersTest.CONSTRUCTOR_PRIVATE; import static com.tngtech.archunit.lang.syntax.elements.GivenMembersTest.CONSTRUCTOR_PROTECTED; @@ -149,14 +150,15 @@ public static Object[][] restricted_property_rule_ends() { $(codeUnits().should().haveFullNameMatching(quote(classNameDot) + ".*A" + quote("()")), allCodeUnitsExcept(METHOD_A)), $(methods().should().haveFullNameMatching(quote(classNameDot) + ".*A" + quote("()")), allMethodsExcept(METHOD_A)), $(codeUnits().should().haveFullNameMatching(quote(classNameDot) + "..*init.*"), ALL_METHOD_DESCRIPTIONS), - $(constructors().should().haveFullNameMatching(quote(classNameDot) + ".*init.*"), emptySet()), + $(constructors().should().haveFullNameMatching(quote(classNameDot) + ".*init.*String\\)"), + allConstructorsExcept(CONSTRUCTOR_ONE_ARG)), $(members().should().haveFullNameNotMatching(quote(classNameDot) + ".*A\\(?\\)?"), ImmutableSet.of(FIELD_A, METHOD_A)), $(codeUnits().should().haveFullNameNotMatching(quote(classNameDot) + ".*A"), emptySet()), $(fields().should().haveFullNameNotMatching(quote(classNameDot) + ".*A"), ImmutableSet.of(FIELD_A)), $(codeUnits().should().haveFullNameNotMatching(quote(classNameDot) + ".*A" + quote("()")), ImmutableSet.of(METHOD_A)), $(methods().should().haveFullNameNotMatching(quote(classNameDot) + ".*A" + quote("()")), ImmutableSet.of(METHOD_A)), $(codeUnits().should().haveFullNameNotMatching(quote(classNameDot) + ".*init.*"), ALL_CONSTRUCTOR_DESCRIPTIONS), - $(constructors().should().haveFullNameNotMatching(quote(classNameDot) + ".*init.*"), ALL_CONSTRUCTOR_DESCRIPTIONS), + $(constructors().should().haveFullNameNotMatching(quote(classNameDot) + ".*init.*String\\)"), ImmutableSet.of(CONSTRUCTOR_ONE_ARG)), $(members().should().bePublic(), allMembersExcept( FIELD_PUBLIC, METHOD_PUBLIC, CONSTRUCTOR_PUBLIC)),