Skip to content

Commit

Permalink
Issue checkstyle#14620: LITERAL_CASE token support in RightCurlyCheck
Browse files Browse the repository at this point in the history
  • Loading branch information
mahfouz72 committed Apr 8, 2024
1 parent 571e547 commit bf6da15
Show file tree
Hide file tree
Showing 23 changed files with 1,411 additions and 23 deletions.
Expand Up @@ -1574,6 +1574,17 @@
<lineContent>.orElse(Boolean.TRUE);</lineContent>
</checkerFrameworkError>

<checkerFrameworkError unstable="false">
<fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
<specifier>argument</specifier>
<message>incompatible argument for parameter lcurly of Details constructor.</message>
<lineContent>return new Details(lcurly.orElse(null), rcurly, nextToken.orElse(null), true);</lineContent>
<details>
found : @Initialized @Nullable DetailAST
required: @Initialized @NonNull DetailAST
</details>
</checkerFrameworkError>

<checkerFrameworkError unstable="false">
<fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
<specifier>argument</specifier>
Expand All @@ -1585,6 +1596,17 @@
</details>
</checkerFrameworkError>

<checkerFrameworkError unstable="false">
<fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
<specifier>argument</specifier>
<message>incompatible argument for parameter nextToken of Details constructor.</message>
<lineContent>return new Details(lcurly.orElse(null), rcurly, nextToken.orElse(null), true);</lineContent>
<details>
found : @Initialized @Nullable DetailAST
required: @Initialized @NonNull DetailAST
</details>
</checkerFrameworkError>

<checkerFrameworkError unstable="false">
<fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
<specifier>argument</specifier>
Expand Down Expand Up @@ -1629,6 +1651,17 @@
</details>
</checkerFrameworkError>

<checkerFrameworkError unstable="false">
<fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
<specifier>argument</specifier>
<message>incompatible argument for parameter rcurly of Details constructor.</message>
<lineContent>return new Details(lcurly.orElse(null), rcurly, nextToken.orElse(null), true);</lineContent>
<details>
found : @Initialized @Nullable DetailAST
required: @Initialized @NonNull DetailAST
</details>
</checkerFrameworkError>

<checkerFrameworkError unstable="false">
<fileName>src/main/java/com/puppycrawl/tools/checkstyle/checks/blocks/RightCurlyCheck.java</fileName>
<specifier>return</specifier>
Expand Down
1 change: 1 addition & 0 deletions config/checkstyle-checks.xml
Expand Up @@ -330,6 +330,7 @@
<property name="tokens" value="ENUM_DEF"/>
<property name="tokens" value="RECORD_DEF"/>
<property name="tokens" value="COMPACT_CTOR_DEF"/>
<property name="tokens" value="LITERAL_CASE"/>
<property name="option" value="alone"/>
</module>
<module name="RightCurly">
Expand Down
Expand Up @@ -130,4 +130,19 @@ public void testRightCurlySwitch() throws Exception {
final Integer[] warnList = getLinesWithWarn(filePath);
verify(checkConfig, filePath, expected, warnList);
}

@Test
public void testRightCurlySwitchCases() throws Exception {
final String[] expected = {
"25:13: " + getCheckMessage(RightCurlyCheck.class, MSG_KEY_LINE_ALONE, "}", 13),
"34:28: " + getCheckMessage(RightCurlyCheck.class, MSG_KEY_LINE_ALONE, "}", 28),
"57:33: " + getCheckMessage(RightCurlyCheck.class, MSG_KEY_LINE_ALONE, "}", 33),
};

final Configuration checkConfig = createTreeWalkerConfig(getModuleConfigsByIds(MODULES));
final String filePath = getPath("InputRightCurlySwitchCasesBlocks.java");

final Integer[] warnList = getLinesWithWarn(filePath);
verify(checkConfig, filePath, expected, warnList);
}
}
@@ -0,0 +1,60 @@
package com.google.checkstyle.test.chapter4formatting.rule412nonemptyblocks;

public class InputRightCurlySwitchCasesBlocks {

public static void test0() {
int mode = 0;
switch (mode) {
case 1: {
int x = 1;
break;
}
case 2: {
int x = 0;
break;
}
}
}

public static void test() {
int mode = 0;
switch (mode) {
case 1:{
int x = 1;
break;
} default : // warn
int x = 0;
}
}

public static void test1() {
int k = 0;
switch (k) {
case 1:{
int x = 1;} // warn
case 2:
int x = 2;
break;
}
}

public static void test2() {
int mode = 0;
switch (mode) {
case 1: int x = 1;
case 2: {
break;
}
}
}

public static void test3() {
int k = 0;
switch (k) {
case 1:{
int x = 1;
}
case 2: { int x = 2;} // warn
}
}
}
Expand Up @@ -21,6 +21,7 @@

