@Nullable
  private PyStringLiteralExpression addFunctionInheritedDocString(@NotNull PyFunction pyFunction, @NotNull PyClass pyClass) {
    final String methodName = pyFunction.getName();
    if (methodName == null) {
      return null;
    }
    final boolean isConstructor = PyUtil.isInitOrNewMethod(pyFunction);
    List<PyClass> classes = pyClass.getAncestorClasses(myContext);
    if (isConstructor) {
      // look at our own class again and maybe inherit class's doc
      classes = ContainerUtil.prepend(classes, pyClass);
    }
    for (PyClass ancestor : classes) {
      PyStringLiteralExpression docstringElement = null;
      PyFunction inherited = null;
      boolean isFromClass = false;
      if (isConstructor) {
        docstringElement = getEffectiveDocStringExpression(ancestor);
        isFromClass = docstringElement != null;
      }
      if (!isFromClass) {
        inherited = ancestor.findMethodByName(methodName, false, null);
        if (inherited != null) {
          docstringElement = getEffectiveDocStringExpression(inherited);
        }
      }
      if (docstringElement != null && !docstringElement.getStringValue().isEmpty()) {
        final HtmlChunk ancestorLink = isFromClass ? getLinkToClass(ancestor, false) : getLinkToFunction(inherited, false);
        if (ancestorLink != null) {
          mySectionsMap.get(PyPsiBundle.message("QDOC.copied.from")).append(ancestorLink.code());
        }
        return docstringElement;
      }
    }

    // above could have not worked because inheritance is not searched down to 'object'.
    // for well-known methods, copy built-in doc string.
    // TODO: also handle predefined __xxx__ that are not part of 'object'.
    if (PyNames.UNDERSCORED_ATTRIBUTES.contains(methodName)) {
      return addPredefinedMethodDoc(pyFunction, methodName);
    }
    return null;
  }
@Nullable
  private PyStringLiteralExpression addFunctionInheritedDocString(@NotNull PyFunction pyFunction, @NotNull PyClass pyClass)