Programmatically perform extract method on multiple method invocations

Answered

Hello,

I am currently working on a plugin that programmatically performs an inline method, performs some operations (or doesn't), and then extracts the method later. I am using the extract method processor to undo the inline method currently, however I am running into some issues with it. If there are multiple invocations that are inlined, I am only able to extract one of them. I am also unable to get the same signature that I had before I inlined the method. If I manually extract the method, I can extract all of the necessary invocations with a mostly correct signature (I need to perform a change signature refactoring to get the signature textually correct).

I'm pretty sure the method signature is user error and that's something I can figure out. Do you have any suggestions to perform the extract method on all of the method invocations in the source method?

Thanks,

Max

0
5 comments

Hi,
It can be dangerous to use the extract method to undo the inline refactoring. Both these refactorings do some code optimizations and thus inline+refactoring may fail or result in different code sometimes.

As far as I can understand the question is how to extract method from several code fragments simultaneously (with suggested change signature). The most similar case is extract method + replace duplicates. There is no straight API for this but you can use the test code as an example (github):

com.intellij.java.refactoring.ExtractMethodTest#performExtractMethod(boolean, boolean, com.intellij.openapi.editor.Editor, com.intellij.psi.PsiFile, com.intellij.openapi.project.Project, boolean, com.intellij.psi.PsiType, boolean, java.lang.String, com.intellij.psi.PsiClass, java.lang.String, int...)
1
Avatar
Permanently deleted user

Hi Alexandr,

Thank you for the quick reply. Is there by chance any way to disable the code optimizations? 

I'm aware that if I perform an inline method using the editor that I can undo it. Is the operation stored on a stack that I could use to undo it programmatically instead of performing extract method on it?

Thank you for directing me to the extract method + replace duplicates test code, that does appear to be what I'm looking for.

0

It's possible to invoke undo programmatically via `com.intellij.openapi.command.undo.UndoManager#undo`

0
Avatar
Permanently deleted user

Hi Alexandr,

I've been playing around with the extract method + replace duplicates case and I've been using the test code you suggested as an example. I can successfully extract the method and replace duplicates now! Unfortunately, there's a scenario I ran into that needs to extract the parameters to replace duplicates. When I use "Boolean hasDuplicates = processor.hasDuplicates();",  a prompt pops up suggesting a signature change so that the processor can replace duplicates.

The example I'm working with looks something like the following before the method is extracted:

private void sourceMethod() {
  assertThat(new Object(String1).asString(), equalTo(String2));
  assertThat(new Object(String3).asString(), equalTo(String4));
}

After the method is extracted, the example should look something like this:

private void sourceMethod() {
  extractedMethod(String1, String2);
  extractedMethod(String3, String4);
}

private void extractedMethod(String1, String2) {
assertThat(new Object(String1).asString(), equalTo(String2));
}


After I use "ExtractMethodHandler.extractMethod(project, processor);", the result looks like the following:

private void sourceMethod() {
  extractedMethod();
  assertThat(new Object(String3).asString(), equalTo(String4));
}

private void extractedMethod() {
assertThat(new Object(String1).asString(), equalTo(String2));
}

and after the changed signature is accepted, it matches the expected extract method result.

I was not able to find a way to set the parameters before I extract the method. Is there a way to set the parameters before I extract the method? If not, is there an easy way to get the event handler for the prompt and automatically accept the changed signature?

Thank you again for your help so far :)

0
Avatar
Permanently deleted user

When I was looking through the source code, I totally missed the ExtractMethodProcessor.initParameterizedDuplicates(boolean showDialog) method. If anyone has a similar issue, this solved my problem.

0

Please sign in to leave a comment.