自定义Eclipse重构预览中的错误

我正在实现一个新的eclipse重构。 这将使开发人员能够将子方法的前置条件语句拉到父方法。

当我在重构向导中select“完成”时,这一切都可以正常工作,但是当我select“预览”时,出现“未提供任何目标编辑”错误。 这似乎是由ASTRewrite.rewriteAST()返回的TextEdit的问题引起的。 但是我不明白为什么。

exception的堆栈跟踪发生在我的Refactoring.createChange()代码运行后,并且更改用于生成预览。

 org.eclipse.text.edits.MalformedTreeException: No target edit provided. at org.eclipse.text.edits.MoveSourceEdit.performConsistencyCheck(MoveSourceEdit.java:208) at org.eclipse.text.edits.TextEdit.traverseConsistencyCheck(TextEdit.java:873) at org.eclipse.text.edits.MoveSourceEdit.traverseConsistencyCheck(MoveSourceEdit.java:183) at org.eclipse.text.edits.TextEdit.traverseConsistencyCheck(TextEdit.java:869) at org.eclipse.text.edits.TextEdit.traverseConsistencyCheck(TextEdit.java:869) at org.eclipse.text.edits.TextEditProcessor.checkIntegrityDo(TextEditProcessor.java:176) at org.eclipse.text.edits.TextEdit.dispatchCheckIntegrity(TextEdit.java:743) at org.eclipse.text.edits.TextEditProcessor.performEdits(TextEditProcessor.java:151) at org.eclipse.ltk.core.refactoring.TextChange.getPreviewDocument(TextChange.java:534) at org.eclipse.ltk.core.refactoring.TextChange.getPreviewDocument(TextChange.java:403) at org.eclipse.ltk.core.refactoring.TextChange.getPreviewContent(TextChange.java:411) at org.eclipse.ltk.internal.ui.refactoring.TextEditChangePreviewViewer.setInput(TextEditChangePreviewViewer.java:209) at org.eclipse.ltk.internal.ui.refactoring.AbstractChangeNode.feedInput(AbstractChangeNode.java:99) at org.eclipse.ltk.internal.ui.refactoring.PreviewWizardPage.showPreview(PreviewWizardPage.java:598) at org.eclipse.ltk.internal.ui.refactoring.PreviewWizardPage.access$6(PreviewWizardPage.java:583) at org.eclipse.ltk.internal.ui.refactoring.PreviewWizardPage$7.selectionChanged(PreviewWizardPage.java:574) at org.eclipse.jface.viewers.Viewer$2.run(Viewer.java:162) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) at org.eclipse.core.runtime.Platform.run(Platform.java:888) at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:48) at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) at org.eclipse.jface.viewers.Viewer.fireSelectionChanged(Viewer.java:160) at org.eclipse.jface.viewers.StructuredViewer.updateSelection(StructuredViewer.java:2132) at org.eclipse.jface.viewers.StructuredViewer.setSelection(StructuredViewer.java:1669) at org.eclipse.jface.viewers.TreeViewer.setSelection(TreeViewer.java:1124) at org.eclipse.jface.viewers.Viewer.setSelection(Viewer.java:392) at org.eclipse.ltk.internal.ui.refactoring.PreviewWizardPage.setVisible(PreviewWizardPage.java:505) at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.makeVisible(RefactoringWizardDialog2.java:762) at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.showCurrentPage(RefactoringWizardDialog2.java:477) at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.nextOrPreviewPressed(RefactoringWizardDialog2.java:507) at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.access$2(RefactoringWizardDialog2.java:492) at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2$1.widgetSelected(RefactoringWizardDialog2.java:691) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473) at org.eclipse.jface.window.Window.runEventLoop(Window.java:825) at org.eclipse.jface.window.Window.open(Window.java:801) at org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation$1.run(RefactoringWizardOpenOperation.java:143) at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) at org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation.run(RefactoringWizardOpenOperation.java:155) at org.jmlspecs.eclipse.refactor.action.AbstractMethodActionDelegate.run(AbstractMethodActionDelegate.java:78) at org.jmlspecs.eclipse.refactor.action.AbstractMethodActionDelegate.run(AbstractMethodActionDelegate.java:67) at org.eclipse.ui.internal.PluginAction.runWithEvent(PluginAction.java:251) at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:584) at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:501) at org.eclipse.jface.action.ActionContributionItem$6.handleEvent(ActionContributionItem.java:452) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2405) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2369) at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2221) at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:500) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:493) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514) at org.eclipse.equinox.launcher.Main.run(Main.java:1311) at org.eclipse.equinox.launcher.Main.main(Main.java:1287) 

目前执行更改的代码如下所示:

 CompilationUnit sourceNode = ... ASTRewrite sourceRewrite = ASTRewrite.create(sourceNode.getAST()); Statement statement = ... sourceRewrite.createMoveTarget(statement); CompilationUnit destinationNode = ... MethodDeclaration destinationMethod = ... ASTRewrite destinationRewrite = ASTRewrite.create(destinationNode.getAST()); ListRewrite lrw = destinationRewrite.getListRewrite(destinationMethod.getBody(), Block.STATEMENTS_PROPERTY); lrw.insertFirst(statement, null); 

我知道使用createMoveTarget的方式不是如何logging,但是当我按照下面的文档,从源删除语句,但没有移动到目的地,我仍然在预览中得到相同的错误。

 CompilationUnit sourceNode = ... ASTRewrite sourceRewrite = ASTRewrite.create(sourceNode.getAST()); Statement statement = ... Statement replacement = sourceRewrite.createMoveTarget(statement); sourceRewrite.remove(statement, null); CompilationUnit destinationNode = ... MethodDeclaration destinationMethod = ... ASTRewrite destinationRewrite = ASTRewrite.create(destinationNode.getAST()); ListRewrite lrw = destinationRewrite.getListRewrite(destinationMethod.getBody(), Block.STATEMENTS_PROPERTY); lrw.insertFirst(replacement, null); 

这是重构正在执行的一个例子。

之前:

 class A { foo(int a) { return a * 2; } } class B { foo(int a) { JC.requires(a > 1); return a * 3; } } 

后:

 class A { foo(int a) { JC.requires(a > 1); return a * 2; } } class B extends A { foo(int a) { return a * 3; } } 

我发现eclipse.org文章最有帮助,让我开始。

开始debugging代码的好地方是在org.eclipse.jdt.core.dom.rewrite.ASTRewrite上设置断点,特别是rewriteAST()方法,然后触发一些重构。

这里有几个你可能会觉得有用的。 你在寻找什么特别的东西,或者如何处理AST的一般意义?

 http://www.ibm.com/developerworks/opensource/library/os-ast/ http://blog.sahits.ch/?p=228 http://www.vogella.com/articles/EclipseJDT/article.html