From 68f080743ce5dd0a3b6d01cb26101f8f674f8c7f Mon Sep 17 00:00:00 2001 From: Petr Golubev Date: Thu, 3 Nov 2022 02:01:38 +0100 Subject: [PATCH] move python formatter extensions to python.psi.impl module GitOrigin-RevId: 452346cbd12e9c21c636dc8dbcab9a29813bc67b --- .../codeStyle/PostFormatProcessorHelper.java | 0 .../resources/META-INF/IdeCore.xml | 2 + .../editor/actions/CaretStopOptions.kt | 0 .../openapi/editor/ex/BidiTextDirection.java | 0 .../ex/EditorSettingsExternalizable.java | 0 .../softwrap/SoftWrapAppliancePlaces.java | 0 .../src/com/intellij/ide/GeneralSettings.java | 20 ++- .../src/com/intellij/ide/BrowserUtil.java | 15 -- .../src/META-INF/PlatformExtensions.xml | 3 - .../python/PythonCommonFormatterTest.java} | 25 +-- .../PythonCommonCodeInsightTestFixture.kt | 2 + .../python/fixture/PythonCommonTestCase.java | 19 ++ .../intellij.python.commonTests.iml | 2 + .../resources/META-INF/PythonPsiImpl.xml | 8 + .../python/editor/PyWhiteSpaceUtil.java | 166 ++++++++++++++++++ .../PyFromImportPostFormatProcessor.java | 0 .../formatter/PyLineWrapPositionStrategy.java | 0 .../formatter/PyPreFormatProcessor.java | 0 ...TrailingBlankLinesPostFormatProcessor.java | 0 .../PyWhiteSpaceFormattingStrategy.java | 6 +- python/src/META-INF/python-core-common.xml | 7 - .../python/editor/PythonEnterHandler.java | 158 +---------------- .../jetbrains/python/PythonFormatterTest.java | 13 ++ .../PythonPlatformCodeInsightTestFixture.kt | 2 + 24 files changed, 249 insertions(+), 199 deletions(-) rename platform/{lang-impl => code-style-impl}/src/com/intellij/psi/impl/source/codeStyle/PostFormatProcessorHelper.java (100%) rename platform/{platform-impl => ide-core-impl}/src/com/intellij/openapi/editor/actions/CaretStopOptions.kt (100%) rename platform/{platform-impl => ide-core-impl}/src/com/intellij/openapi/editor/ex/BidiTextDirection.java (100%) rename platform/{platform-impl => ide-core-impl}/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java (100%) rename platform/{platform-impl => ide-core-impl}/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapAppliancePlaces.java (100%) rename platform/{platform-api => ide-core}/src/com/intellij/ide/GeneralSettings.java (94%) rename python/{testSrc/com/jetbrains/python/PyFormatterTest.java => python-common-tests/com/jetbrains/python/PythonCommonFormatterTest.java} (98%) create mode 100644 python/python-psi-impl/src/com/jetbrains/python/editor/PyWhiteSpaceUtil.java rename python/{ => python-psi-impl}/src/com/jetbrains/python/formatter/PyFromImportPostFormatProcessor.java (100%) rename python/{ => python-psi-impl}/src/com/jetbrains/python/formatter/PyLineWrapPositionStrategy.java (100%) rename python/{ => python-psi-impl}/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java (100%) rename python/{ => python-psi-impl}/src/com/jetbrains/python/formatter/PyTrailingBlankLinesPostFormatProcessor.java (100%) rename python/{ => python-psi-impl}/src/com/jetbrains/python/formatter/PyWhiteSpaceFormattingStrategy.java (95%) create mode 100644 python/testSrc/com/jetbrains/python/PythonFormatterTest.java diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PostFormatProcessorHelper.java b/platform/code-style-impl/src/com/intellij/psi/impl/source/codeStyle/PostFormatProcessorHelper.java similarity index 100% rename from platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/PostFormatProcessorHelper.java rename to platform/code-style-impl/src/com/intellij/psi/impl/source/codeStyle/PostFormatProcessorHelper.java diff --git a/platform/ide-core-impl/resources/META-INF/IdeCore.xml b/platform/ide-core-impl/resources/META-INF/IdeCore.xml index 3e591fc6b513..6869207d3302 100644 --- a/platform/ide-core-impl/resources/META-INF/IdeCore.xml +++ b/platform/ide-core-impl/resources/META-INF/IdeCore.xml @@ -9,5 +9,7 @@ serviceImplementation="com.intellij.util.download.impl.DownloadableFileServiceImpl"/> + + \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CaretStopOptions.kt b/platform/ide-core-impl/src/com/intellij/openapi/editor/actions/CaretStopOptions.kt similarity index 100% rename from platform/platform-impl/src/com/intellij/openapi/editor/actions/CaretStopOptions.kt rename to platform/ide-core-impl/src/com/intellij/openapi/editor/actions/CaretStopOptions.kt diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/BidiTextDirection.java b/platform/ide-core-impl/src/com/intellij/openapi/editor/ex/BidiTextDirection.java similarity index 100% rename from platform/platform-impl/src/com/intellij/openapi/editor/ex/BidiTextDirection.java rename to platform/ide-core-impl/src/com/intellij/openapi/editor/ex/BidiTextDirection.java diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java b/platform/ide-core-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java similarity index 100% rename from platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java rename to platform/ide-core-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapAppliancePlaces.java b/platform/ide-core-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapAppliancePlaces.java similarity index 100% rename from platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapAppliancePlaces.java rename to platform/ide-core-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapAppliancePlaces.java diff --git a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java b/platform/ide-core/src/com/intellij/ide/GeneralSettings.java similarity index 94% rename from platform/platform-api/src/com/intellij/ide/GeneralSettings.java rename to platform/ide-core/src/com/intellij/ide/GeneralSettings.java index 514a96849201..4391d1f3de0a 100644 --- a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java +++ b/platform/ide-core/src/com/intellij/ide/GeneralSettings.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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. +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide; import com.intellij.ide.ui.UINumericRange; @@ -8,6 +8,7 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.SystemInfo; import com.intellij.util.ObjectUtils; import com.intellij.util.PlatformUtils; import com.intellij.util.xmlb.XmlSerializerUtil; @@ -42,7 +43,7 @@ public final class GeneralSettings implements PersistentStateComponent /** @deprecated the result is a pain to deal with; please use {@link #getOpenBrowserCommand(String, String, List, boolean)} instead */ @Deprecated(forRemoval = true) diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index b68f446ff022..bd9e6114c7ff 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -160,8 +160,6 @@ - - @@ -638,7 +636,6 @@ - + + \ No newline at end of file diff --git a/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml b/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml index fff4307cdbf2..09cb9a15126c 100644 --- a/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml +++ b/python/python-psi-impl/resources/META-INF/PythonPsiImpl.xml @@ -51,6 +51,14 @@ implementationClass="com.jetbrains.python.psi.impl.references.PyKeywordPatternManipulator"/> + + + + + + + diff --git a/python/python-psi-impl/src/com/jetbrains/python/editor/PyWhiteSpaceUtil.java b/python/python-psi-impl/src/com/jetbrains/python/editor/PyWhiteSpaceUtil.java new file mode 100644 index 000000000000..9d9803566e74 --- /dev/null +++ b/python/python-psi-impl/src/com/jetbrains/python/editor/PyWhiteSpaceUtil.java @@ -0,0 +1,166 @@ +package com.jetbrains.python.editor; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.TreeUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.jetbrains.python.PyTokenTypes; +import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyPsiUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class PyWhiteSpaceUtil { + public static boolean needInsertBackslash(PsiFile file, int offset, boolean autoWrapInProgress) { + if (offset > 0) { + final PsiElement beforeCaret = file.findElementAt(offset - 1); + if (beforeCaret instanceof PsiWhiteSpace && beforeCaret.getText().indexOf('\\') >= 0) { + // we've got a backslash at EOL already, don't need another one + return false; + } + } + PsiElement atCaret = file.findElementAt(offset); + if (atCaret == null) { + return false; + } + ASTNode nodeAtCaret = atCaret.getNode(); + return needInsertBackslash(nodeAtCaret, autoWrapInProgress); + } + + public static boolean needInsertBackslash(ASTNode nodeAtCaret, boolean autoWrapInProgress) { + if (PsiTreeUtil.getParentOfType(nodeAtCaret.getPsi(), PyFStringFragment.class) != null) { + return false; + } + + PsiElement statementBefore = findStatementBeforeCaret(nodeAtCaret); + PsiElement statementAfter = findStatementAfterCaret(nodeAtCaret); + if (statementBefore != statementAfter) { // Enter pressed at statement break + return false; + } + if (statementBefore == null) { // empty file + return false; + } + + if (PsiTreeUtil.hasErrorElements(statementBefore)) { + if (!autoWrapInProgress) { + // code is already bad, don't mess it up even further + return false; + } + // if we're in middle of typing, it's expected that we will have error elements + } + + final int offset = nodeAtCaret.getTextRange().getStartOffset(); + if (inFromImportParentheses(statementBefore, offset) || inWithItemsParentheses(statementBefore, offset)) { + return false; + } + + PsiElement wrappableBefore = findWrappable(nodeAtCaret, true); + PsiElement wrappableAfter = findWrappable(nodeAtCaret, false); + if (!(wrappableBefore instanceof PsiComment)) { + while (wrappableBefore != null) { + PsiElement next = PsiTreeUtil.getParentOfType(wrappableBefore, PyEditorHandlerConfig.WRAPPABLE_CLASSES); + if (next == null) { + break; + } + wrappableBefore = next; + } + } + if (!(wrappableAfter instanceof PsiComment)) { + while (wrappableAfter != null) { + PsiElement next = PsiTreeUtil.getParentOfType(wrappableAfter, PyEditorHandlerConfig.WRAPPABLE_CLASSES); + if (next == null) { + break; + } + wrappableAfter = next; + } + } + if (wrappableBefore instanceof PsiComment || wrappableAfter instanceof PsiComment) { + return false; + } + if (wrappableAfter == null) { + return !(wrappableBefore instanceof PyDecoratorList); + } + return wrappableBefore != wrappableAfter; + } + + @Nullable + private static PsiElement findWrappable(ASTNode nodeAtCaret, boolean before) { + PsiElement wrappable = before + ? findBeforeCaret(nodeAtCaret, PyEditorHandlerConfig.WRAPPABLE_CLASSES) + : findAfterCaret(nodeAtCaret, PyEditorHandlerConfig.WRAPPABLE_CLASSES); + if (wrappable == null) { + PsiElement emptyTuple = before + ? findBeforeCaret(nodeAtCaret, PyTupleExpression.class) + : findAfterCaret(nodeAtCaret, PyTupleExpression.class); + if (emptyTuple != null && emptyTuple.getNode().getFirstChildNode().getElementType() == PyTokenTypes.LPAR) { + wrappable = emptyTuple; + } + } + return wrappable; + } + + @Nullable + private static PsiElement findStatementBeforeCaret(ASTNode node) { + return findBeforeCaret(node, PyStatement.class, PyStatementPart.class); + } + + @Nullable + private static PsiElement findStatementAfterCaret(ASTNode node) { + return findAfterCaret(node, PyStatement.class, PyStatementPart.class); + } + + private static PsiElement findBeforeCaret(ASTNode atCaret, Class... classes) { + while (atCaret != null) { + atCaret = TreeUtil.prevLeaf(atCaret); + if (atCaret != null && atCaret.getElementType() != TokenType.WHITE_SPACE) { + return getNonStrictParentOfType(atCaret.getPsi(), classes); + } + } + return null; + } + + private static PsiElement findAfterCaret(ASTNode atCaret, Class... classes) { + while (atCaret != null) { + if (atCaret.getElementType() != TokenType.WHITE_SPACE) { + return getNonStrictParentOfType(atCaret.getPsi(), classes); + } + atCaret = TreeUtil.nextLeaf(atCaret); + } + return null; + } + + @Nullable + private static T getNonStrictParentOfType(@NotNull PsiElement element, Class @NotNull ... classes) { + PsiElement run = element; + while (run != null) { + for (Class aClass : classes) { + if (aClass.isInstance(run)) return (T)run; + } + if (run instanceof PsiFile || run instanceof PyStatementList) break; + run = run.getParent(); + } + + return null; + } + + private static boolean inFromImportParentheses(PsiElement statement, int offset) { + if (!(statement instanceof PyFromImportStatement)) { + return false; + } + PyFromImportStatement fromImportStatement = (PyFromImportStatement)statement; + PsiElement leftParen = fromImportStatement.getLeftParen(); + if (leftParen != null && offset >= leftParen.getTextRange().getEndOffset()) { + return true; + } + return false; + } + + private static boolean inWithItemsParentheses(@NotNull PsiElement statement, int offset) { + if (!(statement instanceof PyWithStatement)) { + return false; + } + + final PsiElement leftParen = PyPsiUtils.getFirstChildOfType(statement, PyTokenTypes.LPAR); + return leftParen != null && offset >= leftParen.getTextRange().getEndOffset(); + } +} diff --git a/python/src/com/jetbrains/python/formatter/PyFromImportPostFormatProcessor.java b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyFromImportPostFormatProcessor.java similarity index 100% rename from python/src/com/jetbrains/python/formatter/PyFromImportPostFormatProcessor.java rename to python/python-psi-impl/src/com/jetbrains/python/formatter/PyFromImportPostFormatProcessor.java diff --git a/python/src/com/jetbrains/python/formatter/PyLineWrapPositionStrategy.java b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyLineWrapPositionStrategy.java similarity index 100% rename from python/src/com/jetbrains/python/formatter/PyLineWrapPositionStrategy.java rename to python/python-psi-impl/src/com/jetbrains/python/formatter/PyLineWrapPositionStrategy.java diff --git a/python/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java similarity index 100% rename from python/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java rename to python/python-psi-impl/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java diff --git a/python/src/com/jetbrains/python/formatter/PyTrailingBlankLinesPostFormatProcessor.java b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyTrailingBlankLinesPostFormatProcessor.java similarity index 100% rename from python/src/com/jetbrains/python/formatter/PyTrailingBlankLinesPostFormatProcessor.java rename to python/python-psi-impl/src/com/jetbrains/python/formatter/PyTrailingBlankLinesPostFormatProcessor.java diff --git a/python/src/com/jetbrains/python/formatter/PyWhiteSpaceFormattingStrategy.java b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyWhiteSpaceFormattingStrategy.java similarity index 95% rename from python/src/com/jetbrains/python/formatter/PyWhiteSpaceFormattingStrategy.java rename to python/python-psi-impl/src/com/jetbrains/python/formatter/PyWhiteSpaceFormattingStrategy.java index a2626b88ec04..3dc75f59eb4f 100644 --- a/python/src/com/jetbrains/python/formatter/PyWhiteSpaceFormattingStrategy.java +++ b/python/python-psi-impl/src/com/jetbrains/python/formatter/PyWhiteSpaceFormattingStrategy.java @@ -6,7 +6,7 @@ import com.intellij.openapi.util.text.Strings; import com.intellij.psi.PsiElement; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.StaticSymbolWhiteSpaceDefinitionStrategy; -import com.jetbrains.python.editor.PythonEnterHandler; +import com.jetbrains.python.editor.PyWhiteSpaceUtil; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.IntIterator; @@ -25,7 +25,7 @@ public class PyWhiteSpaceFormattingStrategy extends StaticSymbolWhiteSpaceDefini CodeStyleSettings codeStyleSettings) { CharSequence whiteSpace = super.adjustWhiteSpaceIfNecessary(whiteSpaceText, startElement, startOffset, endOffset, codeStyleSettings); if (whiteSpace.length() > 0 && whiteSpace.charAt(0) == '\n' && !Strings.contains(whiteSpace, 0, whiteSpace.length(), '\\') && - PythonEnterHandler.needInsertBackslash(startElement.getContainingFile(), startOffset, false)) { + PyWhiteSpaceUtil.needInsertBackslash(startElement.getContainingFile(), startOffset, false)) { return addBackslashPrefix(whiteSpace, codeStyleSettings); } return whiteSpace; @@ -60,7 +60,7 @@ public class PyWhiteSpaceFormattingStrategy extends StaticSymbolWhiteSpaceDefini Int2IntMap initialBackSlashes = countBackSlashes(text, startOffset, endOffset); if (initialBackSlashes.isEmpty()) { if (nodeAfter != null && whiteSpaceText.length() > 0 && whiteSpaceText.charAt(0) == '\n' && - PythonEnterHandler.needInsertBackslash(nodeAfter, false)) { + PyWhiteSpaceUtil.needInsertBackslash(nodeAfter, false)) { return addBackslashPrefix(whiteSpaceText, codeStyleSettings); } return whiteSpaceText; diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml index 3a5412f6ffa8..13cf7d3a9158 100644 --- a/python/src/META-INF/python-core-common.xml +++ b/python/src/META-INF/python-core-common.xml @@ -46,13 +46,6 @@ - - - - - - diff --git a/python/src/com/jetbrains/python/editor/PythonEnterHandler.java b/python/src/com/jetbrains/python/editor/PythonEnterHandler.java index f3c7d64de459..7c477392a522 100644 --- a/python/src/com/jetbrains/python/editor/PythonEnterHandler.java +++ b/python/src/com/jetbrains/python/editor/PythonEnterHandler.java @@ -17,7 +17,6 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.LineTokenizer; import com.intellij.psi.*; -import com.intellij.psi.impl.source.tree.TreeUtil; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; @@ -25,9 +24,7 @@ import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.codeInsight.PyCodeInsightSettings; import com.jetbrains.python.documentation.docstrings.*; import com.jetbrains.python.psi.*; -import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.regex.Matcher; @@ -145,85 +142,13 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter { Document doc) { boolean autoWrapInProgress = DataManager.getInstance().loadFromDataContext(dataContext, AutoHardWrapHandler.AUTO_WRAP_LINE_IN_PROGRESS_KEY) != null; - if (needInsertBackslash(file, offset, autoWrapInProgress)) { + if (PyWhiteSpaceUtil.needInsertBackslash(file, offset, autoWrapInProgress)) { doc.insertString(offset, "\\"); caretOffset.set(caretOffset.get() + 1); } return Result.Continue; } - public static boolean needInsertBackslash(PsiFile file, int offset, boolean autoWrapInProgress) { - if (offset > 0) { - final PsiElement beforeCaret = file.findElementAt(offset - 1); - if (beforeCaret instanceof PsiWhiteSpace && beforeCaret.getText().indexOf('\\') >= 0) { - // we've got a backslash at EOL already, don't need another one - return false; - } - } - PsiElement atCaret = file.findElementAt(offset); - if (atCaret == null) { - return false; - } - ASTNode nodeAtCaret = atCaret.getNode(); - return needInsertBackslash(nodeAtCaret, autoWrapInProgress); - } - - public static boolean needInsertBackslash(ASTNode nodeAtCaret, boolean autoWrapInProgress) { - if (PsiTreeUtil.getParentOfType(nodeAtCaret.getPsi(), PyFStringFragment.class) != null) { - return false; - } - - PsiElement statementBefore = findStatementBeforeCaret(nodeAtCaret); - PsiElement statementAfter = findStatementAfterCaret(nodeAtCaret); - if (statementBefore != statementAfter) { // Enter pressed at statement break - return false; - } - if (statementBefore == null) { // empty file - return false; - } - - if (PsiTreeUtil.hasErrorElements(statementBefore)) { - if (!autoWrapInProgress) { - // code is already bad, don't mess it up even further - return false; - } - // if we're in middle of typing, it's expected that we will have error elements - } - - final int offset = nodeAtCaret.getTextRange().getStartOffset(); - if (inFromImportParentheses(statementBefore, offset) || inWithItemsParentheses(statementBefore, offset)) { - return false; - } - - PsiElement wrappableBefore = findWrappable(nodeAtCaret, true); - PsiElement wrappableAfter = findWrappable(nodeAtCaret, false); - if (!(wrappableBefore instanceof PsiComment)) { - while (wrappableBefore != null) { - PsiElement next = PsiTreeUtil.getParentOfType(wrappableBefore, PyEditorHandlerConfig.WRAPPABLE_CLASSES); - if (next == null) { - break; - } - wrappableBefore = next; - } - } - if (!(wrappableAfter instanceof PsiComment)) { - while (wrappableAfter != null) { - PsiElement next = PsiTreeUtil.getParentOfType(wrappableAfter, PyEditorHandlerConfig.WRAPPABLE_CLASSES); - if (next == null) { - break; - } - wrappableAfter = next; - } - } - if (wrappableBefore instanceof PsiComment || wrappableAfter instanceof PsiComment) { - return false; - } - if (wrappableAfter == null) { - return !(wrappableBefore instanceof PyDecoratorList); - } - return wrappableBefore != wrappableAfter; - } - private static void insertDocStringStub(Editor editor, PsiElement element, DocstringState state) { PyDocStringOwner docOwner = PsiTreeUtil.getParentOfType(element, PyDocStringOwner.class); if (docOwner != null) { @@ -244,87 +169,6 @@ public class PythonEnterHandler extends EnterHandlerDelegateAdapter { } } - @Nullable - private static PsiElement findWrappable(ASTNode nodeAtCaret, boolean before) { - PsiElement wrappable = before - ? findBeforeCaret(nodeAtCaret, PyEditorHandlerConfig.WRAPPABLE_CLASSES) - : findAfterCaret(nodeAtCaret, PyEditorHandlerConfig.WRAPPABLE_CLASSES); - if (wrappable == null) { - PsiElement emptyTuple = before - ? findBeforeCaret(nodeAtCaret, PyTupleExpression.class) - : findAfterCaret(nodeAtCaret, PyTupleExpression.class); - if (emptyTuple != null && emptyTuple.getNode().getFirstChildNode().getElementType() == PyTokenTypes.LPAR) { - wrappable = emptyTuple; - } - } - return wrappable; - } - - @Nullable - private static PsiElement findStatementBeforeCaret(ASTNode node) { - return findBeforeCaret(node, PyStatement.class, PyStatementPart.class); - } - - @Nullable - private static PsiElement findStatementAfterCaret(ASTNode node) { - return findAfterCaret(node, PyStatement.class, PyStatementPart.class); - } - - private static PsiElement findBeforeCaret(ASTNode atCaret, Class... classes) { - while (atCaret != null) { - atCaret = TreeUtil.prevLeaf(atCaret); - if (atCaret != null && atCaret.getElementType() != TokenType.WHITE_SPACE) { - return getNonStrictParentOfType(atCaret.getPsi(), classes); - } - } - return null; - } - - private static PsiElement findAfterCaret(ASTNode atCaret, Class... classes) { - while (atCaret != null) { - if (atCaret.getElementType() != TokenType.WHITE_SPACE) { - return getNonStrictParentOfType(atCaret.getPsi(), classes); - } - atCaret = TreeUtil.nextLeaf(atCaret); - } - return null; - } - - @Nullable - private static T getNonStrictParentOfType(@NotNull PsiElement element, Class @NotNull ... classes) { - PsiElement run = element; - while (run != null) { - for (Class aClass : classes) { - if (aClass.isInstance(run)) return (T)run; - } - if (run instanceof PsiFile || run instanceof PyStatementList) break; - run = run.getParent(); - } - - return null; - } - - private static boolean inFromImportParentheses(PsiElement statement, int offset) { - if (!(statement instanceof PyFromImportStatement)) { - return false; - } - PyFromImportStatement fromImportStatement = (PyFromImportStatement)statement; - PsiElement leftParen = fromImportStatement.getLeftParen(); - if (leftParen != null && offset >= leftParen.getTextRange().getEndOffset()) { - return true; - } - return false; - } - - private static boolean inWithItemsParentheses(@NotNull PsiElement statement, int offset) { - if (!(statement instanceof PyWithStatement)) { - return false; - } - - final PsiElement leftParen = PyPsiUtils.getFirstChildOfType(statement, PyTokenTypes.LPAR); - return leftParen != null && offset >= leftParen.getTextRange().getEndOffset(); - } - @Override public Result postProcessEnter(@NotNull PsiFile file, @NotNull Editor editor, diff --git a/python/testSrc/com/jetbrains/python/PythonFormatterTest.java b/python/testSrc/com/jetbrains/python/PythonFormatterTest.java new file mode 100644 index 000000000000..7c7f777f233c --- /dev/null +++ b/python/testSrc/com/jetbrains/python/PythonFormatterTest.java @@ -0,0 +1,13 @@ +// 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; + +import com.jetbrains.python.fixture.PythonCommonCodeInsightTestFixture; +import com.jetbrains.python.fixtures.PythonPlatformCodeInsightTestFixture; +import com.jetbrains.python.psi.LanguageLevel; + +public class PythonFormatterTest extends PythonCommonFormatterTest { + @Override + protected PythonCommonCodeInsightTestFixture getFixture() { + return new PythonPlatformCodeInsightTestFixture(LANGUAGE_LEVEL); + } +} diff --git a/python/testSrc/com/jetbrains/python/fixtures/PythonPlatformCodeInsightTestFixture.kt b/python/testSrc/com/jetbrains/python/fixtures/PythonPlatformCodeInsightTestFixture.kt index 1bedf968644d..47098d9ba3fd 100644 --- a/python/testSrc/com/jetbrains/python/fixtures/PythonPlatformCodeInsightTestFixture.kt +++ b/python/testSrc/com/jetbrains/python/fixtures/PythonPlatformCodeInsightTestFixture.kt @@ -42,6 +42,8 @@ class PythonPlatformCodeInsightTestFixture(languageLevel: LanguageLevel) : Pytho get() = requireNotNull(myDelegateFixture.tempDirFixture.getFile(".")) override val testRootDisposable: Disposable get() = myDelegateFixture.testRootDisposable + override val caretOffset: Int + get() = myDelegateFixture.caretOffset override fun setUp() { super.setUp()