use of spoon.reflect.code.CtIf in project spoon by INRIA.
the class NullParentTest method testIfNullBranches.
@Test
public void testIfNullBranches() {
CtIf ctIf = get(CtIf.class);
assertEquals("if(true){}else{}", noSpaceToString(ctIf));
ctIf.setThenStatement(null);
assertEquals("if(true);else{}", noSpaceToString(ctIf));
ctIf.setElseStatement(null);
assertEquals("if(true);", noSpaceToString(ctIf));
}
use of spoon.reflect.code.CtIf in project spoon by INRIA.
the class ParentTest method testParentSetInSetter.
@Test
// too fragile because of conventions
@Ignore
public void testParentSetInSetter() throws Exception {
// contract: Check that all setters protect their parameter.
final Launcher launcher = new Launcher();
final Factory factory = launcher.getFactory();
launcher.setArgs(new String[] { "--output-type", "nooutput" });
launcher.getEnvironment().setNoClasspath(true);
// interfaces.
launcher.addInputResource("./src/main/java/spoon/reflect/code");
launcher.addInputResource("./src/main/java/spoon/reflect/declaration");
launcher.addInputResource("./src/main/java/spoon/reflect/reference");
// implementations.
launcher.addInputResource("./src/main/java/spoon/support/reflect/code");
launcher.addInputResource("./src/main/java/spoon/support/reflect/declaration");
launcher.addInputResource("./src/main/java/spoon/support/reflect/reference");
// Utils.
launcher.addInputResource("./src/test/java/spoon/reflect/ast/");
launcher.buildModel();
// Asserts.
new IntercessionScanner(launcher.getFactory()) {
@Override
protected boolean isToBeProcessed(CtMethod<?> candidate) {
return (//
candidate.getSimpleName().startsWith("set") || //
candidate.getSimpleName().startsWith("add")) && //
candidate.hasModifier(ModifierKind.PUBLIC) && //
takeSetterForCtElement(candidate) && //
avoidInterfaces(candidate) && avoidThrowUnsupportedOperationException(candidate);
}
@Override
public void process(CtMethod<?> element) {
if (element.getAnnotation(UnsettableProperty.class) != null) {
// we don't check the contracts for unsettable setters
return;
}
if (element.getSimpleName().startsWith("add")) {
checkAddStrategy(element);
} else {
checkSetStrategy(element);
}
}
private void checkAddStrategy(CtMethod<?> element) {
final CtStatement statement = element.getBody().getStatement(0);
if (!(statement instanceof CtIf)) {
fail("First statement should be an if to check the parameter of the setter." + element.getSignature() + " declared in " + element.getDeclaringType().getQualifiedName());
}
if (!createCheckNull(element.getParameters().get(0)).equals(((CtIf) statement).getCondition())) {
fail("Condition should test if the parameter is null. The condition was " + ((CtIf) statement).getCondition() + "in " + element.getSignature() + " declared in " + element.getDeclaringType().getQualifiedName());
}
}
private void checkSetStrategy(CtMethod<?> element) {
final CtTypeReference<?> type = element.getParameters().get(0).getType();
if (!COLLECTIONS.contains(type) && !(type instanceof CtArrayTypeReference)) {
CtInvocation<?> setParent = searchSetParent(element.getBody());
if (setParent == null) {
return;
}
try {
if (setParent.getParent(CtIf.class) == null) {
fail("Missing condition in " + element.getSignature() + " declared in the class " + element.getDeclaringType().getQualifiedName());
}
} catch (ParentNotInitializedException e) {
fail("Missing parent condition in " + element.getSignature() + " declared in the class " + element.getDeclaringType().getQualifiedName());
}
}
}
/**
* Creates <code>parameter == null</code>.
*
* @param ctParameter <code>parameter</code>
*/
private CtBinaryOperator<Boolean> createCheckNull(CtParameter<?> ctParameter) {
final CtLiteral nullLiteral = factory.Code().createLiteral(null);
nullLiteral.setType(factory.Type().NULL_TYPE.clone());
final CtBinaryOperator<Boolean> operator = //
factory.Code().createBinaryOperator(//
factory.Code().createVariableRead(ctParameter.getReference(), true), nullLiteral, BinaryOperatorKind.EQ);
operator.setType(factory.Type().BOOLEAN_PRIMITIVE);
return operator;
}
private CtInvocation<?> searchSetParent(CtBlock<?> body) {
final List<CtInvocation<?>> ctInvocations = body.getElements(new TypeFilter<CtInvocation<?>>(CtInvocation.class) {
@Override
public boolean matches(CtInvocation<?> element) {
return "setParent".equals(element.getExecutable().getSimpleName()) && super.matches(element);
}
});
return ctInvocations.size() > 0 ? ctInvocations.get(0) : null;
}
}.scan(launcher.getModel().getRootPackage());
}
use of spoon.reflect.code.CtIf in project spoon by INRIA.
the class PositionTest method getPositionOfImplicitBlock.
@Test
public void getPositionOfImplicitBlock() {
// contract: position of implicit block in if (cond) [implicit block] else [implicit block] should be the source position of implicit block content.
Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/java/spoon/test/position/testclasses/ImplicitBlock.java");
launcher.buildModel();
CtIf ifElement = launcher.getModel().getElements(new TypeFilter<CtIf>(CtIf.class)).get(0);
CtStatement thenStatement = ifElement.getThenStatement();
assertTrue(thenStatement instanceof CtBlock);
CtBlock thenBlock = (CtBlock) thenStatement;
SourcePosition positionThen = thenBlock.getPosition();
CtStatement returnStatement = thenBlock.getStatement(0);
assertEquals(returnStatement.getPosition(), positionThen);
assertEquals("ImplicitBlock.java", positionThen.getFile().getName());
assertEquals(7, positionThen.getLine());
CtStatement elseStatement = ifElement.getElseStatement();
assertTrue(elseStatement instanceof CtBlock);
CtBlock elseBlock = (CtBlock) elseStatement;
SourcePosition positionElse = elseBlock.getPosition();
CtStatement otherReturnStatement = elseBlock.getStatement(0);
assertEquals(otherReturnStatement.getPosition(), positionElse);
assertEquals("ImplicitBlock.java", positionThen.getFile().getName());
assertEquals(8, positionElse.getLine());
assertNotEquals(returnStatement, otherReturnStatement);
}
use of spoon.reflect.code.CtIf in project spoon by INRIA.
the class APITest method testSetterInNodes.
@Test
public void testSetterInNodes() throws Exception {
// that the new value is != null to avoid NPE when we set the parent.
class SetterMethodWithoutCollectionsFilter extends TypeFilter<CtMethod<?>> {
private final List<CtTypeReference<?>> collections = new ArrayList<>(4);
public SetterMethodWithoutCollectionsFilter(Factory factory) {
super(CtMethod.class);
for (Class<?> aCollectionClass : Arrays.asList(Collection.class, List.class, Map.class, Set.class)) {
collections.add(factory.Type().createReference(aCollectionClass));
}
}
@Override
public boolean matches(CtMethod<?> element) {
boolean isSetter = isSetterMethod(element);
boolean isNotSubType = !isSubTypeOfCollection(element);
// setter with unsettableProperty should not respect the contract, as well as derived properties
boolean doesNotHaveUnsettableAnnotation = doesNotHaveUnsettableAnnotation(element);
boolean isNotSetterForADerivedProperty = isNotSetterForADerivedProperty(element);
boolean superMatch = super.matches(element);
return isSetter && doesNotHaveUnsettableAnnotation && isNotSetterForADerivedProperty && isNotSubType && superMatch;
}
private boolean isNotSetterForADerivedProperty(CtMethod<?> method) {
String methodName = method.getSimpleName();
String getterName = methodName.replace("set", "get");
if (getterName.equals(methodName)) {
return false;
}
CtType<?> zeClass = (CtType) method.getParent();
List<CtMethod<?>> getterMethods = zeClass.getMethodsByName(getterName);
if (getterMethods.size() != 1) {
return false;
}
CtMethod<?> getterMethod = getterMethods.get(0);
return (getterMethod.getAnnotation(DerivedProperty.class) == null);
}
private boolean doesNotHaveUnsettableAnnotation(CtMethod<?> element) {
return (element.getAnnotation(UnsettableProperty.class) == null);
}
private boolean isSubTypeOfCollection(CtMethod<?> element) {
final List<CtParameter<?>> parameters = element.getParameters();
if (parameters.size() != 1) {
return false;
}
final CtTypeReference<?> type = parameters.get(0).getType();
for (CtTypeReference<?> aCollectionRef : collections) {
if (type.isSubtypeOf(aCollectionRef) || type.equals(aCollectionRef)) {
return true;
}
}
return false;
}
private boolean isSetterMethod(CtMethod<?> element) {
final List<CtParameter<?>> parameters = element.getParameters();
if (parameters.size() != 1) {
return false;
}
final CtTypeReference<?> typeParameter = parameters.get(0).getType();
final CtTypeReference<CtElement> ctElementRef = element.getFactory().Type().createReference(CtElement.class);
// isSubtypeOf will return true in case of equality
boolean isSubtypeof = typeParameter.isSubtypeOf(ctElementRef);
if (!isSubtypeof) {
return false;
}
return element.getSimpleName().startsWith("set") && element.getDeclaringType().getSimpleName().startsWith("Ct") && element.getBody() != null;
}
}
class CheckNotNullToSetParentMatcher extends CtElementImpl {
public TemplateParameter<CtVariableAccess<?>> _parameter_access_;
public void matcher() {
if (_parameter_access_.S() != null) {
_parameter_access_.S().setParent(this);
}
}
@Override
@Local
public void accept(CtVisitor visitor) {
}
}
final Launcher launcher = new Launcher();
launcher.setArgs(new String[] { "--output-type", "nooutput" });
launcher.getEnvironment().setNoClasspath(true);
// Implementations
launcher.addInputResource("./src/main/java/spoon/support/reflect/code");
launcher.addInputResource("./src/main/java/spoon/support/reflect/declaration");
launcher.addInputResource("./src/main/java/spoon/support/reflect/reference");
launcher.addInputResource("./src/test/java/" + this.getClass().getCanonicalName().replace(".", "/") + ".java");
// Needed for #isSubTypeOf method.
launcher.addInputResource("./src/main/java/spoon/reflect/");
launcher.buildModel();
// Template matcher.
CtClass<CheckNotNullToSetParentMatcher> matcherCtClass = launcher.getFactory().Class().get(CheckNotNullToSetParentMatcher.class);
CtIf templateRoot = matcherCtClass.getMethod("matcher").getBody().getStatement(0);
final List<CtMethod<?>> setters = Query.getElements(launcher.getFactory(), new SetterMethodWithoutCollectionsFilter(launcher.getFactory()));
assertTrue("Number of setters found null", setters.size() > 0);
for (CtStatement statement : setters.stream().map((Function<CtMethod<?>, CtStatement>) ctMethod -> ctMethod.getBody().getStatement(0)).collect(Collectors.toList())) {
// First statement should be a condition to protect the setter of the parent.
assertTrue("Check the method " + statement.getParent(CtMethod.class).getSignature() + " in the declaring class " + statement.getParent(CtType.class).getQualifiedName(), statement instanceof CtIf);
CtIf ifCondition = (CtIf) statement;
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
assertEquals("Check the number of if in method " + statement.getParent(CtMethod.class).getSignature() + " in the declaring class " + statement.getParent(CtType.class).getQualifiedName(), 1, matcher.find(ifCondition).size());
}
}
use of spoon.reflect.code.CtIf in project spoon by INRIA.
the class ConditionalTest method testBlockInConditionAndLoop.
@Test
public void testBlockInConditionAndLoop() throws Exception {
final CtType<Foo> aFoo = ModelUtils.buildClass(Foo.class);
final List<CtIf> conditions = aFoo.getMethod("m3").getElements(new TypeFilter<CtIf>(CtIf.class));
assertEquals(4, conditions.size());
for (CtIf condition : conditions) {
assertTrue(condition.getThenStatement() instanceof CtBlock);
if (condition.getElseStatement() != null && !(condition.getElseStatement() instanceof CtIf)) {
assertTrue(condition.getElseStatement() instanceof CtBlock);
}
}
}
Aggregations