2012-12-07 5 views
2

Eclipse 플러그인 프로젝트의 일부로, 필자가 수행 한 기능을 구현하기 위해 추가, 삭제 및 메소드 변경 사항을 추적해야합니다.Eclipse 플러그인에서 메소드 내부의 변경 사항을 캡처하는 방법

JavaCore.addElementChangedListener을 통해 수신기를 등록하고 IJavaElementDelta.getElement()이 참조 할 때까지 IJavaElementDelta을 반복적으로 통과함으로써 메서드 추가 및 삭제를 캡처 할 수 있습니다.

예. 내가 얻을 클래스 B에 방법 a를 추가

[Working copy] B.java[*]: {CHILDREN | FINE GRAINED | AST AFFECTED} 
    B[*]: {CHILDREN | FINE GRAINED} 
     a()[+]: {}] 

문제는 이미 기존의 방법을 편집 할 때이 발생하지 않는다는 것입니다 : 나는 그것을 위해 트리거 방법 및 변경 이벤트의 구현을 수정할 때, 델타의 해상도는이 메서드가 포함 된 클래스에서 확장되지 않고 중지됩니다.

예. 내가 클래스 B의 방법 a을 수정 내가 얻을 :

[Working copy] B.java[*]: {CONTENT | FINE GRAINED | AST AFFECTED} 

이 정보는 구현 그냥 변경에도 불구하고, 방법 a에 대한 정보가 포함되어 있습니다.은 어떻게 추적 할 수 있습니다 자신의 구현 (건물과 AST 여러 번 저장하지 않고) 변경 방법에 대한 알림을받을 :이 문제는 부분적으로 문제는, https://bugs.eclipse.org/bugs/show_bug.cgi?id=327753

따라서이 오래된 이클립스 버그 리포트에 연결되어있을 수 있습니다?

답변

1

다소 엄격한 조사 끝에 AST 관련 정보가없는 메소드 내에서 변경 사항을 캡처하는 것은 불가능하다고 결론을 내 렸습니다. 따라서 필자는 최소한의 정보 만 저장하는 가장 효율적인 방법과이 정보를 비교하는 가장 적합한 방법을 모색했습니다.

여기에 나와있는 해결책이 있습니다. 며칠간 테스트를하면 ElementChangedEvent마다 실행하는 것이 가능할만큼 효율적이라고 보입니다.

// during each user-invoked-compile, these are processed and cleared 
private static HashMap<String, IMethod> added = new HashMap<String, IMethod>(); 
private static HashMap<String, IMethod> changed = new HashMap<String, IMethod>(); 
private static HashMap<String, IMethod> removed = new HashMap<String, IMethod>(); 

// this persists through out the entire session 
private static HashMap<String, ASTNode> subtrees = new HashMap<String, ASTNode>(); 

private static void attachModelPart() { 
    JavaCore.addElementChangedListener(new IElementChangedListener() { 

     @Override 
     public void elementChanged(ElementChangedEvent event) { 
      ... // added and removed IMethod handling 
      IJavaElementDelta delta = event.getDelta(); 
      if (delta.getElement() instanceof CompilationUnit) { 
       delta.getCompilationUnitAST().accept(new ASTVisitor() { 

        @Override 
        public boolean visit(MethodDeclaration node) { 
         String mName = ((TypeDeclaration) node.getParent()).getName() 
           .getFullyQualifiedName() + "." + node.getName().getFullyQualifiedName(); 
         // Finding match for this methods name(mName) in saved method subtrees... 
         boolean methodHasChanged = false; 
         if (subtrees.containsKey(mName)) { 
          // Found match 
          // Comparing new subtree to one saved during an earlier event (using ASTNode.subtreeMatch()) 
          methodHasChanged = !node.subtreeMatch(new ASTMatcher(), subtrees.get(mName)); 
         } else { 
          // No earlier entry found, definitely changed 
          methodHasChanged = true; 
         } 
         if (methodHasChanged) { 
          // "changed" is a HashMap of IMethods that have been earlierly identified as changed 
          // "added" works similarly but for added methods (using IJavaElementDelta.getAddedChildren()) 
          if (!changed.containsKey(mName) && !added.containsKey(mName)) { 
           // Method has indeed changed and is not yet queued for further actions 
           changed.put(mName, (IMethod) node.resolveBinding().getJavaElement()); 
          } 
         } 
         // "subtrees" must be updated with every method's AST subtree in order for this to work 
         subtrees.put(mName, node); 
         // continue visiting after first MethodDeclaration 
         return true; 
        } 
       }); 
      } 
     } 
    } 
} 

의견을 환영합니다.

관련 문제