10

I have an annotation that requires defaultValue to be compile-time constant. I take defaultValue from enum below:

enum class RaceType {
    MARATHON,
    SPRINT;

    companion object {
        fun apply(type: RaceType): RaceDto {
            return when (type) {
                MARATHON -> MarathonDto()
                SPRINT -> SprintDto()
            }
        }
    }
}

My dtos are the following:

interface RaceDto {
}

data class MarathonDto: RaceDto

data class SprintDto: RaceDto

when I use annotation @QraphQLArgument(defaultValue = RaceType.SPRINT.name) Kotlin requires RaceType.SPRINT.name to be compile-time constant.

Annotation implementation itself:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface GraphQLArgument {
    String NONE = "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
    String NULL = "\n\t\t\n\t\t\n\ue000\ue001\ue002\ue003\n\t\t\t\t\n";

    String name();

    String description() default "";

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";

    Class<? extends DefaultValueProvider> defaultValueProvider() default JsonDefaultValueProvider.class;
}

I looked through similar questions but don't see a way how it can be resolved. I also found article related to the topic but nothing worked so far.

Side note: I cannot change annotation since it is from the library and I cannot change the library as well.

To summarize, is there a way to make from enum compile-time constant in Kotlin to use in an annotation?

Dmytro Chasovskyi
  • 3,209
  • 4
  • 40
  • 82

1 Answers1

12

is there a way to make from enum compile-time constant in Kotlin to use in an annotation?

No, because formally enums aren't compile-time constants in Java.

However please consider the sealed classes:

sealed class RaceType {
    object MARATHON: RaceType() {
        const val name = "MARATHON" // copy-paste is required here until https://youtrack.jetbrains.com/issue/KT-16304
    }
    object SPRINT: RaceType()

    companion object {
        fun apply(type: RaceType): RaceDto {
            return when (type) { // the check is in compile time, because of sealed class
                MARATHON -> MarathonDto()
                SPRINT -> SprintDto()
            }
        }
    }
}

A little part of copy-paste is still required. Please vote on kotlin compiler bug or follow this thread.

However, as I understand, this doesn't solve your issue with @QraphQLArgument(defaultValue = RaceType.SPRINT.name) unfortunately, because the name of class is not the same with value. In the other words, with sealed classes you need to write code to convert input strings to them.

Manushin Igor
  • 3,398
  • 1
  • 26
  • 40