import java.util.Arrays;
import java.util.Locale;
import java.util.Optional;

import com.puppycrawl.tools.checkstyle.StatelessCheck;
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
Expand All @@ -32,8 +33,8 @@
/**
* <p>
* Checks the placement of right curly braces (<code>'}'</code>) for code blocks. This check
* supports if-else, try-catch-finally blocks, switch statements, while-loops, for-loops,
* method definitions, class definitions, constructor definitions,
* supports if-else, try-catch-finally blocks, switch statements, switch cases, while-loops,
* for-loops, method definitions, class definitions, constructor definitions,
* instance, static initialization blocks, annotation definitions and enum definitions.
* For right curly brace of expression blocks of arrays, lambdas and class instances
* please follow issue
Expand Down Expand Up @@ -155,6 +156,7 @@ public int[] getAcceptableTokens() {
TokenTypes.RECORD_DEF,
TokenTypes.COMPACT_CTOR_DEF,
TokenTypes.LITERAL_SWITCH,
TokenTypes.LITERAL_CASE,
};
}

Expand Down Expand Up @@ -432,6 +434,9 @@ private static Details getDetails(DetailAST ast) {
case TokenTypes.LITERAL_SWITCH:
details = getDetailsForSwitch(ast);
break;
case TokenTypes.LITERAL_CASE:
details = getDetailsForCase(ast);
break;
default:
details = getDetailsForOthers(ast);
break;
Expand Down Expand Up @@ -460,6 +465,36 @@ private static Details getDetailsForSwitch(DetailAST switchNode) {
return new Details(lcurly, rcurly, nextToken, true);
}

/**
* Collects details about case statements.
*
* @param caseNode case statement to gather details about
* @return new Details about given case statement
*/
private static Details getDetailsForCase(DetailAST caseNode) {
final DetailAST caseParent = caseNode.getParent();
final int parentType = caseParent.getType();
final DetailAST statementList = caseParent.findFirstToken(TokenTypes.SLIST);
final Optional<DetailAST> lcurly;

if (parentType == TokenTypes.SWITCH_RULE) {
lcurly = Optional.ofNullable(statementList);
}
else {
lcurly = Optional.ofNullable(statementList)
.map(DetailAST::getFirstChild)
.filter(node -> node.getType() == TokenTypes.SLIST);
}
final DetailAST rcurly = lcurly.map(DetailAST::getLastChild)
.filter(child -> !isSwitchExpression(caseParent))
.orElse(null);
final Optional<DetailAST> nextToken =
Optional.ofNullable(lcurly.map(DetailAST::getNextSibling)
.orElseGet(() -> getNextToken(caseParent)));

return new Details(lcurly.orElse(null), rcurly, nextToken.orElse(null), true);
}

