[python] PY-80436 support ellipsis

GitOrigin-RevId: 82e38fcb502ed68d5676f2cc774ef2653d69febb
This commit is contained in:
Morgan Bartholomew
2025-04-18 18:01:11 +10:00
committed by intellij-monorepo-bot
parent 1cfa311783
commit 4b1d24562a
50 changed files with 251 additions and 190 deletions

View File

@@ -70,6 +70,7 @@ public interface PyElementTypes {
PyElementType IMAGINARY_LITERAL_EXPRESSION = new PyElementType("IMAGINARY_LITERAL_EXPRESSION", Companion.getINSTANCE().getImaginaryLiteralExpressionConstructor());
PyElementType STRING_LITERAL_EXPRESSION = new PyElementType("STRING_LITERAL_EXPRESSION", Companion.getINSTANCE().getStringLiteralExpressionConstructor());
PyElementType NONE_LITERAL_EXPRESSION = new PyElementType("NONE_LITERAL_EXPRESSION", Companion.getINSTANCE().getNoneLiteralExpressionConstructor());
PyElementType ELLIPSIS_LITERAL_EXPRESSION = new PyElementType("ELLIPSIS_LITERAL_EXPRESSION", Companion.getINSTANCE().getEllipsisLiteralExpressionConstructor());
PyElementType BOOL_LITERAL_EXPRESSION = new PyElementType("BOOL_LITERAL_EXPRESSION", Companion.getINSTANCE().getBoolLiteralExpressionConstructor());
PyElementType PARENTHESIZED_EXPRESSION = new PyElementType("PARENTHESIZED_EXPRESSION", Companion.getINSTANCE().getParenthesizedExpressionConstructor());
PyElementType SUBSCRIPTION_EXPRESSION = new PyElementType("SUBSCRIPTION_EXPRESSION", Companion.getINSTANCE().getSubscriptionExpressionConstructor());

View File

@@ -67,6 +67,7 @@ abstract class PyElementTypesFacade {
abstract val imaginaryLiteralExpressionConstructor: Function<in ASTNode, out PsiElement>
abstract val stringLiteralExpressionConstructor: Function<in ASTNode, out PsiElement>
abstract val noneLiteralExpressionConstructor: Function<in ASTNode, out PsiElement>
abstract val ellipsisLiteralExpressionConstructor: Function<in ASTNode, out PsiElement>
abstract val boolLiteralExpressionConstructor: Function<in ASTNode, out PsiElement>
abstract val parenthesizedExpressionConstructor: Function<in ASTNode, out PsiElement>
abstract val subscriptionExpressionConstructor: Function<in ASTNode, out PsiElement>

View File

@@ -58,6 +58,7 @@ public final class PyTokenTypes {
// new keywords in Python 3
public static final PyElementType NONE_KEYWORD = new PyElementType("NONE_KEYWORD");
public static final PyElementType ELLIPSIS_LITERAL = new PyElementType("ELLIPSIS_LITERAL");
public static final PyElementType TRUE_KEYWORD = new PyElementType("TRUE_KEYWORD");
public static final PyElementType FALSE_KEYWORD = new PyElementType("FALSE_KEYWORD");
public static final PyElementType NONLOCAL_KEYWORD = new PyElementType("NONLOCAL_KEYWORD");
@@ -168,8 +169,8 @@ public final class PyTokenTypes {
public static final TokenSet NUMERIC_LITERALS = TokenSet.create(FLOAT_LITERAL, INTEGER_LITERAL, IMAGINARY_LITERAL);
public static final TokenSet BOOL_LITERALS = TokenSet.create(TRUE_KEYWORD, FALSE_KEYWORD);
public static final TokenSet SCALAR_LITERALS = TokenSet.orSet(BOOL_LITERALS, NUMERIC_LITERALS, TokenSet.create(NONE_KEYWORD));
public static final TokenSet EXPRESSION_KEYWORDS = TokenSet.create(TRUE_KEYWORD, FALSE_KEYWORD, NONE_KEYWORD);
public static final TokenSet SCALAR_LITERALS = TokenSet.orSet(BOOL_LITERALS, NUMERIC_LITERALS, TokenSet.create(NONE_KEYWORD, ELLIPSIS_LITERAL));
public static final TokenSet EXPRESSION_KEYWORDS = TokenSet.create(TRUE_KEYWORD, FALSE_KEYWORD, NONE_KEYWORD, ELLIPSIS_LITERAL);
public static final TokenSet AUG_ASSIGN_OPERATIONS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, ATEQ, DIVEQ,
PERCEQ, EXPEQ, GTGTEQ, LTLTEQ, ANDEQ, OREQ, XOREQ, FLOORDIVEQ);

View File

@@ -40,7 +40,7 @@ public final class PythonTokenSetContributor extends PythonDialectsTokenSetContr
LIST_LITERAL_EXPRESSION, TUPLE_EXPRESSION, KEYWORD_ARGUMENT_EXPRESSION, STAR_ARGUMENT_EXPRESSION,
LAMBDA_EXPRESSION, LIST_COMP_EXPRESSION, DICT_LITERAL_EXPRESSION, KEY_VALUE_EXPRESSION,
REPR_EXPRESSION, GENERATOR_EXPRESSION, CONDITIONAL_EXPRESSION, YIELD_EXPRESSION,
TARGET_EXPRESSION, NONE_LITERAL_EXPRESSION, BOOL_LITERAL_EXPRESSION,
TARGET_EXPRESSION, NONE_LITERAL_EXPRESSION, ELLIPSIS_LITERAL_EXPRESSION, BOOL_LITERAL_EXPRESSION,
SET_LITERAL_EXPRESSION, SET_COMP_EXPRESSION, DICT_COMP_EXPRESSION, STAR_EXPRESSION, DOUBLE_STAR_EXPRESSION,
ASSIGNMENT_EXPRESSION);
}
@@ -57,7 +57,7 @@ public final class PythonTokenSetContributor extends PythonDialectsTokenSetContr
RAISE_KEYWORD, RETURN_KEYWORD, TRY_KEYWORD, WITH_KEYWORD, WHILE_KEYWORD,
YIELD_KEYWORD,
MATCH_KEYWORD, CASE_KEYWORD,
NONE_KEYWORD, TRUE_KEYWORD, FALSE_KEYWORD, NONLOCAL_KEYWORD, DEBUG_KEYWORD, ASYNC_KEYWORD, AWAIT_KEYWORD, TYPE_KEYWORD);
NONE_KEYWORD, ELLIPSIS_LITERAL, TRUE_KEYWORD, FALSE_KEYWORD, NONLOCAL_KEYWORD, DEBUG_KEYWORD, ASYNC_KEYWORD, AWAIT_KEYWORD, TYPE_KEYWORD);
}
@Override

