Eclipse移动参与者包含许多文件

时间:2014-09-18 15:31:58

标签: java eclipse refactoring pde

我处理一组使用Xtext和Graphiti开发的插件。它与DSL和图形编辑器有关,可满足研究需求。我们在一些用户项目中有许多文件,它们之间有链接和引用。我需要实现一个Move Participant,当我们将某个东西从一个包移动到另一个时,如果该文件是其他文件中的引用,则自动更新所有文件。

例如:

ProjectA
    |- src
    |   |-org.comp.A
    |   |   |-networkA
    |   |   |-networkB
    |   |-org.comp.B
    |   |   |-fileC
    |   |   |-fileD

org.comp.A.networkA引用org.comp.B.fileCorg.comp.B.fileD。如果我将fileC和fileD移动到另一个包或另一个项目,我需要正确更新networkA。在networkA的内容中至少有2个不同的替换。

我已经写了一个类,简化了这里:

public class NetworkMoveParticipant extends MoveParticipant {

    private IFile originalNetworkFile;
    private IFolder destination;
    private IPath newNetworkPath;

    @Override
    protected boolean initialize(Object element) {
        if (element instanceof IFile) {
            originalNetworkFile = (IFile) element;
            destination = (IFolder) getArguments().getDestination();
            newNetworkPath = destination.getFile(
                     originalNetworkFile.getName()
            ).getFullPath();
            return true;
        }
        return false;
    }

    @Override
    public String getName() {
        return "The move participant";
    }

    @Override
    public RefactoringStatus checkConditions(IProgressMonitor pm,
            CheckConditionsContext context) throws OperationCanceledException {
        return new RefactoringStatus();
    }

    @Override
    public Change createChange(IProgressMonitor pm) throws CoreException,
            OperationCanceledException {
        return getOtherNetworksContentChanges();
    }

    private Change getOtherNetworksContentChanges() {
        final CompositeChange changes = new CompositeChange();

        for(IFile file : getAffectedFiles()) {
            final TextFileChange textFileChange =
                    new TextFileChange(file.getName(), file);
            textFileChange.setEdit(new ReplaceEdit(0,
                             content.length(), getNewFileContent(file)));
            changes.add(textFileChange);
        }
        return changes;
    }

    private Iterable<IFile> getAffectedFiles() {
        // Returns the list of projects' IFile which reference the moved file
    }

    private String getNewFileContent(IFile file) {
        // Perform the replacement in the content of the project's file
    }
}

当我移动1个文件时,这非常有效:所有引用此文件的网络都按预期更新。该窗口显示应用替换前的更改预览。

但是如果我尝试移动2个或更多文件并且网络引用它们,即使显示的预览正常,也不会正确应用替换。在某些情况下,有一个例外(因为文件大小小于第二个ReplaceEdit实例中指定的),在其他情况下,执行第二次替换,但文件的第一个版本的最后一个字符仍然在结尾,并且第一次更换不可见。

这是由于

new ReplaceEdit(0, content.length(), "the new file content")

当我初始化替换编辑实例时,我还尝试了更好(和真实)的索引,但没有更多运气。这里的问题是Eclipse,当它在多个文件上使用MoveParticipant类时,不会处理每个替换的结果以适应其他(更新索引等)。

Eclipse API中是否有某些内容可以确保在同一文件上有很多替换当移动2个或更多文件时会正确执行?

1 个答案:

答案 0 :(得分:2)

我终于找到了解决问题的方法。我的移动参与者应该实现ISharableParticipant接口。通过这个技巧,RefactoringProcess自动重用参与者实例,并使用addElement()方法注册所有文件(第一个对象仍然传递initialize()。然后具体参与者必须照顾整个正确创建更改实例的文件列表。