Skip to content

Instantly share code, notes, and snippets.

@rssh
Created April 22, 2021 04:08
Show Gist options
  • Save rssh/49d0e05dcd27678417a18248a114930e to your computer and use it in GitHub Desktop.
Save rssh/49d0e05dcd27678417a18248a114930e to your computer and use it in GitHub Desktop.
dn-q: ShowLabel
val dottyVersion = "3.0.0-RC3"
lazy val root = project
.in(file("."))
.settings(
name := "test",
version := "0.0.1",
scalaVersion := dottyVersion,
scalacOptions ++= Seq( "-unchecked", "-Ycheck:macros" ),
)
// in src/main/scala/x
package x
// should pass compile
case class TestMappingTemplate() derives ShowName {
//...
}
// should fail on compile
case class SomeOtherThing() derives ShowName {
// ...
}
object Run extends App:
println("run")
// in src/main/scala/x
package x
import scala.deriving._
import scala.compiletime._
import scala.quoted.*
object ShowLabel {
def showLabelExpr[T](label: Expr[String])(using Quotes)(using Type[T]): Expr[ShowName[T]] = {
val docRegex = "(Test)(Mapping)([a-zA-Z]+)".r
val simpleRegex = "([a-zA-Z]+)(Mapping)([a-zA-Z]+)".r
given ToExpr[ShowName[T]] with {
override def apply(x: ShowName[T])(using Quotes): Expr[ShowName[T]] =
Expr.summon[ShowName[T]].get
}
label.value match {
case Some(docRegex(doc, _, _)) =>
Expr(
new ShowName[T] {
def name(source: Option[String]): String =
s"$doc".toLowerCase
}
)
case Some(simpleRegex(docType, _, _)) =>
Expr(
new ShowName[T] {
def name(source: Option[String]): String =
s"$docType".toLowerCase
}
)
case Some(value) =>
quotes.reflect.report.throwError(s"Can't produce such name: $value")
case None =>
quotes.reflect.report.throwError(s"Expected label to be a known string but was: ${label.show}")
}
}
}
// in src/main/scala/x
package x
import scala.deriving._
import scala.compiletime._
import scala.quoted.*
trait ShowName[T] {
def name(source: Option[String]): String
}
object ShowName {
// you need helper because you can't pass '{m.MirroredLabel} directly
inline def _helper[T](inline label: String): ShowName[T] =
${ ShowLabel.showLabelExpr[T]('label) }
inline given derived[T](using m: Mirror.Of[T]): ShowName[T] =
_helper[T](constValue[m.MirroredLabel])
}
@DenisNovac
Copy link

Thank you for reply. It really works with compile check but the name method won't work if you try to use it:

object Run extends App:
   extension[T](t: T) {
    def getName(source: Option[String] = Some(""))(using ShowName[T]) =
      summon[ShowName[T]].name(source)
   }


  println(TestMappingTemplate().getName(Some("testSource")))  

It just runs the app forever without error or output.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment