PY-61639 Move PythonFormattingModelBuilder to python.syntax.core

GitOrigin-RevId: bdcbd076cd3c1531204eff35515b44cd0edc9f68
This commit is contained in:
Petr
2024-02-08 21:19:05 +01:00
committed by intellij-monorepo-bot
parent da4a4b066b
commit 85c54b3a4c
39 changed files with 469 additions and 386 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -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) {

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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()}.
*

View File

@@ -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.
*/

View File

@@ -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"/>

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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");

View File

@@ -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

View File

@@ -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.*;

View File

@@ -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()) {

View File

@@ -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.
*

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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() {

View File

@@ -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() {

View File

@@ -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();

View File

@@ -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);

View File

@@ -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

View File

@@ -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();

View File

@@ -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>

View File

@@ -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());
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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());