use of com.intellij.refactoring.util.AbstractVariableData in project intellij-community by JetBrains.
the class PyExtractMethodUtil method getNameAndVariableData.
@NotNull
private static Pair<String, AbstractVariableData[]> getNameAndVariableData(@NotNull final Project project, @NotNull final CodeFragment fragment, @NotNull final PsiElement element, final boolean isClassMethod, final boolean isStaticMethod) {
final ExtractMethodValidator validator = new PyExtractMethodValidator(element, project);
if (ApplicationManager.getApplication().isUnitTestMode()) {
String name = System.getProperty(NAME);
if (name == null) {
name = "foo";
}
final String error = validator.check(name);
if (error != null) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
throw new CommonRefactoringUtil.RefactoringErrorHintException(error);
}
if (Messages.showOkCancelDialog(error + ". " + RefactoringBundle.message("do.you.wish.to.continue"), RefactoringBundle.message("warning.title"), Messages.getWarningIcon()) != Messages.OK) {
throw new CommonRefactoringUtil.RefactoringErrorHintException(error);
}
}
final List<AbstractVariableData> data = new ArrayList<>();
for (String in : fragment.getInputVariables()) {
final AbstractVariableData d = new AbstractVariableData();
d.name = in + "_new";
d.originalName = in;
d.passAsParameter = true;
data.add(d);
}
return Pair.create(name, data.toArray(new AbstractVariableData[data.size()]));
}
final boolean isMethod = PyPsiUtils.isMethodContext(element);
final ExtractMethodDecorator decorator = new ExtractMethodDecorator() {
@NotNull
public String createMethodSignature(final String methodName, @NotNull final AbstractVariableData[] variableDatas) {
final StringBuilder builder = new StringBuilder();
if (isClassMethod) {
builder.append("cls");
} else if (isMethod && !isStaticMethod) {
builder.append("self");
}
for (AbstractVariableData variableData : variableDatas) {
if (variableData.passAsParameter) {
if (builder.length() != 0) {
builder.append(", ");
}
builder.append(variableData.name);
}
}
builder.insert(0, "(");
builder.insert(0, methodName);
builder.insert(0, "def ");
builder.append(")");
return builder.toString();
}
};
final AbstractExtractMethodDialog dialog = new AbstractExtractMethodDialog(project, "method_name", fragment, validator, decorator, PythonFileType.INSTANCE) {
@Override
protected String getHelpId() {
return "python.reference.extractMethod";
}
};
dialog.show();
//return if don`t want to extract method
if (!dialog.isOK()) {
return Pair.empty();
}
return Pair.create(dialog.getMethodName(), dialog.getAbstractVariableData());
}
use of com.intellij.refactoring.util.AbstractVariableData in project intellij-community by JetBrains.
the class AbstractExtractMethodDialog method createVariableDataByNames.
public static AbstractVariableData[] createVariableDataByNames(final List<String> args) {
final AbstractVariableData[] datas = new AbstractVariableData[args.size()];
for (int i = 0; i < args.size(); i++) {
final AbstractVariableData data = new AbstractVariableData();
final String name = args.get(i);
data.originalName = name;
data.name = name;
data.passAsParameter = true;
datas[i] = data;
}
return datas;
}
use of com.intellij.refactoring.util.AbstractVariableData in project intellij-community by JetBrains.
the class AbstractExtractMethodDialog method updateOutputVariables.
private void updateOutputVariables() {
final StringBuilder builder = new StringBuilder();
boolean first = true;
for (String variable : myOutputVariables) {
if (myVariablesMap != null) {
final AbstractVariableData data = myVariablesMap.get(variable);
final String outputName = data != null ? data.getName() : variable;
if (first) {
first = false;
} else {
builder.append(", ");
}
builder.append(outputName);
}
}
myOutputVariablesTextArea.setText(builder.length() > 0 ? builder.toString() : RefactoringBundle.message("refactoring.extract.method.dialog.empty"));
}
use of com.intellij.refactoring.util.AbstractVariableData in project intellij-community by JetBrains.
the class PyExtractMethodUtil method extractFromStatements.
public static void extractFromStatements(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PyCodeFragment fragment, @NotNull final PsiElement statement1, @NotNull final PsiElement statement2) {
if (!fragment.getOutputVariables().isEmpty() && fragment.isReturnInstructionInside()) {
CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.extract.method.error.local.variable.modifications.and.returns"), RefactoringBundle.message("error.title"), "refactoring.extractMethod");
return;
}
final PyFunction function = PsiTreeUtil.getParentOfType(statement1, PyFunction.class);
final PyUtil.MethodFlags flags = function == null ? null : PyUtil.MethodFlags.of(function);
final boolean isClassMethod = flags != null && flags.isClassMethod();
final boolean isStaticMethod = flags != null && flags.isStaticMethod();
// collect statements
final List<PsiElement> elementsRange = PyPsiUtils.collectElements(statement1, statement2);
if (elementsRange.isEmpty()) {
CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.extract.method.error.empty.fragment"), RefactoringBundle.message("extract.method.title"), "refactoring.extractMethod");
return;
}
final Pair<String, AbstractVariableData[]> data = getNameAndVariableData(project, fragment, statement1, isClassMethod, isStaticMethod);
if (data.first == null || data.second == null) {
return;
}
final String methodName = data.first;
final AbstractVariableData[] variableData = data.second;
final SimpleDuplicatesFinder finder = new SimpleDuplicatesFinder(statement1, statement2, fragment.getOutputVariables(), variableData);
CommandProcessor.getInstance().executeCommand(project, () -> {
final RefactoringEventData beforeData = new RefactoringEventData();
beforeData.addElements(new PsiElement[] { statement1, statement2 });
project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(getRefactoringId(), beforeData);
final StringBuilder builder = new StringBuilder();
final boolean isAsync = fragment.isAsync();
if (isAsync) {
builder.append("async ");
}
builder.append("def f():\n ");
final List<PsiElement> newMethodElements = new ArrayList<>(elementsRange);
final boolean hasOutputVariables = !fragment.getOutputVariables().isEmpty();
final PyElementGenerator generator = PyElementGenerator.getInstance(project);
final LanguageLevel languageLevel = LanguageLevel.forElement(statement1);
if (hasOutputVariables) {
// Generate return modified variables statements
final String outputVariables = StringUtil.join(fragment.getOutputVariables(), ", ");
final String newMethodText = builder + "return " + outputVariables;
builder.append(outputVariables);
final PyFunction function1 = generator.createFromText(languageLevel, PyFunction.class, newMethodText);
final PsiElement returnStatement = function1.getStatementList().getStatements()[0];
newMethodElements.add(returnStatement);
}
// Generate method
final PyFunction generatedMethod = generateMethodFromElements(project, methodName, variableData, newMethodElements, flags, isAsync);
final PyFunction insertedMethod = WriteAction.compute(() -> insertGeneratedMethod(statement1, generatedMethod));
// Process parameters
final PsiElement firstElement = elementsRange.get(0);
final boolean isMethod = PyPsiUtils.isMethodContext(firstElement);
WriteAction.run(() -> {
processParameters(project, insertedMethod, variableData, isMethod, isClassMethod, isStaticMethod);
processGlobalWrites(insertedMethod, fragment);
processNonlocalWrites(insertedMethod, fragment);
});
// Generate call element
if (hasOutputVariables) {
builder.append(" = ");
} else if (fragment.isReturnInstructionInside()) {
builder.append("return ");
}
if (isAsync) {
builder.append("await ");
} else if (fragment.isYieldInside()) {
builder.append("yield from ");
}
if (isMethod) {
appendSelf(firstElement, builder, isStaticMethod);
}
builder.append(methodName).append("(");
builder.append(createCallArgsString(variableData)).append(")");
final PyFunction function1 = generator.createFromText(languageLevel, PyFunction.class, builder.toString());
final PsiElement callElement = function1.getStatementList().getStatements()[0];
// Both statements are used in finder, so should be valid at this moment
PyPsiUtils.assertValid(statement1);
PyPsiUtils.assertValid(statement2);
final List<SimpleMatch> duplicates = collectDuplicates(finder, statement1, insertedMethod);
// replace statements with call
PsiElement insertedCallElement = WriteAction.compute(() -> replaceElements(elementsRange, callElement));
insertedCallElement = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(insertedCallElement);
if (insertedCallElement != null) {
processDuplicates(duplicates, insertedCallElement, editor);
}
// Set editor
setSelectionAndCaret(editor, insertedCallElement);
final RefactoringEventData afterData = new RefactoringEventData();
afterData.addElement(insertedMethod);
project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(getRefactoringId(), afterData);
}, PyBundle.message("refactoring.extract.method"), null);
}
use of com.intellij.refactoring.util.AbstractVariableData in project intellij-community by JetBrains.
the class PyExtractMethodUtil method processParameters.
private static void processParameters(@NotNull final Project project, @NotNull final PyFunction generatedMethod, @NotNull final AbstractVariableData[] variableData, final boolean isMethod, final boolean isClassMethod, final boolean isStaticMethod) {
final Map<String, String> map = createMap(variableData);
// Rename parameters
for (PyParameter parameter : generatedMethod.getParameterList().getParameters()) {
final String name = parameter.getName();
final String newName = map.get(name);
if (name != null && newName != null && !name.equals(newName)) {
final Map<PsiElement, String> allRenames = new java.util.HashMap<>();
allRenames.put(parameter, newName);
final UsageInfo[] usages = RenameUtil.findUsages(parameter, newName, false, false, allRenames);
try {
RenameUtil.doRename(parameter, newName, usages, project, new RefactoringElementListenerComposite());
} catch (IncorrectOperationException e) {
RenameUtil.showErrorMessage(e, parameter, project);
return;
}
}
}
// Change signature according to pass settings and
final PyFunctionBuilder builder = new PyFunctionBuilder("foo", generatedMethod);
if (isClassMethod) {
builder.parameter("cls");
} else if (isMethod && !isStaticMethod) {
builder.parameter("self");
}
for (AbstractVariableData data : variableData) {
if (data.isPassAsParameter()) {
builder.parameter(data.getName());
}
}
final PyParameterList pyParameterList = builder.buildFunction(project, LanguageLevel.forElement(generatedMethod)).getParameterList();
generatedMethod.getParameterList().replace(pyParameterList);
}
Aggregations