Skip to content

Commit 9f6e6c7

Browse files
committed
remove <none> and the *Any* and *All* variants
1 parent 7bf36ff commit 9f6e6c7

1 file changed

Lines changed: 28 additions & 175 deletions

File tree

enable-if-version-annotation-macros/src/main/scala/org/apache/comet/enableIfVer.scala

Lines changed: 28 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -26,65 +26,34 @@ import scala.reflect.macros.whitebox
2626
import org.semver4j.{RangesListFactory, Semver}
2727

2828
/**
29-
* Shared machinery behind the conditional compilation based on version annotation families:
30-
* - single dimension: [[enableIfVer]] (exactly one dimension, e.g. `@enableIfVer(spark =
31-
* ">=3.5.0")`)
32-
* - multi-dimension combinators: [[enableIfAllVer]] (every listed dimension must match) and
33-
* [[enableIfAnyVer]] (at least one must match).
29+
* Shared machinery behind the version annotations [[enableIfVer]], [[implementIfVer]] and
30+
* [[enableOverrideIfVer]].
3431
*
35-
* Every annotation performs the same compile-time tree rewrite (drop / empty-body-except-marked /
36-
* strip-`override`). the ONLY thing that differs is a single `Boolean` - does the build's
37-
* targeted version(s) satisfy the given range(s)? So the match decision is computed per
38-
* annotation and handed to the shared expansions here.
32+
* Every annotation performs the same compile-time tree rewrite (drop / empty-body / strip
33+
* `override`). the ONLY thing that differs is a single `Boolean` - does the build's targeted
34+
* version satisfy the given range? So the match decision is computed per annotation and handed to
35+
* the shared expansions here.
3936
*
4037
* The build feeds the targeted version of each dimension to the macro via
4138
* `-Xmacro-settings:enableIfVer.<dimension>=<version>`, read at expansion time from `c.settings`
4239
* (see [[versionOf]]). Adding a dimension is therefore just one more build entry - no generated
43-
* sources. Comet currently configures a single dimension, `spark`. A dimension may be configured
44-
* as `<none>` ([[NONE_VERSION]]) meaning "known to the build but not enabled".
40+
* sources. Comet currently configures a single dimension, `spark`.
4541
*
4642
* Ranges are matched by <a href="https://github.com/semver4j/semver4j">semver4j</a>: full
4743
* `major.minor.patch` versions with `>` `>=` `<` `<=` `=` `!=`, space = AND, `||` = OR, `A - B`
48-
* hyphen ranges and more. The literal range `"<none>"` is special - it matches iff the dimension
49-
* is configured but disabled (see [[satisfies]]).
44+
* hyphen ranges and more.
5045
*/
5146
object EnableIfVerSupport {
5247

53-
/**
54-
* Sentinel for a dimension that is known to the build but not enabled. As a configured value it
55-
* resolves to `None`. as a range (`@enableIfVer(spark = "<none>")`) it matches only such
56-
* disabled dimensions.
57-
*/
58-
val NONE_VERSION = "<none>"
59-
60-
/**
61-
* Does the configured `version` satisfy `range`?
62-
* - `range == "<none>"` matches iff the dimension is disabled (`version` is `None`).
63-
* - any other range never matches a disabled dimension.
64-
* - otherwise semver logic.
65-
*/
66-
def satisfies(c: whitebox.Context, range: String, version: Option[String]): Boolean =
67-
(range.trim, version) match {
68-
case (NONE_VERSION, None) => true
69-
case (NONE_VERSION, Some(_)) => false
70-
case (_, None) => false
71-
case (range, _) if range.contains(NONE_VERSION) =>
72-
c.abort(
73-
c.enclosingPosition,
74-
s"$NONE_VERSION is not supported with ranges, use semverAny* and " +
75-
s"""pass $NONE_VERSION explicitly (e.g. """ +
76-
s"""@enableIfAnyVer(spark = "<3.5.0", spark = "$NONE_VERSION"))""")
77-
case (range, Some(version)) =>
78-
val rangeList = RangesListFactory.create(range)
79-
80-
new Semver(version).satisfies(rangeList)
81-
}
48+
/** Does the configured `version` satisfy the semver `range`? */
49+
def satisfies(range: String, version: String): Boolean =
50+
new Semver(version).satisfies(RangesListFactory.create(range.trim))
8251

8352
/** Prefix of the `-Xmacro-settings` keys this macro understands. */
8453
private val SettingPrefix = "enableIfVer."
8554

8655
/** Parse `enableIfVer.<dimension>=<version>` entries out of `-Xmacro-settings`. */
87-
private def configuredVersions(c: whitebox.Context): Map[String, Option[String]] =
56+
private def configuredVersions(c: whitebox.Context): Map[String, String] =
8857
c.settings.collect {
8958
case s if s.startsWith(SettingPrefix) =>
9059
s.stripPrefix(SettingPrefix).split("=", 2) match {
@@ -97,20 +66,18 @@ object EnableIfVerSupport {
9766
}
9867
}.toMap
9968

100-
private def parseVersionFromSetting(name: String, version: String): Option[String] = {
101-
if (version == NONE_VERSION) return None
102-
69+
private def parseVersionFromSetting(name: String, version: String): String = {
10370
try {
10471
// Not using Semver.parse as it will return null instead of giving us meaningful
10572
// exceptions on invalid input
10673
new Semver(version)
10774

108-
Some(version)
75+
version
10976
} catch {
11077
case e: Throwable =>
11178
sys.error(
112-
s"malformed version passed in macro setting for '$name', expected either a valid " +
113-
s"SemVer or '$NONE_VERSION' got '$version' (error: ${e.toString})")
79+
s"malformed version passed in macro setting for '$name', expected a valid " +
80+
s"SemVer got '$version' (error: ${e.toString})")
11481
}
11582
}
11683

@@ -119,14 +86,13 @@ object EnableIfVerSupport {
11986
* extensibility seam: to add a dimension, pass
12087
* `-Xmacro-settings:${SettingPrefix}<dimension>=<version>` from the build.
12188
*
122-
* Returns `None` when the dimension is configured as `<none>` (known but disabled), and aborts
123-
* compilation when the dimension was not configured at all.
89+
* Aborts compilation when the dimension was not configured at all.
12490
*/
125-
private def versionOf(c: whitebox.Context, dimension: String): Option[String] = {
91+
private def versionOf(c: whitebox.Context, dimension: String): String = {
12692
val versions = configuredVersions(c)
12793
versions.getOrElse(
12894
dimension,
129-
// we do not treat missing dimension as None since we want to avoid having silent failures
95+
// we do not treat a missing dimension as a match since we want to avoid silent failures
13096
c.abort(
13197
c.enclosingPosition,
13298
s"@enableIfVer: no version configured for dimension '$dimension'" +
@@ -138,10 +104,10 @@ object EnableIfVerSupport {
138104
object Macros {
139105

140106
/**
141-
* Extract the named `dimension = range` arguments of a combined annotation. A named argument
142-
* is `name = value`, whose immediate children are `[Ident(name), value]` - matched
143-
* structurally so this works on both Scala 2.12 (`AssignOrNamedArg`) and 2.13 (`NamedArg`). A
144-
* positional arg (e.g. a bare literal) has no such children and is rejected.
107+
* Extract the named `dimension = range` argument of a version annotation. A named argument is
108+
* `name = value`, whose immediate children are `[Ident(name), value]` - matched structurally
109+
* so this works on both Scala 2.12 (`AssignOrNamedArg`) and 2.13 (`NamedArg`). A positional
110+
* arg (e.g. a bare literal) has no such children and is rejected.
145111
*/
146112
private def namedRanges(c: whitebox.Context): List[(String, String)] = {
147113
import c.universe._
@@ -162,33 +128,18 @@ object EnableIfVerSupport {
162128
}
163129
}
164130

165-
/** Single dimension: require exactly one named arg and match it. */
131+
/** Require exactly one named dimension arg and return whether the build matches its range. */
166132
def singleKeep(c: whitebox.Context, specificMacroPrefix: String): Boolean = {
167133
val ranges = namedRanges(c)
168134
if (ranges.size != 1) {
169135
val ifCase = if (specificMacroPrefix.isEmpty) "enableIf" else "If"
170136
c.abort(
171137
c.enclosingPosition,
172138
s"@${specificMacroPrefix}${ifCase}Ver accepts exactly one dimension " +
173-
s"(got ${ranges.size}). use @${specificMacroPrefix}${ifCase}AllVer / " +
174-
s"@${specificMacroPrefix}${ifCase}AnyVer for multiple dimensions.")
139+
s"(got ${ranges.size}).")
175140
}
176141
val (dim, range) = ranges.head
177-
satisfies(c, range, versionOf(c, dim))
178-
}
179-
180-
/** Combined AND: keep iff every provided dimension matches (requires at least one). */
181-
def allKeep(c: whitebox.Context): Boolean = {
182-
val ranges = namedRanges(c)
183-
ranges.nonEmpty && ranges.forall { case (dim, range) =>
184-
satisfies(c, range, versionOf(c, dim))
185-
}
186-
}
187-
188-
/** Combined OR: keep iff at least one provided dimension matches. */
189-
def anyKeep(c: whitebox.Context): Boolean = {
190-
val ranges = namedRanges(c)
191-
ranges.exists { case (dim, range) => satisfies(c, range, versionOf(c, dim)) }
142+
satisfies(range, versionOf(c, dim))
192143
}
193144

194145
// ----- generic tree-rewrite expansions (take a precomputed keep) ---------------------------
@@ -245,10 +196,6 @@ object EnableIfVerSupport {
245196
}
246197
}
247198

248-
// =================================================================================================
249-
// Single dimension
250-
// =================================================================================================
251-
252199
object enableIfVer {
253200
object Macros {
254201
def verEnable(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] =
@@ -264,9 +211,8 @@ object enableIfVer {
264211

265212
/**
266213
* Keep the annotated member only when the build matches a single dimension's range. otherwise
267-
* drop it entirely. Exactly one dimension must be given as a named semver range (use
268-
* [[enableIfAllVer]] / [[enableIfAnyVer]] for multiple). Known dimensions are whatever the build
269-
* configures via `-Xmacro-settings` (currently `spark`).
214+
* drop it entirely. Exactly one dimension must be given as a named semver range. Known dimensions
215+
* are whatever the build configures via `-Xmacro-settings` (currently `spark`).
270216
*
271217
* Example:
272218
* {{{
@@ -351,96 +297,3 @@ final class implementIfVer(spark: String = "") extends StaticAnnotation {
351297
final class enableOverrideIfVer(spark: String = "") extends StaticAnnotation {
352298
def macroTransform(annottees: Any*): Any = macro enableIfVer.Macros.verEnableOverride
353299
}
354-
355-
// =================================================================================================
356-
// Combined: ALL dimensions must match (AND)
357-
// =================================================================================================
358-
359-
object enableIfAllVer {
360-
object Macros {
361-
def verEnable(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] =
362-
EnableIfVerSupport.Macros.enable(c)(annottees)(EnableIfVerSupport.Macros.allKeep(c))
363-
def verImplementIf(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] =
364-
EnableIfVerSupport.Macros.implementIf(c)(annottees)(EnableIfVerSupport.Macros.allKeep(c))
365-
def verEnableOverride(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] =
366-
EnableIfVerSupport.Macros.enableOverride(c)(annottees)(EnableIfVerSupport.Macros.allKeep(c))
367-
}
368-
}
369-
370-
/**
371-
* Keep the annotated member only when the build matches EVERY listed dimension (logical AND).
372-
* Dimensions are named semver ranges. omitted dimensions are not constrained, and within a single
373-
* dimension you can still use `||` for OR. Arguments must be named. Comet currently configures
374-
* only the `spark` dimension; this combinator exists for builds that add more.
375-
*
376-
* Example:
377-
* {{{
378-
* @enableIfAllVer(spark = ">=3.5.0") // keep on Spark 3.5+
379-
* def needsSpark35(): Unit = ...
380-
* }}}
381-
*/
382-
@nowarn("cat=unused") // params are used by the macro
383-
@compileTimeOnly("enable macro paradise to expand macro annotations")
384-
final class enableIfAllVer(spark: String = "") extends StaticAnnotation {
385-
def macroTransform(annottees: Any*): Any = macro enableIfAllVer.Macros.verEnable
386-
}
387-
388-
/** Like [[implementIfVer]] but with all condition like [[enableIfAllVer]]. */
389-
@nowarn("cat=unused") // params are used by the macro
390-
@compileTimeOnly("enable macro paradise to expand macro annotations")
391-
final class implementIfAllVer(spark: String = "") extends StaticAnnotation {
392-
def macroTransform(annottees: Any*): Any = macro enableIfAllVer.Macros.verImplementIf
393-
}
394-
395-
/** Like [[enableIfAllVer]], but strips the `override` modifier on a non-matching combination. */
396-
@nowarn("cat=unused") // params are used by the macro
397-
@compileTimeOnly("enable macro paradise to expand macro annotations")
398-
final class enableOverrideIfAllVer(spark: String = "") extends StaticAnnotation {
399-
def macroTransform(annottees: Any*): Any = macro enableIfAllVer.Macros.verEnableOverride
400-
}
401-
402-
// =================================================================================================
403-
// Combined: ANY dimension matches (OR)
404-
// =================================================================================================
405-
406-
object enableIfAnyVer {
407-
object Macros {
408-
def verEnable(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] =
409-
EnableIfVerSupport.Macros.enable(c)(annottees)(EnableIfVerSupport.Macros.anyKeep(c))
410-
def implementIf(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] =
411-
EnableIfVerSupport.Macros.implementIf(c)(annottees)(EnableIfVerSupport.Macros.anyKeep(c))
412-
def verEnableOverride(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] =
413-
EnableIfVerSupport.Macros.enableOverride(c)(annottees)(EnableIfVerSupport.Macros.anyKeep(c))
414-
}
415-
}
416-
417-
/**
418-
* Keep the annotated member when the build matches AT LEAST ONE listed dimension (logical OR).
419-
* Arguments must be named. Comet currently configures only the `spark` dimension; this combinator
420-
* exists for builds that add more.
421-
*
422-
* Example:
423-
* {{{
424-
* @enableIfAnyVer(spark = ">=4.0.0") // keep on Spark 4+
425-
* def newApi(): Unit = ...
426-
* }}}
427-
*/
428-
@nowarn("cat=unused") // params are used by the macro
429-
@compileTimeOnly("enable macro paradise to expand macro annotations")
430-
final class enableIfAnyVer(spark: String = "") extends StaticAnnotation {
431-
def macroTransform(annottees: Any*): Any = macro enableIfAnyVer.Macros.verEnable
432-
}
433-
434-
/** Like [[implementIfVer]] but with any condition like [[enableIfAnyVer]]. */
435-
@nowarn("cat=unused") // params are used by the macro
436-
@compileTimeOnly("enable macro paradise to expand macro annotations")
437-
final class implementIfAnyVer(spark: String = "") extends StaticAnnotation {
438-
def macroTransform(annottees: Any*): Any = macro enableIfAnyVer.Macros.implementIf
439-
}
440-
441-
/** Like [[enableIfAnyVer]], but strips the `override` modifier on a non-matching combination. */
442-
@nowarn("cat=unused") // params are used by the macro
443-
@compileTimeOnly("enable macro paradise to expand macro annotations")
444-
final class enableOverrideIfAnyVer(spark: String = "") extends StaticAnnotation {
445-
def macroTransform(annottees: Any*): Any = macro enableIfAnyVer.Macros.verEnableOverride
446-
}

0 commit comments

Comments
 (0)