Skip to content

Commit 54ebc25

Browse files
SONARJAVA-5621 Fix issue in CFG computation with generic record pattern (#5191)
1 parent 1f5b248 commit 54ebc25

2 files changed

Lines changed: 59 additions & 1 deletion

File tree

java-frontend/src/main/java/org/sonar/java/cfg/CFG.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import org.sonar.plugins.java.api.tree.NewArrayTree;
6969
import org.sonar.plugins.java.api.tree.NewClassTree;
7070
import org.sonar.plugins.java.api.tree.NullPatternTree;
71+
import org.sonar.plugins.java.api.tree.ParameterizedTypeTree;
7172
import org.sonar.plugins.java.api.tree.ParenthesizedTree;
7273
import org.sonar.plugins.java.api.tree.PatternInstanceOfTree;
7374
import org.sonar.plugins.java.api.tree.PatternTree;
@@ -88,6 +89,7 @@
8889
import org.sonar.plugins.java.api.tree.UnaryExpressionTree;
8990
import org.sonar.plugins.java.api.tree.VariableTree;
9091
import org.sonar.plugins.java.api.tree.WhileStatementTree;
92+
import org.sonar.plugins.java.api.tree.WildcardTree;
9193
import org.sonar.plugins.java.api.tree.YieldStatementTree;
9294
import org.sonarsource.analyzer.commons.collections.ListUtils;
9395

@@ -687,6 +689,20 @@ private void build(Tree tree) {
687689
DEFAULT_PATTERN:
688690
buildPattern((PatternTree) tree);
689691
break;
692+
case PARAMETERIZED_TYPE:
693+
var typeTree = (ParameterizedTypeTree) tree;
694+
build(typeTree.type());
695+
build(typeTree.typeArguments());
696+
break;
697+
case UNBOUNDED_WILDCARD,
698+
EXTENDS_WILDCARD,
699+
SUPER_WILDCARD:
700+
TypeTree bound = ((WildcardTree) tree).bound();
701+
if (bound != null) {
702+
build(bound);
703+
}
704+
currentBlock.elements.add(tree);
705+
break;
690706
default:
691707
throw new UnsupportedOperationException(tree.kind().name() + " " + ((JavaTree) tree).getLine());
692708
}

java-frontend/src/test/java/org/sonar/java/cfg/CFGTest.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import static org.sonar.plugins.java.api.tree.Tree.Kind.DEFAULT_PATTERN;
6060
import static org.sonar.plugins.java.api.tree.Tree.Kind.DO_STATEMENT;
6161
import static org.sonar.plugins.java.api.tree.Tree.Kind.EQUAL_TO;
62+
import static org.sonar.plugins.java.api.tree.Tree.Kind.EXTENDS_WILDCARD;
6263
import static org.sonar.plugins.java.api.tree.Tree.Kind.FOR_EACH_STATEMENT;
6364
import static org.sonar.plugins.java.api.tree.Tree.Kind.FOR_STATEMENT;
6465
import static org.sonar.plugins.java.api.tree.Tree.Kind.GREATER_THAN;
@@ -87,6 +88,7 @@
8788
import static org.sonar.plugins.java.api.tree.Tree.Kind.RECORD_PATTERN;
8889
import static org.sonar.plugins.java.api.tree.Tree.Kind.RETURN_STATEMENT;
8990
import static org.sonar.plugins.java.api.tree.Tree.Kind.STRING_LITERAL;
91+
import static org.sonar.plugins.java.api.tree.Tree.Kind.SUPER_WILDCARD;
9092
import static org.sonar.plugins.java.api.tree.Tree.Kind.SWITCH_EXPRESSION;
9193
import static org.sonar.plugins.java.api.tree.Tree.Kind.SWITCH_STATEMENT;
9294
import static org.sonar.plugins.java.api.tree.Tree.Kind.SYNCHRONIZED_STATEMENT;
@@ -95,6 +97,7 @@
9597
import static org.sonar.plugins.java.api.tree.Tree.Kind.TYPE_CAST;
9698
import static org.sonar.plugins.java.api.tree.Tree.Kind.TYPE_PATTERN;
9799
import static org.sonar.plugins.java.api.tree.Tree.Kind.UNARY_MINUS;
100+
import static org.sonar.plugins.java.api.tree.Tree.Kind.UNBOUNDED_WILDCARD;
98101
import static org.sonar.plugins.java.api.tree.Tree.Kind.VARIABLE;
99102
import static org.sonar.plugins.java.api.tree.Tree.Kind.WHILE_STATEMENT;
100103
import static org.sonar.plugins.java.api.tree.Tree.Kind.YIELD_STATEMENT;
@@ -403,7 +406,10 @@ public ElementChecker(final Tree.Kind kind) {
403406
TYPE_PATTERN,
404407
GUARDED_PATTERN,
405408
DEFAULT_PATTERN,
406-
RECORD_PATTERN:
409+
RECORD_PATTERN,
410+
UNBOUNDED_WILDCARD,
411+
SUPER_WILDCARD,
412+
EXTENDS_WILDCARD:
407413
break;
408414
default:
409415
throw new IllegalArgumentException("Unsupported element kind: " + kind);
@@ -3149,6 +3155,42 @@ void throw_statement_within_try_catch() {
31493155

31503156
}
31513157

3158+
@Test
3159+
void generic_record_pattern() {
3160+
CFG cfg = buildCFG("""
3161+
private static boolean testGen3(GenBase<Integer, String> o) {
3162+
return o instanceof GenRecord1<?, ? super Integer, ? extends CharSequence>(String a, Integer i, CharSequence s) && i == 3 && s.isEmpty();
3163+
}
3164+
""");
3165+
3166+
CFGChecker cfgChecker = checker(
3167+
block(
3168+
element(IDENTIFIER, "o"),
3169+
element(RECORD_PATTERN),
3170+
element(UNBOUNDED_WILDCARD),
3171+
element(SUPER_WILDCARD),
3172+
element(IDENTIFIER, "Integer"),
3173+
element(EXTENDS_WILDCARD),
3174+
element(IDENTIFIER, "CharSequence"),
3175+
element(IDENTIFIER, "GenRecord1"),
3176+
element(TYPE_PATTERN),
3177+
element(VARIABLE, "a"),
3178+
element(TYPE_PATTERN),
3179+
element(VARIABLE, "i"),
3180+
element(TYPE_PATTERN),
3181+
element(VARIABLE, "s"),
3182+
element(PATTERN_INSTANCE_OF)
3183+
).terminator(CONDITIONAL_AND).ifTrue(4).ifFalse(3),
3184+
block(element(IDENTIFIER, "i"), element(INT_LITERAL, "3"), element(EQUAL_TO))
3185+
.successors(3),
3186+
terminator(CONDITIONAL_AND).ifTrue(2).ifFalse(1),
3187+
block(element(IDENTIFIER, "s"), element(METHOD_INVOCATION))
3188+
.successors(1),
3189+
terminator(RETURN_STATEMENT).successors(0));
3190+
3191+
cfgChecker.check(cfg);
3192+
}
3193+
31523194
@Test
31533195
void build_partial_cfg_with_break() {
31543196
build_partial_cfg("break");

0 commit comments

Comments
 (0)