diff --git a/python/python-psi-impl/resources/intellij.python.psi.impl.xml b/python/python-psi-impl/resources/intellij.python.psi.impl.xml
index 9607e1d50e04..bf210ecaf980 100644
--- a/python/python-psi-impl/resources/intellij.python.psi.impl.xml
+++ b/python/python-psi-impl/resources/intellij.python.psi.impl.xml
@@ -170,14 +170,7 @@
-
-
-
-
-
-
-
diff --git a/python/python-psi-impl/src/com/jetbrains/python/validation/PyFStringsAnnotator.java b/python/python-psi-impl/src/com/jetbrains/python/validation/PyFStringsAnnotator.java
index 23ce375ed59e..90ef8b4fad4a 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/validation/PyFStringsAnnotator.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/validation/PyFStringsAnnotator.java
@@ -29,71 +29,63 @@ import org.jetbrains.annotations.NotNull;
/**
* @author Mikhail Golubev
*/
-public final class PyFStringsAnnotator extends PyAnnotatorBase {
+final class PyFStringsAnnotator extends PyElementVisitor {
+ private final @NotNull PyAnnotationHolder myHolder;
+
+ PyFStringsAnnotator(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
@Override
- public void annotate(@NotNull PsiElement element, @NotNull PyAnnotationHolder holder) {
- element.accept(new MyVisitor(holder));
- }
-
- private static class MyVisitor extends PyElementVisitor {
- private final @NotNull PyAnnotationHolder myHolder;
-
- private MyVisitor(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
-
- @Override
- public void visitPyFStringFragment(@NotNull PyFStringFragment node) {
- final PsiElement typeConversion = node.getTypeConversion();
- if (typeConversion != null) {
- final String conversionChar = typeConversion.getText().substring(1);
- if (conversionChar.isEmpty()) {
- report(typeConversion, PyPsiBundle.message("ANN.fstrings.missing.conversion.character"));
- }
- else if (conversionChar.length() > 1 || "sra".indexOf(conversionChar.charAt(0)) < 0) {
- report(typeConversion, PyPsiBundle.message("ANN.fstrings.illegal.conversion.character", conversionChar));
- }
+ public void visitPyFStringFragment(@NotNull PyFStringFragment node) {
+ final PsiElement typeConversion = node.getTypeConversion();
+ if (typeConversion != null) {
+ final String conversionChar = typeConversion.getText().substring(1);
+ if (conversionChar.isEmpty()) {
+ report(typeConversion, PyPsiBundle.message("ANN.fstrings.missing.conversion.character"));
+ }
+ else if (conversionChar.length() > 1 || "sra".indexOf(conversionChar.charAt(0)) < 0) {
+ report(typeConversion, PyPsiBundle.message("ANN.fstrings.illegal.conversion.character", conversionChar));
}
}
+ }
- @Override
- public void visitPyFormattedStringElement(@NotNull PyFormattedStringElement node) {
- final String wholeNodeText = node.getText();
- for (TextRange textRange : node.getLiteralPartRanges()) {
- int i = textRange.getStartOffset();
- while (i < textRange.getEndOffset()) {
- final int nextOffset = skipNamedUnicodeEscape(wholeNodeText, i, textRange.getEndOffset());
- if (i != nextOffset) {
- i = nextOffset;
+ @Override
+ public void visitPyFormattedStringElement(@NotNull PyFormattedStringElement node) {
+ final String wholeNodeText = node.getText();
+ for (TextRange textRange : node.getLiteralPartRanges()) {
+ int i = textRange.getStartOffset();
+ while (i < textRange.getEndOffset()) {
+ final int nextOffset = skipNamedUnicodeEscape(wholeNodeText, i, textRange.getEndOffset());
+ if (i != nextOffset) {
+ i = nextOffset;
+ continue;
+ }
+ final char c = wholeNodeText.charAt(i);
+ if (c == '}') {
+ if (i + 1 < textRange.getEndOffset() && wholeNodeText.charAt(i + 1) == '}') {
+ i += 2;
continue;
}
- final char c = wholeNodeText.charAt(i);
- if (c == '}') {
- if (i + 1 < textRange.getEndOffset() && wholeNodeText.charAt(i + 1) == '}') {
- i += 2;
- continue;
- }
- reportCharacter(node, i, PyPsiBundle.message("ANN.fstrings.single.right.brace.not.allowed.inside.fstrings"));
- }
- i++;
+ reportCharacter(node, i, PyPsiBundle.message("ANN.fstrings.single.right.brace.not.allowed.inside.fstrings"));
}
+ i++;
}
}
-
- private static int skipNamedUnicodeEscape(@NotNull String nodeText, int offset, int endOffset) {
- if (StringUtil.startsWith(nodeText, offset, "\\N{")) {
- final int rightBraceOffset = nodeText.indexOf('}', offset + 3);
- return rightBraceOffset < 0 ? endOffset : rightBraceOffset + 1;
- }
- return offset;
- }
-
- public void reportCharacter(@NotNull PsiElement element, int offset, @NotNull @InspectionMessage String message) {
- final int nodeStartOffset = element.getTextRange().getStartOffset();
- myHolder.newAnnotation(HighlightSeverity.ERROR, message).range(TextRange.from(offset, 1).shiftRight(nodeStartOffset)).create();
- }
-
- public void report(@NotNull PsiElement element, @NotNull @InspectionMessage String error) {
- myHolder.newAnnotation(HighlightSeverity.ERROR, error).range(element).create();
- }
}
-}
+
+ private static int skipNamedUnicodeEscape(@NotNull String nodeText, int offset, int endOffset) {
+ if (StringUtil.startsWith(nodeText, offset, "\\N{")) {
+ final int rightBraceOffset = nodeText.indexOf('}', offset + 3);
+ return rightBraceOffset < 0 ? endOffset : rightBraceOffset + 1;
+ }
+ return offset;
+ }
+
+ public void reportCharacter(@NotNull PsiElement element, int offset, @NotNull @InspectionMessage String message) {
+ final int nodeStartOffset = element.getTextRange().getStartOffset();
+ myHolder.newAnnotation(HighlightSeverity.ERROR, message).range(TextRange.from(offset, 1).shiftRight(nodeStartOffset)).create();
+ }
+
+ public void report(@NotNull PsiElement element, @NotNull @InspectionMessage String error) {
+ myHolder.newAnnotation(HighlightSeverity.ERROR, error).range(element).create();
+ }
+}
\ No newline at end of file
diff --git a/python/python-psi-impl/src/com/jetbrains/python/validation/PyGeneratorInArgumentListAnnotator.java b/python/python-psi-impl/src/com/jetbrains/python/validation/PyGeneratorInArgumentListAnnotator.java
index 9e55abd63be3..0e20528d943b 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/validation/PyGeneratorInArgumentListAnnotator.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/validation/PyGeneratorInArgumentListAnnotator.java
@@ -16,7 +16,6 @@
package com.jetbrains.python.validation;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.PsiElement;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.PyArgumentList;
@@ -26,26 +25,19 @@ import com.jetbrains.python.psi.PyGeneratorExpression;
import org.jetbrains.annotations.NotNull;
-public final class PyGeneratorInArgumentListAnnotator extends PyAnnotatorBase {
+final class PyGeneratorInArgumentListAnnotator extends PyElementVisitor {
+ private final @NotNull PyAnnotationHolder myHolder;
+
+ PyGeneratorInArgumentListAnnotator(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
+
@Override
- public void annotate(@NotNull PsiElement element, @NotNull PyAnnotationHolder holder) {
- element.accept(new MyVisitor(holder));
- }
-
- private static class MyVisitor extends PyElementVisitor {
- private final @NotNull PyAnnotationHolder myHolder;
-
- private MyVisitor(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
-
- @Override
- public void visitPyArgumentList(@NotNull PyArgumentList node) {
- if (node.getArguments().length > 1) {
- for (PyExpression expression : node.getArguments()) {
- if (expression instanceof PyGeneratorExpression) {
- ASTNode firstChildNode = expression.getNode().getFirstChildNode();
- if (firstChildNode.getElementType() != PyTokenTypes.LPAR) {
- myHolder.markError(expression, PyPsiBundle.message("ANN.generator.expression.must.be.parenthesized.if.not.sole.argument"));
- }
+ public void visitPyArgumentList(@NotNull PyArgumentList node) {
+ if (node.getArguments().length > 1) {
+ for (PyExpression expression : node.getArguments()) {
+ if (expression instanceof PyGeneratorExpression) {
+ ASTNode firstChildNode = expression.getNode().getFirstChildNode();
+ if (firstChildNode.getElementType() != PyTokenTypes.LPAR) {
+ myHolder.markError(expression, PyPsiBundle.message("ANN.generator.expression.must.be.parenthesized.if.not.sole.argument"));
}
}
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/validation/PyPatternAnnotator.java b/python/python-psi-impl/src/com/jetbrains/python/validation/PyPatternAnnotator.java
index 9389d96c4655..84cc1e6a0e3a 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/validation/PyPatternAnnotator.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/validation/PyPatternAnnotator.java
@@ -15,180 +15,173 @@ import java.util.*;
import static com.jetbrains.python.psi.PyUtil.as;
-public final class PyPatternAnnotator extends PyAnnotatorBase {
+final class PyPatternAnnotator extends PyElementVisitor {
+ private final @NotNull PyAnnotationHolder myHolder;
+
+ PyPatternAnnotator(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
+
@Override
- public void annotate(@NotNull PsiElement element, @NotNull PyAnnotationHolder holder) {
- element.accept(new MyVisitor(holder));
+ public void visitPySingleStarPattern(@NotNull PySingleStarPattern starPattern) {
+ PsiElement parent = starPattern.getParent();
+ if (!(parent instanceof PySequencePattern)) {
+ myHolder.markError(starPattern, PyPsiBundle.message("ANN.patterns.single.star.pattern.cannot.be.used.outside.sequence.patterns"));
+ }
}
- private static class MyVisitor extends PyElementVisitor {
- private final @NotNull PyAnnotationHolder myHolder;
+ @Override
+ public void visitPyDoubleStarPattern(@NotNull PyDoubleStarPattern starPattern) {
+ PsiElement parent = starPattern.getParent();
+ if (!(parent instanceof PyMappingPattern)) {
+ myHolder.markError(starPattern, PyPsiBundle.message("ANN.patterns.double.star.pattern.cannot.be.used.outside.mapping.patterns"));
+ }
+ }
- private MyVisitor(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
+ @Override
+ public void visitPyLiteralPattern(@NotNull PyLiteralPattern literalPattern) {
+ PyBinaryExpression expression = as(literalPattern.getExpression(), PyBinaryExpression.class);
+ if (expression != null) {
+ PyNumericLiteralExpression rightOperand = as(expression.getRightExpression(), PyNumericLiteralExpression.class);
+ if (rightOperand != null && rightOperand.getFirstChild().getNode().getElementType() != PyTokenTypes.IMAGINARY_LITERAL) {
+ myHolder.markError(expression, PyPsiBundle.message("ANN.patterns.invalid.complex.number.literal"));
+ }
+ }
+ }
- @Override
- public void visitPySingleStarPattern(@NotNull PySingleStarPattern starPattern) {
- PsiElement parent = starPattern.getParent();
- if (!(parent instanceof PySequencePattern)) {
- myHolder.markError(starPattern, PyPsiBundle.message("ANN.patterns.single.star.pattern.cannot.be.used.outside.sequence.patterns"));
+ @Override
+ public void visitPyKeyValuePattern(@NotNull PyKeyValuePattern keyValuePattern) {
+ PyPattern keyPattern = keyValuePattern.getKeyPattern();
+ if (!(keyPattern instanceof PyValuePattern || keyPattern instanceof PyLiteralPattern)) {
+ myHolder.markError(keyPattern, PyPsiBundle.message("ANN.patterns.key.pattern.can.only.be.value.or.literal.pattern"));
+ }
+ }
+
+ @Override
+ public void visitPyOrPattern(@NotNull PyOrPattern orPattern) {
+ List alternatives = orPattern.getAlternatives();
+ PyPattern lastAlternative = alternatives.get(alternatives.size() - 1);
+ Map> patternToBoundNames = new HashMap<>();
+ Set allBoundNames = new HashSet<>();
+
+ for (PyPattern alternative : alternatives) {
+ Set boundNames = SyntaxTraverser.psiTraverser(alternative)
+ .filter(PyTargetExpression.class)
+ .map(PyTargetExpression::getName)
+ .toSet();
+ patternToBoundNames.put(alternative, boundNames);
+ allBoundNames.addAll(boundNames);
+
+ if (alternative != lastAlternative && alternative.isIrrefutable()) {
+ myHolder.markError(alternative, PyPsiBundle.message("ANN.patterns.pattern.makes.remaining.alternatives.unreachable"));
}
}
- @Override
- public void visitPyDoubleStarPattern(@NotNull PyDoubleStarPattern starPattern) {
- PsiElement parent = starPattern.getParent();
- if (!(parent instanceof PyMappingPattern)) {
- myHolder.markError(starPattern, PyPsiBundle.message("ANN.patterns.double.star.pattern.cannot.be.used.outside.mapping.patterns"));
+ for (Map.Entry> entry : patternToBoundNames.entrySet()) {
+ Set boundNames = entry.getValue();
+ if (!boundNames.equals(allBoundNames)) {
+ Collection missingNames = ContainerUtil.subtract(allBoundNames, boundNames);
+ String nameList = StringUtil.join(ContainerUtil.sorted(missingNames), ", ");
+ myHolder.markError(entry.getKey(), PyPsiBundle.message("ANN.patterns.pattern.does.not.bind.names", missingNames.size(), nameList));
}
}
+ }
- @Override
- public void visitPyLiteralPattern(@NotNull PyLiteralPattern literalPattern) {
- PyBinaryExpression expression = as(literalPattern.getExpression(), PyBinaryExpression.class);
- if (expression != null) {
- PyNumericLiteralExpression rightOperand = as(expression.getRightExpression(), PyNumericLiteralExpression.class);
- if (rightOperand != null && rightOperand.getFirstChild().getNode().getElementType() != PyTokenTypes.IMAGINARY_LITERAL) {
- myHolder.markError(expression, PyPsiBundle.message("ANN.patterns.invalid.complex.number.literal"));
- }
+ @Override
+ public void visitPyMatchStatement(@NotNull PyMatchStatement matchStatement) {
+ List clauses = matchStatement.getCaseClauses();
+ if (clauses.isEmpty()) return;
+
+ for (PyCaseClause clause : clauses.subList(0, clauses.size() - 1)) {
+ PyPattern pattern = clause.getPattern();
+ if (pattern == null) {
+ continue;
+ }
+ PyPattern unwrappedPattern = unwrapGroupAndAsPatterns(pattern);
+ // There will be another warning for top-level star patterns
+ if (unwrappedPattern instanceof PySingleStarPattern || unwrappedPattern instanceof PyDoubleStarPattern) {
+ continue;
+ }
+ if (clause.getGuardCondition() == null && pattern.isIrrefutable()) {
+ myHolder.markError(pattern, PyPsiBundle.message("ANN.patterns.pattern.makes.remaining.case.clauses.unreachable"));
}
}
+ }
- @Override
- public void visitPyKeyValuePattern(@NotNull PyKeyValuePattern keyValuePattern) {
- PyPattern keyPattern = keyValuePattern.getKeyPattern();
- if (!(keyPattern instanceof PyValuePattern || keyPattern instanceof PyLiteralPattern)) {
- myHolder.markError(keyPattern, PyPsiBundle.message("ANN.patterns.key.pattern.can.only.be.value.or.literal.pattern"));
+ @Override
+ public void visitPyPatternArgumentList(@NotNull PyPatternArgumentList argumentList) {
+ Set usedAttrNames = new HashSet<>();
+ for (PyPattern attrPattern : argumentList.getPatterns()) {
+ PyKeywordPattern keywordPattern = as(attrPattern, PyKeywordPattern.class);
+ if (keywordPattern == null) {
+ continue;
+ }
+ if (!usedAttrNames.add(keywordPattern.getKeyword())) {
+ myHolder.markError(keywordPattern.getKeywordElement(),
+ PyPsiBundle.message("ANN.patterns.attribute.name.is.repeated", keywordPattern.getKeyword()));
}
}
+ }
- @Override
- public void visitPyOrPattern(@NotNull PyOrPattern orPattern) {
- List alternatives = orPattern.getAlternatives();
- PyPattern lastAlternative = alternatives.get(alternatives.size() - 1);
- Map> patternToBoundNames = new HashMap<>();
- Set allBoundNames = new HashSet<>();
+ @Override
+ public void visitPyCaseClause(@NotNull PyCaseClause caseClause) {
+ PyPattern pattern = caseClause.getPattern();
+ if (pattern == null) return;
- for (PyPattern alternative : alternatives) {
- Set boundNames = SyntaxTraverser.psiTraverser(alternative)
- .filter(PyTargetExpression.class)
- .map(PyTargetExpression::getName)
- .toSet();
- patternToBoundNames.put(alternative, boundNames);
- allBoundNames.addAll(boundNames);
+ Stack> boundNamesPerOrBranch = new Stack<>();
+ // Assume that the top-level pattern is a single branch of a synthetic OR pattern
+ boundNamesPerOrBranch.push(new HashSet<>());
- if (alternative != lastAlternative && alternative.isIrrefutable()) {
- myHolder.markError(alternative, PyPsiBundle.message("ANN.patterns.pattern.makes.remaining.alternatives.unreachable"));
+ pattern.accept(new PyRecursiveElementVisitor() {
+ @Override
+ public void visitPyOrPattern(@NotNull PyOrPattern orPattern) {
+ Set allBoundNamesInOrPattern = new HashSet<>();
+ for (PyPattern alternative : orPattern.getAlternatives()) {
+ boundNamesPerOrBranch.push(new HashSet<>());
+ alternative.accept(this);
+ allBoundNamesInOrPattern.addAll(boundNamesPerOrBranch.peek());
+ boundNamesPerOrBranch.pop();
}
+ boundNamesPerOrBranch.peek().addAll(allBoundNamesInOrPattern);
}
- for (Map.Entry> entry : patternToBoundNames.entrySet()) {
- Set boundNames = entry.getValue();
- if (!boundNames.equals(allBoundNames)) {
- Collection missingNames = ContainerUtil.subtract(allBoundNames, boundNames);
- String nameList = StringUtil.join(ContainerUtil.sorted(missingNames), ", ");
- myHolder.markError(entry.getKey(), PyPsiBundle.message("ANN.patterns.pattern.does.not.bind.names", missingNames.size(), nameList));
+ @Override
+ public void visitPyTargetExpression(@NotNull PyTargetExpression target) {
+ String name = target.getName();
+ boolean alreadyBound = ContainerUtil.exists(boundNamesPerOrBranch, names -> names.contains(name));
+ if (alreadyBound) {
+ myHolder.markError(target, PyPsiBundle.message("ANN.patterns.name.already.bound", name));
}
+ boundNamesPerOrBranch.peek().add(name);
+ }
+ });
+ }
+
+ @Override
+ public void visitPySequencePattern(@NotNull PySequencePattern sequencePattern) {
+ List starPatterns = PsiTreeUtil.getChildrenOfTypeAsList(sequencePattern, PySingleStarPattern.class);
+ if (starPatterns.size() > 1) {
+ for (PySingleStarPattern pattern : starPatterns.subList(1, starPatterns.size())) {
+ myHolder.markError(pattern, PyPsiBundle.message("ANN.patterns.repeated.star.pattern"));
}
}
+ }
- @Override
- public void visitPyMatchStatement(@NotNull PyMatchStatement matchStatement) {
- List clauses = matchStatement.getCaseClauses();
- if (clauses.isEmpty()) return;
-
- for (PyCaseClause clause : clauses.subList(0, clauses.size() - 1)) {
- PyPattern pattern = clause.getPattern();
- if (pattern == null) {
- continue;
- }
- PyPattern unwrappedPattern = unwrapGroupAndAsPatterns(pattern);
- // There will be another warning for top-level star patterns
- if (unwrappedPattern instanceof PySingleStarPattern || unwrappedPattern instanceof PyDoubleStarPattern) {
- continue;
- }
- if (clause.getGuardCondition() == null && pattern.isIrrefutable()) {
- myHolder.markError(pattern, PyPsiBundle.message("ANN.patterns.pattern.makes.remaining.case.clauses.unreachable"));
- }
+ @Override
+ public void visitPyMappingPattern(@NotNull PyMappingPattern mappingPattern) {
+ List starPatterns = PsiTreeUtil.getChildrenOfTypeAsList(mappingPattern, PyDoubleStarPattern.class);
+ if (starPatterns.size() > 1) {
+ for (PyDoubleStarPattern pattern : starPatterns.subList(1, starPatterns.size())) {
+ myHolder.markError(pattern, PyPsiBundle.message("ANN.patterns.repeated.star.pattern"));
}
}
+ }
- @Override
- public void visitPyPatternArgumentList(@NotNull PyPatternArgumentList argumentList) {
- Set usedAttrNames = new HashSet<>();
- for (PyPattern attrPattern : argumentList.getPatterns()) {
- PyKeywordPattern keywordPattern = as(attrPattern, PyKeywordPattern.class);
- if (keywordPattern == null) {
- continue;
- }
- if (!usedAttrNames.add(keywordPattern.getKeyword())) {
- myHolder.markError(keywordPattern.getKeywordElement(),
- PyPsiBundle.message("ANN.patterns.attribute.name.is.repeated", keywordPattern.getKeyword()));
- }
- }
+ private static @NotNull PyPattern unwrapGroupAndAsPatterns(@NotNull PyPattern pattern) {
+ if (pattern instanceof PyGroupPattern) {
+ return unwrapGroupAndAsPatterns(((PyGroupPattern)pattern).getPattern());
}
-
- @Override
- public void visitPyCaseClause(@NotNull PyCaseClause caseClause) {
- PyPattern pattern = caseClause.getPattern();
- if (pattern == null) return;
-
- Stack> boundNamesPerOrBranch = new Stack<>();
- // Assume that the top-level pattern is a single branch of a synthetic OR pattern
- boundNamesPerOrBranch.push(new HashSet<>());
-
- pattern.accept(new PyRecursiveElementVisitor() {
- @Override
- public void visitPyOrPattern(@NotNull PyOrPattern orPattern) {
- Set allBoundNamesInOrPattern = new HashSet<>();
- for (PyPattern alternative : orPattern.getAlternatives()) {
- boundNamesPerOrBranch.push(new HashSet<>());
- alternative.accept(this);
- allBoundNamesInOrPattern.addAll(boundNamesPerOrBranch.peek());
- boundNamesPerOrBranch.pop();
- }
- boundNamesPerOrBranch.peek().addAll(allBoundNamesInOrPattern);
- }
-
- @Override
- public void visitPyTargetExpression(@NotNull PyTargetExpression target) {
- String name = target.getName();
- boolean alreadyBound = ContainerUtil.exists(boundNamesPerOrBranch, names -> names.contains(name));
- if (alreadyBound) {
- myHolder.markError(target, PyPsiBundle.message("ANN.patterns.name.already.bound", name));
- }
- boundNamesPerOrBranch.peek().add(name);
- }
- });
- }
-
- @Override
- public void visitPySequencePattern(@NotNull PySequencePattern sequencePattern) {
- List starPatterns = PsiTreeUtil.getChildrenOfTypeAsList(sequencePattern, PySingleStarPattern.class);
- if (starPatterns.size() > 1) {
- for (PySingleStarPattern pattern : starPatterns.subList(1, starPatterns.size())) {
- myHolder.markError(pattern, PyPsiBundle.message("ANN.patterns.repeated.star.pattern"));
- }
- }
- }
-
- @Override
- public void visitPyMappingPattern(@NotNull PyMappingPattern mappingPattern) {
- List starPatterns = PsiTreeUtil.getChildrenOfTypeAsList(mappingPattern, PyDoubleStarPattern.class);
- if (starPatterns.size() > 1) {
- for (PyDoubleStarPattern pattern : starPatterns.subList(1, starPatterns.size())) {
- myHolder.markError(pattern, PyPsiBundle.message("ANN.patterns.repeated.star.pattern"));
- }
- }
- }
-
- private static @NotNull PyPattern unwrapGroupAndAsPatterns(@NotNull PyPattern pattern) {
- if (pattern instanceof PyGroupPattern) {
- return unwrapGroupAndAsPatterns(((PyGroupPattern)pattern).getPattern());
- }
- if (pattern instanceof PyAsPattern) {
- return unwrapGroupAndAsPatterns(((PyAsPattern)pattern).getPattern());
- }
- return pattern;
+ if (pattern instanceof PyAsPattern) {
+ return unwrapGroupAndAsPatterns(((PyAsPattern)pattern).getPattern());
}
+ return pattern;
}
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/validation/PyStarAnnotator.java b/python/python-psi-impl/src/com/jetbrains/python/validation/PyStarAnnotator.java
index 62a1f1620ecc..5fe37e6c6c44 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/validation/PyStarAnnotator.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/validation/PyStarAnnotator.java
@@ -25,45 +25,38 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public final class PyStarAnnotator extends PyAnnotatorBase {
+final class PyStarAnnotator extends PyElementVisitor {
+ private final @NotNull PyAnnotationHolder myHolder;
+
+ PyStarAnnotator(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
+
@Override
- public void annotate(@NotNull PsiElement element, @NotNull PyAnnotationHolder holder) {
- element.accept(new MyVisitor(holder));
+ public void visitPyStarExpression(@NotNull PyStarExpression node) {
+ super.visitPyStarExpression(node);
+ PsiElement parent = node.getParent();
+ if (!node.isAssignmentTarget() &&
+ !allowedUnpacking(node) &&
+ !(parent instanceof PyParameterTypeList) &&
+ !(parent instanceof PyTypeParameter) &&
+ !(parent instanceof PyAnnotation && isVariadicArg(parent.getParent()))) {
+ myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.can.t.use.starred.expression.here")).create();
+ }
}
- private static class MyVisitor extends PyElementVisitor {
- private final @NotNull PyAnnotationHolder myHolder;
-
- private MyVisitor(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
-
- @Override
- public void visitPyStarExpression(@NotNull PyStarExpression node) {
- super.visitPyStarExpression(node);
- PsiElement parent = node.getParent();
- if (!node.isAssignmentTarget() &&
- !allowedUnpacking(node) &&
- !(parent instanceof PyParameterTypeList) &&
- !(parent instanceof PyTypeParameter) &&
- !(parent instanceof PyAnnotation && isVariadicArg(parent.getParent()))) {
- myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.can.t.use.starred.expression.here")).create();
- }
+ private static boolean allowedUnpacking(@NotNull PyStarExpression starExpression) {
+ if (!starExpression.isUnpacking()) {
+ return false;
}
- private static boolean allowedUnpacking(@NotNull PyStarExpression starExpression) {
- if (!starExpression.isUnpacking()) {
+ // Additional contexts where unpacking is prohibited depending on the language version are covered in CompatibilityVisitor.
+ final PsiElement parent = PsiTreeUtil.skipParentsOfType(starExpression, PyParenthesizedExpression.class);
+ if (parent instanceof PyTupleExpression) {
+ final PsiElement tupleParent = parent.getParent();
+ if (tupleParent instanceof PyYieldExpression && ((PyYieldExpression)tupleParent).isDelegating()) {
return false;
}
-
- // Additional contexts where unpacking is prohibited depending on the language version are covered in CompatibilityVisitor.
- final PsiElement parent = PsiTreeUtil.skipParentsOfType(starExpression, PyParenthesizedExpression.class);
- if (parent instanceof PyTupleExpression) {
- final PsiElement tupleParent = parent.getParent();
- if (tupleParent instanceof PyYieldExpression && ((PyYieldExpression)tupleParent).isDelegating()) {
- return false;
- }
- }
- return true;
}
+ return true;
}
public static boolean isVariadicArg(@Nullable PsiElement parameter) {
diff --git a/python/python-psi-impl/src/com/jetbrains/python/validation/PyStringLiteralQuotesAnnotator.java b/python/python-psi-impl/src/com/jetbrains/python/validation/PyStringLiteralQuotesAnnotator.java
index 1c0fa848375e..6c7b2eb25894 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/validation/PyStringLiteralQuotesAnnotator.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/validation/PyStringLiteralQuotesAnnotator.java
@@ -5,7 +5,6 @@ import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiElement;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyPsiBundle;
import com.jetbrains.python.psi.PyElementVisitor;
@@ -19,82 +18,75 @@ import java.util.List;
/**
* Looks for well-formedness of string constants.
*/
-public final class PyStringLiteralQuotesAnnotator extends PyAnnotatorBase {
+final class PyStringLiteralQuotesAnnotator extends PyElementVisitor {
+ private final @NotNull PyAnnotationHolder myHolder;
+
+ PyStringLiteralQuotesAnnotator(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
+
+ private static final String TRIPLE_QUOTES = "\"\"\"";
+ private static final String TRIPLE_APOS = "'''";
+
@Override
- public void annotate(@NotNull PsiElement element, @NotNull PyAnnotationHolder holder) {
- element.accept(new MyVisitor(holder));
+ public void visitPyStringLiteralExpression(final @NotNull PyStringLiteralExpression node) {
+ final List stringNodes = node.getStringNodes();
+ for (ASTNode stringNode : stringNodes) {
+ // TODO Migrate to newer PyStringElement API
+ if (stringNode.getElementType() == PyElementTypes.FSTRING_NODE) {
+ continue;
+ }
+ final String nodeText = PyPsiUtils.getElementTextWithoutHostEscaping(stringNode.getPsi());
+ final int index = PyStringLiteralUtil.getPrefixLength(nodeText);
+ final String unprefixed = nodeText.substring(index);
+ final boolean foundError;
+ if (StringUtil.startsWith(unprefixed, TRIPLE_QUOTES)) {
+ foundError = checkTripleQuotedString(stringNode, unprefixed, TRIPLE_QUOTES);
+ }
+ else if (StringUtil.startsWith(unprefixed, TRIPLE_APOS)) {
+ foundError = checkTripleQuotedString(stringNode, unprefixed, TRIPLE_APOS);
+ }
+ else {
+ foundError = checkQuotedString(stringNode, unprefixed);
+ }
+ if (foundError) {
+ break;
+ }
+ }
}
- private static class MyVisitor extends PyElementVisitor {
- private final @NotNull PyAnnotationHolder myHolder;
-
- private MyVisitor(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
-
- private static final String TRIPLE_QUOTES = "\"\"\"";
- private static final String TRIPLE_APOS = "'''";
-
- @Override
- public void visitPyStringLiteralExpression(final @NotNull PyStringLiteralExpression node) {
- final List stringNodes = node.getStringNodes();
- for (ASTNode stringNode : stringNodes) {
- // TODO Migrate to newer PyStringElement API
- if (stringNode.getElementType() == PyElementTypes.FSTRING_NODE) {
- continue;
- }
- final String nodeText = PyPsiUtils.getElementTextWithoutHostEscaping(stringNode.getPsi());
- final int index = PyStringLiteralUtil.getPrefixLength(nodeText);
- final String unprefixed = nodeText.substring(index);
- final boolean foundError;
- if (StringUtil.startsWith(unprefixed, TRIPLE_QUOTES)) {
- foundError = checkTripleQuotedString(stringNode, unprefixed, TRIPLE_QUOTES);
- }
- else if (StringUtil.startsWith(unprefixed, TRIPLE_APOS)) {
- foundError = checkTripleQuotedString(stringNode, unprefixed, TRIPLE_APOS);
- }
- else {
- foundError = checkQuotedString(stringNode, unprefixed);
- }
- if (foundError) {
- break;
- }
+ private boolean checkQuotedString(@NotNull ASTNode stringNode, @NotNull String nodeText) {
+ final char firstQuote = nodeText.charAt(0);
+ final char lastChar = nodeText.charAt(nodeText.length() - 1);
+ int precedingBackslashCount = 0;
+ for (int i = nodeText.length() - 2; i >= 0; i--) {
+ if (nodeText.charAt(i) == '\\') {
+ precedingBackslashCount++;
+ }
+ else {
+ break;
}
}
-
- private boolean checkQuotedString(@NotNull ASTNode stringNode, @NotNull String nodeText) {
- final char firstQuote = nodeText.charAt(0);
- final char lastChar = nodeText.charAt(nodeText.length() - 1);
- int precedingBackslashCount = 0;
- for (int i = nodeText.length() - 2; i >= 0; i--) {
- if (nodeText.charAt(i) == '\\') {
- precedingBackslashCount++;
- }
- else {
- break;
- }
- }
- if (nodeText.length() == 1 || lastChar != firstQuote || precedingBackslashCount % 2 != 0) {
- myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.missing.closing.quote", firstQuote)).range(stringNode)
- .create();
- return true;
- }
- return false;
+ if (nodeText.length() == 1 || lastChar != firstQuote || precedingBackslashCount % 2 != 0) {
+ myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.missing.closing.quote", firstQuote)).range(stringNode)
+ .create();
+ return true;
}
+ return false;
+ }
- private boolean checkTripleQuotedString(@NotNull ASTNode stringNode, @NotNull String text, @NotNull String quotes) {
- if (text.length() < 6 || !text.endsWith(quotes)) {
- int startOffset = StringUtil.trimTrailing(stringNode.getText()).lastIndexOf('\n');
- if (startOffset < 0) {
- startOffset = stringNode.getTextRange().getStartOffset();
- }
- else {
- startOffset = stringNode.getTextRange().getStartOffset() + startOffset + 1;
- }
- final TextRange highlightRange = new TextRange(startOffset, stringNode.getTextRange().getEndOffset());
- myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.missing.closing.triple.quotes")).range(highlightRange)
- .create();
- return true;
+ private boolean checkTripleQuotedString(@NotNull ASTNode stringNode, @NotNull String text, @NotNull String quotes) {
+ if (text.length() < 6 || !text.endsWith(quotes)) {
+ int startOffset = StringUtil.trimTrailing(stringNode.getText()).lastIndexOf('\n');
+ if (startOffset < 0) {
+ startOffset = stringNode.getTextRange().getStartOffset();
}
- return false;
+ else {
+ startOffset = stringNode.getTextRange().getStartOffset() + startOffset + 1;
+ }
+ final TextRange highlightRange = new TextRange(startOffset, stringNode.getTextRange().getEndOffset());
+ myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.missing.closing.triple.quotes")).range(highlightRange)
+ .create();
+ return true;
}
+ return false;
}
}
\ No newline at end of file
diff --git a/python/python-psi-impl/src/com/jetbrains/python/validation/PySyntaxAnnotator.java b/python/python-psi-impl/src/com/jetbrains/python/validation/PySyntaxAnnotator.java
index 43bf80116fcf..7eb2957b16a4 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/validation/PySyntaxAnnotator.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/validation/PySyntaxAnnotator.java
@@ -21,7 +21,14 @@ public final class PySyntaxAnnotator extends PyAnnotatorBase implements DumbAwar
new PyGlobalAnnotatorVisitor(holder),
new PyImportAnnotatorVisitor(holder),
new PyAsyncAwaitAnnotatorVisitor(holder),
- new PyAstNumericLiteralAnnotatorVisitor(holder)
+ new PyAstNumericLiteralAnnotatorVisitor(holder),
+ new PyGeneratorInArgumentListAnnotator(holder),
+ new PyStarAnnotator(holder),
+ new PyStringLiteralQuotesAnnotator(holder),
+ new PyFStringsAnnotator(holder),
+ new PyPatternAnnotator(holder),
+ new PyTryExceptAnnotator(holder),
+ new PyTypeParameterListAnnotator(holder)
);
for (PsiElementVisitor visitor : visitors) {
psiElement.accept(visitor);
diff --git a/python/python-psi-impl/src/com/jetbrains/python/validation/PyTryExceptAnnotator.java b/python/python-psi-impl/src/com/jetbrains/python/validation/PyTryExceptAnnotator.java
index 9f7bcb89a0a6..55bd91ad7e37 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/validation/PyTryExceptAnnotator.java
+++ b/python/python-psi-impl/src/com/jetbrains/python/validation/PyTryExceptAnnotator.java
@@ -11,116 +11,109 @@ import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public final class PyTryExceptAnnotator extends PyAnnotatorBase {
+final class PyTryExceptAnnotator extends PyElementVisitor {
+ private final @NotNull PyAnnotationHolder myHolder;
+
+ PyTryExceptAnnotator(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
+
@Override
- public void annotate(@NotNull PsiElement element, @NotNull PyAnnotationHolder holder) {
- element.accept(new MyVisitor(holder));
+ public void visitPyTryExceptStatement(@NotNull PyTryExceptStatement node) {
+ boolean haveDefaultExcept = false;
+ for (PyExceptPart part : node.getExceptParts()) {
+ if (haveDefaultExcept) {
+ myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.default.except.must.be.last")).range(part).create();
+ }
+ if (part.getExceptClass() == null) {
+ haveDefaultExcept = true;
+ }
+ }
+
+ boolean haveStar = false;
+ boolean haveNotStar = false;
+ for (PyExceptPart exceptPart : node.getExceptParts()) {
+ var star = PyPsiUtils.getFirstChildOfType(exceptPart, PyTokenTypes.MULT);
+ if (star != null) {
+ haveStar = true;
+ }
+ else {
+ haveNotStar = true;
+ }
+ if (haveNotStar && haveStar) {
+ var exceptKeyword = exceptPart.getFirstChild();
+ int startOffset = exceptKeyword.getTextOffset();
+ int endOffset = exceptKeyword.getTextRange().getEndOffset();
+ if (star != null) {
+ endOffset = star.getTextRange().getEndOffset();
+ }
+ var textRange = new TextRange(startOffset, endOffset);
+ myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.try.except.can.not.have.except.and.star.except"))
+ .range(textRange).create();
+ break;
+ }
+ }
}
- private static class MyVisitor extends PyElementVisitor {
- private final @NotNull PyAnnotationHolder myHolder;
+ @Override
+ public void visitPyRaiseStatement(@NotNull PyRaiseStatement node) {
+ if (node.getExpressions().length == 0 &&
+ PsiTreeUtil.getParentOfType(node, PyExceptPart.class, PyFinallyPart.class, PyFunction.class) == null) {
+ myHolder.markError(node, PyPsiBundle.message("ANN.no.exception.to.reraise"));
+ }
+ }
- private MyVisitor(@NotNull PyAnnotationHolder holder) { myHolder = holder; }
-
- @Override
- public void visitPyTryExceptStatement(@NotNull PyTryExceptStatement node) {
- boolean haveDefaultExcept = false;
- for (PyExceptPart part : node.getExceptParts()) {
- if (haveDefaultExcept) {
- myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.default.except.must.be.last")).range(part).create();
- }
- if (part.getExceptClass() == null) {
- haveDefaultExcept = true;
- }
- }
-
- boolean haveStar = false;
- boolean haveNotStar = false;
- for (PyExceptPart exceptPart : node.getExceptParts()) {
- var star = PyPsiUtils.getFirstChildOfType(exceptPart, PyTokenTypes.MULT);
- if (star != null) {
- haveStar = true;
- }
- else {
- haveNotStar = true;
- }
- if (haveNotStar && haveStar) {
- var exceptKeyword = exceptPart.getFirstChild();
- int startOffset = exceptKeyword.getTextOffset();
- int endOffset = exceptKeyword.getTextRange().getEndOffset();
- if (star != null) {
- endOffset = star.getTextRange().getEndOffset();
- }
- var textRange = new TextRange(startOffset, endOffset);
- myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.try.except.can.not.have.except.and.star.except"))
- .range(textRange).create();
- break;
+ private static @Nullable PyReferenceExpression tryGetExceptionGroupInExpression(@Nullable PsiElement exceptExpression) {
+ if (exceptExpression instanceof PyReferenceExpression &&
+ "ExceptionGroup".equals(((PyReferenceExpression)exceptExpression).getName())) {
+ return (PyReferenceExpression)exceptExpression;
+ }
+ if (exceptExpression instanceof PyParenthesizedExpression) {
+ return tryGetExceptionGroupInExpression(PyPsiUtils.flattenParens((PyParenthesizedExpression)exceptExpression));
+ }
+ if (exceptExpression instanceof PyTupleExpression) {
+ for (PsiElement child : exceptExpression.getChildren()) {
+ var result = tryGetExceptionGroupInExpression(child);
+ if (result != null) {
+ return result;
}
}
}
+ return null;
+ }
- @Override
- public void visitPyRaiseStatement(@NotNull PyRaiseStatement node) {
- if (node.getExpressions().length == 0 &&
- PsiTreeUtil.getParentOfType(node, PyExceptPart.class, PyFinallyPart.class, PyFunction.class) == null) {
- myHolder.markError(node, PyPsiBundle.message("ANN.no.exception.to.reraise"));
- }
+ @Override
+ public void visitPyExceptBlock(@NotNull PyExceptPart node) {
+ if (!node.isStar()) return;
+
+ var exceptClass = node.getExceptClass();
+ var exceptionGroup = tryGetExceptionGroupInExpression(exceptClass);
+ if (exceptionGroup != null) {
+ myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.exception.group.in.star.except")).range(exceptionGroup)
+ .create();
}
+ }
- private static @Nullable PyReferenceExpression tryGetExceptionGroupInExpression(@Nullable PsiElement exceptExpression) {
- if (exceptExpression instanceof PyReferenceExpression &&
- "ExceptionGroup".equals(((PyReferenceExpression)exceptExpression).getName())) {
- return (PyReferenceExpression)exceptExpression;
- }
- if (exceptExpression instanceof PyParenthesizedExpression) {
- return tryGetExceptionGroupInExpression(PyPsiUtils.flattenParens((PyParenthesizedExpression)exceptExpression));
- }
- if (exceptExpression instanceof PyTupleExpression) {
- for (PsiElement child : exceptExpression.getChildren()) {
- var result = tryGetExceptionGroupInExpression(child);
- if (result != null) {
- return result;
- }
- }
- }
- return null;
+ @Override
+ public void visitPyReturnStatement(@NotNull PyReturnStatement node) {
+ PyExceptPart exceptPart = PsiTreeUtil.getParentOfType(node, PyExceptPart.class, false, PyFunction.class);
+ if (exceptPart != null && exceptPart.isStar()) {
+ myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.continue.break.or.return.in.star.except")).create();
}
+ }
- @Override
- public void visitPyExceptBlock(@NotNull PyExceptPart node) {
- if (!node.isStar()) return;
-
- var exceptClass = node.getExceptClass();
- var exceptionGroup = tryGetExceptionGroupInExpression(exceptClass);
- if (exceptionGroup != null) {
- myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.exception.group.in.star.except")).range(exceptionGroup)
- .create();
- }
+ private void checkForContinueAndReturn(@NotNull PsiElement node) {
+ PyExceptPart exceptPart = PsiTreeUtil.getParentOfType(node, PyExceptPart.class, false, PyLoopStatement.class);
+ if (exceptPart != null && exceptPart.isStar()) {
+ myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.continue.break.or.return.in.star.except")).create();
}
+ }
- @Override
- public void visitPyReturnStatement(@NotNull PyReturnStatement node) {
- PyExceptPart exceptPart = PsiTreeUtil.getParentOfType(node, PyExceptPart.class, false, PyFunction.class);
- if (exceptPart != null && exceptPart.isStar()) {
- myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.continue.break.or.return.in.star.except")).create();
- }
- }
+ @Override
+ public void visitPyContinueStatement(@NotNull PyContinueStatement node) {
+ checkForContinueAndReturn(node);
+ }
- private void checkForContinueAndReturn(@NotNull PsiElement node) {
- PyExceptPart exceptPart = PsiTreeUtil.getParentOfType(node, PyExceptPart.class, false, PyLoopStatement.class);
- if (exceptPart != null && exceptPart.isStar()) {
- myHolder.newAnnotation(HighlightSeverity.ERROR, PyPsiBundle.message("ANN.continue.break.or.return.in.star.except")).create();
- }
- }
-
- @Override
- public void visitPyContinueStatement(@NotNull PyContinueStatement node) {
- checkForContinueAndReturn(node);
- }
-
- @Override
- public void visitPyBreakStatement(@NotNull PyBreakStatement node) {
- checkForContinueAndReturn(node);
- }
+ @Override
+ public void visitPyBreakStatement(@NotNull PyBreakStatement node) {
+ checkForContinueAndReturn(node);
}
}
diff --git a/python/python-psi-impl/src/com/jetbrains/python/validation/PyTypeParameterListAnnotator.kt b/python/python-psi-impl/src/com/jetbrains/python/validation/PyTypeParameterListAnnotator.kt
index a150ea27b5fb..be270aad890b 100644
--- a/python/python-psi-impl/src/com/jetbrains/python/validation/PyTypeParameterListAnnotator.kt
+++ b/python/python-psi-impl/src/com/jetbrains/python/validation/PyTypeParameterListAnnotator.kt
@@ -1,7 +1,6 @@
package com.jetbrains.python.validation
import com.intellij.lang.annotation.HighlightSeverity
-import com.intellij.psi.PsiElement
import com.jetbrains.python.PyPsiBundle
import com.jetbrains.python.ast.PyAstTypeParameter.Kind.TypeVar
import com.jetbrains.python.psi.PyElementVisitor
@@ -10,13 +9,7 @@ import com.jetbrains.python.psi.PyTypeParameter
import com.jetbrains.python.psi.PyTypeParameterList
import com.jetbrains.python.psi.impl.PyPsiUtils
-class PyTypeParameterListAnnotator : PyAnnotatorBase() {
- override fun annotate(element: PsiElement, holder: PyAnnotationHolder) {
- element.accept(PyTypeParameterListAnnotatorVisitor(holder))
- }
-}
-
-private class PyTypeParameterListAnnotatorVisitor(private val holder: PyAnnotationHolder) : PyElementVisitor() {
+class PyTypeParameterListAnnotator(private val holder: PyAnnotationHolder) : PyElementVisitor() {
override fun visitPyTypeParameterList(node: PyTypeParameterList) {
if (!node.typeParameters.isEmpty()) {
val namesSet = mutableSetOf()