a PyTargetExpression will itself call PyTypeProvider.getReferenceType() when asked for its type (PY-7270)

This commit is contained in:
Dmitry Jemerov
2012-08-22 15:42:48 +02:00
parent cda3a70765
commit 3490280116
4 changed files with 30 additions and 6 deletions
@@ -9,5 +9,6 @@ import org.jetbrains.annotations.Nullable;
* @author yole
*/
public interface InstructionTypeCallback {
@Nullable
PyType getType(TypeEvalContext context, @Nullable PsiElement anchor);
}
@@ -5,6 +5,7 @@ import com.intellij.codeInsight.controlflow.impl.InstructionImpl;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.impl.PyTargetExpressionImpl;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NonNls;
@@ -12,9 +13,18 @@ import org.jetbrains.annotations.Nullable;
public class ReadWriteInstruction extends InstructionImpl {
final InstructionTypeCallback EXPR_TYPE = new InstructionTypeCallback() {
@Nullable
@Override
public PyType getType(TypeEvalContext context, @Nullable PsiElement anchor) {
return myElement instanceof PyExpression ? context.getType((PyExpression)myElement) : null;
if (myElement instanceof PyTargetExpressionImpl) {
return ((PyTargetExpressionImpl) myElement).getTypeWithAnchor(context, anchor);
}
if (myElement instanceof PyExpression) {
return context.getType((PyExpression)myElement);
}
else {
return null;
}
}
};
@@ -281,9 +281,11 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
public static PyType getTypeFromTarget(@NotNull final PsiElement target,
final TypeEvalContext context,
PyReferenceExpression anchor) {
final PyType pyType = getReferenceTypeFromProviders(target, context, anchor);
if (pyType != null) {
return pyType;
if (!(target instanceof PyTargetExpression)) { // PyTargetExpression will ask about its type itself
final PyType pyType = getReferenceTypeFromProviders(target, context, anchor);
if (pyType != null) {
return pyType;
}
}
if (target instanceof PyTargetExpression) {
final String name = ((PyTargetExpression)target).getName();
@@ -329,7 +331,7 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
if (propertyDecorator != null) {
return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY);
}
for (PyDecorator decorator: decoratorList.getDecorators()) {
for (PyDecorator decorator : decoratorList.getDecorators()) {
final PyQualifiedName qName = decorator.getQualifiedName();
if (qName != null && (qName.endsWith(PyNames.SETTER) || qName.endsWith(PyNames.DELETER))) {
return PyBuiltinCache.getInstance(target).getObjectType(PyNames.PROPERTY);
@@ -342,7 +344,9 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
}
if (target instanceof PsiDirectory) {
PsiFile file = ((PsiDirectory)target).findFile(PyNames.INIT_DOT_PY);
if (file != null) return getTypeFromTarget(file, context, anchor);
if (file != null) {
return getTypeFromTarget(file, context, anchor);
}
}
return null;
}
@@ -98,6 +98,11 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
}
public PyType getType(@NotNull TypeEvalContext context) {
return getTypeWithAnchor(context, null);
}
@Nullable
public PyType getTypeWithAnchor(TypeEvalContext context, @Nullable PsiElement anchor) {
if (!TypeEvalStack.mayEvaluate(this)) {
return null;
}
@@ -107,6 +112,10 @@ public class PyTargetExpressionImpl extends PyPresentableElementImpl<PyTargetExp
// imported via __all__
return null;
}
final PyType pyType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(this, context, anchor);
if (pyType != null) {
return pyType;
}
if (!context.maySwitchToAST(this)) {
final PsiElement value = getStub() != null ? findAssignedValueByStub() : findAssignedValue();
if (value instanceof PyTypedElement) {