diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/AppendChainPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/AppendChainPredicate.java
new file mode 100644
index 000000000000..c57a407e59c0
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/AppendChainPredicate.java
@@ -0,0 +1,38 @@
+package com.siyeh.ipp.concatenation;
+
+import com.intellij.psi.*;
+import com.siyeh.ipp.base.PsiElementPredicate;
+
+class AppendChainPredicate implements PsiElementPredicate{
+ public boolean satisfiedBy(PsiElement element){
+ if(!(element instanceof PsiMethodCallExpression)){
+ return false;
+ }
+ final PsiMethodCallExpression call = (PsiMethodCallExpression) element;
+ if(!AppendUtil.isAppend(call))
+ {
+ return false;
+ }
+ final PsiReferenceExpression methodExpression =
+ call.getMethodExpression();
+ final PsiExpression qualifier = methodExpression.getQualifierExpression();
+ if(!(qualifier instanceof PsiMethodCallExpression)){
+ return false;
+ }
+ final PsiMethodCallExpression qualifierCall = (PsiMethodCallExpression) element;
+ if(!AppendUtil.isAppend(qualifierCall)){
+ return false;
+ }
+ final PsiElement parent = element.getParent();
+ if(parent instanceof PsiExpressionStatement)
+ return true;
+ if(parent instanceof PsiLocalVariable && parent.getParent() instanceof PsiDeclarationStatement &&
+ ( (PsiDeclarationStatement)(parent.getParent())).getDeclaredElements().length == 1)
+ return true;
+ if(parent instanceof PsiAssignmentExpression &&
+ parent.getParent() instanceof PsiExpressionStatement)
+ return true;
+ return false;
+ }
+
+}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/AppendUtil.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/AppendUtil.java
new file mode 100644
index 000000000000..689327e7c93d
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/AppendUtil.java
@@ -0,0 +1,32 @@
+package com.siyeh.ipp.concatenation;
+
+import com.intellij.psi.PsiMethodCallExpression;
+import com.intellij.psi.PsiReferenceExpression;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiClass;
+
+public class AppendUtil{
+ public static boolean isAppend(PsiMethodCallExpression call)
+ {
+ final PsiReferenceExpression methodExpression =
+ call.getMethodExpression();
+ if(methodExpression == null){
+ return false;
+ }
+ final String callName = methodExpression.getReferenceName();
+ if(!"append".equals(callName)){
+ return false;
+ }
+ final PsiMethod method = call.resolveMethod();
+ if(method == null){
+ return false;
+ }
+ final PsiClass containingClass = method.getContainingClass();
+ if(containingClass == null){
+ return false;
+ }
+ final String name = containingClass.getQualifiedName();
+ return "java.lang.StringBuffer".equals(name)||
+ "java.lang.StringBuilder".equals(name);
+ }
+}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/MakeAppendChainIntoAppendSequenceIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/MakeAppendChainIntoAppendSequenceIntention.java
new file mode 100644
index 000000000000..df7552e3a2d1
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/MakeAppendChainIntoAppendSequenceIntention.java
@@ -0,0 +1,107 @@
+package com.siyeh.ipp.concatenation;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ipp.base.Intention;
+import com.siyeh.ipp.base.PsiElementPredicate;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class MakeAppendChainIntoAppendSequenceIntention extends Intention{
+ protected PsiElementPredicate getElementPredicate(){
+ return new AppendChainPredicate();
+ }
+
+ public String getText(){
+ return "Make .append() chain into .append() sequence";
+ }
+
+ public String getFamilyName(){
+ return "Make Append Chain Into Append Sequence";
+ }
+
+ public void invoke(Project project, Editor editor, PsiFile file)
+ throws IncorrectOperationException{
+ if(isFileReadOnly(project, file)){
+ return;
+ }
+
+ PsiExpression call =
+ (PsiExpression) findMatchingElement(file, editor);
+ final List argsList = new ArrayList();
+ PsiExpression currentCall = call;
+ while(currentCall instanceof PsiMethodCallExpression &&
+ AppendUtil.isAppend((PsiMethodCallExpression) currentCall)){
+ final PsiExpressionList args =
+ ((PsiMethodCallExpression) currentCall).getArgumentList();
+ final String argText = args.getText();
+ argsList.add(argText);
+ final PsiReferenceExpression methodExpression =
+ ((PsiMethodCallExpression) currentCall).getMethodExpression();
+ currentCall = methodExpression.getQualifierExpression();
+ }
+ final String targetText;
+ final String firstTargetText;
+ final PsiManager mgr = PsiManager.getInstance(project);
+ final PsiElementFactory factory = mgr.getElementFactory();
+ final CodeStyleManager codeStyleManager = mgr.getCodeStyleManager();
+ final PsiStatement statement;
+ final String firstStatementPreamble;
+ if(call.getParent() instanceof PsiExpressionStatement){
+ targetText = currentCall.getText();
+ firstTargetText = currentCall.getText();
+ statement = (PsiStatement) call.getParent();
+ firstStatementPreamble = "";
+ } else if(call.getParent() instanceof PsiAssignmentExpression &&
+ call.getParent()
+ .getParent() instanceof PsiExpressionStatement){
+ statement = (PsiStatement) call.getParent().getParent();
+ final PsiAssignmentExpression assignment =
+ (PsiAssignmentExpression) call.getParent();
+ targetText = assignment.getLExpression().getText();
+ firstTargetText = currentCall.getText();
+ firstStatementPreamble =
+ assignment.getLExpression().getText() +
+ assignment.getOperationSign().getText();
+ } else{
+ statement = (PsiStatement) call.getParent().getParent();
+ final PsiDeclarationStatement declaration =
+ (PsiDeclarationStatement) statement;
+ final PsiVariable variable =
+ (PsiVariable) declaration.getDeclaredElements()[0];
+ targetText = variable.getName();
+ firstTargetText = currentCall.getText();
+ if(variable.hasModifierProperty(PsiModifier.FINAL)){
+ firstStatementPreamble = "final " +
+ variable.getType().getPresentableText() +
+ ' ' + variable.getName() + '=';
+ } else{
+ firstStatementPreamble =
+ variable.getType().getPresentableText() +
+ ' ' + variable.getName() + '=';
+ }
+ }
+
+ for(Iterator iterator = argsList.iterator(); iterator.hasNext();){
+ final String arg = (String) iterator.next();
+ final String append;
+ if(iterator.hasNext()){
+ append = targetText + ".append" + arg + ';';
+ } else{
+ append = firstStatementPreamble +
+ firstTargetText + ".append" + arg + ';';
+ }
+ final PsiStatement newCall =
+ factory.createStatementFromText(append, null);
+ final PsiElement insertedElement = statement.getParent()
+ .addAfter(newCall, statement);
+ codeStyleManager.reformat(insertedElement);
+ }
+ statement.delete();
+ }
+}
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/Make Append Chain Into Append Sequence/after.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/Make Append Chain Into Append Sequence/after.java.template
new file mode 100644
index 000000000000..c01ad8e932ba
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/Make Append Chain Into Append Sequence/after.java.template
@@ -0,0 +1,7 @@
+public class X {
+ void f(String a, String b) {
+ StringBuffer buffer = new StringBuffer
+ buffer.append(a);
+ buffer.append(b);
+ }
+}}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/Make Append Chain Into Append Sequence/before.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/Make Append Chain Into Append Sequence/before.java.template
new file mode 100644
index 000000000000..bc0c2d52b0aa
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/Make Append Chain Into Append Sequence/before.java.template
@@ -0,0 +1,6 @@
+public class X {
+ void f(String a, String b) {
+ StringBuffer buffer = new StringBuffer
+