mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-20744 Warn about illegal targets for variable annotations
This commit is contained in:
@@ -33,6 +33,7 @@ public class PyAnnotatingVisitor implements Annotator {
|
||||
private static final Logger LOGGER = Logger.getInstance(PyAnnotatingVisitor.class.getName());
|
||||
private static final Class[] ANNOTATOR_CLASSES = new Class[] {
|
||||
AssignTargetAnnotator.class,
|
||||
TypeAnnotationTargetAnnotator.class,
|
||||
ParameterListAnnotator.class,
|
||||
HighlightingAnnotator.class,
|
||||
ReturnAnnotator.class,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.validation;
|
||||
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Mikhail Golubev
|
||||
*/
|
||||
public class TypeAnnotationTargetAnnotator extends PyAnnotator {
|
||||
@Override
|
||||
public void visitPyAssignmentStatement(PyAssignmentStatement node) {
|
||||
if (node.getAnnotation() != null && LanguageLevel.forElement(node).isAtLeast(LanguageLevel.PYTHON36)) {
|
||||
if (node.getRawTargets().length > 1) {
|
||||
getHolder().createErrorAnnotation(node, "Variable annotation cannot be used in assignment with multiple targets");
|
||||
}
|
||||
final PyExpression target = node.getLeftHandSideExpression();
|
||||
if (target != null) {
|
||||
checkAnnotationTarget(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyTypeDeclarationStatement(PyTypeDeclarationStatement node) {
|
||||
if (node.getAnnotation() != null && LanguageLevel.forElement(node).isAtLeast(LanguageLevel.PYTHON36)) {
|
||||
checkAnnotationTarget(node.getTarget());
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAnnotationTarget(@NotNull PyExpression expression) {
|
||||
final PyExpression innerExpr = PyPsiUtils.flattenParens(expression);
|
||||
if (innerExpr instanceof PyTupleExpression || innerExpr instanceof PyListLiteralExpression) {
|
||||
getHolder().createErrorAnnotation(innerExpr, "Variable annotation cannot be combined with tuple unpacking");
|
||||
}
|
||||
else if (innerExpr != null && !(innerExpr instanceof PyTargetExpression || innerExpr instanceof PySubscriptionExpression)) {
|
||||
getHolder().createErrorAnnotation(innerExpr, "Illegal target for variable annotation");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
(x): int = 42
|
||||
(((x))): float
|
||||
x['foo']: str
|
||||
f(42).attr: dict
|
||||
|
||||
<error descr="Illegal target for variable annotation">2 ** 8</error>: int
|
||||
<error descr="Illegal target for variable annotation">f()</error>: bool
|
||||
<error descr="Variable annotation cannot be combined with tuple unpacking">x, y, z</error>: Tuple[int, ...]
|
||||
(<error descr="Variable annotation cannot be combined with tuple unpacking">x, y, z</error>): Tuple[int, int, int]
|
||||
<error descr="Variable annotation cannot be combined with tuple unpacking">[x, y, z]</error>: Tuple[Any, Any, Any]
|
||||
<error descr="Variable annotation cannot be combined with tuple unpacking">x, *xs</error>: tuple = range(10)
|
||||
<error descr="Variable annotation cannot be used in assignment with multiple targets">x:int = y = 42</error>
|
||||
@@ -297,6 +297,10 @@ public class PythonHighlightingTest extends PyTestCase {
|
||||
doTest(LanguageLevel.PYTHON35, true, false);
|
||||
}
|
||||
|
||||
public void testIllegalVariableAnnotationTarget() {
|
||||
doTest(LanguageLevel.PYTHON36, true, false);
|
||||
}
|
||||
|
||||
// ---
|
||||
private void doTest(final LanguageLevel languageLevel, final boolean checkWarnings, final boolean checkInfos) {
|
||||
PythonLanguageLevelPusher.setForcedLanguageLevel(myFixture.getProject(), languageLevel);
|
||||
|
||||
Reference in New Issue
Block a user