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);
}
public TypeEvalContext getTypeEvalContext() {
- return myTypeEvalContext != null ? myTypeEvalContext : TypeEvalContext.codeInsightFallback();
+ return myTypeEvalContext != null ? myTypeEvalContext : TypeEvalContext.codeInsightFallback(null);
}
@Override
--- /dev/null
+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;
+ }
+}
*/
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;
* @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>();
};
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() {
public void traceUnindent() {
if (myTrace != null && myTraceIndent.length() >= 2) {
- myTraceIndent = myTraceIndent.substring(0, myTraceIndent.length()-2);
+ myTraceIndent = myTraceIndent.substring(0, myTraceIndent.length() - 2);
}
}
}
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;
}
}
--- /dev/null
+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;
+ }
+ }
+}
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) {
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();
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();
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)) {
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;
}
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();
}
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;
}
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");
(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;
}
}
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() {
@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) {
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
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());
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();
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());
}
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)) {
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,
}
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);
}
@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();
}
//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);
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);
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();
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;
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);
}
}
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);
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);
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.
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);
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();
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();
// 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;
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;
}
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);
@NotNull
@Override
public List<PyClass> getAncestorClasses() {
- return getAncestorClasses(TypeEvalContext.codeInsightFallback());
+ return getAncestorClasses(TypeEvalContext.codeInsightFallback(getProject()));
}
@NotNull
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;
}
@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;
}
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;
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);
}
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);
}
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);
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()) &&
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;
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
@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,
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;
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
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;
*/
package com.jetbrains.python.psi.types;
+import com.intellij.openapi.project.Project;
import com.jetbrains.python.PyNames;
import org.jetbrains.annotations.NotNull;
@Override
public String getName() {
- PyType res = excludeNull(TypeEvalContext.codeInsightFallback());
+ PyType res = excludeNull(TypeEvalContext.codeInsightFallback(null));
return res != null ? res.getName() : PyNames.UNKNOWN_TYPE;
}
}
@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);
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>();
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();
// 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
}
*/
@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)));
}
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();
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;
}
}
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;
@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;
}
}
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;
}
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() {
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();
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);
}
}
}
private TypeEvalContext getTypeEvalContext() {
- return TypeEvalContext.userInitiated(myFixture.getFile());
+ return TypeEvalContext.userInitiated(myFixture.getProject(), myFixture.getFile());
}
public void testUnionType() {
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);
}
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());
}
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;
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);
}
}
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) {
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");
}
}
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) {