[java] merge UnnecessaryFinalModifier into UnnecessaryModifier
- I take the chance to also flag final resources in try-with-resources - This resolves #411 - This resolves #676 - The rule is now using the rulechain
This commit is contained in:
@ -76,6 +76,7 @@ public class RuleSetFactoryCompatibility {
|
|||||||
addFilterRuleMoved("java", "typeresolution", "imports", "UnusedImports");
|
addFilterRuleMoved("java", "typeresolution", "imports", "UnusedImports");
|
||||||
addFilterRuleMoved("java", "typeresolution", "strictexception", "SignatureDeclareThrowsException");
|
addFilterRuleMoved("java", "typeresolution", "strictexception", "SignatureDeclareThrowsException");
|
||||||
addFilterRuleRenamed("java", "naming", "MisleadingVariableName", "MIsLeadingVariableName");
|
addFilterRuleRenamed("java", "naming", "MisleadingVariableName", "MIsLeadingVariableName");
|
||||||
|
addFilterRuleRenamed("java", "unnecessary", "UnnecessaryFinalModifier", "UnnecessaryModifier");
|
||||||
}
|
}
|
||||||
|
|
||||||
void addFilterRuleRenamed(String language, String ruleset, String oldName, String newName) {
|
void addFilterRuleRenamed(String language, String ruleset, String oldName, String newName) {
|
||||||
|
@ -5,16 +5,31 @@
|
|||||||
package net.sourceforge.pmd.lang.java.rule.codestyle;
|
package net.sourceforge.pmd.lang.java.rule.codestyle;
|
||||||
|
|
||||||
import net.sourceforge.pmd.lang.ast.Node;
|
import net.sourceforge.pmd.lang.ast.Node;
|
||||||
|
import net.sourceforge.pmd.lang.java.ast.ASTAllocationExpression;
|
||||||
|
import net.sourceforge.pmd.lang.java.ast.ASTAnnotation;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationMethodDeclaration;
|
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationMethodDeclaration;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
|
import net.sourceforge.pmd.lang.java.ast.ASTAnnotationTypeDeclaration;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
|
||||||
|
import net.sourceforge.pmd.lang.java.ast.ASTEnumConstant;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
|
import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||||
|
import net.sourceforge.pmd.lang.java.ast.ASTMarkerAnnotation;
|
||||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||||
|
import net.sourceforge.pmd.lang.java.ast.ASTResource;
|
||||||
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
|
||||||
|
|
||||||
public class UnnecessaryModifierRule extends AbstractJavaRule {
|
public class UnnecessaryModifierRule extends AbstractJavaRule {
|
||||||
|
|
||||||
|
public UnnecessaryModifierRule() {
|
||||||
|
addRuleChainVisit(ASTEnumDeclaration.class);
|
||||||
|
addRuleChainVisit(ASTAnnotationTypeDeclaration.class);
|
||||||
|
addRuleChainVisit(ASTClassOrInterfaceDeclaration.class);
|
||||||
|
addRuleChainVisit(ASTMethodDeclaration.class);
|
||||||
|
addRuleChainVisit(ASTResource.class);
|
||||||
|
addRuleChainVisit(ASTFieldDeclaration.class);
|
||||||
|
addRuleChainVisit(ASTAnnotationMethodDeclaration.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visit(ASTEnumDeclaration node, Object data) {
|
public Object visit(ASTEnumDeclaration node, Object data) {
|
||||||
if (node.isStatic()) {
|
if (node.isStatic()) {
|
||||||
@ -22,7 +37,7 @@ public class UnnecessaryModifierRule extends AbstractJavaRule {
|
|||||||
addViolation(data, node, getMessage());
|
addViolation(data, node, getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.visit(node, data);
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visit(ASTAnnotationTypeDeclaration node, Object data) {
|
public Object visit(ASTAnnotationTypeDeclaration node, Object data) {
|
||||||
@ -32,7 +47,7 @@ public class UnnecessaryModifierRule extends AbstractJavaRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!node.isNested()) {
|
if (!node.isNested()) {
|
||||||
return super.visit(node, data);
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node parent = node.jjtGetParent().jjtGetParent().jjtGetParent();
|
Node parent = node.jjtGetParent().jjtGetParent().jjtGetParent();
|
||||||
@ -49,7 +64,7 @@ public class UnnecessaryModifierRule extends AbstractJavaRule {
|
|||||||
addViolation(data, node, getMessage());
|
addViolation(data, node, getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.visit(node, data);
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
|
public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
|
||||||
@ -59,7 +74,7 @@ public class UnnecessaryModifierRule extends AbstractJavaRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!node.isNested()) {
|
if (!node.isNested()) {
|
||||||
return super.visit(node, data);
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node parent = node.jjtGetParent().jjtGetParent().jjtGetParent();
|
Node parent = node.jjtGetParent().jjtGetParent().jjtGetParent();
|
||||||
@ -81,28 +96,67 @@ public class UnnecessaryModifierRule extends AbstractJavaRule {
|
|||||||
addViolation(data, node, getMessage());
|
addViolation(data, node, getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.visit(node, data);
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visit(ASTMethodDeclaration node, Object data) {
|
public Object visit(final ASTMethodDeclaration node, Object data) {
|
||||||
if (node.isSyntacticallyPublic() || node.isSyntacticallyAbstract()) {
|
if (node.isSyntacticallyPublic() || node.isSyntacticallyAbstract()) {
|
||||||
check(node, data);
|
check(node, data);
|
||||||
}
|
}
|
||||||
return super.visit(node, data);
|
|
||||||
|
if (node.isFinal()) {
|
||||||
|
// If the method is annotated by @SafeVarargs then it's ok
|
||||||
|
if (!isSafeVarargs(node)) {
|
||||||
|
if (node.isPrivate()) {
|
||||||
|
addViolation(data, node);
|
||||||
|
} else {
|
||||||
|
final Node n = node.getNthParent(3);
|
||||||
|
// A final method of an anonymous class / enum constant. Neither can be extended / overridden
|
||||||
|
if (n instanceof ASTAllocationExpression || n instanceof ASTEnumConstant) {
|
||||||
|
addViolation(data, node);
|
||||||
|
} else if (n instanceof ASTClassOrInterfaceDeclaration
|
||||||
|
&& ((ASTClassOrInterfaceDeclaration) n).isFinal()) {
|
||||||
|
addViolation(data, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object visit(final ASTResource node, final Object data) {
|
||||||
|
if (node.isFinal()) {
|
||||||
|
addViolation(data, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visit(ASTFieldDeclaration node, Object data) {
|
public Object visit(ASTFieldDeclaration node, Object data) {
|
||||||
if (node.isSyntacticallyPublic() || node.isSyntacticallyStatic() || node.isSyntacticallyFinal()) {
|
if (node.isSyntacticallyPublic() || node.isSyntacticallyStatic() || node.isSyntacticallyFinal()) {
|
||||||
check(node, data);
|
check(node, data);
|
||||||
}
|
}
|
||||||
return super.visit(node, data);
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object visit(ASTAnnotationMethodDeclaration node, Object data) {
|
public Object visit(ASTAnnotationMethodDeclaration node, Object data) {
|
||||||
if (node.isPublic() || node.isAbstract()) {
|
if (node.isPublic() || node.isAbstract()) {
|
||||||
check(node, data);
|
check(node, data);
|
||||||
}
|
}
|
||||||
return super.visit(node, data);
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSafeVarargs(final ASTMethodDeclaration node) {
|
||||||
|
for (final ASTAnnotation annotation : node.jjtGetParent().findChildrenOfType(ASTAnnotation.class)) {
|
||||||
|
final Node childAnnotation = annotation.jjtGetChild(0);
|
||||||
|
if (childAnnotation instanceof ASTMarkerAnnotation
|
||||||
|
&& SafeVarargs.class.isAssignableFrom(((ASTMarkerAnnotation) childAnnotation).getType())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void check(Node fieldOrMethod, Object data) {
|
private void check(Node fieldOrMethod, Object data) {
|
||||||
|
@ -1435,45 +1435,6 @@ public class Foo {
|
|||||||
</example>
|
</example>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
<rule name="UnnecessaryFinalModifier"
|
|
||||||
language="java"
|
|
||||||
since="3.0"
|
|
||||||
message="Unnecessary final modifier in final class / private methods"
|
|
||||||
class="net.sourceforge.pmd.lang.rule.XPathRule"
|
|
||||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_codestyle.html#unnecessaryfinalmodifier">
|
|
||||||
<description>
|
|
||||||
When a class has the final modifier, all the methods are automatically final and do not need to be
|
|
||||||
tagged as such. Similarly, methods that can't be overridden (private methods, methods of anonymous classes,
|
|
||||||
methods of enum instance) do not need to be tagged either.
|
|
||||||
</description>
|
|
||||||
<priority>3</priority>
|
|
||||||
<properties>
|
|
||||||
<property name="xpath">
|
|
||||||
<value>
|
|
||||||
<![CDATA[
|
|
||||||
//ClassOrInterfaceDeclaration[@Final='true' and @Interface='false']
|
|
||||||
/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration
|
|
||||||
[count(./Annotation/MarkerAnnotation/Name[@Image='SafeVarargs' or @Image='java.lang.SafeVarargs']) = 0]
|
|
||||||
/MethodDeclaration[@Final='true']
|
|
||||||
| //MethodDeclaration[@Final='true' and @Private='true']
|
|
||||||
| //EnumConstant/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/MethodDeclaration[@Final='true']
|
|
||||||
| //AllocationExpression/ClassOrInterfaceBody/ClassOrInterfaceBodyDeclaration/MethodDeclaration[@Final='true']
|
|
||||||
]]>
|
|
||||||
</value>
|
|
||||||
</property>
|
|
||||||
</properties>
|
|
||||||
<example>
|
|
||||||
<![CDATA[
|
|
||||||
public final class Foo {
|
|
||||||
// This final modifier is not necessary, since the class is final
|
|
||||||
// and thus, all methods are final
|
|
||||||
private final void foo() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</example>
|
|
||||||
</rule>
|
|
||||||
|
|
||||||
<rule name="UnnecessaryFullyQualifiedName"
|
<rule name="UnnecessaryFullyQualifiedName"
|
||||||
language="java"
|
language="java"
|
||||||
since="5.0"
|
since="5.0"
|
||||||
|
@ -13,7 +13,6 @@ The Unnecessary Ruleset contains a collection of rules for unnecessary code.
|
|||||||
<rule ref="category/java/errorprone.xml/UnusedNullCheckInEquals" deprecated="true" />
|
<rule ref="category/java/errorprone.xml/UnusedNullCheckInEquals" deprecated="true" />
|
||||||
<rule ref="category/java/errorprone.xml/UselessOperationOnImmutable" deprecated="true" />
|
<rule ref="category/java/errorprone.xml/UselessOperationOnImmutable" deprecated="true" />
|
||||||
|
|
||||||
<rule ref="category/java/codestyle.xml/UnnecessaryFinalModifier" deprecated="true" />
|
|
||||||
<rule ref="category/java/codestyle.xml/UnnecessaryModifier" deprecated="true" />
|
<rule ref="category/java/codestyle.xml/UnnecessaryModifier" deprecated="true" />
|
||||||
<rule ref="category/java/codestyle.xml/UnnecessaryReturn" deprecated="true" />
|
<rule ref="category/java/codestyle.xml/UnnecessaryReturn" deprecated="true" />
|
||||||
<rule ref="category/java/codestyle.xml/UselessParentheses" deprecated="true" />
|
<rule ref="category/java/codestyle.xml/UselessParentheses" deprecated="true" />
|
||||||
|
@ -59,7 +59,6 @@ public class CodeStyleRulesTest extends SimpleAggregatorTst {
|
|||||||
addRule(RULESET, "SuspiciousConstantFieldName");
|
addRule(RULESET, "SuspiciousConstantFieldName");
|
||||||
addRule(RULESET, "TooManyStaticImports");
|
addRule(RULESET, "TooManyStaticImports");
|
||||||
addRule(RULESET, "UnnecessaryConstructor");
|
addRule(RULESET, "UnnecessaryConstructor");
|
||||||
addRule(RULESET, "UnnecessaryFinalModifier");
|
|
||||||
addRule(RULESET, "UnnecessaryFullyQualifiedName");
|
addRule(RULESET, "UnnecessaryFullyQualifiedName");
|
||||||
addRule(RULESET, "UnnecessaryLocalBeforeReturn");
|
addRule(RULESET, "UnnecessaryLocalBeforeReturn");
|
||||||
addRule(RULESET, "UnnecessaryModifier");
|
addRule(RULESET, "UnnecessaryModifier");
|
||||||
|
@ -1,161 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<test-data
|
|
||||||
xmlns="http://pmd.sourceforge.net/rule-tests"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">
|
|
||||||
<test-code>
|
|
||||||
<description><![CDATA[
|
|
||||||
TEST1
|
|
||||||
]]></description>
|
|
||||||
<expected-problems>0</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
public void foo() { }
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description><![CDATA[
|
|
||||||
TEST2
|
|
||||||
]]></description>
|
|
||||||
<expected-problems>0</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
public final void foo() { }
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description><![CDATA[
|
|
||||||
TEST3
|
|
||||||
]]></description>
|
|
||||||
<expected-problems>0</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
public final void foo() { }
|
|
||||||
public void foo2() { }
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description><![CDATA[
|
|
||||||
TEST4
|
|
||||||
]]></description>
|
|
||||||
<expected-problems>1</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public final class Foo {
|
|
||||||
public final void foo() { }
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description><![CDATA[
|
|
||||||
TEST5
|
|
||||||
]]></description>
|
|
||||||
<expected-problems>1</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public final class Foo {
|
|
||||||
public final void foo() { }
|
|
||||||
public void foo2() { }
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description><![CDATA[
|
|
||||||
TEST6
|
|
||||||
]]></description>
|
|
||||||
<expected-problems>3</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public final class Foo {
|
|
||||||
public final void fooA() { }
|
|
||||||
public final void fooS() { }
|
|
||||||
public final void fooD() { }
|
|
||||||
public void foo2() { }
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description><![CDATA[
|
|
||||||
final method in inner class of non-final outer class
|
|
||||||
]]></description>
|
|
||||||
<expected-problems>0</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public final class Foo {
|
|
||||||
public static class Bar {
|
|
||||||
public final void buz() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description><![CDATA[
|
|
||||||
final method in inner final class
|
|
||||||
]]></description>
|
|
||||||
<expected-problems>1</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public final class Foo {
|
|
||||||
public final class Bar {
|
|
||||||
public final void buz() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
|
|
||||||
<test-code>
|
|
||||||
<description>#1464 UnnecessaryFinalModifier false positive on a @SafeVarargs method</description>
|
|
||||||
<expected-problems>0</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public final class InboxContents<T> {
|
|
||||||
@SafeVarargs
|
|
||||||
public final InboxContents<T> conflateWith(T... values) { // false positive
|
|
||||||
return conflateWith(ImmutableList.copyOf(values));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public final class InboxContents2 {
|
|
||||||
@java.lang.SafeVarargs
|
|
||||||
public final InboxContents conflateWith(String... values) {
|
|
||||||
return conflateWith(ImmutableList.copyOf(values));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description>Unnecessary final of private method</description>
|
|
||||||
<expected-problems>1</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public class TestClass {
|
|
||||||
private final int getValue() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description>Unnecessary final of enum method</description>
|
|
||||||
<expected-problems>1</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public enum Foo {
|
|
||||||
BAR {
|
|
||||||
@Override
|
|
||||||
public final void magic() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
public void magic() {}
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
<test-code>
|
|
||||||
<description>Unnecessary final of anonymous class method</description>
|
|
||||||
<expected-problems>1</expected-problems>
|
|
||||||
<code><![CDATA[
|
|
||||||
public class Foo {
|
|
||||||
public void stuff() {
|
|
||||||
Listener list = new Listener() {
|
|
||||||
@Override
|
|
||||||
public final void onEvent() {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></code>
|
|
||||||
</test-code>
|
|
||||||
</test-data>
|
|
@ -428,6 +428,163 @@ public abstract interface TestInterface {
|
|||||||
<expected-problems>1</expected-problems>
|
<expected-problems>1</expected-problems>
|
||||||
<code><![CDATA[
|
<code><![CDATA[
|
||||||
public abstract @interface TestAnnotation {
|
public abstract @interface TestAnnotation {
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
final method on non-final class is ok
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
public final void foo() { }
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
final and non-final methods mixed
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
public final void foo() { }
|
||||||
|
public void foo2() { }
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
final method on a final class
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public final class Foo {
|
||||||
|
public final void foo() { }
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
mixed final and non-final methods on final class
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public final class Foo {
|
||||||
|
public final void foo() { }
|
||||||
|
public void foo2() { }
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
multiple final methods on final class
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>3</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public final class Foo {
|
||||||
|
public final void fooA() { }
|
||||||
|
public final void fooS() { }
|
||||||
|
public final void fooD() { }
|
||||||
|
public void foo2() { }
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
final method in inner class of non-final outer class
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public final class Foo {
|
||||||
|
public static class Bar {
|
||||||
|
public final void buz() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description><![CDATA[
|
||||||
|
final method in inner final class
|
||||||
|
]]></description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public final class Foo {
|
||||||
|
public final class Bar {
|
||||||
|
public final void buz() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
|
||||||
|
<test-code>
|
||||||
|
<description>#1464 UnnecessaryFinalModifier false positive on a @SafeVarargs method</description>
|
||||||
|
<expected-problems>0</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public final class InboxContents<T> {
|
||||||
|
@SafeVarargs
|
||||||
|
public final InboxContents<T> conflateWith(T... values) { // false positive
|
||||||
|
return conflateWith(ImmutableList.copyOf(values));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public final class InboxContents2 {
|
||||||
|
@java.lang.SafeVarargs
|
||||||
|
public final InboxContents conflateWith(String... values) {
|
||||||
|
return conflateWith(ImmutableList.copyOf(values));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description>Unnecessary final of private method</description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class TestClass {
|
||||||
|
private final int getValue() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description>Unnecessary final of enum method</description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public enum Foo {
|
||||||
|
BAR {
|
||||||
|
@Override
|
||||||
|
public final void magic() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void magic() {}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description>Unnecessary final of anonymous class method</description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
public void stuff() {
|
||||||
|
Listener list = new Listener() {
|
||||||
|
@Override
|
||||||
|
public final void onEvent() {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></code>
|
||||||
|
</test-code>
|
||||||
|
<test-code>
|
||||||
|
<description>Unnecessary final of try-with-resources resource</description>
|
||||||
|
<expected-problems>1</expected-problems>
|
||||||
|
<code><![CDATA[
|
||||||
|
public class Foo {
|
||||||
|
public void stuff() {
|
||||||
|
try (final FileWriter fw = new FileWriter(new File("something.txt"))) {
|
||||||
|
// do something on fw
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]]></code>
|
]]></code>
|
||||||
</test-code>
|
</test-code>
|
||||||
|
Reference in New Issue
Block a user