From 1c74d72fe4fe63b16f09e9613b7afd2c9510d64c Mon Sep 17 00:00:00 2001
From: Pavel Vojtechovsky
Date: Wed, 11 Jan 2017 20:34:35 +0100
Subject: [PATCH 1/5] remove unused imports
---
src/test/java/spoon/test/template/TemplateTest.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/test/java/spoon/test/template/TemplateTest.java b/src/test/java/spoon/test/template/TemplateTest.java
index b08bbd410f9..a686f96393a 100644
--- a/src/test/java/spoon/test/template/TemplateTest.java
+++ b/src/test/java/spoon/test/template/TemplateTest.java
@@ -19,7 +19,6 @@
import spoon.reflect.visitor.filter.NameFilter;
import spoon.support.compiler.FileSystemFile;
import spoon.support.template.Parameters;
-import spoon.template.Substitution;
import spoon.template.TemplateMatcher;
import spoon.test.template.testclasses.SecurityCheckerTemplate;
@@ -28,7 +27,6 @@
import java.rmi.Remote;
import java.util.ArrayList;
import java.util.Date;
-import java.util.LinkedList;
import java.util.List;
import static org.junit.Assert.assertEquals;
From 5b107d8f32526eea36a29d1973e2aead4b728096 Mon Sep 17 00:00:00 2001
From: Pavel Vojtechovsky
Date: Wed, 11 Jan 2017 20:36:26 +0100
Subject: [PATCH 2/5] TemplateMatcher implemented as Filter
---
.../java/spoon/template/TemplateMatcher.java | 43 +++++++------------
1 file changed, 15 insertions(+), 28 deletions(-)
diff --git a/src/main/java/spoon/template/TemplateMatcher.java b/src/main/java/spoon/template/TemplateMatcher.java
index 59ae1ca216e..83aa37cab8f 100644
--- a/src/main/java/spoon/template/TemplateMatcher.java
+++ b/src/main/java/spoon/template/TemplateMatcher.java
@@ -37,6 +37,7 @@
import spoon.reflect.reference.CtTypeParameterReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.CtScanner;
+import spoon.reflect.visitor.Filter;
import spoon.reflect.visitor.Query;
import spoon.reflect.visitor.filter.InvocationFilter;
import spoon.support.template.DefaultParameterMatcher;
@@ -58,7 +59,7 @@
/**
* This class defines an engine for matching a template to pieces of code.
*/
-public class TemplateMatcher {
+public class TemplateMatcher implements Filter {
private List> getMethods(CtClass extends Template>> root) {
CtExecutableReference> methodRef = root.getFactory().Executable()
@@ -132,6 +133,7 @@ private List> getVarargs(CtClass extends Template>> root
* Constructs a matcher for a given template.
*
*/
+ @SuppressWarnings("unchecked")
public TemplateMatcher(CtElement templateRoot) {
this.templateType = templateRoot.getParent(CtClass.class);
this.templateRoot = templateRoot;
@@ -139,7 +141,10 @@ public TemplateMatcher(CtElement templateRoot) {
typeVariables = getTemplateTypeParameters(templateType);
names = getTemplateNameParameters(templateType);
varArgs = getVarargs(templateType, variables);
- this.templateType = templateType;
+ //check that template matches itself
+ if (helperMatch(this.templateRoot, this.templateRoot) == false) {
+ throw new SpoonException("TemplateMatcher was unable to find itself, it certainly indicates a bug. Please revise your template or report an issue.");
+ }
}
private boolean addMatch(Object template, Object target) {
@@ -177,31 +182,7 @@ private CtElement checkListStatements(List> teList) {
* @return the matched elements
*/
public List find(final CtElement targetRoot) {
- CtScanner scanner = new CtScanner() {
- @Override
- public void scan(CtElement element) {
- if (match(element, templateRoot)) {
- finds.add(element);
- // matches.clear();
- }
- super.scan(element);
- }
- };
-
- scanner.scan(templateRoot);
- if (!finds.contains(templateRoot)) {
- throw new SpoonException("TemplateMatcher was unable to find itself, it certainly indicates a bug. Please revise your template or report an issue.");
- }
- finds.clear();
-
- scanner.scan(targetRoot);
-
- // This case can occur when we are scanning the entire package for example see TemplateTest#testTemplateMatcherWithWholePackage
- if (finds.contains(templateRoot)) {
- finds.remove(templateRoot);
- }
-
- return (List) finds;
+ return (List) targetRoot.filterChildren(this).list();
}
/**
@@ -476,7 +457,13 @@ private boolean isCurrentTemplate(Object object, CtElement inMulti) {
* @return true if matches
* @see #getMatches()
*/
- private boolean match(CtElement targetRoot, CtElement templateRoot) {
+ @Override
+ public boolean matches(CtElement targetRoot) {
+ if (targetRoot == templateRoot) {
+ // This case can occur when we are scanning the entire package for example see TemplateTest#testTemplateMatcherWithWholePackage
+ // Correct template matches itself of course, but client does not want that
+ return false;
+ }
return helperMatch(targetRoot, templateRoot);
}
From 47ecfdf9c539872b400556dc7703f47b91f00177 Mon Sep 17 00:00:00 2001
From: Pavel Vojtechovsky
Date: Wed, 11 Jan 2017 22:17:54 +0100
Subject: [PATCH 3/5] explicitly use TemplateMatcher as Filter of a query
---
src/test/java/spoon/test/template/TemplateTest.java | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/test/java/spoon/test/template/TemplateTest.java b/src/test/java/spoon/test/template/TemplateTest.java
index a686f96393a..a8ba53e4581 100644
--- a/src/test/java/spoon/test/template/TemplateTest.java
+++ b/src/test/java/spoon/test/template/TemplateTest.java
@@ -416,6 +416,7 @@ public void testTemplateMatcherMatchTwoSnippets() throws Exception {
CtIf templateRoot = (CtIf) templateMethod.getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
+ //match using legacy TemplateMatcher#find method
List matches = matcher.find(factory.getModel().getRootPackage());
assertEquals(2, matches.size());
@@ -424,5 +425,15 @@ public void testTemplateMatcherMatchTwoSnippets() throws Exception {
CtElement match2 = matches.get(1);
assertTrue(match1.equals(match2));
+
+ //match using TemplateMatcher#matches method and query filter
+ matches = factory.getModel().getRootPackage().filterChildren(matcher).list();
+
+ assertEquals(2, matches.size());
+
+ match1 = matches.get(0);
+ match2 = matches.get(1);
+
+ assertTrue(match1.equals(match2));
}
}
From f611c7f16f6e65e53908ad4de9cad47f5264666b Mon Sep 17 00:00:00 2001
From: Pavel Vojtechovsky
Date: Thu, 12 Jan 2017 15:31:41 +0100
Subject: [PATCH 4/5] documentation added
---
doc/matcher.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/doc/matcher.md b/doc/matcher.md
index 66c92e27359..a1b64f33eac 100644
--- a/doc/matcher.md
+++ b/doc/matcher.md
@@ -30,7 +30,7 @@ To define a template matcher one must:
1. specify the "holes" of the template matcher
1. write the matcher in a dedicated method
-1. instantiate TemplateMatcher and call method `find`.
+1. instantiate TemplateMatcher and call method `find` or use it as Filter of a query.
Taking again the same example.
@@ -53,9 +53,9 @@ CtClass> templateKlass = factory.Class().get(CheckBoundMatcher.class);
CtIf templateRoot = (CtIf) ((CtMethod) templateKlass.getElements(new NameFilter("matcher1")).get(0)).getBody().getStatement(0);
TemplateMatcher matcher = new TemplateMatcher(templateRoot);
for (CtElement elems : matcher.find(aPackage)) { ... };
-
+//or TemplateMatcher as a Filter of query
+aPackage.filterChildren(matcher).forEach((CtElement elem)->{ ... });
```
For named elements, a wildcard can be specified: if the named element (eg a method) to be matched is called `f` and the template matcher class contains a template parameter called `f` (of type Object), all methods starting by `f` will be matched.
-
From 89ef107cc98cb009d9442cb7f739122c429d6ae3 Mon Sep 17 00:00:00 2001
From: Pavel Vojtechovsky
Date: Thu, 12 Jan 2017 15:43:18 +0100
Subject: [PATCH 5/5] fix the type cast
---
src/main/java/spoon/template/TemplateMatcher.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/spoon/template/TemplateMatcher.java b/src/main/java/spoon/template/TemplateMatcher.java
index 83aa37cab8f..8445c46b6a5 100644
--- a/src/main/java/spoon/template/TemplateMatcher.java
+++ b/src/main/java/spoon/template/TemplateMatcher.java
@@ -182,7 +182,7 @@ private CtElement checkListStatements(List> teList) {
* @return the matched elements
*/
public List find(final CtElement targetRoot) {
- return (List) targetRoot.filterChildren(this).list();
+ return targetRoot.filterChildren(this).list();
}
/**