Jonathan S. Fisher
Jonathan S. Fisher

Reputation: 8817

Is there a way to check for explicit types on Lambda variables?

Take this Lambda:

final List<String> badKeys = pivMap.entrySet().stream()
 .filter(entry -> StringUtils.trimToNull(entry.getValue()) == null || entry.getValue().equals("{}") || entry.getValue().equals("{ }"))
 .map(Map.Entry::getKey)
 .collect(Collectors.toList());

We want to make sure there's an explicit type on the Lambda variable:

final List<String> badKeys = pivMap.entrySet().stream()
 .filter((final Map.Entry<String, String> entry) -> StringUtils.trimToNull(entry.getValue()) == null || entry.getValue().equals("{}") || entry.getValue().equals("{ }"))
 .map(Map.Entry::getKey)
 .collect(Collectors.toList());

Is there a way to use puppycrawl checkstyle to check there's a type on the lambda expression above? In this case the type declaration on the variable is: (final Map.Entry<String, String> entry)

Upvotes: 3

Views: 214

Answers (1)

Nick Mancuso
Nick Mancuso

Reputation: 191

This can be achieved with MatchXPathCheck:

Configuration:


<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
        "http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">

<module name="Checker">
    <property name="charset" value="UTF-8"/>
    <property name="haltOnException" value="true"/>
    <property name="severity" value="error"/>

    <module name="TreeWalker">
        <module name="MatchXpath">
            <property name="query" value="//LAMBDA[IDENT][1]"/>
            <message key="matchxpath.match"
                     value="Lambda parameters must have type."/>
        </module>
    </module>
</module>

Here we use an XPath expression to check if IDENT is the first child of the lambda, which would mean in this case that it is not typed.

Java Example:


import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;

public class MyClass {

    void badLambda(Map<String, String> pivMap) {
        final List<String> badKeys = pivMap.entrySet().stream()
                .filter(entry -> StringUtils.trimToNull(entry.getValue()) == null // violation
                        || entry.getValue().equals("{}")
                        || entry.getValue().equals("{ }"))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }

    void goodLambda(Map<String, String> pivMap) {
        final List<String> badKeys = pivMap.entrySet().stream()
                .filter((final Map.Entry<String, String> entry) -> StringUtils.trimToNull(entry.getValue()) == null // ok
                        || entry.getValue().equals("{}")
                        || entry.getValue().equals("{ }"))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }
}

Result:


➜  src java -jar checkstyle-8.41-all.jar -c config.xml MyClass.java
Starting audit...
[ERROR] MyClass.java:11:31: Lambda parameters must have type. [MatchXpath]
Audit done.
Checkstyle ends with 1 errors.

Upvotes: 2

Related Questions