All Downloads are FREE. Search and download functionalities are using the official Maven repository.

arrow.optics.DslSnippetGenerator.kt Maven / Gradle / Ivy

There is a newer version: 1.6.3-alpha.2
Show newest version
package arrow.optics

import arrow.common.utils.simpleName

fun generateLensDsl(ele: AnnotatedElement, optic: DataClassDsl) = Snippet(
  `package` = ele.packageName,
  name = ele.classData.simpleName,
  content = processLensSyntax(ele, optic.foci)
)

fun generateOptionalDsl(ele: AnnotatedElement, optic: DataClassDsl) = Snippet(
  `package` = ele.packageName,
  name = ele.classData.simpleName,
  content = processOptionalSyntax(ele, optic)
)

fun generatePrismDsl(ele: AnnotatedElement, isoOptic: SealedClassDsl) = Snippet(
  `package` = ele.packageName,
  name = ele.classData.simpleName,
  content = processPrismSyntax(ele, isoOptic)
)

private fun processLensSyntax(ele: AnnotatedElement, foci: List): String = foci.joinToString(separator = "\n") { focus ->
  """
  |inline val  $Iso.${focus.lensParamName()}: $Lens inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()}
  |inline val  $Lens.${focus.lensParamName()}: $Lens inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()}
  |inline val  $Optional.${focus.lensParamName()}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()}
  |inline val  $Prism.${focus.lensParamName()}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()}
  |inline val  $Getter.${focus.lensParamName()}: $Getter inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()}
  |inline val  $Setter.${focus.lensParamName()}: $Setter inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()}
  |inline val  $Traversal.${focus.lensParamName()}: $Traversal inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()}
  |inline val  $Fold.${focus.lensParamName()}: $Fold inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()}
  |""".trimMargin()
}

private fun processOptionalSyntax(ele: AnnotatedElement, optic: DataClassDsl) = optic.foci.filterNot { it is NonNullFocus }.joinToString(separator = "\n") { focus ->
  val targetClassName = when (focus) {
    is NullableFocus -> focus.nonNullClassName
    is OptionFocus -> focus.nestedClassName
    is NonNullFocus -> ""
  }

  """
  |inline val  $Iso.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Lens.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Optional.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Prism.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Setter.${focus.paramName}: $Setter inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Traversal.${focus.paramName}: $Traversal inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Fold.${focus.paramName}: $Fold inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |""".trimMargin()
}

private fun processPrismSyntax(ele: AnnotatedElement, dsl: SealedClassDsl): String = dsl.foci.joinToString(separator = "\n\n") { focus ->
  """
  |inline val  $Iso.${focus.paramName}: $Prism inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Lens.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Optional.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Prism.${focus.paramName}: $Prism inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Setter.${focus.paramName}: $Setter inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Traversal.${focus.paramName}: $Traversal inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |inline val  $Fold.${focus.paramName}: $Fold inline get() = this + ${ele.sourceClassName}.${focus.paramName}
  |""".trimMargin()
}