Skip to content

JavaTemplate can fail when operating on an AST element not contained within elements accessible via Cursor #1828

@sambsnyd

Description

@sambsnyd

There is a really subtle problem with how Visitor, Cursor, and JavaTemplate interact that potentially affects many recipes.

In circumstances like these templating can fail:

  1. Visitor calls super.visitX() (or otherwise modifies an AST, but this is common)
  2. The AST element returned by super.visitX() is different than AST element passed into super.visitX()
  3. JavaTemplate is used on the new AST element returned by super.visitX()
  4. During templating, BlockStatementTemplateGenerator.template() makes a comparison of prior to the AST element returned from the call to super.visitX()

BlockStatementTemplateGenerator uses the Cursor to look up the AST elements surrounding the element you're templating. So that it can generate a valid Java snippet with all of the appropriate variables in scope.
So say you called super.visitNewClass() on an instantiation passed as an argument to a method. We operate on immutable data structures, so the method invocation containing that is unchanged.
BlockStatementTemplateGenerator will use the Cursor to look up the old J.MethodInvocation that does not have the updated argument from the call to super.visitNewClass().
BlockStatementTemplateGenerater.template() knows that the thing its templating is some part of a J.MethodInvocation, and tries to figure out which part so it can construct an appropriate snippet to contain it. But because it is comparing the old J.MethodInvocation's arguments with an element not contained in that argument list, the comparison fails and a correct snippet is not generated.
So this is most likely to be an issue with recipes that use JavaTemplate on AST elements that can contain elements of the same type. i.e.: Recipes which modify MethodDeclaration, MethodInvocation, NewClass, ClassDeclaration, Body, Lambda, etc.

First noticed this

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions