| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.refactoring.util; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.psi.*; |
| import com.intellij.psi.codeStyle.CodeStyleManager; |
| import com.intellij.psi.util.InheritanceUtil; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.psi.util.PsiUtil; |
| import com.intellij.util.IncorrectOperationException; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| public class RefactoringChangeUtil { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.util.ChangeUtil"); |
| |
| @Nullable |
| private static String getMethodExpressionName(@Nullable PsiElement element) { |
| if (!(element instanceof PsiMethodCallExpression)) return null; |
| PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)element).getMethodExpression(); |
| return methodExpression.getReferenceName(); |
| } |
| |
| public static boolean isSuperOrThisMethodCall(@Nullable PsiElement element) { |
| String name = getMethodExpressionName(element); |
| return PsiKeyword.SUPER.equals(name) || PsiKeyword.THIS.equals(name); |
| } |
| |
| public static boolean isSuperMethodCall(@Nullable PsiElement element) { |
| String name = getMethodExpressionName(element); |
| return PsiKeyword.SUPER.equals(name); |
| } |
| |
| public static PsiType getTypeByExpression(PsiExpression expr) { |
| PsiType type = expr.getType(); |
| if (type == null) { |
| if (expr instanceof PsiArrayInitializerExpression) { |
| PsiExpression[] initializers = ((PsiArrayInitializerExpression)expr).getInitializers(); |
| if (initializers.length > 0) { |
| PsiType initType = getTypeByExpression(initializers[0]); |
| if (initType == null) return null; |
| return initType.createArrayType(); |
| } |
| } |
| |
| if (expr instanceof PsiReferenceExpression && PsiUtil.isOnAssignmentLeftHand(expr)) { |
| return getTypeByExpression(((PsiAssignmentExpression)expr.getParent()).getRExpression()); |
| } |
| return null; |
| } |
| PsiClass refClass = PsiUtil.resolveClassInType(type); |
| if (refClass instanceof PsiAnonymousClass) { |
| type = ((PsiAnonymousClass)refClass).getBaseClassType(); |
| } |
| |
| return GenericsUtil.getVariableTypeByExpressionType(type); |
| } |
| |
| public static PsiReferenceExpression qualifyReference(@NotNull PsiReferenceExpression referenceExpression, |
| @NotNull PsiMember member, |
| @Nullable final PsiClass qualifyingClass) throws IncorrectOperationException { |
| PsiManager manager = referenceExpression.getManager(); |
| PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(referenceExpression, PsiMethodCallExpression.class, true); |
| while (methodCallExpression != null) { |
| if (isSuperOrThisMethodCall(methodCallExpression)) { |
| return referenceExpression; |
| } |
| methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression.class, true); |
| } |
| PsiReferenceExpression expressionFromText; |
| final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); |
| if (qualifyingClass == null) { |
| PsiClass parentClass = PsiTreeUtil.getParentOfType(referenceExpression, PsiClass.class); |
| final PsiClass containingClass = member.getContainingClass(); |
| if (parentClass != null && !InheritanceUtil.isInheritorOrSelf(parentClass, containingClass, true)) { |
| while (parentClass != null && !InheritanceUtil.isInheritorOrSelf(parentClass, containingClass, true)) { |
| parentClass = PsiTreeUtil.getParentOfType(parentClass, PsiClass.class, true); |
| } |
| LOG.assertTrue(parentClass != null); |
| expressionFromText = (PsiReferenceExpression)factory.createExpressionFromText("A.this." + member.getName(), null); |
| ((PsiThisExpression)expressionFromText.getQualifierExpression()).getQualifier().replace(factory.createClassReferenceElement(parentClass)); |
| } |
| else { |
| expressionFromText = (PsiReferenceExpression)factory.createExpressionFromText("this." + member.getName(), null); |
| } |
| } |
| else { |
| expressionFromText = (PsiReferenceExpression)factory.createExpressionFromText("A." + member.getName(), null); |
| expressionFromText.setQualifierExpression(factory.createReferenceExpression(qualifyingClass)); |
| } |
| CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject()); |
| expressionFromText = (PsiReferenceExpression)codeStyleManager.reformat(expressionFromText); |
| return (PsiReferenceExpression)referenceExpression.replace(expressionFromText); |
| } |
| |
| public static PsiClass getThisClass(@NotNull PsiElement place) { |
| PsiElement parent = place.getContext(); |
| if (parent == null) return null; |
| PsiElement prev = null; |
| while (true) { |
| if (parent instanceof PsiClass) { |
| if (!(parent instanceof PsiAnonymousClass && ((PsiAnonymousClass)parent).getArgumentList() == prev)) { |
| return (PsiClass)parent; |
| } |
| } |
| prev = parent; |
| parent = parent.getContext(); |
| if (parent == null) return null; |
| } |
| } |
| |
| static <T extends PsiQualifiedExpression> T createQualifiedExpression(@NotNull PsiManager manager, |
| PsiClass qualifierClass, |
| @NotNull String qName) throws IncorrectOperationException { |
| PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); |
| if (qualifierClass != null) { |
| T qualifiedThis = (T)factory.createExpressionFromText("q." + qName, null); |
| qualifiedThis = (T)CodeStyleManager.getInstance(manager.getProject()).reformat(qualifiedThis); |
| PsiJavaCodeReferenceElement thisQualifier = qualifiedThis.getQualifier(); |
| LOG.assertTrue(thisQualifier != null); |
| thisQualifier.bindToElement(qualifierClass); |
| return qualifiedThis; |
| } |
| else { |
| return (T)factory.createExpressionFromText(qName, null); |
| } |
| } |
| |
| public static PsiThisExpression createThisExpression(PsiManager manager, PsiClass qualifierClass) throws IncorrectOperationException { |
| return RefactoringChangeUtil.<PsiThisExpression>createQualifiedExpression(manager, qualifierClass, "this"); |
| } |
| |
| public static PsiSuperExpression createSuperExpression(PsiManager manager, PsiClass qualifierClass) throws IncorrectOperationException { |
| return RefactoringChangeUtil.<PsiSuperExpression>createQualifiedExpression(manager, qualifierClass, "super"); |
| } |
| } |