您可以使用谓词而不是流畅的 API 来编写强大的ArchRules;在你的情况下
.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;