1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 01:15:29 +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);
}
}
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

@ -37,7 +37,8 @@ public class ResourceLookup {
* Searches for files with the given location suffix.
*
* 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 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
* of the path. The method does not work for files where the name (last segment) of the
* resources differs from the name of the location.
* of the path.
*/
public static IFile[] findFilesForLocationURI(URI location) {
return lookupTree.findFilesForLocationURI(location);

View file

@ -93,16 +93,18 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
private static class Node {
final Node fParent;
final char[] fResourceName;
final boolean fIsFolder;
final boolean fHasFileLocationName;
final boolean fIsFileLinkTarget;
boolean fDeleted;
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;
fResourceName= name;
fIsFolder= isFolder;
fHasFileLocationName= hasFileLocationName;
fIsFileLinkTarget= isFileLinkTarget;
if (parent != null)
parent.fHasChildren= true;
}
@ -121,7 +123,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
private Node fLastFolderNode;
public ResourceLookupTree() {
fRootNode= new Node(null, CharArrayUtils.EMPTY, true) {};
fRootNode= new Node(null, CharArrayUtils.EMPTY, false, false) {};
fFileExtensions= new HashMap<String, Extensions>();
fUnrefJob= new Job("Timer") { //$NON-NLS-1$
@Override
@ -243,8 +245,22 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
assert Thread.holdsLock(fLock);
if (res instanceof IFile) {
if (fCurrentExtensions.isRelevant(res.getName())) {
createFileNode(res.getFullPath());
final String resName = res.getName();
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 {
try {
@ -261,7 +277,14 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
public boolean visit(IResourceProxy proxy) throws CoreException {
if (proxy.getType() == IResource.FILE) {
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;
@ -370,15 +393,23 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
/**
* Inserts a node for the given path.
*/
private void createFileNode(IPath fullPath) {
private void createFileNode(IPath fullPath, String fileLink) {
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) {
final int len= segments.length;
char[][] chsegs= new char[len][];
for (int i = 0; i < segments.length; i++) {
private char[][] toCharArrayArray(String[] segments, String fileLink) {
final int segmentLen = segments.length;
char[][] chsegs;
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();
}
return chsegs;
@ -387,14 +418,14 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
/**
* 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);
if (segmentCount == 0)
return fRootNode;
if (folder && fLastFolderNode != null) {
if (isNodeForSegments(fLastFolderNode, segments, segmentCount))
if (!hasFileLocationName && fLastFolderNode != null) {
if (isNodeForSegments(fLastFolderNode, segments, segmentCount, isFileLinkTarget))
return fLastFolderNode;
}
@ -409,8 +440,8 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
if (obj != null) {
if (obj instanceof Node) {
Node node= (Node) obj;
if (isNodeForSegments(node, segments, segmentCount)) {
if (folder)
if (isNodeForSegments(node, segments, segmentCount, isFileLinkTarget)) {
if (!hasFileLocationName)
fLastFolderNode= node;
return node;
}
@ -423,16 +454,16 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
Node node = nodes[len];
if (node == null)
break;
if (isNodeForSegments(node, segments, segmentCount)) {
if (folder)
if (isNodeForSegments(node, segments, segmentCount, isFileLinkTarget)) {
if (!hasFileLocationName)
fLastFolderNode= node;
return node;
}
}
}
}
final Node parent= createNode(segments, segmentCount-1, true);
Node node= new Node(parent, name, folder);
final Node parent= createNode(segments, segmentCount-1, false, false);
Node node= new Node(parent, name, hasFileLocationName, isFileLinkTarget);
if (nodes == null) {
fNodeMap.put(hash, node);
} else {
@ -445,7 +476,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
nodes[len]= node;
}
if (folder)
if (!hasFileLocationName)
fLastFolderNode= node;
return node;
}
@ -453,9 +484,12 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
/**
* 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);
if (node.fIsFileLinkTarget != isFileLinkTarget)
return false;
while(segmentLength > 0 && node != null) {
if (!CharArrayUtils.equals(segments[--segmentLength], node.fResourceName))
return false;
@ -482,10 +516,10 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
if (segmentCount == 0)
return;
final char[][]segments= toCharArrayArray(fullPath.segments());
final char[][]segments= toCharArrayArray(fullPath.segments(), null);
if (obj instanceof Node) {
final Node node= (Node) obj;
if (!node.fDeleted && isNodeForSegments(node, segments, segmentCount)) {
if (!node.fDeleted && isNodeForSegments(node, segments, segmentCount, false)) {
node.fDeleted= true;
if (node.fHasChildren)
fNeedCleanup= true;
@ -497,7 +531,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
Node node = nodes[i];
if (node == null)
return;
if (!node.fDeleted && isNodeForSegments(node, segments, segmentCount)) {
if (!node.fDeleted && isNodeForSegments(node, segments, segmentCount, false)) {
remove(nodes, i);
if (nodes[0] == null)
@ -695,7 +729,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
IFile[] result= null;
outer: for (int i = 0; i < candidates.length; i++) {
final Node node = candidates[i];
if (!node.fIsFolder && checkProject(node, prjSet)) {
if (node.fHasFileLocationName && checkProject(node, prjSet)) {
final char[] n2= node.fResourceName;
if (namelen == n2.length) {
for (int j = 0; j < n2.length; j++) {
@ -744,7 +778,10 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
private IPath createPath(Node node) {
if (node == fRootNode)
return Path.ROOT;
if (node.fIsFileLinkTarget)
return createPath(node.fParent);
return createPath(node.fParent).append(new String(node.fResourceName));
}
@ -758,7 +795,7 @@ class ResourceLookupTree implements IResourceChangeListener, IResourceDeltaVisit
int resultIdx= 0;
for (int i = 0; i < candidates.length; i++) {
final Node node = candidates[i];
if (!node.fIsFolder) {
if (node.fHasFileLocationName) {
final IFile file= root.getFile(createPath(node));
final T loc= adapter.getLocation(file);
if (loc != null) {