以编程方式重构参数名称

时间:2013-01-18 22:20:12

标签: java eclipse parameters refactoring

使用eclipse的jdt重构框架,我试图将两个不同的代码库转换为相同的名称。它们几乎是相同的代码库,除了名称不同。 函数/字段/类重命名工作正常,但是当涉及到参数时,它会向我大喊工作台尚未创建。但是,我试图在无头庄园里做这件事。

private void refactor(String task, IJavaElement element, String new_name) throws CoreException
{
    RefactoringStatus status = new RefactoringStatus();

    RefactoringContribution contrib = RefactoringCore.getRefactoringContribution(task);
    RenameJavaElementDescriptor rnDesc = (RenameJavaElementDescriptor)contrib.createDescriptor();
    rnDesc.setFlags(JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING);
    rnDesc.setProject(element.getJavaProject().getProject().getName());
    rnDesc.setUpdateReferences(true);
    rnDesc.setJavaElement(element);
    rnDesc.setNewName(new_name);

    Refactoring ref = rnDesc.createRefactoring(status);

    ref.checkInitialConditions(NULL_MON);
    ref.checkFinalConditions(NULL_MON);

    Change change = ref.createChange(NULL_MON);
    change.perform(NULL_MON);
}

这很好用:

for (IMethod method : type.getMethods())
{
    refactor(IJavaRefactorings.RENAME_METHOD, method, {new name});
}

这不是:

for (IMethod method : type.getMethods())
{
    for (ILocalVariable param : method.getParameters())
    {
        refactor(IJavaRefactorings.RENAME_LOCAL_VARIABLE, param, {new name});
    }
}

错误,并没有真正有用,因为我说我需要在无头庄园做这个{所以不能做工作台}

java.lang.IllegalStateException: Workbench has not been created yet.
    at org.eclipse.ui.PlatformUI.getWorkbench(PlatformUI.java:92)
    at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.install(ASTProvider.java:245)
    at org.eclipse.jdt.internal.ui.javaeditor.ASTProvider.<init>(ASTProvider.java:236)
    at org.eclipse.jdt.internal.ui.JavaPlugin.getASTProvider(JavaPlugin.java:710)
    at org.eclipse.jdt.ui.SharedASTProvider.getAST(SharedASTProvider.java:128)
    at org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser.parseWithASTProvider(RefactoringASTParser.java:119)
    at org.eclipse.jdt.internal.corext.refactoring.rename.RenameLocalVariableProcessor.initAST(RenameLocalVariableProcessor.java:231)
    at org.eclipse.jdt.internal.corext.refactoring.rename.RenameLocalVariableProcessor.checkInitialConditions(RenameLocalVariableProcessor.java:218)
    at org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring.checkInitialConditions(ProcessorBasedRefactoring.java:203)

更新:取得了一些进展,现在我可以重构不会覆盖的功能。但任何覆盖另一个或界面的功能都会搞砸:

F_ARGUMENTS = JavaRefactoringDescriptor.class.getDeclaredField("fArguments");
F_ARGUMENTS.setAccessible(true);

private void refactor(IMethod method, String[] names) throws CoreException
{
    /* My attempt to fix the interface issues, causes duplicate functions instead of renaming the parameters
    IMethod parent = null;
    if (method.getDeclaringType().isInterface())
    {
        parent = MethodChecks.overridesAnotherMethod(method, method.getDeclaringType().newSupertypeHierarchy(NULL_MON));
    }
    else if (MethodChecks.isVirtual(method))
    {
        ITypeHierarchy hierarchy = method.getDeclaringType().newTypeHierarchy(NULL_MON);
        parent = MethodChecks.isDeclaredInInterface(method, hierarchy, NULL_MON);
        if (parent == null)
        {
            parent = MethodChecks.overridesAnotherMethod(method, hierarchy);
        }
    }

    parent = (parent == null ? method : parent);
    if (!method.equals(parent))
    {
        refactor(parent, names);
        return;
    }*/

    String task = IJavaRefactorings.CHANGE_METHOD_SIGNATURE;
    RefactoringStatus status = new RefactoringStatus();

    ChangeMethodSignatureRefactoringContribution contrib = (ChangeMethodSignatureRefactoringContribution)RefactoringCore.getRefactoringContribution(task);
    ChangeMethodSignatureDescriptor desc = (ChangeMethodSignatureDescriptor)contrib.createDescriptor();
    desc.setFlags(JavaRefactoringDescriptor.JAR_MIGRATION |
                  JavaRefactoringDescriptor.JAR_REFACTORING |
                  RefactoringDescriptor.MULTI_CHANGE |
                  RefactoringDescriptor.STRUCTURAL_CHANGE);

    Map<String, String> args = null;
    try
    {
        args = (Map<String, String>)F_ARGUMENTS.get(desc);
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    String project = method.getJavaProject().getProject().getName();

    desc.setProject(method.getJavaProject().getProject().getName());

    args.put("input", JavaRefactoringDescriptorUtil.elementToHandle(project, method));
    args.put("name", method.getElementName());
    args.put("deprecate", "false");
    args.put("delegate", "true");        

    boolean changed = false;
    int x = 0;
    for (ILocalVariable param : method.getParameters())
    {
        if (!param.getElementName().equals(names[x]))
        {
            changed = true;
        }
        String type = "String"; //Doesn't seem to actually matter as long as they are both the same
        String info = type + " " + param.getElementName() + " " + x + " " + 
                      type + " " + names[x] + " false";
        args.put("parameter" + (x + 1), info);
        x++;
    }
    if (changed)
    {
        refactor(desc.createRefactoring(status));
    }
}

1 个答案:

答案 0 :(得分:2)

这就是我提出的:

ChangeSignatureProcessor changeSignatureProcessor = new ChangeSignatureProcessor((IMethod) node.resolveBinding().getJavaElement());

ParameterInfo info=new ParameterInfo("FormContext", "formContext", ParameterInfo.INDEX_FOR_ADDED);
info.setDefaultValue("formContext");
changeSignatureProcessor.getParameterInfos().add(0,info);

RefactoringStatus status = new RefactoringStatus();
CheckConditionsContext context= new CheckConditionsContext();
context.add(new ValidateEditChecker(null));
context.add(new ResourceChangeChecker());

changeSignatureProcessor.checkInitialConditions(monitor);
changeSignatureProcessor.checkFinalConditions(monitor,context);

changeSignatureProcessor.createChange(monitor).perform(monitor);