@Nullable public PyType getReturnStatementType(TypeEvalContext typeEvalContext) { final ReturnVisitor visitor = new ReturnVisitor(this, typeEvalContext); final PyStatementList statements = getStatementList(); statements.accept(visitor); if (isGeneratedStub() && !visitor.myHasReturns) { if (PyNames.INIT.equals(getName())) { return PyNoneType.INSTANCE; } return null; } return visitor.result(); }
private static boolean suggestRename( @NotNull PsiNameIdentifierOwner element, @NotNull PsiElement originalElement) { // Target expressions in the same scope are treated as the same variable if ((element instanceof PyTargetExpression) && originalElement instanceof PyTargetExpression) { return false; } // Renaming an __init__ method results in renaming its class else if (element instanceof PyFunction && PyNames.INIT.equals(element.getName()) && ((PyFunction) element).getContainingClass() != null) { return false; } return true; }
/** * Map decorators of element to {@link * com.jetbrains.python.psi.PyKnownDecoratorUtil.KnownDecorator}. * * @param element decoratable element to check * @param context type evaluation context. If it doesn't allow switch to AST, decorators will be * compared by the text of the last component of theirs qualified names. * @return list of known decorators in declaration order with duplicates (with any) */ @NotNull public static List<KnownDecorator> getKnownDecorators( @NotNull PyDecoratable element, @NotNull TypeEvalContext context) { final PyDecoratorList decoratorList = element.getDecoratorList(); if (decoratorList == null) { return Collections.emptyList(); } final List<KnownDecorator> result = new ArrayList<>(); final boolean allowResolve = context.maySwitchToAST((PsiElement) element); for (PyDecorator decorator : decoratorList.getDecorators()) { final QualifiedName qualifiedName = decorator.getQualifiedName(); if (qualifiedName == null) { continue; } final KnownDecorator knownDecorator = ourByShortName.get(qualifiedName.getLastComponent()); if (knownDecorator != null) { if (allowResolve) { PyQualifiedNameOwner resolved = as(resolveDecorator(decorator), PyQualifiedNameOwner.class); if (resolved instanceof PyFunction && PyNames.INIT.equals(resolved.getName())) { resolved = ((PyFunction) resolved).getContainingClass(); } if (resolved != null && resolved.getQualifiedName() != null) { final QualifiedName resolvedName = QualifiedName.fromDottedString(resolved.getQualifiedName()); if (resolvedName.equals(knownDecorator.getQualifiedName())) { result.add(knownDecorator); } } } else { result.add(knownDecorator); } } } return result; }
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); } } }