diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheck.java index 041c660bc3a..036b164224a 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheck.java @@ -1562,10 +1562,18 @@ public boolean hasStaticMethod(final DetailAST ident) { public boolean hasFinalField(final DetailAST instanceMember) { boolean result = false; for (DetailAST member : instanceMembers) { - final DetailAST mods = member.getParent().findFirstToken(TokenTypes.MODIFIERS); - final boolean finalMod = mods.findFirstToken(TokenTypes.FINAL) != null; - if (finalMod && isAstSimilar(member, instanceMember)) { + final DetailAST parent = member.getParent(); + if (parent.getType() == TokenTypes.RECORD_COMPONENT_DEF) { result = true; + } + else { + final DetailAST mods = parent.findFirstToken(TokenTypes.MODIFIERS); + final boolean finalMod = mods.findFirstToken(TokenTypes.FINAL) != null; + if (finalMod && isAstSimilar(member, instanceMember)) { + result = true; + } + } + if (result) { break; } } diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheckTest.java index 64dca1b4dd9..24e40c27e0f 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheckTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/coding/RequireThisCheckTest.java @@ -471,6 +471,26 @@ public void testRecordsDefault() throws Exception { expected); } + @Test + public void testRecordsWithCheckFields() throws Exception { + final String[] expected = CommonUtil.EMPTY_STRING_ARRAY; + verifyWithInlineConfigParser( + getNonCompilablePath("InputRequireThisRecordsWithCheckFields.java"), + expected); + } + + @Test + public void testRecordsWithCheckFieldsOverlap() throws Exception { + final String[] expected = { + "20:20: " + getCheckMessage(MSG_VARIABLE, "a", ""), + "39:20: " + getCheckMessage(MSG_VARIABLE, "a", ""), + "46:16: " + getCheckMessage(MSG_VARIABLE, "a", ""), + }; + verifyWithInlineConfigParser( + getNonCompilablePath("InputRequireThisRecordsWithCheckFieldsOverlap.java"), + expected); + } + @Test public void testLocalClassesInsideLambdas() throws Exception { final String[] expected = CommonUtil.EMPTY_STRING_ARRAY; diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/requirethis/InputRequireThisRecordsWithCheckFields.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/requirethis/InputRequireThisRecordsWithCheckFields.java new file mode 100644 index 00000000000..d952f1c5ac9 --- /dev/null +++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/requirethis/InputRequireThisRecordsWithCheckFields.java @@ -0,0 +1,48 @@ +/* +RequireThis +checkFields = true +checkMethods = (default)true +validateOnlyOverlapping = (default)true + + +*/ + +//non-compiled with javac: Compilable with Java14 +package com.puppycrawl.tools.checkstyle.checks.coding.requirethis; + +public record InputRequireThisRecordsWithCheckFields(String a) { + void method() { + String a = "BUG"; + a = a.substring(0, 1); // ok, field 'a' is final and cannot be changed + } + + void method2() { + String x = a; // ok, not overlapping + String y = this.a; // ok, uses 'this' + String a = this.a; // ok, local variable assigned from field + a += a; // ok, local variable + } +} +class InputRequireThisRecordsWithCheckFieldsClass { + public final String a; + + public InputRequireThisRecordsWithCheckFieldsClass(String a) { + this.a = a; + } + + void method() { + String a = "BUG"; + a = a.substring(0, 1); // ok, field 'a' is final and cannot be changed + } + + void method2() { + String x = a; // ok, not overlapping + String y = this.a; // ok, uses 'this' + String a = this.a; // ok, local variable assigned from field + a += a; // ok, local variable + } + + public String a() { + return a; // ok + } +} diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/requirethis/InputRequireThisRecordsWithCheckFieldsOverlap.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/requirethis/InputRequireThisRecordsWithCheckFieldsOverlap.java new file mode 100644 index 00000000000..eb649df3d29 --- /dev/null +++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/checks/coding/requirethis/InputRequireThisRecordsWithCheckFieldsOverlap.java @@ -0,0 +1,48 @@ +/* +RequireThis +checkFields = true +checkMethods = (default)true +validateOnlyOverlapping = false + + +*/ + +//non-compiled with javac: Compilable with Java14 +package com.puppycrawl.tools.checkstyle.checks.coding.requirethis; + +public record InputRequireThisRecordsWithCheckFieldsOverlap(String a) { + void method() { + String a = "BUG"; + a = a.substring(0, 1); // ok, field 'a' is final and cannot be changed + } + + void method2() { + String x = a; // violation 'Reference to instance variable 'a' needs "this.".' + String y = this.a; // ok, uses 'this' + String a = this.a; // ok, local variable assigned from field + a += a; // ok, local variable + } +} +class InputRequireThisRecordsWithCheckFieldsClass { + public final String a; + + public InputRequireThisRecordsWithCheckFieldsClass(String a) { + this.a = a; + } + + void method() { + String a = "BUG"; + a = a.substring(0, 1); // ok, field 'a' is final and cannot be changed + } + + void method2() { + String x = a; // violation 'Reference to instance variable 'a' needs "this.".' + String y = this.a; // ok, uses 'this' + String a = this.a; // ok, local variable assigned from field + a += a; // ok, local variable + } + + public String a() { + return a; // violation 'Reference to instance variable 'a' needs "this.".' + } +}