blob: 5027752e47d0c0b1e56702dab57ca8eddb570a5b [file] [log] [blame]
/*
* Copyright 2000-2011 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.ExpectedTypesProvider;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.analysis.AnnotationsHighlightUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class CreateAnnotationMethodFromUsageFix extends CreateFromUsageBaseFix {
private static final Logger LOG = Logger.getInstance("#" + CreateAnnotationMethodFromUsageFix.class.getName());
private final SmartPsiElementPointer<PsiNameValuePair> myNameValuePair;
public CreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair valuePair) {
myNameValuePair = SmartPointerManager.getInstance(valuePair.getProject()).createSmartPsiElementPointer(valuePair);
}
@Override
protected boolean isAvailableImpl(int offset) {
final PsiNameValuePair call = getNameValuePair();
if (call == null || !call.isValid()) return false;
String name = call.getName();
if (name == null || !PsiNameHelper.getInstance(call.getProject()).isIdentifier(name)) return false;
if (getAnnotationValueType(call.getValue()) == null) return false;
setText(QuickFixBundle.message("create.method.from.usage.text", name));
return true;
}
@Override
protected PsiElement getElement() {
final PsiNameValuePair call = getNameValuePair();
if (call == null || !call.getManager().isInProject(call)) return null;
return call;
}
@Override
protected void invokeImpl(final PsiClass targetClass) {
if (targetClass == null) return;
PsiNameValuePair nameValuePair = getNameValuePair();
if (nameValuePair == null || isValidElement(nameValuePair)) return;
final PsiElementFactory factory = JavaPsiFacade.getInstance(nameValuePair.getProject()).getElementFactory();
final String methodName = nameValuePair.getName();
LOG.assertTrue(methodName != null);
PsiMethod method = factory.createMethod(methodName, PsiType.VOID);
method = (PsiMethod)targetClass.add(method);
PsiCodeBlock body = method.getBody();
assert body != null;
body.delete();
final PsiElement context = PsiTreeUtil.getParentOfType(nameValuePair, PsiClass.class, PsiMethod.class);
final PsiType type = getAnnotationValueType(nameValuePair.getValue());
LOG.assertTrue(type != null);
final ExpectedTypeInfo[] expectedTypes =
new ExpectedTypeInfo[]{ExpectedTypesProvider.createInfo(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.NONE)};
CreateMethodFromUsageFix.doCreate(targetClass, method, true, ContainerUtil.map2List(PsiExpression.EMPTY_ARRAY, Pair.<PsiExpression, PsiType>createFunction(null)),
getTargetSubstitutor(nameValuePair), expectedTypes, context);
}
@Nullable
private static PsiType getAnnotationValueType(PsiAnnotationMemberValue value) {
PsiType type = null;
if (value instanceof PsiExpression) {
type = ((PsiExpression)value).getType();
} else if (value instanceof PsiArrayInitializerMemberValue) {
final PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)value).getInitializers();
PsiType currentType = null;
for (PsiAnnotationMemberValue initializer : initializers) {
if (initializer instanceof PsiArrayInitializerMemberValue) return null;
if (!(initializer instanceof PsiExpression)) return null;
final PsiType psiType = ((PsiExpression)initializer).getType();
if (psiType != null) {
if (currentType == null) {
currentType = psiType;
} else {
if (!TypeConversionUtil.isAssignable(currentType, psiType)) {
if (TypeConversionUtil.isAssignable(psiType, currentType)) {
currentType = psiType;
} else {
return null;
}
}
}
}
}
if (currentType != null) {
type = currentType.createArrayType();
}
}
if (type != null && type.accept(AnnotationsHighlightUtil.AnnotationReturnTypeVisitor.INSTANCE).booleanValue()) {
return type;
}
return null;
}
@Override
protected boolean isValidElement(PsiElement element) {
final PsiReference reference = element.getReference();
return reference != null && reference.resolve() != null;
}
@Override
@NotNull
public String getFamilyName() {
return QuickFixBundle.message("create.method.from.usage.family");
}
@Nullable
protected PsiNameValuePair getNameValuePair() {
return myNameValuePair.getElement();
}
}