Skip to content

Commit a70a727

Browse files
rsshjapgollynicolasstucki
committed
added -Xmacro-settings option and API with the same behaviour as in Scala2
added @Experimenta annotation to new API method modified message, according to review Update library/src/scala/quoted/Quotes.scala settings -> XmacroSettings added CompilationInfo.XmacroSettings to MiMaFilters corrected MiMaFilters added examples from #12039 with workarround against #14245 remove trailing '\n' from file Co-authored-by: David Barri <[email protected]> Co-authored-by: Nicolas Stucki <[email protected]>
1 parent 0b4c6e7 commit a70a727

File tree

11 files changed

+137
-0
lines changed

11 files changed

+137
-0
lines changed

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ private sealed trait XSettings:
234234
def isTruthy(using Context) = XmixinForceForwarders.value == "true"
235235
def isAtLeastJunit(using Context) = isTruthy || XmixinForceForwarders.value == "junit"
236236
}
237+
238+
val XmacroSettings: Setting[List[String]] = MultiStringSetting("-Xmacro-settings", "setting1,setting2,..settingN", "List of settings which exposed to the macros")
237239
end XSettings
238240

239241
/** -Y "Forking" as in forked tongue or "Private" settings */

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
7878

7979
object CompilationInfo extends CompilationInfoModule:
8080
def isWhileTyping: Boolean = !ctx.isAfterTyper
81+
def XmacroSettings: List[String] = ctx.settings.XmacroSettings.value
8182
end CompilationInfo
8283

8384
extension (expr: Expr[Any])

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ class CompilationTests {
207207
compileFile("tests/run-custom-args/defaults-serizaliable-no-forwarders.scala", defaultOptions and "-Xmixin-force-forwarders:false"),
208208
compileFilesInDir("tests/run-custom-args/erased", defaultOptions.and("-language:experimental.erasedDefinitions")),
209209
compileFilesInDir("tests/run-custom-args/fatal-warnings", defaultOptions.and("-Xfatal-warnings")),
210+
compileDir("tests/run-custom-args/Xmacro-settings/simple", defaultOptions.and("-Xmacro-settings:one,two,three")),
211+
compileDir("tests/run-custom-args/Xmacro-settings/compileTimeEnv", defaultOptions.and("-Xmacro-settings:a,b=1,c.b.a=x.y.z=1,myLogger.level=INFO")),
210212
compileFilesInDir("tests/run-deep-subtype", allowDeepSubtypes),
211213
compileFilesInDir("tests/run", defaultOptions.and("-Ysafe-init"))
212214
).checkRuns()

library/src/scala/quoted/Quotes.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,15 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
238238
* This will be true when the macro is used in a transparent inline.
239239
*/
240240
def isWhileTyping: Boolean
241+
242+
/** Expose macro-specific settings as a list of strings.
243+
* Settings can be set from command line with help of -Xmacro-settings options.
244+
*
245+
* These will be used to expand any transparent macros or any non-transparent macro that is forced to expand while expanding the transparent macro.
246+
* Non-transparent macros are not guaranteed to be expanded with the same set of settings.
247+
*/
248+
@experimental
249+
def XmacroSettings: List[String]
241250
}
242251

243252

