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

bug in printing of Implicit access to static field #913

Merged
merged 6 commits into from
Nov 15, 2016

Conversation

pvojtechovsky
Copy link
Collaborator

Added test to reproduce bug in printing of Implicit access to static field

@pvojtechovsky
Copy link
Collaborator Author

Hi Martin,
I have committed the change, which fixes the problem for me, but I am really not sure if that code is correct. My spoon knowledge is not good enough to be sure.
Best regards,
Pavel

@pvojtechovsky
Copy link
Collaborator Author

This solution is different. It does not try to use implicit access, but it instead forces to use qualified name in case of conflict of Class name and static field name. It has less impact on printed sources, so it is more compatible with existing tests.

I see these remaining problems:

  1. I would like to see the new private method DefaultJavaPrettyPrinter.getDeclareddOrInheritedField as public method on CtType. Use a better name of course. I can make a PR if you like that idea. Just give me some better name.
  2. performance of pretty-printing is 5 times worse then before... It all the time checks whether there are conflict fields. Before the pretty-printing time was about 10s and now it needs 40-60s! :-(

May be we can try to improve performance by replacing of CtTypeImpl.typeMembers list by a LinkedHashMap?

@pvojtechovsky
Copy link
Collaborator Author

The method on CtType.getDeclaredOrInheritedField would be nice, but the correct solution for the performance problem is to store set of all names of localy visible fields and methods in Printer context. Then we will resolve that list only once when we enter the scope of some class/interface and just check it whenever we need to print type access.

@tdurieux
Copy link
Collaborator

getDeclaredOrInheritedField is very similar to CtTypeInformation#getAllFields().
The performance issue comes from the method getTypeDeclaration() that may use the reflection to retrieve the information of the Type.
The PR #898 may resolve your performance issue.

@monperrus
Copy link
Collaborator

merged #898.

Before the pretty-printing time was about 10s and now it needs 40-60s! :-(

can you rebase and measure again?

@pvojtechovsky
Copy link
Collaborator Author

Windows is bad system to measure performance... it does so many things on the background ... :-(
I measured this configurations:
#898
printed in: 8584, 9214, 11176 ms

#898 + this PR
printed in: 29257, 18295 ms

this PR without #898
printed in: 36987, 136324 ms ... so different results. I hate MS...

Results:

  1. The Fix #867: perf shadow #898 really improves performance
  2. This PR even with Fix #867: perf shadow #898 is still 2-3 times slower then origin code.

@monperrus monperrus changed the title test to reproduce bug in printing of Implicit access to static field bug in printing of Implicit access to static field Nov 3, 2016
}
return false;
} else {
return true;
}
}

private static CtField<?> getDeclareddOrInheritedField(CtType<?> type, String fieldName) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

getDeclareddOrInheritedField -> getDeclaredOrInheritedField (double dd)

We agree to move it to CtType.
We must also handle fields from interfaces.

@pvojtechovsky
Copy link
Collaborator Author

I just noticed there is new comment...
What will be the name of that new method on CtType?

We must also handle fields from interfaces.

I agree

@tdurieux
Copy link
Collaborator

tdurieux commented Nov 9, 2016

You can keep getDeclareddOrInheritedField is long but it is explicit

@pvojtechovsky
Copy link
Collaborator Author

Do you agree that CtType.getDeclaredOrInheritedField(fieldName) should return also fields from classes, which are not in CtModel? ... the fields found by java reflection.
So I should add

interface CtTypeReference {
CtFieldReference<?> getField(name);
CtFieldReference<?> getDeclaredOrInheritedField(name);
}

because if we would ignore such fields, then bug #913 would be still reproducible on classes inherited from classes which are not part of the model.

@monperrus
Copy link
Collaborator

Do you agree that |CtType.getDeclaredOrInheritedField(fieldName)|
should return also fields from classes, which are not in CtModel? ...
the fields found by java reflection.
Yes.

CtFieldReference<?> getDeclaredOrInheritedField(name);
That could go in CtType, or even better in CtTypeInformation.

--Martin

@pvojtechovsky
Copy link
Collaborator Author

