Fixed resolving '/' to __truediv__ when available (PY-5499, PY-4460)

This commit is contained in:
Andrey Vlasovskikh
2012-02-03 22:20:14 +04:00
parent 0cfcfe61eb
commit 6adf2a5ec6
4 changed files with 46 additions and 19 deletions

View File

@@ -82,6 +82,8 @@ public class PyNames {
public static final String DELITEM = "__delitem__";
public static final String POS = "__pos__";
public static final String NEG = "__neg__";
public static final String DIV = "__div__";
public static final String TRUEDIV = "__truediv__";
public static final String NAME = "__name__";
public static final String ENTER = "__enter__";
@@ -91,7 +93,7 @@ public class PyNames {
public static final String COLLECTIONS_PY = "collections.py";
public static final String SET = "set";
public static final String KEYS = "keys";
public static final String PASS = "pass";
@@ -267,7 +269,7 @@ public class PyNames {
// canonical names, not forced by interpreter
public static final String CANONICAL_SELF = "self";
public static final String BASESTRING = "basestring";
/**
* Contains keywords as of CPython 2.5.
*/
@@ -324,7 +326,7 @@ public class PyNames {
* @return true iff name is not reserved and is a well-formed identifier.
*/
public static boolean isIdentifier(@NotNull @NonNls String name) {
return ! isReserved(name) && IDENTIFIER_PATTERN.matcher(name).matches();
return ! isReserved(name) && IDENTIFIER_PATTERN.matcher(name).matches();
}
public static boolean isRightOperatorName(@Nullable String name) {

View File

@@ -2,6 +2,7 @@ package com.jetbrains.python.psi.impl.references;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
@@ -35,23 +36,10 @@ public class PyOperatorReference extends PyReferenceImpl {
res = resolveMember(expr.getRightExpression(), name);
}
else {
final TypeEvalContext typeEvalContext = myContext.getTypeEvalContext();
typeEvalContext.trace("Trying to resolve left operator");
typeEvalContext.traceIndent();
try {
res.addAll(resolveMember(expr.getLeftExpression(), name));
}
finally {
typeEvalContext.traceUnindent();
}
typeEvalContext.trace("Trying to resolve right operator");
typeEvalContext.traceIndent();
try {
res.addAll(resolveMember(expr.getRightExpression(), leftToRightOperatorName(name)));
}
finally {
typeEvalContext.traceUnindent();
if (PyNames.DIV.equals(name) && isTrueDivEnabled(myElement)) {
resolveLeftAndRightOperators(res, expr, PyNames.TRUEDIV);
}
resolveLeftAndRightOperators(res, expr, name);
}
}
else if (myElement instanceof PySubscriptionExpression) {
@@ -92,6 +80,35 @@ public class PyOperatorReference extends PyReferenceImpl {
return name.replaceFirst("__([a-z]+)__", "__r$1__");
}
private static boolean isTrueDivEnabled(@NotNull PyElement anchor) {
final PsiFile file = anchor.getContainingFile();
if (file instanceof PyFile) {
final PyFile pyFile = (PyFile)file;
return FutureFeature.DIVISION.requiredAt(pyFile.getLanguageLevel()) || pyFile.hasImportFromFuture(FutureFeature.DIVISION);
}
return false;
}
private void resolveLeftAndRightOperators(List<RatedResolveResult> res, PyBinaryExpression expr, String name) {
final TypeEvalContext typeEvalContext = myContext.getTypeEvalContext();
typeEvalContext.trace("Trying to resolve left operator");
typeEvalContext.traceIndent();
try {
res.addAll(resolveMember(expr.getLeftExpression(), name));
}
finally {
typeEvalContext.traceUnindent();
}
typeEvalContext.trace("Trying to resolve right operator");
typeEvalContext.traceIndent();
try {
res.addAll(resolveMember(expr.getRightExpression(), leftToRightOperatorName(name)));
}
finally {
typeEvalContext.traceUnindent();
}
}
@NotNull
private List<RatedResolveResult> resolveMember(@Nullable PyExpression object, @Nullable String name) {
final ArrayList<RatedResolveResult> results = new ArrayList<RatedResolveResult>();

View File

@@ -0,0 +1,3 @@
def test(x):
return 1 / x
# <ref>

View File

@@ -40,4 +40,9 @@ public class Py3ResolveTest extends PyResolveTestCase {
public void testObjectMethods() { // PY-1494
assertResolvesTo(PyFunction.class, "__repr__");
}
// PY-5499
public void testTrueDiv() {
assertResolvesTo(PyFunction.class, "__truediv__");
}
}