use of spoon.template.TemplateMatcher in project spoon by INRIA.
the class TemplateTest method testTemplateMatcherWithWholePackage.
@Test
public void testTemplateMatcherWithWholePackage() throws Exception {
Launcher spoon = new Launcher();
spoon.addInputResource("./src/test/java/spoon/test/template/testclasses/ContextHelper.java");
spoon.addInputResource("./src/test/java/spoon/test/template/testclasses/BServiceImpl.java");
spoon.addTemplateResource(new FileSystemFile("./src/test/java/spoon/test/template/testclasses/SecurityCheckerTemplate.java"));
spoon.buildModel();
Factory factory = spoon.getFactory();
CtClass<?> templateKlass = factory.Class().get(SecurityCheckerTemplate.class);
CtMethod templateMethod = (CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher1")).get(0);
CtIf templateRoot = (CtIf) templateMethod.getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
List<CtElement> matches = matcher.find(factory.getModel().getRootPackage());
assertEquals(1, matches.size());
CtElement match = matches.get(0);
assertTrue("Match is not a if", match instanceof CtIf);
CtElement matchParent = match.getParent();
assertTrue("Match parent is not a block", matchParent instanceof CtBlock);
CtElement matchParentParent = matchParent.getParent();
assertTrue("Match grand parent is not a method", matchParentParent instanceof CtMethod);
CtMethod methodHello = (CtMethod) matchParentParent;
assertEquals("Match grand parent is not a method called hello", "hello", methodHello.getSimpleName());
CtElement methodParent = methodHello.getParent();
assertTrue("Parent of the method is not a class", methodParent instanceof CtClass);
CtClass bservice = (CtClass) methodParent;
assertEquals("Parent of the method is not a class called BServiceImpl", "BServiceImpl", bservice.getSimpleName());
}
use of spoon.template.TemplateMatcher 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.template.TemplateMatcher in project spoon by INRIA.
the class TemplateTest method testTemplateMatcherMatchTwoSnippets.
@Test
public void testTemplateMatcherMatchTwoSnippets() throws Exception {
Launcher spoon = new Launcher();
spoon.addInputResource("./src/test/java/spoon/test/template/testclasses/TwoSnippets.java");
spoon.addTemplateResource(new FileSystemFile("./src/test/java/spoon/test/template/testclasses/SecurityCheckerTemplate.java"));
spoon.buildModel();
Factory factory = spoon.getFactory();
CtClass<?> templateKlass = factory.Class().get(SecurityCheckerTemplate.class);
CtMethod templateMethod = (CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher1")).get(0);
CtIf templateRoot = (CtIf) templateMethod.getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
// match using legacy TemplateMatcher#find method
List<CtElement> matches = matcher.find(factory.getModel().getRootPackage());
assertEquals(2, matches.size());
CtElement match1 = matches.get(0);
CtElement match2 = matches.get(1);
assertTrue(match1.equals(match2));
// match using TemplateMatcher#matches method and query filter
matches = factory.getModel().filterChildren(matcher).list();
assertEquals(2, matches.size());
match1 = matches.get(0);
match2 = matches.get(1);
assertTrue(match1.equals(match2));
}
use of spoon.template.TemplateMatcher in project spoon by INRIA.
the class TemplateTest method testTemplateMatcher.
@Test
public void testTemplateMatcher() throws Exception {
// contract: the given templates should match the expected elements
Launcher spoon = new Launcher();
Factory factory = spoon.getFactory();
spoon.createCompiler(factory, SpoonResourceHelper.resources("./src/test/java/spoon/test/template/testclasses/bounds/CheckBound.java"), SpoonResourceHelper.resources("./src/test/java/spoon/test/template/testclasses/bounds/CheckBoundMatcher.java")).build();
{
// testing matcher1
CtClass<?> templateKlass = factory.Class().get(CheckBoundMatcher.class);
CtClass<?> klass = factory.Class().get(CheckBound.class);
CtIf templateRoot = (CtIf) ((CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher1")).get(0)).getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
assertEquals(2, matcher.find(klass).size());
assertThat(asList("foo", "fbar"), is(klass.filterChildren(matcher).map((CtElement e) -> e.getParent(CtMethod.class).getSimpleName()).list()));
}
{
// testing matcher2
CtClass<?> templateKlass = factory.Class().get(CheckBoundMatcher.class);
CtClass<?> klass = factory.Class().get(CheckBound.class);
CtIf templateRoot = (CtIf) ((CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher2")).get(0)).getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
assertEquals(1, matcher.find(klass).size());
assertThat(asList("bov"), is(klass.filterChildren(matcher).map((CtElement e) -> e.getParent(CtMethod.class).getSimpleName()).list()));
}
{
// testing matcher3
CtClass<?> templateKlass = factory.Class().get(CheckBoundMatcher.class);
CtClass<?> klass = factory.Class().get(CheckBound.class);
CtIf templateRoot = (CtIf) ((CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher3")).get(0)).getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
assertEquals(2, matcher.find(klass).size());
assertThat(asList("foo", "fbar"), is(klass.filterChildren(matcher).map((CtElement e) -> e.getParent(CtMethod.class).getSimpleName()).list()));
}
{
// testing matcher4
CtClass<?> templateKlass = factory.Class().get(CheckBoundMatcher.class);
CtClass<?> klass = factory.Class().get(CheckBound.class);
CtIf templateRoot = (CtIf) ((CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher4")).get(0)).getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
assertEquals(3, matcher.find(klass).size());
assertThat(asList("foo", "foo2", "fbar"), is(klass.filterChildren(matcher).map((CtElement e) -> e.getParent(CtMethod.class).getSimpleName()).list()));
}
{
// testing matcher5
CtClass<?> templateKlass = factory.Class().get(CheckBoundMatcher.class);
CtClass<?> klass = factory.Class().get(CheckBound.class);
CtIf templateRoot = (CtIf) ((CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher5")).get(0)).getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
assertEquals(6, matcher.find(klass).size());
assertThat(asList("foo", "foo2", "fbar", "baz", "bou", "bov"), is(klass.filterChildren(matcher).map((CtElement e) -> e.getParent(CtMethod.class).getSimpleName()).list()));
}
{
// testing matcher6
CtClass<?> templateKlass = factory.Class().get(CheckBoundMatcher.class);
CtClass<?> klass = factory.Class().get(CheckBound.class);
CtIf templateRoot = (CtIf) ((CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher6")).get(0)).getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
assertEquals(2, matcher.find(klass).size());
assertThat(asList("baz", "bou"), is(klass.filterChildren(matcher).map((CtElement e) -> e.getParent(CtMethod.class).getSimpleName()).list()));
}
// testing with named elements, at the method level
{
CtClass<?> templateKlass = factory.Class().get(CheckBoundMatcher.class);
CtClass<?> klass = factory.Class().get(CheckBound.class);
CtMethod meth = (CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher3")).get(0);
// exact match
meth.setSimpleName("foo");
TemplateMatcher matcher = new TemplateMatcher(meth);
List<CtMethod> ctElements = matcher.find(klass);
assertEquals(1, ctElements.size());
assertEquals("foo", ctElements.get(0).getSimpleName());
}
{
// contract: the name to be matched does not have to be an exact match
CtClass<?> templateKlass = factory.Class().get(CheckBoundMatcher.class);
CtClass<?> klass = factory.Class().get(CheckBound.class);
CtMethod meth = (CtMethod) templateKlass.getElements(new NamedElementFilter<>(CtMethod.class, "matcher5")).get(0);
// together with the appropriate @Parameter _w_, this means
// we match all methods with name f*, because parameter _w_ acts as a wildcard
meth.setSimpleName("f_w_");
TemplateMatcher matcher = new TemplateMatcher(meth);
List<CtMethod> ctElements = matcher.find(klass);
assertEquals(3, ctElements.size());
assertEquals("foo", ctElements.get(0).getSimpleName());
assertEquals("foo2", ctElements.get(1).getSimpleName());
assertEquals("fbar", ctElements.get(2).getSimpleName());
}
}
Aggregations