mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'python3.5'
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -357,8 +357,23 @@ public class PyNames {
|
||||
.put("__round__", new BuiltinDescription("(self, n=None)"))
|
||||
.build();
|
||||
|
||||
public static ImmutableMap<String, BuiltinDescription> PY35_BUILTIN_METHODS = ImmutableMap.<String, BuiltinDescription>builder()
|
||||
.putAll(PY3_BUILTIN_METHODS)
|
||||
.put("__imatmul__", _self_other_descr)
|
||||
.put("__matmul__", _self_other_descr)
|
||||
.put("__rmatmul__", _self_other_descr)
|
||||
.build();
|
||||
|
||||
public static ImmutableMap<String, BuiltinDescription> getBuiltinMethods(LanguageLevel level) {
|
||||
return level.isPy3K() ? PY3_BUILTIN_METHODS : PY2_BUILTIN_METHODS;
|
||||
if (level.isAtLeast(LanguageLevel.PYTHON35)) {
|
||||
return PY35_BUILTIN_METHODS;
|
||||
}
|
||||
else if (level.isAtLeast(LanguageLevel.PYTHON30)) {
|
||||
return PY3_BUILTIN_METHODS;
|
||||
}
|
||||
else {
|
||||
return PY2_BUILTIN_METHODS;
|
||||
}
|
||||
}
|
||||
|
||||
// canonical names, not forced by interpreter
|
||||
|
||||
@@ -118,7 +118,7 @@ public class PyTokenTypes {
|
||||
public static final PyElementType RBRACKET = new PyElementType("RBRACKET");// ]
|
||||
public static final PyElementType LBRACE = new PyElementType("LBRACE");// {
|
||||
public static final PyElementType RBRACE = new PyElementType("RBRACE");// }
|
||||
public static final PyElementType AT = new PyElementType("AT");// @
|
||||
public static final PyElementType AT = new PyElementType("AT", "__matmul__");// @
|
||||
public static final PyElementType COMMA = new PyElementType("COMMA");// ,
|
||||
public static final PyElementType COLON = new PyElementType("COLON");// :
|
||||
public static final PyElementType DOT = new PyElementType("DOT");// .
|
||||
@@ -128,6 +128,7 @@ public class PyTokenTypes {
|
||||
public static final PyElementType PLUSEQ = new PyElementType("PLUSEQ");// +=
|
||||
public static final PyElementType MINUSEQ = new PyElementType("MINUSEQ");// -=
|
||||
public static final PyElementType MULTEQ = new PyElementType("MULTEQ");// *=
|
||||
public static final PyElementType ATEQ = new PyElementType("ATEQ"); // @=
|
||||
public static final PyElementType DIVEQ = new PyElementType("DIVEQ"); // /=
|
||||
public static final PyElementType FLOORDIVEQ = new PyElementType("FLOORDIVEQ"); // //=
|
||||
public static final PyElementType PERCEQ = new PyElementType("PERCEQ");// %=
|
||||
@@ -139,10 +140,10 @@ public class PyTokenTypes {
|
||||
public static final PyElementType EXPEQ = new PyElementType("EXPEQ");// **=
|
||||
|
||||
public static final TokenSet OPERATIONS = TokenSet.create(
|
||||
PLUS, MINUS, MULT, EXP, DIV, FLOORDIV, PERC, LTLT, GTGT, AND, OR,
|
||||
PLUS, MINUS, MULT, AT, EXP, DIV, FLOORDIV, PERC, LTLT, GTGT, AND, OR,
|
||||
XOR, TILDE, LT, GT, LE, GE, EQEQ, NE, NE_OLD, AT, COLON, TICK, EQ,
|
||||
PLUSEQ, MINUSEQ,
|
||||
MULTEQ, DIVEQ, FLOORDIVEQ, PERCEQ, ANDEQ, OREQ, XOREQ, LTLTEQ, GTGTEQ,
|
||||
MULTEQ, ATEQ, DIVEQ, FLOORDIVEQ, PERCEQ, ANDEQ, OREQ, XOREQ, LTLTEQ, GTGTEQ,
|
||||
EXPEQ);
|
||||
|
||||
public static final TokenSet COMPARISON_OPERATIONS = TokenSet.create(
|
||||
@@ -150,8 +151,8 @@ public class PyTokenTypes {
|
||||
|
||||
public static final TokenSet SHIFT_OPERATIONS = TokenSet.create(LTLT, GTGT);
|
||||
public static final TokenSet ADDITIVE_OPERATIONS = TokenSet.create(PLUS, MINUS);
|
||||
public static final TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, FLOORDIV, DIV, PERC);
|
||||
public static final TokenSet MULTIPLICATIVE_OR_EXP = TokenSet.create(MULT, FLOORDIV, DIV, PERC, EXP);
|
||||
public static final TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, AT, FLOORDIV, DIV, PERC);
|
||||
public static final TokenSet MULTIPLICATIVE_OR_EXP = TokenSet.create(MULT, AT, FLOORDIV, DIV, PERC, EXP);
|
||||
public static final TokenSet UNARY_OPERATIONS = TokenSet.create(PLUS, MINUS, TILDE);
|
||||
public static final TokenSet BITWISE_OPERATIONS = TokenSet.create(AND, OR, XOR);
|
||||
public static final TokenSet EQUALITY_OPERATIONS = TokenSet.create(EQEQ, NE, NE_OLD);
|
||||
@@ -162,7 +163,7 @@ public class PyTokenTypes {
|
||||
public static final TokenSet OPEN_BRACES = TokenSet.create(LBRACKET, LBRACE, LPAR);
|
||||
public static final TokenSet CLOSE_BRACES = TokenSet.create(RBRACKET, RBRACE, RPAR);
|
||||
|
||||
public static final TokenSet AUG_ASSIGN_OPERATIONS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, DIVEQ,
|
||||
public static final TokenSet AUG_ASSIGN_OPERATIONS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, ATEQ, DIVEQ,
|
||||
PERCEQ, EXPEQ, GTGTEQ, LTLTEQ, ANDEQ, OREQ, XOREQ, FLOORDIVEQ);
|
||||
|
||||
public static final PyElementType BACKSLASH = new PyElementType("BACKSLASH");
|
||||
|
||||
@@ -32,10 +32,11 @@ public enum LanguageLevel {
|
||||
PYTHON31(31, true, false, true, true),
|
||||
PYTHON32(32, true, false, true, true),
|
||||
PYTHON33(33, true, false, true, true),
|
||||
PYTHON34(34, true, false, true, true);
|
||||
PYTHON34(34, true, false, true, true),
|
||||
PYTHON35(35, true, false, true, true);
|
||||
|
||||
private static LanguageLevel DEFAULT2 = PYTHON27;
|
||||
private static LanguageLevel DEFAULT3 = PYTHON33;
|
||||
private static LanguageLevel DEFAULT3 = PYTHON34;
|
||||
|
||||
public static LanguageLevel FORCE_LANGUAGE_LEVEL = null;
|
||||
|
||||
@@ -121,6 +122,9 @@ public enum LanguageLevel {
|
||||
if (pythonVersion.startsWith("3.4")) {
|
||||
return PYTHON34;
|
||||
}
|
||||
if (pythonVersion.startsWith("3.5")) {
|
||||
return PYTHON35;
|
||||
}
|
||||
return DEFAULT3;
|
||||
}
|
||||
return getDefault();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.jetbrains.python.psi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -26,4 +27,6 @@ public interface PyAugAssignmentStatement extends PyStatement {
|
||||
PyExpression getTarget();
|
||||
@Nullable
|
||||
PyExpression getValue();
|
||||
@Nullable
|
||||
PsiElement getOperation();
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@ public interface PyElementTypes {
|
||||
PyTokenTypes.OR, PyTokenTypes.XOR, PyTokenTypes.AND, PyTokenTypes.LTLT, PyTokenTypes.GTGT,
|
||||
PyTokenTypes.EQEQ, PyTokenTypes.GE, PyTokenTypes.LE, PyTokenTypes.NE, PyTokenTypes.NE_OLD,
|
||||
PyTokenTypes.IN_KEYWORD, PyTokenTypes.IS_KEYWORD, PyTokenTypes.NOT_KEYWORD, PyTokenTypes.PLUS,
|
||||
PyTokenTypes.MINUS, PyTokenTypes.MULT, PyTokenTypes.FLOORDIV, PyTokenTypes.DIV, PyTokenTypes.PERC, PyTokenTypes.EXP);
|
||||
PyTokenTypes.MINUS, PyTokenTypes.MULT, PyTokenTypes.AT, PyTokenTypes.FLOORDIV, PyTokenTypes.DIV,
|
||||
PyTokenTypes.PERC, PyTokenTypes.EXP);
|
||||
|
||||
TokenSet UNARY_OPS = TokenSet.create(PyTokenTypes.NOT_KEYWORD, PyTokenTypes.PLUS, PyTokenTypes.MINUS, PyTokenTypes.TILDE);
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilderEx, C
|
||||
.between(FROM_KEYWORD, DOT).spaces(1)
|
||||
.between(DOT, IMPORT_KEYWORD).spaces(1)
|
||||
.around(DOT).spaces(0)
|
||||
.aroundInside(AT, DECORATOR_CALL).none()
|
||||
.before(SEMICOLON).spaceIf(commonSettings.SPACE_BEFORE_SEMICOLON)
|
||||
.withinPairInside(LPAR, RPAR, ARGUMENT_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES)
|
||||
.withinPairInside(LPAR, RPAR, PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_PARENTHESES)
|
||||
|
||||
@@ -160,6 +160,7 @@ return PyTokenTypes.DOCSTRING; }
|
||||
"-=" { return PyTokenTypes.MINUSEQ; }
|
||||
"**=" { return PyTokenTypes.EXPEQ; }
|
||||
"*=" { return PyTokenTypes.MULTEQ; }
|
||||
"@=" { return PyTokenTypes.ATEQ; }
|
||||
"//=" { return PyTokenTypes.FLOORDIVEQ; }
|
||||
"/=" { return PyTokenTypes.DIVEQ; }
|
||||
"%=" { return PyTokenTypes.PERCEQ; }
|
||||
|
||||
@@ -453,7 +453,7 @@ public class PyReplaceExpressionUtil implements PyElementTypes {
|
||||
else if (expr instanceof PyBinaryExpression) {
|
||||
final IElementType opType = getOperationType(expr);
|
||||
if (opType == EXP) priority = 3;
|
||||
if (opType == MULT || opType == DIV || opType == PERC || opType == FLOORDIV) priority = 4;
|
||||
if (opType == MULT || opType == AT || opType == DIV || opType == PERC || opType == FLOORDIV) priority = 4;
|
||||
if (opType == PLUS || opType == MINUS) priority = 5;
|
||||
if (opType == LTLT || opType == GTGT) priority = 6;
|
||||
if (opType == AND) priority = 7;
|
||||
|
||||
@@ -50,7 +50,6 @@ import com.jetbrains.python.PythonLanguage;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyAugAssignmentStatementImpl;
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils;
|
||||
import com.jetbrains.python.refactoring.PyDefUseUtil;
|
||||
import com.jetbrains.python.refactoring.PyReplaceExpressionUtil;
|
||||
@@ -315,8 +314,8 @@ public class PyInlineLocalHandler extends InlineActionHandler {
|
||||
private static PyExpression prepareValue(@NotNull PyStatement def, @NotNull String localName, @NotNull Project project) {
|
||||
final PyExpression value = getValue(def);
|
||||
assert value != null;
|
||||
if (def instanceof PyAugAssignmentStatementImpl) {
|
||||
final PyAugAssignmentStatementImpl expression = (PyAugAssignmentStatementImpl)def;
|
||||
if (def instanceof PyAugAssignmentStatement) {
|
||||
final PyAugAssignmentStatement expression = (PyAugAssignmentStatement)def;
|
||||
final PsiElement operation = expression.getOperation();
|
||||
assert operation != null;
|
||||
final String op = operation.getText().replace('=', ' ');
|
||||
|
||||
@@ -919,6 +919,7 @@ ihave
|
||||
ilog
|
||||
imagetext
|
||||
imagnumber
|
||||
imatmul
|
||||
imode
|
||||
impls
|
||||
importfile
|
||||
@@ -1242,6 +1243,7 @@ mapdict
|
||||
mapstar
|
||||
markedsectionclose
|
||||
markobject
|
||||
matmul
|
||||
maxamount
|
||||
maxbinsize
|
||||
maxcache
|
||||
@@ -1702,6 +1704,7 @@ ripemd
|
||||
rlecoderengine
|
||||
rledecoderengine
|
||||
rlshift
|
||||
rmatmul
|
||||
rmcolorizer
|
||||
rmenu
|
||||
rmod
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.jetbrains.python.PyNames;
|
||||
@@ -50,10 +51,10 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
|
||||
AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON30, Sets.newHashSet("R", "B"));
|
||||
AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON31, Sets.newHashSet("R", "B", "BR"));
|
||||
AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON32, Sets.newHashSet("R", "B", "BR"));
|
||||
AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON33, Sets.newHashSet("R", "U", "B", "BR", "RB"));
|
||||
AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON34, Sets.newHashSet("R", "U", "B", "BR", "RB"));
|
||||
}
|
||||
|
||||
private static final Set<String> DEFAULT_PREFIXES = Sets.newHashSet(Sets.newHashSet("R", "U", "B", "BR", "RB"));
|
||||
|
||||
public CompatibilityVisitor(List<LanguageLevel> versionsToProcess) {
|
||||
myVersionsToProcess = versionsToProcess;
|
||||
}
|
||||
@@ -195,6 +196,22 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
|
||||
}
|
||||
commonRegisterProblem(message, " not support <>, use != instead.", len, node, new ReplaceNotEqOperatorQuickFix());
|
||||
}
|
||||
else if (node.isOperator("@")) {
|
||||
checkMatrixMultiplicationOperator(node.getPsiOperator());
|
||||
}
|
||||
}
|
||||
|
||||
private void checkMatrixMultiplicationOperator(PsiElement node) {
|
||||
boolean problem = false;
|
||||
for (LanguageLevel level : myVersionsToProcess) {
|
||||
if (level.isOlderThan(LanguageLevel.PYTHON35)) {
|
||||
problem = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (problem) {
|
||||
registerProblem(node, "Python versions < 3.5 do not support matrix multiplication operators");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -254,7 +271,8 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
|
||||
final LanguageLevel languageLevel = myVersionsToProcess.get(i);
|
||||
if (prefix.isEmpty()) continue;
|
||||
|
||||
final Set<String> prefixes = AVAILABLE_PREFIXES.get(languageLevel);
|
||||
final Set<String> prefixesForLanguageLevel = AVAILABLE_PREFIXES.get(languageLevel);
|
||||
final Set<String> prefixes = prefixesForLanguageLevel != null ? prefixesForLanguageLevel : DEFAULT_PREFIXES;
|
||||
if (!prefixes.contains(prefix))
|
||||
len = appendLanguageLevel(message, len, languageLevel);
|
||||
}
|
||||
@@ -541,6 +559,18 @@ public abstract class CompatibilityVisitor extends PyAnnotator {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyAugAssignmentStatement(PyAugAssignmentStatement node) {
|
||||
super.visitPyAugAssignmentStatement(node);
|
||||
final PsiElement operation = node.getOperation();
|
||||
if (operation != null) {
|
||||
final IElementType operationType = operation.getNode().getElementType();
|
||||
if (PyTokenTypes.ATEQ.equals(operationType)) {
|
||||
checkMatrixMultiplicationOperator(operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class YieldVisitor extends PyElementVisitor {
|
||||
private boolean _haveYield = false;
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
class C:
|
||||
def __matmul__(self, other):
|
||||
@@ -0,0 +1,2 @@
|
||||
class C:
|
||||
def __matmul<caret>
|
||||
@@ -0,0 +1,2 @@
|
||||
x <warning descr="Python versions < 3.5 do not support matrix multiplication operators">@</warning> y
|
||||
x <warning descr="Python versions < 3.5 do not support matrix multiplication operators">@=</warning> y
|
||||
@@ -0,0 +1,5 @@
|
||||
x @ y
|
||||
x @ y @ z
|
||||
x @ y * z
|
||||
x + y @ z
|
||||
z @= x
|
||||
@@ -0,0 +1,67 @@
|
||||
PyFile:MatMul.py
|
||||
PyExpressionStatement
|
||||
PyBinaryExpression
|
||||
PyReferenceExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AT)('@')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: y
|
||||
PsiElement(Py:IDENTIFIER)('y')
|
||||
PsiWhiteSpace('\n')
|
||||
PyExpressionStatement
|
||||
PyBinaryExpression
|
||||
PyBinaryExpression
|
||||
PyReferenceExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AT)('@')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: y
|
||||
PsiElement(Py:IDENTIFIER)('y')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AT)('@')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: z
|
||||
PsiElement(Py:IDENTIFIER)('z')
|
||||
PsiWhiteSpace('\n')
|
||||
PyExpressionStatement
|
||||
PyBinaryExpression
|
||||
PyBinaryExpression
|
||||
PyReferenceExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AT)('@')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: y
|
||||
PsiElement(Py:IDENTIFIER)('y')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:MULT)('*')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: z
|
||||
PsiElement(Py:IDENTIFIER)('z')
|
||||
PsiWhiteSpace('\n')
|
||||
PyExpressionStatement
|
||||
PyBinaryExpression
|
||||
PyReferenceExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:PLUS)('+')
|
||||
PsiWhiteSpace(' ')
|
||||
PyBinaryExpression
|
||||
PyReferenceExpression: y
|
||||
PsiElement(Py:IDENTIFIER)('y')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:AT)('@')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: z
|
||||
PsiElement(Py:IDENTIFIER)('z')
|
||||
PsiWhiteSpace('\n')
|
||||
PyAugAssignmentStatement
|
||||
PyReferenceExpression: z
|
||||
PsiElement(Py:IDENTIFIER)('z')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:ATEQ)('@=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
(y @ z)[::-5]
|
||||
(y @ z)[5]
|
||||
(y @ z)(5)
|
||||
(y @ z).foo
|
||||
|
||||
-(y @ z)
|
||||
+(y @ z)
|
||||
~(y @ z)
|
||||
|
||||
5 ** (y @ z)
|
||||
(y @ z) ** 5
|
||||
|
||||
5 * y @ z
|
||||
y @ z * 5
|
||||
|
||||
5 / (y @ z)
|
||||
y @ z / 5
|
||||
|
||||
5 // (y @ z)
|
||||
y @ z // 5
|
||||
|
||||
5 + y @ z
|
||||
y @ z + 5
|
||||
|
||||
y @ z - 5
|
||||
5 - y @ z
|
||||
|
||||
5 >> y @ z
|
||||
y @ z << 5
|
||||
|
||||
5 & y @ z
|
||||
y @ z & 5
|
||||
|
||||
5 ^ y @ z
|
||||
y @ z ^ 5
|
||||
|
||||
5 | y @ z
|
||||
y @ z | 5
|
||||
|
||||
() in y @ z
|
||||
y @ z in ()
|
||||
|
||||
5 is y @ z
|
||||
y @ z is 5
|
||||
|
||||
5 < y @ z
|
||||
y @ z < 5
|
||||
|
||||
not y @ z
|
||||
|
||||
5 and y @ z
|
||||
y @ z and 5
|
||||
|
||||
5 or y @ z
|
||||
y @ z or 5
|
||||
|
||||
y @ z if y @ z else y @ z
|
||||
@@ -0,0 +1,8 @@
|
||||
class C:
|
||||
def __matmul__(self, other):
|
||||
return self
|
||||
|
||||
|
||||
x = C()
|
||||
x @ y
|
||||
# <ref>
|
||||
@@ -0,0 +1,8 @@
|
||||
class C:
|
||||
def __rmatmul__(self, other):
|
||||
return self
|
||||
|
||||
|
||||
x = C()
|
||||
y @ x
|
||||
# <ref>
|
||||
@@ -141,4 +141,14 @@ public class Py3CompletionTest extends PyTestCase {
|
||||
public void testNotImportedSubmodulesOfNamespacePackage() {
|
||||
doMultiFileTest();
|
||||
}
|
||||
|
||||
// PY-15390
|
||||
public void testMatMul() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON35, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doTest();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,4 +571,14 @@ public class PyResolveTest extends PyResolveTestCase {
|
||||
public void testResolveAttributesUsingOldStyleMROWhenUnresolvedAncestorsAndC3Fails() {
|
||||
assertResolvesTo(PyFunction.class, "foo");
|
||||
}
|
||||
|
||||
// PY-15390
|
||||
public void testMatMul() {
|
||||
assertResolvesTo(PyFunction.class, "__matmul__");
|
||||
}
|
||||
|
||||
// PY-15390
|
||||
public void testRMatMul() {
|
||||
assertResolvesTo(PyFunction.class, "__rmatmul__");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,6 +468,11 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-15390
|
||||
public void testMatMul() {
|
||||
doTest(LanguageLevel.PYTHON35);
|
||||
}
|
||||
|
||||
public void doTest(LanguageLevel languageLevel) {
|
||||
LanguageLevel prev = myLanguageLevel;
|
||||
myLanguageLevel = languageLevel;
|
||||
|
||||
@@ -150,6 +150,11 @@ public class PyCompatibilityInspectionTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-15390
|
||||
public void testMatMul() {
|
||||
doTest(LanguageLevel.PYTHON35);
|
||||
}
|
||||
|
||||
private void doTest(@NotNull LanguageLevel level) {
|
||||
runWithLanguageLevel(level, new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -145,6 +145,11 @@ public class PyInlineLocalTest extends PyTestCase {
|
||||
checkOperatorPrecedence("x = 10 if True else 2", "conditional");
|
||||
}
|
||||
|
||||
// PY-15390
|
||||
public void testMatMulPrecedence() throws Exception {
|
||||
checkOperatorPrecedence("x = y @ z", "matrixMultiplication");
|
||||
}
|
||||
|
||||
private void checkOperatorPrecedence(@NotNull final String firstLine, @NotNull String resultPrefix) throws Exception {
|
||||
myFixture.configureByFile("/refactoring/inlinelocal/operatorPrecedence/template.py");
|
||||
WriteCommandAction.runWriteCommandAction(myFixture.getProject(), new Runnable() {
|
||||
|
||||
Reference in New Issue
Block a user