blob: 8d9b4f7fe1f03748ed1eebaa9184f225f396b3d2 [file] [log] [blame]
/*
* Copyright 2000-2009 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.refactoring.tempWithQuery;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.extractMethod.ExtractMethodHandler;
import com.intellij.refactoring.extractMethod.ExtractMethodProcessor;
import com.intellij.refactoring.extractMethod.PrepareFailedException;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.duplicates.DuplicatesImpl;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
public class TempWithQueryHandler implements RefactoringActionHandler {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.tempWithQuery.TempWithQueryHandler");
private static final String REFACTORING_NAME = RefactoringBundle.message("replace.temp.with.query.title");
public void invoke(@NotNull final Project project, final Editor editor, PsiFile file, DataContext dataContext) {
PsiElement element = TargetElementUtilBase.findTargetElement(editor, TargetElementUtilBase
.ELEMENT_NAME_ACCEPTED | TargetElementUtilBase
.LOOKUP_ITEM_ACCEPTED | TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED);
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
if (!(element instanceof PsiLocalVariable)) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("error.wrong.caret.position.local.name"));
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
return;
}
invokeOnVariable(file, project, (PsiLocalVariable)element, editor);
}
private static void invokeOnVariable(final PsiFile file, final Project project, final PsiLocalVariable local, final Editor editor) {
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) return;
String localName = local.getName();
final PsiExpression initializer = local.getInitializer();
if (initializer == null) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.has.no.initializer", localName));
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
return;
}
final PsiReference[] refs = ReferencesSearch.search(local, GlobalSearchScope.projectScope(project), false).toArray(new PsiReference[0]);
if (refs.length == 0) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.is.never.used", localName));
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
return;
}
final HighlightManager highlightManager = HighlightManager.getInstance(project);
ArrayList<PsiReference> array = new ArrayList<PsiReference>();
EditorColorsManager manager = EditorColorsManager.getInstance();
final TextAttributes attributes = manager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
for (PsiReference ref : refs) {
PsiElement refElement = ref.getElement();
if (PsiUtil.isAccessedForWriting((PsiExpression)refElement)) {
array.add(ref);
}
if (!array.isEmpty()) {
PsiReference[] refsForWriting = array.toArray(new PsiReference[array.size()]);
highlightManager.addOccurrenceHighlights(editor, refsForWriting, attributes, true, null);
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("variable.is.accessed.for.writing", localName));
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
return;
}
}
final ExtractMethodProcessor processor = new ExtractMethodProcessor(
project, editor,
new PsiElement[]{initializer}, local.getType(),
REFACTORING_NAME, localName, HelpID.REPLACE_TEMP_WITH_QUERY
);
try {
if (!processor.prepare()) return;
}
catch (PrepareFailedException e) {
CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
ExtractMethodHandler.highlightPrepareError(e, file, editor, project);
return;
}
final PsiClass targetClass = processor.getTargetClass();
if (targetClass != null && targetClass.isInterface()) {
String message = RefactoringBundle.message("cannot.replace.temp.with.query.in.interface");
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.REPLACE_TEMP_WITH_QUERY);
return;
}
if (processor.showDialog()) {
CommandProcessor.getInstance().executeCommand(
project, new Runnable() {
public void run() {
final Runnable action = new Runnable() {
public void run() {
try {
processor.doRefactoring();
local.normalizeDeclaration();
PsiExpression initializer = local.getInitializer();
PsiExpression[] exprs = new PsiExpression[refs.length];
for (int idx = 0; idx < refs.length; idx++) {
PsiElement ref = refs[idx].getElement();
exprs[idx] = (PsiExpression) ref.replace(initializer);
}
PsiDeclarationStatement declaration = (PsiDeclarationStatement) local.getParent();
declaration.delete();
highlightManager.addOccurrenceHighlights(editor, exprs, attributes, true, null);
} catch (IncorrectOperationException e) {
LOG.error(e);
}
}
};
PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(new Runnable () {
public void run() {
ApplicationManager.getApplication().runWriteAction(action);
DuplicatesImpl.processDuplicates(processor, project, editor);
}
});
}
},
REFACTORING_NAME,
null
);
}
WindowManager.getInstance().getStatusBar(project).setInfo(RefactoringBundle.message("press.escape.to.remove.the.highlighting"));
}
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
if (elements.length == 1 && elements[0] instanceof PsiLocalVariable) {
if (dataContext != null) {
final PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext);
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
if (file != null && editor != null) {
invokeOnVariable(file, project, (PsiLocalVariable)elements[0], editor);
}
}
}
}
}