mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Fix "String concatenation in loop" inspection for polyadic expressions
This commit is contained in:
+20
-38
@@ -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;
|
||||
|
||||
+6
@@ -46,4 +46,10 @@ public class StringConcatenationInLoop
|
||||
s += k;
|
||||
}
|
||||
}
|
||||
|
||||
void bla() {
|
||||
while (true) {
|
||||
System.out.println("a" + "b" + "c");
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -22,6 +22,13 @@
|
||||
<description>String concatenation <code>+</code> 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 <code>+</code> in loop #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>StringConcatenationInLoop.java</file>
|
||||
<line>46</line>
|
||||
@@ -29,4 +36,10 @@
|
||||
<description>String concatenation <code>+=</code> 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 <code>+=</code> in loop #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
|
||||
+3
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user