[java-dfa] Support empty component in STR template (IDEA-327154)

GitOrigin-RevId: b7ef312b3b35b8aa7aa55ecb1f6bdc7a99c3aac6
This commit is contained in:
Tagir Valeev
2023-09-06 18:13:49 +00:00
committed by intellij-monorepo-bot
parent c1d8be0b63
commit 00eb284508
3 changed files with 16 additions and 4 deletions
@@ -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();
@@ -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;
@@ -38,6 +38,8 @@ class Main {
if (<warning descr="Condition 's3.equals(\"a123b\")' is always 'true'">s3.equals("a123b")</warning>) {}
String s4 = STR."x = \{x}";
if (<warning descr="Condition 's4.length() >= 5 && s4.length() <= 15' is always 'true'"><warning descr="Condition 's4.length() >= 5' is always 'true'">s4.length() >= 5</warning> && <warning descr="Condition 's4.length() <= 15' is always 'true' when reached">s4.length() <= 15</warning></warning>) {}
String s5 = STR."hello\{}";
if (<warning descr="Condition 's5.equals(\"hellonull\")' is always 'true'">s5.equals("hellonull")</warning>) {}
}
void testIncomplete() {