@Nullable
 @Override
 public PyType getReturnType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
   for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
     final PyType returnType = typeProvider.getReturnType(this, context);
     if (returnType != null) {
       returnType.assertValid(typeProvider.toString());
       return returnType;
     }
   }
   if (context.maySwitchToAST(this)
       && LanguageLevel.forElement(this).isAtLeast(LanguageLevel.PYTHON30)) {
     PyAnnotation anno = getAnnotation();
     if (anno != null) {
       PyClass pyClass = anno.resolveToClass();
       if (pyClass != null) {
         return new PyClassTypeImpl(pyClass, false);
       }
     }
   }
   final PyType docStringType = getReturnTypeFromDocString();
   if (docStringType != null) {
     docStringType.assertValid("from docstring");
     return docStringType;
   }
   if (context.allowReturnTypes(this)) {
     final Ref<? extends PyType> yieldTypeRef = getYieldStatementType(context);
     if (yieldTypeRef != null) {
       return yieldTypeRef.get();
     }
     return getReturnStatementType(context);
   }
   return null;
 }
 @Nullable
 private PyType getGenericReturnType(
     @NotNull TypeEvalContext typeEvalContext, @Nullable PyQualifiedExpression callSite) {
   if (typeEvalContext.maySwitchToAST(this)
       && LanguageLevel.forElement(this).isAtLeast(LanguageLevel.PYTHON30)) {
     PyAnnotation anno = getAnnotation();
     if (anno != null) {
       PyClass pyClass = anno.resolveToClass();
       if (pyClass != null) {
         return new PyClassTypeImpl(pyClass, false);
       }
     }
   }
   for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
     final PyType returnType = typeProvider.getReturnType(this, callSite, typeEvalContext);
     if (returnType != null) {
       returnType.assertValid(typeProvider.toString());
       return returnType;
     }
   }
   final PyType docStringType = getReturnTypeFromDocString();
   if (docStringType != null) {
     docStringType.assertValid("from docstring");
     return docStringType;
   }
   if (typeEvalContext.allowReturnTypes(this)) {
     final PyType yieldType = getYieldStatementType(typeEvalContext);
     if (yieldType != null) {
       return yieldType;
     }
     return getReturnStatementType(typeEvalContext);
   }
   return null;
 }
 @Nullable
 private PyType getReturnType(@NotNull TypeEvalContext context) {
   for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
     final Ref<PyType> returnTypeRef = typeProvider.getReturnType(this, context);
     if (returnTypeRef != null) {
       final PyType returnType = returnTypeRef.get();
       if (returnType != null) {
         returnType.assertValid(typeProvider.toString());
       }
       return returnType;
     }
   }
   final PyType docStringType = getReturnTypeFromDocString();
   if (docStringType != null) {
     docStringType.assertValid("from docstring");
     return docStringType;
   }
   if (context.allowReturnTypes(this)) {
     final Ref<? extends PyType> yieldTypeRef = getYieldStatementType(context);
     if (yieldTypeRef != null) {
       return yieldTypeRef.get();
     }
     return getReturnStatementType(context);
   }
   return null;
 }
  /**
   * Adds type and description representation from function docstring
   *
   * @param parameter parameter of a function
   * @return true if type from docstring was added
   */
  private boolean addTypeAndDescriptionFromDocstring(@NotNull final PyNamedParameter parameter) {
    final PyFunction function = PsiTreeUtil.getParentOfType(parameter, PyFunction.class);
    if (function != null) {
      final String docString = PyPsiUtils.strValue(function.getDocStringExpression());
      final Pair<String, String> typeAndDescr = getTypeAndDescription(docString, parameter);

      final String type = typeAndDescr.first;
      final String description = typeAndDescr.second;

      if (type != null) {
        final PyType pyType = PyTypeParser.getTypeByName(parameter, type);
        if (pyType instanceof PyClassType) {
          myBody
              .addItem(": ")
              .addWith(
                  new LinkWrapper(PythonDocumentationProvider.LINK_TYPE_PARAM),
                  $(pyType.getName()));
        } else {
          myBody.addItem(": ").addItem(type);
        }
      }

      if (description != null) {
        myEpilog.addItem(BR).addItem(description);
      }

      return type != null;
    }

    return false;
  }
 private static void highlightStarArgumentTypeMismatch(
     PyArgumentList node, ProblemsHolder holder, TypeEvalContext context) {
   for (PyExpression arg : node.getArguments()) {
     if (arg instanceof PyStarArgument) {
       PyExpression content =
           PyUtil.peelArgument(PsiTreeUtil.findChildOfType(arg, PyExpression.class));
       if (content != null) {
         PyType inside_type = context.getType(content);
         if (inside_type != null && !PyTypeChecker.isUnknown(inside_type)) {
           if (((PyStarArgument) arg).isKeyword()) {
             if (!PyABCUtil.isSubtype(inside_type, PyNames.MAPPING)) {
               holder.registerProblem(
                   arg, PyBundle.message("INSP.expected.dict.got.$0", inside_type.getName()));
             }
           } else { // * arg
             if (!PyABCUtil.isSubtype(inside_type, PyNames.ITERABLE)) {
               holder.registerProblem(
                   arg, PyBundle.message("INSP.expected.iter.got.$0", inside_type.getName()));
             }
           }
         }
       }
     }
   }
 }
 @Nullable
 private static PyType derefType(
     @NotNull Ref<PyType> typeRef, @NotNull PyTypeProvider typeProvider) {
   final PyType type = typeRef.get();
   if (type != null) {
     type.assertValid(typeProvider.toString());
   }
   return type;
 }
  protected Collection<String> generateSuggestedNames(PyExpression expression) {
    Collection<String> candidates =
        new LinkedHashSet<String>() {
          @Override
          public boolean add(String s) {
            if (PyNames.isReserved(s)) {
              return false;
            }
            return super.add(s);
          }
        };
    String text = expression.getText();
    final Pair<PsiElement, TextRange> selection =
        expression.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE);
    if (selection != null) {
      text = selection.getSecond().substring(text);
    }
    if (expression instanceof PyCallExpression) {
      final PyExpression callee = ((PyCallExpression) expression).getCallee();
      if (callee != null) {
        text = callee.getText();
      }
    }
    if (text != null) {
      candidates.addAll(NameSuggesterUtil.generateNames(text));
    }
    final TypeEvalContext context = TypeEvalContext.userInitiated(expression.getContainingFile());
    PyType type = context.getType(expression);
    if (type != null && type != PyNoneType.INSTANCE) {
      String typeName = type.getName();
      if (typeName != null) {
        if (type.isBuiltin()) {
          typeName = typeName.substring(0, 1);
        }
        candidates.addAll(NameSuggesterUtil.generateNamesByType(typeName));
      }
    }
    final PyKeywordArgument kwArg =
        PsiTreeUtil.getParentOfType(expression, PyKeywordArgument.class);
    if (kwArg != null && kwArg.getValueExpression() == expression) {
      candidates.add(kwArg.getKeyword());
    }

    final PyArgumentList argList = PsiTreeUtil.getParentOfType(expression, PyArgumentList.class);
    if (argList != null) {
      final CallArgumentsMapping result = argList.analyzeCall(PyResolveContext.noImplicits());
      if (result.getMarkedCallee() != null) {
        final PyNamedParameter namedParameter = result.getPlainMappedParams().get(expression);
        if (namedParameter != null) {
          candidates.add(namedParameter.getName());
        }
      }
    }
    return candidates;
  }
 @NotNull
 private static List<RatedResolveResult> resolveMemberFromReferenceTypeProviders(
     @NotNull PsiElement parent, @NotNull String referencedName) {
   final PyResolveContext resolveContext = PyResolveContext.defaultContext();
   final PyType refType =
       PyReferenceExpressionImpl.getReferenceTypeFromProviders(
           parent, resolveContext.getTypeEvalContext(), null);
   if (refType != null) {
     final List<? extends RatedResolveResult> result =
         refType.resolveMember(referencedName, null, AccessDirection.READ, resolveContext);
     if (result != null) {
       return Lists.newArrayList(result);
     }
   }
   return Collections.emptyList();
 }
 @Nullable
 @Override
 public PyType getCallType(
     @NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) {
   PyType type = null;
   for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
     type = typeProvider.getCallType(this, callSite, context);
     if (type != null) {
       type.assertValid(typeProvider.toString());
       break;
     }
   }
   if (type == null) {
     type = context.getReturnType(this);
   }
   final PyTypeChecker.AnalyzeCallResults results =
       PyTypeChecker.analyzeCallSite(callSite, context);
   if (results != null) {
     return analyzeCallType(type, results.getReceiver(), results.getArguments(), context);
   }
   return type;
 }
 @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);
 }
 private static boolean isAbstract(@NotNull PyClass pyClass) {
   final PyType metaClass =
       pyClass.getMetaClassType(
           TypeEvalContext.userInitiated(pyClass.getProject(), pyClass.getContainingFile()));
   if (metaClass instanceof PyClassLikeType
       && PyNames.ABC_META_CLASS.equals(metaClass.getName())) {
     return true;
   }
   if (metaClass == null) {
     final PyExpression metaClassExpr =
         as(pyClass.getMetaClassExpression(), PyReferenceExpression.class);
     if (metaClassExpr != null && PyNames.ABC_META_CLASS.equals(metaClassExpr.getName())) {
       return true;
     }
   }
   for (PyFunction method : pyClass.getMethods(false)) {
     if (PyUtil.isDecoratedAsAbstract(method)) {
       return true;
     }
   }
   return false;
 }