psi过滤直接用JavaRecursiveElementVisitor过滤PsiMethodCallExpression会发现只识别到了collect的调用
因为JavaRecursiveElementVisitor的逻辑是当一个节点满足要求后,下一个继续的节点是nextSibing
0 1 2 3 4 5 6 7 8 9 |
//com/intellij/psi/impl/source/tree/CompositePsiElement.java:62 @Override public void acceptChildren(@NotNull PsiElementVisitor visitor) { PsiElement child = getFirstChild(); while (child != null) { child.accept(visitor); child = child.getNextSibling(); } } |
因此需要增加特殊逻辑,当第一层PsiMethodCallExpression被匹配到后,需要递归在PsiReferenceExpression继续寻找,需要把PsiReferenceExpression+PsiReferenceParameterList中的lamda表达式以及其中的方法调用和方法引用都找出来,这里只写方法调用,方法引用也是一样的套路
不知道jetbrains有没有类似的工具类做这种深度搜索,代码太多了懒得看,就先这么写着,附语义树如下
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
PsiMethodCallExpression:stringList.stream() .map(Main::function2) .map(v -> main.function3(v)) .map(main::function3) .collect(Collectors.toSet())(342,527) PsiReferenceExpression:stringList.stream() .map(Main::function2) .map(v -> main.function3(v)) .map(main::function3) .collect(342,507) PsiMethodCallExpression:stringList.stream() .map(Main::function2) .map(v -> main.function3(v)) .map(main::function3)(342,482) PsiReferenceExpression:stringList.stream() .map(Main::function2) .map(v -> main.function3(v)) .map(342,465) PsiMethodCallExpression:stringList.stream() .map(Main::function2) .map(v -> main.function3(v))(342,444) PsiReferenceExpression:stringList.stream() .map(Main::function2) .map(342,420) PsiMethodCallExpression:stringList.stream() .map(Main::function2)(342,399) PsiReferenceExpression:stringList.stream() .map(342,382) PsiMethodCallExpression:stringList.stream()(342,361) PsiReferenceExpression:stringList.stream(342,359) PsiReferenceExpression:stringList(342,352) PsiReferenceParameterList(342,342) <empty list> PsiIdentifier:stringList('stringList')(342,352) PsiJavaToken:DOT('.')(352,353) PsiReferenceParameterList(353,353) <empty list> PsiIdentifier:stream('stream')(353,359) PsiExpressionList(359,361) PsiJavaToken:LPARENTH('(')(359,360) PsiJavaToken:RPARENTH(')')(360,361) PsiWhiteSpace('\n ')(361,378) PsiJavaToken:DOT('.')(378,379) PsiReferenceParameterList(379,379) <empty list> PsiIdentifier:map('map')(379,382) PsiExpressionList(382,399) PsiJavaToken:LPARENTH('(')(382,383) PsiMethodReferenceExpression(383,398) PsiReferenceExpression:Main(383,387) PsiReferenceParameterList(383,383) <empty list> PsiIdentifier:Main('Main')(383,387) PsiJavaToken:DOUBLE_COLON('::')(387,389) PsiReferenceParameterList(389,389) <empty list> PsiIdentifier:function2('function2')(389,398) PsiJavaToken:RPARENTH(')')(398,399) PsiWhiteSpace('\n ')(399,416) PsiJavaToken:DOT('.')(416,417) PsiReferenceParameterList(417,417) <empty list> PsiIdentifier:map('map')(417,420) PsiExpressionList(420,444) PsiJavaToken:LPARENTH('(')(420,421) PsiLambdaExpression(421,443) PsiParameterList:v(421,422) PsiParameter:v(421,422) PsiModifierList:(421,421) <empty list> PsiIdentifier:v('v')(421,422) PsiWhiteSpace(' ')(422,423) PsiJavaToken:ARROW('->')(423,425) PsiWhiteSpace(' ')(425,426) PsiMethodCallExpression:main.function3(v)(426,443) PsiReferenceExpression:main.function3(426,440) PsiReferenceExpression:main(426,430) PsiReferenceParameterList(426,426) <empty list> PsiIdentifier:main('main')(426,430) PsiJavaToken:DOT('.')(430,431) PsiReferenceParameterList(431,431) <empty list> PsiIdentifier:function3('function3')(431,440) PsiExpressionList(440,443) PsiJavaToken:LPARENTH('(')(440,441) PsiReferenceExpression:v(441,442) PsiReferenceParameterList(441,441) <empty list> PsiIdentifier:v('v')(441,442) PsiJavaToken:RPARENTH(')')(442,443) PsiJavaToken:RPARENTH(')')(443,444) PsiWhiteSpace('\n ')(444,461) PsiJavaToken:DOT('.')(461,462) PsiReferenceParameterList(462,462) <empty list> PsiIdentifier:map('map')(462,465) PsiExpressionList(465,482) PsiJavaToken:LPARENTH('(')(465,466) PsiMethodReferenceExpression(466,481) PsiReferenceExpression:main(466,470) PsiReferenceParameterList(466,466) <empty list> PsiIdentifier:main('main')(466,470) PsiJavaToken:DOUBLE_COLON('::')(470,472) PsiReferenceParameterList(472,472) <empty list> PsiIdentifier:function3('function3')(472,481) PsiJavaToken:RPARENTH(')')(481,482) PsiWhiteSpace('\n ')(482,499) PsiJavaToken:DOT('.')(499,500) PsiReferenceParameterList(500,500) <empty list> PsiIdentifier:collect('collect')(500,507) PsiExpressionList(507,527) PsiJavaToken:LPARENTH('(')(507,508) PsiMethodCallExpression:Collectors.toSet()(508,526) PsiReferenceExpression:Collectors.toSet(508,524) PsiReferenceExpression:Collectors(508,518) PsiReferenceParameterList(508,508) <empty list> PsiIdentifier:Collectors('Collectors')(508,518) PsiJavaToken:DOT('.')(518,519) PsiReferenceParameterList(519,519) <empty list> PsiIdentifier:toSet('toSet')(519,524) PsiExpressionList(524,526) PsiJavaToken:LPARENTH('(')(524,525) PsiJavaToken:RPARENTH(')')(525,526) PsiJavaToken:RPARENTH(')')(526,527) PsiJavaToken:SEMICOLON(';')(527,528) |
完整代码,更新中
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
// Copyright 2000-2022 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.intellij.sdk.psi; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ui.Messages; import com.intellij.psi.*; public class PsiNavigationDemoAction extends AnAction { @Override public void actionPerformed(AnActionEvent anActionEvent) { Editor editor = anActionEvent.getData(CommonDataKeys.EDITOR); PsiFile psiFile = anActionEvent.getData(CommonDataKeys.PSI_FILE); if (editor == null || psiFile == null) { return; } int offset = editor.getCaretModel().getOffset(); final StringBuilder infoBuilder = new StringBuilder(); psiFile.accept(new JavaRecursiveElementVisitor() { @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { infoBuilder.append("visit method call:" + expression.getText()).append("\n"); recursiveFindMethodCallInReferenceAndArgs(expression, infoBuilder); } }); Messages.showMessageDialog(anActionEvent.getProject(), infoBuilder.toString(), "PSI Info", null); } // class Holder { // boolean hasMethodCallInReference = false; // boolean hasMethodCallInArgs = false; // } private void recursiveFindMethodCallInReferenceAndArgs(PsiMethodCallExpression expression, StringBuilder infoBuilder) { if (expression == null) { return; } PsiReferenceExpression referenceExpression = expression.getMethodExpression(); // Holder holder = new Holder(); referenceExpression.accept(new JavaRecursiveElementVisitor() { @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { // holder.hasMethodCallInReference = true; infoBuilder.append("visit method call:" + expression.getText()).append("\n"); recursiveFindMethodCallInReferenceAndArgs(expression, infoBuilder); } }); PsiExpressionList argumentList = expression.getArgumentList(); argumentList.accept(new JavaRecursiveElementVisitor() { @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { // holder.hasMethodCallInArgs = true; infoBuilder.append("visit method call:" + expression.getText()).append("\n"); recursiveFindMethodCallInReferenceAndArgs(expression, infoBuilder); } }); } @Override public void update(AnActionEvent e) { Editor editor = e.getData(CommonDataKeys.EDITOR); PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE); e.getPresentation().setEnabled(editor != null && psiFile != null); } } |
0 Comments