use of com.jetbrains.python.psi.impl.PyFunctionBuilder in project intellij-community by JetBrains.
the class PyOverrideImplementUtil method buildOverriddenFunction.
private static PyFunctionBuilder buildOverriddenFunction(PyClass pyClass, PyFunction baseFunction, boolean implement) {
final boolean overridingNew = PyNames.NEW.equals(baseFunction.getName());
assert baseFunction.getName() != null;
PyFunctionBuilder pyFunctionBuilder = new PyFunctionBuilder(baseFunction.getName(), baseFunction);
final PyDecoratorList decorators = baseFunction.getDecoratorList();
boolean baseMethodIsStatic = false;
if (decorators != null) {
if (decorators.findDecorator(PyNames.CLASSMETHOD) != null) {
pyFunctionBuilder.decorate(PyNames.CLASSMETHOD);
} else if (decorators.findDecorator(PyNames.STATICMETHOD) != null) {
baseMethodIsStatic = true;
pyFunctionBuilder.decorate(PyNames.STATICMETHOD);
} else if (decorators.findDecorator(PyNames.PROPERTY) != null || decorators.findDecorator(PyNames.ABSTRACTPROPERTY) != null) {
pyFunctionBuilder.decorate(PyNames.PROPERTY);
}
}
final LanguageLevel level = LanguageLevel.forElement(pyClass);
PyAnnotation anno = baseFunction.getAnnotation();
if (anno != null && level.isAtLeast(LanguageLevel.PYTHON30)) {
pyFunctionBuilder.annotation(anno.getText());
}
final TypeEvalContext context = TypeEvalContext.userInitiated(baseFunction.getProject(), baseFunction.getContainingFile());
final List<PyParameter> baseParams = PyUtil.getParameters(baseFunction, context);
for (PyParameter parameter : baseParams) {
final PyNamedParameter namedParameter = parameter.getAsNamed();
if (namedParameter != null) {
final StringBuilder parameterBuilder = new StringBuilder();
if (namedParameter.isPositionalContainer()) {
parameterBuilder.append("*");
} else if (namedParameter.isKeywordContainer()) {
parameterBuilder.append("**");
}
parameterBuilder.append(namedParameter.getName());
final PyAnnotation annotation = namedParameter.getAnnotation();
if (annotation != null && level.isAtLeast(LanguageLevel.PYTHON30)) {
parameterBuilder.append(annotation.getText());
}
final PyExpression defaultValue = namedParameter.getDefaultValue();
if (defaultValue != null) {
parameterBuilder.append("=");
parameterBuilder.append(defaultValue.getText());
}
pyFunctionBuilder.parameter(parameterBuilder.toString());
} else {
pyFunctionBuilder.parameter(parameter.getText());
}
}
PyClass baseClass = baseFunction.getContainingClass();
assert baseClass != null;
StringBuilder statementBody = new StringBuilder();
boolean hadStar = false;
List<String> parameters = new ArrayList<>();
for (PyParameter parameter : baseParams) {
final PyNamedParameter pyNamedParameter = parameter.getAsNamed();
if (pyNamedParameter != null) {
String repr = pyNamedParameter.getRepr(false);
parameters.add(hadStar && !pyNamedParameter.isKeywordContainer() ? pyNamedParameter.getName() + "=" + repr : repr);
if (pyNamedParameter.isPositionalContainer()) {
hadStar = true;
}
} else if (parameter instanceof PySingleStarParameter) {
hadStar = true;
} else {
parameters.add(parameter.getText());
}
}
if (PyNames.TYPES_INSTANCE_TYPE.equals(baseClass.getQualifiedName()) || raisesNotImplementedError(baseFunction) || implement) {
statementBody.append(PyNames.PASS);
} else {
if (!PyNames.INIT.equals(baseFunction.getName()) && context.getReturnType(baseFunction) != PyNoneType.INSTANCE || overridingNew) {
statementBody.append("return ");
}
if (baseClass.isNewStyleClass(context)) {
statementBody.append(PyNames.SUPER);
statementBody.append("(");
final LanguageLevel langLevel = ((PyFile) pyClass.getContainingFile()).getLanguageLevel();
if (!langLevel.isPy3K()) {
final String baseFirstName = !baseParams.isEmpty() ? baseParams.get(0).getName() : null;
final String firstName = baseFirstName != null ? baseFirstName : PyNames.CANONICAL_SELF;
PsiElement outerClass = PsiTreeUtil.getParentOfType(pyClass, PyClass.class, true, PyFunction.class);
String className = pyClass.getName();
final List<String> nameResult = Lists.newArrayList(className);
while (outerClass != null) {
nameResult.add(0, ((PyClass) outerClass).getName());
outerClass = PsiTreeUtil.getParentOfType(outerClass, PyClass.class, true, PyFunction.class);
}
StringUtil.join(nameResult, ".", statementBody);
statementBody.append(", ").append(firstName);
}
statementBody.append(").").append(baseFunction.getName()).append("(");
// type.__new__ is explicitly decorated as @staticmethod in our stubs, but not in real Python code
if (parameters.size() > 0 && !(baseMethodIsStatic || overridingNew)) {
parameters.remove(0);
}
} else {
statementBody.append(getReferenceText(pyClass, baseClass)).append(".").append(baseFunction.getName()).append("(");
}
StringUtil.join(parameters, ", ", statementBody);
statementBody.append(")");
}
pyFunctionBuilder.statement(statementBody.toString());
return pyFunctionBuilder;
}
use of com.jetbrains.python.psi.impl.PyFunctionBuilder in project intellij-community by JetBrains.
the class PyOverrideImplementUtil method write.
private static void write(@NotNull final PyClass pyClass, @NotNull final List<PyMethodMember> newMembers, @NotNull final Editor editor, boolean implement) {
final PyStatementList statementList = pyClass.getStatementList();
final int offset = editor.getCaretModel().getOffset();
PsiElement anchor = null;
for (PyStatement statement : statementList.getStatements()) {
if (statement.getTextRange().getStartOffset() < offset || (statement instanceof PyExpressionStatement && ((PyExpressionStatement) statement).getExpression() instanceof PyStringLiteralExpression)) {
anchor = statement;
}
}
PyFunction element = null;
for (PyMethodMember newMember : newMembers) {
PyFunction baseFunction = (PyFunction) newMember.getPsiElement();
final PyFunctionBuilder builder = buildOverriddenFunction(pyClass, baseFunction, implement);
PyFunction function = builder.addFunctionAfter(statementList, anchor, LanguageLevel.forElement(statementList));
element = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(function);
}
PyPsiUtils.removeRedundantPass(statementList);
if (element != null) {
final PyStatementList targetStatementList = element.getStatementList();
final int start = targetStatementList.getTextRange().getStartOffset();
editor.getCaretModel().moveToOffset(start);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
editor.getSelectionModel().setSelection(start, element.getTextRange().getEndOffset());
}
}
use of com.jetbrains.python.psi.impl.PyFunctionBuilder in project intellij-community by JetBrains.
the class PyConvertLambdaToFunctionIntention method doInvoke.
public void doInvoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PyLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyLambdaExpression.class);
if (lambdaExpression != null) {
String name = "function";
while (IntroduceValidator.isDefinedInScope(name, lambdaExpression)) {
name += "1";
}
PsiElement parent = lambdaExpression.getParent();
if (parent instanceof PyAssignmentStatement) {
name = ((PyAssignmentStatement) parent).getLeftHandSideExpression().getText();
}
if (name.isEmpty())
return;
PyExpression body = lambdaExpression.getBody();
PyFunctionBuilder functionBuilder = new PyFunctionBuilder(name, lambdaExpression);
for (PyParameter param : lambdaExpression.getParameterList().getParameters()) {
functionBuilder.parameter(param.getText());
}
functionBuilder.statement("return " + body.getText());
PyFunction function = functionBuilder.buildFunction(project, LanguageLevel.getDefault());
final PyStatement statement = PsiTreeUtil.getParentOfType(lambdaExpression, PyStatement.class);
if (statement != null) {
final PsiElement statementParent = statement.getParent();
if (statementParent != null)
function = (PyFunction) statementParent.addBefore(function, statement);
}
function = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(function);
if (parent instanceof PyAssignmentStatement) {
parent.delete();
} else {
PsiFile parentScope = lambdaExpression.getContainingFile();
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(parentScope);
PsiElement functionName = function.getNameIdentifier();
functionName = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(functionName);
lambdaExpression = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(lambdaExpression);
ReferenceNameExpression refExpr = new ReferenceNameExpression(name);
((TemplateBuilderImpl) builder).replaceElement(lambdaExpression, name, refExpr, true);
((TemplateBuilderImpl) builder).replaceElement(functionName, name, name, false);
int textOffSet = functionName.getTextOffset();
editor.getCaretModel().moveToOffset(parentScope.getTextRange().getStartOffset());
Template template = ((TemplateBuilderImpl) builder).buildInlineTemplate();
TemplateManager.getInstance(project).startTemplate(editor, template);
editor.getCaretModel().moveToOffset(textOffSet);
}
}
}
use of com.jetbrains.python.psi.impl.PyFunctionBuilder in project intellij-community by JetBrains.
the class UnresolvedRefCreateFunctionQuickFix method applyFix.
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PyCallExpression callExpr = myCallExpr.getElement();
final PyReferenceExpression referenceExpr = myReferenceExpr.getElement();
if (callExpr == null || !callExpr.isValid() || referenceExpr == null || !referenceExpr.isValid()) {
return;
}
final PyFunctionBuilder functionBuilder = new PyFunctionBuilder(referenceExpr.getText(), callExpr);
// if function is actually an argument of a call, don't use other arguments of the call to create parameter list of new function
final PyArgumentList argumentList = callExpr.getArgumentList();
if (argumentList != null && !PsiTreeUtil.isAncestor(argumentList, referenceExpr, false)) {
for (PyExpression param : argumentList.getArguments()) {
if (param instanceof PyKeywordArgument) {
functionBuilder.parameter(((PyKeywordArgument) param).getKeyword());
} else if (param instanceof PyReferenceExpression) {
PyReferenceExpression refex = (PyReferenceExpression) param;
functionBuilder.parameter(refex.getReferencedName());
} else {
functionBuilder.parameter("param");
}
}
} else {
functionBuilder.parameter("args");
}
PyFunction function = functionBuilder.buildFunction(project, LanguageLevel.getDefault());
final InjectedLanguageManager instance = InjectedLanguageManager.getInstance(project);
final PsiLanguageInjectionHost host = instance.getInjectionHost(callExpr);
final PsiElement insertAnchor = host != null ? host : callExpr;
final PyFunction parentFunction = PsiTreeUtil.getTopmostParentOfType(insertAnchor, PyFunction.class);
if (parentFunction != null) {
final PyClass parentClass = PsiTreeUtil.getTopmostParentOfType(parentFunction, PyClass.class);
if (parentClass != null) {
final PsiElement parent = parentClass.getParent();
function = (PyFunction) parent.addBefore(function, parentClass);
} else {
final PsiElement parent = parentFunction.getParent();
function = (PyFunction) parent.addBefore(function, parentFunction);
}
} else {
final PyStatement statement = PsiTreeUtil.getTopmostParentOfType(insertAnchor, PyStatement.class);
if (statement != null) {
final PsiElement parent = statement.getParent();
if (parent != null) {
function = (PyFunction) parent.addBefore(function, statement);
}
}
}
function = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(function);
final TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(function);
ParamHelper.walkDownParamArray(function.getParameterList().getParameters(), new ParamHelper.ParamVisitor() {
public void visitNamedParameter(PyNamedParameter param, boolean first, boolean last) {
builder.replaceElement(param, param.getName());
}
});
builder.replaceElement(function.getStatementList(), PyNames.PASS);
final FileEditor editor = FileEditorManager.getInstance(project).getSelectedEditor(insertAnchor.getContainingFile().getVirtualFile());
if (!(editor instanceof TextEditor)) {
return;
}
builder.run(((TextEditor) editor).getEditor(), false);
}
use of com.jetbrains.python.psi.impl.PyFunctionBuilder in project intellij-community by JetBrains.
the class PyExtractMethodUtil method generateMethodFromElements.
@NotNull
private static PyFunction generateMethodFromElements(@NotNull final Project project, @NotNull final String methodName, @NotNull final AbstractVariableData[] variableData, @NotNull final List<PsiElement> elementsRange, @Nullable PyUtil.MethodFlags flags, boolean isAsync) {
assert !elementsRange.isEmpty() : "Empty statements list was selected!";
final PyFunctionBuilder builder = new PyFunctionBuilder(methodName, elementsRange.get(0));
if (isAsync) {
builder.makeAsync();
}
addDecorators(builder, flags);
addFakeParameters(builder, variableData);
final PyFunction method = builder.buildFunction(project, LanguageLevel.forElement(elementsRange.get(0)));
final PyStatementList statementList = method.getStatementList();
for (PsiElement element : elementsRange) {
if (element instanceof PsiWhiteSpace) {
continue;
}
statementList.add(element);
}
// remove last instruction
final PsiElement child = statementList.getFirstChild();
if (child != null) {
child.delete();
}
PsiElement last = statementList;
while (last != null) {
last = last.getLastChild();
if (last instanceof PsiWhiteSpace) {
last.delete();
}
}
return method;
}
Aggregations