Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 320683

Summary: [refactoring] [plan] Pull Out Refactoring: exception when pulling out a method from an Aspect into itself
Product: [Tools] AJDT Reporter: Kris De Volder <kdevolder>
Component: UIAssignee: AJDT-inbox <AJDT-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: andrew.eisenberg
Version: 2.1.0   
Target Milestone: 2.1.1   
Hardware: PC   
OS: Linux   
Whiteboard:
Attachments:
Description Flags
Fix for this issue + tests andrew.eisenberg: iplog+

Description Kris De Volder CLA 2010-07-22 20:27:25 EDT
Build Identifier: 

Example: pull out the test method into the aspect itself

----
package myspects;

import classzes.MyClass;

public aspect MyAspect {
	
	public void test() {}

	public void MyClass.pullMe() {
		System.out.println("Hi");
	}

}
---
!ENTRY org.eclipse.ltk.ui.refactoring 4 10000 2010-07-22 17:23:39.961
!MESSAGE Internal Error
!STACK 0
java.lang.reflect.InvocationTargetException
	at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:421)
	at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.run(RefactoringWizardDialog2.java:330)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizard.internalPerformFinish(RefactoringWizard.java:573)
	at org.eclipse.ltk.ui.refactoring.UserInputWizardPage.performFinish(UserInputWizardPage.java:153)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizard.performFinish(RefactoringWizard.java:646)
	at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.okPressed(RefactoringWizardDialog2.java:454)
	at org.eclipse.jface.dialogs.Dialog.buttonPressed(Dialog.java:472)
	at org.eclipse.jface.dialogs.Dialog$2.widgetSelected(Dialog.java:624)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:234)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3552)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3171)
	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:180)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation.run(RefactoringWizardOpenOperation.java:192)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation.run(RefactoringWizardOpenOperation.java:115)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoringAction.run(PullOutRefactoringAction.java:118)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoringAction.run(PullOutRefactoringAction.java:112)
	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$5.handleEvent(ActionContributionItem.java:411)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3552)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3171)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2629)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593)
	at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2427)
	at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:663)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	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:369)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1407)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1383)
Caused by: org.eclipse.core.runtime.AssertionFailedException: assertion failed: 
	at org.eclipse.core.runtime.Assert.isTrue(Assert.java:110)
	at org.eclipse.core.runtime.Assert.isTrue(Assert.java:96)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring.getInsertLocation(PullOutRefactoring.java:863)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring.access$2(PullOutRefactoring.java:861)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring$AspectRewrite.rewriteAspect(PullOutRefactoring.java:148)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring$AspectRewrite.access$0(PullOutRefactoring.java:120)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring.createChange(PullOutRefactoring.java:837)
	at org.eclipse.ltk.core.refactoring.CreateChangeOperation.run(CreateChangeOperation.java:124)
	at org.eclipse.ltk.core.refactoring.PerformChangeOperation.run(PerformChangeOperation.java:209)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1975)
	at org.eclipse.ltk.internal.ui.refactoring.WorkbenchRunnableAdapter.run(WorkbenchRunnableAdapter.java:87)
	at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:121)
Root exception:
org.eclipse.core.runtime.AssertionFailedException: assertion failed: 
	at org.eclipse.core.runtime.Assert.isTrue(Assert.java:110)
	at org.eclipse.core.runtime.Assert.isTrue(Assert.java:96)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring.getInsertLocation(PullOutRefactoring.java:863)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring.access$2(PullOutRefactoring.java:861)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring$AspectRewrite.rewriteAspect(PullOutRefactoring.java:148)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring$AspectRewrite.access$0(PullOutRefactoring.java:120)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoring.createChange(PullOutRefactoring.java:837)
	at org.eclipse.ltk.core.refactoring.CreateChangeOperation.run(CreateChangeOperation.java:124)
	at org.eclipse.ltk.core.refactoring.PerformChangeOperation.run(PerformChangeOperation.java:209)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1975)
	at org.eclipse.ltk.internal.ui.refactoring.WorkbenchRunnableAdapter.run(WorkbenchRunnableAdapter.java:87)
	at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:121)


Reproducible: Always
Comment 1 Kris De Volder CLA 2010-07-24 12:36:41 EDT
From the stacktrace, it looks like this may be nothing to do with being "from aspect to itself", but rather the assert that fails as in bug

https://bugs.eclipse.org/bugs/show_bug.cgi?id=320753

which was fixed in 

https://bugs.eclipse.org/bugs/show_bug.cgi?id=316809

