Skip to content

Commit

Permalink
added javadoc
Browse files Browse the repository at this point in the history
  • Loading branch information
pvojtechovsky committed Apr 16, 2018
1 parent 96f7b13 commit 5765da2
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 170 deletions.
Expand Up @@ -18,6 +18,7 @@

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Set;

import spoon.SpoonException;
import spoon.compiler.Environment;
Expand Down Expand Up @@ -153,8 +154,6 @@ private void onTokenWriterWrite(String tokenWriterMethodName, String token, CtCo
printAction.run();
}

private final SourceFragmentContextNormal EMPTY_FRAGMENT_CONTEXT = new SourceFragmentContextNormal();

/**
* Called whenever {@link DefaultJavaPrettyPrinter} scans/prints an element
*/
Expand All @@ -177,17 +176,17 @@ private void scanInternal(CtElement element) {
if (mutableTokenWriter.isMuted()) {
//it is already muted by an parent. Simply scan and ignore all tokens,
//because the content is not modified and was already copied from source
sourceFragmentContextStack.push(EMPTY_FRAGMENT_CONTEXT);
sourceFragmentContextStack.push(SourceFragmentContextNormal.EMPTY_FRAGMENT_CONTEXT);
super.scan(element);
sourceFragmentContextStack.pop();
return;
}
//it is not muted yet, so some this element or any sibling was modified
//it is not muted yet, so this element or any sibling is modified
//detect SourceFragments of element and whether they are modified or not
SourceFragment rootFragmentOfElement = SourcePositionUtils.getSourceFragmentsOfElement(changeCollector, element);
SourceFragment rootFragmentOfElement = getSourceFragmentsOfElementUsableForPrintingOfOriginCode(changeCollector, element);
if (rootFragmentOfElement == null) {
//we have no origin sources or this element has one source fragment only and it is modified. Use normal printing
sourceFragmentContextStack.push(EMPTY_FRAGMENT_CONTEXT);
sourceFragmentContextStack.push(SourceFragmentContextNormal.EMPTY_FRAGMENT_CONTEXT);
super.scan(element);
sourceFragmentContextStack.pop();
return;
Expand All @@ -201,4 +200,45 @@ private void scanInternal(CtElement element) {
//at the end we always un-mute the token writer
mutableTokenWriter.setMuted(false);
}

/**
* @param changeCollector holds information about modified elements
* @param element to be printed element
* @return {@link SourceFragment} or chain of {@link SourceFragment} siblings which wraps all the source parts of the `element`
* It returns null when there are no sources at all or when all are modified so we cannot use them anyway
*/
private static SourceFragment getSourceFragmentsOfElementUsableForPrintingOfOriginCode(ChangeCollector changeCollector, CtElement element) {
//detect source code fragments of this element
SourceFragment rootFragmentOfElement = SourcePositionUtils.getSourceFragmentOfElement(element);
if (rootFragmentOfElement == null) {
//we have no origin sources for this element
return null;
}
//The origin sources of this element are available
//check if this element was changed
Set<CtRole> changedRoles = changeCollector.getChanges(element);
if (changedRoles.isEmpty()) {
//element was not changed and we know origin sources
//use origin source instead of printed code
return rootFragmentOfElement;
}
//element is changed. Detect source fragments of this element
SourceFragment childSourceFragmentsOfSameElement = rootFragmentOfElement.getChildFragmentOfSameElement();
if (childSourceFragmentsOfSameElement == null || childSourceFragmentsOfSameElement.getNextFragmentOfSameElement() == null) {
//there is only one source fragment and it is modified.
//So we cannot use origin sources
return null;
}
/*
* there are more fragments. So may be some of them are not modified and we can use origin source to print them
* e.g. when only type members of class are modified, we can still print the class header from the origin sources
* Mark which fragments contains source code of data from modified roles
*/
//detect which roles of this element contains a change
if (SourcePositionUtils.markChangedFragments(element, childSourceFragmentsOfSameElement, changedRoles)) {
return childSourceFragmentsOfSameElement;
}
//this kind of changes is not supported for this element yet. We cannot use origin sources :-(
return null;
}
}
Expand Up @@ -7,10 +7,14 @@
import spoon.reflect.path.CtRole;
import spoon.reflect.visitor.printer.change.SourcePositionUtils.FragmentDescriptor;

/**
* Knows how to handle actually printed {@link CtElement}.
* It drives printing of main element and single value attributes,
* while {@link SourceFragmentContextList} is used to drive printing of lists of attribute values
*/
class SourceFragmentContextNormal extends SourceFragmentContext {
/**
*
*/
static final SourceFragmentContextNormal EMPTY_FRAGMENT_CONTEXT = new SourceFragmentContextNormal();

private final MutableTokenWriter mutableTokenWriter;
private SourceFragment currentFragment;
private CtElement element;
Expand All @@ -19,6 +23,11 @@ class SourceFragmentContextNormal extends SourceFragmentContext {
*/
private SourceFragmentContext childContext;

/**
* @param mutableTokenWriter {@link MutableTokenWriter}, which is used for printing
* @param element the {@link CtElement} which is printed
* @param rootFragment the {@link SourceFragment}, which represents whole elements. E.g. whole type or method
*/
SourceFragmentContextNormal(MutableTokenWriter mutableTokenWriter, CtElement element, SourceFragment rootFragment) {
super();
this.mutableTokenWriter = mutableTokenWriter;
Expand All @@ -27,12 +36,15 @@ class SourceFragmentContextNormal extends SourceFragmentContext {
handlePrinting();
}

SourceFragmentContextNormal() {
private SourceFragmentContextNormal() {
mutableTokenWriter = null;
currentFragment = null;
}

SourceFragment getNextFragment() {
/**
* @return next {@link SourceFragment} of the actually printed element.
*/
private SourceFragment getNextFragment() {
if (currentFragment != null) {
return currentFragment.getNextFragmentOfSameElement();
}
Expand All @@ -42,12 +54,17 @@ SourceFragment getNextFragment() {
/**
* Called when next fragment is going to be printed
*/
void nextFragment() {
private void nextFragment() {
currentFragment = getNextFragment();
handlePrinting();
}

void handlePrinting() {
/**
* checks if current fragment is modified
* If not modified, then origin source code is directly printed and token writer is muted
* If modified, then token writer is enabled and code is printed normally
*/
private void handlePrinting() {
if (currentFragment != null) {
if (currentFragment.isModified() == false) {
//we are going to print not modified fragment
Expand All @@ -72,14 +89,6 @@ void handlePrinting() {
}
}

boolean testFagmentDescriptor(SourceFragment sourceFragment, Predicate<FragmentDescriptor> predicate) {
if (sourceFragment != null) {
if (sourceFragment.fragmentDescriptor != null) {
return predicate.test(sourceFragment.fragmentDescriptor);
}
}
return false;
}

@Override
void onTokenWriterToken(String tokenWriterMethodName, String token, Runnable printAction) {
Expand Down Expand Up @@ -129,4 +138,13 @@ void onParentFinished() {
//we will see if it is true... I (Pavel) am not sure yet
throw new SpoonException("SourceFragmentContextNormal shouldn't be used as child context");
}

private boolean testFagmentDescriptor(SourceFragment sourceFragment, Predicate<FragmentDescriptor> predicate) {
if (sourceFragment != null) {
if (sourceFragment.fragmentDescriptor != null) {
return predicate.test(sourceFragment.fragmentDescriptor);
}
}
return false;
}
}

0 comments on commit 5765da2

Please sign in to comment.