diff --git a/python/src/com/jetbrains/python/inspections/PyCompatibilityInspection.java b/python/src/com/jetbrains/python/inspections/PyCompatibilityInspection.java
index 4ee578511eec..8b2d0ec7dac7 100644
--- a/python/src/com/jetbrains/python/inspections/PyCompatibilityInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyCompatibilityInspection.java
@@ -27,15 +27,14 @@ import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiReference;
+import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
+import com.jetbrains.python.inspections.quickfix.PyRenameElementQuickFix;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.types.PyClassType;
@@ -325,5 +324,35 @@ public class PyCompatibilityInspection extends PyInspection {
}
}
}
+
+ @Override
+ public void visitPyTargetExpression(PyTargetExpression node) {
+ super.visitPyTargetExpression(node);
+ warnAboutAsyncAndAwaitInPy35AndPy36(node);
+ }
+
+ @Override
+ public void visitPyClass(PyClass node) {
+ super.visitPyClass(node);
+ warnAboutAsyncAndAwaitInPy35AndPy36(node);
+ }
+
+ @Override
+ public void visitPyFunction(PyFunction node) {
+ super.visitPyFunction(node);
+ warnAboutAsyncAndAwaitInPy35AndPy36(node);
+ }
+
+ private void warnAboutAsyncAndAwaitInPy35AndPy36(@NotNull PsiNameIdentifierOwner nameIdentifierOwner) {
+ final PsiElement nameIdentifier = nameIdentifierOwner.getNameIdentifier();
+
+ if (nameIdentifier != null && ArrayUtil.contains(nameIdentifierOwner.getName(), PyNames.AWAIT, PyNames.ASYNC)) {
+ registerOnFirstMatchingVersion(level -> LanguageLevel.PYTHON35.equals(level) || LanguageLevel.PYTHON36.equals(level),
+ "'async' and 'await' are not recommended to be used as variable, class, function or module names. " +
+ "They will become proper keywords in Python 3.7.",
+ nameIdentifier,
+ new PyRenameElementQuickFix());
+ }
+ }
}
}
\ No newline at end of file
diff --git a/python/testData/inspections/PyCompatibilityInspection/warningAboutAsyncAndAwaitInPy35.py b/python/testData/inspections/PyCompatibilityInspection/warningAboutAsyncAndAwaitInPy35.py
new file mode 100644
index 000000000000..eea16c40ef25
--- /dev/null
+++ b/python/testData/inspections/PyCompatibilityInspection/warningAboutAsyncAndAwaitInPy35.py
@@ -0,0 +1,14 @@
+class async(object):
+ pass
+
+class await(object):
+ pass
+
+def async():
+ pass
+
+def await():
+ pass
+
+async = 1
+await = 2
\ No newline at end of file
diff --git a/python/testData/inspections/PyCompatibilityInspection/warningAboutAsyncAndAwaitInPy36.py b/python/testData/inspections/PyCompatibilityInspection/warningAboutAsyncAndAwaitInPy36.py
new file mode 100644
index 000000000000..eea16c40ef25
--- /dev/null
+++ b/python/testData/inspections/PyCompatibilityInspection/warningAboutAsyncAndAwaitInPy36.py
@@ -0,0 +1,14 @@
+class async(object):
+ pass
+
+class await(object):
+ pass
+
+def async():
+ pass
+
+def await():
+ pass
+
+async = 1
+await = 2
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy35.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy35.py
new file mode 100644
index 000000000000..bc25733ddf5d
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy35.py
@@ -0,0 +1,2 @@
+class async(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy35_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy35_after.py
new file mode 100644
index 000000000000..1a98a9cfc6c4
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy35_after.py
@@ -0,0 +1,2 @@
+class a(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy36.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy36.py
new file mode 100644
index 000000000000..bc25733ddf5d
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy36.py
@@ -0,0 +1,2 @@
+class async(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy36_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy36_after.py
new file mode 100644
index 000000000000..1a98a9cfc6c4
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncClassInPy36_after.py
@@ -0,0 +1,2 @@
+class a(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy35.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy35.py
new file mode 100644
index 000000000000..f48d631547da
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy35.py
@@ -0,0 +1,2 @@
+def async():
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy35_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy35_after.py
new file mode 100644
index 000000000000..690f3c163030
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy35_after.py
@@ -0,0 +1,2 @@
+def a():
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy36.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy36.py
new file mode 100644
index 000000000000..f48d631547da
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy36.py
@@ -0,0 +1,2 @@
+def async():
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy36_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy36_after.py
new file mode 100644
index 000000000000..690f3c163030
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncFunctionInPy36_after.py
@@ -0,0 +1,2 @@
+def a():
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy35.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy35.py
new file mode 100644
index 000000000000..96bae926eb40
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy35.py
@@ -0,0 +1 @@
+async = 1
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy35_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy35_after.py
new file mode 100644
index 000000000000..d25d49e0ffc3
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy35_after.py
@@ -0,0 +1 @@
+a = 1
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy36.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy36.py
new file mode 100644
index 000000000000..96bae926eb40
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy36.py
@@ -0,0 +1 @@
+async = 1
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy36_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy36_after.py
new file mode 100644
index 000000000000..d25d49e0ffc3
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAsyncVariableInPy36_after.py
@@ -0,0 +1 @@
+a = 1
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy35.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy35.py
new file mode 100644
index 000000000000..c531a434721e
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy35.py
@@ -0,0 +1,2 @@
+class await(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy35_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy35_after.py
new file mode 100644
index 000000000000..1a98a9cfc6c4
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy35_after.py
@@ -0,0 +1,2 @@
+class a(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy36.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy36.py
new file mode 100644
index 000000000000..c531a434721e
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy36.py
@@ -0,0 +1,2 @@
+class await(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy36_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy36_after.py
new file mode 100644
index 000000000000..1a98a9cfc6c4
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitClassInPy36_after.py
@@ -0,0 +1,2 @@
+class a(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy35.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy35.py
new file mode 100644
index 000000000000..c1ef9d6ccfae
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy35.py
@@ -0,0 +1,2 @@
+def await():
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy35_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy35_after.py
new file mode 100644
index 000000000000..690f3c163030
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy35_after.py
@@ -0,0 +1,2 @@
+def a():
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy36.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy36.py
new file mode 100644
index 000000000000..c1ef9d6ccfae
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy36.py
@@ -0,0 +1,2 @@
+def await():
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy36_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy36_after.py
new file mode 100644
index 000000000000..690f3c163030
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitFunctionInPy36_after.py
@@ -0,0 +1,2 @@
+def a():
+ pass
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy35.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy35.py
new file mode 100644
index 000000000000..1a28415ce838
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy35.py
@@ -0,0 +1 @@
+await = 1
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy35_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy35_after.py
new file mode 100644
index 000000000000..d25d49e0ffc3
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy35_after.py
@@ -0,0 +1 @@
+a = 1
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy36.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy36.py
new file mode 100644
index 000000000000..1a28415ce838
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy36.py
@@ -0,0 +1 @@
+await = 1
\ No newline at end of file
diff --git a/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy36_after.py b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy36_after.py
new file mode 100644
index 000000000000..d25d49e0ffc3
--- /dev/null
+++ b/python/testData/quickFixes/RenameElementQuickFixTest/renameAwaitVariableInPy36_after.py
@@ -0,0 +1 @@
+a = 1
\ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java
index 4bc87459c36f..7afe19f1f695 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java
@@ -209,6 +209,16 @@ public class PyCompatibilityInspectionTest extends PyTestCase {
doTest(LanguageLevel.PYTHON36);
}
+ // PY-16098
+ public void testWarningAboutAsyncAndAwaitInPy35() {
+ doTest(LanguageLevel.PYTHON35);
+ }
+
+ // PY-16098
+ public void testWarningAboutAsyncAndAwaitInPy36() {
+ doTest(LanguageLevel.PYTHON36);
+ }
+
private void doTest(@NotNull LanguageLevel level) {
runWithLanguageLevel(level, this::doTest);
}
diff --git a/python/testSrc/com/jetbrains/python/quickFixes/RenameElementQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/RenameElementQuickFixTest.java
index 5a63b49b66e6..66a01ae20e1f 100644
--- a/python/testSrc/com/jetbrains/python/quickFixes/RenameElementQuickFixTest.java
+++ b/python/testSrc/com/jetbrains/python/quickFixes/RenameElementQuickFixTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@ package com.jetbrains.python.quickFixes;
import com.intellij.testFramework.TestDataPath;
import com.jetbrains.python.PyQuickFixTestCase;
+import com.jetbrains.python.inspections.PyCompatibilityInspection;
import com.jetbrains.python.inspections.PyPep8NamingInspection;
import com.jetbrains.python.inspections.PyProtectedMemberInspection;
import com.jetbrains.python.inspections.PyShadowingBuiltinsInspection;
@@ -47,4 +48,63 @@ public class RenameElementQuickFixTest extends PyQuickFixTestCase {
doQuickFixTest(PyShadowingBuiltinsInspection.class, "Rename element");
}
+ // PY-16098
+ public void testRenameAsyncClassInPy35() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAsyncClassInPy36() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAwaitClassInPy35() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAwaitClassInPy36() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAsyncFunctionInPy35() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAsyncFunctionInPy36() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAwaitFunctionInPy35() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAwaitFunctionInPy36() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAsyncVariableInPy35() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAsyncVariableInPy36() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAwaitVariableInPy35() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
+
+ // PY-16098
+ public void testRenameAwaitVariableInPy36() {
+ doQuickFixTest(PyCompatibilityInspection.class, "Rename element");
+ }
}