Changed copy relative path algorithm (except for Java modules)

This is a temporary solution for RUBY-19057 which may take some time, because of UX involved (and probably not necessary at all)

- For Java modules everything works as before
- For everyone else we are trying to find relative path in the following order:

1. Relative to the closest module content root
2. Relative to project working dir
3. Using file absolute path

IDEA-CR-31595
This commit is contained in:
Alexandr Evstigneev
2018-04-19 11:15:27 +03:00
parent be823cd068
commit 5264e9729e
4 changed files with 101 additions and 19 deletions
@@ -220,6 +220,7 @@
<fileStructureGroupRuleProvider implementation="com.intellij.usages.impl.rules.JavaMethodGroupRuleProvider"/>
<fileStructureGroupRuleProvider implementation="com.intellij.usages.impl.rules.NonJavaFileGroupRuleProvider"/>
<qualifiedNameProvider implementation="com.intellij.ide.actions.JavaQualifiedNameProvider"/>
<virtualFileQualifiedNameProvider implementation="com.intellij.ide.actions.JavaVirtualFileQualifiedNameProvider"/>
<referenceImporter implementation="com.intellij.codeInsight.daemon.impl.JavaReferenceImporter"/>
<elementDescriptionProvider implementation="com.intellij.ide.util.JavaDeleteTypeDescriptionProvider"/>
<elementDescriptionProvider implementation="com.intellij.usageView.JavaUsageViewDescriptionProvider"/>
@@ -0,0 +1,51 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.actions;
import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.LogicalRoot;
import com.intellij.util.LogicalRootsManager;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class JavaVirtualFileQualifiedNameProvider implements CopyReferenceAction.VirtualFileQualifiedNameProvider {
@Nullable
@Override
public String getQualifiedName(@NotNull Project project, @NotNull VirtualFile virtualFile) {
Module module = ModuleUtilCore.findModuleForFile(virtualFile, project);
if (module == null || !ModuleType.is(module, JavaModuleType.getModuleType())) {
return null;
}
final LogicalRoot logicalRoot = LogicalRootsManager.getLogicalRootsManager(project).findLogicalRoot(virtualFile);
VirtualFile logicalRootFile = logicalRoot != null ? logicalRoot.getVirtualFile() : null;
if (logicalRootFile != null && !virtualFile.equals(logicalRootFile)) {
return ObjectUtils.assertNotNull(VfsUtilCore.getRelativePath(virtualFile, logicalRootFile, '/'));
}
VirtualFile outerMostRoot = null;
VirtualFile each = virtualFile;
ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
while (each != null && (each = index.getContentRootForFile(each, false)) != null) {
outerMostRoot = each;
each = each.getParent();
}
if (outerMostRoot != null && !outerMostRoot.equals(virtualFile)) {
String relative = VfsUtilCore.getRelativePath(virtualFile, outerMostRoot, '/');
if (relative != null) {
return relative;
}
}
return virtualFile.getPath();
}
}
@@ -20,31 +20,33 @@ import com.intellij.codeInsight.daemon.impl.IdentifierUtil;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.dnd.FileCopyPasteUtil;
import com.intellij.ide.scratch.RootType;
import com.intellij.ide.scratch.ScratchFileService;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.StatusBarEx;
import com.intellij.psi.*;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.LogicalRoot;
import com.intellij.util.LogicalRootsManager;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -53,6 +55,7 @@ import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
@@ -288,28 +291,53 @@ public class CopyReferenceAction extends DumbAwareAction {
return virtualFile == null ? file.getName() : getVirtualFileFqn(virtualFile, file.getProject());
}
@NotNull
private static String getVirtualFileFqn(@NotNull VirtualFile virtualFile, @NotNull Project project) {
final LogicalRoot logicalRoot = LogicalRootsManager.getLogicalRootsManager(project).findLogicalRoot(virtualFile);
VirtualFile logicalRootFile = logicalRoot != null ? logicalRoot.getVirtualFile() : null;
if (logicalRootFile != null && !virtualFile.equals(logicalRootFile)) {
return ObjectUtils.assertNotNull(VfsUtilCore.getRelativePath(virtualFile, logicalRootFile, '/'));
for (VirtualFileQualifiedNameProvider provider : Extensions.getExtensions(VirtualFileQualifiedNameProvider.EP_NAME)) {
String qualifiedName = provider.getQualifiedName(project, virtualFile);
if (qualifiedName != null) {
return qualifiedName;
}
}
VirtualFile outerMostRoot = null;
VirtualFile each = virtualFile;
ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
while (each != null && (each = index.getContentRootForFile(each, false)) != null) {
outerMostRoot = each;
each = each.getParent();
Module module = ModuleUtilCore.findModuleForFile(virtualFile, project);
if (module != null) {
for (VirtualFile root : ModuleRootManager.getInstance(module).getContentRoots()) {
String relativePath = VfsUtilCore.getRelativePath(virtualFile, root);
if (relativePath != null) {
return relativePath;
}
}
}
if (outerMostRoot != null && !outerMostRoot.equals(virtualFile)) {
String relative = VfsUtilCore.getRelativePath(virtualFile, outerMostRoot, '/');
if (relative != null) {
return relative;
String relativePath = VfsUtilCore.getRelativePath(virtualFile, project.getBaseDir());
if (relativePath != null) {
return relativePath;
}
RootType rootType = RootType.forFile(virtualFile);
if (rootType != null) {
VirtualFile scratchRootVirtualFile =
VfsUtil.findFileByIoFile(new File(ScratchFileService.getInstance().getRootPath(rootType)), false);
if (scratchRootVirtualFile != null) {
String scratchRelativePath = VfsUtilCore.getRelativePath(virtualFile, scratchRootVirtualFile);
if (scratchRelativePath != null) {
return scratchRelativePath;
}
}
}
return virtualFile.getPath();
}
public interface VirtualFileQualifiedNameProvider {
ExtensionPointName<VirtualFileQualifiedNameProvider> EP_NAME =
ExtensionPointName.create("com.intellij.virtualFileQualifiedNameProvider");
/**
* @return {@code virtualFile} fqn (relative path for example) or null if not handled by this provider
*/
@Nullable
String getQualifiedName(@NotNull Project project, @NotNull VirtualFile virtualFile);
}
}
@@ -641,6 +641,8 @@
<extensionPoint name="modelScopeItemPresenter" interface="com.intellij.analysis.dialog.ModelScopeItemPresenter" />
<extensionPoint name="qualifiedNameProvider" interface="com.intellij.ide.actions.QualifiedNameProvider"/>
<extensionPoint name="virtualFileQualifiedNameProvider"
interface="com.intellij.ide.actions.CopyReferenceAction$VirtualFileQualifiedNameProvider"/>
<extensionPoint name="completionData"
beanClass="com.intellij.codeInsight.completion.CompletionDataEP"/>