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

Fixes for missing position information and invocation ordering problem #262

Conversation

benmss
Copy link
Contributor

@benmss benmss commented Dec 1, 2022

Two issues are fixed in this pull request:

Missing Position Information
CtVirtualElement and CtWrapper objects do not contain the related position information. As this information is still useful, especially for debugging purposes, this fix correctly maps the objects to their position information during creation. For the case where CtWrapper objects represent more than one code element, the positions are merged.
Relates to: Issue 199 and Issue 132

Invocation Ordering
In the AST, invocation nodes have two types of child nodes: Targets and Arguments. During matching these two types of child nodes are considered to be equal, leading to problems where reordering the target or arguments of an invocation produces no AST change. This fix creates a new class, CtTargetWrapper, that behaves similarly to CtVirtualElement, wrapping any invocation targets so they are treated differently to other invocation child nodes.
Relates to: Issue 126

@algomaster99
Copy link
Member

Hey! Thank you for your contribution. I am sorry it slipped my mind to look at this after I approved the workflow run.

I will try to look at it by the week's end. I hope you can use the snapshot build of the project to satisfy your use case for the time being. :)

Copy link
Member

@algomaster99 algomaster99 left a comment

Choose a reason for hiding this comment

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

Hi @benmss ! Sorry, it took so long, but I thank you again for the contribution. However, there are some changes that I would suggest.

Firstly, since this PR does two things - Missing Position Information and Invocation Ordering. We should have two separate PRs for it. It makes reviewing efficient.

Secondly, I have looked at the first issue thoroughly and suggested the change in my comments. Please have a look at that and let me know if you disagree with any.

Finally, I have had a cursory look at the second fix because I thought we should focus on the "missing position" issue first.

Comment on lines 85 to 101
CompilationUnit cu = null;
Integer sourceStart = null;
int sourceEnd = 0;
for (var position : positions) {
if (position instanceof NoSourcePosition) { continue; }
if (sourceStart == null || position.getSourceStart() < sourceStart) {
sourceStart = position.getSourceStart();
}
if (position.getSourceEnd() > sourceEnd) {
sourceEnd = position.getSourceEnd();
}
if (cu == null) { cu = position.getCompilationUnit(); }
}
if (sourceStart != null) {
SourcePosition virtualPosition = new SourcePositionImpl(cu, sourceStart, sourceEnd, cu.getLineSeparatorPositions());
virtualElement.setPosition(virtualPosition);
}
Copy link
Member

Choose a reason for hiding this comment

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

I think you can get the sourceStart from the first modifier and sourceEnd from the last modifier.

@I-Al-Istannen the set returned by method.getExtendendedModifiers is ordered by the source position of the the modifier, right?

Choose a reason for hiding this comment

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

Preetty sure that this would be accidental. The CtModifierHandler creates a hashset. See also INRIA/spoon#4033 for reference. Just don't try to fix that in spoon if you can't spare a week :^)

@@ -171,7 +214,9 @@ public <A extends Annotation> void visitCtAnnotation(CtAnnotation<A> annotation)
for (Map.Entry<String, CtExpression> entry: annotation.getValues().entrySet()) {
Tree annotationValueNode = builder.createNode("ANNOTATION_VALUE", entry.toString());
annotationNode.addChild(annotationValueNode);
annotationValueNode.setMetadata(SpoonGumTreeBuilder.SPOON_OBJECT, new CtWrapper(entry, annotation, CtRole.VALUE));
var wrapper = new CtWrapper(entry, annotation, CtRole.VALUE);
Copy link
Member

Choose a reason for hiding this comment

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

I personally avoid using var as I think it hampers readability. I think it is more readable when you can directly figure out the type.

Copy link
Contributor Author

@benmss benmss Dec 11, 2022

Choose a reason for hiding this comment

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

Not a problem, I will remove all added uses.

Comment on lines 1 to 17
/*
/* *****************************************************************************
* Copyright 2016 Matias Martinez
* Copyright (c) 2022, Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* *****************************************************************************/
Copy link
Member

Choose a reason for hiding this comment

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

This is unrelated to the review process, but I am curious about adding license. @monperrus, do you know on what basis we should add names to license? For example, this file has been revised by many contributors, so why only Matias' name be there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Matias' name was added only because it already exists as a copyright header in one of the test files. Can change it to whatever you feel best represents the work done.

As to why the headers were added: it is a requirement set by Oracle for this kind of contribution.

String left = "class A { static void a() {} }";
String right = "class A { private static synchronized void a() {} }";
Diff diff = new AstComparator().compare(left, right);
diff.getRootOperations().forEach(e -> assertFalse(e.getSrcNode().getPosition() instanceof NoSourcePosition));
Copy link
Member

Choose a reason for hiding this comment

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

I like the test case overall. I would suggest that you compare the exact position like /test:1 or the expected source line, character start, and character end of each modifier. It makes the test stronger.

@@ -601,4 +619,19 @@ public void test_nestedReturnTypeOfMethodShouldGetParsed() throws Exception {
assertEquals(1, returnType.getDescendants().size());
assertEquals("java.lang.Integer", returnType.getChild(0).getLabel());
}

@Test
public void test_AccessModifierShouldHaveSourcePosition() {
Copy link
Member

Choose a reason for hiding this comment

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

There are two ways to pass code to compare. You can use the string code like you have done or you could pass a path to a file. I suggest adding a test for the latter case as well.

* This class wraps any node that appears as an invocation target to provide a means of differentiating
* between that node and any other child nodes the invocation may have.
*/
public class CtTargetWrapper extends CtElementImpl {
Copy link
Member

Choose a reason for hiding this comment

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

Can we use CtWrapper instead to wrap the target? CtTargetWrapper seems to be designed exactly like CtWrapper. You could also look at the proposed solution here.

But we can think more about this later. Let's focus on the other issue first.

@benmss
Copy link
Contributor Author

benmss commented Dec 11, 2022

Hi @algomaster99, thanks for taking the time to look through it all.

I will separate the second fix out of this PR as you suggest, and makes the other changes as above where applicable.

@benmss benmss closed this Dec 13, 2022
@benmss benmss deleted the missing-position-and-invocation-ordering-fixes branch December 13, 2022 23:59
@algomaster99
Copy link
Member

algomaster99 commented Jan 11, 2023

@benmss time to move to the second PR :)

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