@Override public boolean isAsyncAllowed() { final LanguageLevel languageLevel = LanguageLevel.forElement(this); final String functionName = getName(); return languageLevel.isAtLeast(LanguageLevel.PYTHON35) && (functionName == null || ArrayUtil.contains( functionName, PyNames.AITER, PyNames.ANEXT, PyNames.AENTER, PyNames.AEXIT) || !PyNames.getBuiltinMethods(languageLevel).containsKey(functionName)); }
@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; }
/** * Creates abstract version of each method in each class (does not touch method itself as opposite * to {@link #moveMethods(com.jetbrains.python.psi.PyClass, java.util.Collection, * com.jetbrains.python.psi.PyClass...)}) * * @param currentFunctions functions to make them abstract * @param to classes where abstract method should be created */ private static void makeMethodsAbstract( final Collection<PyFunction> currentFunctions, final PyClass... to) { final Set<PsiFile> filesToCheckImport = new HashSet<PsiFile>(); final Set<PyClass> classesToAddMetaAbc = new HashSet<PyClass>(); for (final PyFunction function : currentFunctions) { for (final PyClass destClass : to) { final PyFunctionBuilder functionBuilder = PyFunctionBuilder.copySignature(function, DECORATORS_MAY_BE_COPIED_TO_ABSTRACT); functionBuilder.decorate(PyNames.ABSTRACTMETHOD); final LanguageLevel level = LanguageLevel.forElement(destClass); PyClassRefactoringUtil.addMethods( destClass, false, functionBuilder.buildFunction(destClass.getProject(), level)); classesToAddMetaAbc.add(destClass); } } // Add ABCMeta to new classes if needed for (final PyClass aClass : classesToAddMetaAbc) { if (addMetaAbcIfNeeded(aClass)) { filesToCheckImport.add(aClass.getContainingFile()); } } // Add imports for ABC if needed for (final PsiFile file : filesToCheckImport) { addImportFromAbc(file, PyNames.ABSTRACTMETHOD); addImportFromAbc(file, ABC_META_CLASS); PyClassRefactoringUtil.optimizeImports(file); // To remove redundant imports } }
@Nullable private ParseResult parseBuiltinType(@NotNull Token<PyElementType> token) { final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(myAnchor); final String name = token.getText().toString(); final TextRange range = token.getRange(); if (PyNames.UNKNOWN_TYPE.equals(name)) { return EMPTY_RESULT; } else if (PyNames.NONE.equals(name)) { return new ParseResult(null, PyNoneType.INSTANCE, range); } else if ("integer".equals(name) || ("long".equals(name) && LanguageLevel.forElement(myAnchor).isPy3K())) { final PyClassType type = builtinCache.getIntType(); return type != null ? new ParseResult(null, type, range) : EMPTY_RESULT; } else if ("string".equals(name)) { final PyType type = builtinCache.getStringType(LanguageLevel.forElement(myAnchor)); return type != null ? new ParseResult(null, type, range) : EMPTY_RESULT; } else if ("bytestring".equals(name)) { final PyType type = builtinCache.getByteStringType(LanguageLevel.forElement(myAnchor)); return type != null ? new ParseResult(null, type, range) : EMPTY_RESULT; } else if ("bytes".equals(name)) { final PyClassType type = builtinCache.getBytesType(LanguageLevel.forElement(myAnchor)); return type != null ? new ParseResult(null, type, range) : EMPTY_RESULT; } else if ("unicode".equals(name)) { final PyClassType type = builtinCache.getUnicodeType(LanguageLevel.forElement(myAnchor)); return type != null ? new ParseResult(null, type, range) : EMPTY_RESULT; } else if ("boolean".equals(name)) { final PyClassType type = builtinCache.getBoolType(); return type != null ? new ParseResult(null, type, range) : EMPTY_RESULT; } else if ("dictionary".equals(name)) { final PyClassType type = builtinCache.getDictType(); return type != null ? new ParseResult(null, type, range) : EMPTY_RESULT; } final PyType builtinType = builtinCache.getObjectType(name); if (builtinType != null) { return new ParseResult(null, builtinType, range); } return null; }
/** * @return if method could be made abstract? (that means "create abstract version if method in * parent class") */ private static boolean couldBeAbstract(@NotNull final PyFunction function) { if (PyUtil.isInit(function)) { return false; // Who wants to make __init__ abstract?! } final PyUtil.MethodFlags flags = PyUtil.MethodFlags.of(function); assert flags != null : "Function should be called on method!"; final boolean py3K = LanguageLevel.forElement(function).isPy3K(); // TODO: use strategy because we already has the same check in #addMetaAbcIfNeeded return flags.isInstanceMethod() || py3K; // Any method could be made abstract in py3 }
// TODO: Copy/Paste with PyClass.getMeta.. private static boolean addMetaAbcIfNeeded(@NotNull final PyClass aClass) { final PsiFile file = aClass.getContainingFile(); final PyType type = aClass.getMetaClassType(TypeEvalContext.userInitiated(file)); if (type != null) { return false; // User already has metaclass. He probably knows about metaclasses, so we should // not add ABCMeta } final LanguageLevel languageLevel = LanguageLevel.forElement(aClass); if (languageLevel .isPy3K()) { // TODO: Copy/paste, use strategy because we already has the same check in // #couldBeAbstract // Add (metaclass= for Py3K PyClassRefactoringUtil.addSuperClassExpressions( aClass.getProject(), aClass, null, Collections.singletonList(Pair.create(PyNames.METACLASS, ABC_META_CLASS))); } else { // Add __metaclass__ for Py2 PyClassRefactoringUtil.addClassAttributeIfNotExist( aClass, PyNames.DUNDER_METACLASS, ABC_META_CLASS); } return true; }
protected PyExpression createExpression(Project project, String name, PsiElement declaration) { return PyElementGenerator.getInstance(project) .createExpressionFromText(LanguageLevel.forElement(declaration), name); }