Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASTRewrite.rewriteAST fails with AssertionFailedException for records when it contains inner class #3002

Merged
merged 6 commits into from
Oct 16, 2024

Conversation

subyssurendran666
Copy link
Contributor

@subyssurendran666 subyssurendran666 commented Sep 24, 2024

What it does

#2835

How to test

Author checklist

@jarthana
Copy link
Member

@subyssurendran666 Can you say a word or two about the root cause of the problem and what the fix does? Thanks!

Copy link
Member

@jarthana jarthana left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said on the PR, a word or two about why the fix is correct would help speed up the review. For e.g., it's not clear why this is not a problem for regular classes but only a problem for records?

@subyssurendran666
Copy link
Contributor Author

I have a code snippet

record Test(String name, String address) {

    public static Builder builder() {
    }

    public static final class Builder {
    }
}

and trying to rewrite the inner node using the ASTRewrite, then it throws an exception

org.eclipse.core.runtime.AssertionFailedException: assertion failed: 
	at org.eclipse.core.runtime.Assert.isTrue(Assert.java:113)
	at org.eclipse.core.runtime.Assert.isTrue(Assert.java:99)
	at org.eclipse.text.edits.TextEdit.<init>(TextEdit.java:153)
	at org.eclipse.text.edits.DeleteEdit.<init>(DeleteEdit.java:36)
	at org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doTextRemove(ASTRewriteAnalyzer.java:409)
	at org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer$ListRewriter.rewriteList(ASTRewriteAnalyzer.java:752)

The exception occurs when the length of DeleteEdit becomes negative. However, when I change the record in the test to a class, the issue resolves.

In the method ASTRewriteAnalyzer.doTextRemove(), it already checks if the len == 0 and returns null accordingly. I applied a similar check to handle cases where the value becomes negative.

@subyssurendran666
Copy link
Contributor Author

I have a code snippet

record Test(String name, String address) {

    public static Builder builder() {
    }

    public static final class Builder {
    }
}

and trying to rewrite the inner node using the ASTRewrite, then it throws an exception

org.eclipse.core.runtime.AssertionFailedException: assertion failed: 
	at org.eclipse.core.runtime.Assert.isTrue(Assert.java:113)
	at org.eclipse.core.runtime.Assert.isTrue(Assert.java:99)
	at org.eclipse.text.edits.TextEdit.<init>(TextEdit.java:153)
	at org.eclipse.text.edits.DeleteEdit.<init>(DeleteEdit.java:36)
	at org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer.doTextRemove(ASTRewriteAnalyzer.java:409)
	at org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer$ListRewriter.rewriteList(ASTRewriteAnalyzer.java:752)

The exception occurs when the length of DeleteEdit becomes negative. However, when I change the record in the test to a class, the issue resolves.

In the method ASTRewriteAnalyzer.doTextRemove(), it already checks if the len == 0 and returns null accordingly. I applied a similar check to handle cases where the value becomes negative.

@jarthana I've noticed another issue related to the AST: the starting position of the MethodDeclaration is invalid. I'm currently debugging this issue.

Screenshot 2024-10-11 at 3 08 29 PM

@subyssurendran666
Copy link
Contributor Author

subyssurendran666 commented Oct 13, 2024

The method ASTConvert.convert(TypeDeclaration) is responsible for converting the Compiler AST into a DOM AST, utilising ASTConverter.convertToRecordDeclaration(). During this conversion, it invokes ASTConverter.buildBodyDeclarations() to handle the body declarations. In this process, the typeDeclaration may include a default constructor, even if the test code doesn't explicitly define one. This is due to the automatic constructor generation by the Eclipse Compiler for Java (ECJ).

As the ASTConverter attempts to generate a RecordDeclaration from the Compiler AST, it processes the body in a specific order: fields first, then methods, and finally member types. In the current scenario, there are no fields, so the converter immediately moves on to the methods. The first method encountered is the default constructor generated by the ECJ, which is correctly omitted. The process then moves to the member types.

The issue arises in the subsequent iteration of the loop, which only processes members. This behavior leads to the BAD AST issue, as the ASTConverter incorrectly handles the generated RecordDeclaration. This misprocessing is also the root cause of the reported issue with ASTRewrite. The ASTRewrite process ends up rewriting the wrong inner node inside the record, which results in an invalid AST structure.

Screenshot 2024-10-13 at 3 26 20 PM

The positions of the inner nodes inside the MethodDeclaration in the DOM AST have now been corrected.

Copy link
Contributor

@mpalat mpalat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@subyssurendran666 since this is an issue primarily due to conversion, can you please add a junit test case for DOM AST conversion. Once review comments are incorporated please go ahead and merge. Thanks!

@subyssurendran666
Copy link
Contributor Author

@subyssurendran666 since this is an issue primarily due to conversion, can you please add a junit test case for DOM AST conversion. Once review comments are incorporated please go ahead and merge. Thanks!

Sure, I will add ASTConversion test also.

@subyssurendran666 subyssurendran666 force-pushed the ASTRewrite-fail-2835 branch 2 times, most recently from a11cb36 to 8a2f7b7 Compare October 14, 2024 10:22
@subyssurendran666
Copy link
Contributor Author

As I said on the PR, a word or two about why the fix is correct would help speed up the review. For e.g., it's not clear why this is not a problem for regular classes but only a problem for records?

Done.

@mpalat mpalat merged commit fdfdec2 into eclipse-jdt:master Oct 16, 2024
10 checks passed
@mpalat
Copy link
Contributor

mpalat commented Oct 16, 2024

@jarthana: I took the liberty of merging - didn't want to risk another rebase :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants