Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: Suppression unsupported in Kotlin 2.0+ generated by the Kotlin codegen for some classes #2010

Open
dmoidl opened this issue Sep 17, 2024 · 1 comment
Assignees
Labels
backlog bug Something isn't working codegen

Comments

@dmoidl
Copy link

dmoidl commented Sep 17, 2024

Expected behavior

No compilation issues are produced when compiling classes generated by the Kotlin codegen using Kotlin 2.0+

Actual behavior

This warning:

w: file:///Users/david.moidl/Productboard/pb-universe/board-module/board/build/generated/sources/dgs-codegen/com/productboard/board/graphql/generated/types/User.kt:20:13 This code uses error suppression for 'INAPPLICABLE_JVM_NAME'. While it might compile and work, the compiler behavior is UNSPECIFIED and WON'T BE PRESERVED. Please report your use case to the Kotlin issue tracker instead: https://kotl.in/issue

is issued for some of the classes generated via the DGS's Kotlin codegen.

Normally, I wouldn't worry too much about warnings being issued during compilation of a generated code. However, this warning seems to be intentionally scary as it communicates a possible compilation errors in the future.

Steps to reproduce

Generate any class representing a GQL type that implements a GQL interface via the Kotlin codegen. Any fields of the interface implemented by the class will get annotated with @Suppress("INAPPLICABLE_JVM_NAME"), triggering this error.

An excerpt from our GQL schema:

directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE
directive @external on FIELD_DEFINITION
directive @extends repeatable on OBJECT | INTERFACE

interface Node {
    id: ID!
}

interface Error {
    message: String!
}

type Team implements Node @key(fields: "id") @extends {
    id: ID! @external
}

type LocatedEntityNotFoundError implements Error {
    message: String!
}

And the corresponding generated classes:

Node.kt

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME,
  include = JsonTypeInfo.As.PROPERTY,
  property = "__typename",
)
@JsonSubTypes(value = [
  // removed for brevity
])
public sealed interface Node {
  @Suppress("INAPPLICABLE_JVM_NAME")  // <-- this is the problem
  @get:JvmName("getId")
  public val id: String
}

Team.kt

@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
@JsonDeserialize(builder = Team.Builder::class)
public class Team(
  id: () -> String = idDefault,
) : Node,
    RoadmapGroupingValue {
  private val __id: () -> String = id

  @Suppress("INAPPLICABLE_JVM_NAME")  // <-- this is the problem
  @get:JvmName("getId")
  override val id: String
    get() = __id.invoke()

  public companion object {
    private val idDefault: () -> String = 
        { throw IllegalStateException("Field `id` was not requested") }
  }

  @JsonPOJOBuilder
  @JsonIgnoreProperties("__typename")
  public class Builder {
    private var id: () -> String = idDefault

    @JsonProperty("id")
    public fun withId(id: String): Builder = this.apply {
      this.id = { id }
    }

    public fun build(): Team = Team(
      id = id,
    )
  }
}

Error.kt

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME,
  include = JsonTypeInfo.As.PROPERTY,
  property = "__typename",
)
@JsonSubTypes(value = [
  // removed for brevity
])
public sealed interface Error {
  @Suppress("INAPPLICABLE_JVM_NAME")  // <-- this is the problem
  @get:JvmName("getMessage")
  public val message: String
}

LocatedEntityNotFoundError

@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
@JsonDeserialize(builder = LocatedEntityNotFoundError.Builder::class)
public class LocatedEntityNotFoundError(
  message: () -> String = messageDefault,
) : Error,
    GridRowConnectionError {
  private val __message: () -> String = message

  @Suppress("INAPPLICABLE_JVM_NAME")  // <-- this is the problem
  @get:JvmName("getMessage")
  override val message: String
    get() = __message.invoke()

  public companion object {
    private val messageDefault: () -> String = 
        { throw IllegalStateException("Field `message` was not requested") }
  }

  @JsonPOJOBuilder
  @JsonIgnoreProperties("__typename")
  public class Builder {
    private var message: () -> String = messageDefault

    @JsonProperty("message")
    public fun withMessage(message: String): Builder = this.apply {
      this.message = { message }
    }

    public fun build(): LocatedEntityNotFoundError = LocatedEntityNotFoundError(
      message = message,
    )
  }
}

Notes

Please note that I understand the Kotlin codegen is still marked as experimental. However, with the recent release of Kotlin 2.0, this looks like a possible incompatibility that I believe should be addressed to keep the project up-to-date with the latest language version.

@dmoidl dmoidl added the bug Something isn't working label Sep 17, 2024
@paulbakker paulbakker self-assigned this Nov 14, 2024
@paulbakker
Copy link
Collaborator

@mbossenbroek Could you have a look at this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backlog bug Something isn't working codegen
Projects
None yet
Development

No branches or pull requests

3 participants