| /* |
| * Copyright 2000-2009 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.anonymousToInner; |
| |
| import com.intellij.codeInsight.ChangeContextUtil; |
| import com.intellij.openapi.actionSystem.CommonDataKeys; |
| import com.intellij.openapi.actionSystem.DataContext; |
| import com.intellij.openapi.actionSystem.PlatformDataKeys; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.command.CommandProcessor; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.openapi.editor.ScrollType; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.psi.*; |
| import com.intellij.psi.codeStyle.CodeStyleManager; |
| import com.intellij.psi.impl.PsiDiamondTypeUtil; |
| import com.intellij.psi.search.LocalSearchScope; |
| import com.intellij.psi.search.searches.ReferencesSearch; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.psi.util.PsiUtil; |
| import com.intellij.refactoring.HelpID; |
| import com.intellij.refactoring.RefactoringActionHandler; |
| import com.intellij.refactoring.RefactoringBundle; |
| import com.intellij.refactoring.util.CommonRefactoringUtil; |
| import com.intellij.refactoring.util.classMembers.ElementNeedsThis; |
| import com.intellij.util.IncorrectOperationException; |
| import com.intellij.psi.util.FileTypeUtils; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.*; |
| |
| public class AnonymousToInnerHandler implements RefactoringActionHandler { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.anonymousToInner.AnonymousToInnerHandler"); |
| |
| static final String REFACTORING_NAME = RefactoringBundle.message("anonymousToInner.refactoring.name"); |
| |
| private Project myProject; |
| |
| private PsiManager myManager; |
| |
| private PsiAnonymousClass myAnonClass; |
| private PsiClass myTargetClass; |
| protected String myNewClassName; |
| |
| private VariableInfo[] myVariableInfos; |
| protected boolean myMakeStatic; |
| private final Set<PsiTypeParameter> myTypeParametersToCreate = new LinkedHashSet<PsiTypeParameter>(); |
| |
| public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { |
| if (elements.length == 1 && elements[0] instanceof PsiAnonymousClass) { |
| invoke(project, CommonDataKeys.EDITOR.getData(dataContext), (PsiAnonymousClass)elements[0]); |
| } |
| } |
| |
| public void invoke(@NotNull final Project project, Editor editor, final PsiFile file, DataContext dataContext) { |
| if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) return; |
| |
| final int offset = editor.getCaretModel().getOffset(); |
| editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); |
| final PsiAnonymousClass anonymousClass = findAnonymousClass(file, offset); |
| if (anonymousClass == null) { |
| showErrorMessage(editor, RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("error.wrong.caret.position.anonymous"))); |
| return; |
| } |
| final PsiElement parent = anonymousClass.getParent(); |
| if (parent instanceof PsiEnumConstant) { |
| showErrorMessage(editor, RefactoringBundle.getCannotRefactorMessage("Enum constant can't be converted to inner class")); |
| return; |
| } |
| invoke(project, editor, anonymousClass); |
| } |
| |
| private void showErrorMessage(Editor editor, String message) { |
| CommonRefactoringUtil.showErrorHint(myProject, editor, message, REFACTORING_NAME, HelpID.ANONYMOUS_TO_INNER); |
| } |
| |
| public void invoke(final Project project, Editor editor, final PsiAnonymousClass anonymousClass) { |
| myProject = project; |
| |
| myManager = PsiManager.getInstance(myProject); |
| myAnonClass = anonymousClass; |
| |
| PsiClassType baseRef = myAnonClass.getBaseClassType(); |
| |
| if (baseRef.resolve() == null) { |
| String message = RefactoringBundle.message("error.cannot.resolve", baseRef.getCanonicalText()); |
| showErrorMessage(editor, message); |
| return; |
| } |
| PsiElement targetContainer = findTargetContainer(myAnonClass); |
| if (FileTypeUtils.isInServerPageFile(targetContainer) && targetContainer instanceof PsiFile) { |
| String message = RefactoringBundle.message("error.not.supported.for.jsp", REFACTORING_NAME); |
| showErrorMessage(editor, message); |
| return; |
| } |
| LOG.assertTrue(targetContainer instanceof PsiClass); |
| myTargetClass = (PsiClass) targetContainer; |
| |
| if (!CommonRefactoringUtil.checkReadOnlyStatus(project, myTargetClass)) return; |
| |
| Map<PsiVariable,VariableInfo> variableInfoMap = new LinkedHashMap<PsiVariable, VariableInfo>(); |
| collectUsedVariables(variableInfoMap, myAnonClass); |
| myVariableInfos = variableInfoMap.values().toArray(new VariableInfo[variableInfoMap.values().size()]); |
| if (!showRefactoringDialog()) return; |
| |
| CommandProcessor.getInstance().executeCommand( |
| myProject, new Runnable() { |
| public void run() { |
| final Runnable action = new Runnable() { |
| public void run() { |
| try { |
| doRefactoring(); |
| } catch (IncorrectOperationException e) { |
| LOG.error(e); |
| } |
| } |
| }; |
| ApplicationManager.getApplication().runWriteAction(action); |
| } |
| }, |
| REFACTORING_NAME, |
| null |
| ); |
| |
| } |
| |
| protected boolean showRefactoringDialog() { |
| final boolean anInterface = myTargetClass.isInterface(); |
| final boolean needsThis = needsThis() || PsiUtil.isInnerClass(myTargetClass); |
| final AnonymousToInnerDialog dialog = new AnonymousToInnerDialog( |
| myProject, |
| myAnonClass, |
| myVariableInfos, |
| needsThis || anInterface); |
| dialog.show(); |
| if (!dialog.isOK()) { |
| return false; |
| } |
| myNewClassName = dialog.getClassName(); |
| myVariableInfos = dialog.getVariableInfos(); |
| myMakeStatic = !needsThis && (anInterface || dialog.isMakeStatic()); |
| return true; |
| } |
| |
| private void doRefactoring() throws IncorrectOperationException { |
| calculateTypeParametersToCreate(); |
| PsiClass aClass = createClass(myNewClassName); |
| myTargetClass.add(aClass); |
| |
| PsiNewExpression newExpr = (PsiNewExpression) myAnonClass.getParent(); |
| @NonNls StringBuffer buf = new StringBuffer(); |
| buf.append("new "); |
| buf.append(aClass.getName()); |
| if (!myTypeParametersToCreate.isEmpty()) { |
| buf.append("<"); |
| int idx = 0; |
| //noinspection ForLoopThatDoesntUseLoopVariable |
| for (Iterator<PsiTypeParameter> it = myTypeParametersToCreate.iterator(); it.hasNext(); idx++) { |
| if (idx > 0) buf.append(", "); |
| String typeParamName = it.next().getName(); |
| buf.append(typeParamName); |
| } |
| buf.append(">"); |
| } |
| buf.append("("); |
| boolean isFirstParameter = true; |
| for (VariableInfo info : myVariableInfos) { |
| if (info.passAsParameter) { |
| if (isFirstParameter) { |
| isFirstParameter = false; |
| } |
| else { |
| buf.append(","); |
| } |
| buf.append(info.variable.getName()); |
| } |
| } |
| buf.append(")"); |
| PsiNewExpression newClassExpression = |
| (PsiNewExpression)JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory().createExpressionFromText(buf.toString(), null); |
| newClassExpression = (PsiNewExpression)newExpr.replace(newClassExpression); |
| if (PsiDiamondTypeUtil.canCollapseToDiamond(newClassExpression, newClassExpression, newClassExpression.getType())) { |
| PsiDiamondTypeUtil.replaceExplicitWithDiamond(newClassExpression.getClassOrAnonymousClassReference().getParameterList()); |
| } |
| } |
| |
| @Nullable |
| public static PsiAnonymousClass findAnonymousClass(PsiFile file, int offset) { |
| PsiElement element = file.findElementAt(offset); |
| while (element != null) { |
| if (element instanceof PsiAnonymousClass) { |
| return (PsiAnonymousClass) element; |
| } |
| if (element instanceof PsiNewExpression) { |
| final PsiNewExpression newExpression = (PsiNewExpression)element; |
| if (newExpression.getAnonymousClass() != null) { |
| return newExpression.getAnonymousClass(); |
| } |
| } |
| element = element.getParent(); |
| } |
| return null; |
| } |
| |
| public static PsiElement findTargetContainer(PsiAnonymousClass anonClass) { |
| PsiElement parent = anonClass.getParent(); |
| while (true) { |
| if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) { |
| return parent; |
| } |
| if (parent instanceof PsiFile) { |
| return parent; |
| } |
| parent = parent.getParent(); |
| } |
| } |
| |
| private void collectUsedVariables(final Map<PsiVariable, VariableInfo> variableInfoMap, |
| PsiElement scope) { |
| scope.accept(new JavaRecursiveElementWalkingVisitor() { |
| @Override public void visitReferenceExpression(PsiReferenceExpression expression) { |
| if (expression.getQualifierExpression() == null) { |
| PsiElement refElement = expression.resolve(); |
| if (refElement instanceof PsiVariable && !(refElement instanceof PsiField)) { |
| PsiVariable var = (PsiVariable)refElement; |
| |
| final PsiClass containingClass = PsiTreeUtil.getParentOfType(var, PsiClass.class); |
| if (PsiTreeUtil.isAncestor(containingClass, myAnonClass, true)) { |
| saveVariable(variableInfoMap, var, expression); |
| } |
| } |
| } |
| super.visitReferenceExpression(expression); |
| } |
| }); |
| } |
| |
| private Boolean cachedNeedsThis = null; |
| public boolean needsThis() { |
| if(cachedNeedsThis == null) { |
| |
| ElementNeedsThis memberNeedsThis = new ElementNeedsThis(myTargetClass, myAnonClass); |
| myAnonClass.accept(memberNeedsThis); |
| class HasExplicitThis extends JavaRecursiveElementWalkingVisitor { |
| boolean hasExplicitThis = false; |
| @Override public void visitReferenceExpression(PsiReferenceExpression expression) { |
| } |
| |
| @Override public void visitThisExpression(PsiThisExpression expression) { |
| hasExplicitThis = true; |
| } |
| } |
| final HasExplicitThis hasExplicitThis = new HasExplicitThis(); |
| PsiExpressionList argList = myAnonClass.getArgumentList(); |
| if (argList != null) argList.accept(hasExplicitThis); |
| cachedNeedsThis = memberNeedsThis.usesMembers() || hasExplicitThis.hasExplicitThis; |
| } |
| return cachedNeedsThis.booleanValue(); |
| } |
| |
| |
| private void saveVariable(Map<PsiVariable, VariableInfo> variableInfoMap, |
| PsiVariable var, |
| PsiReferenceExpression usage) { |
| VariableInfo info = variableInfoMap.get(var); |
| if (info == null) { |
| info = new VariableInfo(var); |
| variableInfoMap.put(var, info); |
| } |
| info.saveInField |= !isUsedInInitializer(usage); |
| } |
| |
| private boolean isUsedInInitializer(PsiElement usage) { |
| PsiElement parent = usage.getParent(); |
| while (!myAnonClass.equals(parent)) { |
| if (parent instanceof PsiExpressionList) { |
| PsiExpressionList expressionList = (PsiExpressionList) parent; |
| if (myAnonClass.equals(expressionList.getParent())) { |
| return true; |
| } |
| } else if (parent instanceof PsiClassInitializer && myAnonClass.equals(((PsiClassInitializer)parent).getContainingClass())) { |
| //class initializers will be moved to constructor to be generated |
| return true; |
| } |
| parent = parent.getParent(); |
| } |
| return false; |
| } |
| |
| private PsiClass createClass(String name) throws IncorrectOperationException { |
| PsiElementFactory factory = JavaPsiFacade.getInstance(myAnonClass.getProject()).getElementFactory(); |
| CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(myProject); |
| final PsiNewExpression newExpression = (PsiNewExpression) myAnonClass.getParent(); |
| final PsiMethod superConstructor = newExpression.resolveConstructor(); |
| |
| PsiClass aClass = factory.createClass(name); |
| final PsiTypeParameterList typeParameterList = aClass.getTypeParameterList(); |
| LOG.assertTrue(typeParameterList != null); |
| for (PsiTypeParameter typeParameter : myTypeParametersToCreate) { |
| typeParameterList.add((typeParameter)); |
| } |
| |
| if (!myTargetClass.isInterface()) { |
| PsiUtil.setModifierProperty(aClass, PsiModifier.PRIVATE, true); |
| PsiModifierListOwner owner = PsiTreeUtil.getParentOfType(myAnonClass, PsiModifierListOwner.class); |
| if (owner != null && owner.hasModifierProperty(PsiModifier.STATIC)) { |
| PsiUtil.setModifierProperty(aClass, PsiModifier.STATIC, true); |
| } |
| } else { |
| PsiUtil.setModifierProperty(aClass, PsiModifier.PACKAGE_LOCAL, true); |
| } |
| PsiJavaCodeReferenceElement baseClassRef = myAnonClass.getBaseClassReference(); |
| PsiClass baseClass = (PsiClass)baseClassRef.resolve(); |
| if (baseClass == null || !CommonClassNames.JAVA_LANG_OBJECT.equals(baseClass.getQualifiedName())) { |
| PsiReferenceList refList = baseClass != null && baseClass.isInterface() ? |
| aClass.getImplementsList() : |
| aClass.getExtendsList(); |
| if (refList != null) refList.add(baseClassRef); |
| } |
| |
| renameReferences(myAnonClass); |
| copyClassBody(myAnonClass, aClass, myVariableInfos.length > 0); |
| |
| if (myVariableInfos.length > 0) { |
| createFields(aClass); |
| } |
| |
| PsiExpressionList argList = newExpression.getArgumentList(); |
| assert argList != null; |
| PsiExpression[] originalExpressions = argList.getExpressions(); |
| final PsiReferenceList superConstructorThrowsList = |
| superConstructor != null && superConstructor.getThrowsList().getReferencedTypes().length > 0 |
| ? superConstructor.getThrowsList() |
| : null; |
| if (myVariableInfos.length > 0 || originalExpressions.length > 0 || superConstructorThrowsList != null) { |
| PsiMethod constructor = factory.createConstructor(); |
| if (superConstructorThrowsList != null) { |
| constructor.getThrowsList().replace(superConstructorThrowsList); |
| } |
| if (originalExpressions.length > 0) { |
| createSuperStatement(constructor, originalExpressions); |
| } |
| if (myVariableInfos.length > 0) { |
| fillParameterList(constructor); |
| createAssignmentStatements(constructor); |
| |
| appendInitializers(constructor); |
| } |
| |
| constructor = (PsiMethod) codeStyleManager.reformat(constructor); |
| aClass.add(constructor); |
| } |
| |
| if (!needsThis() && myMakeStatic && !myTargetClass.isInterface()) { |
| PsiUtil.setModifierProperty(aClass, PsiModifier.STATIC, true); |
| } |
| PsiElement lastChild = aClass.getLastChild(); |
| if (lastChild instanceof PsiJavaToken && ((PsiJavaToken)lastChild).getTokenType() == JavaTokenType.SEMICOLON) { |
| lastChild.delete(); |
| } |
| |
| return aClass; |
| } |
| |
| private void appendInitializers(final PsiMethod constructor) throws IncorrectOperationException { |
| PsiCodeBlock constructorBody = constructor.getBody(); |
| assert constructorBody != null; |
| |
| List<PsiElement> toAdd = new ArrayList<PsiElement>(); |
| for (PsiClassInitializer initializer : myAnonClass.getInitializers()) { |
| if (!initializer.hasModifierProperty(PsiModifier.STATIC)) { |
| toAdd.add(initializer); |
| } |
| } |
| for (PsiField field : myAnonClass.getFields()) { |
| if (!field.hasModifierProperty(PsiModifier.STATIC) && field.getInitializer() != null) { |
| toAdd.add(field); |
| } |
| } |
| |
| Collections.sort(toAdd, new Comparator<PsiElement>() { |
| public int compare(PsiElement e1, PsiElement e2) { |
| return e1.getTextRange().getStartOffset() - e2.getTextRange().getStartOffset(); |
| } |
| }); |
| |
| for (PsiElement element : toAdd) { |
| if (element instanceof PsiClassInitializer) { |
| PsiClassInitializer initializer = (PsiClassInitializer) element; |
| final PsiCodeBlock initializerBody = initializer.getBody(); |
| PsiElement firstBodyElement = initializerBody.getFirstBodyElement(); |
| if (firstBodyElement != null) { |
| constructorBody.addRange(firstBodyElement, initializerBody.getLastBodyElement()); |
| } |
| } else { |
| PsiField field = (PsiField) element; |
| final PsiExpressionStatement statement = (PsiExpressionStatement)JavaPsiFacade.getInstance(myManager.getProject()) |
| .getElementFactory() |
| .createStatementFromText(field.getName() + "= 0;", null); |
| PsiExpression rightExpression = ((PsiAssignmentExpression) statement.getExpression()).getRExpression(); |
| assert rightExpression != null; |
| PsiExpression fieldInitializer = field.getInitializer(); |
| assert fieldInitializer != null; |
| rightExpression.replace(fieldInitializer); |
| constructorBody.add(statement); |
| } |
| } |
| } |
| |
| private static void copyClassBody(PsiClass sourceClass, |
| PsiClass targetClass, |
| boolean appendInitializersToConstructor) throws IncorrectOperationException { |
| PsiElement lbrace = sourceClass.getLBrace(); |
| PsiElement rbrace = sourceClass.getRBrace(); |
| if (lbrace != null) { |
| targetClass.addRange(lbrace.getNextSibling(), rbrace != null ? rbrace.getPrevSibling() : sourceClass.getLastChild()); |
| if (appendInitializersToConstructor) { //see SCR 41692 |
| final PsiClassInitializer[] initializers = targetClass.getInitializers(); |
| for (PsiClassInitializer initializer : initializers) { |
| if (!initializer.hasModifierProperty(PsiModifier.STATIC)) initializer.delete(); |
| } |
| final PsiField[] fields = targetClass.getFields(); |
| for (PsiField field : fields) { |
| PsiExpression initializer = field.getInitializer(); |
| if (!field.hasModifierProperty(PsiModifier.STATIC) && initializer != null) { |
| initializer.delete(); |
| } |
| } |
| } |
| } |
| } |
| |
| private void fillParameterList(PsiMethod constructor) throws IncorrectOperationException { |
| PsiElementFactory factory = JavaPsiFacade.getInstance(constructor.getProject()).getElementFactory(); |
| PsiParameterList parameterList = constructor.getParameterList(); |
| for (VariableInfo info : myVariableInfos) { |
| if (info.passAsParameter) { |
| parameterList.add(factory.createParameter(info.parameterName, info.variable.getType())); |
| } |
| } |
| } |
| |
| private void createFields(PsiClass aClass) throws IncorrectOperationException { |
| PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); |
| for (VariableInfo info : myVariableInfos) { |
| if (info.saveInField) { |
| PsiType type = info.variable.getType(); |
| if (type instanceof PsiEllipsisType) type = ((PsiEllipsisType)type).toArrayType(); |
| PsiField field = factory.createField(info.fieldName, type); |
| PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); |
| aClass.add(field); |
| } |
| } |
| } |
| |
| private void createAssignmentStatements(PsiMethod constructor) throws IncorrectOperationException { |
| PsiElementFactory factory = JavaPsiFacade.getInstance(constructor.getProject()).getElementFactory(); |
| for (VariableInfo info : myVariableInfos) { |
| if (info.saveInField) { |
| @NonNls String text = info.fieldName + "=a;"; |
| boolean useThis = info.passAsParameter && info.parameterName.equals(info.fieldName); |
| if (useThis) { |
| text = "this." + text; |
| } |
| PsiExpressionStatement statement = (PsiExpressionStatement)factory.createStatementFromText(text, null); |
| statement = (PsiExpressionStatement)CodeStyleManager.getInstance(myProject).reformat(statement); |
| // in order for "..." trick to work, the statement must be added to constructor first |
| PsiCodeBlock constructorBody = constructor.getBody(); |
| assert constructorBody != null; |
| statement = (PsiExpressionStatement)constructorBody.add(statement); |
| |
| PsiAssignmentExpression assignment = (PsiAssignmentExpression)statement.getExpression(); |
| PsiReferenceExpression rExpr = (PsiReferenceExpression)assignment.getRExpression(); |
| assert rExpr != null; |
| if (info.passAsParameter) { |
| rExpr.replace(factory.createExpressionFromText(info.parameterName, null)); |
| } |
| else { |
| rExpr.delete(); |
| } |
| } |
| } |
| } |
| |
| private void renameReferences(PsiElement scope) throws IncorrectOperationException { |
| PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory(); |
| for (VariableInfo info : myVariableInfos) { |
| for (PsiReference reference : ReferencesSearch.search(info.variable, new LocalSearchScope(scope))) { |
| PsiElement ref = reference.getElement(); |
| PsiIdentifier identifier = (PsiIdentifier)((PsiJavaCodeReferenceElement)ref).getReferenceNameElement(); |
| assert identifier != null; |
| boolean renameToFieldName = !isUsedInInitializer(ref); |
| PsiIdentifier newNameIdentifier = factory.createIdentifier(renameToFieldName ? info.fieldName : info.parameterName); |
| if (renameToFieldName) { |
| identifier.replace(newNameIdentifier); |
| } |
| else { |
| if (info.passAsParameter) { |
| identifier.replace(newNameIdentifier); |
| } |
| } |
| } |
| } |
| } |
| |
| private void createSuperStatement(PsiMethod constructor, PsiExpression[] paramExpressions) throws IncorrectOperationException { |
| PsiCodeBlock body = constructor.getBody(); |
| assert body != null; |
| final PsiElementFactory factory = JavaPsiFacade.getInstance(constructor.getProject()).getElementFactory(); |
| |
| PsiStatement statement = factory.createStatementFromText("super();", null); |
| statement = (PsiStatement) CodeStyleManager.getInstance(myProject).reformat(statement); |
| statement = (PsiStatement) body.add(statement); |
| |
| PsiMethodCallExpression methodCall = (PsiMethodCallExpression) ((PsiExpressionStatement) statement).getExpression(); |
| PsiExpressionList exprList = methodCall.getArgumentList(); |
| |
| |
| { |
| final PsiThisExpression qualifiedThis = |
| (PsiThisExpression) factory.createExpressionFromText("A.this", null); |
| final PsiJavaCodeReferenceElement targetClassRef = factory.createClassReferenceElement(myTargetClass); |
| PsiJavaCodeReferenceElement thisQualifier = qualifiedThis.getQualifier(); |
| assert thisQualifier != null; |
| thisQualifier.replace(targetClassRef); |
| |
| for (PsiExpression expr : paramExpressions) { |
| ChangeContextUtil.encodeContextInfo(expr, true); |
| final PsiElement newExpr = exprList.add(expr); |
| ChangeContextUtil.decodeContextInfo(newExpr, myTargetClass, qualifiedThis); |
| } |
| } |
| |
| class SupersConvertor extends JavaRecursiveElementVisitor { |
| @Override public void visitThisExpression(PsiThisExpression expression) { |
| try { |
| final PsiThisExpression qualifiedThis = |
| (PsiThisExpression) factory.createExpressionFromText("A.this", null); |
| final PsiJavaCodeReferenceElement targetClassRef = factory.createClassReferenceElement(myTargetClass); |
| PsiJavaCodeReferenceElement thisQualifier = qualifiedThis.getQualifier(); |
| assert thisQualifier != null; |
| thisQualifier.replace(targetClassRef); |
| expression.replace(qualifiedThis); |
| } catch (IncorrectOperationException e) { |
| LOG.error(e); |
| } |
| } |
| |
| @Override public void visitReferenceExpression(PsiReferenceExpression expression) { |
| } |
| } |
| |
| final SupersConvertor supersConvertor = new SupersConvertor(); |
| methodCall.getArgumentList().accept(supersConvertor); |
| } |
| |
| private void calculateTypeParametersToCreate () { |
| myAnonClass.accept(new JavaRecursiveElementWalkingVisitor() { |
| @Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { |
| super.visitReferenceElement(reference); |
| final PsiElement resolved = reference.resolve(); |
| if (resolved instanceof PsiTypeParameter) { |
| final PsiTypeParameterListOwner owner = ((PsiTypeParameter)resolved).getOwner(); |
| if (owner != null && !PsiTreeUtil.isAncestor(myAnonClass, owner, false)) { |
| myTypeParametersToCreate.add((PsiTypeParameter)resolved); |
| } |
| } |
| } |
| }); |
| } |
| } |