Skip to content

Commit

Permalink
Issue #643: New SingleMethodTypeParameter check implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
yaziza committed Apr 13, 2020
1 parent bd5ca6b commit 9672a0b
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ IllegalCatchExtendedCheck.illegalClassNames = Illegal class names
LogicConditionNeedOptimizationCheck.name = Logic condition need optimization
LogicConditionNeedOptimizationCheck.desc = This check prevents the placement of local variables and fields after calling methods in '&&' and '||' conditions.
MapIterationInForEachLoopCheck.name = Map Iteration In For Each Loop
MapIterationInForEachLoopCheck.name = Map Iteration In For Each Loop
MapIterationInForEachLoopCheck.desc = This check can help you to write the whole for-each map iteration more correctly:<ol><li> If you iterate over a map using map.keySet() or map.entrySet(), but your code uses only map values, Check will propose you to use map.values() instead of map.keySet() or map.entrySet(). Replacing map.keySet() or map.entrySet() with map.values() for such cases can a bit improve an iteration performance. <p>Bad:</p><pre>for (Map.Entry<String, String>; entry : map.entrySet()){<br/> System.out.println(entry.getValue());<br/>}</pre><pre>for (String key : map.keySet(){<br/> System.out.println(map.get(key));<br/>}</pre><p>Good:</p><pre>for (String value : map.values()){<br/> System.out.println(value);<br/>}</pre> </li><li>If you iterate over a map using map.entrySet(), but never call entry.getValue(), Check will propose you to use map.keySet() instead of map.entrySet(). to iterate over map keys only. <p>Bad:</p><pre>for (Map.Entry<String, String> entry : map.entrySet()){<br/> System.out.println(entry.getKey());<br/>}</pre><p>Good:</p><pre>for (String key : map.keySet()){<br/> System.out.println(key);<br/>}</pre></li><li>If you iterate over a map with map.keySet() and use both keys and values, check will propose you to use map.entrySet() to improve an iteration performance by avoiding search operations inside a map. For this case, iteration can significantly grow up a performance. <p>Bad:</p><pre>for (String key : map.keySet()){<br/> System.out.println(key + " " + map.get(key));<br/>}</pre><p>Good:</p><pre>for (Map.Entry<String, String> entry : map.entrySet()){<br/> System.out.println(entry.getValue() + " " + entry.getKey());<br/>}</pre></li></ol>
MapIterationInForEachLoopCheck.supportedMapImplQualifiedNames = Enter your own Map implementations.
MapIterationInForEachLoopCheck.proposeValuesUsage = If this checkbox is checked, Check will propose to replace wrong usage to value().
Expand All @@ -92,7 +92,7 @@ MapIterationInForEachLoopCheck.proposeEntrySetUsage = If this checkbox is checke
MultipleVariableDeclarationsExtendedCheck.name = Multiple Variable Declarations Extended
MultipleVariableDeclarationsExtendedCheck.desc = Warn when declaring several variables in one line
MultipleVariableDeclarationsExtendedCheck.ignoreCycles = Turning on this option makes check not to warn on multiple variable definitions inside cycles.
MultipleVariableDeclarationsExtendedCheck.ignoreCycles = Turning on this option makes check not to warn on multiple variable definitions inside cycles.
MultipleVariableDeclarationsExtendedCheck.ignoreMethods = Turning on this option makes check not to warn on multiple variable definitions inside methods.
MultipleStringLiteralsExtendedCheck.allowedDuplicates = The maximum number of occurences to allow without generating a warning
Expand All @@ -106,7 +106,7 @@ TernaryPerExpressionCountCheck.name = Ternary Per Expression Count
TernaryPerExpressionCountCheck.desc = Restricts the number of ternary operators in expression to a specific limit.<br><br><b>Rationale:</b> This Check helps to improve code readability by pointing developer on<br>expressions which contain more than user-defined count of ternary operators.<br><br>It points to complicated ternary <a href="http://docs.oracle.com/javase/tutorial/java/nutsandbolts/expressions.html">expressions</a>. Reason:<br>- Complicated ternary expressions are not easy to read.<br>- Complicated ternary expressions could lead to ambiguous result if user<br>does not know Java's operators priority well, e.g.:<br><p><code>String str = null;<br>String x = str != null ? "A" : "B" + str == null ? "C" : "D";<br>System.out.println(x);</code></p>Output for code above is "D", but more obvious would be "BC".<br></p>Check has following properties:<br><ul><li><b>maxTernaryPerExpressionCount</b> - limit of ternary operators per expression<br></li><li><b>ignoreTernaryOperatorsInBraces</b> - if true Check will ignore ternary operators<br>in braces (braces explicitly set priority level)<br></li><li><b>ignoreIsolatedTernaryOnLine</b> - if true Check will ignore one line ternary operators,<br>if only it is places in line alone.<br> </li></ul>Options <b>ignoreTernaryOperatorsInBraces</b> and <b>ignoreIsolatedTernaryOnLine</b> can<br>make Check less strict, e.g.:<br>Using <b>ignoreTernaryOperatorsInBraces</b> option (value = <b>true</b>)<br>does not put violation on code below:<br><p><code><pre>callString = "{? = call " +<br> (StringUtils.hasLength(catalogNameToUse) ? catalogNameToUse + "." : "") +<br> (StringUtils.hasLength(schemaNameToUse) ? schemaNameToUse + "." : "") +<br> procedureNameToUse + "(";<br></pre></code></p>When using <b>ignoreIsolatedTernaryOnLine</b> (value = <b>true</b>), even without<br><b>ignoreTernaryOperatorsInBraces</b> option Check won't warn on code below:<br> <p><code><pre>int a = (d == 5) ? d : f<br> +<br> ((d == 6) ? g : k);</pre></code></p>@author <a href="mailto:[email protected]">Aleksey Nesterenko</a>
TernaryPerExpressionCountCheck.maxTernaryPerExpressionCount = Maximum number of ternary operators in expression
TernaryPerExpressionCountCheck.ignoreTernaryOperatorsInBraces = Ignore ternary operators in expression in case if priority level is set explicitly
TernaryPerExpressionCountCheck.ignoreIsolatedTernaryOnLine = Ignore ternary operators in expression in case if ternary operator is isolated in line
TernaryPerExpressionCountCheck.ignoreIsolatedTernaryOnLine = Ignore ternary operators in expression in case if ternary operator is isolated in line

NameConventionForJunit4TestClassesCheck.name = Name Convention For JUnit4 Test Classes Check
NameConventionForJunit4TestClassesCheck.desc = <p>This check verifies the name of JUnit4 test class for compliance with user defined naming convention(by default Check expects test classes names matching ".+Test\\d*|.+Tests\\d*|Test.+|Tests.+|.+IT|.+ITs|.+TestCase\\d*|.+TestCases\\d*" regex). </p> <p> Class is considered to be a test if its definition or one of its method definitions annotated with user defined annotations. By default Check looks for classes which contain methods annotated with "Test" or "org.junit.Test". </p> <p> Check has following options: </p> <p> "expectedClassNameRegex" - regular expression which matches expected test class names. If test class name does not matches this regex then Check will log violation. This option defaults to ".+Test\\d*|.+Tests\\d*|Test.+|Tests.+|.+IT|.+ITs|.+TestCase\\d*|.+TestCases\\d*". </p> <p> "classAnnotationNameRegex" - regular expression which matches test annotation names on classes. If class annotated with matching annotation, it is considered to be a test. This option defaults to empty regex(one that matches nothing). If for example this option set to "RunWith", then class "SomeClass" is considered to be a test: <pre> <code>@RunWith(Parameterized.class)<br> class SomeClass<br> {<br> }<br> </code> </pre> </p> <p>"methodAnnotationNameRegex" - regular expression which matches test annotation names on methods. If class contains a method annotated with matching annotation, it is considered to be a test. This option defaults to "Test|org.junit.Test". For example, if this option set to "Test", then class SomeClass" is considered to be a test. <pre> <code> class SomeClass<br> {<br> @Test<br> void method() {<br> <br> }<br> }<br></code></pre></p><p>Annotation names must be specified exactly the same way it specified in code, thus if Check must match annotation with fully qualified name, corresponding options must contain qualified annotation name and vice versa. For example, if annotation regex is "org.junit.Test" Check will recognize "@org.junit.Test" annotation and will skip "@Test" annotation and vice versa if annotation regex is "Test" Check will recognize "@Test" annotation and skip "@org.junit.Test" annotation. </p>@author <a href="mailto:[email protected]">Zuy Alexey</a>
Expand Down Expand Up @@ -142,7 +142,7 @@ ReturnCountExtendedCheck.name=Return Count Extended
ReturnCountExtendedCheck.desc=Checks that method/ctor "return" literal count is not greater than the given value ("maxReturnCount" property).<br><br>Rationale:<br><br>One return per method is a good practice as its ease understanding of method logic.<br><br>Reasoning is that:<dl><li>It is easier to understand control flow when you know exactly where the method returns.<li>Methods with 2-3 or many "return" statements are much more difficult to understand, debug and refactor.</dl>Setting up the check options will make it to ignore:<ol><li>Methods by name ("ignoreMethodsNames" property). Note, that the "ignoreMethodsNames" property type is NOT regexp: using this property you can list the names of ignored methods separated by comma.</li><li>Methods which linelength less than given value ("linesLimit" property).<li>"return" statements which depth is greater or equal to the given value ("returnDepthLimit" property). There are few supported<br>coding blocks when depth counting: "if-else", "for", "while"/"do-while" and "switch".<li>"Empty" return statements = return statements in void methods and ctors that have not any expression ("ignoreEmptyReturns" property).<li>Return statements, which are located in the top lines of method/ctor (you can specify the count of top method/ctor lines that will be ignored using "rowsToIgnoreCount" property).</ol>So, this is much improved version of the existing <i>Return Count</i> check.<br><br>
ReturnCountExtendedCheck.maxReturnCount=maximum allowed number of return statements per method/ctor (1 by default).
ReturnCountExtendedCheck.ignoreMethodLinesCount=Option to ignore methods/ctors which body has the linelength is less than given (20 lines by default). Set "0" to switch this option off and check all methods/ctors.
ReturnCountExtendedCheck.minIgnoreReturnDepth=Option to ignore methods/ctors that have return statement(s) with depth value is less than N levels(scopes). 4 by default. 0 is the min depth. Depth is 0 when the "return" statement is not wrapped on one of the supported coding blocks.
ReturnCountExtendedCheck.minIgnoreReturnDepth=Option to ignore methods/ctors that have return statement(s) with depth value is less than N levels(scopes). 4 by default. 0 is the min depth. Depth is 0 when the "return" statement is not wrapped on one of the supported coding blocks.
ReturnCountExtendedCheck.ignoreEmptyReturns=Option to ignore "empty" (with no any expression) return statements in void methods and ctors. 'False' by default.
ReturnCountExtendedCheck.topLinesToIgnoreCount=Option to set the count of code lines that will be ignored in top of all methods.
ReturnCountExtendedCheck.ignoreMethodsNames=Option to set the RegExp patterns for methods' names which would be ignored by check.
Expand All @@ -161,6 +161,9 @@ SimpleAccessorNameNotationCheck.prefix=prefix of field's name
SingleBreakOrContinueCheck.name = Single break or continue inside a loop
SingleBreakOrContinueCheck.desc = <p>This check restricts the number of break and continue statements inside cycle body (only one is allowed).</p><p>Restricting the number of break and continue statements in a loop is done in the interest of good structured programming.</p>
SingleMethodTypeParameterCheck.name = Single type parameter method check
SingleMethodTypeParameterCheck.desc = <p>This check restricts the use of type parameters. If a type parameter appears only once in a method declaration, it should be replaced with a wildcard.</p>
UnnecessaryParenthesesExtendedCheck.desc = Checks for the use of unnecessary parentheses.
UnnecessaryParenthesesExtendedCheck.name = Unnecessary Parentheses Extended
UnnecessaryParenthesesExtendedCheck.ignoreCalculationOfBooleanVariables = Cancel validation setups of unnecessary parentheses in Boolean computations.
Expand All @@ -178,7 +181,7 @@ UselessSuperCtorCallCheck.allowCallToNoArgsSuperCtorIfMultiplePublicCtor = Allow
EitherLogOrThrowCheck.desc = <p>Either log the exception, or throw it, but never do both. Logging and throwing results in multiple log messages for a single problem in the code, and makes problems for the support engineer who is trying to dig through the logs. This is one of the most annoying error-handling antipatterns. All of these examples are equally wrong.</p><p><b>Examples:</b><pre>catch (NoSuchMethodException e) {\t\nLOG.error("Message", e);\t\nthrow e;\n}</pre><b>or</b><pre>catch (NoSuchMethodException e) {\t\nLOG.error("Message", e);\t\nthrow new MyServiceException("AnotherMessage", e);\n}</pre><b>or</b><pre>catch (NoSuchMethodException e) {\t\ne.printStackTrace();\t\nthrow new MyServiceException("Message", e);\n}</pre></p><p><b>What check can detect:</b> <br><b>Loggers</b><ul><li>logger is declared as class field</li><li>logger is declared as method's local variable</li><li>logger is declared as local variable in <code>catch</code> block</li><li>logger is passed through method's parameters</li></ul><b>Exceptions</b><ul><li>logger logs <code>catch</code> parameter exception or it's message</li><li>throw <code>catch</code> parameter exception</li><li>throw another exception which is based on <code>catch</code> parameter exception</li><li>printStackTrace was called on <code>catch</code> parameter exception</li></ul></p><b>What check can not detect:</b> <br><ul><li>loggers that is used like method's return value. Example:<pre>getLogger().error(&quot;message&quot;, e)</pre></li> <li>loggers that is used like static fields from another classes:<pre>MyAnotherClass.LOGGER.error("message", e);<pre></li></ul></p><p>Default parameters are:<ul><li><b>loggerFullyQualifiedClassName</b> - fully qualified class name of logger type. Default value is <i>"org.slf4j.Logger"</i>.</li><li><b>loggingMethodNames</b> - comma separated names of logging methods. Default value is <i>"error, warn, info, debug"</i>.</li></ul></p><p>Note that check works with only one logger type. If you have multiple different loggers, then create another instance of this check.</p>
EitherLogOrThrowCheck.name = Either log exception or throw exception.
EitherLogOrThrowCheck.loggerFullyQualifiedClassName = Logger fully qualified class name. Example: "org.slf4j.Logger".
EitherLogOrThrowCheck.loggingMethodNames = Logging method names separated with commas. Example: "error,warn".
EitherLogOrThrowCheck.loggingMethodNames = Logging method names separated with commas. Example: "error,warn".
WhitespaceBeforeArrayInitializerCheck.name = Whitespace Before Array Initializer
WhitespaceBeforeArrayInitializerCheck.desc = This checks enforces whitespace before array initializer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,13 @@
<message-key key="single.break.or.continue.in.loops"/>
</rule-metadata>

<rule-metadata name="%SingleMethodTypeParameterCheck.name" internal-name="SingleMethodTypeParameterCheck" parent="TreeWalker">
<alternative-name internal-name="com.github.sevntu.checkstyle.checks.coding.SingleMethodTypeParameterCheck"/>
<description>%SingleMethodTypeParameterCheck.desc</description>

<message-key key="single.method.type.parameter"/>
</rule-metadata>

<rule-metadata name="%WhitespaceBeforeArrayInitializerCheck.name" internal-name="WhitespaceBeforeArrayInitializerCheck" parent="TreeWalker">
<alternative-name internal-name="com.github.sevntu.checkstyle.checks.coding.WhitespaceBeforeArrayInitializerCheck"/>
<description>%WhitespaceBeforeArrayInitializerCheck.desc</description>
Expand Down
1 change: 1 addition & 0 deletions sevntu-checks/sevntu-checks.xml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
<property name="allowReturnInEmptyMethodsAndConstructors" value="false"/>
</module>
<module name="com.github.sevntu.checkstyle.checks.coding.SingleBreakOrContinueCheck"/>
<module name="com.github.sevntu.checkstyle.checks.coding.SingleMethodTypeParameterCheck"/>
<module name="com.github.sevntu.checkstyle.checks.coding.NumericLiteralNeedsUnderscoreCheck">
<property name="minDecimalSymbolLength" value="7"/>
<property name="maxDecimalSymbolsUntilUnderscore" value="3"/>
Expand Down
Loading

0 comments on commit 9672a0b

Please sign in to comment.