PY-81269 Extremely High RAM Usage

(cherry picked from commit bb534d62931c176d2395e2cceb0afabc57464669)

GitOrigin-RevId: 4a5b1398ca3fc3245d8e497fdd0522971e9fca51
This commit is contained in:
Andrey Vokin
2025-06-18 15:17:14 +02:00
committed by intellij-monorepo-bot
parent 377919aee2
commit c129ddc506
14 changed files with 85 additions and 16 deletions

View File

@@ -0,0 +1,7 @@
// Copyright 2000-2025 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.ApiStatus
@ApiStatus.Internal
interface PyInstantTypeProvider : PyTypedElement

View File

@@ -4,13 +4,12 @@ package com.jetbrains.python.psi.types;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.psi.PyCallable;
import com.jetbrains.python.psi.PyNoneLiteralExpression;
import com.jetbrains.python.psi.PyTypedElement;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyTypeProvider;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -22,7 +21,7 @@ import java.util.List;
import java.util.Map;
public final class TypeEvalContext {
public sealed class TypeEvalContext {
/**
* This class ensures that only {@link TypeEvalContext} instances can directly invoke
@@ -97,7 +96,7 @@ public final class TypeEvalContext {
* Inspections should not create a new type evaluation context. They should re-use the context of the inspection session.
*/
public static TypeEvalContext codeAnalysis(final @NotNull Project project, final @Nullable PsiFile origin) {
return getContextFromCache(project, new TypeEvalContext(false, false, false, origin));
return getContextFromCache(project, buildCodeAnalysisContext(origin));
}
/**
@@ -124,6 +123,13 @@ public final class TypeEvalContext {
return getContextFromCache(project, new TypeEvalContext(false, true, false, null));
}
private static TypeEvalContext buildCodeAnalysisContext(@Nullable PsiFile origin) {
if (Registry.is("python.optimized.type.eval.context")) {
return new OptimizedTypeEvalContext(false, false, false, origin);
}
return new TypeEvalContext(false, false, false, origin);
}
/**
* Moves context through cache returning one from cache (if exists).
*
@@ -283,4 +289,48 @@ public final class TypeEvalContext {
return getContextFile(context);
}
}
final static class OptimizedTypeEvalContext extends TypeEvalContext {
private volatile TypeEvalContext codeInsightFallback;
OptimizedTypeEvalContext(boolean allowDataFlow, boolean allowStubToAST, boolean allowCallContext, @Nullable PsiFile origin) {
super(allowDataFlow, allowStubToAST, allowCallContext, origin);
}
private boolean shouldSwitchToFallbackContext(PsiElement element) {
PsiFile file = element.getContainingFile();
if (file instanceof PyExpressionCodeFragment codeFragment) {
PsiElement context = codeFragment.getContext();
if (context != null) {
file = context.getContainingFile();
}
}
TypeEvalConstraints constraints = getConstraints();
return constraints.myOrigin != null && file != constraints.myOrigin && (file instanceof PyFile) &&
!constraints.myAllowDataFlow && !constraints.myAllowStubToAST && !constraints.myAllowCallContext;
}
private TypeEvalContext getFallbackContext(Project project) {
if (codeInsightFallback == null) {
codeInsightFallback = codeInsightFallback(project);
}
return codeInsightFallback;
}
@Override
public @Nullable PyType getType(@NotNull PyTypedElement element) {
if (shouldSwitchToFallbackContext(element)) {
return getFallbackContext(element.getProject()).getType(element);
}
return super.getType(element);
}
@Override
public @Nullable PyType getReturnType(@NotNull PyCallable callable) {
if (shouldSwitchToFallbackContext(callable)) {
return getFallbackContext(callable.getProject()).getReturnType(callable);
}
return super.getReturnType(callable);
}
}
}

View File

@@ -477,6 +477,8 @@
description="Require marking namespace packages explicitly, treat regular directories as implicit source roots"/>
<registryKey key="python.type.hints.literal.string" defaultValue="true"
description="When enabled, activates LiteralString inference for Python string literals" />
<registryKey key="python.optimized.type.eval.context" defaultValue="true"
description="It optimises cache usage for storing calculated types."/>
<registryKey key="python.statement.lists.incremental.reparse" defaultValue="false"
description="Enables incremental reparse for statement lists"/>
</extensions>

View File

@@ -4,12 +4,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyBoolLiteralExpression;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
public class PyBoolLiteralExpressionImpl extends PyElementImpl implements PyBoolLiteralExpression {
public class PyBoolLiteralExpressionImpl extends PyElementImpl implements PyBoolLiteralExpression, PyInstantTypeProvider {
public PyBoolLiteralExpressionImpl(ASTNode astNode) {
super(astNode);
}

View File

@@ -18,12 +18,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyDoubleStarExpression;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyDoubleStarExpressionImpl extends PyElementImpl implements PyDoubleStarExpression {
public class PyDoubleStarExpressionImpl extends PyElementImpl implements PyDoubleStarExpression, PyInstantTypeProvider {
public PyDoubleStarExpressionImpl(ASTNode astNode) {
super(astNode);
}

View File

@@ -3,12 +3,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyDoubleStarPattern;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyDoubleStarPatternImpl extends PyElementImpl implements PyDoubleStarPattern {
public class PyDoubleStarPatternImpl extends PyElementImpl implements PyDoubleStarPattern, PyInstantTypeProvider {
public PyDoubleStarPatternImpl(ASTNode astNode) {
super(astNode);
}

View File

@@ -3,12 +3,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyEmptyExpression;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
public class PyEmptyExpressionImpl extends PyElementImpl implements PyEmptyExpression {
public class PyEmptyExpressionImpl extends PyElementImpl implements PyEmptyExpression, PyInstantTypeProvider {
public PyEmptyExpressionImpl(ASTNode astNode) {
super(astNode);
}

View File

@@ -2,6 +2,7 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyKeyValuePattern;
import com.jetbrains.python.psi.PyPattern;
import com.jetbrains.python.psi.types.PyTupleType;
@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public class PyKeyValuePatternImpl extends PyElementImpl implements PyKeyValuePattern {
public class PyKeyValuePatternImpl extends PyElementImpl implements PyKeyValuePattern, PyInstantTypeProvider {
public PyKeyValuePatternImpl(ASTNode astNode) {
super(astNode);
}

View File

@@ -17,6 +17,7 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyNoneLiteralExpression;
import com.jetbrains.python.psi.types.PyNoneType;
import com.jetbrains.python.psi.types.PyType;
@@ -25,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyNoneLiteralExpressionImpl extends PyElementImpl implements PyNoneLiteralExpression {
public class PyNoneLiteralExpressionImpl extends PyElementImpl implements PyNoneLiteralExpression, PyInstantTypeProvider {
public PyNoneLiteralExpressionImpl(ASTNode astNode) {
super(astNode);
}

View File

@@ -19,6 +19,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.psi.tree.IElementType;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyNumericLiteralExpression;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -26,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyNumericLiteralExpressionImpl extends PyElementImpl implements PyNumericLiteralExpression {
public class PyNumericLiteralExpressionImpl extends PyElementImpl implements PyNumericLiteralExpression, PyInstantTypeProvider {
public PyNumericLiteralExpressionImpl(@NotNull ASTNode astNode) {
super(astNode);

View File

@@ -3,13 +3,14 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyReprExpression;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
public class PyReprExpressionImpl extends PyElementImpl implements PyReprExpression {
public class PyReprExpressionImpl extends PyElementImpl implements PyReprExpression, PyInstantTypeProvider {
public PyReprExpressionImpl(ASTNode astNode) {
super(astNode);
}

View File

@@ -9,7 +9,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
public class PySingleStarPatternImpl extends PyElementImpl implements PySingleStarPattern {
public class PySingleStarPatternImpl extends PyElementImpl implements PySingleStarPattern, PyInstantTypeProvider {
public PySingleStarPatternImpl(ASTNode astNode) {
super(astNode);
}

View File

@@ -2,13 +2,14 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyStarArgument;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
public class PyStarArgumentImpl extends PyElementImpl implements PyStarArgument {
public class PyStarArgumentImpl extends PyElementImpl implements PyStarArgument, PyInstantTypeProvider {
public PyStarArgumentImpl(ASTNode astNode) {
super(astNode);
}

View File

@@ -3,12 +3,13 @@ package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.psi.PyElementVisitor;
import com.jetbrains.python.psi.PyInstantTypeProvider;
import com.jetbrains.python.psi.PyStarExpression;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
public class PyStarExpressionImpl extends PyElementImpl implements PyStarExpression {
public class PyStarExpressionImpl extends PyElementImpl implements PyStarExpression, PyInstantTypeProvider {
public PyStarExpressionImpl(ASTNode astNode) {
super(astNode);
}