View File

@@ -70,6 +70,7 @@ public class PythonHighlightingLexer extends PythonLexer {
if (myLanguageLevel.isPy3K()) {
if (tokenText.equals(PyNames.NONE)) return PyTokenTypes.NONE_KEYWORD;
if (tokenText.equals(PyNames.ELLIPSIS)) return PyTokenTypes.ELLIPSIS_LITERAL;
if (tokenText.equals(PyNames.TRUE)) return PyTokenTypes.TRUE_KEYWORD;
if (tokenText.equals(PyNames.FALSE)) return PyTokenTypes.FALSE_KEYWORD;
if (tokenText.equals(PyNames.NONLOCAL)) return PyTokenTypes.NONLOCAL_KEYWORD;

View File

@@ -50,6 +50,10 @@ public class ExpressionParsing extends Parsing {
buildTokenElement(PyElementTypes.NONE_LITERAL_EXPRESSION, myBuilder);
return true;
}
else if (firstToken == PyTokenTypes.ELLIPSIS_LITERAL) {
buildTokenElement(PyElementTypes.ELLIPSIS_LITERAL_EXPRESSION, myBuilder);
return true;
}
else if (firstToken == PyTokenTypes.TRUE_KEYWORD ||
firstToken == PyTokenTypes.FALSE_KEYWORD ||
firstToken == PyTokenTypes.DEBUG_KEYWORD) {
@@ -580,10 +584,8 @@ public class ExpressionParsing extends Parsing {
if (atToken(PyTokenTypes.DOT)) {
final SyntaxTreeBuilder.Marker maybeEllipsis = myBuilder.mark();
myBuilder.advanceLexer();
//duplication is intended as matchToken advances the lexer
//noinspection DuplicateBooleanBranch
if (matchToken(PyTokenTypes.DOT) && matchToken(PyTokenTypes.DOT)) {
maybeEllipsis.done(PyElementTypes.NONE_LITERAL_EXPRESSION);
maybeEllipsis.done(PyElementTypes.ELLIPSIS_LITERAL_EXPRESSION);
return true;
}
maybeEllipsis.rollbackTo();

View File

@@ -357,6 +357,10 @@ public class PatternParsing extends Parsing {
buildTokenElement(PyElementTypes.NONE_LITERAL_EXPRESSION, myBuilder);
return true;
}
else if (atToken(PyTokenTypes.ELLIPSIS_LITERAL)) {
buildTokenElement(PyElementTypes.ELLIPSIS_LITERAL_EXPRESSION, myBuilder);
return true;
}
else if (atAnyOfTokens(PyTokenTypes.PLUS, PyTokenTypes.MINUS) || atAnyOfTokens(PyTokenTypes.NUMERIC_LITERALS)) {
parseComplexNumber();
return true;

View File

@@ -30,6 +30,7 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
protected static final @NonNls String TOK_AS = PyNames.AS;
protected static final @NonNls String TOK_PRINT = PyNames.PRINT;
protected static final @NonNls String TOK_NONE = PyNames.NONE;
protected static final @NonNls String TOK_ELLIPSIS = PyNames.ELLIPSIS;
protected static final @NonNls String TOK_TRUE = PyNames.TRUE;
protected static final @NonNls String TOK_DEBUG = PyNames.DEBUG;
protected static final @NonNls String TOK_FALSE = PyNames.FALSE;
@@ -1114,6 +1115,9 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
if (isWordAtPosition(text, start, end, TOK_NONE)) {
return PyTokenTypes.NONE_KEYWORD;
}
if (isWordAtPosition(text, start, end, TOK_ELLIPSIS)) {
return PyTokenTypes.ELLIPSIS_LITERAL;
}
if (isWordAtPosition(text, start, end, TOK_TRUE)) {
return PyTokenTypes.TRUE_KEYWORD;
}