PY-14081 Django: QuerySet.as_manager() code editing is really slow
authorIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Tue, 14 Oct 2014 19:32:38 +0000 (23:32 +0400)
committerIlya.Kazakevich <Ilya.Kazakevich@jetbrains.com>
Tue, 14 Oct 2014 19:32:38 +0000 (23:32 +0400)
Context cache added

56 files changed:
python/pluginSrc/com/jetbrains/python/psi/impl/PyJavaSuperMethodsSearchExecutor.java
python/psi-api/src/com/jetbrains/python/psi/resolve/PyResolveContext.java
python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalConstraints.java [new file with mode: 0644]
python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java
python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContextCache.java [new file with mode: 0644]
python/src/com/jetbrains/python/PyParameterInfoHandler.java
python/src/com/jetbrains/python/codeInsight/completion/PyDictKeyNamesCompletionContributor.java
python/src/com/jetbrains/python/codeInsight/intentions/ConvertFormatOperatorToMethodIntention.java
python/src/com/jetbrains/python/codeInsight/intentions/ImportFromToImportIntention.java
python/src/com/jetbrains/python/codeInsight/intentions/PyDictConstructorToLiteralFormIntention.java
python/src/com/jetbrains/python/codeInsight/intentions/PyStringConcatenationToFormatIntention.java
python/src/com/jetbrains/python/codeInsight/intentions/TypeAssertionIntention.java
python/src/com/jetbrains/python/codeInsight/intentions/TypeIntention.java
python/src/com/jetbrains/python/codeInsight/liveTemplates/PyIterableVariableMacro.java
python/src/com/jetbrains/python/codeInsight/override/PyMethodMember.java
python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java
python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java
python/src/com/jetbrains/python/documentation/DocStringTypeReference.java
python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java
python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
python/src/com/jetbrains/python/findUsages/PyUsageTypeProvider.java
python/src/com/jetbrains/python/inspections/PyCompatibilityInspection.java
python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java
python/src/com/jetbrains/python/inspections/quickfix/AddFunctionQuickFix.java
python/src/com/jetbrains/python/inspections/quickfix/AddMethodQuickFix.java
python/src/com/jetbrains/python/inspections/quickfix/PyAddSpecifierToFormatQuickFix.java
python/src/com/jetbrains/python/inspections/quickfix/PyCreatePropertyQuickFix.java
python/src/com/jetbrains/python/patterns/PythonPatterns.java
python/src/com/jetbrains/python/psi/PyUtil.java
python/src/com/jetbrains/python/psi/impl/PyBaseElementImpl.java
python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
python/src/com/jetbrains/python/psi/impl/references/KeywordArgumentCompletionUtil.java
python/src/com/jetbrains/python/psi/impl/references/PyImportReference.java
python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java
python/src/com/jetbrains/python/psi/resolve/CompletionVariantsProcessor.java
python/src/com/jetbrains/python/psi/types/PyCallableTypeImpl.java
python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java
python/src/com/jetbrains/python/psi/types/PyCollectionTypeImpl.java
python/src/com/jetbrains/python/psi/types/PyDynamicallyEvaluatedType.java
python/src/com/jetbrains/python/psi/types/PyFunctionType.java
python/src/com/jetbrains/python/psi/types/PyTypeParser.java
python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java
python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java
python/src/com/jetbrains/python/refactoring/classes/pullUp/PyAncestorsUtils.java
python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
python/src/com/jetbrains/python/testing/PythonUnitTestUtil.java
python/src/com/jetbrains/python/testing/attest/PythonAtTestConfigurationProducer.java
python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java
python/testSrc/com/jetbrains/env/python/PythonSkeletonsTest.java
python/testSrc/com/jetbrains/python/PyClassicPropertyTest.java
python/testSrc/com/jetbrains/python/PyStubsTest.java
python/testSrc/com/jetbrains/python/PyTypeParserTest.java
python/testSrc/com/jetbrains/python/PyTypeTest.java
python/testSrc/com/jetbrains/python/PyTypingTest.java
python/testSrc/com/jetbrains/python/codeInsight/PyClassMROTest.java

