| /* |
| * Copyright 2000-2009 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.codeInsight.daemon.impl.quickfix; |
| |
| import com.intellij.codeInsight.ExpectedTypeInfo; |
| import com.intellij.codeInsight.daemon.QuickFixBundle; |
| import com.intellij.codeInsight.template.Template; |
| import com.intellij.codeInsight.template.TemplateEditingAdapter; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.editor.Editor; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.psi.*; |
| import com.intellij.psi.codeStyle.CodeStyleManager; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.psi.util.PsiUtil; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * @author Mike |
| */ |
| public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { |
| public CreateFieldFromUsageFix(@NotNull PsiReferenceExpression referenceElement) { |
| super(referenceElement); |
| } |
| |
| @Override |
| protected String getText(String varName) { |
| return QuickFixBundle.message("create.field.from.usage.text", varName); |
| } |
| |
| protected boolean createConstantField() { |
| return false; |
| } |
| |
| @NotNull |
| @Override |
| protected List<PsiClass> getTargetClasses(PsiElement element) { |
| final List<PsiClass> targetClasses = new ArrayList<PsiClass>(); |
| for (PsiClass psiClass : super.getTargetClasses(element)) { |
| if (psiClass.getManager().isInProject(psiClass) && |
| (!psiClass.isInterface() && !psiClass.isAnnotationType() || shouldCreateStaticMember(myReferenceExpression, psiClass))) { |
| targetClasses.add(psiClass); |
| } |
| } |
| return targetClasses; |
| } |
| |
| @Override |
| protected boolean canBeTargetClass(PsiClass psiClass) { |
| return psiClass.getManager().isInProject(psiClass) && !psiClass.isInterface() && !psiClass.isAnnotationType(); |
| } |
| |
| @Override |
| protected void invokeImpl(final PsiClass targetClass) { |
| final Project project = myReferenceExpression.getProject(); |
| JVMElementFactory factory = JVMElementFactories.getFactory(targetClass.getLanguage(), project); |
| if (factory == null) factory = JavaPsiFacade.getElementFactory(project); |
| |
| PsiMember enclosingContext = null; |
| PsiClass parentClass; |
| do { |
| enclosingContext = PsiTreeUtil.getParentOfType(enclosingContext == null ? myReferenceExpression : enclosingContext, PsiMethod.class, |
| PsiField.class, PsiClassInitializer.class); |
| parentClass = enclosingContext == null ? null : enclosingContext.getContainingClass(); |
| } |
| while (parentClass instanceof PsiAnonymousClass); |
| |
| ExpectedTypeInfo[] expectedTypes = CreateFromUsageUtils.guessExpectedTypes(myReferenceExpression, false); |
| |
| String fieldName = myReferenceExpression.getReferenceName(); |
| assert fieldName != null; |
| |
| PsiField field = factory.createField(fieldName, PsiType.INT); |
| if (createConstantField()) { |
| PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); |
| } |
| |
| if (createConstantField()) { |
| PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true); |
| PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); |
| } else { |
| if (!targetClass.isInterface() && shouldCreateStaticMember(myReferenceExpression, targetClass)) { |
| PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true); |
| } |
| if (shouldCreateFinalMember(myReferenceExpression, targetClass)) { |
| PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); |
| } |
| } |
| |
| field = CreateFieldFromUsageHelper.insertField(targetClass, field, myReferenceExpression); |
| |
| setupVisibility(parentClass, targetClass, field.getModifierList()); |
| |
| createFieldFromUsageTemplate(targetClass, project, expectedTypes, field, createConstantField(), myReferenceExpression); |
| } |
| |
| public static void createFieldFromUsageTemplate(final PsiClass targetClass, |
| final Project project, |
| final ExpectedTypeInfo[] expectedTypes, |
| final PsiField field, |
| final boolean createConstantField, |
| final PsiElement context) { |
| final PsiFile targetFile = targetClass.getContainingFile(); |
| final Editor newEditor = positionCursor(project, targetFile, field); |
| if (newEditor == null) return; |
| Template template = |
| CreateFieldFromUsageHelper.setupTemplate(field, expectedTypes, targetClass, newEditor, context, createConstantField); |
| |
| startTemplate(newEditor, template, project, new TemplateEditingAdapter() { |
| @Override |
| public void templateFinished(Template template, boolean brokenOff) { |
| PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument()); |
| final int offset = newEditor.getCaretModel().getOffset(); |
| final PsiField psiField = PsiTreeUtil.findElementOfClassAtOffset(targetFile, offset, PsiField.class, false); |
| if (psiField != null) { |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| CodeStyleManager.getInstance(project).reformat(psiField); |
| } |
| }); |
| newEditor.getCaretModel().moveToOffset(psiField.getTextRange().getEndOffset() - 1); |
| } |
| } |
| }); |
| } |
| |
| private static boolean shouldCreateFinalMember(@NotNull PsiReferenceExpression ref, @NotNull PsiClass targetClass) { |
| if (!PsiTreeUtil.isAncestor(targetClass, ref, true)) { |
| return false; |
| } |
| final PsiElement element = PsiTreeUtil.getParentOfType(ref, PsiClassInitializer.class, PsiMethod.class); |
| if (element instanceof PsiClassInitializer) { |
| return true; |
| } |
| |
| if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| @Override |
| @NotNull |
| public String getFamilyName() { |
| return QuickFixBundle.message("create.field.from.usage.family"); |
| } |
| } |