From 87a2b2f6e1c1825da89a509442cb33184f294af4 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 21 Jan 2020 11:27:11 +0700 Subject: [PATCH] IDEA-230889 'Object allocation in a loop' doesn't detect concatenation of two constant Strings inside the loop GitOrigin-RevId: 0952486abeb99ba108af82028dce126d01a8fcfa --- .../messages/InspectionGadgetsBundle.properties | 1 + .../ObjectAllocationInLoopInspection.java | 16 +++++++++++++++- .../ObjectAllocationInLoop.java | 11 +++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/resources/messages/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/resources/messages/InspectionGadgetsBundle.properties index 3fa39f56ebe7..44b93475c3c5 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/resources/messages/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/resources/messages/InspectionGadgetsBundle.properties @@ -1029,6 +1029,7 @@ object.allocation.in.loop.new.descriptor=Object allocation new #ref()#ref() call in loop #loc object.allocation.in.loop.problem.methodref.descriptor=Object allocation via instance-bound method reference #ref() in loop #loc object.allocation.in.loop.problem.lambda.descriptor=Object allocation via capturing lambda in loop #loc +object.allocation.in.loop.problem.string.concat=Object allocation via string concatenation in loop #loc instantiating.object.to.get.class.object.problem.descriptor=Instantiating object to get Class object #loc field.may.be.static.problem.descriptor=Field #ref may be 'static' #loc method.may.be.static.problem.descriptor=Method #ref() may be 'static' #loc diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ObjectAllocationInLoopInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ObjectAllocationInLoopInspection.java index eeeda924de2d..7708b1fb9b08 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ObjectAllocationInLoopInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ObjectAllocationInLoopInspection.java @@ -22,12 +22,15 @@ import com.intellij.codeInspection.dataFlow.JavaMethodContractUtil; import com.intellij.codeInspection.dataFlow.NullabilityUtil; import com.intellij.codeInspection.dataFlow.StandardMethodContract; import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.ControlFlowUtils; import com.siyeh.ig.psiutils.ExpressionUtils; +import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.PropertyKey; @@ -40,7 +43,8 @@ public class ObjectAllocationInLoopInspection extends BaseInspection { NEW_OPERATOR("object.allocation.in.loop.new.descriptor"), METHOD_CALL("object.allocation.in.loop.problem.call.descriptor"), METHOD_REFERENCE("object.allocation.in.loop.problem.methodref.descriptor"), - CAPTURING_LAMBDA("object.allocation.in.loop.problem.lambda.descriptor"); + CAPTURING_LAMBDA("object.allocation.in.loop.problem.lambda.descriptor"), + STRING_CONCAT("object.allocation.in.loop.problem.string.concat"); private final String myMessage; @@ -105,6 +109,16 @@ public class ObjectAllocationInLoopInspection extends BaseInspection { } } + @Override + public void visitPolyadicExpression(PsiPolyadicExpression expression) { + IElementType type = expression.getOperationTokenType(); + if (JavaTokenType.PLUS.equals(type) && TypeUtils.isJavaLangString(expression.getType()) && + !PsiUtil.isConstantExpression(expression) && isPerformedRepeatedlyInLoop(expression)) { + registerError(expression, Kind.STRING_CONCAT); + } + super.visitPolyadicExpression(expression); + } + private static boolean isPerformedRepeatedlyInLoop(@NotNull PsiExpression expression) { if (!ControlFlowUtils.isInLoop(expression)) return false; if (ControlFlowUtils.isInExitStatement(expression)) return false; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/object_allocation_in_loop/ObjectAllocationInLoop.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/object_allocation_in_loop/ObjectAllocationInLoop.java index fb0feb0fedd1..b1b5ca31f14f 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/object_allocation_in_loop/ObjectAllocationInLoop.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/object_allocation_in_loop/ObjectAllocationInLoop.java @@ -87,4 +87,15 @@ class ObjectAllocationInLoop { } static native Integer key(); + + final int CONST = 10; + + void concat() { + for (int i = 0; i < 10; i++) { + String s = "value: " + i; + String s2 = "value: " + CONST; + System.out.println(s); + System.out.println(s2); + } + } } \ No newline at end of file