0

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.

Christian Semrau
  • 8,913
  • 2
  • 32
  • 39

1 Answers1

1

You can use a search template like this:

new SimpleListSubstitution<$Type$>() {
    @Override
    protected Iterable<$Type$> getItems() {
        return $EXPRESSION$;
    }
    $ReturnType$ $Method$($ParameterType$ $Parameter$);
}

With the following variable settings:
Method min: 0, max: 0
Parameter min: 0, max: unlimited

Note that this pattern tries to match additional methods, but because Method is set to 0 occurrences, the match will fail if a method is found. This way only the classes which do not define additional methods will end up in the search results.

Bas Leijdekkers
  • 23,709
  • 4
  • 70
  • 68
  • Yes! This works. One must take care to actually set all the variable settings (missed the Parameter count at first, which did suppress only some of the matches). Thank you! – Christian Semrau Jun 19 '17 at 19:28