Skip to content

Commit

Permalink
feat: Enhance support for enum fields in 'field' (#1083)
Browse files Browse the repository at this point in the history
  • Loading branch information
tangcent authored Nov 26, 2023
1 parent 42123b0 commit 8593919
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import com.itangcent.annotation.script.ScriptIgnore
import com.itangcent.annotation.script.ScriptTypeName
import com.itangcent.common.logger.traceError
import com.itangcent.common.utils.asBool
import com.itangcent.common.utils.getSub
import com.itangcent.common.utils.mapToTypedArray
import com.itangcent.http.RequestUtils
import com.itangcent.idea.plugin.api.MethodInferHelper
import com.itangcent.idea.plugin.format.Json5Formatter
import com.itangcent.intellij.config.rule.*
import com.itangcent.intellij.context.ActionContext
import com.itangcent.intellij.extend.notReentrant
import com.itangcent.intellij.extend.toPrettyString
import com.itangcent.intellij.jvm.*
import com.itangcent.intellij.jvm.duck.ArrayDuckType
Expand Down Expand Up @@ -599,6 +601,14 @@ abstract class ScriptRuleParser : AbstractRuleParser() {
return ScriptPsiTypeContext(classRuleConfig!!.tryConvert(psiField.type, psiField))
}

fun isEnumField(): Boolean {
return psiField is PsiEnumConstant
}

fun asEnumField(): ScriptPsiEnumConstantContext? {
return (psiField as? PsiEnumConstant)?.let { ScriptPsiEnumConstantContext(it) }
}

override fun toString(): String {
return containingClass().name() + "#" + psiField.name
}
Expand Down Expand Up @@ -626,6 +636,40 @@ abstract class ScriptRuleParser : AbstractRuleParser() {
}
}

@ScriptTypeName("enumField")
inner class ScriptPsiEnumConstantContext(private val psiEnumConstant: PsiEnumConstant) :
BaseScriptRuleContext(psiEnumConstant) {

override fun getName(): String {
return psiEnumConstant.name
}

fun ordinal(): Int {
return actionContext.callInReadUI {
psiEnumConstant.containingClass?.fields?.indexOf(psiEnumConstant)
} ?: 0
}

private fun getEnumFields(): Map<String, Any?> {
return actionContext.notReentrant("enumFields") {
actionContext.callInReadUI {
actionContext.instance(PsiResolver::class).resolveEnumFields(
ordinal(), psiEnumConstant
)
}
} ?: emptyMap()

}

fun getParams(): Map<String, Any?> {
return getEnumFields().getSub("params") ?: emptyMap()
}

fun getParam(name: String): Any? {
return getParams()[name]
}
}

/**
* it.returnType:class
* it.isVarArgs:Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,16 @@ fun ActionContext.withBoundary(action: () -> Unit) {
*/
private val reentrantIdx = AtomicInteger()

