91f0f6be7c791e2cd4d8f39659a5fd43cfe46466
[idea/community.git] / java / java-impl / src / com / intellij / psi / impl / file / PsiPackageImplementationHelperImpl.java
1 /*
2  * Copyright 2000-2011 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 package com.intellij.psi.impl.file;
17
18 import com.intellij.ide.projectView.ProjectView;
19 import com.intellij.ide.projectView.impl.PackageViewPane;
20 import com.intellij.ide.projectView.impl.ProjectRootsUtil;
21 import com.intellij.ide.projectView.impl.nodes.PackageElement;
22 import com.intellij.openapi.application.ApplicationManager;
23 import com.intellij.openapi.command.undo.GlobalUndoableAction;
24 import com.intellij.openapi.command.undo.UndoManager;
25 import com.intellij.openapi.module.Module;
26 import com.intellij.openapi.module.ModuleManager;
27 import com.intellij.openapi.project.Project;
28 import com.intellij.openapi.roots.*;
29 import com.intellij.openapi.vfs.VfsUtil;
30 import com.intellij.openapi.vfs.VirtualFile;
31 import com.intellij.openapi.wm.ToolWindow;
32 import com.intellij.openapi.wm.ToolWindowId;
33 import com.intellij.openapi.wm.ToolWindowManager;
34 import com.intellij.psi.NonClasspathClassFinder;
35 import com.intellij.psi.PsiDirectory;
36 import com.intellij.psi.PsiPackage;
37 import com.intellij.psi.impl.PackagePrefixElementFinder;
38 import com.intellij.psi.search.GlobalSearchScope;
39 import com.intellij.psi.util.PsiModificationTracker;
40
41 import java.util.ArrayList;
42 import java.util.List;
43
44 /**
45  * @author yole
46  */
47 public class PsiPackageImplementationHelperImpl extends PsiPackageImplementationHelper {
48   @Override
49   public GlobalSearchScope adjustAllScope(PsiPackage psiPackage, GlobalSearchScope globalSearchScope) {
50     return NonClasspathClassFinder.addNonClasspathScope(psiPackage.getProject(), globalSearchScope);
51   }
52
53   @Override
54   public VirtualFile[] occursInPackagePrefixes(PsiPackage psiPackage) {
55     List<VirtualFile> result = new ArrayList<VirtualFile>();
56     final Module[] modules = ModuleManager.getInstance(psiPackage.getProject()).getModules();
57
58     for (final Module module : modules) {
59       final ContentEntry[] contentEntries = ModuleRootManager.getInstance(module).getContentEntries();
60       for (final ContentEntry contentEntry : contentEntries) {
61         final SourceFolder[] sourceFolders = contentEntry.getSourceFolders();
62         for (final SourceFolder sourceFolder : sourceFolders) {
63           final String packagePrefix = sourceFolder.getPackagePrefix();
64           if (packagePrefix.startsWith(psiPackage.getQualifiedName())) {
65             final VirtualFile file = sourceFolder.getFile();
66             if (file != null) {
67               result.add(file);
68             }
69           }
70         }
71       }
72     }
73
74     return VfsUtil.toVirtualFileArray(result);
75   }
76
77   @Override
78   public void handleQualifiedNameChange(final PsiPackage psiPackage, final String newQualifiedName) {
79     ApplicationManager.getApplication().assertWriteAccessAllowed();
80     final String oldQualifedName = psiPackage.getQualifiedName();
81     final boolean anyChanged = changePackagePrefixes(psiPackage, oldQualifedName, newQualifiedName);
82     if (anyChanged) {
83       UndoManager.getInstance(psiPackage.getProject()).undoableActionPerformed(new GlobalUndoableAction() {
84         @Override
85         public void undo() {
86           changePackagePrefixes(psiPackage, newQualifiedName, oldQualifedName);
87         }
88
89         @Override
90         public void redo() {
91           changePackagePrefixes(psiPackage, oldQualifedName, newQualifiedName);
92         }
93       });
94     }
95   }
96
97   private static boolean changePackagePrefixes(PsiPackage psiPackage, final String oldQualifiedName, final String newQualifiedName) {
98     final Module[] modules = ModuleManager.getInstance(psiPackage.getProject()).getModules();
99     List<ModifiableRootModel> modelsToCommit = new ArrayList<ModifiableRootModel>();
100     for (final Module module : modules) {
101       boolean anyChange = false;
102       final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module).getModifiableModel();
103       final ContentEntry[] contentEntries = rootModel.getContentEntries();
104       for (final ContentEntry contentEntry : contentEntries) {
105         final SourceFolder[] sourceFolders = contentEntry.getSourceFolders();
106         for (final SourceFolder sourceFolder : sourceFolders) {
107           final String packagePrefix = sourceFolder.getPackagePrefix();
108           if (packagePrefix.startsWith(oldQualifiedName)) {
109             sourceFolder.setPackagePrefix(newQualifiedName + packagePrefix.substring(oldQualifiedName.length()));
110             anyChange = true;
111           }
112         }
113       }
114       if (anyChange) {
115         modelsToCommit.add(rootModel);
116       } else {
117         rootModel.dispose();
118       }
119     }
120
121     if (!modelsToCommit.isEmpty()) {
122       ProjectRootManager.getInstance(psiPackage.getProject()).multiCommit(
123         modelsToCommit.toArray(new ModifiableRootModel[modelsToCommit.size()])
124       );
125       return true;
126     } else {
127       return false;
128     }
129   }
130
131   @Override
132   public void navigate(final PsiPackage psiPackage, final boolean requestFocus) {
133     final Project project = psiPackage.getProject();
134     ToolWindow window = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.PROJECT_VIEW);
135     window.activate(null);
136     window.getActivation().doWhenDone(new Runnable() {
137       @Override
138       public void run() {
139         final ProjectView projectView = ProjectView.getInstance(project);
140         projectView.changeView(PackageViewPane.ID);
141         final PsiDirectory[] directories = psiPackage.getDirectories();
142         final VirtualFile firstDir = directories[0].getVirtualFile();
143         final boolean isLibraryRoot = ProjectRootsUtil.isLibraryRoot(firstDir, project);
144
145         final Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(firstDir);
146         final PackageElement packageElement = new PackageElement(module, psiPackage, isLibraryRoot);
147         projectView.getProjectViewPaneById(PackageViewPane.ID).select(packageElement, firstDir, requestFocus);
148       }
149     });
150   }
151
152   @Override
153   public boolean packagePrefixExists(PsiPackage psiPackage) {
154     return PackagePrefixElementFinder.getInstance(psiPackage.getProject()).packagePrefixExists(psiPackage.getQualifiedName());
155   }
156
157   @Override
158   public Object[] getDirectoryCachedValueDependencies(PsiPackage psiPackage) {
159     return new Object[] { PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, ProjectRootManager.getInstance(psiPackage.getProject()) };
160   }
161 }