PY-34617 Remove if stubs

GitOrigin-RevId: 13f49394e92daca80af9c82ac9ac1a439a6ae1f5
This commit is contained in:
Petr
2024-08-12 09:37:32 +00:00
committed by intellij-monorepo-bot
parent 6efb57a0f7
commit a3608ebd22
47 changed files with 264 additions and 538 deletions
@@ -2,10 +2,7 @@
package com.jetbrains.python.ast;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.TokenType;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayFactory;
import com.intellij.util.ArrayUtil;
@@ -14,9 +11,9 @@ import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonDialectsTokenSetProvider;
import com.jetbrains.python.ast.impl.PyUtilCore;
import com.jetbrains.python.ast.controlFlow.AstScopeOwner;
import com.jetbrains.python.ast.docstring.DocStringUtilCore;
import com.jetbrains.python.ast.impl.PyUtilCore;
import com.jetbrains.python.psi.LanguageLevel;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -234,7 +231,7 @@ public interface PyAstFunction extends PsiNameIdentifierOwner, PyAstCompoundStat
@Override
@Nullable
default PyAstClass getContainingClass() {
final PsiElement parent = PsiTreeUtil.getParentOfType(this, AstScopeOwner.class);
final PsiElement parent = PsiTreeUtil.getParentOfType(this, StubBasedPsiElement.class);
if (parent instanceof PyAstClass) {
return (PyAstClass)parent;
}
@@ -26,6 +26,7 @@ import java.util.regex.Pattern;
/**
* Assorted utility methods for Python code insight.
*
* These methods don't depend on the Python runtime.
*
* @see PyPsiUtilsCore for utilities used in Python PSI API
@@ -98,13 +99,11 @@ public final class PyUtilCore {
public static boolean isTopLevel(@NotNull PsiElement element) {
if (element instanceof StubBasedPsiElement) {
final StubElement<?> stub = ((StubBasedPsiElement<?>)element).getStub();
final StubElement stub = ((StubBasedPsiElement<?>)element).getStub();
if (stub != null) {
for (StubElement<?> parentStub = stub.getParentStub(); parentStub != null; parentStub = parentStub.getParentStub()) {
PsiElement psi = parentStub.getPsi();
if (!(psi instanceof PyAstIfPart || psi instanceof PyAstElsePart)) {
return psi instanceof PsiFile;
}
final StubElement parentStub = stub.getParentStub();
if (parentStub != null) {
return parentStub.getPsi() instanceof PsiFile;
}
}
}
@@ -100,8 +100,8 @@ public interface PyElementTypes {
TokenSet STATEMENT_LISTS = TokenSet.create(STATEMENT_LIST);
// Parts
IElementType IF_PART_IF = Companion.getINSTANCE().getIfPartIf();
IElementType IF_PART_ELIF = Companion.getINSTANCE().getIfPartElif();
PyElementType IF_PART_IF = new PyElementType("IF_IF", Companion.getINSTANCE().getIfPartIfConstructor());
PyElementType IF_PART_ELIF = new PyElementType("IF_ELIF", Companion.getINSTANCE().getIfPartElifConstructor());
PyElementType FOR_PART = new PyElementType("FOR_PART", Companion.getINSTANCE().getForPartConstructor());
PyElementType WHILE_PART = new PyElementType("WHILE_PART", Companion.getINSTANCE().getWhilePartConstructor());
@@ -109,7 +109,7 @@ public interface PyElementTypes {
PyElementType TRY_PART = new PyElementType("TRY_PART", Companion.getINSTANCE().getTryPartConstructor());
PyElementType FINALLY_PART = new PyElementType("FINALLY_PART", Companion.getINSTANCE().getFinallyPartConstructor());
IElementType ELSE_PART = Companion.getINSTANCE().getElsePart();
PyElementType ELSE_PART = new PyElementType("ELSE_PART", Companion.getINSTANCE().getElsePartConstructor());
TokenSet PARTS = TokenSet.create(IF_PART_IF, IF_PART_ELIF, FOR_PART, WHILE_PART, TRY_PART, FINALLY_PART, ELSE_PART, EXCEPT_PART);
TokenSet ELIFS = TokenSet.create(IF_PART_ELIF);
@@ -31,9 +31,6 @@ abstract class PyElementTypesFacade {
abstract val typeParameter: IElementType
abstract val typeParameterList: IElementType
abstract val typeAliasStatement: IElementType
abstract val ifPartIf: IElementType
abstract val ifPartElif: IElementType
abstract val elsePart: IElementType
// reparseable elements
abstract val statementList: IElementType
@@ -97,10 +94,13 @@ abstract class PyElementTypesFacade {
abstract val setLiteralExpressionConstructor: Function<in ASTNode, out PsiElement>
abstract val setCompExpressionConstructor: Function<in ASTNode, out PsiElement>
abstract val dictCompExpressionConstructor: Function<in ASTNode, out PsiElement>
abstract val ifPartIfConstructor: Function<in ASTNode, out PsiElement>
abstract val ifPartElifConstructor: Function<in ASTNode, out PsiElement>
abstract val forPartConstructor: Function<in ASTNode, out PsiElement>
abstract val whilePartConstructor: Function<in ASTNode, out PsiElement>
abstract val tryPartConstructor: Function<in ASTNode, out PsiElement>
abstract val finallyPartConstructor: Function<in ASTNode, out PsiElement>
abstract val elsePartConstructor: Function<in ASTNode, out PsiElement>
abstract val fStringNodeConstructor: Function<in ASTNode, out PsiElement>
abstract val fStringFragmentConstructor: Function<in ASTNode, out PsiElement>
abstract val fStringFragmentFormatPartConstructor: Function<in ASTNode, out PsiElement>
@@ -15,12 +15,10 @@
*/
package com.jetbrains.python.psi;
import com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.ast.PyAstElsePart;
import com.jetbrains.python.psi.stubs.PyElsePartStub;
/**
* The 'else:' part of various compound statements.
*/
public interface PyElsePart extends PyAstElsePart, PyStatementPart, StubBasedPsiElement<PyElsePartStub> {
public interface PyElsePart extends PyAstElsePart, PyStatementPart {
}
@@ -1,9 +1,7 @@
// Copyright 2000-2024 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 com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.ast.PyAstIfPartElif;
import com.jetbrains.python.psi.stubs.PyIfPartElifStub;
public interface PyIfPartElif extends PyAstIfPartElif, PyIfPart, StubBasedPsiElement<PyIfPartElifStub> {
public interface PyIfPartElif extends PyAstIfPartElif, PyIfPart {
}
@@ -1,9 +1,7 @@
// Copyright 2000-2024 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 com.intellij.psi.StubBasedPsiElement;
import com.jetbrains.python.ast.PyAstIfPartIf;
import com.jetbrains.python.psi.stubs.PyIfPartIfStub;
public interface PyIfPartIf extends PyAstIfPartIf, PyIfPart, StubBasedPsiElement<PyIfPartIfStub> {
public interface PyIfPartIf extends PyAstIfPartIf, PyIfPart {
}
@@ -11,20 +11,14 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.stubs.PyElsePartStub;
import com.jetbrains.python.psi.stubs.PyIfPartElifStub;
import com.jetbrains.python.psi.stubs.PyIfPartIfStub;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -632,59 +626,4 @@ public final class PyPsiUtils {
while (next != null);
return null;
}
/**
* @see <a href="https://typing.readthedocs.io/en/latest/source/stubs.html#version-and-platform-checks">Version and Platform Checks</a>
*/
@ApiStatus.Internal
@Nullable
public static StubElement<?> getParentStubSkippingVersionChecks(@Nullable StubElement<?> stub) {
if (stub != null) {
for (StubElement<?> e = stub.getParentStub(); e != null; e = e.getParentStub()) {
boolean isVersionCheck = e instanceof PyIfPartIfStub || e instanceof PyIfPartElifStub || e instanceof PyElsePartStub;
if (!isVersionCheck) {
return e;
}
}
}
return null;
}
/**
* @see <a href="https://typing.readthedocs.io/en/latest/source/stubs.html#version-and-platform-checks">Version and Platform Checks</a>
*/
@ApiStatus.Internal
public static boolean processChildrenStubs(@NotNull StubElement<?> stub,
@NotNull LanguageLevel languageLevel,
@NotNull Processor<? super StubElement<?>> processor) {
boolean recurse = false;
for (StubElement<?> child : stub.getChildrenStubs()) {
if (child instanceof PyIfPartIfStub ifStub) {
if (ifStub.getVersionCheck().matches(languageLevel)) {
recurse = false;
if (!processChildrenStubs(child, languageLevel, processor)) return false;
}
else {
recurse = true;
}
}
else if (child instanceof PyIfPartElifStub elifStub) {
if (recurse && elifStub.getVersionCheck().matches(languageLevel)) {
recurse = false;
if (!processChildrenStubs(child, languageLevel, processor)) return false;
}
}
else if (child instanceof PyElsePartStub) {
if (recurse) {
recurse = false;
if (!processChildrenStubs(child, languageLevel, processor)) return false;
}
}
else {
recurse = false;
if (!processor.process(child)) return false;
}
}
return true;
}
}
@@ -13,7 +13,7 @@ import java.math.BigInteger
@ApiStatus.Internal
data class PyVersionCheck(val version: Version, val isLessThan: Boolean) {
fun matches(languageLevel: LanguageLevel): Boolean {
return isLessThan == version.compareTo(languageLevel.majorVersion, languageLevel.minorVersion) > 0
return isLessThan == languageLevel.isLessThan(version)
}
companion object {
@@ -79,3 +79,7 @@ data class PyVersionCheck(val version: Version, val isLessThan: Boolean) {
}
}
}
fun LanguageLevel.isLessThan(version: Version): Boolean {
return version.compareTo(majorVersion, minorVersion) > 0
}
@@ -29,7 +29,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
public interface PyClassStub extends NamedStub<PyClass> {
public interface PyClassStub extends NamedStub<PyClass>, PyVersionSpecificStub {
/**
* @return a {@code Map} which contains imported class names as keys and their original names as values.
@@ -1,8 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.psi.stubs;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.PyElsePart;
public interface PyElsePartStub extends StubElement<PyElsePart> {
}
@@ -4,7 +4,7 @@ package com.jetbrains.python.psi.stubs;
import com.intellij.psi.stubs.NamedStub;
import com.jetbrains.python.psi.PyFunction;
public interface PyFunctionStub extends NamedStub<PyFunction>, PyAnnotationOwnerStub, PyTypeCommentOwnerStub {
public interface PyFunctionStub extends NamedStub<PyFunction>, PyAnnotationOwnerStub, PyTypeCommentOwnerStub, PyVersionSpecificStub {
String getDocString();
String getDeprecationMessage();
boolean isAsync();
@@ -1,10 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.psi.stubs;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.impl.PyVersionCheck;
import com.jetbrains.python.psi.PyIfPartElif;
public interface PyIfPartElifStub extends StubElement<PyIfPartElif> {
PyVersionCheck getVersionCheck();
}
@@ -1,10 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.psi.stubs;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.impl.PyVersionCheck;
import com.jetbrains.python.psi.PyIfPartIf;
public interface PyIfPartIfStub extends StubElement<PyIfPartIf> {
PyVersionCheck getVersionCheck();
}
@@ -8,7 +8,8 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
public interface PyTargetExpressionStub extends NamedStub<PyTargetExpression>, PyTypeCommentOwnerStub, PyAnnotationOwnerStub {
public interface PyTargetExpressionStub
extends NamedStub<PyTargetExpression>, PyTypeCommentOwnerStub, PyAnnotationOwnerStub, PyVersionSpecificStub {
enum InitializerType {
ReferenceExpression(1),
CallExpression(2),
@@ -5,7 +5,7 @@ import com.intellij.psi.stubs.NamedStub;
import com.jetbrains.python.psi.PyTypeAliasStatement;
import org.jetbrains.annotations.Nullable;
public interface PyTypeAliasStatementStub extends NamedStub<PyTypeAliasStatement> {
public interface PyTypeAliasStatementStub extends NamedStub<PyTypeAliasStatement>, PyVersionSpecificStub {
@Nullable
String getTypeExpressionText();
@@ -0,0 +1,10 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.python.psi.stubs
import com.intellij.openapi.util.Version
interface PyVersionSpecificStub {
val versionRange: PyVersionRange
}
class PyVersionRange(val lowInclusive: Version?, val highExclusive: Version?)
@@ -4,7 +4,6 @@ package com.jetbrains.python
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.tree.IElementType
import com.intellij.psi.tree.IReparseableElementType
import com.jetbrains.python.psi.impl.*
import java.util.function.Function
@@ -52,12 +51,6 @@ class PyElementTypesFacadeImpl : PyElementTypesFacade() {
get() = PyStubElementTypes.TYPE_PARAMETER_LIST
override val typeAliasStatement: IStubElementType<*, *>
get() = PyStubElementTypes.TYPE_ALIAS_STATEMENT
override val ifPartIf: IElementType
get() = PyStubElementTypes.IF_PART_IF
override val ifPartElif: IElementType
get() = PyStubElementTypes.IF_PART_ELIF
override val elsePart: IElementType
get() = PyStubElementTypes.ELSE_PART
override val statementList: IReparseableElementType
get() = PyStatementListElementType()
@@ -177,6 +170,10 @@ class PyElementTypesFacadeImpl : PyElementTypesFacade() {
get() = F { node -> PySetCompExpressionImpl(node) }
override val dictCompExpressionConstructor: F
get() = F { node -> PyDictCompExpressionImpl(node) }
override val ifPartIfConstructor: F
get() = F { node -> PyIfPartIfImpl(node) }
override val ifPartElifConstructor: F
get() = F { node -> PyIfPartElifImpl(node) }
override val forPartConstructor: F
get() = F { node -> PyForPartImpl(node) }
override val whilePartConstructor: F
@@ -185,6 +182,8 @@ class PyElementTypesFacadeImpl : PyElementTypesFacade() {
get() = F { node -> PyTryPartImpl(node) }
override val finallyPartConstructor: F
get() = F { node -> PyFinallyPartImpl(node) }
override val elsePartConstructor: F
get() = F { node -> PyElsePartImpl(node) }
override val fStringNodeConstructor: F
get() = F { node -> PyFormattedStringElementImpl(node) }
override val fStringFragmentConstructor: F
@@ -33,8 +33,4 @@ public interface PyStubElementTypes {
PyStubElementType<PyTypeParameterStub, PyTypeParameter> TYPE_PARAMETER = new PyTypeParameterElementType();
PyStubElementType<PyTypeParameterListStub, PyTypeParameterList> TYPE_PARAMETER_LIST = new PyTypeParameterListElementType();
PyStubElementType<PyTypeAliasStatementStub, PyTypeAliasStatement> TYPE_ALIAS_STATEMENT = new PyTypeAliasStatementElementType();
PyStubElementType<PyIfPartIfStub, PyIfPartIf> IF_PART_IF = new PyIfPartIfElementType();
PyStubElementType<PyIfPartElifStub, PyIfPartElif> IF_PART_ELIF = new PyIfPartElifElementType();
PyStubElementType<PyElsePartStub, PyElsePart> ELSE_PART = new PyElsePartElementType();
}
@@ -60,7 +60,7 @@ public class PyFileElementType extends IStubFileElementType<PyFileStub> {
@Override
public int getStubVersion() {
// Don't forget to update versions of indexes that use the updated stub-based elements
return 90;
return 91;
}
@Nullable
@@ -37,6 +37,7 @@ import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.stubs.PyClassElementType;
import com.jetbrains.python.psi.impl.stubs.PyVersionSpecificStubBaseKt;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.resolve.PyResolveUtil;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
@@ -642,9 +643,8 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
final Property decoratedProperty = processDecoratedProperties(filter);
if (decoratedProperty != null) return decoratedProperty;
PyClassStub stub = getStub();
if (stub != null) {
return processStubProperties(stub, filter);
if (getStub() != null) {
return processStubProperties(filter);
}
else {
// name = property(...) assignments from PSI
@@ -722,12 +722,11 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
}
@Nullable
private Property processStubProperties(@NotNull PyClassStub stub, @Nullable Processor<? super Property> filter) {
class StubPropertiesProcessor implements Processor<StubElement<?>> {
private @Nullable Property myResult;
@Override
public boolean process(StubElement<?> subStub) {
private Property processStubProperties(@Nullable Processor<? super Property> filter) {
final PyClassStub stub = getStub();
if (stub != null) {
LanguageLevel languageLevel = PyiUtil.getOriginalLanguageLevel(this);
for (StubElement<?> subStub : PyVersionSpecificStubBaseKt.getChildrenStubs(stub, languageLevel)) {
if (subStub.getStubType() == PyElementTypes.TARGET_EXPRESSION) {
final PyTargetExpressionStub targetStub = (PyTargetExpressionStub)subStub;
final PropertyStubStorage prop = targetStub.getCustomStub(PropertyStubStorage.class);
@@ -738,19 +737,13 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
final String doc = prop.getDoc();
if (getter != NONE || setter != NONE || deleter != NONE) {
final PropertyImpl property = new PropertyImpl(targetStub.getName(), getter, setter, deleter, doc, targetStub.getPsi());
if (filter == null || filter.process(property)) {
myResult = property;
return false;
}
if (filter == null || filter.process(property)) return property;
}
}
}
return true;
}
}
StubPropertiesProcessor processor = new StubPropertiesProcessor();
PyPsiUtils.processChildrenStubs(stub, PyiUtil.getOriginalLanguageLevel(this), processor);
return processor.myResult;
return null;
}
@Nullable
@@ -1023,16 +1016,15 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
@Override
public List<PyTargetExpression> getClassAttributes() {
final List<PyTargetExpression> result = new ArrayList<>();
LanguageLevel languageLevel = PyiUtil.getOriginalLanguageLevel(this);
final ArrayList<PyTargetExpression> result = new ArrayList<>();
PyClassStub stub = getStub();
if (stub != null) {
PyPsiUtils.processChildrenStubs(stub, languageLevel, child -> {
if (child.getStubType() == PyElementTypes.TARGET_EXPRESSION) {
result.add((PyTargetExpression)child.getPsi());
for (StubElement<?> element : PyVersionSpecificStubBaseKt.getChildrenStubs(stub, languageLevel)) {
if (element.getStubType() == PyElementTypes.TARGET_EXPRESSION) {
result.add((PyTargetExpression)element.getPsi());
}
return true;
});
}
}
else {
getStatementList().acceptChildren(new PyVersionAwareTopLevelElementVisitor(languageLevel) {
@@ -1055,7 +1047,6 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
}
});
}
result.trimToSize();
return result;
}
@@ -1254,8 +1245,10 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
final PyClassStub stub = getStub();
if (stub != null) {
LanguageLevel languageLevel = PyiUtil.getOriginalLanguageLevel(this);
if (!PyPsiUtils.processChildrenStubs(stub, languageLevel, child -> processor.execute(child.getPsi(), ResolveState.initial()))) {
return false;
for (StubElement<?> child : PyVersionSpecificStubBaseKt.getChildrenStubs(stub, languageLevel)) {
if (!processor.execute(child.getPsi(), ResolveState.initial())) {
return false;
}
}
}
else {
@@ -2,22 +2,14 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.PyConditionalStatementPart;
import com.jetbrains.python.psi.PyElementVisitor;
public abstract class PyConditionalStatementPartImpl<T extends StubElement<? extends PsiElement>> extends PyBaseElementImpl<T>
implements PyConditionalStatementPart {
public abstract class PyConditionalStatementPartImpl extends PyElementImpl implements PyConditionalStatementPart {
public PyConditionalStatementPartImpl(ASTNode astNode) {
super(astNode);
}
protected PyConditionalStatementPartImpl(T stub, IStubElementType<?, ?> elementType) {
super(stub, elementType);
}
@Override
protected void acceptPyVisitor(PyElementVisitor pyVisitor) {
pyVisitor.visitPyConditionalStatementPart(this);
@@ -16,16 +16,11 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.PyStubElementTypes;
import com.jetbrains.python.psi.PyElsePart;
import com.jetbrains.python.psi.stubs.PyElsePartStub;
public class PyElsePartImpl extends PyBaseElementImpl<PyElsePartStub> implements PyElsePart {
public class PyElsePartImpl extends PyElementImpl implements PyElsePart {
public PyElsePartImpl(ASTNode astNode) {
super(astNode);
}
public PyElsePartImpl(PyElsePartStub stub) {
super(stub, PyStubElementTypes.ELSE_PART);
}
}
@@ -33,6 +33,7 @@ import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.references.PyReferenceImpl;
import com.jetbrains.python.psi.impl.stubs.PyVersionSpecificStubBaseKt;
import com.jetbrains.python.psi.resolve.*;
import com.jetbrains.python.psi.stubs.PyFileStub;
import com.jetbrains.python.psi.types.PyModuleType;
@@ -852,26 +853,19 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
@NotNull
private <T extends PyElement> List<T> collectChildren(Class<T> type) {
return collectChildren(this, getGreenStub(), PyiUtil.getOriginalLanguageLevel(this), type);
}
@NotNull
private static <T extends PyElement> List<T> collectChildren(@NotNull PsiElement element,
@Nullable StubElement<?> stub,
@NotNull LanguageLevel languageLevel,
@NotNull Class<T> type) {
@Nullable StubElement<?> stub = getGreenStub();
@NotNull LanguageLevel languageLevel = PyiUtil.getOriginalLanguageLevel(this);
final List<T> result = new ArrayList<>();
if (stub != null) {
PyPsiUtils.processChildrenStubs(stub, languageLevel, child -> {
for (StubElement<?> child : PyVersionSpecificStubBaseKt.getChildrenStubs(stub, languageLevel)) {
PsiElement childPsi = child.getPsi();
if (type.isInstance(childPsi)) {
result.add(type.cast(childPsi));
}
return true;
});
}
}
else {
element.acceptChildren(new PyVersionAwareTopLevelElementVisitor(languageLevel) {
acceptChildren(new PyVersionAwareTopLevelElementVisitor(languageLevel) {
@Override
protected void checkAddElement(PsiElement node) {
if (type.isInstance(node)) {
@@ -898,10 +892,9 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
@NotNull LanguageLevel languageLevel) {
List<PsiElement> result = new ArrayList<>();
if (stub != null) {
PyPsiUtils.processChildrenStubs(stub, languageLevel, child -> {
for (StubElement<?> child : PyVersionSpecificStubBaseKt.getChildrenStubs(stub, languageLevel)) {
result.add(child.getPsi());
return true;
});
}
}
else {
element.acceptChildren(new PyVersionAwareTopLevelElementVisitor(languageLevel) {
@@ -29,7 +29,10 @@ import com.jetbrains.python.documentation.docstrings.DocStringUtil;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.icons.PythonPsiApiIcons;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import com.jetbrains.python.psi.stubs.*;
import com.jetbrains.python.psi.stubs.PyAnnotationOwnerStub;
import com.jetbrains.python.psi.stubs.PyClassStub;
import com.jetbrains.python.psi.stubs.PyFunctionStub;
import com.jetbrains.python.psi.stubs.PyTargetExpressionStub;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.sdk.PythonSdkUtil;
import org.jetbrains.annotations.NotNull;
@@ -131,9 +134,9 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
public @Nullable PyClass getContainingClass() {
final PyFunctionStub stub = getStub();
if (stub != null) {
final StubElement<?> parentStub = PyPsiUtils.getParentStubSkippingVersionChecks(stub);
if (parentStub instanceof PyClassStub classStub) {
return classStub.getPsi();
final StubElement parentStub = stub.getParentStub();
if (parentStub instanceof PyClassStub) {
return ((PyClassStub)parentStub).getPsi();
}
return null;
@@ -2,19 +2,13 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.PyStubElementTypes;
import com.jetbrains.python.psi.PyIfPartElif;
import com.jetbrains.python.psi.stubs.PyIfPartElifStub;
/**
* PyIfPart that represents an 'elif' part.
*/
public class PyIfPartElifImpl extends PyConditionalStatementPartImpl<PyIfPartElifStub> implements PyIfPartElif {
public class PyIfPartElifImpl extends PyConditionalStatementPartImpl implements PyIfPartElif {
public PyIfPartElifImpl(ASTNode astNode) {
super(astNode);
}
public PyIfPartElifImpl(PyIfPartElifStub stub) {
super(stub, PyStubElementTypes.IF_PART_ELIF);
}
}
@@ -2,19 +2,15 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.jetbrains.python.PyStubElementTypes;
import com.jetbrains.python.psi.PyIfPartIf;
import com.jetbrains.python.psi.stubs.PyIfPartIfStub;
/**
* PyIfPart that represents an 'if' part.
*/
public class PyIfPartIfImpl extends PyConditionalStatementPartImpl<PyIfPartIfStub> implements PyIfPartIf {
public class PyIfPartIfImpl extends PyConditionalStatementPartImpl implements PyIfPartIf {
public PyIfPartIfImpl(ASTNode astNode) {
super(astNode);
}
public PyIfPartIfImpl(PyIfPartIfStub stub) {
super(stub, PyStubElementTypes.IF_PART_IF);
}
}
@@ -590,7 +590,7 @@ public class PyTargetExpressionImpl extends PyBaseElementImpl<PyTargetExpression
public PyClass getContainingClass() {
final PyTargetExpressionStub stub = getStub();
if (stub != null) {
final StubElement parentStub = PyPsiUtils.getParentStubSkippingVersionChecks(stub);
final StubElement parentStub = stub.getParentStub();
if (parentStub instanceof PyClassStub) {
return ((PyClassStub)parentStub).getPsi();
}
@@ -16,10 +16,9 @@
package com.jetbrains.python.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.PyWhilePart;
public class PyWhilePartImpl extends PyConditionalStatementPartImpl<StubElement<PyWhilePart>> implements PyWhilePart {
public class PyWhilePartImpl extends PyConditionalStatementPartImpl implements PyWhilePart {
public PyWhilePartImpl(ASTNode astNode) {
super(astNode);
}
@@ -55,6 +55,7 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
PyPsiUtils.strValue(psi.getDocStringExpression()),
psi.getDeprecationMessage(),
getStubElementType(),
PyVersionSpecificStubBaseKt.evaluateVersionRangeForElement(psi),
createCustomStub(psi));
}
@@ -135,6 +136,8 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
dataStream.writeUTFFast(docString != null ? docString : "");
dataStream.writeName(pyClassStub.getDeprecationMessage());
PyVersionSpecificStubBaseKt.serializeVersionRange(pyClassStub.getVersionRange(), dataStream);
serializeCustomStub(pyClassStub.getCustomStub(PyCustomClassStub.class), dataStream);
}
@@ -161,14 +164,16 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
final List<String> slots = PyFileElementType.readNullableList(dataStream);
final String docStringInStub = dataStream.readUTFFast();
final String docString = !docStringInStub.isEmpty() ? docStringInStub : null;
final String docString = StringUtil.nullize(docStringInStub);
final String deprecationMessage = dataStream.readNameString();
final PyVersionRange versionRange = PyVersionSpecificStubBaseKt.deserializeVersionRange(dataStream);
final PyCustomClassStub customStub = deserializeCustomStub(dataStream);
return new PyClassStubImpl(name, parentStub, superClasses, baseClassesText, metaClass, slots, docString, deprecationMessage,
getStubElementType(), customStub);
getStubElementType(), versionRange, customStub);
}
@Override
@@ -177,7 +182,7 @@ public class PyClassElementType extends PyStubElementType<PyClassStub, PyClass>
if (name != null) {
sink.occurrence(PyClassNameIndex.KEY, name);
sink.occurrence(PyClassNameIndexInsensitive.KEY, StringUtil.toLowerCase(name));
if (PyPsiUtils.getParentStubSkippingVersionChecks(stub) instanceof PyFileStub && PyUtil.getInitialUnderscores(name) == 0) {
if (stub.getParentStub() instanceof PyFileStub && PyUtil.getInitialUnderscores(name) == 0) {
sink.occurrence(PyExportedModuleAttributeIndex.KEY, name);
}
}
@@ -2,19 +2,19 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.ObjectUtils;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.stubs.PyClassStub;
import com.jetbrains.python.psi.stubs.PyVersionRange;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
public class PyClassStubImpl extends PyVersionSpecificStubBase<PyClass> implements PyClassStub {
@Nullable
private final String myName;
@@ -49,8 +49,9 @@ public class PyClassStubImpl extends StubBase<PyClass> implements PyClassStub {
@Nullable String docString,
@Nullable String deprecationMessage,
@NotNull IStubElementType stubElementType,
@NotNull PyVersionRange versionRange,
@Nullable PyCustomClassStub customStub) {
super(parentStub, stubElementType);
super(parentStub, stubElementType, versionRange);
myName = name;
mySuperClasses = superClasses;
mySuperClassesText = superClassesText;
@@ -1,41 +0,0 @@
package com.jetbrains.python.psi.impl.stubs
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.stubs.StubInputStream
import com.intellij.psi.stubs.StubOutputStream
import com.jetbrains.python.psi.impl.PyVersionCheck
import com.jetbrains.python.psi.PyElsePart
import com.jetbrains.python.psi.PyIfStatement
import com.jetbrains.python.psi.PyStubElementType
import com.jetbrains.python.psi.impl.PyElsePartImpl
import com.jetbrains.python.psi.stubs.PyElsePartStub
class PyElsePartElementType : PyStubElementType<PyElsePartStub, PyElsePart>("ELSE_PART") {
override fun createPsi(stub: PyElsePartStub): PyElsePart {
return PyElsePartImpl(stub)
}
override fun createStub(psi: PyElsePart, parentStub: StubElement<out PsiElement>): PyElsePartStub {
return PyElsePartStubImpl(parentStub)
}
override fun serialize(stub: PyElsePartStub, dataStream: StubOutputStream) {
}
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): PyElsePartStub {
return PyElsePartStubImpl(parentStub)
}
override fun createElement(node: ASTNode): PsiElement {
return PyElsePartImpl(node)
}
override fun shouldCreateStub(node: ASTNode): Boolean {
val ifStatement = node.treeParent?.psi as? PyIfStatement ?: return false
if (!isFileOrClassTopLevel(ifStatement)) return false
val ifParts = sequenceOf(ifStatement.ifPart) + ifStatement.elifParts.asSequence()
return ifParts.all { PyVersionCheck.fromCondition(it) != null }
}
}
@@ -1,9 +0,0 @@
package com.jetbrains.python.psi.impl.stubs
import com.intellij.psi.stubs.StubBase
import com.intellij.psi.stubs.StubElement
import com.jetbrains.python.PyStubElementTypes
import com.jetbrains.python.psi.PyElsePart
import com.jetbrains.python.psi.stubs.PyElsePartStub
class PyElsePartStubImpl(parent: StubElement<*>) : StubBase<PyElsePart>(parent, PyStubElementTypes.ELSE_PART), PyElsePartStub
@@ -26,10 +26,7 @@ import com.jetbrains.python.psi.PyStubElementType;
import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.impl.PyFunctionImpl;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.stubs.PyExportedModuleAttributeIndex;
import com.jetbrains.python.psi.stubs.PyFileStub;
import com.jetbrains.python.psi.stubs.PyFunctionNameIndex;
import com.jetbrains.python.psi.stubs.PyFunctionStub;
import com.jetbrains.python.psi.stubs.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -63,6 +60,7 @@ public class PyFunctionElementType extends PyStubElementType<PyFunctionStub, PyF
final PyStringLiteralExpression docStringExpression = function.getDocStringExpression();
final String typeComment = function.getTypeCommentAnnotation();
final String annotationContent = function.getAnnotationValue();
final PyVersionRange versionRange = PyVersionSpecificStubBaseKt.evaluateVersionRangeForElement(psi);
return new PyFunctionStubImpl(psi.getName(),
PyPsiUtils.strValue(docStringExpression),
message,
@@ -72,7 +70,8 @@ public class PyFunctionElementType extends PyStubElementType<PyFunctionStub, PyF
typeComment,
annotationContent,
parentStub,
getStubElementType());
getStubElementType(),
versionRange);
}
@Override
@@ -85,6 +84,7 @@ public class PyFunctionElementType extends PyStubElementType<PyFunctionStub, PyF
dataStream.writeBoolean(stub.onlyRaisesNotImplementedError());
dataStream.writeName(stub.getTypeComment());
dataStream.writeName(stub.getAnnotation());
PyVersionSpecificStubBaseKt.serializeVersionRange(stub.getVersionRange(), dataStream);
}
@Override
@@ -98,6 +98,7 @@ public class PyFunctionElementType extends PyStubElementType<PyFunctionStub, PyF
final boolean onlyRaisesNotImplementedError = dataStream.readBoolean();
String typeComment = dataStream.readNameString();
String annotationContent = dataStream.readNameString();
PyVersionRange versionRange = PyVersionSpecificStubBaseKt.deserializeVersionRange(dataStream);
return new PyFunctionStubImpl(name,
StringUtil.nullize(docString),
deprecationMessage,
@@ -107,7 +108,8 @@ public class PyFunctionElementType extends PyStubElementType<PyFunctionStub, PyF
typeComment,
annotationContent,
parentStub,
getStubElementType());
getStubElementType(),
versionRange);
}
@Override
@@ -115,7 +117,7 @@ public class PyFunctionElementType extends PyStubElementType<PyFunctionStub, PyF
final String name = stub.getName();
if (name != null) {
sink.occurrence(PyFunctionNameIndex.KEY, name);
if (PyPsiUtils.getParentStubSkippingVersionChecks(stub) instanceof PyFileStub && PyUtil.getInitialUnderscores(name) == 0) {
if (stub.getParentStub() instanceof PyFileStub && PyUtil.getInitialUnderscores(name) == 0) {
sink.occurrence(PyExportedModuleAttributeIndex.KEY, name);
}
}
@@ -2,14 +2,14 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.stubs.PyFunctionStub;
import com.jetbrains.python.psi.stubs.PyVersionRange;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyFunctionStubImpl extends StubBase<PyFunction> implements PyFunctionStub {
public class PyFunctionStubImpl extends PyVersionSpecificStubBase<PyFunction> implements PyFunctionStub {
private final String myName;
private final String myDocString;
private final String myDeprecationMessage;
@@ -28,8 +28,9 @@ public class PyFunctionStubImpl extends StubBase<PyFunction> implements PyFuncti
@Nullable String typeCommentContent,
@Nullable String annotation,
final StubElement parent,
@NotNull IStubElementType stubElementType) {
super(parent, stubElementType);
@NotNull IStubElementType stubElementType,
@NotNull PyVersionRange versionRange) {
super(parent, stubElementType, versionRange);
myName = name;
myDocString = docString;
myDeprecationMessage = deprecationMessage;
@@ -1,44 +0,0 @@
package com.jetbrains.python.psi.impl.stubs
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.stubs.StubInputStream
import com.intellij.psi.stubs.StubOutputStream
import com.intellij.util.takeWhileInclusive
import com.jetbrains.python.psi.impl.PyVersionCheck
import com.jetbrains.python.psi.PyIfPartElif
import com.jetbrains.python.psi.PyIfStatement
import com.jetbrains.python.psi.PyStubElementType
import com.jetbrains.python.psi.impl.PyIfPartElifImpl
import com.jetbrains.python.psi.stubs.PyIfPartElifStub
class PyIfPartElifElementType : PyStubElementType<PyIfPartElifStub, PyIfPartElif>("IF_PART_ELIF") {
override fun createPsi(stub: PyIfPartElifStub): PyIfPartElif {
return PyIfPartElifImpl(stub)
}
override fun createStub(psi: PyIfPartElif, parentStub: StubElement<out PsiElement>): PyIfPartElifStub {
return PyIfPartElifStubImpl(parentStub, requireNotNull(PyVersionCheck.fromCondition (psi)))
}
override fun serialize(stub: PyIfPartElifStub, dataStream: StubOutputStream) {
serializeVersionCheck(stub.versionCheck, dataStream)
}
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): PyIfPartElifStub {
return PyIfPartElifStubImpl(parentStub, deserializeVersionCheck(dataStream))
}
override fun createElement(node: ASTNode): PsiElement {
return PyIfPartElifImpl(node)
}
override fun shouldCreateStub(node: ASTNode): Boolean {
val ifStatement = node.treeParent?.psi as? PyIfStatement ?: return false
if (!isFileOrClassTopLevel(ifStatement)) return false
return (sequenceOf(ifStatement.ifPart) + ifStatement.elifParts.asSequence())
.takeWhileInclusive { it !== node.psi }
.all { PyVersionCheck.fromCondition(it) != null }
}
}
@@ -1,13 +0,0 @@
package com.jetbrains.python.psi.impl.stubs
import com.intellij.psi.stubs.StubBase
import com.intellij.psi.stubs.StubElement
import com.jetbrains.python.PyStubElementTypes
import com.jetbrains.python.psi.impl.PyVersionCheck
import com.jetbrains.python.psi.PyIfPartElif
import com.jetbrains.python.psi.stubs.PyIfPartElifStub
class PyIfPartElifStubImpl(parent: StubElement<*>, private val versionCheck: PyVersionCheck)
: StubBase<PyIfPartElif>(parent, PyStubElementTypes.IF_PART_ELIF), PyIfPartElifStub {
override fun getVersionCheck(): PyVersionCheck = versionCheck
}
@@ -1,38 +0,0 @@
package com.jetbrains.python.psi.impl.stubs
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.stubs.StubInputStream
import com.intellij.psi.stubs.StubOutputStream
import com.jetbrains.python.psi.impl.PyVersionCheck
import com.jetbrains.python.psi.*
import com.jetbrains.python.psi.impl.PyIfPartIfImpl
import com.jetbrains.python.psi.stubs.PyIfPartIfStub
class PyIfPartIfElementType : PyStubElementType<PyIfPartIfStub, PyIfPartIf>("IF_PART_IF") {
override fun createPsi(stub: PyIfPartIfStub): PyIfPartIf {
return PyIfPartIfImpl(stub)
}
override fun createStub(psi: PyIfPartIf, parentStub: StubElement<out PsiElement>): PyIfPartIfStub {
return PyIfPartIfStubImpl(parentStub, requireNotNull(PyVersionCheck.fromCondition (psi)))
}
override fun serialize(stub: PyIfPartIfStub, dataStream: StubOutputStream) {
serializeVersionCheck(stub.versionCheck, dataStream)
}
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): PyIfPartIfStub {
return PyIfPartIfStubImpl(parentStub, deserializeVersionCheck(dataStream))
}
override fun createElement(node: ASTNode): PsiElement {
return PyIfPartIfImpl(node)
}
override fun shouldCreateStub(node: ASTNode): Boolean {
val psi = node.psi as PyIfPartIf
return isFileOrClassTopLevel(psi) && PyVersionCheck.fromCondition(psi) != null
}
}
@@ -1,13 +0,0 @@
package com.jetbrains.python.psi.impl.stubs
import com.intellij.psi.stubs.StubBase
import com.intellij.psi.stubs.StubElement
import com.jetbrains.python.PyStubElementTypes
import com.jetbrains.python.psi.impl.PyVersionCheck
import com.jetbrains.python.psi.PyIfPartIf
import com.jetbrains.python.psi.stubs.PyIfPartIfStub
class PyIfPartIfStubImpl(parent: StubElement<*>, private val versionCheck: PyVersionCheck)
: StubBase<PyIfPartIf>(parent, PyStubElementTypes.IF_PART_IF), PyIfPartIfStub {
override fun getVersionCheck(): PyVersionCheck = versionCheck
}
@@ -1,29 +0,0 @@
package com.jetbrains.python.psi.impl.stubs
import com.intellij.openapi.util.Version
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.StubInputStream
import com.intellij.psi.stubs.StubOutputStream
import com.intellij.psi.util.PsiTreeUtil
import com.jetbrains.python.psi.impl.PyVersionCheck
import com.jetbrains.python.psi.PyClass
import com.jetbrains.python.psi.PyFile
import com.jetbrains.python.psi.PyFunction
internal fun isFileOrClassTopLevel(element: PsiElement): Boolean {
val parent = PsiTreeUtil.getParentOfType(element, PyFile::class.java, PyClass::class.java, PyFunction::class.java)
return parent is PyFile || parent is PyClass
}
internal fun serializeVersionCheck(versionCheck: PyVersionCheck, dataStream: StubOutputStream) {
dataStream.writeBoolean(versionCheck.isLessThan)
dataStream.writeVarInt(versionCheck.version.major)
dataStream.writeVarInt(versionCheck.version.minor)
}
internal fun deserializeVersionCheck(dataStream: StubInputStream): PyVersionCheck {
val isLessThan = dataStream.readBoolean()
val major = dataStream.readVarInt()
val minor = dataStream.readVarInt()
return PyVersionCheck(Version(major, minor, 0), isLessThan)
}
@@ -15,12 +15,8 @@ import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PythonDialectsTokenSetProvider;
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.impl.PyTargetExpressionImpl;
import com.jetbrains.python.psi.stubs.PyExportedModuleAttributeIndex;
import com.jetbrains.python.psi.stubs.PyFileStub;
import com.jetbrains.python.psi.stubs.PyTargetExpressionStub;
import com.jetbrains.python.psi.stubs.PyVariableNameIndex;
import com.jetbrains.python.psi.stubs.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -59,10 +55,12 @@ public class PyTargetExpressionElementType extends PyStubElementType<PyTargetExp
final String docString = DocStringUtil.getDocStringValue(psi);
final String typeComment = psi.getTypeCommentAnnotation();
final String annotation = psi.getAnnotationValue();
final PyVersionRange versionRange = PyVersionSpecificStubBaseKt.evaluateVersionRangeForElement(psi);
CustomTargetExpressionStub customStub = createCustomStub(psi);
if (customStub != null) {
return new PyTargetExpressionStubImpl(name, docString, typeComment, annotation, psi.hasAssignedValue(), customStub, parentStub);
return new PyTargetExpressionStubImpl(name, docString, typeComment, annotation, psi.hasAssignedValue(), customStub, parentStub,
versionRange);
}
PyTargetExpressionStub.InitializerType initializerType = PyTargetExpressionStub.InitializerType.Other;
@@ -80,7 +78,7 @@ public class PyTargetExpressionElementType extends PyStubElementType<PyTargetExp
}
}
return new PyTargetExpressionStubImpl(name, docString, initializerType, initializer, psi.isQualified(), typeComment, annotation,
psi.hasAssignedValue(), parentStub);
psi.hasAssignedValue(), parentStub, versionRange);
}
@Override
@@ -92,6 +90,7 @@ public class PyTargetExpressionElementType extends PyStubElementType<PyTargetExp
stream.writeName(stub.getTypeComment());
stream.writeName(stub.getAnnotation());
stream.writeBoolean(stub.hasAssignedValue());
PyVersionSpecificStubBaseKt.serializeVersionRange(stub.getVersionRange(), stream);
final CustomTargetExpressionStub customStub = stub.getCustomStub(CustomTargetExpressionStub.class);
if (customStub != null) {
serializeCustomStub(customStub, stream);
@@ -114,14 +113,15 @@ public class PyTargetExpressionElementType extends PyStubElementType<PyTargetExp
String typeComment = stream.readNameString();
String annotation = stream.readNameString();
final boolean hasAssignedValue = stream.readBoolean();
PyVersionRange versionRange = PyVersionSpecificStubBaseKt.deserializeVersionRange(stream);
if (initializerType == PyTargetExpressionStub.InitializerType.Custom) {
CustomTargetExpressionStub stub = deserializeCustomStub(stream);
return new PyTargetExpressionStubImpl(name, docString, typeComment, annotation, hasAssignedValue, stub, parentStub);
return new PyTargetExpressionStubImpl(name, docString, typeComment, annotation, hasAssignedValue, stub, parentStub, versionRange);
}
QualifiedName initializer = QualifiedName.deserialize(stream);
boolean isQualified = stream.readBoolean();
return new PyTargetExpressionStubImpl(name, docString, initializerType, initializer, isQualified, typeComment, annotation,
hasAssignedValue, parentStub);
hasAssignedValue, parentStub, versionRange);
}
@Override
@@ -150,7 +150,7 @@ public class PyTargetExpressionElementType extends PyStubElementType<PyTargetExp
public void indexStub(@NotNull PyTargetExpressionStub stub, @NotNull IndexSink sink) {
String name = stub.getName();
if (name != null && PyUtil.getInitialUnderscores(name) == 0) {
if (PyPsiUtils.getParentStubSkippingVersionChecks(stub) instanceof PyFileStub) {
if (stub.getParentStub() instanceof PyFileStub) {
sink.occurrence(PyVariableNameIndex.KEY, name);
sink.occurrence(PyExportedModuleAttributeIndex.KEY, name);
}
@@ -16,17 +16,18 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.ObjectUtils;
import com.jetbrains.python.PyStubElementTypes;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.stubs.PyTargetExpressionStub;
import com.jetbrains.python.psi.stubs.PyVersionRange;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyTargetExpressionStubImpl extends StubBase<PyTargetExpression> implements PyTargetExpressionStub {
public class PyTargetExpressionStubImpl extends PyVersionSpecificStubBase<PyTargetExpression> implements PyTargetExpressionStub {
private final String myName;
private final InitializerType myInitializerType;
private final QualifiedName myInitializer;
@@ -44,8 +45,9 @@ public class PyTargetExpressionStubImpl extends StubBase<PyTargetExpression> imp
@Nullable String annotation,
boolean hasAssignedValue,
CustomTargetExpressionStub customStub,
StubElement parent) {
super(parent, PyStubElementTypes.TARGET_EXPRESSION);
StubElement parent,
@NotNull PyVersionRange versionRange) {
super(parent, PyStubElementTypes.TARGET_EXPRESSION, versionRange);
myName = name;
myTypeComment = typeComment;
myAnnotation = annotation;
@@ -62,11 +64,12 @@ public class PyTargetExpressionStubImpl extends StubBase<PyTargetExpression> imp
final InitializerType initializerType,
final QualifiedName initializer,
final boolean qualified,
@Nullable String typeComment,
@Nullable String typeComment,
@Nullable String annotation,
boolean hasAssignedValue,
final StubElement parentStub) {
super(parentStub, PyStubElementTypes.TARGET_EXPRESSION);
final StubElement parentStub,
@NotNull PyVersionRange versionRange) {
super(parentStub, PyStubElementTypes.TARGET_EXPRESSION, versionRange);
myName = name;
myTypeComment = typeComment;
myAnnotation = annotation;
@@ -6,13 +6,12 @@ import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyStubElementTypes;
import com.jetbrains.python.psi.PyStubElementType;
import com.jetbrains.python.psi.PyTypeAliasStatement;
import com.jetbrains.python.psi.impl.PyTypeAliasStatementImpl;
import com.jetbrains.python.psi.stubs.PyTypeAliasStatementStub;
import org.jetbrains.annotations.NonNls;
import com.jetbrains.python.psi.stubs.PyVersionRange;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@@ -38,13 +37,14 @@ public class PyTypeAliasStatementElementType extends PyStubElementType<PyTypeAli
@NotNull
public PyTypeAliasStatementStub createStub(@NotNull PyTypeAliasStatement psi, StubElement<? extends PsiElement> parentStub) {
return new PyTypeAliasStatementStubImpl(psi.getName(), (psi.getTypeExpression() != null ? psi.getTypeExpression().getText() : null),
parentStub, getStubElementType());
parentStub, getStubElementType(), PyVersionSpecificStubBaseKt.evaluateVersionRangeForElement(psi));
}
@Override
public void serialize(@NotNull PyTypeAliasStatementStub stub, @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeName(stub.getName());
dataStream.writeName(stub.getTypeExpressionText());
PyVersionSpecificStubBaseKt.serializeVersionRange(stub.getVersionRange(), dataStream);
}
@Override
@@ -52,8 +52,9 @@ public class PyTypeAliasStatementElementType extends PyStubElementType<PyTypeAli
public PyTypeAliasStatementStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
String name = dataStream.readNameString();
String typeExpressionText = dataStream.readNameString();
PyVersionRange versionRange = PyVersionSpecificStubBaseKt.deserializeVersionRange(dataStream);
return new PyTypeAliasStatementStubImpl(name, typeExpressionText, parentStub, getStubElementType());
return new PyTypeAliasStatementStubImpl(name, typeExpressionText, parentStub, getStubElementType(), versionRange);
}
@NotNull
@@ -1,14 +1,14 @@
package com.jetbrains.python.psi.impl.stubs;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.jetbrains.python.psi.PyTypeAliasStatement;
import com.jetbrains.python.psi.stubs.PyTypeAliasStatementStub;
import com.jetbrains.python.psi.stubs.PyVersionRange;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PyTypeAliasStatementStubImpl extends StubBase<PyTypeAliasStatement> implements PyTypeAliasStatementStub {
public class PyTypeAliasStatementStubImpl extends PyVersionSpecificStubBase<PyTypeAliasStatement> implements PyTypeAliasStatementStub {
private final String myName;
private final String myTypeExpressionText;
@@ -16,8 +16,9 @@ public class PyTypeAliasStatementStubImpl extends StubBase<PyTypeAliasStatement>
public PyTypeAliasStatementStubImpl(@Nullable String name,
@Nullable String typeExpressionText,
@Nullable StubElement parent,
@NotNull IStubElementType stubElementType) {
super(parent, stubElementType);
@NotNull IStubElementType stubElementType,
@NotNull PyVersionRange versionRange) {
super(parent, stubElementType, versionRange);
myName = name;
myTypeExpressionText = typeExpressionText;
}
@@ -0,0 +1,116 @@
package com.jetbrains.python.psi.impl.stubs
import com.intellij.openapi.util.Version
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.*
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.jetbrains.python.psi.LanguageLevel
import com.jetbrains.python.psi.PyElsePart
import com.jetbrains.python.psi.PyIfPart
import com.jetbrains.python.psi.PyIfStatement
import com.jetbrains.python.psi.impl.PyVersionCheck
import com.jetbrains.python.psi.impl.isLessThan
import com.jetbrains.python.psi.stubs.PyVersionRange
import com.jetbrains.python.psi.stubs.PyVersionSpecificStub
internal abstract class PyVersionSpecificStubBase<T : PsiElement>(
parent: StubElement<*>?,
elementType: IStubElementType<*, *>?,
override val versionRange: PyVersionRange,
) : StubBase<T>(parent, elementType), PyVersionSpecificStub
internal fun getChildrenStubs(stub: StubElement<*>, languageLevel: LanguageLevel): Iterable<StubElement<*>> {
return stub.childrenStubs.asSequence()
.filter { it !is PyVersionSpecificStub || it.versionRange.contains(languageLevel) }
.asIterable()
}
private fun PyVersionRange.contains(languageLevel: LanguageLevel): Boolean {
val low = lowInclusive
val high = highExclusive
return (low == null || !languageLevel.isLessThan(low)) &&
(high == null || languageLevel.isLessThan(high))
}
internal fun evaluateVersionRangeForElement(element: PsiElement): PyVersionRange {
return CachedValuesManager.getCachedValue(element) {
val parent = element.parent
var range: PyVersionRange
if (parent == null) {
range = PyVersionRange(null, null)
}
else {
range = evaluateVersionRangeForElement(parent)
if (parent is PyIfPart || parent is PyElsePart) {
val grandParent = parent.parent
if (grandParent is PyIfStatement) {
range = evaluateRange(range, grandParent, parent)
}
}
}
CachedValueProvider.Result.create(range, element)
}
}
private fun evaluateRange(
initialRange: PyVersionRange,
ifStatement: PyIfStatement,
ifStatementPart: PsiElement,
): PyVersionRange {
val versionChecks = mutableListOf<PyVersionCheck>()
val ifParts = sequenceOf(ifStatement.ifPart) + ifStatement.elifParts.asSequence()
for (ifPart in ifParts.takeWhile { it !== ifStatementPart }) {
val versionCheck = PyVersionCheck.fromCondition(ifPart) ?: return initialRange
versionChecks.add(PyVersionCheck(versionCheck.version, !versionCheck.isLessThan))
}
if (ifStatementPart is PyIfPart) {
val versionCheck = PyVersionCheck.fromCondition(ifStatementPart) ?: return initialRange
versionChecks.add(versionCheck)
}
return versionChecks.fold(initialRange, ::clampRange)
}
private fun clampRange(versionRange: PyVersionRange, versionCheck: PyVersionCheck): PyVersionRange {
return if (versionCheck.isLessThan)
PyVersionRange(versionRange.lowInclusive, min(versionRange.highExclusive, versionCheck.version))
else
PyVersionRange(max(versionRange.lowInclusive, versionCheck.version), versionRange.highExclusive)
}
private fun min(a: Version?, b: Version): Version {
return if (a == null) b else minOf(a, b)
}
private fun max(a: Version?, b: Version): Version {
return if (a == null) b else maxOf(a, b)
}
internal fun serializeVersionRange(versionRange: PyVersionRange, outputStream: StubOutputStream) {
serializeVersion(versionRange.lowInclusive, outputStream)
serializeVersion(versionRange.highExclusive, outputStream)
}
private fun serializeVersion(version: Version?, outputStream: StubOutputStream) {
outputStream.writeBoolean(version != null)
if (version != null) {
outputStream.writeVarInt(version.major)
outputStream.writeVarInt(version.minor)
}
}
internal fun deserializeVersionRange(stream: StubInputStream): PyVersionRange {
val lowInclusive = deserializeVersion(stream)
val highExclusive = deserializeVersion(stream)
return PyVersionRange(lowInclusive, highExclusive)
}
private fun deserializeVersion(stream: StubInputStream): Version? {
val isNotNull = stream.readBoolean()
if (isNotNull) {
val major = stream.readVarInt()
val minor = stream.readVarInt()
return Version(major, minor, 0)
}
return null
}
@@ -1,21 +0,0 @@
import sys
if condition1:
if sys.version_info >= (3,):
if sys.version_info < (3, 12):
def foo(): ...
else:
if sys.version_info < (2, 2):
pass
elif sys.version_info < (2, 5):
pass
else:
class MyClass:
if sys.version_info < (3, 12):
class MyNestedClass:
if sys.version_info >= (3, 11):
pass
else:
pass
else:
pass
@@ -5,7 +5,6 @@ import com.intellij.lang.FileASTNode;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Version;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiFileImpl;
@@ -19,7 +18,6 @@ import com.intellij.testFramework.TestDataPath;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.ast.PyAstFunction;
import com.jetbrains.python.psi.impl.PyVersionCheck;
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.*;
@@ -132,43 +130,6 @@ public class PyStubsTest extends PyTestCase {
);
}
// PY-34617
public void testStubStructureWithVersionChecks() {
final PsiFileImpl file = (PsiFileImpl)getTestFile();
element(PyFileStub.class)
.withChildren(
element(PyImportStatementStub.class),
ifPart(3, 0, false)
.withChildren(
ifPart(3, 12, true)
.withChildren(
element(PyFunctionStub.class)
)
),
element(PyElsePartStub.class)
.withChildren(
ifPart(2, 2, true),
elifPart(2, 5, true),
element(PyElsePartStub.class)
.withChildren(
element(PyClassStub.class)
.withChildren(
ifPart(3, 12, true)
.withChildren(
element(PyClassStub.class)
.withChildren(
ifPart(3, 11, false),
element(PyElsePartStub.class)
)
),
element(PyElsePartStub.class)
)
)
)
)
.test(file.getStub());
}
public void testLoadingDeeperTreeRemainsKnownPsiElement() {
final PyFile file = getTestFile();
final List<PyClass> classes = file.getTopLevelClasses();
@@ -321,14 +282,13 @@ public class PyStubsTest extends PyTestCase {
}
public void testImportInExcept() {
runWithLanguageLevel(LanguageLevel.PYTHON26, () -> {
final PyFileImpl file = (PyFileImpl)getTestFile();
final PsiElement element = file.getElementNamed("tzinfo");
assertTrue(String.valueOf(element), element instanceof PyClass);
assertNotParsed(file);
});
final PyFileImpl file = (PyFileImpl) getTestFile();
final PsiElement element = file.getElementNamed("tzinfo");
assertTrue(element != null ? element.toString() : "null", element instanceof PyClass);
assertNotParsed(file);
}
public void testImportFeatures() {
final PyFileImpl file = (PyFileImpl) getTestFile();
assertTrue(file.hasImportFromFuture(FutureFeature.DIVISION));
@@ -1163,6 +1123,7 @@ public class PyStubsTest extends PyTestCase {
doTestTypeParameterStub(typeAliasStatement, file);
}
private void doTestTypingTypedDictArguments() {
doTestTypedDict("name", Arrays.asList("x", "y"), Arrays.asList("str", "int"), QualifiedName.fromComponents("TypedDict"));
}
@@ -1272,37 +1233,4 @@ public class PyStubsTest extends PyTestCase {
assertEquals(initValue, fieldStub.initValue());
}
}
private static @NotNull StubElementValidator element(@NotNull Class<?> clazz) {
return stub -> assertInstanceOf(stub, clazz);
}
private static @NotNull StubElementValidator ifPart(int major, int minor, boolean isLessThan) {
return stub -> {
assertInstanceOf(stub, PyIfPartIfStub.class);
assertEquals(new PyVersionCheck(new Version(major, minor, 0), isLessThan), ((PyIfPartIfStub)stub).getVersionCheck());
};
}
private static @NotNull StubElementValidator elifPart(int major, int minor, boolean isLessThan) {
return stub -> {
assertInstanceOf(stub, PyIfPartElifStub.class);
assertEquals(new PyVersionCheck(new Version(major, minor, 0), isLessThan), ((PyIfPartElifStub)stub).getVersionCheck());
};
}
private interface StubElementValidator {
void test(@NotNull StubElement<?> stub);
default @NotNull StubElementValidator withChildren(StubElementValidator @NotNull ... children) {
return stub -> {
test(stub);
List<StubElement<?>> childrenStubs = stub.getChildrenStubs();
assertSize(children.length, childrenStubs);
for (int i = 0; i != children.length; i++) {
children[i].test(childrenStubs.get(i));
}
};
}
}
}