From 23ed6bcdaaf61d596dd621b4f061ba9b2d97857b Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 8 May 2013 19:02:56 +0400 Subject: [PATCH] Slow TypeEvalContext for completion, documentation, find usages, quick-fixes --- .../jetbrains/python/psi/types/TypeEvalContext.java | 5 +++++ .../PyDictKeyNamesCompletionContributor.java | 2 +- .../python/documentation/DocStringTypeReference.java | 2 +- .../python/documentation/PyDocumentationBuilder.java | 2 +- .../documentation/PythonDocumentationProvider.java | 2 +- .../python/findUsages/PyUsageTypeProvider.java | 2 +- .../inspections/quickfix/AddMethodQuickFix.java | 2 +- .../python/psi/impl/references/PyImportReference.java | 11 +++++++---- .../com/jetbrains/python/PyTypeParserTest.java | 4 ++-- 9 files changed, 20 insertions(+), 12 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java index e7790bec470d..23f9cf885024 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java @@ -53,6 +53,11 @@ public class TypeEvalContext { return myAllowDataFlow || element.getContainingFile() == myOrigin; } + /** + * The most detailed type evaluation context for user-initiated actions. + * + * Should be used for code completion, go to definition, find usages, refactorings, documentation. + */ public static TypeEvalContext slow() { return new TypeEvalContext(true, true, null); } diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyDictKeyNamesCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyDictKeyNamesCompletionContributor.java index ee5c6a315ac8..ca6e440cb922 100644 --- a/python/src/com/jetbrains/python/codeInsight/completion/PyDictKeyNamesCompletionContributor.java +++ b/python/src/com/jetbrains/python/codeInsight/completion/PyDictKeyNamesCompletionContributor.java @@ -114,7 +114,7 @@ public class PyDictKeyNamesCompletionContributor extends CompletionContributor { if (callee == null) return; final String name = callee.getText(); if ("dict".equals(name)) { - final TypeEvalContext context = TypeEvalContext.fast(); + final TypeEvalContext context = TypeEvalContext.slow(); final PyType type = context.getType(dictConstructor); if (type != null && type.isBuiltin(context)) { final PyArgumentList list = dictConstructor.getArgumentList(); diff --git a/python/src/com/jetbrains/python/documentation/DocStringTypeReference.java b/python/src/com/jetbrains/python/documentation/DocStringTypeReference.java index 722d8e8168cc..6c3b1c8dfb01 100644 --- a/python/src/com/jetbrains/python/documentation/DocStringTypeReference.java +++ b/python/src/com/jetbrains/python/documentation/DocStringTypeReference.java @@ -113,7 +113,7 @@ public class DocStringTypeReference extends PsiPolyVariantReferenceBase 0) { - PyType first_arg_type = TypeEvalContext.fast().getType(args[0]); + PyType first_arg_type = TypeEvalContext.slow().getType(args[0]); if (first_arg_type instanceof PyClassType && ((PyClassType)first_arg_type).getPyClass().isSubclass(cls)) { // class, first arg ok: instance method builder.parameter("self"); // NOTE: might use a name other than 'self', according to code style. diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyImportReference.java b/python/src/com/jetbrains/python/psi/impl/references/PyImportReference.java index cffc4a2790c2..a83df0b203e1 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyImportReference.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyImportReference.java @@ -81,9 +81,10 @@ public class PyImportReference extends PyReferenceImpl { } PyExpression qualifier = myElement.getQualifier(); + final TypeEvalContext context = TypeEvalContext.slow(); if (qualifier != null) { // qualifier's type must be module, it should know how to complete - PyType type = TypeEvalContext.fast().getType(qualifier); + PyType type = context.getType(qualifier); if (type != null) { Object[] variants = getTypeCompletionVariants(myElement, type); if (!alreadyHasImportKeyword()) { @@ -97,7 +98,7 @@ public class PyImportReference extends PyReferenceImpl { } else { // complete to possible modules - return new ImportVariantCollector().execute(); + return new ImportVariantCollector(context).execute(); } } @@ -153,8 +154,10 @@ public class PyImportReference extends PyReferenceImpl { private final PsiFile myCurrentFile; private final Set myNamesAlready; private final List myObjects; + @NotNull private final TypeEvalContext myContext; - public ImportVariantCollector() { + public ImportVariantCollector(@NotNull TypeEvalContext context) { + myContext = context; PsiFile currentFile = myElement.getContainingFile(); if (currentFile != null) currentFile = currentFile.getOriginalFile(); myCurrentFile = currentFile; @@ -177,7 +180,7 @@ public class PyImportReference extends PyReferenceImpl { addImportedNames(from_import.getImportElements()); // don't propose already imported items // try to collect submodules PyExpression module = (PyExpression)mod_candidate; - PyType qualifierType = TypeEvalContext.fast().getType(module); + PyType qualifierType = myContext.getType(module); if (qualifierType != null) { ProcessingContext ctx = new ProcessingContext(); ctx.put(PyType.CTX_NAMES, myNamesAlready); diff --git a/python/testSrc/com/jetbrains/python/PyTypeParserTest.java b/python/testSrc/com/jetbrains/python/PyTypeParserTest.java index ac59d7594cc0..601878d77c06 100644 --- a/python/testSrc/com/jetbrains/python/PyTypeParserTest.java +++ b/python/testSrc/com/jetbrains/python/PyTypeParserTest.java @@ -33,7 +33,7 @@ public class PyTypeParserTest extends PyTestCase { myFixture.configureByFile("typeParser/typeParser.py"); final PyCollectionType type = (PyCollectionType) PyTypeParser.getTypeByName(myFixture.getFile(), "list of MyObject"); assertClassType(type, "list"); - assertClassType(type.getElementType(TypeEvalContext.fast()), "MyObject"); + assertClassType(type.getElementType(TypeEvalContext.slow()), "MyObject"); } public void testDictType() { @@ -41,7 +41,7 @@ public class PyTypeParserTest extends PyTestCase { final PyCollectionType type = (PyCollectionType) PyTypeParser.getTypeByName(myFixture.getFile(), "dict from str to MyObject"); assertNotNull(type); assertClassType(type, "dict"); - final PyType elementType = type.getElementType(TypeEvalContext.fast()); + final PyType elementType = type.getElementType(TypeEvalContext.slow()); assertInstanceOf(elementType, PyTupleType.class); final PyTupleType tupleType = (PyTupleType)elementType; assertEquals(2, tupleType.getElementCount());