mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DfaExpressionFactory: do not eagerly resolve qualifier for special field
Fixes performance degradation on long method chains SpecialField API polishing
This commit is contained in:
-7
@@ -1123,13 +1123,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
if (constValue != null) {
|
||||
return constValue;
|
||||
}
|
||||
DfaVariableValue qualifier = var.getQualifier();
|
||||
if (qualifier != null) {
|
||||
DfaValue value = SpecialField.tryCreateValue(qualifier, var.getPsiVariable());
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
|
||||
+17
-15
@@ -7,7 +7,10 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.MethodUtils;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -22,10 +25,10 @@ import static com.intellij.codeInspection.dataFlow.MethodContract.ValueConstrain
|
||||
public enum SpecialField implements DfaVariableSource {
|
||||
ARRAY_LENGTH(null, "length", true, LongRangeSet.indexRange()) {
|
||||
@Override
|
||||
public boolean isMyAccessor(PsiModifierListOwner accessor) {
|
||||
return accessor instanceof PsiField && "length".equals(((PsiField)accessor).getName()) &&
|
||||
boolean isMyAccessor(PsiMember accessor) {
|
||||
return accessor instanceof PsiField && "length".equals(accessor.getName()) &&
|
||||
JavaPsiFacade.getElementFactory(accessor.getProject()).getArrayClass(PsiUtil.getLanguageLevel(accessor)) ==
|
||||
((PsiField)accessor).getContainingClass();
|
||||
accessor.getContainingClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,21 +101,20 @@ public enum SpecialField implements DfaVariableSource {
|
||||
* @param accessor accessor to test to test
|
||||
* @return true if supplied accessor can be used to read this special field
|
||||
*/
|
||||
public boolean isMyAccessor(PsiModifierListOwner accessor) {
|
||||
boolean isMyAccessor(PsiMember accessor) {
|
||||
return accessor instanceof PsiMethod && MethodUtils.methodMatches((PsiMethod)accessor, myClassName, null, myMethodName);
|
||||
}
|
||||
|
||||
public static DfaValue tryCreateValue(DfaValue qualifier, PsiElement element) {
|
||||
if (qualifier == null) return null;
|
||||
DfaValueFactory factory = qualifier.getFactory();
|
||||
if (factory == null) return null;
|
||||
if (!(element instanceof PsiVariable) && !(element instanceof PsiMethod)) return null;
|
||||
for (SpecialField field : values()) {
|
||||
if (field.isMyAccessor((PsiModifierListOwner)element)) {
|
||||
return field.createValue(factory, qualifier);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
/**
|
||||
* Finds a special field which corresponds to given accessor (method or field)
|
||||
* @param accessor accessor to find a special field for
|
||||
* @return found special field or null if accessor cannot be used to access a special field
|
||||
*/
|
||||
@Contract("null -> null")
|
||||
@Nullable
|
||||
public static SpecialField findSpecialField(PsiElement accessor) {
|
||||
if (!(accessor instanceof PsiMember)) return null;
|
||||
return StreamEx.of(values()).findFirst(sf -> sf.isMyAccessor((PsiMember)accessor)).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -503,9 +503,9 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
||||
|
||||
if (methodType == MethodCallInstruction.MethodType.METHOD_REFERENCE_CALL && qualifierValue instanceof DfaVariableValue) {
|
||||
PsiMethod method = instruction.getTargetMethod();
|
||||
DfaValue value = SpecialField.tryCreateValue(qualifierValue, method);
|
||||
if (value != null) {
|
||||
return value;
|
||||
SpecialField field = SpecialField.findSpecialField(method);
|
||||
if (field != null) {
|
||||
return field.createValue(factory, qualifierValue);
|
||||
}
|
||||
DfaVariableSource source = DfaExpressionFactory.getAccessedVariableOrGetter(method);
|
||||
if (source != null) {
|
||||
|
||||
+1
-2
@@ -199,8 +199,7 @@ public class MethodCallInstruction extends Instruction {
|
||||
|
||||
private boolean isPureCall() {
|
||||
if (myTargetMethod == null) return false;
|
||||
return ControlFlowAnalyzer.isPure(myTargetMethod) ||
|
||||
Arrays.stream(SpecialField.values()).anyMatch(sf -> sf.isMyAccessor(myTargetMethod));
|
||||
return ControlFlowAnalyzer.isPure(myTargetMethod) || SpecialField.findSpecialField(myTargetMethod) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+4
-1
@@ -197,8 +197,11 @@ public class DfaExpressionFactory {
|
||||
private DfaValue createFromSpecialField(PsiReferenceExpression refExpr) {
|
||||
PsiElement target = refExpr.resolve();
|
||||
if (!(target instanceof PsiModifierListOwner)) return null;
|
||||
SpecialField sf = SpecialField.findSpecialField(target);
|
||||
if (sf == null) return null;
|
||||
DfaVariableValue qualifier = getQualifierVariable(refExpr.getQualifierExpression());
|
||||
return SpecialField.tryCreateValue(qualifier, target);
|
||||
if (qualifier == null) return null;
|
||||
return sf.createValue(myFactory, qualifier);
|
||||
}
|
||||
|
||||
@Contract("null -> null")
|
||||
|
||||
Reference in New Issue
Block a user