From 14e94b2dc05b1801462f8f6c916ab45b18d8e056 Mon Sep 17 00:00:00 2001 From: Kumar Kalpadiptya Roy Date: Sun, 31 Mar 2024 00:51:11 +0530 Subject: [PATCH] Issue #14716: Fix the violation for modifiers wrapped in class def --- .../AbstractExpressionHandler.java | 5 ++++ .../tools/checkstyle/utils/TokenUtil.java | 16 ++++++++++ .../indentation/IndentationCheckTest.java | 16 ++++++++++ .../tools/checkstyle/utils/TokenUtilTest.java | 28 +++++++++++++++++ ...putIndentationClassDeclarationWrapped.java | 30 +++++++++++++++++++ 5 files changed, 95 insertions(+) create mode 100644 src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationClassDeclarationWrapped.java diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/AbstractExpressionHandler.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/AbstractExpressionHandler.java index fde840aa6bc..2f99a7c89df 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/AbstractExpressionHandler.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/AbstractExpressionHandler.java @@ -24,6 +24,7 @@ import com.puppycrawl.tools.checkstyle.api.DetailAST; import com.puppycrawl.tools.checkstyle.api.TokenTypes; import com.puppycrawl.tools.checkstyle.utils.CommonUtil; +import com.puppycrawl.tools.checkstyle.utils.TokenUtil; /** * Abstract base class for all handlers. @@ -500,6 +501,10 @@ protected void checkModifiers() { modifier != null; modifier = modifier.getNextSibling()) { if (isOnStartOfLine(modifier) + && (!TokenUtil.isOfType(modifier, + TokenTypes.ANNOTATION, TokenTypes.STRICTFP, TokenTypes.LITERAL_STATIC) + || modifier.getPreviousSibling() == null + || !TokenUtil.isPrecededByAnyModifier(modifier)) && !getIndent().isAcceptable(expandedTabsColumnNo(modifier))) { logError(modifier, "modifier", expandedTabsColumnNo(modifier)); diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/utils/TokenUtil.java b/src/main/java/com/puppycrawl/tools/checkstyle/utils/TokenUtil.java index d302e993a18..8d69e43d50d 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/TokenUtil.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/TokenUtil.java @@ -353,4 +353,20 @@ public static BitSet asBitSet(String... tokens) { .collect(BitSet::new, BitSet::set, BitSet::or); } + /** + * Check whether given node a preceding access modifier or not. + * + * @param node the node whose predecessors are to be checked. + * @return true if node is preceded by an access modifier else false. + */ + public static boolean isPrecededByAnyModifier(DetailAST node) { + DetailAST tempNode = node; + while (tempNode.getPreviousSibling() != null + && !isOfType(tempNode.getPreviousSibling(), + TokenTypes.LITERAL_PUBLIC, TokenTypes.FINAL, TokenTypes.ABSTRACT)) { + tempNode = tempNode.getPreviousSibling(); + } + return tempNode.getPreviousSibling() != null; + } + } diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java index 67a6c076029..579038972c5 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java @@ -3019,6 +3019,22 @@ public void testIndentationLineBreakVariableDeclaration() verifyWarns(checkConfig, fileName, expected); } + @Test + public void testClassDeclarationWrapped() throws Exception { + final DefaultConfiguration checkConfig = createModuleConfig(IndentationCheck.class); + checkConfig.addProperty("tabWidth", "4"); + checkConfig.addProperty("basicOffset", "2"); + checkConfig.addProperty("braceAdjustment", "2"); + checkConfig.addProperty("lineWrappingIndentation", "4"); + checkConfig.addProperty("caseIndent", "2"); + checkConfig.addProperty("throwsIndent", "2"); + checkConfig.addProperty("arrayInitIndent", "2"); + + final String fileName = getPath("InputIndentationClassDeclarationWrapped.java"); + final String[] expected = CommonUtil.EMPTY_STRING_ARRAY; + verifyWarns(checkConfig, fileName, expected); + } + private static final class IndentAudit implements AuditListener { private final IndentComment[] comments; diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/utils/TokenUtilTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/utils/TokenUtilTest.java index 577d8bc851d..cd0d1ef6964 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/utils/TokenUtilTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/utils/TokenUtilTest.java @@ -395,4 +395,32 @@ public void testIsBooleanLiteralType() { .isFalse(); } + @Test + public void testIsPrecededByAnyModifier() { + final DetailAstImpl node1 = new DetailAstImpl(); + final DetailAstImpl node2 = new DetailAstImpl(); + final DetailAstImpl node3 = new DetailAstImpl(); + + node1.setType(TokenTypes.AT); + node2.setType(TokenTypes.ANNOTATION); + node3.setType(TokenTypes.LITERAL_PUBLIC); + + final DetailAstImpl node4 = new DetailAstImpl(); + final DetailAstImpl node5 = new DetailAstImpl(); + + node4.setType(TokenTypes.ANNOTATIONS); + node5.setType(TokenTypes.AT); + + node2.addPreviousSibling(node3); + node1.addPreviousSibling(node2); + node4.addPreviousSibling(node5); + + assertWithMessage("Result is not expected") + .that(TokenUtil.isPrecededByAnyModifier(node1)) + .isTrue(); + assertWithMessage("Result is not expected") + .that(TokenUtil.isPrecededByAnyModifier(node4)) + .isFalse(); + } + } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationClassDeclarationWrapped.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationClassDeclarationWrapped.java new file mode 100644 index 00000000000..8fabfbea090 --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationClassDeclarationWrapped.java @@ -0,0 +1,30 @@ +package com.puppycrawl.tools.checkstyle.checks.indentation.indentation;//indent:0 exp:0 + +public class InputIndentationClassDeclarationWrapped {//indent:0 exp:0 + + public class A {};//indent:2 exp:2 + + public//indent:2 exp:2 + class B {};//indent:6 exp:6 + + final//indent:2 exp:2 + static class C {};//indent:6 exp:6 + + abstract//indent:2 exp:2 + strictfp class G {};//indent:6 exp:6 + + public//indent:2 exp:2 + class T {};//indent:6 exp:6 + + public//indent:2 exp:2 + @X class D {};//indent:6 exp:6 + + abstract @Y//indent:2 exp:2 + @Z strictfp class E {};//indent:6 exp:6 + + @X class F {};//indent:2 exp:2 + + @interface X{}//indent:2 exp:2 + @interface Y{}//indent:2 exp:2 + @interface Z{}//indent:2 exp:2 +}//indent:0 exp:0