1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-09 19:43:27 +02:00

Support for linked files that change the name of the file in ResourceLookup, bug 251161.

This commit is contained in:
Markus Schorn 2008-10-17 14:01:35 +00:00
parent 129297342f
commit 2760c4fe5f
3 changed files with 94 additions and 34 deletions

View file

@ -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);
}
} }

View file

@ -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);

View file

@ -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) {