Skip to content

Read @UseCase through UAST so Kotlin tests are supported - #1

Open
atrifyllis wants to merge 1 commit into
AI-Unified-Process:mainfrom
atrifyllis:feat/uast-support
Open

atrifyllis wants to merge 1 commit into
AI-Unified-Process:mainfrom
atrifyllis:feat/uast-support

Conversation

@atrifyllis

Copy link
Copy Markdown

In a project whose tests are written in Kotlin, none of the code-side features fire: no gutter icon on @UseCase, no "ID has no matching spec" inspection, and no Find Usages in either direction. The Markdown side and the diagram tool window work, so the plugin looks half-installed rather than broken, which is what sent me reading the source.

The cause is that all four code-side extensions speak Java PSI — PsiAnnotation, PsiLiteralExpression, AbstractBaseJavaLocalInspectionTool — and plugin.xml registers the line marker and the inspection for language="JAVA".

What this changes

The four extensions now read annotations through UAST, the platform's language-neutral view of JVM annotations, and the two registrations move from language="JAVA" to language="UAST". One code path then serves Java, Kotlin and anything else with a UAST implementation.

  • UseCaseToSpecLineMarkerProvider, UseCaseIdInspection, UseCaseDeclarationProvider, UseCaseUsageSearcher — UAnnotation in place of PsiAnnotation, values read via evaluate() and anchored on sourcePsi.
  • UseCaseIndex gains the shared helpers (isUseCaseAnnotation, attributeString, attributeStrings, arrayElements) and keeps its Java-array handling; the array unwrapper covers Java's {...} and Kotlin's [...].
  • No new runtime dependency. UAST is platform, and the meta-language matches whatever languages the IDE has. The Kotlin plugin is added to build.gradle.kts only so the tests have a Kotlin language to parse and runIde a sandbox to try it in.
  • UseCaseIndex's lookups needed no change: PsiShortNamesCache and AnnotatedElementsSearch already see Kotlin light classes. A consequence worth documenting — and now in the README — is that the UseCase annotation type itself may be declared in Kotlin.

The usage searcher additionally maps each found method back to source through UAST. The Java-shaped search returns a light method for a Kotlin test, whose text ranges point at synthesized code rather than at anything the author wrote.

Two details worth a reviewer's eye

Kotlin nests the annotation name deeper than Java. From the name token, Java reaches its annotation in two hops; Kotlin takes five, through a type reference and a constructor callee. My first attempt capped the walk at four and silently produced no marker at all — the tests caught it, reading the code did not.

A Kotlin string value can look exactly like the annotation's name. The contents of "UseCase" are a leaf whose text is UseCase, indistinguishable from the name token, so a naive port marks @UseCase(scenario = "UseCase") twice. The guard is that the token's parent must be a reference; testKotlinStringValueMatchingTheAnnotationNameIsNotMarked pins it.

Tests

./gradlew build is green on IntelliJ IDEA 2026.1 — 51 tests, no compiler warnings. Four are new, mirroring the existing Java cases: the Kotlin gutter icon, the string-leaf trap above, the inspection in both directions, and UseCaseIndex.findTestMethods resolving a Kotlin @UseCase (which also pins that light-method attribute reading works in K2 mode).

The two Kotlin inspection tests assert on highlight descriptions rather than through checkHighlighting: the light test project has no JDK, so Kotlin cannot resolve java.lang.String in the Java-declared annotation and reports a type mismatch on every argument — noise unrelated to the inspection.

Left to you

The version stays at 0.8.1 and I added no changeNotes entry, since releases are yours to cut.

🤖 Generated with Claude Code

The four code-side extensions read annotations through the Java PSI model, so a
@usecase on a Kotlin test method is invisible to all of them: no gutter icon, no
inspection, no Find Usages, and no spec-to-test navigation landing in real source.

Switch them to UAST, the platform's language-neutral view of JVM annotations, and
register the line marker and the inspection for the UAST meta-language instead of
JAVA. One code path now serves Java, Kotlin and any other language with a UAST
implementation, with no new runtime dependency: the Kotlin plugin is added to the
build only so the tests have a Kotlin language to parse.

The annotation type itself may now be declared in Kotlin as well - it is still
looked up by short name through PsiShortNamesCache, which sees light classes.
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.

1 participant