private void buildFromDocstring(@NotNull final PsiElement elementDefinition, boolean isProperty) { PyClass pyClass = null; final PyStringLiteralExpression docStringExpression = ((PyDocStringOwner) elementDefinition).getDocStringExpression(); if (elementDefinition instanceof PyClass) { pyClass = (PyClass) elementDefinition; myBody.add(PythonDocumentationProvider.describeDecorators(pyClass, TagItalic, BR, LCombUp)); myBody.add(PythonDocumentationProvider.describeClass(pyClass, TagBold, true, false)); } else if (elementDefinition instanceof PyFunction) { PyFunction pyFunction = (PyFunction) elementDefinition; if (!isProperty) { pyClass = pyFunction.getContainingClass(); if (pyClass != null) { myBody .addWith( TagSmall, PythonDocumentationProvider.describeClass(pyClass, TagCode, true, true)) .addItem(BR) .addItem(BR); } } myBody .add(PythonDocumentationProvider.describeDecorators(pyFunction, TagItalic, BR, LCombUp)) .add(PythonDocumentationProvider.describeFunction(pyFunction, TagBold, LCombUp)); if (docStringExpression == null) { addInheritedDocString(pyFunction, pyClass); } } else if (elementDefinition instanceof PyFile) { addModulePath((PyFile) elementDefinition); } if (docStringExpression != null) { myBody.addItem(BR); addFormattedDocString(myElement, docStringExpression.getStringValue(), myBody, myEpilog); } }
private void buildFromParameter( @NotNull final TypeEvalContext context, @Nullable final PsiElement outerElement, @NotNull final PsiElement elementDefinition) { myBody.addItem(combUp("Parameter " + PyUtil.getReadableRepr(elementDefinition, false))); boolean typeFromDocstringAdded = addTypeAndDescriptionFromDocstring((PyNamedParameter) elementDefinition); if (outerElement instanceof PyExpression) { PyType type = context.getType((PyExpression) outerElement); if (type != null) { String typeString = null; if (type instanceof PyDynamicallyEvaluatedType) { if (!typeFromDocstringAdded) { typeString = "\nDynamically inferred type: "; } } else { if (outerElement.getReference() != null) { PsiElement target = outerElement.getReference().resolve(); if (target instanceof PyTargetExpression) { final String targetName = ((PyTargetExpression) target).getName(); if (targetName != null && targetName.equals(((PyNamedParameter) elementDefinition).getName())) { typeString = "\nReassigned value has type: "; } } } } if (typeString == null && !typeFromDocstringAdded) { typeString = "\nInferred type: "; } if (typeString != null) { myBody.addItem(combUp(typeString)); PythonDocumentationProvider.describeTypeWithLinks( myBody, elementDefinition, type, context); } } } }
public String build() { final TypeEvalContext context = TypeEvalContext.userInitiated(myElement.getProject(), myElement.getContainingFile()); final PsiElement outerElement = myOriginalElement != null ? myOriginalElement.getParent() : null; final PsiElement elementDefinition = resolveToDocStringOwner(); final boolean isProperty = buildFromProperty(elementDefinition, outerElement, context); if (myProlog.isEmpty() && !isProperty && !isAttribute()) { myProlog.add(myReassignmentChain); } if (elementDefinition instanceof PyDocStringOwner) { buildFromDocstring(elementDefinition, isProperty); } else if (isAttribute()) { buildFromAttributeDoc(); } else if (elementDefinition instanceof PyNamedParameter) { buildFromParameter(context, outerElement, elementDefinition); } else if (elementDefinition != null && outerElement instanceof PyReferenceExpression) { myBody.addItem(combUp("\nInferred type: ")); PythonDocumentationProvider.describeExpressionTypeWithLinks( myBody, (PyReferenceExpression) outerElement, context); } if (elementDefinition != null && PythonDialectsTokenSetProvider.INSTANCE .getKeywordTokens() .contains(elementDefinition.getNode().getElementType())) { buildForKeyword(elementDefinition.getText()); } if (myBody.isEmpty() && myEpilog.isEmpty()) { return null; // got nothing substantial to say! } else { return myResult.toString(); } }
private boolean buildFromProperty( PsiElement elementDefinition, @Nullable final PsiElement outerElement, @NotNull final TypeEvalContext context) { if (myOriginalElement == null) { return false; } final String elementName = myOriginalElement.getText(); if (!PyNames.isIdentifier(elementName)) { return false; } if (!(outerElement instanceof PyQualifiedExpression)) { return false; } final PyExpression qualifier = ((PyQualifiedExpression) outerElement).getQualifier(); if (qualifier == null) { return false; } final PyType type = context.getType(qualifier); if (!(type instanceof PyClassType)) { return false; } final PyClass cls = ((PyClassType) type).getPyClass(); final Property property = cls.findProperty(elementName, true, null); if (property == null) { return false; } final AccessDirection direction = AccessDirection.of((PyElement) outerElement); final Maybe<PyCallable> accessor = property.getByDirection(direction); myProlog .addItem("property ") .addWith(TagBold, $().addWith(TagCode, $(elementName))) .addItem(" of ") .add(PythonDocumentationProvider.describeClass(cls, TagCode, true, true)); if (accessor.isDefined() && property.getDoc() != null) { myBody.addItem(": ").addItem(property.getDoc()).addItem(BR); } else { final PyCallable getter = property.getGetter().valueOrNull(); if (getter != null && getter != myElement && getter instanceof PyFunction) { // not in getter, getter's doc comment may be useful final PyStringLiteralExpression docstring = ((PyFunction) getter).getDocStringExpression(); if (docstring != null) { myProlog .addItem(BR) .addWith(TagItalic, $("Copied from getter:")) .addItem(BR) .addItem(docstring.getStringValue()); } } myBody.addItem(BR); } myBody.addItem(BR); if (accessor.isDefined() && accessor.value() == null) elementDefinition = null; final String accessorKind = getAccessorKind(direction); if (elementDefinition != null) { myEpilog.addWith(TagSmall, $(BR, BR, accessorKind, " of property")).addItem(BR); } if (!(elementDefinition instanceof PyDocStringOwner)) { myBody .addWith( TagItalic, elementDefinition != null ? $("Declaration: ") : $(accessorKind + " is not defined.")) .addItem(BR); if (elementDefinition != null) { myBody.addItem(combUp(PyUtil.getReadableRepr(elementDefinition, false))); } } return true; }