PY-80002 Don't report non-quoted forward references in Python 3.14+ (PEP 649)

GitOrigin-RevId: b16fffe886d350a54434adb57519eb9c1992e217
This commit is contained in:
Mikhail Golubev
2025-09-16 17:00:01 +00:00
committed by intellij-monorepo-bot
parent bea0075b8f
commit 761c8be02a
5 changed files with 26 additions and 7 deletions
@@ -424,12 +424,14 @@ public final class PyResolveUtil {
// Forward references are allowed in annotations according to PEP 563
PsiFile file = element.getContainingFile();
if (file instanceof PyFile pyFile) {
boolean isAnnotation = pyFile.getLanguageLevel().isAtLeast(LanguageLevel.PYTHON37) &&
pyFile.hasImportFromFuture(FutureFeature.ANNOTATIONS) &&
PsiTreeUtil.getParentOfType(element, PyAnnotation.class) != null;
if (isAnnotation) return true;
LanguageLevel languageLevel = pyFile.getLanguageLevel();
boolean nonEagerEvaluationEnabled =
(languageLevel.isAtLeast(LanguageLevel.PYTHON37) && pyFile.hasImportFromFuture(FutureFeature.ANNOTATIONS))
|| languageLevel.isAtLeast(LanguageLevel.PYTHON314);
boolean insideAnnotation = PsiTreeUtil.getParentOfType(element, PyAnnotation.class) != null;
if (insideAnnotation && nonEagerEvaluationEnabled) return true;
boolean isReferenceFromTypeParameterList = pyFile.getLanguageLevel().isAtLeast(LanguageLevel.PYTHON312) &&
boolean isReferenceFromTypeParameterList = languageLevel.isAtLeast(LanguageLevel.PYTHON312) &&
PsiTreeUtil.getParentOfType(element, PyTypeParameter.class, true) != null;
if (isReferenceFromTypeParameterList) return true;
}
@@ -0,0 +1,6 @@
def f(a: A):
pass
class A:
pass
@@ -11,6 +11,7 @@ import com.intellij.util.io.URLUtil
import com.jetbrains.python.PythonTestUtil
import com.jetbrains.python.fixtures.PyTestCase
import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection
import com.jetbrains.python.psi.LanguageLevel
import com.jetbrains.python.psi.PyRecursiveElementVisitor
import org.junit.AfterClass
import org.junit.Test
@@ -51,7 +52,12 @@ class PyTypingConformanceTest(private val testFileName: String) : PyTestCase() {
fun test() {
myFixture.configureByFiles(*getFilePaths())
myFixture.enableInspections(*inspections)
checkHighlighting()
// The test suite has not been updated for 3.14 by default.
// In particular, forward references are not enabled by default
// and require an explicit `from __future__ import annotations`.
runWithLanguageLevel(LanguageLevel.PYTHON313, {
checkHighlighting()
})
}
private fun getFilePaths(): Array<String> {
@@ -251,7 +251,12 @@ public class PyUnboundLocalVariableInspectionTest extends PyInspectionTestCase {
doTest();
}
public void testForwardReferenceInAnnotations() {
public void testForwardReferenceInAnnotationsWithFromFutureImportAnnotationsBefore314() {
runWithLanguageLevel(LanguageLevel.PYTHON313, this::doTest);
}
// PY-80002
public void testForwardReferenceInAnnotationsInPython314() {
doTest();
}