update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / daemon / impl / quickfix / CreateLocalFromUsageFix.java
blob742e997e7e18e1affebd8d96899885e5ea637600
1 /*
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;
35 /**
36 * @author Mike
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)) {
60 return;
63 Project project = myReferenceExpression.getProject();
64 PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
66 PsiFile targetFile = targetClass.getContainingFile();
68 try {
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();
81 isInline = true;
85 PsiDeclarationStatement decl = factory.createVariableDeclarationStatement(varName, type, initializer);
87 TypeExpression expression = new TypeExpression(project, expectedTypes);
89 if (isInline) {
90 decl = (PsiDeclarationStatement)anchor.replace(decl);
92 else {
93 decl = (PsiDeclarationStatement)anchor.getParent().addBefore(decl, anchor);
96 PsiVariable var = (PsiVariable)decl.getDeclaredElements()[0];
97 boolean isFinal =
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) {
116 LOG.error(e);
120 protected boolean isAllowOuterTargetClass() {
121 return false;
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];
142 @NotNull
143 public String getFamilyName() {
144 return QuickFixBundle.message("create.local.from.usage.family");