mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
PY-61651 Deprecation highlighting with PEP 702 @deprecated decorator
GitOrigin-RevId: 426e7001d20849d7029fea55431d3e2cfae3eb11
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c02d4c094d
commit
673383c3da
@@ -2,8 +2,8 @@ import sys
|
||||
from _warnings import warn as warn, warn_explicit as warn_explicit
|
||||
from collections.abc import Sequence
|
||||
from types import ModuleType, TracebackType
|
||||
from typing import Any, Generic, TextIO, TypeVar, overload
|
||||
from typing_extensions import Literal, TypeAlias
|
||||
from typing import Any, Generic, Literal, TextIO, TypeVar, overload
|
||||
from typing_extensions import LiteralString, TypeAlias
|
||||
|
||||
__all__ = [
|
||||
"warn",
|
||||
@@ -16,6 +16,10 @@ __all__ = [
|
||||
"catch_warnings",
|
||||
]
|
||||
|
||||
if sys.version_info >= (3, 13):
|
||||
__all__ += ["deprecated"]
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_W = TypeVar("_W", bound=list[WarningMessage] | None)
|
||||
_ActionKind: TypeAlias = Literal["default", "error", "ignore", "always", "module", "once"]
|
||||
|
||||
@@ -110,3 +114,11 @@ class catch_warnings(Generic[_W]):
|
||||
def __exit__(
|
||||
self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None
|
||||
) -> None: ...
|
||||
|
||||
if sys.version_info >= (3, 13):
|
||||
class deprecated:
|
||||
message: LiteralString
|
||||
category: type[Warning] | None
|
||||
stacklevel: int
|
||||
def __init__(self, message: LiteralString, /, *, category: type[Warning] | None = ..., stacklevel: int = 1) -> None: ...
|
||||
def __call__(self, arg: _T, /) -> _T: ...
|
||||
|
||||
@@ -41,8 +41,7 @@ import java.util.List;
|
||||
@ApiStatus.Experimental
|
||||
public interface PyAstClass extends PsiNameIdentifierOwner, PyAstCompoundStatement, PyAstDocStringOwner, AstScopeOwner,
|
||||
PyAstDecoratable, PyAstTypedElement, PyAstQualifiedNameOwner, PyAstStatementListContainer,
|
||||
PyAstWithAncestors,
|
||||
PyAstTypeParameterListOwner {
|
||||
PyAstWithAncestors, PyAstTypeParameterListOwner {
|
||||
PyAstClass[] EMPTY_ARRAY = new PyAstClass[0];
|
||||
ArrayFactory<PyAstClass> ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new PyAstClass[count];
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.jetbrains.python.ast;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayFactory;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
@@ -12,7 +11,6 @@ import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonDialectsTokenSetProvider;
|
||||
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.ast.controlFlow.AstScopeOwner;
|
||||
import com.jetbrains.python.ast.docstring.DocStringUtilCore;
|
||||
@@ -21,8 +19,6 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -32,7 +28,7 @@ import java.util.Optional;
|
||||
@ApiStatus.Experimental
|
||||
public interface PyAstFunction extends PsiNameIdentifierOwner, PyAstCompoundStatement,
|
||||
PyAstDecoratable, PyAstCallable, PyAstStatementListContainer, PyAstPossibleClassMember,
|
||||
AstScopeOwner, PyAstDocStringOwner, PyAstTypeCommentOwner, PyAstAnnotationOwner, PyAstTypeParameterListOwner {
|
||||
AstScopeOwner, PyAstDocStringOwner, PyAstTypeCommentOwner, PyAstAnnotationOwner, PyAstTypeParameterListOwner{
|
||||
|
||||
PyAstFunction[] EMPTY_ARRAY = new PyAstFunction[0];
|
||||
ArrayFactory<PyAstFunction> ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new PyAstFunction[count];
|
||||
@@ -88,39 +84,6 @@ public interface PyAstFunction extends PsiNameIdentifierOwner, PyAstCompoundStat
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the function raises a DeprecationWarning or a PendingDeprecationWarning, returns the explanation text provided for the warning..
|
||||
*
|
||||
* @return the deprecation message or null if the function is not deprecated.
|
||||
*/
|
||||
@Nullable
|
||||
default String getDeprecationMessage() {
|
||||
return extractDeprecationMessage();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default String extractDeprecationMessage() {
|
||||
PyAstStatementList statementList = getStatementList();
|
||||
return extractDeprecationMessage(Arrays.asList(statementList.getStatements()));
|
||||
}
|
||||
|
||||
static @Nullable String extractDeprecationMessage(List<? extends PyAstStatement> statements) {
|
||||
for (PyAstStatement statement : statements) {
|
||||
if (statement instanceof PyAstExpressionStatement expressionStatement) {
|
||||
if (expressionStatement.getExpression() instanceof PyAstCallExpression callExpression) {
|
||||
if (callExpression.isCalleeText(PyNames.WARN)) {
|
||||
PyAstReferenceExpression warningClass = callExpression.getArgument(1, PyAstReferenceExpression.class);
|
||||
if (warningClass != null && (PyNames.DEPRECATION_WARNING.equals(warningClass.getReferencedName()) ||
|
||||
PyNames.PENDING_DEPRECATION_WARNING.equals(warningClass.getReferencedName()))) {
|
||||
return PyPsiUtilsCore.strValue(callExpression.getArguments()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
default String getDocStringValue() {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.jetbrains.python.ast.impl
|
||||
|
||||
import com.jetbrains.python.ast.PyAstDecoratable
|
||||
import com.jetbrains.python.ast.PyAstStringLiteralExpression
|
||||
|
||||
val deprecatedDecoratorContainers = arrayOf("typing_extensions.pyi", "warnings.pyi")
|
||||
|
||||
fun extractDeprecationMessageFromDecorator(element: PyAstDecoratable): String? {
|
||||
val deprecatedDecorator = element.decoratorList?.decorators?.firstOrNull { it.name == "deprecated" } ?: return null
|
||||
val annotationClass = deprecatedDecorator.callee?.reference?.resolve() ?: return null
|
||||
if (annotationClass.containingFile?.name !in deprecatedDecoratorContainers) {
|
||||
return null
|
||||
}
|
||||
|
||||
val argumentList = deprecatedDecorator.argumentList ?: return null
|
||||
|
||||
if (argumentList.arguments.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
val argument = argumentList.arguments[0] as? PyAstStringLiteralExpression ?: return null
|
||||
return argument.stringValue
|
||||
}
|
||||
@@ -36,12 +36,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.jetbrains.python.ast.impl.PyDeprecationUtilKt.extractDeprecationMessageFromDecorator;
|
||||
|
||||
/**
|
||||
* Represents a class declaration in source.
|
||||
*/
|
||||
public interface PyClass extends PyAstClass, PsiNameIdentifierOwner, PyCompoundStatement, PyDocStringOwner, StubBasedPsiElement<PyClassStub>,
|
||||
ScopeOwner, PyDecoratable, PyTypedElement, PyQualifiedNameOwner, PyStatementListContainer, PyWithAncestors,
|
||||
PyTypeParameterListOwner {
|
||||
PyTypeParameterListOwner, PyDeprecatable {
|
||||
PyClass[] EMPTY_ARRAY = new PyClass[0];
|
||||
ArrayFactory<PyClass> ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new PyClass[count];
|
||||
|
||||
@@ -367,6 +369,12 @@ public interface PyClass extends PyAstClass, PsiNameIdentifierOwner, PyCompoundS
|
||||
@Nullable
|
||||
PyClassLikeType getType(@NotNull TypeEvalContext context);
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
default String getDeprecationMessage() {
|
||||
return extractDeprecationMessageFromDecorator(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
default PyStringLiteralExpression getDocStringExpression() {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.jetbrains.python.psi;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface PyDeprecatable {
|
||||
@Nullable
|
||||
String getDeprecationMessage();
|
||||
}
|
||||
@@ -4,7 +4,9 @@ package com.jetbrains.python.psi;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.intellij.util.ArrayFactory;
|
||||
import com.jetbrains.python.ast.PyAstFunction;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.psi.stubs.PyFunctionStub;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
@@ -12,14 +14,18 @@ import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static com.jetbrains.python.ast.impl.PyDeprecationUtilKt.extractDeprecationMessageFromDecorator;
|
||||
|
||||
/**
|
||||
* Function declaration in source (the {@code def} and everything within).
|
||||
*/
|
||||
public interface PyFunction extends PyAstFunction, StubBasedPsiElement<PyFunctionStub>, PsiNameIdentifierOwner, PyCompoundStatement,
|
||||
PyDecoratable, PyCallable, PyStatementListContainer, PyPossibleClassMember,
|
||||
ScopeOwner, PyDocStringOwner, PyTypeCommentOwner, PyAnnotationOwner, PyTypeParameterListOwner {
|
||||
ScopeOwner, PyDocStringOwner, PyTypeCommentOwner, PyAnnotationOwner, PyTypeParameterListOwner,
|
||||
PyDeprecatable {
|
||||
|
||||
PyFunction[] EMPTY_ARRAY = new PyFunction[0];
|
||||
ArrayFactory<PyFunction> ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new PyFunction[count];
|
||||
@@ -66,6 +72,44 @@ public interface PyFunction extends PyAstFunction, StubBasedPsiElement<PyFunctio
|
||||
return (PyStringLiteralExpression)PyAstFunction.super.getDocStringExpression();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the function raises a DeprecationWarning or a PendingDeprecationWarning, returns the explanation text provided for the warning..
|
||||
*
|
||||
* @return the deprecation message or null if the function is not deprecated.
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
default String getDeprecationMessage() {
|
||||
return extractDeprecationMessage();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
default String extractDeprecationMessage() {
|
||||
String deprecationMessageFromDecorator = extractDeprecationMessageFromDecorator(this);
|
||||
if (deprecationMessageFromDecorator != null) {
|
||||
return deprecationMessageFromDecorator;
|
||||
}
|
||||
PyAstStatementList statementList = getStatementList();
|
||||
return extractDeprecationMessage(Arrays.asList(statementList.getStatements()));
|
||||
}
|
||||
|
||||
static @Nullable String extractDeprecationMessage(List<? extends PyAstStatement> statements) {
|
||||
for (PyAstStatement statement : statements) {
|
||||
if (statement instanceof PyAstExpressionStatement expressionStatement) {
|
||||
if (expressionStatement.getExpression() instanceof PyAstCallExpression callExpression) {
|
||||
if (callExpression.isCalleeText(PyNames.WARN)) {
|
||||
PyAstReferenceExpression warningClass = callExpression.getArgument(1, PyAstReferenceExpression.class);
|
||||
if (warningClass != null && (PyNames.DEPRECATION_WARNING.equals(warningClass.getReferencedName()) ||
|
||||
PyNames.PENDING_DEPRECATION_WARNING.equals(warningClass.getReferencedName()))) {
|
||||
return PyPsiUtilsCore.strValue(callExpression.getArguments()[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
default PyClass getContainingClass() {
|
||||
|
||||
@@ -47,6 +47,9 @@ public interface PyClassStub extends NamedStub<PyClass> {
|
||||
@Nullable
|
||||
String getDocString();
|
||||
|
||||
@Nullable
|
||||
String getDeprecationMessage();
|
||||
|
||||
/**
|
||||
* @return literal text of expressions in the base classes list.
|
||||
*/
|
||||
|
||||
@@ -48,6 +48,17 @@ public final class PyDeprecationInspection extends PyInspection {
|
||||
super(holder, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyBinaryExpression(@NotNull PyBinaryExpression node) {
|
||||
final PsiElement resolveResult = node.getReference(getResolveContext()).resolve();
|
||||
if (resolveResult instanceof PyDeprecatable) {
|
||||
@NlsSafe String deprecationMessage = ((PyDeprecatable)resolveResult).getDeprecationMessage();
|
||||
if (deprecationMessage != null) {
|
||||
registerProblem(node.getPsiOperator(), deprecationMessage, ProblemHighlightType.WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyReferenceExpression(@NotNull PyReferenceExpression node) {
|
||||
final PyExceptPart exceptPart = PsiTreeUtil.getParentOfType(node, PyExceptPart.class);
|
||||
@@ -62,8 +73,8 @@ public final class PyDeprecationInspection extends PyInspection {
|
||||
if (resolveResult != null && element != resolveResult.getContainingFile()) return;
|
||||
}
|
||||
@NlsSafe String deprecationMessage = null;
|
||||
if (resolveResult instanceof PyFunction) {
|
||||
deprecationMessage = ((PyFunction)resolveResult).getDeprecationMessage();
|
||||
if (resolveResult instanceof PyDeprecatable deprecatable) {
|
||||
deprecationMessage = deprecatable.getDeprecationMessage();
|
||||
}
|
||||
else if (resolveResult instanceof PyFile) {
|
||||
deprecationMessage = ((PyFile)resolveResult).getDeprecationMessage();
|
||||
|
||||
@@ -61,7 +61,7 @@ public class PyFileElementType extends IStubFileElementType<PyFileStub> {
|
||||
@Override
|
||||
public int getStubVersion() {
|
||||
// Don't forget to update versions of indexes that use the updated stub-based elements
|
||||
return 87;
|
||||
return 88;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1305,6 +1305,15 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
return PyClass.super.getDocStringValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getDeprecationMessage() {
|
||||
PyClassStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.getDeprecationMessage();
|
||||
}
|
||||
return PyClass.super.getDeprecationMessage();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StructuredDocString getStructuredDocString() {
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.ast.PyAstElementVisitor;
|
||||
import com.jetbrains.python.ast.PyAstFunction;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
@@ -701,7 +700,7 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
|
||||
|
||||
public String extractDeprecationMessage() {
|
||||
if (canHaveDeprecationMessage(getText())) {
|
||||
return PyAstFunction.extractDeprecationMessage(getStatements());
|
||||
return PyFunction.extractDeprecationMessage(getStatements());
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.stubs.*;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyStubElementTypes;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyClassImpl;
|
||||
@@ -54,6 +53,7 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
|
||||
PyPsiUtils.asQualifiedName(psi.getMetaClassExpression()),
|
||||
psi.getOwnSlots(),
|
||||
PyPsiUtils.strValue(psi.getDocStringExpression()),
|
||||
psi.getDeprecationMessage(),
|
||||
getStubElementType(),
|
||||
createCustomStub(psi));
|
||||
}
|
||||
@@ -133,6 +133,7 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
|
||||
|
||||
final String docString = pyClassStub.getDocString();
|
||||
dataStream.writeUTFFast(docString != null ? docString : "");
|
||||
dataStream.writeName(pyClassStub.getDeprecationMessage());
|
||||
|
||||
serializeCustomStub(pyClassStub.getCustomStub(PyCustomClassStub.class), dataStream);
|
||||
}
|
||||
@@ -162,9 +163,11 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
|
||||
final String docStringInStub = dataStream.readUTFFast();
|
||||
final String docString = docStringInStub.length() > 0 ? docStringInStub : null;
|
||||
|
||||
final String deprecationMessage = dataStream.readNameString();
|
||||
|
||||
final PyCustomClassStub customStub = deserializeCustomStub(dataStream);
|
||||
|
||||
return new PyClassStubImpl(name, parentStub, superClasses, baseClassesText, metaClass, slots, docString,
|
||||
return new PyClassStubImpl(name, parentStub, superClasses, baseClassesText, metaClass, slots, docString, deprecationMessage,
|
||||
getStubElementType(), customStub);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
@NotNull
|
||||
private final List<String> mySuperClassesText;
|
||||
|
||||
@Nullable
|
||||
private final String myDeprecationMessage;
|
||||
|
||||
@Nullable
|
||||
private final PyCustomClassStub myCustomStub;
|
||||
|
||||
@@ -44,6 +47,7 @@ public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
@Nullable QualifiedName metaClass,
|
||||
@Nullable List<String> slots,
|
||||
@Nullable String docString,
|
||||
@Nullable String deprecationMessage,
|
||||
@NotNull IStubElementType stubElementType,
|
||||
@Nullable PyCustomClassStub customStub) {
|
||||
super(parentStub, stubElementType);
|
||||
@@ -53,6 +57,7 @@ public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
myMetaClass = metaClass;
|
||||
mySlots = slots;
|
||||
myDocString = docString;
|
||||
myDeprecationMessage = deprecationMessage;
|
||||
myCustomStub = customStub;
|
||||
}
|
||||
|
||||
@@ -86,6 +91,12 @@ public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
|
||||
return myDocString;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getDeprecationMessage() {
|
||||
return myDeprecationMessage;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<String> getSuperClassesText() {
|
||||
|
||||
21
python/testData/deprecation/customDeprecatedAnnotation.py
Normal file
21
python/testData/deprecation/customDeprecatedAnnotation.py
Normal file
@@ -0,0 +1,21 @@
|
||||
class deprecated():
|
||||
def __init__(
|
||||
self,
|
||||
message: str,
|
||||
/,
|
||||
*,
|
||||
category: type[Warning] | None = DeprecationWarning,
|
||||
stacklevel: int = 1,
|
||||
) -> None:
|
||||
return None
|
||||
|
||||
def __call__(self, arg, /):
|
||||
pass
|
||||
|
||||
|
||||
@deprecated("deprecated")
|
||||
def my_method():
|
||||
pass
|
||||
|
||||
|
||||
my_method()
|
||||
9
python/testData/deprecation/deprecatedAdd.py
Normal file
9
python/testData/deprecation/deprecatedAdd.py
Normal file
@@ -0,0 +1,9 @@
|
||||
from warnings import deprecated
|
||||
|
||||
class Spam:
|
||||
@deprecated("There is enough spam in the world")
|
||||
def __add__(self, other: object) -> object:
|
||||
pass
|
||||
|
||||
|
||||
Spam() <warning descr="There is enough spam in the world">+</warning> 1
|
||||
@@ -0,0 +1,3 @@
|
||||
from library import <warning descr="Use Spam instead">Ham</warning>
|
||||
|
||||
ham = <warning descr="Use Spam instead">Ham</warning>()
|
||||
4
python/testData/deprecation/deprecatedClass/library.pyi
Normal file
4
python/testData/deprecation/deprecatedClass/library.pyi
Normal file
@@ -0,0 +1,4 @@
|
||||
from warnings import deprecated
|
||||
|
||||
@deprecated("Use Spam instead")
|
||||
class Ham: ...
|
||||
@@ -0,0 +1,7 @@
|
||||
from typing_extensions import deprecated
|
||||
|
||||
@deprecated("Deprecated class")
|
||||
class MyClass:
|
||||
pass
|
||||
|
||||
var = <warning descr="Deprecated class">MyClass</warning>()
|
||||
7
python/testData/deprecation/deprecatedMethod.py
Normal file
7
python/testData/deprecation/deprecatedMethod.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from warnings import deprecated
|
||||
|
||||
@deprecated("It is pining for the fiords")
|
||||
def norwegian_blue(x: int) -> int:
|
||||
pass
|
||||
|
||||
<warning descr="It is pining for the fiords">norwegian_blue</warning>(1)
|
||||
@@ -0,0 +1,7 @@
|
||||
from warnings import deprecated
|
||||
|
||||
@deprecated("Deprecated class", category=DeprecationWarning, stacklevel=1)
|
||||
class MyClass:
|
||||
pass
|
||||
|
||||
var = <warning descr="Deprecated class">MyClass</warning>()
|
||||
5
python/testData/stubs/DeprecationMessageInClass.py
Normal file
5
python/testData/stubs/DeprecationMessageInClass.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from warnings import deprecated
|
||||
|
||||
@deprecated("Use Spam instead")
|
||||
class Ham:
|
||||
pass
|
||||
@@ -83,6 +83,43 @@ public class PyDeprecationTest extends PyTestCase {
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testDeprecatedClass() {
|
||||
myFixture.enableInspections(PyDeprecationInspection.class);
|
||||
myFixture.copyDirectoryToProject("deprecation/deprecatedClass", "");
|
||||
myFixture.configureByFile("deprecatedClass.py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testDeprecatedMethod() {
|
||||
myFixture.enableInspections(PyDeprecationInspection.class);
|
||||
myFixture.configureByFile("deprecation/deprecatedMethod.py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testDeprecatedAdd() {
|
||||
myFixture.enableInspections(PyDeprecationInspection.class);
|
||||
myFixture.configureByFile("deprecation/deprecatedAdd.py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testDeprecatedFromTypingExtension() {
|
||||
myFixture.enableInspections(PyDeprecationInspection.class);
|
||||
myFixture.configureByFile("deprecation/deprecatedFromTypingExtension.py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testDeprecatedWithSeveralArguments() {
|
||||
myFixture.enableInspections(PyDeprecationInspection.class);
|
||||
myFixture.configureByFile("deprecation/deprecatedWithSeveralArguments.py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testCustomDeprecatedAnnotation() {
|
||||
myFixture.enableInspections(PyDeprecationInspection.class);
|
||||
myFixture.configureByFile("deprecation/customDeprecatedAnnotation.py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testAbcDeprecatedAbstracts() {
|
||||
myFixture.enableInspections(PyDeprecationInspection.class);
|
||||
myFixture.configureByFile("deprecation/abcDeprecatedAbstracts.py");
|
||||
|
||||
@@ -1107,6 +1107,14 @@ public class PyStubsTest extends PyTestCase {
|
||||
doTestTypeParameterStub(cls, file);
|
||||
}
|
||||
|
||||
// PY-61651 Deprecation highlighting with PEP 702 @deprecated decorator
|
||||
public void testDeprecationMessageInClass() {
|
||||
PyFile file = getTestFile();
|
||||
PyClass cls = file.findTopLevelClass("Ham");
|
||||
assertNotNull(cls);
|
||||
assertEquals("Use Spam instead", cls.getDeprecationMessage());
|
||||
}
|
||||
|
||||
// PY-62608
|
||||
public void testTypeAliasStatement() {
|
||||
PyFile file = getTestFile();
|
||||
|
||||
Reference in New Issue
Block a user