下面列出了怎么用com.intellij.psi.PsiReferenceExpression的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* If element is a {@link PsiStatement} with {@code Component.create()} call, finds missing
* required props for it.
*
* @param element element to verify
* @param errorHandler handles a list of missing required props and reference to the {@code
* Component.create()} call in the statement
* @param generatedClassResolver returns generated Litho class, or null if the provided method
* doesn't belong to any
*/
static void annotate(
PsiElement element,
BiConsumer<Collection<String>, PsiReferenceExpression> errorHandler,
Function<PsiMethodCallExpression, PsiClass> generatedClassResolver) {
if (element instanceof PsiDeclarationStatement) {
Arrays.stream(((PsiDeclarationStatement) element).getDeclaredElements())
.filter(PsiVariable.class::isInstance)
.map(declaredVariable -> ((PsiVariable) declaredVariable).getInitializer())
.forEach(
expression -> handleIfMethodCall(expression, errorHandler, generatedClassResolver));
} else if (element instanceof PsiExpressionStatement) {
handleIfMethodCall(
((PsiExpressionStatement) element).getExpression(), errorHandler, generatedClassResolver);
} else if (element instanceof PsiReturnStatement) {
handleIfMethodCall(
((PsiReturnStatement) element).getReturnValue(), errorHandler, generatedClassResolver);
}
}
private Object invoke(Method method, Object[] args) throws IllegalAccessException {
Class<?> returnType = method.getReturnType();
if (returnType.isEnum()) {
PsiAnnotation currentAnnotation =
AnnotationUtil.findAnnotationInHierarchy(
mListOwner, Collections.singleton(mAnnotationClass.getCanonicalName()));
PsiReferenceExpression declaredValue =
(PsiReferenceExpression) currentAnnotation.findAttributeValue(method.getName());
if (declaredValue == null) {
return method.getDefaultValue();
}
PsiIdentifier identifier = PsiTreeUtil.getChildOfType(declaredValue, PsiIdentifier.class);
return Enum.valueOf((Class<Enum>) returnType, identifier.getText());
}
try {
if (args == null) {
return method.invoke(mStubbed);
}
return method.invoke(mStubbed, args);
} catch (InvocationTargetException e) {
return method.getDefaultValue();
}
}
/** Checks if `expression` matches an expected R.abc.xyz pattern. */
private static boolean isResourceExpression(PsiElement expression) {
if (!(expression instanceof PsiQualifiedReferenceElement)) {
return false;
}
PsiQualifiedReferenceElement qualifiedExpression = (PsiQualifiedReferenceElement) expression;
// qualifier should be `R.abc` which is also a `PsiReferenceExpression`
PsiElement qualifier = qualifiedExpression.getQualifier();
if (!(qualifier instanceof PsiReferenceExpression)) {
return false;
}
PsiReferenceExpression qualifierExpression = (PsiReferenceExpression) qualifier;
// rClassExpression should be `R`
PsiElement rClassExpression = qualifierExpression.getQualifier();
// rTypeExpression should be `abc`
String rType = qualifierExpression.getReferenceName();
return rClassExpression != null
&& rType != null
&& SdkConstants.R_CLASS.equals(rClassExpression.getText())
&& ResourceType.fromClassName(rType) != null;
}
public final boolean value( PsiFile psiFile )
{
final boolean[] hasPolygeneImportPackage = new boolean[]{ false };
psiFile.accept( new JavaElementVisitor()
{
@Override
public final void visitImportStatement( PsiImportStatement statement )
{
String packageName = statement.getQualifiedName();
if( packageName != null && packageName.startsWith( "org.apache.polygene" ) )
{
hasPolygeneImportPackage[ 0 ] = true;
}
}
@Override
public void visitReferenceExpression( PsiReferenceExpression expression )
{
// Ignore
}
} );
return hasPolygeneImportPackage[ 0 ];
}
public static boolean isInitializedInConstructors(@NotNull PsiElement element) {
if (!(element instanceof PsiIdentifier)) {
return false;
}
PsiElement parent = element.getParent();
if (!(parent instanceof PsiReferenceExpression)) {
return false;
}
PsiElement qualifier = ((PsiReferenceExpression) parent).getQualifier();
if (qualifier == null) {
return false;
}
PsiReference reference = qualifier.getReference();
if (reference == null) {
return false;
}
PsiElement field = reference.resolve();
if (!(field instanceof PsiField)) {
return false;
}
PsiClass containingClass = ((PsiField) field).getContainingClass();
if (containingClass == null) {
return false;
}
return isInitializedInConstructors((PsiField) field, containingClass);
}
public static PsiField getReferencedField(final PsiElement element) {
if (!(element instanceof PsiReferenceExpression)) {
return null;
}
final PsiElement referenced = ((PsiReferenceExpression) element).resolve();
return referenced instanceof PsiField ? (PsiField) referenced : null;
}
@Nullable
@Override
public LineMarkerInfo getLineMarkerInfo(PsiElement element) {
final List<PsiReferenceExpression> methodCalls = new ArrayList<>();
final List<Collection<String>> missingPropNames = new ArrayList<>();
// One annotation per statement
RequiredPropAnnotator.annotate(
element,
(missingRequiredPropNames, createMethodCall) -> {
methodCalls.add(createMethodCall);
missingPropNames.add(missingRequiredPropNames);
},
generatedClassResolver);
if (methodCalls.isEmpty()) {
return null;
}
PsiElement leaf = methodCalls.get(0);
final Collection<String> missingProps = missingPropNames.get(0);
while (leaf.getFirstChild() != null) {
leaf = leaf.getFirstChild();
}
return new LineMarkerInfo<>(
leaf,
leaf.getTextRange(),
LithoPluginIcons.ERROR_ACTION,
0,
ignored -> RequiredPropAnnotator.createErrorMessage(missingProps),
null,
GutterIconRenderer.Alignment.CENTER);
}
private static void handleIfMethodCall(
@Nullable PsiExpression expression,
BiConsumer<Collection<String>, PsiReferenceExpression> errorHandler,
Function<PsiMethodCallExpression, PsiClass> generatedClassResolver) {
if (expression instanceof PsiMethodCallExpression) {
PsiMethodCallExpression rootMethodCall = (PsiMethodCallExpression) expression;
handleMethodCall(rootMethodCall, new HashSet<>(), errorHandler, generatedClassResolver);
}
}
private static void handleMethodCall(
PsiMethodCallExpression currentMethodCall,
Set<String> methodNamesCalled,
BiConsumer<Collection<String>, PsiReferenceExpression> errorHandler,
Function<PsiMethodCallExpression, PsiClass> generatedClassResolver) {
PsiReferenceExpression methodExpression = currentMethodCall.getMethodExpression();
methodNamesCalled.add(methodExpression.getReferenceName());
// Assumption to find next method in a call chain
PsiMethodCallExpression nextMethodCall =
PsiTreeUtil.getChildOfType(methodExpression, PsiMethodCallExpression.class);
if (nextMethodCall != null) {
handleMethodCall(nextMethodCall, methodNamesCalled, errorHandler, generatedClassResolver);
} else if ("create".equals(methodExpression.getReferenceName())) {
// Finish call chain
// TODO T47712852: allow setting required prop in another statement
Optional.ofNullable(generatedClassResolver.apply(currentMethodCall))
.map(generatedCls -> collectMissingRequiredProps(generatedCls, methodNamesCalled))
.filter(result -> !result.isEmpty())
.ifPresent(
missingRequiredProps -> errorHandler.accept(missingRequiredProps, methodExpression));
}
PsiExpressionList argumentList = currentMethodCall.getArgumentList();
for (PsiExpression argument : argumentList.getExpressions()) {
handleIfMethodCall(argument, errorHandler, generatedClassResolver);
}
}
private void markLeakSuspects(PsiElement element, PsiElement lambdaBody, @NonNull final JavaContext context) {
if (element instanceof PsiReferenceExpression) {
PsiReferenceExpression ref = (PsiReferenceExpression) element;
if (ref.getQualifierExpression() == null) {
PsiElement res = ref.resolve();
if (!(res instanceof PsiParameter)) {
if (!(res instanceof PsiClass)) {
boolean error = false;
if (res instanceof PsiLocalVariable) {
PsiLocalVariable lVar = (PsiLocalVariable) res;
if (!isParent(lambdaBody, lVar.getParent())) {
error = true;
}
}
if (res instanceof PsiField) {
PsiField field = (PsiField) res;
final PsiModifierList modifierList = field.getModifierList();
if (modifierList == null) {
error = true;
} else if (!modifierList.hasExplicitModifier(PsiModifier.STATIC)) {
error = true;
}
}
if (error) {
context.report(ISSUE, element, context.getNameLocation(element), "Possible leak");
}
}
}
}
}
for (PsiElement psiElement : element.getChildren()) {
markLeakSuspects(psiElement, lambdaBody, context);
}
}
@Override
public PsiClass getBeanClass(PsiElement element) {
final PsiElement beanPsiElement = getPsiElementForCamelBeanMethod(element);
if (beanPsiElement != null) {
if (beanPsiElement instanceof PsiClass) {
return (PsiClass) beanPsiElement;
}
PsiJavaCodeReferenceElement referenceElement = PsiTreeUtil.findChildOfType(beanPsiElement, PsiJavaCodeReferenceElement.class);
final PsiClass psiClass = getJavaClassUtils().resolveClassReference(referenceElement);
if (psiClass != null && !JAVA_LANG_STRING.equals(psiClass.getQualifiedName())) {
return psiClass;
}
String beanName = "";
if (referenceElement instanceof PsiReferenceExpression) {
beanName = getStaticBeanName(referenceElement, beanName);
} else {
final String[] beanParameters = beanPsiElement.getText().replace("(", "").replace(")", "").split(",");
if (beanParameters.length > 0) {
beanName = StringUtils.stripDoubleQuotes(beanParameters[0]);
}
}
return searchForMatchingBeanClass(beanName, beanPsiElement.getProject()).orElse(null);
}
return null;
}
private String getStaticBeanName(PsiJavaCodeReferenceElement referenceElement, String beanName) {
final PsiType type = ((PsiReferenceExpression) referenceElement).getType();
if (type != null && JAVA_LANG_STRING.equals(type.getCanonicalText())) {
beanName = StringUtils.stripDoubleQuotes(PsiTreeUtil.getChildOfAnyType(referenceElement.getReference().resolve(), PsiLiteralExpression.class).getText());
}
return beanName;
}
public void testStartRouteWithVariableIdentifier() {
// caret is at start of rout in the test java file
PsiFile psiFile = myFixture.configureByText("DummyTestData.java", CODE_VAR_URI);
PsiVariable variable = myFixture.findElementByText("uri", PsiVariable.class);
PsiElement identifier = myFixture.findUsages(variable).iterator().next().getElement();
assertInstanceOf(identifier, PsiReferenceExpression.class);
assertTrue(getCamelIdeaUtils().isCamelRouteStart(identifier));
}
public void testStartRouteWithConstantIdentifier() {
// caret is at start of rout in the test java file
PsiFile psiFile = myFixture.configureByText("DummyTestData.java", CODE_CONST_URI);
PsiVariable variable = myFixture.findElementByText("URI", PsiVariable.class);
PsiElement identifier = myFixture.findUsages(variable).iterator().next().getElement();
assertInstanceOf(identifier, PsiReferenceExpression.class);
assertTrue(getCamelIdeaUtils().isCamelRouteStart(identifier));
}
private void visitExpression(final PsiElement element) {
if (element.getNode().getElementType().equals(JavaElementType.NEW_EXPRESSION)) {
visitPsiNewExpression((PsiNewExpression) element);
} else if (element.getNode().getElementType().
equals(JavaElementType.METHOD_CALL_EXPRESSION)) {
visitPsiMethodCallExpression((PsiMethodCallExpression) element);
} else if (element.getNode().getElementType().
equals(JavaElementType.ASSIGNMENT_EXPRESSION)) {
visitPsiAssignmentExpression((PsiAssignmentExpression) element);
} else if (element.getNode().getElementType().
equals(JavaElementType.REFERENCE_EXPRESSION)) {
visitPsiReferenceExpression((PsiReferenceExpression) element);
}
}
private void visitPsiReferenceExpression(final PsiReferenceExpression element) {
PsiExpression psiExpression = element.getQualifierExpression();
if (psiExpression != null) {
PsiType psiType = psiExpression.getType();
if (psiType != null) {
String qualifiedName = removeSpecialSymbols(psiType.getCanonicalText());
addInMap(qualifiedName, emptySet);
}
}
}
private Set<String> getMethods(final PsiReferenceExpression methodExpr) {
Set<String> methods = new HashSet<>();
if (WindowObjects.getInstance().isIncludeMethods()) {
PsiIdentifier[] identifiers =
PsiTreeUtil.getChildrenOfType(methodExpr, PsiIdentifier.class);
if (identifiers != null) {
for (PsiIdentifier identifier : identifiers) {
methods.add(identifier.getText());
}
}
}
return methods;
}
public static boolean isFieldReference(PsiElement expression) {
return expression instanceof PsiReferenceExpression;
}
public void setReference(PsiReferenceExpression reference) {
this.reference = toPointer(reference);
}
public PsiReferenceExpression getReference() {
PsiElement node = this.reference.getElement();
return (PsiReferenceExpression) node;
}
public boolean instanceOf(PsiExpression expression) {
return (expression instanceof PsiReferenceExpression &&
((PsiReferenceExpression) expression).resolve() instanceof PsiVariable);
}
private List<MoveMethodCandidateRefactoring> identifyConceptualBindings(MyMethod method, Set<String> targetClasses) {
SmartList<MoveMethodCandidateRefactoring> candidateRefactoringList = new SmartList<>();
MethodObject methodObject = method.getMethodObject();
String sourceClass = method.getClassOrigin();
for (String targetClass : targetClasses) {
if (!targetClass.equals(sourceClass)) {
ClassObject targetClassObject = system.getClass(targetClass).getClassObject();
ListIterator<ParameterObject> parameterIterator = methodObject.getParameterListIterator();
while (parameterIterator.hasNext()) {
ParameterObject parameter = parameterIterator.next();
Association association = system.containsAssociationWithMultiplicityBetweenClasses(targetClass, parameter.getType().getClassType());
if (association != null) {
List<MethodInvocationObject> methodInvocations = methodObject.getMethodInvocations();
for (MethodInvocationObject methodInvocation : methodInvocations) {
if (methodInvocation.getOriginClassName().equals(targetClass)) {
PsiMethodCallExpression invocation = methodInvocation.getMethodInvocation();
boolean parameterIsPassedAsArgument = false;
PsiExpression[] invocationArguments = invocation.getArgumentList().getExpressions();
for (PsiExpression expression : invocationArguments) {
if (expression instanceof PsiReferenceExpression) {
PsiReferenceExpression argumentName = (PsiReferenceExpression) expression;
if (parameter.getSingleVariableDeclaration().equals(argumentName.resolve()))
parameterIsPassedAsArgument = true;
}
}
if (parameterIsPassedAsArgument) {
MethodObject invokedMethod = targetClassObject.getMethod(methodInvocation);
if (invokedMethod != null) {
List<FieldInstructionObject> fieldInstructions = invokedMethod.getFieldInstructions();
boolean containerFieldIsAccessed = false;
for (FieldInstructionObject fieldInstruction : fieldInstructions) {
if (association.getFieldObject().equals(fieldInstruction)) {
containerFieldIsAccessed = true;
break;
}
}
if (containerFieldIsAccessed) {
MyClass mySourceClass = classList.get(classIndexMap.get(sourceClass));
MyClass myTargetClass = classList.get(classIndexMap.get(targetClass));
MoveMethodCandidateRefactoring candidate = new MoveMethodCandidateRefactoring(system, mySourceClass, myTargetClass, method);
Map<PsiMethodCallExpression, PsiMethod> additionalMethodsToBeMoved = candidate.getAdditionalMethodsToBeMoved();
Collection<PsiMethod> values = additionalMethodsToBeMoved.values();
Set<String> methodEntitySet = entityMap.get(method.toString());
Set<String> sourceClassEntitySet = classMap.get(sourceClass);
Set<String> targetClassEntitySet = classMap.get(targetClass);
Set<String> intersectionWithSourceClass = DistanceCalculator.intersection(methodEntitySet, sourceClassEntitySet);
Set<String> intersectionWithTargetClass = DistanceCalculator.intersection(methodEntitySet, targetClassEntitySet);
Set<String> entitiesToRemoveFromIntersectionWithSourceClass = new LinkedHashSet<>();
if (!values.isEmpty()) {
for (String s : intersectionWithSourceClass) {
int entityPosition = entityIndexMap.get(s);
Entity e = entityList.get(entityPosition);
if (e instanceof MyMethod) {
MyMethod myInvokedMethod = (MyMethod) e;
if (values.contains(myInvokedMethod.getMethodObject().getMethodDeclaration())) {
entitiesToRemoveFromIntersectionWithSourceClass.add(s);
}
}
}
intersectionWithSourceClass.removeAll(entitiesToRemoveFromIntersectionWithSourceClass);
}
if (intersectionWithTargetClass.size() >= intersectionWithSourceClass.size()) {
if (candidate.isApplicable()) {
int sourceClassDependencies = candidate.getDistinctSourceDependencies();
int targetClassDependencies = candidate.getDistinctTargetDependencies();
if (sourceClassDependencies <= maximumNumberOfSourceClassMembersAccessedByMoveMethodCandidate
&& sourceClassDependencies < targetClassDependencies) {
candidateRefactoringList.add(candidate);
}
}
}
}
}
}
}
}
}
}
}
}
return candidateRefactoringList;
}
@Nullable
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, final boolean onTheFly) {
return new PsiElementVisitor() {
public void visitReferenceExpression(PsiReferenceExpression psiReferenceExpression) {}
public void visitMethod(final PsiMethod psiMethod) {
if (onTheFly && psiMethod.getModifierList().hasModifierProperty(PsiModifier.NATIVE)) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (!psiMethod.isValid()) return;
final RangeHighlighter currentHighlighter = psiMethod.getUserData(myCurrentHighlighterKey);
Editor editor = CppSupportLoader.findEditor(psiMethod.getProject(), psiMethod.getContainingFile().getVirtualFile());
if (editor != null) {
if (currentHighlighter != null) editor.getMarkupModel().removeHighlighter(currentHighlighter);
int textOffset = psiMethod.getTextOffset();
RangeHighlighter rangeHighlighter = editor.getMarkupModel().addRangeHighlighter(
textOffset,
textOffset + psiMethod.getName().length(),
1,
null,
HighlighterTargetArea.EXACT_RANGE
);
rangeHighlighter.setGutterIconRenderer(
new IconableGutterNavigator(IconLoader.getIcon("/gutter/implementedMethod.png"),"implemented in native code") {
protected void doNavigate(Project project) {
final NativeMethod2JNIFunctionBinding binding = new NativeMethod2JNIFunctionBinding(psiMethod);
NavigationUtils.navigate(project, binding.getUsagesList());
}
}
);
psiMethod.putUserData(myCurrentHighlighterKey, rangeHighlighter);
}
}
});
}
}
};
}