private void addFunctionSpecificSections(@NotNull PyStringLiteralExpression docstring, @NotNull PyFunction function) {
    final StructuredDocString structured = DocStringUtil.parseDocString(docstring);

    final List<PyCallableParameter> parameters = function.getParameters(myContext);
    final List<String> actualNames = ContainerUtil.mapNotNull(parameters, PyCallableParameter::getName);
    StreamEx.of(actualNames).filter(name -> structured.getParamDescription(name) != null).forEach(name -> {
      final String description = structured.getParamDescription(name);
      myFormatterFragments.add(new FormatterDocFragment(name, StringUtil.notNullize(description), FormatterDocFragmentType.PARAMETER));
    });

    final List<String> allKeywordArgs = structured.getKeywordArguments();
    if (!ContainerUtil.exists(parameters, PyCallableParameter::isKeywordContainer)) {
      allKeywordArgs.retainAll(new HashSet<>(actualNames));
    }
    StreamEx.of(allKeywordArgs).forEach(name -> {
      final String description = structured.getKeywordArgumentDescription(name);
      myFormatterFragments.add(
        new FormatterDocFragment(name, StringUtil.notNullize(description), FormatterDocFragmentType.KEYWORD_ARGUMENT));
    });

    final String returnDescription = structured.getReturnDescription();
    if (returnDescription != null) {
      myFormatterFragments.add(new FormatterDocFragment("return", returnDescription, FormatterDocFragmentType.RETURN));
    }

    StreamEx.of(structured.getRaisedExceptions()).forEach(name -> {
      final String description = structured.getRaisedExceptionDescription(name);
      myFormatterFragments.add(new FormatterDocFragment(name, StringUtil.notNullize(description), FormatterDocFragmentType.RAISE));
    });
  }
private void addFunctionSpecificSections(@NotNull PyStringLiteralExpression docstring, @NotNull PyFunction function)