Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to match an assignment using TemplateMatcher #1989

Closed
EdgarACarneiro opened this issue May 11, 2018 · 6 comments
Closed

How to match an assignment using TemplateMatcher #1989

EdgarACarneiro opened this issue May 11, 2018 · 6 comments
Labels

Comments

@EdgarACarneiro
Copy link

Hey there!

I have a doubt regarding the usage of the TemplateMatcher that I can not seem to get clarified.
I am trying to use the TemplateMatcher to match code with some patterns. However, in the definition of the patterns, I am not being able to write assignments ( for example a pattern were inside an if clause there's an assignment to an existing variable ).

I have tried different approaches, such as

public TemplateParameter<CtVariableAccess> _var_x_
....
if (true)
			_var_x_.S() = 1;
			//_var_x_ = 1;

but I can not get it to work.. The code calling the matching is written similarly to the code present in spoon/src/test/java/spoon/test/template/TemplateTest.java

{// 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())) ;
}

Any help would be much appreciated!

@pvojtechovsky
Copy link
Collaborator

Hi Edgar!

try something like this:

@Parameter
int _var_x_;
...
  if (true)
    _var_x_ = 1;

@EdgarACarneiro
Copy link
Author

Hey @pvojtechovsky !
I tried that approach and although the code compiled, I do not seem to be able to get a match...

My pattern is something like:

@Parameter
int _var_x_;

public void possibleTernaryOperator() {
    if (true) {
        _var_x_ = 500;
    } else {
       _var_x_ = 1000;
    }
}

In the code, the comparison being made is:

comparing: if (true) {
    x = 500;
}else {
    x = 1000;
}
 with pattern: if (true) {
    _var_x_ = 500;
}else {
    _var_x_ = 1000;

A match should be expected, however, it does not happen...

In the code, we are first compiling the pattern files using:

Launcher launcher = new Launcher();
launcher.addInputResource(targetDefinitions); //Analyze the patterns file
launcher.buildModel();

And only when creating a template matcher with the snippet available inside the method (for example: possibleTernaryOperator()), as in:

TemplateMatcher matcher = new TemplateMatcher(patternElement);

where patterElement is the body of the method.

Is that the problem? The fact that the lines containing the @parameter int var_x aren't being passed to the template matcher? I assumed it wouldn't since the model is being correctly created, and therefore there should be references to it...

Thank you for your time and help!

@pvojtechovsky
Copy link
Collaborator

Hi Edgar,

you are probably the second (after me) who tries to use Spoon TemplateMatcher. Note that current TemplateMatcher code is not ideal and is not proved by real clients. I personally like the idea of template matching a lot. During experimenting with it I found some conceptual problems in current implementation. So I implemented completely new template matching engine in PR #1686 ... but it will need some time (month(s)) until it gets merged into standard.

So what next?
A) wait until PR #1686 is merged
B) checkout PR #1686 https://github.com/pvojtechovsky/spoon/tree/feaPattern and try it
C) debug legacy TemplateMatcher code and try to convince it to work in your case. May be it is possible. Hard to say.... I am sorry, but I do not want to spent my time by fixing old Template matcher, which will be removed soon anyway.

where patterElement is the body of the method

One idea ... try the CtIf statement as a pattern element, otherwise template matcher will search for CtBody which contains one statement CtIf.

@monperrus
Copy link
Collaborator

monperrus commented May 13, 2018 via email

@EdgarACarneiro
Copy link
Author

EdgarACarneiro commented May 19, 2018

@pvojtechovsky , so, I followed your advice and decided to try your PR (#1686).
After looking a little bit around, your PR seems to be exactly what I need!

I just have a small question regarding it.
Right now, in our project, we had preprocessed the Patterns file and so, when it comes to checking if the pattern matches, what we have is: a CtElement representing my pattern and a CtElement of the same class (class extending CtElement) representing my possible match (let's call it rootNode).

Exemplifying:
My patternElement is the CtElement corresponding to:

if (_var_x_ == null)
    return ;

and rootNode to:

if (test == null)
    return ;

In the test, you often used the file itself, and then got the bodies of the methods for defining the patterns, such as:

Pattern pattern = PatternBuilder.create(new PatternBuilderHelper(type).setBodyOfMethod("matcher1") ...

My question is: Is there a way to do it with my PatternElement? Something like (this as it is, does not seem to work):

Pattern pattern = PatternBuilder.create(patternElement).build();

So that after I could do my matching with:

if (pattern.getMatches(rootNode).size() == 1)
    System.out.println("I got a match!!");

Thank you for your time and patience!

@pvojtechovsky
Copy link
Collaborator

Hi Edgar,

Pattern pattern = PatternBuilder.create(patternElement).build();

that should work, you just have to specify what are your pattern parameters. E.g.

Pattern pattern = PatternBuilder.create(patternElement)
  .configureParameters(pb->pb.parameter("_var_x_").byVariable("_var_x_"))
  .build();

There is some new documentation in this PR. See /spoon-core/doc/pattern.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants