Skip to content
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

refactor: simplify sniper code in ElementSourceFragment#addChild #3415

Merged
merged 10 commits into from
Jun 14, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,6 @@ public String getSourceCode(int start, int end) {
return null;
}

/**
* @return true if position points to same compilation unit (source file) as this SourceFragment
*/
private boolean isFromSameSource(SourcePosition position) {
return getSourcePosition().getCompilationUnit().equals(position.getCompilationUnit());
}

/**
* Builds a tree of source fragments for `element` and all its children, based on the source positions of each element
* @param element the root element of the tree
Expand Down Expand Up @@ -232,64 +225,41 @@ protected void exit(CtElement e) {
return rootFragment;
}
/**
* @param parentFragment the parent {@link ElementSourceFragment}, which will receive {@link ElementSourceFragment} made for `otherElement`
* Add a new child in this fragment.
* @param roleInParent the {@link CtRole} of `otherElement` in scope of element of `parentFragment`
* @param otherElement {@link SourcePositionHolder} whose {@link ElementSourceFragment} has to be added to `parentFragment`
* @return new {@link ElementSourceFragment} created for `otherElement` or null if `otherElement` has no source position or doesn't belong to the same compilation unit
* @return new {@link ElementSourceFragment} created for `otherElement` or null if `otherElement` cannot be included
*/
private ElementSourceFragment addChild(CtRole roleInParent, SourcePositionHolder otherElement) {
SourcePosition otherSourcePosition = otherElement.getPosition();
if (otherSourcePosition instanceof SourcePositionImpl && !(otherSourcePosition.getCompilationUnit() instanceof NoSourcePosition.NullCompilationUnit)) {
if (this.isFromSameSource(otherSourcePosition)) {
ElementSourceFragment otherFragment = new ElementSourceFragment(otherElement, this.getRoleHandler(roleInParent, otherElement));
//parent and child are from the same file. So we can connect their positions into one tree
CMP cmp = this.compare(otherFragment);
if (cmp == CMP.OTHER_IS_CHILD) {
//child belongs under parent - OK
// core contract:
// the position of children fragments must be included inside the positions of the paernt fragment
this.addChild(otherFragment);
return otherFragment;
} else {
if (cmp == CMP.OTHER_IS_AFTER || cmp == CMP.OTHER_IS_BEFORE) {
if (otherElement instanceof CtComment) {
// one exception
// comment positions have the right to not be part of the parent fragment in some cases
if (otherElement instanceof CtComment) {
/*
* comments of elements are sometime not included in source position of element.
* because comments are ignored tokens for java compiler, which computes start/end of elements
* because comments are ignored tokens for JDT, which computes start/end of elements
* Example:
*
* //a comment
* aStatement();
*
*/
if (otherFragment.getStart() == 0) {
//it is CompilationUnit comment, which is before package and imports, so it doesn't belong to class
//No problem. Simply add comment at correct position into SourceFragment tree, starting from ROOT
addChild(otherFragment);
return otherFragment;
}
//add this child into parent's source fragment and extend that parent source fragment
this.addChild(otherFragment);
return otherFragment;
}
throw new SpoonException("otherFragment (" + otherElement.getPosition() + ") " + cmp.toString() + " of " + this.getSourcePosition());

} else {
throw new SpoonException("The SourcePosition of elements are not consistent\nparentFragment: " + this + "\notherFragment: " + otherFragment);
}
//the source position of child element is not included in source position of parent element
//I (Pavel) am not sure how to handle it, so let's wait until it happens...
// if (otherElement instanceof CtAnnotation<?>) {
// /*
// * it can happen for annotations of type TYPE_USE and FIELD
// * In such case the annotation belongs to 2 elements
// * And one of them cannot have matching source position - OK
// */
// return null;
// }
//It happened... See spoon.test.issue3321.SniperPrettyPrinterJavaxTest
//something is wrong ...
throw new SpoonException("The SourcePosition of elements are not consistent\nparentFragment: " + this + "\notherFragment: " + otherElement.getPosition());
}
} else {
throw new SpoonException("SourcePosition from unexpected compilation unit: " + otherSourcePosition + " expected is: " + this.getSourcePosition());
}
}
//do not connect that undefined source position
return null;
Expand Down