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.
18 * Created by IntelliJ IDEA.
23 package com
.intellij
.xml
.refactoring
;
25 import com
.intellij
.featureStatistics
.FeatureUsageTracker
;
26 import com
.intellij
.lang
.Language
;
27 import com
.intellij
.openapi
.actionSystem
.DataContext
;
28 import com
.intellij
.openapi
.actionSystem
.LangDataKeys
;
29 import com
.intellij
.openapi
.actionSystem
.PlatformDataKeys
;
30 import com
.intellij
.openapi
.diagnostic
.Logger
;
31 import com
.intellij
.openapi
.editor
.Editor
;
32 import com
.intellij
.openapi
.project
.Project
;
33 import com
.intellij
.patterns
.PlatformPatterns
;
34 import com
.intellij
.psi
.PsiElement
;
35 import com
.intellij
.psi
.PsiFile
;
36 import com
.intellij
.psi
.PsiManager
;
37 import com
.intellij
.psi
.util
.PsiUtilBase
;
38 import com
.intellij
.psi
.xml
.XmlFile
;
39 import com
.intellij
.psi
.xml
.XmlTag
;
40 import com
.intellij
.refactoring
.actions
.BaseRefactoringAction
;
41 import com
.intellij
.refactoring
.rename
.RenameHandler
;
42 import com
.intellij
.refactoring
.rename
.PsiElementRenameHandler
;
43 import com
.intellij
.xml
.XmlElementDescriptor
;
44 import com
.intellij
.xml
.impl
.schema
.AnyXmlElementDescriptor
;
45 import org
.jetbrains
.annotations
.NotNull
;
46 import org
.jetbrains
.annotations
.Nullable
;
48 public class XmlTagRenameHandler
implements RenameHandler
{
49 private static final Logger LOG
= Logger
.getInstance("#com.intellij.xml.refactoring.XmlTagRenameHandler");
52 public boolean isAvailableOnDataContext(final DataContext dataContext
) {
53 final PsiElement element
= getElement(dataContext
);
54 if (PsiElementRenameHandler
.isVetoed(element
)) return false;
55 //noinspection ConstantConditions
56 return PlatformPatterns
.psiElement().withParent(XmlTag
.class).accepts(element
) &&
57 isDeclarationOutOfProjectOrAbsent(element
.getProject(), dataContext
);
60 public boolean isRenaming(final DataContext dataContext
) {
61 return isAvailableOnDataContext(dataContext
);
64 private static boolean isInplaceRenameAvailable(final Editor editor
) {
65 return editor
.getSettings().isVariableInplaceRenameEnabled();
68 private static boolean isDeclarationOutOfProjectOrAbsent(@NotNull final Project project
, final DataContext context
) {
69 final PsiElement
[] elements
= BaseRefactoringAction
.getPsiElementArray(context
);
70 return elements
.length
== 0 || elements
.length
== 1 && shouldBeRenamedInplace(project
, elements
);
73 private static boolean shouldBeRenamedInplace(Project project
, PsiElement
[] elements
) {
74 boolean inProject
= PsiManager
.getInstance(project
).isInProject(elements
[0]);
75 if (inProject
&& elements
[0] instanceof XmlTag
) {
76 XmlElementDescriptor descriptor
= ((XmlTag
)elements
[0]).getDescriptor();
77 return descriptor
instanceof AnyXmlElementDescriptor
;
83 private static Editor
getEditor(@Nullable DataContext context
) {
84 return PlatformDataKeys
.EDITOR
.getData(context
);
88 private static PsiElement
getElement(@Nullable final DataContext context
) {
89 if (context
!= null) {
90 final Editor editor
= getEditor(context
);
92 final int offset
= editor
.getCaretModel().getOffset();
93 final PsiFile file
= LangDataKeys
.PSI_FILE
.getData(context
);
94 if (file
instanceof XmlFile
) {
95 return file
.getViewProvider().findElementAt(offset
);
98 final Language language
= PsiUtilBase
.getLanguageAtOffset(file
, offset
);
99 if (language
!= file
.getLanguage()) {
100 final PsiFile psiAtOffset
= file
.getViewProvider().getPsi(language
);
101 if (psiAtOffset
instanceof XmlFile
) {
102 return psiAtOffset
.findElementAt(offset
);
112 private void invoke(@Nullable final Editor editor
, @NotNull final PsiElement element
, @Nullable final DataContext context
) {
113 if (!isRenaming(context
)) {
117 FeatureUsageTracker
.getInstance().triggerFeatureUsed("refactoring.rename");
119 if (isInplaceRenameAvailable(editor
)) {
120 XmlTagInplaceRenamer
.rename(editor
, (XmlTag
)element
.getParent());
123 XmlTagRenameDialog
.renameXmlTag(editor
, element
, (XmlTag
)element
.getParent());
127 public void invoke(@NotNull final Project project
, final Editor editor
, final PsiFile file
, @Nullable final DataContext dataContext
) {
128 if (!isRenaming(dataContext
)) {
132 final PsiElement element
= getElement(dataContext
);
133 assert element
!= null;
135 invoke(editor
, element
, dataContext
);
138 public void invoke(@NotNull final Project project
, @NotNull final PsiElement
[] elements
, @Nullable final DataContext dataContext
) {
139 PsiElement element
= elements
.length
== 1 ? elements
[0] : null;
140 if (element
== null) {
141 element
= getElement(dataContext
);
144 LOG
.assertTrue(element
!= null);
145 invoke(getEditor(dataContext
), element
, dataContext
);