@Nullable private PsiElement resolveToDocStringOwner() { // here the ^Q target is already resolved; the resolved element may point to intermediate // assignments if (myElement instanceof PyTargetExpression) { final String targetName = myElement.getText(); myReassignmentChain.addWith( TagSmall, $(PyBundle.message("QDOC.assigned.to.$0", targetName)).addItem(BR)); final PyExpression assignedValue = ((PyTargetExpression) myElement).findAssignedValue(); if (assignedValue instanceof PyReferenceExpression) { final PsiElement resolved = resolveWithoutImplicits((PyReferenceExpression) assignedValue); if (resolved != null) { return resolved; } } return assignedValue; } if (myElement instanceof PyReferenceExpression) { myReassignmentChain.addWith( TagSmall, $(PyBundle.message("QDOC.assigned.to.$0", myElement.getText())).addItem(BR)); return resolveWithoutImplicits((PyReferenceExpression) myElement); } // it may be a call to a standard wrapper if (myElement instanceof PyCallExpression) { final PyCallExpression call = (PyCallExpression) myElement; final Pair<String, PyFunction> wrapInfo = PyCallExpressionHelper.interpretAsModifierWrappingCall(call, myOriginalElement); if (wrapInfo != null) { String wrapperName = wrapInfo.getFirst(); PyFunction wrappedFunction = wrapInfo.getSecond(); myReassignmentChain.addWith( TagSmall, $(PyBundle.message("QDOC.wrapped.in.$0", wrapperName)).addItem(BR)); return wrappedFunction; } } return myElement; }
private void addModulePath(PyFile followed) { // what to prepend to a module description? final VirtualFile file = followed.getVirtualFile(); if (file == null) { myProlog.addWith(TagSmall, $(PyBundle.message("QDOC.module.path.unknown"))); } else { final String path = file.getPath(); RootFinder finder = new RootFinder(path); RootVisitorHost.visitRoots(followed, finder); final String rootPath = finder.getResult(); if (rootPath != null) { String afterPart = path.substring(rootPath.length()); myProlog.addWith(TagSmall, $(rootPath).addWith(TagBold, $(afterPart))); } else { myProlog.addWith(TagSmall, $(path)); } } }
private void addPredefinedMethodDoc(PyFunction fun, String mothodName) { PyClassType objectType = PyBuiltinCache.getInstance(fun) .getObjectType(); // old- and new-style classes share the __xxx__ stuff if (objectType != null) { PyClass objectClass = objectType.getPyClass(); PyFunction predefinedMethod = objectClass.findMethodByName(mothodName, false); if (predefinedMethod != null) { PyStringLiteralExpression predefinedDocstring = predefinedMethod.getDocStringExpression(); String predefinedDoc = predefinedDocstring != null ? predefinedDocstring.getStringValue() : null; if (predefinedDoc != null && predefinedDoc.length() > 1) { // only a real-looking doc string counts addFormattedDocString(fun, predefinedDoc, myBody, myBody); myEpilog.addItem(BR).addItem(BR).addItem(PyBundle.message("QDOC.copied.from.builtin")); } } } }
private void addInheritedDocString( @NotNull final PyFunction pyFunction, @Nullable final PyClass pyClass) { boolean notFound = true; final String methodName = pyFunction.getName(); if (pyClass == null || methodName == null) { return; } final boolean isConstructor = PyNames.INIT.equals(methodName); Iterable<PyClass> classes = pyClass.getAncestorClasses(null); if (isConstructor) { // look at our own class again and maybe inherit class's doc classes = new ChainIterable<PyClass>(pyClass).add(classes); } for (PyClass ancestor : classes) { PyStringLiteralExpression docstringElement = null; PyFunction inherited = null; boolean isFromClass = false; if (isConstructor) docstringElement = pyClass.getDocStringExpression(); if (docstringElement != null) { isFromClass = true; } else { inherited = ancestor.findMethodByName(methodName, false); } if (inherited != null) { docstringElement = inherited.getDocStringExpression(); } if (docstringElement != null) { final String inheritedDoc = docstringElement.getStringValue(); if (inheritedDoc.length() > 1) { myEpilog.addItem(BR).addItem(BR); String ancestor_name = ancestor.getName(); String marker = (pyClass == ancestor) ? PythonDocumentationProvider.LINK_TYPE_CLASS : PythonDocumentationProvider.LINK_TYPE_PARENT; final String ancestor_link = $().addWith(new LinkWrapper(marker + ancestor_name), $(ancestor_name)).toString(); if (isFromClass) { myEpilog.addItem(PyBundle.message("QDOC.copied.from.class.$0", ancestor_link)); } else { myEpilog.addItem(PyBundle.message("QDOC.copied.from.$0.$1", ancestor_link, methodName)); } myEpilog.addItem(BR).addItem(BR); ChainIterable<String> formatted = new ChainIterable<String>(); ChainIterable<String> unformatted = new ChainIterable<String>(); addFormattedDocString(pyFunction, inheritedDoc, formatted, unformatted); myEpilog.addWith(TagCode, formatted).add(unformatted); notFound = false; break; } } } if (notFound) { // 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.UnderscoredAttributes.contains(methodName)) { addPredefinedMethodDoc(pyFunction, methodName); } } }