| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * 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.intellij.codeInsight.intention.impl; |
| |
| import com.intellij.codeInsight.CodeInsightBundle; |
| import com.intellij.codeInsight.FileModificationService; |
| import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; |
| import com.intellij.lang.java.JavaLanguage; |
| 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.psi.javadoc.PsiDocComment; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.refactoring.util.RefactoringUtil; |
| import com.intellij.util.IncorrectOperationException; |
| import org.jetbrains.annotations.NotNull; |
| |
| /** |
| * @author max |
| */ |
| public class SplitDeclarationAction extends PsiElementBaseIntentionAction { |
| @Override |
| @NotNull |
| public String getFamilyName() { |
| return CodeInsightBundle.message("intention.split.declaration.family"); |
| } |
| |
| @Override |
| public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { |
| |
| if (element instanceof PsiCompiledElement) return false; |
| if (!element.getManager().isInProject(element)) return false; |
| if (!element.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return false; |
| |
| final PsiElement context = PsiTreeUtil.getParentOfType(element, PsiDeclarationStatement.class, PsiClass.class); |
| if (context instanceof PsiDeclarationStatement) { |
| return isAvailableOnDeclarationStatement((PsiDeclarationStatement)context, element); |
| } |
| |
| PsiField field = PsiTreeUtil.getParentOfType(element, PsiField.class); |
| if (field != null && PsiTreeUtil.getParentOfType(element, PsiDocComment.class) == null && isAvailableOnField(field)) { |
| setText(CodeInsightBundle.message("intention.split.declaration.text")); |
| return true; |
| } |
| return false; |
| } |
| |
| private static boolean isAvailableOnField(PsiField field) { |
| final PsiTypeElement typeElement = field.getTypeElement(); |
| if (typeElement == null) return false; |
| if (PsiTreeUtil.getParentOfType(typeElement, PsiField.class) != field) return true; |
| |
| PsiElement nextField = field.getNextSibling(); |
| while (nextField != null && !(nextField instanceof PsiField)) nextField = nextField.getNextSibling(); |
| |
| if (nextField != null && ((PsiField)nextField).getTypeElement() == typeElement) return true; |
| |
| return false; |
| } |
| |
| private boolean isAvailableOnDeclarationStatement(PsiDeclarationStatement decl, PsiElement element) { |
| PsiElement[] declaredElements = decl.getDeclaredElements(); |
| if (declaredElements.length == 0) return false; |
| if (!(declaredElements[0] instanceof PsiLocalVariable)) return false; |
| if (declaredElements.length == 1) { |
| PsiLocalVariable var = (PsiLocalVariable)declaredElements[0]; |
| if (var.getInitializer() == null) return false; |
| setText(CodeInsightBundle.message("intention.split.declaration.assignment.text")); |
| return true; |
| } |
| else if (declaredElements.length > 1) { |
| if (decl.getParent() instanceof PsiForStatement) return false; |
| |
| setText(CodeInsightBundle.message("intention.split.declaration.text")); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { |
| if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; |
| |
| final PsiDeclarationStatement decl = PsiTreeUtil.getParentOfType(element, PsiDeclarationStatement.class); |
| |
| final PsiManager psiManager = PsiManager.getInstance(project); |
| if (decl != null) { |
| invokeOnDeclarationStatement(decl, psiManager, project); |
| } |
| else { |
| PsiField field = PsiTreeUtil.getParentOfType(element, PsiField.class); |
| if (field != null) { |
| field.normalizeDeclaration(); |
| } |
| } |
| } |
| |
| private static void invokeOnDeclarationStatement(PsiDeclarationStatement decl, PsiManager psiManager, |
| Project project) throws IncorrectOperationException { |
| if (decl.getDeclaredElements().length == 1) { |
| PsiLocalVariable var = (PsiLocalVariable)decl.getDeclaredElements()[0]; |
| var.normalizeDeclaration(); |
| PsiExpressionStatement statement = (PsiExpressionStatement)JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory() |
| .createStatementFromText(var.getName() + "=xxx;", null); |
| statement = (PsiExpressionStatement)CodeStyleManager.getInstance(project).reformat(statement); |
| PsiAssignmentExpression assignment = (PsiAssignmentExpression)statement.getExpression(); |
| PsiExpression initializer = var.getInitializer(); |
| PsiExpression rExpression = RefactoringUtil.convertInitializerToNormalExpression(initializer, var.getType()); |
| |
| assignment.getRExpression().replace(rExpression); |
| initializer.delete(); |
| |
| PsiElement block = decl.getParent(); |
| if (block instanceof PsiForStatement) { |
| final PsiDeclarationStatement varDeclStatement = |
| JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createVariableDeclarationStatement(var.getName(), var.getType(), null); |
| |
| // For index can't be final, right? |
| for (PsiElement varDecl : varDeclStatement.getDeclaredElements()) { |
| if (varDecl instanceof PsiModifierListOwner) { |
| final PsiModifierList modList = ((PsiModifierListOwner)varDecl).getModifierList(); |
| assert modList != null; |
| modList.setModifierProperty(PsiModifier.FINAL, false); |
| } |
| } |
| |
| final PsiElement parent = block.getParent(); |
| decl.replace(statement); |
| if (!(parent instanceof PsiCodeBlock)) { |
| final PsiBlockStatement blockStatement = |
| (PsiBlockStatement)JavaPsiFacade.getElementFactory(project).createStatementFromText("{}", null); |
| final PsiCodeBlock codeBlock = blockStatement.getCodeBlock(); |
| codeBlock.add(varDeclStatement); |
| codeBlock.add(block); |
| block.replace(blockStatement); |
| } |
| else { |
| parent.addBefore(varDeclStatement, block); |
| } |
| } |
| else { |
| block.addAfter(statement, decl); |
| } |
| } |
| else { |
| ((PsiLocalVariable)decl.getDeclaredElements()[0]).normalizeDeclaration(); |
| } |
| } |
| } |