mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 13:31:28 +07:00
PY-61639 Move PythonFormattingModelBuilder to python.syntax.core
GitOrigin-RevId: bdcbd076cd3c1531204eff35515b44cd0edc9f68
This commit is contained in:
committed by
intellij-monorepo-bot
parent
da4a4b066b
commit
85c54b3a4c
@@ -2,10 +2,7 @@
|
||||
package com.jetbrains.python.ast;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayFactory;
|
||||
@@ -282,4 +279,21 @@ public interface PyAstFunction extends PsiNameIdentifierOwner, PyAstCompoundStat
|
||||
default void acceptPyVisitor(PyAstElementVisitor pyVisitor) {
|
||||
pyVisitor.visitPyFunction(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
default @Nullable PsiComment getTypeComment() {
|
||||
final PsiComment inlineComment = PyUtilCore.getCommentOnHeaderLine(this);
|
||||
if (inlineComment != null && PyUtilCore.getTypeCommentValue(inlineComment.getText()) != null) {
|
||||
return inlineComment;
|
||||
}
|
||||
|
||||
final PyAstStatementList statements = getStatementList();
|
||||
if (statements.getStatements().length != 0) {
|
||||
final PsiComment comment = ObjectUtils.tryCast(statements.getFirstChild(), PsiComment.class);
|
||||
if (comment != null && PyUtilCore.getTypeCommentValue(comment.getText()) != null) {
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
package com.jetbrains.python.ast;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.stubs.IStubElementType;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
@@ -165,4 +163,20 @@ public interface PyAstNamedParameter extends PyAstParameter, PsiNamedElement, Ps
|
||||
default void acceptPyVisitor(PyAstElementVisitor pyVisitor) {
|
||||
pyVisitor.visitPyNamedParameter(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
default PsiComment getTypeComment() {
|
||||
for (PsiElement next = getNextSibling(); next != null; next = next.getNextSibling()) {
|
||||
if (next.textContains('\n')) break;
|
||||
if (!(next instanceof PsiWhiteSpace)) {
|
||||
if (",".equals(next.getText())) continue;
|
||||
if (next instanceof PsiComment && PyUtilCore.getTypeCommentValue(next.getText()) != null) {
|
||||
return (PsiComment)next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
package com.jetbrains.python.ast;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import com.intellij.psi.PsiNamedElement;
|
||||
@@ -12,6 +13,7 @@ import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonDialectsTokenSetProvider;
|
||||
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.ast.docstring.DocStringUtilCore;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -205,4 +207,33 @@ public interface PyAstTargetExpression extends PyAstQualifiedExpression, PsiName
|
||||
default void acceptPyVisitor(PyAstElementVisitor pyVisitor) {
|
||||
pyVisitor.visitPyTargetExpression(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
default PsiComment getTypeComment() {
|
||||
PsiComment comment = null;
|
||||
final PyAstAssignmentStatement assignment = PsiTreeUtil.getParentOfType(this, PyAstAssignmentStatement.class);
|
||||
if (assignment != null) {
|
||||
final PyAstExpression assignedValue = assignment.getAssignedValue();
|
||||
if (assignedValue != null && !PsiTreeUtil.isAncestor(assignedValue, this, false)) {
|
||||
comment = ObjectUtils.tryCast(PyPsiUtilsCore.getNextNonWhitespaceSiblingOnSameLine(assignedValue), PsiComment.class);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyAstStatementListContainer forOrWith = null;
|
||||
final PyAstForPart forPart = PsiTreeUtil.getParentOfType(this, PyAstForPart.class);
|
||||
if (forPart != null && PsiTreeUtil.isAncestor(forPart.getTarget(), this, false)) {
|
||||
forOrWith = forPart;
|
||||
}
|
||||
final PyAstWithItem withPart = PsiTreeUtil.getParentOfType(this, PyAstWithItem.class);
|
||||
if (withPart != null && PsiTreeUtil.isAncestor(withPart.getTarget(), this, false)) {
|
||||
forOrWith = ObjectUtils.tryCast(withPart.getParent(), PyAstWithStatement.class);
|
||||
}
|
||||
|
||||
if (forOrWith != null) {
|
||||
comment = PyUtilCore.getCommentOnHeaderLine(forOrWith);
|
||||
}
|
||||
}
|
||||
return comment != null && PyUtilCore.getTypeCommentValue(comment.getText()) != null ? comment : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,24 @@
|
||||
*/
|
||||
package com.jetbrains.python.ast;
|
||||
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public interface PyAstTypeCommentOwner extends PsiElement {
|
||||
/**
|
||||
* Returns a special comment that follows element definition and starts with conventional "type:" prefix.
|
||||
* It is supposed to contain type annotation in PEP 484 compatible format. For further details see sections
|
||||
* <a href="https://www.python.org/dev/peps/pep-0484/#type-comments">Type Comments</a> and
|
||||
* <a href="https://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code">Suggested syntax for Python 2.7 and straddling code</a> and
|
||||
* in PEP 484.
|
||||
* <p/>
|
||||
* Use {@link #getTypeCommentAnnotation()} to get its content with the prefix stripped accessing either stubs or AST.
|
||||
*
|
||||
* @see #getTypeCommentAnnotation()
|
||||
*/
|
||||
@Nullable
|
||||
PsiComment getTypeComment();
|
||||
}
|
||||
|
||||
@@ -117,6 +117,24 @@ public final class PyPsiUtilsCore {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first non-whitespace sibling following the given element but within its line boundaries.
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiElement getNextNonWhitespaceSiblingOnSameLine(@NotNull PsiElement element) {
|
||||
PsiElement cur = element.getNextSibling();
|
||||
while (cur != null) {
|
||||
if (!(cur instanceof PsiWhiteSpace)) {
|
||||
return cur;
|
||||
}
|
||||
else if (cur.textContains('\n')) {
|
||||
break;
|
||||
}
|
||||
cur = cur.getNextSibling();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static abstract class TopLevelVisitor extends PyAstRecursiveElementVisitor {
|
||||
@Override
|
||||
public void visitPyElement(final @NotNull PyAstElement node) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
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.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
@@ -10,6 +12,7 @@ import com.intellij.util.ObjectUtils;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.ast.controlFlow.AstScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtilCore;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -17,6 +20,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Assorted utility methods for Python code insight.
|
||||
@@ -28,6 +34,8 @@ import java.util.List;
|
||||
@ApiStatus.Experimental
|
||||
public final class PyUtilCore {
|
||||
|
||||
private static final Pattern TYPE_COMMENT_PATTERN = Pattern.compile("# *type: *([^#]+) *(#.*)?");
|
||||
|
||||
private PyUtilCore() {
|
||||
}
|
||||
|
||||
@@ -80,6 +88,28 @@ public final class PyUtilCore {
|
||||
return unfoldParentheses(targets, new ArrayList<>(targets.length), false, true);
|
||||
}
|
||||
|
||||
public static boolean onSameLine(@NotNull PsiElement e1, @NotNull PsiElement e2) {
|
||||
PsiFile firstFile = e1.getContainingFile();
|
||||
PsiFile secondFile = e2.getContainingFile();
|
||||
if (firstFile == null || secondFile == null) return false;
|
||||
Document document = firstFile.getFileDocument();
|
||||
if (document != secondFile.getFileDocument()) return false;
|
||||
return document.getLineNumber(e1.getTextOffset()) == document.getLineNumber(e2.getTextOffset());
|
||||
}
|
||||
|
||||
public static boolean isTopLevel(@NotNull PsiElement element) {
|
||||
if (element instanceof StubBasedPsiElement) {
|
||||
final StubElement stub = ((StubBasedPsiElement<?>)element).getStub();
|
||||
if (stub != null) {
|
||||
final StubElement parentStub = stub.getParentStub();
|
||||
if (parentStub != null) {
|
||||
return parentStub.getPsi() instanceof PsiFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ScopeUtilCore.getScopeOwner(element) instanceof PsiFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the document from {@link PsiDocumentManager} using the anchor PSI element and, if it's not null,
|
||||
* passes it to the consumer function.
|
||||
@@ -115,6 +145,10 @@ public final class PyUtilCore {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isSpecialName(@NotNull String name) {
|
||||
return name.length() > 4 && name.startsWith("__") && name.endsWith("__");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PyAstLoopStatement getCorrespondingLoop(@NotNull PsiElement breakOrContinue) {
|
||||
return breakOrContinue instanceof PyAstContinueStatement || breakOrContinue instanceof PyAstBreakStatement
|
||||
@@ -198,4 +232,67 @@ public final class PyUtilCore {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isAssignmentToModuleLevelDunderName(@Nullable PsiElement element) {
|
||||
if (element instanceof PyAstAssignmentStatement statement && isTopLevel(element)) {
|
||||
PyAstExpression[] targets = statement.getTargets();
|
||||
if (targets.length == 1) {
|
||||
String name = targets[0].getName();
|
||||
return name != null && isSpecialName(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the line comment that immediately precedes statement list of the given compound statement. Python parser ensures
|
||||
* that it follows the statement header, i.e. it's directly after the colon, not on its own line.
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiComment getCommentOnHeaderLine(@NotNull PyAstStatementListContainer container) {
|
||||
return ObjectUtils.tryCast(getHeaderEndAnchor(container), PsiComment.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiElement getHeaderEndAnchor(@NotNull PyAstStatementListContainer container) {
|
||||
final PyAstStatementList statementList = container.getStatementList();
|
||||
return Objects.requireNonNull(PsiTreeUtil.skipWhitespacesBackward(statementList));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that text of a comment starts with "# type:" prefix and returns trimmed type hint after it.
|
||||
* The trailing part is supposed to contain type annotation in PEP 484 compatible format and an optional
|
||||
* plain text comment separated from it with another "#".
|
||||
* <p>
|
||||
* For instance, for {@code # type: List[int] # comment} it returns {@code List[int]}.
|
||||
* <p>
|
||||
* This method cannot return an empty string.
|
||||
*
|
||||
* @see #getTypeCommentValueRange(String)
|
||||
*/
|
||||
@Nullable
|
||||
public static String getTypeCommentValue(@NotNull String text) {
|
||||
final Matcher m = TYPE_COMMENT_PATTERN.matcher(text);
|
||||
if (m.matches()) {
|
||||
return StringUtil.nullize(m.group(1).trim());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding text range for a type hint as returned by {@link #getTypeCommentValue(String)}.
|
||||
*
|
||||
* @see #getTypeCommentValue(String)
|
||||
*/
|
||||
@Nullable
|
||||
public static TextRange getTypeCommentValueRange(@NotNull String text) {
|
||||
final Matcher m = TYPE_COMMENT_PATTERN.matcher(text);
|
||||
if (m.matches()) {
|
||||
final String hint = getTypeCommentValue(text);
|
||||
if (hint != null) {
|
||||
return TextRange.from(m.start(1), hint.length());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.jetbrains.python.codeInsight.dataflow.scope;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.ast.controlFlow.AstScopeOwner;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.intellij.psi.util.PsiTreeUtil.getParentOfType;
|
||||
import static com.intellij.psi.util.PsiTreeUtil.isAncestor;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public final class ScopeUtilCore {
|
||||
/**
|
||||
* Return the scope owner for the element.
|
||||
*
|
||||
* Scope owner is not always the first ScopeOwner parent of the element. Some elements are resolved in outer scopes.
|
||||
*
|
||||
* This method does not access AST if underlying PSI is stub based.
|
||||
*/
|
||||
@Nullable
|
||||
public static AstScopeOwner getScopeOwner(@Nullable final PsiElement element) {
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
if (element instanceof PyAstExpressionCodeFragment) {
|
||||
final PsiElement context = element.getContext();
|
||||
return context instanceof AstScopeOwner ? (AstScopeOwner)context : getScopeOwner(context);
|
||||
}
|
||||
if (element instanceof StubBasedPsiElement) {
|
||||
final StubElement stub = ((StubBasedPsiElement<?>)element).getStub();
|
||||
if (stub != null) {
|
||||
StubElement parentStub = stub.getParentStub();
|
||||
while (parentStub != null) {
|
||||
final PsiElement parent = parentStub.getPsi();
|
||||
if (parent instanceof AstScopeOwner) {
|
||||
return (AstScopeOwner)parent;
|
||||
}
|
||||
parentStub = parentStub.getParentStub();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return CachedValuesManager.getCachedValue(element, () -> CachedValueProvider.Result
|
||||
.create(calculateScopeOwnerByAST(element), PsiModificationTracker.MODIFICATION_COUNT));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static AstScopeOwner calculateScopeOwnerByAST(@Nullable PsiElement element) {
|
||||
final AstScopeOwner firstOwner = getParentOfType(element, AstScopeOwner.class);
|
||||
if (firstOwner == null) {
|
||||
return null;
|
||||
}
|
||||
final AstScopeOwner nextOwner = getParentOfType(firstOwner, AstScopeOwner.class);
|
||||
// References in decorator expressions are resolved outside of the function (if the lambda is not inside the decorator)
|
||||
final PyAstElement decoratorAncestor = getParentOfType(element, PyAstDecorator.class);
|
||||
if (decoratorAncestor != null && !isAncestor(decoratorAncestor, firstOwner, true)) {
|
||||
return nextOwner;
|
||||
}
|
||||
/*
|
||||
* References in default values are resolved outside of the function (if the lambda is not inside the default value).
|
||||
* Annotations of parameters are resolved outside of the function if the function doesn't have type parameters list
|
||||
*/
|
||||
final PyAstNamedParameter parameterAncestor = getParentOfType(element, PyAstNamedParameter.class);
|
||||
if (parameterAncestor != null && !isAncestor(parameterAncestor, firstOwner, true)) {
|
||||
final PyAstExpression defaultValue = parameterAncestor.getDefaultValue();
|
||||
final PyAstAnnotation annotation = parameterAncestor.getAnnotation();
|
||||
if (firstOwner instanceof PyAstFunction function) {
|
||||
PyAstTypeParameterList typeParameterList = function.getTypeParameterList();
|
||||
if ((typeParameterList == null && isAncestor(annotation, element, false))
|
||||
|| (isAncestor(defaultValue, element, false))) {
|
||||
return nextOwner;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Superclasses are resolved outside of the class if the class doesn't have type parameters list
|
||||
final PyAstClass containingClass = getParentOfType(element, PyAstClass.class);
|
||||
if (containingClass != null && isAncestor(containingClass.getSuperClassExpressionList(), element, false) && containingClass.getTypeParameterList() == null) {
|
||||
return nextOwner;
|
||||
}
|
||||
// Function return annotations and type comments are resolved outside of the function if the function doesn't have type parameters list
|
||||
if (firstOwner instanceof PyAstFunction function) {
|
||||
PyAstTypeParameterList typeParameterList = function.getTypeParameterList();
|
||||
if ((typeParameterList == null && isAncestor(function.getAnnotation(), element, false)
|
||||
|| isAncestor(function.getTypeComment(), element, false))) {
|
||||
return nextOwner;
|
||||
}
|
||||
}
|
||||
return firstOwner;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,11 @@
|
||||
hashBangs="python"
|
||||
implementationClass="com.jetbrains.python.PythonFileType"
|
||||
fieldName="INSTANCE"/>
|
||||
<fileType name="PythonStub"
|
||||
language="PythonStub"
|
||||
extensions="pyi"
|
||||
implementationClass="com.jetbrains.python.pyi.PyiFileType"
|
||||
fieldName="INSTANCE"/>
|
||||
</extensions>
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="Pythonid.dialectsTokenSetContributor"
|
||||
|
||||
@@ -73,4 +73,6 @@ PARSE.function.type.annotations.py2=Type annotations are unsupported in Python 2
|
||||
PARSE.function.return.type.annotations.py2=Return type annotations are unsupported in Python 2
|
||||
|
||||
PARSE.console.multiline.magic.warn=Multiline magic cannot be used as an expression
|
||||
PARSE.console.help.request.warn=IPython introspection syntax error
|
||||
PARSE.console.help.request.warn=IPython introspection syntax error
|
||||
|
||||
filetype.python.stub.description=Python stub
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.jetbrains.python.pyi;
|
||||
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PyParsingBundle;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -36,7 +36,7 @@ public final class PyiFileType extends PythonFileType {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return PyPsiBundle.message("filetype.python.stub.description");
|
||||
return PyParsingBundle.message("filetype.python.stub.description");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.jetbrains.python.psi;
|
||||
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.jetbrains.python.ast.PyAstTypeCommentOwner;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -24,20 +23,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @author Mikhail Golubev
|
||||
*/
|
||||
public interface PyTypeCommentOwner extends PyAstTypeCommentOwner, PsiElement {
|
||||
/**
|
||||
* Returns a special comment that follows element definition and starts with conventional "type:" prefix.
|
||||
* It is supposed to contain type annotation in PEP 484 compatible format. For further details see sections
|
||||
* <a href="https://www.python.org/dev/peps/pep-0484/#type-comments">Type Comments</a> and
|
||||
* <a href="https://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code">Suggested syntax for Python 2.7 and straddling code</a> and
|
||||
* in PEP 484.
|
||||
* <p/>
|
||||
* Use {@link #getTypeCommentAnnotation()} to get its content with the prefix stripped accessing either stubs or AST.
|
||||
*
|
||||
* @see #getTypeCommentAnnotation()
|
||||
*/
|
||||
@Nullable
|
||||
PsiComment getTypeComment();
|
||||
|
||||
/**
|
||||
* Returns type annotation after the "type:" prefix extracted from the commentary returned by {@link #getTypeComment()}.
|
||||
*
|
||||
|
||||
@@ -90,24 +90,6 @@ public final class PyPsiUtils {
|
||||
return PsiTreeUtil.skipWhitespacesForward(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first non-whitespace sibling following the given element but within its line boundaries.
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiElement getNextNonWhitespaceSiblingOnSameLine(@NotNull PsiElement element) {
|
||||
PsiElement cur = element.getNextSibling();
|
||||
while (cur != null) {
|
||||
if (!(cur instanceof PsiWhiteSpace)) {
|
||||
return cur;
|
||||
}
|
||||
else if (cur.textContains('\n')) {
|
||||
break;
|
||||
}
|
||||
cur = cur.getNextSibling();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first non-whitespace sibling preceding the given element but within its line boundaries.
|
||||
*/
|
||||
|
||||
@@ -12,11 +12,6 @@
|
||||
<!-- We run it before FilePathCompletionContributor (id="filePath") to get help text about full path results in the extended completion -->
|
||||
<psi.referenceContributor implementation="com.jetbrains.python.codeInsight.PySoftFileReferenceContributor" language="Python"
|
||||
order="before filePath"/>
|
||||
<fileType name="PythonStub"
|
||||
language="PythonStub"
|
||||
extensions="pyi"
|
||||
implementationClass="com.jetbrains.python.pyi.PyiFileType"
|
||||
fieldName="INSTANCE"/>
|
||||
|
||||
<lang.elementManipulator forClass="com.jetbrains.python.psi.PyReferenceExpression"
|
||||
implementationClass="com.jetbrains.python.psi.impl.PyReferenceExpressionManipulator"/>
|
||||
@@ -72,7 +67,6 @@
|
||||
implementationClass="com.jetbrains.python.psi.impl.references.PyKeywordPatternManipulator"/>
|
||||
<lang.parserDefinition language="Python" implementationClass="com.jetbrains.python.PythonParserDefinition"/>
|
||||
|
||||
<lang.formatter language="Python" implementationClass="com.jetbrains.python.formatter.PythonFormattingModelBuilder"/>
|
||||
<preFormatProcessor implementation="com.jetbrains.python.formatter.PyPreFormatProcessor"/>
|
||||
<postFormatProcessor implementation="com.jetbrains.python.formatter.PyTrailingBlankLinesPostFormatProcessor"/>
|
||||
<postFormatProcessor implementation="com.jetbrains.python.formatter.PyFromImportPostFormatProcessor"/>
|
||||
|
||||
@@ -902,8 +902,6 @@ INSP.unresolved.refs.ignore.references.label=Ignored references:
|
||||
unresolved.docstring.param.reference=Function ''{0}'' does not have a parameter ''{1}''
|
||||
unresolved.import.reference=No module named ''{0}''
|
||||
|
||||
filetype.python.stub.description=Python stub
|
||||
|
||||
# PyRedundantParenthesesInspection
|
||||
INSP.NAME.redundant.parentheses=Redundant parentheses
|
||||
INSP.redundant.parens.ignore.empty.lists.of.base.classes=Ignore empty lists of base classes
|
||||
|
||||
@@ -16,11 +16,6 @@
|
||||
package com.jetbrains.python.codeInsight.dataflow.scope;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.StubBasedPsiElement;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
@@ -35,7 +30,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.psi.util.PsiTreeUtil.getParentOfType;
|
||||
import static com.intellij.psi.util.PsiTreeUtil.isAncestor;
|
||||
|
||||
public final class ScopeUtil {
|
||||
private ScopeUtil() {
|
||||
@@ -76,73 +70,7 @@ public final class ScopeUtil {
|
||||
*/
|
||||
@Nullable
|
||||
public static ScopeOwner getScopeOwner(@Nullable final PsiElement element) {
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
if (element instanceof PyExpressionCodeFragment) {
|
||||
final PsiElement context = element.getContext();
|
||||
return context instanceof ScopeOwner ? (ScopeOwner)context : getScopeOwner(context);
|
||||
}
|
||||
if (element instanceof StubBasedPsiElement) {
|
||||
final StubElement stub = ((StubBasedPsiElement<?>)element).getStub();
|
||||
if (stub != null) {
|
||||
StubElement parentStub = stub.getParentStub();
|
||||
while (parentStub != null) {
|
||||
final PsiElement parent = parentStub.getPsi();
|
||||
if (parent instanceof ScopeOwner) {
|
||||
return (ScopeOwner)parent;
|
||||
}
|
||||
parentStub = parentStub.getParentStub();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return CachedValuesManager.getCachedValue(element, () -> CachedValueProvider.Result
|
||||
.create(calculateScopeOwnerByAST(element), PsiModificationTracker.MODIFICATION_COUNT));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ScopeOwner calculateScopeOwnerByAST(@Nullable PsiElement element) {
|
||||
final ScopeOwner firstOwner = getParentOfType(element, ScopeOwner.class);
|
||||
if (firstOwner == null) {
|
||||
return null;
|
||||
}
|
||||
final ScopeOwner nextOwner = getParentOfType(firstOwner, ScopeOwner.class);
|
||||
// References in decorator expressions are resolved outside of the function (if the lambda is not inside the decorator)
|
||||
final PyElement decoratorAncestor = getParentOfType(element, PyDecorator.class);
|
||||
if (decoratorAncestor != null && !isAncestor(decoratorAncestor, firstOwner, true)) {
|
||||
return nextOwner;
|
||||
}
|
||||
/*
|
||||
* References in default values are resolved outside of the function (if the lambda is not inside the default value).
|
||||
* Annotations of parameters are resolved outside of the function if the function doesn't have type parameters list
|
||||
*/
|
||||
final PyNamedParameter parameterAncestor = getParentOfType(element, PyNamedParameter.class);
|
||||
if (parameterAncestor != null && !isAncestor(parameterAncestor, firstOwner, true)) {
|
||||
final PyExpression defaultValue = parameterAncestor.getDefaultValue();
|
||||
final PyAnnotation annotation = parameterAncestor.getAnnotation();
|
||||
if (firstOwner instanceof PyFunction function) {
|
||||
PyTypeParameterList typeParameterList = function.getTypeParameterList();
|
||||
if ((typeParameterList == null && isAncestor(annotation, element, false))
|
||||
|| (isAncestor(defaultValue, element, false))) {
|
||||
return nextOwner;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Superclasses are resolved outside of the class if the class doesn't have type parameters list
|
||||
final PyClass containingClass = getParentOfType(element, PyClass.class);
|
||||
if (containingClass != null && isAncestor(containingClass.getSuperClassExpressionList(), element, false) && containingClass.getTypeParameterList() == null) {
|
||||
return nextOwner;
|
||||
}
|
||||
// Function return annotations and type comments are resolved outside of the function if the function doesn't have type parameters list
|
||||
if (firstOwner instanceof PyFunction function) {
|
||||
PyTypeParameterList typeParameterList = function.getTypeParameterList();
|
||||
if ((typeParameterList == null && isAncestor(function.getAnnotation(), element, false)
|
||||
|| isAncestor(function.getTypeComment(), element, false))) {
|
||||
return nextOwner;
|
||||
}
|
||||
}
|
||||
return firstOwner;
|
||||
return (ScopeOwner)ScopeUtilCore.getScopeOwner(element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PythonCodeStyleService;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
import com.jetbrains.python.documentation.doctest.PyDocstringFile;
|
||||
@@ -228,7 +229,7 @@ public final class AddImportHelper {
|
||||
feeler = feeler.getNextSibling();
|
||||
seeker = feeler;
|
||||
}
|
||||
else if (isAssignmentToModuleLevelDunderName(feeler)) {
|
||||
else if (PyUtilCore.isAssignmentToModuleLevelDunderName(feeler)) {
|
||||
if (priority == ImportPriority.FUTURE) {
|
||||
seeker = feeler;
|
||||
break;
|
||||
@@ -820,17 +821,6 @@ public final class AddImportHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isAssignmentToModuleLevelDunderName(@Nullable PsiElement element) {
|
||||
if (element instanceof PyAssignmentStatement statement && PyUtil.isTopLevel(element)) {
|
||||
PyExpression[] targets = statement.getTargets();
|
||||
if (targets.length == 1) {
|
||||
String name = targets[0].getName();
|
||||
return name != null && PyUtil.isSpecialName(name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void addFileSystemItemImport(@NotNull PsiFileSystemItem target, @NotNull PsiFile file, @NotNull PyElement element) {
|
||||
final PsiFileSystemItem toImport = target.getParent();
|
||||
if (toImport == null) return;
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PythonUiService;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
|
||||
import com.jetbrains.python.codeInsight.imports.AddImportHelper.ImportPriority;
|
||||
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider;
|
||||
@@ -207,10 +208,10 @@ public final class PyTypeHintGenerationUtil {
|
||||
insertionAnchor = statement.getLastChild();
|
||||
}
|
||||
else if (statement instanceof PyWithStatement) {
|
||||
insertionAnchor = PyUtil.getHeaderEndAnchor((PyStatementListContainer)statement);
|
||||
insertionAnchor = PyUtilCore.getHeaderEndAnchor((PyStatementListContainer)statement);
|
||||
}
|
||||
else if (statement instanceof PyForStatement) {
|
||||
insertionAnchor = PyUtil.getHeaderEndAnchor(((PyForStatement)statement).getForPart());
|
||||
insertionAnchor = PyUtilCore.getHeaderEndAnchor(((PyForStatement)statement).getForPart());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Target expression must belong to an assignment, \"with\" statement or \"for\" loop");
|
||||
|
||||
@@ -4,7 +4,6 @@ package com.jetbrains.python.codeInsight.typing;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -20,6 +19,7 @@ import com.jetbrains.python.PyCustomType;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.ast.PyAstFunction;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
@@ -43,7 +43,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.intellij.openapi.util.RecursionManager.doPreventingRecursion;
|
||||
@@ -119,7 +118,6 @@ public final class PyTypingTypeProvider extends PyTypeProviderWithCustomContext<
|
||||
private static final String PY3_BINARY_FILE_TYPE = "typing.BinaryIO";
|
||||
private static final String PY3_TEXT_FILE_TYPE = "typing.TextIO";
|
||||
|
||||
private static final Pattern TYPE_COMMENT_PATTERN = Pattern.compile("# *type: *([^#]+) *(#.*)?");
|
||||
public static final Pattern TYPE_IGNORE_PATTERN = Pattern.compile("# *type: *ignore(\\[ *[^ ,\\]]+ *(, *[^ ,\\]]+ *)*\\])? *($|(#.*))",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
@@ -577,11 +575,7 @@ public final class PyTypingTypeProvider extends PyTypeProviderWithCustomContext<
|
||||
*/
|
||||
@Nullable
|
||||
public static String getTypeCommentValue(@NotNull String text) {
|
||||
final Matcher m = TYPE_COMMENT_PATTERN.matcher(text);
|
||||
if (m.matches()) {
|
||||
return StringUtil.nullize(m.group(1).trim());
|
||||
}
|
||||
return null;
|
||||
return PyUtilCore.getTypeCommentValue(text);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -591,14 +585,7 @@ public final class PyTypingTypeProvider extends PyTypeProviderWithCustomContext<
|
||||
*/
|
||||
@Nullable
|
||||
public static TextRange getTypeCommentValueRange(@NotNull String text) {
|
||||
final Matcher m = TYPE_COMMENT_PATTERN.matcher(text);
|
||||
if (m.matches()) {
|
||||
final String hint = getTypeCommentValue(text);
|
||||
if (hint != null) {
|
||||
return TextRange.from(m.start(1), hint.length());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return PyUtilCore.getTypeCommentValueRange(text);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.ast.docstring.DocStringUtilCore;
|
||||
import com.jetbrains.python.psi.*;
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PythonUiService;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -252,7 +253,7 @@ public final class PyPep8NamingInspection extends PyInspection {
|
||||
if (ignoreOverriddenFunctions && isOverriddenMethod(function)) return;
|
||||
final String name = function.getName();
|
||||
if (name == null) return;
|
||||
if (containingClass != null && (PyUtil.isSpecialName(name) || isIgnoredOrHasIgnoredAncestor(containingClass))) {
|
||||
if (containingClass != null && (PyUtilCore.isSpecialName(name) || isIgnoredOrHasIgnoredAncestor(containingClass))) {
|
||||
return;
|
||||
}
|
||||
if (!LOWERCASE_REGEX.matcher(name).matches()) {
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.ui.IconManager;
|
||||
@@ -344,26 +343,8 @@ public final class PyUtil {
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
public static boolean onSameLine(@NotNull PsiElement e1, @NotNull PsiElement e2) {
|
||||
PsiFile firstFile = e1.getContainingFile();
|
||||
PsiFile secondFile = e2.getContainingFile();
|
||||
if (firstFile == null || secondFile == null) return false;
|
||||
Document document = firstFile.getFileDocument();
|
||||
if (document != secondFile.getFileDocument()) return false;
|
||||
return document.getLineNumber(e1.getTextOffset()) == document.getLineNumber(e2.getTextOffset());
|
||||
}
|
||||
|
||||
public static boolean isTopLevel(@NotNull PsiElement element) {
|
||||
if (element instanceof StubBasedPsiElement) {
|
||||
final StubElement stub = ((StubBasedPsiElement<?>)element).getStub();
|
||||
if (stub != null) {
|
||||
final StubElement parentStub = stub.getParentStub();
|
||||
if (parentStub != null) {
|
||||
return parentStub.getPsi() instanceof PsiFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ScopeUtil.getScopeOwner(element) instanceof PsiFile;
|
||||
return PyUtilCore.isTopLevel(element);
|
||||
}
|
||||
|
||||
public static void deletePycFiles(String pyFilePath) {
|
||||
@@ -688,21 +669,6 @@ public final class PyUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the line comment that immediately precedes statement list of the given compound statement. Python parser ensures
|
||||
* that it follows the statement header, i.e. it's directly after the colon, not on its own line.
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiComment getCommentOnHeaderLine(@NotNull PyStatementListContainer container) {
|
||||
return as(getHeaderEndAnchor(container), PsiComment.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiElement getHeaderEndAnchor(@NotNull PyStatementListContainer container) {
|
||||
final PyStatementList statementList = container.getStatementList();
|
||||
return Objects.requireNonNull(PyPsiUtils.getPrevNonWhitespaceSibling(statementList));
|
||||
}
|
||||
|
||||
public static boolean isPy2ReservedWord(@NotNull PyReferenceExpression node) {
|
||||
if (LanguageLevel.forElement(node).isPython2()) {
|
||||
if (!node.isQualified()) {
|
||||
@@ -1014,10 +980,6 @@ public final class PyUtil {
|
||||
return name.startsWith("__") && !name.endsWith("__");
|
||||
}
|
||||
|
||||
public static boolean isSpecialName(@NotNull String name) {
|
||||
return name.length() > 4 && name.startsWith("__") && name.endsWith("__");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new lookup element for completion of keyword argument with equals sign appended.
|
||||
*
|
||||
|
||||
@@ -29,8 +29,8 @@ import com.jetbrains.python.PythonFileType;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.ast.PyAstElementVisitor;
|
||||
import com.jetbrains.python.ast.PyAstFunction;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.references.PyReferenceImpl;
|
||||
@@ -672,7 +672,7 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
|
||||
|
||||
// skip module level dunders
|
||||
boolean hasModuleLevelDunders = false;
|
||||
while (AddImportHelper.isAssignmentToModuleLevelDunderName(currentStatement)) {
|
||||
while (PyUtilCore.isAssignmentToModuleLevelDunderName(currentStatement)) {
|
||||
hasModuleLevelDunders = true;
|
||||
currentStatement = PyPsiUtils.getNextNonCommentSibling(currentStatement, true);
|
||||
}
|
||||
|
||||
@@ -17,18 +17,18 @@ import com.intellij.psi.util.*;
|
||||
import com.intellij.ui.IconManager;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyStubElementTypes;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider;
|
||||
import com.jetbrains.python.documentation.docstrings.DocStringUtil;
|
||||
import com.jetbrains.python.parser.icons.PythonParserIcons;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.icons.PythonPsiApiIcons;
|
||||
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
|
||||
@@ -472,23 +472,6 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
|
||||
return PyFunction.super.getAnnotationValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PsiComment getTypeComment() {
|
||||
final PsiComment inlineComment = PyUtil.getCommentOnHeaderLine(this);
|
||||
if (inlineComment != null && PyTypingTypeProvider.getTypeCommentValue(inlineComment.getText()) != null) {
|
||||
return inlineComment;
|
||||
}
|
||||
|
||||
final PyStatementList statements = getStatementList();
|
||||
if (statements.getStatements().length != 0) {
|
||||
final PsiComment comment = as(statements.getFirstChild(), PsiComment.class);
|
||||
if (comment != null && PyTypingTypeProvider.getTypeCommentValue(comment.getText()) != null) {
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getTypeCommentAnnotation() {
|
||||
return getTypeCommentAnnotationFromStubOrPsi(this);
|
||||
|
||||
@@ -16,9 +16,9 @@ import com.intellij.util.Processor;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyStubElementTypes;
|
||||
import com.jetbrains.python.ast.PyAstFunction;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.stubs.PyAnnotationOwnerStub;
|
||||
@@ -453,22 +453,6 @@ public class PyNamedParameterImpl extends PyBaseElementImpl<PyNamedParameterStub
|
||||
return new LocalSearchScope(getContainingFile());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiComment getTypeComment() {
|
||||
for (PsiElement next = getNextSibling(); next != null; next = next.getNextSibling()) {
|
||||
if (next.textContains('\n')) break;
|
||||
if (!(next instanceof PsiWhiteSpace)) {
|
||||
if (",".equals(next.getText())) continue;
|
||||
if (next instanceof PsiComment && PyTypingTypeProvider.getTypeCommentValue(next.getText()) != null) {
|
||||
return (PsiComment)next;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getTypeCommentAnnotation() {
|
||||
|
||||
@@ -14,10 +14,13 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.ui.IconManager;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyStubElementTypes;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
@@ -47,8 +50,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
|
||||
|
||||
public class PyTargetExpressionImpl extends PyBaseElementImpl<PyTargetExpressionStub> implements PyTargetExpression {
|
||||
@Nullable private volatile QualifiedName myQualifiedName;
|
||||
@@ -620,35 +621,6 @@ public class PyTargetExpressionImpl extends PyBaseElementImpl<PyTargetExpression
|
||||
return QualifiedNameFinder.getQualifiedName(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiComment getTypeComment() {
|
||||
PsiComment comment = null;
|
||||
final PyAssignmentStatement assignment = PsiTreeUtil.getParentOfType(this, PyAssignmentStatement.class);
|
||||
if (assignment != null) {
|
||||
final PyExpression assignedValue = assignment.getAssignedValue();
|
||||
if (assignedValue != null && !PsiTreeUtil.isAncestor(assignedValue, this, false)) {
|
||||
comment = as(PyPsiUtils.getNextNonWhitespaceSiblingOnSameLine(assignedValue), PsiComment.class);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyStatementListContainer forOrWith = null;
|
||||
final PyForPart forPart = PsiTreeUtil.getParentOfType(this, PyForPart.class);
|
||||
if (forPart != null && PsiTreeUtil.isAncestor(forPart.getTarget(), this, false)) {
|
||||
forOrWith = forPart;
|
||||
}
|
||||
final PyWithItem withPart = PsiTreeUtil.getParentOfType(this, PyWithItem.class);
|
||||
if (withPart != null && PsiTreeUtil.isAncestor(withPart.getTarget(), this, false)) {
|
||||
forOrWith = as(withPart.getParent(), PyWithStatement.class);
|
||||
}
|
||||
|
||||
if (forOrWith != null) {
|
||||
comment = PyUtil.getCommentOnHeaderLine(forOrWith);
|
||||
}
|
||||
}
|
||||
return comment != null && PyTypingTypeProvider.getTypeCommentValue(comment.getText()) != null ? comment : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getTypeCommentAnnotation() {
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.intellij.psi.ResolveResult;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PythonCodeStyleService;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.completion.OverwriteEqualsInsertHandler;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
@@ -76,7 +77,7 @@ public final class PyKeywordPatternReference extends PsiReferenceBase.Poly<PyKey
|
||||
|
||||
private static boolean isMeaningfulClassPatternAttribute(@NotNull LookupElement lookupElement) {
|
||||
String lookupString = lookupElement.getLookupString();
|
||||
if (lookupString.contains(".") || PyUtil.isSpecialName(lookupString)) {
|
||||
if (lookupString.contains(".") || PyUtilCore.isSpecialName(lookupString)) {
|
||||
return false;
|
||||
}
|
||||
PsiElement elem = lookupElement.getPsiElement();
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.psi.stubs.StubInputStream;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.stubs.PyTargetExpressionStub;
|
||||
import com.jetbrains.python.psi.stubs.PyTargetExpressionStub.InitializerType;
|
||||
@@ -84,7 +85,7 @@ public final class PyTypingAliasStubType extends CustomTargetExpressionStubType<
|
||||
return false;
|
||||
}
|
||||
final String name = target.getName();
|
||||
if (name == null || PyUtil.isSpecialName(name)) {
|
||||
if (name == null || PyUtilCore.isSpecialName(name)) {
|
||||
return false;
|
||||
}
|
||||
final PyAssignmentStatement assignment = PsiTreeUtil.getParentOfType(target, PyAssignmentStatement.class);
|
||||
|
||||
@@ -46,7 +46,7 @@ public final class PyiUtil {
|
||||
}
|
||||
|
||||
public static boolean isInsideStub(@NotNull PsiElement element) {
|
||||
return element.getContainingFile() instanceof PyiFile;
|
||||
return PyiUtilCore.isInsideStub(element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.NotNullPredicate;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
|
||||
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -86,7 +87,7 @@ public final class PyPsiRefactoringUtil {
|
||||
boolean toTheBeginning) {
|
||||
final PsiElement prevElem = PyPsiUtils.getPrevNonWhitespaceSibling(statementList);
|
||||
// If statement list is on the same line as previous element (supposedly colon), move its only statement on the next line
|
||||
if (prevElem != null && PyUtil.onSameLine(statementList, prevElem)) {
|
||||
if (prevElem != null && PyUtilCore.onSameLine(statementList, prevElem)) {
|
||||
final PsiDocumentManager manager = PsiDocumentManager.getInstance(statementList.getProject());
|
||||
final Document document = statementList.getContainingFile().getFileDocument();
|
||||
final PyStatementListContainer container = (PyStatementListContainer)statementList.getParent();
|
||||
|
||||
@@ -8,5 +8,7 @@
|
||||
<applicationService serviceImplementation="com.jetbrains.python.documentation.PyDocumentationSettings$AppService"/>
|
||||
<applicationService serviceInterface="com.jetbrains.python.PythonCodeStyleService"
|
||||
serviceImplementation="com.jetbrains.python.PythonCodeStyleServiceImpl"/>
|
||||
|
||||
<lang.formatter language="Python" implementationClass="com.jetbrains.python.formatter.PythonFormattingModelBuilder"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
@@ -17,10 +17,10 @@ import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonCodeStyleService;
|
||||
import com.jetbrains.python.PythonDialectsTokenSetProvider;
|
||||
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import com.jetbrains.python.pyi.PyiUtil;
|
||||
import com.jetbrains.python.ast.*;
|
||||
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.pyi.PyiUtilCore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -28,7 +28,6 @@ import java.util.*;
|
||||
|
||||
import static com.jetbrains.python.formatter.PyCodeStyleSettings.DICT_ALIGNMENT_ON_COLON;
|
||||
import static com.jetbrains.python.formatter.PyCodeStyleSettings.DICT_ALIGNMENT_ON_VALUE;
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
|
||||
|
||||
public class PyBlock implements ASTBlock {
|
||||
@@ -369,7 +368,7 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
else if (parentType == PyElementTypes.GENERATOR_EXPRESSION || parentType == PyElementTypes.PARENTHESIZED_EXPRESSION) {
|
||||
final boolean tupleOrGenerator = parentType == PyElementTypes.GENERATOR_EXPRESSION ||
|
||||
myNode.getPsi(PyParenthesizedExpression.class).getContainedExpression() instanceof PyTupleExpression;
|
||||
myNode.getPsi(PyAstParenthesizedExpression.class).getContainedExpression() instanceof PyAstTupleExpression;
|
||||
if ((childType == PyTokenTypes.RPAR && !(tupleOrGenerator && settings.HANG_CLOSING_BRACKETS)) ||
|
||||
!hasLineBreaksBeforeInSameParent(child, 1)) {
|
||||
childIndent = Indent.getNoneIndent();
|
||||
@@ -399,7 +398,7 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
}
|
||||
else if (parentType == PyElementTypes.SUBSCRIPTION_EXPRESSION) {
|
||||
final PyExpression indexExpression = ((PySubscriptionExpression)myNode.getPsi()).getIndexExpression();
|
||||
final PyAstExpression indexExpression = ((PyAstSubscriptionExpression)myNode.getPsi()).getIndexExpression();
|
||||
if (indexExpression != null && child == indexExpression.getNode()) {
|
||||
childIndent = Indent.getNormalIndent();
|
||||
}
|
||||
@@ -414,9 +413,9 @@ public class PyBlock implements ASTBlock {
|
||||
else {
|
||||
PyBlock b = myParent;
|
||||
while (b != null) {
|
||||
if (b.getNode().getPsi() instanceof PyParenthesizedExpression ||
|
||||
b.getNode().getPsi() instanceof PyArgumentList ||
|
||||
b.getNode().getPsi() instanceof PyParameterList) {
|
||||
if (b.getNode().getPsi() instanceof PyAstParenthesizedExpression ||
|
||||
b.getNode().getPsi() instanceof PyAstArgumentList ||
|
||||
b.getNode().getPsi() instanceof PyAstParameterList) {
|
||||
childAlignment = getAlignmentOfChild(b, 1);
|
||||
break;
|
||||
}
|
||||
@@ -514,13 +513,14 @@ public class PyBlock implements ASTBlock {
|
||||
|
||||
private static boolean isIfCondition(@NotNull ASTNode node) {
|
||||
@NotNull PsiElement element = node.getPsi();
|
||||
final PyIfPart ifPart = as(element.getParent(), PyIfPart.class);
|
||||
final PyAstIfPart ifPart = ObjectUtils.tryCast(element.getParent(), PyAstIfPart.class);
|
||||
return ifPart != null && ifPart.getCondition() == element && !ifPart.isElif();
|
||||
}
|
||||
|
||||
private static boolean isCondition(@NotNull ASTNode node) {
|
||||
final PsiElement element = node.getPsi();
|
||||
final PyConditionalStatementPart conditionalStatement = as(element.getParent(), PyConditionalStatementPart.class);
|
||||
final PyAstConditionalStatementPart conditionalStatement =
|
||||
ObjectUtils.tryCast(element.getParent(), PyAstConditionalStatementPart.class);
|
||||
return conditionalStatement != null && conditionalStatement.getCondition() == element;
|
||||
}
|
||||
|
||||
@@ -559,11 +559,11 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
|
||||
private static boolean isValueOfKeyValuePair(@NotNull ASTNode node) {
|
||||
return isChildOfKeyValuePair(node) && node.getTreeParent().getPsi(PyKeyValueExpression.class).getValue() == node.getPsi();
|
||||
return isChildOfKeyValuePair(node) && node.getTreeParent().getPsi(PyAstKeyValueExpression.class).getValue() == node.getPsi();
|
||||
}
|
||||
|
||||
private static boolean isEmptySequence(@NotNull ASTNode node) {
|
||||
return node.getPsi() instanceof PySequenceExpression && ((PySequenceExpression)node.getPsi()).isEmpty();
|
||||
return node.getPsi() instanceof PyAstSequenceExpression && ((PyAstSequenceExpression)node.getPsi()).isEmpty();
|
||||
}
|
||||
|
||||
private boolean argumentMayHaveSameIndentAsFollowingStatementList() {
|
||||
@@ -572,29 +572,29 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
// This check is supposed to prevent PEP8's error: Continuation line with the same indent as next logical line
|
||||
final PsiElement header = getControlStatementHeader(myNode);
|
||||
if (header instanceof PyStatementListContainer) {
|
||||
final PyStatementList statementList = ((PyStatementListContainer)header).getStatementList();
|
||||
return PyUtil.onSameLine(header, myNode.getPsi()) && !PyUtil.onSameLine(header, statementList);
|
||||
if (header instanceof PyAstStatementListContainer) {
|
||||
final PyAstStatementList statementList = ((PyAstStatementListContainer)header).getStatementList();
|
||||
return PyUtilCore.onSameLine(header, myNode.getPsi()) && !PyUtilCore.onSameLine(header, statementList);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check https://www.python.org/dev/peps/pep-0008/#indentation
|
||||
private static boolean hasHangingIndent(@NotNull PsiElement elem) {
|
||||
if (elem instanceof PyCallExpression) {
|
||||
final PyArgumentList argumentList = ((PyCallExpression)elem).getArgumentList();
|
||||
if (elem instanceof PyAstCallExpression) {
|
||||
final PyAstArgumentList argumentList = ((PyAstCallExpression)elem).getArgumentList();
|
||||
return argumentList != null && hasHangingIndent(argumentList);
|
||||
}
|
||||
else if (elem instanceof PyFunction) {
|
||||
return hasHangingIndent(((PyFunction)elem).getParameterList());
|
||||
else if (elem instanceof PyAstFunction) {
|
||||
return hasHangingIndent(((PyAstFunction)elem).getParameterList());
|
||||
}
|
||||
|
||||
final PsiElement firstChild;
|
||||
if (elem instanceof PyFromImportStatement) {
|
||||
firstChild = ((PyFromImportStatement)elem).getLeftParen();
|
||||
if (elem instanceof PyAstFromImportStatement) {
|
||||
firstChild = ((PyAstFromImportStatement)elem).getLeftParen();
|
||||
}
|
||||
else if (elem instanceof PyWithStatement) {
|
||||
firstChild = PyPsiUtils.getFirstChildOfType(elem, PyTokenTypes.LPAR);
|
||||
else if (elem instanceof PyAstWithStatement) {
|
||||
firstChild = PyPsiUtilsCore.getFirstChildOfType(elem, PyTokenTypes.LPAR);
|
||||
}
|
||||
else {
|
||||
firstChild = elem.getFirstChild();
|
||||
@@ -613,20 +613,20 @@ public class PyBlock implements ASTBlock {
|
||||
return !PyTokenTypes.CLOSE_BRACES.contains(elem.getLastChild().getNode().getElementType());
|
||||
}
|
||||
else {
|
||||
if (firstItem instanceof PyNamedParameter) {
|
||||
final PyExpression defaultValue = ((PyNamedParameter)firstItem).getDefaultValue();
|
||||
if (firstItem instanceof PyAstNamedParameter) {
|
||||
final PyAstExpression defaultValue = ((PyAstNamedParameter)firstItem).getDefaultValue();
|
||||
return defaultValue != null && hasHangingIndent(defaultValue);
|
||||
}
|
||||
else if (firstItem instanceof PyKeywordArgument) {
|
||||
final PyExpression valueExpression = ((PyKeywordArgument)firstItem).getValueExpression();
|
||||
else if (firstItem instanceof PyAstKeywordArgument) {
|
||||
final PyAstExpression valueExpression = ((PyAstKeywordArgument)firstItem).getValueExpression();
|
||||
return valueExpression != null && hasHangingIndent(valueExpression);
|
||||
}
|
||||
else if (firstItem instanceof PyKeyValueExpression) {
|
||||
final PyExpression value = ((PyKeyValueExpression)firstItem).getValue();
|
||||
else if (firstItem instanceof PyAstKeyValueExpression) {
|
||||
final PyAstExpression value = ((PyAstKeyValueExpression)firstItem).getValue();
|
||||
return value != null && hasHangingIndent(value);
|
||||
}
|
||||
else if (firstItem instanceof PyWithItem) {
|
||||
PyExpression contextExpression = ((PyWithItem)firstItem).getExpression();
|
||||
else if (firstItem instanceof PyAstWithItem) {
|
||||
PyAstExpression contextExpression = ((PyAstWithItem)firstItem).getExpression();
|
||||
return hasHangingIndent(contextExpression);
|
||||
}
|
||||
return hasHangingIndent(firstItem);
|
||||
@@ -640,32 +640,32 @@ public class PyBlock implements ASTBlock {
|
||||
@Nullable
|
||||
private static PsiElement getFirstItem(@NotNull PsiElement elem) {
|
||||
PsiElement[] items = PsiElement.EMPTY_ARRAY;
|
||||
if (elem instanceof PySequenceExpression) {
|
||||
items = ((PySequenceExpression)elem).getElements();
|
||||
if (elem instanceof PyAstSequenceExpression) {
|
||||
items = ((PyAstSequenceExpression)elem).getElements();
|
||||
}
|
||||
else if (elem instanceof PyParameterList) {
|
||||
items = ((PyParameterList)elem).getParameters();
|
||||
else if (elem instanceof PyAstParameterList) {
|
||||
items = ((PyAstParameterList)elem).getParameters();
|
||||
}
|
||||
else if (elem instanceof PyArgumentList) {
|
||||
items = ((PyArgumentList)elem).getArguments();
|
||||
else if (elem instanceof PyAstArgumentList) {
|
||||
items = ((PyAstArgumentList)elem).getArguments();
|
||||
}
|
||||
else if (elem instanceof PyFromImportStatement) {
|
||||
items = ((PyFromImportStatement)elem).getImportElements();
|
||||
else if (elem instanceof PyAstFromImportStatement) {
|
||||
items = ((PyAstFromImportStatement)elem).getImportElements();
|
||||
}
|
||||
else if (elem instanceof PyWithStatement) {
|
||||
items = ((PyWithStatement)elem).getWithItems();
|
||||
else if (elem instanceof PyAstWithStatement) {
|
||||
items = ((PyAstWithStatement)elem).getWithItems();
|
||||
}
|
||||
else if (elem instanceof PyParenthesizedExpression) {
|
||||
final PyExpression containedExpression = ((PyParenthesizedExpression)elem).getContainedExpression();
|
||||
if (containedExpression instanceof PyTupleExpression) {
|
||||
items = ((PyTupleExpression)containedExpression).getElements();
|
||||
else if (elem instanceof PyAstParenthesizedExpression) {
|
||||
final PyAstExpression containedExpression = ((PyAstParenthesizedExpression)elem).getContainedExpression();
|
||||
if (containedExpression instanceof PyAstTupleExpression) {
|
||||
items = ((PyAstTupleExpression)containedExpression).getElements();
|
||||
}
|
||||
else if (containedExpression != null) {
|
||||
return containedExpression;
|
||||
}
|
||||
}
|
||||
else if (elem instanceof PyComprehensionElement) {
|
||||
return ((PyComprehensionElement)elem).getResultExpression();
|
||||
else if (elem instanceof PyAstComprehensionElement) {
|
||||
return ((PyAstComprehensionElement)elem).getResultExpression();
|
||||
}
|
||||
return ArrayUtil.getFirstElement(items);
|
||||
}
|
||||
@@ -683,22 +683,22 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
|
||||
private static boolean isIndentNext(@NotNull ASTNode child) {
|
||||
final PsiElement psi = PsiTreeUtil.getParentOfType(child.getPsi(), PyStatement.class);
|
||||
final PsiElement psi = PsiTreeUtil.getParentOfType(child.getPsi(), PyAstStatement.class);
|
||||
|
||||
return psi instanceof PyIfStatement ||
|
||||
psi instanceof PyForStatement ||
|
||||
psi instanceof PyWithStatement ||
|
||||
psi instanceof PyClass ||
|
||||
psi instanceof PyFunction ||
|
||||
psi instanceof PyTryExceptStatement ||
|
||||
psi instanceof PyElsePart ||
|
||||
psi instanceof PyIfPart ||
|
||||
psi instanceof PyWhileStatement;
|
||||
return psi instanceof PyAstIfStatement ||
|
||||
psi instanceof PyAstForStatement ||
|
||||
psi instanceof PyAstWithStatement ||
|
||||
psi instanceof PyAstClass ||
|
||||
psi instanceof PyAstFunction ||
|
||||
psi instanceof PyAstTryExceptStatement ||
|
||||
psi instanceof PyAstElsePart ||
|
||||
psi instanceof PyAstIfPart ||
|
||||
psi instanceof PyAstWhileStatement;
|
||||
}
|
||||
|
||||
private static boolean isSubscriptionOperand(@NotNull ASTNode child) {
|
||||
return child.getTreeParent().getElementType() == PyElementTypes.SUBSCRIPTION_EXPRESSION &&
|
||||
child.getPsi() == ((PySubscriptionExpression)child.getTreeParent().getPsi()).getOperand();
|
||||
child.getPsi() == ((PyAstSubscriptionExpression)child.getTreeParent().getPsi()).getOperand();
|
||||
}
|
||||
|
||||
private boolean isInControlStatement() {
|
||||
@@ -707,11 +707,11 @@ public class PyBlock implements ASTBlock {
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getControlStatementHeader(@NotNull ASTNode node) {
|
||||
final PyStatementPart statementPart = PsiTreeUtil.getParentOfType(node.getPsi(), PyStatementPart.class, false, PyStatementList.class);
|
||||
final PyAstStatementPart statementPart = PsiTreeUtil.getParentOfType(node.getPsi(), PyAstStatementPart.class, false, PyAstStatementList.class);
|
||||
if (statementPart != null) {
|
||||
return statementPart;
|
||||
}
|
||||
final PyWithItem withItem = PsiTreeUtil.getParentOfType(node.getPsi(), PyWithItem.class);
|
||||
final PyAstWithItem withItem = PsiTreeUtil.getParentOfType(node.getPsi(), PyAstWithItem.class);
|
||||
if (withItem != null) {
|
||||
return withItem.getParent();
|
||||
}
|
||||
@@ -719,8 +719,8 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
|
||||
private boolean isSliceOperand(@NotNull ASTNode child) {
|
||||
if (myNode.getPsi() instanceof PySliceExpression sliceExpression) {
|
||||
final PyExpression operand = sliceExpression.getOperand();
|
||||
if (myNode.getPsi() instanceof PyAstSliceExpression sliceExpression) {
|
||||
final PyAstExpression operand = sliceExpression.getOperand();
|
||||
return operand.getNode() == child;
|
||||
}
|
||||
return false;
|
||||
@@ -728,11 +728,11 @@ public class PyBlock implements ASTBlock {
|
||||
|
||||
private static boolean isAfterStatementList(@NotNull ASTNode child) {
|
||||
final PsiElement prev = child.getPsi().getPrevSibling();
|
||||
if (!(prev instanceof PyStatement)) {
|
||||
if (!(prev instanceof PyAstStatement)) {
|
||||
return false;
|
||||
}
|
||||
final PsiElement lastChild = PsiTreeUtil.getDeepestLast(prev);
|
||||
return lastChild.getParent() instanceof PyStatementList;
|
||||
return lastChild.getParent() instanceof PyAstStatementList;
|
||||
}
|
||||
|
||||
private boolean needListAlignment(@NotNull ASTNode child) {
|
||||
@@ -876,14 +876,14 @@ public class PyBlock implements ASTBlock {
|
||||
|
||||
PsiElement psi2 = node2.getPsi();
|
||||
|
||||
if (psi2 instanceof PyStatementList) {
|
||||
if (psi2 instanceof PyAstStatementList) {
|
||||
// Quite odd getSpacing() doesn't get called with child1=null for the first statement
|
||||
// in the statement list of a class, yet it does get called for the preceding colon and
|
||||
// the statement list itself. Hence we have to handle blank lines around methods here in
|
||||
// addition to SpacingBuilder.
|
||||
if (myNode.getElementType() == PyElementTypes.CLASS_DECLARATION) {
|
||||
final PyStatement[] statements = ((PyStatementList)psi2).getStatements();
|
||||
if (statements.length > 0 && statements[0] instanceof PyFunction) {
|
||||
final PyAstStatement[] statements = ((PyAstStatementList)psi2).getStatements();
|
||||
if (statements.length > 0 && statements[0] instanceof PyAstFunction) {
|
||||
return getBlankLinesForOption(pySettings.BLANK_LINES_BEFORE_FIRST_METHOD);
|
||||
}
|
||||
}
|
||||
@@ -900,7 +900,7 @@ public class PyBlock implements ASTBlock {
|
||||
|
||||
// skip not inline comments to handles blank lines between various declarations
|
||||
if (psi2 instanceof PsiComment && hasLineBreaksBeforeInSameParent(node2, 1)) {
|
||||
final PsiElement nonCommentAfter = PyPsiUtils.getNextNonCommentSibling(psi2, true);
|
||||
final PsiElement nonCommentAfter = PyPsiUtilsCore.getNextNonCommentSibling(psi2, true);
|
||||
if (nonCommentAfter != null) {
|
||||
psi2 = nonCommentAfter;
|
||||
}
|
||||
@@ -927,14 +927,14 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
|
||||
if ((childType1 == PyTokenTypes.EQ || childType2 == PyTokenTypes.EQ)) {
|
||||
final PyNamedParameter namedParameter = as(myNode.getPsi(), PyNamedParameter.class);
|
||||
final PyAstNamedParameter namedParameter = ObjectUtils.tryCast(myNode.getPsi(), PyAstNamedParameter.class);
|
||||
if (namedParameter != null && namedParameter.getAnnotation() != null) {
|
||||
return Spacing.createSpacing(1, 1, 0, settings.KEEP_LINE_BREAKS, settings.KEEP_BLANK_LINES_IN_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
if (psi1 instanceof PyImportStatementBase) {
|
||||
if (psi2 instanceof PyImportStatementBase) {
|
||||
if (psi1 instanceof PyAstImportStatementBase) {
|
||||
if (psi2 instanceof PyAstImportStatementBase) {
|
||||
final Boolean leftImportIsGroupStart = psi1.getCopyableUserData(PythonCodeStyleService.IMPORT_GROUP_BEGIN);
|
||||
final Boolean rightImportIsGroupStart = psi2.getCopyableUserData(PythonCodeStyleService.IMPORT_GROUP_BEGIN);
|
||||
// Cleanup user data, it's no longer needed
|
||||
@@ -952,8 +952,8 @@ public class PyBlock implements ASTBlock {
|
||||
return Spacing.createSpacing(0, 0, 1, false, 0);
|
||||
}
|
||||
}
|
||||
if (psi2 instanceof PyStatement && !(psi2 instanceof PyImportStatementBase)) {
|
||||
if (PyUtil.isTopLevel(psi1)) {
|
||||
if (psi2 instanceof PyAstStatement && !(psi2 instanceof PyAstImportStatementBase)) {
|
||||
if (PyUtilCore.isTopLevel(psi1)) {
|
||||
// If there is any function or class after a top-level import, it should be top-level as well
|
||||
if (PyElementTypes.CLASS_OR_FUNCTION.contains(childType2)) {
|
||||
return getBlankLinesForOption(Math.max(settings.BLANK_LINES_AFTER_IMPORTS,
|
||||
@@ -967,14 +967,14 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
}
|
||||
|
||||
if (psi2 instanceof PyImportStatementBase && AddImportHelper.isAssignmentToModuleLevelDunderName(psi1)) {
|
||||
if (psi2 instanceof PyAstImportStatementBase && PyUtilCore.isAssignmentToModuleLevelDunderName(psi1)) {
|
||||
// blank line between module-level dunder name and import statement
|
||||
return Spacing.createSpacing(0, 0, 2, settings.KEEP_LINE_BREAKS, settings.KEEP_BLANK_LINES_IN_DECLARATIONS);
|
||||
}
|
||||
|
||||
if ((PyElementTypes.CLASS_OR_FUNCTION.contains(childType1) && STATEMENT_OR_DECLARATION.contains(childType2)) ||
|
||||
STATEMENT_OR_DECLARATION.contains(childType1) && PyElementTypes.CLASS_OR_FUNCTION.contains(childType2)) {
|
||||
if (PyUtil.isTopLevel(psi1)) {
|
||||
if (PyUtilCore.isTopLevel(psi1)) {
|
||||
return getBlankLinesForOption(pySettings.BLANK_LINES_AROUND_TOP_LEVEL_CLASSES_FUNCTIONS);
|
||||
}
|
||||
}
|
||||
@@ -992,11 +992,11 @@ public class PyBlock implements ASTBlock {
|
||||
|
||||
private boolean needLineBreakInStatement() {
|
||||
final PsiElement psiElement = myNode.getPsi();
|
||||
final boolean isInStubFile = PyiUtil.isInsideStub(psiElement);
|
||||
if (psiElement instanceof PyStatementListContainer) {
|
||||
final PyStatement statement = PsiTreeUtil.getParentOfType(psiElement, PyStatement.class);
|
||||
final boolean isInStubFile = PyiUtilCore.isInsideStub(psiElement);
|
||||
if (psiElement instanceof PyAstStatementListContainer) {
|
||||
final PyAstStatement statement = PsiTreeUtil.getParentOfType(psiElement, PyAstStatement.class);
|
||||
if (statement != null) {
|
||||
final Collection<PyStatementPart> parts = PsiTreeUtil.collectElementsOfType(statement, PyStatementPart.class);
|
||||
final Collection<PyAstStatementPart> parts = PsiTreeUtil.collectElementsOfType(statement, PyAstStatementPart.class);
|
||||
return (parts.size() == 1 && myContext.getPySettings().NEW_LINE_AFTER_COLON && !isInStubFile) ||
|
||||
(parts.size() > 1 && myContext.getPySettings().NEW_LINE_AFTER_COLON_MULTI_CLAUSE);
|
||||
}
|
||||
@@ -1014,7 +1014,7 @@ public class PyBlock implements ASTBlock {
|
||||
|
||||
if (newChildIndex > 0) {
|
||||
// always pass decision to a sane block from top level from file or definition
|
||||
if (myNode.getPsi() instanceof PyFile || myNode.getElementType() == PyTokenTypes.COLON) {
|
||||
if (myNode.getPsi() instanceof PyAstFile || myNode.getElementType() == PyTokenTypes.COLON) {
|
||||
return ChildAttributes.DELEGATE_TO_PREV_CHILD;
|
||||
}
|
||||
|
||||
@@ -1039,13 +1039,13 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
|
||||
// stmt lists, parts and definitions should also think for themselves
|
||||
if (prevElt instanceof PyStatementList) {
|
||||
if (dedentAfterLastStatement((PyStatementList)prevElt)) {
|
||||
if (prevElt instanceof PyAstStatementList) {
|
||||
if (dedentAfterLastStatement((PyAstStatementList)prevElt)) {
|
||||
return new ChildAttributes(Indent.getNoneIndent(), getChildAlignment());
|
||||
}
|
||||
return ChildAttributes.DELEGATE_TO_PREV_CHILD;
|
||||
}
|
||||
else if (prevElt instanceof PyStatementPart) {
|
||||
else if (prevElt instanceof PyAstStatementPart) {
|
||||
return ChildAttributes.DELEGATE_TO_PREV_CHILD;
|
||||
}
|
||||
|
||||
@@ -1058,7 +1058,7 @@ public class PyBlock implements ASTBlock {
|
||||
while (lastChild != null) {
|
||||
final IElementType lastType = lastChild.getElementType();
|
||||
if (lastType == PyElementTypes.STATEMENT_LIST && hasLineBreaksBeforeInSameParent(lastChild, 1)) {
|
||||
if (dedentAfterLastStatement((PyStatementList)lastChild.getPsi())) {
|
||||
if (dedentAfterLastStatement((PyAstStatementList)lastChild.getPsi())) {
|
||||
break;
|
||||
}
|
||||
statementListsBelow++;
|
||||
@@ -1099,20 +1099,20 @@ public class PyBlock implements ASTBlock {
|
||||
return new ChildAttributes(childIndent, childAlignment);
|
||||
}
|
||||
|
||||
private static boolean dedentAfterLastStatement(@NotNull PyStatementList statementList) {
|
||||
final PyStatement[] statements = statementList.getStatements();
|
||||
private static boolean dedentAfterLastStatement(@NotNull PyAstStatementList statementList) {
|
||||
final PyAstStatement[] statements = statementList.getStatements();
|
||||
if (statements.length == 0) {
|
||||
return false;
|
||||
}
|
||||
final PyStatement last = statements[statements.length - 1];
|
||||
return last instanceof PyReturnStatement || last instanceof PyRaiseStatement || last instanceof PyPassStatement || isEllipsis(last);
|
||||
final PyAstStatement last = statements[statements.length - 1];
|
||||
return last instanceof PyAstReturnStatement || last instanceof PyAstRaiseStatement || last instanceof PyAstPassStatement || isEllipsis(last);
|
||||
}
|
||||
|
||||
private static boolean isEllipsis(@NotNull PyStatement statement) {
|
||||
if (statement instanceof PyExpressionStatement) {
|
||||
final PyExpression expression = ((PyExpressionStatement)statement).getExpression();
|
||||
if (expression instanceof PyNoneLiteralExpression) {
|
||||
return ((PyNoneLiteralExpression)expression).isEllipsis();
|
||||
private static boolean isEllipsis(@NotNull PyAstStatement statement) {
|
||||
if (statement instanceof PyAstExpressionStatement) {
|
||||
final PyAstExpression expression = ((PyAstExpressionStatement)statement).getExpression();
|
||||
if (expression instanceof PyAstNoneLiteralExpression) {
|
||||
return ((PyAstNoneLiteralExpression)expression).isEllipsis();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1130,26 +1130,26 @@ public class PyBlock implements ASTBlock {
|
||||
return null;
|
||||
}
|
||||
final PsiElement elem = myNode.getPsi();
|
||||
if (elem instanceof PyParameterList && !myContext.getSettings().ALIGN_MULTILINE_PARAMETERS) {
|
||||
if (elem instanceof PyAstParameterList && !myContext.getSettings().ALIGN_MULTILINE_PARAMETERS) {
|
||||
return null;
|
||||
}
|
||||
if ((elem instanceof PySequenceExpression || elem instanceof PyComprehensionElement) &&
|
||||
if ((elem instanceof PyAstSequenceExpression || elem instanceof PyAstComprehensionElement) &&
|
||||
!myContext.getPySettings().ALIGN_COLLECTIONS_AND_COMPREHENSIONS) {
|
||||
return null;
|
||||
}
|
||||
if (elem instanceof PyParenthesizedExpression) {
|
||||
final PyExpression parenthesized = ((PyParenthesizedExpression)elem).getContainedExpression();
|
||||
if (parenthesized instanceof PyTupleExpression && !myContext.getPySettings().ALIGN_COLLECTIONS_AND_COMPREHENSIONS) {
|
||||
if (elem instanceof PyAstParenthesizedExpression) {
|
||||
final PyAstExpression parenthesized = ((PyAstParenthesizedExpression)elem).getContainedExpression();
|
||||
if (parenthesized instanceof PyAstTupleExpression && !myContext.getPySettings().ALIGN_COLLECTIONS_AND_COMPREHENSIONS) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (elem instanceof PyDictLiteralExpression) {
|
||||
final PyKeyValueExpression lastElement = ArrayUtil.getLastElement(((PyDictLiteralExpression)elem).getElements());
|
||||
if (elem instanceof PyAstDictLiteralExpression) {
|
||||
final PyAstKeyValueExpression lastElement = ArrayUtil.getLastElement(((PyAstDictLiteralExpression)elem).getElements());
|
||||
if (lastElement == null || lastElement.getValue() == null /* incomplete */) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (elem instanceof PyWithStatement && PyPsiUtils.getFirstChildOfType(elem, PyTokenTypes.LPAR) == null) {
|
||||
if (elem instanceof PyAstWithStatement && PyPsiUtilsCore.getFirstChildOfType(elem, PyTokenTypes.LPAR) == null) {
|
||||
return null;
|
||||
}
|
||||
return getAlignmentForChildren();
|
||||
@@ -1185,7 +1185,7 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
|
||||
if (afterNode != null && afterNode.getElementType() == PyElementTypes.KEY_VALUE_EXPRESSION) {
|
||||
final PyKeyValueExpression keyValue = (PyKeyValueExpression)afterNode.getPsi();
|
||||
final PyAstKeyValueExpression keyValue = (PyAstKeyValueExpression)afterNode.getPsi();
|
||||
if (keyValue != null && keyValue.getValue() == null) { // incomplete
|
||||
return Indent.getContinuationIndent();
|
||||
}
|
||||
@@ -1200,7 +1200,7 @@ public class PyBlock implements ASTBlock {
|
||||
if (ourCollectionLiteralTypes.contains(parentType) || parentType == PyElementTypes.TUPLE_EXPRESSION) {
|
||||
return settings.USE_CONTINUATION_INDENT_FOR_COLLECTION_AND_COMPREHENSIONS ? Indent.getContinuationIndent() : Indent.getNormalIndent();
|
||||
}
|
||||
else if (ourListElementTypes.contains(parentType) || myNode.getPsi() instanceof PyStatementPart) {
|
||||
else if (ourListElementTypes.contains(parentType) || myNode.getPsi() instanceof PyAstStatementPart) {
|
||||
return Indent.getNormalIndent();
|
||||
}
|
||||
|
||||
@@ -1263,7 +1263,7 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
}
|
||||
if (lastChild.getElementType() == PyElementTypes.BINARY_EXPRESSION) {
|
||||
final PyBinaryExpression binaryExpression = (PyBinaryExpression)lastChild.getPsi();
|
||||
final PyAstBinaryExpression binaryExpression = (PyAstBinaryExpression)lastChild.getPsi();
|
||||
if (binaryExpression.getRightExpression() == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -1271,7 +1271,7 @@ public class PyBlock implements ASTBlock {
|
||||
if (isIncompleteCall(lastChild)) return true;
|
||||
}
|
||||
|
||||
if (myNode.getPsi() instanceof PyArgumentList argumentList) {
|
||||
if (myNode.getPsi() instanceof PyAstArgumentList argumentList) {
|
||||
return argumentList.getClosingParen() == null;
|
||||
}
|
||||
if (isIncompleteCall(myNode) || isIncompleteExpressionWithBrackets(myNode.getPsi())) {
|
||||
@@ -1283,8 +1283,8 @@ public class PyBlock implements ASTBlock {
|
||||
|
||||
private static boolean isIncompleteCall(@NotNull ASTNode node) {
|
||||
if (node.getElementType() == PyElementTypes.CALL_EXPRESSION) {
|
||||
final PyCallExpression callExpression = (PyCallExpression)node.getPsi();
|
||||
final PyArgumentList argumentList = callExpression.getArgumentList();
|
||||
final PyAstCallExpression callExpression = (PyAstCallExpression)node.getPsi();
|
||||
final PyAstArgumentList argumentList = callExpression.getArgumentList();
|
||||
if (argumentList == null || argumentList.getClosingParen() == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -1293,7 +1293,7 @@ public class PyBlock implements ASTBlock {
|
||||
}
|
||||
|
||||
private static boolean isIncompleteExpressionWithBrackets(@NotNull PsiElement elem) {
|
||||
if (elem instanceof PySequenceExpression || elem instanceof PyComprehensionElement || elem instanceof PyParenthesizedExpression) {
|
||||
if (elem instanceof PyAstSequenceExpression || elem instanceof PyAstComprehensionElement || elem instanceof PyAstParenthesizedExpression) {
|
||||
return PyTokenTypes.OPEN_BRACES.contains(elem.getFirstChild().getNode().getElementType()) &&
|
||||
!PyTokenTypes.CLOSE_BRACES.contains(elem.getLastChild().getNode().getElementType());
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.jetbrains.python.pyi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public final class PyiUtilCore {
|
||||
public static boolean isInsideStub(@NotNull PsiElement element) {
|
||||
PsiFile file = element.getContainingFile();
|
||||
return file != null && file.getFileType() == PyiFileType.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import com.intellij.util.Processor
|
||||
import com.jetbrains.python.PyBundle
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore
|
||||
import com.jetbrains.python.psi.PyClass
|
||||
import com.jetbrains.python.psi.PyFile
|
||||
import com.jetbrains.python.psi.PyFunction
|
||||
@@ -41,7 +42,7 @@ class PyReferencesCodeVisionProvider : ReferencesCodeVisionProvider() {
|
||||
if (containingClass == null || !PyUtil.isTopLevel(containingClass)) return false
|
||||
}
|
||||
val elementName = element.name ?: return false
|
||||
return !PyUtil.isSpecialName(elementName)
|
||||
return !PyUtilCore.isSpecialName(elementName)
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.jetbrains.python.PyParsingBundle;
|
||||
import com.jetbrains.python.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
|
||||
import com.jetbrains.python.codeInsight.editorActions.smartEnter.SmartEnterUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -57,9 +58,9 @@ public class PyCollectionLiteralFixer extends PyFixer<PySequenceExpression> {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiElement nextOnSameLine = PyPsiUtils.getNextNonWhitespaceSiblingOnSameLine(collectionItem);
|
||||
PsiElement nextOnSameLine = PyPsiUtilsCore.getNextNonWhitespaceSiblingOnSameLine(collectionItem);
|
||||
if (nextOnSameLine != null && isMissingColonError(nextOnSameLine)) {
|
||||
nextOnSameLine = PyPsiUtils.getNextNonWhitespaceSiblingOnSameLine(nextOnSameLine);
|
||||
nextOnSameLine = PyPsiUtilsCore.getNextNonWhitespaceSiblingOnSameLine(nextOnSameLine);
|
||||
}
|
||||
if (nextOnSameLine == null || nextOnSameLine instanceof PsiComment) {
|
||||
int separatorOffset = collectionItem.getTextRange().getEndOffset();
|
||||
|
||||
@@ -10,6 +10,7 @@ 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.ast.impl.PyPsiUtilsCore;
|
||||
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
@@ -83,7 +84,7 @@ public final class PyMatchStatementFixer extends PyFixer<PyStatement> {
|
||||
}
|
||||
if (isMatchIdentifier(statement)) {
|
||||
// "<caret>match expr"
|
||||
PsiElement nextSibling = PyPsiUtils.getNextNonWhitespaceSiblingOnSameLine(statement);
|
||||
PsiElement nextSibling = PyPsiUtilsCore.getNextNonWhitespaceSiblingOnSameLine(statement);
|
||||
if (nextSibling instanceof PyExpressionStatement) {
|
||||
return Couple.of(statement, nextSibling);
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.ast.impl.PyUtilCore;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.psi.PyElement;
|
||||
import com.jetbrains.python.psi.PyFile;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyUtil;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import com.jetbrains.python.psi.search.PyOverridingMethodsSearch;
|
||||
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
|
||||
@@ -182,7 +182,7 @@ public final class PyMoveSymbolDelegate extends MoveHandlerDelegate {
|
||||
return false;
|
||||
}
|
||||
final String funcName = function.getName();
|
||||
if (funcName == null || PyUtil.isSpecialName(funcName)) {
|
||||
if (funcName == null || PyUtilCore.isSpecialName(funcName)) {
|
||||
return false;
|
||||
}
|
||||
final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(function.getProject(), function.getContainingFile());
|
||||
|
||||
Reference in New Issue
Block a user