mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
GuessManagerImpl: more precise slow-path selection on lambda parameters
Fixes IDEA-190133 Slow completion of lambda parameter
This commit is contained in:
+8
-16
@@ -343,32 +343,24 @@ public class GuessManagerImpl extends GuessManager {
|
||||
if (expr.getType() instanceof PsiPrimitiveType) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<PsiType> result = null;
|
||||
PsiExpression place = PsiUtil.skipParenthesizedExprDown(expr);
|
||||
if (place == null) return Collections.emptyList();
|
||||
if (place instanceof PsiReferenceExpression) {
|
||||
PsiElement target = ((PsiReferenceExpression)place).resolve();
|
||||
if (target instanceof PsiParameter) {
|
||||
PsiElement parent = target.getParent();
|
||||
if (parent instanceof PsiParameterList && parent.getParent() instanceof PsiLambdaExpression) {
|
||||
result = getTypesFromDfa(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
|
||||
List<PsiType> result = null;
|
||||
if (!ControlFlowAnalyzer.inlinerMayInferPreciseType(place)) {
|
||||
GuessTypeVisitor visitor = new GuessTypeVisitor(place);
|
||||
getTopmostBlock(place).accept(visitor);
|
||||
|
||||
if (visitor.isDfaNeeded()) {
|
||||
result = getTypesFromDfa(expr);
|
||||
}
|
||||
else {
|
||||
if (!visitor.isDfaNeeded()) {
|
||||
result = visitor.mySpecificType == null ?
|
||||
Collections.emptyList() : Collections.singletonList(tryGenerify(expr, visitor.mySpecificType));
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
result = getTypesFromDfa(expr);
|
||||
}
|
||||
if (result.equals(Collections.singletonList(expr.getType()))) {
|
||||
result = Collections.emptyList();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+8
@@ -2029,6 +2029,14 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
return variable.getSource() instanceof Synthetic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expression expression to test
|
||||
* @return true if some inliner may add constraints on the precise type of given expression
|
||||
*/
|
||||
public static boolean inlinerMayInferPreciseType(PsiExpression expression) {
|
||||
return Arrays.stream(INLINERS).anyMatch(inliner -> inliner.mayInferPreciseType(expression));
|
||||
}
|
||||
|
||||
private static final class Synthetic implements DfaVariableSource {
|
||||
private final int myLocation;
|
||||
|
||||
|
||||
+9
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInspection.dataFlow.inliner;
|
||||
|
||||
import com.intellij.codeInspection.dataFlow.CFGBuilder;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiMethodCallExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -33,4 +34,12 @@ public interface CallInliner {
|
||||
* If false is returned, inliner must not emit any instructions via builder.
|
||||
*/
|
||||
boolean tryInlineCall(@NotNull CFGBuilder builder, @NotNull PsiMethodCallExpression call);
|
||||
|
||||
/**
|
||||
* @param expression expression to test
|
||||
* @return true if this inliner may add constraints on the precise type of given expression
|
||||
*/
|
||||
default boolean mayInferPreciseType(@NotNull PsiExpression expression) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInspection.dataFlow.inliner;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.ig.psiutils.MethodCallUtils;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
class InlinerUtil {
|
||||
static boolean isLambdaChainParameterReference(PsiExpression expression, Predicate<PsiType> chainTypePredicate) {
|
||||
if(!(expression instanceof PsiReferenceExpression)) return false;
|
||||
PsiParameter target = tryCast(((PsiReferenceExpression)expression).resolve(), PsiParameter.class);
|
||||
if (target == null) return false;
|
||||
if (!(target.getParent() instanceof PsiParameterList)) return false;
|
||||
PsiLambdaExpression lambda = tryCast(target.getParent().getParent(), PsiLambdaExpression.class);
|
||||
if (lambda == null) return false;
|
||||
PsiExpressionList list = tryCast(PsiUtil.skipParenthesizedExprUp(lambda.getParent()), PsiExpressionList.class);
|
||||
if (list == null) return false;
|
||||
PsiMethodCallExpression call = tryCast(list.getParent(), PsiMethodCallExpression.class);
|
||||
if (call == null) return false;
|
||||
PsiMethodCallExpression qualifierCall = MethodCallUtils.getQualifierMethodCall(call);
|
||||
if (qualifierCall == null) return false;
|
||||
PsiType type = qualifierCall.getType();
|
||||
return type != null && chainTypePredicate.test(type);
|
||||
}
|
||||
}
|
||||
+6
@@ -28,6 +28,7 @@ import com.intellij.util.ObjectUtils;
|
||||
import com.siyeh.ig.callMatcher.CallMapper;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -265,4 +266,9 @@ public class OptionalChainInliner implements CallInliner {
|
||||
builder.checkNotNull(argument, NullabilityProblemKind.passingNullableToNotNullParameter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayInferPreciseType(@NotNull PsiExpression expression) {
|
||||
return InlinerUtil.isLambdaChainParameterReference(expression, TypeUtils::isOptional);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-4
@@ -19,9 +19,9 @@ import com.intellij.codeInspection.dataFlow.*;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValue;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.siyeh.ig.callMatcher.CallMapper;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import com.siyeh.ig.psiutils.MethodCallUtils;
|
||||
@@ -33,6 +33,7 @@ import java.util.Objects;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import static com.intellij.psi.CommonClassNames.*;
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
import static com.siyeh.ig.callMatcher.CallMatcher.*;
|
||||
|
||||
public class StreamChainInliner implements CallInliner {
|
||||
@@ -359,7 +360,7 @@ public class StreamChainInliner implements CallInliner {
|
||||
super(call, next, null);
|
||||
// Try to inline smoothly .flatMap(x -> stream().call().chain())
|
||||
PsiLambdaExpression lambda =
|
||||
ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(myCall.getArgumentList().getExpressions()[0]), PsiLambdaExpression.class);
|
||||
tryCast(PsiUtil.skipParenthesizedExprDown(myCall.getArgumentList().getExpressions()[0]), PsiLambdaExpression.class);
|
||||
Step chain = null;
|
||||
PsiParameter parameter = null;
|
||||
PsiExpression streamSource = null;
|
||||
@@ -639,7 +640,7 @@ public class StreamChainInliner implements CallInliner {
|
||||
|
||||
static void buildStreamCFG(CFGBuilder builder, Step firstStep, PsiExpression originalQualifier) {
|
||||
PsiType inType = StreamApiUtil.getStreamElementType(originalQualifier.getType());
|
||||
PsiMethodCallExpression sourceCall = ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(originalQualifier), PsiMethodCallExpression.class);
|
||||
PsiMethodCallExpression sourceCall = tryCast(PsiUtil.skipParenthesizedExprDown(originalQualifier), PsiMethodCallExpression.class);
|
||||
if(STREAM_GENERATE.test(sourceCall)) {
|
||||
PsiExpression fn = sourceCall.getArgumentList().getExpressions()[0];
|
||||
builder
|
||||
@@ -765,7 +766,7 @@ public class StreamChainInliner implements CallInliner {
|
||||
|
||||
private static Step createTerminalFromCollector(PsiMethodCallExpression call) {
|
||||
PsiMethodCallExpression collectorCall =
|
||||
ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(call.getArgumentList().getExpressions()[0]), PsiMethodCallExpression.class);
|
||||
tryCast(PsiUtil.skipParenthesizedExprDown(call.getArgumentList().getExpressions()[0]), PsiMethodCallExpression.class);
|
||||
if (COUNTING_COLLECTOR.matches(collectorCall)) {
|
||||
return new SumTerminalStep(call);
|
||||
}
|
||||
@@ -787,4 +788,9 @@ public class StreamChainInliner implements CallInliner {
|
||||
}
|
||||
return new UnknownTerminalStep(call);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayInferPreciseType(@NotNull PsiExpression expression) {
|
||||
return InlinerUtil.isLambdaChainParameterReference(expression, type -> InheritanceUtil.isInheritor(type, JAVA_UTIL_STREAM_STREAM));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user