PY-35961 Report missing parentheses in return/yield depending on language version

Previously it was done unconditionally for all Python versions in StarAnnotator.
I moved the corresponding checks from there to CompatibilityVisitor so that
it was clear in which particular versions it's mandatory.

GitOrigin-RevId: 205de8768431445baed98aecd5f9820efe28d281
This commit is contained in:
Mikhail Golubev
2019-07-26 19:15:01 +03:00
committed by intellij-monorepo-bot
parent 895d00f457
commit 5c9ec47997
8 changed files with 58 additions and 14 deletions

View File

@@ -157,6 +157,25 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
registerForAllMatchingVersions(level -> level.isOlderThan(LanguageLevel.PYTHON35) && registerForLanguageLevel(level),
" not support starred expressions in tuples, lists, and sets",
node);
final PsiElement container = PsiTreeUtil.skipParentsOfType(node, PyParenthesizedExpression.class);
if (container instanceof PyTupleExpression) {
final PsiElement tupleParent = container.getParent();
if (tupleParent instanceof PyReturnStatement) {
registerForAllMatchingVersions(level -> level.isAtLeast(LanguageLevel.PYTHON35) &&
level.isOlderThan(LanguageLevel.PYTHON38) &&
registerForLanguageLevel(level),
" not support unpacking without parentheses in return statements",
node);
}
if (tupleParent instanceof PyYieldExpression && !((PyYieldExpression)tupleParent).isDelegating()) {
registerForAllMatchingVersions(level -> level.isAtLeast(LanguageLevel.PYTHON35) &&
level.isOlderThan(LanguageLevel.PYTHON38) &&
registerForLanguageLevel(level),
" not support unpacking without parentheses in yield statements",
node);
}
}
}
}

View File

@@ -16,8 +16,9 @@
package com.jetbrains.python.validation;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.codeInsight.functionTypeComments.psi.PyParameterTypeList;
import com.jetbrains.python.psi.PyReturnStatement;
import com.jetbrains.python.psi.PyParenthesizedExpression;
import com.jetbrains.python.psi.PyStarExpression;
import com.jetbrains.python.psi.PyTupleExpression;
import com.jetbrains.python.psi.PyYieldExpression;
@@ -40,10 +41,13 @@ public class StarAnnotator extends PyAnnotator {
return false;
}
final PsiElement parent = starExpression.getParent();
if (parent instanceof PyTupleExpression && (parent.getParent() instanceof PyReturnStatement ||
parent.getParent() instanceof PyYieldExpression)) {
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;
}

View File

@@ -0,0 +1,4 @@
def func(xs):
yield 42, *xs
yield from 42, <error descr="Can't use starred expression here">*xs</error>
return 42, *xs

View File

@@ -0,0 +1,4 @@
def func(xs):
yield 42, <error descr="Python version 3.5 does not support unpacking without parentheses in yield statements">*xs</error>
yield from 42, <error descr="Can't use starred expression here">*xs</error>
return 42, <error descr="Python version 3.5 does not support unpacking without parentheses in return statements">*xs</error>

View File

@@ -8,12 +8,3 @@ if <error descr="Can't use starred expression here">*x</error>:
1 + (<error descr="Can't use starred expression here">*x</error>)
1 + (*x,)
def f(x):
return x, <error descr="Can't use starred expression here">*x</error>
def g(x):
yield from x, <error descr="Can't use starred expression here">*x</error>
yield x, <error descr="Can't use starred expression here">*x</error>

View File

@@ -0,0 +1,7 @@
def gen(xs):
yield 42, <warning descr="Python version 2.6, 2.7, 3.4 do not support starred expressions in tuples, lists, and sets"><warning descr="Python version 3.5, 3.6, 3.7 do not support unpacking without parentheses in yield statements">*xs</warning></warning>
<warning descr="Python version 2.6, 2.7 do not support this syntax. Delegating to a subgenerator is available since Python 3.3; use explicit iteration over subgenerator instead.">yield from 42, <error descr="Can't use starred expression here"><warning descr="Python version 2.6, 2.7, 3.4 do not support starred expressions in tuples, lists, and sets">*xs</warning></error></warning>
def func(xs):
return 42, <warning descr="Python version 2.6, 2.7, 3.4 do not support starred expressions in tuples, lists, and sets"><warning descr="Python version 3.5, 3.6, 3.7 do not support unpacking without parentheses in return statements">*xs</warning></warning>

View File

@@ -263,6 +263,16 @@ public class PythonHighlightingTest extends PyTestCase {
doTest(LanguageLevel.PYTHON35, false, false);
}
// PY-35961
public void testUnpackingInNonParenthesizedTuplesInReturnAndYieldBefore38() {
doTest(LanguageLevel.PYTHON35, false, false);
}
// PY-35961
public void testUnpackingInNonParenthesizedTuplesInReturnAndYield() {
doTest(LanguageLevel.PYTHON38, false, false);
}
// PY-19927
public void testMagicMethods() {
EditorColorsScheme scheme = createTemporaryColorScheme();

View File

@@ -252,6 +252,11 @@ public class PyCompatibilityInspectionTest extends PyInspectionTestCase {
);
}
// PY-35961
public void testUnpackingInNonParenthesizedTuplesInReturnAndYield() {
doTest(LanguageLevel.PYTHON38);
}
private void doTest(@NotNull LanguageLevel level) {
runWithLanguageLevel(level, this::doTest);
}