Skip to content

Commit

Permalink
fix: allow multiple params & specify which by name
Browse files Browse the repository at this point in the history
- Default to first param but allow additional ones
- Allow specifying which param by name

Fixes #1
  • Loading branch information
rushiiMachine committed Nov 8, 2023
1 parent fa742c9 commit be356d7
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,42 @@ class FromValueVisitor(
) : KSVisitorVoid() {
override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
if (classDeclaration.classKind != ClassKind.ENUM_CLASS) {
logger.error("Cannot run FromValue on a non enum class!", classDeclaration)
logger.error("Cannot apply FromValue onto a non enum class!", classDeclaration)
return
}

val param = classDeclaration.primaryConstructor?.parameters?.singleOrNull() ?: run {
logger.error("Must have exactly one constructor parameter in order to run FromValue!", classDeclaration)
return
val annotation = classDeclaration.annotations
.find { it.shortName.asString() == "FromValue" } // I can't find a way to use qualified name, hopefully nobody else uses @FromValue
?: throw IllegalStateException("annotation missing; lib broken")

val targetFieldName = annotation.arguments
.find { it.name?.getShortName() == "field" }
?.value.let { it as String? }
?: throw IllegalStateException("annotation missing field; lib broken")

// If it is the default, use first param
val targetParam = if (targetFieldName == "") {
val param = classDeclaration.primaryConstructor
?.parameters?.getOrNull(0)

if (param == null) {
logger.error("Must have exactly one constructor parameter in order to run FromValue!", classDeclaration)
return
}

param
} else {
// Check target param exists
val param = classDeclaration.primaryConstructor
?.parameters
?.find { it.name?.getShortName() == targetFieldName }

if (param == null) {
logger.error("FromValue: target field does not exist in enum", classDeclaration)
return
}

param
}

val enumFields = classDeclaration.declarations
Expand Down Expand Up @@ -56,7 +85,7 @@ class FromValueVisitor(
makeFromValueFunction(
companion = companion,
parentClass = classDeclaration,
param = param,
param = targetParam,
fields = enumFields,
)
)
Expand Down Expand Up @@ -86,7 +115,7 @@ class FromValueVisitor(
val fieldClassName = field.toClassName()

addStatement(
"%T.`%L` -> %T",
"%T.%N -> %T",
fieldClassName,
param.name!!.asString(),
fieldClassName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.github.materiiapps.enumutil

/**
* Generate `fromValue(...)` extension methods for the target class.
* This matches the first enum parameter and returns the matched enum value.
* @param field Match a specific field by name instead of defaulting to the first one.
*/
@Target(AnnotationTarget.CLASS)
public annotation class FromValue
public annotation class FromValue(val field: String = "")
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package com.github.materiiapps.enumutil.ksp.example

import com.github.materiiapps.enumutil.FromValue

@FromValue
enum class OpCodes(val code: Int) {
READY(1),
DELETE(2),
CREATE(3),
DISCONNECT(4);
@FromValue("code")
enum class OpCodes(val code: Int, val display: String) {
READY(1, "Ready"),
DELETE(2, "Delete"),
CREATE(3, "Create"),
DISCONNECT(4, "Disconnect");

companion object Serializer {
// blah blah blah
Expand Down

0 comments on commit be356d7

Please sign in to comment.