From fcbf07b798d15bd6c5849bc03eb2ef0bffc539d3 Mon Sep 17 00:00:00 2001 From: Leonard Husmann Date: Fri, 28 Apr 2023 10:43:06 +0200 Subject: [PATCH] add support to detect references of fields in methods This adds a method to the public API of FieldsShould.java to check if a field has been accessed by methods matching a given predicate. Issue: #857 Signed-off-by: Leonard Husmann --- .../archunit/lang/conditions/ArchConditions.java | 12 ++++++++++++ .../archunit/lang/syntax/FieldsShouldInternal.java | 6 ++++++ .../archunit/lang/syntax/elements/FieldsShould.java | 10 ++++++++++ 3 files changed, 28 insertions(+) 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 d59fe58788..060b3a97e1 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 @@ -1274,6 +1274,18 @@ public static ArchCondition onlyBeCalledByConstructorsThat(Describ origin.is(matching(JavaConstructor.class, predicate)), GET_CALLS_OF_SELF); } + @PublicAPI(usage = ACCESS) + public static ArchCondition notBeAccessedByMethodsThat(DescribedPredicate predicate) { + return new ArchCondition("not be accessed by methods that " + predicate.getDescription()) { + @Override + public void check(JavaField field, ConditionEvents events) { + field.getAccessesToSelf().stream() + .filter(access -> access.getOrigin() instanceof JavaMethod && predicate.test((JavaMethod) access.getOrigin())) + .forEach(violation -> events.add(SimpleConditionEvent.violated(field, violation.getDescription()))); + } + }; + } + /** * Derives an {@link ArchCondition} from a {@link DescribedPredicate}. Similar to {@link ArchCondition#from(DescribedPredicate)}, * but more conveniently creates a message to be used within a 'have'-sentence. diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/FieldsShouldInternal.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/FieldsShouldInternal.java index 4cddb9baf0..aa2448d722 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/FieldsShouldInternal.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/FieldsShouldInternal.java @@ -20,6 +20,7 @@ import com.tngtech.archunit.base.DescribedPredicate; import com.tngtech.archunit.core.domain.JavaClass; import com.tngtech.archunit.core.domain.JavaField; +import com.tngtech.archunit.core.domain.JavaMethod; import com.tngtech.archunit.lang.ArchCondition; import com.tngtech.archunit.lang.ClassesTransformer; import com.tngtech.archunit.lang.Priority; @@ -93,4 +94,9 @@ public FieldsShouldInternal haveRawType(DescribedPredicate pr public FieldsShouldInternal notHaveRawType(DescribedPredicate predicate) { return addCondition(not(ArchConditions.haveRawType(predicate))); } + + @Override + public FieldsShouldInternal notBeAccessedByMethodsThat(DescribedPredicate predicate) { + return addCondition(ArchConditions.notBeAccessedByMethodsThat(predicate)); + } } diff --git a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/FieldsShould.java b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/FieldsShould.java index dc8b39260e..4e7118db1e 100644 --- a/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/FieldsShould.java +++ b/archunit/src/main/java/com/tngtech/archunit/lang/syntax/elements/FieldsShould.java @@ -18,6 +18,7 @@ import com.tngtech.archunit.PublicAPI; import com.tngtech.archunit.base.DescribedPredicate; import com.tngtech.archunit.core.domain.JavaClass; +import com.tngtech.archunit.core.domain.JavaMethod; import com.tngtech.archunit.core.domain.properties.HasName; import com.tngtech.archunit.lang.syntax.ArchRuleDefinition; @@ -156,6 +157,15 @@ public interface FieldsShould exten @PublicAPI(usage = ACCESS) CONJUNCTION notHaveRawType(DescribedPredicate predicate); + /** + * Asserts that fields are not accessed by methods matching the given predicate. + * + * @param predicate A predicate determining the methods this field should not be accessed by + * @return A syntax element that can either be used as working rule, or to continue specifying a more complex rule + */ + @PublicAPI(usage = ACCESS) + CONJUNCTION notBeAccessedByMethodsThat(DescribedPredicate predicate); + /** * Asserts that fields are static. *