mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
PY-81936 Code unreachable under sys.version_info guards is not highlighted
(cherry picked from commit ea1c276b5648f0ca4237b770179b27d6c5ee1048) IJ-MR-167790 GitOrigin-RevId: e76f0a1150903d9eb85141c6c4ac898f67584d3d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
fefa1ad70a
commit
9575aedee8
@@ -68,7 +68,7 @@ public final class ControlFlowCache {
|
||||
public static @NotNull PyDataFlow getDataFlow(@NotNull ScopeOwner element, @NotNull TypeEvalContext context) {
|
||||
// Cache will reset on psi modification, same as TypeEvalContext
|
||||
return PyUtil.getParameterizedCachedValue(element, context, (ctx) -> {
|
||||
return new PyDataFlow(getControlFlow(element), context);
|
||||
return new PyDataFlow(element, getControlFlow(element), context);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,27 @@ package com.jetbrains.python.codeInsight.controlflow
|
||||
|
||||
import com.intellij.codeInsight.controlflow.ControlFlow
|
||||
import com.intellij.codeInsight.controlflow.Instruction
|
||||
import com.intellij.openapi.util.Version
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil
|
||||
import com.jetbrains.python.psi.*
|
||||
import com.jetbrains.python.psi.impl.PyEvaluator
|
||||
import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher
|
||||
import com.jetbrains.python.psi.impl.stubs.evaluateVersionsForElement
|
||||
import com.jetbrains.python.psi.types.PyNeverType
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.util.*
|
||||
|
||||
@ApiStatus.Internal
|
||||
class PyDataFlow(controlFlow: ControlFlow, private val context: TypeEvalContext) : ControlFlow by controlFlow {
|
||||
class PyDataFlow(scopeOwner: ScopeOwner, controlFlow: ControlFlow, private val context: TypeEvalContext) : ControlFlow by controlFlow {
|
||||
private val reachability: BooleanArray = BooleanArray(instructions.size)
|
||||
private val languageVersion = run {
|
||||
val languageLevel = PythonLanguageLevelPusher.getLanguageLevelForFile(scopeOwner.containingFile)
|
||||
Version(languageLevel.majorVersion, languageLevel.minorVersion, 0)
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
buildReachability()
|
||||
@@ -45,19 +53,25 @@ class PyDataFlow(controlFlow: ControlFlow, private val context: TypeEvalContext)
|
||||
private fun getReachableSuccessors(instruction: Instruction): Collection<Instruction> {
|
||||
if (instruction is CallInstruction && instruction.isNoReturnCall(context)) return emptyList()
|
||||
if (instruction is PyWithContextExitInstruction && !instruction.isSuppressingExceptions(context)) return emptyList()
|
||||
return instruction.allSucc().filter { next: Instruction ->
|
||||
if (next is ReadWriteInstruction && next.access.isAssertTypeAccess) {
|
||||
val type = next.getType(context, null)
|
||||
return@filter !(type != null && type.get() is PyNeverType)
|
||||
return instruction.allSucc()
|
||||
.filter { it.isReachableWithVersionChecks() }
|
||||
.filter { next: Instruction ->
|
||||
if (next is ReadWriteInstruction && next.access.isAssertTypeAccess) {
|
||||
val type = next.getType(context, null)
|
||||
return@filter !(type != null && type.get() is PyNeverType)
|
||||
}
|
||||
return@filter true
|
||||
}
|
||||
return@filter true
|
||||
}
|
||||
}
|
||||
|
||||
fun isUnreachable(instruction: Instruction): Boolean {
|
||||
if (instruction.num() >= reachability.size) return false
|
||||
return !reachability[instruction.num()]
|
||||
}
|
||||
|
||||
private fun Instruction.isReachableWithVersionChecks(): Boolean {
|
||||
return evaluateVersionsForElement(element ?: return true).contains(languageVersion)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,19 @@ public class PyUnreachableCodeInspectionTest extends PyInspectionTestCase {
|
||||
public void testUnreachable() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON26, () -> doTest());
|
||||
}
|
||||
|
||||
// PY-81936
|
||||
public void testUnreachableWithLangLevel() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON310, () -> doTestByText("""
|
||||
import sys
|
||||
|
||||
if sys.version_info < (2, 7):
|
||||
<warning descr="This code is unreachable">print("Unreachable")</warning>
|
||||
|
||||
if sys.version_info > (3, 11):
|
||||
<warning descr="This code is unreachable">print("Unreachable")</warning>
|
||||
"""));
|
||||
}
|
||||
|
||||
// PY-81947
|
||||
public void testAnyOrNoneAfterIsNotNoneCast(){
|
||||
|
||||
Reference in New Issue
Block a user