public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
    if (!TypeEvalStack.mayEvaluate(this)) {
      return null;
    }
    try {
      final boolean qualified = isQualified();
      if (!qualified) {
        String name = getReferencedName();
        if (PyNames.NONE.equals(name)) {
          return PyNoneType.INSTANCE;
        }
      }
      PyType type = getTypeFromProviders(context);
      if (type != null) {
        return type;
      }
      if (qualified) {
        PyType maybe_type = PyUtil.getSpecialAttributeType(this, context);
        if (maybe_type != null) return maybe_type;
        Ref<PyType> typeOfProperty = getTypeOfProperty(context);
        if (typeOfProperty != null) {
          return typeOfProperty.get();
        }
      }
      final PsiPolyVariantReference reference =
          getReference(PyResolveContext.noImplicits().withTypeEvalContext(context));
      final List<PsiElement> targets = PyUtil.multiResolveTopPriority(reference);
      if (targets.isEmpty()) {
        return getQualifiedReferenceTypeByControlFlow(context);
      }

      final List<PyType> members = new ArrayList<PyType>();
      for (PsiElement target : targets) {
        if (target == this || target == null) {
          continue;
        }
        if (!target.isValid()) {
          LOG.error(
              "Reference "
                  + this
                  + " resolved to invalid element "
                  + target
                  + " (text="
                  + target.getText()
                  + ")");
          continue;
        }
        members.add(getTypeFromTarget(target, context, this));
      }

      return PyUnionType.union(members);
    } finally {
      TypeEvalStack.evaluated(this);
    }
  }
 @NotNull
 private static List<PsiElement> tryResolving(
     @NotNull PyExpression expression, @NotNull TypeEvalContext context) {
   final List<PsiElement> elements = Lists.newArrayList();
   if (expression instanceof PyReferenceExpression) {
     final PyReferenceExpression referenceExpr = (PyReferenceExpression) expression;
     final PyResolveContext resolveContext =
         PyResolveContext.noImplicits().withTypeEvalContext(context);
     final PsiPolyVariantReference reference = referenceExpr.getReference(resolveContext);
     final List<PsiElement> resolved = PyUtil.multiResolveTopPriority(reference);
     for (PsiElement element : resolved) {
       if (element instanceof PyFunction) {
         final PyFunction function = (PyFunction) element;
         if (PyUtil.isInit(function)) {
           final PyClass cls = function.getContainingClass();
           if (cls != null) {
             elements.add(cls);
             continue;
           }
         }
       } else if (element instanceof PyTargetExpression) {
         final PyTargetExpression targetExpr = (PyTargetExpression) element;
         // XXX: Requires switching from stub to AST
         final PyExpression assignedValue = targetExpr.findAssignedValue();
         if (assignedValue != null) {
           elements.add(assignedValue);
           continue;
         }
       }
       if (element != null) {
         elements.add(element);
       }
     }
   }
   return !elements.isEmpty() ? elements : Collections.singletonList(expression);
 }