However... there is still a problem with "pulling into same aspect or compilation unit".

When looking in the "preview" the inserts and deletions show up in two seperate "CU changes" (i.e. the compilation unit is shown twice, once showing the inserts, and once showing the deletions). In some cases when we execute the refactoring it "works" anyway, but in some cases it fails with some error in the error log

(e.g. in the example provided in this bug report we get:

eclipse.buildId=unknown
java.version=1.6.0_20
java.vendor=Sun Microsystems Inc.
BootLoader constants: OS=linux, ARCH=x86, WS=gtk, NL=en_CA
Framework arguments:  -product org.eclipse.platform.ide
Command-line arguments:  -product org.eclipse.platform.ide -data /home/kdvolder/workspaces/ajdt/../runtime-New_configuration -dev file:/home/kdvolder/workspaces/ajdt/.metadata/.plugins/org.eclipse.pde.core/New_configuration/dev.properties -os linux -ws gtk -arch x86 -consoleLog


Error
Sat Jul 24 09:25:01 PDT 2010
Unhandled event loop exception during blocked modal context.

org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.text.edits.MalformedTreeException: End position lies outside document range)
	at org.eclipse.swt.SWT.error(SWT.java:4083)
	at org.eclipse.swt.SWT.error(SWT.java:3998)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:137)
	at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3527)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3174)
	at org.eclipse.jface.operation.ModalContext$ModalContextThread.block(ModalContext.java:173)
	at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:388)
	at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.run(RefactoringWizardDialog2.java:330)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizard.internalPerformFinish(RefactoringWizard.java:573)
	at org.eclipse.ltk.internal.ui.refactoring.PreviewWizardPage.performFinish(PreviewWizardPage.java:384)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizard.performFinish(RefactoringWizard.java:646)
	at org.eclipse.ltk.internal.ui.refactoring.RefactoringWizardDialog2.okPressed(RefactoringWizardDialog2.java:454)
	at org.eclipse.jface.dialogs.Dialog.buttonPressed(Dialog.java:472)
	at org.eclipse.jface.dialogs.Dialog$2.widgetSelected(Dialog.java:624)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:234)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3552)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3171)
	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:180)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation.run(RefactoringWizardOpenOperation.java:192)
	at org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation.run(RefactoringWizardOpenOperation.java:115)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoringAction.run(PullOutRefactoringAction.java:116)
	at org.eclipse.ajdt.internal.ui.refactoring.pullout.PullOutRefactoringAction.run(PullOutRefactoringAction.java:110)
	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$5.handleEvent(ActionContributionItem.java:411)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1258)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3552)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3171)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2629)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593)
	at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2427)
	at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:663)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	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:369)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1407)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1383)
Caused by: org.eclipse.text.edits.MalformedTreeException: End position lies outside document range
	at org.eclipse.text.edits.TextEditProcessor.checkIntegrityDo(TextEditProcessor.java:178)
	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.performEdits(TextChange.java:277)
	at org.eclipse.ltk.core.refactoring.TextFileChange.access$0(TextFileChange.java:1)
	at org.eclipse.ltk.core.refactoring.TextFileChange$1.run(TextFileChange.java:275)
	at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
	at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:134)
	... 53 more
Comment 2 Andrew Eisenberg CLA 2010-07-26 13:55:54 EDT
> However... there is still a problem with "pulling into same aspect or
> compilation unit".
> 
> When looking in the "preview" the inserts and deletions show up in two seperate
> "CU changes" (i.e. the compilation unit is shown twice, once showing the
> inserts, and once showing the deletions). In some cases when we execute the
> refactoring it "works" anyway, but in some cases it fails with some error in
> the error log

This would make sense since the fix would only work if the two changes do not step on each other's toes.  This is why it is necessary to combine the two text edits into a single CompilationUnitChange.
Comment 3 Kris De Volder CLA 2010-07-26 15:13:40 EDT
Created attachment 175264 [details]
Fix for this issue + tests

This patch should fix the issue.

The fix makes it so that the changes for insertion and deletion of the ITD members are both added to the same CompilationUnitChange object. We do not create a new CUChange object for the aspect if it was already created during the generation of the changes for deleting ITDs.

This works because the deletions do not rewrite imports and all other edits are in completely disjoint regions of the CU text. (deletions are inside the aspect body whereas insertions happen just before the end of the any class or aspect body)
Comment 4 Andrew Eisenberg CLA 2010-07-26 19:01:35 EDT
Patch is applied and committed.