Skip to content

Commit

Permalink
Issue checkstyle#11187: OperatorWrapCheck throws NPE on guarded patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
nrmancuso committed Jan 20, 2022
1 parent c504a7c commit f0e1eca
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,9 @@ private static DetailAST getLeftNode(DetailAST node) {
if (node.getFirstChild() == null || isAssignToVariable(node)) {
result = node.getPreviousSibling();
}
else if (isInPatternDefinition(node)) {
result = node.getFirstChild();
}
else {
result = adjustParens(node.getFirstChild(), DetailAST::getNextSibling);
}
Expand All @@ -399,6 +402,21 @@ private static DetailAST getLeftNode(DetailAST node) {
return result;
}

/**
* Ascends AST to determine if given node is part of a pattern
* definition.
*
* @param node the node to check
* @return true if node is in pattern definition
*/
private static boolean isInPatternDefinition(DetailAST node) {
DetailAST parent = node.getParent();
while (parent != null && parent.getType() != TokenTypes.PATTERN_DEF) {
parent = parent.getParent();
}
return parent != null;
}

/**
* Returns the right neighbour of a binary operator. This is the leftmost
* grandchild of the right child or sibling. For the ternary operator this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,24 @@ public void testArraysAssign() throws Exception {
getPath("InputOperatorWrapArrayAssign.java"), expected);
}

@Test
public void testGuardedPattern() throws Exception {
final String[] expected = {
"52:30: " + getCheckMessage(MSG_LINE_NEW, "&&"),
"54:31: " + getCheckMessage(MSG_LINE_NEW, "&&"),
"62:30: " + getCheckMessage(MSG_LINE_NEW, "&&"),
"64:31: " + getCheckMessage(MSG_LINE_NEW, "&&"),
"71:23: " + getCheckMessage(MSG_LINE_NEW, "&&"),
"72:43: " + getCheckMessage(MSG_LINE_NEW, "&&"),
"75:30: " + getCheckMessage(MSG_LINE_NEW, "&&"),
"76:44: " + getCheckMessage(MSG_LINE_NEW, "&&"),
"77:34: " + getCheckMessage(MSG_LINE_NEW, "&&"),
};

verifyWithInlineConfigParser(
getNonCompilablePath("InputOperatorWrapGuardedPatterns.java"), expected);
}

@Test
public void testInvalidOption() throws Exception {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
OperatorWrap
option = (default)nl
tokens = (default)QUESTION, COLON, EQUAL, NOT_EQUAL, DIV, PLUS, MINUS, STAR, MOD, \
SR, BSR, GE, GT, SL, LE, LT, BXOR, BOR, LOR, BAND, LAND, TYPE_EXTENSION_AND, \
LITERAL_INSTANCEOF
*/
//non-compiled with javac: Compilable with Java17

package com.puppycrawl.tools.checkstyle.checks.whitespace.operatorwrap;

public class InputOperatorWrapGuardedPatterns {
String typeGuardAfterParenthesizedTrueSwitchStatement1(Object o) {
switch (o) {
case (Integer i)
&& i == 0: o = String.valueOf(i); return "true"; // ok
case ((Integer i)
&& i == 2): o = String.valueOf(i); return "second"; // ok
case Object x: return "any";
}
}

String typeGuardAfterParenthesizedTrueSwitchExpression1(Object o) {
return switch (o) {
case (Integer i)
&& i == 0: o = String.valueOf(i); yield "true"; // ok
case ((Integer i)
&& i == 2): o = String.valueOf(i); yield "second"; // ok
case Object x: yield "any";
};
}

String typeGuardAfterParenthesizedTrueIfStatement1(Object o) {
if (o != null
&& o instanceof ((Integer i) // ok
&& i == 0)) { // ok
return "true";
} else if (o != null
&& o instanceof (((Integer i) // ok
&& i == 2)) // ok
&& (o = i) != null) { // ok
return "second";
} else {
return "any";
}
}

String typeGuardAfterParenthesizedTrueSwitchStatement2(Object o) {
switch (o) {
case (Integer i) && // violation
i == 0: o = String.valueOf(i); return "true";
case ((Integer i) && // violation
i == 2): o = String.valueOf(i); return "second";
case Object x: return "any";
}
}

String typeGuardAfterParenthesizedTrueSwitchExpression2(Object o) {
return switch (o) {
case (Integer i) && // violation
i == 0: o = String.valueOf(i); yield "true";
case ((Integer i) && // violation
i == 2): o = String.valueOf(i); yield "second";
case Object x: yield "any";
};
}

String typeGuardAfterParenthesizedTrueIfStatement2(Object o) {
if (o != null && // violation
o instanceof ((Integer i) && // violation
i == 0)) {
return "true";
} else if (o != null && // violation
o instanceof (((Integer i) && // violation
i == 2)) && // violation
(o = i) != null) {
return "second";
} else {
return "any";
}
}
}

0 comments on commit f0e1eca

Please sign in to comment.