Ref<PyType> (@NotNull PsiElement referenceTarget, @NotNull TypeEvalContext context, @Nullable PsiElement anchor) { if (!(referenceTarget instanceof PyDecoratable pyDecoratable)) { return null; } PyDecoratorList decoratorList = pyDecoratable.getDecoratorList(); if (decoratorList == null) { return null; } List<PyDecorator> decorators = ContainerUtil.filter(decoratorList.getDecorators(), d -> PyKnownDecoratorUtil.asKnownDecorators(d, context).isEmpty() ); if (decorators.isEmpty()) { return null; } /* Our goal is to infer the type of reference of decorated object. * For that we going to infer a type of expression <code>decorator(reference)<code>. * The expression contains a new reference for the same object, and our * type inferring engine will ask this provider about the type of the object again. * To prevent an infinite loop, we need to add a recursion guard here. */ return RecursionManager.doPreventingRecursion( Pair.create(referenceTarget, context), false, () -> evaluateType(pyDecoratable, context, decorators) ); }