From 00eb2845083139b98ae785c7b70aaaa99236b140 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 6 Sep 2023 10:34:46 +0200 Subject: [PATCH] [java-dfa] Support empty component in STR template (IDEA-327154) GitOrigin-RevId: b7ef312b3b35b8aa7aa55ecb1f6bdc7a99c3aac6 --- .../dataFlow/java/ControlFlowAnalyzer.java | 12 +++++++++--- .../dataFlow/java/inst/StringConcatInstruction.java | 6 +++++- .../inspection/dataFlow/fixture/StringTemplates.java | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/ControlFlowAnalyzer.java index fe07ce3cd083..7add501df752 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/ControlFlowAnalyzer.java @@ -37,6 +37,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaControlTransferValue.Trap; import com.intellij.openapi.diagnostic.Logger; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.java.PsiEmptyExpressionImpl; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.*; @@ -1288,7 +1289,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { for (int i = 0; i < count; i++) { PsiFragment fragment = fragments.get(i); Object value = fragment.getValue(); - if (value instanceof String) { + if (value != null) { addInstruction(new PushValueInstruction(DfTypes.referenceConstant(value, stringType))); } else { pushUnknown(); @@ -1296,12 +1297,17 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { if (i > 0) { addInstruction(new StringConcatInstruction(null, constraint)); } - expressions.get(i).accept(this); + PsiExpression embeddedExpression = expressions.get(i); + if (embeddedExpression instanceof PsiEmptyExpressionImpl) { + addInstruction(new PushValueInstruction(DfTypes.NULL)); + } else { + embeddedExpression.accept(this); + } addInstruction(new StringConcatInstruction(null, constraint)); } PsiFragment lastFragment = fragments.get(count); Object value = lastFragment.getValue(); - if (value instanceof String) { + if (value != null) { addInstruction(new PushValueInstruction(DfTypes.referenceConstant(value, stringType))); } else { pushUnknown(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/StringConcatInstruction.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/StringConcatInstruction.java index 21811b3318c6..5465561dd26e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/StringConcatInstruction.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/java/inst/StringConcatInstruction.java @@ -69,7 +69,11 @@ public class StringConcatInstruction extends EvalInstruction { @Nullable private static String getString(@NotNull DfaMemoryState state, DfaValue value) { - Object constant = state.getDfType(value).getConstantOfType(Object.class); + DfType dfType = state.getDfType(value); + if (dfType.equals(NULL)) { + return "null"; + } + Object constant = dfType.getConstantOfType(Object.class); // Do not process float/double constants, as their string representation may depend on JDK version return constant instanceof String || constant instanceof Integer || constant instanceof Long || constant instanceof Boolean ? constant.toString() : null; diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/StringTemplates.java b/java/java-tests/testData/inspection/dataFlow/fixture/StringTemplates.java index 8ae43cff902a..511ec4bb9ccd 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/StringTemplates.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/StringTemplates.java @@ -38,6 +38,8 @@ class Main { if (s3.equals("a123b")) {} String s4 = STR."x = \{x}"; if (s4.length() >= 5 && s4.length() <= 15) {} + String s5 = STR."hello\{}"; + if (s5.equals("hellonull")) {} } void testIncomplete() {