mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-09 11:33:20 +02:00
Support for linked files that change the name of the file in ResourceLookup, bug 251161.
This commit is contained in:
parent
129297342f
commit
2760c4fe5f
3 changed files with 94 additions and 34 deletions
|
@ -207,4 +207,27 @@ public class ResourceLookupTests extends TestCase {
|
||||||
assertEquals(1, files.length);
|
assertEquals(1, files.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testLinkedResourceFiles() throws Exception {
|
||||||
|
IProject[] prjs= new IProject[]{fProject};
|
||||||
|
|
||||||
|
fProject.create(new NullProgressMonitor());
|
||||||
|
fProject.open(new NullProgressMonitor());
|
||||||
|
createFolder(fProject, "folder1");
|
||||||
|
File f= File.createTempFile("extern", "h");
|
||||||
|
IPath location= Path.fromOSString(f.getAbsolutePath());
|
||||||
|
IFile file1= fProject.getFile("linked1");
|
||||||
|
IFile file2= fProject.getFile("linked2.h");
|
||||||
|
file1.createLink(location, 0, new NullProgressMonitor());
|
||||||
|
file2.createLink(location, 0, new NullProgressMonitor());
|
||||||
|
|
||||||
|
IFile[] files = ResourceLookup.findFilesForLocation(location);
|
||||||
|
assertEquals(2, files.length);
|
||||||
|
|
||||||
|
files= ResourceLookup.findFilesByName(new Path(location.lastSegment()), prjs, false);
|
||||||
|
assertEquals(2, files.length);
|
||||||
|
|
||||||
|
files= ResourceLookup.findFilesByName(new Path("linked2.h"), prjs, false);
|
||||||
|
assertEquals(0, files.length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ public class ResourceLookup {
|
||||||
*
|
*
|
||||||
* At this point the method works for sources and headers (no other content types), only.
|
* At this point the method works for sources and headers (no other content types), only.
|
||||||
* This is done to use less memory and can be changed if necessary.
|
* This is done to use less memory and can be changed if necessary.
|
||||||
|
* For linked resource files, the name of the link target is relevant.
|
||||||
*
|
*
|
||||||
* @param locationSuffix the suffix to match, always used as relative path.
|
* @param locationSuffix the suffix to match, always used as relative path.
|
||||||
* @param projects the projects to search
|
* @param projects the projects to search
|
||||||
|
@ -49,8 +50,7 @@ public class ResourceLookup {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses a lookup-tree that finds resources for locations using the canonical representation
|
* Uses a lookup-tree that finds resources for locations using the canonical representation
|
||||||
* of the path. The method does not work for files where the name (last segment) of the
|
* of the path.
|
||||||
* resources differs from the name of the location.
|
|
||||||
*/
|
*/
|
||||||
public static IFile[] findFilesForLocationURI(URI location) {
|
public static IFile[] findFilesForLocationURI(URI location) {
|
||||||
return lookupTree.findFilesForLocationURI(location);
|
return lookupTree.findFilesForLocationURI(location);
|
||||||
|
|
|
@ -93,16 +93,18 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
private static class Node {
|
private static class Node {
|
||||||
final Node fParent;
|
final Node fParent;
|
||||||
final char[] fResourceName;
|
final char[] fResourceName;
|
||||||
final boolean fIsFolder;
|
final boolean fHasFileLocationName;
|
||||||
|
final boolean fIsFileLinkTarget;
|
||||||
|
|
||||||
boolean fDeleted;
|
boolean fDeleted;
|
||||||
boolean fHasChildren;
|
boolean fHasChildren;
|
||||||
private int fCanonicHash;
|
int fCanonicHash;
|
||||||
|
|
||||||
Node(Node parent, char[] name, boolean isFolder) {
|
Node(Node parent, char[] name, boolean hasFileLocationName, boolean isFileLinkTarget) {
|
||||||
fParent= parent;
|
fParent= parent;
|
||||||
fResourceName= name;
|
fResourceName= name;
|
||||||
fIsFolder= isFolder;
|
fHasFileLocationName= hasFileLocationName;
|
||||||
|
fIsFileLinkTarget= isFileLinkTarget;
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
parent.fHasChildren= true;
|
parent.fHasChildren= true;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +123,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
private Node fLastFolderNode;
|
private Node fLastFolderNode;
|
||||||
|
|
||||||
public ResourceLookupTree() {
|
public ResourceLookupTree() {
|
||||||
fRootNode= new Node(null, CharArrayUtils.EMPTY, true) {};
|
fRootNode= new Node(null, CharArrayUtils.EMPTY, false, false) {};
|
||||||
fFileExtensions= new HashMap<String, Extensions>();
|
fFileExtensions= new HashMap<String, Extensions>();
|
||||||
fUnrefJob= new Job("Timer") { //$NON-NLS-1$
|
fUnrefJob= new Job("Timer") { //$NON-NLS-1$
|
||||||
@Override
|
@Override
|
||||||
|
@ -243,8 +245,22 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
assert Thread.holdsLock(fLock);
|
assert Thread.holdsLock(fLock);
|
||||||
|
|
||||||
if (res instanceof IFile) {
|
if (res instanceof IFile) {
|
||||||
if (fCurrentExtensions.isRelevant(res.getName())) {
|
final String resName = res.getName();
|
||||||
createFileNode(res.getFullPath());
|
String linkedName= null;
|
||||||
|
if (res.isLinked()) {
|
||||||
|
URI uri= res.getLocationURI();
|
||||||
|
if (uri != null) {
|
||||||
|
linkedName= LocationAdapter.URI.extractName(uri);
|
||||||
|
if (linkedName.length() > 0 && fCurrentExtensions.isRelevant(linkedName)) {
|
||||||
|
if (linkedName.equals(resName)) {
|
||||||
|
createFileNode(res.getFullPath(), null);
|
||||||
|
} else {
|
||||||
|
createFileNode(res.getFullPath(), linkedName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (fCurrentExtensions.isRelevant(resName)) {
|
||||||
|
createFileNode(res.getFullPath(), null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
@ -261,7 +277,14 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
public boolean visit(IResourceProxy proxy) throws CoreException {
|
public boolean visit(IResourceProxy proxy) throws CoreException {
|
||||||
if (proxy.getType() == IResource.FILE) {
|
if (proxy.getType() == IResource.FILE) {
|
||||||
if (fCurrentExtensions.isRelevant(proxy.getName())) {
|
if (fCurrentExtensions.isRelevant(proxy.getName())) {
|
||||||
createFileNode(proxy.requestFullPath());
|
if (proxy.isLinked()) {
|
||||||
|
IResource res= proxy.requestResource();
|
||||||
|
if (res instanceof IFile) {
|
||||||
|
add(res);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
createFileNode(proxy.requestFullPath(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -370,15 +393,23 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
/**
|
/**
|
||||||
* Inserts a node for the given path.
|
* Inserts a node for the given path.
|
||||||
*/
|
*/
|
||||||
private void createFileNode(IPath fullPath) {
|
private void createFileNode(IPath fullPath, String fileLink) {
|
||||||
final String[] segments= fullPath.segments();
|
final String[] segments= fullPath.segments();
|
||||||
createNode(toCharArrayArray(segments), segments.length, false);
|
final boolean isFileLinkTarget= fileLink != null;
|
||||||
|
final char[][] charArraySegments = toCharArrayArray(segments, fileLink);
|
||||||
|
createNode(charArraySegments, charArraySegments.length, true, isFileLinkTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
private char[][] toCharArrayArray(String[] segments) {
|
private char[][] toCharArrayArray(String[] segments, String fileLink) {
|
||||||
final int len= segments.length;
|
final int segmentLen = segments.length;
|
||||||
char[][] chsegs= new char[len][];
|
char[][] chsegs;
|
||||||
for (int i = 0; i < segments.length; i++) {
|
if (fileLink != null) {
|
||||||
|
chsegs= new char[segmentLen+1][];
|
||||||
|
chsegs[segmentLen]= fileLink.toCharArray();
|
||||||
|
} else {
|
||||||
|
chsegs= new char[segmentLen][];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < segmentLen; i++) {
|
||||||
chsegs[i]= segments[i].toCharArray();
|
chsegs[i]= segments[i].toCharArray();
|
||||||
}
|
}
|
||||||
return chsegs;
|
return chsegs;
|
||||||
|
@ -387,14 +418,14 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
/**
|
/**
|
||||||
* Inserts a node for the given path.
|
* Inserts a node for the given path.
|
||||||
*/
|
*/
|
||||||
private Node createNode(char[][] segments, int segmentCount, boolean folder) {
|
private Node createNode(char[][] segments, int segmentCount, boolean hasFileLocationName, boolean isFileLinkTarget) {
|
||||||
assert Thread.holdsLock(fLock);
|
assert Thread.holdsLock(fLock);
|
||||||
|
|
||||||
if (segmentCount == 0)
|
if (segmentCount == 0)
|
||||||
return fRootNode;
|
return fRootNode;
|
||||||
|
|
||||||
if (folder && fLastFolderNode != null) {
|
if (!hasFileLocationName && fLastFolderNode != null) {
|
||||||
if (isNodeForSegments(fLastFolderNode, segments, segmentCount))
|
if (isNodeForSegments(fLastFolderNode, segments, segmentCount, isFileLinkTarget))
|
||||||
return fLastFolderNode;
|
return fLastFolderNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,8 +440,8 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
if (obj instanceof Node) {
|
if (obj instanceof Node) {
|
||||||
Node node= (Node) obj;
|
Node node= (Node) obj;
|
||||||
if (isNodeForSegments(node, segments, segmentCount)) {
|
if (isNodeForSegments(node, segments, segmentCount, isFileLinkTarget)) {
|
||||||
if (folder)
|
if (!hasFileLocationName)
|
||||||
fLastFolderNode= node;
|
fLastFolderNode= node;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -423,16 +454,16 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
Node node = nodes[len];
|
Node node = nodes[len];
|
||||||
if (node == null)
|
if (node == null)
|
||||||
break;
|
break;
|
||||||
if (isNodeForSegments(node, segments, segmentCount)) {
|
if (isNodeForSegments(node, segments, segmentCount, isFileLinkTarget)) {
|
||||||
if (folder)
|
if (!hasFileLocationName)
|
||||||
fLastFolderNode= node;
|
fLastFolderNode= node;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final Node parent= createNode(segments, segmentCount-1, true);
|
final Node parent= createNode(segments, segmentCount-1, false, false);
|
||||||
Node node= new Node(parent, name, folder);
|
Node node= new Node(parent, name, hasFileLocationName, isFileLinkTarget);
|
||||||
if (nodes == null) {
|
if (nodes == null) {
|
||||||
fNodeMap.put(hash, node);
|
fNodeMap.put(hash, node);
|
||||||
} else {
|
} else {
|
||||||
|
@ -445,7 +476,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
nodes[len]= node;
|
nodes[len]= node;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (folder)
|
if (!hasFileLocationName)
|
||||||
fLastFolderNode= node;
|
fLastFolderNode= node;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -453,9 +484,12 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
/**
|
/**
|
||||||
* Checks whether the given node matches the given segments.
|
* Checks whether the given node matches the given segments.
|
||||||
*/
|
*/
|
||||||
private boolean isNodeForSegments(Node node, char[][] segments, int segmentLength) {
|
private boolean isNodeForSegments(Node node, char[][] segments, int segmentLength, boolean isFileLinkTarget) {
|
||||||
assert Thread.holdsLock(fLock);
|
assert Thread.holdsLock(fLock);
|
||||||
|
|
||||||
|
if (node.fIsFileLinkTarget != isFileLinkTarget)
|
||||||
|
return false;
|
||||||
|
|
||||||
while(segmentLength > 0 && node != null) {
|
while(segmentLength > 0 && node != null) {
|
||||||
if (!CharArrayUtils.equals(segments[--segmentLength], node.fResourceName))
|
if (!CharArrayUtils.equals(segments[--segmentLength], node.fResourceName))
|
||||||
return false;
|
return false;
|
||||||
|
@ -482,10 +516,10 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
if (segmentCount == 0)
|
if (segmentCount == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final char[][]segments= toCharArrayArray(fullPath.segments());
|
final char[][]segments= toCharArrayArray(fullPath.segments(), null);
|
||||||
if (obj instanceof Node) {
|
if (obj instanceof Node) {
|
||||||
final Node node= (Node) obj;
|
final Node node= (Node) obj;
|
||||||
if (!node.fDeleted && isNodeForSegments(node, segments, segmentCount)) {
|
if (!node.fDeleted && isNodeForSegments(node, segments, segmentCount, false)) {
|
||||||
node.fDeleted= true;
|
node.fDeleted= true;
|
||||||
if (node.fHasChildren)
|
if (node.fHasChildren)
|
||||||
fNeedCleanup= true;
|
fNeedCleanup= true;
|
||||||
|
@ -497,7 +531,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
Node node = nodes[i];
|
Node node = nodes[i];
|
||||||
if (node == null)
|
if (node == null)
|
||||||
return;
|
return;
|
||||||
if (!node.fDeleted && isNodeForSegments(node, segments, segmentCount)) {
|
if (!node.fDeleted && isNodeForSegments(node, segments, segmentCount, false)) {
|
||||||
remove(nodes, i);
|
remove(nodes, i);
|
||||||
|
|
||||||
if (nodes[0] == null)
|
if (nodes[0] == null)
|
||||||
|
@ -695,7 +729,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
IFile[] result= null;
|
IFile[] result= null;
|
||||||
outer: for (int i = 0; i < candidates.length; i++) {
|
outer: for (int i = 0; i < candidates.length; i++) {
|
||||||
final Node node = candidates[i];
|
final Node node = candidates[i];
|
||||||
if (!node.fIsFolder && checkProject(node, prjSet)) {
|
if (node.fHasFileLocationName && checkProject(node, prjSet)) {
|
||||||
final char[] n2= node.fResourceName;
|
final char[] n2= node.fResourceName;
|
||||||
if (namelen == n2.length) {
|
if (namelen == n2.length) {
|
||||||
for (int j = 0; j < n2.length; j++) {
|
for (int j = 0; j < n2.length; j++) {
|
||||||
|
@ -745,6 +779,9 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
if (node == fRootNode)
|
if (node == fRootNode)
|
||||||
return Path.ROOT;
|
return Path.ROOT;
|
||||||
|
|
||||||
|
if (node.fIsFileLinkTarget)
|
||||||
|
return createPath(node.fParent);
|
||||||
|
|
||||||
return createPath(node.fParent).append(new String(node.fResourceName));
|
return createPath(node.fParent).append(new String(node.fResourceName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,7 +795,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
|
||||||
int resultIdx= 0;
|
int resultIdx= 0;
|
||||||
for (int i = 0; i < candidates.length; i++) {
|
for (int i = 0; i < candidates.length; i++) {
|
||||||
final Node node = candidates[i];
|
final Node node = candidates[i];
|
||||||
if (!node.fIsFolder) {
|
if (node.fHasFileLocationName) {
|
||||||
final IFile file= root.getFile(createPath(node));
|
final IFile file= root.getFile(createPath(node));
|
||||||
final T loc= adapter.getLocation(file);
|
final T loc= adapter.getLocation(file);
|
||||||
if (loc != null) {
|
if (loc != null) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue