/*
* Copyright (C) 2006-2015 INRIA and contributors
* Spoon - http://spoon.gforge.inria.fr/
*
* This software is governed by the CeCILL-C License under French law and
* abiding by the rules of distribution of free software. You can use, modify
* and/or redistribute the software under the terms of the CeCILL-C license as
* circulated by CEA, CNRS and INRIA at http://www.cecill.info.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
*
* The fact that you are presently reading this means that you have had
* knowledge of the CeCILL-C license and that you accept its terms.
*/
package spoon.test.field;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static spoon.testing.Assert.assertThat;
import static spoon.testing.utils.ModelUtils.build;
import static spoon.testing.utils.ModelUtils.buildClass;
import static spoon.testing.utils.ModelUtils.createFactory;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import org.junit.Test;
import spoon.Launcher;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtFieldAccess;
import spoon.reflect.code.CtFieldRead;
import spoon.reflect.code.CtReturn;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtField;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.ModifierKind;
import spoon.reflect.factory.Factory;
import spoon.reflect.visitor.filter.TypeFilter;
import spoon.support.reflect.eval.VisitorPartialEvaluator;
import spoon.test.field.testclasses.A;
import spoon.test.field.testclasses.AddFieldAtTop;
import spoon.test.field.testclasses.BaseClass;
public class FieldTest {
@Test
public void testAddAFieldInAClassAtAPositionGiven() throws Exception {
final Factory factory = createFactory();
final CtClass<Object> fieldClass = factory.Class().create("FieldClass");
final HashSet<ModifierKind> modifiers = new HashSet<ModifierKind>();
modifiers.add(ModifierKind.STATIC);
final CtField<Integer> first = createField(factory, modifiers, "FIELD");
fieldClass.addField(first);
final CtField<Integer> second = createField(factory, modifiers, "FIELD_2");
second.setDefaultExpression(factory.Code().createCodeSnippetExpression(first.getSimpleName() + " + 1"));
fieldClass.addField(1, second);
final CtField<Integer> third = createField(factory, modifiers, "FIELD_3");
third.setDefaultExpression(factory.Code().createCodeSnippetExpression(first.getSimpleName() + " + 1"));
fieldClass.addField(1, third);
assertEquals(3, fieldClass.getFields().size());
assertEquals(first, fieldClass.getFields().get(0));
assertEquals(third, fieldClass.getFields().get(1));
assertEquals(second, fieldClass.getFields().get(2));
}
@Test
public void testAddFieldsAtTop() throws Exception {
// contract: When we use CtType#addFieldAtTop, field added should be printed at the top of the type.
final CtClass<AddFieldAtTop> aClass = (CtClass<AddFieldAtTop>) buildClass(AddFieldAtTop.class);
assertEquals(1, aClass.getFields().size());
final CtField<String> generated = aClass.getFactory().Field().create(null, new HashSet<>(), aClass.getFactory().Type().STRING, "generated");
aClass.addFieldAtTop(generated);
final CtField<String> generated2 = aClass.getFactory().Field().create(null, new HashSet<>(), aClass.getFactory().Type().STRING, "generated2");
aClass.addFieldAtTop(generated2);
assertEquals(3, aClass.getFields().size());
// For now, DefaultJavaPrettyPrinter sorts elements according to their position.
assertEquals(generated2, aClass.getTypeMembers().get(0));
assertEquals(generated, aClass.getTypeMembers().get(1));
assertEquals(aClass.getAnonymousExecutables().get(0), aClass.getTypeMembers().get(3));
}
@Test
public void testFieldImplicitTarget() throws Exception {
// contract: no "." when target is implicit
final CtClass<AddFieldAtTop> aClass = (CtClass<AddFieldAtTop>) buildClass(AddFieldAtTop.class);
List<CtFieldRead> fieldReads = aClass.getElements(new TypeFilter<>(CtFieldRead.class));
assertEquals(1, fieldReads.size());
assertEquals("i", fieldReads.get(0).toString());
fieldReads.get(0).getTarget().setImplicit(false);
assertEquals(false, fieldReads.get(0).getTarget().isImplicit());
assertEquals("this.i", fieldReads.get(0).toString());
}
private CtField<Integer> createField(Factory factory, HashSet<ModifierKind> modifiers, String name) {
final CtField<Integer> first = factory.Core().createField();
first.setModifiers(modifiers);
first.setType(factory.Type().INTEGER_PRIMITIVE);
first.setSimpleName(name);
return first;
}
@Test
public void testGetDefaultExpression() throws Exception {
Launcher spoon = new Launcher();
spoon.addInputResource("./src/test/java/spoon/test/field/testclasses/A.java");
spoon.addInputResource("./src/test/java/spoon/test/field/testclasses/BaseClass.java");
spoon.buildModel();
final CtClass<A> aClass = spoon.getFactory().Class().get(A.class);
CtClass<A.ClassB> bClass = aClass.getFactory().Class().get(A.ClassB.class);
List<CtMethod<?>> methods = bClass.getMethodsByName("getKey");
assertEquals(1, methods.size());
CtReturn<?> returnExpression = methods.get(0).getBody().getStatement(0);
CtFieldRead fieldRead = (CtFieldRead) returnExpression.getReturnedExpression();
assertEquals("spoon.test.field.testclasses.BaseClass.PREFIX", fieldRead.toString());
CtField<?> field = fieldRead.getVariable().getDeclaration();
CtClass<BaseClass> baseClass = aClass.getFactory().Class().get(BaseClass.class);
CtField<?> expectedField = baseClass.getField("PREFIX");
assertEquals(expectedField, field);
VisitorPartialEvaluator visitorPartial = new VisitorPartialEvaluator();
Object retour = visitorPartial.evaluate(methods.get(0));
assertTrue(retour != null);
}
}