Closed goblinbr closed 7 months ago
I don't think that ArchUnit (currently) recognizes switch
statements, sorry!
By the way: JavaCodeUnit
is the base class of JavaMethod
, JavaConstructor
and JavaStaticInitializer
(see also Domain model), so you could check whether a code unit has switch
statements, but IMO not whether a code unit is a switch
statement.
I will close this issue because I found a way to "solve"
When it's a switch statement java also calls equals method at the same code line, so I just ignore cases where there's also a equals call at the same line. It may ignore some cases like "aaa.hashCode() == bbb.hashCode() && aaa.equals(ccc)" but it's good enough for me.
package com.github.goblinbr.archunitswitchtest;
import com.tngtech.archunit.core.domain.*;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.SimpleConditionEvent;
import org.junit.Test;
import java.util.stream.Stream;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
public class UseHashCodeTest {
@Test
public void checkHashCodeCall() {
JavaClasses classes = new ClassFileImporter().importPackages("com.github.goblinbr.archunitswitchtest");
noClasses()
.should(new ArchCondition<JavaClass>("") {
@Override
public void check(JavaClass javaClass, ConditionEvents events) {
Stream.concat(javaClass.getMethodCallsFromSelf().stream(), javaClass.getMethodReferencesFromSelf().stream())
.filter(jmc -> !jmc.getOrigin().getName().equals("hashCode") &&
jmc.getTarget().getName().equals("hashCode") &&
jmc.getTarget().getParameterTypes().isEmpty() &&
!isSwitchCase(jmc)
)
.forEach(jmc -> events.add(SimpleConditionEvent.satisfied(javaClass, jmc.getDescription())));
}
private boolean isSwitchCase(JavaCodeUnitAccess<? extends AccessTarget.CodeUnitAccessTarget> jmc) {
if (jmc.getTarget().getFullName().equals("java.lang.String.hashCode()")) {
return jmc.getOrigin().getMethodCallsFromSelf().stream()
.anyMatch(e -> e.getLineNumber() == jmc.getLineNumber() &&
e.getTarget().getFullName().equals("java.lang.String.equals(java.lang.Object)"));
}
return false;
}
})
.as("No class should call hashCode()")
.check(classes);
}
}
Sounds like a pragmatic hack workaround! 😅
I want to check if there's any call to hashCode(), but the problem is that JVM calls hashCode() at a switch statement and I want to ignore this case.
Example: