提交 df4b6bfa 编写于 作者: I IceMimosa

Add apply & constructor

上级 3575a35e
......@@ -2,8 +2,8 @@ package io.github.dreamylost.plugin
import com.intellij.openapi.Disposable
import io.github.dreamylost.plugin.processor.Processor
import io.github.dreamylost.plugin.processor.clazz.{ BuilderProcessor, JsonProcessor, LogProcessor }
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.{ ScClass, ScObject, ScTypeDefinition }
import io.github.dreamylost.plugin.processor.clazz.{ApplyProcessor, BuilderProcessor, ConstructorProcessor, JsonProcessor, LogProcessor}
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.{ScClass, ScObject, ScTypeDefinition}
import scala.collection.mutable
......@@ -18,6 +18,8 @@ class ScalaMacroProcessorProvider extends Disposable {
regist(ScalaMacroNames.BUILDER, new BuilderProcessor())
regist(ScalaMacroNames.LOG, new LogProcessor())
regist(ScalaMacroNames.JSON, new JsonProcessor())
regist(ScalaMacroNames.APPLY, new ApplyProcessor())
regist(ScalaMacroNames.CONSTRUCTOR, new ConstructorProcessor())
override def dispose(): Unit = {}
......
package io.github.dreamylost.plugin.processor
import org.jetbrains.plugins.scala.lang.psi.api.base.ScMethodLike
import org.jetbrains.plugins.scala.lang.psi.api.statements.params.ScClassParameter
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.ScClass
/**
* Mail: chk19940609@gmail.com
* Created by IceMimosa
......@@ -9,4 +13,23 @@ abstract class AbsProcessor extends Processor {
override def needCompanion: Boolean = false
/**
* get constructor parameters
*
* @return name and type
*/
protected def getConstructorParameters(clazz: ScClass, withSecond: Boolean = true): Seq[(String, String)] = {
val constructors = if (withSecond) {
clazz.constructors.map(Some(_))
} else {
Seq(clazz.constructor.map(_.asInstanceOf[ScMethodLike]))
}
constructors.filter(_.isDefined).map(_.get).flatMap(_.getParameterList.getParameters)
.map {
case p: ScClassParameter =>
p.name -> p.`type`().toOption.map(_.toString).getOrElse("Unit")
case _ => "" -> ""
}
.filter(_._1 != "")
}
}
package io.github.dreamylost.plugin.processor.clazz
import io.github.dreamylost.plugin.processor.ProcessType.ProcessType
import io.github.dreamylost.plugin.processor.{AbsProcessor, ProcessType}
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.{ScClass, ScObject, ScTypeDefinition}
/**
* Desc: Processor for annotation apply
*
* Mail: chk19940609@gmail.com
* Created by IceMimosa
* Date: 2021/7/8
*/
class ApplyProcessor extends AbsProcessor {
override def needCompanion: Boolean = true
override def process(source: ScTypeDefinition, typ: ProcessType): Seq[String] = {
typ match {
case ProcessType.Method =>
source match {
case obj: ScObject =>
val clazz = obj.fakeCompanionClassOrCompanionClass.asInstanceOf[ScClass]
val nameAndTypes = getConstructorParameters(clazz, withSecond = false)
.map(o => s"${o._1}: ${o._2}")
.mkString(", ")
Seq(s"def apply($nameAndTypes): ${clazz.getName} = ???")
case _ => Nil
}
case _ => Nil
}
}
}
......@@ -4,7 +4,6 @@ import io.github.dreamylost.plugin.processor.{ AbsProcessor, ProcessType }
import io.github.dreamylost.plugin.processor.ProcessType.ProcessType
import org.jetbrains.plugins.scala.lang.psi.api.statements.params.ScClassParameter
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.{ ScClass, ScObject, ScTypeDefinition }
import org.jetbrains.plugins.scala.lang.psi.impl.toplevel.typedef.ScClassImpl
/**
* Desc: Processor for annotation builder
......@@ -40,11 +39,7 @@ class BuilderProcessor extends AbsProcessor {
val clazz = obj.fakeCompanionClassOrCompanionClass
val className = clazz.getName
// support constructor and second constructor
val nameAndTypes = clazz.asInstanceOf[ScClassImpl].constructors.flatMap(_.getParameterList.getParameters)
.map {
case p: ScClassParameter =>
p.name -> p.`type`().toOption.getOrElse("Unit")
}
val nameAndTypes = getConstructorParameters(clazz.asInstanceOf[ScClass])
val assignMethods = nameAndTypes.map(term =>
s"def ${term._1}(${term._1}: ${term._2}): ${genBuilderName(className, returnType = true)} = ???"
)
......
package io.github.dreamylost.plugin.processor.clazz
import io.github.dreamylost.plugin.ScalaMacroNames
import io.github.dreamylost.plugin.processor.ProcessType.ProcessType
import io.github.dreamylost.plugin.processor.{AbsProcessor, ProcessType}
import org.jetbrains.plugins.scala.lang.psi.api.expr.ScMethodCall
import org.jetbrains.plugins.scala.lang.psi.api.statements.ScVariableDefinition
import org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.{ScClass, ScTypeDefinition}
import org.jetbrains.plugins.scala.lang.psi.types.ScLiteralType
/**
* Desc: Processor for annotation constructor
*
* Mail: chk19940609@gmail.com
* Created by IceMimosa
* Date: 2021/7/8
*/
class ConstructorProcessor extends AbsProcessor {
private val excludeFieldsName = "excludeFields"
override def needCompanion: Boolean = true
override def process(source: ScTypeDefinition, typ: ProcessType): Seq[String] = {
typ match {
case ProcessType.Method =>
source match {
case clazz: ScClass =>
val consFields = getConstructorParameters(clazz, withSecond = false)
val excludeFields = clazz.annotations(ScalaMacroNames.CONSTRUCTOR).lastOption match {
case Some(an) =>
an.getParameterList.getAttributes.findLast(_.getAttributeName == excludeFieldsName)
.map { expr =>
expr.getDetachedValue.asInstanceOf[ScMethodCall].argumentExpressions.map(_.`type`().toOption)
.filter(_.isDefined)
.map(_.get)
.map {
case str: ScLiteralType => str.value.value.toString
case _ => ""
}
.filter(_.nonEmpty)
.mkString(", ")
}.getOrElse("")
case None => ""
}
val varFields = clazz.extendsBlock.members
.filter {
case _: ScVariableDefinition => true // var
case _ => false // ScPatternDefinition, ScFunctionDefinition
}
.flatMap { v =>
val vd = v.asInstanceOf[ScVariableDefinition]
vd.declaredNames.map(n => (n, vd.`type`().toOption.map(_.toString).getOrElse("Unit")))
}
.filter(v => !excludeFields.contains(v._1))
val consFieldsStr = consFields.map(_._1).mkString(", ")
val allFieldsStr = (consFields ++ varFields).map(f => s"${f._1}: ${f._2}").mkString(", ")
Seq(s"def this($allFieldsStr) = this($consFieldsStr)")
case _ => Nil
}
case _ => Nil
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册