PyDocStringOwner (@NotNull String replacementText) { Preconditions.checkNotNull(myDocStringOwner, "For this action docstring owner must be supplied"); final Project project = myDocStringOwner.getProject(); PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project); final PyExpressionStatement replacement = elementGenerator.createDocstring(replacementText); final PyStringLiteralExpression docStringExpression = getDocStringExpression(); if (docStringExpression != null) { docStringExpression.replace(replacement.getExpression()); } else { PyStatementListContainer container = PyUtil.as(myDocStringOwner, PyStatementListContainer.class); if (container == null) { throw new IllegalStateException("Should be a function or class"); } final PyStatementList statements = container.getStatementList(); final String indentation = PyIndentUtil.getElementIndent(statements); PyUtil.updateDocumentUnblockedAndCommitted(myDocStringOwner, document -> { final PsiElement beforeStatements = statements.getPrevSibling(); String replacementWithLineBreaks = "\n" + indentation + replacementText; if (statements.getStatements().length > 0) { replacementWithLineBreaks += "\n" + indentation; } final TextRange range = beforeStatements.getTextRange(); if (!(beforeStatements instanceof PsiWhiteSpace)) { document.insertString(range.getEndOffset(), replacementWithLineBreaks); } else if (statements.getStatements().length == 0 && beforeStatements.textContains('\n')) { // preserve original spacing, since it probably separates function and other declarations document.insertString(range.getStartOffset(), replacementWithLineBreaks); } else { document.replaceString(range.getStartOffset(), range.getEndOffset(), replacementWithLineBreaks); } }); } return myDocStringOwner; }