2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.codeInsight
.daemon
.impl
.quickfix
;
18 import com
.intellij
.codeInsight
.CodeInsightUtilBase
;
19 import com
.intellij
.codeInsight
.daemon
.QuickFixBundle
;
20 import com
.intellij
.codeInsight
.intention
.impl
.TypeExpression
;
21 import com
.intellij
.codeInsight
.template
.Template
;
22 import com
.intellij
.codeInsight
.template
.TemplateBuilderImpl
;
23 import com
.intellij
.codeInsight
.template
.TemplateManager
;
24 import com
.intellij
.openapi
.diagnostic
.Logger
;
25 import com
.intellij
.openapi
.editor
.Editor
;
26 import com
.intellij
.openapi
.project
.Project
;
27 import com
.intellij
.openapi
.util
.TextRange
;
28 import com
.intellij
.psi
.*;
29 import com
.intellij
.psi
.codeStyle
.CodeStyleSettingsManager
;
30 import com
.intellij
.psi
.util
.PsiTreeUtil
;
31 import com
.intellij
.psi
.util
.PsiUtil
;
32 import com
.intellij
.util
.IncorrectOperationException
;
33 import org
.jetbrains
.annotations
.NotNull
;
38 public class CreateLocalFromUsageFix
extends CreateVarFromUsageFix
{
40 public CreateLocalFromUsageFix(PsiReferenceExpression referenceExpression
) {
41 super(referenceExpression
);
44 private static final Logger LOG
= Logger
.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.CreateLocalFromUsageFix");
46 public String
getText(String varName
) {
47 return QuickFixBundle
.message("create.local.from.usage.text", varName
);
50 protected boolean isAvailableImpl(int offset
) {
51 if (!super.isAvailableImpl(offset
)) return false;
52 if(myReferenceExpression
.isQualified()) return false;
53 PsiElement scope
= PsiTreeUtil
.getParentOfType(myReferenceExpression
, PsiModifierListOwner
.class);
54 return scope
instanceof PsiMethod
|| scope
instanceof PsiClassInitializer
||
55 scope
instanceof PsiLocalVariable
|| scope
instanceof PsiAnonymousClass
;
58 protected void invokeImpl(PsiClass targetClass
) {
59 if (CreateFromUsageUtils
.isValidReference(myReferenceExpression
, true)) {
63 Project project
= myReferenceExpression
.getProject();
64 PsiElementFactory factory
= JavaPsiFacade
.getInstance(project
).getElementFactory();
66 PsiFile targetFile
= targetClass
.getContainingFile();
69 PsiType
[] expectedTypes
= CreateFromUsageUtils
.guessType(myReferenceExpression
, false);
70 PsiType type
= expectedTypes
[0];
72 String varName
= myReferenceExpression
.getReferenceName();
73 PsiExpression initializer
= null;
74 boolean isInline
= false;
75 PsiExpression
[] expressions
= CreateFromUsageUtils
.collectExpressions(myReferenceExpression
, PsiMember
.class, PsiFile
.class);
76 PsiStatement anchor
= getAnchor(expressions
);
77 if (anchor
instanceof PsiExpressionStatement
&& ((PsiExpressionStatement
)anchor
).getExpression() instanceof PsiAssignmentExpression
) {
78 PsiAssignmentExpression assignment
= (PsiAssignmentExpression
)((PsiExpressionStatement
)anchor
).getExpression();
79 if (assignment
.getLExpression().textMatches(myReferenceExpression
)) {
80 initializer
= assignment
.getRExpression();
85 PsiDeclarationStatement decl
= factory
.createVariableDeclarationStatement(varName
, type
, initializer
);
87 TypeExpression expression
= new TypeExpression(project
, expectedTypes
);
90 decl
= (PsiDeclarationStatement
)anchor
.replace(decl
);
93 decl
= (PsiDeclarationStatement
)anchor
.getParent().addBefore(decl
, anchor
);
96 PsiVariable var
= (PsiVariable
)decl
.getDeclaredElements()[0];
98 CodeStyleSettingsManager
.getSettings(project
).GENERATE_FINAL_LOCALS
&& !CreateFromUsageUtils
.isAccessedForWriting(expressions
);
99 PsiUtil
.setModifierProperty(var
, PsiModifier
.FINAL
, isFinal
);
101 var
= CodeInsightUtilBase
.forcePsiPostprocessAndRestoreElement(var
);
102 if (var
== null) return;
103 TemplateBuilderImpl builder
= new TemplateBuilderImpl(var
);
104 builder
.replaceElement(var
.getTypeElement(), expression
);
105 builder
.setEndVariableAfter(var
.getNameIdentifier());
106 Template template
= builder
.buildTemplate();
108 Editor newEditor
= positionCursor(project
, targetFile
, var
);
109 TextRange range
= var
.getTextRange();
110 newEditor
.getDocument().deleteString(range
.getStartOffset(), range
.getEndOffset());
112 TemplateManager manager
= TemplateManager
.getInstance(project
);
113 manager
.startTemplate(newEditor
, template
);
115 catch (IncorrectOperationException e
) {
120 protected boolean isAllowOuterTargetClass() {
124 private static PsiStatement
getAnchor(PsiExpression
[] expressionOccurences
) {
125 PsiElement parent
= expressionOccurences
[0];
126 int minOffset
= expressionOccurences
[0].getTextRange().getStartOffset();
127 for (int i
= 1; i
< expressionOccurences
.length
; i
++) {
128 parent
= PsiTreeUtil
.findCommonParent(parent
, expressionOccurences
[i
]);
129 LOG
.assertTrue(parent
!= null);
130 minOffset
= Math
.min(minOffset
, expressionOccurences
[i
].getTextRange().getStartOffset());
133 PsiCodeBlock block
= (PsiCodeBlock
) (parent
instanceof PsiCodeBlock ? parent
: PsiTreeUtil
.getParentOfType(parent
, PsiCodeBlock
.class));
134 LOG
.assertTrue(block
!= null && block
.getStatements().length
> 0);
135 PsiStatement
[] statements
= block
.getStatements();
136 for (int i
= 1; i
< statements
.length
; i
++) {
137 if (statements
[i
].getTextRange().getStartOffset() > minOffset
) return statements
[i
-1];
139 return statements
[statements
.length
- 1];
143 public String
getFamilyName() {
144 return QuickFixBundle
.message("create.local.from.usage.family");