From a9176c04ea00816b41964b004a45d4c22d5a0700 Mon Sep 17 00:00:00 2001 From: "Kirill.Safonov" Date: Thu, 23 Dec 2010 13:39:07 +0300 Subject: [PATCH] AS move static members, create class from usage, create class/component on UML, create subclass/interface, extract superclass/interface, create Flex skin: allow to choose directory for new class (IDEA-56194) --- .../ide/util/PlatformPackageUtil.java | 275 ++++++++++++++++++ .../ExtractSuperBaseDialog.java | 2 +- 2 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java diff --git a/platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java b/platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java new file mode 100644 index 000000000000..731c2f661715 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java @@ -0,0 +1,275 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide.util; + +import com.intellij.ide.IdeBundle; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectBundle; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.roots.impl.DirectoryIndex; +import com.intellij.openapi.roots.ui.configuration.CommonContentEntriesEditor; +import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.*; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +// TODO this should eventually replace PackageUtil from java-impl +public class PlatformPackageUtil { + + private static final Logger LOG = Logger.getInstance("com.intellij.ide.util.PlatformPackageUtil"); + + @Nullable + private static String findLongestExistingPackage(Project project, String packageName, GlobalSearchScope scope) { + final PsiManager manager = PsiManager.getInstance(project); + DirectoryIndex index = DirectoryIndex.getInstance(project); + + String nameToMatch = packageName; + while (true) { + Query vFiles = index.getDirectoriesByPackageName(nameToMatch, false); + PsiDirectory directory = getWritableModuleDirectory(vFiles, scope, manager); + if (directory != null) return index.getPackageName(directory.getVirtualFile()); + + int lastDotIndex = nameToMatch.lastIndexOf('.'); + if (lastDotIndex >= 0) { + nameToMatch = nameToMatch.substring(0, lastDotIndex); + } + else { + return null; + } + } + } + + @Nullable + private static PsiDirectory getWritableModuleDirectory(@NotNull Query vFiles, + GlobalSearchScope scope, + PsiManager manager) { + for (VirtualFile vFile : vFiles) { + if (!scope.contains(vFile)) continue; + PsiDirectory directory = manager.findDirectory(vFile); + if (directory != null && directory.isValid() && directory.isWritable()) { + return directory; + } + } + return null; + } + + @Nullable + public static PsiDirectory findOrCreateDirectoryForPackage(@NotNull final Project project, + @Nullable Module module, + GlobalSearchScope scope, + String packageName, + PsiDirectory baseDir, + boolean askUserToCreate) throws IncorrectOperationException { + PsiDirectory psiDirectory = null; + if (!"".equals(packageName)) { + String rootPackage = findLongestExistingPackage(project, packageName, scope); + if (rootPackage != null) { + int beginIndex = rootPackage.length() + 1; + packageName = beginIndex < packageName.length() ? packageName.substring(beginIndex) : ""; + String postfixToShow = packageName.replace('.', File.separatorChar); + if (packageName.length() > 0) { + postfixToShow = File.separatorChar + postfixToShow; + } + psiDirectory = + DirectoryChooserUtil.selectDirectory(project, getPackageDirectories(project, rootPackage, scope), baseDir, postfixToShow); + if (psiDirectory == null) return null; + } + } + + if (psiDirectory == null) { + if (module != null && !checkSourceRootsConfigured(module)) return null; + final GlobalSearchScope scope_ = scope; + List dirs = + ContainerUtil + .mapNotNull(ProjectRootManager.getInstance(project).getContentSourceRoots(), new Function() { + @Override + public PsiDirectory fun(VirtualFile virtualFile) { + return scope_.contains(virtualFile) ? PsiManager.getInstance(project).findDirectory(virtualFile) : null; + } + }); + psiDirectory = DirectoryChooserUtil.selectDirectory(project, dirs.toArray(new PsiDirectory[dirs.size()]), baseDir, + File.separatorChar + packageName.replace('.', File.separatorChar)); + if (psiDirectory == null) return null; + } + + String restOfName = packageName; + boolean askedToCreate = false; + while (restOfName.length() > 0) { + final String name = getLeftPart(restOfName); + PsiDirectory foundExistingDirectory = psiDirectory.findSubdirectory(name); + if (foundExistingDirectory == null) { + if (!askedToCreate && askUserToCreate) { + if (!ApplicationManager.getApplication().isUnitTestMode()) { + int toCreate = Messages.showYesNoDialog(project, + IdeBundle.message("prompt.create.non.existing.package", packageName), + IdeBundle.message("title.package.not.found"), + Messages.getQuestionIcon()); + if (toCreate != 0) { + return null; + } + } + askedToCreate = true; + } + + final PsiDirectory psiDirectory_ = psiDirectory; + try { + psiDirectory = ActionRunner.runInsideWriteAction(new ActionRunner.InterruptibleRunnableWithResult() { + public PsiDirectory run() throws Exception { + return psiDirectory_.createSubdirectory(name); + } + }); + } + catch (IncorrectOperationException e) { + throw e; + } + catch (IOException e) { + throw new IncorrectOperationException(e.toString(), e); + } + catch (Exception e) { + LOG.error(e); + } + } + else { + psiDirectory = foundExistingDirectory; + } + restOfName = cutLeftPart(restOfName); + } + return psiDirectory; + } + + public static GlobalSearchScope adjustScope(PsiDirectory baseDir, + GlobalSearchScope scope, + boolean skipSourceDirsForBaseTestDirectory, + boolean skipTestDirsForBaseSourceDirectory) { + if (baseDir != null) { + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(baseDir.getProject()).getFileIndex(); + if (fileIndex.isInTestSourceContent(baseDir.getVirtualFile())) { + if (skipSourceDirsForBaseTestDirectory) { + return scope.intersectWith(GlobalSearchScope.projectTestScope(baseDir.getProject())); + } + } + else { + if (skipTestDirsForBaseSourceDirectory) { + return scope.intersectWith(GlobalSearchScope.projectProductionScope(baseDir.getProject())); + } + } + } + return scope; + } + + private static PsiDirectory[] getPackageDirectories(Project project, String rootPackage, final GlobalSearchScope scope) { + final PsiManager manager = PsiManager.getInstance(project); + + Query query = DirectoryIndex.getInstance(scope.getProject()).getDirectoriesByPackageName(rootPackage, true); + query = new FilteredQuery(query, new Condition() { + @Override + public boolean value(VirtualFile virtualFile) { + return scope.contains(virtualFile); + } + }); + + List directories = ContainerUtil.mapNotNull(query.findAll(), new Function() { + @Override + public PsiDirectory fun(VirtualFile virtualFile) { + return manager.findDirectory(virtualFile); + } + }); + return directories.toArray(new PsiDirectory[directories.size()]); + } + + private static boolean checkSourceRootsConfigured(final Module module) { + VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots(); + if (sourceRoots.length == 0) { + Messages.showErrorDialog( + module.getProject(), + ProjectBundle.message("module.source.roots.not.configured.error", module.getName()), + ProjectBundle.message("module.source.roots.not.configured.title") + ); + + ProjectSettingsService + .getInstance(module.getProject()).showModuleConfigurationDialog(module.getName(), CommonContentEntriesEditor.NAME, false); + + sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots(); + if (sourceRoots.length == 0) { + return false; + } + } + return true; + } + + private static String getLeftPart(String packageName) { + int index = packageName.indexOf('.'); + return index > -1 ? packageName.substring(0, index) : packageName; + } + + private static String cutLeftPart(String packageName) { + int index = packageName.indexOf('.'); + return index > -1 ? packageName.substring(index + 1) : ""; + } + + @Nullable + public static PsiDirectory findPossiblePackageDirectoryInModule(Module module, GlobalSearchScope scope, String packageName) { + if (!"".equals(packageName)) { + String rootPackage = findLongestExistingPackage(module.getProject(), packageName, scope); + if (rootPackage != null) { + final PsiDirectory[] psiDirectories = getPackageDirectories(module.getProject(), rootPackage, scope); + if (psiDirectories.length > 0) { + return psiDirectories[0]; + } + } + } + + if (!checkSourceRootsConfigured(module)) return null; + + final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots(); + for (VirtualFile sourceRoot : sourceRoots) { + final PsiDirectory directory = PsiManager.getInstance(module.getProject()).findDirectory(sourceRoot); + if (directory != null) { + return directory; + } + } + + return null; + } + + @Nullable + public static PsiDirectory getDirectory(PsiElement element) { + PsiFile file = element.getContainingFile(); + final PsiElement context = file.getContext(); + if (context != null) { + file = context.getContainingFile(); + } + return file.getParent(); + } +} diff --git a/platform/lang-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseDialog.java b/platform/lang-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseDialog.java index db14c1c37ae6..6a24a6e51baa 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseDialog.java @@ -207,7 +207,7 @@ public abstract class ExtractSuperBaseDialog