use of spoon.reflect.declaration.CtMethod in project spoon by INRIA.
the class SpoonArchitectureEnforcerTest method testSrcMainJava.
// this test contains all the architectural rules that are valid for the whole src/main/java
// we put them in the same test in order to only build the full model once
@Test
public void testSrcMainJava() throws Exception {
Launcher spoon = new Launcher();
spoon.getEnvironment().setCommentEnabled(true);
spoon.addInputResource("src/main/java/");
// contract: all non-trivial public methods should be documented with proper API Javadoc
spoon.buildModel();
List<String> notDocumented = new ArrayList<>();
for (CtMethod method : spoon.getModel().getElements(new TypeFilter<>(CtMethod.class))) {
// now we see whether this should be documented
if (// public methods should be documented
method.hasModifier(ModifierKind.PUBLIC) && // all kinds of setters can be undocumented
!method.getSimpleName().startsWith("get") && !method.getSimpleName().startsWith("set") && !method.getSimpleName().startsWith("is") && !method.getSimpleName().startsWith("add") && !method.getSimpleName().startsWith("remove") && // only the top declarations should be documented (not the overriding methods which are lower in the hierarchy)
method.getTopDefinitions().size() == 0 && (// all interface methods and abstract class methods must be documented
method.hasModifier(ModifierKind.ABSTRACT) || // 4) you commit your changes and create the corresponding pull requests
method.filterChildren(new TypeFilter<>(CtCodeElement.class)).list().size() > // means that only large methods must be documented
35)) {
// is it really well documented?
if (method.getDocComment().length() <= 15) {
// the Javadoc must be at least at least 15 characters (still pretty short...)
notDocumented.add(method.getParent(CtType.class).getQualifiedName() + "#" + method.getSignature());
}
}
}
if (notDocumented.size() > 0) {
fail(notDocumented.size() + " public methods should be documented with proper API documentation: \n" + StringUtils.join(notDocumented, "\n"));
}
// contract: Spoon's code never uses TreeSet constructor, because they implicitly depend on Comparable (no static check, only dynamic checks)
List<CtConstructorCall> treeSetWithoutComparators = spoon.getFactory().Package().getRootPackage().filterChildren(new AbstractFilter<CtConstructorCall>() {
@Override
public boolean matches(CtConstructorCall element) {
return element.getType().getActualClass().equals(TreeSet.class) && element.getArguments().size() == 0;
}
}).list();
assertEquals(0, treeSetWithoutComparators.size());
}
use of spoon.reflect.declaration.CtMethod in project spoon by INRIA.
the class SpoonArchitectureEnforcerTest method testGoodTestClassNames.
@Test
public void testGoodTestClassNames() throws Exception {
// contract: to be run by Maven surefire, all test classes must be called Test* or *Test
// reference: "By default, the Surefire Plugin will automatically include all test classes with the following wildcard patterns:"
// "**/Test*.java" and "**/*Test.java"
// http://maven.apache.org/surefire/maven-surefire-plugin/examples/inclusion-exclusion.html
SpoonAPI spoon = new Launcher();
spoon.addInputResource("src/test/java/");
spoon.buildModel();
for (CtMethod<?> meth : spoon.getModel().getElements(new TypeFilter<CtMethod>(CtMethod.class) {
@Override
public boolean matches(CtMethod element) {
return super.matches(element) && element.getAnnotation(Test.class) != null;
}
})) {
assertTrue("naming contract violated for " + meth.getParent(CtClass.class).getSimpleName(), meth.getParent(CtClass.class).getSimpleName().startsWith("Test") || meth.getParent(CtClass.class).getSimpleName().endsWith("Test"));
}
// contract: the Spoon test suite does not depend on Junit 3 classes and methods
// otherwise, intellij automatically selects the junit3 runner, finds nothing
// and crashes with a dirty exception
assertEquals(0, spoon.getModel().getElements(new TypeFilter<CtTypeReference>(CtTypeReference.class) {
@Override
public boolean matches(CtTypeReference element) {
CtMethod parent = element.getParent(CtMethod.class);
return "junit.framework.TestCase".equals(element.getQualifiedName());
}
}).size());
}
use of spoon.reflect.declaration.CtMethod in project spoon by INRIA.
the class ReplaceScanner method getTypeFromTypeParameterReference.
private CtTypeReference getTypeFromTypeParameterReference(CtTypeParameterReference ctTypeParameterRef) {
final CtMethod parentMethod = ctTypeParameterRef.getParent(CtMethod.class);
for (CtTypeParameter formal : parentMethod.getFormalCtTypeParameters()) {
if (formal.getSimpleName().equals(ctTypeParameterRef.getSimpleName())) {
return ((CtTypeParameterReference) formal).getBoundingType();
}
}
final CtInterface parentInterface = ctTypeParameterRef.getParent(CtInterface.class);
for (CtTypeParameter formal : parentInterface.getFormalCtTypeParameters()) {
if (formal.getSimpleName().equals(ctTypeParameterRef.getSimpleName())) {
return formal.getReference().getBoundingType();
}
}
throw new SpoonException("Can't get the type of the CtTypeParameterReference " + ctTypeParameterRef);
}
use of spoon.reflect.declaration.CtMethod in project spoon by INRIA.
the class ReplaceScanner method createInvocation.
private <T> CtInvocation<?> createInvocation(Factory factory, CtMethod<T> candidate, List<CtExpression<?>> invArgs, CtInvocation getter, Class getterTypeClass) {
CtInvocation<?> invocation;
Type type;
if (getterTypeClass.equals(Collection.class) || getterTypeClass.equals(List.class)) {
invocation = factory.Code().createInvocation(null, this.list, invArgs);
type = Type.LIST;
} else if (getterTypeClass.equals(Map.class)) {
invocation = factory.Code().createInvocation(null, this.map, invArgs);
type = Type.MAP;
} else if (getterTypeClass.equals(Set.class)) {
invocation = factory.Code().createInvocation(null, this.set, invArgs);
type = Type.SET;
} else {
invocation = factory.Code().createInvocation(null, this.element, invArgs);
type = Type.ELEMENT;
}
// Listener
final String name = getter.getExecutable().getSimpleName().substring(3);
final String listenerName = getter.getExecutable().getDeclaringType().getSimpleName() + name + "ReplaceListener";
CtClass listener;
if (listeners.containsKey(listenerName)) {
listener = listeners.get(listenerName);
} else {
final CtTypeReference getterType = getGetterType(factory, getter);
listener = createListenerClass(factory, listenerName, getterType, type);
final CtMethod setter = getSetter(name, getter.getTarget().getType().getDeclaration());
final CtField field = updateField(listener, setter.getDeclaringType().getReference());
updateConstructor(listener, setter.getDeclaringType().getReference());
updateSetter(factory, (CtMethod<?>) listener.getMethodsByName("set").get(0), getterType, field, setter);
// Add auto-generated comment.
final CtComment comment = factory.Core().createComment();
comment.setCommentType(CtComment.CommentType.INLINE);
comment.setContent("auto-generated, see " + ReplacementVisitorGenerator.class.getName());
listener.addComment(comment);
listeners.put(listenerName, listener);
}
invocation.addArgument(getConstructorCall(listener, factory.Code().createVariableRead(candidate.getParameters().get(0).getReference(), false)));
return invocation;
}
use of spoon.reflect.declaration.CtMethod in project spoon by INRIA.
the class Substitution method insertAllMethods.
/**
* Inserts all the methods from a given template by substituting all the
* template parameters by their values. Members annotated with
* {@link spoon.template.Local} or {@link Parameter} are not inserted.
*
* @param targetType
* the target type
* @param template
* the source template
* @param sourceClass
* the model of source template
*/
static void insertAllMethods(CtType<?> targetType, Template<?> template, CtClass<?> sourceClass) {
Set<CtMethod<?>> methodsOfTemplate = sourceClass.getFactory().Type().get(Template.class).getMethods();
// insert all the methods
for (CtMethod<?> m : sourceClass.getMethods()) {
if (m.getAnnotation(Local.class) != null) {
continue;
}
if (m.getAnnotation(Parameter.class) != null) {
continue;
}
boolean isOverridingTemplateItf = false;
for (CtMethod m2 : methodsOfTemplate) {
if (m.isOverriding(m2)) {
isOverridingTemplateItf = true;
}
}
if (isOverridingTemplateItf) {
continue;
}
insertMethod(targetType, template, m);
}
}
Aggregations