Added 'origin' parameter to TypeEvalContext.userInitiated()

This commit is contained in:
Andrey Vlasovskikh
2013-05-13 17:02:34 +04:00
parent 17abf2d666
commit fce1b98e7c
15 changed files with 38 additions and 37 deletions
@@ -58,8 +58,8 @@ public class TypeEvalContext {
*
* Should be used for code completion, go to definition, find usages, refactorings, documentation.
*/
public static TypeEvalContext userInitiated() {
return new TypeEvalContext(true, true, null);
public static TypeEvalContext userInitiated(@Nullable PsiFile origin) {
return new TypeEvalContext(true, true, origin);
}
/**
@@ -114,7 +114,7 @@ public class PyDictKeyNamesCompletionContributor extends CompletionContributor {
if (callee == null) return;
final String name = callee.getText();
if ("dict".equals(name)) {
final TypeEvalContext context = TypeEvalContext.userInitiated();
final TypeEvalContext context = TypeEvalContext.userInitiated(callee.getContainingFile());
final PyType type = context.getType(dictConstructor);
if (type != null && type.isBuiltin(context)) {
final PyArgumentList list = dictConstructor.getArgumentList();
@@ -196,7 +196,8 @@ public class PyOverrideImplementUtil {
statementBody.append(PyNames.PASS);
}
else {
if (!PyNames.INIT.equals(baseFunction.getName()) && baseFunction.getReturnType(TypeEvalContext.userInitiated(), null) != PyNoneType.INSTANCE) {
final TypeEvalContext context = TypeEvalContext.userInitiated(baseFunction.getContainingFile());
if (!PyNames.INIT.equals(baseFunction.getName()) && baseFunction.getReturnType(context, null) != PyNoneType.INSTANCE) {
statementBody.append("return ");
}
if (baseClass.isNewStyleClass()) {
@@ -113,7 +113,7 @@ public class DocStringTypeReference extends PsiPolyVariantReferenceBase<PsiEleme
for (PyImportElement element : elements) {
final PyReferenceExpression referenceExpression = element.getImportReferenceExpression();
if (referenceExpression == null) continue;
final PyType type = TypeEvalContext.userInitiated().getType(referenceExpression);
final PyType type = TypeEvalContext.userInitiated(file).getType(referenceExpression);
if (type instanceof PyClassType) {
variants.add(((PyClassType)type).getPyClass());
}
@@ -75,6 +75,7 @@ class PyDocumentationBuilder {
PsiElement outer = null;
boolean is_property = false;
String accessor_kind = "None";
final TypeEvalContext context = TypeEvalContext.userInitiated(myElement.getContainingFile());
if (myOriginalElement != null) {
String elementName = myOriginalElement.getText();
if (PyUtil.isPythonIdentifier(elementName)) {
@@ -82,7 +83,7 @@ class PyDocumentationBuilder {
if (outer instanceof PyQualifiedExpression) {
PyExpression qual = ((PyQualifiedExpression)outer).getQualifier();
if (qual != null) {
PyType type = TypeEvalContext.userInitiated().getType(qual);
PyType type = context.getType(qual);
if (type instanceof PyClassType) {
cls = ((PyClassType)type).getPyClass();
Property property = cls.findProperty(elementName);
@@ -190,7 +191,6 @@ class PyDocumentationBuilder {
myBody.addItem(combUp("Parameter " + PyUtil.getReadableRepr(followed, false)));
boolean typeFromDocstringAdded = addTypeAndDescriptionFromDocstring((PyNamedParameter)followed);
if (outer instanceof PyExpression) {
TypeEvalContext context = TypeEvalContext.userInitiated();
PyType type = context.getType((PyExpression)outer);
if (type != null) {
String s = null;
@@ -216,14 +216,14 @@ class PyDocumentationBuilder {
if (s != null) {
myBody
.addItem(combUp(s));
PythonDocumentationProvider.describeTypeWithLinks(myBody, followed, type, TypeEvalContext.userInitiated());
PythonDocumentationProvider.describeTypeWithLinks(myBody, followed, type, context);
}
}
}
}
else if (followed != null && outer instanceof PyReferenceExpression) {
myBody.addItem(combUp("\nInferred type: "));
PythonDocumentationProvider.describeExpressionTypeWithLinks(myBody, (PyReferenceExpression)outer, TypeEvalContext.userInitiated());
PythonDocumentationProvider.describeExpressionTypeWithLinks(myBody, (PyReferenceExpression)outer, context);
}
if (myBody.isEmpty() && myEpilog.isEmpty()) {
return null; // got nothing substantial to say!
@@ -148,18 +148,18 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
}
static String describeExpressionType(PyExpression expr) {
final TypeEvalContext context = TypeEvalContext.userInitiated();
final TypeEvalContext context = TypeEvalContext.userInitiated(expr.getContainingFile());
return String.format("Inferred type: %s", getTypeName(context.getType(expr), context));
}
public static String getTypeDescription(@NotNull PyFunction fun) {
final TypeEvalContext context = TypeEvalContext.userInitiated();
final TypeEvalContext context = TypeEvalContext.userInitiated(fun.getContainingFile());
PyTypeModelBuilder builder = new PyTypeModelBuilder(context);
return builder.build(fun).asString();
}
public static void getTypeDescription(@NotNull PyFunction fun, ChainIterable<String> body) {
final TypeEvalContext context = TypeEvalContext.userInitiated();
final TypeEvalContext context = TypeEvalContext.userInitiated(fun.getContainingFile());
PyTypeModelBuilder builder = new PyTypeModelBuilder(context);
builder.build(fun).toBodyWithLinks(body, fun);
}
@@ -481,7 +481,7 @@ public class PythonDocumentationProvider extends AbstractDocumentationProvider i
@Nullable
private static PyClass inferClassOfParameter(PsiElement context) {
if (context instanceof PyNamedParameter) {
final PyType type = TypeEvalContext.userInitiated().getType((PyNamedParameter)context);
final PyType type = TypeEvalContext.userInitiated(context.getContainingFile()).getType((PyNamedParameter)context);
if (type instanceof PyClassType) {
return ((PyClassType)type).getPyClass();
}
@@ -39,7 +39,7 @@ public class PyUsageTypeProvider implements UsageTypeProviderEx {
if (element instanceof PyQualifiedExpression) {
final PyExpression qualifier = ((PyQualifiedExpression)element).getQualifier();
if (qualifier != null) {
final TypeEvalContext context = TypeEvalContext.userInitiated();
final TypeEvalContext context = TypeEvalContext.userInitiated(element.getContainingFile());
final PyType type = context.getType(qualifier);
if (type == null || type instanceof PyTypeReference) {
final PyCallExpression call = PsiTreeUtil.getParentOfType(element, PyCallExpression.class);
@@ -75,7 +75,7 @@ public class AddMethodQuickFix implements LocalQuickFix {
boolean made_instance = false;
if (call_by_class) {
if (args.length > 0) {
PyType first_arg_type = TypeEvalContext.userInitiated().getType(args[0]);
PyType first_arg_type = TypeEvalContext.userInitiated(cls.getContainingFile()).getType(args[0]);
if (first_arg_type instanceof PyClassType && ((PyClassType)first_arg_type).getPyClass().isSubclass(cls)) {
// class, first arg ok: instance method
builder.parameter("self"); // NOTE: might use a name other than 'self', according to code style.
@@ -81,7 +81,7 @@ public class PyImportReference extends PyReferenceImpl {
}
PyExpression qualifier = myElement.getQualifier();
final TypeEvalContext context = TypeEvalContext.userInitiated();
final TypeEvalContext context = TypeEvalContext.userInitiated(myElement.getContainingFile());
if (qualifier != null) {
// qualifier's type must be module, it should know how to complete
PyType type = context.getType(qualifier);
@@ -247,7 +247,7 @@ public class PyQualifiedReference extends PyReferenceImpl {
}
final PyQualifiedExpression element = CompletionUtil.getOriginalOrSelf(myElement);
PyType qualifierType = TypeEvalContext.userInitiated().getType(qualifier);
PyType qualifierType = TypeEvalContext.userInitiated(myElement.getContainingFile()).getType(qualifier);
ProcessingContext ctx = new ProcessingContext();
final Set<String> namesAlready = new HashSet<String>();
ctx.put(PyType.CTX_NAMES, namesAlready);
@@ -348,7 +348,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType {
boolean suppressParentheses = context.get(CTX_SUPPRESS_PARENTHESES) != null;
addOwnClassMembers(location, namesAlready, suppressParentheses, ret);
final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated();
final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(location != null ? location.getContainingFile() : null);
addInheritedMembers(prefix, location, namesAlready, context, ret, typeEvalContext);
// from providers
@@ -110,7 +110,7 @@ public class PyReplaceExpressionUtil implements PyElementTypes {
return replaceSubstringWithDictFormatting(oldExpression, quotes, prefix, suffix, formatValue, newText);
}
else {
final TypeEvalContext context = TypeEvalContext.userInitiated();
final TypeEvalContext context = TypeEvalContext.userInitiated(oldExpression.getContainingFile());
final PyType valueType = context.getType(formatValue);
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(oldExpression);
final PyType tupleType = builtinCache.getTupleType();
@@ -188,7 +188,7 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
if (text != null) {
candidates.addAll(NameSuggesterUtil.generateNames(text));
}
final TypeEvalContext context = TypeEvalContext.userInitiated();
final TypeEvalContext context = TypeEvalContext.userInitiated(expression.getContainingFile());
PyType type = context.getType(expression);
if (type != null && type != PyNoneType.INSTANCE) {
String typeName = type.getName();
@@ -33,7 +33,7 @@ public class PyTypeParserTest extends PyTestCase {
myFixture.configureByFile("typeParser/typeParser.py");
final PyCollectionType type = (PyCollectionType) PyTypeParser.getTypeByName(myFixture.getFile(), "list of MyObject");
assertClassType(type, "list");
assertClassType(type.getElementType(TypeEvalContext.userInitiated()), "MyObject");
assertClassType(type.getElementType(TypeEvalContext.userInitiated(null)), "MyObject");
}
public void testDictType() {
@@ -41,7 +41,7 @@ public class PyTypeParserTest extends PyTestCase {
final PyCollectionType type = (PyCollectionType) PyTypeParser.getTypeByName(myFixture.getFile(), "dict from str to MyObject");
assertNotNull(type);
assertClassType(type, "dict");
final PyType elementType = type.getElementType(TypeEvalContext.userInitiated());
final PyType elementType = type.getElementType(TypeEvalContext.userInitiated(null));
assertInstanceOf(elementType, PyTupleType.class);
final PyTupleType tupleType = (PyTupleType)elementType;
assertEquals(2, tupleType.getElementCount());
@@ -220,7 +220,7 @@ public class PyTypeTest extends PyTestCase {
" return x\n" +
"expr = f(1, 2)\n";
PyExpression expr = parseExpr(text);
PyType t = TypeEvalContext.userInitiated().getType(expr);
PyType t = TypeEvalContext.userInitiated(null).getType(expr);
assertTrue(PyTypeChecker.isUnknown(t));
doTest("int", text);
}
@@ -234,7 +234,7 @@ public class PyTypeTest extends PyTestCase {
" return foo(x)\n" +
"expr = xyzzy(a, b)";
PyExpression expr = parseExpr(text);
PyType t = TypeEvalContext.userInitiated().getType(expr);
PyType t = TypeEvalContext.userInitiated(null).getType(expr);
assertInstanceOf(t, PyTypeReference.class);
}
@@ -296,7 +296,7 @@ public class PyTypeTest extends PyTestCase {
public void testSOEOnRecursiveCall() {
PyExpression expr = parseExpr("def foo(x): return foo(x)\n" +
"expr = foo(1)");
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType actual = context.getType(expr);
assertFalse(actual.isBuiltin(context));
}
@@ -310,7 +310,7 @@ public class PyTypeTest extends PyTestCase {
" return x\n" +
"\n" +
"expr = f(1)\n");
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType actual = context.getType(expr);
assertNotNull(actual);
assertEquals("int", actual.getName());
@@ -325,7 +325,7 @@ public class PyTypeTest extends PyTestCase {
" return x\n" +
"\n" +
"expr = f(1)\n");
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType actual = context.getType(expr);
assertNotNull(actual);
assertEquals("int", actual.getName());
@@ -335,7 +335,7 @@ public class PyTypeTest extends PyTestCase {
public void testYieldType() {
PyExpression expr = parseExpr("def f():\n" +
" expr = yield 2\n");
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType actual = context.getType(expr);
assertNull(actual);
}
@@ -344,7 +344,7 @@ public class PyTypeTest extends PyTestCase {
public void testYieldParensType() {
PyExpression expr = parseExpr("def f():\n" +
" expr = (yield 2)\n");
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType actual = context.getType(expr);
assertNull(actual);
}
@@ -389,7 +389,7 @@ public class PyTypeTest extends PyTestCase {
"\n" +
"x = f()\n" +
"expr = x.start\n");
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType actual = context.getType(expr);
assertNull(actual);
}
@@ -401,7 +401,7 @@ public class PyTypeTest extends PyTestCase {
"\n" +
"x = C()\n" +
"expr = type(x)\n");
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType type = context.getType(expr);
assertInstanceOf(type, PyClassType.class);
assertTrue("Got instance type instead of class type", ((PyClassType)type).isDefinition());
@@ -413,7 +413,7 @@ public class PyTypeTest extends PyTestCase {
" pass\n" +
"\n" +
"expr = type(C)\n");
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType type = context.getType(expr);
assertInstanceOf(type, PyClassType.class);
assertEquals(type.getName(), "type");
@@ -423,7 +423,7 @@ public class PyTypeTest extends PyTestCase {
public void testReturnTypeOfTypeForUnknown() {
PyExpression expr = parseExpr("def f(x):\n" +
" expr = type(x)\n");
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType type = context.getType(expr);
assertNull(type);
}
@@ -453,7 +453,7 @@ public class PyTypeTest extends PyTestCase {
// PY-7020
public void testListComprehensionType() {
final PyExpression expr = parseExpr("expr = [str(x) for x in range(10)]\n");
final TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
final TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
final PyType type = context.getType(expr);
assertNotNull(type);
assertInstanceOf(type, PyCollectionType.class);
@@ -467,7 +467,7 @@ public class PyTypeTest extends PyTestCase {
// PY-7021
public void testGeneratorComprehensionType() {
final PyExpression expr = parseExpr("expr = (str(x) for x in range(10))\n");
final TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
final TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
final PyType type = context.getType(expr);
assertNotNull(type);
assertInstanceOf(type, PyCollectionType.class);
@@ -558,7 +558,7 @@ public class PyTypeTest extends PyTestCase {
public void testDefaultParameterIgnoreNone() {
final PyExpression expr = parseExpr("def f(x=None):\n" +
" expr = x\n");
final TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
final TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
final PyType type = context.getType(expr);
assertNull(type);
}
@@ -576,7 +576,7 @@ public class PyTypeTest extends PyTestCase {
private void doTest(final String expectedType, final String text) {
PyExpression expr = parseExpr(text);
TypeEvalContext context = TypeEvalContext.userInitiated().withTracing();
TypeEvalContext context = TypeEvalContext.userInitiated(null).withTracing();
PyType actual = context.getType(expr);
PyType expected = PyTypeParser.getTypeByName(expr, expectedType);
if (expected != null) {