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

scalapb.compiler.SealedOneofsGenerator.scala Maven / Gradle / Ivy

The newest version!
package scalapb.compiler

import scalapb.compiler.FunctionalPrinter.PrinterEndo
import com.google.protobuf.Descriptors._

sealed trait SealedOneofStyle

object SealedOneofStyle {
  case object Default extends SealedOneofStyle

  case object Optional extends SealedOneofStyle
}

class SealedOneofsGenerator(message: Descriptor, implicits: DescriptorImplicits) {
  import implicits._

  def generateSealedOneofTrait: PrinterEndo = { fp =>
    if (!message.isSealedOneofType) fp
    else {
      val baseType        = message.scalaType.fullName
      val sealedOneofType = message.sealedOneofScalaType
      val sealedOneofName = message.sealedOneofTraitScalaType.nameSymbol
      val typeMapper      = s"_root_.scalapb.TypeMapper[${baseType}, ${sealedOneofType}]"
      val oneof           = message.getRealOneofs.get(0)
      val typeMapperName  = message.sealedOneofTypeMapper.name

      if (message.sealedOneofStyle != SealedOneofStyle.Optional) {
        val sealedOneofNonEmptyName = message.sealedOneofNonEmptyScalaType.nameSymbol
        val sealedOneofNonEmptyType = message.sealedOneofNonEmptyScalaType.fullName
        val bases =
          if (message.sealedOneofBaseClasses.nonEmpty)
            s"extends ${message.sealedOneofBaseClasses.mkString(" with ")} "
          else ""

        fp.add(
            s"sealed trait $sealedOneofName $bases{"
          )
          .addIndented(
            s"type MessageType = $baseType",
            s"final def isEmpty = this.isInstanceOf[${sealedOneofType}.Empty.type]",
            s"final def isDefined = !isEmpty",
            s"final def asMessage: $baseType = ${message.sealedOneofTypeMapper.fullName}.toBase(this)",
            s"final def asNonEmpty: Option[$sealedOneofNonEmptyType] = if (isEmpty) None else Some(this.asInstanceOf[$sealedOneofNonEmptyType])"
          )
          .add("}")
          .add("")
          .add(s"object $sealedOneofName {")
          .indented(
            _.add(s"case object Empty extends $sealedOneofType", "")
              .add(s"sealed trait $sealedOneofNonEmptyName extends $sealedOneofType")
              .add(
                s"def defaultInstance: ${sealedOneofType} = Empty",
                "",
                s"implicit val $typeMapperName: $typeMapper = new $typeMapper {"
              )
              .indented(
                _.add(
                  s"override def toCustom(__base: $baseType): $sealedOneofType = __base.${oneof.scalaName.nameSymbol} match {"
                ).indented(
                    _.print(oneof.fields) {
                      case (fp, field) =>
                        fp.add(s"case __v: ${field.oneOfTypeName.fullName} => __v.value")
                    }.add(s"case ${oneof.empty.fullName} => Empty")
                  )
                  .add("}")
                  .add(
                    s"override def toBase(__custom: $sealedOneofType): $baseType = $baseType(__custom match {"
                  )
                  .indented(
                    _.print(oneof.fields) {
                      case (fp, field) =>
                        fp.add(
                          s"case __v: ${field.scalaTypeName} => ${field.oneOfTypeName.fullName}(__v)"
                        )
                    }.add(s"case Empty => ${oneof.empty.fullName}")
                  )
                  .add("})")
              )
              .add("}")
          )
          .add("}")
      } else {
        val bases =
          if (message.sealedOneofBaseClasses.nonEmpty)
            s"extends ${message.sealedOneofBaseClasses.mkString(" with ")} "
          else ""
        fp.add(
            s"sealed trait $sealedOneofName $bases{"
          )
          .addIndented(
            s"type MessageType = $baseType",
            s"final def asMessage: $baseType = ${message.sealedOneofTypeMapper.fullName}.toBase(Some(this))"
          )
          .add("}")
          .add("")
          .add(s"object $sealedOneofName {")
          .indented(
            _.add(
              s"implicit val $typeMapperName: $typeMapper = new $typeMapper {"
            ).indented(
                _.add(
                  s"override def toCustom(__base: $baseType): $sealedOneofType = __base.${oneof.scalaName.nameSymbol} match {"
                ).indented(
                    _.print(oneof.fields) {
                      case (fp, field) =>
                        fp.add(s"case __v: ${field.oneOfTypeName.fullName} => Some(__v.value)")
                    }.add(s"case ${oneof.empty.fullName} => None")
                  )
                  .add("}")
                  .add(
                    s"override def toBase(__custom: $sealedOneofType): $baseType = $baseType(__custom match {"
                  )
                  .indented(
                    _.print(oneof.fields) {
                      case (fp, field) =>
                        fp.add(
                          s"case Some(__v: ${field.scalaTypeName}) => ${field.oneOfTypeName.fullName}(__v)"
                        )
                    }.add(s"case None => ${oneof.empty.fullName}")
                  )
                  .add("})")
              )
              .add("}")
          )
          .add("}")
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy