Community
Participate
Working Groups
I precreate a directory under my eclipse workspace: /Workspace/ Project/ src@ -> /SomewhereElse/Files where /SomewhereElse/Files contains a simple C/C++ source file: /SomewhereElse/Files/ main.C main.C: int x; int main() { x = 1; } I create a C++ project "Project" with Project type "Executable". This works as expected: I get a Project with a folder "src" containing "main.C". However, if I open "main.C", highlight "x" on line 3 above, and hit F3 (Open Declaration), a 2nd "main.C" editor window is opened. The tooltip for the 1st editor window shows "Project/src/main.C" and the tooltip for the 2nd window shows "/Workspace/Project/src/main.C".
Of course this problem doesn't occur when src is a real directory and not a symlink. I had done some digging into the source and I think located the piece of code where a difference in behavior occurs: (cdt.core:cdt.internal.core.pdom.indexer) ProjectIndexerInputAdapter.resolveASTPath ProjectIndexerInputAdapter.doResolveASTPath (cdt.core.index) IndexLocationFactory.getIFLExpensive first line calls ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(new Path(absolutePath)); findFilesForLocation for absolutePath="/Workspace/Project/src/main.C" returns a 0 length array if src is a symlink and a 1 element array if src is a directory.
*** Bug 471990 has been marked as a duplicate of this bug. ***
I'm not able to reproduce the problem described in comment 0 with current CDT. I can, however, reproduce the issue described in bug 471990; I'll pursue a fix for that here.
I investigated the issue described in bug 471990, and found the following. First, some notes about how the project structure described in that bug is represented in Eclipse/CDT. - Entries in the Project Explorer are modeled as "resources", using the interface IResource (specifically IFile for files). - In a situation where a single file is reachable through multiple entries in Project Explorer, each entry has its own IFile. - IFiles have a notion of a "path in the workspace", accessed via IFile.getFullPath(), and a "location in the filesystem", accessed via IResource.getLocation(). If multiple resources represent the same file, they will have different paths in the workspace (e.g. /Project/folder/file vs. /Project/[Subprojects]/folder/file), but they have the same location in the filesystem. - CDT models the contents of a project as translation units, using the interface ITranslationUnit. An ITranslationUnit is tied to a particular IFile, so in the above case there can be multiple ITranslationUnits corresponding to the same file. - However, even if multiple ITranslationUnits correspond to the same file, it appears that only one of them is indexed. (This is a good thing. If multiple copies of the translation unit were indexed, we'd have problems caused by multiple definitions of the same entity and similar problems.)
Now, when doing "Open Declaration" on a project structure like this, one of two things can happen: 1) The target of the action is in the same file that the action was invoked in. In this case, the target of the action is represented as an IASTName found in the AST of the ITranslationUnit that the action was invoked in. To navigate to the target, "Open Declaration" needs an ITranslationUnit to open. It was getting this in a roundabout way that involved getting the path on the filesystem, searching for resources that resolve to that path, and then using some heuristics to choose a single resource. In the affected project setup, often a different resource (resolving to the same file) was chosen than the one from which the action originated. The solution for this is simple: choose the resource from which the action originated. This was fixed today in [1]. 2) The target of the action is in a different file than the one the action was invoked in. In this case, the target was found through an index lookup, and it's represented as an IIndexName. To navigate to a target like this, CDT asks the index "what was the workspace path of the translation unit that was indexed that contained this name" (this path is stored in the index). As I mentioned in comment 4, the file could have been indexed under any one of the workspace paths that resolve to it. Whichever it was, "Open Declaration" opens that file. So, for example, starting from "/Project/folder/file.cpp", we can open "/Project/[Subprojects]/folder/file.hpp", if "file.hpp" happened to be indexed under that path. Of course, we'd prefer to open "/Project/folder/file.hpp" instead. To fix this, I propose to take the following approach (kindly suggested by Gregory Kramida): Instead of taking the workspace path under which the file was indexed, find all workspace paths that resolve to the same location in the filesystem, and select whichever of these paths shares the greatest common prefix with the workspace path of the file originating the action. For example, if the originating file is "/Project/folder/file.cpp", then "/Project/folder/file.hpp" (which shares 2 paths segments with the originating path) would be preferred over "/Project/[Subprojects]/folder/file.hpp" (which shares 1 path segment with the originating path). [1] http://git.eclipse.org/c/cdt/org.eclipse.cdt.git/commit/?id=d4c3e42e7eb920fe37f173f90d8e0936fcedfdb8
New Gerrit change created: https://git.eclipse.org/r/63690
Gerrit change https://git.eclipse.org/r/63690 was merged to [master]. Commit: http://git.eclipse.org/c/cdt/org.eclipse.cdt.git/commit/?id=7eeecab0209a14240dd23e2258c3357a0c6c3d6d