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));
}
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);
}
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);
}
}
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);
}
}
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);
}
}
Aggregations