@Nullable
 private Ref<PyType> getTypeOfProperty(
     @Nullable PyType qualifierType, @NotNull String name, @NotNull TypeEvalContext context) {
   if (qualifierType instanceof PyClassType) {
     final PyClassType classType = (PyClassType) qualifierType;
     PyClass pyClass = classType.getPyClass();
     Property property = pyClass.findProperty(name, true);
     if (property != null) {
       if (classType.isDefinition()) {
         return Ref.<PyType>create(
             PyBuiltinCache.getInstance(pyClass).getObjectType(PyNames.PROPERTY));
       }
       if (AccessDirection.of(this) == AccessDirection.READ) {
         final PyType type = property.getType(context);
         if (type != null) {
           return Ref.create(type);
         }
       }
       return Ref.create();
     }
   } else if (qualifierType instanceof PyUnionType) {
     final PyUnionType unionType = (PyUnionType) qualifierType;
     for (PyType type : unionType.getMembers()) {
       final Ref<PyType> result = getTypeOfProperty(type, name, context);
       if (result != null) {
         return result;
       }
     }
   }
   return null;
 }
  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);
    }
  }
 private static PyType getTypeByControlFlow(
     @NotNull String name,
     @NotNull TypeEvalContext context,
     @NotNull PyExpression anchor,
     @NotNull ScopeOwner scopeOwner) {
   PyAugAssignmentStatement augAssignment =
       PsiTreeUtil.getParentOfType(anchor, PyAugAssignmentStatement.class);
   try {
     final PyElement element = augAssignment != null ? augAssignment : anchor;
     final List<ReadWriteInstruction> defs =
         PyDefUseUtil.getLatestDefs(scopeOwner, name, element, true);
     if (!defs.isEmpty()) {
       PyType type = defs.get(0).getType(context, anchor);
       for (int i = 1; i < defs.size(); i++) {
         type = PyUnionType.union(type, defs.get(i).getType(context, anchor));
       }
       return type;
     }
   } catch (PyDefUseUtil.InstructionNotFoundException ignored) {
   }
   return null;
 }