void (@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)); }); }