diff --git a/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/ErrorMessage.scala b/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/ErrorMessage.scala index deecc26e..438a202b 100644 --- a/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/ErrorMessage.scala +++ b/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/ErrorMessage.scala @@ -18,7 +18,7 @@ object ErrorMessage { } final case class NoChildFound(childName: String, destTpe: Type[?]) extends ErrorMessage { - def render(using Quotes): String = s"No child named '$childName found in ${destTpe.repr.show}" + def render(using Quotes): String = s"No child named '$childName' found in ${destTpe.repr.show}" def span = None val target = Target.Source } diff --git a/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/Path.scala b/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/Path.scala index 3afeb9d2..33c5d27f 100644 --- a/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/Path.scala +++ b/ducktapeNext/src/main/scala/io/github/arainko/ducktape/internal/Path.scala @@ -46,15 +46,14 @@ final case class Path(root: Type[?], segments: Vector[Path.Segment]) { self => def render(using Quotes): String = { import quotes.reflect.* - given Printer[TypeRepr] = Printer.TypeReprShortCode - val printedRoot = root.repr.widen.show + val printedRoot = root.repr.widen.show(using Printer.TypeReprShortCode) if (self.segments.isEmpty) printedRoot else self.segments.map { case Path.Segment.Field(_, name) => name - case Path.Segment.Case(tpe) => s"at[${tpe.repr.show}]" + case Path.Segment.Case(tpe) => s"at[${tpe.repr.show(using Printer.TypeReprAnsiCode)}]" }.mkString(s"$printedRoot.", ".", "") } } diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/DucktapeSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/DucktapeSuite.scala index 7690654c..79a55775 100644 --- a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/DucktapeSuite.scala +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/DucktapeSuite.scala @@ -1,8 +1,13 @@ package io.github.arainko.ducktape import munit.{ FunSuite, Location } +import munit.Compare trait DucktapeSuite extends FunSuite { + def assertEachEquals[Source, Dest](head: Source, tail: Source*)(expected: Dest)(using Location, Compare[Source, Dest]) = { + (head :: tail.toList).foreach(actual => assertEquals(actual, expected)) + } + transparent inline def assertFailsToCompile(inline code: String)(using Location) = { assert(compiletime.testing.typeChecks(code), "Code snippet compiled despite expecting not to") } diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/builder/AppliedBuilderSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/AppliedBuilderSuite.scala similarity index 97% rename from ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/builder/AppliedBuilderSuite.scala rename to ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/AppliedBuilderSuite.scala index afaeecce..0f0a1ece 100644 --- a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/builder/AppliedBuilderSuite.scala +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/AppliedBuilderSuite.scala @@ -1,4 +1,4 @@ -package io.github.arainko.ducktape.total.builder +package io.github.arainko.ducktape.total import io.github.arainko.ducktape.* @@ -28,7 +28,7 @@ class AppliedBuilderSuite extends DucktapeSuite { .transform(Field.const(_.additionalArg, "const")) """ }( - "No field 'additionalArg' found in io.github.arainko.ducktape.total.builder.AppliedBuilderSuite.TestClass @ TestClassWithAdditionalList.additionalArg", + "No field 'additionalArg' found in io.github.arainko.ducktape.total.AppliedBuilderSuite.TestClass @ TestClassWithAdditionalList.additionalArg", "Configuration is not valid since the provided type (java.lang.String) is not a subtype of scala.collection.immutable.List[scala.Predef.String] @ TestClassWithAdditionalList.additionalArg" ) } @@ -53,7 +53,7 @@ class AppliedBuilderSuite extends DucktapeSuite { """ }( "Configuration is not valid since the provided type (scala.collection.immutable.List[scala.Int]) is not a subtype of scala.collection.immutable.List[scala.Predef.String] @ TestClassWithAdditionalList.additionalArg", - "No field 'additionalArg' found in io.github.arainko.ducktape.total.builder.AppliedBuilderSuite.TestClass @ TestClassWithAdditionalList.additionalArg" + "No field 'additionalArg' found in io.github.arainko.ducktape.total.AppliedBuilderSuite.TestClass @ TestClassWithAdditionalList.additionalArg" ) } @@ -76,7 +76,7 @@ class AppliedBuilderSuite extends DucktapeSuite { .transform(Field.renamed(_.additionalArg, _.int)) """ }( - "No field 'additionalArg' found in io.github.arainko.ducktape.total.builder.AppliedBuilderSuite.TestClass @ TestClassWithAdditionalString.additionalArg", + "No field 'additionalArg' found in io.github.arainko.ducktape.total.AppliedBuilderSuite.TestClass @ TestClassWithAdditionalString.additionalArg", "Configuration is not valid since the provided type (scala.Int) is not a subtype of java.lang.String @ TestClassWithAdditionalString.additionalArg" ) } diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/builder/AppliedViaBuilderSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/AppliedViaBuilderSuite.scala similarity index 92% rename from ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/builder/AppliedViaBuilderSuite.scala rename to ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/AppliedViaBuilderSuite.scala index b04aafab..ddbaf152 100644 --- a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/builder/AppliedViaBuilderSuite.scala +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/AppliedViaBuilderSuite.scala @@ -1,7 +1,7 @@ -package io.github.arainko.ducktape.total.builder +package io.github.arainko.ducktape.total import io.github.arainko.ducktape.* -import io.github.arainko.ducktape.total.builder.AppliedViaBuilderSuite.* +import io.github.arainko.ducktape.total.AppliedViaBuilderSuite.* import scala.annotation.nowarn @@ -74,7 +74,7 @@ class AppliedViaBuilderSuite extends DucktapeSuite { .intoVia(method) .transform() """ - }("No field 'additionalArg' found in io.github.arainko.ducktape.total.builder.AppliedViaBuilderSuite.TestClass @ TestClassWithAdditionalString.additionalArg") + }("No field 'additionalArg' found in io.github.arainko.ducktape.total.AppliedViaBuilderSuite.TestClass @ TestClassWithAdditionalString.additionalArg") } } diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/builder/DefinitionViaBuilderSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DefinitionViaBuilderSuite.scala similarity index 93% rename from ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/builder/DefinitionViaBuilderSuite.scala rename to ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DefinitionViaBuilderSuite.scala index e01532fe..75048430 100644 --- a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/builder/DefinitionViaBuilderSuite.scala +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DefinitionViaBuilderSuite.scala @@ -1,8 +1,8 @@ -package io.github.arainko.ducktape.total.builder +package io.github.arainko.ducktape.total import io.github.arainko.* import io.github.arainko.ducktape.* -import io.github.arainko.ducktape.total.builder.DefinitionViaBuilderSuite.* +import io.github.arainko.ducktape.total.DefinitionViaBuilderSuite.* import munit.* class DefinitionViaBuilderSuite extends DucktapeSuite { @@ -93,7 +93,7 @@ class DefinitionViaBuilderSuite extends DucktapeSuite { .defineVia[TestClass](method) .build() """ - }("No field 'additionalArg' found in io.github.arainko.ducktape.total.builder.DefinitionViaBuilderSuite.TestClass @ TestClassWithAdditionalString.additionalArg") + }("No field 'additionalArg' found in io.github.arainko.ducktape.total.DefinitionViaBuilderSuite.TestClass @ TestClassWithAdditionalString.additionalArg") } } diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/derivation/DerivedTransformerSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DerivedTransformerSuite.scala similarity index 97% rename from ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/derivation/DerivedTransformerSuite.scala rename to ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DerivedTransformerSuite.scala index 83a91a0b..590300bf 100644 --- a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/derivation/DerivedTransformerSuite.scala +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/DerivedTransformerSuite.scala @@ -1,4 +1,4 @@ -package io.github.arainko.ducktape.total.derivation +package io.github.arainko.ducktape.total import io.github.arainko.ducktape.* import io.github.arainko.ducktape.model.* @@ -356,7 +356,7 @@ class DerivedTransformerSuite extends DucktapeSuite { } assertFailsToCompileWith("summon[Transformer.Derived[Sum1, Sum2]]") { - "No field 'str1' found in Sum1.Leaf1 @ Sum2.at[Leaf1].str1" + "No field 'str1' found in Sum1.Leaf1 @ Sum2.at[Sum2.Leaf1].str1" } } @@ -372,6 +372,6 @@ class DerivedTransformerSuite extends DucktapeSuite { } test("derivation fails when going from a sum with more cases to a sum with less cases") { - assertFailsToCompileWith("MoreCases.Case3.to[LessCases]")("No child named 'Case4 found in io.github.arainko.ducktape.total.derivation.DerivedTransformerSuite.LessCases @ MoreCases.at[Case4]") + assertFailsToCompileWith("MoreCases.Case3.to[LessCases]")("No child named 'Case4 found in io.github.arainko.ducktape.total.DerivedTransformerSuite.LessCases @ MoreCases.at[io.github.arainko.ducktape.total.DerivedTransformerSuite.MoreCases.Case4]") } } diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ErrorReportingSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ErrorReportingSuite.scala new file mode 100644 index 00000000..b08d2a65 --- /dev/null +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ErrorReportingSuite.scala @@ -0,0 +1,7 @@ +package io.github.arainko.ducktape.total + +import io.github.arainko.ducktape.DucktapeSuite + +class ErrorReportingSuite extends DucktapeSuite { + +} diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/NestedConfigurationSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/NestedConfigurationSuite.scala new file mode 100644 index 00000000..a2bc06d7 --- /dev/null +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/NestedConfigurationSuite.scala @@ -0,0 +1,380 @@ +package io.github.arainko.ducktape.total + +import io.github.arainko.ducktape.DucktapeSuite +import io.github.arainko.ducktape.* +import scala.annotation.nowarn + +class NestedConfigurationSuite extends DucktapeSuite { + test("nested product fields can be configured") { + final case class SourceToplevel1(level1: SourceLevel1) + final case class SourceLevel1(level2: SourceLevel2) + final case class SourceLevel2(int: Int) + + final case class DestToplevel1(level1: DestLevel1) + final case class DestLevel1(level2: DestLevel2) + final case class DestLevel2(int: Int, extra: String) + + val source = SourceToplevel1(SourceLevel1(SourceLevel2(1))) + val expected = DestToplevel1(DestLevel1(DestLevel2(1, "CONFIGURED"))) + + assertEachEquals( + source.into[DestToplevel1].transform(Field.const(_.level1.level2.extra, "CONFIGURED")), + source.intoVia(DestToplevel1.apply).transform(Field.const(_.level1.level2.extra, "CONFIGURED")), + Transformer + .define[SourceToplevel1, DestToplevel1] + .build(Field.const(_.level1.level2.extra, "CONFIGURED")) + .transform(source), + Transformer + .defineVia[SourceToplevel1](DestToplevel1.apply) + .build(Field.const(_.level1.level2.extra, "CONFIGURED")) + .transform(source) + )(expected) + } + + test("nested product fields inside nested coproduct cases can be configured") { + final case class SourceToplevel1(level1: SourceLevel1) + enum SourceLevel1 { + case Level1(level2: SourceLevel2) + } + final case class SourceLevel2(int: Int) + + final case class DestToplevel1(level1: DestLevel1) + enum DestLevel1 { + case Level1(level2: DestLevel2) + } + final case class DestLevel2(int: Int, extra: String) + + val source = SourceToplevel1(SourceLevel1.Level1(SourceLevel2(1))) + val expected = DestToplevel1(DestLevel1.Level1(DestLevel2(1, "CONFIGURED"))) + + assertEachEquals( + source.into[DestToplevel1].transform(Field.const(_.level1.at[DestLevel1.Level1].level2.extra, "CONFIGURED")), + source.intoVia(DestToplevel1.apply).transform(Field.const(_.level1.at[DestLevel1.Level1].level2.extra, "CONFIGURED")), + Transformer + .define[SourceToplevel1, DestToplevel1] + .build(Field.const(_.level1.at[DestLevel1.Level1].level2.extra, "CONFIGURED")) + .transform(source), + Transformer + .defineVia[SourceToplevel1](DestToplevel1.apply) + .build(Field.const(_.level1.at[DestLevel1.Level1].level2.extra, "CONFIGURED")) + .transform(source) + )(expected) + } + + test("nested product fields can be overriden") { + final case class SourceToplevel1(level1: SourceLevel1) + final case class SourceLevel1(level2: SourceLevel2) + final case class SourceLevel2(int: Int) + + final case class DestToplevel1(level1: DestLevel1) + final case class DestLevel1(level2: DestLevel2) + final case class DestLevel2(int: Int) + + val source = SourceToplevel1(SourceLevel1(SourceLevel2(1))) + val expected = DestToplevel1(DestLevel1(DestLevel2(50))) + + assertEachEquals( + source.into[DestToplevel1].transform(Field.const(_.level1.level2.int, 50)), + source.intoVia(DestToplevel1.apply).transform(Field.const(_.level1.level2.int, 50)), + Transformer + .define[SourceToplevel1, DestToplevel1] + .build(Field.const(_.level1.level2.int, 50)) + .transform(source), + Transformer + .defineVia[SourceToplevel1](DestToplevel1.apply) + .build(Field.const(_.level1.level2.int, 50)) + .transform(source) + )(expected) + } + + test("nested product fields can be configured by overriding the transformation that is a level above") { + final case class SourceToplevel1(level1: SourceLevel1) + final case class SourceLevel1(level2: SourceLevel2) + final case class SourceLevel2(int: Int) + + final case class DestToplevel1(level1: DestLevel1) + final case class DestLevel1(level2: DestLevel2) + final case class DestLevel2(int: Int, extra: String) + + val source = SourceToplevel1(SourceLevel1(SourceLevel2(1))) + val expected = DestToplevel1(DestLevel1(DestLevel2(50, "CONFIGURED"))) + + assertEachEquals( + source.into[DestToplevel1].transform(Field.const(_.level1.level2, DestLevel2(50, "CONFIGURED"))), + source.intoVia(DestToplevel1.apply).transform(Field.const(_.level1.level2, DestLevel2(50, "CONFIGURED"))), + Transformer + .define[SourceToplevel1, DestToplevel1] + .build(Field.const(_.level1.level2, DestLevel2(50, "CONFIGURED"))) + .transform(source), + Transformer + .defineVia[SourceToplevel1](DestToplevel1.apply) + .build(Field.const(_.level1.level2, DestLevel2(50, "CONFIGURED"))) + .transform(source) + )(expected) + } + + test("nested product configuration fails if the types do not line up") { + final case class SourceToplevel1(level1: SourceLevel1) + final case class SourceLevel1(level2: SourceLevel2) + final case class SourceLevel2(int: Int) + + final case class DestToplevel1(level1: DestLevel1) + final case class DestLevel1(level2: DestLevel2) + final case class DestLevel2(int: Int, extra: String) + + val source = SourceToplevel1(SourceLevel1(SourceLevel2(1))) + + assertFailsToCompileWith { + """ + source.into[DestToplevel1].transform(Field.const(_.level1.level2.extra, 123)) + """ + }( + "Configuration is not valid since the provided type (scala.Int) is not a subtype of java.lang.String @ DestToplevel1.level1.level2.extra", + "No field 'extra' found in SourceLevel2 @ DestToplevel1.level1.level2.extra" + ) + }: @nowarn("msg=unused local definition") + + test("nested coproduct cases can be configured") { + enum SourceToplevel1 { + case Level1(level2: SourceLevel2) + } + + enum SourceLevel2 { + case Level2(level3: SourceLevel3) + } + + enum SourceLevel3 { + case One + case Two + case Extra + } + + enum DestToplevel1 { + case Level1(level2: DestLevel2) + } + + enum DestLevel2 { + case Level2(level3: DestLevel3) + } + + enum DestLevel3 { + case One + case Two + } + + val source = SourceToplevel1.Level1(SourceLevel2.Level2(SourceLevel3.Extra)) + val expected = DestToplevel1.Level1(DestLevel2.Level2(DestLevel3.One)) + + // scalafmt: { maxColumn = 150 } + assertEachEquals( + source + .into[DestToplevel1] + .transform( + Case.const(_.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra.type], DestLevel3.One) + ), + Transformer + .define[SourceToplevel1, DestToplevel1] + .build( + Case.const(_.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra.type], DestLevel3.One) + ) + .transform(source) + )(expected) + } + + test("nested coproduct cases inside nested fields can be configured") { + final case class SourceToplevel1(level1: SourceLevel1) + + enum SourceLevel1 { + case Level1(level2: SourceLevel2) + } + + enum SourceLevel2 { + case Level2(level3: SourceLevel3) + } + + enum SourceLevel3 { + case One + case Two + case Extra + } + + final case class DestToplevel1(level1: DestLevel1) + + enum DestLevel1 { + case Level1(level2: DestLevel2) + } + + enum DestLevel2 { + case Level2(level3: DestLevel3) + } + + enum DestLevel3 { + case One + case Two + } + + val source = SourceToplevel1(SourceLevel1.Level1(SourceLevel2.Level2(SourceLevel3.Extra))) + val expected = DestToplevel1(DestLevel1.Level1(DestLevel2.Level2(DestLevel3.One))) + + assertEachEquals( + source + .into[DestToplevel1] + .transform( + Case.const(_.level1.at[SourceLevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra.type], DestLevel3.One) + ), + source + .intoVia(DestToplevel1.apply) + .transform( + Case.const(_.level1.at[SourceLevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra.type], DestLevel3.One) + ), + Transformer + .define[SourceToplevel1, DestToplevel1] + .build( + Case.const(_.level1.at[SourceLevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra.type], DestLevel3.One) + ) + .transform(source), + Transformer + .defineVia[SourceToplevel1](DestToplevel1.apply) + .build( + Case.const(_.level1.at[SourceLevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra.type], DestLevel3.One) + ) + .transform(source) + )(expected) + } + + test("nested coproduct cases can be overridden") { + enum SourceToplevel1 { + case Level1(level2: SourceLevel2) + } + + enum SourceLevel2 { + case Level2(level3: SourceLevel3) + } + + enum SourceLevel3 { + case One + case Two + } + + enum DestToplevel1 { + case Level1(level2: DestLevel2) + } + + enum DestLevel2 { + case Level2(level3: DestLevel3) + } + + enum DestLevel3 { + case One + case Two + } + + val source = SourceToplevel1.Level1(SourceLevel2.Level2(SourceLevel3.One)) + val expected = DestToplevel1.Level1(DestLevel2.Level2(DestLevel3.Two)) + + // scalafmt: { maxColumn = 150 } + assertEachEquals( + source + .into[DestToplevel1] + .transform( + Case.const(_.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.One.type], DestLevel3.Two) + ), + Transformer + .define[SourceToplevel1, DestToplevel1] + .build( + Case.const(_.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.One.type], DestLevel3.Two) + ) + .transform(source) + )(expected) + } + + test("nested coproduct cases can be configured by configuring the case that is a level above") { + enum SourceToplevel1 { + case Level1(level2: SourceLevel2) + } + + enum SourceLevel2 { + case Level2(level3: SourceLevel3) + } + + enum SourceLevel3 { + case One + case Two + case Extra + } + + enum DestToplevel1 { + case Level1(level2: DestLevel2) + } + + enum DestLevel2 { + case Level2(level3: DestLevel3) + } + + enum DestLevel3 { + case One + case Two + } + + val source = SourceToplevel1.Level1(SourceLevel2.Level2(SourceLevel3.Extra)) + val expected = DestToplevel1.Level1(DestLevel2.Level2(DestLevel3.One)) + + assertEachEquals( + source + .into[DestToplevel1] + .transform( + Case.const(_.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2], DestLevel2.Level2(DestLevel3.One)) + ), + Transformer + .define[SourceToplevel1, DestToplevel1] + .build( + Case.const(_.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2], DestLevel2.Level2(DestLevel3.One)) + ) + .transform(source) + )(expected) + } + + test("nested coproduct configuration fails if the types do not line up") { + enum SourceToplevel1 { + case Level1(level2: SourceLevel2) + } + + enum SourceLevel2 { + case Level2(level3: SourceLevel3) + } + + enum SourceLevel3 { + case One + case Two + case Extra + } + + enum DestToplevel1 { + case Level1(level2: DestLevel2) + } + + enum DestLevel2 { + case Level2(level3: DestLevel3) + } + + enum DestLevel3 { + case One + case Two + } + + val source = SourceToplevel1.Level1(SourceLevel2.Level2(SourceLevel3.Extra)) + + assertFailsToCompileWith { + """ + source + .into[DestToplevel1] + .transform( + Case.const(_.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra.type], 123) + ) + """ + }( + "No child named 'Extra' found in DestLevel3 @ SourceToplevel1.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra]", + "Configuration is not valid since the provided type (123) is not a subtype of DestLevel3 @ SourceToplevel1.at[SourceToplevel1.Level1].level2.at[SourceLevel2.Level2].level3.at[SourceLevel3.Extra]" + ) + }: @nowarn("msg=unused local definition") +} diff --git a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/derivation/ViaSuite.scala b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ViaSuite.scala similarity index 95% rename from ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/derivation/ViaSuite.scala rename to ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ViaSuite.scala index 65d3c28d..2bfb059f 100644 --- a/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/derivation/ViaSuite.scala +++ b/ducktapeNext/src/test/scala/io/github/arainko/ducktape/total/ViaSuite.scala @@ -1,4 +1,4 @@ -package io.github.arainko.ducktape.total.derivation +package io.github.arainko.ducktape.total import io.github.arainko.ducktape.* import munit.FunSuite @@ -72,7 +72,7 @@ class ViaSuite extends DucktapeSuite { value.via(method) """ - }("No field 'extraField' found in io.github.arainko.ducktape.total.derivation.Input @ Nothing.extraField") + }("No field 'extraField' found in io.github.arainko.ducktape.total.Input @ Nothing.extraField") } }