list all method who called another method (even through a bunch of intermediate method)

36 Views Asked by At

Hy, I want to check that the name of all method who call some other method "post" aren't prefixed with "get", but I can only reach to method who directly call the said "post", not the ones who call one (or more) intermediate method.

Any idea?

my code so far:

   methods().that().haveNameStartingWith("post")
            .should()
            .onlyBeCalled()
            .byMethodsThat(
                not(
                    HasName.Predicates.nameStartingWith("post")
                )
            ).check(classes
1

There are 1 best solutions below

0
Manfred On

I think that ArchUnit currently (as of ArchUnit 1.2.1) does not offer a predefined API for such a rule, but you can implement a custom ArchCondition for your needs.

A naive solution (which may lead to duplicates and even StackOverflowErrors) could look like this:

// import static com.tngtech.archunit.lang.conditions.ArchConditions.not;


ArchRule rule = methods().that().haveNameStartingWith("post")
        .should(not(beTransitivelyCalledByMethodsWithNameStartingWith("get")));

ArchCondition<JavaMethod> beTransitivelyCalledByMethodsWithNameStartingWith(String prefix) {
    return new ArchCondition<JavaMethod>("be transitively called by methods with name starting with " + prefix) {
        @Override
        public void check(JavaMethod method, ConditionEvents events) {
            check(method, events, "");
        }

        void check(JavaCodeUnit codeUnit, ConditionEvents events, String suffix) {
            codeUnit.getCallsOfSelf().stream()
                .peek(call -> check(
                    call.getOrigin(), events, ",\n– and " + call.getDescription() + suffix
                ))
                .filter(call -> call.getOrigin().getName().startsWith(prefix))
                .map(call -> SimpleConditionEvent.satisfied(codeUnit, call.getDescription() + suffix))
                .forEach(events::add);
        }
    };
}

For a proper solution, you should track which code units were already visited, similarly as done in JavaClassTransitiveDependencies from PR #401.