IDEA-201703 Allow extract variable from field initializer

This commit is contained in:
Tagir Valeev
2018-11-04 08:44:54 +07:00
parent 4e62b4899d
commit d910120ac7
7 changed files with 50 additions and 3 deletions
@@ -62,6 +62,7 @@ import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -162,7 +163,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
if (!selectionModel.hasSelection()) {
final List<PsiExpression> expressions = ContainerUtil
.filter(collectExpressions(file, editor, offset), expression -> RefactoringUtil.getParentStatement(expression, false) != null);
.filter(collectExpressions(file, editor, offset), expression ->
RefactoringUtil.getParentStatement(expression, false) != null ||
PsiTreeUtil.getParentOfType(expression, PsiField.class, true, PsiStatement.class) != null);
if (expressions.isEmpty()) {
selectionModel.selectLineAtCaret();
} else if (!isChooserNeeded(expressions)) {
@@ -612,7 +615,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
final PsiElement physicalElement = expr.getUserData(ElementToWorkOn.PARENT);
final PsiElement anchorStatement = RefactoringUtil.getParentStatement(physicalElement != null ? physicalElement : expr, false);
final PsiElement anchorStatement = getAnchor(physicalElement != null ? physicalElement : expr);
PsiElement tempContainer = checkAnchorStatement(project, editor, anchorStatement);
if (tempContainer == null) return false;
@@ -756,6 +759,19 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
return wasSucceed[0];
}
@Nullable
private static PsiElement getAnchor(PsiElement place) {
PsiElement anchorStatement = RefactoringUtil.getParentStatement(place, false);
if (anchorStatement == null) {
PsiField field = PsiTreeUtil.getParentOfType(place, PsiField.class, true, PsiStatement.class);
if (field != null) {
anchorStatement = field.getInitializer();
}
}
return anchorStatement;
}
@Contract("_, _, null -> null")
protected PsiElement checkAnchorStatement(Project project, Editor editor, PsiElement anchorStatement) {
if (anchorStatement == null) {
String message = RefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME);
@@ -78,7 +78,8 @@ public abstract class BaseOccurrenceManager implements OccurrenceManager {
}
@Override
public PsiElement getAnchorStatementForAllInScope(PsiElement scope) {
return RefactoringUtil.getAnchorElementForMultipleExpressions(myOccurrences, scope);
PsiElement anchor = RefactoringUtil.getAnchorElementForMultipleExpressions(myOccurrences, scope);
return anchor instanceof PsiField ? ((PsiField)anchor).getInitializer() : anchor;
}
private static boolean needToDeclareFinal(PsiExpression[] occurrences) {
@@ -0,0 +1,8 @@
class Test {
private static final String STRING;
static {
String temp = "foo".trim();
STRING = temp +"foo".trim();
}
}
@@ -0,0 +1,3 @@
class Test {
private static final String STRING = <selection>"foo".trim()</selection>+"foo".trim();
}
@@ -0,0 +1,8 @@
class Test {
private static final String STRING;
static {
String temp = "foo".trim();
STRING = temp + temp;
}
}
@@ -0,0 +1,3 @@
class Test {
private static final String STRING = <selection>"foo".trim()</selection>+"foo".trim();
}
@@ -203,6 +203,14 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
public void testWhileCondition2() {
doTest(new MockIntroduceVariableHandler("temp", true, false, false, "Node"));
}
public void testField() {
doTest(new MockIntroduceVariableHandler("temp", false, false, false, CommonClassNames.JAVA_LANG_STRING));
}
public void testFieldAll() {
doTest(new MockIntroduceVariableHandler("temp", true, false, false, CommonClassNames.JAVA_LANG_STRING));
}
public void testCaseLabel() {
doTest(new MockIntroduceVariableHandler("temp", true, false, false, "int"));