PY-79967 Simplify Template type inference for t-strings

GitOrigin-RevId: 2964402eac2061e0230e612badc790d0d289f469
This commit is contained in:
Daniil Kalinin
2025-04-23 08:21:26 +02:00
committed by intellij-monorepo-bot
parent 2647731608
commit 5e12117835
2 changed files with 21 additions and 32 deletions

View File

@@ -99,6 +99,8 @@ public final @NonNls class PyNames {
public static final String FUTURE_MODULE = "__future__";
public static final String UNICODE_LITERALS = "unicode_literals";
public static final String TEMPLATELIB_TEMPLATE = "string.templatelib.Template";
public static final String CLASSMETHOD = "classmethod";
public static final String STATICMETHOD = "staticmethod";
public static final String OVERLOAD = "overload";

View File

@@ -6,25 +6,20 @@ import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.ContributedReferenceHost;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLiteralValue;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceService.Hints;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.lexer.PythonHighlightingLexer;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.PyResolveImportUtil;
import com.jetbrains.python.psi.types.PyClassLikeType;
import com.jetbrains.python.psi.types.PyClassType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -34,7 +29,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
import java.util.Objects;
public class PyStringLiteralExpressionImpl extends PyElementImpl implements PyStringLiteralExpression, PsiLiteralValue, ContributedReferenceHost {
@@ -121,33 +115,17 @@ public class PyStringLiteralExpressionImpl extends PyElementImpl implements PySt
if (firstNode != null) {
if (firstNode.getElementType() == PyElementTypes.FSTRING_NODE) {
String prefix = PyStringLiteralCoreUtil.getPrefix(firstNode.getText());
if (StringUtil.containsIgnoreCase(prefix, "t")) {
// For t-strings, return the string.templatelib.Template type
if (!context.maySwitchToAST(this)) {
return builtinCache.getStrType();
if (PyStringLiteralUtil.isTemplatePrefix(prefix)) {
if (languageLevel.isOlderThan(LanguageLevel.PYTHON314)) {
return PyBuiltinCache.getInstance(this).getStrType();
}
final List<PsiElement> templateModules = PyResolveImportUtil.resolveQualifiedName(
QualifiedName.fromDottedString("string.templatelib"), // find a stub file
PyResolveImportUtil.fromFoothold(this)
);
if (templateModules.isEmpty()) {
return builtinCache.getStrType();
PyClassType templateClassType = getTemplateClassType();
if (templateClassType != null) {
return templateClassType;
}
final PsiElement templateModule = templateModules.get(0);
if (!(templateModule instanceof PyFile)) {
return builtinCache.getStrType();
}
final PyClass templateClassElement = PyUtil.as(((PyFile)templateModule).findExportedName("Template"), PyClass.class);
if (templateClassElement == null) {
return builtinCache.getStrType();
}
final PyClassType templateType = (PyClassType)templateClassElement.getType(context);
return templateType != null ? templateType.toInstance() : builtinCache.getStrType();
} else
// f-strings can't have "b" prefix, so they are always unicode
return builtinCache.getUnicodeType(languageLevel);
}
// f-strings can't have "b" prefix, so they are always unicode
return builtinCache.getUnicodeType(languageLevel);
}
else if (firstNode.getElementType() == PyTokenTypes.DOCSTRING) {
return builtinCache.getStrType();
@@ -168,6 +146,15 @@ public class PyStringLiteralExpressionImpl extends PyElementImpl implements PySt
return builtinCache.getStrType();
}
private @Nullable PyClassType getTemplateClassType() {
PyPsiFacade facade = PyPsiFacade.getInstance(getProject());
PyClass templateClass = facade.createClassByQName(PyNames.TEMPLATELIB_TEMPLATE, getContainingFile());
if (templateClass != null) {
return facade.createClassType(templateClass, false);
}
return null;
}
@Override
public final PsiReference @NotNull [] getReferences() {
return ReferenceProvidersRegistry.getReferencesFromProviders(this, Hints.NO_HINTS);