My latest changes fails because of bug #959. After this bug is fixed, then it should pass the tests too.

@pvojtechovsky
Copy link
Collaborator Author

It now performs well. It is back on 10s. The currentThis type field names are now cached in PrintingContext, so they does not have to be resolved again and again.

I am not using new method getDeclaredOrInheritedField, but existing CtTypeInformation.getAllFields(). The difference is that CtTypeInformation.getAllFields() is not checking fields on interfaces. So may be we should change getAllFields by way it gets fields from interfaces too.

May be the new getDeclaredOrInheritedField should be removed if it is not used? But some client might appreciate it.

It still fails on bug #959
And it fails on code snippet, which has not set class path?

@monperrus
Copy link
Collaborator

The difference is that CtTypeInformation.getAllFields() is not checking fields on interfaces.

This is a bug, would you propose a PR? Thanks.

@monperrus
Copy link
Collaborator

May be the new getDeclaredOrInheritedField should be removed if it is not used?

Yes, you can remove it from here. However, I like the idea, we could you move it to another PR.

@pvojtechovsky pvojtechovsky force-pushed the implicitStaticFieldReference branch 2 times, most recently from e2162b0 to b16ba96 Compare November 12, 2016 18:28
@pvojtechovsky
Copy link
Collaborator Author

The getDeclaredOrInheritedField is moved to #967
The getAllFields() now collects fields of interfaces too. I have prepared the test too, but it is in conflict with PR #967, so please merge #967 first.

I had to fix SnippetCompilationHelper. Now it prints the Wrapper helper class, which is made to wrap the snippet ,before Wrapper class is removed from the CtModel of factory. It avoids ClassNotFoundException.

@pvojtechovsky
Copy link
Collaborator Author

Looks like might be merged after bug #959 is fixed

@monperrus monperrus changed the title bug in printing of Implicit access to static field bug in printing of Implicit access to static field (depends on #959, #960) Nov 13, 2016
@monperrus
Copy link
Collaborator

According to @tdurieux 's comment, the only solution seems to be to make a minimal change to ImportTest.testSpoonWithImports so that all tests pass.

@tdurieux
Copy link
Collaborator

Unfortunately we cannot change testSpoonWithImports it tests some tricky access path in java.
This test was created because an user encounter a compilation error in this specific scenario.

The solution is not removing the difficulties.

@monperrus monperrus changed the title bug in printing of Implicit access to static field (depends on #959, #960) bug in printing of Implicit access to static field Nov 14, 2016
@monperrus
Copy link
Collaborator

your last commit makes sense.

I would propose to also change CtType<?> t = getDeclaration(); by CtType<?> t = getTypeDeclaration(); (use of shadow classes if possible), and then we can rid of return RtHelper.getAllFields(getActualClass(), getFactory());.(but you would still catch the exception and do the hack-of-hack.

@pvojtechovsky
Copy link
Collaborator Author

access path problem - the hack

OK, I did not know before, that "access path" is used to reference super type. But may be I have now an idea, how to fix that without need of deeper change of spoon model.
Where we can discuss that?
A) spoon mailing
B) make a issue or PR for that
C) we do not need/want to discuss it with you.... even if it is not the answer I want to hear, I will really appreciate it, comparing to letting me write some ideas, which nobody is interested in :-) ... because you have already a better concept. I will then focus on other interesting parts of spoon and trust You! ;-)

@monperrus
Copy link
Collaborator

Where we can discuss that?

issue or PR is perfect (PR is even better, you can start one with an
empty commit)

@pvojtechovsky
Copy link
Collaborator Author

Thanks for the tip with CtType<?> t = getDeclaration(), the code looks better now :-) ... even if it is quite dirty ;p
:-)))

@monperrus monperrus merged commit 91a21c7 into INRIA:master Nov 15, 2016
@monperrus
Copy link
Collaborator

thanks a lot for this long and hard PR!

@pvojtechovsky
Copy link
Collaborator Author

You are welcome!

@pvojtechovsky pvojtechovsky deleted the implicitStaticFieldReference branch November 15, 2016 17:48
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