2014-09-18 4 views
1

Я работаю над набором плагинов, разработанных с использованием Xtext и Graphiti. Это связано с DSL и графическим редактором для исследований. В некоторых пользовательских проектах мы имеем множество файлов со ссылками и ссылками между ними. Мне нужно реализовать участника Move, чтобы автоматически обновлять все файлы, когда мы перемещаем что-то из пакета в другой, если этот файл является ссылкой в ​​других файлах.Участник Eclipse move со многими файлами

Например:

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

И org.comp.A.networkA ссылки org.comp.B.fileC и org.comp.B.fileD. Если я перейду fileC и fileD в другой пакет или другой проект, мне нужно правильно обновить networkA. Существует как минимум 2 разных замены для выполнения в сети networkA.

Я уже написал класс, упрощенный здесь:

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 в более чем 1 файле, не заботится о результатах каждой замены, чтобы адаптировать другие (индексы обновления и т. Д.)

Есть ли что-то в Eclipse API для обеспечения многих замен в одном файле при перемещении 2 файлов или более будет выполнено правильно?

+0

Вы пытаетесь сделать несколько изменений в одном файле? –

+0

Если вы хотите внести несколько изменений в один файл, вам нужно использовать 'MultiTextEdit' и выполнить некоторую обработку слияния на отдельных изменениях. 'org.eclipse.jdt.internal.corext.refactoring.util.TextEditUtil', чтобы узнать, что делает JDT. –

+0

Короче, да. Но так, что я ничего не знаю о других заменах в одном файле. API Eclipse не дает мне знать другие изменения, уже зарегистрированные для файла с одного и того же хода действие – Antwane

ответ

1

Наконец-то я нашел решение моей проблемы. Мой участник должен реализовать интерфейс ISharableParticipant. С помощью этого метода RefactoringProcess автоматически повторно использует экземпляр участника и регистрирует все файлы с использованием метода addElement() (первый объект по-прежнему передается с initialize(). Затем конкретному участнику необходимо позаботиться обо всем списке файлов для правильного создания экземпляров экземпляра