PY-16098 Fixed: Warn that async and await will become keywords in Python 3.7

Warn about variables, classes and functions called "await" or "async" in Pythons 3.5 and 3.6. Suggest quick fix to rename such nodes
This commit is contained in:
Semyon Proshev
2016-10-07 12:21:53 +03:00
parent bd632e61f4
commit 42fc094e4e
29 changed files with 172 additions and 5 deletions
@@ -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());
}
}
}
}
@@ -0,0 +1,14 @@
class <warning descr="'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.">async</warning>(object):
pass
class <warning descr="'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.">await</warning>(object):
pass
def <warning descr="'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.">async</warning>():
pass
def <warning descr="'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.">await</warning>():
pass
<warning descr="'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.">async</warning> = 1
<warning descr="'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.">await</warning> = 2
@@ -0,0 +1,14 @@
class <warning descr="'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.">async</warning>(object):
pass
class <warning descr="'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.">await</warning>(object):
pass
def <warning descr="'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.">async</warning>():
pass
def <warning descr="'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.">await</warning>():
pass
<warning descr="'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.">async</warning> = 1
<warning descr="'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.">await</warning> = 2
@@ -0,0 +1,2 @@
class <warning descr="'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.">a<caret>sync</warning>(object):
pass
@@ -0,0 +1,2 @@
class a(object):
pass
@@ -0,0 +1,2 @@
class <warning descr="'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.">a<caret>sync</warning>(object):
pass
@@ -0,0 +1,2 @@
class a(object):
pass
@@ -0,0 +1,2 @@
def <warning descr="'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.">a<caret>sync</warning>():
pass
@@ -0,0 +1,2 @@
def <warning descr="'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.">a<caret>sync</warning>():
pass
@@ -0,0 +1 @@
<warning descr="'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.">async</warning> = 1
@@ -0,0 +1 @@
<warning descr="'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.">async</warning> = 1
@@ -0,0 +1,2 @@
class <warning descr="'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.">a<caret>wait</warning>(object):
pass
@@ -0,0 +1,2 @@
class a(object):
pass
@@ -0,0 +1,2 @@
class <warning descr="'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.">a<caret>wait</warning>(object):
pass
@@ -0,0 +1,2 @@
class a(object):
pass
@@ -0,0 +1,2 @@
def <warning descr="'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.">a<caret>wait</warning>():
pass
@@ -0,0 +1,2 @@
def <warning descr="'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.">a<caret>wait</warning>():
pass
@@ -0,0 +1 @@
<warning descr="'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.">await</warning> = 1
@@ -0,0 +1 @@
<warning descr="'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.">await</warning> = 1
@@ -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);
}
@@ -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");
}
}