Fix "String concatenation in loop" inspection for polyadic expressions

This commit is contained in:
Bas Leijdekkers
2012-09-27 21:15:26 +02:00
parent fd84b9a936
commit 06f5380031
5 changed files with 62 additions and 69 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,9 +32,7 @@ import javax.swing.JComponent;
public class StringConcatenationInLoopsInspection extends BaseInspection {
/**
* @noinspection PublicField
*/
@SuppressWarnings("PublicField")
public boolean m_ignoreUnlessAssigned = true;
@Override
@@ -46,23 +44,19 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"string.concatenation.in.loops.display.name");
return InspectionGadgetsBundle.message("string.concatenation.in.loops.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"string.concatenation.in.loops.problem.descriptor");
return InspectionGadgetsBundle.message("string.concatenation.in.loops.problem.descriptor");
}
@Override
public JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(
InspectionGadgetsBundle.message(
"string.concatenation.in.loops.only.option"),
this, "m_ignoreUnlessAssigned");
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("string.concatenation.in.loops.only.option"),
this, "m_ignoreUnlessAssigned");
}
@Override
@@ -70,12 +64,12 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
return new StringConcatenationInLoopsVisitor();
}
private class StringConcatenationInLoopsVisitor
extends BaseInspectionVisitor {
private class StringConcatenationInLoopsVisitor extends BaseInspectionVisitor {
@Override
public void visitPolyadicExpression(PsiPolyadicExpression expression) {
super.visitPolyadicExpression(expression);
PsiExpression[] operands = expression.getOperands();
final PsiExpression[] operands = expression.getOperands();
if (operands.length <= 1) {
return;
}
@@ -107,8 +101,7 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
}
@Override
public void visitAssignmentExpression(
@NotNull PsiAssignmentExpression expression) {
public void visitAssignmentExpression(@NotNull PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
if (expression.getRExpression() == null) {
return;
@@ -137,8 +130,7 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
}
if (m_ignoreUnlessAssigned) {
while (lhs instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression =
(PsiParenthesizedExpression)lhs;
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)lhs;
lhs = parenthesizedExpression.getExpression();
}
if (!(lhs instanceof PsiReferenceExpression)) {
@@ -149,52 +141,42 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
}
private boolean containingStatementExits(PsiElement element) {
final PsiStatement newExpressionStatement =
PsiTreeUtil.getParentOfType(element, PsiStatement.class);
final PsiStatement newExpressionStatement = PsiTreeUtil.getParentOfType(element, PsiStatement.class);
if (newExpressionStatement == null) {
return containingStatementExits(element);
}
final PsiStatement parentStatement =
PsiTreeUtil.getParentOfType(newExpressionStatement,
PsiStatement.class);
return !ControlFlowUtils.statementMayCompleteNormally(
parentStatement);
final PsiStatement parentStatement = PsiTreeUtil.getParentOfType(newExpressionStatement, PsiStatement.class);
return !ControlFlowUtils.statementMayCompleteNormally(parentStatement);
}
private boolean isAppendedRepeatedly(PsiExpression expression) {
PsiElement parent = expression.getParent();
while (parent instanceof PsiParenthesizedExpression ||
parent instanceof PsiPolyadicExpression) {
while (parent instanceof PsiParenthesizedExpression || parent instanceof PsiPolyadicExpression) {
parent = parent.getParent();
}
if (!(parent instanceof PsiAssignmentExpression)) {
return false;
}
final PsiAssignmentExpression assignmentExpression =
(PsiAssignmentExpression)parent;
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
PsiExpression lhs = assignmentExpression.getLExpression();
while (lhs instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression =
(PsiParenthesizedExpression)lhs;
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)lhs;
lhs = parenthesizedExpression.getExpression();
}
if (!(lhs instanceof PsiReferenceExpression)) {
return false;
}
if (assignmentExpression.getOperationTokenType() ==
JavaTokenType.PLUSEQ) {
if (assignmentExpression.getOperationTokenType() == JavaTokenType.PLUSEQ) {
return true;
}
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)lhs;
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
final PsiElement element = referenceExpression.resolve();
if (!(element instanceof PsiVariable)) {
return false;
}
final PsiVariable variable = (PsiVariable)element;
final PsiExpression rhs = assignmentExpression.getRExpression();
return rhs != null &&
VariableAccessUtils.variableIsUsed(variable, rhs);
return rhs != null && VariableAccessUtils.variableIsUsed(variable, rhs);
}
}
}
@@ -87,28 +87,27 @@ public class ExpressionUtils {
field.hasModifierProperty(PsiModifier.FINAL);
}
public static boolean isEvaluatedAtCompileTime(
@Nullable PsiExpression expression) {
public static boolean isEvaluatedAtCompileTime(@Nullable PsiExpression expression) {
if (expression instanceof PsiLiteralExpression) {
return true;
}
if (expression instanceof PsiBinaryExpression) {
final PsiBinaryExpression binaryExpression =
(PsiBinaryExpression)expression;
final PsiExpression lhs = binaryExpression.getLOperand();
final PsiExpression rhs = binaryExpression.getROperand();
return isEvaluatedAtCompileTime(lhs) &&
isEvaluatedAtCompileTime(rhs);
if (expression instanceof PsiPolyadicExpression) {
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
final PsiExpression[] operands = polyadicExpression.getOperands();
for (PsiExpression operand : operands) {
if (!isEvaluatedAtCompileTime(operand)) {
return false;
}
}
return true;
}
if (expression instanceof PsiPrefixExpression) {
final PsiPrefixExpression prefixExpression =
(PsiPrefixExpression)expression;
final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression;
final PsiExpression operand = prefixExpression.getOperand();
return isEvaluatedAtCompileTime(operand);
}
if (expression instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression =
(PsiReferenceExpression)expression;
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiElement qualifier = referenceExpression.getQualifier();
if (qualifier instanceof PsiThisExpression) {
return false;
@@ -117,8 +116,7 @@ public class ExpressionUtils {
if (element instanceof PsiField) {
final PsiField field = (PsiField)element;
final PsiExpression initializer = field.getInitializer();
return field.hasModifierProperty(PsiModifier.FINAL) &&
isEvaluatedAtCompileTime(initializer);
return field.hasModifierProperty(PsiModifier.FINAL) && isEvaluatedAtCompileTime(initializer);
}
if (element instanceof PsiVariable) {
final PsiVariable variable = (PsiVariable)element;
@@ -126,32 +124,25 @@ public class ExpressionUtils {
return false;
}
final PsiExpression initializer = variable.getInitializer();
return variable.hasModifierProperty(PsiModifier.FINAL) &&
isEvaluatedAtCompileTime(initializer);
return variable.hasModifierProperty(PsiModifier.FINAL) && isEvaluatedAtCompileTime(initializer);
}
}
if (expression instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression =
(PsiParenthesizedExpression)expression;
final PsiExpression deparenthesizedExpression =
parenthesizedExpression.getExpression();
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
final PsiExpression deparenthesizedExpression = parenthesizedExpression.getExpression();
return isEvaluatedAtCompileTime(deparenthesizedExpression);
}
if (expression instanceof PsiConditionalExpression) {
final PsiConditionalExpression conditionalExpression =
(PsiConditionalExpression)expression;
final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)expression;
final PsiExpression condition = conditionalExpression.getCondition();
final PsiExpression thenExpression =
conditionalExpression.getThenExpression();
final PsiExpression elseExpression =
conditionalExpression.getElseExpression();
final PsiExpression thenExpression = conditionalExpression.getThenExpression();
final PsiExpression elseExpression = conditionalExpression.getElseExpression();
return isEvaluatedAtCompileTime(condition) &&
isEvaluatedAtCompileTime(thenExpression) &&
isEvaluatedAtCompileTime(elseExpression);
}
if (expression instanceof PsiTypeCastExpression) {
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)expression;
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)expression;
final PsiTypeElement castType = typeCastExpression.getCastType();
if (castType == null) {
return false;
@@ -46,4 +46,10 @@ public class StringConcatenationInLoop
s += k;
}
}
void bla() {
while (true) {
System.out.println("a" + "b" + "c");
}
}
}
@@ -22,6 +22,13 @@
<description>String concatenation &lt;code&gt;+&lt;/code&gt; in loop #loc</description>
</problem>
<problem>
<file>StringConcatenationInLoop.java</file>
<line>16</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">String concatenation in loop</problem_class>
<description>String concatenation &lt;code&gt;+&lt;/code&gt; in loop #loc</description>
</problem>
<problem>
<file>StringConcatenationInLoop.java</file>
<line>46</line>
@@ -29,4 +36,10 @@
<description>String concatenation &lt;code&gt;+=&lt;/code&gt; in loop #loc</description>
</problem>
<problem>
<file>StringConcatenationInLoop.java</file>
<line>45</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">String concatenation in loop</problem_class>
<description>String concatenation &lt;code&gt;+=&lt;/code&gt; in loop #loc</description>
</problem>
</problems>
@@ -5,7 +5,8 @@ import com.siyeh.ig.IGInspectionTestCase;
public class StringConcatenationInLoopsInspectionTest extends IGInspectionTestCase {
public void test() throws Exception {
doTest("com/siyeh/igtest/performance/string_concatenation_in_loops",
new StringConcatenationInLoopsInspection());
final StringConcatenationInLoopsInspection tool = new StringConcatenationInLoopsInspection();
tool.m_ignoreUnlessAssigned = false;
doTest("com/siyeh/igtest/performance/string_concatenation_in_loops", tool);
}
}