Check records are not declare with final modifier

This commit is contained in:
Vincent Galloy
2022-01-04 17:18:19 +01:00
parent b792c14f4d
commit ee763ee3d7
7 changed files with 45 additions and 22 deletions

View File

@ -55,12 +55,6 @@ public final class ASTRecordDeclaration extends AbstractAnyTypeDeclaration {
return isNested() || isLocal();
}
@Override
public boolean isFinal() {
// A record is implicitly final
return true;
}
@Override
public boolean isLocal() {
return getParent() instanceof ASTBlockStatement;

View File

@ -269,7 +269,10 @@ public class UnnecessaryModifierRule extends AbstractJavaRule {
@Override
public Object visit(ASTRecordDeclaration node, Object data) {
if (node.isStatic()) {
reportUnnecessaryModifiers(data, node, Modifier.STATIC, "record are implicitly static");
reportUnnecessaryModifiers(data, node, Modifier.STATIC, "records are implicitly static");
}
if (node.isFinal()) {
reportUnnecessaryModifiers(data, node, Modifier.FINAL, "records are implicitly final");
}
return data;
}

View File

@ -60,7 +60,7 @@
| | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = false, @ForeachVariable = false, @FormalParameter = true, @Image = "month", @LambdaParameter = false, @LocalVariable = false, @Name = "month", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "month"]
| +- Block[@containsComment = false]
| +- BlockStatement[@Allocation = false]
| | +- RecordDeclaration[@Abstract = false, @BinaryName = "LocalRecords$MerchantSales", @Default = false, @Final = true, @Image = "MerchantSales", @Local = true, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "MerchantSales", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| | +- RecordDeclaration[@Abstract = false, @BinaryName = "LocalRecords$MerchantSales", @Default = false, @Final = false, @Image = "MerchantSales", @Local = true, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "MerchantSales", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| | +- RecordComponentList[@Size = 2]
| | | +- RecordComponent[@Varargs = false]
| | | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "Merchant"]
@ -194,7 +194,7 @@
| | +- Annotation[@AnnotationName = "Deprecated"]
| | | +- MarkerAnnotation[@AnnotationName = "Deprecated"]
| | | +- Name[@Image = "Deprecated"]
| | +- RecordDeclaration[@Abstract = false, @BinaryName = "LocalRecords$MyRecord3", @Default = false, @Final = true, @Image = "MyRecord3", @Local = true, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "MyRecord3", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| | +- RecordDeclaration[@Abstract = false, @BinaryName = "LocalRecords$MyRecord3", @Default = false, @Final = false, @Image = "MyRecord3", @Local = true, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "MyRecord3", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| | +- RecordComponentList[@Size = 1]
| | | +- RecordComponent[@Varargs = false]
| | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"]

View File

@ -1,6 +1,6 @@
+- CompilationUnit[@PackageName = "", @declarationsAreInDefaultPackage = true]
+- TypeDeclaration[]
+- RecordDeclaration[@Abstract = false, @BinaryName = "Point", @Default = false, @Final = true, @Image = "Point", @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "Point", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
+- RecordDeclaration[@Abstract = false, @BinaryName = "Point", @Default = false, @Final = false, @Image = "Point", @Local = false, @Modifiers = 1, @Native = false, @Nested = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "Point", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
+- RecordComponentList[@Size = 2]
| +- RecordComponent[@Varargs = false]
| | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"]

View File

@ -35,7 +35,7 @@
| +- AnnotationTypeDeclaration[@Abstract = false, @BinaryName = "Records$MyAnnotation", @Default = false, @Final = false, @Image = "MyAnnotation", @Local = false, @Modifiers = 0, @Native = false, @Nested = true, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "MyAnnotation", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.ANNOTATION, @Volatile = false]
| +- AnnotationTypeBody[]
+- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.RECORD]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$MyComplex", @Default = false, @Final = true, @Image = "MyComplex", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "MyComplex", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$MyComplex", @Default = false, @Final = false, @Image = "MyComplex", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "MyComplex", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordComponentList[@Size = 2]
| | +- RecordComponent[@Varargs = false]
| | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"]
@ -113,7 +113,7 @@
| | +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
| | +- Name[@Image = "imaginary"]
| +- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.RECORD]
| | +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$MyComplex$Nested", @Default = false, @Final = true, @Image = "Nested", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "Nested", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| | +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$MyComplex$Nested", @Default = false, @Final = false, @Image = "Nested", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "Nested", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| | +- RecordComponentList[@Size = 1]
| | | +- RecordComponent[@Varargs = false]
| | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"]
@ -124,7 +124,7 @@
| +- ClassOrInterfaceDeclaration[@Abstract = false, @BinaryName = "Records$MyComplex$NestedClass", @Default = false, @Final = false, @Image = "NestedClass", @Interface = false, @Local = false, @Modifiers = 17, @Native = false, @Nested = true, @NonSealed = false, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @Sealed = false, @SimpleName = "NestedClass", @Static = true, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.CLASS, @Volatile = false]
| +- ClassOrInterfaceBody[@AnonymousInnerClass = false, @EnumChild = false]
+- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.RECORD]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$Range", @Default = false, @Final = true, @Image = "Range", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "Range", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$Range", @Default = false, @Final = false, @Image = "Range", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "Range", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordComponentList[@Size = 2]
| | +- RecordComponent[@Varargs = false]
| | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"]
@ -186,7 +186,7 @@
| | +- FormalParameters[@ParameterCount = 0, @Size = 0]
| +- Block[@containsComment = false]
+- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.RECORD]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$VarRec", @Default = false, @Final = true, @Image = "VarRec", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "VarRec", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$VarRec", @Default = false, @Final = false, @Image = "VarRec", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "VarRec", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordComponentList[@Size = 1]
| | +- RecordComponent[@Varargs = true]
| | +- Annotation[@AnnotationName = "Nullable"]
@ -204,7 +204,7 @@
| | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = false, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = true, @ForeachVariable = false, @FormalParameter = false, @Image = "x", @LambdaParameter = false, @LocalVariable = false, @Name = "x", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "x"]
| +- RecordBody[]
+- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.RECORD]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$ArrayRec", @Default = false, @Final = true, @Image = "ArrayRec", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "ArrayRec", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$ArrayRec", @Default = false, @Final = false, @Image = "ArrayRec", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "ArrayRec", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordComponentList[@Size = 1]
| | +- RecordComponent[@Varargs = false]
| | +- Type[@Array = true, @ArrayDepth = 1, @ArrayType = true, @TypeImage = "int"]
@ -213,7 +213,7 @@
| | +- VariableDeclaratorId[@Array = false, @ArrayDepth = 0, @ArrayType = true, @ExceptionBlockParameter = false, @ExplicitReceiverParameter = false, @Field = false, @Final = true, @ForeachVariable = false, @FormalParameter = false, @Image = "x", @LambdaParameter = false, @LocalVariable = false, @Name = "x", @PatternBinding = false, @ResourceDeclaration = false, @TypeInferred = false, @VariableName = "x"]
| +- RecordBody[]
+- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.RECORD]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$EmptyRec", @Default = false, @Final = true, @Image = "EmptyRec", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "EmptyRec", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Records$EmptyRec", @Default = false, @Final = false, @Image = "EmptyRec", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "EmptyRec", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- TypeParameters[]
| | +- TypeParameter[@Image = "Type", @Name = "Type", @ParameterName = "Type", @TypeBound = false]
| +- RecordComponentList[@Size = 0]
@ -299,7 +299,7 @@
| +- MethodDeclarator[@Image = "lastName", @ParameterCount = 0]
| +- FormalParameters[@ParameterCount = 0, @Size = 0]
+- ClassOrInterfaceBodyDeclaration[@AnonymousInnerClass = false, @EnumChild = false, @Kind = DeclarationKind.RECORD]
+- RecordDeclaration[@Abstract = false, @BinaryName = "Records$PersonRecord", @Default = false, @Final = true, @Image = "PersonRecord", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "PersonRecord", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
+- RecordDeclaration[@Abstract = false, @BinaryName = "Records$PersonRecord", @Default = false, @Final = false, @Image = "PersonRecord", @Local = false, @Modifiers = 1, @Native = false, @Nested = true, @PackagePrivate = false, @Private = false, @Protected = false, @Public = true, @SimpleName = "PersonRecord", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
+- RecordComponentList[@Size = 2]
| +- RecordComponent[@Varargs = false]
| | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "String"]

View File

@ -180,7 +180,7 @@
| +- PrimaryPrefix[@SuperModifier = false, @ThisModifier = false]
| +- Name[@Image = "o"]
+- TypeDeclaration[]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Point", @Default = false, @Final = true, @Image = "Point", @Local = false, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "Point", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordDeclaration[@Abstract = false, @BinaryName = "Point", @Default = false, @Final = false, @Image = "Point", @Local = false, @Modifiers = 0, @Native = false, @Nested = false, @PackagePrivate = true, @Private = false, @Protected = false, @Public = false, @SimpleName = "Point", @Static = false, @Strictfp = false, @Synchronized = false, @Transient = false, @TypeKind = TypeKind.RECORD, @Volatile = false]
| +- RecordComponentList[@Size = 2]
| | +- RecordComponent[@Varargs = false]
| | | +- Type[@Array = false, @ArrayDepth = 0, @ArrayType = false, @TypeImage = "int"]

View File

@ -700,10 +700,10 @@ public interface Bar {
</test-code>
<test-code>
<description>Static is not necessary in class</description>
<description>Static is not necessary for record declaration in class</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'static' on record 'BarRecord': record are implicitly static</message>
<message>Unnecessary modifier 'static' on record 'BarRecord': records are implicitly static</message>
</expected-messages>
<code><![CDATA[
public class FooClass {
@ -723,10 +723,10 @@ public class FooClass {
</test-code>
<test-code>
<description>Static is not necessary in interface</description>
<description>Static is not necessary for record declaration in interface</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'static' on record 'BarRecord': record are implicitly static</message>
<message>Unnecessary modifier 'static' on record 'BarRecord': records are implicitly static</message>
</expected-messages>
<code><![CDATA[
public interface FooInterface {
@ -741,6 +741,32 @@ public interface FooInterface {
<code><![CDATA[
public interface FooInterface {
record BarRecord() {}
}
]]></code>
</test-code>
<test-code>
<description>Final is not necessary for record declaration in class</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'final' on record 'BarRecord': records are implicitly final</message>
</expected-messages>
<code><![CDATA[
public class FooClass {
final record BarRecord() {}
}
]]></code>
</test-code>
<test-code>
<description>Final is not necessary for record declaration in interface</description>
<expected-problems>1</expected-problems>
<expected-messages>
<message>Unnecessary modifier 'final' on record 'BarRecord': records are implicitly final</message>
</expected-messages>
<code><![CDATA[
public interface FooInterface {
final record BarRecord() {}
}
]]></code>
</test-code>