From 3f3378685e808f6c4c4544ef8950bc84ac2d0627 Mon Sep 17 00:00:00 2001 From: Damian Reeves <957246+DamianReeves@users.noreply.github.com> Date: Tue, 24 Sep 2024 13:18:22 -0500 Subject: [PATCH] Did some basic work on ElmApplication --- .../lang/elm/ElmApplicationDependencies.scala | 24 ++++ .../morphir/lang/elm/ElmDependencyMap.scala | 4 + .../lang/elm/elm.packagemanagement.scala | 1 - .../finos/morphir/lang/elm/elm.types.scala | 1 - .../org/finos/morphir/lang/elm/project.scala | 118 ++++++++++-------- .../morphir/lang/elm/ElmProjectSpec.scala | 11 +- 6 files changed, 96 insertions(+), 63 deletions(-) create mode 100644 morphir/src/org/finos/morphir/lang/elm/ElmApplicationDependencies.scala diff --git a/morphir/src/org/finos/morphir/lang/elm/ElmApplicationDependencies.scala b/morphir/src/org/finos/morphir/lang/elm/ElmApplicationDependencies.scala new file mode 100644 index 000000000..ad7c9c419 --- /dev/null +++ b/morphir/src/org/finos/morphir/lang/elm/ElmApplicationDependencies.scala @@ -0,0 +1,24 @@ +package org.finos.morphir.lang.elm + +import kyo.Result +import org.finos.morphir.api.SemVerString +import metaconfig.* +import metaconfig.generic.* +import metaconfig.sconfig.* +import org.finos.morphir.NonNegativeInt +import org.finos.morphir.config.{ConfigCompanion, MorphirConfig} + +final case class ElmApplicationDependencies( + direct: ElmDependencyMap, + indirect: ElmDependencyMap +) + +object ElmApplicationDependencies: + val empty: ElmApplicationDependencies = ElmApplicationDependencies(ElmDependencyMap.empty, ElmDependencyMap.empty) + val default: ElmApplicationDependencies = ElmApplicationDependencies.empty + + given Surface[ElmApplicationDependencies] = generic.deriveSurface + given confDecoder: ConfDecoder[ElmApplicationDependencies] = + generic.deriveDecoder[ElmApplicationDependencies](ElmApplicationDependencies.default).noTypos + + given confEncoder: ConfEncoder[ElmApplicationDependencies] = generic.deriveEncoder diff --git a/morphir/src/org/finos/morphir/lang/elm/ElmDependencyMap.scala b/morphir/src/org/finos/morphir/lang/elm/ElmDependencyMap.scala index 726995f57..75f0f9075 100644 --- a/morphir/src/org/finos/morphir/lang/elm/ElmDependencyMap.scala +++ b/morphir/src/org/finos/morphir/lang/elm/ElmDependencyMap.scala @@ -22,6 +22,8 @@ import io.bullet.borer.Json type ElmDependencyMap = ElmDependencyMap.Type object ElmDependencyMap extends Subtype[Map[ElmPackageName, ElmPackageVersion]]: + val empty: ElmDependencyMap = unsafeMake(Map.empty) + given confDecoder: ConfDecoder[ElmDependencyMap] = ConfDecoder[Map[String, ElmPackageVersion]] .transformKeys[ElmPackageName](key => ElmPackageName.parseAsConfigured(key)) @@ -33,4 +35,6 @@ object ElmDependencyMap extends Subtype[Map[ElmPackageName, ElmPackageVersion]]: given jsonValueCodec: JsonValueCodec[ElmDependencyMap] = subtypeCodec[Map[ElmPackageName, ElmPackageVersion], ElmDependencyMap] + + def fromMap(map: Map[ElmPackageName, ElmPackageVersion]): ElmDependencyMap = unsafeMake(map) end ElmDependencyMap diff --git a/morphir/src/org/finos/morphir/lang/elm/elm.packagemanagement.scala b/morphir/src/org/finos/morphir/lang/elm/elm.packagemanagement.scala index 19293213e..d0772b917 100644 --- a/morphir/src/org/finos/morphir/lang/elm/elm.packagemanagement.scala +++ b/morphir/src/org/finos/morphir/lang/elm/elm.packagemanagement.scala @@ -1,5 +1,4 @@ package org.finos.morphir.lang.elm final case class ElmConfig( - ) diff --git a/morphir/src/org/finos/morphir/lang/elm/elm.types.scala b/morphir/src/org/finos/morphir/lang/elm/elm.types.scala index 991b4d09f..23e09a6c3 100644 --- a/morphir/src/org/finos/morphir/lang/elm/elm.types.scala +++ b/morphir/src/org/finos/morphir/lang/elm/elm.types.scala @@ -52,4 +52,3 @@ object ElmPackageName extends Subtype[String]: extension (self: ElmPackageName) def value: String = self - diff --git a/morphir/src/org/finos/morphir/lang/elm/project.scala b/morphir/src/org/finos/morphir/lang/elm/project.scala index d5623a40e..6d274f07f 100644 --- a/morphir/src/org/finos/morphir/lang/elm/project.scala +++ b/morphir/src/org/finos/morphir/lang/elm/project.scala @@ -7,28 +7,12 @@ import metaconfig.generic.* import metaconfig.sconfig.* import org.finos.morphir.NonNegativeInt import org.finos.morphir.config.{ConfigCompanion, MorphirConfig} +import io.bullet.borer.Reader.Config +import metaconfig.annotation.* -//TODO: Add Encoders and Decoders for this using scalameta/metaconfig -//: See: https://scalameta.org/metaconfig/docs/reference.html#genericderivedecoder -// -enum ElmProject: +sealed trait ElmProject extends Product with Serializable: self => - case ElmApplication( - override val sourceDirectories: List[String], - elmVersion: SemVerString, - dependencies: ElmApplicationDependencies, - testDependencies: ElmApplicationDependencies - ) - case ElmPackage( - name: ElmPackageName, - summary: Option[String], - version: ElmPackageVersion, - elmVersion: String, - exposedModules: List[ElmModuleName], - dependencies: Map[String, String], - testDependencies: Map[String, String] - ) - + import ElmProject.* def kind: ElmProject.Kind = self match case _: ElmPackage => ElmProject.Kind.Package case _: ElmApplication => ElmProject.Kind.Application @@ -43,43 +27,71 @@ enum ElmProject: end ElmProject -object ElmProject: - enum Kind: - case Package, Application - - private def defaultApp: ElmApplication = ElmApplication( - List.empty, - SemVerString("v0.0.1"), - ElmApplicationDependencies.default, - ElmApplicationDependencies.default - ) +object ElmProject extends ConfigCompanion[ElmProject]: + given confDecoder: ConfDecoder[ElmProject] = new ConfDecoder[ElmProject] { + def read(conf: Conf): Configured[ElmProject] = conf match + case obj @ Conf.Obj(_) => + obj.field("type") match + case Some(Conf.Str("package")) => ElmPackage.confDecoder.read(conf) + case Some(Conf.Str("application")) => ElmApplication.confDecoder.read(conf) + case _ => Configured.error("Expected 'type' field with value 'package' or 'application'") + case _ => Configured.error("Expected an object") + } - private def defaultPackage: ElmPackage = ElmPackage( - ElmPackageName("author/name"), - None, - ElmPackageVersion.default, - "", - List.empty, - Map.empty, - Map.empty - ) + final case class ElmApplication( + @ExtraName("source-directories") override val sourceDirectories: List[String], + @ExtraName("elm-version") elmVersion: SemVerString, + dependencies: ElmApplicationDependencies, + @ExtraName("test-dependencies") testDependencies: ElmApplicationDependencies + ) extends ElmProject -// type ElmApplication = ElmProject.ElmApplication -// object ElmApplication: -// final case class PackageDependency(packageName:ElmPackageName, version:ElmPackageVersion) + object ElmApplication: + private val default: ElmApplication = ElmApplication( + List("src"), + SemVerString("0.0.1"), + ElmApplicationDependencies.default, + ElmApplicationDependencies.default + ) + given Surface[ElmApplication] = generic.deriveSurface + given confDecoder: ConfDecoder[ElmApplication] = + generic.deriveDecoder[ElmApplication](ElmApplication.default) + given confEncoder: ConfEncoder[ElmApplication] = generic.deriveEncoder + end ElmApplication -final case class ElmApplicationDependencies( - direct: Map[String, ElmPackageVersion], - indirect: Map[String, ElmPackageVersion] -) // TODO: change this to ElmPackageName + final case class ElmPackage( + name: ElmPackageName, + summary: Option[String], + version: ElmPackageVersion, + elmVersion: String, + exposedModules: List[ElmModuleName], + dependencies: Map[String, String], + testDependencies: Map[String, String] + ) extends ElmProject -object ElmApplicationDependencies: - val default: ElmApplicationDependencies = ElmApplicationDependencies(Map.empty, Map.empty) + object ElmPackage: + private val default: ElmPackage = ElmPackage( + ElmPackageName("author/name"), + None, + ElmPackageVersion.default, + "", + List.empty, + Map.empty, + Map.empty + ) + given Surface[ElmPackage] = generic.deriveSurface + given confDecoder: ConfDecoder[ElmPackage] = + generic.deriveDecoder[ElmPackage](ElmPackage.default).noTypos + given confEncoder: ConfEncoder[ElmPackage] = generic.deriveEncoder + end ElmPackage - given Surface[ElmApplicationDependencies] = generic.deriveSurface - given confDecoder: ConfDecoder[ElmApplicationDependencies] = - generic.deriveDecoder[ElmApplicationDependencies](ElmApplicationDependencies.default).noTypos + enum Kind: + case Package, Application +end ElmProject - given confEncoder: ConfEncoder[ElmApplicationDependencies] = generic.deriveEncoder type ElmPackage = ElmProject.ElmPackage -object ElmPackage +object ElmPackage: + export ElmProject.ElmPackage.* + +type ElmApplication = ElmProject.ElmApplication +object ElmApplication: + export ElmProject.ElmApplication.* diff --git a/morphir/test/src/org/finos/morphir/lang/elm/ElmProjectSpec.scala b/morphir/test/src/org/finos/morphir/lang/elm/ElmProjectSpec.scala index 8412dbd0a..00afca8ec 100644 --- a/morphir/test/src/org/finos/morphir/lang/elm/ElmProjectSpec.scala +++ b/morphir/test/src/org/finos/morphir/lang/elm/ElmProjectSpec.scala @@ -29,7 +29,8 @@ object ElmProjectSpec extends MorphirSpecDefault { val workspaceFilePath = os.resource / "org" / "finos" / "morphir" / "lang" / "elm" / "application" / "elm.json" val contents: String = os.read(workspaceFilePath) val input: metaconfig.Input = Input.String(contents) - assertTrue(true) + val actual = ElmProject.parseInput(input) + assertTrue(actual.isInstanceOf[kyo.Result.Success[ElmProject]]) } ) @@ -140,11 +141,7 @@ object ElmProjectSpec extends MorphirSpecDefault { test("should be able to parse into json") { val packageVersion = ElmPackageVersion(MajorVersionNumber(5), MinorVersionNumber(0), PatchVersionNumber(2)) val result = confEncoder.write(packageVersion) - assertTrue(result == Conf.Obj( - "major" -> Conf.Num(5), - "minor" -> Conf.Num(0), - "patch" -> Conf.Num(2) - )) + assertTrue(result == Conf.Str("5.0.2")) }, test("does not decode invalid json") { val result = confDecoder.read(Conf.Obj( @@ -158,8 +155,6 @@ object ElmProjectSpec extends MorphirSpecDefault { } private def elmApplicationDependenciesSuite = { - import ElmApplicationDependencies.given - suite("ElmApplicationDependenciesSpec")( // test("should be able to parse Map[ElmPackageName, ElmPackageVersion] into json") { // val direct = Map.apply(