public void doClone(PsiElement element) { FeatureUsageTracker.getInstance().triggerFeatureUsed("refactoring.copyClass"); PsiClass[] classes = getTopLevelClasses(element); if (classes == null) { CopyFilesOrDirectoriesHandler.doCloneFile(element); return; } Project project = element.getProject(); CopyClassDialog dialog = new CopyClassDialog(classes[0], null, project, true); dialog.setTitle(RefactoringBundle.message("copy.handler.clone.class")); dialog.show(); if (dialog.isOK()) { String className = dialog.getClassName(); PsiDirectory targetDirectory = element.getContainingFile().getContainingDirectory(); copyClassesImpl( className, project, Collections.singletonMap(classes[0].getContainingFile(), classes), null, targetDirectory, targetDirectory, RefactoringBundle.message("copy.handler.clone.class"), true, true); } }
private static PsiFile copy( @NotNull PsiFile file, PsiDirectory directory, String name, String relativePath, int[] choice) { final String fileName = getNewFileName(file, name); if (relativePath != null && !relativePath.isEmpty()) { return buildRelativeDir(directory, relativePath) .findOrCreateTargetDirectory() .copyFileFrom(fileName, file); } if (CopyFilesOrDirectoriesHandler.checkFileExist(directory, choice, file, fileName, "Copy")) return null; return directory.copyFileFrom(fileName, file); }
@Nullable public static PsiElement doCopyClasses( final Map<PsiFile, PsiClass[]> fileToClasses, @Nullable HashMap<PsiFile, String> map, final String copyClassName, final PsiDirectory targetDirectory, final Project project) throws IncorrectOperationException { PsiElement newElement = null; final Map<PsiClass, PsiElement> oldToNewMap = new HashMap<PsiClass, PsiElement>(); for (final PsiClass[] psiClasses : fileToClasses.values()) { if (psiClasses != null) { for (PsiClass aClass : psiClasses) { if (aClass instanceof SyntheticElement) { continue; } oldToNewMap.put(aClass, null); } } } final List<PsiFile> createdFiles = new ArrayList<PsiFile>(fileToClasses.size()); int[] choice = fileToClasses.size() > 1 ? new int[] {-1} : null; List<PsiFile> files = new ArrayList<PsiFile>(); for (final Map.Entry<PsiFile, PsiClass[]> entry : fileToClasses.entrySet()) { final PsiFile psiFile = entry.getKey(); final PsiClass[] sources = entry.getValue(); if (psiFile instanceof PsiClassOwner && sources != null) { final PsiFile createdFile = copy( psiFile, targetDirectory, copyClassName, map == null ? null : map.get(psiFile), choice); if (createdFile == null) return null; for (final PsiClass destination : ((PsiClassOwner) createdFile).getClasses()) { if (destination instanceof SyntheticElement) { continue; } PsiClass source = findByName(sources, destination.getName()); if (source != null) { final PsiClass copy = copy(source, copyClassName); newElement = destination.replace(copy); oldToNewMap.put(source, newElement); } else { destination.delete(); } } createdFiles.add(createdFile); } else { files.add(psiFile); } } for (PsiFile file : files) { try { PsiDirectory finalTarget = targetDirectory; final String relativePath = map != null ? map.get(file) : null; if (relativePath != null && !relativePath.isEmpty()) { finalTarget = buildRelativeDir(targetDirectory, relativePath).findOrCreateTargetDirectory(); } final PsiFile fileCopy = CopyFilesOrDirectoriesHandler.copyToDirectory( file, getNewFileName(file, copyClassName), finalTarget, choice); if (fileCopy != null) { createdFiles.add(fileCopy); } } catch (IOException e) { throw new IncorrectOperationException(e.getMessage()); } } final Set<PsiElement> rebindExpressions = new HashSet<PsiElement>(); for (PsiElement element : oldToNewMap.values()) { if (element == null) { LOG.error(oldToNewMap.keySet()); continue; } decodeRefs(element, oldToNewMap, rebindExpressions); } final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); for (PsiFile psiFile : createdFiles) { if (psiFile instanceof PsiJavaFile) { codeStyleManager.removeRedundantImports((PsiJavaFile) psiFile); } } for (PsiElement expression : rebindExpressions) { codeStyleManager.shortenClassReferences(expression); } new OptimizeImportsProcessor( project, createdFiles.toArray(new PsiFile[createdFiles.size()]), null) .run(); return newElement != null ? newElement : createdFiles.size() > 0 ? createdFiles.get(0) : null; }
public void doCopy(PsiElement[] elements, PsiDirectory defaultTargetDirectory) { FeatureUsageTracker.getInstance().triggerFeatureUsed("refactoring.copyClass"); final HashMap<PsiFile, String> relativePathsMap = new HashMap<PsiFile, String>(); final Map<PsiFile, PsiClass[]> classes = convertToTopLevelClasses(elements, false, "", relativePathsMap); assert classes != null; if (defaultTargetDirectory == null) { final PsiFile psiFile = classes.keySet().iterator().next(); defaultTargetDirectory = psiFile.getContainingDirectory(); LOG.assertTrue(defaultTargetDirectory != null, psiFile); } else { Project project = defaultTargetDirectory.getProject(); VirtualFile sourceRootForFile = ProjectRootManager.getInstance(project) .getFileIndex() .getSourceRootForFile(defaultTargetDirectory.getVirtualFile()); if (sourceRootForFile == null) { final List<PsiElement> files = new ArrayList<PsiElement>(); for (int i = 0, elementsLength = elements.length; i < elementsLength; i++) { PsiFile containingFile = elements[i].getContainingFile(); if (containingFile != null) { files.add(containingFile); } else if (elements[i] instanceof PsiDirectory) { files.add(elements[i]); } } CopyFilesOrDirectoriesHandler.copyAsFiles( files.toArray(new PsiElement[files.size()]), defaultTargetDirectory, project); return; } } Project project = defaultTargetDirectory.getProject(); Object targetDirectory = null; String className = null; boolean openInEditor = true; if (copyOneClass(classes)) { final String commonPath = ArrayUtil.find(elements, classes.values().iterator().next()) == -1 ? normalizeRelativeMap(relativePathsMap) : null; CopyClassDialog dialog = new CopyClassDialog( classes.values().iterator().next()[0], defaultTargetDirectory, project, false) { @Override protected String getQualifiedName() { if (commonPath != null && !commonPath.isEmpty()) { return StringUtil.getQualifiedName( super.getQualifiedName(), commonPath.replaceAll("/", ".")); } return super.getQualifiedName(); } }; dialog.setTitle(RefactoringBundle.message("copy.handler.copy.class")); dialog.show(); if (dialog.isOK()) { openInEditor = dialog.openInEditor(); targetDirectory = dialog.getTargetDirectory(); className = dialog.getClassName(); if (className == null || className.length() == 0) return; } } else { if (ApplicationManager.getApplication().isUnitTestMode()) { targetDirectory = defaultTargetDirectory; } else { defaultTargetDirectory = CopyFilesOrDirectoriesHandler.resolveDirectory(defaultTargetDirectory); if (defaultTargetDirectory == null) return; PsiElement[] files = PsiUtilCore.toPsiFileArray(classes.keySet()); if (classes.keySet().size() == 1) { // do not choose a new name for a file when multiple classes exist in one file final PsiClass[] psiClasses = classes.values().iterator().next(); if (psiClasses != null) { files = psiClasses; } } final CopyFilesOrDirectoriesDialog dialog = new CopyFilesOrDirectoriesDialog(files, defaultTargetDirectory, project, false); dialog.show(); if (dialog.isOK()) { targetDirectory = dialog.getTargetDirectory(); className = dialog.getNewName(); openInEditor = dialog.openInEditor(); } } } if (targetDirectory != null) { copyClassesImpl( className, project, classes, relativePathsMap, targetDirectory, defaultTargetDirectory, RefactoringBundle.message("copy.handler.copy.class"), false, openInEditor); } }