/**
* Check whether switch is expression or not.
*
Expand Down
Expand Up @@ -6,8 +6,8 @@
parent="com.puppycrawl.tools.checkstyle.TreeWalker">
<description>&lt;p&gt;
Checks the placement of right curly braces (&lt;code&gt;'}'&lt;/code&gt;) for code blocks. This check
supports if-else, try-catch-finally blocks, switch statements, while-loops, for-loops,
method definitions, class definitions, constructor definitions,
supports if-else, try-catch-finally blocks, switch statements, switch cases, while-loops,
for-loops, method definitions, class definitions, constructor definitions,
instance, static initialization blocks, annotation definitions and enum definitions.
For right curly brace of expression blocks of arrays, lambdas and class instances
please follow issue
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/google_checks.xml
Expand Up @@ -96,7 +96,7 @@
<property name="tokens"
value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF, INTERFACE_DEF, RECORD_DEF,
COMPACT_CTOR_DEF, LITERAL_SWITCH"/>
COMPACT_CTOR_DEF, LITERAL_SWITCH, LITERAL_CASE"/>
</module>
<module name="SuppressionXpathSingleFilter">
<!-- suppresion is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
Expand Down
Expand Up @@ -827,4 +827,158 @@ public void testSwitchExpression7() throws Exception {
verifyWithInlineConfigParser(
getNonCompilablePath("InputRightCurlyTestSwitchExpression7.java"), expected);
}

@Test
public void testCaseBlocksInSwitchStatementAlone() throws Exception {
final String[] expected = {
"33:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"44:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"73:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"78:44: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 44),
"90:39: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 39),
"97:42: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 42),
"107:35: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 35),
};
verifyWithInlineConfigParser(
getPath("InputRightCurlyCaseBlocksInSwitchStatementAlone.java"), expected);
}

@Test
public void testCaseBlocksInSwitchStatementAlone2() throws Exception {
final String[] expected = {
"17:15: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 15),
"26:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"38:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"41:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"49:24: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 24),
"49:45: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 45),
"57:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"68:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"68:26: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 26),
"75:34: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 34),
"75:47: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 47),
"82:23: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 23),
"102:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
};
verifyWithInlineConfigParser(
getPath("InputRightCurlyCaseBlocksInSwitchStatementAlone2.java"), expected);
}

@Test
public void testCaseBlocksInSwitchStatementAloneOrSingleLine() throws Exception {
final String[] expected = {
"33:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"44:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"73:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"78:51: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 51),
};
verifyWithInlineConfigParser(
getPath("InputRightCurlyCaseBlocksInSwitchStatementAloneOrSingleline.java"),
expected);
}

@Test
public void testCaseBlocksInSwitchStatementAloneOrSingle2() throws Exception {
final String[] expected = {
"18:15: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 15),
"27:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"39:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"42:15: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 15),
"50:23: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 23),
"71:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"80:23: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 23),
"100:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
};
verifyWithInlineConfigParser(
getPath("InputRightCurlyCaseBlocksInSwitchStatementAloneOrSingleline2.java"),
expected);
}

@Test
public void testCaseBlocksInSwitchStatementSame() throws Exception {
final String[] expected = {
"33:16: " + getCheckMessage(MSG_KEY_LINE_BREAK_BEFORE, "}", 16),
"44:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"73:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"78:51: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 51),
"106:23: " + getCheckMessage(MSG_KEY_LINE_BREAK_BEFORE, "}", 23),
};
verifyWithInlineConfigParser(
getPath("InputRightCurlyCaseBlocksInSwitchStatementSame.java"), expected);
}

@Test
public void testCaseBlocksInSwitchStatementSame2() throws Exception {
final String[] expected = {
"18:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"27:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"39:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"42:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"50:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"70:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"77:34: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 34),
"77:47: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 47),
"85:23: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 23),
"103:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
};
verifyWithInlineConfigParser(
getPath("InputRightCurlyCaseBlocksInSwitchStatementSame2.java"), expected);
}

@Test
public void testCaseBlocksWithSwitchRuleAlone() throws Exception {
final String[] expected = {
"32:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"44:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"45:27: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 27),
"56:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"69:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"74:46: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 46),
"83:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"83:36: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 36),
"93:31: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 31),
"94:31: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 31),
};
verifyWithInlineConfigParser(
getNonCompilablePath("InputRightCurlyCaseBlocksWithSwitchRuleAlone.java"),
expected);
}

@Test
public void testCaseBlocksWithSwitchRuleAloneOrSingleLine() throws Exception {

final String[] expected = {
"27:19: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 19),
"41:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"53:23: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 23),
"54:27: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 27),
"64:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"77:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"82:46: " + git getCheckMessage(MSG_KEY_LINE_ALONE, "}", 46),
"91:13: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 13),
"102:31: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 31),
};
final String fileName = "InputRightCurlyCaseBlocksWithSwitchRuleAloneOrSingleline.java";
verifyWithInlineConfigParser(getNonCompilablePath(fileName), expected);
}

@Test
public void testCaseBlocksWithSwitchExpressionAlone() throws Exception {
final String[] expected = {
"63:31: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 31),
"86:42: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 42),
};
final String fileName = "InputRightCurlyCaseBlocksWithSwitchExpressionAlone.java";
verifyWithInlineConfigParser(getNonCompilablePath(fileName), expected);
}

@Test
public void testCaseBlocksWithSwitchExpressionAloneOrSingleLine() throws Exception {
final String[] expected = {
"63:31: " + getCheckMessage(MSG_KEY_LINE_ALONE, "}", 31),
};
final String fileName =
"InputRightCurlyCaseBlocksWithSwitchExpressionAloneOrSingleline.java";
verifyWithInlineConfigParser(getNonCompilablePath(fileName), expected);
}
}

0 comments on commit bf6da15

Please sign in to comment.