/* * Copyright 2003-2006 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.decls; import com.intellij.codeInsight.highlighting.HighlightManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.StatusBar; import com.intellij.psi.*; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.IntentionPowerPackBundle; import com.siyeh.ipp.base.Intention; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; public class MoveDeclarationIntention extends Intention { @NotNull protected PsiElementPredicate getElementPredicate() { return new MoveDeclarationPredicate(); } public void processIntention(@NotNull PsiElement element) throws IncorrectOperationException { final PsiLocalVariable variable = (PsiLocalVariable)element; final PsiReference[] references = ReferencesSearch.search(variable, variable.getUseScope(), false).toArray(PsiReference.EMPTY_ARRAY); final PsiCodeBlock tightestBlock = MoveDeclarationPredicate.getTightestBlock(references); assert tightestBlock != null; final PsiDeclarationStatement declaration = (PsiDeclarationStatement)variable.getParent(); final PsiReference firstReference = references[0]; final PsiElement referenceElement = firstReference.getElement(); PsiDeclarationStatement newDeclaration; if (tightestBlock.equals(PsiTreeUtil.getParentOfType(referenceElement, PsiCodeBlock.class))) { // containing block of first reference is the same as the common // block of all. newDeclaration = moveDeclarationToReference(referenceElement, variable, tightestBlock); } else { // declaration must be moved to common block (first reference block // is too deep) final PsiElement child = MoveDeclarationPredicate.getChildWhichContainsElement( tightestBlock, referenceElement); newDeclaration = createNewDeclaration(variable, null); newDeclaration = (PsiDeclarationStatement) tightestBlock.addBefore(newDeclaration, child); } assert declaration != null; if (declaration.getDeclaredElements().length == 1) { declaration.delete(); } else { variable.delete(); } highlightElement(newDeclaration); } private static void highlightElement(@NotNull PsiElement element) { final Project project = element.getProject(); final FileEditorManager editorManager = FileEditorManager.getInstance(project); final HighlightManager highlightManager = HighlightManager.getInstance(project); final EditorColorsManager editorColorsManager = EditorColorsManager.getInstance(); final Editor editor = editorManager.getSelectedTextEditor(); final EditorColorsScheme globalScheme = editorColorsManager.getGlobalScheme(); final TextAttributes textattributes = globalScheme.getAttributes( EditorColors.SEARCH_RESULT_ATTRIBUTES); final PsiElement[] elements = new PsiElement[]{element}; highlightManager.addOccurrenceHighlights(editor, elements, textattributes, true, null); StatusBar.Info.set(IntentionPowerPackBundle.message( "status.bar.escape.highlighting.message"), project); } private static PsiDeclarationStatement moveDeclarationToReference( @NotNull PsiElement referenceElement, @NotNull PsiLocalVariable variable, @NotNull PsiCodeBlock block) throws IncorrectOperationException { PsiStatement statement = PsiTreeUtil.getParentOfType(referenceElement, PsiStatement.class); assert statement != null; if (statement.getParent() instanceof PsiForStatement) { statement = (PsiStatement)statement.getParent(); } final PsiElement referenceParent = referenceElement.getParent(); if (referenceParent instanceof PsiAssignmentExpression) { final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)referenceParent; if (referenceElement.equals( assignmentExpression.getLExpression())) { PsiDeclarationStatement newDeclaration = createNewDeclaration(variable, assignmentExpression.getRExpression()); newDeclaration = (PsiDeclarationStatement) block.addBefore(newDeclaration, statement); final PsiElement parent = assignmentExpression.getParent(); assert parent != null; parent.delete(); return newDeclaration; } } return createNewDeclaration(variable, null); } private static PsiDeclarationStatement createNewDeclaration( @NotNull PsiLocalVariable variable, PsiExpression initializer) throws IncorrectOperationException { final PsiManager manager = variable.getManager(); final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); final PsiDeclarationStatement newDeclaration = factory.createVariableDeclarationStatement( variable.getName(), variable.getType(), initializer); if (variable.hasModifierProperty(PsiModifier.FINAL)) { final PsiLocalVariable newVariable = (PsiLocalVariable)newDeclaration.getDeclaredElements()[0]; final PsiModifierList modifierList = newVariable.getModifierList(); modifierList.setModifierProperty(PsiModifier.FINAL, true); } return newDeclaration; } }