| /* |
| * 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. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.siyeh.ipp.concatenation; |
| |
| import com.intellij.openapi.project.Project; |
| import com.intellij.psi.*; |
| import com.intellij.psi.codeStyle.CodeStyleManager; |
| import com.intellij.psi.codeStyle.CodeStyleSettings; |
| import com.intellij.psi.codeStyle.CodeStyleSettingsManager; |
| import com.intellij.util.IncorrectOperationException; |
| import com.siyeh.ipp.base.Intention; |
| import com.siyeh.ipp.base.PsiElementPredicate; |
| import com.siyeh.ipp.psiutils.HighlightUtil; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| public class MakeCallChainIntoCallSequenceIntention extends Intention { |
| |
| @Override |
| @NotNull |
| protected PsiElementPredicate getElementPredicate() { |
| return new MethodCallChainPredicate(); |
| } |
| |
| @Override |
| public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException { |
| final List<String> callTexts = new ArrayList<String>(); |
| PsiExpression root = (PsiExpression)element; |
| while (root instanceof PsiMethodCallExpression) { |
| final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) root; |
| final PsiExpressionList arguments = methodCallExpression.getArgumentList(); |
| final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); |
| callTexts.add(methodExpression.getReferenceName() + arguments.getText()); |
| root = methodExpression.getQualifierExpression(); |
| if (root == null) { |
| return; |
| } |
| } |
| final PsiType rootType = root.getType(); |
| if (rootType == null) { |
| return; |
| } |
| final String targetText; |
| final PsiStatement appendStatement; |
| @NonNls final String firstStatement; |
| final String variableDeclaration; |
| final boolean showRenameTemplate; |
| final PsiElement parent = element.getParent(); |
| if (parent instanceof PsiExpressionStatement) { |
| targetText = root.getText(); |
| appendStatement = (PsiStatement)parent; |
| firstStatement = null; |
| variableDeclaration = null; |
| showRenameTemplate = false; |
| } |
| else { |
| final PsiElement grandParent = parent.getParent(); |
| appendStatement = (PsiStatement)grandParent; |
| if (parent instanceof PsiAssignmentExpression && grandParent instanceof PsiExpressionStatement) { |
| final PsiAssignmentExpression assignment = (PsiAssignmentExpression)parent; |
| final PsiExpression lhs = assignment.getLExpression(); |
| if (!(lhs instanceof PsiReferenceExpression)) { |
| return; |
| } |
| final PsiReferenceExpression expression = (PsiReferenceExpression)lhs; |
| final PsiElement target = expression.resolve(); |
| if (!(target instanceof PsiVariable)) { |
| return; |
| } |
| final PsiVariable variable = (PsiVariable)target; |
| final PsiType variableType = variable.getType(); |
| if (variableType.equals(rootType)) { |
| targetText = lhs.getText(); |
| final PsiJavaToken token = assignment.getOperationSign(); |
| firstStatement = targetText + token.getText() + root.getText() + ';'; |
| showRenameTemplate = false; |
| } else { |
| targetText = "x"; |
| showRenameTemplate = true; |
| final Project project = element.getProject(); |
| final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); |
| if (codeStyleSettings.GENERATE_FINAL_LOCALS) { |
| firstStatement = "final " + rootType.getCanonicalText() + ' ' + targetText + '=' + root.getText() + ';'; |
| } else { |
| firstStatement = rootType.getCanonicalText() + ' ' + targetText + '=' + root.getText() + ';'; |
| } |
| } |
| variableDeclaration = null; |
| } |
| else { |
| final PsiDeclarationStatement declaration = (PsiDeclarationStatement)appendStatement; |
| final PsiVariable variable = (PsiVariable)declaration.getDeclaredElements()[0]; |
| final PsiType variableType = variable.getType(); |
| if (variableType.equals(rootType)) { |
| targetText = variable.getName(); |
| if (variable.hasModifierProperty(PsiModifier.FINAL)) { |
| firstStatement = "final " + variableType.getCanonicalText() + ' ' + variable.getName() + '=' + root.getText() + ';'; |
| } |
| else { |
| firstStatement = variableType.getCanonicalText() + ' ' + variable.getName() + '=' + root.getText() + ';'; |
| } |
| variableDeclaration = null; |
| showRenameTemplate = false; |
| } else { |
| if (variable.hasModifierProperty(PsiModifier.FINAL)) { |
| variableDeclaration = "final " + variableType.getCanonicalText() + ' ' + variable.getName() + '='; |
| } |
| else { |
| variableDeclaration = variableType.getCanonicalText() + ' ' + variable.getName() + '='; |
| } |
| targetText = "x"; |
| showRenameTemplate = true; |
| final Project project = element.getProject(); |
| final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project); |
| if (codeStyleSettings.GENERATE_FINAL_LOCALS) { |
| firstStatement = "final " + rootType.getCanonicalText() + " x=" + root.getText() + ';'; |
| } else { |
| firstStatement = rootType.getCanonicalText() + " x=" + root.getText() + ';'; |
| } |
| } |
| } |
| } |
| final StringBuilder builder = new StringBuilder("{\n"); |
| if (firstStatement != null) { |
| builder.append(firstStatement); |
| } |
| Collections.reverse(callTexts); |
| for (int i = 0, size = callTexts.size(); i < size; i++) { |
| final String callText = callTexts.get(i); |
| if (i == size - 1 && variableDeclaration != null) { |
| builder.append(variableDeclaration); |
| } |
| builder.append(targetText).append('.').append(callText).append(";\n"); |
| } |
| builder.append('}'); |
| final PsiManager manager = element.getManager(); |
| final Project project = manager.getProject(); |
| final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); |
| final PsiElement appendStatementParent = appendStatement.getParent(); |
| final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject()); |
| final PsiCodeBlock codeBlock = factory.createCodeBlockFromText(builder.toString(), appendStatement); |
| if (appendStatementParent instanceof PsiLoopStatement || appendStatementParent instanceof PsiIfStatement) { |
| final PsiElement insertedCodeBlock = appendStatement.replace(codeBlock); |
| final PsiCodeBlock reformattedCodeBlock = (PsiCodeBlock)codeStyleManager.reformat(insertedCodeBlock); |
| if (showRenameTemplate) { |
| final PsiStatement[] statements = reformattedCodeBlock.getStatements(); |
| final PsiVariable variable = (PsiVariable)((PsiDeclarationStatement) statements[0]).getDeclaredElements()[0]; |
| HighlightUtil.showRenameTemplate(appendStatementParent, variable); |
| } |
| } |
| else { |
| final PsiStatement[] statements = codeBlock.getStatements(); |
| PsiVariable variable = null; |
| for (int i = 0, length = statements.length; i < length; i++) { |
| final PsiElement insertedStatement = appendStatementParent.addBefore(statements[i], appendStatement); |
| if (i == 0 && showRenameTemplate) { |
| variable = (PsiVariable)((PsiDeclarationStatement) insertedStatement).getDeclaredElements()[0]; |
| } |
| codeStyleManager.reformat(insertedStatement); |
| } |
| appendStatement.delete(); |
| if (variable != null) { |
| HighlightUtil.showRenameTemplate(appendStatementParent, variable); |
| } |
| } |
| } |
| } |