-
-
Notifications
You must be signed in to change notification settings - Fork 355
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
Discussion: Concept of printing imports and qualified names #2624
Comments
Initially, autoimports meant B1. Now that we have the sniper mode, which is basically B1, we can more autoimport to B2 and make autoimport independent of implicit values. This will likely simplify the autoimport code quite a lot. |
It will not work, because Sniper mode uses internally standard printing (auto import) and just wraps it to minimize changes. So the standard printing should try to produce the origin code as much as possible, then also Sniper mode will print source more matching to origin code. So I suggest to Use B1 in standard auto import mode too.
The complexity and correctness of printer and autoimport (ImportScannerImpl) code is a relevant topic here too. Both implementations DJPP and ImportScannerImpl must decide whether a type will be imported or not in the same way. So they should somehow use same algorithm. That leads to an idea of next refactoring, which will keep that "to import or not to import" algorithm in DJPP only the ImportScannerImpl will just follow the decisions made by DJPP. WDYT? |
I am trying to understand what is the expected behavior of the printer and import scanner... to fix some problems. If If /**
* <ul>
* <li>if the reference.isImplicit() == false the reference has to be printed inline,
* so this occurrence doesn't cause import. BUT only if it is possible (there is no conflict, etc.)
* <li>if the reference.isImplicit() == true the reference should not be printed,
* so it should be imported. BUT only if it is possible (there is no conflict, etc.)
* </ul>
*
* When printing references, it is not relevant whether import existed in origin file or not. Only {@link CtElement#isImplicit()} drives printing.
* The list of origin imports should influence only the order of printed imports.
*
* The spoon model builder should set reference.setImplicit(X) following the origin source code, so we know later,
* whether reference exists in source code or whether it doesn't exist and therfore it must be imported or is locally available.
*/ @surli I guess you know the First: I am not asking about current (sometime probably buggy) implementation, I am asking about future concept, which should help me to fix it in correct way. Second: How much is the current implementation fitting to the concept above? Does it needs deep refactoring or just little fix? |
Hi @pvojtechovsky I don't think I completely agree with the final rule:
I'm ok that on first traversal the model builder shoud set the
I think the work on the pretty printer should be quite easy, as everything is now based on the impliciteness that has been computed before. Now regarding the ImportScanner itself, I'm not sure it will be so easy:
|
Hi Simon,
I would prefer to remember information about conflict in some printing context. The modification of the original model is not good in these cases
The purpose of ImportScanner is not to validate model, so it should not change the model. WDYT?
@surli, many thanks for your notes regarding refactoring. It is very helpful to see the bigger challenges which are waiting there. |
I think you rise an important point that we need to clarify: the exact purpose of the ImportScanner.
For me, at the beginning the purpose of the ImportScanner was only 1, but I have the feeling that the usage of our user led to have 2: that's why I pushed to have CtImport inside the model and so one. So, I'd say it should allow both:
|
I agree that since CtImport is in model situation changed. The simpler and probably the most powerful approach looks like this: I1) pretty printer doesn't need import scanner at all. It can simply print sources following current model. Note: Everything is defined in model. There are imports, which has to be printed and there is attribute I2) import scanner will modify model (adds/removes imports and changes note: import scanner (may be we should call it WDYT? Is it the way we want to go? |
Actually I like the idea of having in Spoon a list of "processors" that would validate a processed model before its printing. So we could imagine that the ImportScanner would be a first "default" validator in that list, but users are able to change the list to add their own. On a long term view it would allow us to develop new ways to check the model before printing. Sorry, it wasn't exactly your point, but it makes me think about that.
So for me, yeah absolutely. |
Super! So we have a new powerful concept for PrettyPrinter and ImportScanner for the case of autoImport=true. I guess the printing of model in mode So we should be able to configure PrettyPrinter by way it ignores isImplicit and ignores imports and simply prints fully qualified names whenever is it possible. ... but that is completely different approach - different concept -> more code needed, more maintenance ... Do you have any better idea? Or do you think that some clients might need to modify model by way all |
For me both mode are working the same way: The model is processed, transformed, and validated before being printed. So we stand on those principles:
WDYT? |
I like it. But that needs a change in spoon behavior concerning |
I personally think it's better: as you mentioned I had many times the problem when debugging a scanner, of an element changing because of the ImportScanner in |
This issue is the most urgent for me now, so I will probably make time to have a look at it next days. @monperrus could you give us feedback whether new concepts discussed here are OK from your point of view? |
everything OK, we make good progress. I propose to change the title of the issue because we discuss
more than isImplicit.
|
Do you agree that assertEquals("java.lang.String value = \"\";", fieldValue.toString()); has to be replaced by assertEquals("String value = \"\";", fieldValue.toString()); because origin source code is String value = ""; Will you accept such changes in tests? |
It makes sense for me: the test is even closer to the reality so I find it better. If we really want to check the fully qualified type, then we can always get its reference and check it. |
|
That would mean if an user use Spoon with "no import", and get the imports from the model before printing it, he'll get a list of imports. So ok for now to always collect and to remove them in the no import validator. We'll see later if we need to trigger the validators at different places in the process or not, it might be the subject of another discussion. |
I changed my mind. I found algorithms, where it is necessary to have CtElement printed to String with fully qualified names and it would be bad at this place to apply model validator which removes implicit attributes from model - to print it fully qualified. So I suggest to make it more backward compatible. It means CtElement#toString() will print in fully qualified mode (same like before). I added But then there are places where client needs to see how CtElement will really look like (follow is implicit). So I added CtElement method /**
* @param forceFullyQualified if true then fully qualified names are used even for implicit elements.
* if false then print follows implicitness of elements
*
* @return pretty printed source code of this element
*/
String print(boolean forceFullyQualified); WDYT? |
Not sure to understand:
If the |
I just checked the PR so I understand better what you're doing. But still, I'm not sure to agree: IMO the long-term goal is to simplify how we manage those cases, so possibly to get rid of those corner-cases where we need to pretty-print in FQN etc. So following this vision, I'd prefer to keep a |
Thanks for your constructive feedback! I agree that having
is too complicated. So I like idea to have only two methods. One for FQN and second for normal printing. I actually tend to opposite solution:
This solution
WDYT? |
I am trying to fix tests in #2621, which marked a CtTypeAccess of enum field as implicit, when such field is statically imported.
Now I would need a concept/specification of how the spoon printer should behave in
A) autoImport = false -> MinimalImportScanner
B) autoImport = true -> ImportScannerImpl
C) snipermode
Example of source code:
In my understanding the
autoImport = false
means that all what can use fully qualified name will use it. So it should print:It means isImplicit is ignored and always understood as false.
Then the
autoImport = true
means thatB1) we try to print the sources in the way how they are modeled. It means we print or not print qualified name depending on implicit attribute
B2) we try to automatically import as much as possible. We import (including static import?) as much as possible
And the
sniper mode
means we try to print the sources in the way how they are modeled. It means we print or not print qualified name depending on implicit attribute. It expects that model (implicit=true/false) reflects origin sources.The text was updated successfully, but these errors were encountered: