mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
[java-inspections] IDEA-338114 Suggest to replace (int)(v ^ (v >>> 32)) with a Long.hashCode(v)
GitOrigin-RevId: 2d9591f9d9a558c4a61ac226556ef9f551d6e0c2
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6da9127fbb
commit
2770254f2f
@@ -663,3 +663,5 @@ intention.family.name.move.members.into.class=Move members into class
|
||||
chooser.popup.title.select.class.to.move.members.to=Select Target Class
|
||||
intention.family.name.move.members.to=Move members to {0}
|
||||
action.StatisticCollectorAction.text=Collect Documentation Data
|
||||
inspection.message.can.be.replaced.with.long.hashcode=Can be replaced with 'Long.hashCode()'
|
||||
inspection.name.can.be.replaced.with.long.hashcode='Long.hashCode()' can be used
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.java.analysis.JavaAnalysisBundle;
|
||||
import com.intellij.modcommand.ModPsiUpdater;
|
||||
import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import com.siyeh.ig.psiutils.EquivalenceChecker;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class UseHashCodeMethodInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
if (!PsiUtil.isLanguageLevel8OrHigher(holder.getFile())) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
return new JavaElementVisitor() {
|
||||
@Override
|
||||
public void visitTypeCastExpression(@NotNull PsiTypeCastExpression expression) {
|
||||
if (getHashCodeOperand(expression) != null) {
|
||||
holder.registerProblem(expression, JavaAnalysisBundle.message("inspection.message.can.be.replaced.with.long.hashcode"),
|
||||
new ReplaceWithLongHashCodeFix());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static @Nullable PsiExpression getHashCodeOperand(PsiTypeCastExpression typeCastExpression) {
|
||||
if (typeCastExpression == null) return null;
|
||||
if (!PsiTypes.intType().equals(typeCastExpression.getType())) return null;
|
||||
PsiExpression operand = PsiUtil.skipParenthesizedExprDown(typeCastExpression.getOperand());
|
||||
if (!(operand instanceof PsiBinaryExpression binaryExpression)) return null;
|
||||
|
||||
PsiJavaToken operationSign = binaryExpression.getOperationSign();
|
||||
if (operationSign.getTokenType() != JavaTokenType.XOR) return null;
|
||||
|
||||
|
||||
PsiExpression leftOperand = PsiUtil.skipParenthesizedExprDown(binaryExpression.getLOperand());
|
||||
PsiExpression rightOperand = PsiUtil.skipParenthesizedExprDown(binaryExpression.getROperand());
|
||||
|
||||
if (leftOperand == null || rightOperand == null) return null;
|
||||
if (!PsiTypes.longType().equals(leftOperand.getType())) return null;
|
||||
|
||||
if (isXorShift(leftOperand, rightOperand)) return leftOperand;
|
||||
if (isXorShift(rightOperand, leftOperand)) return rightOperand;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isXorShift(@NotNull PsiExpression leftOperand, @NotNull PsiExpression rightOperand) {
|
||||
if (rightOperand instanceof PsiBinaryExpression shiftingExpression) {
|
||||
if (shiftingExpression.getOperationSign().getTokenType() != JavaTokenType.GTGTGT) return false;
|
||||
|
||||
PsiExpression leftSubOperand = shiftingExpression.getLOperand();
|
||||
return EquivalenceChecker.getCanonicalPsiEquivalence()
|
||||
.expressionsAreEquivalent(leftOperand, leftSubOperand) &&
|
||||
Objects.equals(32, ExpressionUtils.computeConstantExpression(shiftingExpression.getROperand()));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class ReplaceWithLongHashCodeFix extends PsiUpdateModCommandQuickFix {
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return CommonQuickFixBundle.message("fix.replace.with.x", "Long.hashCode()");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyFix(@NotNull Project project, @NotNull PsiElement startElement, @NotNull ModPsiUpdater updater) {
|
||||
PsiTypeCastExpression element = (PsiTypeCastExpression)startElement;
|
||||
PsiExpression operand = getHashCodeOperand(element);
|
||||
if (operand != null) {
|
||||
CommentTracker ct = new CommentTracker();
|
||||
ct.replace(element, "Long.hashCode(" + ct.text(operand) + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1742,6 +1742,10 @@
|
||||
groupKey="group.names.language.level.specific.issues.and.migration.aids8" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="INFORMATION"
|
||||
implementationClass="com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection"
|
||||
key="inspection.convert.2.streamapi.display.name" bundle="messages.JavaBundle"/>
|
||||
<localInspection groupPathKey="group.path.names.java.language.level.specific.issues.and.migration.aids" language="JAVA" shortName="UseHashCodeMethodInspection"
|
||||
groupKey="group.names.language.level.specific.issues.and.migration.aids8" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.UseHashCodeMethodInspection"
|
||||
key="inspection.convert.2.streamapi.display.name" bundle="messages.JavaBundle"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="FuseStreamOperations"
|
||||
bundle="messages.JavaBundle" key="inspection.fuse.stream.operations.display.name"
|
||||
groupKey="group.names.code.style.issues" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>
|
||||
Informs you when bitwise operations can be replaced with the <code>Long.hashCode</code> method.
|
||||
It detects instances of the pattern <code>(int)(x ^ (x >>> 32))</code> where <code>x</code> is a variable of type <code>long</code>.
|
||||
This improves readability of code.
|
||||
</p>
|
||||
<p>
|
||||
Example:
|
||||
</p>
|
||||
<pre><code>
|
||||
int result = (int)(var ^ (var >>> 32));
|
||||
</code></pre>
|
||||
After applying the quick-fix:
|
||||
<pre><code>
|
||||
int result = Long.hashCode(var);
|
||||
</code></pre>
|
||||
<!-- tooltip end -->
|
||||
<p>This inspection only reports if the language level of the project or module is 8 or higher.
|
||||
<p><small>New in 2024.1</small></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Replace with 'Long.hashCode()'" "true-preview"
|
||||
public class Test {
|
||||
long var = 1234567890123456789L;
|
||||
|
||||
public void testMethod() {
|
||||
int result = Long.hashCode(var);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Replace with 'Long.hashCode()'" "true-preview"
|
||||
public class Test {
|
||||
long var = 1234567890123456789L;
|
||||
|
||||
public void testMethod() {
|
||||
int result = Long.hashCode(var);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Replace with 'Long.hashCode()'" "true-preview"
|
||||
public class Test {
|
||||
long var = 1234567890123456789L;
|
||||
|
||||
public void testMethod() {
|
||||
int result = (int<caret>)(var ^ (var >>> /*shift amount*/ 32));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Replace with 'Long.hashCode()'" "true-preview"
|
||||
public class Test {
|
||||
long var = 1234567890123456789L;
|
||||
|
||||
public void testMethod() {
|
||||
int result = (int<caret>)((var >>> (16+16)) ^ var);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LightIntentionActionTestCase;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.UseHashCodeMethodInspection;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class UseHashCodeMethodInspectionTest extends LightIntentionActionTestCase {
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/useHashCode";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LocalInspectionTool @NotNull [] configureLocalInspectionTools() {
|
||||
return new UseHashCodeMethodInspection[]{new UseHashCodeMethodInspection()};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
|
||||
return LightJavaCodeInsightFixtureTestCase.JAVA_11;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user