2012-04-07 21 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; 
}