2012-04-07 72 views
1

當我寫的代碼,我有一絲呼籲在每個看起來像這樣方法的開始:Eclipse的RenameParticipant偏移處理

public void doOperation() 
{ 
    Trace tr = new Trace("doOperation"); 
    ... method body ... 
} 

我想寫一個Eclipse插件,這樣,當我重命名方法跟蹤方法調用中的字符串常量也會更新。爲了實現這一點,我正在實施一個RenameParticipant。

我遇到的問題是隻有當方法名稱不改變長度時,我生成的更改才能正常工作。如果方法名稱改變了長度,那麼我的更改最終會在更改後的文件中編輯錯誤的偏移量。

我在做什麼錯?我怎樣才能說明方法重命名可能會改變我的跟蹤調用文件中的偏移量?


要計算我用下面的代碼更改:

@Override 
public Change createChange(IProgressMonitor pm) 
    throws CoreException, 
     OperationCanceledException 
{ 
    ICompilationUnit unit = element.getCompilationUnit(); 
    CompilationUnit astCompUnit = parse(unit, pm); 
    ASTNode astElement = NodeFinder.perform(astCompUnit, element.getNameRange()); 
    MethodDeclaration astMethod = (MethodDeclaration)getParent(astElement, MethodDeclaration.class); 

    String newName = getArguments().getNewName(); 
    List<TraceFnFixOperation> ops = new ArrayList<TraceFnFixOperation>(1); 
    TraceFnCtorFinder finder = new TraceFnCtorFinder(newName, ops); 
    astMethod.accept(finder); 

    if (ops.size() == 0) 
    return null; 

    return new TraceChange("Fix Trace", unit, ops); 
} 

的TraceFnCtorFinder的身體:

public static class TraceFnCtorFinder extends ASTVisitor 
{ 
    private final String methodName; 
    private final List<TraceFnFixOperation> workingops; 

    public TraceFnCtorFinder(String methodName, List<TraceFnFixOperation> workingops) 
    { 
    this.methodName = methodName; 
    this.workingops = workingops; 
    } 

    @Override 
    public boolean visit(ClassInstanceCreation ctorClass) 
    { 
    Type type = ctorClass.getType(); 

    // Only examine simple types 
    if (type.isSimpleType()) 
    { 
     SimpleType simpleType = (SimpleType)type; 
     String typeName = simpleType.getName().getFullyQualifiedName(); 

     // Check type has correct name 
     if ("Trace".equals(typeName)) 
     { 
     List<?> arguments = ctorClass.arguments(); 

     // Only check a single argument 
     if ((arguments != null) && 
      (arguments.size() == 1)) 
     { 
      Object arg = arguments.get(0); 

      // Only check a string literal argument 
      if (arg instanceof StringLiteral) 
      { 
      StringLiteral literal = (StringLiteral) arg; 
      String currentArg = literal.getLiteralValue(); 

      // Check whether argument value is valid 
      if (!methodName.equals(currentArg)) 
      { 
       workingops.add(new TraceFnFixOperation(literal.getStartPosition(), 
                literal.getLength(), 
                methodName)); 
      } 
      } 
     } 
     } 
    } 
    return false; 
    } 
} 

TraceChange的身體:

public static class TraceChange extends CompilationUnitChange 
{ 
    public TraceChange(String name, 
        ICompilationUnit cunit, 
        List<TraceFnFixOperation> ops) 
    { 
    super(name, cunit); 

    MultiTextEdit multiTextEdit= new MultiTextEdit(); 
    setEdit(multiTextEdit); 
    for (TraceFnFixOperation op : ops) 
    { 
     addEdit(new ReplaceEdit(op.startPosition, 
           op.length, 
           "\"" + op.methodName + "\"")); 
    } 
    } 
} 

回答

1

我能夠得到我的代碼w通過使用createPreChange(...)進行修改。這使我可以返回執行主重構之前在源上執行的更改。這意味着我的代碼計算的變化在實際應用時仍然是準確的。

http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fltk%2Fcore%2Frefactoring%2Fparticipants%2FRefactoringParticipant.html

編輯:使用createPreChange(...)是真的只是一個解決方法,因爲我的改變仍然可以與另一個PreChange衝突。通過回到使用createChange(...)並調用getTextChange(...)來獲取現有文本編輯對象並將編輯添加到此對象,我想出了一個更好的解決方案。這似乎使補償正常工作。

public Change createChange(IProgressMonitor pm) 
    throws CoreException, 
     OperationCanceledException 
{ 
    ICompilationUnit unit = element.getCompilationUnit(); 
    TextChange change = getTextChange(unit); 

    // Failed to find existing change to add our changes to 
    if (change == null) 
    return null; 

    // Find the AST version of the method being changed 
    CompilationUnit astCompUnit = parse(unit, pm); 
    ASTNode astElement = NodeFinder.perform(astCompUnit, element.getNameRange()); 
    MethodDeclaration astMethod = (MethodDeclaration)getParent(astElement, MethodDeclaration.class); 

    // Visit the contents of the method to find changes to make 
    String newName = getArguments().getNewName(); 
    List<TraceFnFixOperation> ops = new ArrayList<TraceFnFixOperation>(1); 
    TraceFnCtorFinder finder = new TraceFnCtorFinder(newName, ops); 
    astMethod.accept(finder); 

    // Add identified edits to the overall change 
    for (TraceFnFixOperation op : ops) 
    { 
    change.addEdit(new ReplaceEdit(op.startPosition, 
            op.length, 
            "\"" + op.methodName + "\"")); 
    } 

    // Don't return a dedicated change 
    return null; 
}