From 3ff0ba6be449a27169dcc6f679eb7ade4dfbbf4b Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 19 Aug 2015 15:07:06 +0200 Subject: [PATCH] IG: quick fix for "Unary plus" inspection & highlight like unused symbol --- .../siyeh/InspectionGadgetsBundle.properties | 3 +- .../siyeh/ig/numeric/UnaryPlusInspection.java | 78 +++++++++++++++++-- .../siyeh/ig/psiutils/MethodCallUtils.java | 21 +++++ .../igtest/numeric/unary_plus/UnaryPlus.java | 11 +++ .../ig/numeric/UnaryPlusInspectionTest.java | 36 +++++++++ 5 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unary_plus/UnaryPlus.java create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/UnaryPlusInspectionTest.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 45f93ba01a96..d60181ed9d65 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -2161,4 +2161,5 @@ assert.message.not.string.display.name='assert' message is not a String assert.message.of.type.boolean.problem.descriptor=''assert'' message of type ''{0}'' #loc assert.message.not.string.only.warn.boolean.option=Only warn when 'assert' message is boolean or java.lang.Boolean suspicious.literal.underscore.display.name=Suspicious underscore in number literal -suspicious.literal.underscore.problem.descriptor=Group in number literal with underscores does not have length 3 #loc \ No newline at end of file +suspicious.literal.underscore.problem.descriptor=Group in number literal with underscores does not have length 3 #loc +unary.plus.quickfix=Remove unary '+' \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnaryPlusInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnaryPlusInspection.java index 9d7ad81d72d6..56a09e875c16 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnaryPlusInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnaryPlusInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2006-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,14 +15,19 @@ */ package com.siyeh.ig.numeric; -import com.intellij.psi.JavaTokenType; -import com.intellij.psi.PsiJavaToken; -import com.intellij.psi.PsiPrefixExpression; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.InspectionGadgetsFix; +import com.siyeh.ig.psiutils.MethodCallUtils; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class UnaryPlusInspection extends BaseInspection { @@ -39,6 +44,44 @@ public class UnaryPlusInspection extends BaseInspection { "unary.plus.problem.descriptor"); } + @Nullable + @Override + protected InspectionGadgetsFix buildFix(Object... infos) { + return new UnaryPlusFix(); + } + + private static class UnaryPlusFix extends InspectionGadgetsFix { + + @Nls + @NotNull + @Override + public String getName() { + return InspectionGadgetsBundle.message("unary.plus.quickfix"); + } + + @Nls + @NotNull + @Override + public String getFamilyName() { + return getName(); + } + + @Override + protected void doFix(Project project, ProblemDescriptor descriptor) { + final PsiElement element = descriptor.getPsiElement(); + final PsiElement parent = element.getParent(); + if (!(parent instanceof PsiPrefixExpression)) { + return; + } + final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)parent; + final PsiExpression operand = prefixExpression.getOperand(); + if (operand == null) { + return; + } + prefixExpression.replace(operand); + } + } + @Override public BaseInspectionVisitor buildVisitor() { return new UnaryPlusVisitor(); @@ -47,15 +90,36 @@ public class UnaryPlusInspection extends BaseInspection { private static class UnaryPlusVisitor extends BaseInspectionVisitor { @Override - public void visitPrefixExpression( - PsiPrefixExpression prefixExpression) { + public void visitPrefixExpression(PsiPrefixExpression prefixExpression) { super.visitPrefixExpression(prefixExpression); final PsiJavaToken token = prefixExpression.getOperationSign(); final IElementType tokenType = token.getTokenType(); if (!tokenType.equals(JavaTokenType.PLUS)) { return; } - registerError(token); + final PsiExpression operand = prefixExpression.getOperand(); + if (operand == null) { + return; + } + final PsiType type = operand.getType(); + if (PsiType.BYTE.equals(type) || PsiType.SHORT.equals(type)) { + PsiExpression expression = prefixExpression; + PsiElement parent = expression.getParent(); + while (parent instanceof PsiParenthesizedExpression) { + expression = (PsiExpression)parent; + parent = parent.getParent(); + } + final PsiElement grandParent = parent.getParent(); + if (parent instanceof PsiExpressionList && grandParent instanceof PsiCall) { + // unary plus might have been used as cast to int + final PsiCall call = (PsiCall)grandParent; + final PsiMethod method = call.resolveMethod(); + if (MethodCallUtils.findMethodWithReplacedArgument(call, expression, operand) != method) { + return; + } + } + } + registerError(token, ProblemHighlightType.LIKE_UNUSED_SYMBOL); } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java index 7c825185d4eb..192eba07d679 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java @@ -277,4 +277,25 @@ public class MethodCallUtils { final PsiElement element = referenceExpression.resolve(); return variable.equals(element); } + + public static PsiMethod findMethodWithReplacedArgument(@NotNull PsiCall call, @NotNull PsiExpression target, + @NotNull PsiExpression replacement) { + final PsiExpressionList argumentList = call.getArgumentList(); + assert argumentList != null; + final PsiExpression[] expressions = argumentList.getExpressions(); + int index = -1; + for (int i = 0; i < expressions.length; i++) { + final PsiExpression expression = expressions[i]; + if (expression == target) { + index = i; + } + } + assert index >= 0; + final PsiCall copy = (PsiCall)call.copy(); + final PsiExpressionList copyArgumentList = copy.getArgumentList(); + assert copyArgumentList != null; + final PsiExpression[] arguments = copyArgumentList.getExpressions(); + arguments[index].replace(replacement); + return copy.resolveMethod(); + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unary_plus/UnaryPlus.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unary_plus/UnaryPlus.java new file mode 100644 index 000000000000..35b553618260 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unary_plus/UnaryPlus.java @@ -0,0 +1,11 @@ +class UnaryPlus { + + void m(byte b) {} + void m(int i) {} + + void p() { + byte b = 1; + m(+b); // calls different method when unary plus removed. + System.out.println(+1); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/UnaryPlusInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/UnaryPlusInspectionTest.java new file mode 100644 index 000000000000..a51023ec15f0 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/numeric/UnaryPlusInspectionTest.java @@ -0,0 +1,36 @@ +/* + * 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.siyeh.ig.numeric; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; + +/** + * @author Bas Leijdekkers + */ +public class UnaryPlusInspectionTest extends LightInspectionTestCase { + + public void testUnaryPlus() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + return new UnaryPlusInspection(); + } +} \ No newline at end of file