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