From 353d7f24d1ac6b2dd786bb4143db1a824a45e6be Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 31 May 2021 18:31:20 +0300 Subject: [PATCH] PY-48014 Implement Complete Current Statement for match statement and its clauses GitOrigin-RevId: dba29d39fc90397a2f4af8a347cfcbf208ce5c92 --- .../smartEnter/PySmartEnterProcessor.java | 2 + .../smartEnter/fixers/PyCaseClauseFixer.java | 78 +++++++++++++ .../fixers/PyMatchStatementFixer.java | 107 ++++++++++++++++++ ...eClauseWithPatternWithoutGuardCondition.py | 2 + ...eWithPatternWithoutGuardCondition_after.py | 2 + .../colonAfterCaseClauseWithoutPattern.py | 2 + ...eClauseWithoutPatternWithGuardCondition.py | 2 + ...eWithoutPatternWithGuardCondition_after.py | 2 + ...auseWithoutPatternWithoutGuardCondition.py | 2 + ...thoutPatternWithoutGuardCondition_after.py | 2 + ...olonAfterCaseClauseWithoutPattern_after.py | 2 + ...nAfterEmptyMatchStatementWithoutSubject.py | 1 + ...EmptyMatchStatementWithoutSubject_after.py | 1 + ...tyMatchStatementWithSubjectCaretOnMatch.py | 1 + ...hStatementWithSubjectCaretOnMatch_after.py | 2 + ...MatchStatementWithSubjectCaretOnSubject.py | 1 + ...tatementWithSubjectCaretOnSubject_after.py | 2 + ...tyMatchStatementWithSubjectCustomIndent.py | 1 + ...hStatementWithSubjectCustomIndent_after.py | 2 + ...tWithSubjectLookingLikeBinaryExpression.py | 1 + ...ubjectLookingLikeBinaryExpression_after.py | 2 + ...entWithSubjectLookingLikeCallExpression.py | 1 + ...hSubjectLookingLikeCallExpression_after.py | 2 + ...olonAndIndentAfterCaseClauseWithPattern.py | 2 + ...rCaseClauseWithPatternAndGuardCondition.py | 2 + ...lauseWithPatternAndGuardCondition_after.py | 3 + ...dIndentAfterCaseClauseWithPattern_after.py | 3 + ...rEmptyMatchStatementWithSubjectAndColon.py | 1 + ...MatchStatementWithSubjectAndColon_after.py | 2 + ...ndentAfterCaseClauseWithPatternAndColon.py | 2 + ...fterCaseClauseWithPatternAndColon_after.py | 3 + ...nEmptyMatchStatementWithSubjectAndColon.py | 3 + ...MatchStatementWithSubjectAndColon_after.py | 4 + ...hStatementWithIncompleteStatementInside.py | 2 + ...mentWithIncompleteStatementInside_after.py | 3 + ...rUnambiguousExpressionStartingWithMatch.py | 1 + ...iguousExpressionStartingWithMatch_after.py | 2 + ...eAfterCaseClauseWithColonWithoutPattern.py | 2 + ...CaseClauseWithColonWithoutPattern_after.py | 2 + ...eAfterCaseClauseWithGuardWithoutPattern.py | 2 + ...CaseClauseWithGuardWithoutPattern_after.py | 2 + ...ithPatternAndColonWithoutGuardCondition.py | 2 + ...ternAndColonWithoutGuardCondition_after.py | 2 + ...erMatchStatementWithColonWithoutSubject.py | 1 + ...hStatementWithColonWithoutSubject_after.py | 1 + .../jetbrains/python/PySmartEnterTest.java | 106 +++++++++++++++++ 46 files changed, 373 insertions(+) create mode 100644 python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyCaseClauseFixer.java create mode 100644 python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMatchStatementFixer.java create mode 100644 python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithPatternWithoutGuardCondition.py create mode 100644 python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithPatternWithoutGuardCondition_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPattern.py create mode 100644 python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithGuardCondition.py create mode 100644 python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithGuardCondition_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithoutGuardCondition.py create mode 100644 python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithoutGuardCondition_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPattern_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAfterEmptyMatchStatementWithoutSubject.py create mode 100644 python/testData/codeInsight/smartEnter/colonAfterEmptyMatchStatementWithoutSubject_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnMatch.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnMatch_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnSubject.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnSubject_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCustomIndent.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCustomIndent_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeBinaryExpression.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeBinaryExpression_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeCallExpression.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeCallExpression_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPattern.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPatternAndGuardCondition.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPatternAndGuardCondition_after.py create mode 100644 python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPattern_after.py create mode 100644 python/testData/codeInsight/smartEnter/firstClauseAfterEmptyMatchStatementWithSubjectAndColon.py create mode 100644 python/testData/codeInsight/smartEnter/firstClauseAfterEmptyMatchStatementWithSubjectAndColon_after.py create mode 100644 python/testData/codeInsight/smartEnter/indentAfterCaseClauseWithPatternAndColon.py create mode 100644 python/testData/codeInsight/smartEnter/indentAfterCaseClauseWithPatternAndColon_after.py create mode 100644 python/testData/codeInsight/smartEnter/lineBreakAndIndentAfterNonEmptyMatchStatementWithSubjectAndColon.py create mode 100644 python/testData/codeInsight/smartEnter/lineBreakAndIndentAfterNonEmptyMatchStatementWithSubjectAndColon_after.py create mode 100644 python/testData/codeInsight/smartEnter/noFirstClauseInMatchStatementWithIncompleteStatementInside.py create mode 100644 python/testData/codeInsight/smartEnter/noFirstClauseInMatchStatementWithIncompleteStatementInside_after.py create mode 100644 python/testData/codeInsight/smartEnter/nothingAfterUnambiguousExpressionStartingWithMatch.py create mode 100644 python/testData/codeInsight/smartEnter/nothingAfterUnambiguousExpressionStartingWithMatch_after.py create mode 100644 python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithColonWithoutPattern.py create mode 100644 python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithColonWithoutPattern_after.py create mode 100644 python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithGuardWithoutPattern.py create mode 100644 python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithGuardWithoutPattern_after.py create mode 100644 python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithPatternAndColonWithoutGuardCondition.py create mode 100644 python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithPatternAndColonWithoutGuardCondition_after.py create mode 100644 python/testData/codeInsight/smartEnter/onlyCaretMoveAfterMatchStatementWithColonWithoutSubject.py create mode 100644 python/testData/codeInsight/smartEnter/onlyCaretMoveAfterMatchStatementWithColonWithoutSubject_after.py diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java index 60b6cace3b8e..41aa4225e0cf 100644 --- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java @@ -49,6 +49,8 @@ public class PySmartEnterProcessor extends SmartEnterProcessor { .add(new PyClassFixer()) .add(new PyWithFixer()) .add(new PyCollectionLiteralFixer()) + .add(new PyMatchStatementFixer()) + .add(new PyCaseClauseFixer()) .build(); private static final List ourProcessors = ImmutableList.of(new PyCommentBreakerEnterProcessor(), new PyPlainEnterProcessor()); diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyCaseClauseFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyCaseClauseFixer.java new file mode 100644 index 000000000000..947286304d16 --- /dev/null +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyCaseClauseFixer.java @@ -0,0 +1,78 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.codeInsight.editorActions.smartEnter.fixers; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiWhiteSpace; +import com.jetbrains.python.PyTokenTypes; +import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; +import com.jetbrains.python.psi.PyCaseClause; +import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.psi.PyPattern; +import com.jetbrains.python.psi.impl.PyPsiUtils; +import org.jetbrains.annotations.NotNull; + +import static com.jetbrains.python.psi.PyUtil.as; + +public final class PyCaseClauseFixer extends PyFixer { + public PyCaseClauseFixer() { + super(PyCaseClause.class); + } + + @Override + protected void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyCaseClause element) { + PyPattern pattern = element.getPattern(); + PsiElement ifKeyword = PyPsiUtils.getFirstChildOfType(element, PyTokenTypes.IF_KEYWORD); + PyExpression condition = element.getGuardCondition(); + PsiElement colon = PyPsiUtils.getFirstChildOfType(element, PyTokenTypes.COLON); + Document document = editor.getDocument(); + int colonOffset; + if (colon == null) { + String colonSuffix; + if (condition != null) { + colonSuffix = ":"; + colonOffset = condition.getTextRange().getEndOffset(); + } + else if (ifKeyword != null) { + colonSuffix = " :"; + colonOffset = ifKeyword.getTextRange().getEndOffset() + 1; + } + else if (pattern != null) { + colonSuffix = ":"; + colonOffset = pattern.getTextRange().getEndOffset(); + } + else { + colonSuffix = " :"; + colonOffset = element.getFirstChild().getTextRange().getEndOffset() + 1; + } + document.insertString(colonOffset - (colonSuffix.length() - 1), colonSuffix); + } + else { + colonOffset = colon.getTextOffset(); + } + + if (pattern == null) { + if (ifKeyword != null) { + int ifOffset = ifKeyword.getTextOffset(); + PsiWhiteSpace prevWhitespace = as(ifKeyword.getPrevSibling(), PsiWhiteSpace.class); + if (prevWhitespace != null && prevWhitespace.getTextLength() < 2) { + document.insertString(ifOffset, " "); + } + processor.registerUnresolvedError(ifOffset); + } + else { + processor.registerUnresolvedError(colonOffset); + } + } + else if (ifKeyword != null && condition == null) { + if (ifKeyword.getTextRange().getEndOffset() == colonOffset) { + document.insertString(colonOffset, " "); + processor.registerUnresolvedError(colonOffset + 1); + } + else { + processor.registerUnresolvedError(colonOffset); + } + } + } +} diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMatchStatementFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMatchStatementFixer.java new file mode 100644 index 000000000000..d922d966df55 --- /dev/null +++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMatchStatementFixer.java @@ -0,0 +1,107 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.codeInsight.editorActions.smartEnter.fixers; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.Couple; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; +import com.jetbrains.python.PyNames; +import com.jetbrains.python.PyTokenTypes; +import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor; +import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyPsiUtils; +import org.jetbrains.annotations.NotNull; + +import static com.jetbrains.python.psi.PyUtil.as; + +public final class PyMatchStatementFixer extends PyFixer { + public PyMatchStatementFixer() { + super(PyStatement.class); + } + + @Override + protected void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyStatement element) { + Document document = editor.getDocument(); + PyMatchStatement matchStatement = as(element, PyMatchStatement.class); + if (matchStatement != null) { + PsiElement colon = PyPsiUtils.getFirstChildOfType(element, PyTokenTypes.COLON); + assert colon != null; + if (matchStatement.getSubject() == null) { + processor.registerUnresolvedError(colon.getTextOffset()); + return; + } + int colonEndOffset = colon.getTextRange().getEndOffset(); + // It's not enough to check matchStatement.getCaseClauses().isEmpty() + boolean hasEmptyBody = colonEndOffset == matchStatement.getTextRange().getEndOffset(); + if (hasEmptyBody) { + String matchIndent = PyIndentUtil.getElementIndent(element); + String indent = PyIndentUtil.getIndentFromSettings(element.getContainingFile()); + String caseClausePlaceholder = "\n" + matchIndent + indent + PyNames.CASE + " :"; + document.insertString(colonEndOffset, caseClausePlaceholder); + processor.registerUnresolvedError(colonEndOffset + caseClausePlaceholder.length() - 1); + } + return; + } + + Couple pair = findMatchKeywordAndSubject(element); + PsiElement matchKeyword = pair.getFirst(); + if (matchKeyword == null) { + return; + } + PsiElement subject = pair.getSecond(); + if (subject != null) { + int endOffset = subject.getTextRange().getEndOffset(); + String matchIndent = PyIndentUtil.getElementIndent(matchKeyword); + String indent = PyIndentUtil.getIndentFromSettings(element.getContainingFile()); + String caseClausePlaceholder = ":\n" + matchIndent + indent + PyNames.CASE + " :"; + document.insertString(endOffset, caseClausePlaceholder); + processor.registerUnresolvedError(endOffset + caseClausePlaceholder.length() - 1); + } + else { + int endOffset = element.getTextRange().getEndOffset(); + document.insertString(endOffset, " :"); + processor.registerUnresolvedError(endOffset + 1); + } + } + + @NotNull + private static Couple findMatchKeywordAndSubject(@NotNull PyStatement statement) { + if (!(statement instanceof PyExpressionStatement)) return Couple.getEmpty(); + // "match expr" case + PsiElement prevSibling = PyPsiUtils.getPrevNonWhitespaceSiblingOnSameLine(statement); + if (prevSibling instanceof PyExpressionStatement && isMatchIdentifier(prevSibling)) { + return Couple.of(prevSibling, statement); + } + if (isMatchIdentifier(statement)) { + // "match expr" + PsiElement nextSibling = PyPsiUtils.getNextNonWhitespaceSiblingOnSameLine(statement); + if (nextSibling instanceof PyExpressionStatement) { + return Couple.of(statement, nextSibling); + } + // "match" case + else if (nextSibling == null) { + return Couple.of(statement, null); + } + } + // "match + x" or "match [x]" case + if (isMatchIdentifier(PsiTreeUtil.getDeepestFirst(statement))) { + LanguageLevel languageLevel = LanguageLevel.forElement(statement); + PyElementGenerator generator = PyElementGenerator.getInstance(statement.getProject()); + String subjectSuspect = StringUtil.trimStart(statement.getText(), PyNames.MATCH); + try { + generator.createExpressionFromText(languageLevel, subjectSuspect.trim()); + return Couple.of(statement, statement); + } + catch (IncorrectOperationException ignored) { + } + } + return Couple.getEmpty(); + } + + private static boolean isMatchIdentifier(@NotNull PsiElement element) { + return element.getText().equals(PyNames.MATCH); + } +} diff --git a/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithPatternWithoutGuardCondition.py b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithPatternWithoutGuardCondition.py new file mode 100644 index 000000000000..960d47f6c3ea --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithPatternWithoutGuardCondition.py @@ -0,0 +1,2 @@ +match x: + case int(n) if \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithPatternWithoutGuardCondition_after.py b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithPatternWithoutGuardCondition_after.py new file mode 100644 index 000000000000..24260a915325 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithPatternWithoutGuardCondition_after.py @@ -0,0 +1,2 @@ +match x: + case int(n) if : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPattern.py b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPattern.py new file mode 100644 index 000000000000..caebe607c0d0 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPattern.py @@ -0,0 +1,2 @@ +match x: + case \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithGuardCondition.py b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithGuardCondition.py new file mode 100644 index 000000000000..aab83f008831 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithGuardCondition.py @@ -0,0 +1,2 @@ +match x: + case if n > 0 \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithGuardCondition_after.py b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithGuardCondition_after.py new file mode 100644 index 000000000000..db925269e78a --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithGuardCondition_after.py @@ -0,0 +1,2 @@ +match x: + case if n > 0: \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithoutGuardCondition.py b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithoutGuardCondition.py new file mode 100644 index 000000000000..2acdf871d49c --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithoutGuardCondition.py @@ -0,0 +1,2 @@ +match x: + case if \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithoutGuardCondition_after.py b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithoutGuardCondition_after.py new file mode 100644 index 000000000000..5a949c200cc6 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPatternWithoutGuardCondition_after.py @@ -0,0 +1,2 @@ +match x: + case if : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPattern_after.py b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPattern_after.py new file mode 100644 index 000000000000..ce12806d3be8 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterCaseClauseWithoutPattern_after.py @@ -0,0 +1,2 @@ +match x: + case : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAfterEmptyMatchStatementWithoutSubject.py b/python/testData/codeInsight/smartEnter/colonAfterEmptyMatchStatementWithoutSubject.py new file mode 100644 index 000000000000..e010b2cc6f32 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterEmptyMatchStatementWithoutSubject.py @@ -0,0 +1 @@ +match \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAfterEmptyMatchStatementWithoutSubject_after.py b/python/testData/codeInsight/smartEnter/colonAfterEmptyMatchStatementWithoutSubject_after.py new file mode 100644 index 000000000000..5374301d6dbe --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAfterEmptyMatchStatementWithoutSubject_after.py @@ -0,0 +1 @@ +match : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnMatch.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnMatch.py new file mode 100644 index 000000000000..737da8323870 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnMatch.py @@ -0,0 +1 @@ +match x \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnMatch_after.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnMatch_after.py new file mode 100644 index 000000000000..ce12806d3be8 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnMatch_after.py @@ -0,0 +1,2 @@ +match x: + case : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnSubject.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnSubject.py new file mode 100644 index 000000000000..7daa2988fe5c --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnSubject.py @@ -0,0 +1 @@ +match x \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnSubject_after.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnSubject_after.py new file mode 100644 index 000000000000..ce12806d3be8 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnSubject_after.py @@ -0,0 +1,2 @@ +match x: + case : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCustomIndent.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCustomIndent.py new file mode 100644 index 000000000000..7daa2988fe5c --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCustomIndent.py @@ -0,0 +1 @@ +match x \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCustomIndent_after.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCustomIndent_after.py new file mode 100644 index 000000000000..a1e06f1c62f7 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectCustomIndent_after.py @@ -0,0 +1,2 @@ +match x: + case : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeBinaryExpression.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeBinaryExpression.py new file mode 100644 index 000000000000..be95a0166848 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeBinaryExpression.py @@ -0,0 +1 @@ +match -x \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeBinaryExpression_after.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeBinaryExpression_after.py new file mode 100644 index 000000000000..2ca17b9dffba --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeBinaryExpression_after.py @@ -0,0 +1,2 @@ +match -x: + case : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeCallExpression.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeCallExpression.py new file mode 100644 index 000000000000..34f440407ac2 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeCallExpression.py @@ -0,0 +1 @@ +match (x) \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeCallExpression_after.py b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeCallExpression_after.py new file mode 100644 index 000000000000..5389187e36a6 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeCallExpression_after.py @@ -0,0 +1,2 @@ +match (x): + case : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPattern.py b/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPattern.py new file mode 100644 index 000000000000..98e2561ddcb0 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPattern.py @@ -0,0 +1,2 @@ +match x: + case 42 \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPatternAndGuardCondition.py b/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPatternAndGuardCondition.py new file mode 100644 index 000000000000..7e5c5e591057 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPatternAndGuardCondition.py @@ -0,0 +1,2 @@ +match x: + case int(n) if n > 0 \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPatternAndGuardCondition_after.py b/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPatternAndGuardCondition_after.py new file mode 100644 index 000000000000..bb6ae6b26ff0 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPatternAndGuardCondition_after.py @@ -0,0 +1,3 @@ +match x: + case int(n) if n > 0: + \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPattern_after.py b/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPattern_after.py new file mode 100644 index 000000000000..43a3dd0d72ed --- /dev/null +++ b/python/testData/codeInsight/smartEnter/colonAndIndentAfterCaseClauseWithPattern_after.py @@ -0,0 +1,3 @@ +match x: + case 42: + \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/firstClauseAfterEmptyMatchStatementWithSubjectAndColon.py b/python/testData/codeInsight/smartEnter/firstClauseAfterEmptyMatchStatementWithSubjectAndColon.py new file mode 100644 index 000000000000..cc8f8f037147 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/firstClauseAfterEmptyMatchStatementWithSubjectAndColon.py @@ -0,0 +1 @@ +match x: \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/firstClauseAfterEmptyMatchStatementWithSubjectAndColon_after.py b/python/testData/codeInsight/smartEnter/firstClauseAfterEmptyMatchStatementWithSubjectAndColon_after.py new file mode 100644 index 000000000000..ce12806d3be8 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/firstClauseAfterEmptyMatchStatementWithSubjectAndColon_after.py @@ -0,0 +1,2 @@ +match x: + case : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/indentAfterCaseClauseWithPatternAndColon.py b/python/testData/codeInsight/smartEnter/indentAfterCaseClauseWithPatternAndColon.py new file mode 100644 index 000000000000..77cd0a1b18ca --- /dev/null +++ b/python/testData/codeInsight/smartEnter/indentAfterCaseClauseWithPatternAndColon.py @@ -0,0 +1,2 @@ +match x: + case 42: \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/indentAfterCaseClauseWithPatternAndColon_after.py b/python/testData/codeInsight/smartEnter/indentAfterCaseClauseWithPatternAndColon_after.py new file mode 100644 index 000000000000..43a3dd0d72ed --- /dev/null +++ b/python/testData/codeInsight/smartEnter/indentAfterCaseClauseWithPatternAndColon_after.py @@ -0,0 +1,3 @@ +match x: + case 42: + \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/lineBreakAndIndentAfterNonEmptyMatchStatementWithSubjectAndColon.py b/python/testData/codeInsight/smartEnter/lineBreakAndIndentAfterNonEmptyMatchStatementWithSubjectAndColon.py new file mode 100644 index 000000000000..8834b969ba5b --- /dev/null +++ b/python/testData/codeInsight/smartEnter/lineBreakAndIndentAfterNonEmptyMatchStatementWithSubjectAndColon.py @@ -0,0 +1,3 @@ +match x: + case 42: + pass \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/lineBreakAndIndentAfterNonEmptyMatchStatementWithSubjectAndColon_after.py b/python/testData/codeInsight/smartEnter/lineBreakAndIndentAfterNonEmptyMatchStatementWithSubjectAndColon_after.py new file mode 100644 index 000000000000..503cc23f0dab --- /dev/null +++ b/python/testData/codeInsight/smartEnter/lineBreakAndIndentAfterNonEmptyMatchStatementWithSubjectAndColon_after.py @@ -0,0 +1,4 @@ +match x: + + case 42: + pass \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/noFirstClauseInMatchStatementWithIncompleteStatementInside.py b/python/testData/codeInsight/smartEnter/noFirstClauseInMatchStatementWithIncompleteStatementInside.py new file mode 100644 index 000000000000..869fad5d9538 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/noFirstClauseInMatchStatementWithIncompleteStatementInside.py @@ -0,0 +1,2 @@ +match x: + ca \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/noFirstClauseInMatchStatementWithIncompleteStatementInside_after.py b/python/testData/codeInsight/smartEnter/noFirstClauseInMatchStatementWithIncompleteStatementInside_after.py new file mode 100644 index 000000000000..a3b23ab5cbe4 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/noFirstClauseInMatchStatementWithIncompleteStatementInside_after.py @@ -0,0 +1,3 @@ +match x: + ca + \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/nothingAfterUnambiguousExpressionStartingWithMatch.py b/python/testData/codeInsight/smartEnter/nothingAfterUnambiguousExpressionStartingWithMatch.py new file mode 100644 index 000000000000..aa4db83f7feb --- /dev/null +++ b/python/testData/codeInsight/smartEnter/nothingAfterUnambiguousExpressionStartingWithMatch.py @@ -0,0 +1 @@ +match / 42 \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/nothingAfterUnambiguousExpressionStartingWithMatch_after.py b/python/testData/codeInsight/smartEnter/nothingAfterUnambiguousExpressionStartingWithMatch_after.py new file mode 100644 index 000000000000..574ecde847c8 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/nothingAfterUnambiguousExpressionStartingWithMatch_after.py @@ -0,0 +1,2 @@ +match / 42 + \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithColonWithoutPattern.py b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithColonWithoutPattern.py new file mode 100644 index 000000000000..172983cb27ac --- /dev/null +++ b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithColonWithoutPattern.py @@ -0,0 +1,2 @@ +match x: + case : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithColonWithoutPattern_after.py b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithColonWithoutPattern_after.py new file mode 100644 index 000000000000..ce12806d3be8 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithColonWithoutPattern_after.py @@ -0,0 +1,2 @@ +match x: + case : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithGuardWithoutPattern.py b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithGuardWithoutPattern.py new file mode 100644 index 000000000000..f397ff4e91ad --- /dev/null +++ b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithGuardWithoutPattern.py @@ -0,0 +1,2 @@ +match x: + case if n > 0: \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithGuardWithoutPattern_after.py b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithGuardWithoutPattern_after.py new file mode 100644 index 000000000000..cd21e619b23e --- /dev/null +++ b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithGuardWithoutPattern_after.py @@ -0,0 +1,2 @@ +match x: + case if n > 0: \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithPatternAndColonWithoutGuardCondition.py b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithPatternAndColonWithoutGuardCondition.py new file mode 100644 index 000000000000..84106ad93162 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithPatternAndColonWithoutGuardCondition.py @@ -0,0 +1,2 @@ +match x: + case int(n) if: \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithPatternAndColonWithoutGuardCondition_after.py b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithPatternAndColonWithoutGuardCondition_after.py new file mode 100644 index 000000000000..fe08b07217a1 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterCaseClauseWithPatternAndColonWithoutGuardCondition_after.py @@ -0,0 +1,2 @@ +match x: + case int(n) if : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterMatchStatementWithColonWithoutSubject.py b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterMatchStatementWithColonWithoutSubject.py new file mode 100644 index 000000000000..1f21701c22f4 --- /dev/null +++ b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterMatchStatementWithColonWithoutSubject.py @@ -0,0 +1 @@ +match : \ No newline at end of file diff --git a/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterMatchStatementWithColonWithoutSubject_after.py b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterMatchStatementWithColonWithoutSubject_after.py new file mode 100644 index 000000000000..5374301d6dbe --- /dev/null +++ b/python/testData/codeInsight/smartEnter/onlyCaretMoveAfterMatchStatementWithColonWithoutSubject_after.py @@ -0,0 +1 @@ +match : \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PySmartEnterTest.java b/python/testSrc/com/jetbrains/python/PySmartEnterTest.java index 624f6d5ebb40..86d8788233b3 100644 --- a/python/testSrc/com/jetbrains/python/PySmartEnterTest.java +++ b/python/testSrc/com/jetbrains/python/PySmartEnterTest.java @@ -358,4 +358,110 @@ public class PySmartEnterTest extends PyTestCase { public void testColonAfterReturnTypeAnnotation() { runWithLanguageLevel(LanguageLevel.PYTHON34, this::doTest); } + + // PY-48014 + public void testColonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnSubject() { + doTest(); + } + + // PY-48014 + public void testColonAndFirstClauseAfterEmptyMatchStatementWithSubjectCaretOnMatch() { + doTest(); + } + + // PY-48014 + public void testColonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeBinaryExpression() { + doTest(); + } + + // PY-48014 + public void testColonAndFirstClauseAfterEmptyMatchStatementWithSubjectLookingLikeCallExpression() { + doTest(); + } + + // PY-48014 + public void testNothingAfterUnambiguousExpressionStartingWithMatch() { + doTest(); + } + + // PY-48014 + public void testColonAndFirstClauseAfterEmptyMatchStatementWithSubjectCustomIndent() { + getIndentOptions().INDENT_SIZE = 2; + doTest(); + } + + // PY-48014 + public void testColonAfterEmptyMatchStatementWithoutSubject() { + doTest(); + } + + // PY-48014 + public void testOnlyCaretMoveAfterMatchStatementWithColonWithoutSubject() { + doTest(); + } + + // PY-48014 + public void testFirstClauseAfterEmptyMatchStatementWithSubjectAndColon() { + doTest(); + } + + // PY-48014 + public void testLineBreakAndIndentAfterNonEmptyMatchStatementWithSubjectAndColon() { + doTest(); + } + + // PY-48014 + public void testNoFirstClauseInMatchStatementWithIncompleteStatementInside() { + doTest(); + } + + // PY-48014 + public void testColonAndIndentAfterCaseClauseWithPattern() { + doTest(); + } + + // PY-48014 + public void testColonAfterCaseClauseWithoutPattern() { + doTest(); + } + + // PY-48014 + public void testOnlyCaretMoveAfterCaseClauseWithColonWithoutPattern() { + doTest(); + } + + // PY-48014 + public void testIndentAfterCaseClauseWithPatternAndColon() { + doTest(); + } + + // PY-48014 + public void testColonAndIndentAfterCaseClauseWithPatternAndGuardCondition() { + doTest(); + } + + // PY-48014 + public void testColonAfterCaseClauseWithPatternWithoutGuardCondition() { + doTest(); + } + + // PY-48014 + public void testOnlyCaretMoveAfterCaseClauseWithGuardWithoutPattern() { + doTest(); + } + + // PY-48014 + public void testOnlyCaretMoveAfterCaseClauseWithPatternAndColonWithoutGuardCondition() { + doTest(); + } + + // PY-48014 + public void testColonAfterCaseClauseWithoutPatternWithoutGuardCondition() { + doTest(); + } + + // PY-48014 + public void testColonAfterCaseClauseWithoutPatternWithGuardCondition() { + doTest(); + } }