PY-83900 Inspect Code consumes 100% CPU and takes unusually long on specific simple file

GitOrigin-RevId: 81973d162072c94b4d7201dffc68d43669f449a3
This commit is contained in:
Aleksandr.Govenko
2025-09-08 13:48:34 +00:00
committed by intellij-monorepo-bot
parent 0aa8300d60
commit e9d4a103a0
12 changed files with 55 additions and 49 deletions
@@ -4,7 +4,7 @@ package com.jetbrains.python.psi;
import com.jetbrains.python.ast.PyAstCaseClause;
import org.jetbrains.annotations.Nullable;
public interface PyCaseClause extends PyAstCaseClause, PyStatementPart, PyCaptureContext {
public interface PyCaseClause extends PyAstCaseClause, PyStatementPart {
@Override
default @Nullable PyPattern getPattern() {
return (PyPattern)PyAstCaseClause.super.getPattern();
@@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Set;
public interface PyClassPattern extends PyAstClassPattern, PyPattern, PyCaptureContext {
public interface PyClassPattern extends PyAstClassPattern, PyPattern {
Set<String> SPECIAL_BUILTINS = Set.of(
"bool", "bytearray", "bytes", "dict", "float", "frozenset", "int", "list", "set", "str", "tuple");
@@ -3,4 +3,4 @@ package com.jetbrains.python.psi
import com.jetbrains.python.ast.PyAstMappingPattern
interface PyMappingPattern : PyAstMappingPattern, PyPattern, PyCaptureContext
interface PyMappingPattern : PyAstMappingPattern, PyPattern
@@ -1,7 +1,6 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.jetbrains.python.psi
import com.intellij.psi.util.findParentOfType
import com.jetbrains.python.ast.PyAstPattern
import com.jetbrains.python.psi.types.PyType
import com.jetbrains.python.psi.types.TypeEvalContext
@@ -40,38 +39,3 @@ interface PyPattern : PyAstPattern, PyTypedElement {
return true
}
}
interface PyCaptureContext : PyElement {
fun getCaptureTypeForChild(pattern: PyPattern, context: TypeEvalContext): PyType?
companion object {
/**
* Determines what type this pattern would have if it was a capture pattern (like a bare name or _).
*
* In pattern matching, a capture pattern takes on the type of the entire matched expression,
* regardless of any specific pattern constraints.
*
* For example:
* ```python
* x: int | str
* match x:
* case a: # This is a capture pattern
* # Here 'a' has type int | str
* case str(): # This is a class pattern
* # Capture type: int | str (same as what 'case a:' would get)
* # Regular getType: str
*
* y: int
* match y:
* case str() as a:
* # Capture type: int (same as what 'case a:' would get)
* # Regular getType: intersect(int, str) (just 'str' for now)
* ```
* @see PyPattern#getType(TypeEvalContext, TypeEvalContext.Key)
*/
@JvmStatic
fun getCaptureType(pattern: PyPattern, context: TypeEvalContext): PyType? {
return pattern.findParentOfType<PyCaptureContext>()?.getCaptureTypeForChild(pattern, context)
}
}
}
@@ -4,7 +4,7 @@ package com.jetbrains.python.psi
import com.jetbrains.python.ast.PyAstSequencePattern
import com.jetbrains.python.ast.findChildrenByClass
interface PySequencePattern : PyAstSequencePattern, PyPattern, PyCaptureContext {
interface PySequencePattern : PyAstSequencePattern, PyPattern {
val elements: List<PyPattern>
get() = findChildrenByClass(PyPattern::class.java).toList()
}
@@ -0,0 +1,45 @@
package com.jetbrains.python.psi.impl
import com.intellij.psi.util.findParentOfType
import com.jetbrains.python.psi.PyElement
import com.jetbrains.python.psi.PyPattern
import com.jetbrains.python.psi.PyUtil
import com.jetbrains.python.psi.types.PyType
import com.jetbrains.python.psi.types.TypeEvalContext
interface PyCaptureContext : PyElement {
fun getCaptureTypeForChild(pattern: PyPattern, context: TypeEvalContext): PyType?
companion object {
/**
* Determines what type this pattern would have if it was a capture pattern (like a bare name or _).
*
* In pattern matching, a capture pattern takes on the type of the entire matched expression,
* regardless of any specific pattern constraints.
*
* For example:
* ```python
* x: int | str
* match x:
* case a: # This is a capture pattern
* # Here 'a' has type int | str
* case str(): # This is a class pattern
* # Capture type: int | str (same as what 'case a:' would get)
* # Regular getType: str
*
* y: int
* match y:
* case str() as a:
* # Capture type: int (same as what 'case a:' would get)
* # Regular getType: intersect(int, str) (just 'str' for now)
* ```
* @see PyPattern#getType(TypeEvalContext, TypeEvalContext.Key)
*/
@JvmStatic
fun getCaptureType(pattern: PyPattern, context: TypeEvalContext): PyType? {
return PyUtil.getNullableParameterizedCachedValue(pattern, context) {
pattern.findParentOfType<PyCaptureContext>()?.getCaptureTypeForChild(pattern, context)
}
}
}
}
@@ -1,7 +1,6 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyCaptureContext;
import com.jetbrains.python.psi.PyCapturePattern;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.types.PyType;
@@ -10,7 +10,7 @@ import com.jetbrains.python.psi.PyPattern
import com.jetbrains.python.psi.types.PyType
import com.jetbrains.python.psi.types.TypeEvalContext
class PyCaseClauseImpl(astNode: ASTNode?) : PyElementImpl(astNode), PyCaseClause {
class PyCaseClauseImpl(astNode: ASTNode?) : PyElementImpl(astNode), PyCaseClause, PyCaptureContext {
override fun acceptPyVisitor(pyVisitor: PyElementVisitor) {
pyVisitor.visitPyCaseClause(this)
}
@@ -19,7 +19,7 @@ import static com.intellij.util.containers.ContainerUtil.getFirstItem;
import static com.jetbrains.python.psi.PyUtil.as;
import static com.jetbrains.python.psi.PyUtil.multiResolveTopPriority;
public class PyClassPatternImpl extends PyElementImpl implements PyClassPattern {
public class PyClassPatternImpl extends PyElementImpl implements PyClassPattern, PyCaptureContext {
public PyClassPatternImpl(ASTNode astNode) {
super(astNode);
}
@@ -4,12 +4,11 @@ import com.intellij.lang.ASTNode
import com.intellij.psi.PsiListLikeElement
import com.intellij.psi.util.findParentInFile
import com.jetbrains.python.psi.*
import com.jetbrains.python.psi.PyCaptureContext.Companion.getCaptureType
import com.jetbrains.python.psi.impl.PyBuiltinCache.Companion.getInstance
import com.jetbrains.python.psi.types.*
import com.jetbrains.python.psi.types.PyLiteralType.Companion.upcastLiteralToClass
class PyMappingPatternImpl(astNode: ASTNode?) : PyElementImpl(astNode), PyMappingPattern, PsiListLikeElement {
class PyMappingPatternImpl(astNode: ASTNode?) : PyElementImpl(astNode), PyMappingPattern, PyCaptureContext, PsiListLikeElement {
override fun acceptPyVisitor(pyVisitor: PyElementVisitor) {
pyVisitor.visitPyMappingPattern(this)
}
@@ -30,7 +29,7 @@ class PyMappingPatternImpl(astNode: ASTNode?) : PyElementImpl(astNode), PyMappin
val patternMappingType = wrapInMappingType(PyUnionType.union(keyTypes), PyUnionType.union(valueTypes))
val filteredType = getCaptureType(this, context).toList().filter { captureType: PyType? ->
val filteredType = PyCaptureContext.getCaptureType(this, context).toList().filter { captureType: PyType? ->
val mappingType = PyTypeUtil.convertToType(captureType, "typing.Mapping", this, context) ?: return@filter false
PyTypeChecker.match(mappingType, patternMappingType, context)
}.let {
@@ -53,7 +52,7 @@ class PyMappingPatternImpl(astNode: ASTNode?) : PyElementImpl(astNode), PyMappin
if (sequenceMember !is PyKeyValuePattern) return null
return getCaptureType(this, context).toList()
return PyCaptureContext.getCaptureType(this, context).toList()
.map { possibleMapping -> possibleMapping.getValueType(sequenceMember, context) }
.let { PyUnionType.union(it) }
}
@@ -9,7 +9,7 @@ import com.jetbrains.python.psi.types.PyLiteralType.Companion.upcastLiteralToCla
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
class PySequencePatternImpl(astNode: ASTNode?) : PyElementImpl(astNode), PySequencePattern, PsiListLikeElement {
class PySequencePatternImpl(astNode: ASTNode?) : PyElementImpl(astNode), PySequencePattern, PyCaptureContext, PsiListLikeElement {
override fun acceptPyVisitor(pyVisitor: PyElementVisitor) {
pyVisitor.visitPySequencePattern(this)
}
@@ -1,7 +1,6 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyCaptureContext;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyWildcardPattern;
import com.jetbrains.python.psi.types.PyType;