PY-61639 Extracted PythonEnterHandler

GitOrigin-RevId: 8fd0c063c917e07c3f1bf98533c3de867f770ee9
This commit is contained in:
Petr Golubev
2024-01-24 16:22:01 +01:00
committed by intellij-monorepo-bot
parent 1a73bd2d21
commit 25b8ebcf83
74 changed files with 535 additions and 372 deletions

View File

@@ -90,6 +90,14 @@ public interface PyAstNamedParameter extends PyAstParameter, PsiNamedElement, Ps
return ParamHelperCore.getDefaultValueText(getDefaultValue());
}
/**
* @param includeDefaultValue if true, include the default value after an "=".
* @return canonical representation of parameter.
* Includes asterisks for *param and **param, and name.
*/
@NotNull
String getRepr(boolean includeDefaultValue);
@Override
@NotNull
default PyAstNamedParameter getAsNamed() {

View File

@@ -1,6 +1,7 @@
package com.jetbrains.python.ast.docstring;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.ast.PyAstDocStringOwner;
import com.jetbrains.python.ast.PyAstElement;
import com.jetbrains.python.ast.PyAstExpressionStatement;
@@ -35,4 +36,20 @@ public final class DocStringUtilCore {
}
return null;
}
/**
* Returns containing docstring expression of class definition, function definition or module.
* Useful to test whether particular PSI element is or belongs to such docstring.
*/
@Nullable
public static PyAstStringLiteralExpression getParentDefinitionDocString(@NotNull PsiElement element) {
final PyAstDocStringOwner docStringOwner = PsiTreeUtil.getParentOfType(element, PyAstDocStringOwner.class);
if (docStringOwner != null) {
final PyAstStringLiteralExpression docString = docStringOwner.getDocStringExpression();
if (PsiTreeUtil.isAncestor(docString, element, false)) {
return docString;
}
}
return null;
}
}

View File

@@ -12,6 +12,7 @@ import com.intellij.psi.util.QualifiedName;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.jetbrains.python.ast.*;
import com.jetbrains.python.psi.PyElementType;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -47,6 +48,20 @@ public final class PyPsiUtilsCore {
return PsiTreeUtil.skipWhitespacesAndCommentsForward(start);
}
/**
* Returns first child psi element with specified element type or {@code null} if no such element exists.
* Semantically it's the same as {@code getChildByFilter(element, TokenSet.create(type), 0)}.
*
* @param element tree parent node
* @param type element type expected
* @return child element described
*/
@Nullable
public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
final ASTNode child = element.getNode().findChildByType(type);
return child != null ? child.getPsi() : null;
}
/**
* Returns child element in the psi tree
*

View File

@@ -1,7 +1,11 @@
package com.jetbrains.python.ast.impl;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.ObjectUtils;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.ast.*;
@@ -76,6 +80,41 @@ public final class PyUtilCore {
return unfoldParentheses(targets, new ArrayList<>(targets.length), false, true);
}
/**
* Retrieves the document from {@link PsiDocumentManager} using the anchor PSI element and, if it's not null,
* passes it to the consumer function.
* <p>
* The document is first released from pending PSI operations and then committed after the function has been applied
* in a {@code try/finally} block, so that subsequent operations on PSI could be performed.
*
* @see PsiDocumentManager#doPostponedOperationsAndUnblockDocument(Document)
* @see PsiDocumentManager#commitDocument(Document)
* @see #updateDocumentUnblockedAndCommitted(PsiElement, Function)
*/
public static void updateDocumentUnblockedAndCommitted(@NotNull PsiElement anchor, @NotNull Consumer<? super Document> consumer) {
updateDocumentUnblockedAndCommitted(anchor, document -> {
consumer.consume(document);
return null;
});
}
@Nullable
public static <T> T updateDocumentUnblockedAndCommitted(@NotNull PsiElement anchor, @NotNull Function<? super Document, ? extends T> func) {
final PsiDocumentManager manager = PsiDocumentManager.getInstance(anchor.getProject());
// manager.getDocument(anchor.getContainingFile()) doesn't work with intention preview
final Document document = anchor.getContainingFile().getViewProvider().getDocument();
if (document != null) {
manager.doPostponedOperationsAndUnblockDocument(document);
try {
return func.fun(document);
}
finally {
manager.commitDocument(document);
}
}
return null;
}
@Nullable
public static PyAstLoopStatement getCorrespondingLoop(@NotNull PsiElement breakOrContinue) {
return breakOrContinue instanceof PyAstContinueStatement || breakOrContinue instanceof PyAstBreakStatement