fun ActionContext.notReentrant(flag: String, action: () -> Unit) {
fun <T> ActionContext.notReentrant(flag: String, action: () -> T): T? {
val idx = reentrantIdx.getAndIncrement()
if (this.cacheOrCompute("reentrantFlag-${flag}") { idx } == idx) {
try {
action()
return action()
} finally {
this.deleteCache<Int>("reentrantFlag-${flag}")
}
}
return null
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ abstract class ScriptClassContextBaseTest : PluginContextLightCodeInsightFixture
internal lateinit var addPsiClass: PsiClass
internal lateinit var updatePsiClass: PsiClass
internal lateinit var validationGroupedDemoDtoPsiClass: PsiClass
internal lateinit var userTypePsiClass: PsiClass
internal lateinit var userInfoPsiClass: PsiClass

override fun beforeBind() {
super.beforeBind()
Expand Down Expand Up @@ -64,6 +66,8 @@ abstract class ScriptClassContextBaseTest : PluginContextLightCodeInsightFixture
addPsiClass = loadClass("constant/Add.java")!!
updatePsiClass = loadClass("constant/Update.java")!!
validationGroupedDemoDtoPsiClass = loadClass("model/ValidationGroupedDemoDto.java")!!
userTypePsiClass = loadClass("constant/UserType.java")!!
userInfoPsiClass = loadClass("model/UserInfo.java")!!
}

override fun customConfig(): String? {
Expand All @@ -90,6 +94,12 @@ abstract class ScriptClassContextBaseTest : PluginContextLightCodeInsightFixture
" }else{\n" +
" return -1\n" +
" }\n" +
"```\n" +
"field.doc=groovy:```\n" +
"if(!it.isEnumField()){\n" +
" return\n" +
"}\n" +
"return it.asEnumField().getParam(\"desc\")\n" +
"```"
}

Expand Down Expand Up @@ -532,6 +542,18 @@ abstract class ScriptClassContextBaseTest : PluginContextLightCodeInsightFixture
fun testToJson() {
assertEquals("{}", objectPsiClass.asClassContext().toJson(true, true))

assertEquals(
"{\n" +
" \"id\": 0,\n" +
" \"type\": 0,\n" +
" \"name\": \"\",\n" +
" \"age\": 0,\n" +
" \"sex\": 0,\n" +
" \"birthDay\": \"\",\n" +
" \"regtime\": \"\"\n" +
"}", userInfoPsiClass.asClassContext().toJson(true, true)
)

assertEquals(
"{\n" +
" \"shouldBeFirst\": \"\",\n" +
Expand Down Expand Up @@ -695,6 +717,26 @@ abstract class ScriptClassContextBaseTest : PluginContextLightCodeInsightFixture
fun testToJson5() {
assertEquals("{}", objectPsiClass.asClassContext().toJson5(true, true))

assertEquals(
"{\n" +
" \"id\": 0, //user id\n" +
" /**\n" +
" * user type\n" +
" * 1 :administration\n" +
" * ADMINISTRATION\n" +
" * 2 :a person, an animal or a plant\n" +
" * MEMBER\n" +
" * 3 :Anonymous visitor\n" +
" * ANONYMOUS\n" +
" */\n" +
" \"type\": 0,\n" +
" \"name\": \"\", //user name\n" +
" \"age\": 0, //user age\n" +
" \"sex\": 0,\n" +
" \"birthDay\": \"\", //user birthDay\n" +
" \"regtime\": \"\" //user regtime\n" +
"}", userInfoPsiClass.asClassContext().toJson5(true, true)
)
assertEquals(
"{\n" +
" \"shouldBeFirst\": \"\",\n" +
Expand Down Expand Up @@ -1145,5 +1187,34 @@ abstract class ScriptClassContextBaseTest : PluginContextLightCodeInsightFixture
}

//endregion

//region tests of ScriptFieldContext

fun testIsEnumField() {
assertFalse(userInfoPsiClass.asClassContext().fields()[0].isEnumField())
assertTrue(userTypePsiClass.asClassContext().fields()[0].isEnumField())
}

fun testAsEnumField() {
assertNull(userInfoPsiClass.asClassContext().fields()[0].asEnumField())
run {
val enumField = userTypePsiClass.asClassContext().fields()[0].asEnumField()
assertNotNull(enumField)
enumField!!
assertEquals(0, enumField.ordinal())
assertEquals(mapOf("type" to 1, "desc" to "ADMINISTRATION"), enumField.getParams())
assertEquals("ADMINISTRATION", enumField.getParam("desc"))
}
run {
val enumField = userTypePsiClass.asClassContext().fields()[1].asEnumField()
assertNotNull(enumField)
enumField!!
assertEquals(1, enumField.ordinal())
assertEquals(mapOf("type" to 2, "desc" to "MEMBER"), enumField.getParams())
assertEquals("MEMBER", enumField.getParam("desc"))
}
}

//endregion
}

0 comments on commit 8593919

Please sign in to comment.