diff --git a/python/src/com/jetbrains/python/validation/PyAnnotatingVisitor.java b/python/src/com/jetbrains/python/validation/PyAnnotatingVisitor.java
index d5d1964b0faa..150bebc9a1c6 100644
--- a/python/src/com/jetbrains/python/validation/PyAnnotatingVisitor.java
+++ b/python/src/com/jetbrains/python/validation/PyAnnotatingVisitor.java
@@ -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,
diff --git a/python/src/com/jetbrains/python/validation/TypeAnnotationTargetAnnotator.java b/python/src/com/jetbrains/python/validation/TypeAnnotationTargetAnnotator.java
new file mode 100644
index 000000000000..d54de6f85e1c
--- /dev/null
+++ b/python/src/com/jetbrains/python/validation/TypeAnnotationTargetAnnotator.java
@@ -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");
+ }
+ }
+}
diff --git a/python/testData/highlighting/illegalVariableAnnotationTarget.py b/python/testData/highlighting/illegalVariableAnnotationTarget.py
new file mode 100644
index 000000000000..cbaecf67be4e
--- /dev/null
+++ b/python/testData/highlighting/illegalVariableAnnotationTarget.py
@@ -0,0 +1,12 @@
+(x): int = 42
+(((x))): float
+x['foo']: str
+f(42).attr: dict
+
+2 ** 8: int
+f(): bool
+x, y, z: Tuple[int, ...]
+(x, y, z): Tuple[int, int, int]
+[x, y, z]: Tuple[Any, Any, Any]
+x, *xs: tuple = range(10)
+x:int = y = 42
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java b/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java
index b9c6daeaf54e..5991a6d16135 100644
--- a/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonHighlightingTest.java
@@ -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);