| /* |
| * Copyright 2009 Bas Leijdekkers |
| * |
| * 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.siyeh.ipp.adapter; |
| |
| import com.siyeh.ipp.base.MutablyNamedIntention; |
| import com.siyeh.ipp.base.PsiElementPredicate; |
| import com.siyeh.IntentionPowerPackBundle; |
| import com.intellij.psi.*; |
| import com.intellij.psi.javadoc.PsiDocComment; |
| import com.intellij.psi.util.PsiUtil; |
| import com.intellij.psi.codeStyle.CodeStyleSettings; |
| import com.intellij.psi.codeStyle.CodeStyleSettingsManager; |
| import com.intellij.util.IncorrectOperationException; |
| import com.intellij.openapi.project.Project; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.List; |
| import java.util.ArrayList; |
| |
| public class AdapterToListenerIntention extends MutablyNamedIntention { |
| |
| @NotNull |
| @Override |
| protected PsiElementPredicate getElementPredicate() { |
| return new AdapterToListenerPredicate(); |
| } |
| |
| @Override |
| protected String getTextForElement(PsiElement element) { |
| final String text = element.getText(); |
| return IntentionPowerPackBundle.message( |
| "adapter.to.listener.intention.name", text); |
| } |
| |
| @Override |
| protected void processIntention(@NotNull PsiElement element) |
| throws IncorrectOperationException { |
| final PsiElement parent = element.getParent(); |
| final PsiElement grandParent = parent.getParent(); |
| if (!(grandParent instanceof PsiClass)) { |
| return; |
| } |
| final PsiClass aClass = (PsiClass)grandParent; |
| final PsiReferenceList extendsList = aClass.getExtendsList(); |
| if (extendsList == null) { |
| return; |
| } |
| final PsiJavaCodeReferenceElement[] extendsReferences = |
| extendsList.getReferenceElements(); |
| if (extendsReferences.length != 1) { |
| return; |
| } |
| final PsiJavaCodeReferenceElement extendsReference = |
| extendsReferences[0]; |
| final PsiElement target = extendsReference.resolve(); |
| if (!(target instanceof PsiClass)) { |
| return; |
| } |
| final PsiClass extendsClass = (PsiClass)target; |
| final PsiReferenceList implementsList = |
| extendsClass.getImplementsList(); |
| if (implementsList == null) { |
| return; |
| } |
| final PsiJavaCodeReferenceElement[] implementsReferences = |
| implementsList.getReferenceElements(); |
| final List<PsiJavaCodeReferenceElement> listenerReferences = |
| new ArrayList(); |
| for (PsiJavaCodeReferenceElement implementsReference : |
| implementsReferences) { |
| final String name = implementsReference.getReferenceName(); |
| if (name != null && !name.endsWith("Listener")) { |
| continue; |
| } |
| final PsiElement implementsTarget = implementsReference.resolve(); |
| if (!(implementsTarget instanceof PsiClass)) { |
| continue; |
| } |
| final PsiClass implementsClass = (PsiClass)implementsTarget; |
| if (!implementsClass.isInterface()) { |
| continue; |
| } |
| final PsiMethod[] methods = implementsClass.getMethods(); |
| for (PsiMethod method : methods) { |
| final PsiMethod overridingMethod = |
| aClass.findMethodBySignature(method, false); |
| if (overridingMethod == null) { |
| implementMethodInClass(method, aClass); |
| continue; |
| } |
| final PsiMethod[] superMethods = |
| overridingMethod.findSuperMethods(implementsClass); |
| for (PsiMethod superMethod : superMethods) { |
| if (!superMethod.equals(method)) { |
| continue; |
| } |
| removeCallsToSuperMethodFromMethod(overridingMethod, |
| extendsClass); |
| } |
| } |
| listenerReferences.add(implementsReference); |
| } |
| extendsReference.delete(); |
| final PsiReferenceList referenceList = aClass.getImplementsList(); |
| if (referenceList != null) { |
| for (PsiJavaCodeReferenceElement listenerReference : |
| listenerReferences) { |
| referenceList.add(listenerReference); |
| } |
| } |
| } |
| |
| private static void removeCallsToSuperMethodFromMethod( |
| @NotNull PsiMethod overridingMethod, |
| @NotNull PsiClass superClass) { |
| final PsiCodeBlock body = overridingMethod.getBody(); |
| if (body == null) { |
| return; |
| } |
| final PsiStatement[] statements = body.getStatements(); |
| for (PsiStatement statement : statements) { |
| if (!(statement instanceof PsiExpressionStatement)) { |
| continue; |
| } |
| final PsiExpressionStatement expressionStatement = |
| (PsiExpressionStatement)statement; |
| final PsiExpression expression = |
| expressionStatement.getExpression(); |
| if (!(expression instanceof PsiMethodCallExpression)) { |
| continue; |
| } |
| final PsiMethodCallExpression |
| methodCallExpression = |
| (PsiMethodCallExpression)expression; |
| final PsiReferenceExpression methodExpression = |
| methodCallExpression.getMethodExpression(); |
| final PsiExpression qualifier = |
| methodExpression.getQualifierExpression(); |
| if (!(qualifier instanceof PsiSuperExpression)) { |
| continue; |
| } |
| final PsiMethod targetMethod = |
| methodCallExpression.resolveMethod(); |
| if (targetMethod == null) { |
| continue; |
| } |
| final PsiClass containingClass = targetMethod.getContainingClass(); |
| if (!superClass.equals(containingClass)) { |
| continue; |
| } |
| statement.delete(); |
| } |
| } |
| |
| private static void implementMethodInClass(@NotNull PsiMethod method, |
| @NotNull PsiClass aClass) { |
| final PsiMethod newMethod = (PsiMethod)aClass.add(method); |
| final PsiDocComment comment = newMethod.getDocComment(); |
| if (comment != null) { |
| comment.delete(); |
| } |
| final PsiModifierList modifierList = newMethod.getModifierList(); |
| modifierList.setModifierProperty(PsiModifier.ABSTRACT, false); |
| final Project project = aClass.getProject(); |
| final CodeStyleSettings codeStyleSettings = |
| CodeStyleSettingsManager.getSettings(project); |
| if (codeStyleSettings.INSERT_OVERRIDE_ANNOTATION && |
| PsiUtil.isLanguageLevel6OrHigher(aClass)) { |
| modifierList.addAnnotation("java.lang.Override"); |
| } |
| final PsiElementFactory factory = |
| JavaPsiFacade.getElementFactory(project); |
| final PsiCodeBlock codeBlock = factory.createCodeBlock(); |
| newMethod.add(codeBlock); |
| } |
| } |