diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/LineWrappingHandler.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/LineWrappingHandler.java index 36bae931602..44c53bc5320 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/LineWrappingHandler.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/indentation/LineWrappingHandler.java @@ -317,7 +317,33 @@ private void checkAnnotationIndentation(DetailAST atNode, final boolean isCurrentNodeCloseAnnotationAloneInLine = node.getLineNo() == lastAnnotationLine && isEndOfScope(lastAnnotationNode, node); + final boolean isPreviousToPreviousSiblingAccessModifier = + parentNode.getPreviousSibling() != null + && parentNode.getPreviousSibling().getPreviousSibling() != null + && (parentNode.getPreviousSibling().getPreviousSibling().getType() + == TokenTypes.LITERAL_PUBLIC + || parentNode.getPreviousSibling().getPreviousSibling().getType() + == TokenTypes.LITERAL_PRIVATE + || parentNode.getPreviousSibling().getPreviousSibling().getType() + == TokenTypes.LITERAL_PROTECTED); + final boolean isCurrentNodeAnnotationLineWrappedInClassDef = + node.getType() == TokenTypes.AT && parentNode.getType() == TokenTypes.ANNOTATION + && parentNode.getPreviousSibling() != null + && parentNode.getPreviousSibling().getType() == TokenTypes.ANNOTATION + && isPreviousToPreviousSiblingAccessModifier + && parentNode.getPreviousSibling().getFirstChild() != null + && parentNode.getPreviousSibling().getFirstChild().getType() == TokenTypes.AT; + if (!isArrayInitPresentInAncestors + && (isCurrentNodeCloseAnnotationAloneInLine + || node.getType() == TokenTypes.AT + && (parentNode.getParent().getType() == TokenTypes.MODIFIERS + || parentNode.getParent().getType() == TokenTypes.ANNOTATIONS) + || TokenUtil.areOnSameLine(node, atNode)) + && isCurrentNodeAnnotationLineWrappedInClassDef) { + logWarningMessage(node, currentIndent); + } + else if (!isArrayInitPresentInAncestors && (isCurrentNodeCloseAnnotationAloneInLine || node.getType() == TokenTypes.AT && (parentNode.getParent().getType() == TokenTypes.MODIFIERS 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 eeb45204588..20c15926c34 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 @@ -2997,6 +2997,24 @@ public void testIndentationAnnotationFieldDefinition() throws Exception { expected); } + @Test + public void testIndentationAnnotationMultiLine() throws Exception { + final DefaultConfiguration checkConfig = createModuleConfig(IndentationCheck.class); + checkConfig.addProperty("tabWidth", "4"); + checkConfig.addProperty("basicOffset", "2"); + checkConfig.addProperty("braceAdjustment", "2"); + checkConfig.addProperty("caseIndent", "2"); + checkConfig.addProperty("throwsIndent", "4"); + checkConfig.addProperty("lineWrappingIndentation", "4"); + checkConfig.addProperty("arrayInitIndent", "2"); + + final String[] expected = { + "16:1: " + getCheckMessage(MSG_ERROR, "@", 0, 4), + }; + + verifyWarns(checkConfig, getPath("InputIndentationAnnotationMultiLine.java"), expected); + } + @Test public void testIndentationLongConcatenatedString() throws Exception { final DefaultConfiguration checkConfig = createModuleConfig(IndentationCheck.class); diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationAnnotationMultiLine.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationAnnotationMultiLine.java new file mode 100644 index 00000000000..b7b65004175 --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/indentation/indentation/InputIndentationAnnotationMultiLine.java @@ -0,0 +1,38 @@ +package com.puppycrawl.tools.checkstyle.checks.indentation.indentation;//indent:0 exp:0 +//indent:0 exp:0 +/** //indent:0 exp:0 + * This test-input is intended to be checked using following configuration: //indent:1 exp:1 + * //indent:1 exp:1 + * arrayInitIndent = 2 //indent:1 exp:1 + * basicOffset = 2 //indent:1 exp:1 + * braceAdjustment = 2 //indent:1 exp:1 + * caseIndent = 4 //indent:1 exp:1 + * lineWrappingIndentation = 4 //indent:1 exp:1 + * throwsIndent = 4 //indent:1 exp:1 + */ //indent:1 exp:1 +//indent:0 exp:0 +@AppleAnnotation//indent:0 exp:0 +public @GrapeAnnotation//indent:0 exp:0 +@NutsAnnotation class InputIndentationAnnotationMultiLine//indent:0 exp:4 warn + implements MyInterface {//indent:4 exp:4 +//indent:0 exp:0 +//indent:0 exp:0 +}//indent:0 exp:0 +//indent:0 exp:0 +@interface AppleAnnotation {//indent:0 exp:0 +//indent:0 exp:0 +}//indent:0 exp:0 +//indent:0 exp:0 +@interface GrapeAnnotation {//indent:0 exp:0 +//indent:0 exp:0 +}//indent:0 exp:0 +//indent:0 exp:0 +@interface NutsAnnotation {//indent:0 exp:0 +//indent:0 exp:0 +}//indent:0 exp:0 +//indent:0 exp:0 +@interface ThisAnnotation {//indent:0 exp:0 +//indent:0 exp:0 +}//indent:0 exp:0 +interface MyInterface {//indent:0 exp:0 +}//indent:0 exp:0