Merge remote-tracking branch 'origin/master'

This commit is contained in:
Alexey Kudravtsev
2013-10-17 13:42:33 +04:00
6 changed files with 134 additions and 19 deletions
@@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -45,27 +46,29 @@ public class AdjustAutotestDelayActionGroup extends ActionGroup {
public AnAction[] getChildren(@Nullable AnActionEvent e) {
final AnAction[] actions = new AnAction[MAX_DELAY];
for (int i = 0; i < MAX_DELAY; i++) {
actions[i] = new SetAutoTestDelayAction(i + 1);
actions[i] = new SetAutoTestDelayAction(myEnvironment.getProject(), i + 1);
}
return actions;
}
private static class SetAutoTestDelayAction extends ToggleAction {
private final int myDelay;
@NotNull private final Project myProject;
public SetAutoTestDelayAction(int delay) {
public SetAutoTestDelayAction(@NotNull Project project, int delay) {
super(delay + "s");
myProject = project;
myDelay = delay * 1000;
}
@Override
public boolean isSelected(AnActionEvent e) {
return AutoTestManager.getInstance(e.getProject()).getDelay() == myDelay;
return AutoTestManager.getInstance(myProject).getDelay() == myDelay;
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
AutoTestManager.getInstance(e.getProject()).setDelay(myDelay);
AutoTestManager.getInstance(myProject).setDelay(myDelay);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2013 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.
@@ -21,6 +21,7 @@ import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -31,8 +32,6 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class StringBufferReplaceableByStringBuilderInspection extends BaseInspection {
@@ -151,8 +150,8 @@ public class StringBufferReplaceableByStringBuilderInspection extends BaseInspec
private static class StringBufferReplaceableByStringBuilderVisitor extends BaseInspectionVisitor {
private static final Set<String> excludes = new HashSet(Arrays.asList(CommonClassNames.JAVA_LANG_STRING_BUILDER,
CommonClassNames.JAVA_LANG_STRING_BUFFER));
private static final Set<String> excludes = ContainerUtil.newHashSet(CommonClassNames.JAVA_LANG_STRING_BUILDER,
CommonClassNames.JAVA_LANG_STRING_BUFFER);
@Override
public void visitDeclarationStatement(PsiDeclarationStatement statement) {
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -31,7 +32,6 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class StringBufferReplaceableByStringInspection extends BaseInspection {
@@ -257,7 +257,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection {
private final PsiVariable myVariable;
private final StringBuilder myBuilder;
private final List<PsiMethodCallExpression> expressions = new ArrayList();
private final List<PsiMethodCallExpression> expressions = ContainerUtil.newArrayList();
private boolean myProblem = false;
public StringBuildingVisitor(@NotNull PsiVariable variable, StringBuilder builder) {
@@ -425,8 +425,9 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection {
private static class ReplaceableByStringVisitor extends JavaRecursiveElementVisitor {
private final PsiElement myParent;
private PsiVariable myVariable;
private final PsiVariable myVariable;
private boolean myReplaceable = true;
private boolean myPossibleSideEffect = false;
private boolean myToStringFound = false;
public ReplaceableByStringVisitor(@NotNull PsiVariable variable) {
@@ -450,7 +451,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection {
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
if (expression.getTextOffset() > myVariable.getTextOffset() && !myToStringFound) {
myReplaceable = false;
myPossibleSideEffect = true;
}
}
@@ -458,7 +459,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection {
public void visitPostfixExpression(PsiPostfixExpression expression) {
super.visitPostfixExpression(expression);
if (expression.getTextOffset() > myVariable.getTextOffset() && !myToStringFound) {
myReplaceable = false;
myPossibleSideEffect = true;
}
}
@@ -466,10 +467,77 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection {
public void visitPrefixExpression(PsiPrefixExpression expression) {
super.visitPrefixExpression(expression);
if (expression.getTextOffset() > myVariable.getTextOffset() && !myToStringFound) {
myReplaceable = false;
myPossibleSideEffect = true;
}
}
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
if (expression.getTextOffset() < myVariable.getTextOffset() || myToStringFound) {
return;
}
final PsiMethod method = expression.resolveMethod();
if (method == null) {
myPossibleSideEffect = true;
return;
}
final PsiClass aClass = method.getContainingClass();
if (aClass == null) {
myPossibleSideEffect = true;
return;
}
final String name = aClass.getQualifiedName();
if (CommonClassNames.JAVA_LANG_STRING_BUFFER.equals(name) ||
CommonClassNames.JAVA_LANG_STRING_BUILDER.equals(name)) {
return;
}
if (isArgumentOfStringBuilderMethod(expression)) {
return;
}
myPossibleSideEffect = true;
}
private boolean isArgumentOfStringBuilderMethod(PsiMethodCallExpression expression) {
final PsiElement parent = expression.getParent();
if (!(parent instanceof PsiExpressionList)) {
return false;
}
final PsiElement grandParent = parent.getParent();
if (!(grandParent instanceof PsiMethodCallExpression)) {
return false;
}
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)grandParent;
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
PsiExpression qualifier = methodExpression.getQualifierExpression();
while (qualifier instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)qualifier;
final PsiReferenceExpression methodExpression1 = callExpression.getMethodExpression();
qualifier = methodExpression1.getQualifierExpression();
}
if (qualifier instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
final PsiElement target = referenceExpression.resolve();
if (!myVariable.equals(target)) {
return false;
}
}
final PsiMethod method = methodCallExpression.resolveMethod();
if (method == null) {
return false;
}
final PsiClass aClass = method.getContainingClass();
if (aClass == null) {
return false;
}
final String name1 = aClass.getQualifiedName();
if (CommonClassNames.JAVA_LANG_STRING_BUFFER.equals(name1) ||
CommonClassNames.JAVA_LANG_STRING_BUILDER.equals(name1)) {
return true;
}
return false;
}
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
if (!myReplaceable || expression.getTextOffset() < myVariable.getTextOffset()) {
@@ -508,6 +576,10 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection {
myToStringFound = true;
return;
}
if (myPossibleSideEffect) {
myReplaceable = false;
return;
}
parent = grandParent.getParent();
if (parent instanceof PsiExpressionStatement) {
return;
@@ -39,12 +39,12 @@ public class StringBufferReplaceableByString {
public void assignment(int p) {
StringBuilder b = new StringBuilder();
b.append(p);
p++;
b.append(p);
System.out.println(b.toString());
StringBuilder c = new StringBuilder();
c.append(p);
p = 2;
c.append(p);
System.out.println(c.toString());
StringBuilder d = new StringBuilder();
@@ -79,4 +79,38 @@ public class StringBufferReplaceableByString {
data.append(String.format("%02d:%02d", Math.abs(hours), min));
return data.toString();
}
class HighlightStaticImport {
void example1() {
System.out.println();
final StringBuilder builder = new StringBuilder();
builder.append(foo1());
b(); // side effect
builder.append(foo1());
bar(builder.toString());
System.out.println();
}
void example2() {
final StringBuilder builder = new StringBuilder();
builder.append(foo1());
b(); // side effect, but has no effect on builder anymore
bar(builder.toString());
}
String s;
void b() {
s = "asdf";
}
private void bar(String s) {
}
private String foo1() {
return null;
}
}
}
@@ -36,4 +36,11 @@
<description>&lt;code&gt;StringBuilder d&lt;/code&gt; can be replaced with 'String' #loc</description>
</problem>
<problem>
<file>StringBufferReplaceableByString.java</file>
<line>96</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'StringBuffer' can be replaced with 'String'</problem_class>
<description>&lt;code&gt;StringBuilder builder&lt;/code&gt; can be replaced with 'String' #loc</description>
</problem>
</problems>
@@ -33,7 +33,7 @@ org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=Java:
#org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=
#org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=
#org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=Java:ALIGN_GROUP_FIELD_DECLARATIONS
#org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=Java:ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION
#org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=Java:SPACE_BEFORE_FOR_PARENTHESES
@@ -65,7 +65,7 @@ org.eclipse.jdt.core.formatter.blank_lines_before_package=Java:BLANK_LINES_BEFOR
#org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=Java:SPACE_BEFORE_COMMA
#org.eclipse.jdt.core.formatter.blank_lines_before_member_type=
#org.eclipse.jdt.core.formatter.align_type_members_on_columns=
org.eclipse.jdt.core.formatter.align_type_members_on_columns=Java:ALIGN_GROUP_FIELD_DECLARATIONS
#org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=Java:SPACE_WITHIN_FOR_PARENTHESES
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=Java:SPACE_BEFORE_METHOD_PARENTHESES