Search in sources :

Example 1 with PyFunctionBuilder

use of com.jetbrains.python.psi.impl.PyFunctionBuilder in project intellij-community by JetBrains.

the class PyExtractMethodUtil method generateMethodFromExpression.

@NotNull
private static PyFunction generateMethodFromExpression(@NotNull final Project project, @NotNull final String methodName, @NotNull final AbstractVariableData[] variableData, @NotNull final PsiElement expression, @Nullable final PyUtil.MethodFlags flags, boolean isAsync) {
    final PyFunctionBuilder builder = new PyFunctionBuilder(methodName, expression);
    addDecorators(builder, flags);
    addFakeParameters(builder, variableData);
    if (isAsync) {
        builder.makeAsync();
    }
    final String text;
    if (expression instanceof PyYieldExpression) {
        text = String.format("(%s)", expression.getText());
    } else {
        text = expression.getText();
    }
    builder.statement("return " + text);
    return builder.buildFunction(project, LanguageLevel.forElement(expression));
}
Also used : PyFunctionBuilder(com.jetbrains.python.psi.impl.PyFunctionBuilder) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with PyFunctionBuilder

use of com.jetbrains.python.psi.impl.PyFunctionBuilder in project intellij-community by JetBrains.

the class InstanceFieldsManager method createInitMethod.

/**
   * Creates init method and adds it to certain class.
   *
   * @param to Class where method should be added
   * @return newly created method
   */
//TODO: Move to utils?
@NotNull
private static PyFunction createInitMethod(@NotNull final PyClass to) {
    final PyFunctionBuilder functionBuilder = new PyFunctionBuilder(PyNames.INIT, to);
    //TODO: Take param from codestyle?
    functionBuilder.parameter(PyNames.CANONICAL_SELF);
    final PyFunction function = functionBuilder.buildFunction(to.getProject(), LanguageLevel.forElement(to));
    return PyClassRefactoringUtil.addMethods(to, true, function).get(0);
}
Also used : PyFunctionBuilder(com.jetbrains.python.psi.impl.PyFunctionBuilder) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with PyFunctionBuilder

use of com.jetbrains.python.psi.impl.PyFunctionBuilder in project intellij-community by JetBrains.

the class MethodsManager method makeMethodsAbstract.

/**
   * Creates abstract version of each method in each class (does not touch method itself as opposite to {@link #moveMethods(com.jetbrains.python.psi.PyClass, java.util.Collection, com.jetbrains.python.psi.PyClass...)})
   *
   * @param currentFunctions functions to make them abstract
   * @param to               classes where abstract method should be created
   */
private static void makeMethodsAbstract(final Collection<PyFunction> currentFunctions, final PyClass... to) {
    final Set<PsiFile> filesToCheckImport = new HashSet<>();
    final Set<PyClass> classesToAddMetaAbc = new HashSet<>();
    for (final PyFunction function : currentFunctions) {
        for (final PyClass destClass : to) {
            final PyFunctionBuilder functionBuilder = PyFunctionBuilder.copySignature(function, DECORATORS_MAY_BE_COPIED_TO_ABSTRACT);
            functionBuilder.decorate(PyNames.ABSTRACTMETHOD);
            final LanguageLevel level = LanguageLevel.forElement(destClass);
            PyClassRefactoringUtil.addMethods(destClass, false, functionBuilder.buildFunction(destClass.getProject(), level));
            classesToAddMetaAbc.add(destClass);
        }
    }
    // Add ABCMeta to new classes if needed
    for (final PyClass aClass : classesToAddMetaAbc) {
        if (addMetaAbcIfNeeded(aClass)) {
            filesToCheckImport.add(aClass.getContainingFile());
        }
    }
    // Add imports for ABC if needed
    for (final PsiFile file : filesToCheckImport) {
        addImportFromAbc(file, PyNames.ABSTRACTMETHOD);
        addImportFromAbc(file, PyNames.ABC_META_CLASS);
        //To remove redundant imports
        PyClassRefactoringUtil.optimizeImports(file);
    }
}
Also used : PyFunctionBuilder(com.jetbrains.python.psi.impl.PyFunctionBuilder) PsiFile(com.intellij.psi.PsiFile)

Example 4 with PyFunctionBuilder

use of com.jetbrains.python.psi.impl.PyFunctionBuilder 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 5 with PyFunctionBuilder

