blob: 7ad0f6b1559338469630e7c286b46765a56f673d [file] [log] [blame]
/*
* 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;
}
}