Skip to content

Fix Kotlin @DgsData fetchers never indexed due to PsiAnnotation cast#121

Open
MappuniMaku wants to merge 1 commit into
Netflix:mainfrom
MappuniMaku:fix/kotlin-data-fetcher-indexing
Open

Fix Kotlin @DgsData fetchers never indexed due to PsiAnnotation cast#121
MappuniMaku wants to merge 1 commit into
Netflix:mainfrom
MappuniMaku:fix/kotlin-data-fetcher-indexing

Conversation

@MappuniMaku
Copy link
Copy Markdown

Hey guys. It's now been a while since data fetchers navigation stopped working for my colleagues and me, so I decided to try to find and fix the issue using AI. I'm not specializing in Java/Kotlin development.

I tested it for the following IDEA versions:

  • 2024.3.1 by running ./gradlew runIde
  • 2025.3.4 by upgrading versions in gradle.properties, upgrading org.jetbrains.kotlin.jvm to 2.3.20 and running ./gradlew runIde
  • 2026.1 by upgrading versions in gradle.properties, upgrading org.jetbrains.kotlin.jvm to 2.3.20 and running ./gradlew runIde
  • 2026.1 in my locally installed IDEA by building the plugin and installing it from the result .zip file

Below is the AI summary of the bug that I asked it to write:

Issue

Gutter icons in Kotlin DGS projects appear as gray / unresolved ("no fetcher found"
variant). Clicking them does nothing — navigation to the GraphQL schema field is
completely broken. Java DGS projects are unaffected throughout.

Related issues: #83, #88, #102.


Root cause

In DgsDataProcessor.kt, the processDataFetcher method had:

val annotationPsi = uAnnotation.sourcePsi as? PsiAnnotation
if (annotationPsi != null) {
    createDataFetchersForAnnotation(uMethod, methodPsi, annotationPsi, ...)
}

PsiAnnotation is a Java PSI interface. Java source annotations implement it
directly. Kotlin source annotations use KtAnnotationEntry, which does not
implement PsiAnnotation. The cast therefore always returned null for Kotlin,
createDataFetchersForAnnotation was never called, and no Kotlin data fetcher
was ever added to the component index.

The bug was introduced in commit 2a4abb6 ("Properly handle implicit DgsData.List
linkage", 2025-12-18), which refactored processDataFetcher to separate the
@DgsData.List container case but accidentally added the cast to the else branch.
The original Kotlin compatibility commit from 2021 had used uAnnotation.sourcePsi
directly without casting.

It went undetected because all existing test data files are Java; the Kotlin code
path was never exercised by tests.


Fix

DgsDataProcessor.kt — in the else branch, replace the as? PsiAnnotation
cast with uAnnotation.sourcePsi ?: return and pass the UAnnotation directly to
createDataFetchersForAnnotation. The method signature changes from
annotation: PsiAnnotation to uAnnotation: UAnnotation + annotationSourcePsi: PsiElement,
so annotation attributes are read via UAST (works for both languages) while the
source PSI element is stored as-is for navigation.

In the @DgsData.List branch, each extracted child PsiAnnotation is now converted
to UAnnotation via toUElement() before being passed to the same method, keeping
a single code path for the indexing logic.

DgsDataFetcher.kt — add UAnnotation overloads for getParentType and
getFieldFromAnnotation as the primary implementations; make the existing
PsiAnnotation overloads delegate through them. This also removes an unsafe bare
as UAnnotation cast that was already present in the original code.


Tests

No test changes. The existing DgsDataMultipleAnnotationsTest covers both the
implicit @Repeatable and explicit @DgsData.List cases with Java test data and
was already asserting correct fetcher counts, parentType/field values, schema
linkage, shared method references, and distinct annotation PSI elements per entry.
All tests pass.


Verified working

Manually tested via ./gradlew runIde on:

IDE version Build
IntelliJ IDEA 2025.3.4 IU-253.32098.37
IntelliJ IDEA 2026.1 IU-261.22158.277

Gutter icons appear next to @DgsQuery / @DgsMutation / @DgsData methods in
Kotlin DGS projects and navigate correctly to the GraphQL schema field.

For Kotlin annotations, sourcePsi is KtAnnotationEntry, not PsiAnnotation.
The cast in processDataFetcher always returned null, so the component index
was empty for every Kotlin data fetcher. Add UAnnotation overloads to
DgsDataFetcher and thread UAnnotation through createDataFetchersForAnnotation
so annotation metadata is read via UAST, which works for both languages.
@lthoulon-locala
Copy link
Copy Markdown

lthoulon-locala commented May 12, 2026

Confirming this affects our Kotlin DGS project. Gutter icons have been grayed out for a couple of months. That's consistent with the December 2025 regression you identified. Navigation from schema to data fetchers is completely non-functional. Looking forward to this being merged.

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.

2 participants