mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-10 13:17:09 +07:00
IDEA-58049 partial implementation
This commit is contained in:
+53
-37
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.util.containers.CollectionFactory;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
@@ -53,7 +53,8 @@ public class GenericsHighlightUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil");
|
||||
private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance();
|
||||
|
||||
private GenericsHighlightUtil() {}
|
||||
private GenericsHighlightUtil() {
|
||||
}
|
||||
|
||||
public static HighlightInfo checkInferredTypeArguments(PsiMethod genericMethod,
|
||||
PsiMethodCallExpression call,
|
||||
@@ -66,7 +67,7 @@ public class GenericsHighlightUtil {
|
||||
PsiClassType[] extendsTypes = typeParameter.getExtendsListTypes();
|
||||
for (PsiClassType type : extendsTypes) {
|
||||
PsiType extendsType = substitutor.substitute(type);
|
||||
if (substituted instanceof PsiWildcardType && TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(((PsiWildcardType)substituted).getExtendsBound()))){
|
||||
if (substituted instanceof PsiWildcardType && TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(((PsiWildcardType)substituted).getExtendsBound()))) {
|
||||
PsiType extendsBound = ((PsiWildcardType)substituted).getExtendsBound();
|
||||
if (extendsBound instanceof PsiClassType) {
|
||||
PsiType[] parameters = ((PsiClassType)extendsBound).getParameters();
|
||||
@@ -148,7 +149,8 @@ public class GenericsHighlightUtil {
|
||||
if (PsiTreeUtil.getParentOfType(referenceParameterList, PsiCall.class) != null &&
|
||||
PsiUtil.isLanguageLevel7OrHigher(referenceParameterList)) {
|
||||
description = null;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
description = JavaErrorMessages.message(
|
||||
"generics.type.or.method.does.not.have.type.parameters",
|
||||
typeParameterListOwnerCategoryDescription(typeParameterListOwner),
|
||||
@@ -157,9 +159,7 @@ public class GenericsHighlightUtil {
|
||||
}
|
||||
}
|
||||
else {
|
||||
description = JavaErrorMessages.message(
|
||||
"generics.wrong.number.of.type.arguments", refParametersNum, targetParametersNum
|
||||
);
|
||||
description = JavaErrorMessages.message("generics.wrong.number.of.type.arguments", refParametersNum, targetParametersNum);
|
||||
}
|
||||
|
||||
if (description != null) {
|
||||
@@ -170,7 +170,10 @@ public class GenericsHighlightUtil {
|
||||
PsiElement variable = pparent.getParent();
|
||||
if (variable instanceof PsiVariable) {
|
||||
if (targetParametersNum == 0) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveTypeArgumentsFix(variable), null);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveTypeArgumentsFix(variable));
|
||||
}
|
||||
if (typeParameterListOwner instanceof PsiClass) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new ChangeClassSignatureFromUsageFix((PsiClass)typeParameterListOwner, referenceParameterList));
|
||||
}
|
||||
VariableParameterizedTypeFix.registerIntentions(highlightInfo, (PsiVariable)variable, referenceParameterList);
|
||||
}
|
||||
@@ -186,10 +189,11 @@ public class GenericsHighlightUtil {
|
||||
final PsiType[] types = inferenceResult.getTypes();
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
final PsiType type = types[i];
|
||||
final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, type, referenceElements[0]);
|
||||
final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, type, referenceElements[0]);
|
||||
if (highlightInfo != null) return highlightInfo;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
final PsiTypeElement typeElement = referenceElements[i];
|
||||
final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, typeElement.getType(), typeElement);
|
||||
@@ -243,9 +247,10 @@ public class GenericsHighlightUtil {
|
||||
final PsiType type,
|
||||
final PsiElement typeElement2Highlight) {
|
||||
final PsiClass referenceClass;
|
||||
if (type instanceof PsiClassType){
|
||||
if (type instanceof PsiClassType) {
|
||||
referenceClass = ((PsiClassType)type).resolve();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
referenceClass = null;
|
||||
}
|
||||
final PsiType psiType = substitutor.substitute(classParameter);
|
||||
@@ -314,7 +319,8 @@ public class GenericsHighlightUtil {
|
||||
boundBound = ((PsiWildcardType)bound).isSuper()
|
||||
? ((PsiWildcardType)bound).getSuperBound()
|
||||
: ((PsiWildcardType)bound).getExtendsBound();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -335,10 +341,12 @@ public class GenericsHighlightUtil {
|
||||
? ((PsiWildcardType)bound).getExtendsBound()
|
||||
: ((PsiWildcardType)bound).getSuperBound();
|
||||
return !TypeConversionUtil.isAssignable(boundBound, type, allowUncheckedConversion);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return !TypeConversionUtil.isAssignable(bound, type, allowUncheckedConversion);
|
||||
}
|
||||
}
|
||||
@@ -349,7 +357,7 @@ public class GenericsHighlightUtil {
|
||||
final PsiClass classType = ((PsiClassType)type).resolve();
|
||||
if (classType != null) {
|
||||
for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(classType)) {
|
||||
allowUncheckedConversions &= parameter.getExtendsListTypes().length == 0;
|
||||
allowUncheckedConversions &= parameter.getExtendsListTypes().length == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,13 +412,14 @@ public class GenericsHighlightUtil {
|
||||
IntentionAction fix = QUICK_FIX_FACTORY.createExtendsListFix(aClass, type, false);
|
||||
QuickFixAction.registerQuickFixAction(errorResult, fix, null);
|
||||
}
|
||||
if (errorResult == null && JavaVersionService.getInstance().isAtLeast(referenceList, JavaSdkVersion.JDK_1_7) &&
|
||||
if (errorResult == null && JavaVersionService.getInstance().isAtLeast(referenceList, JavaSdkVersion.JDK_1_7) &&
|
||||
referenceElements.length > 1) {
|
||||
//todo suppress erased methods which come from the same class
|
||||
return checkOverrideEquivalentMethods(aClass);
|
||||
}
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
public static HighlightInfo checkInterfaceMultipleInheritance(PsiClass aClass) {
|
||||
if (aClass instanceof PsiTypeParameter) return null;
|
||||
final PsiClassType[] types = aClass.getSuperTypes();
|
||||
@@ -466,7 +475,7 @@ public class GenericsHighlightUtil {
|
||||
PsiManager manager = aClass.getManager();
|
||||
Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods =
|
||||
new THashMap<MethodSignature, MethodSignatureBackedByPsiMethod>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY);
|
||||
|
||||
|
||||
for (HierarchicalMethodSignature signature : signaturesWithSupers) {
|
||||
HighlightInfo info = checkSameErasureNotSubSignatureInner(signature, manager, aClass, sameErasureMethods);
|
||||
if (info != null) return info;
|
||||
@@ -529,7 +538,8 @@ public class GenericsHighlightUtil {
|
||||
if (checkEqualsSuper && atLeast17) {
|
||||
if (retErasure1 != null && retErasure2 != null) {
|
||||
differentReturnTypeErasure = !TypeConversionUtil.isAssignable(retErasure1, retErasure2);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
differentReturnTypeErasure = !(retErasure1 == null && retErasure2 == null);
|
||||
}
|
||||
}
|
||||
@@ -565,10 +575,10 @@ public class GenericsHighlightUtil {
|
||||
|
||||
private static HighlightInfo getSameErasureMessage(final boolean sameClass, final PsiMethod method, final PsiMethod superMethod,
|
||||
TextRange textRange) {
|
||||
@NonNls final String key = sameClass ? "generics.methods.have.same.erasure" :
|
||||
method.hasModifierProperty(PsiModifier.STATIC) ?
|
||||
"generics.methods.have.same.erasure.hide" :
|
||||
"generics.methods.have.same.erasure.override";
|
||||
@NonNls final String key = sameClass ? "generics.methods.have.same.erasure" :
|
||||
method.hasModifierProperty(PsiModifier.STATIC) ?
|
||||
"generics.methods.have.same.erasure.hide" :
|
||||
"generics.methods.have.same.erasure.override";
|
||||
String description = JavaErrorMessages.message(key, HighlightMethodUtil.createClashMethodMessage(method, superMethod, !sameClass));
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description);
|
||||
}
|
||||
@@ -650,7 +660,8 @@ public class GenericsHighlightUtil {
|
||||
if (isRawToGeneric(lType, type)) return true;
|
||||
}
|
||||
return false;
|
||||
} else if (lType instanceof PsiIntersectionType) {
|
||||
}
|
||||
else if (lType instanceof PsiIntersectionType) {
|
||||
for (PsiType type : ((PsiIntersectionType)lType).getConjuncts()) {
|
||||
if (isRawToGeneric(type, rType)) return true;
|
||||
}
|
||||
@@ -672,7 +683,9 @@ public class GenericsHighlightUtil {
|
||||
PsiSubstitutor rSubstitutor = rResolveResult.getSubstitutor();
|
||||
if (lClass == null || rClass == null) return false;
|
||||
if (lClass instanceof PsiTypeParameter &&
|
||||
!InheritanceUtil.isInheritorOrSelf(rClass, lClass, true)) return true;
|
||||
!InheritanceUtil.isInheritorOrSelf(rClass, lClass, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!lClass.getManager().areElementsEquivalent(lClass, rClass)) {
|
||||
if (lClass.isInheritor(rClass, true)) {
|
||||
@@ -698,7 +711,7 @@ public class GenericsHighlightUtil {
|
||||
PsiType rTypeArg = rSubstitutor.substituteWithBoundsPromotion(rParameter);
|
||||
if (lTypeArg == null) continue;
|
||||
if (rTypeArg == null) {
|
||||
if (lTypeArg instanceof PsiWildcardType && ((PsiWildcardType) lTypeArg).getBound() == null) {
|
||||
if (lTypeArg instanceof PsiWildcardType && ((PsiWildcardType)lTypeArg).getBound() == null) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
@@ -922,7 +935,7 @@ public class GenericsHighlightUtil {
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
final PsiTypeParameter typeParameter1 = typeParameters[i];
|
||||
String name1 = typeParameter1.getName();
|
||||
for (int j = i+1; j < typeParameters.length; j++) {
|
||||
for (int j = i + 1; j < typeParameters.length; j++) {
|
||||
final PsiTypeParameter typeParameter2 = typeParameters[j];
|
||||
String name2 = typeParameter2.getName();
|
||||
if (Comparing.strEqual(name1, name2)) {
|
||||
@@ -937,7 +950,7 @@ public class GenericsHighlightUtil {
|
||||
@Nullable
|
||||
public static Collection<HighlightInfo> checkCatchParameterIsClass(PsiParameter parameter) {
|
||||
if (!(parameter.getDeclarationScope() instanceof PsiCatchSection)) return null;
|
||||
final Collection<HighlightInfo> result = Lists.newArrayList();
|
||||
final Collection<HighlightInfo> result = CollectionFactory.arrayList();
|
||||
|
||||
final List<PsiTypeElement> typeElements = PsiUtil.getParameterTypeElements(parameter);
|
||||
for (PsiTypeElement typeElement : typeElements) {
|
||||
@@ -975,12 +988,12 @@ public class GenericsHighlightUtil {
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("illegal.generic.type.for.instanceof"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final PsiType[] parameters = ref.getTypeParameters();
|
||||
for (PsiType parameterType : parameters) {
|
||||
if (parameterType != null &&
|
||||
!(parameterType instanceof PsiWildcardType && ((PsiWildcardType)parameterType).getBound() == null)) {
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("illegal.generic.type.for.instanceof"));
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("illegal.generic.type.for.instanceof"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1057,7 +1070,6 @@ public class GenericsHighlightUtil {
|
||||
}
|
||||
|
||||
|
||||
|
||||
LOG.assertTrue(varParameter.isVarArgs());
|
||||
final PsiEllipsisType ellipsisType = (PsiEllipsisType)varParameter.getType();
|
||||
final PsiType componentType = ellipsisType.getComponentType();
|
||||
@@ -1099,14 +1111,15 @@ public class GenericsHighlightUtil {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (lastArg instanceof PsiMethodCallExpression) {
|
||||
}
|
||||
else if (lastArg instanceof PsiMethodCallExpression) {
|
||||
if (lastArg.getType() instanceof PsiArrayType) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = parametersCount - 1; i < args.length; i++) {
|
||||
if (!isReifiableType(resolveResult.getSubstitutor().substitute(args[i].getType()))){
|
||||
if (!isReifiableType(resolveResult.getSubstitutor().substitute(args[i].getType()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1156,7 +1169,8 @@ public class GenericsHighlightUtil {
|
||||
}
|
||||
|
||||
static void checkEnumConstantForConstructorProblems(PsiEnumConstant enumConstant, final HighlightInfoHolder holder) {
|
||||
PsiClass containingClass = enumConstant.getContainingClass(); if (enumConstant.getInitializingClass() == null) {
|
||||
PsiClass containingClass = enumConstant.getContainingClass();
|
||||
if (enumConstant.getInitializingClass() == null) {
|
||||
HighlightInfo highlightInfo = HighlightClassUtil.checkInstantiationOfAbstractClass(containingClass, enumConstant.getNameIdentifier());
|
||||
if (highlightInfo != null) {
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createImplementMethodsFix(enumConstant));
|
||||
@@ -1233,8 +1247,9 @@ public class GenericsHighlightUtil {
|
||||
PsiElement parent = refParamList.getParent();
|
||||
if (parent instanceof PsiJavaCodeReferenceElement) {
|
||||
resolveResult = ((PsiJavaCodeReferenceElement)parent).advancedResolve(false);
|
||||
} else if (parent instanceof PsiCallExpression) {
|
||||
resolveResult = ((PsiCallExpression)parent).resolveMethodGenerics();
|
||||
}
|
||||
else if (parent instanceof PsiCallExpression) {
|
||||
resolveResult = ((PsiCallExpression)parent).resolveMethodGenerics();
|
||||
}
|
||||
if (resolveResult != null) {
|
||||
PsiElement element = resolveResult.getElement();
|
||||
@@ -1257,12 +1272,13 @@ public class GenericsHighlightUtil {
|
||||
|
||||
public static HighlightInfo checkCannotInheritFromEnum(PsiClass superClass, PsiElement elementToHighlight) {
|
||||
HighlightInfo errorResult = null;
|
||||
if (Comparing.strEqual("java.lang.Enum",superClass.getQualifiedName())) {
|
||||
if (Comparing.strEqual("java.lang.Enum", superClass.getQualifiedName())) {
|
||||
String message = JavaErrorMessages.message("classes.extends.enum");
|
||||
errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, elementToHighlight, message);
|
||||
}
|
||||
return errorResult;
|
||||
}
|
||||
|
||||
public static HighlightInfo checkGenericCannotExtendException(PsiReferenceList list) {
|
||||
PsiElement parent = list.getParent();
|
||||
if (!(parent instanceof PsiClass)) return null;
|
||||
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.CodeInsightUtilBase;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Danila Ponomarenko
|
||||
*/
|
||||
public class ChangeClassSignatureFromUsageFix extends BaseIntentionAction {
|
||||
private final PsiClass myClass;
|
||||
private final PsiReferenceParameterList myParameterList;
|
||||
|
||||
public ChangeClassSignatureFromUsageFix(@NotNull PsiClass aClass,
|
||||
@NotNull PsiReferenceParameterList parameterList) {
|
||||
myClass = aClass;
|
||||
myParameterList = parameterList;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return QuickFixBundle.message("change.class.signature.family");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
if (!myClass.isValid() || !myParameterList.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myClass.getTypeParameters().length >= myParameterList.getTypeArguments().length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiTypeParameterList classTypeParameterList = myClass.getTypeParameterList();
|
||||
if (classTypeParameterList == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
Map<PsiTypeParameter, Boolean> typeParameterBooleanMap = createTypeParameters(
|
||||
factory,
|
||||
classTypeParameterList.getTypeParameters(),
|
||||
myParameterList.getTypeParameterElements()
|
||||
);
|
||||
|
||||
if (isAddOneTypeParameter(typeParameterBooleanMap)) {
|
||||
setText(QuickFixBundle.message("add.type.parameter.text", myClass.getName()));
|
||||
}
|
||||
else {
|
||||
setText(QuickFixBundle.message("change.class.signature.text", myClass.getName(), parametersToSignatureText(typeParameterBooleanMap)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isAddOneTypeParameter(@NotNull Map<PsiTypeParameter, Boolean> map) {
|
||||
boolean oneParameter = false;
|
||||
for (Boolean b : map.values()) {
|
||||
if (b == Boolean.TRUE) {
|
||||
if (oneParameter) {
|
||||
return false;
|
||||
}
|
||||
oneParameter = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String parametersToSignatureText(@NotNull Map<PsiTypeParameter, Boolean> map) {
|
||||
final StringBuilder result = new StringBuilder("<");
|
||||
for (Map.Entry<PsiTypeParameter, Boolean> e : map.entrySet()) {
|
||||
final String text = e.getKey().getText();
|
||||
if (e.getValue() == Boolean.TRUE) {
|
||||
result.append("<b>").append(text).append("</b>");
|
||||
}
|
||||
else {
|
||||
result.append(text);
|
||||
}
|
||||
result.append(", ");
|
||||
}
|
||||
|
||||
final int lng = result.length();
|
||||
result.delete(lng - 2, lng);
|
||||
|
||||
return result.append(">").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
|
||||
|
||||
final PsiTypeParameterList classTypeParameterList = myClass.getTypeParameterList();
|
||||
if (classTypeParameterList == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
final PsiElement newTypeParameterList = classTypeParameterList.replace(
|
||||
createTypeParameterList(
|
||||
factory,
|
||||
classTypeParameterList.getTypeParameters(),
|
||||
myParameterList.getTypeParameterElements()
|
||||
)
|
||||
);
|
||||
|
||||
navigateTo(newTypeParameterList);
|
||||
}
|
||||
|
||||
private static void navigateTo(@NotNull PsiElement element) {
|
||||
element.getContainingFile().navigate(false);
|
||||
final Editor editor = PsiUtilBase.findEditor(element);
|
||||
if (editor == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
editor.getCaretModel().moveToOffset(element.getTextRange().getStartOffset());
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiTypeParameterList createTypeParameterList(@NotNull PsiElementFactory factory,
|
||||
@NotNull PsiTypeParameter[] classTypeParameters,
|
||||
@NotNull PsiTypeElement[] typeElements) {
|
||||
final PsiTypeParameterList result = factory.createTypeParameterList();
|
||||
for (PsiTypeParameter p : createTypeParameters(factory, classTypeParameters, typeElements).keySet()) {
|
||||
result.add(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<PsiTypeParameter, Boolean> createTypeParameters(@NotNull PsiElementFactory factory,
|
||||
@NotNull PsiTypeParameter[] classTypeParameters,
|
||||
@NotNull PsiTypeElement[] typeElements) {
|
||||
final LinkedHashMap<PsiTypeParameter, Boolean> result = new LinkedHashMap<PsiTypeParameter, Boolean>();
|
||||
final TypeParameterNameSuggester suggester = new TypeParameterNameSuggester(classTypeParameters);
|
||||
|
||||
final Queue<PsiTypeParameter> classTypeParametersQueue = new LinkedList<PsiTypeParameter>(Arrays.asList(classTypeParameters));
|
||||
for (PsiTypeElement typeElement : typeElements) {
|
||||
if (!classTypeParametersQueue.isEmpty()) {
|
||||
final PsiTypeParameter typeParameter = classTypeParametersQueue.peek();
|
||||
|
||||
if (isAssignable(typeParameter, typeElement.getType())) {
|
||||
result.put(typeParameter, false);
|
||||
classTypeParametersQueue.poll();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
result.put(toTypeParameter(factory, suggester, typeElement), true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isAssignable(@NotNull PsiTypeParameter typeParameter, @NotNull PsiType type) {
|
||||
for (PsiClassType t : typeParameter.getExtendsListTypes()) {
|
||||
if (!t.isAssignableFrom(type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiTypeParameter toTypeParameter(@NotNull PsiElementFactory factory,
|
||||
@NotNull TypeParameterNameSuggester suggester,
|
||||
@NotNull PsiTypeElement typeElement) {
|
||||
final PsiType type = typeElement.getType();
|
||||
|
||||
return factory.createTypeParameter(suggester.suggest((PsiClassType)type), PsiClassType.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static class TypeParameterNameSuggester {
|
||||
private final Set<String> usedNames = new HashSet<String>();
|
||||
|
||||
public TypeParameterNameSuggester(@NotNull PsiTypeParameter[] typeParameters) {
|
||||
for (PsiTypeParameter p : typeParameters) {
|
||||
usedNames.add(p.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String suggestUnusedName(@NotNull String name) {
|
||||
String unusedName = name;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
if (usedNames.add(unusedName)) {
|
||||
return unusedName;
|
||||
}
|
||||
unusedName = name + ++i;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String suggest(@NotNull PsiClassType type) {
|
||||
return suggestUnusedName(type.getClassName().substring(0, 1).toUpperCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -73,7 +73,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction, HighP
|
||||
private final boolean myChangeAllUsages;
|
||||
private final int myMinUsagesNumberToShowDialog;
|
||||
ParameterInfoImpl[] myNewParametersInfo;
|
||||
private static final Logger LOG = Logger.getInstance("#" + ChangeMethodSignatureFromUsageFix.class.getName());
|
||||
private static final Logger LOG = Logger.getInstance(ChangeMethodSignatureFromUsageFix.class);
|
||||
|
||||
ChangeMethodSignatureFromUsageFix(@NotNull PsiMethod targetMethod,
|
||||
@NotNull PsiExpression[] expressions,
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
* @author ven
|
||||
*/
|
||||
public abstract class MethodArgumentFix implements IntentionAction {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.MethodArgumentFix");
|
||||
private static final Logger LOG = Logger.getInstance(MethodArgumentFix.class);
|
||||
|
||||
protected final PsiExpressionList myArgList;
|
||||
protected final int myIndex;
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Add type parameter to 'Foo'" "true"
|
||||
|
||||
class Foo<caret><T extends Integer, S> {
|
||||
|
||||
void method() {
|
||||
Foo<Integer, String> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Add type parameter to 'Foo'" "true"
|
||||
|
||||
class Foo<caret><S, T extends Integer> {
|
||||
|
||||
void method() {
|
||||
Foo<String, Integer> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "<html>Change signature of 'Foo' to 'Foo<<b>S</b>, T extends Integer, <b>S1</b>>'</html>" "true"
|
||||
|
||||
class Foo<caret><S, T extends Integer, S1> {
|
||||
|
||||
void method() {
|
||||
Foo<String, Integer, String> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Add type parameter to 'Foo'" "true"
|
||||
|
||||
class Foo<caret><T extends Integer, S, K extends Integer> {
|
||||
|
||||
void method() {
|
||||
Foo<Integer, String, Integer> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Add type parameter to 'Foo'" "true"
|
||||
|
||||
class Foo<caret><S> {
|
||||
|
||||
void method() {
|
||||
Foo<String> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Add type parameter to 'Foo'" "true"
|
||||
|
||||
class Foo<T extends Integer> {
|
||||
|
||||
void method() {
|
||||
Foo<Integer, St<caret>ring> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Add type parameter to 'Foo'" "true"
|
||||
|
||||
class Foo<T extends Integer> {
|
||||
|
||||
void method() {
|
||||
Foo<St<caret>ring, Integer> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "<html>Change signature of 'Foo' to 'Foo<<b>S</b>, T extends Integer, <b>S1</b>>'</html>" "true"
|
||||
|
||||
class Foo<T extends Integer> {
|
||||
|
||||
void method() {
|
||||
Foo<String, Integer, St<caret>ring> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Add type parameter to 'Foo'" "true"
|
||||
|
||||
class Foo<T extends Integer, K extends Integer> {
|
||||
|
||||
void method() {
|
||||
Foo<Integer, St<caret>ring, Integer> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Add type parameter to 'Foo'" "true"
|
||||
|
||||
class Foo {
|
||||
|
||||
void method() {
|
||||
Foo<St<caret>ring> foo = new Foo();
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.quickFix;
|
||||
|
||||
/**
|
||||
* @author Danila Ponomarenko
|
||||
*/
|
||||
public class ChangeClassSignatureFromUsageTest extends LightQuickFix15TestCase {
|
||||
public void test() throws Exception { doAllTests(); }
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/changeClassSignatureFromUsage";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ cast.single.parameter.text=Cast parameter to ''{0}''
|
||||
add.type.arguments.text=Add explicit type arguments to {0, choice, 1#1st|2#2nd|3#3rd|4#{0,number}th} argument
|
||||
add.type.arguments.single.argument.text=Add explicit type arguments
|
||||
|
||||
change.class.signature.text=<html>Change signature of ''{0}'' to ''{0}{1}''</html>
|
||||
add.type.parameter.text=Add type parameter to ''{0}''
|
||||
change.class.signature.family=Change class signature
|
||||
|
||||
uidesigner.change.bound.field.type=Change bound field type
|
||||
cannot.change.field.exception=Cannot change field ''{0}'' type.\nReason: {1}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user