/* * 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.CodeInsightUtilCore; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.ExpectedTypeUtil; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.intention.HighPriorityAction; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateBuilderImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.List; public class CreateEnumConstantFromUsageFix extends CreateVarFromUsageFix implements HighPriorityAction{ private static final Logger LOG = Logger.getInstance("com.intellij.codeInsight.daemon.impl.quickfix.CreateEnumConstantFromUsageFix"); public CreateEnumConstantFromUsageFix(final PsiReferenceExpression referenceElement) { super(referenceElement); } @Override protected String getText(String varName) { return QuickFixBundle.message("create.enum.constant.from.usage.text", myReferenceExpression.getReferenceName()); } @Override protected void invokeImpl(final PsiClass targetClass) { LOG.assertTrue(targetClass.isEnum()); final String name = myReferenceExpression.getReferenceName(); LOG.assertTrue(name != null); final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(myReferenceExpression.getProject()).getElementFactory(); PsiEnumConstant enumConstant = elementFactory.createEnumConstantFromText(name, null); enumConstant = (PsiEnumConstant)targetClass.add(enumConstant); final PsiMethod[] constructors = targetClass.getConstructors(); if (constructors.length > 0) { final PsiMethod constructor = constructors[0]; final PsiParameter[] parameters = constructor.getParameterList().getParameters(); if (parameters.length > 0) { final String params = StringUtil.join(parameters, psiParameter -> psiParameter.getName(), ","); enumConstant = (PsiEnumConstant)enumConstant.replace(elementFactory.createEnumConstantFromText(name + "(" + params + ")", null)); final TemplateBuilderImpl builder = new TemplateBuilderImpl(enumConstant); final PsiExpressionList argumentList = enumConstant.getArgumentList(); LOG.assertTrue(argumentList != null); for (PsiExpression expression : argumentList.getExpressions()) { builder.replaceElement(expression, new EmptyExpression()); } enumConstant = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(enumConstant); final Template template = builder.buildTemplate(); final Project project = targetClass.getProject(); final Editor newEditor = positionCursor(project, targetClass.getContainingFile(), enumConstant); if (newEditor != null) { final TextRange range = enumConstant.getTextRange(); newEditor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset()); startTemplate(newEditor, template, project); } } } } @NotNull @Override protected List<PsiClass> getTargetClasses(PsiElement element) { final List<PsiClass> classes = super.getTargetClasses(element); PsiClass enumClass = null; for (PsiClass aClass : classes) { if (aClass.isEnum()) { if (enumClass == null) { enumClass = aClass; } else { enumClass = null; break; } } } if (enumClass != null) { return Collections.singletonList(enumClass); } if (myReferenceExpression.isQualified()) { final PsiClass aClass = getTargetClassByExpectedTypes(myReferenceExpression.getQualifierExpression()); if (aClass != null) { return Collections.singletonList(aClass); } } else { final PsiClass targetClass = getTargetClassByExpectedTypes(myReferenceExpression); if (targetClass != null) { final PsiFile containingFile = myReferenceExpression.getContainingFile(); if (containingFile instanceof PsiJavaFile) { final PsiImportList importList = ((PsiJavaFile)containingFile).getImportList(); if (importList != null) { for (PsiImportStaticStatement statement : importList.getImportStaticStatements()) { if (statement.isOnDemand() && targetClass.equals(statement.resolveTargetClass())) { return Collections.singletonList(targetClass); } } } } } } return Collections.emptyList(); } private static PsiClass getTargetClassByExpectedTypes(PsiExpression expression) { ExpectedTypeInfo[] typeInfos = CreateFromUsageUtils.guessExpectedTypes(expression, false); for (final ExpectedTypeInfo typeInfo : typeInfos) { final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(typeInfo.getType()); if (psiClass != null && psiClass.isEnum()) { return psiClass; } } return null; } @Override protected boolean isAvailableImpl(int offset) { if (!super.isAvailableImpl(offset)) return false; PsiElement element = getElement(); final List<PsiClass> classes = getTargetClasses(element); if (classes.size() != 1 || !classes.get(0).isEnum()) return false; ExpectedTypeInfo[] typeInfos = CreateFromUsageUtils.guessExpectedTypes(myReferenceExpression, false); PsiType enumType = JavaPsiFacade.getInstance(myReferenceExpression.getProject()).getElementFactory().createType(classes.get(0)); for (final ExpectedTypeInfo typeInfo : typeInfos) { if (ExpectedTypeUtil.matches(enumType, typeInfo)) return true; } return false; } @Override @NotNull public String getFamilyName() { return QuickFixBundle.message("create.constant.from.usage.family"); } }