use of com.jetbrains.python.psi.impl.PyFunctionBuilder in project intellij-community by JetBrains.

the class AddFunctionQuickFix method applyFix.

public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
    try {
        final PsiElement problemElement = descriptor.getPsiElement();
        if (!(problemElement instanceof PyQualifiedExpression))
            return;
        final PyExpression qualifier = ((PyQualifiedExpression) problemElement).getQualifier();
        if (qualifier == null)
            return;
        final PyType type = TypeEvalContext.userInitiated(problemElement.getProject(), problemElement.getContainingFile()).getType(qualifier);
        if (!(type instanceof PyModuleType))
            return;
        final PyFile file = ((PyModuleType) type).getModule();
        sure(file);
        sure(FileModificationService.getInstance().preparePsiElementForWrite(file));
        // try to at least match parameter count
        // TODO: get parameter style from code style
        PyFunctionBuilder builder = new PyFunctionBuilder(myIdentifier, problemElement);
        PsiElement problemParent = problemElement.getParent();
        if (problemParent instanceof PyCallExpression) {
            PyArgumentList arglist = ((PyCallExpression) problemParent).getArgumentList();
            if (arglist == null)
                return;
            final PyExpression[] args = arglist.getArguments();
            for (PyExpression arg : args) {
                if (arg instanceof PyKeywordArgument) {
                    // foo(bar) -> def foo(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");
                }
            }
        } else if (problemParent != null) {
            for (PyInspectionExtension extension : Extensions.getExtensions(PyInspectionExtension.EP_NAME)) {
                List<String> params = extension.getFunctionParametersFromUsage(problemElement);
                if (params != null) {
                    for (String param : params) {
                        builder.parameter(param);
                    }
                    break;
                }
            }
        }
        // else: no arglist, use empty args
        PyFunction function = builder.buildFunction(project, LanguageLevel.forElement(file));
        // add to the bottom
        function = (PyFunction) file.add(function);
        showTemplateBuilder(function, file);
    } catch (IncorrectOperationException ignored) {
        // we failed. tell about this
        PyUtil.showBalloon(project, PyBundle.message("QFIX.failed.to.add.function"), MessageType.ERROR);
    }
}
Also used : PyInspectionExtension(com.jetbrains.python.inspections.PyInspectionExtension) PyType(com.jetbrains.python.psi.types.PyType) PyFunctionBuilder(com.jetbrains.python.psi.impl.PyFunctionBuilder) List(java.util.List) IncorrectOperationException(com.intellij.util.IncorrectOperationException) PsiElement(com.intellij.psi.PsiElement) PyModuleType(com.jetbrains.python.psi.types.PyModuleType)

Aggregations

PyFunctionBuilder (com.jetbrains.python.psi.impl.PyFunctionBuilder)12 PsiElement (com.intellij.psi.PsiElement)7 NotNull (org.jetbrains.annotations.NotNull)4 IncorrectOperationException (com.intellij.util.IncorrectOperationException)3 PsiFile (com.intellij.psi.PsiFile)2 PyType (com.jetbrains.python.psi.types.PyType)2 TypeEvalContext (com.jetbrains.python.psi.types.TypeEvalContext)2 TemplateBuilder (com.intellij.codeInsight.template.TemplateBuilder)1 InjectedLanguageManager (com.intellij.lang.injection.InjectedLanguageManager)1 FileEditor (com.intellij.openapi.fileEditor.FileEditor)1 TextEditor (com.intellij.openapi.fileEditor.TextEditor)1 PsiLanguageInjectionHost (com.intellij.psi.PsiLanguageInjectionHost)1 RefactoringElementListenerComposite (com.intellij.refactoring.listeners.RefactoringElementListenerComposite)1 AbstractVariableData (com.intellij.refactoring.util.AbstractVariableData)1 UsageInfo (com.intellij.usageView.UsageInfo)1 HashMap (com.intellij.util.containers.hash.HashMap)1 PyInspectionExtension (com.jetbrains.python.inspections.PyInspectionExtension)1 ParamHelper (com.jetbrains.python.psi.impl.ParamHelper)1 PyClassType (com.jetbrains.python.psi.types.PyClassType)1 PyModuleType (com.jetbrains.python.psi.types.PyModuleType)1