Skip to content

Commit

Permalink
add refactorings for variable name rename
Browse files Browse the repository at this point in the history
  • Loading branch information
pvojtechovsky committed Nov 24, 2016
1 parent e086cd3 commit d8f30aa
Showing 1 changed file with 118 additions and 5 deletions.
123 changes: 118 additions & 5 deletions src/main/java/spoon/refactoring/Refactoring.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,23 @@
*/
package spoon.refactoring;

import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtCatchVariable;
import spoon.reflect.code.CtLocalVariable;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtExecutable;
import spoon.reflect.declaration.CtField;
import spoon.reflect.declaration.CtNamedElement;
import spoon.reflect.declaration.CtParameter;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.CtVariable;
import spoon.reflect.declaration.ModifierKind;
import spoon.reflect.reference.CtFieldReference;
import spoon.reflect.reference.CtReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.Filter;
import spoon.reflect.visitor.Query;
import spoon.reflect.visitor.filter.AbstractReferenceFilter;
import spoon.reflect.visitor.filter.TypeFilter;

import java.util.List;

Expand All @@ -36,15 +49,115 @@ public final class Refactoring {
* New name of the element.
*/
public static void changeTypeName(final CtType<?> type, String name) {
final List<CtTypeReference<?>> references = Query.getReferences(type.getFactory(), new AbstractReferenceFilter<CtTypeReference<?>>(CtTypeReference.class) {
String oldQualifiedName = type.getQualifiedName();
changeSimpleName(type, name, null, new TypeFilter<CtTypeReference<?>>(CtTypeReference.class) {
@Override
public boolean matches(CtTypeReference<?> reference) {
return type.getQualifiedName().equals(reference.getQualifiedName());
return oldQualifiedName.equals(reference.getQualifiedName());
}
});
}

public static void changeVariableName(CtVariable<?> variable, String name) {
if (variable instanceof CtParameter<?>) {
changeParameterName((CtParameter<?>) variable, name);
} else if (variable instanceof CtLocalVariable<?>) {
changeLocalVariableName((CtLocalVariable<?>) variable, name);
} else if (variable instanceof CtField<?>) {
changeFieldName((CtField<?>) variable, name);
} else if (variable instanceof CtCatchVariable<?>) {
throw new UnsupportedOperationException("Renaming of CtCatchVariable is not supported yet");
} else {
throw new UnsupportedOperationException("Renaming of " + variable.getClass().getName() + " is not supported yet");
}
}
/**
* Changes name of a parameter element.
*
* @param parameter
* Parameter in the AST of the executable.
* @param name
* New parameter name.
*/
public static void changeParameterName(CtParameter<?> parameter, String name) {
changeSimpleName(parameter, name, parameter.getParent(CtExecutable.class).getBody());
}

/**
* Changes name of a local variable.
*
* @param localVariable
* localVariable in the AST of some block.
* @param name
* New variable name.
*/
public static void changeLocalVariableName(CtLocalVariable<?> localVariable, String name) {
changeSimpleName(localVariable, name, localVariable.getParent(CtBlock.class));
}

/**
* Changes name of a field.
*
* @param field
* Field in the AST of some Type.
* @param name
* New field name.
*/
public static void changeFieldName(CtField<?> field, String name) {
CtElement container;
if (field.hasModifier(ModifierKind.PUBLIC)) {
//the reference can be everywhere in the model
container = null;
} else if (field.hasModifier(ModifierKind.PROTECTED)) {
//the reference can be in any inherited class in the model. Search everywhere
container = null;
} else if (field.hasModifier(ModifierKind.PRIVATE)) {
//the reference can be only in scope of top level declaring class
container = field.getParent(CtType.class).getTopLevelType();
} else {
//package protected. The reference can be only in this package
container = field.getParent(CtType.class).getTopLevelType().getPackage();
}
String oldQualifiedName = field.getReference().getQualifiedName();
changeSimpleName(field, name, container, new TypeFilter<CtFieldReference<?>>(CtFieldReference.class) {
@Override
public boolean matches(CtFieldReference<?> fieldRef) {
return oldQualifiedName.equals(fieldRef.getQualifiedName());
}
});
}

type.setSimpleName(name);
for (CtTypeReference<?> reference : references) {
/**
* Searches for all references to the element in scope of container.
* Then changes the simpleName of the element and all the found references.
* @param element - the element which is going to be renamed
* @param name - the new name of the element
* @param container - the container element which will be searched for references to element
*/
private static <T extends CtNamedElement> void changeSimpleName(T element, String name, CtElement container) {
final String oldName = element.getSimpleName();
changeSimpleName(element, name, container, new TypeFilter<CtReference>(CtReference.class) {
@Override
public boolean matches(CtReference p_element) {
return p_element.getSimpleName().equals(oldName);
}
});
}
/**
* Searches for all references which matches the filter.
* Then changes the simpleName of the element and all the found references.
* @param element - the element which is going to be renamed
* @param name - the new name of the element
* @param container - the container element which will be searched for references to element
* @param filter - filter which matches on references to the element
*/
private static <T extends CtNamedElement> void changeSimpleName(T element, String name, CtElement container, Filter<? extends CtReference> filter) {
if (container == null) {
container = element.getFactory().Package().getRootPackage();
}
List<? extends CtReference> references = Query.getElements(container, filter);
element.setSimpleName(name);
for (CtReference reference : references) {
reference.setSimpleName(name);
}
}
Expand Down

0 comments on commit d8f30aa

Please sign in to comment.