diff --git a/java/java-impl/src/com/intellij/refactoring/HelpID.java b/java/java-impl/src/com/intellij/refactoring/HelpID.java index 91e07764cf42..550124d70a1f 100644 --- a/java/java-impl/src/com/intellij/refactoring/HelpID.java +++ b/java/java-impl/src/com/intellij/refactoring/HelpID.java @@ -76,7 +76,6 @@ public class HelpID { public static final String METHOD_DUPLICATES = "refactoring.replaceMethodCodeDuplicates"; public static final String CHANGE_CLASS_SIGNATURE = "change.class.signature.dialog"; public static final String MOVE_INSTANCE_METHOD = "refactoring.moveInstMethod"; - public static final String INVERT_BOOLEAN = "refactoring.invertBoolean"; public static final String EXTRACT_METHOD_OBJECT = "refactoring.extractMethodObject"; public static final String REPLACE_CONSTRUCTOR_WITH_BUILDER = "refactoring.replaceConstructorWithBuilder"; @NonNls public static final String ExtractClass = "refactorj.extractClass"; diff --git a/java/java-impl/src/com/intellij/refactoring/actions/InvertBooleanAction.java b/java/java-impl/src/com/intellij/refactoring/actions/InvertBooleanAction.java index 3f95b678cafc..c544ed07e9de 100644 --- a/java/java-impl/src/com/intellij/refactoring/actions/InvertBooleanAction.java +++ b/java/java-impl/src/com/intellij/refactoring/actions/InvertBooleanAction.java @@ -17,8 +17,10 @@ package com.intellij.refactoring.actions; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.extensions.Extensions; import com.intellij.psi.*; import com.intellij.refactoring.RefactoringActionHandler; +import com.intellij.refactoring.invertBoolean.InvertBooleanDelegate; import com.intellij.refactoring.invertBoolean.InvertBooleanHandler; import org.jetbrains.annotations.NotNull; @@ -31,15 +33,24 @@ public class InvertBooleanAction extends BaseRefactoringAction { } protected boolean isEnabledOnElements(@NotNull PsiElement[] elements) { - return elements.length == 1 && (elements[0] instanceof PsiMethod || elements[0] instanceof PsiVariable); + if (elements.length == 1) { + for (InvertBooleanDelegate delegate : Extensions.getExtensions(InvertBooleanDelegate.EP_NAME)) { + if (delegate.isVisibleOnElement(elements[0])) { + return true; + } + } + } + return false; } - protected boolean isAvailableOnElementInEditorAndFile(@NotNull final PsiElement element, @NotNull final Editor editor, @NotNull PsiFile file, @NotNull DataContext context) { - if (element instanceof PsiVariable) { - return PsiType.BOOLEAN.equals(((PsiVariable) element).getType()); - } - else if (element instanceof PsiMethod) { - return PsiType.BOOLEAN.equals(((PsiMethod) element).getReturnType()); + protected boolean isAvailableOnElementInEditorAndFile(@NotNull final PsiElement element, + @NotNull final Editor editor, + @NotNull PsiFile file, + @NotNull DataContext context) { + for (InvertBooleanDelegate delegate : Extensions.getExtensions(InvertBooleanDelegate.EP_NAME)) { + if (delegate.isAvailableOnElement(element)) { + return true; + } } return false; } diff --git a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java b/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java deleted file mode 100644 index 70d4570a9ced..000000000000 --- a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.invertBoolean; - -import com.intellij.ide.util.SuperMethodWarningUtil; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.DataContext; -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.refactoring.HelpID; -import com.intellij.refactoring.RefactoringActionHandler; -import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import org.jetbrains.annotations.NotNull; - -/** - * @author ven - */ -public class InvertBooleanHandler implements RefactoringActionHandler { - static final String REFACTORING_NAME = RefactoringBundle.message("invert.boolean.title"); - - public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { - editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); - PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext); - if (element instanceof PsiMethod) { - invoke((PsiMethod)element, project, editor); - } - else if (element instanceof PsiVariable) { - invoke((PsiVariable)element, project, editor); - } - else { - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage( - RefactoringBundle.message("error.wrong.caret.position.method.or.variable.name")), REFACTORING_NAME, HelpID.INVERT_BOOLEAN); - } - } - - private static void invoke(PsiVariable var, final Project project, Editor editor) { - final PsiType returnType = var.getType(); - if (!PsiType.BOOLEAN.equals(returnType)) { - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("invert.boolean.wrong.type")), REFACTORING_NAME, HelpID.INVERT_BOOLEAN); - return; - } - - if (var instanceof PsiParameter && ((PsiParameter)var).getDeclarationScope() instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)((PsiParameter)var).getDeclarationScope(); - final PsiMethod superMethod = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor")); - if (superMethod == null) return; - var = superMethod.getParameterList().getParameters()[method.getParameterList().getParameterIndex((PsiParameter)var)]; - } - - new InvertBooleanDialog(var).show(); - } - - public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { - if (elements.length == 1) { - if (elements[0] instanceof PsiMethod) { - invoke((PsiMethod)elements[0], project, null); - } - else if (elements[0] instanceof PsiVariable) { - invoke((PsiVariable)elements[0], project, null); - } - } - } - - private static void invoke(PsiMethod method, final Project project, Editor editor) { - final PsiType returnType = method.getReturnType(); - if (!PsiType.BOOLEAN.equals(returnType)) { - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("invert.boolean.wrong.type")), REFACTORING_NAME, HelpID.INVERT_BOOLEAN); - return; - } - - final PsiMethod superMethod = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor")); - if (superMethod == null) return; - method = superMethod; - - new InvertBooleanDialog(method).show(); - } -} diff --git a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java b/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java deleted file mode 100644 index 14ad1ab6c4b1..000000000000 --- a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright 2000-2015 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.invertBoolean; - -import com.intellij.codeInsight.CodeInsightServicesUtil; -import com.intellij.codeInsight.daemon.impl.RecursiveCallLineMarkerProvider; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Ref; -import com.intellij.psi.*; -import com.intellij.psi.search.searches.MethodReferencesSearch; -import com.intellij.psi.search.searches.OverridingMethodsSearch; -import com.intellij.psi.search.searches.ReferencesSearch; -import com.intellij.refactoring.BaseRefactoringProcessor; -import com.intellij.refactoring.rename.RenameProcessor; -import com.intellij.refactoring.rename.RenameUtil; -import com.intellij.refactoring.util.MoveRenameUsageInfo; -import com.intellij.usageView.UsageInfo; -import com.intellij.usageView.UsageViewDescriptor; -import com.intellij.util.IncorrectOperationException; -import com.intellij.util.Query; -import com.intellij.util.containers.HashMap; -import com.intellij.util.containers.HashSet; -import com.intellij.util.containers.MultiMap; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - * @author ven - */ -public class InvertBooleanProcessor extends BaseRefactoringProcessor { - private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.invertBoolean.InvertBooleanMethodProcessor"); - - private PsiNamedElement myElement; - private final String myNewName; - private final RenameProcessor myRenameProcessor; - private final Map myToInvert = new HashMap(); - private final SmartPointerManager mySmartPointerManager; - - public InvertBooleanProcessor(final PsiNamedElement namedElement, final String newName) { - super(namedElement.getProject()); - myElement = namedElement; - myNewName = newName; - final Project project = namedElement.getProject(); - myRenameProcessor = Comparing.equal(namedElement.getName(), myNewName) ? null : new RenameProcessor(project, namedElement, newName, false, false); - mySmartPointerManager = SmartPointerManager.getInstance(project); - } - - @Override - @NotNull - protected UsageViewDescriptor createUsageViewDescriptor(@NotNull UsageInfo[] usages) { - return new InvertBooleanUsageViewDescriptor(myElement); - } - - @Override - protected boolean preprocessUsages(@NotNull Ref refUsages) { - final MultiMap conflicts = new MultiMap(); - for (UsageInfo info : myToInvert.keySet()) { - final PsiElement element = info.getElement(); - if (element instanceof PsiMethodReferenceExpression) { - conflicts.putValue(element, "Method is used in method reference expression"); - } - } - - if (!conflicts.isEmpty()) { - return showConflicts(conflicts, null); - } - - if (myRenameProcessor == null || myRenameProcessor.preprocessUsages(refUsages)) { - prepareSuccessful(); - return true; - } - return false; - } - - @Override - @NotNull - protected UsageInfo[] findUsages() { - final List toInvert = new ArrayList(); - - addRefsToInvert(toInvert, myElement); - - if (myElement instanceof PsiMethod) { - final Collection overriders = OverridingMethodsSearch.search((PsiMethod)myElement).findAll(); - if (myRenameProcessor != null) { - for (PsiMethod overrider : overriders) { - myRenameProcessor.addElement(overrider, myNewName); - } - } - - Collection allMethods = new HashSet(overriders); - allMethods.add((PsiMethod)myElement); - - for (PsiMethod method : allMethods) { - method.accept(new JavaRecursiveElementWalkingVisitor() { - @Override public void visitReturnStatement(PsiReturnStatement statement) { - final PsiExpression returnValue = statement.getReturnValue(); - if (returnValue != null && PsiType.BOOLEAN.equals(returnValue.getType())) { - toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(returnValue)); - } - } - - @Override - public void visitClass(PsiClass aClass) {} - - @Override - public void visitLambdaExpression(PsiLambdaExpression expression) {} - }); - } - } else if (myElement instanceof PsiParameter && ((PsiParameter)myElement).getDeclarationScope() instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)((PsiParameter)myElement).getDeclarationScope(); - int index = method.getParameterList().getParameterIndex((PsiParameter)myElement); - LOG.assertTrue(index >= 0); - final Query methodQuery = MethodReferencesSearch.search(method); - final Collection methodRefs = methodQuery.findAll(); - for (PsiReference ref : methodRefs) { - PsiElement parent = ref.getElement().getParent(); - if (parent instanceof PsiAnonymousClass) { - parent = parent.getParent(); - } - if (parent instanceof PsiCall) { - final PsiCall call = (PsiCall)parent; - final PsiReferenceExpression methodExpression = call instanceof PsiMethodCallExpression ? - ((PsiMethodCallExpression)call).getMethodExpression() : - null; - final PsiExpressionList argumentList = call.getArgumentList(); - if (argumentList != null) { - final PsiExpression[] args = argumentList.getExpressions(); - if (index < args.length) { - if (methodExpression == null || - canInvert(methodExpression, args[index] instanceof PsiReferenceExpression && ((PsiReferenceExpression)args[index]).resolve() == myElement)) { - toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(args[index])); - } - } - } - } - } - final Collection overriders = OverridingMethodsSearch.search(method).findAll(); - for (PsiMethod overrider : overriders) { - final PsiParameter overriderParameter = overrider.getParameterList().getParameters()[index]; - if (myRenameProcessor != null) { - myRenameProcessor.addElement(overriderParameter, myNewName); - } - addRefsToInvert(toInvert, overriderParameter); - } - } - - final UsageInfo[] renameUsages = myRenameProcessor != null ? myRenameProcessor.findUsages() : UsageInfo.EMPTY_ARRAY; - - final SmartPsiElementPointer[] usagesToInvert = toInvert.toArray(new SmartPsiElementPointer[toInvert.size()]); - - //merge rename and invert usages - Map expressionsToUsages = new HashMap(); - List result = new ArrayList(); - for (UsageInfo renameUsage : renameUsages) { - expressionsToUsages.put(renameUsage.getElement(), renameUsage); - result.add(renameUsage); - } - - for (SmartPsiElementPointer pointer : usagesToInvert) { - final PsiExpression expression = (PsiExpression)pointer.getElement(); - if (!expressionsToUsages.containsKey(expression)) { - final UsageInfo usageInfo = new UsageInfo(expression); - expressionsToUsages.put(expression, usageInfo); - result.add(usageInfo); //fake UsageInfo - myToInvert.put(usageInfo, pointer); - } else { - myToInvert.put(expressionsToUsages.get(expression), pointer); - } - } - - return result.toArray(new UsageInfo[result.size()]); - } - - private static boolean canInvert(PsiReferenceExpression methodExpression, boolean checkRecursive) { - PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); - if (qualifierExpression == null || !"super".equals(qualifierExpression.getText())) { - PsiElement parent = methodExpression.getParent(); - if (parent instanceof PsiMethodCallExpression) { - return !(checkRecursive && RecursiveCallLineMarkerProvider.isRecursiveMethodCall((PsiMethodCallExpression)parent)); - } else { - return true; - } - } - return false; - } - - private void addRefsToInvert(final List toInvert, final PsiNamedElement namedElement) { - final Query query = namedElement instanceof PsiMethod ? - MethodReferencesSearch.search((PsiMethod)namedElement) : - ReferencesSearch.search(namedElement); - final Collection refs = query.findAll(); - - for (PsiReference ref : refs) { - final PsiElement element = ref.getElement(); - if (element instanceof PsiReferenceExpression) { - final PsiReferenceExpression refExpr = (PsiReferenceExpression)element; - PsiElement parent = refExpr.getParent(); - if (parent instanceof PsiAssignmentExpression && refExpr.equals(((PsiAssignmentExpression)parent).getLExpression())) { - toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(((PsiAssignmentExpression)parent).getRExpression())); - } - else { - if (namedElement instanceof PsiParameter) { //filter usages in super method calls - PsiElement gParent = refExpr.getParent().getParent(); - if (gParent instanceof PsiMethodCallExpression) { - if (!canInvert(((PsiMethodCallExpression)gParent).getMethodExpression(), true)) { - continue; - } - } - } - - toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(refExpr)); - } - } - } - - if (namedElement instanceof PsiVariable) { - final PsiExpression initializer = ((PsiVariable)namedElement).getInitializer(); - if (initializer != null) { - toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(initializer)); - } - } - } - - @Override - protected void refreshElements(@NotNull PsiElement[] elements) { - LOG.assertTrue(elements.length == 1 && elements[0] instanceof PsiMethod); - myElement = (PsiMethod)elements[0]; - } - - private static UsageInfo[] extractUsagesForElement(PsiElement element, UsageInfo[] usages) { - final ArrayList extractedUsages = new ArrayList(usages.length); - for (UsageInfo usage : usages) { - if (usage instanceof MoveRenameUsageInfo) { - MoveRenameUsageInfo usageInfo = (MoveRenameUsageInfo)usage; - if (element.equals(usageInfo.getReferencedElement())) { - extractedUsages.add(usageInfo); - } - } - } - return extractedUsages.toArray(new UsageInfo[extractedUsages.size()]); - } - - - @Override - protected void performRefactoring(@NotNull UsageInfo[] usages) { - if (myRenameProcessor != null) { - for (final PsiElement element : myRenameProcessor.getElements()) { - try { - RenameUtil.doRename(element, myRenameProcessor.getNewName(element), extractUsagesForElement(element, usages), myProject, null); - } - catch (final IncorrectOperationException e) { - RenameUtil.showErrorMessage(e, element, myProject); - return; - } - } - } - - - for (UsageInfo usage : usages) { - final SmartPsiElementPointer pointerToInvert = myToInvert.get(usage); - if (pointerToInvert != null) { - PsiExpression expression = (PsiExpression)pointerToInvert.getElement(); - LOG.assertTrue(expression != null); - if (expression.getParent() instanceof PsiMethodCallExpression) expression = (PsiExpression)expression.getParent(); - try { - while (expression.getParent() instanceof PsiPrefixExpression && - ((PsiPrefixExpression)expression.getParent()).getOperationTokenType() == JavaTokenType.EXCL) { - expression = (PsiExpression)expression.getParent(); - } - if (!(expression.getParent() instanceof PsiExpressionStatement)) { - expression.replace(CodeInsightServicesUtil.invertCondition(expression)); - } - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - } - } - - if (myElement instanceof PsiField && ((PsiField)myElement).getInitializer() == null) { - ((PsiField)myElement).setInitializer(JavaPsiFacade.getElementFactory(myProject).createExpressionFromText("true", myElement)); - } - } - - @Override - protected String getCommandName() { - return InvertBooleanHandler.REFACTORING_NAME; - } -} diff --git a/java/java-impl/src/com/intellij/refactoring/invertBoolean/JavaInvertBooleanDelegate.java b/java/java-impl/src/com/intellij/refactoring/invertBoolean/JavaInvertBooleanDelegate.java new file mode 100644 index 000000000000..e5cabf1e88a8 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/invertBoolean/JavaInvertBooleanDelegate.java @@ -0,0 +1,256 @@ +/* + * Copyright 2000-2015 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.invertBoolean; + +import com.intellij.codeInsight.CodeInsightServicesUtil; +import com.intellij.codeInsight.daemon.impl.RecursiveCallLineMarkerProvider; +import com.intellij.ide.util.SuperMethodWarningUtil; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.search.searches.MethodReferencesSearch; +import com.intellij.psi.search.searches.OverridingMethodsSearch; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.rename.RenameProcessor; +import com.intellij.refactoring.util.CommonRefactoringUtil; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.Query; +import com.intellij.util.containers.HashSet; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public class JavaInvertBooleanDelegate extends InvertBooleanDelegate { + @Override + public boolean isVisibleOnElement(@NotNull PsiElement element) { + return element instanceof PsiVariable || element instanceof PsiMethod; + } + + @Override + public boolean isAvailableOnElement(@NotNull PsiElement element) { + if (element instanceof PsiVariable) { + return PsiType.BOOLEAN.equals(((PsiVariable) element).getType()); + } + else if (element instanceof PsiMethod) { + return PsiType.BOOLEAN.equals(((PsiMethod) element).getReturnType()); + } + return false; + } + + @Override + public PsiElement adjustElement(PsiElement element, Project project, Editor editor) { + if (element instanceof PsiVariable) { + PsiVariable var = (PsiVariable)element; + final PsiType returnType = var.getType(); + if (!PsiType.BOOLEAN.equals(returnType)) { + CommonRefactoringUtil.showErrorHint(project, editor, + RefactoringBundle + .getCannotRefactorMessage(RefactoringBundle.message("invert.boolean.wrong.type")), + InvertBooleanHandler.REFACTORING_NAME, InvertBooleanHandler.INVERT_BOOLEAN_HELP_ID); + return null; + } + + if (var instanceof PsiParameter && ((PsiParameter)var).getDeclarationScope() instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)((PsiParameter)var).getDeclarationScope(); + final PsiMethod superMethod = SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor")); + if (superMethod == null) { + return null; + } + var = superMethod.getParameterList().getParameters()[method.getParameterList().getParameterIndex((PsiParameter)var)]; + } + return var; + } + else if (element instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)element; + final PsiType returnType = method.getReturnType(); + if (!PsiType.BOOLEAN.equals(returnType)) { + CommonRefactoringUtil.showErrorHint(project, editor, + RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("invert.boolean.wrong.type")), + InvertBooleanHandler.REFACTORING_NAME, + InvertBooleanHandler.INVERT_BOOLEAN_HELP_ID); + return null; + } + + return SuperMethodWarningUtil.checkSuperMethod(method, RefactoringBundle.message("to.refactor")); + } + return null; + } + + public void collectRefsToInvert(PsiElement namedElement, Collection elementsToInvert) { + final Query query = namedElement instanceof PsiMethod ? + MethodReferencesSearch.search((PsiMethod)namedElement) : + ReferencesSearch.search(namedElement); + final Collection refs = query.findAll(); + + for (PsiReference ref : refs) { + PsiElement refElement = null; + final PsiElement element = ref.getElement(); + if (element instanceof PsiReferenceExpression) { + final PsiReferenceExpression refExpr = (PsiReferenceExpression)element; + PsiElement parent = refExpr.getParent(); + if (parent instanceof PsiAssignmentExpression && refExpr.equals(((PsiAssignmentExpression)parent).getLExpression())) { + refElement = ((PsiAssignmentExpression)parent).getRExpression(); + } + else { + if (namedElement instanceof PsiParameter) { //filter usages in super method calls + PsiElement gParent = refExpr.getParent().getParent(); + if (gParent instanceof PsiMethodCallExpression) { + if (!canInvertReferenceElement(((PsiMethodCallExpression)gParent).getMethodExpression(), true)) { + continue; + } + } + } + refElement = refExpr; + } + } + if (refElement != null) { + elementsToInvert.add(refElement); + } + } + + if (namedElement instanceof PsiVariable) { + final PsiExpression initializer = ((PsiVariable)namedElement).getInitializer(); + if (initializer != null) { + elementsToInvert.add(initializer); + } + } + } + + private static boolean canInvertReferenceElement(PsiElement expression, boolean recursive) { + PsiExpression qualifierExpression = expression instanceof PsiReferenceExpression ? ((PsiReferenceExpression)expression).getQualifierExpression() + : null; + if (qualifierExpression == null || !"super".equals(qualifierExpression.getText())) { + PsiElement parent = expression.getParent(); + if (parent instanceof PsiMethodCallExpression) { + return !(recursive && RecursiveCallLineMarkerProvider.isRecursiveMethodCall((PsiMethodCallExpression)parent)); + } else { + return true; + } + } + return false; + } + + @Override + public void replaceWithNegatedExpression(@NotNull PsiElement expression) { + if (expression.getParent() instanceof PsiMethodCallExpression) { + expression = expression.getParent(); + } + while (expression.getParent() instanceof PsiPrefixExpression && + ((PsiPrefixExpression)expression.getParent()).getOperationTokenType() == JavaTokenType.EXCL) { + expression = expression.getParent(); + } + + if (!(expression.getParent() instanceof PsiExpressionStatement)) { + expression.replace(CodeInsightServicesUtil.invertCondition((PsiExpression)expression)); + } + } + + @Override + public void invertDefaultElementInitializer(final PsiElement element) { + if (element instanceof PsiField && ((PsiField)element).getInitializer() == null) { + ((PsiField)element).setInitializer(JavaPsiFacade.getElementFactory(element.getProject()).createExpressionFromText("true", element)); + } + } + + public void collectRefElements(final PsiElement element, + final Collection elementsToInvert, + final RenameProcessor renameProcessor, + @NotNull final String newName) { + collectRefsToInvert(element, elementsToInvert); + + if (element instanceof PsiMethod) { + final Collection overriders = OverridingMethodsSearch.search((PsiMethod)element).findAll(); + if (renameProcessor != null) { + for (PsiMethod overrider : overriders) { + renameProcessor.addElement(overrider, newName); + } + } + + Collection allMethods = new HashSet(overriders); + allMethods.add((PsiMethod)element); + + for (PsiMethod method : allMethods) { + method.accept(new JavaRecursiveElementWalkingVisitor() { + @Override public void visitReturnStatement(PsiReturnStatement statement) { + final PsiExpression returnValue = statement.getReturnValue(); + if (returnValue != null && PsiType.BOOLEAN.equals(returnValue.getType())) { + elementsToInvert.add(returnValue); + } + } + + @Override + public void visitClass(PsiClass aClass) {} + + @Override + public void visitLambdaExpression(PsiLambdaExpression expression) {} + }); + } + } + else if (element instanceof PsiParameter && ((PsiParameter)element).getDeclarationScope() instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)((PsiParameter)element).getDeclarationScope(); + int index = method.getParameterList().getParameterIndex((PsiParameter)element); + assert index >= 0; + final Query methodQuery = MethodReferencesSearch.search(method); + final Collection methodRefs = methodQuery.findAll(); + for (PsiReference ref : methodRefs) { + PsiElement parent = ref.getElement().getParent(); + if (parent instanceof PsiAnonymousClass) { + parent = parent.getParent(); + } + if (parent instanceof PsiCall) { + final PsiCall call = (PsiCall)parent; + final PsiReferenceExpression methodExpression = call instanceof PsiMethodCallExpression ? + ((PsiMethodCallExpression)call).getMethodExpression() : + null; + final PsiExpressionList argumentList = call.getArgumentList(); + if (argumentList != null) { + final PsiExpression[] args = argumentList.getExpressions(); + if (index < args.length) { + if (methodExpression == null || + canInvertReferenceElement(methodExpression, + args[index] instanceof PsiReferenceExpression && + ((PsiReferenceExpression)args[index]).resolve() == element)) { + elementsToInvert.add(args[index]); + } + } + } + } + } + + final Collection overriders = OverridingMethodsSearch.search(method).findAll(); + for (PsiMethod overrider : overriders) { + final PsiParameter overriderParameter = overrider.getParameterList().getParameters()[index]; + if (renameProcessor != null) { + renameProcessor.addElement(overriderParameter, newName); + } + collectRefsToInvert(overriderParameter, elementsToInvert); + } + } + } + + @Override + public void findConflicts(MultiMap conflicts, UsageInfo[] usageInfos) { + for (UsageInfo info : usageInfos) { + final PsiElement element = info.getElement(); + if (element instanceof PsiMethodReferenceExpression) { + conflicts.putValue(element, "Method is used in method reference expression"); + } + } + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBoolean.form b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBoolean.form similarity index 100% rename from java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBoolean.form rename to platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBoolean.form diff --git a/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanDelegate.java b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanDelegate.java new file mode 100644 index 000000000000..82365831f46f --- /dev/null +++ b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanDelegate.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2015 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.invertBoolean; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.refactoring.rename.RenameProcessor; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public abstract class InvertBooleanDelegate { + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.refactoring.invertBoolean"); + + /** + * Quick check if element is potentially acceptable by delegate + * + * @return true if element is possible to invert, e.g. variable or method + */ + public abstract boolean isVisibleOnElement(@NotNull PsiElement element); + + /** + * @return true if element is of boolean type + */ + public abstract boolean isAvailableOnElement(@NotNull PsiElement element); + + /** + * Adjust element to invert, e.g. suggest to refactor super method instead of current + * + * @return null if user canceled the operation + */ + @Nullable + public abstract PsiElement adjustElement(PsiElement element, Project project, Editor editor); + + /** + * Eventually collect additional elements to rename, e.g. override methods + * and find expressions which need to be inverted + * + * @param renameProcessor null if element is not named or name was not changed + */ + public abstract void collectRefElements(PsiElement element, + Collection elementsToInvert, + @Nullable RenameProcessor renameProcessor, + @NotNull String newName); + + /** + * Replace expression with created negation + * @param expression to be inverted, found in {@link #collectRefElements(PsiElement, Collection, RenameProcessor, String)} + */ + public abstract void replaceWithNegatedExpression(PsiElement expression); + + /** + * Initialize variable with negated default initializer when default was initially omitted + */ + public void invertDefaultElementInitializer(PsiElement var) {} + + /** + * Detect usages which can't be inverted + */ + public void findConflicts(MultiMap conflicts, + UsageInfo[] usageInfos) {} +} diff --git a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanDialog.java b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanDialog.java similarity index 85% rename from java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanDialog.java rename to platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanDialog.java index 48702418c8ea..089927426293 100644 --- a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanDialog.java @@ -18,8 +18,8 @@ package com.intellij.refactoring.invertBoolean; import com.intellij.lang.findUsages.DescriptiveNameUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.help.HelpManager; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; -import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.ui.RefactoringDialog; import com.intellij.refactoring.util.CommonRefactoringUtil; @@ -36,12 +36,12 @@ public class InvertBooleanDialog extends RefactoringDialog { private JLabel myLabel; private JLabel myCaptionLabel; - private final PsiNamedElement myElement; + private final PsiElement myElement; - public InvertBooleanDialog(final PsiNamedElement element) { + public InvertBooleanDialog(final PsiElement element) { super(element.getProject(), false); myElement = element; - final String name = myElement.getName(); + final String name = myElement instanceof PsiNamedElement ? ((PsiNamedElement)myElement).getName() : myElement.getText(); myNameField.setText(name); myLabel.setLabelFor(myNameField); final String typeString = UsageViewUtil.getType(myElement); @@ -65,7 +65,7 @@ public class InvertBooleanDialog extends RefactoringDialog { CommonRefactoringUtil.showErrorMessage(InvertBooleanHandler.REFACTORING_NAME, RefactoringBundle.message("please.enter.a.valid.name.for.inverted.element", UsageViewUtil.getType(myElement)), - HelpID.INVERT_BOOLEAN, project); + InvertBooleanHandler.INVERT_BOOLEAN_HELP_ID, project); return; } @@ -73,7 +73,7 @@ public class InvertBooleanDialog extends RefactoringDialog { } protected void doHelpAction() { - HelpManager.getInstance().invokeHelp(HelpID.INVERT_BOOLEAN); + HelpManager.getInstance().invokeHelp(InvertBooleanHandler.INVERT_BOOLEAN_HELP_ID); } protected JComponent createCenterPanel() { diff --git a/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java new file mode 100644 index 000000000000..e5998de72746 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanHandler.java @@ -0,0 +1,71 @@ +/* + * 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.invertBoolean; + +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.refactoring.RefactoringActionHandler; +import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.util.CommonRefactoringUtil; +import org.jetbrains.annotations.NotNull; + +/** + * @author ven + */ +public class InvertBooleanHandler implements RefactoringActionHandler { + public static final String INVERT_BOOLEAN_HELP_ID = "refactoring.invertBoolean"; + static final String REFACTORING_NAME = RefactoringBundle.message("invert.boolean.title"); + private static final Logger LOG = Logger.getInstance("#" + InvertBooleanHandler.class.getName()); + + public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext); + PsiElement namedElement = adjustElement(element, project, editor); + if (namedElement == null) { + CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage( + RefactoringBundle.message("error.wrong.caret.position.method.or.variable.name")), REFACTORING_NAME, INVERT_BOOLEAN_HELP_ID); + return; + } + new InvertBooleanDialog(namedElement).show(); + } + + public static PsiElement adjustElement(PsiElement element, Project project, Editor editor) { + for (InvertBooleanDelegate delegate : Extensions.getExtensions(InvertBooleanDelegate.EP_NAME)) { + if (delegate.isVisibleOnElement(element)) { + return delegate.adjustElement(element, project, editor); + } + } + return null; + } + + public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { + LOG.assertTrue(elements.length == 1); + PsiElement element = adjustElement(elements[0], project, null); + if (element == null) { + CommonRefactoringUtil.showErrorHint(project, null, RefactoringBundle.getCannotRefactorMessage( + RefactoringBundle.message("error.wrong.caret.position.method.or.variable.name")), REFACTORING_NAME, INVERT_BOOLEAN_HELP_ID); + return; + } + new InvertBooleanDialog(element).show(); + } +} diff --git a/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java new file mode 100644 index 000000000000..27c6027fa1d7 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanProcessor.java @@ -0,0 +1,189 @@ +/* + * Copyright 2000-2015 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.invertBoolean; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Ref; +import com.intellij.psi.*; +import com.intellij.refactoring.BaseRefactoringProcessor; +import com.intellij.refactoring.rename.RenameProcessor; +import com.intellij.refactoring.rename.RenameUtil; +import com.intellij.refactoring.util.MoveRenameUsageInfo; +import com.intellij.usageView.UsageInfo; +import com.intellij.usageView.UsageViewDescriptor; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.HashMap; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; + +/** + * @author ven + */ +public class InvertBooleanProcessor extends BaseRefactoringProcessor { + private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.invertBoolean.InvertBooleanMethodProcessor"); + private final InvertBooleanDelegate myDelegate; + + private PsiElement myElement; + private final String myNewName; + private final RenameProcessor myRenameProcessor; + private final Map myToInvert = new HashMap(); + private final SmartPointerManager mySmartPointerManager; + + public InvertBooleanProcessor(final PsiElement namedElement, final String newName) { + super(namedElement.getProject()); + myElement = namedElement; + myNewName = newName; + final Project project = namedElement.getProject(); + myRenameProcessor = !(namedElement instanceof PsiNamedElement) || Comparing.equal(((PsiNamedElement)namedElement).getName(), myNewName) + ? null : new RenameProcessor(project, namedElement, newName, false, false); + mySmartPointerManager = SmartPointerManager.getInstance(project); + myDelegate = findInvertBooleanDelegate(myElement); + } + + private static InvertBooleanDelegate findInvertBooleanDelegate(PsiElement element) { + for (InvertBooleanDelegate delegate : Extensions.getExtensions(InvertBooleanDelegate.EP_NAME)) { + if (delegate.isVisibleOnElement(element)) { + return delegate; + } + } + LOG.error(element); + return null; + } + + @Override + @NotNull + protected UsageViewDescriptor createUsageViewDescriptor(@NotNull UsageInfo[] usages) { + return new InvertBooleanUsageViewDescriptor(myElement); + } + + @Override + protected boolean preprocessUsages(@NotNull Ref refUsages) { + final MultiMap conflicts = new MultiMap(); + myDelegate.findConflicts(conflicts, refUsages.get()); + + if (!conflicts.isEmpty()) { + return showConflicts(conflicts, null); + } + + if (myRenameProcessor == null || myRenameProcessor.preprocessUsages(refUsages)) { + prepareSuccessful(); + return true; + } + return false; + } + + @Override + @NotNull + protected UsageInfo[] findUsages() { + final List toInvert = new ArrayList(); + + final LinkedHashSet elementsToInvert = new LinkedHashSet(); + myDelegate.collectRefElements(myElement, elementsToInvert, myRenameProcessor, myNewName); + for (PsiElement element : elementsToInvert) { + toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(element)); + } + + final UsageInfo[] renameUsages = myRenameProcessor != null ? myRenameProcessor.findUsages() : UsageInfo.EMPTY_ARRAY; + + final SmartPsiElementPointer[] usagesToInvert = toInvert.toArray(new SmartPsiElementPointer[toInvert.size()]); + + //merge rename and invert usages + Map expressionsToUsages = new HashMap(); + List result = new ArrayList(); + for (UsageInfo renameUsage : renameUsages) { + expressionsToUsages.put(renameUsage.getElement(), renameUsage); + result.add(renameUsage); + } + + for (SmartPsiElementPointer pointer : usagesToInvert) { + final PsiElement expression = pointer.getElement(); + if (!expressionsToUsages.containsKey(expression)) { + final UsageInfo usageInfo = new UsageInfo(expression); + expressionsToUsages.put(expression, usageInfo); + result.add(usageInfo); //fake UsageInfo + myToInvert.put(usageInfo, pointer); + } else { + myToInvert.put(expressionsToUsages.get(expression), pointer); + } + } + + return result.toArray(new UsageInfo[result.size()]); + } + + @Override + protected void refreshElements(@NotNull PsiElement[] elements) { + myElement = elements[0]; + } + + private static UsageInfo[] extractUsagesForElement(PsiElement element, UsageInfo[] usages) { + final ArrayList extractedUsages = new ArrayList(usages.length); + for (UsageInfo usage : usages) { + if (usage instanceof MoveRenameUsageInfo) { + MoveRenameUsageInfo usageInfo = (MoveRenameUsageInfo)usage; + if (element.equals(usageInfo.getReferencedElement())) { + extractedUsages.add(usageInfo); + } + } + } + return extractedUsages.toArray(new UsageInfo[extractedUsages.size()]); + } + + + @Override + protected void performRefactoring(@NotNull UsageInfo[] usages) { + if (myRenameProcessor != null) { + for (final PsiElement element : myRenameProcessor.getElements()) { + try { + RenameUtil.doRename(element, myRenameProcessor.getNewName(element), extractUsagesForElement(element, usages), myProject, null); + } + catch (final IncorrectOperationException e) { + RenameUtil.showErrorMessage(e, element, myProject); + return; + } + } + } + + + for (UsageInfo usage : usages) { + final SmartPsiElementPointer pointerToInvert = myToInvert.get(usage); + if (pointerToInvert != null) { + PsiElement element = pointerToInvert.getElement(); + LOG.assertTrue(element != null); + try { + myDelegate.replaceWithNegatedExpression(element); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + } + + myDelegate.invertDefaultElementInitializer(myElement); + } + + @Override + protected String getCommandName() { + return InvertBooleanHandler.REFACTORING_NAME; + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanUsageViewDescriptor.java b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanUsageViewDescriptor.java similarity index 93% rename from java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanUsageViewDescriptor.java rename to platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanUsageViewDescriptor.java index 3fbeff0727aa..0cc559c6bbfb 100644 --- a/java/java-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanUsageViewDescriptor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/invertBoolean/InvertBooleanUsageViewDescriptor.java @@ -27,9 +27,9 @@ import org.jetbrains.annotations.NotNull; * @author ven */ public class InvertBooleanUsageViewDescriptor implements UsageViewDescriptor { - private final PsiNamedElement myElement; + private final PsiElement myElement; - public InvertBooleanUsageViewDescriptor(final PsiNamedElement element) { + public InvertBooleanUsageViewDescriptor(final PsiElement element) { myElement = element; } diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index b0d916dffe9a..1b7914d616bf 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -368,6 +368,7 @@ + diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index a31632735880..8c296ea14da4 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -319,6 +319,7 @@ + diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml index c80d3bd8a6ba..29489c86a618 100644 --- a/python/src/META-INF/python-core.xml +++ b/python/src/META-INF/python-core.xml @@ -562,6 +562,7 @@ + @@ -765,10 +766,6 @@ - - - - diff --git a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBoolean.form b/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBoolean.form deleted file mode 100644 index 9dd64539b156..000000000000 --- a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBoolean.form +++ /dev/null @@ -1,42 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanAction.java b/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanAction.java deleted file mode 100644 index dc16dc73e4c8..000000000000 --- a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanAction.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2000-2014 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.jetbrains.python.refactoring.invertBoolean; - -import com.intellij.lang.Language; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.RefactoringActionHandler; -import com.intellij.refactoring.actions.BaseRefactoringAction; -import com.jetbrains.python.PyNames; -import com.jetbrains.python.PythonLanguage; -import com.jetbrains.python.psi.*; -import org.jetbrains.annotations.NotNull; - -/** - * User : ktisha - */ -public class PyInvertBooleanAction extends BaseRefactoringAction { - @Override - protected boolean isAvailableInEditorOnly() { - return true; - } - - @Override - protected boolean isEnabledOnElements(@NotNull PsiElement[] elements) { - if (elements.length == 1) { - return isApplicable(elements[0], elements[0].getContainingFile()); - } - return false; - } - - private static boolean isApplicable(@NotNull final PsiElement element, @NotNull final PsiFile file) { - final VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile != null && ProjectRootManager.getInstance(element.getProject()).getFileIndex().isInLibraryClasses(virtualFile)) return false; - if (element instanceof PyTargetExpression) { - final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(element, PyAssignmentStatement.class); - if (assignmentStatement != null) { - final PyExpression assignedValue = assignmentStatement.getAssignedValue(); - if (assignedValue == null) return false; - final String name = assignedValue.getText(); - return name != null && (PyNames.TRUE.equals(name) || PyNames.FALSE.equals(name)); - } - } - if (element instanceof PyNamedParameter) { - final PyExpression defaultValue = ((PyNamedParameter)element).getDefaultValue(); - if (defaultValue instanceof PyBoolLiteralExpression) return true; - } - return element.getParent() instanceof PyBoolLiteralExpression; - } - - @Override - protected boolean isAvailableOnElementInEditorAndFile(@NotNull final PsiElement element, @NotNull final Editor editor, @NotNull PsiFile file, @NotNull DataContext context) { - return isApplicable(element, element.getContainingFile()); - } - - @Override - protected RefactoringActionHandler getHandler(@NotNull DataContext dataContext) { - return new PyInvertBooleanHandler(); - } - - @Override - protected boolean isAvailableForLanguage(Language language) { - return language.isKindOf(PythonLanguage.getInstance()); - } -} diff --git a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanDelegate.java b/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanDelegate.java new file mode 100644 index 000000000000..5eb92bfed0d6 --- /dev/null +++ b/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanDelegate.java @@ -0,0 +1,148 @@ +/* + * Copyright 2000-2015 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.jetbrains.python.refactoring.invertBoolean; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.invertBoolean.InvertBooleanDelegate; +import com.intellij.refactoring.rename.RenameProcessor; +import com.jetbrains.python.PyNames; +import com.jetbrains.python.PyTokenTypes; +import com.jetbrains.python.psi.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public class PyInvertBooleanDelegate extends InvertBooleanDelegate { + @Override + public boolean isVisibleOnElement(@NotNull PsiElement element) { + final VirtualFile virtualFile = element.getContainingFile().getVirtualFile(); + if (virtualFile != null && + ProjectRootManager.getInstance(element.getProject()).getFileIndex().isInLibraryClasses(virtualFile)) { + return false; + } + if (element instanceof PyTargetExpression || element instanceof PyNamedParameter) { + return true; + } + return element.getParent() instanceof PyBoolLiteralExpression; + } + + @Override + public boolean isAvailableOnElement(@NotNull PsiElement element) { + final VirtualFile virtualFile = element.getContainingFile().getVirtualFile(); + if (virtualFile != null && ProjectRootManager.getInstance(element.getProject()).getFileIndex().isInLibraryClasses(virtualFile)) return false; + if (element instanceof PyTargetExpression) { + final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(element, PyAssignmentStatement.class); + if (assignmentStatement != null) { + final PyExpression assignedValue = assignmentStatement.getAssignedValue(); + if (assignedValue == null) return false; + final String name = assignedValue.getText(); + return name != null && (PyNames.TRUE.equals(name) || PyNames.FALSE.equals(name)); + } + } + if (element instanceof PyNamedParameter) { + final PyExpression defaultValue = ((PyNamedParameter)element).getDefaultValue(); + if (defaultValue instanceof PyBoolLiteralExpression) return true; + } + return element.getParent() instanceof PyBoolLiteralExpression; + } + + @Nullable + @Override + public PsiElement adjustElement(PsiElement element, Project project, Editor editor) { + final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(element, PyAssignmentStatement.class); + if (assignmentStatement != null) { + return assignmentStatement.getTargets()[0]; + } + else if (element instanceof PyNamedParameter) { + return element; + } + return null; + } + + @Override + public void collectRefElements(PsiElement psiElement, + Collection elementsToInvert, + @Nullable RenameProcessor renameProcessor, + @NotNull String newName) { + final Collection refs = ReferencesSearch.search(psiElement).findAll(); + + for (PsiReference ref : refs) { + final PsiElement element = ref.getElement(); + if (element instanceof PyTargetExpression) { + final PyTargetExpression target = (PyTargetExpression)element; + final PyAssignmentStatement parent = PsiTreeUtil.getParentOfType(target, PyAssignmentStatement.class); + if (parent != null && parent.getTargets().length == 1) { + final PyExpression value = parent.getAssignedValue(); + if (value != null) + elementsToInvert.add(value); + } + } + else if (element.getParent() instanceof PyPrefixExpression) { + elementsToInvert.add(element.getParent()); + } + else if (element instanceof PyReferenceExpression) { + final PyReferenceExpression refExpr = (PyReferenceExpression)element; + elementsToInvert.add(refExpr); + } + } + + if (psiElement instanceof PyNamedParameter) { + PyExpression defaultValue = ((PyNamedParameter)psiElement).getDefaultValue(); + if (defaultValue != null) { + elementsToInvert.add(defaultValue); + } + } + } + + @Override + public void replaceWithNegatedExpression(PsiElement expression) { + if (expression != null && PsiTreeUtil.getParentOfType(expression, PyImportStatementBase.class, false) == null) { + final PyExpression replacement = invertExpression(expression); + expression.replace(replacement); + } + } + + @NotNull + private static PyExpression invertExpression(@NotNull final PsiElement expression) { + final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(expression.getProject()); + if (expression instanceof PyBoolLiteralExpression) { + final String value = ((PyBoolLiteralExpression)expression).getValue() ? PyNames.FALSE : PyNames.TRUE; + return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), value); + } + if (expression instanceof PyReferenceExpression && (PyNames.FALSE.equals(expression.getText()) || + PyNames.TRUE.equals(expression.getText()))) { + + final String value = PyNames.TRUE.equals(expression.getText()) ? PyNames.FALSE : PyNames.TRUE; + return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), value); + } + else if (expression instanceof PyPrefixExpression) { + if (((PyPrefixExpression)expression).getOperator() == PyTokenTypes.NOT_KEYWORD) { + final PyExpression operand = ((PyPrefixExpression)expression).getOperand(); + if (operand != null) + return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), operand.getText()); + } + } + return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), "not " + expression.getText()); + } +} diff --git a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanDialog.java b/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanDialog.java deleted file mode 100644 index f33e4040cbe6..000000000000 --- a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanDialog.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2000-2014 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.jetbrains.python.refactoring.invertBoolean; - -import com.intellij.lang.findUsages.DescriptiveNameUtil; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiNamedElement; -import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.rename.RenameUtil; -import com.intellij.refactoring.ui.RefactoringDialog; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.usageView.UsageViewUtil; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; - -/** - * User : ktisha - */ -public class PyInvertBooleanDialog extends RefactoringDialog { - private JTextField myNameField; - private JPanel myPanel; - private JLabel myLabel; - private JLabel myCaptionLabel; - - private final PsiElement myElement; - private final String myName; - - public PyInvertBooleanDialog(final PsiElement element) { - super(element.getProject(), false); - myElement = element; - myName = element instanceof PsiNamedElement ? ((PsiNamedElement)element).getName() : element.getText(); - myNameField.setText(myName); - myLabel.setLabelFor(myNameField); - final String typeString = UsageViewUtil.getType(myElement); - myLabel.setText(RefactoringBundle.message("invert.boolean.name.of.inverted.element", typeString)); - myCaptionLabel.setText(RefactoringBundle.message("invert.0.1", - typeString, - DescriptiveNameUtil.getDescriptiveName(myElement))); - - setTitle(PyInvertBooleanHandler.REFACTORING_NAME); - init(); - } - - public JComponent getPreferredFocusedComponent() { - return myNameField; - } - - protected void doAction() { - Project project = myElement.getProject(); - final String name = myNameField.getText().trim(); - if (name.length() == 0 || (!name.equals(myName) && !RenameUtil.isValidName(myProject, myElement, name))) { - CommonRefactoringUtil.showErrorMessage(PyInvertBooleanHandler.REFACTORING_NAME, - RefactoringBundle.message("please.enter.a.valid.name.for.inverted.element", - UsageViewUtil.getType(myElement)), - "refactoring.invertBoolean", project); - return; - } - - invokeRefactoring(new PyInvertBooleanProcessor(myElement, name)); - } - - protected JComponent createCenterPanel() { - return myPanel; - } - - @Nullable - @Override - protected String getHelpId() { - return "reference.invert.boolean"; - } -} diff --git a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanHandler.java b/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanHandler.java deleted file mode 100644 index 41f5f733bf94..000000000000 --- a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanHandler.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2000-2014 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.jetbrains.python.refactoring.invertBoolean; - -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.LangDataKeys; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.RefactoringActionHandler; -import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.jetbrains.python.psi.PyAssignmentStatement; -import com.jetbrains.python.psi.PyNamedParameter; -import org.jetbrains.annotations.NotNull; - -/** - * User : ktisha - */ -public class PyInvertBooleanHandler implements RefactoringActionHandler { - static final String REFACTORING_NAME = RefactoringBundle.message("invert.boolean.title"); - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) { - PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext); - if (element == null && editor != null && file != null) { - element = file.findElementAt(editor.getCaretModel().getOffset()); - } - final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(element, PyAssignmentStatement.class); - if (assignmentStatement != null) { - invoke(assignmentStatement.getTargets()[0]); - } - else if (element instanceof PyNamedParameter) { - invoke(element); - } - else { - CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage( - RefactoringBundle.message("error.wrong.caret.position.local.or.expression.name")), REFACTORING_NAME, "refactoring.invertBoolean"); - } - } - - @Override - public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) { - if (elements.length == 1) { - final PyAssignmentStatement assignmentStatement = PsiTreeUtil.getParentOfType(elements[0], PyAssignmentStatement.class); - if (assignmentStatement != null) { - invoke(assignmentStatement.getTargets()[0]); - } - } - } - - private static void invoke(@NotNull final PsiElement element) { - new PyInvertBooleanDialog(element).show(); - } -} diff --git a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanProcessor.java b/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanProcessor.java deleted file mode 100644 index 734560753dc8..000000000000 --- a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanProcessor.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2000-2015 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.jetbrains.python.refactoring.invertBoolean; - -import com.intellij.openapi.util.Ref; -import com.intellij.psi.*; -import com.intellij.psi.search.searches.ReferencesSearch; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.refactoring.BaseRefactoringProcessor; -import com.intellij.refactoring.rename.RenameProcessor; -import com.intellij.refactoring.rename.RenameUtil; -import com.intellij.refactoring.util.MoveRenameUsageInfo; -import com.intellij.usageView.UsageInfo; -import com.intellij.usageView.UsageViewDescriptor; -import com.intellij.util.IncorrectOperationException; -import com.intellij.util.containers.HashMap; -import com.jetbrains.python.PyNames; -import com.jetbrains.python.PyTokenTypes; -import com.jetbrains.python.psi.*; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - * User : ktisha - */ -public class PyInvertBooleanProcessor extends BaseRefactoringProcessor { - private PsiElement myElement; - private String myNewName; - private final RenameProcessor myRenameProcessor; - private final Map myToInvert = new HashMap(); - private final SmartPointerManager mySmartPointerManager; - - public PyInvertBooleanProcessor(@NotNull final PsiElement namedElement, @NotNull final String newName) { - super(namedElement.getProject()); - myElement = namedElement; - myNewName = newName; - mySmartPointerManager = SmartPointerManager.getInstance(myProject); - myRenameProcessor = new RenameProcessor(myProject, namedElement, newName, false, false); - } - - @Override - @NotNull - protected UsageViewDescriptor createUsageViewDescriptor(@NotNull UsageInfo[] usages) { - return new PyInvertBooleanUsageViewDescriptor(myElement); - } - - @Override - protected boolean preprocessUsages(@NotNull Ref refUsages) { - if (!myNewName.equals(myElement instanceof PsiNamedElement ? ((PsiNamedElement)myElement).getName() : myElement.getText())) { - if (myRenameProcessor.preprocessUsages(refUsages)) { - prepareSuccessful(); - return true; - } - return false; - } - prepareSuccessful(); - return true; - } - - @Override - @NotNull - protected UsageInfo[] findUsages() { - final List toInvert = new ArrayList(); - - addRefsToInvert(toInvert, myElement); - - final UsageInfo[] renameUsages = myRenameProcessor.findUsages(); - - final Map expressionsToUsages = new HashMap(); - final List result = new ArrayList(); - for (UsageInfo renameUsage : renameUsages) { - expressionsToUsages.put(renameUsage.getElement(), renameUsage); - result.add(renameUsage); - } - - for (SmartPsiElementPointer pointer : toInvert) { - final PyExpression expression = (PyExpression)pointer.getElement(); - if (!expressionsToUsages.containsKey(expression) && expression != null) { - final UsageInfo usageInfo = new UsageInfo(expression); - expressionsToUsages.put(expression, usageInfo); - result.add(usageInfo); - myToInvert.put(usageInfo, pointer); - } else { - myToInvert.put(expressionsToUsages.get(expression), pointer); - } - } - - return result.toArray(new UsageInfo[result.size()]); - } - - private void addRefsToInvert(@NotNull final List toInvert, @NotNull final PsiElement psiElement) { - final Collection refs = ReferencesSearch.search(psiElement).findAll(); - - for (PsiReference ref : refs) { - final PsiElement element = ref.getElement(); - if (element instanceof PyTargetExpression) { - final PyTargetExpression target = (PyTargetExpression)element; - final PyAssignmentStatement parent = PsiTreeUtil.getParentOfType(target, PyAssignmentStatement.class); - if (parent != null && parent.getTargets().length == 1) { - final PyExpression value = parent.getAssignedValue(); - if (value != null) - toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(value)); - } - } - else if (element.getParent() instanceof PyPrefixExpression) { - toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(element.getParent())); - } - else if (element instanceof PyReferenceExpression) { - final PyReferenceExpression refExpr = (PyReferenceExpression)element; - toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(refExpr)); - } - } - if (psiElement instanceof PyNamedParameter) { - final PyExpression defaultValue = ((PyNamedParameter)psiElement).getDefaultValue(); - if (defaultValue != null) - toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(defaultValue)); - } - } - - @NotNull - private static UsageInfo[] extractUsagesForElement(@NotNull final PsiElement element, @NotNull final UsageInfo[] usages) { - final ArrayList extractedUsages = new ArrayList(usages.length); - for (UsageInfo usage : usages) { - if (usage instanceof MoveRenameUsageInfo) { - MoveRenameUsageInfo usageInfo = (MoveRenameUsageInfo)usage; - if (element.equals(usageInfo.getReferencedElement())) { - extractedUsages.add(usageInfo); - } - } - } - return extractedUsages.toArray(new UsageInfo[extractedUsages.size()]); - } - - - @Override - protected void performRefactoring(@NotNull UsageInfo[] usages) { - for (final PsiElement element : myRenameProcessor.getElements()) { - try { - RenameUtil.doRename(element, myRenameProcessor.getNewName(element), extractUsagesForElement(element, usages), myProject, null); - } - catch (final IncorrectOperationException e) { - RenameUtil.showErrorMessage(e, element, myProject); - return; - } - } - for (UsageInfo usage : usages) { - final SmartPsiElementPointer pointerToInvert = myToInvert.get(usage); - if (pointerToInvert != null) { - PsiElement expression = pointerToInvert.getElement(); - if (expression != null && PsiTreeUtil.getParentOfType(expression, PyImportStatementBase.class, false) == null) { - final PyExpression replacement = invertExpression(expression); - expression.replace(replacement); - } - } - } - } - - @NotNull - private PyExpression invertExpression(@NotNull final PsiElement expression) { - final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(myProject); - if (expression instanceof PyBoolLiteralExpression) { - final String value = ((PyBoolLiteralExpression)expression).getValue() ? PyNames.FALSE : PyNames.TRUE; - return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), value); - } - if (expression instanceof PyReferenceExpression && (PyNames.FALSE.equals(expression.getText()) || - PyNames.TRUE.equals(expression.getText()))) { - - final String value = PyNames.TRUE.equals(expression.getText()) ? PyNames.FALSE : PyNames.TRUE; - return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), value); - } - else if (expression instanceof PyPrefixExpression) { - if (((PyPrefixExpression)expression).getOperator() == PyTokenTypes.NOT_KEYWORD) { - final PyExpression operand = ((PyPrefixExpression)expression).getOperand(); - if (operand != null) - return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), operand.getText()); - } - } - return elementGenerator.createExpressionFromText(LanguageLevel.forElement(expression), "not " + expression.getText()); - } - - @Override - protected String getCommandName() { - return PyInvertBooleanHandler.REFACTORING_NAME; - } -} diff --git a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanUsageViewDescriptor.java b/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanUsageViewDescriptor.java deleted file mode 100644 index e346d495ec41..000000000000 --- a/python/src/com/jetbrains/python/refactoring/invertBoolean/PyInvertBooleanUsageViewDescriptor.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2000-2014 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.jetbrains.python.refactoring.invertBoolean; - -import com.intellij.psi.PsiElement; -import com.intellij.refactoring.RefactoringBundle; -import com.intellij.usageView.UsageViewBundle; -import com.intellij.usageView.UsageViewDescriptor; -import com.intellij.usageView.UsageViewUtil; -import org.jetbrains.annotations.NotNull; - -/** - * User : ktisha - */ -public class PyInvertBooleanUsageViewDescriptor implements UsageViewDescriptor { - private final PsiElement myElement; - - public PyInvertBooleanUsageViewDescriptor(final PsiElement element) { - myElement = element; - } - - @NotNull - public PsiElement[] getElements() { - return new PsiElement[] {myElement}; - } - - public String getProcessedElementsHeader() { - return RefactoringBundle.message("invert.boolean.elements.header", UsageViewUtil.getType(myElement)); - } - - public String getCodeReferencesText(int usagesCount, int filesCount) { - return RefactoringBundle.message("invert.boolean.refs.to.invert", UsageViewBundle.getReferencesString(usagesCount, filesCount)); - } - - public String getCommentReferencesText(int usagesCount, int filesCount) { - return null; - } -} diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyInvertBooleanTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyInvertBooleanTest.java index 9e6bcd66d31c..4f75b2c19558 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyInvertBooleanTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyInvertBooleanTest.java @@ -19,9 +19,9 @@ import com.google.common.collect.Lists; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; +import com.intellij.refactoring.invertBoolean.InvertBooleanProcessor; import com.intellij.testFramework.TestDataPath; import com.jetbrains.python.fixtures.PyTestCase; -import com.jetbrains.python.refactoring.invertBoolean.PyInvertBooleanProcessor; import java.util.List; @@ -52,7 +52,7 @@ public class PyInvertBooleanTest extends PyTestCase { final PsiNamedElement target = (PsiNamedElement)element; final String name = target.getName(); assertNotNull(name); - new PyInvertBooleanProcessor(target, "not"+ StringUtil.toTitleCase(name)).run(); + new InvertBooleanProcessor(target, "not" + StringUtil.toTitleCase(name)).run(); myFixture.checkResultByFile("refactoring/invertBoolean/" + getTestName(true) + ".after.py"); } } diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index e22372e282df..acf869df5c46 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1685,6 +1685,7 @@ + diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index 0a41f3885cea..9496fe398e72 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -60,7 +60,6 @@ -