Search in sources :

Example 6 with TypeEvalContext

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();
}
Also used : PyClass(com.jetbrains.python.psi.PyClass) PyChangeSignatureDialog(com.jetbrains.python.refactoring.changeSignature.PyChangeSignatureDialog) PyFunction(com.jetbrains.python.psi.PyFunction) PyMethodDescriptor(com.jetbrains.python.refactoring.changeSignature.PyMethodDescriptor) PyParameterInfo(com.jetbrains.python.refactoring.changeSignature.PyParameterInfo) TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext)

Example 7 with TypeEvalContext

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);
    }
}
Also used : PyClassType(com.jetbrains.python.psi.types.PyClassType) TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext) PyFunctionBuilder(com.jetbrains.python.psi.impl.PyFunctionBuilder) PyType(com.jetbrains.python.psi.types.PyType) IncorrectOperationException(com.intellij.util.IncorrectOperationException) PsiElement(com.intellij.psi.PsiElement)

Example 8 with TypeEvalContext

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);
            }
        }
    }
}
Also used : PyResolveContext(com.jetbrains.python.psi.resolve.PyResolveContext) PsiElement(com.intellij.psi.PsiElement) TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext)

Example 9 with TypeEvalContext

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;
}
Also used : ArrayList(java.util.ArrayList) PsiFileSystemItem(com.intellij.psi.PsiFileSystemItem) TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext) PyImportedModule(com.jetbrains.python.psi.impl.PyImportedModule) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

Example 10 with TypeEvalContext

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;
}
Also used : PyType(com.jetbrains.python.psi.types.PyType) PyStructuralType(com.jetbrains.python.psi.types.PyStructuralType) TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext)

Aggregations

TypeEvalContext (com.jetbrains.python.psi.types.TypeEvalContext)44 PyType (com.jetbrains.python.psi.types.PyType)15 PsiElement (com.intellij.psi.PsiElement)13 NotNull (org.jetbrains.annotations.NotNull)10 Nullable (org.jetbrains.annotations.Nullable)8 PyResolveContext (com.jetbrains.python.psi.resolve.PyResolveContext)6 PyClassLikeType (com.jetbrains.python.psi.types.PyClassLikeType)5 ArrayList (java.util.ArrayList)5 ScopeOwner (com.jetbrains.python.codeInsight.controlflow.ScopeOwner)4 com.jetbrains.python.psi (com.jetbrains.python.psi)4 TextRange (com.intellij.openapi.util.TextRange)3 PsiTreeUtil (com.intellij.psi.util.PsiTreeUtil)3 XmlStringUtil (com.intellij.xml.util.XmlStringUtil)3 PyNames (com.jetbrains.python.PyNames)3 PyFunction (com.jetbrains.python.psi.PyFunction)3 PyClassType (com.jetbrains.python.psi.types.PyClassType)3 Lists (com.google.common.collect.Lists)2 Instruction (com.intellij.codeInsight.controlflow.Instruction)2 LookupElement (com.intellij.codeInsight.lookup.LookupElement)2 ASTNode (com.intellij.lang.ASTNode)2