use of com.jetbrains.python.psi.types.TypeEvalContext in project intellij-community by JetBrains.
the class PyChangeSignatureQuickFix method applyFix.
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
final PyFunction function = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PyFunction.class);
if (function == null)
return;
final PyClass cls = function.getContainingClass();
assert cls != null;
final String functionName = function.getName();
final String complementaryName = PyNames.NEW.equals(functionName) ? PyNames.INIT : PyNames.NEW;
final TypeEvalContext context = TypeEvalContext.userInitiated(project, descriptor.getEndElement().getContainingFile());
final PyFunction complementaryMethod = myOverridenMethod ? (PyFunction) PySuperMethodsSearch.search(function, context).findFirst() : cls.findMethodByName(complementaryName, true, null);
assert complementaryMethod != null;
final PyMethodDescriptor methodDescriptor = new PyMethodDescriptor(function) {
@Override
public List<PyParameterInfo> getParameters() {
final List<PyParameterInfo> parameterInfos = super.getParameters();
final int paramLength = function.getParameterList().getParameters().length;
final int complementaryParamLength = complementaryMethod.getParameterList().getParameters().length;
if (complementaryParamLength > paramLength)
parameterInfos.add(new PyParameterInfo(-1, "**kwargs", "", false));
return parameterInfos;
}
};
final PyChangeSignatureDialog dialog = new PyChangeSignatureDialog(project, methodDescriptor);
dialog.show();
}
use of com.jetbrains.python.psi.types.TypeEvalContext in project intellij-community by JetBrains.
the class AddMethodQuickFix method applyFix.
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
try {
// there can be no name clash, else the name would have resolved, and it hasn't.
final PsiElement problemElement = descriptor.getPsiElement();
final PyClassType type = getClassType(problemElement);
if (type == null)
return;
final PyClass cls = type.getPyClass();
boolean callByClass = type.isDefinition();
PyStatementList clsStmtList = cls.getStatementList();
sure(FileModificationService.getInstance().preparePsiElementForWrite(clsStmtList));
// try to at least match parameter count
// TODO: get parameter style from code style
PyFunctionBuilder builder = new PyFunctionBuilder(myIdentifier, cls);
PsiElement pe = problemElement.getParent();
// set to non-null to add a decorator
String decoratorName = null;
PyExpression[] args = PyExpression.EMPTY_ARRAY;
if (pe instanceof PyCallExpression) {
PyArgumentList arglist = ((PyCallExpression) pe).getArgumentList();
if (arglist == null)
return;
args = arglist.getArguments();
}
boolean madeInstance = false;
if (callByClass) {
if (args.length > 0) {
final TypeEvalContext context = TypeEvalContext.userInitiated(cls.getProject(), cls.getContainingFile());
final PyType firstArgType = context.getType(args[0]);
if (firstArgType instanceof PyClassType && ((PyClassType) firstArgType).getPyClass().isSubclass(cls, context)) {
// class, first arg ok: instance method
// NOTE: might use a name other than 'self', according to code style.
builder.parameter("self");
madeInstance = true;
}
}
if (!madeInstance) {
// class, first arg absent or of different type: classmethod
// NOTE: might use a name other than 'cls', according to code style.
builder.parameter("cls");
decoratorName = PyNames.CLASSMETHOD;
}
} else {
// instance method
// NOTE: might use a name other than 'self', according to code style.
builder.parameter("self");
}
// ClassFoo.meth(foo_instance)
boolean skipFirst = callByClass && madeInstance;
for (PyExpression arg : args) {
if (skipFirst) {
skipFirst = false;
continue;
}
if (arg instanceof PyKeywordArgument) {
// foo(bar) -> def foo(self, bar_1)
builder.parameter(((PyKeywordArgument) arg).getKeyword());
} else if (arg instanceof PyReferenceExpression) {
PyReferenceExpression refex = (PyReferenceExpression) arg;
builder.parameter(refex.getReferencedName());
} else {
// use a boring name
builder.parameter("param");
}
}
PyFunction method = builder.buildFunction(project, LanguageLevel.getDefault());
if (decoratorName != null) {
PyElementGenerator generator = PyElementGenerator.getInstance(project);
PyDecoratorList decoratorList = generator.createFromText(LanguageLevel.getDefault(), PyDecoratorList.class, "@" + decoratorName + "\ndef foo(): pass", new int[] { 0, 0 });
// in the very beginning
method.addBefore(decoratorList, method.getFirstChild());
}
method = (PyFunction) PyUtil.addElementToStatementList(method, clsStmtList, PyNames.INIT.equals(method.getName()));
if (myReplaceUsage) {
showTemplateBuilder(method);
}
} catch (IncorrectOperationException ignored) {
// we failed. tell about this
PyUtil.showBalloon(project, PyBundle.message("QFIX.failed.to.add.method"), MessageType.ERROR);
}
}
use of com.jetbrains.python.psi.types.TypeEvalContext in project intellij-community by JetBrains.
the class PyReplaceTupleWithListQuickFix method applyFix.
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement element = descriptor.getPsiElement();
assert element instanceof PyAssignmentStatement;
PyExpression[] targets = ((PyAssignmentStatement) element).getTargets();
if (targets.length == 1 && targets[0] instanceof PySubscriptionExpression) {
PySubscriptionExpression subscriptionExpression = (PySubscriptionExpression) targets[0];
if (subscriptionExpression.getOperand() instanceof PyReferenceExpression) {
PyReferenceExpression referenceExpression = (PyReferenceExpression) subscriptionExpression.getOperand();
final TypeEvalContext context = TypeEvalContext.userInitiated(project, element.getContainingFile());
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
element = referenceExpression.followAssignmentsChain(resolveContext).getElement();
if (element instanceof PyParenthesizedExpression) {
final PyExpression expression = ((PyParenthesizedExpression) element).getContainedExpression();
replaceWithListLiteral(element, (PyTupleExpression) expression);
} else if (element instanceof PyTupleExpression) {
replaceWithListLiteral(element, (PyTupleExpression) element);
}
}
}
}
use of com.jetbrains.python.psi.types.TypeEvalContext in project intellij-community by JetBrains.
the class PyFindUsagesHandlerFactory method createFindUsagesHandler.
@Nullable
@Override
public FindUsagesHandler createFindUsagesHandler(@NotNull PsiElement element, boolean forHighlightUsages) {
if (element instanceof PyImportedModule) {
final PsiElement resolved = ((PyImportedModule) element).resolve();
if (resolved != null) {
element = resolved;
}
}
if (element instanceof PsiFileSystemItem) {
return new PyModuleFindUsagesHandler((PsiFileSystemItem) element);
}
if (element instanceof PyFunction) {
if (!forHighlightUsages) {
TypeEvalContext context = TypeEvalContext.userInitiated(element.getProject(), null);
final Collection<PsiElement> superMethods = PySuperMethodsSearch.search((PyFunction) element, true, context).findAll();
if (superMethods.size() > 0) {
final PsiElement next = superMethods.iterator().next();
// TODO should do this for Jython functions overriding Java methods too
if (next instanceof PyFunction && !isInObject((PyFunction) next)) {
int rc = Messages.showYesNoDialog(element.getProject(), "Method " + ((PyFunction) element).getName() + " overrides method of class " + ((PyFunction) next).getContainingClass().getName() + ".\nDo you want to find usages of the base method?", "Find Usages", Messages.getQuestionIcon());
if (rc == Messages.YES) {
List<PsiElement> allMethods = new ArrayList<>();
allMethods.add(element);
allMethods.addAll(superMethods);
return new PyFunctionFindUsagesHandler(element, allMethods);
} else {
return new PyFunctionFindUsagesHandler(element);
}
}
}
}
return new PyFunctionFindUsagesHandler(element);
}
if (element instanceof PyClass) {
return new PyClassFindUsagesHandler((PyClass) element);
}
if (element instanceof PyTargetExpression) {
return new PyTargetExpressionFindUsagesHandler(((PyTargetExpression) element));
}
return null;
}
use of com.jetbrains.python.psi.types.TypeEvalContext in project intellij-community by JetBrains.
the class PyUsageTypeProvider method getUsageType.
public UsageType getUsageType(PsiElement element, @NotNull UsageTarget[] targets) {
if (element instanceof PyElement) {
if (PsiTreeUtil.getParentOfType(element, PyImportStatementBase.class) != null) {
return IN_IMPORT;
}
if (element instanceof PyQualifiedExpression) {
final PyExpression qualifier = ((PyQualifiedExpression) element).getQualifier();
if (qualifier != null) {
final TypeEvalContext context = TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile());
final PyType type = context.getType(qualifier);
if (type == null || type instanceof PyStructuralType) {
return UNTYPED;
}
}
}
if (element instanceof PyReferenceExpression) {
final PyCallExpression call = PsiTreeUtil.getParentOfType(element, PyCallExpression.class);
if (call != null && call.isCalleeText(PyNames.ISINSTANCE)) {
final PyExpression[] args = call.getArguments();
if (args.length == 2) {
PyExpression typeExpression = args[1];
if (element == typeExpression) {
return USAGE_IN_ISINSTANCE;
}
typeExpression = PyPsiUtils.flattenParens(typeExpression);
if (typeExpression instanceof PySequenceExpression && element.getParent() == typeExpression) {
return USAGE_IN_ISINSTANCE;
}
}
}
final PyClass pyClass = PsiTreeUtil.getParentOfType(element, PyClass.class);
if (pyClass != null && PsiTreeUtil.isAncestor(pyClass.getSuperClassExpressionList(), element, true)) {
return USAGE_IN_SUPERCLASS;
}
}
}
return null;
}
Aggregations