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);
    }
  }
 public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
   final ASTNode nameElement = PyUtil.createNewName(this, name);
   final ASTNode nameNode = getNameNode();
   if (nameNode != null) {
     getNode().replaceChild(nameNode, nameElement);
   }
   return this;
 }
 @Override
 public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
   for (PyTypeProvider provider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
     final PyType type = provider.getCallableType(this, context);
     if (type != null) {
       return type;
     }
   }
   final boolean hasCustomDecorators =
       PyUtil.hasCustomDecorators(this)
           && !PyUtil.isDecoratedAsAbstract(this)
           && getProperty() == null;
   final PyFunctionType type = new PyFunctionType(this);
   if (hasCustomDecorators) {
     return PyUnionType.createWeakType(type);
   }
   return type;
 }
 @NotNull
 @Override
 public ProtectionLevel getProtectionLevel() {
   final int underscoreLevels = PyUtil.getInitialUnderscores(getName());
   for (final ProtectionLevel level : ProtectionLevel.values()) {
     if (level.getUnderscoreLevel() == underscoreLevels) {
       return level;
     }
   }
   return ProtectionLevel.PRIVATE;
 }
 @Nullable
 private static Boolean isOverrides(final PyFunction pyFunction) {
   final PyClass clazz = PyUtil.getContainingClassOrSelf(pyFunction);
   assert clazz != null : "Refactoring called on function, not method: " + pyFunction;
   for (final PyClass parentClass : clazz.getSuperClasses()) {
     final PyFunction parentMethod = parentClass.findMethodByName(pyFunction.getName(), true);
     if (parentMethod != null) {
       return true;
     }
   }
   return null;
 }
  /**
   * @return if method could be made abstract? (that means "create abstract version if method in
   *     parent class")
   */
  private static boolean couldBeAbstract(@NotNull final PyFunction function) {
    if (PyUtil.isInit(function)) {
      return false; // Who wants to make __init__ abstract?!
    }
    final PyUtil.MethodFlags flags = PyUtil.MethodFlags.of(function);
    assert flags != null : "Function should be called on method!";

    final boolean py3K = LanguageLevel.forElement(function).isPy3K();

    // TODO: use strategy because we already has the same check in #addMetaAbcIfNeeded
    return flags.isInstanceMethod() || py3K; // Any method could be made abstract in py3
  }
 @Override
 public void visitPyCallExpression(final PyCallExpression node) {
   // TODO: refactor, messy code
   final PyExpression callee = node.getCallee();
   if (callee != null) {
     final PsiReference calleeRef = callee.getReference();
     if (calleeRef != null) {
       final PsiElement calleeDeclaration = calleeRef.resolve();
       if (calleeDeclaration instanceof PyFunction) {
         final PyFunction calleeFunction = (PyFunction) calleeDeclaration;
         final PyClass clazz = calleeFunction.getContainingClass();
         if (clazz != null) {
           if (PyUtil.isInit(calleeFunction)) {
             return; // Init call should not be marked as dependency
           }
           myResult.putValue(clazz, calleeFunction);
         }
       }
     }
   }
 }
 @Nullable
 @Override
 public PyType getCallType(
     @NotNull TypeEvalContext context, @NotNull PyCallSiteExpression callSite) {
   for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
     final PyType type = typeProvider.getCallType(this, callSite, context);
     if (type != null) {
       type.assertValid(typeProvider.toString());
       return type;
     }
   }
   final PyExpression receiver = PyTypeChecker.getReceiver(callSite, this);
   final List<PyExpression> arguments = PyTypeChecker.getArguments(callSite, this);
   final List<PyParameter> parameters = PyUtil.getParameters(this, context);
   final PyResolveContext resolveContext =
       PyResolveContext.noImplicits().withTypeEvalContext(context);
   final List<PyParameter> explicitParameters =
       PyTypeChecker.filterExplicitParameters(parameters, this, callSite, resolveContext);
   final Map<PyExpression, PyNamedParameter> mapping =
       PyCallExpressionHelper.mapArguments(arguments, explicitParameters);
   return getCallType(receiver, mapping, context);
 }
 @Nullable
 public static PyType getTypeFromTarget(
     @NotNull final PsiElement target,
     final TypeEvalContext context,
     PyReferenceExpression anchor) {
   if (!(target
       instanceof PyTargetExpression)) { // PyTargetExpression will ask about its type itself
     final PyType pyType = getReferenceTypeFromProviders(target, context, anchor);
     if (pyType != null) {
       return pyType;
     }
   }
   if (target instanceof PyTargetExpression) {
     final String name = ((PyTargetExpression) target).getName();
     if (PyNames.NONE.equals(name)) {
       return PyNoneType.INSTANCE;
     }
     if (PyNames.TRUE.equals(name) || PyNames.FALSE.equals(name)) {
       return PyBuiltinCache.getInstance(target).getBoolType();
     }
   }
   if (target instanceof PyFile) {
     return new PyModuleType((PyFile) target);
   }
   if (target instanceof PyImportedModule) {
     return new PyImportedModuleType((PyImportedModule) target);
   }
   if ((target instanceof PyTargetExpression || target instanceof PyNamedParameter)
       && anchor != null
       && context.allowDataFlow(anchor)) {
     final ScopeOwner scopeOwner = PsiTreeUtil.getStubOrPsiParentOfType(anchor, ScopeOwner.class);
     if (scopeOwner != null
         && scopeOwner == PsiTreeUtil.getStubOrPsiParentOfType(target, ScopeOwner.class)) {
       final String name = ((PyElement) target).getName();
       if (name != null) {
         final PyType type = getTypeByControlFlow(name, context, anchor, scopeOwner);
         if (type != null) {
           return type;
         }
       }
     }
   }
   if (target instanceof PyFunction) {
     final PyDecoratorList decoratorList = ((PyFunction) target).getDecoratorList();
     if (decoratorList != null) {
       final PyDecorator propertyDecorator = decoratorList.findDecorator(PyNames.PROPERTY);
       if (propertyDecorator != null) {
         return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY);
       }
       for (PyDecorator decorator : decoratorList.getDecorators()) {
         final QualifiedName qName = decorator.getQualifiedName();
         if (qName != null
             && (qName.endsWith(PyNames.SETTER)
                 || qName.endsWith(PyNames.DELETER)
                 || qName.endsWith(PyNames.GETTER))) {
           return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY);
         }
       }
     }
   }
   if (target instanceof PyTypedElement) {
     return context.getType((PyTypedElement) target);
   }
   if (target instanceof PsiDirectory) {
     final PsiDirectory dir = (PsiDirectory) target;
     PsiFile file = dir.findFile(PyNames.INIT_DOT_PY);
     if (file != null) {
       return getTypeFromTarget(file, context, anchor);
     }
     if (PyUtil.isPackage(dir, anchor)) {
       final PsiFile containingFile = anchor.getContainingFile();
       if (containingFile instanceof PyFile) {
         final QualifiedName qualifiedName = QualifiedNameFinder.findShortestImportableQName(dir);
         if (qualifiedName != null) {
           final PyImportedModule module =
               new PyImportedModule(null, (PyFile) containingFile, qualifiedName);
           return new PyImportedModuleType(module);
         }
       }
     }
   }
   return null;
 }