Skip to content

Commit 5660c9b

Browse files
committed
metadata constructors can now apply filters
1 parent a277cfb commit 5660c9b

File tree

6 files changed

+57
-33
lines changed

6 files changed

+57
-33
lines changed

commons-macros/src/main/scala/com/avsystem/commons/macros/meta/AdtMetadataMacros.scala

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ class AdtMetadataMacros(ctx: blackbox.Context) extends AbstractMacroCommons(ctx)
158158

159159
def tryMaterializeFor(adtSymbol: AdtSymbol): Res[Tree] =
160160
for {
161+
_ <- matchFilters(adtSymbol)
161162
_ <- if (paramMdParams.isEmpty) Ok(()) else adtSymbol match {
162163
case _: AdtClass => Ok(())
163164
case _ => Fail(s"${adtSymbol.nameStr} is not a case class or case class like type")
@@ -212,13 +213,19 @@ class AdtMetadataMacros(ctx: blackbox.Context) extends AbstractMacroCommons(ctx)
212213
def allowListedMulti: Boolean = true
213214

214215
val auxiliary: Boolean =
215-
findAnnotation(symbol, AuxiliaryAT).nonEmpty
216+
annot(AuxiliaryAT).nonEmpty
216217

217218
private def metadataTree(adtParam: AdtParam, indexInRaw: Int): Option[Res[Tree]] =
218219
Some(MatchedAdtParam(adtParam, this, indexInRaw)).filter(m => matchFilters(m).isOk).map { matched =>
219220
val result = for {
220221
mdType <- actualMetadataType(arity.collectedType, adtParam.actualType, "parameter type", verbatim = false)
221-
tree <- materializeOneOf(mdType)(t => new AdtParamMetadataConstructor(t, None).tryMaterializeFor(matched))
222+
tree <- materializeOneOf(mdType) { t =>
223+
val constructor = new AdtParamMetadataConstructor(t, None)
224+
for {
225+
_ <- constructor.matchFilters(matched)
226+
tree <- constructor.tryMaterializeFor(matched)
227+
} yield tree
228+
}
222229
} yield tree
223230
result.mapFailure(msg => s"${adtParam.problemStr}: cannot map it to $shortDescription $pathStr: $msg")
224231
}

commons-macros/src/main/scala/com/avsystem/commons/macros/meta/MacroMetadatas.scala

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,16 @@ trait MacroMetadatas extends MacroSymbols {
8282
}
8383

8484
abstract class MetadataConstructor(val ownerType: Type, val atParam: Option[CompositeParam])
85-
extends MacroMethod { this: MetadataConstructor =>
85+
extends MacroMethod with FilteringSymbol {
8686

8787
lazy val symbol: Symbol =
8888
primaryConstructor(ownerType, atParam)
8989

90-
lazy val allowIncomplete: Boolean =
91-
findAnnotation(ownerType.typeSymbol, AllowIncompleteAT).nonEmpty
90+
override def annotationSource: Symbol =
91+
ownerType.typeSymbol
9292

93-
// fallback to annotations on the class itself
94-
def annot(tpe: Type): Option[Annot] =
95-
findAnnotation(symbol, tpe) orElse findAnnotation(ownerType.typeSymbol, tpe)
93+
lazy val allowIncomplete: Boolean =
94+
annot(AllowIncompleteAT).nonEmpty
9695

9796
def shortDescription = "metadata class"
9897
def description = s"$shortDescription $ownerType"
@@ -163,7 +162,7 @@ trait MacroMetadatas extends MacroSymbols {
163162
def allowNamedMulti: Boolean = false
164163
def allowListedMulti: Boolean = false
165164

166-
val checked: Boolean = findAnnotation(symbol, CheckedAT).nonEmpty
165+
val checked: Boolean = annot(CheckedAT).nonEmpty
167166

168167
def tryMaterializeFor(matchedSymbol: MatchedSymbol): Res[Tree] =
169168
arity match {
@@ -206,7 +205,7 @@ trait MacroMetadatas extends MacroSymbols {
206205
case ParamArity.Optional(_) =>
207206
Ok(mkOptional(matchedSymbol.annot(annotTpe).map(validatedAnnotTree)))
208207
case ParamArity.Multi(_, _) =>
209-
Ok(mkMulti(matchedSymbol.allAnnots(annotTpe).map(validatedAnnotTree)))
208+
Ok(mkMulti(matchedSymbol.annots(annotTpe).map(validatedAnnotTree)))
210209
}
211210
}
212211
}
@@ -219,7 +218,7 @@ trait MacroMetadatas extends MacroSymbols {
219218
}
220219

221220
def tryMaterializeFor(matchedSymbol: MatchedSymbol): Res[Tree] =
222-
Ok(q"${matchedSymbol.allAnnots(annotTpe).nonEmpty}")
221+
Ok(q"${matchedSymbol.annots(annotTpe).nonEmpty}")
223222
}
224223

225224
class ReifiedNameParam(owner: MetadataConstructor, symbol: Symbol, useRawName: Boolean)

commons-macros/src/main/scala/com/avsystem/commons/macros/meta/MacroSymbols.scala

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ trait MacroSymbols extends MacroCommons {
4141
object ParamArity {
4242
def fromAnnotation(param: ArityParam, allowListedMulti: Boolean, allowNamedMulti: Boolean): ParamArity = {
4343

44-
val at = findAnnotation(param.symbol, RpcArityAT).fold(SingleArityAT)(_.tpe)
44+
val at = param.annot(RpcArityAT).fold(SingleArityAT)(_.tpe)
4545
if (at <:< SingleArityAT) ParamArity.Single(param.actualType)
4646
else if (at <:< OptionalArityAT) {
4747
val optionLikeType = typeOfCachedImplicit(param.optionLike)
@@ -75,7 +75,7 @@ trait MacroSymbols extends MacroCommons {
7575
sealed abstract class MethodArity(val verbatimByDefault: Boolean) extends Arity
7676
object MethodArity {
7777
def fromAnnotation(method: MacroMethod): MethodArity = {
78-
val at = findAnnotation(method.symbol, RpcArityAT).fold(SingleArityAT)(_.tpe)
78+
val at = method.annot(RpcArityAT).fold(SingleArityAT)(_.tpe)
7979
if (at <:< SingleArityAT) Single
8080
else if (at <:< OptionalArityAT) Optional
8181
else if (at <:< MultiArityAT) Multi
@@ -89,6 +89,7 @@ trait MacroSymbols extends MacroCommons {
8989

9090
abstract class MacroSymbol {
9191
def symbol: Symbol
92+
def annotationSource: Symbol = symbol
9293
def pos: Position = symbol.pos
9394
def seenFrom: Type
9495
def shortDescription: String
@@ -98,14 +99,20 @@ trait MacroSymbols extends MacroCommons {
9899
def reportProblem(msg: String, detailPos: Position = NoPosition): Nothing =
99100
abortAt(s"$problemStr: $msg", if (detailPos != NoPosition) detailPos else pos)
100101

102+
def annot(tpe: Type, fallback: List[Tree] = Nil): Option[Annot] =
103+
findAnnotation(annotationSource, tpe, seenFrom, withInherited = true, fallback)
104+
105+
def annots(tpe: Type, fallback: List[Tree] = Nil): List[Annot] =
106+
allAnnotations(annotationSource, tpe, seenFrom, withInherited = true, fallback)
107+
101108
def infer(tpt: Tree): TermName =
102109
infer(getType(tpt))
103110

104111
def infer(tpe: Type, forSym: MacroSymbol = this, clue: String = ""): TermName =
105112
inferCachedImplicit(tpe, s"${forSym.problemStr}: $clue", forSym.pos)
106113

107114
val name: TermName = symbol.name.toTermName
108-
val safeName: TermName = c.freshName(symbol.name.toTermName)
115+
val safeName: TermName = c.freshName(name)
109116
val nameStr: String = name.decodedName.toString
110117
val encodedNameStr: String = name.encodedName.toString
111118

@@ -166,7 +173,7 @@ trait MacroSymbols extends MacroCommons {
166173

167174
trait FilteringSymbol extends MacroSymbol {
168175
lazy val requiredAnnots: List[Type] =
169-
allAnnotations(symbol, AnnotatedAT).map(_.tpe.dealias.typeArgs.head)
176+
annots(AnnotatedAT).map(_.tpe.dealias.typeArgs.head)
170177

171178
def matchFilters(realSymbol: MatchedSymbol): Res[Unit] =
172179
Res.traverse(requiredAnnots) { annotTpe =>
@@ -188,9 +195,6 @@ trait MacroSymbols extends MacroCommons {
188195
def baseTagTpe: Type
189196
def fallbackTag: FallbackTag
190197

191-
def annot(tpe: Type): Option[Annot] =
192-
findAnnotation(symbol, tpe, seenFrom)
193-
194198
def tagAnnot(tpe: Type): Option[Annot] =
195199
annot(tpe)
196200

@@ -218,7 +222,7 @@ trait MacroSymbols extends MacroCommons {
218222

219223
// returns fallback tag tree only IF it was necessary
220224
def matchTag(realSymbol: MacroSymbol): Res[FallbackTag] = {
221-
val tagAnnot = findAnnotation(realSymbol.symbol, baseTagTpe, realSymbol.seenFrom)
225+
val tagAnnot = realSymbol.annot(baseTagTpe)
222226
val fallbackTagUsed = if (tagAnnot.isEmpty) whenUntaggedTag orElse fallbackTag else FallbackTag.Empty
223227
val realTagTpe = tagAnnot.map(_.tpe).getOrElse(NoType) orElse fallbackTagUsed.annotTree.tpe orElse baseTagTpe
224228

@@ -269,9 +273,10 @@ trait MacroSymbols extends MacroCommons {
269273
def fallbackTagUsed: FallbackTag = FallbackTag.Empty
270274

271275
def annot(tpe: Type): Option[Annot] =
272-
findAnnotation(real.symbol, tpe, real.seenFrom, fallback = fallbackTagUsed.asList)
273-
def allAnnots(tpe: Type): List[Annot] =
274-
allAnnotations(real.symbol, tpe, real.seenFrom, fallback = fallbackTagUsed.asList)
276+
real.annot(tpe, fallbackTagUsed.asList)
277+
278+
def annots(tpe: Type): List[Annot] =
279+
real.annots(tpe, fallbackTagUsed.asList)
275280
}
276281

277282
trait SelfMatchedSymbol extends MacroSymbol with MatchedSymbol {

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package macros.rpc
33

44
import com.avsystem.commons.macros.AbstractMacroCommons
55
import com.avsystem.commons.macros.meta.MacroSymbols
6+
import com.avsystem.commons.macros.misc.Res
67

78
import scala.reflect.macros.blackbox
89

@@ -98,7 +99,13 @@ class RpcMacros(ctx: blackbox.Context) extends RpcMacroCommons(ctx)
9899
val realRpc = RealRpcTrait(weakTypeOf[Real].dealias)
99100
val metadataTpe = c.macroApplication.tpe.dealias
100101
val constructor = new RpcTraitMetadataConstructor(metadataTpe, None)
101-
guardedMetadata(metadataTpe, realRpc.tpe)(
102-
constructor.tryMaterializeFor(realRpc, constructor.methodMappings(realRpc)).getOrElse(abort))
102+
103+
def materialize: Res[Tree] = for {
104+
_ <- constructor.matchFilters(realRpc)
105+
methodMappings = constructor.methodMappings(realRpc)
106+
tree <- constructor.tryMaterializeFor(realRpc, methodMappings)
107+
} yield tree
108+
109+
guardedMetadata(metadataTpe, realRpc.tpe)(materialize.getOrElse(abort))
103110
}
104111
}

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ trait RpcMetadatas extends MacroMetadatas { this: RpcMacroCommons with RpcSymbol
3333
tree <- materializeOneOf(mdType) { t =>
3434
val constructor = new MethodMetadataConstructor(t, this, None)
3535
for {
36+
_ <- constructor.matchFilters(matchedMethod)
3637
paramMappings <- constructor.paramMappings(matchedMethod)
3738
tree <- constructor.tryMaterializeFor(matchedMethod, paramMappings)
3839
} yield tree
@@ -59,8 +60,13 @@ trait RpcMetadatas extends MacroMetadatas { this: RpcMacroCommons with RpcSymbol
5960
val realParam = matchedParam.real
6061
val result = for {
6162
mdType <- actualMetadataType(arity.collectedType, realParam.actualType, "parameter type", verbatim)
62-
tree <- materializeOneOf(mdType)(t =>
63-
new ParamMetadataConstructor(t, None, indexInRaw).tryMaterializeFor(matchedParam))
63+
tree <- materializeOneOf(mdType) { t =>
64+
val constructor = new ParamMetadataConstructor(t, None, indexInRaw)
65+
for {
66+
_ <- constructor.matchFilters(matchedParam)
67+
tree <- constructor.tryMaterializeFor(matchedParam)
68+
} yield tree
69+
}
6470
} yield tree
6571
result.mapFailure(msg => s"${realParam.problemStr}: $cannotMapClue: $msg")
6672
}
@@ -89,9 +95,6 @@ trait RpcMetadatas extends MacroMetadatas { this: RpcMacroCommons with RpcSymbol
8995
def baseTagTpe: Type = NothingTpe
9096
def fallbackTag: FallbackTag = FallbackTag.Empty
9197

92-
override def annot(tpe: Type): Option[Annot] =
93-
super[MetadataConstructor].annot(tpe)
94-
9598
val (baseMethodTag, fallbackMethodTag) =
9699
annot(MethodTagAT).map(tagSpec).getOrElse((NothingTpe, FallbackTag.Empty))
97100
val (baseParamTag, fallbackParamTag) =
@@ -113,7 +116,10 @@ trait RpcMetadatas extends MacroMetadatas { this: RpcMacroCommons with RpcSymbol
113116
)(_.mappingFor(_)).groupBy(_.mdParam)
114117
}
115118

116-
def tryMaterializeFor(rpc: RealRpcTrait, methodMappings: Map[MethodMetadataParam, List[MethodMetadataMapping]]): Res[Tree] =
119+
def tryMaterializeFor(
120+
rpc: RealRpcTrait,
121+
methodMappings: Map[MethodMetadataParam, List[MethodMetadataMapping]]
122+
): Res[Tree] =
117123
tryMaterialize(MatchedRpcTrait(rpc)) { case mmp: MethodMetadataParam =>
118124
val mappings = methodMappings.getOrElse(mmp, Nil)
119125
mmp.arity match {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ trait RpcSymbols extends MacroSymbols { this: RpcMacroCommons =>
1515
def overloaded: Boolean
1616

1717
val rawName: String = {
18-
val prefixes = allAnnotations(real.symbol, RpcNamePrefixAT, fallback = fallbackTagUsed.asList)
18+
val prefixes = real.annots(RpcNamePrefixAT, fallback = fallbackTagUsed.asList)
1919
.filter(a => overloaded || !a.findArg[Boolean](RpcNameOverloadedOnlyArg, false))
2020
.map(_.findArg[String](RpcNamePrefixArg))
2121
prefixes.mkString("", "", real.rpcName)
@@ -83,7 +83,7 @@ trait RpcSymbols extends MacroSymbols { this: RpcMacroCommons =>
8383

8484
trait RealRpcSymbol extends MacroSymbol {
8585
val rpcName: String =
86-
findAnnotation(symbol, RpcNameAT).fold(nameStr)(_.findArg[String](RpcNameArg))
86+
annot(RpcNameAT).fold(nameStr)(_.findArg[String](RpcNameArg))
8787
}
8888

8989
abstract class RpcTrait(val symbol: Symbol) extends MacroSymbol {
@@ -295,7 +295,7 @@ trait RpcSymbols extends MacroSymbols { this: RpcMacroCommons =>
295295
tpe.members.sorted.iterator.filter(m => m.isTerm && m.isAbstract).map(RawMethod(this, _)).toList
296296
}
297297

298-
case class RealRpcTrait(tpe: Type) extends RpcTrait(tpe.typeSymbol) with RealRpcSymbol {
298+
case class RealRpcTrait(tpe: Type) extends RpcTrait(tpe.typeSymbol) with RealRpcSymbol with SelfMatchedSymbol {
299299
def shortDescription = "real RPC"
300300
def description = s"$shortDescription $tpe"
301301

0 commit comments

Comments
 (0)