From 648db651870c5ba5f92a55a839cc859ea2bee78f Mon Sep 17 00:00:00 2001 From: Michelle Date: Mon, 14 Mar 2022 14:38:29 -0400 Subject: [PATCH] Adding rest of ModuleModule and test (#62) * adding rest of ModuleModule --- .../scala/zio/morphir/ir/ModuleModule.scala | 33 +++++- .../scala/zio/morphir/ir/TypeModule.scala | 8 ++ .../zio/morphir/ir/ModuleModuleSpec.scala | 112 ++++++++++++++++++ 3 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 morphir-ir/shared/src/test/scala/zio/morphir/ir/ModuleModuleSpec.scala diff --git a/morphir-ir/shared/src/main/scala/zio/morphir/ir/ModuleModule.scala b/morphir-ir/shared/src/main/scala/zio/morphir/ir/ModuleModule.scala index dff5bfe4..fe448536 100644 --- a/morphir-ir/shared/src/main/scala/zio/morphir/ir/ModuleModule.scala +++ b/morphir-ir/shared/src/main/scala/zio/morphir/ir/ModuleModule.scala @@ -1,5 +1,7 @@ package zio.morphir.ir + import zio.Chunk +import zio.morphir.ir.TypeModule.Definition.{CustomType, TypeAlias} object ModuleModule { @@ -37,10 +39,33 @@ object ModuleModule { def mapAttributes: Definition[Annotations] = ??? - def collectTypeReferences: Set[FQName] = ??? - def collectValueReferences: Set[FQName] = ??? - def collectReferences: Set[FQName] = ??? - def dependsOnModules: Set[QualifiedModuleName] = ??? + def collectTypeReferences: Set[FQName] = self.types.flatMap { + case (_, AccessControlled.WithPrivateAccess(definition)) => + definition.value match { + case TypeAlias(_, typeExp) => typeExp.collectReferences + case CustomType(_, ctors) => ctors.withPrivateAccess.collectReferences + } + case (_, AccessControlled.WithPublicAccess(definition)) => + definition.value match { + case TypeAlias(_, typeExp) => typeExp.collectReferences + case CustomType(_, ctors) => ctors.withPrivateAccess.collectReferences + } + case _ => Nil + + }.toSet + + def collectValueReferences: Set[FQName] = self.values.flatMap { + case (_, AccessControlled.WithPrivateAccess(definition)) => + definition.body.collectReferences + case (_, AccessControlled.WithPublicAccess(definition)) => + definition.body.collectReferences + case _ => Nil + }.toSet + + def collectReferences: Set[FQName] = collectTypeReferences ++ collectValueReferences + def dependsOnModules: Set[QualifiedModuleName] = self.collectReferences.map { case FQName(pp, mp, _) => + QualifiedModuleName(pp.toPath, mp.toPath) + } } object Definition { diff --git a/morphir-ir/shared/src/main/scala/zio/morphir/ir/TypeModule.scala b/morphir-ir/shared/src/main/scala/zio/morphir/ir/TypeModule.scala index 625bb6e7..d7bee725 100644 --- a/morphir-ir/shared/src/main/scala/zio/morphir/ir/TypeModule.scala +++ b/morphir-ir/shared/src/main/scala/zio/morphir/ir/TypeModule.scala @@ -19,6 +19,14 @@ object TypeModule extends TypeModuleSyntax { def toUnannotated: Constructors[Any] = Constructors(items.map { case (ctor, args) => (ctor, args.map { case (paramName, paramType) => (paramName, paramType.toUnannotated) }) }) + + def collectReferences: Set[FQName] = { + items.values.flatMap { + case Chunk((_, tpe)) => + tpe.collectReferences + case _ => Nil + }.toSet + } } sealed trait Definition[+Annotations] { self => diff --git a/morphir-ir/shared/src/test/scala/zio/morphir/ir/ModuleModuleSpec.scala b/morphir-ir/shared/src/test/scala/zio/morphir/ir/ModuleModuleSpec.scala new file mode 100644 index 00000000..f3363203 --- /dev/null +++ b/morphir-ir/shared/src/test/scala/zio/morphir/ir/ModuleModuleSpec.scala @@ -0,0 +1,112 @@ +package zio.morphir.ir + +import zio.morphir.ir.ModuleModule.{Definition, Specification} +import zio.{Chunk, ZEnvironment} +import zio.morphir.ir.TypeModule.Definition.{CustomType, TypeAlias} +import zio.morphir.ir.TypeModule.Specification.OpaqueTypeSpecification +import zio.morphir.ir.TypeModule.Constructors +import zio.morphir.syntax.AllSyntax +import zio.morphir.testing.MorphirBaseSpec +import zio.test.* + +object ModuleModuleSpec extends MorphirBaseSpec with AllSyntax { + val items = Map { + Name("type") -> Chunk((Name("var"), defineVariable("var1"))) + Name("rainbow") -> Chunk((Name("red"), defineVariable("red"))) + } + + val typeAlias = Documented( + "doc", + TypeAlias(Chunk(Name.fromString("hello")), defineVariable("type1")) + ) + + val customType = Documented( + "doc", + CustomType(Chunk(Name.fromString("world")), AccessControlled.publicAccess(Constructors(items))) + ) + + val definitionTypes = Map { + Name("hello") -> AccessControlled.publicAccess(typeAlias) + Name("world") -> AccessControlled.publicAccess(customType) + } + + val definitionValues = Map { + Name("val") -> AccessControlled.publicAccess( + ValueModule.Definition.fromLiteral(string("string")) + ) + } + + val moduleDef = Definition(definitionTypes, definitionValues) + + val specTypes = Map { + Name("hello") -> Documented( + "doc", + OpaqueTypeSpecification(Chunk(Name("name1")), ZEnvironment.empty) + ) + Name("world") -> Documented( + "doc", + OpaqueTypeSpecification(Chunk(Name("name2")), ZEnvironment.empty) + ) + } + + val specValues = Map { + Name("spec1") -> ValueModule.Specification( + Chunk( + (Name("type1"), defineVariable("Float")), + (Name("type2"), defineVariable("Decimal")) + ), + defineVariable("WholeNumbers") + ) + } + + val moduleSpec = Specification(specTypes, specValues) + + def spec = suite("Type")( + suite("Module Definition")( + test("Can be turned to Specification") { +// val expected = Specification(types = Map{ +// Name("hello") -> typeAlias.map(_.toSpecification) +// Name("world") -> customType.map(_.toSpecification) +// }, +// Map{ +// Name("val") -> ValueModule.Definition.fromLiteral(string("string")).toSpecification +// } +// ) +// assertTrue(moduleDef.toSpecification == expected) + // todo add when TypeModule toSpec is added + assertTrue(1 == 1) + }, + test("Can look up values") { + val result = moduleDef.lookupValue(Name("val")) + assertTrue(result.isDefined && result.get == ValueModule.Definition.fromLiteral(string("string"))) + }, + test("Can be erased") { + assertTrue(moduleDef.eraseAttributes == Definition.empty) + }, + test("Can collect all references") { + assertTrue( + moduleDef.collectTypeReferences.size == 0 && + moduleDef.collectValueReferences.size == 0 && + moduleDef.collectValueReferences.size == 0 + ) + } + ), + suite("Module Specification")( + test("Can look up values") { + val result = moduleSpec.lookupValue(Name("spec1")) + assertTrue( + result.isDefined && result.get.inputs.size == 2 && result.get.output == defineVariable("WholeNumbers") + ) + }, + test("Can look up types") { + val result = moduleSpec.lookupType(Name("world")) + assertTrue( + result.isDefined && !moduleSpec.lookupType(Name("notHere")).isDefined + ) + }, + test("Can be erased") { + assertTrue(moduleSpec.eraseAttributes == Specification.empty) + } + ) + ) +}