-
-
Notifications
You must be signed in to change notification settings - Fork 358
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
fix: print square brackets in array initalisation #4341
Conversation
4c2e7fd
to
bb98a8d
Compare
I tried this approach today, but it fails to work for elements that have no source position. Maybe a better way to go about it is to just add metadata to |
@slarse I wanted to ask a question. I managed to attach metadata in
The model is built with metadata attached however, the Please note that f97fccd is not the perfect solution and that's why it hasn't been refactored yet. |
This reverts commit bb98a8d.
Approach 2
f97fccd
to
9328791
Compare
I needed some help with this pull request. Only one test is failing, and I cannot figure out why. I shall first explain the changes to get better insights. I have added a psuedo metamodel element in However, this approach works for all the existing test cases and the new ones introduced except @slarse @MartinWitt @I-Al-Istannen any thoughts? I am calling this a pseudo metamodel attribute because it is essentially not part of the AST but just metadata. I did not add it to AST because I agreed with @slarse 's comment here. |
The issue seems to be with the following line.
I think this invocation removes the metadata out of the type of field. The metadata is lost here. |
if (this.templateElement instanceof CtArrayTypeReferenceImpl) { | ||
((CtArrayTypeReferenceImpl<?>) clone).setDeclarationKind(((CtArrayTypeReferenceImpl<?>) this.templateElement).getDeclarationKind()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem was here. The metadata of the declaration style was lost here.
Should we consider copying the metadata as well? We can make it generic and do it for all ElementNode
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (this.templateElement instanceof CtArrayTypeReferenceImpl) { | |
((CtArrayTypeReferenceImpl<?>) clone).setDeclarationKind(((CtArrayTypeReferenceImpl<?>) this.templateElement).getDeclarationKind()); | |
} | |
clone.setAllMetadata(this.templateElement.getAllMetadata()); |
Something like this can be done. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that's a good idea, propagating metadata in a clone is a major change to semantics.
@monperrus is there a conscious decision for not "cloning" metadata?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a conscious decision for not "cloning" metadata?
no, seems to me that it is reasonable to clone the metadata as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, seems to me that it is reasonable to clone the metadata as well?
I'm unsure how it could affect e.g. gumtree-spoon-ast-diff, which uses metadata to map Gumtree nodes to Spoon nodes. And surely there is a reliance somewhere on not propagating metadata, so I'd label this as a breaking change if we use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unsure how it could affect e.g. gumtree-spoon-ast-diff, which uses metadata to map Gumtree nodes to Spoon nodes.
I can check if gumtree-spoon is affected in any way.
And surely there is a reliance somewhere on not propagating metadata
That could be an issue but our test cases are not able to catch that. I was also wondering that there are so many places where we clone elements. We should also discuss if they need to be changed as well. Otherwise, the definition of clone
shall vary from place to place.
EDIT:
Nothing breaks on gumtree-spoon.
I added topLevelClone.setAllMetadata(topLevelElement.getAllMetadata())
here and all the tests still pass. Retaining metadata does not seem to affect anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unsure how it could affect e.g. gumtree-spoon-ast-diff, which uses metadata to map Gumtree nodes to Spoon nodes.
I can check if gumtree-spoon is affected in any way.
And surely there is a reliance somewhere on not propagating metadata
That could be an issue but our test cases are not able to catch that. I was also wondering that there are so many places where we clone elements.
I don't mean in Spoon, but in some other app or library that uses Spoon. It's a behavioral change, and thus potentially breaking to dependents as something may be relying on the old behavior.
We should also discuss if they need to be changed as well. Otherwise, the definition of
clone
shall vary from place to place.
It might be good to add an explicit test to check that metadata is propagated in a clone.
Nothing breaks on gumtree-spoon.
That's good.
I added
topLevelClone.setAllMetadata(topLevelElement.getAllMetadata())
here and all the tests still pass. Retaining metadata does not seem to affect anything.
In libraries we control. Which is good but not sufficient to not mark this a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be good to add an explicit test to check that metadata is propagated in a clone.
@Test
public void test_cloneCopiesMetadata() {
String c1 = "public class A { }";
CtType < ? > type = Launcher.parseClass(c1);
type.putMetadata("meaning of life", 42);
CtType < ? > typeClone = type.clone();
assertEquals(1, typeClone.getAllMetadata().size());
}
This test case passed without the changes, which means that we have been cloning metadata as well, and this is the line that does it.
Cloning via clone
API is different from cloning via ElementNode
. Metadata was propagated for the former, however, it was ignored for the latter. I am unsure of the exact distinction between their semantics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is ready for review. @monperrus @slarse @MartinWitt @I-Al-Istannen , can you have a look? Summary of the changes.
A bit unrelated change: |
LGTM, will merge, thanks @algomaster99 |
@Nested | ||
@GitHubIssue(issueNumber = 4315) | ||
class SquareBracketPrintingInArrayInitialisation { | ||
// contract: square brackets should be printed *only* after the identifier of the field or local variable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@monperrus note that I have added the contract for the nested case instead of individual test cases because all of them are testing the same thing but resources are different.
Fixes #4315