diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index 859e402e3b82..9b8a6a9ea42f 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -143,7 +143,7 @@ object.comparison.display.name=Object comparison using ==, instead of 'equals()' object.comparison.enumerated.ignore.option=Ignore == between enumerated types object.comparison.klass.ignore.option=Ignore == on java.lang.Class objects object.comparison.problem.description=Object values are compared using #ref, not 'equals()' #loc -object.comparison.replace.quickfix=Replace with equals() +object.comparison.replace.quickfix=Replace with 'equals()' object.equals.null.problem.descriptor=.equals(#ref) is probably not what was intended #loc default.tostring.call.display.name=Call to default 'toString()' default.tostring.call.problem.descriptor=Call to default 'toString()' on #ref #loc @@ -1201,8 +1201,8 @@ serializable.inner.class.with.non.serializable.outer.class.ignore.option=Ignore serializable.with.unconstructable.ancestor.problem.descriptor=#ref has an non-serializable ancestor ''{0}'' without a no-arg constructor #loc transient.field.in.non.serializable.class.problem.descriptor=Field ''{0}'' is marked #ref, in non-Serializable class #loc transient.field.in.non.serializable.class.remove.quickfix=Remove 'transient' -condition.signal.replace.quickfix=Replace with signalAll() -object.notify.replace.quickfix=Replace with notifyAll() +condition.signal.replace.quickfix=Replace with 'signalAll()' +object.notify.replace.quickfix=Replace with 'notifyAll()' safe.lock.problem.descriptor=''{0}'' should be locked in front of a try block and unlocked in the corresponding finally block #loc synchronized.method.problem.descriptor=Method ''{0}()'' declared #ref #loc synchronized.method.include.option=Include native methods @@ -1238,7 +1238,7 @@ big.decimal.equals.replace.quickfix=replace with 'compareTo()==0' cast.that.loses.precision.problem.descriptor=Cast to #ref from ''{0}'' may result in loss of precision #loc comparison.to.nan.problem.descriptor1=Comparison to #ref is always false #loc comparison.to.nan.problem.descriptor2=Comparison to #ref is always true #loc -comparison.to.nan.replace.quickfix=replace with call to 'isNaN()' +comparison.to.nan.replace.quickfix=replace with 'isNaN()' confusing.floating.point.literal.change.quickfix=Change To canonical form implicit.numeric.conversion.ignore.widening.conversion.option=Ignore widening conversions implicit.numeric.conversion.ignore.char.conversion.option=Ignore conversions from and to char @@ -1247,7 +1247,7 @@ implicit.numeric.conversion.problem.descriptor=Implicit numeric conversion of #ref can be replaced with ''{0}'' #loc method.complexity.limit.option=Method complexity limit: @@ -1283,10 +1283,10 @@ manual.array.copy.replace.quickfix=Replace with 'System.arrayCopy()' manual.array.to.collection.copy.replace.quickfix=Replace with 'Collection.addAll(Arrays.asList())' method.may.be.static.only.option=Only check private or final methods method.may.be.static.empty.option=Ignore empty methods -random.double.for.random.integer.replace.quickfix=replace with 'nextInt()' +random.double.for.random.integer.replace.quickfix=Replace with 'nextInt()' string.buffer.replaceable.by.string.builder.replace.quickfix=Replace with StringBuilder string.buffer.to.string.in.concatenation.remove.quickfix=Remove 'toString()' -string.concatenation.in.loops.only.option=only warn if string is repeatedly appended +string.concatenation.in.loops.only.option=Only warn if string is repeatedly appended string.concatenation.inside.string.buffer.append.replace.quickfix=Replace with chained append() calls string.equals.empty.string.replace.quickfix=Replace with 'length()==0' tail.recursion.replace.quickfix=Replace tail recursion with iteration @@ -1586,7 +1586,7 @@ assertequals.between.inconvertible.types.display.name='assertEquals()' between o assertequals.between.inconvertible.types.problem.descriptor=#ref() between objects of inconvertible types ''{0}'' and ''{1}'' #loc enumeration.can.be.iteration.display.name=Enumeration can be iteration enumeration.can.be.iteration.problem.descriptor=#ref() can be replaced with ''{0}'' construct #loc -enumeration.can.be.iteration.quickfix=Replace with Iterator construct +enumeration.can.be.iteration.quickfix=Replace with 'Iterator' construct missing.override.annotation.jdk6.option=Use JDK6 @Override rules equals.hashcode.called.on.url.display.name='equals()' or 'hashCode()' called on java.net.URL object equals.hashcode.called.on.url.problem.descriptor=Call to #ref() on URL object #loc @@ -1741,9 +1741,9 @@ class.new.instance.problem.descriptor=Call to #ref() may throw unde class.new.instance.quickfix=Replace with 'Class.getConstructor().newInstance()' call dynamic.regex.replaceable.by.compiled.pattern.display.name=Dynamic regular expression could be replaced by compiled Pattern dynamic.regex.replaceable.by.compiled.pattern.problem.descriptor=#ref() could be replaced with compiled java.util.regex.Pattern construct #loc -dynamic.regex.replaceable.by.compiled.pattern.quickfix=Replace with call to method of compiled Pattern constant -ignore.serializable.option=ignore java.io.Serializable -ignore.cloneable.option=ignore java.lang.Cloneable +dynamic.regex.replaceable.by.compiled.pattern.quickfix=Replace with call to method of compiled 'Pattern' constant +ignore.serializable.option=Ignore java.io.Serializable +ignore.cloneable.option=Ignore java.lang.Cloneable listener.may.use.adapter.display.name=Class may extend adapter instead of implementing listener listener.may.use.adapter.problem.descriptor=Class ''{0}'' may extend ''{1}'' instead of implementing #ref #loc listener.may.use.adapter.quickfix=Replace with ''extends {0}'' @@ -1798,3 +1798,6 @@ unnecessarily.qualified.inner.class.access.display.name=Unnecessarily qualified unnecessarily.qualified.inner.class.access.quickfix=Remove qualifier synchronization.on.static.field.display.name=Synchronization on static field synchronization.on.static.field.problem.descriptor=Synchronization on static field #ref #loc +assertequals.called.on.arrays.display.name='assertEquals()' called on array +assertequals.called.on.arrays.problem.descriptor=#ref() called on array #loc +assertequals.called.on.arrays.quickfix=Replace with 'assertArrayEquals()' diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java index 466d5a5c6c98..03be4c77b888 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionGadgetsPlugin.java @@ -1045,6 +1045,7 @@ public class InspectionGadgetsPlugin implements ApplicationComponent, private void registerJUnitInspections() { m_inspectionClasses.add(AssertEqualsBetweenInconvertibleTypesInspection.class); m_inspectionClasses.add(AssertEqualsMayBeAssertSameInspection.class); + m_inspectionClasses.add(AssertEqualsCalledOnArrayInspection.class); m_inspectionClasses.add(AssertsWithoutMessagesInspection.class); m_inspectionClasses.add(BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection.class); m_inspectionClasses.add(BeforeOrAfterIsPublicVoidNoArgInspection.class); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java new file mode 100644 index 000000000000..7e7fc33b5ae2 --- /dev/null +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java @@ -0,0 +1,123 @@ +/* + * Copyright 2010 Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */package com.siyeh.ig.junit; + +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.InspectionGadgetsFix; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class AssertEqualsCalledOnArrayInspection extends BaseInspection { + @Nls + @NotNull + @Override + public String getDisplayName() { + return InspectionGadgetsBundle.message( + "assertequals.called.on.arrays.display.name"); + } + + @NotNull + @Override + protected String buildErrorString(Object... infos) { + return InspectionGadgetsBundle.message( + "assertequals.called.on.arrays.problem.descriptor"); + } + + @Override + protected InspectionGadgetsFix buildFix(Object... infos) { + return new AssertEqualsCalledOnArrayFix(); + } + + private static class AssertEqualsCalledOnArrayFix + extends InspectionGadgetsFix { + + @NotNull + public String getName() { + return InspectionGadgetsBundle.message( + "assertequals.called.on.arrays.quickfix"); + } + + @Override + protected void doFix(Project project, ProblemDescriptor descriptor) + throws IncorrectOperationException { + final PsiElement methodNameIdentifier = descriptor.getPsiElement(); + final PsiReferenceExpression methodExpression = + (PsiReferenceExpression)methodNameIdentifier.getParent(); + if (methodExpression == null) { + return; + } + final PsiExpression qualifier = + methodExpression.getQualifierExpression(); + if (qualifier == null) { + replaceExpression(methodExpression, "assertArrayEquals"); + } else { + final String qualifierText = qualifier.getText(); + replaceExpression(methodExpression, + qualifierText + ".assertArrayEquals"); + } + } + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new AssertEqualsOnArrayVisitor(); + } + + private static class AssertEqualsOnArrayVisitor + extends BaseInspectionVisitor { + + @Override + public void visitMethodCallExpression( + PsiMethodCallExpression expression) { + super.visitMethodCallExpression(expression); + final PsiReferenceExpression methodExpression = + expression.getMethodExpression(); + @NonNls final String methodName = + methodExpression.getReferenceName(); + if (!"assertEquals".equals(methodName)) { + return; + } + final PsiExpressionList argumentList = expression.getArgumentList(); + final PsiExpression[] arguments = argumentList.getExpressions(); + final PsiType type1; + final PsiType type2; + if (arguments.length == 2) { + final PsiExpression argument0 = arguments[0]; + type1 = argument0.getType(); + final PsiExpression argument1 = arguments[1]; + type2 = argument1.getType(); + } else if (arguments.length == 3) { + final PsiExpression argument0 = arguments[1]; + type1 = argument0.getType(); + final PsiExpression argument1 = arguments[2]; + type2 = argument1.getType(); + } else { + return; + } + if (!(type1 instanceof PsiArrayType) || + !(type2 instanceof PsiArrayType)) { + return; + } + registerMethodCallError(expression); + } + } +} diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/AssertEqualsCalledOnArray.html b/plugins/InspectionGadgets/src/inspectionDescriptions/AssertEqualsCalledOnArray.html new file mode 100644 index 000000000000..76e81ad4aeab --- /dev/null +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/AssertEqualsCalledOnArray.html @@ -0,0 +1,8 @@ + +
+ +This inspection reports any calls to JUnit's assertEquals() +method with arguments of type array. Arrays should be checked with one of the +assertArrayEquals() methods. +
New in 10, Powered by InspectionGadgets
+ \ No newline at end of file