mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
PY-74012 Deprecation decorator stub resolves during indexing
Avoid using resolve when calculating deprecation messages GitOrigin-RevId: 813849bdaeb3819b445db600fc0efbcb014ed5c9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
2f610dc4a8
commit
e6c66dfd5e
@@ -1,21 +0,0 @@
|
||||
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
|
||||
}
|
||||
|
||||
if (deprecatedDecorator.arguments.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val argument = deprecatedDecorator.arguments[0] as? PyAstStringLiteralExpression ?: return null
|
||||
return argument.stringValue
|
||||
}
|
||||
@@ -36,8 +36,6 @@ 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.
|
||||
*/
|
||||
@@ -369,12 +367,6 @@ 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() {
|
||||
|
||||
@@ -5,5 +5,5 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface PyDeprecatable {
|
||||
@Nullable
|
||||
String getDeprecationMessage();
|
||||
default String getDeprecationMessage() { return null; }
|
||||
}
|
||||
|
||||
@@ -14,10 +14,8 @@ 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).
|
||||
@@ -72,27 +70,6 @@ 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) {
|
||||
|
||||
@@ -56,6 +56,7 @@ import java.util.*;
|
||||
import static com.intellij.openapi.util.text.StringUtil.join;
|
||||
import static com.intellij.openapi.util.text.StringUtil.notNullize;
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
import static com.jetbrains.python.psi.impl.PyDeprecationUtilKt.extractDeprecationMessageFromDecorator;
|
||||
|
||||
|
||||
public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyClass {
|
||||
@@ -1311,7 +1312,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
if (stub != null) {
|
||||
return stub.getDeprecationMessage();
|
||||
}
|
||||
return PyClass.super.getDeprecationMessage();
|
||||
return extractDeprecationMessageFromDecorator(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.jetbrains.python.psi.impl
|
||||
|
||||
import com.jetbrains.python.ast.PyAstDecoratable
|
||||
import com.jetbrains.python.ast.PyAstStringLiteralExpression
|
||||
import com.jetbrains.python.psi.PyFromImportStatement
|
||||
import com.jetbrains.python.psi.PyReferenceExpression
|
||||
import com.jetbrains.python.psi.resolve.PyResolveUtil
|
||||
|
||||
val deprecationDecorators = arrayOf("typing_extensions.deprecated", "warnings.deprecated")
|
||||
|
||||
fun extractDeprecationMessageFromDecorator(element: PyAstDecoratable): String? {
|
||||
val deprecatedDecorator = element.decoratorList?.decorators?.firstOrNull { it.name == "deprecated" } ?: return null
|
||||
if (deprecatedDecorator.arguments.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
val decoratorCall = deprecatedDecorator.callee as? PyReferenceExpression ?: return null
|
||||
if (decoratorCall.asQualifiedName()?.toString() !in deprecationDecorators) {
|
||||
if (!PyResolveUtil.resolveLocally(decoratorCall).mapNotNull { it.parent as? PyFromImportStatement }.
|
||||
flatMap { it.fullyQualifiedObjectNames }.any { it in deprecationDecorators }) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return (deprecatedDecorator.arguments[0] as? PyAstStringLiteralExpression)?.stringValue
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import static com.jetbrains.python.ast.PyAstFunction.Modifier.CLASSMETHOD;
|
||||
import static com.jetbrains.python.ast.PyAstFunction.Modifier.STATICMETHOD;
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
import static com.jetbrains.python.psi.impl.PyCallExpressionHelper.interpretAsModifierWrappingCall;
|
||||
import static com.jetbrains.python.psi.impl.PyDeprecationUtilKt.extractDeprecationMessageFromDecorator;
|
||||
|
||||
public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements PyFunction {
|
||||
|
||||
@@ -349,7 +350,17 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
|
||||
if (stub != null) {
|
||||
return stub.getDeprecationMessage();
|
||||
}
|
||||
return PyFunction.super.getDeprecationMessage();
|
||||
return extractDeprecationMessage();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String extractDeprecationMessage() {
|
||||
String deprecationMessageFromDecorator = extractDeprecationMessageFromDecorator(this);
|
||||
if (deprecationMessageFromDecorator != null) {
|
||||
return deprecationMessageFromDecorator;
|
||||
}
|
||||
PyStatementList statementList = getStatementList();
|
||||
return PyFunction.extractDeprecationMessage(Arrays.asList(statementList.getStatements()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import warnings
|
||||
|
||||
@warnings.deprecated("deprecated")
|
||||
class MyClass:
|
||||
pass
|
||||
|
||||
|
||||
var = <warning descr="deprecated">MyClass</warning>()
|
||||
@@ -90,6 +90,12 @@ public class PyDeprecationTest extends PyTestCase {
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testFqnDecorator() {
|
||||
myFixture.enableInspections(PyDeprecationInspection.class);
|
||||
myFixture.configureByFile("deprecation/fqnDeprecation.py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
public void testDeprecatedMethod() {
|
||||
myFixture.enableInspections(PyDeprecationInspection.class);
|
||||
myFixture.configureByFile("deprecation/deprecatedMethod.py");
|
||||
|
||||
Reference in New Issue
Block a user