mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-30 10:20:15 +07:00
IDEA-133322 Add an intention to convert compareTo(x)==0 to equals
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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.intellij.codeInsight.intention.impl;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.intention.BaseElementAtCaretIntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class ConvertCompareToToEqualsIntention extends BaseElementAtCaretIntentionAction {
|
||||
public static final String TEXT = "Convert '.compareTo()' method to '.equals()' (may change semantics)";
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
|
||||
if (!FileModificationService.getInstance().preparePsiElementsForWrite(element)) {
|
||||
return;
|
||||
}
|
||||
final ResolveResult resolveResult = findCompareTo(element);
|
||||
assert resolveResult != null;
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
|
||||
final Pair<PsiExpression, PsiExpression> qualifierAndParameter = getQualifierAndParameter(resolveResult.getCompareToCall());
|
||||
final PsiExpression newExpression =
|
||||
elementFactory.createExpressionFromText(String.format((resolveResult.isEqEq() ? "" : "!") + "%s.equals(%s)", qualifierAndParameter.getFirst().getText(), qualifierAndParameter.getSecond().getText()), null);
|
||||
final PsiElement result = resolveResult.getBinaryExpression().replace(newExpression);
|
||||
|
||||
editor.getCaretModel().moveToOffset(result.getTextOffset() + result.getTextLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
|
||||
return findCompareTo(element) != null;
|
||||
}
|
||||
|
||||
private static Pair<PsiExpression, PsiExpression> getQualifierAndParameter(PsiMethodCallExpression methodCallExpression) {
|
||||
final PsiExpression qualifier = methodCallExpression.getMethodExpression().getQualifierExpression();
|
||||
assert qualifier != null;
|
||||
final PsiExpression parameter = methodCallExpression.getArgumentList().getExpressions()[0];
|
||||
return Pair.create(qualifier, parameter);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ResolveResult findCompareTo(PsiElement element) {
|
||||
final PsiBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(element, PsiBinaryExpression.class);
|
||||
if (binaryExpression == null) {
|
||||
return null;
|
||||
}
|
||||
final PsiJavaToken operationSign = binaryExpression.getOperationSign();
|
||||
boolean isEqEq;
|
||||
if (JavaTokenType.NE.equals(operationSign.getTokenType())) {
|
||||
isEqEq = false;
|
||||
} else if (JavaTokenType.EQEQ.equals(operationSign.getTokenType())) {
|
||||
isEqEq = true;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
PsiMethodCallExpression compareToExpression = null;
|
||||
boolean hasZero = false;
|
||||
for (PsiExpression psiExpression : binaryExpression.getOperands()) {
|
||||
if (compareToExpression == null && detectCompareTo(psiExpression)) {
|
||||
compareToExpression = (PsiMethodCallExpression)psiExpression;
|
||||
continue;
|
||||
}
|
||||
if (!hasZero && detectZero(psiExpression)) {
|
||||
hasZero = true;
|
||||
}
|
||||
}
|
||||
if (!hasZero || compareToExpression == null) {
|
||||
return null;
|
||||
}
|
||||
getQualifierAndParameter(compareToExpression);
|
||||
return new ResolveResult(binaryExpression, compareToExpression, isEqEq);
|
||||
}
|
||||
|
||||
private static boolean detectCompareTo(final @NotNull PsiExpression expression) {
|
||||
if (!(expression instanceof PsiMethodCallExpression)) {
|
||||
return false;
|
||||
}
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
|
||||
if (methodCallExpression.getMethodExpression().getQualifierExpression() == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiMethod psiMethod = methodCallExpression.resolveMethod();
|
||||
if (psiMethod == null || !"compareTo".equals(psiMethod.getName()) || psiMethod.getParameterList().getParametersCount() != 1) {
|
||||
return false;
|
||||
}
|
||||
if (methodCallExpression.getArgumentList().getExpressions().length != 1) {
|
||||
return false;
|
||||
}
|
||||
final PsiClass containingClass = psiMethod.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiClass javaLangComparable = JavaPsiFacade.getInstance(expression.getProject()).findClass(CommonClassNames.JAVA_LANG_COMPARABLE, GlobalSearchScope.allScope(
|
||||
expression.getProject()));
|
||||
if (javaLangComparable == null) {
|
||||
return false;
|
||||
}
|
||||
if (!containingClass.isInheritor(javaLangComparable, true)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean detectZero(final @NotNull PsiExpression expression) {
|
||||
if (!(expression instanceof PsiLiteralExpression)) {
|
||||
return false;
|
||||
}
|
||||
final Object value = ((PsiLiteralExpression)expression).getValue();
|
||||
return Comparing.equal(value, 0);
|
||||
}
|
||||
|
||||
private static class ResolveResult {
|
||||
private final PsiBinaryExpression myBinaryExpression;
|
||||
private final PsiMethodCallExpression myCompareToCall;
|
||||
private final boolean myEqEq;
|
||||
|
||||
private ResolveResult(PsiBinaryExpression binaryExpression, PsiMethodCallExpression compareToCall, boolean eqEq) {
|
||||
myBinaryExpression = binaryExpression;
|
||||
myCompareToCall = compareToCall;
|
||||
myEqEq = eqEq;
|
||||
}
|
||||
|
||||
public PsiBinaryExpression getBinaryExpression() {
|
||||
return myBinaryExpression;
|
||||
}
|
||||
|
||||
public PsiMethodCallExpression getCompareToCall() {
|
||||
return myCompareToCall;
|
||||
}
|
||||
|
||||
public boolean isEqEq() {
|
||||
return myEqEq;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return TEXT;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return getFamilyName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.String;
|
||||
|
||||
class X {
|
||||
void m() {
|
||||
|
||||
Integer i1 = new Integer(0);
|
||||
Integer i2 = new Integer(2);
|
||||
|
||||
boolean b = i1.compareT<caret>o(i2) == 0;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.lang.Integer;
|
||||
import java.lang.String;
|
||||
|
||||
class X {
|
||||
void m() {
|
||||
|
||||
Integer i1 = new Integer(0);
|
||||
Integer i2 = new Integer(2);
|
||||
|
||||
boolean b = i1.equals(i2);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.lang.String;
|
||||
|
||||
class X {
|
||||
void m() {
|
||||
|
||||
boolean b = "asd".substring(1).compareTo("qwe".substring(2)) !<caret>= 0;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.lang.String;
|
||||
|
||||
class X {
|
||||
void m() {
|
||||
|
||||
boolean b = !"asd".substring(1).equals("qwe".substring(2));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import java.lang.String;
|
||||
|
||||
class X {
|
||||
void m() {
|
||||
|
||||
boolean b = "asd".compareTo("qwe") == 1;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.intellij.codeInsight.intention;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.intention.impl.ConvertCompareToToEqualsIntention;
|
||||
import com.intellij.testFramework.fixtures.CodeInsightTestUtil;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
|
||||
/**
|
||||
* @author Dmitry Batkovich
|
||||
*/
|
||||
public class ConvertCompareToToEqualsTest extends JavaCodeInsightFixtureTestCase {
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath() + "/codeInsight/convertCompareToToEquals/";
|
||||
}
|
||||
|
||||
public void testNe() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testEqEq() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNotAvailable() {
|
||||
doTestNotAvailable();;
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
final String name = getTestName(true);
|
||||
CodeInsightTestUtil.doIntentionTest(myFixture, ConvertCompareToToEqualsIntention.TEXT, name + ".java", name + "_after.java");
|
||||
}
|
||||
|
||||
private void doTestNotAvailable() {
|
||||
myFixture.configureByFile(getTestName(true) + ".java");
|
||||
assertEmpty(myFixture.filterAvailableIntentions(ConvertCompareToToEqualsIntention.TEXT));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
void m(String s1, String s2) {
|
||||
if (!s1.equals(s2)) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
void m(String s1, String s2) {
|
||||
if (<spot>s1.compareTo(s2) != 0</spot>) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<html>
|
||||
<body>
|
||||
Converts call if <b>compareTo</b> method to call of <b>equals</b> method.
|
||||
</body>
|
||||
</html>
|
||||
@@ -740,6 +740,10 @@
|
||||
<className>com.intellij.codeInsight.intention.impl.SwapIfStatementsIntentionAction</className>
|
||||
<category>Control Flow</category>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<className>com.intellij.codeInsight.intention.impl.ConvertCompareToToEqualsIntention</className>
|
||||
<category>Control Flow</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>com.intellij.codeInsight.intention.impl.CreateFieldFromParameterAction</className>
|
||||
|
||||
Reference in New Issue
Block a user