2014-09-18 3 views
1

Xtext 및 Graphiti로 개발 된 플러그인 세트에서 작업합니다. 조사가 필요한 경우 DSL 및 그래프 편집기와 관련이 있습니다. 우리는 몇몇 사용자 프로젝트에서 그들 사이의 링크와 참조가있는 많은 파일을 가지고 있습니다. 패키지를 다른 파일로 옮길 때 자동으로 모든 파일을 업데이트하기 위해 Move Participant를 구현해야합니다. 예를 들어많은 파일이있는 Eclipse 이동 프로그램

:

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 
    } 
} 

이 완벽하게 작동합니다 :

는 이미 여기에 간단한 클래스를 썼다. 이 창에는 교체를 적용하기 전에 변경 사항의 미리보기가 표시됩니다.

하지만 두 개 이상의 파일을 이동하려고하고 네트워크가 참조하는 경우 미리보기가 표시되어 있어도 대체 파일이 적용되지 않습니다. 경우에 따라 예외가 있습니다 (파일 크기가 두 번째 ReplaceEdit 인스턴스에서 지정된 것보다 작기 때문). 다른 경우에는 두 번째 대체가 수행되지만 파일의 첫 번째 버전의 마지막 문자는 끝에 남습니다. 첫 번째 교체가 표시되지 않습니다.

이 내가이 편집 인스턴스를 대체 초기화 할 때 또한 더 나은 (실제) 인덱스 시도 I

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

때문이지만, 더 이상 운. 여기서 문제는 이클립스가 두 개 이상의 파일에서 MoveParticipant 클래스를 사용할 때 각 교체 결과를 처리하여 다른 요소를 수정하지 않는다는 것입니다 (업데이트 색인 등)

이클립스 API는 동일한 파일에 많은 대체물을 보장합니다. 2 개 이상의 파일을 이동할 때 올바르게 수행됩니까?

+0

단일 파일을 여러 번 변경하려고한다고 하시겠습니까? –

+0

단일 파일을 여러 번 변경하려면 'MultiTextEdit'을 사용하고 개별 편집 작업을 병합해야합니다. 'org.eclipse.jdt.internal.corext.refactoring.util.TextEditUtil' JDT의 기능을 확인하십시오. –

+0

짧을수록 그렇습니다. 그러나 동일한 파일에서 다른 대체물에 대해서는 알지 못합니다. 이클립스 API는 같은 움직임에서 파일에 대해 이미 등록 된 다른 변경 사항을 알려주지 않는다. 동작 – Antwane

답변

1

마침내 내 문제의 해결책을 발견했습니다. 내 이동 참가자는 ISharableParticipant 인터페이스를 구현해야합니다. 이 트릭을 통해 RefactoringProcess는 참가자 인스턴스를 자동으로 재사용하고 addElement() 메서드를 사용하여 모든 파일을 등록합니다 (첫 번째 객체는 여전히 initialize()과 함께 전달됩니다.) 그런 다음 구체적 참여자는 변경 인스턴스를 올바르게 작성하기 위해 전체 파일 목록을 처리해야합니다.