2009-11-18 2 views
52

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; 
    } 
} 
+1

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. –

+1

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

Antwort

2

fand ich den eclipse.org Artikel das nützlichste mich um loszulegen.

Ein guter Einstieg in den Debugging-Code ist das Setzen von Breakpoints auf org.eclipse.jdt.core.dom.rewrite.ASTRewrite, insbesondere die rewriteAST() -Methode, um dann einige Refactorings auszulösen.

Hier sind ein paar nützliche Hinweise. Suchen Sie etwas Bestimmtes oder ein allgemeines Gespür für die Bearbeitung des AST?

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

Hallo, Danke für die Tipps und Links. Ich hatte die Links von ibm und vogella gesehen, aber nicht die andere. Es ist lange her, dass ich an diesem Code gearbeitet habe, er war Teil einer Masterarbeit und funktional genug, um ihn zu verwenden. Ich werde den Code in den nächsten Wochen oder so ausgraben und sehen, ob ich das Problem angehen kann. Ich verlor mich jedes Mal, wenn ich den jdt debuggte. Die Ebenen der Indirektion sind endlos und die Stock-Refactorings sind mit einer privaten Abstraktionsschicht implementiert, die es schwierig macht, sie zu entschlüsseln. – iain

Verwandte Themen