Reused available TypeEvalContext instead of codeInsightFallback()

This commit is contained in:
Andrey Vlasovskikh
2013-05-08 21:46:48 +04:00
parent 9ffac767d1
commit fd54bc9000
11 changed files with 53 additions and 50 deletions
@@ -87,30 +87,30 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
}
}
return getReturnTypeByQName(qname, function);
return getReturnTypeByQName(qname, function, context);
}
return null;
}
@Nullable
public PyType getConstructorType(@NotNull PyClass cls) {
public PyType getConstructorType(@NotNull PyClass cls, @NotNull TypeEvalContext context) {
final String classQName = cls.getQualifiedName();
if (classQName != null) {
final PyQualifiedName canonicalQName = PyStdlibCanonicalPathProvider.restoreStdlibCanonicalPath(PyQualifiedName.fromDottedString(classQName));
if (canonicalQName != null) {
final PyQualifiedName qname = canonicalQName.append(PyNames.INIT);
return getReturnTypeByQName(qname.toString(), cls);
return getReturnTypeByQName(qname.toString(), cls, context);
}
}
return null;
}
@Nullable
private PyType getReturnTypeByQName(@NotNull String qname, @NotNull PsiElement anchor) {
private PyType getReturnTypeByQName(@NotNull String qname, @NotNull PsiElement anchor, @NotNull TypeEvalContext context) {
final LanguageLevel level = LanguageLevel.forElement(anchor);
final String key = String.format("Python%d/%s.return", level.getVersion(), qname);
final PyBuiltinCache cache = PyBuiltinCache.getInstance(anchor);
final Ref<PyType> cached = cache.getStdlibType(key);
final Ref<PyType> cached = cache.getStdlibType(key, context);
if (cached != null) {
return cached.get();
}
@@ -133,7 +133,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
final String name = param.getName();
final String qname = getQualifiedName(func, param);
if (qname != null && name != null) {
return getParameterTypeByQName(qname, name, func);
return getParameterTypeByQName(qname, name, func, context);
}
return null;
}
@@ -175,7 +175,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
PyType rtype;
do {
final String overloadedQName = String.format("%s.%d", qname, i);
rtype = getReturnTypeByQName(overloadedQName, anchor);
rtype = getReturnTypeByQName(overloadedQName, anchor, context);
if (rtype != null) {
boolean matched = true;
boolean notNullParameterMatch = false;
@@ -192,7 +192,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
continue;
}
final PyType argType = context.getType(entry.getKey());
final PyType paramType = getParameterTypeByQName(overloadedQName, name, anchor);
final PyType paramType = getParameterTypeByQName(overloadedQName, name, anchor, context);
if (PyTypeChecker.match(paramType, argType, context)) {
if (paramType != null && !PyTypeChecker.isUnknown(argType)) {
notNullParameterMatch = true;
@@ -230,7 +230,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
final PyBuiltinCache cache = PyBuiltinCache.getInstance(anchor);
final LanguageLevel level = LanguageLevel.forElement(anchor);
final PyType paramType = getParameterTypeByQName(overloadedQName, "mode", anchor);
final PyType paramType = getParameterTypeByQName(overloadedQName, "mode", anchor, context);
final PyType argType;
// Binary mode
if (mode.contains("b")) {
@@ -249,11 +249,14 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
@Nullable
private PyType getParameterTypeByQName(@NotNull String functionQName, @NotNull String name, @NotNull PsiElement anchor) {
private PyType getParameterTypeByQName(@NotNull String functionQName,
@NotNull String name,
@NotNull PsiElement anchor,
@NotNull TypeEvalContext context) {
final LanguageLevel level = LanguageLevel.forElement(anchor);
final String key = String.format("Python%d/%s.%s", level.getVersion(), functionQName, name);
final PyBuiltinCache cache = PyBuiltinCache.getInstance(anchor);
final Ref<PyType> cached = cache.getStdlibType(key);
final Ref<PyType> cached = cache.getStdlibType(key, context);
if (cached != null) {
return cached.get();
}
@@ -39,11 +39,12 @@ public class PyUsageTypeProvider implements UsageTypeProviderEx {
if (element instanceof PyQualifiedExpression) {
final PyExpression qualifier = ((PyQualifiedExpression)element).getQualifier();
if (qualifier != null) {
final PyType type = TypeEvalContext.userInitiated().getType(qualifier);
final TypeEvalContext context = TypeEvalContext.userInitiated();
final PyType type = context.getType(qualifier);
if (type == null || type instanceof PyTypeReference) {
final PyCallExpression call = PsiTreeUtil.getParentOfType(element, PyCallExpression.class);
if (call != null && element == call.getCallee()) {
return checkMatchingSignatureGroup(call, targets);
return checkMatchingSignatureGroup(call, targets, context);
}
return UNTYPED;
}
@@ -74,7 +75,7 @@ public class PyUsageTypeProvider implements UsageTypeProviderEx {
}
@Nullable
private static UsageType checkMatchingSignatureGroup(PyCallExpression call, UsageTarget[] targets) {
private static UsageType checkMatchingSignatureGroup(PyCallExpression call, UsageTarget[] targets, TypeEvalContext context) {
if (targets.length == 1 && targets[0] instanceof PsiElementUsageTarget) {
final PsiElement element = ((PsiElementUsageTarget)targets[0]).getElement();
if (element instanceof PyFunction) {
@@ -82,7 +83,7 @@ public class PyUsageTypeProvider implements UsageTypeProviderEx {
final PyFunction.Modifier modifier = function.getModifier();
PyCallExpression.PyMarkedCallee callee = new PyCallExpression.PyMarkedCallee(function, modifier, 1, true);
CallArgumentsMappingImpl mapping = new CallArgumentsMappingImpl(call.getArgumentList());
mapping.mapArguments(callee, null);
mapping.mapArguments(callee, context);
if (mapping.hasProblems()) {
return SIGNATURE_MISMATCH;
}
@@ -646,7 +646,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
if (cls.findProperty(refText) != null) {
return true;
}
if (PyUtil.hasUnresolvedAncestors(cls)) {
if (PyUtil.hasUnresolvedAncestors(cls, myTypeEvalContext)) {
return true;
}
if (isDecoratedAsDynamic(cls, true)) {
@@ -617,8 +617,8 @@ public class PyUtil {
: psiNamedElement.getName();
}
public static boolean hasUnresolvedAncestors(@NotNull PyClass cls) {
for (PyClassLikeType type : cls.getAncestorTypes(TypeEvalContext.codeInsightFallback())) {
public static boolean hasUnresolvedAncestors(@NotNull PyClass cls, @NotNull TypeEvalContext context) {
for (PyClassLikeType type : cls.getAncestorTypes(context)) {
if (type == null) {
return true;
}
@@ -47,14 +47,10 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
* positional paramaters, but at least one item long.
* @param arguments what to map, get if from call site
* @param resolved_callee what to map parameters of
* @param type_context optional shared type evaluator / cache.
* @param context optional shared type evaluator / cache.
*/
public void mapArguments(
PyCallExpression.PyMarkedCallee resolved_callee,
@Nullable TypeEvalContext type_context
) {
public void mapArguments(PyCallExpression.PyMarkedCallee resolved_callee, @Nullable TypeEvalContext context) {
PyExpression[] arguments = myArgumentList.getArguments();
if (type_context == null) type_context = TypeEvalContext.codeInsightFallback();
myMarkedCallee = resolved_callee;
List<PyExpression> unmatched_args = new LinkedList<PyExpression>();
Collections.addAll(unmatched_args, arguments);
@@ -144,8 +140,8 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
mapped_args.add(arg); // tuple itself is always mapped; its insides can fail
}
else {
PyType arg_type = type_context.getType(arg);
if (arg_type != null && arg_type.isBuiltin(type_context) && "list".equals(arg_type.getName())) {
PyType arg_type = context.getType(arg);
if (arg_type != null && arg_type.isBuiltin(context) && "list".equals(arg_type.getName())) {
mapped_args.add(arg); // we can't really analyze arbitrary lists statically yet
// but ListLiteralExpressions are handled by visitor
}
@@ -210,10 +206,10 @@ public class CallArgumentsMappingImpl implements CallArgumentsMapping {
if (cnt < parameters.length && cnt < positional_index && myTupleArg != null) {
// check length of myTupleArg
PyType tuple_arg_type = null;
if (type_context != null) {
if (context != null) {
final PyExpression expression = PsiTreeUtil.getChildOfType(myTupleArg, PyExpression.class);
if (expression != null) {
tuple_arg_type = type_context.getType(expression);
tuple_arg_type = context.getType(expression);
}
}
int tuple_length;
@@ -314,11 +314,11 @@ public class PyBuiltinCache {
}
@Nullable
public Ref<PyType> getStdlibType(@NotNull String key) {
public Ref<PyType> getStdlibType(@NotNull String key, @NotNull TypeEvalContext context) {
synchronized (myStdlibTypeCache) {
final Ref<PyType> ref = myStdlibTypeCache.get(key);
if (ref != null) {
if (!isValid(ref.get())) {
if (!isValid(ref.get(), context)) {
myStdlibTypeCache.clear();
return null;
}
@@ -327,10 +327,10 @@ public class PyBuiltinCache {
}
}
private static boolean isValid(@Nullable PyType type) {
private static boolean isValid(@Nullable PyType type, @NotNull TypeEvalContext context) {
if (type instanceof PyCollectionType) {
final PyType elementType = ((PyCollectionType)type).getElementType(TypeEvalContext.codeInsightFallback());
if (!isValid(elementType)) {
final PyType elementType = ((PyCollectionType)type).getElementType(context);
if (!isValid(elementType, context)) {
return false;
}
}
@@ -340,7 +340,7 @@ public class PyBuiltinCache {
}
else if (type instanceof PyUnionType) {
for (PyType member : ((PyUnionType)type).getMembers()) {
if (!isValid(member)) {
if (!isValid(member, context)) {
return false;
}
}
@@ -179,7 +179,7 @@ public class PyNamedParameterImpl extends PyPresentableElementImpl<PyNamedParame
else {
final PyStdlibTypeProvider stdlib = PyStdlibTypeProvider.getInstance();
if (stdlib != null) {
initType = stdlib.getConstructorType(containingClass);
initType = stdlib.getConstructorType(containingClass, context);
}
}
if (initType != null && !(initType instanceof PyNoneType || initType instanceof PyReturnTypeReference)) {
@@ -138,12 +138,13 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
if (elt instanceof PyTargetExpression) {
PsiElement assigned_from = null;
final PyTargetExpression expr = (PyTargetExpression)elt;
if (resolveContext.getTypeEvalContext().maySwitchToAST(expr) || expr.getStub() == null) {
final TypeEvalContext context = resolveContext.getTypeEvalContext();
if (context.maySwitchToAST(expr) || expr.getStub() == null) {
assigned_from = expr.findAssignedValue();
}
// TODO: Maybe findAssignedValueByStub() should become a part of the PyTargetExpression interface
else if (elt instanceof PyTargetExpressionImpl) {
assigned_from = ((PyTargetExpressionImpl)elt).findAssignedValueByStub();
assigned_from = ((PyTargetExpressionImpl)elt).findAssignedValueByStub(context);
}
if (assigned_from instanceof PyReferenceExpression) {
if (visited.contains(assigned_from)) {
@@ -118,7 +118,7 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
return pyType;
}
if (!context.maySwitchToAST(this)) {
final PsiElement value = getStub() != null ? findAssignedValueByStub() : findAssignedValue();
final PsiElement value = getStub() != null ? findAssignedValueByStub(context) : findAssignedValue();
if (value instanceof PyTypedElement) {
return context.getType((PyTypedElement)value);
}
@@ -438,7 +438,7 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
}
@Nullable
public PsiElement findAssignedValueByStub() {
public PsiElement findAssignedValueByStub(@NotNull TypeEvalContext context) {
final PyTargetExpressionStub stub = getStub();
if (stub != null && stub.getInitializerType() == PyTargetExpressionStub.InitializerType.ReferenceExpression) {
final PyQualifiedName initializer = stub.getInitializer();
@@ -451,7 +451,7 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
return ((PyFile)parent).getElementNamed(name);
}
else if (parent instanceof PyClass) {
final PyType type = TypeEvalContext.codeInsightFallback().getType((PyClass)parent);
final PyType type = context.getType((PyClass)parent);
if (type != null) {
final List<? extends RatedResolveResult> results = type.resolveMember(name, null, AccessDirection.READ,
PyResolveContext.noImplicits());
@@ -6,14 +6,16 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiInvalidElementAccessException;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.*;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -271,10 +273,10 @@ public class ResolveImportUtil {
dir = (PsiDirectory)parent;
}
else if (parent != null) {
PyType refType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(parent, TypeEvalContext.codeInsightFallback(), null);
final PyResolveContext resolveContext = PyResolveContext.defaultContext();
PyType refType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(parent, resolveContext.getTypeEvalContext(), null);
if (refType != null) {
final List<? extends RatedResolveResult> result = refType.resolveMember(referencedName, null, AccessDirection.READ,
PyResolveContext.defaultContext());
final List<? extends RatedResolveResult> result = refType.resolveMember(referencedName, null, AccessDirection.READ, resolveContext);
if (result != null && !result.isEmpty()) {
return result.get(0).getElement();
}
@@ -104,7 +104,7 @@ public class PyTypeChecker {
final PyClass superClass = ((PyClassType)expected).getPyClass();
final PyClass subClass = ((PyClassType)actual).getPyClass();
if (expected instanceof PyCollectionType && actual instanceof PyCollectionType) {
if (!matchClasses(superClass, subClass)) {
if (!matchClasses(superClass, subClass, context)) {
return false;
}
final PyType superElementType = ((PyCollectionType)expected).getElementType(context);
@@ -126,7 +126,7 @@ public class PyTypeChecker {
return true;
}
}
else if (matchClasses(superClass, subClass)) {
else if (matchClasses(superClass, subClass, context)) {
return true;
}
else if (((PyClassType)actual).isDefinition() && PyNames.CALLABLE.equals(expected.getName())) {
@@ -287,7 +287,7 @@ public class PyTypeChecker {
// Unify generics in stdlib pseudo-constructor
final PyStdlibTypeProvider stdlib = PyStdlibTypeProvider.getInstance();
if (stdlib != null) {
final PyType initType = stdlib.getConstructorType(cls);
final PyType initType = stdlib.getConstructorType(cls, context);
if (initType != null) {
match(initType, qualifierType, context, substitutions);
}
@@ -297,11 +297,11 @@ public class PyTypeChecker {
return substitutions;
}
private static boolean matchClasses(@Nullable PyClass superClass, @Nullable PyClass subClass) {
private static boolean matchClasses(@Nullable PyClass superClass, @Nullable PyClass subClass, @NotNull TypeEvalContext context) {
if (superClass == null || subClass == null || subClass.isSubclass(superClass) || PyABCUtil.isSubclass(subClass, superClass)) {
return true;
}
else if (PyUtil.hasUnresolvedAncestors(subClass)) {
else if (PyUtil.hasUnresolvedAncestors(subClass, context)) {
return true;
}
else {