@Nullable private static PsiType getInferredTypes( GrReferenceExpressionImpl refExpr, @Nullable PsiElement resolved) { final GrExpression qualifier = refExpr.getQualifier(); if (qualifier == null && !(resolved instanceof PsiClass)) { return TypeInferenceHelper.getCurrentContext().getVariableType(refExpr); } else if (qualifier != null) { // map access PsiType qType = qualifier.getType(); if (qType instanceof PsiClassType && !(qType instanceof GrMapType)) { PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics(); PsiClass clazz = qResult.getElement(); if (clazz != null) { PsiClass mapClass = JavaPsiFacade.getInstance(refExpr.getProject()) .findClass(CommonClassNames.JAVA_UTIL_MAP, refExpr.getResolveScope()); if (mapClass != null && mapClass.getTypeParameters().length == 2) { PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor()); if (substitutor != null) { return TypeConversionUtil.erasure( substitutor.substitute(mapClass.getTypeParameters()[1])); } } } } } return null; }
private JavaResolveResult advancedResolveImpl() { final PsiElement resolve = resolveElement(); if (resolve instanceof PsiClass) { final Map<PsiTypeParameter, PsiType> substitutionMap = new HashMap<PsiTypeParameter, PsiType>(); int index = 0; for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable((PsiClass) resolve)) { if (index >= myTypeParameters.length) { final PsiTypeParameterListOwner parameterOwner = parameter.getOwner(); if (parameterOwner == resolve) { substitutionMap.put(parameter, null); } else if (parameterOwner instanceof PsiClass) { PsiElement containingClass = myParent; while ((containingClass = PsiTreeUtil.getParentOfType(containingClass, PsiClass.class, true)) != null) { final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getClassSubstitutor( (PsiClass) parameterOwner, (PsiClass) containingClass, PsiSubstitutor.EMPTY); if (superClassSubstitutor != null) { substitutionMap.put(parameter, superClassSubstitutor.substitute(parameter)); break; } } } } else { substitutionMap.put(parameter, myTypeParameters[index].getType()); } index++; } return new CandidateInfo(resolve, PsiSubstitutorImpl.createSubstitutor(substitutionMap)); } else { return new CandidateInfo(resolve, PsiSubstitutor.EMPTY); } }
@Nullable private static PsiType getTypeFromMapAccess(@NotNull GrReferenceExpressionImpl ref) { // map access GrExpression qualifier = ref.getQualifierExpression(); if (qualifier != null) { PsiType qType = qualifier.getNominalType(); if (qType instanceof PsiClassType) { PsiClassType.ClassResolveResult qResult = ((PsiClassType) qType).resolveGenerics(); PsiClass clazz = qResult.getElement(); if (clazz != null) { PsiClass mapClass = JavaPsiFacade.getInstance(ref.getProject()) .findClass(CommonClassNames.JAVA_UTIL_MAP, ref.getResolveScope()); if (mapClass != null && mapClass.getTypeParameters().length == 2) { PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(mapClass, clazz, qResult.getSubstitutor()); if (substitutor != null) { return TypeConversionUtil.erasure( substitutor.substitute(mapClass.getTypeParameters()[1])); } } } } } return null; }
/* Guesswork */ @Nullable private static PsiSubstitutor getInheritorSubstitutorForNewExpression( final PsiClass baseClass, final PsiClass inheritor, final PsiSubstitutor baseSubstitutor, final PsiElement context) { final Project project = baseClass.getProject(); JavaPsiFacade facade = JavaPsiFacade.getInstance(project); final PsiResolveHelper resolveHelper = facade.getResolveHelper(); PsiSubstitutor superSubstitutor = TypeConversionUtil.getClassSubstitutor(baseClass, inheritor, PsiSubstitutor.EMPTY); if (superSubstitutor == null) return null; PsiSubstitutor inheritorSubstitutor = PsiSubstitutor.EMPTY; for (PsiTypeParameter inheritorParameter : PsiUtil.typeParametersIterable(inheritor)) { for (PsiTypeParameter baseParameter : PsiUtil.typeParametersIterable(baseClass)) { final PsiType substituted = superSubstitutor.substitute(baseParameter); PsiType arg = baseSubstitutor.substitute(baseParameter); if (arg instanceof PsiWildcardType) arg = ((PsiWildcardType) arg).getBound(); PsiType substitution = resolveHelper.getSubstitutionForTypeParameter( inheritorParameter, substituted, arg, true, PsiUtil.getLanguageLevel(context)); if (PsiType.NULL.equals(substitution)) continue; if (substitution == null) { return facade.getElementFactory().createRawSubstitutor(inheritor); } inheritorSubstitutor = inheritorSubstitutor.put(inheritorParameter, substitution); break; } } return inheritorSubstitutor; }
@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; }
@Override public Result calculateResult(@NotNull Expression[] params, ExpressionContext context) { if (params.length != 1) return null; final Result result = params[0].calculateResult(context); if (result == null) return null; Project project = context.getProject(); PsiExpression expr = MacroUtil.resultToPsiExpression(result, context); if (expr == null) return null; PsiType type = expr.getType(); if (type instanceof PsiArrayType) { return new PsiTypeResult(((PsiArrayType) type).getComponentType(), project); } if (type instanceof PsiClassType) { PsiClassType.ClassResolveResult resolveResult = ((PsiClassType) type).resolveGenerics(); PsiClass aClass = resolveResult.getElement(); if (aClass != null) { PsiClass iterableClass = JavaPsiFacade.getInstance(project) .findClass("java.lang.Iterable", aClass.getResolveScope()); if (iterableClass != null) { PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor( iterableClass, aClass, resolveResult.getSubstitutor()); if (substitutor != null) { PsiType parameterType = substitutor.substitute(iterableClass.getTypeParameters()[0]); if (parameterType instanceof PsiCapturedWildcardType) { parameterType = ((PsiCapturedWildcardType) parameterType).getWildcard(); } if (parameterType != null) { if (parameterType instanceof PsiWildcardType) { if (((PsiWildcardType) parameterType).isExtends()) { return new PsiTypeResult(((PsiWildcardType) parameterType).getBound(), project); } else return null; } return new PsiTypeResult(parameterType, project); } } } } } return null; }
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 Pair<PsiVariable, PsiType> findVariable(final PsiElement element) { PsiVariable variable = null; if (element instanceof PsiIdentifier) { if (element.getParent() instanceof PsiVariable) { variable = (PsiVariable) element.getParent(); } } else if (element instanceof PsiJavaToken) { final PsiJavaToken token = (PsiJavaToken) element; if (token.getTokenType() != JavaTokenType.EQ) return null; if (token.getParent() instanceof PsiVariable) { variable = (PsiVariable) token.getParent(); } } if (variable == null) { return null; } variableName = variable.getName(); final PsiExpression initializer = variable.getInitializer(); if (initializer == null) return null; final PsiType variableType = variable.getType(); final PsiType initializerType = initializer.getType(); if (!(variableType instanceof PsiClassType)) return null; final PsiClassType variableClassType = (PsiClassType) variableType; if (!variableClassType.isRaw()) return null; if (!(initializerType instanceof PsiClassType)) return null; final PsiClassType initializerClassType = (PsiClassType) initializerType; if (initializerClassType.isRaw()) return null; final PsiClassType.ClassResolveResult variableResolveResult = variableClassType.resolveGenerics(); final PsiClassType.ClassResolveResult initializerResolveResult = initializerClassType.resolveGenerics(); if (initializerResolveResult.getElement() == null) return null; final PsiSubstitutor targetSubstitutor = TypeConversionUtil.getClassSubstitutor( variableResolveResult.getElement(), initializerResolveResult.getElement(), initializerResolveResult.getSubstitutor()); if (targetSubstitutor == null) return null; PsiType type = JavaPsiFacade.getInstance(variable.getProject()) .getElementFactory() .createType(variableResolveResult.getElement(), targetSubstitutor); newTypeName = type.getCanonicalText(); return Pair.create(variable, type); }
@Nullable private static PsiType getCollectionComponentType(PsiType type, Project project) { if (!(type instanceof PsiClassType)) return null; PsiClassType classType = (PsiClassType) type; PsiClassType.ClassResolveResult result = classType.resolveGenerics(); PsiClass clazz = result.getElement(); if (clazz == null) return null; JavaPsiFacade facade = JavaPsiFacade.getInstance(project); @SuppressWarnings({"ConstantConditions"}) PsiClass collectionClass = facade.findClass("java.util.Collection", type.getResolveScope()); if (collectionClass == null || collectionClass.getTypeParameters().length != 1) return null; PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(collectionClass, clazz, result.getSubstitutor()); if (substitutor == null) return null; PsiType componentType = substitutor.substitute(collectionClass.getTypeParameters()[0]); return componentType instanceof PsiIntersectionType ? null : componentType; }
private static void fillExpectedTypeArgs( CompletionResultSet resultSet, PsiElement context, final PsiClass actualClass, final int index, PsiClassType.ClassResolveResult expectedType, TailType globalTail) { final PsiClass expectedClass = expectedType.getElement(); if (!InheritanceUtil.isInheritorOrSelf(actualClass, expectedClass, true)) return; assert expectedClass != null; final PsiSubstitutor currentSubstitutor = TypeConversionUtil.getClassSubstitutor(expectedClass, actualClass, PsiSubstitutor.EMPTY); assert currentSubstitutor != null; PsiTypeParameter[] params = actualClass.getTypeParameters(); final List<PsiTypeLookupItem> typeItems = new ArrayList<PsiTypeLookupItem>(); for (int i = index; i < params.length; i++) { PsiType arg = getExpectedTypeArg(context, i, expectedType, currentSubstitutor, params); if (arg == null) { arg = getExpectedTypeArg(context, index, expectedType, currentSubstitutor, params); if (arg != null) { resultSet.addElement( TailTypeDecorator.withTail( PsiTypeLookupItem.createLookupItem(arg, context), getTail(index == params.length - 1))); } return; } typeItems.add(PsiTypeLookupItem.createLookupItem(arg, context)); } resultSet.addElement( new TypeArgsLookupElement( typeItems, globalTail, ConstructorInsertHandler.hasConstructorParameters(actualClass, context))); }
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; }
@Override public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) { if (!LambdaUtil.isFunctionalType(myT)) { return false; } final PsiType groundTargetType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(myT); final PsiClassType.ClassResolveResult classResolveResult = PsiUtil.resolveGenericsClassInType(groundTargetType); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(classResolveResult); if (interfaceMethod == null) { return false; } final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult); final PsiParameter[] targetParameters = interfaceMethod.getParameterList().getParameters(); final PsiType interfaceMethodReturnType = interfaceMethod.getReturnType(); final PsiType returnType = substitutor.substitute(interfaceMethodReturnType); final PsiType[] typeParameters = myExpression.getTypeParameters(); final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(myExpression); if (!myExpression.isExact()) { for (PsiParameter parameter : targetParameters) { if (!session.isProperType(substitutor.substitute(parameter.getType()))) { return false; } } } else { final PsiMember applicableMember = myExpression.getPotentiallyApplicableMember(); LOG.assertTrue(applicableMember != null); final PsiClass applicableMemberContainingClass = applicableMember.getContainingClass(); final PsiClass containingClass = qualifierResolveResult.getContainingClass(); PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor(); psiSubstitutor = applicableMemberContainingClass == null || containingClass == null || myExpression.isConstructor() ? psiSubstitutor : TypeConversionUtil.getSuperClassSubstitutor( applicableMemberContainingClass, containingClass, psiSubstitutor); PsiType applicableMethodReturnType = applicableMember instanceof PsiMethod ? ((PsiMethod) applicableMember).getReturnType() : null; int idx = 0; for (PsiTypeParameter param : ((PsiTypeParameterListOwner) applicableMember).getTypeParameters()) { if (idx < typeParameters.length) { psiSubstitutor = psiSubstitutor.put(param, typeParameters[idx++]); } } final PsiParameter[] parameters = applicableMember instanceof PsiMethod ? ((PsiMethod) applicableMember).getParameterList().getParameters() : PsiParameter.EMPTY_ARRAY; if (targetParameters.length == parameters.length + 1) { specialCase(session, constraints, substitutor, targetParameters, true); for (int i = 1; i < targetParameters.length; i++) { constraints.add( new TypeCompatibilityConstraint( session.substituteWithInferenceVariables( psiSubstitutor.substitute(parameters[i - 1].getType())), substitutor.substitute(targetParameters[i].getType()))); } } else if (targetParameters.length == parameters.length) { for (int i = 0; i < targetParameters.length; i++) { constraints.add( new TypeCompatibilityConstraint( session.substituteWithInferenceVariables( psiSubstitutor.substitute(parameters[i].getType())), substitutor.substitute(targetParameters[i].getType()))); } } else { return false; } if (returnType != PsiType.VOID && returnType != null) { if (applicableMethodReturnType == PsiType.VOID) { return false; } if (applicableMethodReturnType != null) { constraints.add( new TypeCompatibilityConstraint( returnType, session.substituteWithInferenceVariables( psiSubstitutor.substitute(applicableMethodReturnType)))); } else if (applicableMember instanceof PsiClass || applicableMember instanceof PsiMethod && ((PsiMethod) applicableMember).isConstructor()) { final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(applicableMember.getProject()); if (containingClass != null) { final PsiType classType = session.substituteWithInferenceVariables( elementFactory.createType(containingClass, psiSubstitutor)); constraints.add(new TypeCompatibilityConstraint(returnType, classType)); } } } return true; } final Map<PsiElement, PsiType> map = LambdaUtil.getFunctionalTypeMap(); final PsiType added = map.put(myExpression, session.startWithFreshVars(groundTargetType)); final JavaResolveResult resolve; try { resolve = myExpression.advancedResolve(true); } finally { if (added == null) { map.remove(myExpression); } } final PsiElement element = resolve.getElement(); if (element == null) { return false; } if (PsiType.VOID.equals(returnType) || returnType == null) { return true; } if (element instanceof PsiMethod) { final PsiMethod method = (PsiMethod) element; final PsiType referencedMethodReturnType; final PsiClass containingClass = method.getContainingClass(); LOG.assertTrue(containingClass != null, method); PsiClass qContainingClass = qualifierResolveResult.getContainingClass(); PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor(); if (qContainingClass != null) { if (PsiUtil.isRawSubstitutor(qContainingClass, psiSubstitutor)) { psiSubstitutor = PsiSubstitutor.EMPTY; } if (qContainingClass.isInheritor(containingClass, true)) { psiSubstitutor = TypeConversionUtil.getClassSubstitutor( containingClass, qContainingClass, PsiSubstitutor.EMPTY); LOG.assertTrue(psiSubstitutor != null); } } if (method.isConstructor()) { referencedMethodReturnType = JavaPsiFacade.getElementFactory(method.getProject()) .createType(containingClass, PsiSubstitutor.EMPTY); } else { referencedMethodReturnType = method.getReturnType(); } LOG.assertTrue(referencedMethodReturnType != null, method); if (!PsiTreeUtil.isContextAncestor(containingClass, myExpression, false) || PsiUtil.getEnclosingStaticElement(myExpression, containingClass) != null) { session.initBounds(myExpression, containingClass.getTypeParameters()); } session.initBounds(myExpression, method.getTypeParameters()); // if i) the method reference elides NonWildTypeArguments, // ii) the compile-time declaration is a generic method, and // iii) the return type of the compile-time declaration mentions at least one of the method's // type parameters; if (typeParameters.length == 0 && method.getTypeParameters().length > 0) { final PsiClass interfaceClass = classResolveResult.getElement(); LOG.assertTrue(interfaceClass != null); if (PsiPolyExpressionUtil.mentionsTypeParameters( referencedMethodReturnType, ContainerUtil.newHashSet(method.getTypeParameters()))) { // the constraint reduces to the bound set B3 which would be used to determine the method // reference's invocation type // when targeting the return type of the function type, as defined in 18.5.2. session.collectApplicabilityConstraints( myExpression, ((MethodCandidateInfo) resolve), groundTargetType); session.registerReturnTypeConstraints(referencedMethodReturnType, returnType); return true; } } if (PsiType.VOID.equals(referencedMethodReturnType)) { return false; } int idx = 0; for (PsiTypeParameter param : method.getTypeParameters()) { if (idx < typeParameters.length) { psiSubstitutor = psiSubstitutor.put(param, typeParameters[idx++]); } } final PsiParameter[] parameters = method.getParameterList().getParameters(); if (targetParameters.length == parameters.length + 1 && !method.isVarArgs() && PsiPolyExpressionUtil.mentionsTypeParameters( referencedMethodReturnType, ContainerUtil.newHashSet( containingClass.getTypeParameters()))) { // todo specification bug? specialCase(session, constraints, substitutor, targetParameters, false); } constraints.add( new TypeCompatibilityConstraint( returnType, session.substituteWithInferenceVariables( psiSubstitutor.substitute(referencedMethodReturnType)))); } return 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; }
public Binding balance( final PsiType x, final PsiType y, final Balancer balancer, final HashSet<Constraint> constraints) { final int indicator = (x instanceof PsiTypeVariable ? 1 : 0) + (y instanceof PsiTypeVariable ? 2 : 0); switch (indicator) { case 0: if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) { final PsiType xType = x instanceof PsiWildcardType ? ((PsiWildcardType) x).getBound() : x; final PsiType yType = y instanceof PsiWildcardType ? ((PsiWildcardType) y).getBound() : y; switch ((x instanceof PsiWildcardType ? 1 : 0) + (y instanceof PsiWildcardType ? 2 : 0)) { case 1: if (((PsiWildcardType) x).isExtends()) { /* ? extends T1, T2 */ return null; } else { /* ? super T1, T2 */ if (xType != null && !"java.lang.Object".equals(xType.getCanonicalText())) { return null; } return create(); } case 2: if (((PsiWildcardType) y).isExtends()) { /* T1, ? extends T2 */ if (yType instanceof PsiTypeVariable) { final PsiTypeVariable beta = myFactory.create(); if (constraints != null) { constraints.add(new Subtype(beta, yType)); if (x != null) { constraints.add(new Subtype(x, yType)); } } return create(); } else { if (constraints != null && xType != null && yType != null) { constraints.add(new Subtype(xType, yType)); } return balance(xType, yType, balancer, constraints); } } else { /* T1, ? super T2 */ if (yType instanceof PsiTypeVariable) { final PsiTypeVariable beta = myFactory.create(); if (constraints != null) { if (x != null) constraints.add(new Subtype(x, beta)); constraints.add(new Subtype(yType, beta)); } return create(); } else { if (constraints != null && yType != null && xType != null) { constraints.add(new Subtype(yType, xType)); } return balance(xType, yType, balancer, constraints); } } case 3: switch ((((PsiWildcardType) x).isExtends() ? 0 : 1) + (((PsiWildcardType) y).isExtends() ? 0 : 2)) { case 0: /* ? super T1, ? super T2 */ if (constraints != null && xType != null && yType != null) { constraints.add(new Subtype(yType, xType)); } return balance(xType, yType, balancer, constraints); case 1: /* ? extends T1, ? super T2 */ if (constraints != null && xType != null && yType != null) { constraints.add(new Subtype(xType, yType)); } return balance(xType, yType, balancer, constraints); case 2: /* ? super T1, ? extends T2*/ return null; case 3: /* ? extends T1, ? extends T2*/ if (constraints != null && xType != null && yType != null) { constraints.add(new Subtype(xType, yType)); } return balance(xType, yType, balancer, constraints); } } return create(); } else if (x instanceof PsiArrayType || y instanceof PsiArrayType) { final PsiType xType = x instanceof PsiArrayType ? ((PsiArrayType) x).getComponentType() : x; final PsiType yType = y instanceof PsiArrayType ? ((PsiArrayType) y).getComponentType() : y; return balance(xType, yType, balancer, constraints); } else if (x instanceof PsiClassType && y instanceof PsiClassType) { final PsiClassType.ClassResolveResult resultX = Util.resolveType(x); final PsiClassType.ClassResolveResult resultY = Util.resolveType(y); final PsiClass xClass = resultX.getElement(); final PsiClass yClass = resultY.getElement(); if (xClass != null && yClass != null) { final PsiSubstitutor ySubst = resultY.getSubstitutor(); PsiSubstitutor xSubst = TypeConversionUtil.getClassSubstitutor(yClass, xClass, resultX.getSubstitutor()); if (xSubst == null) return null; Binding b = create(); for (final PsiTypeParameter aParm : xSubst.getSubstitutionMap().keySet()) { final PsiType xType = xSubst.substitute(aParm); final PsiType yType = ySubst.substitute(aParm); final Binding b1 = unify( xType, yType, new Unifier() { public Binding unify(final PsiType x, final PsiType y) { return balance(x, y, balancer, constraints); } }); if (b1 == null) { return null; } b = b.compose(b1); } return b; } } else if (y instanceof Bottom) { return create(); } else { return null; } break; case 1: return balancer.varType((PsiTypeVariable) x, y); case 2: return balancer.typeVar(x, (PsiTypeVariable) y); case 3: return balancer.varVar((PsiTypeVariable) x, (PsiTypeVariable) y); } return null; }