@Nullable private PyType getReturnType(@NotNull TypeEvalContext context) { for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { final Ref<PyType> returnTypeRef = typeProvider.getReturnType(this, context); if (returnTypeRef != null) { final PyType returnType = returnTypeRef.get(); if (returnType != null) { returnType.assertValid(typeProvider.toString()); } return returnType; } } final PyType docStringType = getReturnTypeFromDocString(); if (docStringType != null) { docStringType.assertValid("from docstring"); return docStringType; } if (context.allowReturnTypes(this)) { final Ref<? extends PyType> yieldTypeRef = getYieldStatementType(context); if (yieldTypeRef != null) { return yieldTypeRef.get(); } return getReturnStatementType(context); } return null; }
@Nullable @Override public PyType getReturnType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) { for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { final PyType returnType = typeProvider.getReturnType(this, context); if (returnType != null) { returnType.assertValid(typeProvider.toString()); return returnType; } } if (context.maySwitchToAST(this) && LanguageLevel.forElement(this).isAtLeast(LanguageLevel.PYTHON30)) { PyAnnotation anno = getAnnotation(); if (anno != null) { PyClass pyClass = anno.resolveToClass(); if (pyClass != null) { return new PyClassTypeImpl(pyClass, false); } } } final PyType docStringType = getReturnTypeFromDocString(); if (docStringType != null) { docStringType.assertValid("from docstring"); return docStringType; } if (context.allowReturnTypes(this)) { final Ref<? extends PyType> yieldTypeRef = getYieldStatementType(context); if (yieldTypeRef != null) { return yieldTypeRef.get(); } return getReturnStatementType(context); } return null; }
@Nullable private PyType getGenericReturnType( @NotNull TypeEvalContext typeEvalContext, @Nullable PyQualifiedExpression callSite) { if (typeEvalContext.maySwitchToAST(this) && LanguageLevel.forElement(this).isAtLeast(LanguageLevel.PYTHON30)) { PyAnnotation anno = getAnnotation(); if (anno != null) { PyClass pyClass = anno.resolveToClass(); if (pyClass != null) { return new PyClassTypeImpl(pyClass, false); } } } for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { final PyType returnType = typeProvider.getReturnType(this, callSite, typeEvalContext); if (returnType != null) { returnType.assertValid(typeProvider.toString()); return returnType; } } final PyType docStringType = getReturnTypeFromDocString(); if (docStringType != null) { docStringType.assertValid("from docstring"); return docStringType; } if (typeEvalContext.allowReturnTypes(this)) { final PyType yieldType = getYieldStatementType(typeEvalContext); if (yieldType != null) { return yieldType; } return getReturnStatementType(typeEvalContext); } return null; }
/** * Adds type and description representation from function docstring * * @param parameter parameter of a function * @return true if type from docstring was added */ private boolean addTypeAndDescriptionFromDocstring(@NotNull final PyNamedParameter parameter) { final PyFunction function = PsiTreeUtil.getParentOfType(parameter, PyFunction.class); if (function != null) { final String docString = PyPsiUtils.strValue(function.getDocStringExpression()); final Pair<String, String> typeAndDescr = getTypeAndDescription(docString, parameter); final String type = typeAndDescr.first; final String description = typeAndDescr.second; if (type != null) { final PyType pyType = PyTypeParser.getTypeByName(parameter, type); if (pyType instanceof PyClassType) { myBody .addItem(": ") .addWith( new LinkWrapper(PythonDocumentationProvider.LINK_TYPE_PARAM), $(pyType.getName())); } else { myBody.addItem(": ").addItem(type); } } if (description != null) { myEpilog.addItem(BR).addItem(description); } return type != null; } return false; }
@Nullable private static PyType derefType( @NotNull Ref<PyType> typeRef, @NotNull PyTypeProvider typeProvider) { final PyType type = typeRef.get(); if (type != null) { type.assertValid(typeProvider.toString()); } return type; }
@Nullable @Override public PyType getCallType( @NotNull TypeEvalContext context, @NotNull PyQualifiedExpression callSite) { PyType type = null; for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { type = typeProvider.getCallType(this, callSite, context); if (type != null) { type.assertValid(typeProvider.toString()); break; } } if (type == null) { type = context.getReturnType(this); } final PyTypeChecker.AnalyzeCallResults results = PyTypeChecker.analyzeCallSite(callSite, context); if (results != null) { return analyzeCallType(type, results.getReceiver(), results.getArguments(), context); } return type; }
@Nullable @Override public PyType getCallType( @NotNull TypeEvalContext context, @NotNull PyCallSiteExpression callSite) { for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { final PyType type = typeProvider.getCallType(this, callSite, context); if (type != null) { type.assertValid(typeProvider.toString()); return type; } } final PyExpression receiver = PyTypeChecker.getReceiver(callSite, this); final List<PyExpression> arguments = PyTypeChecker.getArguments(callSite, this); final List<PyParameter> parameters = PyUtil.getParameters(this, context); final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context); final List<PyParameter> explicitParameters = PyTypeChecker.filterExplicitParameters(parameters, this, callSite, resolveContext); final Map<PyExpression, PyNamedParameter> mapping = PyCallExpressionHelper.mapArguments(arguments, explicitParameters); return getCallType(receiver, mapping, context); }
@Nullable @Override public ParseResult fun(@NotNull Pair<Token<PyElementType>, List<Token<PyElementType>>> value) { final Token<PyElementType> first = value.getFirst(); final List<Token<PyElementType>> rest = value.getSecond(); final TextRange firstRange = first.getRange(); final boolean unqualified = rest.isEmpty(); if (unqualified) { final ParseResult result = parseBuiltinType(first); if (result != null) { return result; } } final PsiFile file = myAnchor.getContainingFile(); final List<Token<PyElementType>> tokens = new ArrayList<>(); tokens.add(first); tokens.addAll(rest); if (file instanceof PyFile) { final PyFile pyFile = (PyFile) file; final TypeEvalContext context = TypeEvalContext.codeInsightFallback(file.getProject()); final Map<TextRange, PyType> types = new HashMap<>(); final Map<PyType, TextRange> fullRanges = new HashMap<>(); final Map<PyType, PyImportElement> imports = new HashMap<>(); PyType type = resolveQualifierType(tokens, pyFile, context, types, fullRanges, imports); PsiElement resolved = type != null ? getElement(type) : null; if (type != null) { final PyResolveContext resolveContext = PyResolveContext.defaultContext().withTypeEvalContext(context); final PyExpression expression = myAnchor instanceof PyExpression ? (PyExpression) myAnchor : null; for (Token<PyElementType> token : tokens) { final PyType qualifierType = type; type = null; final List<? extends RatedResolveResult> results = qualifierType.resolveMember( token.getText().toString(), expression, AccessDirection.READ, resolveContext); if (results != null && !results.isEmpty()) { resolved = results.get(0).getElement(); if (resolved instanceof PyTypedElement) { type = context.getType((PyTypedElement) resolved); if (type != null && !allowResolveToType(type)) { type = null; break; } if (type instanceof PyClassLikeType) { type = ((PyClassLikeType) type).toInstance(); } } } if (type == null) { break; } types.put(token.getRange(), type); fullRanges.put( type, TextRange.create(firstRange.getStartOffset(), token.getRange().getEndOffset())); } if (type != null) { return new ParseResult(resolved, type, types, fullRanges, imports); } } } return EMPTY_RESULT; }