PHP HTML injection
[idea/community.git] / plugins / groovy / src / org / jetbrains / plugins / groovy / refactoring / move / MoveGroovyClassHandler.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package org.jetbrains.plugins.groovy.refactoring.move;
18
19 import com.intellij.psi.*;
20 import com.intellij.psi.impl.source.tree.Factory;
21 import com.intellij.psi.impl.source.tree.TreeElement;
22 import com.intellij.psi.javadoc.PsiDocComment;
23 import com.intellij.psi.search.LocalSearchScope;
24 import com.intellij.psi.search.searches.ReferencesSearch;
25 import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassHandler;
26 import com.intellij.util.IncorrectOperationException;
27 import org.jetbrains.annotations.NotNull;
28 import org.jetbrains.plugins.groovy.GroovyFileType;
29 import org.jetbrains.plugins.groovy.actions.GroovyTemplatesFactory;
30 import org.jetbrains.plugins.groovy.actions.NewGroovyActionBase;
31 import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
32 import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
33 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
34 import org.jetbrains.plugins.groovy.refactoring.GroovyChangeContextUtil;
35
36 /**
37  * @author Maxim.Medvedev
38  */
39 public class MoveGroovyClassHandler implements MoveClassHandler {
40   public PsiClass doMoveClass(@NotNull PsiClass aClass, @NotNull PsiDirectory moveDestination) throws IncorrectOperationException {
41     if (!aClass.getLanguage().equals(GroovyFileType.GROOVY_LANGUAGE)) return null;
42     PsiFile file = aClass.getContainingFile();
43     final PsiPackage newPackage = JavaDirectoryService.getInstance().getPackage(moveDestination);
44
45     GroovyChangeContextUtil.encodeContextInfo(aClass);
46
47     PsiClass newClass = null;
48     if (file instanceof GroovyFile) {
49       if (((GroovyFile)file).isScript() || ((GroovyFile)file).getClasses().length > 1) {
50         correctSelfReferences(aClass, newPackage);
51         final PsiClass created = ((GroovyFile)GroovyTemplatesFactory
52           .createFromTemplate(moveDestination, aClass.getName(), aClass.getName() + NewGroovyActionBase.GROOVY_EXTENSION,
53                               "GroovyClass.groovy")).getClasses()[0];
54         if (aClass.getDocComment() == null) {
55           final PsiDocComment createdDocComment = created.getDocComment();
56           if (createdDocComment != null) {
57             aClass.addBefore(createdDocComment, null);
58           }
59         }
60         newClass = (PsiClass)created.replace(aClass);
61         correctOldClassReferences(newClass, aClass);
62         aClass.delete();
63       }
64       else if (!moveDestination.equals(file.getContainingDirectory()) && moveDestination.findFile(file.getName()) != null) {
65         // moving second of two classes which were in the same file to a different directory (IDEADEV-3089)
66         correctSelfReferences(aClass, newPackage);
67         PsiFile newFile = moveDestination.findFile(file.getName());
68         TreeElement enter = Factory.createSingleLeafElement(GroovyTokenTypes.mNLS, "\n", 0, 1, null, aClass.getManager());
69         newFile.getNode().addChild(enter);
70         newClass = (PsiClass)newFile.add(aClass);
71         aClass.delete();
72       }
73       else if (!moveDestination.equals(file.getContainingDirectory()) && moveDestination.findFile(file.getName()) == null) {
74         if (!moveDestination.equals(file.getContainingDirectory())) {
75           aClass.getManager().moveFile(file, moveDestination);
76           newClass=((GroovyFile)file).getClasses()[0];
77           if (newPackage != null) {
78             ((PsiClassOwner)file).setPackageName(newPackage.getQualifiedName());
79           }
80         }
81       }
82     }
83     if (newClass != null) GroovyChangeContextUtil.decodeContextInfo(newClass, null, null);
84     return newClass;
85   }
86
87   private static void correctOldClassReferences(final PsiClass newClass, final PsiClass oldClass) {
88     for (PsiReference reference : ReferencesSearch.search(oldClass, new LocalSearchScope(newClass)).findAll()) {
89       reference.bindToElement(newClass);
90     }
91   }
92
93   private static void correctSelfReferences(final PsiClass aClass, final PsiPackage newContainingPackage) {
94     final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(aClass.getContainingFile().getContainingDirectory());
95     if (aPackage == null) {
96       return;
97     }
98
99     for (PsiReference reference : ReferencesSearch.search(aClass, new LocalSearchScope(aClass)).findAll()) {
100       if (reference instanceof GrCodeReferenceElement) {
101         final GrCodeReferenceElement qualifier = ((GrCodeReferenceElement)reference).getQualifier();
102         if (qualifier != null) {
103           qualifier.bindToElement(newContainingPackage);
104         }
105       }
106     }
107   }
108
109   public String getName(PsiClass clazz) {
110     final PsiFile file = clazz.getContainingFile();
111     if (!(file instanceof GroovyFile)) return null;
112     return ((GroovyFile)file).getClasses().length > 1 ? clazz.getName() + "." + GroovyFileType.DEFAULT_EXTENSION : file.getName();
113   }
114
115 }