Bug 77538 - [dom] AST rewrite fails to generate the modified code
Summary: [dom] AST rewrite fails to generate the modified code
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 blocker (vote)
Target Milestone: 3.1 M3   Edit
Assignee: Frederic Fusier CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-11-02 15:59 EST by Olivier Thomann CLA
Modified: 2004-11-04 12:03 EST (History)
2 users (show)

See Also:


Attachments
Install in your workspace (12.10 KB, application/octet-stream)
2004-11-02 16:02 EST, Olivier Thomann CLA
no flags Details
A.java test case (617 bytes, text/plain)
2004-11-02 16:03 EST, Olivier Thomann CLA
no flags Details
More complete fix (3.57 KB, patch)
2004-11-03 09:02 EST, Frederic Fusier CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Olivier Thomann CLA 2004-11-02 15:59:24 EST
I get an assertion error using latest when trying to modify an existing
compilation unit.
This is critical for SWT. They would like to add statements inside existing code
and this small plugin should do the work, but it fails because of a bug in the
DefaultCommentMapper.

Steps to reproduce:
1) Install the attached plugin
2) Start a self-hosting workspace
3) Create a project P in which you add a compilation A with the contents attached.
4) Click on the banana icon
5) You should get the following stack trace in the .log:
org.eclipse.jface.text.Assert$AssertionFailedException: Assertion failed: 
	at org.eclipse.jface.text.Assert.isTrue(Assert.java:177)
	at org.eclipse.jface.text.Assert.isTrue(Assert.java:162)
	at org.eclipse.text.edits.TextEdit.<init>(TextEdit.java:149)
	at org.eclipse.text.edits.MoveSourceEdit.<init>(MoveSourceEdit.java:59)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.getCopySourceEdit(ASTRewriteAnalyzer.java:124)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doCopySourcePreVisit(ASTRewriteAnalyzer.java:1209)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.preVisit(ASTRewriteAnalyzer.java:1192)
	at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2448)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doVisit(ASTRewriteAnalyzer.java:249)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doTextRemoveAndVisit(ASTRewriteAnalyzer.java:241)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.rewriteMethodBody(ASTRewriteAnalyzer.java:916)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.visit(ASTRewriteAnalyzer.java:1436)
	at org.eclipse.jdt.core.dom.MethodDeclaration.accept0(MethodDeclaration.java:489)
	at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2450)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doVisit(ASTRewriteAnalyzer.java:249)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doVisitList(ASTRewriteAnalyzer.java:280)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doVisitUnchangedChildren(ASTRewriteAnalyzer.java:298)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.visit(ASTRewriteAnalyzer.java:1249)
	at org.eclipse.jdt.core.dom.TypeDeclaration.accept0(TypeDeclaration.java:469)
	at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2450)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doVisit(ASTRewriteAnalyzer.java:249)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doVisitList(ASTRewriteAnalyzer.java:280)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doVisitUnchangedChildren(ASTRewriteAnalyzer.java:298)
	at
org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.visit(ASTRewriteAnalyzer.java:1229)
	at org.eclipse.jdt.core.dom.CompilationUnit.accept0(CompilationUnit.java:286)
	at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2450)
	at
org.eclipse.jdt.core.dom.InternalASTRewrite.rewriteAST(InternalASTRewrite.java:71)
	at org.eclipse.jdt.core.dom.AST.rewrite(AST.java:2709)
	at org.eclipse.jdt.core.dom.CompilationUnit.rewrite(CompilationUnit.java:834)
	at actions.SampleAction.run(SampleAction.java:94)
	at org.eclipse.ui.internal.PluginAction.runWithEvent(PluginAction.java:298)
	at org.eclipse.ui.internal.WWinPluginAction.runWithEvent(WWinPluginAction.java:221)
	at
org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:946)
	at
org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:896)
	at
org.eclipse.jface.action.ActionContributionItem$8.handleEvent(ActionContributionItem.java:851)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:82)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:800)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:2794)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2448)
	at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:1527)
	at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1498)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:276)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:144)
	at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplication.java:102)
	at
