private boolean isOverridden( PsiClass inheritor, PsiMethod method, PsiMethod superMethod, PsiClass superInterface) { // calculate substitutor of containingClass --> inheritor PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor( myContainingClass, inheritor, PsiSubstitutor.EMPTY); // calculate substitutor of inheritor --> superInterface substitutor = TypeConversionUtil.getSuperClassSubstitutor(superInterface, inheritor, substitutor); return MethodSignatureUtil.isSubsignature( superMethod.getSignature(substitutor), method.getSignature(PsiSubstitutor.EMPTY)); }
private static void addDefaultConstructor( JavaChangeInfo changeInfo, PsiClass aClass, final UsageInfo[] usages) throws IncorrectOperationException { if (!(aClass instanceof PsiAnonymousClass)) { PsiElementFactory factory = JavaPsiFacade.getElementFactory(aClass.getProject()); PsiMethod defaultConstructor = factory.createMethodFromText(aClass.getName() + "(){}", aClass); defaultConstructor = (PsiMethod) CodeStyleManager.getInstance(aClass.getProject()).reformat(defaultConstructor); defaultConstructor = (PsiMethod) aClass.add(defaultConstructor); PsiUtil.setModifierProperty( defaultConstructor, VisibilityUtil.getVisibilityModifier(aClass.getModifierList()), true); addSuperCall(changeInfo, defaultConstructor, null, usages); } else { final PsiElement parent = aClass.getParent(); if (parent instanceof PsiNewExpression) { final PsiExpressionList argumentList = ((PsiNewExpression) parent).getArgumentList(); final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY); fixActualArgumentsList(argumentList, changeInfo, true, substitutor); } } }
private static PsiSubstitutor calculateSubstitutor( PsiMethod derivedMethod, PsiMethod baseMethod) { PsiSubstitutor substitutor; if (derivedMethod.getManager().areElementsEquivalent(derivedMethod, baseMethod)) { substitutor = PsiSubstitutor.EMPTY; } else { final PsiClass baseClass = baseMethod.getContainingClass(); final PsiClass derivedClass = derivedMethod.getContainingClass(); if (baseClass != null && derivedClass != null && InheritanceUtil.isInheritorOrSelf(derivedClass, baseClass, true)) { final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor( baseClass, derivedClass, PsiSubstitutor.EMPTY); final MethodSignature superMethodSignature = baseMethod.getSignature(superClassSubstitutor); final MethodSignature methodSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY); final PsiSubstitutor superMethodSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor( methodSignature, superMethodSignature); substitutor = superMethodSubstitutor != null ? superMethodSubstitutor : superClassSubstitutor; } else { substitutor = PsiSubstitutor.EMPTY; } } return substitutor; }
@NotNull private static List<PsiMethod> findMethodsBySignature( @NotNull PsiClass aClass, @NotNull PsiMethod patternMethod, boolean checkBases, boolean stopOnFirst) { final PsiMethod[] methodsByName = aClass.findMethodsByName(patternMethod.getName(), checkBases); if (methodsByName.length == 0) return Collections.emptyList(); final List<PsiMethod> methods = new SmartList<PsiMethod>(); final MethodSignature patternSignature = patternMethod.getSignature(PsiSubstitutor.EMPTY); for (final PsiMethod method : methodsByName) { final PsiClass superClass = method.getContainingClass(); final PsiSubstitutor substitutor; if (checkBases && !aClass.equals(superClass)) { substitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); } else { substitutor = PsiSubstitutor.EMPTY; } final MethodSignature signature = method.getSignature(substitutor); if (signature.equals(patternSignature)) { methods.add(method); if (stopOnFirst) { break; } } } return methods; }
@Nullable private static PsiMethod doFindMethodInSuperClassBySignatureInDerived( @NotNull PsiClass superClass, @NotNull PsiSubstitutor superSubstitutor, @NotNull MethodSignature signature, final boolean checkDeep) { final String name = signature.getName(); final PsiMethod[] methods = superClass.findMethodsByName(name, false); for (final PsiMethod method : methods) { if (isSubsignature(method.getSignature(superSubstitutor), signature)) { return method; } } if (checkDeep) { final PsiClass clazz = superClass.getSuperClass(); if (clazz != null && clazz != superClass) { PsiSubstitutor substitutor1 = TypeConversionUtil.getSuperClassSubstitutor(clazz, superClass, superSubstitutor); return doFindMethodInSuperClassBySignatureInDerived(clazz, substitutor1, signature, true); } } return null; }
private static boolean isReturnTypeIsMoreSpecificThan( @NotNull HierarchicalMethodSignature thisSig, @NotNull HierarchicalMethodSignature thatSig) { PsiType thisRet = thisSig.getSubstitutor().substitute(thisSig.getMethod().getReturnType()); PsiType thatRet = thatSig.getSubstitutor().substitute(thatSig.getMethod().getReturnType()); return thatRet != null && thisRet != null && !thatRet.equals(thisRet) && TypeConversionUtil.isAssignable(thatRet, thisRet, false); }
private static boolean isBoxingHappened( PsiType argType, PsiType parameterType, @NotNull LanguageLevel languageLevel) { if (argType == null) return parameterType instanceof PsiPrimitiveType; if (parameterType instanceof PsiClassType) { parameterType = ((PsiClassType) parameterType).setLanguageLevel(languageLevel); } return TypeConversionUtil.boxingConversionApplicable(parameterType, argType); }
@Nullable private static MethodSignature getSignatureForInheritor( @NotNull PsiMethod methodFromSuperClass, @NotNull GrTypeDefinition inheritor) { final PsiClass clazz = methodFromSuperClass.getContainingClass(); if (clazz == null) return null; PsiSubstitutor superSubstitutor = TypeConversionUtil.getClassSubstitutor(clazz, inheritor, PsiSubstitutor.EMPTY); if (superSubstitutor == null) return null; return methodFromSuperClass.getSignature(superSubstitutor); }
static boolean isInheritorOrSelf(PsiMethod inheritorCandidate, PsiMethod base) { PsiClass aClass = inheritorCandidate.getContainingClass(); PsiClass bClass = base.getContainingClass(); if (aClass == null || bClass == null) return false; PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(bClass, aClass, PsiSubstitutor.EMPTY); return substitutor != null && MethodSignatureUtil.findMethodBySignature( bClass, inheritorCandidate.getSignature(substitutor), false) == base; }
@Nullable public static PsiMethod findMethodInSuperClassBySignatureInDerived( @NotNull final PsiClass aClass, @NotNull final PsiClass superClass, @NotNull MethodSignature signature, final boolean checkDeep) { PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); return doFindMethodInSuperClassBySignatureInDerived( superClass, superSubstitutor, signature, checkDeep); }
public static PsiType[] getErasedParameterTypes(MethodSignature signature) { PsiType[] parameterTypes = signature.getParameterTypes(); if (parameterTypes.length == 0) return PsiType.EMPTY_ARRAY; PsiSubstitutor substitutor = signature.getSubstitutor(); PsiType[] erasedTypes = new PsiType[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { erasedTypes[i] = TypeConversionUtil.erasure(substitutor.substitute(parameterTypes[i]), substitutor); } return erasedTypes; }
public static boolean isSuperMethod( @NotNull PsiMethod superMethodCandidate, @NotNull PsiMethod derivedMethod) { PsiClass superClassCandidate = superMethodCandidate.getContainingClass(); PsiClass derivedClass = derivedMethod.getContainingClass(); if (derivedClass == null || superClassCandidate == null) return false; if (!derivedClass.isInheritor(superClassCandidate, true)) return false; final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor( superClassCandidate, derivedClass, PsiSubstitutor.EMPTY); final MethodSignature superSignature = superMethodCandidate.getSignature(superSubstitutor); final MethodSignature derivedSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY); return isSubsignature(superSignature, derivedSignature); }
@Override public int computeHashCode(final MethodSignature signature) { int result = signature.isConstructor() ? 0 : signature.getName().hashCode(); PsiType[] parameterTypes = signature.getParameterTypes(); result += 37 * parameterTypes.length; PsiType firstParamType = parameterTypes.length == 0 ? null : parameterTypes[0]; if (firstParamType != null) { firstParamType = TypeConversionUtil.erasure(firstParamType, signature.getSubstitutor()); assert firstParamType != null : parameterTypes[0]; result = 31 * result + firstParamType.hashCode(); } return result; }
private static AllowedValues getAllowedValuesFromMagic( @NotNull PsiModifierListOwner element, @NotNull PsiType type, PsiAnnotation magic) { if (magic == null) return null; PsiAnnotationMemberValue[] allowedValues; final boolean canBeOred; if (TypeConversionUtil.getTypeRank(type) <= TypeConversionUtil.LONG_RANK) { PsiAnnotationMemberValue intValues = magic.findAttributeValue("intValues"); allowedValues = intValues instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue) intValues).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY; if (allowedValues.length == 0) { PsiAnnotationMemberValue orValue = magic.findAttributeValue("flags"); allowedValues = orValue instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue) orValue).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY; canBeOred = true; } else { canBeOred = false; } } else if (type.equals( PsiType.getJavaLangString( element.getManager(), GlobalSearchScope.allScope(element.getProject())))) { PsiAnnotationMemberValue strValuesAttr = magic.findAttributeValue("stringValues"); allowedValues = strValuesAttr instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue) strValuesAttr).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY; canBeOred = false; } else { return null; // other types not supported } if (allowedValues.length != 0) { return new AllowedValues(allowedValues, canBeOred); } // last resort: try valuesFromClass PsiAnnotationMemberValue[] values = readFromClass("valuesFromClass", magic, type); boolean ored = false; if (values == null) { values = readFromClass("flagsFromClass", magic, type); ored = true; } if (values == null) return null; return new AllowedValues(values, ored); }
public static boolean isSubsignature( MethodSignature superSignature, MethodSignature subSignature) { if (subSignature == superSignature) return true; if (!areSignaturesEqualLightweight(superSignature, subSignature)) return false; PsiSubstitutor unifyingSubstitutor = getSuperMethodSignatureSubstitutor(subSignature, superSignature); if (checkSignaturesEqualInner(superSignature, subSignature, unifyingSubstitutor)) return true; if (subSignature.getTypeParameters().length > 0) return false; final PsiType[] subParameterTypes = subSignature.getParameterTypes(); final PsiType[] superParameterTypes = superSignature.getParameterTypes(); for (int i = 0; i < subParameterTypes.length; i++) { PsiType type1 = subParameterTypes[i]; PsiType type2 = TypeConversionUtil.erasure(superParameterTypes[i]); if (!Comparing.equal(type1, type2)) return false; } return true; }
@Nullable public static PsiMethod findMethodBySuperMethod( @NotNull PsiClass aClass, @NotNull PsiMethod method, final boolean checkBases) { List<Pair<PsiMethod, PsiSubstitutor>> pairs = aClass.findMethodsAndTheirSubstitutorsByName(method.getName(), checkBases); for (Pair<PsiMethod, PsiSubstitutor> pair : pairs) { PsiMethod candidate = pair.first; PsiSubstitutor substitutor = pair.second; MethodSignature candidateSignature = candidate.getSignature(substitutor); final PsiClass methodClass = method.getContainingClass(); final PsiClass candidateClass = candidate.getContainingClass(); if (methodClass == null || candidateClass == null) continue; PsiSubstitutor superSubstitutor = TypeConversionUtil.getClassSubstitutor(methodClass, candidateClass, substitutor); if (superSubstitutor == null) continue; MethodSignature superSignature = method.getSignature(superSubstitutor); if (isSubsignature(superSignature, candidateSignature)) return candidate; } return null; }
@NotNull private static PsiSubstitutor calculateMethodSubstitutor( @NotNull PsiTypeParameter[] typeParameters, @NotNull PsiMethod method, @NotNull PsiSubstitutor siteSubstitutor, @NotNull PsiType[] types1, @NotNull PsiType[] types2, @NotNull LanguageLevel languageLevel) { PsiSubstitutor substitutor = PsiResolveHelper.SERVICE .getInstance(method.getProject()) .inferTypeArguments(typeParameters, types1, types2, languageLevel); for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(method)) { ProgressManager.checkCanceled(); LOG.assertTrue(typeParameter != null); if (!substitutor.getSubstitutionMap().containsKey(typeParameter)) { PsiType type = siteSubstitutor.substitute(typeParameter); if (type instanceof PsiClassType && typeParameter.getOwner() == method) { final PsiClass aClass = ((PsiClassType) type).resolve(); if (aClass instanceof PsiTypeParameter && ((PsiTypeParameter) aClass).getOwner() == method) { type = TypeConversionUtil.erasure(type, siteSubstitutor); } } substitutor = substitutor.put(typeParameter, type); } else { final PsiType type = substitutor.substitute(typeParameter); if (type instanceof PsiClassType) { final PsiClass aClass = ((PsiClassType) type).resolve(); if (aClass instanceof PsiTypeParameter) { substitutor = substitutor.put( typeParameter, JavaPsiFacade.getElementFactory(aClass.getProject()) .createType(aClass, siteSubstitutor)); } } } } return substitutor; }
private static void processConstructor(GrMethod constructor, JavaChangeInfo changeInfo) { final PsiClass containingClass = constructor.getContainingClass(); final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor( baseClass, containingClass, PsiSubstitutor.EMPTY); GrOpenBlock block = constructor.getBlock(); GrConstructorInvocation invocation = GroovyPsiElementFactory.getInstance(constructor.getProject()) .createConstructorInvocation("super()"); invocation = (GrConstructorInvocation) block.addStatementBefore(invocation, getFirstStatement(block)); processMethodUsage( invocation.getInvokedExpression(), changeInfo, changeInfo.isParameterSetOrOrderChanged() || changeInfo.isParameterNamesChanged(), changeInfo.isExceptionSetChanged(), GrClosureSignatureUtil.ArgInfo.<PsiElement>empty_array(), substitutor); }
private static void addSuperCall( JavaChangeInfo changeInfo, PsiMethod constructor, PsiMethod callee, final UsageInfo[] usages) throws IncorrectOperationException { final PsiElementFactory factory = JavaPsiFacade.getElementFactory(constructor.getProject()); PsiExpressionStatement superCall = (PsiExpressionStatement) factory.createStatementFromText("super();", constructor); PsiCodeBlock body = constructor.getBody(); assert body != null; PsiStatement[] statements = body.getStatements(); if (statements.length > 0) { superCall = (PsiExpressionStatement) body.addBefore(superCall, statements[0]); } else { superCall = (PsiExpressionStatement) body.add(superCall); } PsiMethodCallExpression callExpression = (PsiMethodCallExpression) superCall.getExpression(); final PsiClass aClass = constructor.getContainingClass(); final PsiClass baseClass = changeInfo.getMethod().getContainingClass(); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, aClass, PsiSubstitutor.EMPTY); processMethodUsage( callExpression.getMethodExpression(), changeInfo, true, false, callee, substitutor, usages); }
@Nullable public static String getSuspiciousMethodCallMessage( @NotNull PsiMethodCallExpression methodCall, PsiType argType, boolean reportConvertibleMethodCalls, @NotNull List<PsiMethod> patternMethods, @NotNull IntArrayList indices) { final PsiReferenceExpression methodExpression = methodCall.getMethodExpression(); final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (qualifier == null || qualifier instanceof PsiThisExpression || qualifier instanceof PsiSuperExpression) return null; if (argType instanceof PsiPrimitiveType) { argType = ((PsiPrimitiveType) argType).getBoxedType(methodCall); } if (!(argType instanceof PsiClassType)) return null; final JavaResolveResult resolveResult = methodExpression.advancedResolve(false); PsiMethod calleeMethod = (PsiMethod) resolveResult.getElement(); if (calleeMethod == null) return null; PsiMethod contextMethod = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class); //noinspection SynchronizationOnLocalVariableOrMethodParameter synchronized (patternMethods) { if (patternMethods.isEmpty()) { setupPatternMethods( methodCall.getManager(), methodCall.getResolveScope(), patternMethods, indices); } } for (int i = 0; i < patternMethods.size(); i++) { PsiMethod patternMethod = patternMethods.get(i); if (!patternMethod.getName().equals(methodExpression.getReferenceName())) continue; int index = indices.get(i); // we are in collections method implementation if (contextMethod != null && isInheritorOrSelf(contextMethod, patternMethod)) return null; final PsiClass calleeClass = calleeMethod.getContainingClass(); PsiSubstitutor substitutor = resolveResult.getSubstitutor(); final PsiClass patternClass = patternMethod.getContainingClass(); assert patternClass != null; assert calleeClass != null; substitutor = TypeConversionUtil.getClassSubstitutor(patternClass, calleeClass, substitutor); if (substitutor == null) continue; if (!patternMethod .getSignature(substitutor) .equals(calleeMethod.getSignature(PsiSubstitutor.EMPTY))) continue; PsiTypeParameter[] typeParameters = patternClass.getTypeParameters(); if (typeParameters.length <= index) return null; final PsiTypeParameter typeParameter = typeParameters[index]; PsiType typeParamMapping = substitutor.substitute(typeParameter); if (typeParamMapping == null) return null; PsiParameter[] parameters = patternMethod.getParameterList().getParameters(); if (parameters.length == 1 && "removeAll".equals(patternMethod.getName())) { PsiType paramType = parameters[0].getType(); if (InheritanceUtil.isInheritor(paramType, CommonClassNames.JAVA_UTIL_COLLECTION)) { PsiType qualifierType = qualifier.getType(); if (qualifierType != null) { final PsiType itemType = JavaGenericsUtil.getCollectionItemType(argType, calleeMethod.getResolveScope()); final PsiType qualifierItemType = JavaGenericsUtil.getCollectionItemType( qualifierType, calleeMethod.getResolveScope()); if (qualifierItemType != null && itemType != null && !qualifierItemType.isAssignableFrom(itemType)) { return InspectionsBundle.message( "inspection.suspicious.collections.method.calls.problem.descriptor", PsiFormatUtil.formatType(qualifierType, 0, PsiSubstitutor.EMPTY), PsiFormatUtil.formatType(itemType, 0, PsiSubstitutor.EMPTY)); } } return null; } } String message = null; if (typeParamMapping instanceof PsiCapturedWildcardType) { typeParamMapping = ((PsiCapturedWildcardType) typeParamMapping).getWildcard(); } if (!typeParamMapping.isAssignableFrom(argType)) { if (typeParamMapping.isConvertibleFrom(argType)) { if (reportConvertibleMethodCalls) { message = InspectionsBundle.message( "inspection.suspicious.collections.method.calls.problem.descriptor1", PsiFormatUtil.formatMethod( calleeMethod, substitutor, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_CONTAINING_CLASS, PsiFormatUtilBase.SHOW_TYPE)); } } else { PsiType qualifierType = qualifier.getType(); if (qualifierType != null) { message = InspectionsBundle.message( "inspection.suspicious.collections.method.calls.problem.descriptor", PsiFormatUtil.formatType(qualifierType, 0, PsiSubstitutor.EMPTY), PsiFormatUtil.formatType(argType, 0, PsiSubstitutor.EMPTY)); } } } return message; } return null; }
private NamesByExprInfo suggestVariableNameByExpressionPlace( PsiExpression expr, final VariableKind variableKind, boolean correctKeywords) { if (expr.getParent() instanceof PsiExpressionList) { PsiExpressionList list = (PsiExpressionList) expr.getParent(); PsiElement listParent = list.getParent(); PsiSubstitutor subst = PsiSubstitutor.EMPTY; PsiMethod method = null; if (listParent instanceof PsiMethodCallExpression) { final JavaResolveResult resolveResult = ((PsiMethodCallExpression) listParent).getMethodExpression().advancedResolve(false); method = (PsiMethod) resolveResult.getElement(); subst = resolveResult.getSubstitutor(); } else { if (listParent instanceof PsiAnonymousClass) { listParent = listParent.getParent(); } if (listParent instanceof PsiNewExpression) { method = ((PsiNewExpression) listParent).resolveConstructor(); } } if (method != null) { final PsiElement navElement = method.getNavigationElement(); if (navElement instanceof PsiMethod) { method = (PsiMethod) navElement; } PsiExpression[] expressions = list.getExpressions(); int index = -1; for (int i = 0; i < expressions.length; i++) { if (expressions[i] == expr) { index = i; break; } } PsiParameter[] parameters = method.getParameterList().getParameters(); if (index < parameters.length) { String name = parameters[index].getName(); if (name != null && TypeConversionUtil.areTypesAssignmentCompatible( subst.substitute(parameters[index].getType()), expr)) { name = variableNameToPropertyName(name, VariableKind.PARAMETER); String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords); if (expressions.length == 1) { final String methodName = method.getName(); String[] words = NameUtil.nameToWords(methodName); if (words.length > 0) { final String firstWord = words[0]; if (SET_PREFIX.equals(firstWord)) { final String propertyName = methodName.substring(firstWord.length()); final String[] setterNames = getSuggestionsByName(propertyName, variableKind, false, correctKeywords); names = ArrayUtil.mergeArrays(names, setterNames); } } } return new NamesByExprInfo(name, names); } } } } else if (expr.getParent() instanceof PsiAssignmentExpression && variableKind == VariableKind.PARAMETER) { final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) expr.getParent(); if (expr == assignmentExpression.getRExpression()) { final PsiExpression leftExpression = assignmentExpression.getLExpression(); if (leftExpression instanceof PsiReferenceExpression && ((PsiReferenceExpression) leftExpression).getQualifier() == null) { String name = leftExpression.getText(); if (name != null) { final PsiElement resolve = ((PsiReferenceExpression) leftExpression).resolve(); if (resolve instanceof PsiVariable) { name = variableNameToPropertyName(name, getVariableKind((PsiVariable) resolve)); } String[] names = getSuggestionsByName(name, variableKind, false, correctKeywords); return new NamesByExprInfo(name, names); } } } } return new NamesByExprInfo(null, ArrayUtil.EMPTY_STRING_ARRAY); }
private static boolean provablyDistinct(PsiType type1, PsiType type2, int level) { if (type1 instanceof PsiClassType && ((PsiClassType) type1).resolve() instanceof PsiTypeParameter) return false; if (type2 instanceof PsiClassType && ((PsiClassType) type2).resolve() instanceof PsiTypeParameter) return false; if (type1 instanceof PsiWildcardType) { if (type2 instanceof PsiWildcardType) { return provablyDistinct((PsiWildcardType) type1, (PsiWildcardType) type2); } if (type2 instanceof PsiCapturedWildcardType) { return ((PsiWildcardType) type1).isExtends() && level > 0 || provablyDistinct( (PsiWildcardType) type1, ((PsiCapturedWildcardType) type2).getWildcard()); } if (type2 instanceof PsiClassType) { final PsiClass psiClass2 = PsiUtil.resolveClassInType(type2); if (psiClass2 == null) return false; if (((PsiWildcardType) type1).isExtends()) { final PsiType extendsBound = ((PsiWildcardType) type1).getExtendsBound(); if (extendsBound instanceof PsiArrayType && proveArrayTypeDistinct( ((PsiWildcardType) type1).getManager().getProject(), (PsiArrayType) extendsBound, type2)) return true; final PsiClass boundClass1 = PsiUtil.resolveClassInType(extendsBound); if (boundClass1 == null) return false; return proveExtendsBoundsDistinct(type1, type2, boundClass1, psiClass2); } if (((PsiWildcardType) type1).isSuper()) { final PsiType superBound = ((PsiWildcardType) type1).getSuperBound(); if (superBound instanceof PsiArrayType && proveArrayTypeDistinct( ((PsiWildcardType) type1).getManager().getProject(), (PsiArrayType) superBound, type2)) return true; final PsiClass boundClass1 = PsiUtil.resolveClassInType(superBound); if (boundClass1 == null || boundClass1 instanceof PsiTypeParameter) return false; return !InheritanceUtil.isInheritorOrSelf(boundClass1, psiClass2, true); } final PsiType bound = ((PsiWildcardType) type1).getBound(); return bound != null && !bound.equals(psiClass2); } if (type2 instanceof PsiArrayType) { return proveArrayTypeDistinct( ((PsiWildcardType) type1).getManager().getProject(), (PsiArrayType) type2, type1); } } if (type1 instanceof PsiCapturedWildcardType) return provablyDistinct(((PsiCapturedWildcardType) type1).getWildcard(), type2, level); if (type2 instanceof PsiWildcardType || type2 instanceof PsiCapturedWildcardType) return provablyDistinct(type2, type1, level); final PsiClassType.ClassResolveResult classResolveResult1 = PsiUtil.resolveGenericsClassInType(type1); final PsiClassType.ClassResolveResult classResolveResult2 = PsiUtil.resolveGenericsClassInType(type2); if (Comparing.equal(TypeConversionUtil.erasure(type1), TypeConversionUtil.erasure(type2))) { final PsiSubstitutor substitutor1 = classResolveResult1.getSubstitutor(); final PsiSubstitutor substitutor2 = classResolveResult2.getSubstitutor(); for (PsiTypeParameter parameter : substitutor1.getSubstitutionMap().keySet()) { final PsiType substitutedType1 = substitutor1.substitute(parameter); final PsiType substitutedType2 = substitutor2.substitute(parameter); if (substitutedType1 == null && substitutedType2 == null) return false; if (substitutedType1 == null || substitutedType2 == null) { return true; } else { if (provablyDistinct(substitutedType1, substitutedType2, level + 1)) return true; if (substitutedType1 instanceof PsiWildcardType && !((PsiWildcardType) substitutedType1).isBounded()) return true; } } return false; } final PsiClass boundClass1 = classResolveResult1.getElement(); final PsiClass boundClass2 = classResolveResult2.getElement(); return type2 != null && type1 != null && !type1.equals(type2) && (!InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) || !InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true)); }
@NotNull private static LookupElement castQualifier( @NotNull LookupElement item, @Nullable final PsiTypeLookupItem castTypeItem, @Nullable PsiType plainQualifier, JavaCompletionProcessor processor) { if (castTypeItem == null) { return item; } if (plainQualifier != null) { Object o = item.getObject(); if (o instanceof PsiMethod) { PsiType castType = castTypeItem.getType(); if (plainQualifier instanceof PsiClassType && castType instanceof PsiClassType) { PsiMethod method = (PsiMethod) o; PsiClassType.ClassResolveResult plainResult = ((PsiClassType) plainQualifier).resolveGenerics(); PsiClass plainClass = plainResult.getElement(); if (plainClass != null && plainClass.findMethodBySignature(method, true) != null) { PsiClass castClass = ((PsiClassType) castType).resolveGenerics().getElement(); if (castClass == null || !castClass.isInheritor(plainClass, true)) { return item; } PsiSubstitutor plainSub = plainResult.getSubstitutor(); PsiSubstitutor castSub = TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType) castType); PsiType returnType = method.getReturnType(); if (method.getSignature(plainSub).equals(method.getSignature(castSub))) { PsiType typeAfterCast = toRaw(castSub.substitute(returnType)); PsiType typeDeclared = toRaw(plainSub.substitute(returnType)); if (typeAfterCast != null && typeDeclared != null && typeAfterCast.isAssignableFrom(typeDeclared) && processor.isAccessible(plainClass.findMethodBySignature(method, true))) { return item; } } } } } else if (containsMember(plainQualifier, o)) { return item; } } return LookupElementDecorator.withInsertHandler( item, new InsertHandlerDecorator<LookupElement>() { @Override public void handleInsert( InsertionContext context, LookupElementDecorator<LookupElement> item) { final Document document = context.getEditor().getDocument(); context.commitDocument(); final PsiFile file = context.getFile(); final PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset( file, context.getStartOffset(), PsiJavaCodeReferenceElement.class, false); if (ref != null) { final PsiElement qualifier = ref.getQualifier(); if (qualifier != null) { final CommonCodeStyleSettings settings = context.getCodeStyleSettings(); final String parenSpace = settings.SPACE_WITHIN_PARENTHESES ? " " : ""; document.insertString(qualifier.getTextRange().getEndOffset(), parenSpace + ")"); final String spaceWithin = settings.SPACE_WITHIN_CAST_PARENTHESES ? " " : ""; final String prefix = "(" + parenSpace + "(" + spaceWithin; final String spaceAfter = settings.SPACE_AFTER_TYPE_CAST ? " " : ""; final int exprStart = qualifier.getTextRange().getStartOffset(); document.insertString(exprStart, prefix + spaceWithin + ")" + spaceAfter); CompletionUtil.emulateInsertion(context, exprStart + prefix.length(), castTypeItem); PsiDocumentManager.getInstance(file.getProject()) .doPostponedOperationsAndUnblockDocument(document); context.getEditor().getCaretModel().moveToOffset(context.getTailOffset()); } } item.getDelegate().handleInsert(context); } }); }
private Specifics isMoreSpecific( @NotNull MethodCandidateInfo info1, @NotNull MethodCandidateInfo info2, @MethodCandidateInfo.ApplicabilityLevelConstant int applicabilityLevel, @NotNull LanguageLevel languageLevel) { PsiMethod method1 = info1.getElement(); PsiMethod method2 = info2.getElement(); final PsiClass class1 = method1.getContainingClass(); final PsiClass class2 = method2.getContainingClass(); final PsiParameter[] params1 = method1.getParameterList().getParameters(); final PsiParameter[] params2 = method2.getParameterList().getParameters(); final PsiTypeParameter[] typeParameters1 = method1.getTypeParameters(); final PsiTypeParameter[] typeParameters2 = method2.getTypeParameters(); final PsiSubstitutor classSubstitutor1 = info1.getSubstitutor(false); // substitutions for method type parameters will be ignored final PsiSubstitutor classSubstitutor2 = info2.getSubstitutor(false); final int max = Math.max(params1.length, params2.length); PsiType[] types1 = PsiType.createArray(max); PsiType[] types2 = PsiType.createArray(max); final boolean varargsPosition = applicabilityLevel == MethodCandidateInfo.ApplicabilityLevel.VARARGS; for (int i = 0; i < max; i++) { ProgressManager.checkCanceled(); PsiType type1 = params1.length > 0 ? params1[Math.min(i, params1.length - 1)].getType() : null; PsiType type2 = params2.length > 0 ? params2[Math.min(i, params2.length - 1)].getType() : null; if (varargsPosition) { if (type1 instanceof PsiEllipsisType && type2 instanceof PsiEllipsisType && params1.length == params2.length && class1 != null && (!JavaVersionService.getInstance().isAtLeast(class1, JavaSdkVersion.JDK_1_7) || ((PsiArrayType) type1) .getComponentType() .equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || ((PsiArrayType) type2) .getComponentType() .equalsToText(CommonClassNames.JAVA_LANG_OBJECT))) { type1 = ((PsiEllipsisType) type1).toArrayType(); type2 = ((PsiEllipsisType) type2).toArrayType(); } else { type1 = type1 instanceof PsiEllipsisType ? ((PsiArrayType) type1).getComponentType() : type1; type2 = type2 instanceof PsiEllipsisType ? ((PsiArrayType) type2).getComponentType() : type2; } } types1[i] = type1; types2[i] = type2; } boolean sameBoxing = true; int[] boxingHappened = new int[2]; for (int i = 0; i < types1.length; i++) { ProgressManager.checkCanceled(); PsiType type1 = classSubstitutor1.substitute(types1[i]); PsiType type2 = classSubstitutor2.substitute(types2[i]); PsiType argType = i < getActualParameterTypes().length ? getActualParameterTypes()[i] : null; boolean boxingInFirst = false; if (isBoxingHappened(argType, type1, languageLevel)) { boxingHappened[0] += 1; boxingInFirst = true; } boolean boxingInSecond = false; if (isBoxingHappened(argType, type2, languageLevel)) { boxingHappened[1] += 1; boxingInSecond = true; } sameBoxing &= boxingInFirst == boxingInSecond; } if (boxingHappened[0] == 0 && boxingHappened[1] > 0) return Specifics.FIRST; if (boxingHappened[0] > 0 && boxingHappened[1] == 0) return Specifics.SECOND; if (sameBoxing) { final PsiSubstitutor siteSubstitutor1 = info1.getSiteSubstitutor(); final PsiSubstitutor siteSubstitutor2 = info2.getSiteSubstitutor(); final PsiType[] types2AtSite = typesAtSite(types2, siteSubstitutor2); final PsiType[] types1AtSite = typesAtSite(types1, siteSubstitutor1); final PsiSubstitutor methodSubstitutor1 = calculateMethodSubstitutor( typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel); boolean applicable12 = isApplicableTo( types2AtSite, method1, languageLevel, varargsPosition, methodSubstitutor1, method2); final PsiSubstitutor methodSubstitutor2 = calculateMethodSubstitutor( typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel); boolean applicable21 = isApplicableTo( types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2, method1); if (!myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) { final boolean typeArgsApplicable12 = GenericsUtil.isTypeArgumentsApplicable( typeParameters1, methodSubstitutor1, myArgumentsList, !applicable21); final boolean typeArgsApplicable21 = GenericsUtil.isTypeArgumentsApplicable( typeParameters2, methodSubstitutor2, myArgumentsList, !applicable12); if (!typeArgsApplicable12) { applicable12 = false; } if (!typeArgsApplicable21) { applicable21 = false; } } if (applicable12 || applicable21) { if (applicable12 && !applicable21) return Specifics.SECOND; if (applicable21 && !applicable12) return Specifics.FIRST; final boolean abstract1 = method1.hasModifierProperty(PsiModifier.ABSTRACT); final boolean abstract2 = method2.hasModifierProperty(PsiModifier.ABSTRACT); if (abstract1 && !abstract2) { return Specifics.SECOND; } if (abstract2 && !abstract1) { return Specifics.FIRST; } } if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && myArgumentsList instanceof PsiExpressionList && (typeParameters1.length == 0 || typeParameters2.length == 0)) { boolean toCompareFunctional = false; if (types1.length > 0 && types2.length > 0) { for (int i = 0; i < getActualParametersLength(); i++) { final PsiType type1 = types1[Math.min(i, types1.length - 1)]; final PsiType type2 = types2[Math.min(i, types2.length - 1)]; // from 15.12.2.5 Choosing the Most Specific Method // In addition, a functional interface type S is more specific than a functional // interface type T for an expression exp // if T is not a subtype of S and one of the following conditions apply. if (LambdaUtil.isFunctionalType(type1) && !TypeConversionUtil.erasure(type1).isAssignableFrom(type2) && LambdaUtil.isFunctionalType(type2) && !TypeConversionUtil.erasure(type2).isAssignableFrom(type1)) { types1AtSite[Math.min(i, types1.length - 1)] = PsiType.NULL; types2AtSite[Math.min(i, types2.length - 1)] = PsiType.NULL; toCompareFunctional = true; } } } if (toCompareFunctional) { final boolean applicable12ignoreFunctionalType = isApplicableTo( types2AtSite, method1, languageLevel, varargsPosition, calculateMethodSubstitutor( typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel), null); final boolean applicable21ignoreFunctionalType = isApplicableTo( types1AtSite, method2, languageLevel, varargsPosition, calculateMethodSubstitutor( typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel), null); if (applicable12ignoreFunctionalType || applicable21ignoreFunctionalType) { Specifics specifics = null; for (int i = 0; i < getActualParametersLength(); i++) { if (types1AtSite[Math.min(i, types1.length - 1)] == PsiType.NULL && types2AtSite[Math.min(i, types2.length - 1)] == PsiType.NULL) { Specifics specific = isFunctionalTypeMoreSpecific( info1, info2, ((PsiExpressionList) myArgumentsList).getExpressions()[i], i); if (specific == Specifics.NEITHER) { specifics = Specifics.NEITHER; break; } if (specifics == null) { specifics = specific; } else if (specifics != specific) { specifics = Specifics.NEITHER; break; } } } if (!applicable12ignoreFunctionalType && applicable21ignoreFunctionalType) { return specifics == Specifics.FIRST ? Specifics.FIRST : Specifics.NEITHER; } if (!applicable21ignoreFunctionalType && applicable12ignoreFunctionalType) { return specifics == Specifics.SECOND ? Specifics.SECOND : Specifics.NEITHER; } return specifics; } } } } else if (varargsPosition) { final PsiType lastParamType1 = classSubstitutor1.substitute(types1[types1.length - 1]); final PsiType lastParamType2 = classSubstitutor2.substitute(types2[types1.length - 1]); final boolean assignable1 = TypeConversionUtil.isAssignable(lastParamType2, lastParamType1); final boolean assignable2 = TypeConversionUtil.isAssignable(lastParamType1, lastParamType2); if (assignable1 && !assignable2) { return Specifics.FIRST; } if (assignable2 && !assignable1) { return Specifics.SECOND; } } if (class1 != class2) { if (class2.isInheritor(class1, true) || class1.isInterface() && !class2.isInterface()) { if (MethodSignatureUtil.isSubsignature( method1.getSignature(info1.getSubstitutor(false)), method2.getSignature(info2.getSubstitutor(false)))) { return Specifics.SECOND; } else if (method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && boxingHappened[0] == 0) { return Specifics.SECOND; } } else if (MethodSignatureUtil.areErasedParametersEqual( method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY)) && MethodSignatureUtil.isSubsignature( method2.getSignature(info2.getSubstitutor(false)), method1.getSignature(info1.getSubstitutor(false)))) { return Specifics.FIRST; } else if (class1.isInheritor(class2, true) || class2.isInterface()) { if (method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && boxingHappened[0] == 0) { return Specifics.FIRST; } } } final boolean raw1 = PsiUtil.isRawSubstitutor(method1, classSubstitutor1); final boolean raw2 = PsiUtil.isRawSubstitutor(method2, classSubstitutor2); if (raw1 ^ raw2) { return raw1 ? Specifics.SECOND : Specifics.FIRST; } final boolean varargs1 = info1.isVarargs(); final boolean varargs2 = info2.isVarargs(); if (varargs1 ^ varargs2) { return varargs1 ? Specifics.SECOND : Specifics.FIRST; } return Specifics.NEITHER; }
// This methods works equally well for primary usages as well as for propagated callers' usages private static void fixActualArgumentsList( PsiExpressionList list, JavaChangeInfo changeInfo, boolean toInsertDefaultValue, PsiSubstitutor substitutor) throws IncorrectOperationException { final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory(); if (changeInfo.isParameterSetOrOrderChanged()) { if (changeInfo instanceof JavaChangeInfoImpl && ((JavaChangeInfoImpl) changeInfo).isPropagationEnabled) { final ParameterInfoImpl[] createdParmsInfo = ((JavaChangeInfoImpl) changeInfo).getCreatedParmsInfoWithoutVarargs(); for (ParameterInfoImpl info : createdParmsInfo) { PsiExpression newArg; if (toInsertDefaultValue) { newArg = createDefaultValue(changeInfo, factory, info, list); } else { newArg = factory.createExpressionFromText(info.getName(), list); } JavaCodeStyleManager.getInstance(list.getProject()) .shortenClassReferences(list.add(newArg)); } } else { final PsiExpression[] args = list.getExpressions(); final int nonVarargCount = getNonVarargCount(changeInfo, args); final int varargCount = args.length - nonVarargCount; if (varargCount < 0) return; PsiExpression[] newVarargInitializers = null; final int newArgsLength; final int newNonVarargCount; final JavaParameterInfo[] newParms = changeInfo.getNewParameters(); if (changeInfo.isArrayToVarargs()) { newNonVarargCount = newParms.length - 1; final JavaParameterInfo lastNewParm = newParms[newParms.length - 1]; final PsiExpression arrayToConvert = args[lastNewParm.getOldIndex()]; if (arrayToConvert instanceof PsiNewExpression) { final PsiNewExpression expression = (PsiNewExpression) arrayToConvert; final PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer(); if (arrayInitializer != null) { newVarargInitializers = arrayInitializer.getInitializers(); } } newArgsLength = newVarargInitializers == null ? newParms.length : newNonVarargCount + newVarargInitializers.length; } else if (changeInfo.isRetainsVarargs()) { newNonVarargCount = newParms.length - 1; newArgsLength = newNonVarargCount + varargCount; } else if (changeInfo.isObtainsVarags()) { newNonVarargCount = newParms.length - 1; newArgsLength = newNonVarargCount; } else { newNonVarargCount = newParms.length; newArgsLength = newParms.length; } String[] oldVarargs = null; if (changeInfo.wasVararg() && !changeInfo.isRetainsVarargs()) { oldVarargs = new String[varargCount]; for (int i = nonVarargCount; i < args.length; i++) { oldVarargs[i - nonVarargCount] = args[i].getText(); } } final PsiExpression[] newArgs = new PsiExpression[newArgsLength]; for (int i = 0; i < newNonVarargCount; i++) { if (newParms[i].getOldIndex() == nonVarargCount && oldVarargs != null) { PsiType type = newParms[i].createType(changeInfo.getMethod(), list.getManager()); if (type instanceof PsiArrayType) { type = substitutor.substitute(type); type = TypeConversionUtil.erasure(type); String typeText = type.getCanonicalText(); if (type instanceof PsiEllipsisType) { typeText = typeText.replace("...", "[]"); } String text = "new " + typeText + "{" + StringUtil.join(oldVarargs, ",") + "}"; newArgs[i] = factory.createExpressionFromText(text, changeInfo.getMethod()); continue; } } newArgs[i] = createActualArgument(changeInfo, list, newParms[i], toInsertDefaultValue, args); } if (changeInfo.isArrayToVarargs()) { if (newVarargInitializers == null) { newArgs[newNonVarargCount] = createActualArgument( changeInfo, list, newParms[newNonVarargCount], toInsertDefaultValue, args); } else { System.arraycopy( newVarargInitializers, 0, newArgs, newNonVarargCount, newVarargInitializers.length); } } else { final int newVarargCount = newArgsLength - newNonVarargCount; LOG.assertTrue(newVarargCount == 0 || newVarargCount == varargCount); for (int i = newNonVarargCount; i < newArgsLength; i++) { final int oldIndex = newParms[newNonVarargCount].getOldIndex(); if (oldIndex >= 0 && oldIndex != nonVarargCount) { newArgs[i] = createActualArgument( changeInfo, list, newParms[newNonVarargCount], toInsertDefaultValue, args); } else { System.arraycopy(args, nonVarargCount, newArgs, newNonVarargCount, newVarargCount); break; } } } ChangeSignatureUtil.synchronizeList( list, Arrays.asList(newArgs), ExpressionList.INSTANCE, changeInfo.toRemoveParm()); } } }
private static void checkSuperclassMembers( PsiClass superClass, MemberInfoBase<? extends PsiMember>[] infos, MultiMap<PsiElement, String> conflictsList) { for (MemberInfoBase<? extends PsiMember> info : infos) { PsiMember member = info.getMember(); boolean isConflict = false; if (member instanceof PsiField) { String name = member.getName(); isConflict = superClass.findFieldByName(name, false) != null; } else if (member instanceof PsiMethod) { PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor( superClass, member.getContainingClass(), PsiSubstitutor.EMPTY); MethodSignature signature = ((PsiMethod) member).getSignature(superSubstitutor); final PsiMethod superClassMethod = MethodSignatureUtil.findMethodBySignature(superClass, signature, false); isConflict = superClassMethod != null; } if (isConflict) { String message = RefactoringBundle.message( "0.already.contains.a.1", RefactoringUIUtil.getDescription(superClass, false), RefactoringUIUtil.getDescription(member, false)); message = CommonRefactoringUtil.capitalize(message); conflictsList.putValue(superClass, message); } if (member instanceof PsiMethod) { final PsiMethod method = (PsiMethod) member; final PsiModifierList modifierList = method.getModifierList(); if (!modifierList.hasModifierProperty(PsiModifier.PRIVATE)) { for (PsiClass subClass : ClassInheritorsSearch.search(superClass)) { if (method.getContainingClass() != subClass) { MethodSignature signature = ((PsiMethod) member) .getSignature( TypeConversionUtil.getSuperClassSubstitutor( superClass, subClass, PsiSubstitutor.EMPTY)); final PsiMethod wouldBeOverriden = MethodSignatureUtil.findMethodBySignature(subClass, signature, false); if (wouldBeOverriden != null && VisibilityUtil.compare( VisibilityUtil.getVisibilityModifier(wouldBeOverriden.getModifierList()), VisibilityUtil.getVisibilityModifier(modifierList)) > 0) { conflictsList.putValue( wouldBeOverriden, CommonRefactoringUtil.capitalize( RefactoringUIUtil.getDescription(method, true) + " in super class would clash with local method from " + RefactoringUIUtil.getDescription(subClass, true))); } } } } } } }
protected void checkSameSignatures(@NotNull List<CandidateInfo> conflicts) { // candidates should go in order of class hierarchy traversal // in order for this to work Map<MethodSignature, CandidateInfo> signatures = new THashMap<MethodSignature, CandidateInfo>(conflicts.size()); Set<PsiMethod> superMethods = new HashSet<PsiMethod>(); for (CandidateInfo conflict : conflicts) { final PsiMethod method = ((MethodCandidateInfo) conflict).getElement(); for (HierarchicalMethodSignature methodSignature : method.getHierarchicalMethodSignature().getSuperSignatures()) { final PsiMethod superMethod = methodSignature.getMethod(); final PsiClass aClass = superMethod.getContainingClass(); if (aClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) { superMethods.add(superMethod); } } } nextConflict: for (int i = 0; i < conflicts.size(); i++) { ProgressManager.checkCanceled(); CandidateInfo info = conflicts.get(i); PsiMethod method = (PsiMethod) info.getElement(); if (!method.hasModifierProperty(PsiModifier.STATIC) && superMethods.contains(method)) { conflicts.remove(i); i--; continue; } PsiClass class1 = method.getContainingClass(); PsiSubstitutor infoSubstitutor = ((MethodCandidateInfo) info).getSubstitutor(false); MethodSignature signature = method.getSignature(infoSubstitutor); CandidateInfo existing = signatures.get(signature); if (existing == null) { signatures.put(signature, info); continue; } PsiMethod existingMethod = (PsiMethod) existing.getElement(); PsiClass existingClass = existingMethod.getContainingClass(); if (class1 != null && existingClass != null) { // prefer interface methods to methods from Object if (class1.isInterface() && CommonClassNames.JAVA_LANG_OBJECT.equals(existingClass.getQualifiedName())) { signatures.put(signature, info); continue; } else if (existingClass.isInterface() && CommonClassNames.JAVA_LANG_OBJECT.equals(class1.getQualifiedName())) { conflicts.remove(info); i--; continue; } } if (method == existingMethod) { PsiElement scope1 = info.getCurrentFileResolveScope(); PsiElement scope2 = existing.getCurrentFileResolveScope(); if (scope1 instanceof PsiClass && scope2 instanceof PsiClass && PsiTreeUtil.isAncestor(scope1, scope2, true) && !existing .isAccessible()) { // prefer methods from outer class to inaccessible base class // methods signatures.put(signature, info); continue; } } // filter out methods with incorrect inferred bounds (for unrelated methods only) boolean existingTypeParamAgree = areTypeParametersAgree(existing); boolean infoTypeParamAgree = areTypeParametersAgree(info); if (existingTypeParamAgree && !infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(method, existingMethod)) { conflicts.remove(i); i--; continue; } if (!existingTypeParamAgree && infoTypeParamAgree && !PsiSuperMethodImplUtil.isSuperMethodSmart(existingMethod, method)) { signatures.put(signature, info); int index = conflicts.indexOf(existing); conflicts.remove(index); i--; continue; } if (InheritanceUtil.isInheritorOrSelf(class1, existingClass, true) || InheritanceUtil.isInheritorOrSelf(existingClass, class1, true)) { PsiParameter[] parameters = method.getParameterList().getParameters(); final PsiParameter[] existingParameters = existingMethod.getParameterList().getParameters(); for (int i1 = 0, parametersLength = parameters.length; i1 < parametersLength; i1++) { if (parameters[i1].getType() instanceof PsiArrayType && !(existingParameters[i1].getType() instanceof PsiArrayType)) { // prefer more specific type signatures.put(signature, info); continue nextConflict; } } PsiType returnType1 = method.getReturnType(); PsiType returnType2 = existingMethod.getReturnType(); if (returnType1 != null && returnType2 != null) { returnType1 = infoSubstitutor.substitute(returnType1); returnType2 = ((MethodCandidateInfo) existing).getSubstitutor(false).substitute(returnType2); if (!returnType1.equals(returnType2) && returnType1.isAssignableFrom(returnType2)) { conflicts.remove(i); i--; continue; } } // prefer derived class signatures.put(signature, info); } else { final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(myArgumentsList, PsiMethodCallExpression.class); if (methodCallExpression != null) { final PsiReferenceExpression expression = methodCallExpression.getMethodExpression(); final PsiExpression qualifierExpression = expression.getQualifierExpression(); PsiClass currentClass; if (qualifierExpression != null) { currentClass = PsiUtil.resolveClassInClassTypeOnly(qualifierExpression.getType()); } else { currentClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class); } if (currentClass != null && existingClass != null && class1 != null) { final PsiSubstitutor eSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor( existingClass, currentClass, PsiSubstitutor.EMPTY, null); final PsiSubstitutor cSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor( class1, currentClass, PsiSubstitutor.EMPTY, null); if (eSubstitutor != null && cSubstitutor != null && MethodSignatureUtil.areSignaturesEqual( existingMethod.getSignature(eSubstitutor), method.getSignature(cSubstitutor))) { final PsiType returnType = eSubstitutor.substitute(existingMethod.getReturnType()); final PsiType returnType1 = cSubstitutor.substitute(method.getReturnType()); if (returnType != null && returnType1 != null && !returnType1.equals(returnType)) { if (TypeConversionUtil.isAssignable(returnType, returnType1, false)) { if (class1.isInterface() && !existingClass.isInterface()) continue; conflicts.remove(existing); } else { if (!TypeConversionUtil.isAssignable(returnType1, returnType, false)) continue; conflicts.remove(i); } i--; break; } } } } } } }
private PsiType getCategoryTargetType(PsiMethod method) { final PsiType parameterType = method.getParameterList().getParameters()[0].getType(); return TypesUtil.boxPrimitiveType( TypeConversionUtil.erasure(parameterType), myPsiManager, myScope); }