Skip to content

Commit e78d8dd

Browse files
committed
added simple annotation filter to RPCs
1 parent 0533d16 commit e78d8dd

File tree

6 files changed

+43
-13
lines changed

6 files changed

+43
-13
lines changed

commons-annotations/src/main/scala/com/avsystem/commons/rpc/rpcAnnotations.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ final class tried extends RawMethodAnnotation
325325
*
326326
* @tparam BaseTag base type for tags that can be used on real RPC methods
327327
* @param defaultTag default tag value assumed for untagged methods
328-
*/
328+
**/
329329
final class methodTag[BaseTag <: RpcTag](val defaultTag: BaseTag = null) extends RawRpcAnnotation
330330

331331
/**
@@ -383,6 +383,17 @@ final class paramTag[BaseTag <: RpcTag](val defaultTag: BaseTag = null) extends
383383
final class tagged[Tag <: RpcTag](val whenUntagged: Tag = null)
384384
extends RawMethodAnnotation with RawParamAnnotation
385385

386+
/**
387+
* Filter applied on raw methods or parameters which tells the macro engine that this raw method or parameter may
388+
* only match real methods or parameters annotated with at least one annotation of given type `A` (or any subtype).
389+
*
390+
* This is similar to [[tagged]] but simplier. Tagging lets you explicitly specify all possible tag types and provide
391+
* default/fallback tags when no tag is present.
392+
*
393+
* @tparam A type of annotation required to be present on real method or parameter
394+
*/
395+
final class annotated[A <: StaticAnnotation] extends RawRpcAnnotation
396+
386397
/**
387398
* Raw parameters annotated as `@auxiliary` match real parameters without "consuming" them. This means that
388399
* real parameters matched by an auxiliary raw parameter must also be matched by some non-auxiliary raw parameter.

commons-core/src/test/scala/com/avsystem/commons/rpc/NewRawRpc.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ case class renamed(int: Int, name: String) extends DummyParamTag {
2222

2323
case class suchMeta(intMeta: Int, strMeta: String) extends StaticAnnotation
2424

25+
class filter extends StaticAnnotation
26+
2527
sealed trait RestMethod extends RpcTag
2628
case class POST() extends RestMethod with AnnotationAggregate {
2729
@rpcNamePrefix("POST_") type Implied
@@ -38,7 +40,7 @@ case class GetterInvocation(
3840
@methodTag[RestMethod]
3941
@paramTag[DummyParamTag]
4042
trait NewRawRpc {
41-
def doSomething(arg: Double): String
43+
@annotated[filter] def doSomething(@annotated[filter] arg: Double): String
4244
@optional def doSomethingElse(arg: Double): String
4345

4446
@multi

commons-core/src/test/scala/com/avsystem/commons/rpc/NewRpcMetadataTest.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ trait SomeBase {
1313
}
1414

1515
trait TestApi extends SomeBase {
16-
def doSomething(double: Double): String
16+
@filter def doSomething(@filter double: Double): String
1717
def doSomethingElse(double: Double): String
1818
def varargsMethod(krap: String, dubl: Double)(czy: Boolean, @renamed(42, "nejm") ints: Int*): Future[Unit]
1919
def defaultValueMethod(@td int: Int = 0, @whenAbsent(difolt) bul: Boolean): Future[Unit]

commons-macros/src/main/scala/com/avsystem/commons/macros/rpc/RpcMacros.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ abstract class RpcMacroCommons(ctx: blackbox.Context) extends AbstractMacroCommo
4444
val TaggedAT: Type = getType(tq"$RpcPackage.tagged[_]")
4545
val WhenUntaggedArg: Symbol = TaggedAT.member(TermName("whenUntagged"))
4646
val RpcTagAT: Type = getType(tq"$RpcPackage.RpcTag")
47+
val AnnotatedAT: Type = getType(tq"$RpcPackage.annotated[_]")
4748
val RpcImplicitsSym: Symbol = getType(tq"$RpcPackage.RpcImplicitsProvider").member(TermName("implicits"))
4849
val TypedMetadataType: Type = getType(tq"$RpcPackage.TypedMetadata[_]")
4950
val MetadataParamStrategyType: Type = getType(tq"$RpcPackage.MetadataParamStrategy")

commons-macros/src/main/scala/com/avsystem/commons/macros/rpc/RpcMappings.scala

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ trait RpcMappings { this: RpcMacroCommons with RpcSymbols =>
2525
fallbackTag <- rawSymbol.matchTag(realMethod)
2626
matchedMethod = MatchedMethod(realMethod, fallbackTag)
2727
_ <- rawSymbol.matchName(matchedMethod)
28+
_ <- rawSymbol.matchFilters(matchedMethod)
2829
methodMapping <- createMapping(rawSymbol, matchedMethod)
2930
} yield methodMapping
30-
mappingRes match {
31+
mappingRes.mapFailure(msg => s"${rawSymbol.shortDescription} ${rawSymbol.nameStr} did not match: $msg") match {
3132
case Ok(m) => Some(m)
3233
case f: Fail => findMethodMapping(f :: errorsAcc, rawSymbolsRest)
3334
}
@@ -73,12 +74,12 @@ trait RpcMappings { this: RpcMacroCommons with RpcSymbols =>
7374
def loop(): Res[B] =
7475
if (it.hasNext) {
7576
val real = it.next()
76-
raw.matchTag(real) match {
77-
case Ok(fallbackTag) =>
77+
raw.matchRealParam(matchedMethod, real) match {
78+
case Ok(matchedParam) =>
7879
if (!raw.auxiliary) {
7980
it.remove()
8081
}
81-
matcher(MatchedParam(real, fallbackTag, matchedMethod))
82+
matcher(matchedParam)
8283
case Fail(_) => loop()
8384
}
8485
} else Fail(s"${raw.shortDescription} ${raw.pathStr} was not matched by real parameter")
@@ -90,9 +91,9 @@ trait RpcMappings { this: RpcMacroCommons with RpcSymbols =>
9091
def loop(): Option[B] =
9192
if (it.hasNext) {
9293
val real = it.next()
93-
raw.matchTag(real) match {
94-
case Ok(fallbackTag) =>
95-
val res = matcher(MatchedParam(real, fallbackTag, matchedMethod)).toOption
94+
raw.matchRealParam(matchedMethod, real) match {
95+
case Ok(matchedParam) =>
96+
val res = matcher(matchedParam).toOption
9697
if (!raw.auxiliary) {
9798
res.foreach(_ => it.remove())
9899
}
@@ -108,12 +109,12 @@ trait RpcMappings { this: RpcMacroCommons with RpcSymbols =>
108109
def loop(result: ListBuffer[B]): Res[List[B]] =
109110
if (it.hasNext) {
110111
val real = it.next()
111-
raw.matchTag(real) match {
112-
case Ok(fallbackTag) =>
112+
raw.matchRealParam(matchedMethod, real) match {
113+
case Ok(matchedParam) =>
113114
if (!raw.auxiliary) {
114115
it.remove()
115116
}
116-
matcher(MatchedParam(real, fallbackTag, matchedMethod), result.size) match {
117+
matcher(matchedParam, result.size) match {
117118
case Ok(b) =>
118119
result += b
119120
loop(result)

commons-macros/src/main/scala/com/avsystem/commons/macros/rpc/RpcSymbols.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,15 @@ trait RpcSymbols { this: RpcMacroCommons =>
211211
if (realTagTpe <:< requiredTag) Ok(fallbackTagUsed)
212212
else Fail(s"it does not accept ${realRpcSymbol.shortDescription}s tagged with $realTagTpe")
213213
}
214+
215+
lazy val requiredAnnots: List[Type] =
216+
allAnnotations(symbol, AnnotatedAT).map(_.tpe.dealias.typeArgs.head)
217+
218+
def matchFilters(realSymbol: MatchedRealSymbol[RealRpcSymbol]): Res[Unit] =
219+
Res.traverse(requiredAnnots) { annotTpe =>
220+
if (realSymbol.annot(annotTpe).nonEmpty) Ok(())
221+
else Fail(s"no annotation of type $annotTpe found on ${realSymbol.real.shortDescription}")
222+
}.map(_ => ())
214223
}
215224

216225
sealed trait RealRpcSymbol extends RpcSymbol
@@ -321,6 +330,12 @@ trait RpcSymbols { this: RpcMacroCommons =>
321330
annot(AuxiliaryAT).nonEmpty
322331

323332
def cannotMapClue: String
333+
334+
def matchRealParam(matchedMethod: MatchedMethod, realParam: RealParam): Res[MatchedParam] = for {
335+
fallbackTag <- matchTag(realParam)
336+
matchedParam = MatchedParam(realParam, fallbackTag, matchedMethod)
337+
_ <- matchFilters(matchedParam)
338+
} yield matchedParam
324339
}
325340

326341
object RawParam {

0 commit comments

Comments
 (0)