001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2020 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.checks.naming; 021 022import com.puppycrawl.tools.checkstyle.api.DetailAST; 023import com.puppycrawl.tools.checkstyle.api.TokenTypes; 024 025/** 026 * <p> 027 * Checks lambda parameter names. 028 * </p> 029 * <ul> 030 * <li> 031 * Property {@code format} - Specifies valid identifiers. 032 * Type is {@code java.util.regex.Pattern}. 033 * Default value is {@code "^[a-z][a-zA-Z0-9]*$"}. 034 * </li> 035 * </ul> 036 * <p> 037 * An example of how to configure the check is: 038 * </p> 039 * <pre> 040 * <module name="LambdaParameterName"/> 041 * </pre> 042 * <p>Code Example:</p> 043 * <pre> 044 * Function<String, String> function1 = s -> s.toLowerCase(); // OK 045 * Function<String, String> function2 = S -> S.toLowerCase(); // violation, name 'S' 046 * // must match pattern '^[a-z][a-zA-Z0-9]*$' 047 * </pre> 048 * <p> 049 * An example of how to configure the check for names that begin 050 * with a lower case letter, followed by letters is: 051 * </p> 052 * <pre> 053 * <module name="LambdaParameterName"> 054 * <property name="format" value="^[a-z]([a-zA-Z]+)*$"/> 055 * </module> 056 * </pre> 057 * <p> 058 * Code Example: 059 * </p> 060 * <pre> 061 * class MyClass { 062 * Function<String, String> function1 = str -> str.toUpperCase().trim(); // OK 063 * Function<String, String> function2 = _s -> _s.trim(); // violation, name '_s' 064 * // must match pattern '^[a-z]([a-zA-Z]+)*$' 065 * 066 * public boolean myMethod(String sentence) { 067 * return Stream.of(sentence.split(" ")) 068 * .map(word -> word.trim()) // OK 069 * .anyMatch(Word -> "in".equals(Word)); // violation, name 'Word' 070 * // must match pattern '^[a-z]([a-zA-Z]+)*$' 071 * } 072 * } 073 * 074 * </pre> 075 * <p> 076 * Parent is {@code com.puppycrawl.tools.checkstyle.TreeWalker} 077 * </p> 078 * <p> 079 * Violation Message Keys: 080 * </p> 081 * <ul> 082 * <li> 083 * {@code name.invalidPattern} 084 * </li> 085 * </ul> 086 * 087 * @since 8.11 088 */ 089public class LambdaParameterNameCheck extends AbstractNameCheck { 090 091 /** Creates new instance of {@code LambdaParameterNameCheck}. */ 092 public LambdaParameterNameCheck() { 093 super("^[a-z][a-zA-Z0-9]*$"); 094 } 095 096 @Override 097 public int[] getDefaultTokens() { 098 return getRequiredTokens(); 099 } 100 101 @Override 102 public int[] getAcceptableTokens() { 103 return getRequiredTokens(); 104 } 105 106 @Override 107 public int[] getRequiredTokens() { 108 return new int[] { 109 TokenTypes.LAMBDA, 110 }; 111 } 112 113 @Override 114 public void visitToken(DetailAST ast) { 115 final DetailAST parametersNode = ast.findFirstToken(TokenTypes.PARAMETERS); 116 if (parametersNode == null) { 117 super.visitToken(ast); 118 } 119 else { 120 for (DetailAST parameterDef = parametersNode.getFirstChild(); 121 parameterDef != null; 122 parameterDef = parameterDef.getNextSibling()) { 123 if (parameterDef.getType() == TokenTypes.PARAMETER_DEF) { 124 super.visitToken(parameterDef); 125 } 126 } 127 } 128 } 129 130 @Override 131 protected boolean mustCheckName(DetailAST ast) { 132 return true; 133 } 134 135}