5 package com
.intellij
.refactoring
.extractMethodObject
;
7 import com
.intellij
.codeInsight
.AnnotationUtil
;
8 import com
.intellij
.openapi
.diagnostic
.Logger
;
9 import com
.intellij
.openapi
.editor
.Editor
;
10 import com
.intellij
.openapi
.project
.Project
;
11 import com
.intellij
.openapi
.ui
.DialogWrapper
;
12 import com
.intellij
.openapi
.util
.Comparing
;
13 import com
.intellij
.openapi
.util
.text
.StringUtil
;
14 import com
.intellij
.psi
.*;
15 import com
.intellij
.psi
.codeStyle
.CodeStyleManager
;
16 import com
.intellij
.psi
.codeStyle
.CodeStyleSettingsManager
;
17 import com
.intellij
.psi
.codeStyle
.JavaCodeStyleManager
;
18 import com
.intellij
.psi
.codeStyle
.VariableKind
;
19 import com
.intellij
.psi
.controlFlow
.ControlFlowUtil
;
20 import com
.intellij
.psi
.impl
.source
.PsiImmediateClassType
;
21 import com
.intellij
.psi
.search
.GlobalSearchScope
;
22 import com
.intellij
.psi
.search
.searches
.ReferencesSearch
;
23 import com
.intellij
.psi
.util
.PropertyUtil
;
24 import com
.intellij
.psi
.util
.PsiTreeUtil
;
25 import com
.intellij
.psi
.util
.PsiUtil
;
26 import com
.intellij
.refactoring
.BaseRefactoringProcessor
;
27 import com
.intellij
.refactoring
.HelpID
;
28 import com
.intellij
.refactoring
.classMembers
.MemberInfoBase
;
29 import com
.intellij
.refactoring
.changeSignature
.ChangeSignatureProcessor
;
30 import com
.intellij
.refactoring
.changeSignature
.ParameterInfoImpl
;
31 import com
.intellij
.refactoring
.extractMethod
.AbstractExtractDialog
;
32 import com
.intellij
.refactoring
.extractMethod
.ExtractMethodProcessor
;
33 import com
.intellij
.refactoring
.ui
.MemberSelectionPanel
;
34 import com
.intellij
.refactoring
.util
.RefactoringUtil
;
35 import com
.intellij
.refactoring
.util
.VisibilityUtil
;
36 import com
.intellij
.refactoring
.util
.classMembers
.MemberInfo
;
37 import com
.intellij
.refactoring
.util
.duplicates
.Match
;
38 import com
.intellij
.usageView
.UsageInfo
;
39 import com
.intellij
.usageView
.UsageViewDescriptor
;
40 import com
.intellij
.usageView
.UsageViewUtil
;
41 import com
.intellij
.util
.ArrayUtil
;
42 import com
.intellij
.util
.Function
;
43 import com
.intellij
.util
.IncorrectOperationException
;
44 import org
.jetbrains
.annotations
.NonNls
;
45 import org
.jetbrains
.annotations
.NotNull
;
50 public class ExtractMethodObjectProcessor
extends BaseRefactoringProcessor
{
51 private static final Logger LOG
= Logger
.getInstance("#" + com
.intellij
.refactoring
.extractMethodObject
.ExtractMethodObjectProcessor
.class.getName());
52 @NonNls public static final String REFACTORING_NAME
= "Extract Method Object";
54 private final PsiElementFactory myElementFactory
;
56 private final MyExtractMethodProcessor myExtractProcessor
;
57 private boolean myCreateInnerClass
= true;
58 private String myInnerClassName
;
60 private boolean myMultipleExitPoints
;
61 private PsiField
[] myOutputFields
;
63 private PsiMethod myInnerMethod
;
64 private boolean myMadeStatic
= false;
65 private final Set
<MethodToMoveUsageInfo
> myUsages
= new HashSet
<MethodToMoveUsageInfo
>();
66 private PsiClass myInnerClass
;
68 public ExtractMethodObjectProcessor(Project project
, Editor editor
, PsiElement
[] elements
, final String innerClassName
) {
70 myInnerClassName
= innerClassName
;
71 myExtractProcessor
= new MyExtractMethodProcessor(project
, editor
, elements
, null, REFACTORING_NAME
, innerClassName
, HelpID
.EXTRACT_METHOD_OBJECT
);
72 myElementFactory
= JavaPsiFacade
.getInstance(project
).getElementFactory();
75 protected UsageViewDescriptor
createUsageViewDescriptor(final UsageInfo
[] usages
) {
76 return new ExtractMethodObjectViewDescriptor(getMethod());
80 protected UsageInfo
[] findUsages() {
81 final ArrayList
<UsageInfo
> result
= new ArrayList
<UsageInfo
>();
83 ReferencesSearch
.search(getMethod(), GlobalSearchScope
.projectScope(myProject
), false).toArray(PsiReference
.EMPTY_ARRAY
);
84 for (PsiReference ref
: refs
) {
85 final PsiElement element
= ref
.getElement();
86 if (element
!= null && element
.isValid()) {
87 result
.add(new UsageInfo(element
));
90 if (isCreateInnerClass()) {
91 final Set
<PsiMethod
> usedMethods
= new HashSet
<PsiMethod
>();
92 getMethod().accept(new JavaRecursiveElementWalkingVisitor() {
94 public void visitMethodCallExpression(PsiMethodCallExpression expression
) {
95 super.visitMethodCallExpression(expression
);
96 final PsiMethod method
= expression
.resolveMethod();
98 usedMethods
.add(method
);
104 for (PsiMethod usedMethod
: usedMethods
) {
105 if (usedMethod
.getModifierList().hasModifierProperty(PsiModifier
.PRIVATE
)) {
106 PsiMethod toMove
= usedMethod
;
107 for (PsiReference reference
: ReferencesSearch
.search(usedMethod
)) {
108 if (!PsiTreeUtil
.isAncestor(getMethod(), reference
.getElement(), false)) {
113 if (toMove
!= null) {
114 myUsages
.add(new MethodToMoveUsageInfo(toMove
));
119 UsageInfo
[] usageInfos
= result
.toArray(new UsageInfo
[result
.size()]);
120 return UsageViewUtil
.removeDuplicatedUsages(usageInfos
);
123 protected void refreshElements(final PsiElement
[] elements
) {}
125 protected void performRefactoring(final UsageInfo
[] usages
) {
127 if (isCreateInnerClass()) {
128 myInnerClass
= (PsiClass
)getMethod().getContainingClass().add(myElementFactory
.createClass(getInnerClassName()));
129 final boolean isStatic
= copyMethodModifiers() && notHasGeneratedFields();
130 for (UsageInfo usage
: usages
) {
131 final PsiMethodCallExpression methodCallExpression
= PsiTreeUtil
.getParentOfType(usage
.getElement(), PsiMethodCallExpression
.class);
132 if (methodCallExpression
!= null) {
133 replaceMethodCallExpression(inferTypeArguments(methodCallExpression
), methodCallExpression
);
137 final PsiParameter
[] parameters
= getMethod().getParameterList().getParameters();
138 if (parameters
.length
> 0) {
139 createInnerClassConstructor(parameters
);
140 } else if (isStatic
) {
141 final PsiMethod copy
= (PsiMethod
)getMethod().copy();
142 copy
.setName("invoke");
143 myInnerClass
.add(copy
);
144 if (myMultipleExitPoints
) {
145 addOutputVariableFieldsWithGetters();
149 if (myMultipleExitPoints
) {
150 addOutputVariableFieldsWithGetters();
152 copyMethodWithoutParameters();
153 copyMethodTypeParameters();
155 for (UsageInfo usage
: usages
) {
156 final PsiMethodCallExpression methodCallExpression
= PsiTreeUtil
.getParentOfType(usage
.getElement(), PsiMethodCallExpression
.class);
157 if (methodCallExpression
!= null) {
158 methodCallExpression
.replace(processMethodDeclaration( methodCallExpression
.getArgumentList()));
163 catch (IncorrectOperationException e
) {
168 protected void moveUsedMethodsToInner() {
169 if (!myUsages
.isEmpty()) {
170 final List
<MemberInfo
> memberInfos
= new ArrayList
<MemberInfo
>();
171 for (MethodToMoveUsageInfo usage
: myUsages
) {
172 memberInfos
.add(new MemberInfo((PsiMethod
)usage
.getElement()));
175 final MemberSelectionPanel panel
= new MemberSelectionPanel("Methods to move to the extracted class", memberInfos
, null);
176 DialogWrapper dlg
= new DialogWrapper(myProject
, false) {
179 setTitle("Move Methods Used in Extracted Block Only");
184 protected JComponent
createCenterPanel() {
190 for (MemberInfoBase
<PsiMember
> memberInfo
: panel
.getTable().getSelectedMemberInfos()) {
191 if (memberInfo
.isChecked()) {
192 myInnerClass
.add(memberInfo
.getMember().copy());
193 memberInfo
.getMember().delete();
201 private void addOutputVariableFieldsWithGetters() throws IncorrectOperationException
{
202 final Map
<String
, String
> var2FieldNames
= new HashMap
<String
, String
>();
203 final PsiVariable
[] outputVariables
= myExtractProcessor
.getOutputVariables();
204 for (int i
= 0; i
< outputVariables
.length
; i
++) {
205 final PsiVariable var
= outputVariables
[i
];
206 final PsiField outputField
= myOutputFields
[i
];
207 final String name
= getPureName(var
);
208 LOG
.assertTrue(name
!= null);
209 if (outputField
!= null) {
210 var2FieldNames
.put(var
.getName(), outputField
.getName());
211 myInnerClass
.add(outputField
);
213 final PsiField field
= PropertyUtil
.findPropertyField(myProject
, myInnerClass
, name
, false);
214 LOG
.assertTrue(field
!= null, "i:" + i
+ "; output variables: " + Arrays
.toString(outputVariables
) + "; parameters: " + Arrays
.toString(getMethod().getParameterList().getParameters()) + "; output field: " + outputField
);
215 myInnerClass
.add(PropertyUtil
.generateGetterPrototype(field
));
218 PsiParameter
[] params
= getMethod().getParameterList().getParameters();
219 ParameterInfoImpl
[] infos
= new ParameterInfoImpl
[params
.length
];
220 for (int i
= 0; i
< params
.length
; i
++) {
221 PsiParameter param
= params
[i
];
222 infos
[i
] = new ParameterInfoImpl(i
, param
.getName(), param
.getType());
224 ChangeSignatureProcessor cp
= new ChangeSignatureProcessor(myProject
, getMethod(), false, null, getMethod().getName(),
225 new PsiImmediateClassType(myInnerClass
, PsiSubstitutor
.EMPTY
), infos
);
227 final PsiCodeBlock body
= getMethod().getBody();
228 LOG
.assertTrue(body
!= null);
229 final List
<PsiLocalVariable
> vars
= new ArrayList
<PsiLocalVariable
>();
230 final Map
<PsiElement
, PsiElement
> replacementMap
= new LinkedHashMap
<PsiElement
, PsiElement
>();
231 body
.accept(new JavaRecursiveElementWalkingVisitor() {
233 public void visitReturnStatement(final PsiReturnStatement statement
) {
234 super.visitReturnStatement(statement
);
236 replacementMap
.put(statement
, myElementFactory
.createStatementFromText("return this;", statement
));
238 catch (IncorrectOperationException e
) {
244 public void visitDeclarationStatement(final PsiDeclarationStatement statement
) {
245 super.visitDeclarationStatement(statement
);
246 final PsiElement
[] declaredElements
= statement
.getDeclaredElements();//todo
247 for (PsiElement declaredElement
: declaredElements
) {
248 if (declaredElement
instanceof PsiVariable
) {
249 for (PsiVariable variable
: outputVariables
) {
250 PsiLocalVariable var
= (PsiLocalVariable
)declaredElement
;
251 if (Comparing
.strEqual(var
.getName(), variable
.getName())) {
252 final PsiExpression initializer
= var
.getInitializer();
253 if (initializer
== null) {
254 replacementMap
.put(statement
, null);
257 replacementMap
.put(var
, var
);
266 public void visitReferenceExpression(final PsiReferenceExpression expression
) {
267 super.visitReferenceExpression(expression
);
268 final PsiElement resolved
= expression
.resolve();
269 if (resolved
instanceof PsiLocalVariable
) {
270 final String var
= ((PsiLocalVariable
)resolved
).getName();
271 for (PsiVariable variable
: outputVariables
) {
272 if (Comparing
.strEqual(variable
.getName(), var
)) {
273 vars
.add((PsiLocalVariable
)resolved
);
281 for (PsiLocalVariable var
: vars
) {
282 final String fieldName
= var2FieldNames
.get(var
.getName());
283 for (PsiReference reference
: ReferencesSearch
.search(var
)) {
284 reference
.handleElementRename(fieldName
);
288 for (PsiElement statement
: replacementMap
.keySet()) {
289 final PsiElement replacement
= replacementMap
.get(statement
);
290 if (replacement
!= null) {
291 if (statement
instanceof PsiLocalVariable
) {
292 final PsiLocalVariable variable
= (PsiLocalVariable
)statement
;
293 variable
.normalizeDeclaration();
294 final PsiExpression initializer
= variable
.getInitializer();
295 LOG
.assertTrue(initializer
!= null);
296 final PsiStatement assignmentStatement
= myElementFactory
.createStatementFromText(var2FieldNames
.get(variable
.getName()) + " = " + initializer
.getText() + ";", statement
);
297 final PsiDeclarationStatement declaration
= PsiTreeUtil
.getParentOfType(statement
, PsiDeclarationStatement
.class);
298 LOG
.assertTrue(declaration
!= null);
299 declaration
.replace(assignmentStatement
);
301 statement
.replace(replacement
);
309 private String
getPureName(PsiVariable var
) {
310 final JavaCodeStyleManager styleManager
= JavaCodeStyleManager
.getInstance(myProject
);
311 return var
instanceof PsiLocalVariable
312 ? styleManager
.variableNameToPropertyName(var
.getName(), VariableKind
.LOCAL_VARIABLE
) : styleManager
.variableNameToPropertyName(var
.getName(), VariableKind
.PARAMETER
);
315 public PsiExpression
processMethodDeclaration( PsiExpressionList expressionList
) throws IncorrectOperationException
{
316 if (isCreateInnerClass()) {
317 final String typeArguments
= getMethod().hasTypeParameters() ?
"<" + StringUtil
.join(Arrays
.asList(getMethod().getTypeParameters()),
318 new Function
<PsiTypeParameter
, String
>() {
319 public String
fun(final PsiTypeParameter typeParameter
) {
320 final String typeParameterName
=
321 typeParameter
.getName();
322 LOG
.assertTrue(typeParameterName
!= null);
323 return typeParameterName
;
326 final PsiMethodCallExpression methodCallExpression
=
327 (PsiMethodCallExpression
)myElementFactory
.createExpressionFromText("invoke" + expressionList
.getText(), null);
328 return replaceMethodCallExpression(typeArguments
, methodCallExpression
);
331 final String paramsDeclaration
= getMethod().getParameterList().getText();
332 final PsiType returnType
= getMethod().getReturnType();
333 LOG
.assertTrue(returnType
!= null);
335 final PsiCodeBlock methodBody
= getMethod().getBody();
336 LOG
.assertTrue(methodBody
!= null);
337 return myElementFactory
.createExpressionFromText("new Object(){ \n" +
339 returnType
.getPresentableText() +
340 " " + myInnerClassName
+
342 methodBody
.getText() +
343 "}." + myInnerClassName
+
344 expressionList
.getText(), null);
349 private PsiMethodCallExpression
replaceMethodCallExpression(final String inferredTypeArguments
,
350 final PsiMethodCallExpression methodCallExpression
)
351 throws IncorrectOperationException
{
352 @NonNls final String staticqualifier
=
353 getMethod().hasModifierProperty(PsiModifier
.STATIC
) && notHasGeneratedFields() ?
getInnerClassName() : null;
354 @NonNls String newReplacement
;
355 final PsiReferenceExpression methodExpression
= methodCallExpression
.getMethodExpression();
356 final PsiExpressionList argumentList
= methodCallExpression
.getArgumentList();
357 if (staticqualifier
!= null) {
358 newReplacement
= argumentList
.getExpressions().length
> 0
359 ?
"new " + staticqualifier
+ inferredTypeArguments
+ argumentList
.getText() + "."
360 : staticqualifier
+ ".";
362 final PsiExpression qualifierExpression
= methodExpression
.getQualifierExpression();
363 final String qualifier
= qualifierExpression
!= null ? qualifierExpression
.getText() + "." : "";
364 newReplacement
= qualifier
+ "new " + getInnerClassName() + inferredTypeArguments
+ argumentList
.getText()+ ".";
366 return (PsiMethodCallExpression
)methodCallExpression
.replace(myElementFactory
.createExpressionFromText(newReplacement
+ "invoke()", null));
370 private String
inferTypeArguments(final PsiMethodCallExpression methodCallExpression
) {
371 final PsiReferenceParameterList list
= methodCallExpression
.getMethodExpression().getParameterList();
373 if (list
!= null && list
.getTypeArguments().length
> 0) {
374 return list
.getText();
376 final PsiTypeParameter
[] methodTypeParameters
= getMethod().getTypeParameters();
377 if (methodTypeParameters
.length
> 0) {
378 List
<String
> typeSignature
= new ArrayList
<String
>();
379 final PsiResolveHelper resolveHelper
= JavaPsiFacade
.getInstance(getMethod().getProject()).getResolveHelper();
380 for (final PsiTypeParameter typeParameter
: methodTypeParameters
) {
381 final PsiType type
= resolveHelper
.inferTypeForMethodTypeParameter(typeParameter
, getMethod().getParameterList().getParameters(),
382 methodCallExpression
.getArgumentList().getExpressions(),
383 PsiSubstitutor
.EMPTY
, methodCallExpression
, false);
384 if (type
== null || PsiType
.NULL
.equals(type
)) {
387 typeSignature
.add(type
.getPresentableText());
389 return "<" + StringUtil
.join(typeSignature
, ", ") + ">";
395 protected String
getCommandName() {
396 return REFACTORING_NAME
;
400 private boolean copyMethodModifiers() throws IncorrectOperationException
{
401 final PsiModifierList methodModifierList
= getMethod().getModifierList();
403 final PsiModifierList innerClassModifierList
= myInnerClass
.getModifierList();
404 LOG
.assertTrue(innerClassModifierList
!= null);
405 innerClassModifierList
.setModifierProperty(VisibilityUtil
.getVisibilityModifier(methodModifierList
), true);
406 final boolean isStatic
= methodModifierList
.hasModifierProperty(PsiModifier
.STATIC
);
407 innerClassModifierList
.setModifierProperty(PsiModifier
.STATIC
, isStatic
);
411 private void copyMethodTypeParameters() throws IncorrectOperationException
{
412 final PsiTypeParameterList typeParameterList
= myInnerClass
.getTypeParameterList();
413 LOG
.assertTrue(typeParameterList
!= null);
415 for (PsiTypeParameter parameter
: getMethod().getTypeParameters()) {
416 typeParameterList
.add(parameter
);
420 private void copyMethodWithoutParameters() throws IncorrectOperationException
{
421 final PsiMethod newMethod
= myElementFactory
.createMethod("invoke", getMethod().getReturnType());
422 newMethod
.getThrowsList().replace(getMethod().getThrowsList());
424 final PsiCodeBlock replacedMethodBody
= newMethod
.getBody();
425 LOG
.assertTrue(replacedMethodBody
!= null);
426 final PsiCodeBlock methodBody
= getMethod().getBody();
427 LOG
.assertTrue(methodBody
!= null);
428 replacedMethodBody
.replace(methodBody
);
429 PsiUtil
.setModifierProperty(newMethod
, PsiModifier
.STATIC
, myInnerClass
.hasModifierProperty(PsiModifier
.STATIC
) && notHasGeneratedFields());
430 myInnerMethod
= (PsiMethod
)myInnerClass
.add(newMethod
);
433 private boolean notHasGeneratedFields() {
434 return !myMultipleExitPoints
&& getMethod().getParameterList().getParametersCount() == 0;
437 private void createInnerClassConstructor(final PsiParameter
[] parameters
) throws IncorrectOperationException
{
438 final PsiMethod constructor
= myElementFactory
.createConstructor();
439 final PsiParameterList parameterList
= constructor
.getParameterList();
440 for (PsiParameter parameter
: parameters
) {
441 final PsiModifierList parameterModifierList
= parameter
.getModifierList();
442 LOG
.assertTrue(parameterModifierList
!= null);
443 final String parameterName
= parameter
.getName();
444 LOG
.assertTrue(parameterName
!= null);
445 PsiParameter parm
= myElementFactory
.createParameter(parameterName
, parameter
.getType());
446 if (CodeStyleSettingsManager
.getSettings(myProject
).GENERATE_FINAL_PARAMETERS
) {
447 final PsiModifierList modifierList
= parm
.getModifierList();
448 LOG
.assertTrue(modifierList
!= null);
449 modifierList
.setModifierProperty(PsiModifier
.FINAL
, true);
451 parameterList
.add(parm
);
453 final PsiField field
= createField(parm
, constructor
, parameterModifierList
.hasModifierProperty(PsiModifier
.FINAL
));
454 for (PsiReference reference
: ReferencesSearch
.search(parameter
)) {
455 reference
.handleElementRename(field
.getName());
458 myInnerClass
.add(constructor
);
461 private PsiField
createField(PsiParameter parameter
, PsiMethod constructor
, boolean isFinal
) {
462 final String parameterName
= parameter
.getName();
463 PsiType type
= parameter
.getType();
464 if (type
instanceof PsiEllipsisType
) type
= ((PsiEllipsisType
)type
).toArrayType();
466 final JavaCodeStyleManager styleManager
= JavaCodeStyleManager
.getInstance(getMethod().getProject());
467 final String fieldName
= styleManager
.suggestVariableName(VariableKind
.FIELD
, styleManager
.variableNameToPropertyName(parameterName
, VariableKind
.PARAMETER
), null, type
).names
[0];
468 PsiField field
= myElementFactory
.createField(fieldName
, type
);
470 final PsiModifierList modifierList
= field
.getModifierList();
471 LOG
.assertTrue(modifierList
!= null);
472 if (AnnotationUtil
.isAnnotated(parameter
, AnnotationUtil
.NULLABLE
, false)) {
473 modifierList
.addAfter(myElementFactory
.createAnnotationFromText("@" + AnnotationUtil
.NULLABLE
, field
), null);
475 modifierList
.setModifierProperty(PsiModifier
.FINAL
, isFinal
);
477 final PsiCodeBlock methodBody
= constructor
.getBody();
479 LOG
.assertTrue(methodBody
!= null);
481 @NonNls final String stmtText
;
482 if (Comparing
.strEqual(parameterName
, fieldName
)) {
483 stmtText
= "this." + fieldName
+ " = " + parameterName
+ ";";
485 stmtText
= fieldName
+ " = " + parameterName
+ ";";
487 PsiStatement assignmentStmt
= myElementFactory
.createStatementFromText(stmtText
, methodBody
);
488 assignmentStmt
= (PsiStatement
)CodeStyleManager
.getInstance(constructor
.getProject()).reformat(assignmentStmt
);
489 methodBody
.add(assignmentStmt
);
491 field
= (PsiField
)myInnerClass
.add(field
);
494 catch (IncorrectOperationException e
) {
500 protected void changeInstanceAccess(final Project project
)
501 throws IncorrectOperationException
{
503 PsiReference
[] refs
=
504 ReferencesSearch
.search(myInnerMethod
, GlobalSearchScope
.projectScope(project
), false).toArray(PsiReference
.EMPTY_ARRAY
);
505 for (PsiReference ref
: refs
) {
506 final PsiElement element
= ref
.getElement();
507 final PsiMethodCallExpression callExpression
= PsiTreeUtil
.getParentOfType(element
, PsiMethodCallExpression
.class);
508 if (callExpression
!= null) {
509 replaceMethodCallExpression(inferTypeArguments(callExpression
), callExpression
);
515 public PsiMethod
getMethod() {
516 return myExtractProcessor
.getExtractedMethod();
519 public String
getInnerClassName() {
520 return myInnerClassName
;
523 public void setCreateInnerClass(final boolean createInnerClass
) {
524 myCreateInnerClass
= createInnerClass
;
527 public boolean isCreateInnerClass() {
528 return myCreateInnerClass
;
532 public MyExtractMethodProcessor
getExtractProcessor() {
533 return myExtractProcessor
;
536 public class MyExtractMethodProcessor
extends ExtractMethodProcessor
{
538 public MyExtractMethodProcessor(Project project
,
540 PsiElement
[] elements
,
541 PsiType forcedReturnType
,
542 String refactoringName
,
543 String initialMethodName
,
545 super(project
, editor
, elements
, forcedReturnType
, refactoringName
, initialMethodName
, helpId
);
550 protected void apply(final AbstractExtractDialog dialog
) {
552 myCreateInnerClass
= ((ExtractMethodObjectDialog
)dialog
).createInnerClass();
553 myInnerClassName
= myCreateInnerClass ? StringUtil
.capitalize(dialog
.getChosenMethodName()) : dialog
.getChosenMethodName();
557 protected AbstractExtractDialog
createExtractMethodDialog(final boolean direct
) {
558 return new ExtractMethodObjectDialog(myProject
, myTargetClass
, myInputVariables
, myReturnType
, myTypeParameterList
,
559 myThrownExceptions
, myStatic
, myCanBeStatic
, myElements
, myMultipleExitPoints
);
563 protected boolean checkOutputVariablesCount() {
564 myMultipleExitPoints
= super.checkOutputVariablesCount();
565 myOutputFields
= new PsiField
[myOutputVariables
.length
];
566 for (int i
= 0; i
< myOutputVariables
.length
; i
++) {
567 PsiVariable variable
= myOutputVariables
[i
];
568 if (!myInputVariables
.contains(variable
)) { //one field creation
569 final JavaCodeStyleManager styleManager
= JavaCodeStyleManager
.getInstance(myProject
);
570 final String fieldName
=
571 styleManager
.suggestVariableName(VariableKind
.FIELD
, getPureName(variable
), null, variable
.getType()).names
[0];
573 myOutputFields
[i
] = myElementFactory
.createField(fieldName
, variable
.getType());
575 catch (IncorrectOperationException e
) {
580 return !myCreateInnerClass
&& myMultipleExitPoints
;
584 public PsiElement
processMatch(final Match match
) throws IncorrectOperationException
{
585 final boolean makeStatic
= myInnerMethod
!= null &&
586 RefactoringUtil
.isInStaticContext(match
.getMatchStart(), getExtractedMethod().getContainingClass());
587 final PsiElement element
= super.processMatch(match
);
590 final PsiModifierList modifierList
= myInnerMethod
.getContainingClass().getModifierList();
591 LOG
.assertTrue(modifierList
!= null);
592 modifierList
.setModifierProperty(PsiModifier
.STATIC
, true);
593 PsiUtil
.setModifierProperty(myInnerMethod
, PsiModifier
.STATIC
, true);
595 PsiMethodCallExpression methodCallExpression
= null;
596 if (element
instanceof PsiMethodCallExpression
) {
597 methodCallExpression
= (PsiMethodCallExpression
)element
;
599 else if (element
instanceof PsiExpressionStatement
) {
600 final PsiExpression expression
= ((PsiExpressionStatement
)element
).getExpression();
601 if (expression
instanceof PsiMethodCallExpression
) {
602 methodCallExpression
= (PsiMethodCallExpression
)expression
;
604 else if (expression
instanceof PsiAssignmentExpression
) {
605 final PsiExpression psiExpression
= ((PsiAssignmentExpression
)expression
).getRExpression();
606 if (psiExpression
instanceof PsiMethodCallExpression
) {
607 methodCallExpression
= (PsiMethodCallExpression
)psiExpression
;
610 } else if (element
instanceof PsiDeclarationStatement
) {
611 final PsiElement
[] declaredElements
= ((PsiDeclarationStatement
)element
).getDeclaredElements();
612 for (PsiElement declaredElement
: declaredElements
) {
613 if (declaredElement
instanceof PsiLocalVariable
) {
614 final PsiExpression initializer
= ((PsiLocalVariable
)declaredElement
).getInitializer();
615 if (initializer
instanceof PsiMethodCallExpression
) {
616 methodCallExpression
= (PsiMethodCallExpression
)initializer
;
622 if (methodCallExpression
== null) return element
;
624 PsiExpression expression
= processMethodDeclaration(methodCallExpression
.getArgumentList());
626 return methodCallExpression
.replace(expression
);
629 public PsiVariable
[] getOutputVariables() {
630 return myOutputVariables
;
634 protected void declareNecessaryVariablesAfterCall(final PsiVariable outputVariable
) throws IncorrectOperationException
{
635 if (myMultipleExitPoints
) {
636 final String object
= StringUtil
.decapitalize(myInnerClassName
);
637 final PsiStatement methodCallStatement
= PsiTreeUtil
.getParentOfType(getMethodCall(), PsiStatement
.class);
638 LOG
.assertTrue(methodCallStatement
!= null);
639 methodCallStatement
.replace(
640 myElementFactory
.createStatementFromText(myInnerClassName
+ " " + object
+ " = " + getMethodCall().getText() + ";", myInnerMethod
));
642 final List
<PsiVariable
> usedVariables
= myControlFlowWrapper
.getUsedVariables();
643 Collection
<ControlFlowUtil
.VariableInfo
> reassigned
= myControlFlowWrapper
.getInitializedTwice();
644 for (PsiVariable variable
: usedVariables
) {
645 String name
= variable
.getName();
646 LOG
.assertTrue(name
!= null);
647 PsiStatement st
= null;
648 if (isDeclaredInside(variable
)) {
649 st
= myElementFactory
.createStatementFromText(
650 variable
.getType().getCanonicalText() + " " + name
+ " = " + object
+ "." + PropertyUtil
.suggestGetterName(getPureName(variable
), variable
.getType()) + "();",
652 if (reassigned
.contains(new ControlFlowUtil
.VariableInfo(variable
, null))) {
653 final PsiElement
[] psiElements
= ((PsiDeclarationStatement
)st
).getDeclaredElements();
654 assert psiElements
.length
> 0;
655 PsiVariable var
= (PsiVariable
)psiElements
[0];
656 PsiUtil
.setModifierProperty(var
, PsiModifier
.FINAL
, false);
660 if (ArrayUtil
.find(myOutputVariables
, variable
) != -1) {
661 st
= myElementFactory
.createStatementFromText(name
+ " = " + object
+ "." + PropertyUtil
.suggestGetterName(getPureName(variable
), variable
.getType()) + "();", myInnerMethod
);
665 addToMethodCallLocation(st
);
670 super.declareNecessaryVariablesAfterCall(outputVariable
);