use of spoon.reflect.reference.CtFieldReference in project spoon by INRIA.
the class FilterTest method testFieldAccessFilter.
@Test
public void testFieldAccessFilter() throws Exception {
// also specifies VariableAccessFilter since FieldAccessFilter is only a VariableAccessFilter with additional static typing
CtClass<?> foo = factory.Package().get("spoon.test.filters").getType("Foo");
assertEquals("Foo", foo.getSimpleName());
List<CtNamedElement> elements = foo.getElements(new NamedElementFilter<>(CtNamedElement.class, "i"));
assertEquals(1, elements.size());
CtFieldReference<?> ref = (CtFieldReference<?>) (elements.get(0)).getReference();
List<CtFieldAccess<?>> expressions = foo.getElements(new FieldAccessFilter(ref));
assertEquals(2, expressions.size());
final Factory build = build(FieldAccessFilterTacos.class);
final CtType<FieldAccessFilterTacos> fieldAccessFilterTacos = build.Type().get(FieldAccessFilterTacos.class);
try {
List<CtField> fields = fieldAccessFilterTacos.getElements(new TypeFilter<CtField>(CtField.class));
for (CtField ctField : fields) {
fieldAccessFilterTacos.getElements(new FieldAccessFilter(ctField.getReference()));
}
} catch (NullPointerException e) {
fail("FieldAccessFilter must not throw a NPE.");
}
}
use of spoon.reflect.reference.CtFieldReference in project spoon by INRIA.
the class ImportScannerImpl method isTypeInCollision.
/**
* Test if the reference can be imported, i.e. test if the importation could lead to a collision.
* @param ref
* @return true if the ref should be imported.
*/
protected boolean isTypeInCollision(CtReference ref, boolean fqnMode) {
if (targetType != null && targetType.getSimpleName().equals(ref.getSimpleName()) && !targetType.equals(ref)) {
return true;
}
try {
CtElement parent;
if (ref instanceof CtTypeReference) {
parent = ref.getParent();
} else {
parent = ref;
}
// i.e. a string, an int, etc.
if (parent instanceof CtLiteral) {
return false;
}
Set<String> localVariablesOfBlock = new HashSet<>();
if (parent instanceof CtField) {
this.fieldAndMethodsNames.add(((CtField) parent).getSimpleName());
} else if (parent instanceof CtMethod) {
this.fieldAndMethodsNames.add(((CtMethod) parent).getSimpleName());
} else {
localVariablesOfBlock = this.lookForLocalVariables(parent);
}
while (!(parent instanceof CtPackage)) {
if ((parent instanceof CtFieldReference) || (parent instanceof CtExecutableReference) || (parent instanceof CtInvocation)) {
CtReference parentType;
if (parent instanceof CtInvocation) {
parentType = ((CtInvocation) parent).getExecutable();
} else {
parentType = (CtReference) parent;
}
LinkedList<String> qualifiedNameTokens = new LinkedList<>();
// we don't want to test the current ref name, as we risk to create field import and make autoreference
if (parentType != parent) {
qualifiedNameTokens.add(parentType.getSimpleName());
}
CtTypeReference typeReference;
if (parent instanceof CtFieldReference) {
typeReference = ((CtFieldReference) parent).getDeclaringType();
} else if (parent instanceof CtExecutableReference) {
typeReference = ((CtExecutableReference) parent).getDeclaringType();
} else {
typeReference = ((CtInvocation) parent).getExecutable().getDeclaringType();
}
if (typeReference != null) {
qualifiedNameTokens.addFirst(typeReference.getSimpleName());
if (typeReference.getPackage() != null) {
StringTokenizer token = new StringTokenizer(typeReference.getPackage().getSimpleName(), CtPackage.PACKAGE_SEPARATOR);
int index = 0;
while (token.hasMoreElements()) {
qualifiedNameTokens.add(index, token.nextToken());
index++;
}
}
}
if (!qualifiedNameTokens.isEmpty()) {
// if the first package name is a variable name somewhere, it could lead to a collision
if (fieldAndMethodsNames.contains(qualifiedNameTokens.getFirst()) || localVariablesOfBlock.contains(qualifiedNameTokens.getFirst())) {
qualifiedNameTokens.removeFirst();
if (fqnMode) {
// for example: spoon.Launcher if a field spoon and another one Launcher exists
if (ref instanceof CtTypeReference) {
if (qualifiedNameTokens.isEmpty()) {
return true;
}
// but if the other package names are not a variable name, it's ok to import
for (int i = 0; i < qualifiedNameTokens.size(); i++) {
String testedToken = qualifiedNameTokens.get(i);
if (!fieldAndMethodsNames.contains(testedToken) && !localVariablesOfBlock.contains(testedToken)) {
return true;
}
}
return false;
// However if it is a static method/field, we always accept to import them in this case
// It is the last possibility for managing import for us
} else {
return true;
}
} else {
// but if the other package names are not a variable name, it's ok to import
for (int i = 0; i < qualifiedNameTokens.size(); i++) {
String testedToken = qualifiedNameTokens.get(i);
if (!fieldAndMethodsNames.contains(testedToken) && !localVariablesOfBlock.contains(testedToken)) {
return false;
}
}
return true;
}
}
}
}
parent = parent.getParent();
}
} catch (ParentNotInitializedException e) {
return false;
}
return false;
}
use of spoon.reflect.reference.CtFieldReference in project spoon by INRIA.
the class ImportScannerImpl method addClassImport.
/**
* Adds a type to the classImports.
*/
protected boolean addClassImport(CtTypeReference<?> ref) {
this.exploredReferences.add(ref);
if (ref == null) {
return false;
}
if (targetType != null && targetType.getSimpleName().equals(ref.getSimpleName()) && !targetType.equals(ref)) {
return false;
}
if (classImports.containsKey(ref.getSimpleName())) {
return isImportedInClassImports(ref);
}
// don't import unnamed package elements
if (ref.getPackage() == null || ref.getPackage().isUnnamedPackage()) {
return false;
}
if (targetType != null && targetType.canAccess(ref) == false) {
// ref type is not visible in targetType we must not add import for it, java compiler would fail on that.
return false;
}
if (this.isThereAnotherClassWithSameNameInAnotherPackage(ref)) {
return false;
}
if (targetType != null) {
try {
CtElement parent = ref.getParent();
if (parent != null) {
parent = parent.getParent();
if (parent != null) {
if ((parent instanceof CtFieldAccess) || (parent instanceof CtExecutable) || (parent instanceof CtInvocation)) {
CtTypeReference declaringType;
CtReference reference;
CtPackageReference pack = targetType.getPackage();
if (parent instanceof CtFieldAccess) {
CtFieldAccess field = (CtFieldAccess) parent;
CtFieldReference localReference = field.getVariable();
declaringType = localReference.getDeclaringType();
reference = localReference;
} else if (parent instanceof CtExecutable) {
CtExecutable exec = (CtExecutable) parent;
CtExecutableReference localReference = exec.getReference();
declaringType = localReference.getDeclaringType();
reference = localReference;
} else if (parent instanceof CtInvocation) {
CtInvocation invo = (CtInvocation) parent;
CtExecutableReference localReference = invo.getExecutable();
declaringType = localReference.getDeclaringType();
reference = localReference;
} else {
declaringType = null;
reference = null;
}
if (reference != null && isImported(reference)) {
// if we are in the **same** package we do the import for test with method isImported
if (declaringType != null) {
if (declaringType.getPackage() != null && !declaringType.getPackage().isUnnamedPackage()) {
// ignore java.lang package
if (!declaringType.getPackage().getSimpleName().equals("java.lang")) {
// ignore type in same package
if (declaringType.getPackage().getSimpleName().equals(pack.getSimpleName())) {
classImports.put(ref.getSimpleName(), ref);
return true;
}
}
}
}
}
}
}
}
} catch (ParentNotInitializedException e) {
}
CtPackageReference pack = targetType.getPackage();
if (pack != null && ref.getPackage() != null && !ref.getPackage().isUnnamedPackage()) {
// ignore java.lang package
if (!ref.getPackage().getSimpleName().equals("java.lang")) {
// ignore type in same package
if (ref.getPackage().getSimpleName().equals(pack.getSimpleName())) {
return false;
}
}
}
}
classImports.put(ref.getSimpleName(), ref);
return true;
}
use of spoon.reflect.reference.CtFieldReference in project spoon by INRIA.
the class CtAnnotationImpl method convertValueToExpression.
private CtExpression convertValueToExpression(Object value) {
CtExpression res;
if (value.getClass().isArray()) {
// Value should be converted to a CtNewArray.
res = getFactory().Core().createNewArray();
Object[] values = (Object[]) value;
res.setType(getFactory().Type().createArrayReference(getFactory().Type().createReference(value.getClass().getComponentType())));
for (Object o : values) {
((CtNewArray) res).addElement(convertValueToExpression(o));
}
} else if (value instanceof Collection) {
// Value should be converted to a CtNewArray.
res = getFactory().Core().createNewArray();
Collection values = (Collection) value;
res.setType(getFactory().Type().createArrayReference(getFactory().Type().createReference(values.toArray()[0].getClass())));
for (Object o : values) {
((CtNewArray) res).addElement(convertValueToExpression(o));
}
} else if (value instanceof Class) {
// Value should be a field access to a .class.
res = getFactory().Code().createClassAccess(getFactory().Type().createReference((Class) value));
} else if (value instanceof Field) {
// Value should be a field access to a field.
CtFieldReference<Object> variable = getFactory().Field().createReference((Field) value);
variable.setStatic(true);
CtTypeAccess target = getFactory().Code().createTypeAccess(getFactory().Type().createReference(((Field) value).getDeclaringClass()));
CtFieldRead fieldRead = getFactory().Core().createFieldRead();
fieldRead.setVariable(variable);
fieldRead.setTarget(target);
fieldRead.setType(target.getAccessedType());
res = fieldRead;
} else if (isPrimitive(value.getClass()) || value instanceof String) {
// Value should be a literal.
res = getFactory().Code().createLiteral(value);
} else if (value.getClass().isEnum()) {
final CtTypeReference declaringClass = getFactory().Type().createReference(((Enum) value).getDeclaringClass());
final CtFieldReference variableRef = getFactory().Field().createReference(declaringClass, declaringClass, ((Enum) value).name());
CtTypeAccess target = getFactory().Code().createTypeAccess(declaringClass);
CtFieldRead fieldRead = getFactory().Core().createFieldRead();
fieldRead.setVariable(variableRef);
fieldRead.setTarget(target);
fieldRead.setType(declaringClass);
res = fieldRead;
} else {
throw new SpoonException("Please, submit a valid value.");
}
return res;
}
use of spoon.reflect.reference.CtFieldReference in project spoon by INRIA.
the class TypeReferenceTest method doNotCloseLoader.
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void doNotCloseLoader() throws Exception {
/* Given the following scenario:
* - ClassA has a field of ClassB.
* - ClassB has a field of ClassC.
* - Spoon only models ClassA.
*
* We want to get the field of ClassB, which should be accessible because
* the definitions of ClassB and ClassC were provided in the class path.
*/
SpoonModelBuilder comp = new Launcher().createCompiler();
Factory factory = comp.getFactory();
String qualifiedName = "spoontest.a.ClassA";
String referenceQualifiedName = "spoontest.b.ClassB";
// we only create the model for ClassA
List<SpoonResource> fileToBeSpooned = SpoonResourceHelper.resources("./src/test/resources/reference-test-2/" + qualifiedName.replace('.', '/') + ".java");
comp.addInputSources(fileToBeSpooned);
// for ClassA
assertEquals(1, fileToBeSpooned.size());
// Spoon requires the binary version of dependencies
List<SpoonResource> classpath = SpoonResourceHelper.resources("./src/test/resources/reference-test-2/ReferenceTest2.jar");
String[] dependencyClasspath = new String[] { classpath.get(0).getPath() };
factory.getEnvironment().setSourceClasspath(dependencyClasspath);
assertEquals(1, classpath.size());
// now we can build the model
comp.build();
// we can get the model of ClassA
CtType<?> theClass = factory.Type().get(qualifiedName);
// we get ClassA's field of type ClassB
List<CtField<?>> fields = theClass.getFields();
assertEquals(1, fields.size());
CtField<?> bField = fields.get(0);
CtTypeReference referencedType = bField.getType();
assertEquals(referenceQualifiedName, referencedType.getQualifiedName());
// we get ClassB's field of type ClassC
Collection<CtFieldReference<?>> fieldsOfB = referencedType.getAllFields();
if (fieldsOfB.size() == 2) {
// Jacoco instruments all dependencies with an agent.
// So, when we use reflection on ClassB, we don't have one field but two fields.
// First, it is the field of ClassB. Second, it is the field of Jacoco.
final CtFieldReference<?> potentialJacoco = (CtFieldReference<?>) fieldsOfB.toArray()[1];
if ("$jacocoData".equals(potentialJacoco.getSimpleName())) {
fieldsOfB.remove(potentialJacoco);
}
}
assertEquals(1, fieldsOfB.size());
CtFieldReference<?> cField = fieldsOfB.iterator().next();
assertEquals("spoontest.c.ClassC", cField.getType().getQualifiedName());
}
Aggregations