From b28a735dfc841d0164e9b7f9193616ae452f5b8c Mon Sep 17 00:00:00 2001 From: Morgan Bartholomew Date: Sun, 2 Nov 2025 10:48:05 +1000 Subject: [PATCH] [python] PY-61777 support python 3.11 regex features (cherry picked from commit 91f2efe47546d0189840d3f3d21da39483de440f) GitOrigin-RevId: 35c7b142f27130205916522c1bd8c66577be9395 --- .../lang/regexp/RegExpLanguageHost.java | 13 +++++- .../lang/regexp/RegExpLanguageHosts.java | 2 +- .../python/codeInsight/PythonRegExpHost.java | 5 ++- .../com/jetbrains/python/PyRegexpTest.java | 43 +++++++++++++++++++ 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHost.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHost.java index 492be753eb4c..8c4a35e71953 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHost.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHost.java @@ -32,7 +32,18 @@ public interface RegExpLanguageHost { } boolean supportsPerl5EmbeddedComments(); - boolean supportsPossessiveQuantifiers(); + /** + * @deprecated use `supportsPossessiveQuantifiers(RegExpElement)` + */ + @Deprecated + default boolean supportsPossessiveQuantifiers() { + return false; + } + + default boolean supportsPossessiveQuantifiers(RegExpElement context) { + return supportsPossessiveQuantifiers(); + } + default boolean isDuplicateGroupNamesAllowed(@NotNull RegExpGroup group) { return false; } diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHosts.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHosts.java index a1db81af5104..d1b060a2e574 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHosts.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpLanguageHosts.java @@ -131,7 +131,7 @@ public final class RegExpLanguageHosts extends ClassExtension + testHighlighting(""" + import re + re.compile("a++ b*+ c?+")""") + ); + } + + @TestFor(issues="PY-61777") + public void testPossessiveQuantifierUnsupportedPy3() { + runWithLanguageLevel(LanguageLevel.PYTHON310, () -> + testHighlighting(""" + import re + re.compile("a++ b*+ c?+")""") + ); + } + + @TestFor(issues="PY-61777") + public void testAtomicGroupSupportedPy3() { + runWithLanguageLevel(LanguageLevel.PYTHON311, () -> + testHighlighting(""" + import re + re.compile("(?>a+)")""") + ); + } + + @TestFor(issues="PY-61777") + public void testAtomicGroupUnsupportedPy3() { + runWithLanguageLevel(LanguageLevel.PYTHON310, () -> + testHighlighting(""" + import re + re.compile("(?>a+)")""") + ); + } + @Nullable @Override protected LightProjectDescriptor getProjectDescriptor() { @@ -275,6 +313,11 @@ public class PyRegexpTest extends PyTestCase { myFixture.testHighlighting(true, false, true, "regexp/" + getTestName(true) + ".py"); } + private void testHighlighting(String text) { + myFixture.configureByText("test.py", text); + myFixture.testHighlighting(true, false, true, "test.py"); + } + private void doTestLexer(final String text, String... expectedTokens) { Lexer lexer = new PythonRegexpParserDefinition().createLexer(myFixture.getProject()); PyLexerTestCase.doLexerTest(text, lexer, expectedTokens);