1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 244434 - When the target file of "Open Declaration" is reachable via

multiple workspace paths, open it under the path that most closely
matches the originating file

Change-Id: I616804c6ffb9900e5df2f918a409f46c3cbb7a3a
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
Nathan Ridge 2016-01-07 00:59:38 -05:00
parent 0d52c4ab82
commit 7eeecab020
2 changed files with 87 additions and 1 deletions

View file

@ -496,7 +496,17 @@ class OpenDeclarationsJob extends Job implements ASTRunnable {
private ICElementHandle getCElementForName(ICProject project, IIndex index, IName declName) throws CoreException { private ICElementHandle getCElementForName(ICProject project, IIndex index, IName declName) throws CoreException {
if (declName instanceof IIndexName) { if (declName instanceof IIndexName) {
return IndexUI.getCElementForName(project, index, (IIndexName) declName); IIndexName indexName = (IIndexName) declName;
ITranslationUnit tu= IndexUI.getTranslationUnit(project, indexName);
if (tu != null) {
// If the file containing the target name is accessible via multiple
// workspace paths, choose the one that most closely matches the
// workspace path of the file originating the action.
tu = IndexUI.getPreferredTranslationUnit(tu, fTranslationUnit);
return IndexUI.getCElementForName(tu, index, indexName);
}
return null;
} }
if (declName instanceof IASTName) { if (declName instanceof IASTName) {
IASTName astName = (IASTName) declName; IASTName astName = (IASTName) declName;

View file

@ -13,7 +13,9 @@
package org.eclipse.cdt.internal.ui.viewsupport; package org.eclipse.cdt.internal.ui.viewsupport;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
@ -92,6 +94,7 @@ import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
import org.eclipse.cdt.internal.core.model.ext.CElementHandleFactory; import org.eclipse.cdt.internal.core.model.ext.CElementHandleFactory;
import org.eclipse.cdt.internal.core.model.ext.ICElementHandle; import org.eclipse.cdt.internal.core.model.ext.ICElementHandle;
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences; import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
import org.eclipse.cdt.internal.ui.editor.ASTProvider; import org.eclipse.cdt.internal.ui.editor.ASTProvider;
@ -359,6 +362,79 @@ public class IndexUI {
} }
return null; return null;
} }
/**
* Given a 'source' and a 'target' translation unit, return a translation unit
* that resolves to the same file as 'target' and has a workspace path that
* matches the workspace path of 'source' as closely as possible.
*
* Most commonly, 'target' will be the only trasnlation unit that resolves to
* the file in question, and 'target' is returned. In the presence of linked
* folders, however, multiple workspace paths can refer to the same file, and
* this function chooses the one that's closest to 'source'.
*/
public static ITranslationUnit getPreferredTranslationUnit(ITranslationUnit target,
ITranslationUnit source) {
// Get the files corresponding to the source and target translation units.
// These files encode the workspace paths.
IFile sourceFile = source.getFile();
IFile targetFile = target.getFile();
if (sourceFile == null || targetFile == null) {
return target;
}
// Resolve the location of the target in the filesystem.
IPath targetLocation = targetFile.getLocation();
if (targetLocation == null) {
return target;
}
// Find all files that resolve to the same location.
IFile[] candidates = ResourceLookup.findFilesForLocation(targetLocation);
// In the common case that there is one only file that resolves to that
// location, or if the search found no results, return the original target.
if (candidates.length <= 1) {
return target;
}
// Get the workspace path of the source translation unit's file.
final IPath sourcePath = sourceFile.getFullPath();
// Sort the candidates files by how closely they match 'sourcePath'.
Arrays.sort(candidates, new Comparator<IFile>() {
@Override
public int compare(IFile f1, IFile f2) {
// Get the workspace paths of the files being compared.
IPath p1 = f1.getFullPath();
IPath p2 = f2.getFullPath();
// Closeness of the match is defined by how many segments of
// the candidate's workspace path match 'sourcePath'.
int s1 = p1.matchingFirstSegments(sourcePath);
int s2 = p2.matchingFirstSegments(sourcePath);
if (s1 > s2)
return -1;
if (s1 < s2)
return 1;
// Fall back on alphabetical comparison.
return p1.toString().compareTo(p2.toString());
}
});
// Processing in the sorted order, return the first file for which
// a translation unit can be found.
for (IFile candidate : candidates) {
ITranslationUnit tu = CoreModelUtil.findTranslationUnit(candidate);
if (tu != null) {
return tu;
}
}
// Fall back on returning the original target.
return target;
}
public static ICElementHandle getCElementForName(ICProject preferProject, IIndex index, IIndexName declName) public static ICElementHandle getCElementForName(ICProject preferProject, IIndex index, IIndexName declName)
throws CoreException { throws CoreException {