use of spoon.reflect.declaration.CtElement in project spoon by INRIA.
the class ElementPrinterHelper method writeAnnotationElement.
/**
* Writes an annotation element.
*/
public void writeAnnotationElement(Factory factory, Object value) {
if (value instanceof CtTypeAccess) {
prettyPrinter.scan((CtTypeAccess) value);
printer.writeSeparator(".").writeKeyword("class");
} else if (value instanceof CtFieldReference) {
prettyPrinter.scan(((CtFieldReference<?>) value).getDeclaringType());
printer.writeSeparator(".").writeIdentifier(((CtFieldReference<?>) value).getSimpleName());
} else if (value instanceof CtElement) {
prettyPrinter.scan((CtElement) value);
} else if (value instanceof String) {
printer.writeLiteral("\"" + LiteralHelper.getStringLiteral((String) value, true) + "\"");
} else if (value instanceof Collection) {
try (ListPrinter lp = createListPrinter(false, "{", false, true, ",", false, false, "}")) {
for (Object obj : (Collection<?>) value) {
lp.printSeparatorIfAppropriate();
writeAnnotationElement(factory, obj);
}
}
} else if (value instanceof Object[]) {
try (ListPrinter lp = createListPrinter(false, "{", false, true, ",", false, false, "}")) {
for (Object obj : (Object[]) value) {
lp.printSeparatorIfAppropriate();
writeAnnotationElement(factory, obj);
}
}
} else if (value instanceof Enum) {
try (Writable c = prettyPrinter.getContext().modify().ignoreGenerics(true)) {
prettyPrinter.scan(factory.Type().createReference(((Enum<?>) value).getDeclaringClass()));
}
printer.writeSeparator(".");
printer.writeIdentifier(value.toString());
} else {
// it probably prints, boolean, number, ...
printer.writeLiteral(value.toString());
}
}
use of spoon.reflect.declaration.CtElement in project spoon by INRIA.
the class CtParameterRemoveRefactoring method computeAllInvocations.
/**
* search for all methods and lambdas which has to be refactored together with target method
*/
private void computeAllInvocations() {
ExecutableReferenceFilter execRefFilter = new ExecutableReferenceFilter();
for (CtExecutable<?> exec : getTargetExecutables()) {
execRefFilter.addExecutable(exec);
}
// all the invocations, which belongs to same inheritance tree
final List<CtInvocation<?>> invocations = new ArrayList<>();
target.getFactory().getModel().filterChildren(execRefFilter).forEach(new CtConsumer<CtExecutableReference<?>>() {
@Override
public void accept(CtExecutableReference<?> t) {
CtElement parent = t.getParent();
if (parent instanceof CtInvocation<?>) {
invocations.add((CtInvocation<?>) parent);
}
// else ignore other hits, which are not in context of invocation
}
});
targetInvocations = Collections.unmodifiableList(invocations);
}
use of spoon.reflect.declaration.CtElement in project spoon by INRIA.
the class CtRenameLocalVariableRefactoring method detectNameConflicts.
@Override
protected void detectNameConflicts() {
/*
* There can be these conflicts
* 1) target variable would shadow before declared variable (parameter, localVariable, catchVariable)
* --------------------------------------------------------------------------------------------------
*/
PotentialVariableDeclarationFunction potentialDeclarationFnc = new PotentialVariableDeclarationFunction(newName);
CtVariable<?> var = getTarget().map(potentialDeclarationFnc).first();
if (var != null) {
if (var instanceof CtField) {
/*
* we have found a field of same name.
* It is not problem, because variables can hide field declaration.
* Do nothing - OK
*/
} else if (potentialDeclarationFnc.isTypeOnTheWay()) {
/*
* There is a local class declaration between future variable reference and variable declaration `var`.
* The found variable declaration `var` can be hidden by target variable with newName
* as long as there is no reference to `var` in visibility scope of the target variable.
* So search for such `var` reference now
*/
CtVariableReference<?> shadowedVar = target.map(new SiblingsFunction().includingSelf(true).mode(Mode.NEXT)).map(new VariableReferenceFunction(var)).first();
if (shadowedVar != null) {
// found variable reference, which would be shadowed by variable after rename.
createNameConflictIssue(var, shadowedVar);
} else {
/*
* there is no local variable reference, which would be shadowed by variable after rename.
* OK
*/
}
} else {
/*
* the found variable is in conflict with target variable with newName
*/
createNameConflictIssue(var);
}
}
/*
* 2) target variable is shadowed by later declared variable
* ---------------------------------------------------------
*/
final QueryDriver queryDriver = new QueryDriver();
getTarget().map(new LocalVariableScopeFunction(queryDriver)).select(new Filter<CtElement>() {
/**
* return true for all CtVariables, which are in conflict
*/
@Override
public boolean matches(CtElement element) {
if (element instanceof CtType<?>) {
CtType<?> localClass = (CtType<?>) element;
// TODO use faster hasField, implemented using map(new AllFieldsFunction()).select(new NameFilter(newName)).first()!=null
Collection<CtFieldReference<?>> fields = localClass.getAllFields();
for (CtFieldReference<?> fieldRef : fields) {
if (newName.equals(fieldRef.getSimpleName())) {
/*
* we have found a local class field, which will shadow input local variable if it's reference is in visibility scope of that field.
* Search for target variable reference in visibility scope of this field.
* If found than we cannot rename target variable to newName, because that reference would be shadowed
*/
queryDriver.ignoreChildrenOf(element);
CtLocalVariableReference<?> shadowedVar = element.map(new LocalVariableReferenceFunction(target)).first();
if (shadowedVar != null) {
createNameConflictIssue(fieldRef.getFieldDeclaration(), shadowedVar);
return true;
}
return false;
}
}
return false;
}
if (element instanceof CtVariable<?>) {
CtVariable<?> variable = (CtVariable<?>) element;
if (newName.equals(variable.getSimpleName()) == false) {
// the variable with different name. Ignore it
return false;
}
// we have found a variable with new name
if (variable instanceof CtField) {
throw new SpoonException("This should not happen. The children of local class which contains a field with new name should be skipped!");
}
if (variable instanceof CtCatchVariable || variable instanceof CtLocalVariable || variable instanceof CtParameter) {
/*
* we have found a catch variable or local variable or parameter with new name.
*/
if (queryDriver.isInContextOfLocalClass()) {
/*
* We are in context of local class.
* This variable would shadow input local variable after rename
* so we cannot rename if there exist a local variable reference in variable visibility scope.
*/
queryDriver.ignoreChildrenOf(variable.getParent());
CtQueryable searchScope;
if (variable instanceof CtLocalVariable) {
searchScope = variable.map(new SiblingsFunction().includingSelf(true).mode(Mode.NEXT));
} else {
searchScope = variable.getParent();
}
CtLocalVariableReference<?> shadowedVar = searchScope.map(new LocalVariableReferenceFunction(target)).first();
if (shadowedVar != null) {
// found local variable reference, which would be shadowed by variable after rename.
createNameConflictIssue(variable, shadowedVar);
return true;
}
// there is no local variable reference, which would be shadowed by variable after rename.
return false;
} else {
/*
* We are not in context of local class.
* So this variable is in conflict. Return it
*/
createNameConflictIssue(variable);
return true;
}
} else {
// Any new variable type???
throw new SpoonException("Unexpected variable " + variable.getClass().getName());
}
}
return false;
}
}).first();
}
use of spoon.reflect.declaration.CtElement in project spoon by INRIA.
the class TypeFactory method createTypeAdapter.
/**
* Create a {@link GenericTypeAdapter} for adapting of formal type parameters from any compatible context to the context of provided `formalTypeDeclarer`
*
* @param formalTypeDeclarer
* the target scope of the returned {@link GenericTypeAdapter}
*/
public GenericTypeAdapter createTypeAdapter(CtFormalTypeDeclarer formalTypeDeclarer) {
class Visitor extends CtAbstractVisitor {
GenericTypeAdapter adapter;
@Override
public <T> void visitCtClass(CtClass<T> ctClass) {
adapter = new ClassTypingContext(ctClass);
}
@Override
public <T> void visitCtInterface(CtInterface<T> intrface) {
adapter = new ClassTypingContext(intrface);
}
@Override
public <T> void visitCtMethod(CtMethod<T> m) {
adapter = new MethodTypingContext().setMethod(m);
}
@Override
public <T> void visitCtConstructor(CtConstructor<T> c) {
adapter = new MethodTypingContext().setConstructor(c);
}
}
Visitor visitor = new Visitor();
((CtElement) formalTypeDeclarer).accept(visitor);
return visitor.adapter;
}
use of spoon.reflect.declaration.CtElement in project spoon by INRIA.
the class CtElementPathBuilder method fromElement.
/**
* Build path to a CtElement el, from one of its parent.
*
* @throws CtPathException is thrown when root is not a parent of el.
*
* @param el : the element to which the CtPath leads to
* @param root : Starting point of the CtPath
* @return CtPath from root to el
*/
public CtPath fromElement(CtElement el, CtElement root) throws CtPathException {
CtPathImpl path = new CtPathImpl();
CtElement cur = el;
while (cur != root) {
CtElement parent = cur.getParent();
CtRole role = cur.getRoleInParent();
if (role == null) {
throw new CtPathException();
}
RoleHandler roleHandler = RoleHandlerHelper.getOptionalRoleHandler(parent.getClass(), role);
if (roleHandler == null) {
throw new CtPathException();
}
CtPathElement pathElement = new CtRolePathElement(role);
switch(roleHandler.getContainerKind()) {
case SINGLE:
break;
case LIST:
// Element needs to be differentiated from its brothers
List list = roleHandler.asList(parent);
// Assumes that List's order is deterministic.
// Can't be replaced by list.indexOf(cur)
// Because objects must be the same (and not just equals)
int index = 0;
for (Object o : list) {
if (o == cur) {
break;
}
index++;
}
pathElement.addArgument("index", index + "");
break;
case SET:
String name;
if (cur instanceof CtNamedElement) {
name = ((CtNamedElement) cur).getSimpleName();
} else if (cur instanceof CtReference) {
name = ((CtReference) cur).getSimpleName();
} else {
throw new CtPathException();
}
pathElement.addArgument("name", name);
break;
case MAP:
Map map = roleHandler.asMap(parent);
String key = null;
for (Object o : map.keySet()) {
if (map.get(o) == cur) {
key = (String) o;
break;
}
}
if (key == null) {
throw new CtPathException();
} else {
pathElement.addArgument("key", key);
}
break;
}
cur = parent;
path.addFirst(pathElement);
}
return path;
}
Aggregations