-
-
Notifications
You must be signed in to change notification settings - Fork 358
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
feat: CtCompilationUnit extends CtElement #2702
Conversation
c6c2b23
to
107b560
Compare
b8388d2
to
5c32bbe
Compare
Why exactly this new element contains references for types? The type were belonging to CompilationUnit because in the reality the types are declared in their CU. Not sure to understand the move, especially if you keep an inheritance between CompilationUnit and CtCompilationUnit. (Not sure either why to keep the old CompilationUnit class, though except maybe for backward compatibility) |
it is here only for backward compatibility. I will gladly remove old Compilation unit if @surli and @monperrus agrees that.
The But spoon model is a Tree by definition, so it is not allowed for First I started to implement CtCompilationUnit by way it contained CtType directly - saying it is OK that parent/child relationship is not correct in that case. But there were several problems
So then I found that it is much easier and correct too, when CtCompilationUnit has reference to CtPackage and reference to CtType. All the problems above are solved by that change. As a next step we can even add a collection of CtCompilationUnits somewhere into CtModel or into CtPackage and then CtCompilationUnit becomes normal member of spoon model. But that is again possible only if CtCompilationUnit contains references to types and package. WDYT? |
So trying to understand the new hierarchy of Spoon concepts with your change. You'll have something like:
am I right? Isn't it a bit odd that it's the contrary of the reality: the compilation units actually precedes the declaration of package/types. |
This PR doesn't puts CtCompilationUnit into any parent. It is actually without parent.
This is philosophical discussion ... and might be long. I do not want to attend ;-) Do you have an alternative? Where CtCompilationUnit belongs to from your point of view? ... and I suggest to keep Spoon the model a "tree" do not switch it to something else ... it would cause many deep changes. |
The way I see it, the package contains a list of CtCompilationUnit, which themselves contains the CtType. The package only contains CtTypeReference. Now if a CtPackage is declared in a compilation unit (package-info.java) then its parent is a CtCompilationUnit.
|
We speak about two models:
The The |
I'm really mixed on this one.
I agree that the current model does not support directly the filesystem concepts (even though they can be retrieved using the API). The rationale behind that is:
|
@surli thank you for that open and constructive discussion. It is really helpful 👍
I agree.
I agree with this sentence. But this sentence is not fitting to this PR, because this PR actually breaks nothing. All tests passed without need for bigger change. The idea to have CtType contained in CtCompilationUnit is breaking. I do not think it is helpful and needed.
I agree with this sentence too :-) But I think that CtCompilationUnit is secondary think, which should not bother Spoon clients who don't need it. Therefore I would prefer to have CtCompilationUnit somehow outside of primary spoon model. Why I think it is not needed?
I only need to know that about CompilationUntis: Spoon should keep by default the types in origin files (compilation units). I really do not want to touch them all the time I am processing the spoon model. So the compilation units are secondary stuff which should be hidden somewhere in background ... but of course well designed and well accessible when somebody really needs it. May be there is some misunderstanding ... in one of previous comments you draw this picture - as your understanding of what I probably plan to do:
but it is wrong. It doesn't fit to this PR or concepts I would like to have in Spoon. I suggest one of these models M1) compilation units in packages, because packages represents file system directories
... or one of following models, because compilation units are not fitting to java runtime model at all. M2) compilation units in root of model (e.g. Set). It would be very similar to what we already have in Spoon 7.1
M3) compilation units in special model. Just an little alternative of M2.
M4) compilation units under new CtDirectory element. That would be biggest change. And there would be duplicate information - rename of package would need change of package name and change of CtDirectory name. :-(
Before I started to write this comment I liked the most M1, but now I am sure that I do not want to touch compilation units in future of my daily work so I prefer M2. WDYT? |
Thanks for your patience Pavel :) Ok, I indeed misunderstood some parts of the PR and so if it's not breaking I agree with you that M2 looks the better choice. But, I think you forget about the Java modules in your picture :) So for M2 be careful that the CtModel could have several modules, so maybe the CtCompilationUnit are not attached to the CtModel directly, but to their CtModule. WDYT? |
Thanks for pointing to that. I will thing about that later. I suggest to add CtCompilationUnit as child of CtModel in different PR. This PR is already big enough.... and tests actually pass, so it is good time to review and merge it ... after other related and already made PRs are merged. |
5c32bbe
to
cbbe61a
Compare
cbbe61a
to
1838af2
Compare
|
@@ -90,11 +97,11 @@ public void testGetUnitTypeWorksWithCreatedObjects() { | |||
CtPackage myPackage = launcher.getFactory().Package().getOrCreate("my.package"); | |||
CompilationUnit cu = launcher.getFactory().createCompilationUnit(); | |||
assertEquals(CompilationUnit.UNIT_TYPE.UNKNOWN, cu.getUnitType()); | |||
|
|||
cu.setDeclaredPackage(myPackage); |
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.
could we stay backward compatible here and keep setDeclaredPackage?
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.
yes, this can be derived method which will internally create a package reference and package declaration. I will do so
@@ -148,7 +155,7 @@ public void testAddDeclaredTypeInCU() throws IOException { | |||
assertEquals(3, cu.getDeclaredTypes().size()); | |||
|
|||
CtType typeBla = launcher.getFactory().Class().create("spoon.test.model.Bla"); | |||
cu.addDeclaredType(typeBla); |
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.
could we stay backward compatible here and keep addDeclaredType?
Conceptually, we add types not references.
In general, it looks good. There are very few non-backward compatible changes in the tests, and it seems we may even reduce them further. To be sure I understand well: what the final goal of this change? |
To have CtCompilationUnit, which extends CtElement and is CtVisitable. Then we can apply Processor on CtCompilationUnit. That processor will compute imports and manipulate isImplicit attribute to prepare for pretty printing. |
@@ -128,6 +33,7 @@ | |||
* an arbitrary index in the source code | |||
* @return the index where the line starts | |||
*/ | |||
@Deprecated |
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.
Could you specify on the deprecated method what should be used instead with a deprecated annotation in the javadoc.
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.
there is no better alternative for that unused (useless?) method. But may be it is safer to keep it there - without deprecated. WDYT?
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.
Can't you get it using the position somehow?
* Defines a compilation unit. In Java, a compilation unit can contain only one | ||
* public type declaration and other secondary types declarations (not public). | ||
*/ | ||
public interface CtCompilationUnit extends CtElement { |
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 would have put an @Experimental
annotation: it still can 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.
ok
@@ -75,8 +76,9 @@ public CompilationUnit getOrCreate(CtPackage ctPackage) { | |||
String path = file.getCanonicalPath(); | |||
CompilationUnit result = this.getOrCreate(path); | |||
result.setDeclaredPackage(ctPackage); | |||
ctPackage.setPosition(this.factory.createPartialSourcePosition(result)); | |||
|
|||
if (ctPackage.getPosition() == SourcePosition.NOPOSITION) { |
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.
Why those new checks?
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 method creates CompilationUnit for an existing CtPackage. The idea was that such existing CtPackage might have correct SourcePosition... but it is probably impossible. So I will rollback those new checks
/** | ||
* @see PackageFactory#createPackageDeclaration(String) | ||
*/ | ||
CtPackageDeclaration createPackageDeclaration(String name); |
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.
Isn't it linked to #2707 ?
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 method was added in #2707, but then I found (after some changes here) that it is no more needed, so I minimized API here.
enter(compilationUnit); | ||
biScan(spoon.reflect.path.CtRole.COMMENT, compilationUnit.getComments(), other.getComments()); | ||
biScan(spoon.reflect.path.CtRole.ANNOTATION, compilationUnit.getAnnotations(), other.getAnnotations()); | ||
biScan(spoon.reflect.path.CtRole.PACKAGE_DECLARATION, compilationUnit.getPackageDeclaration(), other.getPackageDeclaration()); |
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.
Why the package is not also a ref? When we discussed about the model architecture, the package got a CtRootPackage as ancestor, not a CtCompilationUnit.
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 is ref. Because CtCompilationUnits refers CtPackageDeclaration (new node type), which then has CtPackageReference.
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.
OK this is then used only if the CtCompilationUnit contains java types.
What if the CtCompilationUnit is a package-info or a module-info? Shouldn't we use inherited compilation units to manage those now?
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.
OK this is then used only if the CtCompilationUnit contains java types.
I think it is used for package-info too. But I have not checked it deeper. It should behave same like before this PR.
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.
OK maybe we should clarify that in a future PR.
@@ -558,7 +558,7 @@ public void scan(CtElement element) { | |||
|
|||
if (!spoonUnit.getDeclaredTypes().isEmpty()) { | |||
findCommentParentScanner.scan(spoonUnit.getDeclaredTypes()); | |||
} else if (spoonUnit.getDeclaredModule() != null) { | |||
} else if (spoonUnit.getDeclaredModuleReference() != null) { | |||
findCommentParentScanner.scan(spoonUnit.getDeclaredModule()); |
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.
shouldn't it be changed to spoonUnit.getDeclaredModuleReference().getDeclaration()
?
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 is already in
public CtModule getDeclaredModule() {
return this.moduleReference != null ? this.moduleReference.getDeclaration() : null;
}
Both solutions are correct. Current solution is shorter. I can change it if you like longer in this case. No problem
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.
So you could actually keep getDeclaratedModule()
both in the test != null
and after. I'd prefer a consistent solution: declaredModule
or declaredModuleReference
but not both.
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.
getDeclaratedModule()
is more expensive then getDeclaratedModuleReference()
So I will change the line 562 to be consistent and to use getDeclaratedModuleReference
API changes: 19 (Detected by Revapi) Old API: fr.inria.gforge.spoon:spoon-core:jar:7.2.0-20181025.162741-53 / New API: fr.inria.gforge.spoon:spoon-core:jar:7.2.0-SNAPSHOT
|
All the review comments should be solved. Just unused (actually Deprecated) methods in CompilationUnit needs, which belongs to some utils class are still deprecated. |
Thanks Pavel for the heavy-duty work. |
The refactoring of compilation unit based on discussions in #2254 and #2701
There are several changes
C1) CompilationUnit now extends new CtCompilationUnit
C2) CtCompilationUnit extends CtElement
C3) CtCompilationUnit may have list of type references. before it had list of types.
C4) CtCompilationUnit has one CtPackageDeclaration, which references package.
C5) CtCompilationUnit may have module reference, before it had module.
C6) CtScanner visits CtCompilationUnit and it's package declaration, imports, types references or module reference.