mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
extract method object: process exit statements as they may contain refs to outer vars (IDEA-96772); disable duplicate extraction
This commit is contained in:
@@ -130,7 +130,7 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
private List<Match> myDuplicates;
|
||||
@PsiModifier.ModifierConstant private String myMethodVisibility = PsiModifier.PRIVATE;
|
||||
protected boolean myGenerateConditionalExit;
|
||||
private PsiStatement myFirstExitStatementCopy;
|
||||
protected PsiStatement myFirstExitStatementCopy;
|
||||
private PsiMethod myExtractedMethod;
|
||||
private PsiMethodCallExpression myMethodCall;
|
||||
private boolean myNullConditionalCheck = false;
|
||||
@@ -725,7 +725,7 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
PsiIfStatement ifStatement = (PsiIfStatement)myElementFactory.createStatementFromText("if (a) b;", null);
|
||||
ifStatement = (PsiIfStatement)addToMethodCallLocation(ifStatement);
|
||||
myMethodCall = (PsiMethodCallExpression)ifStatement.getCondition().replace(myMethodCall);
|
||||
ifStatement.getThenBranch().replace(myFirstExitStatementCopy);
|
||||
myFirstExitStatementCopy = (PsiStatement)ifStatement.getThenBranch().replace(myFirstExitStatementCopy);
|
||||
CodeStyleManager.getInstance(myProject).reformat(ifStatement);
|
||||
}
|
||||
else if (myOutputVariable != null) {
|
||||
|
||||
@@ -266,7 +266,7 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
final PsiCodeBlock body = getMethod().getBody();
|
||||
LOG.assertTrue(body != null);
|
||||
final List<PsiLocalVariable> vars = new ArrayList<PsiLocalVariable>();
|
||||
final LinkedHashSet<PsiLocalVariable> vars = new LinkedHashSet<PsiLocalVariable>();
|
||||
final Map<PsiElement, PsiElement> replacementMap = new LinkedHashMap<PsiElement, PsiElement>();
|
||||
final List<PsiReturnStatement> returnStatements = new ArrayList<PsiReturnStatement>();
|
||||
body.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@@ -787,12 +787,45 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
|
||||
} else if (myElements[0] instanceof PsiPostfixExpression || myElements[0] instanceof PsiPrefixExpression) {
|
||||
getMethodCall().getParent().replace(((PsiBinaryExpression)getMethodCall().getParent()).getLOperand());
|
||||
}
|
||||
|
||||
rebindExitStatement(object);
|
||||
}
|
||||
else {
|
||||
super.declareNecessaryVariablesAfterCall(outputVariable);
|
||||
}
|
||||
}
|
||||
|
||||
private void rebindExitStatement(final String objectName) {
|
||||
final PsiStatement exitStatementCopy = myExtractProcessor.myFirstExitStatementCopy;
|
||||
if (exitStatementCopy != null) {
|
||||
myExtractProcessor.getDuplicates().clear();
|
||||
final Map<String, PsiVariable> outVarsNames = new HashMap<String, PsiVariable>();
|
||||
for (PsiVariable variable : myOutputVariables) {
|
||||
outVarsNames.put(variable.getName(), variable);
|
||||
}
|
||||
final Map<PsiElement, PsiElement> replaceMap = new HashMap<PsiElement, PsiElement>();
|
||||
exitStatementCopy.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
if (expression.resolve() == null) {
|
||||
final PsiVariable variable = outVarsNames.get(expression.getReferenceName());
|
||||
if (variable != null) {
|
||||
final String call2Getter = objectName + "." + PropertyUtil.suggestGetterName(getPureName(variable), variable.getType()) + "()";
|
||||
final PsiExpression callToGetter = myElementFactory.createExpressionFromText(call2Getter, variable);
|
||||
replaceMap.put(expression, callToGetter);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
for (PsiElement element : replaceMap.keySet()) {
|
||||
if (element.isValid()) {
|
||||
element.replace(replaceMap.get(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean generatesConditionalExit() {
|
||||
return myGenerateConditionalExit;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
class A {
|
||||
boolean foo() {
|
||||
|
||||
<selection>for (int i = 0; i < 9; i++) {
|
||||
final Boolean foo = Boolean.FALSE;
|
||||
if (foo != null) {
|
||||
return foo;
|
||||
}
|
||||
}</selection>
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
class A {
|
||||
boolean foo() {
|
||||
|
||||
Inner inner = new Inner().invoke();
|
||||
if (inner.is()) return inner.getFoo();
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private class Inner {
|
||||
private boolean myResult;
|
||||
private Boolean foo;
|
||||
|
||||
boolean is() {
|
||||
return myResult;
|
||||
}
|
||||
|
||||
public Boolean getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public Inner invoke() {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
foo = Boolean.FALSE;
|
||||
if (foo != null) {
|
||||
myResult = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
myResult = false;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,4 +114,8 @@ public class ExtractMethodObjectWithMultipleExitPointsTest extends LightRefactor
|
||||
public void testConditionalExitWithoutCodeBlock() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testReturnExitStatement() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user