protected Collection<String> generateSuggestedNames(PyExpression expression) {
    Collection<String> candidates = new LinkedHashSet<>() {
      @Override
      public boolean add(String s) {
        if (PyNames.isReserved(s)) {
          return false;
        }
        return super.add(s);
      }
    };
    String text = PyPsiUtils.getStringValue(expression);
    final Pair<PsiElement, TextRange> selection = expression.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE);
    if (selection != null) {
      text = selection.getSecond().substring(selection.getFirst().getText());
    }
    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.getProject(), expression.getContainingFile());
    PyType type = context.getType(expression);
    if (type != null && type != PyNoneType.INSTANCE) {
      String typeName = type.getName();
      if (typeName != null) {
        if (type instanceof PyLiteralStringType) { // we don't want to suggest "L" for inferred LiteralStrings
          typeName = "s";
        }
        else 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());
    }

    Optional
      .ofNullable(PsiTreeUtil.getParentOfType(expression, PyArgumentList.class))
      .map(PyArgumentList::getCallExpression)
      .ifPresent(
        call -> StreamEx
          .of(call.multiMapArguments(PyResolveContext.defaultContext(context)))
          .map(mapping -> mapping.getMappedParameters().get(expression))
          .nonNull()
          .map(PyCallableParameter::getName)
          .nonNull()
          .forEach(candidates::add)
      );

    return candidates;
  }
protected Collection<String> generateSuggestedNames(PyExpression expression)