Skip to content

Commit

Permalink
fix: template matching ignores casts (#3028)
Browse files Browse the repository at this point in the history
  • Loading branch information
Egor18 authored Feb 19, 2020
1 parent 23edd38 commit ed39577
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 1 deletion.
2 changes: 2 additions & 0 deletions doc/matcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,5 @@ 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.

Note, the matching process ignores some information in the AST nodes: comments; position; implicitness and casts. See `roleToSkippedClass` in class [ElementNode](https://github.com/INRIA/spoon/blob/master/src/main/java/spoon/pattern/internal/node/ElementNode.java)

8 changes: 8 additions & 0 deletions doc/pattern.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ if (something) {
}
```

* casts are skipped. For example:

```java
f(x);
//matches with
(Object) f(x);
```

The main classes of Spoon patterns are those in package `spoon.pattern`:

* classes: PatternBuilder, Pattern, Match, PatternBuilderHelper, PatternParameterConfigurator, InlinedStatementConfigurator
Expand Down
1 change: 1 addition & 0 deletions src/main/java/spoon/pattern/internal/node/ElementNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ protected ImmutableMap matchesRole(ImmutableMap parameters, CtElement target, Me
roleToSkippedClass.put(CtRole.COMMENT, new Class[]{Object.class});
roleToSkippedClass.put(CtRole.POSITION, new Class[]{Object.class});
roleToSkippedClass.put(CtRole.IS_IMPLICIT, new Class[]{Object.class});
roleToSkippedClass.put(CtRole.CAST, new Class[]{Object.class});
roleToSkippedClass.put(CtRole.TYPE, new Class[]{CtExecutableReference.class});
roleToSkippedClass.put(CtRole.DECLARING_TYPE, new Class[]{CtExecutableReference.class});
}
Expand Down
24 changes: 23 additions & 1 deletion src/test/java/spoon/test/template/TemplateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
import spoon.test.template.testclasses.ArrayAccessTemplate;
import spoon.test.template.testclasses.FieldAccessOfInnerClassTemplate;
import spoon.test.template.testclasses.FieldAccessTemplate;
import spoon.test.template.testclasses.Flow;
import spoon.test.template.testclasses.FlowMatcher;
import spoon.test.template.testclasses.InnerClassTemplate;
import spoon.test.template.testclasses.InvocationTemplate;
import spoon.test.template.testclasses.NtonCodeTemplate;
Expand Down Expand Up @@ -1175,5 +1177,25 @@ public void substituteTypeAccessReference() {
assertEquals("o = o instanceof spoon.test.template.TypeReferenceClassAccess.Example<?>", method.getBody().getStatement(4).toString());
assertEquals("java.util.function.Supplier<java.lang.Long> p = spoon.test.template.TypeReferenceClassAccess.Example::currentTimeMillis", method.getBody().getStatement(5).toString());
}


@Test
public void testMethodCast() throws Exception {
//contract: matcher should match methods with cast too
//https://github.com/INRIA/spoon/issues/3026
Launcher spoon = new Launcher();
Factory factory = spoon.getFactory();
spoon.createCompiler(
factory,
SpoonResourceHelper.resources("./src/test/java/spoon/test/template/testclasses/Flow.java"),
SpoonResourceHelper.resources("./src/test/java/spoon/test/template/testclasses/FlowMatcher.java"))
.build();

CtClass<?> templateKlass = factory.Class().get(FlowMatcher.class);
CtClass<?> klass = factory.Class().get(Flow.class);

CtMethod<?> method = (CtMethod<?>) templateKlass.getElements(new NamedElementFilter(CtMethod.class, "subFlowMatcher")).get(0);
CtElement templateRoot = method.getBody().getStatement(0);
TemplateMatcher myMatcher = new TemplateMatcher(templateRoot);
assertEquals(2, myMatcher.find(klass).size());
}
}
14 changes: 14 additions & 0 deletions src/test/java/spoon/test/template/testclasses/Flow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package spoon.test.template.testclasses;

public class Flow {

public Flow subFlow(Object o) {
System.out.println(o);
return (Flow) o;
}

public void f1() {
Flow s1 = subFlow(new Flow());
Flow s2 = (Flow) subFlow(new Flow());
}
}
12 changes: 12 additions & 0 deletions src/test/java/spoon/test/template/testclasses/FlowMatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package spoon.test.template.testclasses;

import spoon.template.TemplateParameter;

public class FlowMatcher extends Flow {

public TemplateParameter<Flow> _subFlow_;

private void subFlowMatcher() {
subFlow(_subFlow_.S());
}
}

0 comments on commit ed39577

Please sign in to comment.