mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Moved isResolvedToSeveralMethods() to PyTypeChecker
This commit is contained in:
@@ -10,13 +10,14 @@ import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
import com.jetbrains.python.documentation.PythonDocumentationProvider;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import com.jetbrains.python.psi.types.*;
|
||||
import com.jetbrains.python.psi.types.PyGenericType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.PyTypeChecker;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -44,11 +45,7 @@ public class PyTypeCheckerInspection extends PyInspection {
|
||||
public void visitPyCallExpression(PyCallExpression node) {
|
||||
final PyExpression callee = node.getCallee();
|
||||
if (callee instanceof PyQualifiedExpression) {
|
||||
final PyQualifiedExpression qualified = (PyQualifiedExpression)callee;
|
||||
if (isResolvedToSeveralMethods(qualified)) {
|
||||
return;
|
||||
}
|
||||
checkCallSite(qualified);
|
||||
checkCallSite((PyQualifiedExpression)callee);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,40 +60,6 @@ public class PyTypeCheckerInspection extends PyInspection {
|
||||
checkCallSite(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hack for skipping type checking for method calls of union members if there are several call alternatives.
|
||||
*
|
||||
* TODO: Multi-resolve callees when analysing calls. This requires multi-resolving in followAssignmentsChain.
|
||||
*/
|
||||
private boolean isResolvedToSeveralMethods(@NotNull PyQualifiedExpression callee) {
|
||||
final PyExpression qualifier = callee.getQualifier();
|
||||
if (qualifier != null) {
|
||||
final PyType qualifierType = qualifier.getType(myTypeEvalContext);
|
||||
if (qualifierType instanceof PyUnionType) {
|
||||
final PyUnionType unionType = (PyUnionType)qualifierType;
|
||||
final String name = callee.getName();
|
||||
int sameNameCount = 0;
|
||||
for (PyType member : unionType.getMembers()) {
|
||||
if (member != null) {
|
||||
final List<? extends RatedResolveResult> results = member.resolveMember(name, callee, AccessDirection.READ,
|
||||
resolveWithoutImplicits());
|
||||
if (results != null && !results.isEmpty()) {
|
||||
sameNameCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sameNameCount > 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
final PyExpression qualifierExpr = qualifier instanceof PyCallExpression ? ((PyCallExpression)qualifier).getCallee() : qualifier;
|
||||
if (qualifierExpr instanceof PyQualifiedExpression) {
|
||||
return isResolvedToSeveralMethods((PyQualifiedExpression)qualifierExpr);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkCallSite(@Nullable PyQualifiedExpression callSite) {
|
||||
final Map<PyGenericType, PyType> substitutions = new LinkedHashMap<PyGenericType, PyType>();
|
||||
final PyTypeChecker.AnalyzeCallResults results = PyTypeChecker.analyzeCallSite(callSite, myTypeEvalContext);
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.jetbrains.python.codeInsight.stdlib.PyStdlibTypeProvider;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.resolve.RatedResolveResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -319,6 +320,13 @@ public class PyTypeChecker {
|
||||
|
||||
@Nullable
|
||||
public static AnalyzeCallResults analyzeCall(@NotNull PyCallExpression call, @NotNull TypeEvalContext context) {
|
||||
final PyExpression callee = call.getCallee();
|
||||
if (callee instanceof PyQualifiedExpression) {
|
||||
final PyQualifiedExpression qualified = (PyQualifiedExpression)callee;
|
||||
if (isResolvedToSeveralMethods(qualified, context)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final PyArgumentList args = call.getArgumentList();
|
||||
if (args != null) {
|
||||
final CallArgumentsMapping mapping = args.analyzeCall(PyResolveContext.noImplicits().withTypeEvalContext(context));
|
||||
@@ -327,7 +335,6 @@ public class PyTypeChecker {
|
||||
if (markedCallee != null) {
|
||||
final Callable callable = markedCallee.getCallable();
|
||||
if (callable instanceof PyFunction) {
|
||||
final PyExpression callee = call.getCallee();
|
||||
final PyExpression receiver = callee instanceof PyQualifiedExpression ? ((PyQualifiedExpression)callee).getQualifier() : null;
|
||||
return new AnalyzeCallResults(callable, receiver, arguments);
|
||||
}
|
||||
@@ -464,6 +471,40 @@ public class PyTypeChecker {
|
||||
return type.equals(builtinCache.getClassMethodType()) || type.equals(builtinCache.getStaticMethodType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Hack for skipping type checking for method calls of union members if there are several call alternatives.
|
||||
*
|
||||
* TODO: Multi-resolve callees when analysing calls. This requires multi-resolving in followAssignmentsChain.
|
||||
*/
|
||||
public static boolean isResolvedToSeveralMethods(@NotNull PyQualifiedExpression callee, @NotNull TypeEvalContext context) {
|
||||
final PyExpression qualifier = callee.getQualifier();
|
||||
if (qualifier != null) {
|
||||
final PyType qualifierType = qualifier.getType(context);
|
||||
if (qualifierType instanceof PyUnionType) {
|
||||
final PyUnionType unionType = (PyUnionType)qualifierType;
|
||||
final String name = callee.getName();
|
||||
int sameNameCount = 0;
|
||||
for (PyType member : unionType.getMembers()) {
|
||||
if (member != null) {
|
||||
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
|
||||
final List<? extends RatedResolveResult> results = member.resolveMember(name, callee, AccessDirection.READ, resolveContext);
|
||||
if (results != null && !results.isEmpty()) {
|
||||
sameNameCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sameNameCount > 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
final PyExpression qualifierExpr = qualifier instanceof PyCallExpression ? ((PyCallExpression)qualifier).getCallee() : qualifier;
|
||||
if (qualifierExpr instanceof PyQualifiedExpression) {
|
||||
return isResolvedToSeveralMethods((PyQualifiedExpression)qualifierExpr, context);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class AnalyzeCallResults {
|
||||
@NotNull private final Callable myCallable;
|
||||
@Nullable private final PyExpression myReceiver;
|
||||
|
||||
Reference in New Issue
Block a user