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

izumi.idealingua.compiler.ManifestReader.scala Maven / Gradle / Ivy

The newest version!
package izumi.idealingua.compiler

import io.circe.parser.parse
import io.circe.syntax.*
import io.circe.{Decoder, Encoder, Json}
import izumi.fundamentals.platform.files.IzFiles
import izumi.idealingua.compiler.Codecs.*
import izumi.idealingua.model.publishing.BuildManifest
import izumi.idealingua.model.publishing.manifests.*
import izumi.idealingua.translator.IDLLanguage

import java.io.File
import scala.util.{Failure, Success, Try}

class ManifestWriter() {
  def write(mf: BuildManifest): String = {
    ((mf: @unchecked) match {
      case m: ScalaBuildManifest =>
        m.asJson
      case m: TypeScriptBuildManifest =>
        m.asJson
      case m: GoLangBuildManifest =>
        m.asJson
      case m: CSharpBuildManifest =>
        m.asJson
    }).toString()
  }
}

class ManifestReader(conf: IDLCArgs, log: CompilerLog, shutdown: Shutdown, patch: Json, lang: IDLLanguage, file: Option[File]) {
  def read(): BuildManifest = {
    lang match {
      case IDLLanguage.Scala =>
        readManifest(ScalaBuildManifest.example)
      case IDLLanguage.Typescript =>
        readManifest(TypeScriptBuildManifest.example)
      case IDLLanguage.Go =>
        readManifest(GoLangBuildManifest.example)
      case IDLLanguage.CSharp =>
        readManifest(CSharpBuildManifest.example)
      case IDLLanguage.Protobuf =>
        readManifest(ProtobufBuildManifest.example)
    }
  }

  private def readManifest[T <: BuildManifest: Decoder: Encoder](default: T): T = {
    val defaultJson   = default.asJson.deepMerge(patch)
    val defaultMfFile = conf.root.resolve(s"manifests/${lang.toString.toLowerCase}.json").toFile

    val mf = file match {
      case Some(path) if path.toString == "@" =>
        RawMf.Default(defaultJson, defaultMfFile, suppressed = true)

      case Some(path) if path.toString == "+" =>
        readMfFromFile(defaultMfFile)

      case Some(path) =>
        readMfFromFile(path)

      case None if defaultMfFile.exists() =>
        log.log(s"Will use default manifest ${defaultMfFile.toPath} for $lang")
        readMfFromFile(defaultMfFile)

      case None =>
        RawMf.Default(defaultJson, defaultMfFile, suppressed = false)
    }

    val rawMf = mf match {
      case RawMf.Loaded(json) =>
        json

      case RawMf.Default(json, d, suppressed) =>
        if (!suppressed) {
          log.log(
            s"No manifest defined for $lang and default manifest file `${d.toPath}` is missing, using default (you may suppress this message by using `-m @` switch):"
          )
          log.log(json.toString())
          log.log("")
        }
        json

      case RawMf.FailedToLoad(e, path) =>
        log.log(s"Failed to parse manifest for $lang from $path, check if it corresponds to the following example:")
        log.log(defaultJson.toString())
        log.log("")
        shutdown.shutdown(s"Failed to parse $lang manifest from $path: ${e.toString}")

      case RawMf.Failed(e, path) =>
        log.log(s"Failed to load manifest for $lang from $path, you may use the following example to create it:")
        log.log(defaultJson.toString())
        log.log("")
        shutdown.shutdown(s"Failed to load $lang manifest from $path: ${e.toString}")
    }

    rawMf.deepMerge(patch).as[T] match {
      case Left(value) =>
        shutdown.shutdown(s"Have $lang manifest but it failed to parse: ${value.toString}")

      case Right(value) =>
        value
    }
  }

  private def readMfFromFile(path: File): RawMf = {
    Try(parse(IzFiles.readString(path))) match {
      case Success(Right(r)) =>
        RawMf.Loaded(r)
      case Success(Left(l)) =>
        RawMf.FailedToLoad(l, path)
      case Failure(f) =>
        RawMf.Failed(f, path)
    }
  }
}

sealed trait RawMf

object RawMf {

  final case class Loaded(json: Json) extends RawMf

  final case class Default(json: Json, defaultFile: File, suppressed: Boolean) extends RawMf

  final case class FailedToLoad(e: Throwable, path: File) extends RawMf

  final case class Failed(e: Throwable, path: File) extends RawMf

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy