Ich bin ein neues Eclipse Refactoring implementieren. Dadurch können Entwickler die Vorbedingungen-Anweisungen von einer untergeordneten Methode auf die übergeordnete Methode heraufziehen.Fehler in der Vorschau von Custom Eclipse Refactoring
Das alles funktioniert perfekt, wenn ich im Refactoring-Assistenten "Fertig stellen" auswähle, aber wenn ich "Vorschau" wähle, bekomme ich einen Fehler "Keine Zieleingabe zur Verfügung gestellt." Dies scheint durch ein Problem in TextEdit
verursacht von ASTRewrite.rewriteAST()
verursacht worden zu sein. Ich kann jedoch nicht herausfinden warum.
Die Stack-Ablaufverfolgung der Ausnahme passiert, nachdem mein Refactoring.createChange()
Code ausgeführt wird, und die Änderung wird verwendet, um die Vorschau zu generieren.
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)
Zur Zeit der Code, der die Änderung wie folgt aussieht führt:
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);
Ich weiß, dass die Art und Weise createMoveTarget
verwendet wird, ist nicht, wie es dokumentiert ist, aber wenn ich beachten Sie die Dokumentation wie unten, die Anweisung wird aus der Quelle gelöscht, aber nicht an das Ziel verschoben, und ich bekomme immer noch den gleichen Fehler in der Vorschau.
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);
Hier ist ein Beispiel für das durchgeführte Refactoring.
Vorher:
class A {
foo(int a) {
return a * 2;
}
}
class B {
foo(int a) {
JC.requires(a > 1);
return a * 3;
}
}
Nach:
class A {
foo(int a) {
JC.requires(a > 1);
return a * 2;
}
}
class B extends A {
foo(int a) {
return a * 3;
}
}
Ihr Refactoring-Beispiel ist eigentlich kein Refactoring, da es die Semantik ändert, aber das liegt an Ihnen. Es ist schwer zu sagen, was mit dem Code nicht stimmt, da ein Teil der Quellen im Stapel nicht verfügbar ist. Vielleicht sollten Sie verfolgen, warum MoveSourceEdit.setTargetEdit nicht aufgerufen oder mit Null-Argument aufgerufen wird. –
Hallo Petr, danke für deinen Vorschlag. Ich werde das genauer untersuchen und eine Sonnenfinsternis mit meiner eigenen vergleichen. Hinsichtlich der Änderung der Semantik beim Refactoring von Spezifikationen ist das sehr interessant, da es die meisten akademischen Arbeiten in diesem Bereich widerspiegelt. Die Fowler-Definition behält jedoch nur das Verhalten bei, zum Beispiel ändert die Pull-Up-Methode die Semantik der Klassenhierarchie. Ich könnte eine Option hinzufügen, um die Semantik beizubehalten, indem ich der Anweisung eine neue Klausel hinzufüge. Jedenfalls wäre ich daran interessiert, das mit dir weiter zu besprechen. – iain