new "'hashCode()' called on array" inspection

This commit is contained in:
Bas Leijdekkers
2011-04-06 22:14:23 +02:00
parent f81fc00bfb
commit d8e411bd86
4 changed files with 161 additions and 0 deletions
@@ -1870,3 +1870,7 @@ try.finally.can.be.try.with.resources.problem.descriptor=<code>#ref</code> can u
try.finally.can.be.try.with.resources.quickfix=Replace with 'try' with resources
array.comparison.display.name=Array comparison using '==', instead of 'Arrays.equals()'
array.comparison.problem.descriptor=Array objects are compared using <code>#ref</code>, not 'Arrays.equals()' #loc
array.hash.code.display.name='hashCode()' called on array
array.hash.code.problem.descriptor=<code>#ref()</code> called on array should probably be 'Arrays.hashCode()' #loc
arrays.deep.hash.code.quickfix=Replace with 'Arrays.deepHashCode()'
arrays.hash.code.quickfix=Replace with 'Arrays.hashCode()'
@@ -518,6 +518,7 @@ public class InspectionGadgetsPlugin implements ApplicationComponent,
m_inspectionClasses.add(ArchaicSystemPropertyAccessInspection.class);
m_inspectionClasses.add(ArrayEqualityInspection.class);
m_inspectionClasses.add(ArrayEqualsInspection.class);
m_inspectionClasses.add(ArrayHashCodeInspection.class);
m_inspectionClasses.add(AssertWithSideEffectsInspection.class);
m_inspectionClasses.add(ConstantAssertConditionInspection.class);
m_inspectionClasses.add(CastConflictsWithInstanceofInspection.class);
@@ -0,0 +1,145 @@
/*
* Copyright 2011 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.bugs;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.HardcodedMethodConstants;
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 ArrayHashCodeInspection extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message("array.hash.code.display.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"array.hash.code.problem.descriptor");
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
final PsiArrayType type = (PsiArrayType) infos[0];
if (type.getComponentType() instanceof PsiArrayType) {
return new ArrayHashCodeFix(true);
}
return new ArrayHashCodeFix(false);
}
private static class ArrayHashCodeFix extends InspectionGadgetsFix {
private final boolean deepHashCode;
public ArrayHashCodeFix(boolean deepHashCode) {
this.deepHashCode = deepHashCode;
}
@NotNull
public String getName() {
if (deepHashCode) {
return InspectionGadgetsBundle.message(
"arrays.deep.hash.code.quickfix");
} else {
return InspectionGadgetsBundle.message(
"arrays.hash.code.quickfix");
}
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = element.getParent();
final PsiElement grandParent = parent.getParent();
if (!(grandParent instanceof PsiMethodCallExpression)) {
return;
}
final PsiMethodCallExpression methodCallExpression =
(PsiMethodCallExpression) grandParent;
final PsiReferenceExpression methodExpression =
methodCallExpression.getMethodExpression();
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
if (qualifier == null) {
return;
}
@NonNls final StringBuilder newExpressionText = new StringBuilder();
if (deepHashCode) {
newExpressionText.append("java.util.Arrays.deepHashCode(");
} else {
newExpressionText.append("java.util.Arrays.hashCode(");
}
newExpressionText.append(qualifier.getText());
newExpressionText.append(')');
replaceExpressionAndShorten(methodCallExpression,
newExpressionText.toString());
}
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new ArrayHashCodeVisitor();
}
private static class ArrayHashCodeVisitor extends BaseInspectionVisitor {
@Override
public void visitMethodCallExpression(
PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
final PsiReferenceExpression methodExpression =
expression.getMethodExpression();
final String methodName = methodExpression.getReferenceName();
if (!HardcodedMethodConstants.HASH_CODE.equals(methodName)) {
return;
}
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression[] arguments = argumentList.getExpressions();
if (arguments.length != 0) {
return;
}
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
if (qualifier == null) {
return;
}
final PsiType type = qualifier.getType();
if (!(type instanceof PsiArrayType)) {
return;
}
registerMethodCallError(expression, type);
}
}
}
@@ -0,0 +1,11 @@
<html>
<body>
This inspection reports <b>hashCode()</b> being called
on an array. To get the same hash code for two arrays
with identical contents call <b>Arrays.hashCode()</b>.
Use <b>Arrays.deepHashCode()</b> to calculate the hash
code of a multi-dimensional array.
<p>
<small>New in 10.5, Powered by InspectionGadgets</small>
</body>
</html>