org.eclipse.core.internal.runtime.PlatformActivator$1.run(PlatformActivator.java:335)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:273)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:129)
	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:585)
	at org.eclipse.core.launcher.Main.basicRun(Main.java:185)
	at org.eclipse.core.launcher.Main.run(Main.java:684)
	at org.eclipse.core.launcher.Main.main(Main.java:668)
Comment 1 Olivier Thomann CLA 2004-11-02 16:02:58 EST
Created attachment 15577 [details]
Install in your workspace
Comment 2 Olivier Thomann CLA 2004-11-02 16:03:26 EST
Created attachment 15578 [details]
A.java test case
Comment 3 Olivier Thomann CLA 2004-11-02 16:25:11 EST
As soon as we have a comment in the code, it is failing.
Comment 4 Philipe Mulet CLA 2004-11-02 16:32:31 EST
Pls investigate:
1. is this a regression from M2 ?
2. can it be fixed (easily) for M3 ?
Comment 5 Frederic Fusier CLA 2004-11-03 05:07:41 EST
Already happens in 3.1 M2 and 3.0.1...
Comment 6 Frederic Fusier CLA 2004-11-03 06:04:07 EST
Understand what happens...
DefaultCommentMapper return extended positions of parent for some specific nodes.
This is the case in this example: a TryStatement with one child Block.
But the block was this of foo method body (so ORIGINAL) but its parent was
created and its start position = -1 and length = 0...!
=> modify algorithm in DefaultCommentMapper not to return parent extended
positions when parent is NOT ORIGINAL:

public int getExtendedEnd(ASTNode node) {
  int end = node.getStartPosition() + node.getLength();
  if (this.trailingComments != null) {
    int[] range = (int[]) this.trailingComments.get(node);
    if (range != null) {
      if (range[0] == -1 && range[1] == -1) {
        ASTNode parent = node.getParent();
        if (parent != null && ((parent.getFlags() & ASTNode.ORIGINAL) != 0)) {
          return getExtendedEnd(parent);
        }
      } else {
        Comment lastComment = this.comments[range[1]];
        end = lastComment.getStartPosition() + lastComment.getLength();
      }
    }
  }
  return end-1;
}
Comment 7 Frederic Fusier CLA 2004-11-03 07:50:17 EST
All tests are green:
- JDT/Core
- DefaultCommentMapper
- JDT/UI

=> I think it's a good candidate for M3...
Comment 8 Frederic Fusier CLA 2004-11-03 09:02:19 EST
Created attachment 15599 [details]
More complete fix

Previous change was not enough as while rewriting parent may be original but
different. Then, returned extended position would be wrong although not equals
to -1!
A better solution is to resolved extended positions for this kind of nodes
during the initialzation and first visit of the ASTNodes hierarchy...
Comment 9 Frederic Fusier CLA 2004-11-03 09:29:03 EST
Using this new patch, all JDT/Core tests are green but DefaultCommentMapper
specific tests failed...

Furthermore, this may be time consuming. So for M3, as deeper investigation is
needed to complete this fix, only first version can be released and I'd open a
new bug in case this one was fixed...
Comment 10 Philipe Mulet CLA 2004-11-03 09:32:05 EST
Ok for me.
Comment 11 Olivier Thomann CLA 2004-11-03 10:19:37 EST
In case a block has a new statement, I don't think it should be considered as
orignal anymore.
Comment 12 Frederic Fusier CLA 2004-11-03 10:36:14 EST
Olivier, the problem is on parent, not on node itself.
So, even if you keep the same block content but just move it to a new parent
created by the parser (ie. ORIGINAL), then you 'll get wrong extended positions
with the fix written in comment 6...
I've opened bug 77644 to track this issue and put you in CC list
Comment 13 Frederic Fusier CLA 2004-11-03 12:02:31 EST
Fixed.

Click on banana icon now modifies correctly the file A.java...

[jdt-core-internal]
Change done in DefaultCommentMapper.getExtendedEnd(ASTNode) as described in
comment 6.
Test case added: ASTRewritingMethodDeclTests#testMethodDeclChangesBug77538()
Comment 14 Philipe Mulet CLA 2004-11-04 05:28:50 EST
Ok for M3
Comment 15 David Audel CLA 2004-11-04 12:03:22 EST
Verified with build I200411040100 for 3.1M3