void (@NotNull Collection<String> newParamNames, UsageInfo @NotNull [] usages) { // Field usages for (String attrName : myAttributeReferences.keySet()) { final Collection<PyReferenceExpression> reads = myAttributeReferences.get(attrName); final String paramName = myAttributeToParameterName.get(attrName); if (!attrName.equals(paramName)) { for (PyReferenceExpression read : reads) { read.replace(myGenerator.createExpressionFromText(LanguageLevel.forElement(read), paramName)); } } else { for (PyReferenceExpression read : reads) { removeQualifier(read); } } } // Function usages final Collection<String> attrNames = myAttributeToParameterName.keySet(); for (UsageInfo usage : usages) { final PsiElement usageElem = usage.getElement(); if (usageElem == null) { continue; } if (usageElem instanceof PyReferenceExpression) { final PyExpression qualifier = ((PyReferenceExpression)usageElem).getQualifier(); final PyCallExpression callExpr = as(usageElem.getParent(), PyCallExpression.class); if (qualifier != null && callExpr != null && callExpr.getArgumentList() != null) { PyExpression instanceExpr = qualifier; final PyArgumentList argumentList = callExpr.getArgumentList(); // Class.method(instance) -> method(instance.attr) if (resolvesToClass(qualifier)) { final PyExpression[] arguments = argumentList.getArguments(); if (arguments.length > 0) { instanceExpr = arguments[0]; instanceExpr.delete(); } else { // It's not clear how to handle usages like Class.method(), since there is no suitable instance instanceExpr = null; } } if (instanceExpr != null) { // module.inst.method() -> method(module.inst.foo, module.inst.bar) if (isPureReferenceExpression(instanceExpr)) { // recursive call inside the method if (myReadsOfSelfParam.contains(instanceExpr)) { addArguments(argumentList, newParamNames); } else { final String instanceExprText = instanceExpr.getText(); addArguments(argumentList, ContainerUtil.map(attrNames, attribute -> instanceExprText + "." + attribute)); } } // Class().method() -> method(Class().foo) else if (newParamNames.size() == 1) { addArguments(argumentList, Collections.singleton(instanceExpr.getText() + "." + ContainerUtil.getFirstItem(attrNames))); } // Class().method() -> inst = Class(); method(inst.foo, inst.bar) else if (!newParamNames.isEmpty()) { final PyStatement anchor = PsiTreeUtil.getParentOfType(callExpr, PyStatement.class); //noinspection ConstantConditions final String className = StringUtil.notNullize(myFunction.getContainingClass().getName(), PyNames.OBJECT); final String targetName = PyRefactoringUtil.selectUniqueNameFromType(className, usageElem); final String assignmentText = targetName + " = " + instanceExpr.getText(); final PyAssignmentStatement assignment = myGenerator.createFromText(LanguageLevel.forElement(callExpr), PyAssignmentStatement.class, assignmentText); //noinspection ConstantConditions anchor.getParent().addBefore(assignment, anchor); addArguments(argumentList, ContainerUtil.map(attrNames, attribute -> targetName + "." + attribute)); } } } // Will replace/invalidate entire expression removeQualifier((PyReferenceExpression)usageElem); } } }