Sadık
Sadık

Reputation: 4419

CDT: Wrong Outline view for my source files, if two source files have the same name

After gaining a bit understanding, I had to edit the whole question.

In my eclipse plugin I am using CDT's CEditor and CContentOutlinePage for files with languages close to C. The outline has a lot of features I don't want to miss. But it also comes with undesired behavior. When I open two files with the same name, the Outline view always displays the functions of the source file that was opened first.

Say, I have a file /subdir1/file.extension and /subdir2/file.extension with different content, I can switch between them without having the Outline view changed.

In my Editor I copied the method getOutlinePage() from the superclass CEditor:

public class MyEditor extends CEditor {

    private final String id = "de.blub.ide.myeditor";

    private MyOutlinePage outlinePage;

    /**
     * Default constructor.
     */
    public MyEditor() {
        super();
        outlinePage = new MyOutlinePage(this); 
        System.out.println("Working example");
    }

    /**
     * Returns the outline page of the C/C++ editor.
     * @return Outline page.
     */
    public CContentOutlinePage getOutlinePage() {
        if (outlinePage == null) {
            outlinePage = new MyOutlinePage(this);
            outlinePage.addSelectionChangedListener(this);
        }
        IEditorInput input = getEditorInput();

        IWorkingCopyManager manager = CUIPlugin.getDefault().getWorkingCopyManager();
        IWorkingCopy workingCopy = manager.getWorkingCopy(input);
        if (workingCopy != outlinePage.getRoot()) {
            outlinePage.setInput(workingCopy);
        }
        return outlinePage;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T getAdapter(Class<T> adapterClass) {
        if (adapterClass.isAssignableFrom(IContentOutlinePage.class)) {
            return (T) getOutlinePage();
        }

        return super.getAdapter(adapterClass);
    }
}

This class has exactly the same behavior as the supeclass, but it gives me the chance to modify the behavior. I can verify that workingCopy has the wrong value, even if input is correct. While the path of input is /project/subdir1/file.extension, workingCopy has a resource pointing to `/project/subdir2/file.extension.

Upvotes: 1

Views: 70

Answers (1)

Sadık
Sadık

Reputation: 4419

This is due to a bug in CDT core. The equals method in CElement checks the type, the name and the parent, but not the resource:

public static boolean equals(ICElement lhs, ICElement rhs) {
    if (lhs == rhs) {
        return true;
    }
    if (lhs.getElementType() != rhs.getElementType()) {
        return false;
    }
    String lhsName = lhs.getElementName();
    String rhsName = rhs.getElementName();
    if (lhsName == null || rhsName == null || lhsName.length() != rhsName.length() || !lhsName.equals(rhsName)) {
        return false;
    }

    if (lhs instanceof ISourceReference && rhs instanceof ISourceReference) {
        if (((ISourceReference) lhs).getIndex() != ((ISourceReference)rhs).getIndex()) {
            return false;
        }
    }

    ICElement lhsParent = lhs.getParent();
    ICElement rhsParent = rhs.getParent();
    if (lhsParent == rhsParent) {
        return true;
    }

    return lhsParent != null && lhsParent.equals(rhsParent);
}

Since getParent() returns the project, the method returns true, if the two files are located inside the same project. To follow updates for this bug, see here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=546295

Upvotes: 2

Related Questions