In our codebase, I am looking for anonymous subclasses of a given class which implement one specific method and have no other methods or fields. These can be converted into a lambda expression and remove the need for that anonymous subclass.
The search template I came up with looks like this:
new SimpleListSubstitution<$Type$>() {
@Modifier Iterable<$Type$> getItems() {
return $EXPRESSION$;
}
}
The replacement template is this:
SimpleListSubstitution.forItems(() -> $EXPRESSION$)
Now this expression finds all the instances I want to refactor, but additionally it finds subclasses that also implement other methods (helper methods or overridden from the superclass).
As an example, I want it to find the subclass in this code:
template.put("pathToRoot", new SimpleListSubstitution<Page>() {
@Override
protected Iterable<Page> getItems() {
return listOfPagesToRoot;
}
});
This will be converted into the following:
template.put("pathToRoot", SimpleListSubstitution.forItems(() -> listOfPagesToRoot));
But I do want it to NOT find the subclass in this code due to the additional putAdditionalSubstitutions
method:
template.put("children", new SimpleListSubstitution<Page>() {
@Override
protected Iterable<Page> getItems() {
return getChildren(page, booleanFeatureName);
}
@Override
protected void putAdditionalSubstitutions(Template template) {
template.put("link", /*...*/);
}
});
Is there a way to express "no other methods" in the search/replace dialog?
Currently I only see the approach of checking each hit in the Find view and removing the unwanted hits and replacing the rest. As we will need to apply this and similar refactorings a few times (e.g. to handle new code written concurrently), this becomes quite laborous.