index d718332f3b8d985d9c4be1369e9fbc61fd0323b2..9b6e3713a697280a5e5f96b3ad373b27c941d143 100644 (file)
@@ -36,7 +36,7 @@ public class PyJavaSuperMethodsSearchExecutor implements QueryExecutor<PsiElemen
     PyFunction func = queryParameters.getDerivedMethod();
     PyClass containingClass = func.getContainingClass();
     if (containingClass != null) {
-      for (PyClassLikeType type : containingClass.getSuperClassTypes(TypeEvalContext.codeInsightFallback())) {
+      for (PyClassLikeType type : containingClass.getSuperClassTypes(TypeEvalContext.codeInsightFallback(containingClass.getProject()))) {
         if (type instanceof PyJavaClassType) {
           final PsiClass psiClass = ((PyJavaClassType)type).getPsiClass();
           PsiMethod[] methods = psiClass.findMethodsByName(func.getName(), true);
index 5fbee9f011a1ce9154206ea2e11e4b9df110352d..e70b2959748d990567a0502d629157f6cbc85820 100644 (file)
@@ -71,7 +71,7 @@ public class PyResolveContext {
   }
 
   public TypeEvalContext getTypeEvalContext() {
-    return myTypeEvalContext != null ? myTypeEvalContext : TypeEvalContext.codeInsightFallback();
+    return myTypeEvalContext != null ? myTypeEvalContext : TypeEvalContext.codeInsightFallback(null);
   }
 
   @Override
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalConstraints.java b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalConstraints.java
new file mode 100644 (file)
index 0000000..bce5f2c
--- /dev/null
@@ -0,0 +1,53 @@
+package com.jetbrains.python.psi.types;
+
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A pack of constraints that limit behavior of {@link com.jetbrains.python.psi.types.TypeEvalContext}.
+ * Any two  {@link com.jetbrains.python.psi.types.TypeEvalContext}s may share their cache if their constraints are equal and no PSI changes
+ * happened between their creation.
+ * <p/>
+ * This class created to support hash/equals for context.
+ *
+ * @author Ilya.Kazakevich
+ */
+@SuppressWarnings("PackageVisibleField")
+  // This is an utility class to be used only in package. Fields are open to type less code
+class TypeEvalConstraints {
+  final boolean myAllowDataFlow;
+  final boolean myAllowStubToAST;
+  @Nullable final PsiFile myOrigin;
+
+  /**
+   * @see com.jetbrains.python.psi.types.TypeEvalContext
+   */
+  TypeEvalConstraints(final boolean allowDataFlow, final boolean allowStubToAST, @Nullable final PsiFile origin) {
+    myAllowDataFlow = allowDataFlow;
+    myAllowStubToAST = allowStubToAST;
+    myOrigin = origin;
+  }
+
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof TypeEvalConstraints)) return false;
+
+    TypeEvalConstraints that = (TypeEvalConstraints)o;
+
+    if (myAllowDataFlow != that.myAllowDataFlow) return false;
+    if (myAllowStubToAST != that.myAllowStubToAST) return false;
+    if (myOrigin != null ? !myOrigin.equals(that.myOrigin) : that.myOrigin != null) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = (myAllowDataFlow ? 1 : 0);
+    result = 31 * result + (myAllowStubToAST ? 1 : 0);
+    result = 31 * result + (myOrigin != null ? myOrigin.hashCode() : 0);
+    return result;
+  }
+}
index f3c688bc88ae31386e5455bdef96062c22671b1c..6cd720be6dc237286c61afca62d057c080cf492f 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.jetbrains.python.psi.types;
 
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
@@ -29,17 +30,25 @@ import java.util.*;
  * @author yole
  */
 public class TypeEvalContext {
+  /**
+   * Contexts are cached here to prevent useless recreations (and cache loss)
+   */
+  @NotNull
+  private static final TypeEvalContextCache CACHE = new TypeEvalContextCache();
+
   public static class Key {
     private static final Key INSTANCE = new Key();
 
-    private Key() {}
+    private Key() {
+    }
   }
 
-  private final boolean myAllowDataFlow;
-  private final boolean myAllowStubToAST;
+  @NotNull
+  private final TypeEvalConstraints myConstraints;
+
+
   private List<String> myTrace;
   private String myTraceIndent = "";
-  @Nullable private final PsiFile myOrigin;
 
   private final Map<PyTypedElement, PyType> myEvaluated = new HashMap<PyTypedElement, PyType>();
   private final Map<Callable, PyType> myEvaluatedReturn = new HashMap<Callable, PyType>();
@@ -57,63 +66,70 @@ public class TypeEvalContext {
   };
 
   private TypeEvalContext(boolean allowDataFlow, boolean allowStubToAST, @Nullable PsiFile origin) {
-    myAllowDataFlow = allowDataFlow;
-    myAllowStubToAST = allowStubToAST;
-    myOrigin = origin;
+    myConstraints = new TypeEvalConstraints(allowDataFlow, allowStubToAST, origin);
   }
 
   @Override
   public String toString() {
-    return String.format("TypeEvalContext(%b, %b, %s)", myAllowDataFlow, myAllowStubToAST, myOrigin);
+    return String
+      .format("TypeEvalContext(%b, %b, %s)", myConstraints.myAllowDataFlow, myConstraints.myAllowStubToAST, myConstraints.myOrigin);
   }
 
   public boolean allowDataFlow(PsiElement element) {
-    return myAllowDataFlow || element.getContainingFile() == myOrigin;
+    return myConstraints.myAllowDataFlow || element.getContainingFile() == myConstraints.myOrigin;
   }
 
   public boolean allowReturnTypes(PsiElement element) {
-    return myAllowDataFlow || element.getContainingFile() == myOrigin;
+    return myConstraints.myAllowDataFlow || element.getContainingFile() == myConstraints.myOrigin;
   }
 
   public boolean allowLocalUsages(@NotNull PsiElement element) {
-    return myAllowStubToAST && myAllowDataFlow && element.getContainingFile() == myOrigin;
+    return myConstraints.myAllowStubToAST && myConstraints.myAllowDataFlow && element.getContainingFile() == myConstraints.myOrigin;
   }
 
   /**
    * Create the most detailed type evaluation context for user-initiated actions.
-   *
+   * <p/>
    * Should be used for code completion, go to definition, find usages, refactorings, documentation.
    */
-  public static TypeEvalContext userInitiated(@Nullable PsiFile origin) {
-    return new TypeEvalContext(true, true, origin);
+  public static TypeEvalContext userInitiated(@NotNull final Project project, @Nullable final PsiFile origin) {
+    return CACHE.getContext(project, new TypeEvalContext(true, true, origin));
   }
 
   /**
    * Create a type evaluation context for performing analysis operations on the specified file which is currently open in the editor,
    * without accessing stubs. For such a file, additional slow operations are allowed.
-   *
+   * <p/>
    * Inspections should not create a new type evaluation context. They should re-use the context of the inspection session.
    */
-  public static TypeEvalContext codeAnalysis(@Nullable PsiFile origin) {
-    return new TypeEvalContext(false, false, origin);
+  public static TypeEvalContext codeAnalysis(@NotNull final Project project, @Nullable final PsiFile origin) {
+    return CACHE.getContext(project, new TypeEvalContext(false, false, origin));
   }
 
   /**
    * Create the most shallow type evaluation context for code insight purposes when other more detailed contexts are not available.
-   *
    * It's use should be minimized.
+   * <p/>
+   * <p/>
+   *
+   * @param project pass project here to enable cache. Pass null if you do not have any project.
+   *                <strong>Always</strong> do your best to pass project here: it increases performance!
    */
-  public static TypeEvalContext codeInsightFallback() {
-    return new TypeEvalContext(false, false, null);
+  public static TypeEvalContext codeInsightFallback(@Nullable final Project project) {
+    final TypeEvalContext anchor = new TypeEvalContext(false, false, null);
+    if (project != null) {
+      return CACHE.getContext(project, anchor);
+    }
+    return anchor;
   }
 
   /**
    * Create a type evaluation context for deeper and slower code insight.
-   *
+   * <p/>
    * Should be used only when normal code insight context is not enough for getting good results.
    */
-  public static TypeEvalContext deepCodeInsight() {
-    return new TypeEvalContext(false, true, null);
+  public static TypeEvalContext deepCodeInsight(@NotNull final Project project) {
+    return CACHE.getContext(project, new TypeEvalContext(false, true, null));
   }
 
   public TypeEvalContext withTracing() {
@@ -137,7 +153,7 @@ public class TypeEvalContext {
 
   public void traceUnindent() {
     if (myTrace != null && myTraceIndent.length() >= 2) {
-      myTraceIndent = myTraceIndent.substring(0, myTraceIndent.length()-2);
+      myTraceIndent = myTraceIndent.substring(0, myTraceIndent.length() - 2);
     }
   }
 
@@ -210,11 +226,19 @@ public class TypeEvalContext {
   }
 
   public boolean maySwitchToAST(@NotNull PsiElement element) {
-    return myAllowStubToAST || myOrigin == element.getContainingFile();
+    return myConstraints.myAllowStubToAST || myConstraints.myOrigin == element.getContainingFile();
   }
 
   @Nullable
   public PsiFile getOrigin() {
-    return myOrigin;
+    return myConstraints.myOrigin;
+  }
+
+  /**
+   * @return context constraints (see {@link com.jetbrains.python.psi.types.TypeEvalConstraints}
+   */
+  @NotNull
+  TypeEvalConstraints getConstraints() {
+    return myConstraints;
   }
 }
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContextCache.java b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContextCache.java
new file mode 100644 (file)
index 0000000..217bb26
--- /dev/null
@@ -0,0 +1,71 @@
+package com.jetbrains.python.psi.types;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.util.PsiModificationTracker;
+import com.intellij.psi.util.PsiModificationTracker.SERVICE;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Caches context by their constraints (to prevent context cache loss). Flushes cache every PSI change.
+ * Class is thread safe.
+ * See {@link #getContext(com.intellij.openapi.project.Project, TypeEvalContext)}
+ *
+ * @author Ilya.Kazakevich
+ */
+class TypeEvalContextCache {
+  /**
+   * Cache itself.
+   */
+  @NotNull
+  private final Map<TypeEvalConstraints, TypeEvalContext> myCache = new HashMap<TypeEvalConstraints, TypeEvalContext>();
+  /**
+   * Current PSI modification count
+   */
+  private long myModificationCount = -1;
+  /**
+   * Lock to sync
+   */
+  @NotNull
+  private final Object myLock = new Object();
+
+
+  /**
+   * Returns context from cache (if exist) or returns the one you provided (and puts it into cache).
+   * To use this method, do the following:
+   * <ol>
+   * <li>Instantiate {@link com.jetbrains.python.psi.types.TypeEvalContext} you want to use</li>
+   * <li>Pass its instance here as argument</li>
+   * <li>Use result</li>
+   * </ol>
+   *
+   * @param project  project is required for caching engine
+   * @param standard context you want to use. Just instantiate it and pass here.
+   * @return context from cache (the one equals by constraints to yours or the one you provided)
+   */
+  @NotNull
+  TypeEvalContext getContext(@NotNull final Project project, @NotNull final TypeEvalContext standard) {
+    final PsiModificationTracker tracker = SERVICE.getInstance(project);
+    synchronized (myLock) {
+      final long currentCount = tracker.getOutOfCodeBlockModificationCount();
+      if (currentCount == myModificationCount) {
+        // Cache is valid, use it
+        final TypeEvalContext valueFromCache = myCache.get(standard.getConstraints());
+        if (valueFromCache != null) {
+          // We have element in cache, return it
+          return valueFromCache;
+        }
+      }
+      else {
+        // Cache is invalid, flush it and store current count
+        myCache.clear();
+        myModificationCount = currentCount;
+      }
+      // We do not have value in cache (or cache is invalid), put it
+      myCache.put(standard.getConstraints(), standard);
+      return standard;
+    }
+  }
+}
index 5aec4444193bc7dac0a55b530519563a22453197..7252014da2113690bb9fdc0f5b995032c3e75862 100644 (file)
@@ -54,7 +54,7 @@ public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentLi
   public PyArgumentList findElementForParameterInfo(@NotNull final CreateParameterInfoContext context) {
     PyArgumentList arglist = findArgumentList(context);
     if (arglist != null) {
-      final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(arglist.getContainingFile());
+      final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(arglist.getProject(), arglist.getContainingFile());
       final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(typeEvalContext);
       CallArgumentsMapping result = arglist.analyzeCall(resolveContext);
       if (result.getMarkedCallee() != null) {
@@ -130,7 +130,7 @@ public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentLi
     final PyArgumentList argList = prevResult.getArgumentList();
     if (!argList.isValid()) return;
     // really we need to redo analysis every UI update; findElementForParameterInfo isn't called while typing
-    final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(argList.getContainingFile());
+    final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(argList.getProject(), argList.getContainingFile());
     final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(typeEvalContext);
     final CallArgumentsMapping argumentsMapping = argList.analyzeCall(resolveContext);
     final PyMarkedCallee marked = argumentsMapping.getMarkedCallee();
index d7b1598f39a6cf100fd08c75ef926b1c392684d9..dbbd338cacef467bc65c413e2752ec1977c29231 100644 (file)
@@ -129,7 +129,7 @@ public class PyDictKeyNamesCompletionContributor extends CompletionContributor {
     if (callee == null) return;
     final String name = callee.getText();
     if ("dict".equals(name)) {
-      final TypeEvalContext context = TypeEvalContext.userInitiated(callee.getContainingFile());
+      final TypeEvalContext context = TypeEvalContext.userInitiated(callee.getProject(), callee.getContainingFile());
       final PyType type = context.getType(dictConstructor);
       if (type != null && type.isBuiltin()) {
         final PyArgumentList list = dictConstructor.getArgumentList();
index 0ba35edad8bf496b37d51c0620fc31362c7c3b01..0865a9481cee5a46f0d0be1849e39ce25efa2f06 100644 (file)
@@ -255,7 +255,7 @@ public class ConvertFormatOperatorToMethodIntention extends BaseIntentionAction
     final PyExpression rhs = PyPsiUtils.flattenParens(rightExpression);
     if (rhs == null) return;
     final String paramText = sure(rhs).getText();
-    final TypeEvalContext context = TypeEvalContext.userInitiated(file);
+    final TypeEvalContext context = TypeEvalContext.userInitiated(file.getProject(), file);
     final PyType rhsType = context.getType(rhs);
     String prefix = "";
     if (PyTypeChecker.match(PyBuiltinCache.getInstance(rhs).getObjectType("unicode"), rhsType, context)) {
index 0170b8b53e5a265a55291cc5ff19c19c94069c6d..870986c38c61b446cedc68d2f227f124cbada50d 100644 (file)
@@ -160,7 +160,7 @@ public class ImportFromToImportIntention implements IntentionAction {
           PyReferenceExpression ref = import_element.getImportReferenceExpression();
           if (ref != null && ref.isValid()) {
             PsiElement target = ref.getReference().resolve();
-            final TypeEvalContext context = TypeEvalContext.codeAnalysis(file);
+            final TypeEvalContext context = TypeEvalContext.codeAnalysis(file.getProject(), file);
             if (target instanceof PyExpression && context.getType((PyExpression)target) instanceof PyModuleType) {
               return false;
             }
index 8a72aa233dc5eae1f9684916e09accba0e9a16cb..b1b898477f8ed8e49b4227bf25abc727324b5a2a 100644 (file)
@@ -56,7 +56,7 @@ public class PyDictConstructorToLiteralFormIntention extends BaseIntentionAction
       PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyCallExpression.class);
     
     if (expression != null && expression.isCalleeText("dict")) {
-      final TypeEvalContext context = TypeEvalContext.codeAnalysis(file);
+      final TypeEvalContext context = TypeEvalContext.codeAnalysis(file.getProject(), file);
       PyType type = context.getType(expression);
       if (type != null && type.isBuiltin()) {
         PyExpression[] argumentList = expression.getArguments();
index f4fd792fc5b1a0485dd15499982d87c3d29e453f..fee281e220e8a4d5795fb19b4597bb7f5f061d0c 100644 (file)
@@ -82,9 +82,9 @@ public class PyStringConcatenationToFormatIntention extends BaseIntentionAction
       }
       if (expression instanceof PyStringLiteralExpression)
         continue;
-      final PyType type = TypeEvalContext.codeAnalysis(file).getType(expression);
+      final PyType type = TypeEvalContext.codeAnalysis(file.getProject(), file).getType(expression);
       final boolean isStringReference = PyTypeChecker.match(cache.getStringType(LanguageLevel.forElement(expression)),
-                                                            type, TypeEvalContext.codeAnalysis(file)) && type != null;
+                                                            type, TypeEvalContext.codeAnalysis(file.getProject(), file)) && type != null;
       if (!isStringReference) {
         return false;
       }
@@ -136,7 +136,7 @@ public class PyStringConcatenationToFormatIntention extends BaseIntentionAction
     List<String> parameters = new ArrayList<String>();
     Pair<String, String> quotes = Pair.create("\"", "\"");
     boolean quotesDetected = false;
-    final TypeEvalContext context = TypeEvalContext.userInitiated(file);
+    final TypeEvalContext context = TypeEvalContext.userInitiated(file.getProject(), file);
     int paramCount = 0;
     boolean isUnicode = false;
     final PyClassTypeImpl unicodeType = PyBuiltinCache.getInstance(element).getObjectType("unicode");
index 6165e8144c58303cfa1d9003cd2322d081bbf0d2..0858632e2234958009110cddb791c8dbb7bdf472 100644 (file)
@@ -75,7 +75,7 @@ public class TypeAssertionIntention implements IntentionAction {
         (reference != null && reference.resolve() == null)) {
       return false;
     }
-    final PyType type = TypeEvalContext.codeAnalysis(file).getType(problemElement);
+    final PyType type = TypeEvalContext.codeAnalysis(file.getProject(), file).getType(problemElement);
     return type == null;
   }
 
index b39af5873d0a1bddb4a09d6e7e041137d372ce7c..0486c6be86cd8ec1de6fab4e7552c04bc386ac58 100644 (file)
@@ -180,7 +180,7 @@ public abstract class TypeIntention implements IntentionAction {
   }
 
   protected PyResolveContext getResolveContext(@NotNull PsiElement origin) {
-    return PyResolveContext.defaultContext().withTypeEvalContext(TypeEvalContext.codeAnalysis(origin.getContainingFile()));
+    return PyResolveContext.defaultContext().withTypeEvalContext(TypeEvalContext.codeAnalysis(origin.getProject(), origin.getContainingFile()));
   }
 
   public boolean startInWriteAction() {
index 68eec70b447781cba3905b308e52c217e999b34a..d3039e1eab229ad49ddc1ba570c88354a623dc0f 100644 (file)
@@ -84,7 +84,7 @@ public class PyIterableVariableMacro extends Macro {
 
   @NotNull
   protected List<PsiNamedElement> getIterableElements(@NotNull PsiElement element) {
-    final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(element.getContainingFile());
+    final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile());
     final List<PsiNamedElement> components = new ArrayList<PsiNamedElement>();
     for (PsiNamedElement namedElement : getVisibleNamedElements(element)) {
       if (namedElement instanceof PyTypedElement) {
index 9630b8b25f9170b547c1dcfb9f7e8ebeffa7c1af..b203010f7fafc86a570c199bb53b5ec4b5cc748e 100644 (file)
@@ -36,7 +36,7 @@ public class PyMethodMember extends PsiElementMemberChooserObject implements Cla
   private final String myFullName;
   private static String buildNameFor(final PyElement element) {
     if (element instanceof PyFunction) {
-      final TypeEvalContext context = TypeEvalContext.userInitiated(element.getContainingFile());
+      final TypeEvalContext context = TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile());
       final List<PyParameter> parameters = PyUtil.getParameters((PyFunction)element, context);
       return element.getName() + "(" + StringUtil.join(parameters, new Function<PyParameter, String>() {
         @Override
index 634eaf9a59c93d0b34a926d97d7bc07894080459..439945b75726a6d3a1f12b53782f02fd9dbabd3b 100644 (file)
@@ -193,7 +193,7 @@ public class PyOverrideImplementUtil {
     if (anno != null) {
       pyFunctionBuilder.annotation(anno.getText());
     }
-    final TypeEvalContext context = TypeEvalContext.userInitiated(baseFunction.getContainingFile());
+    final TypeEvalContext context = TypeEvalContext.userInitiated(baseFunction.getProject(), baseFunction.getContainingFile());
     final List<PyParameter> baseParams = PyUtil.getParameters(baseFunction, context);
     for (PyParameter parameter : baseParams) {
       pyFunctionBuilder.parameter(parameter.getText());
index ef13600bfa43e37e93bbcb23bc9ae0b22a82e663..73b1077336c0d55f2194953845efbd709e48f52c 100644 (file)
@@ -159,7 +159,8 @@ public class PyUserSkeletonsUtil {
       assert owner != element;
       final PsiElement originalOwner = getUserSkeleton(owner, skeletonFile);
       if (originalOwner instanceof PyClass) {
-        final PyType type = TypeEvalContext.codeInsightFallback().getType((PyClass)originalOwner);
+        final PyClass classOwner = (PyClass)originalOwner;
+        final PyType type = TypeEvalContext.codeInsightFallback(classOwner.getProject()).getType(classOwner);
         if (type instanceof PyClassLikeType) {
           final PyClassLikeType classType = (PyClassLikeType)type;
           final PyClassLikeType instanceType = classType.toInstance();
index 92771e70cf5c61319cd1f8a3215316d8cbca0714..65ecc8d9bca3b5f1f8f7670fe74151ef1111304c 100644 (file)
@@ -132,7 +132,7 @@ public class DocStringTypeReference extends PsiPolyVariantReferenceBase<PsiEleme
         for (PyImportElement element : elements) {
           final PyReferenceExpression referenceExpression = element.getImportReferenceExpression();
           if (referenceExpression == null) continue;
-          final PyType type = TypeEvalContext.userInitiated(CompletionUtil.getOriginalOrSelf(file)).getType(referenceExpression);
+          final PyType type = TypeEvalContext.userInitiated(file.getProject(), CompletionUtil.getOriginalOrSelf(file)).getType(referenceExpression);
           if (type instanceof PyClassType) {
             variants.add(((PyClassType)type).getPyClass());
           }
index 4c3432c7e84aa4c8424630e771771538ef51e3a7..e500ebbee4aa7d2a0bc93fe2c7a4a1b9ca37e228 100644 (file)
@@ -84,7 +84,7 @@ class PyDocumentationBuilder {
     PsiElement outer = null;
     boolean is_property = false;
     String accessor_kind = "None";
-    final TypeEvalContext context = TypeEvalContext.userInitiated(myElement.getContainingFile());
+    final TypeEvalContext context = TypeEvalContext.userInitiated(myElement.getProject(), myElement.getContainingFile());
     if (myOriginalElement != null) {
       String elementName = myOriginalElement.getText();
       if (PyUtil.isPythonIdentifier(elementName)) {
index 73a0cb60409104788cf16c46835c4a97fa016d9e..5f2dfe327abbd5f5bce1e14b6df7f2fcfd832867 100644 (file)
@@ -152,7 +152,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
     ChainIterable<String> cat = new ChainIterable<String>();
     final String name = fun.getName();
     cat.addItem("def ").addWith(func_name_wrapper, $(name));
-    final TypeEvalContext context = TypeEvalContext.userInitiated(fun.getContainingFile());
+    final TypeEvalContext context = TypeEvalContext.userInitiated(fun.getProject(), fun.getContainingFile());
     final List<PyParameter> parameters = PyUtil.getParameters(fun, context);
     final String paramStr = "(" +
                             StringUtil.join(parameters,
@@ -195,12 +195,12 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
   }
 
   static String describeType(@NotNull PyTypedElement element) {
-    final TypeEvalContext context = TypeEvalContext.userInitiated(element.getContainingFile());
+    final TypeEvalContext context = TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile());
     return String.format("Inferred type: %s", getTypeName(context.getType(element), context));
   }
 
   public static void getTypeDescription(@NotNull PyFunction fun, ChainIterable<String> body) {
-    final TypeEvalContext context = TypeEvalContext.userInitiated(fun.getContainingFile());
+    final TypeEvalContext context = TypeEvalContext.userInitiated(fun.getProject(), fun.getContainingFile());
     PyTypeModelBuilder builder = new PyTypeModelBuilder(context);
     builder.build(context.getType(fun), true).toBodyWithLinks(body, fun);
   }
@@ -524,7 +524,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
   @Nullable
   private static PyClass inferClassOfParameter(PsiElement context) {
     if (context instanceof PyNamedParameter) {
-      final PyType type = TypeEvalContext.userInitiated(context.getContainingFile()).getType((PyNamedParameter)context);
+      final PyType type = TypeEvalContext.userInitiated(context.getProject(), context.getContainingFile()).getType((PyNamedParameter)context);
       if (type instanceof PyClassType) {
         return ((PyClassType)type).getPyClass();
       }
@@ -594,7 +594,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
     //TODO: this code duplicates PyDocstringGenerator in some parts
 
     final StringBuilder builder = new StringBuilder(offset);
-    final TypeEvalContext context = TypeEvalContext.userInitiated(function.getContainingFile());
+    final TypeEvalContext context = TypeEvalContext.userInitiated(function.getProject(), function.getContainingFile());
     PySignature signature = PySignatureCacheManager.getInstance(function.getProject()).findSignature(function);
     final PyDecoratorList decoratorList = function.getDecoratorList();
     final PyDecorator classMethod = decoratorList == null ? null : decoratorList.findDecorator(PyNames.CLASSMETHOD);
index 6e4204bce627595f8a1e698c7c9e7db00e5c1cfd..1578ba85ae20f77bac6abdae55173de8da6b1927 100644 (file)
@@ -53,7 +53,7 @@ public class PyUsageTypeProvider implements UsageTypeProviderEx {
       if (element instanceof PyQualifiedExpression) {
         final PyExpression qualifier = ((PyQualifiedExpression)element).getQualifier();
         if (qualifier != null) {
-          final TypeEvalContext context = TypeEvalContext.userInitiated(element.getContainingFile());
+          final TypeEvalContext context = TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile());
           final PyType type = context.getType(qualifier);
           if (type == null) {
             final PyCallExpression call = PsiTreeUtil.getParentOfType(element, PyCallExpression.class);
index 0f69f4f72a56622d72516bd6ca24b8dd84545762..c2f2dfa2b61be203ad33990b977400537c1b8bb8 100644 (file)
@@ -302,7 +302,7 @@ public class PyCompatibilityInspection extends PyInspection {
     public void visitPyReferenceExpression(PyReferenceExpression node) {
       super.visitPyElement(node);
       if (shouldBeCompatibleWithPy3()) {
-        final TypeEvalContext context = TypeEvalContext.codeAnalysis(node.getContainingFile());
+        final TypeEvalContext context = TypeEvalContext.codeAnalysis(node.getProject(), node.getContainingFile());
         final String nodeText = node.getText();
         if (nodeText.endsWith("iteritems") || nodeText.endsWith("iterkeys") || nodeText.endsWith("itervalues")) {
           final PyExpression qualifier = node.getQualifier();
index 6c86e72b1bcd1b74e1408cb81977d4098bc7636d..775bc8b69fab736874e6fe5a86ada3adbe11f61e 100644 (file)
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.PsiFile;
 import com.jetbrains.python.psi.PyElementVisitor;
 import com.jetbrains.python.psi.resolve.PyResolveContext;
 import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -45,7 +46,8 @@ public abstract class PyInspectionVisitor extends PyElementVisitor {
     synchronized (INSPECTION_TYPE_EVAL_CONTEXT) {
       context = session.getUserData(INSPECTION_TYPE_EVAL_CONTEXT);
       if (context == null) {
-        context = TypeEvalContext.codeAnalysis(session.getFile());
+        PsiFile file = session.getFile();
+        context = TypeEvalContext.codeAnalysis(file.getProject(), file);
         session.putUserData(INSPECTION_TYPE_EVAL_CONTEXT, context);
       }
     }
index 367f22b0540c038752e8cab66188c6f898f0ae23..49f84e85ec7af73ffe11ed85cd0b1e97a8728961 100644 (file)
@@ -118,7 +118,7 @@ public class AddFieldQuickFix implements LocalQuickFix {
     if (element instanceof PyQualifiedExpression) {
       final PyExpression qualifier = ((PyQualifiedExpression)element).getQualifier();
       if (qualifier == null) return null;
-      final PyType type = TypeEvalContext.userInitiated(element.getContainingFile()).getType(qualifier);
+      final PyType type = TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile()).getType(qualifier);
       return type instanceof PyClassType ? (PyClassType)type : null;
     }
     final PyClass aClass = PsiTreeUtil.getParentOfType(element, PyClass.class);
index 69106cc057d3ace92d6d279e5d052f712a93e254..bd5db4c02361a3ae1480d1f544ff6f8a45099023 100644 (file)
@@ -78,7 +78,7 @@ public class AddFunctionQuickFix  implements LocalQuickFix {
       if (!(problemElement instanceof PyQualifiedExpression)) return;
       final PyExpression qualifier = ((PyQualifiedExpression)problemElement).getQualifier();
       if (qualifier == null) return;
-      final PyType type = TypeEvalContext.userInitiated(problemElement.getContainingFile()).getType(qualifier);
+      final PyType type = TypeEvalContext.userInitiated(problemElement.getProject(), problemElement.getContainingFile()).getType(qualifier);
       if (!(type instanceof PyModuleType)) return;
       final PyFile file = ((PyModuleType)type).getModule();
       sure(file);
index 9924292ad9065a8a18ff9081252b8698bcf5fda3..beac24e00501646fa84407df0fd15e4e86cf48a3 100644 (file)
@@ -96,7 +96,7 @@ public class AddMethodQuickFix implements LocalQuickFix {
       boolean madeInstance = false;
       if (callByClass) {
         if (args.length > 0) {
-          PyType firstArgType = TypeEvalContext.userInitiated(cls.getContainingFile()).getType(args[0]);
+          PyType firstArgType = TypeEvalContext.userInitiated(cls.getProject(), cls.getContainingFile()).getType(args[0]);
           if (firstArgType instanceof PyClassType && ((PyClassType)firstArgType).getPyClass().isSubclass(cls)) {
             // class, first arg ok: instance method
             builder.parameter("self"); // NOTE: might use a name other than 'self', according to code style.
@@ -151,7 +151,7 @@ public class AddMethodQuickFix implements LocalQuickFix {
     if ((problemElement instanceof PyQualifiedExpression)) {
       final PyExpression qualifier = ((PyQualifiedExpression)problemElement).getQualifier();
       if (qualifier == null) return null;
-      final PyType type = TypeEvalContext.userInitiated(problemElement.getContainingFile()).getType(qualifier);
+      final PyType type = TypeEvalContext.userInitiated(problemElement.getProject(), problemElement.getContainingFile()).getType(qualifier);
       return type instanceof PyClassType ? (PyClassType)type : null;
     }
     final PyClass pyClass = PsiTreeUtil.getParentOfType(problemElement, PyClass.class);
index 6d40f31bfb770915a67872f4bb0779fe168f38b2..8590c2d5119056f4be8e94c497abb3a8a25af5ca 100644 (file)
@@ -65,7 +65,7 @@ public class PyAddSpecifierToFormatQuickFix implements LocalQuickFix {
     final Document document = FileDocumentManager.getInstance().getDocument(file.getVirtualFile());
     if (document == null) return;
     final int offset = element.getTextOffset();
-    final TypeEvalContext context = TypeEvalContext.userInitiated(file);
+    final TypeEvalContext context = TypeEvalContext.userInitiated(file.getProject(), file);
 
     final PyClassType strType = PyBuiltinCache.getInstance(element).getStrType();
     final PyClassType floatType = PyBuiltinCache.getInstance(element).getFloatType();
index f88652aa1a12c2e7d036cd068b8f78fd247ae43c..89b4fd531fa5bd5b7872b67fc40757c12443f2d8 100644 (file)
@@ -50,7 +50,7 @@ public class PyCreatePropertyQuickFix implements LocalQuickFix {
     if (element instanceof PyQualifiedExpression) {
       final PyExpression qualifier = ((PyQualifiedExpression)element).getQualifier();
       if (qualifier != null) {
-        final PyType type = TypeEvalContext.codeAnalysis(element.getContainingFile()).getType(qualifier);
+        final PyType type = TypeEvalContext.codeAnalysis(element.getProject(), element.getContainingFile()).getType(qualifier);
         if (type instanceof PyClassType) {
           final PyClass cls = ((PyClassType)type).getPyClass();
           final String propertyName = ((PyQualifiedExpression)element).getName();
index 1ce1d7585220ad541d3bef1c073f5b8143409ceb..213bf6380e4fe100832497086225253cfd2a50ae 100644 (file)
@@ -108,7 +108,7 @@ public class PythonPatterns extends PlatformPatterns {
 
     // TODO is it better or worse to allow implicits here?
     PyResolveContext context = PyResolveContext.noImplicits()
-      .withTypeEvalContext(TypeEvalContext.codeAnalysis(expression.getContainingFile()));
+      .withTypeEvalContext(TypeEvalContext.codeAnalysis(expression.getProject(), expression.getContainingFile()));
 
     PyCallExpression.PyMarkedCallee callee = call.resolveCallee(context);
     return callee != null ? callee.getCallable() : null;
index dc8787328554e5dbcf9b838036bdbb443a266bda..1518b3410f1113234040a833fde8ad4b55f1c634 100644 (file)
@@ -1209,7 +1209,7 @@ public class PyUtil {
     if (isBaseException(pyClass.getQualifiedName())) {
       return true;
     }
-    for (PyClassLikeType type : pyClass.getAncestorTypes(TypeEvalContext.codeInsightFallback())) {
+    for (PyClassLikeType type : pyClass.getAncestorTypes(TypeEvalContext.codeInsightFallback(pyClass.getProject()))) {
       if (type != null && isBaseException(type.getClassQName())) {
         return true;
       }
index bd31703216500bb8ac330eb94e5a5d0b09311427..fd533068b8d0cb939406cf557d4a99c79515bff0 100644 (file)
@@ -148,7 +148,7 @@ public class PyBaseElementImpl<T extends StubElement> extends StubBasedPsiElemen
     List<PsiReference> referencesList = new ArrayList<PsiReference>();
     final PsiFile file = element.getContainingFile();
     final PyResolveContext resolveContext = file != null ?
-                                     PyResolveContext.defaultContext().withTypeEvalContext(TypeEvalContext.codeAnalysis(file)) :
+                                     PyResolveContext.defaultContext().withTypeEvalContext(TypeEvalContext.codeAnalysis(file.getProject(), file)) :
                                      PyResolveContext.defaultContext();
     while (element != null) {
       addReferences(offset, element, referencesList, resolveContext);
index c7f2173973c0f4b6af9b8b24121eabc41cb8724b..ad815a9fcb3ef9413206d48d6f3bc1a86099e285 100644 (file)
@@ -201,7 +201,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
   @NotNull
   @Override
   public List<PyClass> getAncestorClasses() {
-    return getAncestorClasses(TypeEvalContext.codeInsightFallback());
+    return getAncestorClasses(TypeEvalContext.codeInsightFallback(getProject()));
   }
 
   @NotNull
@@ -231,7 +231,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
     if (superClassQName.equals(getQualifiedName())) {
       return true;
     }
-    for (PyClassLikeType type : getAncestorTypes(TypeEvalContext.codeInsightFallback())) {
+    for (PyClassLikeType type : getAncestorTypes(TypeEvalContext.codeInsightFallback(getProject()))) {
       if (type != null && superClassQName.equals(type.getClassQName())) {
         return true;
       }
@@ -279,7 +279,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
 
   @NotNull
   public PyClass[] getSuperClasses() {
-    final List<PyClassLikeType> superTypes = getSuperClassTypes(TypeEvalContext.codeInsightFallback());
+    final List<PyClassLikeType> superTypes = getSuperClassTypes(TypeEvalContext.codeInsightFallback(getProject()));
     if (superTypes.isEmpty()) {
       return EMPTY_ARRAY;
     }
@@ -1033,7 +1033,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
     final PyClass objClass = PyBuiltinCache.getInstance(this).getClass("object");
     if (this == objClass) return true; // a rare but possible case
     if (hasNewStyleMetaClass(this)) return true;
-    for (PyClassLikeType type : getOldStyleAncestorTypes(TypeEvalContext.codeInsightFallback())) {
+    for (PyClassLikeType type : getOldStyleAncestorTypes(TypeEvalContext.codeInsightFallback(getProject()))) {
       if (type == null) {
         // unknown, assume new-style class
         return true;
index 3e60926c6cff832b19d2c0a343813a178d0ed4aa..66bddd1b83a1d4d960a3560b7ada5567f798d27d 100644 (file)
@@ -66,7 +66,7 @@ public class KeywordArgumentCompletionUtil {
     visited.add(def);
     boolean needSelf = def.getContainingClass() != null && def.getModifier() != PyFunction.Modifier.STATICMETHOD;
     final KwArgParameterCollector collector = new KwArgParameterCollector(needSelf, ret);
-    final TypeEvalContext context = TypeEvalContext.userInitiated(def.getContainingFile());
+    final TypeEvalContext context = TypeEvalContext.userInitiated(def.getProject(), def.getContainingFile());
     final List<PyParameter> parameters = PyUtil.getParameters(def, context);
     for (PyParameter parameter : parameters) {
       parameter.accept(collector);
index a3dad0b8eba803c81332abaf47d05597b818e50f..77f5829673bb75030ef492afa373fc446863671f 100644 (file)
@@ -97,7 +97,7 @@ public class PyImportReference extends PyReferenceImpl {
     }
 
     PyExpression qualifier = myElement.getQualifier();
-    final TypeEvalContext context = TypeEvalContext.userInitiated(CompletionUtil.getOriginalOrSelf(myElement).getContainingFile());
+    final TypeEvalContext context = TypeEvalContext.userInitiated(myElement.getProject(), CompletionUtil.getOriginalOrSelf(myElement).getContainingFile());
     if (qualifier != null) {
       // qualifier's type must be module, it should know how to complete
       PyType type = context.getType(qualifier);
index a537dae722c1e9fd8bb332a400d37bc5e4446272..60d2905312b311dec465069a71bc01849dc84eee 100644 (file)
@@ -260,7 +260,7 @@ public class PyQualifiedReference extends PyReferenceImpl {
     }
     final PyQualifiedExpression element = CompletionUtil.getOriginalOrSelf(myElement);
 
-    PyType qualifierType = TypeEvalContext.userInitiated(element.getContainingFile()).getType(qualifier);
+    PyType qualifierType = TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile()).getType(qualifier);
     ProcessingContext ctx = new ProcessingContext();
     final Set<String> namesAlready = new HashSet<String>();
     ctx.put(PyType.CTX_NAMES, namesAlready);
@@ -415,7 +415,7 @@ public class PyQualifiedReference extends PyReferenceImpl {
       if (containingFile instanceof StubBasedPsiElement) {
         assert ((StubBasedPsiElement)containingFile).getStub() == null : "Stub origin for type eval context in isReferenceTo()";
       }
-      final TypeEvalContext context = TypeEvalContext.codeAnalysis(containingFile);
+      final TypeEvalContext context = TypeEvalContext.codeAnalysis(containingFile.getProject(), containingFile);
       resolveContext = resolveContext.withTypeEvalContext(context);
     }
     if (element instanceof PyFunction && Comparing.equal(referencedName, ((PyFunction)element).getName()) &&
index bfa402449853d030d79996240e595e4b6035a7bb..cbc791fbfc60f0dab2e49287b7c0aa45b6d10872 100644 (file)
@@ -17,6 +17,7 @@ package com.jetbrains.python.psi.resolve;
 
 import com.intellij.codeInsight.lookup.LookupElement;
 import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Condition;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiElement;
@@ -65,8 +66,9 @@ public class CompletionVariantsProcessor extends VariantsProcessor {
           object instanceof PyFunction && ((PyFunction)object).getProperty() == null &&
           !PyUtil.hasCustomDecorators((PyFunction)object) &&
           !isSingleArgDecoratorCall(myContext, (PyFunction)object)) {
+        final Project project = ((PyFunction)object).getProject();
         item = item.withInsertHandler(PyFunctionInsertHandler.INSTANCE);
-        final TypeEvalContext context = TypeEvalContext.userInitiated(myContext != null ? myContext.getContainingFile() : null);
+        final TypeEvalContext context = TypeEvalContext.userInitiated(project, myContext != null ? myContext.getContainingFile() : null);
         final List<PyParameter> parameters = PyUtil.getParameters((PyFunction)object, context);
         final String params = StringUtil.join(parameters, new Function<PyParameter, String>() {
           @Override
index 520c9b558881eb2ba2f1911586e770528f364611..08d0ffd6e84eea9ddda1ad50f898ea1ff0350378 100644 (file)
@@ -82,7 +82,7 @@ public class PyCallableTypeImpl implements PyCallableType {
   @Nullable
   @Override
   public String getName() {
-    final TypeEvalContext context = TypeEvalContext.codeInsightFallback();
+    final TypeEvalContext context = TypeEvalContext.codeInsightFallback(null);
     return String.format("(%s) -> %s",
                          myParameters != null ?
                          StringUtil.join(myParameters,
index d9b69121aa50b5552499ee4eefe64cc32c87c959..25b524272b7b891cf534d0afc6ee499f83d717eb 100644 (file)
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.Ref;
 import com.intellij.openapi.util.UserDataHolderBase;
 import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiInvalidElementAccessException;
 import com.intellij.psi.PsiReference;
 import com.intellij.psi.util.PsiTreeUtil;
@@ -410,9 +411,11 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
     boolean suppressParentheses = context.get(CTX_SUPPRESS_PARENTHESES) != null;
     addOwnClassMembers(location, namesAlready, suppressParentheses, ret);
 
-    final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(location != null ?
-                                                                          CompletionUtil.getOriginalOrSelf(location).getContainingFile() :
-                                                                          null);
+    PsiFile origin = (location != null) ?
+                     CompletionUtil.getOriginalOrSelf(location)
+                       .getContainingFile() :
+                     null;
+    final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(myClass.getProject(), origin);
     addInheritedMembers(prefix, location, namesAlready, context, ret, typeEvalContext);
 
     // from providers
index 81efda9e040df0c30a3bb3b215b7631fe245484d..24072ddb74e9e5406ad23940ed7b1b7bcb30e1d7 100644 (file)
@@ -55,7 +55,7 @@ public class PyCollectionTypeImpl extends PyClassTypeImpl implements PyCollectio
 
     PyCollectionType type = (PyCollectionType)o;
 
-    final TypeEvalContext context = TypeEvalContext.codeInsightFallback();
+    final TypeEvalContext context = TypeEvalContext.codeInsightFallback(myClass.getProject());
     if (myElementType != null ? !myElementType.equals(type.getElementType(context)) : type.getElementType(context) != null) return false;
 
     return true;
index 85624b1d0f104ceac544fe29eefae6aa4ad642ca..0260b2f8465623d1518b2813438e02478b30c59d 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.jetbrains.python.psi.types;
 
+import com.intellij.openapi.project.Project;
 import com.jetbrains.python.PyNames;
 import org.jetbrains.annotations.NotNull;
 
@@ -49,7 +50,7 @@ public class PyDynamicallyEvaluatedType extends PyUnionType {
 
   @Override
   public String getName() {
-    PyType res = excludeNull(TypeEvalContext.codeInsightFallback());
+    PyType res = excludeNull(TypeEvalContext.codeInsightFallback(null));
     return res != null ? res.getName() : PyNames.UNKNOWN_TYPE;
   }
 }
index fe3633449b7427afeeb77c418f6f77dc673578a8..35ccb21383222703a98150c761cf69fffbfcc94a 100644 (file)
@@ -88,7 +88,7 @@ public class PyFunctionType implements PyCallableType {
 
   @Override
   public Object[] getCompletionVariants(String completionPrefix, PsiElement location, ProcessingContext context) {
-    final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(location.getContainingFile());
+    final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(location.getProject(), location.getContainingFile());
     final PyClassType delegate;
     if (location instanceof PyReferenceExpression) {
       delegate = selectFakeType(((PyReferenceExpression)location).getQualifier(), typeEvalContext);
index 9e1923218494b741d7286fc70c1bef93aafcbcba..114c6469d4c9c5dc00764403a7dfaecab2fd4cf7 100644 (file)
@@ -343,7 +343,7 @@ public class PyTypeParser {
 
       if (file instanceof PyFile) {
         final PyFile pyFile = (PyFile)file;
-        final TypeEvalContext context = TypeEvalContext.codeInsightFallback();
+        final TypeEvalContext context = TypeEvalContext.codeInsightFallback(file.getProject());
         final Map<TextRange, PyType> types = new HashMap<TextRange, PyType>();
         final Map<PyType, TextRange> fullRanges = new HashMap<PyType, TextRange>();
         final Map<PyType, PyImportElement> imports = new HashMap<PyType, PyImportElement>();
index 6186eafc0905d665abc5d639cde0c273202c2cee..9a2cb502431b1d91923093000f21d4a6cc3a77db 100644 (file)
@@ -152,7 +152,7 @@ public class PyReplaceExpressionUtil implements PyElementTypes {
         return replaceSubstringWithDictFormatting(oldExpression, quotes, prefix, suffix, formatValue, newText);
       }
       else {
-        final TypeEvalContext context = TypeEvalContext.userInitiated(oldExpression.getContainingFile());
+        final TypeEvalContext context = TypeEvalContext.userInitiated(oldExpression.getProject(), oldExpression.getContainingFile());
         final PyType valueType = context.getType(formatValue);
         final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(oldExpression);
         final PyType tupleType = builtinCache.getTupleType();
index 56bd80ca30778743389597b38e8751f42380066f..d3501ec1ea256209b8874482143c8ba4a9d865f9 100644 (file)
@@ -122,7 +122,7 @@ class MethodsManager extends MembersManager<PyFunction> {
   // TODO: Copy/Paste with PyClass.getMeta..
   private static boolean addMetaAbcIfNeeded(@NotNull final PyClass aClass) {
     final PsiFile file = aClass.getContainingFile();
-    final PyType type = aClass.getMetaClassType(TypeEvalContext.userInitiated(file));
+    final PyType type = aClass.getMetaClassType(TypeEvalContext.userInitiated(aClass.getProject(), file));
     if (type != null) {
       return false; //User already has metaclass. He probably knows about metaclasses, so we should not add ABCMeta
     }
index 05c41c47894ad4ea36b6a3120bdb1442c8ce85a5..bc2af5e6f8efe920b532a7639bb34a2ff6d645fb 100644 (file)
@@ -45,7 +45,7 @@ class PyAncestorsUtils extends NotNullPredicate<PyClass> {
    */
   @NotNull
   static Collection<PyClass> getAncestorsUnderUserControl(@NotNull final PyClass pyClass) {
-    final List<PyClass> allAncestors = pyClass.getAncestorClasses(TypeEvalContext.userInitiated(pyClass.getContainingFile()));
+    final List<PyClass> allAncestors = pyClass.getAncestorClasses(TypeEvalContext.userInitiated(pyClass.getProject(), pyClass.getContainingFile()));
     return Collections2.filter(allAncestors, new PyAncestorsUtils(PyUtil.getSourceRoots(pyClass)));
   }
 
index 069f0e596197e6384d721c75241776ff5b8970d5..27c755b7bcd99b3edef05f3c2164cd541b69d570 100644 (file)
@@ -205,7 +205,7 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
     if (text != null) {
       candidates.addAll(NameSuggesterUtil.generateNames(text));
     }
-    final TypeEvalContext context = TypeEvalContext.userInitiated(expression.getContainingFile());
+    final TypeEvalContext context = TypeEvalContext.userInitiated(expression.getProject(), expression.getContainingFile());
     PyType type = context.getType(expression);
     if (type != null && type != PyNoneType.INSTANCE) {
       String typeName = type.getName();
index ef4af733e09678f45ac5a99ed9227cf5f42fe6ee..7b7b4a89965d8011097cc4f6e2108ebabbf554ba 100644 (file)
@@ -82,7 +82,7 @@ public class PythonUnitTestUtil {
         if (expression.getText().equals("TestCase")) return true;
       }
     }
-    for (PyClassLikeType type : cls.getAncestorTypes(TypeEvalContext.codeInsightFallback())) {
+    for (PyClassLikeType type : cls.getAncestorTypes(TypeEvalContext.codeInsightFallback(cls.getProject()))) {
       if (type != null && testQualifiedNames.contains(type.getClassQName())) {
         return true;
       }
@@ -153,7 +153,7 @@ public class PythonUnitTestUtil {
   }
 
   public static boolean isTestCaseClass(@NotNull PyClass cls, Set<String> testQualifiedNames) {
-    for (PyClassLikeType type : cls.getAncestorTypes(TypeEvalContext.codeInsightFallback())) {
+    for (PyClassLikeType type : cls.getAncestorTypes(TypeEvalContext.codeInsightFallback(cls.getProject()))) {
       if (type != null) {
         if (testQualifiedNames.contains(type.getClassQName())) {
           return true;
index 006749a25e9681c79a10fd1092bbad8ad802450f..6035d5b266e1601f0259bbb9180002b09771ac6f 100644 (file)
@@ -51,7 +51,7 @@ public class PythonAtTestConfigurationProducer extends
 
   @Override
   protected boolean isTestClass(@NotNull final PyClass pyClass, @Nullable final AbstractPythonTestRunConfiguration configuration) {
-    for (PyClassLikeType type : pyClass.getAncestorTypes(TypeEvalContext.codeInsightFallback())) {
+    for (PyClassLikeType type : pyClass.getAncestorTypes(TypeEvalContext.codeInsightFallback(pyClass.getProject()))) {
       if (type != null && "TestBase".equals(type.getName()) && hasTestFunction(pyClass)) {
         return true;
       }
index 35722753272777fb4758b1bbdcf194949e23af9b..11dfb4fb0e5c8716d9444c3377a05647e614bc4f 100644 (file)
@@ -71,7 +71,7 @@ public class PyTestUtil {
   }
 
   public static boolean isPyTestClass(PyClass pyClass) {
-    for (PyClassLikeType type : pyClass.getAncestorTypes(TypeEvalContext.codeInsightFallback())) {
+    for (PyClassLikeType type : pyClass.getAncestorTypes(TypeEvalContext.codeInsightFallback(pyClass.getProject()))) {
       if (type != null && PYTHON_TEST_QUALIFIED_CLASSES.contains(type.getClassQName())) {
         return true;
       }
index c6b150f3135993b31eed231f78e3b3bae524e034..325482d239114941c421f054dc5dee25408702ad 100644 (file)
@@ -126,7 +126,8 @@ public class PythonSkeletonsTest extends PyEnvTestCase {
         myFixture.configureByText(PythonFileType.INSTANCE,
                                   "expr = slice(1, 2).start\n");
         final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
-        final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getFile());
+        PsiFile file = myFixture.getFile();
+        final TypeEvalContext context = TypeEvalContext.codeAnalysis(file.getProject(), file);
         ApplicationManager.getApplication().runReadAction(new Runnable() {
           @Override
           public void run() {
index 2e55003cddd0fe6cc077ca072fe6e4200c42e50b..71d2498b39f86904a3b615b9c3ff1327fd412f13 100644 (file)
@@ -95,7 +95,7 @@ public class PyClassicPropertyTest extends PyTestCase {
     accessor = p.getGetter();
     assertFalse(accessor.isDefined());
 
-    final PyType codeInsightType = p.getType(TypeEvalContext.codeInsightFallback());
+    final PyType codeInsightType = p.getType(TypeEvalContext.codeInsightFallback(myClass.getProject()));
     assertNull(codeInsightType);
 
     accessor = p.getSetter();
index 2a58613f1668d4105a649e3f9d4b693d6a9b6c90..633d110116c930f85d4be8d6994a8ec276357d2b 100644 (file)
@@ -422,7 +422,7 @@ public class PyStubsTest extends PyTestCase {
     final PyClass d = file.findTopLevelClass("D");
     assertNotNull(d);
     assertNull(d.getMetaClassExpression());
-    assertNotNull(d.getMetaClassType(TypeEvalContext.codeInsightFallback()));
+    assertNotNull(d.getMetaClassType(TypeEvalContext.codeInsightFallback(c.getProject())));
     assertNotParsed(file);
   }
 }
index 7db230a1d7c1e1d7c155d8a5cf4925b95d4536e3..adc7a931dc86c697400e1abd7e29ce317dcc61d7 100644 (file)
@@ -68,7 +68,7 @@ public class PyTypeParserTest extends PyTestCase {
   }
 
   private TypeEvalContext getTypeEvalContext() {
-    return TypeEvalContext.userInitiated(myFixture.getFile());
+    return TypeEvalContext.userInitiated(myFixture.getProject(), myFixture.getFile());
   }
 
   public void testUnionType() {
@@ -188,7 +188,7 @@ public class PyTypeParserTest extends PyTestCase {
     final PyCollectionType collectionType = (PyCollectionType)type;
     assertNotNull(collectionType);
     assertEquals("list", collectionType.getName());
-    final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
+    final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback(null));
     assertInstanceOf(elementType, PyUnionType.class);
   }
 
@@ -209,7 +209,7 @@ public class PyTypeParserTest extends PyTestCase {
     final PyCollectionType collectionType = (PyCollectionType)type;
     assertNotNull(collectionType);
     assertEquals("list", collectionType.getName());
-    final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
+    final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback(null));
     assertNotNull(elementType);
     assertEquals("int", elementType.getName());
   }
@@ -221,7 +221,7 @@ public class PyTypeParserTest extends PyTestCase {
     final PyCollectionType collectionType = (PyCollectionType)type;
     assertNotNull(collectionType);
     assertEquals("dict", collectionType.getName());
-    final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback());
+    final PyType elementType = collectionType.getElementType(TypeEvalContext.codeInsightFallback(null));
     assertNotNull(elementType);
     assertInstanceOf(elementType, PyTupleType.class);
     final PyTupleType tupleType = (PyTupleType)elementType;
@@ -291,7 +291,7 @@ public class PyTypeParserTest extends PyTestCase {
     myFixture.configureByFile("typeParser/typeParser.py");
     final PsiFile file = myFixture.getFile();
     final PyType type = PyTypeParser.getTypeByName(file, text);
-    TypeEvalContext context = TypeEvalContext.userInitiated(file).withTracing();
+    TypeEvalContext context = TypeEvalContext.userInitiated(file.getProject(), file).withTracing();
     final String actualType = PythonDocumentationProvider.getTypeName(type, context);
     assertEquals(expectedType, actualType);
   }
index 7f33c1185eb4b38ce9f552efd0f1934776dd4294..1596596ad2de4d57edd002e318f4513920126a1f 100644 (file)
@@ -874,7 +874,7 @@ public class PyTypeTest extends PyTestCase {
   }
 
   private static TypeEvalContext getTypeEvalContext(@NotNull PyExpression element) {
-    return TypeEvalContext.userInitiated(element.getContainingFile()).withTracing();
+    return TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile()).withTracing();
   }
 
   private PyExpression parseExpr(String text) {
index 9513795cb5b7de1f678b2f325546c5465a5c73f5..96ad88365d06cc446934871e868995d92deca4e1 100644 (file)
@@ -253,8 +253,8 @@ public class PyTypingTest extends PyTestCase {
     myFixture.copyDirectoryToProject("typing", "");
     myFixture.configureByText(PythonFileType.INSTANCE, text);
     final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
-    final TypeEvalContext codeAnalysis = TypeEvalContext.codeAnalysis(expr.getContainingFile());
-    final TypeEvalContext userInitiated = TypeEvalContext.userInitiated(expr.getContainingFile()).withTracing();
+    final TypeEvalContext codeAnalysis = TypeEvalContext.codeAnalysis(expr.getProject(),expr.getContainingFile());
+    final TypeEvalContext userInitiated = TypeEvalContext.userInitiated(expr.getProject(), expr.getContainingFile()).withTracing();
     assertType(expectedType, expr, codeAnalysis, "code analysis");
     assertType(expectedType, expr, userInitiated, "user initiated");
   }
index 6d9fea6d4a9750449a529483231aa656e942dc3f..eb828b7eed8c449685775f3451efd99ad878f3dc 100644 (file)
@@ -72,7 +72,7 @@ public class PyClassMROTest extends PyTestCase {
   }
 
   public void assertMRO(@NotNull PyClass cls, @NotNull String... mro) {
-    final List<PyClassLikeType> types = cls.getAncestorTypes(TypeEvalContext.codeInsightFallback());
+    final List<PyClassLikeType> types = cls.getAncestorTypes(TypeEvalContext.codeInsightFallback(cls.getProject()));
     final List<String> classNames = new ArrayList<String>();
     for (PyClassLikeType type : types) {
       if (type != null) {