What is the idiomatic way to use Pattern framework in platform/core-api/com.intellij.patterns?
I am looking for documentation and examples of idiomatic and efficient ways of using Pattern framework to check if a PsiElement fits a pattern.
For example, I'd like to check if the PsiElement corresponds to the invocation of java.lang.Object.equals method. I can do this using the following Kotlin code fragment.
val method = element.resolveMethod() ?: return false
val containingClass = method.containingClass ?: return false
val returnType = method.returnType ?: return false
val methodName = method.name
val parameters = method.parameterList.parameters
val returnTypeName = returnType.canonicalText
val containingClassFQN = containingClass.qualifiedName
if (containingClassFQN == "java.lang.Object" && methodName == "equals" && parameters.size == 1 &&
parameters[0].type.canonicalText == "java.lang.Object" && returnTypeName == "boolean") ....
I am wondering if and how can I do the above using the pattern framework. Specifically,
- Can we use patterns to perform all of the checks in the above conditional? If yes, how? [I am guessing it is not possible to match both syntactic and semantic information with the same pattern.]
- Can we use patterns to perform some of the checks in the above conditional? If yes, how? [I am guessing yes.]
- Can we construct patterns objects from a code fragment, e.g., "<java.lang.Object>.equals(<java.lang.Object>)"? If yes, how?
请先登录再写评论。
1 and 2: you can use
PsiJavaPatterns.psiExpression().methodCall(
psiMethod()
.withName("equals")
.definedInClass(CommonClassNames.JAVA_LANG_OBJECT))
3. No, that's not possible at the moment.
Thanks!! That works :)
After some searching, I believe PsiMethodPattern cannot be used to check for return type of methods. Am I right?
Yes, you're right. Patterns aren't supposed to be a substitution for everything, just for the most frequent checks (mostly syntactic).
Thanks for the confirmation.
If folks are interested in a PsiMethodPattern method to check for return type of methods, then here's the extension method in Kotlin.
fun PsiMethodPattern.withReturnType(returnType: String): PsiMethodPattern {
return with(object : PatternCondition<PsiMethod>("withReturnType") {
override fun accepts(psiMethod: PsiMethod, context: ProcessingContext): Boolean {
val text = with(TypeConversionUtil.erasure(psiMethod.returnType)) {
when {
this is PsiEllipsisType && returnType.endsWith("[]") ->
componentType.canonicalText + "[]"
this is PsiArrayType && returnType.endsWith("...") ->
componentType.canonicalText + "..."
else -> canonicalText
}
}
return returnType == text
}
})
}
You could also use PsiType.equalsToText
I adapted the code fragment from PsiMethod.withParameters[PatternCondition.typeEquivalent]. So, the code in withParameters has not been updated since PsiType.equalsToText has been added, right? Or am I missing something?
I see. Apparently the author of that code didn't think about using `equalsToText`. I'll clean that up.