Ref<PyType> (@NotNull PsiElement referenceTarget, @NotNull Context context, @Nullable PsiElement anchor) { if (referenceTarget instanceof PyTargetExpression target) { final String targetQName = target.getQualifiedName(); // Depends on typing.Generic defined as a target expression if (GENERIC.equals(targetQName)) { return Ref.create(createTypingGenericType(target)); } // Depends on typing.Protocol defined as a target expression if (PROTOCOL.equals(targetQName) || PROTOCOL_EXT.equals(targetQName)) { return Ref.create(createTypingProtocolType(target)); } // Depends on typing.Callable defined as a target expression if (CALLABLE.equals(targetQName)) { return Ref.create(createTypingCallableType(referenceTarget)); } final PyType collection = getCollection(target, context.myContext); if (collection instanceof PyInstantiableType) { return Ref.create(((PyInstantiableType<?>)collection).toClass()); } final PyType typedDictType = getTypedDictTypeForTarget(target, context.myContext); if (typedDictType != null) { return Ref.create(typedDictType); } final Ref<PyType> annotatedType = getTypeFromTargetExpressionAnnotation(target, context); if (annotatedType != null) { return annotatedType; } final PyExpression assignedValue = PyTypingAliasStubType.getAssignedValueStubLike(target); if (assignedValue != null) { final PyType type = getTypeParameterTypeFromDeclaration(assignedValue, context); if (type != null) { return Ref.create(type); } } final String name = target.getReferencedName(); final ScopeOwner scopeOwner = ScopeUtil.getScopeOwner(target); if (name == null || scopeOwner == null) { return null; } final PyClass pyClass = target.getContainingClass(); if (target.isQualified()) { if (pyClass != null && scopeOwner instanceof PyFunction) { final PyResolveContext resolveContext = PyResolveContext.defaultContext(context.myContext); boolean isInstanceAttribute; if (context.myContext.maySwitchToAST(target)) { isInstanceAttribute = StreamEx.of(PyUtil.multiResolveTopPriority(target.getQualifier(), resolveContext)) .select(PyParameter.class) .filter(PyParameter::isSelf) .anyMatch(p -> PsiTreeUtil.getParentOfType(p, PyFunction.class) == scopeOwner); } else { isInstanceAttribute = PyUtil.isInstanceAttribute(target); } if (!isInstanceAttribute) { return null; } // Set isDefinition=true to start searching right from the class level. final PyClassTypeImpl classType = new PyClassTypeImpl(pyClass, true); final List<? extends RatedResolveResult> classAttrs = classType.resolveMember(name, target, AccessDirection.READ, resolveContext, true); if (classAttrs == null) { return null; } return StreamEx.of(classAttrs) .map(RatedResolveResult::getElement) .select(PyTargetExpression.class) .filter(x -> ScopeUtil.getScopeOwner(x) instanceof PyClass) .map(x -> getTypeFromTargetExpressionAnnotation(x, context)) .collect(PyTypeUtil.toUnionFromRef()); } } else { StreamEx<PyTargetExpression> candidates = null; if (context.myContext.maySwitchToAST(target)) { final Scope scope = ControlFlowCache.getScope(scopeOwner); candidates = StreamEx.of(scope.getNamedElements(name, false)).select(PyTargetExpression.class); } // Unqualified target expression in either class or module else if (scopeOwner instanceof PyFile) { candidates = StreamEx.of(((PyFile)scopeOwner).getTopLevelAttributes()).filter(t -> name.equals(t.getName())); } else if (scopeOwner instanceof PyClass) { candidates = StreamEx.of(((PyClass)scopeOwner).getClassAttributes()).filter(t -> name.equals(t.getName())); } if (candidates != null) { return candidates .map(x -> getTypeFromTargetExpressionAnnotation(x, context)) .nonNull() .findFirst() .orElse(null); } } } return null; }