IDEADEV-40480
[fedora-idea.git] / platform / lang-impl / src / com / intellij / refactoring / rename / PsiElementRenameHandler.java
blob860e59d8a47ff06ee9118de03f9d242a0e3a66ae
1 package com.intellij.refactoring.rename;
3 import com.intellij.featureStatistics.FeatureUsageTracker;
4 import com.intellij.openapi.actionSystem.DataContext;
5 import com.intellij.openapi.actionSystem.DataKey;
6 import com.intellij.openapi.actionSystem.PlatformDataKeys;
7 import com.intellij.openapi.application.ApplicationManager;
8 import com.intellij.openapi.diagnostic.Logger;
9 import com.intellij.openapi.editor.Editor;
10 import com.intellij.openapi.editor.ScrollType;
11 import com.intellij.openapi.extensions.ExtensionPointName;
12 import com.intellij.openapi.extensions.Extensions;
13 import com.intellij.openapi.project.Project;
14 import com.intellij.openapi.util.Condition;
15 import com.intellij.psi.*;
16 import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
17 import com.intellij.psi.meta.PsiMetaOwner;
18 import com.intellij.psi.meta.PsiWritableMetaData;
19 import com.intellij.refactoring.RefactoringBundle;
20 import com.intellij.refactoring.actions.BaseRefactoringAction;
21 import com.intellij.refactoring.util.CommonRefactoringUtil;
22 import com.intellij.usageView.UsageViewUtil;
23 import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil;
24 import org.jetbrains.annotations.NotNull;
25 import org.jetbrains.annotations.Nullable;
27 /**
28 * created at Nov 13, 2001
30 * @author Jeka, dsl
32 public class PsiElementRenameHandler implements RenameHandler {
33 private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.rename.PsiElementRenameHandler");
35 public static final ExtensionPointName<Condition<PsiElement>> VETO_RENAME_CONDITION_EP = ExtensionPointName.create("com.intellij.vetoRenameCondition");
36 public static DataKey<String> DEFAULT_NAME = DataKey.create("DEFAULT_NAME");
38 public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
39 PsiElement element = getElement(dataContext);
40 editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
41 final PsiElement nameSuggestionContext = file.findElementAt(editor.getCaretModel().getOffset());
42 invoke(element, project, nameSuggestionContext, editor);
45 public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
46 PsiElement element = elements.length == 1 ? elements[0] : null;
47 if (element == null) element = getElement(dataContext);
48 LOG.assertTrue(element != null);
49 Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
50 if (ApplicationManager.getApplication().isUnitTestMode()) {
51 final String newName = DEFAULT_NAME.getData(dataContext);
52 LOG.assertTrue(newName != null);
53 rename(element, project, element, editor, newName);
55 else {
56 invoke(element, project, element, editor);
60 public static void invoke(PsiElement element, Project project, PsiElement nameSuggestionContext, Editor editor) {
61 if (element != null && !canRename(project, editor, element)) {
62 return;
64 FeatureUsageTracker.getInstance().triggerFeatureUsed("refactoring.rename");
66 rename(element, project, nameSuggestionContext, editor);
69 static boolean canRename(Project project, Editor editor, PsiElement element) {
70 if (element == null) return false;
71 if (!(element instanceof PsiFile) && CollectHighlightsUtil.isOutsideSourceRootJavaFile(element.getContainingFile())) return false;
72 boolean hasRenameProcessor = RenamePsiElementProcessor.forElement(element) != RenamePsiElementProcessor.DEFAULT;
73 boolean hasWritableMetaData = element instanceof PsiMetaOwner && ((PsiMetaOwner)element).getMetaData() instanceof PsiWritableMetaData;
75 if (!hasRenameProcessor && !hasWritableMetaData && !(element instanceof PsiNamedElement)) {
76 String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("error.wrong.caret.position.symbol"));
77 if (!ApplicationManager.getApplication().isUnitTestMode()) {
78 showErrorMessage(project, editor, message);
80 return false;
83 if (!PsiManager.getInstance(project).isInProject(element) && element.isPhysical()) {
84 String message = RefactoringBundle
85 .getCannotRefactorMessage(RefactoringBundle.message("error.out.of.project.element", UsageViewUtil.getType(element)));
86 showErrorMessage(project, editor, message);
87 return false;
90 if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(element)) {
91 String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("error.in.injected.lang.prefix.suffix", UsageViewUtil.getType(element)));
92 showErrorMessage(project, editor, message);
93 return false;
96 return true;//CommonRefactoringUtil.checkReadOnlyStatus(project, element);
99 private static void showErrorMessage(Project project, Editor editor, String message) {
100 CommonRefactoringUtil.showErrorHint(project, editor, message, RefactoringBundle.message("rename.title"), null);
103 public static void rename(PsiElement element, final Project project, PsiElement nameSuggestionContext, Editor editor) {
104 rename(element, project, nameSuggestionContext, editor, null);
107 private static void rename(PsiElement element, final Project project, PsiElement nameSuggestionContext, Editor editor, final String defaultName) {
108 RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element);
109 element = processor.substituteElementToRename(element, editor);
110 if (element == null) return;
112 final RenameDialog dialog = new RenameDialog(project, element, nameSuggestionContext, editor);
113 if (defaultName != null) {
114 dialog.performRename(defaultName);
116 else {
117 dialog.show();
121 public boolean isAvailableOnDataContext(DataContext dataContext) {
122 return !isVetoed(getElement(dataContext));
125 public static boolean isVetoed(PsiElement element) {
126 if (element == null || element instanceof SyntheticElement) return true;
127 for(Condition<PsiElement> condition: Extensions.getExtensions(VETO_RENAME_CONDITION_EP)) {
128 if (condition.value(element)) return true;
130 return false;
133 @Nullable
134 public static PsiElement getElement(final DataContext dataContext) {
135 PsiElement[] elementArray = BaseRefactoringAction.getPsiElementArray(dataContext);
137 if (elementArray.length != 1) {
138 return null;
140 return elementArray[0];
143 public boolean isRenaming(DataContext dataContext) {
144 return isAvailableOnDataContext(dataContext);