project/MiMaFilters.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ object MiMaFilters {
1717
ProblemFilters.exclude[MissingClassProblem]("scala.compiletime.ops.float$"),
1818
ProblemFilters.exclude[MissingClassProblem]("scala.compiletime.ops.long"),
1919
ProblemFilters.exclude[MissingClassProblem]("scala.compiletime.ops.long$"),
20+
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#CompilationInfoModule.XmacroSettings"),
21+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule#CompilationInfoModule.XmacroSettings"),
2022

2123
// Should have been added in 3.1.0
2224
// These are only allowed on imports and therefore should not be present in binaries emitted before
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
I'm a info msg
2+
I'm a warn msg
3+
a = []
4+
b = [1]
5+
c.b.a = [x.y.z=1]
6+
wat is not defined
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import scala.compiletime.*
2+
import scala.quoted.*
3+
4+
5+
object Logging {
6+
7+
// Just use your imagination for now :)
8+
private inline val Trace = 0
9+
private inline val Debug = 1
10+
private inline val Info = 2
11+
private inline val Warn = 3
12+
13+
private transparent inline def chosenThreshold: Int = ${
14+
choosenTresholdImpl
15+
}
16+
17+
18+
private def choosenTresholdImpl(using Quotes):Expr[Int] =
19+
import quotes.reflect.*
20+
MacroEnv.getInMacro("myLogger.level") match
21+
case Some("TRACE") => Expr(Trace)
22+
case Some("DEBUG") => Expr(Debug)
23+
case Some("INFO") => Expr(Info)
24+
case Some("WARN") => Expr(Warn)
25+
case Some(x) => report.errorAndAbort("Unsupported logging level: " + x)
26+
case None => Expr(Trace)
27+
28+
private inline def log(inline lvl: Int, inline msg: String): Unit =
29+
inline if lvl >= chosenThreshold then println(msg)
30+
31+
inline def trace(inline msg: String): Unit = log(Trace, msg)
32+
inline def debug(inline msg: String): Unit = log(Debug, msg)
33+
inline def info (inline msg: String): Unit = log(Info , msg)
34+
inline def warn (inline msg: String): Unit = log(Warn , msg)
35+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import scala.quoted.*
2+
3+
object MacroEnv {
4+
5+
inline def get(inline key:String):Option[String] = ${
6+
getImpl('key)
7+
}
8+
9+
def getImpl(key:Expr[String])(using Quotes):Expr[Option[String]] = {
10+
import quotes.reflect.*
11+
val retval = getInMacro(key.valueOrAbort)
12+
Expr(retval)
13+
}
14+
15+
def getInMacro(key:String)(using Quotes):Option[String] = {
16+
import quotes.reflect.*
17+
val keyEq = key + "="
18+
CompilationInfo.XmacroSettings.collectFirst{
19+
case v if v == key => ""
20+
case v if v.startsWith(keyEq) =>
21+
v.substring(keyEq.length)
22+
}
23+
}
24+
25+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import scala.compiletime.*
2+
3+
object Test {
4+
import Logging.*
5+
6+
def main(args: Array[String]): Unit = {
7+
runLog()
8+
runBasic()
9+
}
10+
11+
def runLog(): Unit = {
12+
trace("I'm a trace msg")
13+
debug("I'm a debug msg")
14+
info("I'm a info msg")
15+
warn("I'm a warn msg")
16+
}
17+
18+
def runBasic(): Unit = {
19+
printEnv("a")
20+
printEnv("b")
21+
printEnv("c.b.a")
22+
printEnv("wat")
23+
}
24+
25+
inline def printEnv(inline k: String): Unit =
26+
MacroEnv.get(k) match
27+
case Some(v) => println(s"$k = [$v]")
28+
case None => println(k + " is not defined")
29+
30+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package x
2+
3+
import scala.quoted.*
4+
5+
object M:
6+
7+
inline def settingsContains(inline x:String): Boolean = ${
8+
settingsContainsImpl('x)
9+
}
10+
11+
def settingsContainsImpl(x:Expr[String])(using Quotes): Expr[Boolean] =
12+
import quotes.reflect.*
13+
val v = x.valueOrAbort
14+
val r = CompilationInfo.XmacroSettings.contains(v)
15+
Expr(r)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import x.*
2+
3+
object Test {
4+
5+
def main(args: Array[String]):Unit =
6+
assert(M.settingsContains("one"))
7+
assert(!M.settingsContains("notwo"))
8+
assert(M.settingsContains("two"))
9+
10+
}

0 commit comments

Comments
 (0)