0

给定一组不应禁止使用某些 API(无论出于何种原因)的类。

例如,禁止 Java 8 Streaming API,或调用Builder内部类,因为您想强制对特定类使用循环和构造函数。

ownerName关键部分是您事先不知道,并且callMethod(methodName)我无法粗粒度地禁止调用stream()build()方法。

有任何想法吗?

4

1 回答 1

1

ArchRule您可以使用谓词而不是 fluent API来组合强大的 s;在你的情况下 .callMethodWhere(DescribedPredicate<? super JavaMethodCall> predicate)

为了防止使用someCollection.stream(),您可以从 开始HasName.Predicates.name

noClasses().should().callMethodWhere(name("stream"))

为了避免误报,该规则可能应该变得更加具体。

ArchUnit 提供了许多有用的预定义谓词;您只需要找到它们(并可能通过 处理它们的协变参数类型DescribedPredicate.forSubtype):

noClasses().should().callMethodWhere(target(
    name("stream").<CodeUnitCallTarget>forSubtype().and(
        owner(assignableTo(Collection.class)).<CodeUnitCallTarget>forSubtype().and(
                rawParameterTypes(new Class[0])
        )
    )
))

我个人觉得定义一个自定义谓词更简单(例如使用 DescribedPredicate.describe):

noClasses().should().callMethodWhere(target(describe("is Collection.stream()",
    target -> "stream".equals(target.getName()) &&
            target.getOwner().isAssignableTo(Collection.class) &&
            target.getParameterTypes().isEmpty()
)))

仅供参考:我的解决方案使用以下导入:

import static com.tngtech.archunit.base.DescribedPredicate.describe;
import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target;
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableTo;
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name;
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.lang.syntax.ArchRuleDefinition.noClasses;
于 2021-09-27T20:30:09.187 回答