Skip to content

Conversation

@drawers
Copy link
Contributor

@drawers drawers commented Nov 6, 2025

What I have done and why

Fix #1984 where TestMethodNameDetector does not scan some tests.

The reason this is happening is because the annotations in the unit tests are of usage type AnnotationUsageType.DEFINTION but the detector does not opt in to scan these.

I have based my solution on IgnoreWithoutReasonDetector which is conceptually similar.

@drawers drawers requested a review from dturner as a code owner November 6, 2025 18:18

// Restrict this detector to `AnnotationUsageType.DEFINITION` following
// similar examples in AOSP like `IgnoreWithoutReasonDetector`.
override fun isApplicableAnnotationUsage(type: AnnotationUsageType): Boolean =
Copy link
Contributor Author

@drawers drawers Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't override this function from the superclass, we get the following implementation which skips AnnotationUsageType.DEFINITION:

  open fun isApplicableAnnotationUsage(type: AnnotationUsageType): Boolean {
    // Some annotation usages are off by default (typically because they were introduced
    // later and might introduce false positives in third party checks; checks should
    // opt into these.
    return when (type) {
      AnnotationUsageType.BINARY,
      AnnotationUsageType.EQUALITY,
      AnnotationUsageType.DEFINITION,
      AnnotationUsageType.IMPLICIT_CONSTRUCTOR,
      AnnotationUsageType.IMPLICIT_CONSTRUCTOR_CALL -> false
      else -> true
    }
  }

Hence the problem where test functions with an annotation that is not AnnotationUsageType.METHOD_RETURN aren't scanned.

Docs for AnnotationUsageType.DEFINITION suggest opting in like this:

override fun isApplicableAnnotationUsage(type: AnnotationUsageType): Boolean {
    return type == AnnotationUsageType.DEFINITION || super.isApplicableAnnotationUsage(type)
}

but if I do that, I get duplicate reports. In other words, the same problem is reported twice. So I have based the solution on this one that restricts annotations to just AnnotationUsageType.DEFINITION

usageInfo: AnnotationUsageInfo,
) {
val method = usageInfo.referenced as? PsiMethod ?: return
val method = annotationInfo.annotation.uastParent as? UMethod ?: return
Copy link
Contributor Author

@drawers drawers Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to change this line because for some annotations usageInfo.referenced will return null.

I based the new interpretation on similar logic in IgnoreWithoutReasonDetector. One doubt would be what happens when there are multiple annotations. If I do context.uastFile.asRecursiveLogString() to look at the UAT nodes, these are still siblings within a single parent where the parent is the UMethod.

UMethod (name = test_foo2)
    UAnnotation (fqName = org.junit.Test)
    UAnnotation (fqName = kotlin.Deprecated)
    UBlockExpression

fun `test foo`() = Unit
@Test
fun test_foo2() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous version of the TestMethodNameDetector would not have reported on this method. In other words, a false negative.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: TestMethodNameDetector does not scan all tests

1 participant