2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com
.intellij
.refactoring
.rename
;
19 import com
.intellij
.featureStatistics
.FeatureUsageTracker
;
20 import com
.intellij
.openapi
.actionSystem
.DataContext
;
21 import com
.intellij
.openapi
.actionSystem
.DataKey
;
22 import com
.intellij
.openapi
.actionSystem
.PlatformDataKeys
;
23 import com
.intellij
.openapi
.application
.ApplicationManager
;
24 import com
.intellij
.openapi
.diagnostic
.Logger
;
25 import com
.intellij
.openapi
.editor
.Editor
;
26 import com
.intellij
.openapi
.editor
.ScrollType
;
27 import com
.intellij
.openapi
.extensions
.ExtensionPointName
;
28 import com
.intellij
.openapi
.extensions
.Extensions
;
29 import com
.intellij
.openapi
.project
.Project
;
30 import com
.intellij
.openapi
.util
.Condition
;
31 import com
.intellij
.psi
.*;
32 import com
.intellij
.psi
.impl
.source
.tree
.injected
.InjectedLanguageUtil
;
33 import com
.intellij
.psi
.meta
.PsiMetaOwner
;
34 import com
.intellij
.psi
.meta
.PsiWritableMetaData
;
35 import com
.intellij
.refactoring
.RefactoringBundle
;
36 import com
.intellij
.refactoring
.actions
.BaseRefactoringAction
;
37 import com
.intellij
.refactoring
.util
.CommonRefactoringUtil
;
38 import com
.intellij
.usageView
.UsageViewUtil
;
39 import com
.intellij
.codeInsight
.daemon
.impl
.CollectHighlightsUtil
;
40 import org
.jetbrains
.annotations
.NotNull
;
41 import org
.jetbrains
.annotations
.Nullable
;
44 * created at Nov 13, 2001
48 public class PsiElementRenameHandler
implements RenameHandler
{
49 private static final Logger LOG
= Logger
.getInstance("#com.intellij.refactoring.rename.PsiElementRenameHandler");
51 public static final ExtensionPointName
<Condition
<PsiElement
>> VETO_RENAME_CONDITION_EP
= ExtensionPointName
.create("com.intellij.vetoRenameCondition");
52 public static DataKey
<String
> DEFAULT_NAME
= DataKey
.create("DEFAULT_NAME");
54 public void invoke(@NotNull Project project
, Editor editor
, PsiFile file
, DataContext dataContext
) {
55 PsiElement element
= getElement(dataContext
);
56 editor
.getScrollingModel().scrollToCaret(ScrollType
.MAKE_VISIBLE
);
57 final PsiElement nameSuggestionContext
= file
.findElementAt(editor
.getCaretModel().getOffset());
58 invoke(element
, project
, nameSuggestionContext
, editor
);
61 public void invoke(@NotNull Project project
, @NotNull PsiElement
[] elements
, DataContext dataContext
) {
62 PsiElement element
= elements
.length
== 1 ? elements
[0] : null;
63 if (element
== null) element
= getElement(dataContext
);
64 LOG
.assertTrue(element
!= null);
65 Editor editor
= PlatformDataKeys
.EDITOR
.getData(dataContext
);
66 if (ApplicationManager
.getApplication().isUnitTestMode()) {
67 final String newName
= DEFAULT_NAME
.getData(dataContext
);
68 LOG
.assertTrue(newName
!= null);
69 rename(element
, project
, element
, editor
, newName
);
72 invoke(element
, project
, element
, editor
);
76 public static void invoke(PsiElement element
, Project project
, PsiElement nameSuggestionContext
, Editor editor
) {
77 if (element
!= null && !canRename(project
, editor
, element
)) {
80 FeatureUsageTracker
.getInstance().triggerFeatureUsed("refactoring.rename");
82 rename(element
, project
, nameSuggestionContext
, editor
);
85 static boolean canRename(Project project
, Editor editor
, PsiElement element
) {
86 if (element
== null) return false;
87 if (!(element
instanceof PsiFile
) && CollectHighlightsUtil
.isOutsideSourceRootJavaFile(element
.getContainingFile())) return false;
88 boolean hasRenameProcessor
= RenamePsiElementProcessor
.forElement(element
) != RenamePsiElementProcessor
.DEFAULT
;
89 boolean hasWritableMetaData
= element
instanceof PsiMetaOwner
&& ((PsiMetaOwner
)element
).getMetaData() instanceof PsiWritableMetaData
;
91 if (!hasRenameProcessor
&& !hasWritableMetaData
&& !(element
instanceof PsiNamedElement
)) {
92 String message
= RefactoringBundle
.getCannotRefactorMessage(RefactoringBundle
.message("error.wrong.caret.position.symbol.to.rename"));
93 if (!ApplicationManager
.getApplication().isUnitTestMode()) {
94 showErrorMessage(project
, editor
, message
);
99 if (!PsiManager
.getInstance(project
).isInProject(element
) && element
.isPhysical()) {
100 String message
= RefactoringBundle
101 .getCannotRefactorMessage(RefactoringBundle
.message("error.out.of.project.element", UsageViewUtil
.getType(element
)));
102 showErrorMessage(project
, editor
, message
);
106 if (InjectedLanguageUtil
.isInInjectedLanguagePrefixSuffix(element
)) {
107 String message
= RefactoringBundle
.getCannotRefactorMessage(RefactoringBundle
.message("error.in.injected.lang.prefix.suffix", UsageViewUtil
.getType(element
)));
108 showErrorMessage(project
, editor
, message
);
112 return true;//CommonRefactoringUtil.checkReadOnlyStatus(project, element);
115 private static void showErrorMessage(Project project
, Editor editor
, String message
) {
116 CommonRefactoringUtil
.showErrorHint(project
, editor
, message
, RefactoringBundle
.message("rename.title"), null);
119 public static void rename(PsiElement element
, final Project project
, PsiElement nameSuggestionContext
, Editor editor
) {
120 rename(element
, project
, nameSuggestionContext
, editor
, null);
123 private static void rename(PsiElement element
, final Project project
, PsiElement nameSuggestionContext
, Editor editor
, final String defaultName
) {
124 RenamePsiElementProcessor processor
= RenamePsiElementProcessor
.forElement(element
);
125 element
= processor
.substituteElementToRename(element
, editor
);
126 if (element
== null) return;
128 final RenameDialog dialog
= new RenameDialog(project
, element
, nameSuggestionContext
, editor
);
129 if (defaultName
!= null) {
130 dialog
.performRename(defaultName
);
137 public boolean isAvailableOnDataContext(DataContext dataContext
) {
138 return !isVetoed(getElement(dataContext
));
141 public static boolean isVetoed(PsiElement element
) {
142 if (element
== null || element
instanceof SyntheticElement
) return true;
143 for(Condition
<PsiElement
> condition
: Extensions
.getExtensions(VETO_RENAME_CONDITION_EP
)) {
144 if (condition
.value(element
)) return true;
150 public static PsiElement
getElement(final DataContext dataContext
) {
151 PsiElement
[] elementArray
= BaseRefactoringAction
.getPsiElementArray(dataContext
);
153 if (elementArray
.length
!= 1) {
156 return elementArray
[0];
159 public boolean isRenaming(DataContext dataContext
) {
160 return isAvailableOnDataContext(dataContext
);