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