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); } } }
@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; }
@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; }
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; }
public static String checkReturnType( PsiMethodReferenceExpression expression, JavaResolveResult result, PsiType functionalInterfaceType) { final PsiElement resolve = result.getElement(); if (resolve instanceof PsiMethod) { final PsiClass containingClass = ((PsiMethod) resolve).getContainingClass(); LOG.assertTrue(containingClass != null); PsiSubstitutor subst = result.getSubstitutor(); PsiClass qContainingClass = getQualifierResolveResult(expression).getContainingClass(); if (qContainingClass != null && isReceiverType(functionalInterfaceType, containingClass, (PsiMethod) resolve)) { subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst); LOG.assertTrue(subst != null); } final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); PsiType returnType = PsiTypesUtil.patchMethodGetClassReturnType( expression, expression, (PsiMethod) resolve, null, PsiUtil.getLanguageLevel(expression)); if (returnType == null) { returnType = ((PsiMethod) resolve).getReturnType(); } PsiType methodReturnType = subst.substitute(returnType); if (interfaceReturnType != null && interfaceReturnType != PsiType.VOID) { if (methodReturnType == null) { methodReturnType = JavaPsiFacade.getElementFactory(expression.getProject()) .createType(containingClass, subst); } if (!TypeConversionUtil.isAssignable(interfaceReturnType, methodReturnType, false)) { return "Bad return type in method reference: cannot convert " + methodReturnType.getCanonicalText() + " to " + interfaceReturnType.getCanonicalText(); } } } return null; }
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); }
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); }
public static boolean isCorrectAssignment( PsiType[] parameterTypes, PsiType[] argTypes, boolean varargs, int offset) { final int min = Math.min(parameterTypes.length, argTypes.length - offset); for (int i = 0; i < min; i++) { final PsiType argType = argTypes[i + offset]; PsiType parameterType = parameterTypes[i]; parameterType = GenericsUtil.getVariableTypeByExpressionType(parameterType, true); if (varargs && i == parameterTypes.length - 1) { if (!TypeConversionUtil.isAssignable(parameterType, argType) && !TypeConversionUtil.isAssignable( ((PsiArrayType) parameterType).getComponentType(), argType)) { return false; } } else if (!TypeConversionUtil.isAssignable(parameterType, argType)) { return false; } } return !varargs || parameterTypes.length - 1 <= argTypes.length - offset; }
@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); }
public static boolean isReceiverType( PsiType receiverType, @Nullable PsiClass containingClass, PsiSubstitutor psiSubstitutor) { if (containingClass != null) { receiverType = getExpandedType(receiverType, containingClass); } final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(receiverType); final PsiClass receiverClass = resolveResult.getElement(); if (receiverClass != null && isReceiverType(receiverClass, containingClass)) { if (emptyOrRaw(containingClass, psiSubstitutor)) { return true; } final PsiSubstitutor derivedSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, receiverClass, psiSubstitutor); return derivedSubstitutor != null && TypeConversionUtil.isAssignable( JavaPsiFacade.getElementFactory(containingClass.getProject()) .createType(containingClass, derivedSubstitutor), receiverType); } return false; }
private static MethodSignature getMethodSignature( PsiMethod method, PsiClass psiClass, PsiClass containingClass) { final MethodSignature methodSignature; if (containingClass != null && containingClass != psiClass) { methodSignature = method.getSignature( TypeConversionUtil.getSuperClassSubstitutor( containingClass, psiClass, PsiSubstitutor.EMPTY)); } else { methodSignature = method.getSignature(PsiSubstitutor.EMPTY); } return methodSignature; }
@Nullable private static PsiType getReturnType(PsiClass psiClass, MethodSignature methodSignature) { final PsiMethod method = getMethod(psiClass, methodSignature); if (method != null) { final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) return null; return TypeConversionUtil.getSuperClassSubstitutor( containingClass, psiClass, PsiSubstitutor.EMPTY) .substitute(method.getReturnType()); } else { return null; } }
@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; }
public static PsiSubstitutor getSubstitutor( @NotNull PsiMethod method, @NotNull PsiClassType.ClassResolveResult resolveResult) { final PsiClass derivedClass = resolveResult.getElement(); LOG.assertTrue(derivedClass != null); final PsiClass methodContainingClass = method.getContainingClass(); LOG.assertTrue(methodContainingClass != null); PsiSubstitutor initialSubst = resolveResult.getSubstitutor(); final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor( methodContainingClass, derivedClass, PsiSubstitutor.EMPTY); for (PsiTypeParameter param : superClassSubstitutor.getSubstitutionMap().keySet()) { final PsiType substitute = superClassSubstitutor.substitute(param); if (substitute != null) { initialSubst = initialSubst.put(param, initialSubst.substitute(substitute)); } } return initialSubst; }
@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); }
@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 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))); } } } } } } }
@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; }
// 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 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); }