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,

  1. 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.]
  2. Can we use patterns to perform some of the checks in the above conditional?  If yes, how?  [I am guessing yes.]
  3. Can we construct patterns objects from a code fragment, e.g., "<java.lang.Object>.equals(<java.lang.Object>)"?  If yes, how?
0
正式评论

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? 

0

Yes, you're right. Patterns aren't supposed to be a substitution for everything, just for the most frequent checks (mostly syntactic).

1

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
       }
    })
}

0

You could also use PsiType.equalsToText

0

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?

0

I see. Apparently the author of that code didn't think about using `equalsToText`. I'll clean that up.

0

请先登录再写评论。