mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java] IDEA-391221 Support JEP 532. Detect "MatchException" with primitive type patterns
(cherry picked from commit 79f111cf01c2a56d8cdab062a2be376cbedcaf62) GitOrigin-RevId: 300914c986a54438394eaa52d48c0a92f610c12d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b8bcd55bae
commit
0fd4c1187d
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeserver.core;
|
||||
|
||||
import com.intellij.codeInsight.ExpressionUtil;
|
||||
@@ -26,6 +26,7 @@ import com.intellij.psi.PsiKeyword;
|
||||
import com.intellij.psi.PsiLiteralExpression;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiPattern;
|
||||
import com.intellij.psi.PsiPatternVariable;
|
||||
import com.intellij.psi.PsiPrimitiveType;
|
||||
import com.intellij.psi.PsiRecordComponent;
|
||||
import com.intellij.psi.PsiReferenceExpression;
|
||||
@@ -33,6 +34,7 @@ import com.intellij.psi.PsiStatement;
|
||||
import com.intellij.psi.PsiSwitchBlock;
|
||||
import com.intellij.psi.PsiSwitchLabelStatementBase;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.PsiTypeTestPattern;
|
||||
import com.intellij.psi.PsiTypes;
|
||||
import com.intellij.psi.util.ConstantExpressionUtil;
|
||||
import com.intellij.psi.util.JavaPsiPatternUtil;
|
||||
@@ -501,6 +503,20 @@ public final class JavaPsiSwitchUtil {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (PsiUtil.isAvailable(JavaFeature.PRIMITIVE_TYPES_IN_PATTERNS, deconstructionComponent) &&
|
||||
deconstructionComponent instanceof PsiTypeTestPattern testPattern) {
|
||||
PsiPatternVariable patternVariable = testPattern.getPatternVariable();
|
||||
if (patternVariable != null && patternVariable.getType() instanceof PsiPrimitiveType) {
|
||||
if (!hasDominated(switchBlock,
|
||||
topLevelDeconstruction,
|
||||
deconstructionComponent,
|
||||
recordComponentClass,
|
||||
skipDominatingElements)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class MatchExceptionWithPrimitivePatterns {
|
||||
|
||||
interface Case {
|
||||
String run();
|
||||
}
|
||||
|
||||
static void check(String name, Case c) {
|
||||
try {
|
||||
System.out.println(name + " => OK[" + c.run() + "]");
|
||||
}
|
||||
catch (Throwable t) {
|
||||
System.out.println(name + " => " + t.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
record Point(int x, int y) {
|
||||
}
|
||||
|
||||
record IntBox(@Nullable Integer v) {
|
||||
}
|
||||
|
||||
record LongBox(@Nullable Long v) {
|
||||
}
|
||||
|
||||
record DoubleBox(@Nullable Double v) {
|
||||
}
|
||||
|
||||
record BoolBox(@Nullable Boolean v) {
|
||||
}
|
||||
|
||||
record WidenBox(@Nullable Integer v) {
|
||||
} // Integer component matched by a wider primitive
|
||||
|
||||
record PointBox(@Nullable Point p) {
|
||||
}
|
||||
|
||||
static void main() {
|
||||
check("primInt", () -> primInt(new IntBox(null)));
|
||||
check("primIntWithUncond", () -> primIntWithUncond(new IntBox(null)));
|
||||
check("primLong", () -> primLong(new LongBox(null)));
|
||||
check("primLongWithUncond", () -> primLongWithUncond(new LongBox(null)));
|
||||
check("primDouble", () -> primDouble(new DoubleBox(null)));
|
||||
check("primDoubleWithUncond", () -> primDoubleWithUncond(new DoubleBox(null)));
|
||||
check("primBoolean", () -> primBoolean(new BoolBox(null)));
|
||||
check("primWiden", () -> primWiden(new WidenBox(null)));
|
||||
|
||||
check("recordComponent_control", () -> recordComponent_control(new PointBox(null)));
|
||||
check("typePattern_control", () -> typePattern_control(new PointBox(null)));
|
||||
}
|
||||
|
||||
static String primInt(IntBox b) {
|
||||
return switch (b) {
|
||||
case <warning descr="Switch label 'IntBox(int p)' is the only reachable in the whole switch">IntBox(<warning descr="Pattern matching may throw 'MatchException'">int p</warning>)</warning> -> "int:" + p;
|
||||
};
|
||||
}
|
||||
|
||||
static String primIntWithUncond(IntBox b) {
|
||||
return switch (b) {
|
||||
case IntBox(int p) -> "int:" + p;
|
||||
default -> "primIntWithUncond(" + b + ")";
|
||||
};
|
||||
}
|
||||
|
||||
static String primLong(LongBox b) {
|
||||
return switch (b) {
|
||||
case <warning descr="Switch label 'LongBox(long p)' is the only reachable in the whole switch">LongBox(<warning descr="Pattern matching may throw 'MatchException'">long p</warning>)</warning> -> "long:" + p;
|
||||
};
|
||||
}
|
||||
|
||||
static String primLongWithUncond(LongBox b) {
|
||||
return switch (b) {
|
||||
case LongBox(long p) -> "long:" + p;
|
||||
case LongBox(Long v) -> "primLongWithUncond(" + v + ")";
|
||||
};
|
||||
}
|
||||
|
||||
static String primDouble(DoubleBox b) {
|
||||
return switch (b) {
|
||||
case <warning descr="Switch label 'DoubleBox(double p)' is the only reachable in the whole switch">DoubleBox(<warning descr="Pattern matching may throw 'MatchException'">double p</warning>)</warning> -> "double:" + p;
|
||||
};
|
||||
}
|
||||
|
||||
static String primDoubleWithUncond(DoubleBox b) {
|
||||
return switch (b) {
|
||||
case DoubleBox(double p) -> "double:" + p;
|
||||
case DoubleBox(Object p) -> "primDoubleWithUncond(" + p + ")";
|
||||
};
|
||||
}
|
||||
|
||||
static String primBoolean(BoolBox b) {
|
||||
return switch (b) {
|
||||
case <warning descr="Switch label 'BoolBox(boolean p)' is the only reachable in the whole switch">BoolBox(<warning descr="Pattern matching may throw 'MatchException'">boolean p</warning>)</warning> -> "bool:" + p;
|
||||
};
|
||||
}
|
||||
|
||||
static String primWiden(WidenBox b) {
|
||||
return switch (b) {
|
||||
case WidenBox(<warning descr="Pattern matching may throw 'MatchException'">float p</warning>) -> "widen float:" + p;
|
||||
case WidenBox(double p) -> "widen:" + p;
|
||||
};
|
||||
}
|
||||
|
||||
static String recordComponent_control(PointBox b) {
|
||||
return switch (b) {
|
||||
case <warning descr="Switch label 'PointBox(Point(var x, var y))' is the only reachable in the whole switch">PointBox(<warning descr="Pattern matching may throw 'MatchException'">Point(var x, var y)</warning>)</warning> -> "pt:" + x + "," + y;
|
||||
};
|
||||
}
|
||||
|
||||
static String typePattern_control(PointBox b) {
|
||||
return switch (b) {
|
||||
case <warning descr="Switch label 'PointBox(Point p)' is the only reachable in the whole switch">PointBox(Point p)</warning> -> "p=" + p;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@ public class SwitchWithPrimitive {
|
||||
|
||||
public static int exhaustiveByPrimitives(RecordCharObj source) {
|
||||
switch (source) {
|
||||
case RecordCharObj(char source1) -> System.out.println("1");
|
||||
case <warning descr="Switch label 'RecordCharObj(int source1)' is unreachable">RecordCharObj(int source1)</warning> -> System.out.println("1");
|
||||
case <warning descr="Switch label 'RecordCharObj(char source1)' is the only reachable in the whole switch">RecordCharObj(char source1)</warning> -> System.out.println("1");
|
||||
case RecordCharObj(int source1) -> System.out.println("1");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
+3
-1
@@ -30,6 +30,8 @@ public class DataFlowInspection26Test extends DataFlowInspectionTestCase {
|
||||
public V get();
|
||||
}
|
||||
""");
|
||||
doTestWith((dfi, cvi) -> dfi.TREAT_UNKNOWN_MEMBERS_AS_NULLABLE = false);
|
||||
doTestWith((dfi, _) -> dfi.TREAT_UNKNOWN_MEMBERS_AS_NULLABLE = false);
|
||||
}
|
||||
|
||||
public void testMatchExceptionWithPrimitivePatterns() { doTest(); }
|
||||
}
|
||||
Reference in New Issue
Block a user