diff --git a/java-checks-test-sources/default/src/main/java/checks/VirtualThreadUnsupportedMethodsSample.java b/java-checks-test-sources/default/src/main/java/checks/VirtualThreadUnsupportedMethodsSample.java index df0b51db10c..02692c5df10 100644 --- a/java-checks-test-sources/default/src/main/java/checks/VirtualThreadUnsupportedMethodsSample.java +++ b/java-checks-test-sources/default/src/main/java/checks/VirtualThreadUnsupportedMethodsSample.java @@ -93,4 +93,21 @@ void falseNegatives(Thread virtualAtRuntime){ outerVirtualThread.setDaemon(true); // False negative } + class IdentifierTreeImplTest { + + SampleThread thread = new SampleThread(); + + public void test() { + thread.start(); + } + + private class SampleThread extends Thread { + @Override + public void run() { + setDaemon(true); // generates => mit.methodSelect() instanceof IdentifierTreeImpl + } + } + + } + } diff --git a/java-checks/src/main/java/org/sonar/java/checks/VirtualThreadUnsupportedMethodsCheck.java b/java-checks/src/main/java/org/sonar/java/checks/VirtualThreadUnsupportedMethodsCheck.java index abcb9a06fd8..4357d7e2220 100644 --- a/java-checks/src/main/java/org/sonar/java/checks/VirtualThreadUnsupportedMethodsCheck.java +++ b/java-checks/src/main/java/org/sonar/java/checks/VirtualThreadUnsupportedMethodsCheck.java @@ -21,6 +21,8 @@ import java.util.List; import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.check.Rule; import org.sonar.java.checks.methods.AbstractMethodDetection; import org.sonar.java.model.ExpressionUtils; @@ -37,6 +39,8 @@ @Rule(key = "S6901") public class VirtualThreadUnsupportedMethodsCheck extends AbstractMethodDetection implements JavaVersionAwareVisitor { + private static final Logger LOG = LoggerFactory.getLogger(VirtualThreadUnsupportedMethodsCheck.class); + private static final String ISSUE_MESSAGE = "Method '%s' is not supported on virtual threads."; private static final String SECONDARY_LOCATION_ISSUE_MESSAGE = "Virtual thread initialized here."; @@ -69,15 +73,22 @@ protected MethodMatchers getMethodInvocationMatchers() { @Override protected void onMethodInvocationFound(MethodInvocationTree mit) { - var memberSelect = (MemberSelectExpressionTree) mit.methodSelect(); - var expression = memberSelect.expression(); - var virtualThreadExpression = getVirtualThreadInitializer(expression); - if (virtualThreadExpression.isPresent()) { - reportIssue( - memberSelect.identifier(), - String.format(ISSUE_MESSAGE, memberSelect.identifier().name()), - List.of(new JavaFileScannerContext.Location(SECONDARY_LOCATION_ISSUE_MESSAGE, ExpressionUtils.methodName(virtualThreadExpression.get()))), - null); + // instance can be IdentifierTreeImpl, for example, so guard against class cast exception + if (mit.methodSelect() instanceof MemberSelectExpressionTree memberSelect) { + var expression = memberSelect.expression(); + var virtualThreadExpression = getVirtualThreadInitializer(expression); + if (virtualThreadExpression.isPresent()) { + reportIssue( + memberSelect.identifier(), + String.format(ISSUE_MESSAGE, memberSelect.identifier().name()), + List.of(new JavaFileScannerContext.Location(SECONDARY_LOCATION_ISSUE_MESSAGE, + ExpressionUtils.methodName(virtualThreadExpression.get()))), + null); + } + } else { + LOG.trace("VirtualThreadUnsupportedMethodsCheck.onMethodInvocationFound(): " + + "mit.methodSelect() returns unsupported class instance: {}", + mit.methodSelect().getClass()); } }