Collections.emptyList/set/map as constants (IDEA-227637)

GitOrigin-RevId: c9ea8de1bc8a856de3e5c5608a5ffaa766a035b4
This commit is contained in:
Tagir Valeev
2019-12-12 12:22:26 +07:00
committed by intellij-monorepo-bot
parent 4dd9ac1255
commit 70d68ee998
6 changed files with 68 additions and 1 deletions

View File

@@ -26,6 +26,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import static com.intellij.codeInspection.dataFlow.SpecialField.*;
import static com.intellij.codeInspection.dataFlow.types.DfTypes.LOCAL_OBJECT;
@@ -97,8 +98,10 @@ class CustomMethodHandlers {
(args, memState, factory, method) -> numberAsString(args, memState, 1, Long.SIZE))
.register(instanceCall(JAVA_LANG_ENUM, "name").parameterCount(0),
(args, memState, factory, method) -> enumName(args.myQualifier, memState, factory, method.getReturnType()))
.register(staticCall(JAVA_UTIL_COLLECTIONS, "emptyList", "emptySet", "emptyMap").parameterCount(0),
(args, memState, factory, method) -> getEmptyCollectionConstant(factory, method))
.register(anyOf(
staticCall(JAVA_UTIL_COLLECTIONS, "emptyList", "emptySet", "emptyMap", "singleton", "singletonList", "singletonMap"),
staticCall(JAVA_UTIL_COLLECTIONS, "singleton", "singletonList", "singletonMap"),
staticCall(JAVA_UTIL_LIST, "of"),
staticCall(JAVA_UTIL_SET, "of"),
staticCall(JAVA_UTIL_MAP, "of", "ofEntries"),
@@ -250,6 +253,15 @@ class CustomMethodHandlers {
return asList ? result.meet(LOCAL_OBJECT) : result;
}
private static DfType getEmptyCollectionConstant(DfaValueFactory factory, PsiMethod method) {
String fieldName = "EMPTY_" + method.getName().substring("empty".length()).toUpperCase(Locale.ROOT);
PsiClass collectionsClass = method.getContainingClass();
if (collectionsClass == null) return TOP;
PsiField field = collectionsClass.findFieldByName(fieldName, false);
if (field == null) return TOP;
return DfTypes.constant(field, factory.createDfaType(field.getType()));
}
@NotNull
private static DfType substring(DfaCallArguments args, DfaMemoryState state, DfaValueFactory factory, PsiType stringType) {
if (stringType == null || !stringType.equalsToText(JAVA_LANG_STRING)) return TOP;

View File

@@ -27,6 +27,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Predicate;
import static com.intellij.psi.CommonClassNames.JAVA_UTIL_COLLECTIONS;
import static com.intellij.util.ObjectUtils.tryCast;
/**
@@ -381,6 +382,13 @@ public class DfaUtil {
return ContainerUtil.concat(rangeContracts, contracts);
}
public static boolean isEmptyCollectionConstantField(@Nullable PsiVariable var) {
if (!(var instanceof PsiField)) return false;
PsiField field = (PsiField)var;
return field.getName().startsWith("EMPTY_") && field.getContainingClass() != null &&
JAVA_UTIL_COLLECTIONS.equals(field.getContainingClass().getQualifiedName());
}
private static class ValuableInstructionVisitor extends StandardInstructionVisitor {
final Map<PsiElement, PlaceResult> myResults = new HashMap<>();

View File

@@ -108,6 +108,15 @@ public enum SpecialField implements VariableDescriptor {
return accessor instanceof PsiMethod && SIZE_METHODS.methodMatches((PsiMethod)accessor);
}
@NotNull
@Override
public DfType fromConstant(@Nullable Object obj) {
if (obj instanceof PsiField && DfaUtil.isEmptyCollectionConstantField((PsiVariable)obj)) {
return DfTypes.intValue(0);
}
return super.fromConstant(obj);
}
@NotNull
@Override
public DfaValue createValue(@NotNull DfaValueFactory factory, @Nullable DfaValue qualifier, boolean forAccessor) {

View File

@@ -217,6 +217,9 @@ public class DfaValueFactory {
DfaValue unboxed = getConstant(boo, PsiType.BOOLEAN);
return getBoxedFactory().createBoxed(unboxed, PsiType.BOOLEAN.getBoxedType(variable));
}
if (DfaUtil.isEmptyCollectionConstantField(variable)) {
return getConstant(variable, type);
}
PsiExpression initializer =
variable instanceof PsiFieldImpl ? ((PsiFieldImpl)variable).getDetachedInitializer() : variable.getInitializer();
initializer = PsiUtil.skipParenthesizedExprDown(initializer);