提交 075f34d0 编写于 作者: 梦境迷离's avatar 梦境迷离

optimize

上级 205719d6
......@@ -22,7 +22,7 @@
package io.github.dreamylost.macros
import scala.reflect.macros.whitebox
import io.github.dreamylost.macros.ErrorMessage.UNEXPECTED_PATTERN
/**
*
* @author 梦境迷离
......@@ -100,7 +100,7 @@ abstract class AbstractMacroProcessor(val c: whitebox.Context) {
annottees.map(_.tree).toList match {
case (classDecl: ClassDef) :: Nil => classDecl
case (classDecl: ClassDef) :: (compDecl: ModuleDef) :: Nil => classDecl
case _ => c.abort(c.enclosingPosition, "Unexpected annottee. Only applicable to class definitions.")
case _ => c.abort(c.enclosingPosition, ErrorMessage.UNEXPECTED_PATTERN)
}
}
......@@ -115,7 +115,7 @@ abstract class AbstractMacroProcessor(val c: whitebox.Context) {
case (classDecl: ClassDef) :: Nil => None
case (classDecl: ClassDef) :: (compDecl: ModuleDef) :: Nil => Some(compDecl)
case (compDecl: ModuleDef) :: Nil => Some(compDecl)
case _ => c.abort(c.enclosingPosition, UNEXPECTED_PATTERN)
case _ => c.abort(c.enclosingPosition, ErrorMessage.UNEXPECTED_PATTERN)
}
}
......@@ -128,12 +128,10 @@ abstract class AbstractMacroProcessor(val c: whitebox.Context) {
*/
def treeResultWithCompanionObject(resTree: Tree, annottees: Expr[Any]*): Tree = {
val companionOpt = tryGetCompanionObject(annottees: _*)
if (companionOpt.isEmpty) {
resTree
} else {
companionOpt.fold(resTree) { t =>
q"""
$resTree
${companionOpt.get}
$t
"""
}
}
......@@ -163,10 +161,7 @@ abstract class AbstractMacroProcessor(val c: whitebox.Context) {
def isCaseClass(annotateeClass: ClassDef): Boolean = {
annotateeClass match {
case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" =>
if (mods.asInstanceOf[Modifiers].hasFlag(Flag.CASE)) {
c.info(c.enclosingPosition, "Annotation is used on 'case class'.", force = true)
true
} else false
mods.asInstanceOf[Modifiers].hasFlag(Flag.CASE)
case _ => c.abort(c.enclosingPosition, ErrorMessage.ONLY_CLASS)
}
}
......@@ -193,9 +188,8 @@ abstract class AbstractMacroProcessor(val c: whitebox.Context) {
* @return
*/
def getMethodParamName(field: Tree): Name = {
field match {
case q"$mods val $tname: $tpt = $expr" => tpt.asInstanceOf[Ident].name.decodedName
}
val q"$mods val $tname: $tpt = $expr" = field
tpt.asInstanceOf[Ident].name.decodedName
}
/**
......@@ -285,7 +279,7 @@ abstract class AbstractMacroProcessor(val c: whitebox.Context) {
* @param fieldss
* @param isCase
* @return A constructor with currying, it not contains tpt, provide for calling method.
* @example [[new TestClass12(i)(j)(k)(t)]]
* @example {{ new TestClass12(i)(j)(k)(t) }}
*/
def getConstructorWithCurrying(typeName: TypeName, fieldss: List[List[Tree]], isCase: Boolean): Tree = {
val allFieldsTermName = fieldss.map(f => f.map(ff => getFieldTermName(ff)))
......@@ -308,7 +302,7 @@ abstract class AbstractMacroProcessor(val c: whitebox.Context) {
* @param typeName
* @param fieldss
* @return A apply method with currying.
* @example [[def apply(int: Int)(j: Int)(k: Option[String])(t: Option[Long]): B3 = new B3(int)(j)(k)(t)]]
* @example {{ def apply(int: Int)(j: Int)(k: Option[String])(t: Option[Long]): B3 = new B3(int)(j)(k)(t) }}
*/
def getApplyMethodWithCurrying(typeName: TypeName, fieldss: List[List[Tree]], classTypeParams: List[Tree]): Tree = {
val allFieldsTermName = fieldss.map(f => getFieldAssignExprs(f))
......@@ -321,7 +315,7 @@ abstract class AbstractMacroProcessor(val c: whitebox.Context) {
val first = allFieldsTermName.head
q"def apply[..$classTypeParams](..$first)(...${allFieldsTermName.tail}): $typeName[..$returnTypeParams] = ${getConstructorWithCurrying(typeName, fieldss, isCase = false)}"
}
c.info(c.enclosingPosition, s"getApplyWithCurrying constructor: $applyMethod, paramss: $fieldss", force = true)
c.info(c.enclosingPosition, s"getApplyMethodWithCurrying constructor: $applyMethod, paramss: $fieldss", force = true)
applyMethod
}
......@@ -354,13 +348,12 @@ abstract class AbstractMacroProcessor(val c: whitebox.Context) {
* @return
*/
def extractClassTypeParamsTypeName(tpParams: List[Tree]): List[TypeName] = {
tpParams.map {
case t: TypeDef => t.name
}
tpParams.map(_.asInstanceOf[TypeDef].name)
}
/**
* Is there a parent class? Does not contains sdk class, such as AnyRef Object
*
* @param superClasses
* @return
*/
......
......@@ -60,7 +60,7 @@ object applyMacro {
override def impl(annottees: Expr[Any]*): Expr[Any] = {
val annotateeClass: ClassDef = checkAndGetClassDef(annottees: _*)
if (isCaseClass(annotateeClass)) c.abort(c.enclosingPosition, s"Annotation is only supported on 'case class'")
if (isCaseClass(annotateeClass)) c.abort(c.enclosingPosition, ErrorMessage.ONLY_CASE_CLASS)
val resTree = handleWithImplType(annottees: _*)(modifiedDeclaration)
printTree(force = extractArgumentsDetail._1, resTree.tree)
resTree
......
......@@ -67,7 +67,7 @@ object constructorMacro {
val classFieldDefinitionsOnlyAssignExpr = getClassMemberVarDefOnlyAssignExpr(annotteeClassDefinitions)
if (classFieldDefinitionsOnlyAssignExpr.isEmpty) {
c.abort(c.enclosingPosition, s"Annotation is only supported on class when the internal field (declare as 'var') is nonEmpty.")
c.abort(c.enclosingPosition, s"${ErrorMessage.ONLY_CLASS} and the internal fields (declare as 'var') should not be Empty.")
}
// Extract the internal fields of members belonging to the class, but not in primary constructor.
val classFieldDefinitions = getClassMemberValDefs(annotteeClassDefinitions)
......@@ -107,7 +107,6 @@ object constructorMacro {
override def modifiedDeclaration(classDecl: ClassDef, compDeclOpt: Option[ModuleDef] = None): Any = {
val (annotteeClassParams, annotteeClassDefinitions) = classDecl match {
case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" =>
c.info(c.enclosingPosition, s"modifiedDeclaration className: $tpname, paramss: $paramss", force = extractArgumentsDetail._1)
(paramss.asInstanceOf[List[List[Tree]]], stats.asInstanceOf[Seq[Tree]])
case _ => c.abort(c.enclosingPosition, s"${ErrorMessage.ONLY_CLASS} classDef: $classDecl")
}
......
......@@ -80,28 +80,24 @@ object equalsAndHashCodeMacro {
// equals method
private def getEqualsMethod(className: TypeName, termNames: Seq[TermName], superClasses: Seq[Tree], annotteeClassDefinitions: Seq[Tree]): Tree = {
val existsCanEqual = getClassMemberDefDefs(annotteeClassDefinitions) exists {
case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" if tname.toString() == "canEqual" && paramss.nonEmpty =>
case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" if tname.asInstanceOf[TermName].decodedName.toString == "canEqual" && paramss.nonEmpty =>
val params = paramss.asInstanceOf[List[List[Tree]]].flatten.map(pp => getMethodParamName(pp))
params.exists(p => p.decodedName.toString == "Any")
case _ => false
}
val SDKClasses = Set("java.lang.Object", "scala.AnyRef")
val canEqualsExistsInSuper = if (superClasses.nonEmpty && !superClasses.forall(sc => SDKClasses.contains(sc.toString()))) { // TODO better way
true
} else false
val getEqualsExpr = (termName: TermName) => {
lazy val getEqualsExpr = (termName: TermName) => {
q"this.$termName.equals(t.$termName)"
}
val equalsExprs = termNames.map(getEqualsExpr)
val modifiers = if (canEqualsExistsInSuper) Modifiers(Flag.OVERRIDE, typeNames.EMPTY, List()) else Modifiers(NoFlags, typeNames.EMPTY, List())
// Make a rough judgment on whether override is needed.
val modifiers = if (existsSuperClassExcludeSdkClass(superClasses)) Modifiers(Flag.OVERRIDE, typeNames.EMPTY, List()) else Modifiers(NoFlags, typeNames.EMPTY, List())
val canEqual = if (existsCanEqual) q"" else q"$modifiers def canEqual(that: Any) = that.isInstanceOf[$className]"
q"""
$canEqual
override def equals(that: Any): Boolean =
that match {
case t: $className => t.canEqual(this) && Seq(..$equalsExprs).forall(f => f) && ${if (canEqualsExistsInSuper) q"super.equals(that)" else q"true"}
case t: $className => t.canEqual(this) && Seq(..$equalsExprs).forall(f => f) && ${if (existsSuperClassExcludeSdkClass(superClasses)) q"super.equals(that)" else q"true"}
case _ => false
}
"""
......@@ -130,7 +126,6 @@ object equalsAndHashCodeMacro {
override def modifiedDeclaration(classDecl: ClassDef, compDeclOpt: Option[ModuleDef]): Any = {
val (className, annotteeClassParams, annotteeClassDefinitions, superClasses) = classDecl match {
case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" =>
c.info(c.enclosingPosition, s"modifiedDeclaration className: $tpname, paramss: $paramss", force = extractArgumentsDetail._1)
(tpname.asInstanceOf[TypeName], paramss.asInstanceOf[List[List[Tree]]], stats.asInstanceOf[Seq[Tree]], parents.asInstanceOf[Seq[Tree]])
case _ => c.abort(c.enclosingPosition, s"${ErrorMessage.ONLY_CLASS} classDef: $classDecl")
}
......
......@@ -39,7 +39,6 @@ object jsonMacro {
fields.length match {
case 0 => c.abort(c.enclosingPosition, "Cannot create json formatter for case class with no fields")
case _ =>
c.info(c.enclosingPosition, s"jsonFormatter className: $className, field length: ${fields.length}", force = true)
q"implicit val jsonAnnotationFormat = play.api.libs.json.Json.format[$className]"
}
}
......@@ -54,9 +53,8 @@ object jsonMacro {
val (className, fields) = classDecl match {
case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends ..$bases { ..$body }" =>
if (!mods.asInstanceOf[Modifiers].hasFlag(Flag.CASE)) {
c.abort(c.enclosingPosition, s"Annotation is only supported on case class. classDef: $classDecl, mods: $mods")
c.abort(c.enclosingPosition, ErrorMessage.ONLY_CASE_CLASS)
} else {
c.info(c.enclosingPosition, s"modifiedDeclaration className: $tpname, paramss: $paramss", force = true)
(tpname.asInstanceOf[TypeName], paramss.asInstanceOf[List[List[Tree]]])
}
case _ => c.abort(c.enclosingPosition, s"${ErrorMessage.ONLY_CLASS} classDef: $classDecl")
......
......@@ -68,7 +68,7 @@ object logMacro {
case q"$mods object $tpname extends { ..$earlydefns } with ..$parents { $self => ..$stats }" :: _ =>
val argument = LogTransferArgument(tpname.asInstanceOf[TermName].decodedName.toString, isCaseClass = false)
LogType.getLogImpl(extractArgumentsDetail._2).getTemplate(c)(argument)
case _ => c.abort(c.enclosingPosition, s"Annotation is only supported on class or object.")
case _ => c.abort(c.enclosingPosition, ErrorMessage.ONLY_OBJECT_CLASS)
}
// add result into class
......
......@@ -32,7 +32,9 @@ package object macros {
object ErrorMessage {
// common error msg
final val ONLY_CLASS = "Annotation is only supported on class."
final val UNEXPECTED_PATTERN = "unexpected annotation pattern!"
final val ONLY_CASE_CLASS = "Annotation is only supported on case class."
final val ONLY_OBJECT_CLASS = "Annotation is only supported on class or object."
final val UNEXPECTED_PATTERN = "Unexpected annotation pattern!"
}
}
......@@ -37,23 +37,32 @@ object toStringMacro {
import c.universe._
private def extractTree(aa: Tree, bb: Tree, cc: Tree, dd: Tree): (Boolean, Boolean, Boolean, Boolean) = {
(
evalTree[Boolean](aa),
evalTree[Boolean](bb),
evalTree[Boolean](cc),
evalTree[Boolean](dd)
)
}
private val extractArgumentsDetail: (Boolean, Boolean, Boolean, Boolean) = extractArgumentsTuple4 {
case q"new toString(includeInternalFields=$bb, includeFieldNames=$cc, callSuper=$dd)" =>
(false, evalTree(bb.asInstanceOf[Tree]), evalTree(cc.asInstanceOf[Tree]), evalTree(dd.asInstanceOf[Tree]))
extractTree(q"false", bb.asInstanceOf[Tree], cc.asInstanceOf[Tree], dd.asInstanceOf[Tree])
case q"new toString(verbose=$aa, includeInternalFields=$bb, includeFieldNames=$cc)" =>
(evalTree(aa.asInstanceOf[Tree]), evalTree(bb.asInstanceOf[Tree]), evalTree(cc.asInstanceOf[Tree]), false)
extractTree(aa.asInstanceOf[Tree], bb.asInstanceOf[Tree], cc.asInstanceOf[Tree], q"false")
case q"new toString($aa, $bb, $cc)" =>
(evalTree(aa.asInstanceOf[Tree]), evalTree(bb.asInstanceOf[Tree]), evalTree(cc.asInstanceOf[Tree]), false)
extractTree(aa.asInstanceOf[Tree], bb.asInstanceOf[Tree], cc.asInstanceOf[Tree], q"false")
case q"new toString(verbose=$aa, includeInternalFields=$bb, includeFieldNames=$cc, callSuper=$dd)" =>
(evalTree(aa.asInstanceOf[Tree]), evalTree(bb.asInstanceOf[Tree]), evalTree(cc.asInstanceOf[Tree]), evalTree(dd.asInstanceOf[Tree]))
extractTree(aa.asInstanceOf[Tree], bb.asInstanceOf[Tree], cc.asInstanceOf[Tree], dd.asInstanceOf[Tree])
case q"new toString($aa, $bb, $cc, $dd)" =>
(evalTree(aa.asInstanceOf[Tree]), evalTree(bb.asInstanceOf[Tree]), evalTree(cc.asInstanceOf[Tree]), evalTree(dd.asInstanceOf[Tree]))
extractTree(aa.asInstanceOf[Tree], bb.asInstanceOf[Tree], cc.asInstanceOf[Tree], dd.asInstanceOf[Tree])
case q"new toString(includeInternalFields=$bb, includeFieldNames=$cc)" =>
(false, evalTree(bb.asInstanceOf[Tree]), evalTree(cc.asInstanceOf[Tree]), false)
extractTree(q"false", bb.asInstanceOf[Tree], cc.asInstanceOf[Tree], q"false")
case q"new toString(includeInternalFields=$bb)" =>
(false, evalTree(bb.asInstanceOf[Tree]), true, false)
extractTree(q"false", bb.asInstanceOf[Tree], q"true", q"false")
case q"new toString(includeFieldNames=$cc)" =>
(false, true, evalTree(cc.asInstanceOf[Tree]), false)
extractTree(q"false", q"true", cc.asInstanceOf[Tree], q"false")
case q"new toString()" => (false, true, true, false)
case _ => c.abort(c.enclosingPosition, ErrorMessage.UNEXPECTED_PATTERN)
}
......@@ -110,7 +119,6 @@ object toStringMacro {
val annotteeClassFieldDefinitions = annotteeClassDefinitions.filter(p => p match {
case _: ValDef => true
case mem: MemberDef =>
c.info(c.enclosingPosition, s"MemberDef: ${mem.toString}", force = argument.verbose)
if (mem.toString().startsWith("override def toString")) { // TODO better way
c.abort(mem.pos, "'toString' method has already defined, please remove it or not use'@toString'")
}
......@@ -141,7 +149,6 @@ object toStringMacro {
}
superClassDef.fold(toString)(_ => {
val superClass = q"${"super="}"
c.info(c.enclosingPosition, s"member: $member, superClass: $superClass, superClassDef: $superClassDef, paramsWithName: $paramsWithName", force = argument.verbose)
q"override def toString: String = StringContext(${className.toTermName.decodedName.toString} + ${"("} + $superClass, ${if (member.nonEmpty) ", " else ""}+$paramsWithName + ${")"}).s(super.toString)"
}
)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册