Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature enhancement - implement unique ID generated at compile time #138

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions sourcecode/src-2/sourcecode/Macros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ trait ArgsMacros {
implicit def generate: Args = macro Macros.argsImpl
}

trait UUIDMacros {
implicit def generate: SourceUUID = macro Macros.uuidImpl
}

object Util{
def isSynthetic(c: Compat.Context)(s: c.Symbol) = isSyntheticName(getName(c)(s))
def isSyntheticName(name: String) = {
Expand Down Expand Up @@ -195,4 +199,12 @@ object Macros {
}.mkString.dropRight(1)
c.Expr[T](q"""${c.prefix}($renderedPath)""")
}

def uuidImpl(c: Compat.Context): c.Expr[SourceUUID] = {
import c.universe._
import java.util.UUID
implicit val l: Liftable[UUID] = Liftable((in: UUID) => q"_root_.java.util.UUID.fromString(${in.toString})")
val uuid = java.util.UUID.randomUUID()
c.Expr[SourceUUID](q"""${c.prefix}($uuid)""")
}
}
15 changes: 15 additions & 0 deletions sourcecode/src-3/sourcecode/Macros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ trait ArgsMacros {
${ Macros.argsImpl }
}

trait UUIDMacros {
inline implicit def generate: SourceUUID =
${ Macros.uuidImpl }
}

object Util{
def isSynthetic(using Quotes)(s: quotes.reflect.Symbol) = isSyntheticName(getName(s))
def isSyntheticName(name: String) = {
Expand Down Expand Up @@ -167,6 +172,16 @@ object Macros {
'{Enclosing(${Expr(path)})}
}

def uuidImpl(using Quotes): Expr[SourceUUID] = {
import quotes.reflect._
import java.util.UUID
given ToExpr[UUID] with {
def apply(x: UUID)(using Quotes) = '{ _root_.java.util.UUID.fromString(${ Expr(x.toString) }.toString) }
}
val uuid = UUID.randomUUID()
'{ sourcecode.SourceUUID(${ Expr(uuid) }) }
}

def enclosingMachineImpl(using Quotes): Expr[Enclosing.Machine] = {
val path = enclosing(machine = true)(_ => true)
'{Enclosing.Machine(${Expr(path)})}
Expand Down
7 changes: 7 additions & 0 deletions sourcecode/src/sourcecode/SourceContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@ object Text extends TextMacros

case class Args(value: Seq[Seq[Text[_]]]) extends SourceValue[Seq[Seq[Text[_]]]]
object Args extends SourceCompanion[Seq[Seq[Text[_]]], Args](new Args(_)) with ArgsMacros

// Unique identifiers, labels, and other IDs generated at compile time.
import java.util.UUID

case class SourceUUID(value: UUID) extends SourceValue[UUID]

object SourceUUID extends SourceCompanion[UUID, SourceUUID](new SourceUUID(_)) with UUIDMacros
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package sourcecode

object EnumExaple {
object EnumExample {
def run() = {
case class EnumValue(name: String){
override def toString = name
Expand Down
47 changes: 47 additions & 0 deletions sourcecode/test/src/sourcecode/SourceUUIDTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package sourcecode

import java.util.UUID

object SourceUUIDTests {
case class DataWithId(x: Int, id: UUID)

case class DataWithImplicitId(x: Int)(implicit val id: sourcecode.SourceUUID)

def run() = {
// Verify that UUIDs are different and are generated at compile time, not at run time.
def generateUUIDs() = {
val uuid1 = implicitly[sourcecode.SourceUUID].value
val uuid2 = implicitly[sourcecode.SourceUUID].value
(uuid1, uuid2)
}

val (u1a, u2a) = generateUUIDs() // Generate a pair of UUIDs.
val (u1b, u2b) = generateUUIDs() // This will have the same UUIDs.
assert(u1a != u2a && u1a.toString != u2a.toString, "the two UUIDs are different")
assert(u1a == u1b && u1a.toString == u1b.toString, "the UUIDs are generated at compile time")
assert(u2a == u2b && u2a.toString == u2b.toString, "calling `generateUUIDs()` several times will produce the same results")

def generateData1(x: Int)(implicit uuid: sourcecode.SourceUUID) = DataWithId(x, uuid.value)

def generateData2(x: Int) = DataWithId(x, implicitly[sourcecode.SourceUUID].value)

val u10 = generateData1(10)
val u20 = generateData2(20)
val u30 = generateData1(30)
val u40 = generateData2(40)

assert(u10.id.toString != u30.id.toString, "generateData1() produces different IDs each time")
assert(u20.id.toString == u40.id.toString, "generateData2() produces the same IDs each time")
assert(u10.id.toString != u20.id.toString && u30.id.toString != u40.id.toString, "generateData1() and generateData2() produce different IDs")

val u50 = DataWithImplicitId(50)
val u60 = DataWithImplicitId(60)
assert(u50.id.toString != u60.id.toString, "DataWithImplicitId() produces different IDs each time")

def generateData3(x: Int) = DataWithImplicitId(x)

val u70 = generateData3(70)
val u80 = generateData3(80)
assert(u70.id.toString == u80.id.toString, "generateData3() produces the same IDs each time")
}
}
4 changes: 3 additions & 1 deletion sourcecode/test/src/sourcecode/Tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ object Tests{
println("================Test Begin================")
Apply.applyRun()
Implicits.implicitRun()
EnumExaple.run()
EnumExample.run()
EnumFull.run()
NoSynthetic.run()
Synthetic.run()
Expand All @@ -30,6 +30,8 @@ object Tests{
DebugName.main()
println("================Debug Lite================")
DebugLite.main()
println("================Unique IDs================")
SourceUUIDTests.run()
println("================Regressions===============")
Regressions.main()
println("================Test Ended================")
Expand Down