From df4b6bfae5a11e574692d383dc4d7493e170f887 Mon Sep 17 00:00:00 2001 From: IceMimosa Date: Fri, 9 Jul 2021 14:26:07 +0800 Subject: [PATCH 1/2] Add apply & constructor --- .../plugin/ScalaMacroProcessorProvider.scala | 6 +- .../plugin/processor/AbsProcessor.scala | 23 +++++++ .../processor/clazz/ApplyProcessor.scala | 33 ++++++++++ .../processor/clazz/BuilderProcessor.scala | 7 +- .../clazz/ConstructorProcessor.scala | 66 +++++++++++++++++++ 5 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/ApplyProcessor.scala create mode 100644 intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/ConstructorProcessor.scala diff --git a/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/ScalaMacroProcessorProvider.scala b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/ScalaMacroProcessorProvider.scala index f32a07ba..f73a501c 100644 --- a/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/ScalaMacroProcessorProvider.scala +++ b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/ScalaMacroProcessorProvider.scala @@ -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 = {} diff --git a/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/AbsProcessor.scala b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/AbsProcessor.scala index 20b0c930..0a68cad7 100644 --- a/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/AbsProcessor.scala +++ b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/AbsProcessor.scala @@ -1,5 +1,9 @@ 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 != "") + } } diff --git a/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/ApplyProcessor.scala b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/ApplyProcessor.scala new file mode 100644 index 00000000..794b04a7 --- /dev/null +++ b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/ApplyProcessor.scala @@ -0,0 +1,33 @@ +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 + } + } +} diff --git a/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/BuilderProcessor.scala b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/BuilderProcessor.scala index c572b38c..be3e23e0 100644 --- a/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/BuilderProcessor.scala +++ b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/BuilderProcessor.scala @@ -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)} = ???" ) diff --git a/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/ConstructorProcessor.scala b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/ConstructorProcessor.scala new file mode 100644 index 00000000..79ce9c8a --- /dev/null +++ b/intellij-plugin/src/main/scala/io/github/dreamylost/plugin/processor/clazz/ConstructorProcessor.scala @@ -0,0 +1,66 @@ +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 + } + } +} From 6b8e519f3738b88581e78daf7cb17d6ad6950c57 Mon Sep 17 00:00:00 2001 From: IceMimosa Date: Sat, 10 Jul 2021 23:07:39 +0800 Subject: [PATCH 2/2] Add change log --- .../src/main/resources/patch/change.html | 5 ++++ .../plugin/processor/AbsProcessor.scala | 6 ++-- .../clazz/ConstructorProcessor.scala | 30 +++++++++---------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/intellij-plugin/src/main/resources/patch/change.html b/intellij-plugin/src/main/resources/patch/change.html index 4d273092..26470c7d 100644 --- a/intellij-plugin/src/main/resources/patch/change.html +++ b/intellij-plugin/src/main/resources/patch/change.html @@ -1,3 +1,8 @@ +