From aa82ce5f70810d2c48b0515ef78290e34e8bac14 Mon Sep 17 00:00:00 2001 From: Petr Date: Fri, 13 Jun 2025 00:06:42 +0200 Subject: [PATCH] PY-81646 Get rid of EMPTY_EXPRESSION nodes within SLICE_ITEM GitOrigin-RevId: 6ffe0027790bb41b8ac18251903529aa1b1243f6 --- .../jetbrains/python/ast/PyAstSliceItem.java | 28 ++++++++++++++++--- .../python/parsing/ExpressionParsing.java | 9 ++---- python/testData/psi/ExtendedSlices.txt | 10 ------- python/testData/psi/RangeAsLHS.txt | 2 -- python/testData/psi/SliceList.txt | 2 -- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/python/python-ast/src/com/jetbrains/python/ast/PyAstSliceItem.java b/python/python-ast/src/com/jetbrains/python/ast/PyAstSliceItem.java index 50abc6593bfc..275bc2d17741 100644 --- a/python/python-ast/src/com/jetbrains/python/ast/PyAstSliceItem.java +++ b/python/python-ast/src/com/jetbrains/python/ast/PyAstSliceItem.java @@ -1,7 +1,9 @@ // 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.ast; -import com.jetbrains.python.PythonDialectsTokenSetProvider; +import com.intellij.lang.ASTNode; +import com.intellij.psi.tree.TokenSet; +import com.jetbrains.python.PyTokenTypes; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @@ -9,14 +11,32 @@ import org.jetbrains.annotations.Nullable; @ApiStatus.Experimental public interface PyAstSliceItem extends PyAstExpression { default @Nullable PyAstExpression getLowerBound() { - return childToPsi(PythonDialectsTokenSetProvider.getInstance().getExpressionTokens(), 0); + return getChildExpression(0); } default @Nullable PyAstExpression getUpperBound() { - return childToPsi(PythonDialectsTokenSetProvider.getInstance().getExpressionTokens(), 1); + return getChildExpression(1); } default @Nullable PyAstExpression getStride() { - return childToPsi(PythonDialectsTokenSetProvider.getInstance().getExpressionTokens(), 2); + return getChildExpression(2); + } + + private @Nullable PyAstExpression getChildExpression(int index) { + ASTNode[] children = getNode().getChildren(TokenSet.ANY); + int i = 0; + while (i < children.length && index > 0) { + if (children[i].getElementType() == PyTokenTypes.COLON) { + i++; + } + else { + i += 2; + } + index--; + } + if (i < children.length && children[i].getElementType() != PyTokenTypes.COLON) { + return (PyAstExpression)children[i].getPsi(); + } + return null; } } diff --git a/python/python-parser/src/com/jetbrains/python/parsing/ExpressionParsing.java b/python/python-parser/src/com/jetbrains/python/parsing/ExpressionParsing.java index fdef34dcad04..10c2d766411b 100644 --- a/python/python-parser/src/com/jetbrains/python/parsing/ExpressionParsing.java +++ b/python/python-parser/src/com/jetbrains/python/parsing/ExpressionParsing.java @@ -693,18 +693,13 @@ public class ExpressionParsing extends Parsing { private boolean parseSubscriptionIndexArgument() { SyntaxTreeBuilder.Marker sliceItem = myBuilder.mark(); - if (!parseSingleExpression(false)) { - myBuilder.mark().done(PyElementTypes.EMPTY_EXPRESSION); - } + parseSingleExpression(false); if (!matchToken(PyTokenTypes.COLON)) { sliceItem.rollbackTo(); return parseNamedTestExpression(false, false); } - boolean exprParseResult = parseSingleExpression(false); + parseSingleExpression(false); if (myBuilder.getTokenType() == PyTokenTypes.COLON) { - if (!exprParseResult) { - myBuilder.mark().done(PyElementTypes.EMPTY_EXPRESSION); - } myBuilder.advanceLexer(); parseSingleExpression(false); } diff --git a/python/testData/psi/ExtendedSlices.txt b/python/testData/psi/ExtendedSlices.txt index 0c5edf3dcbe1..1488a671a19a 100644 --- a/python/testData/psi/ExtendedSlices.txt +++ b/python/testData/psi/ExtendedSlices.txt @@ -5,11 +5,7 @@ PyFile:ExtendedSlices.py PsiElement(Py:IDENTIFIER)('d') PsiElement(Py:LBRACKET)('[') PySliceItem - PyEmptyExpression - PsiElement(Py:COLON)(':') - PyEmptyExpression - PsiElement(Py:COLON)(':') PsiElement(Py:RBRACKET)(']') PsiWhiteSpace('\n') @@ -22,8 +18,6 @@ PyFile:ExtendedSlices.py PyNumericLiteralExpression PsiElement(Py:INTEGER_LITERAL)('1') PsiElement(Py:COLON)(':') - PyEmptyExpression - PsiElement(Py:COLON)(':') PyNumericLiteralExpression PsiElement(Py:INTEGER_LITERAL)('2') @@ -94,8 +88,6 @@ PyFile:ExtendedSlices.py PsiElement(Py:LBRACKET)('[') PyTupleExpression PySliceItem - PyEmptyExpression - PsiElement(Py:COLON)(':') PyNumericLiteralExpression PsiElement(Py:INTEGER_LITERAL)('42') @@ -108,8 +100,6 @@ PyFile:ExtendedSlices.py PsiElement(Py:COMMA)(',') PsiWhiteSpace(' ') PySliceItem - PyEmptyExpression - PsiElement(Py:COLON)(':') PyNumericLiteralExpression PsiElement(Py:INTEGER_LITERAL)('24') diff --git a/python/testData/psi/RangeAsLHS.txt b/python/testData/psi/RangeAsLHS.txt index 218966b32617..ce08df6ab261 100644 --- a/python/testData/psi/RangeAsLHS.txt +++ b/python/testData/psi/RangeAsLHS.txt @@ -15,8 +15,6 @@ PyFile:RangeAsLHS.py PsiElement(Py:IDENTIFIER)('foo') PsiElement(Py:LBRACKET)('[') PySliceItem - PyEmptyExpression - PsiElement(Py:COLON)(':') PsiElement(Py:RBRACKET)(']') PsiWhiteSpace(' ') diff --git a/python/testData/psi/SliceList.txt b/python/testData/psi/SliceList.txt index 3cd8e6aa9e0d..e9ef868f984f 100644 --- a/python/testData/psi/SliceList.txt +++ b/python/testData/psi/SliceList.txt @@ -9,7 +9,5 @@ PyFile:SliceList.py PsiElement(Py:IDENTIFIER)('b1') PsiElement(Py:COMMA)(',') PySliceItem - PyEmptyExpression - PsiElement(Py:COLON)(':') PsiElement(Py:RBRACKET)(']') \ No newline at end of file