PsiSubstitutor (final PsiMethodReferenceExpression reference, final MethodCandidateInfo candidateInfo, final PsiType functionalInterfaceType) { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); LOG.assertTrue(interfaceMethod != null, myContext); final PsiSubstitutor functionalInterfaceSubstitutor = LambdaUtil.getSubstitutor(interfaceMethod, resolveResult); final MethodSignature signature = interfaceMethod.getSignature(functionalInterfaceSubstitutor); final boolean varargs = candidateInfo.isVarargs(); final PsiMethod method = candidateInfo.getElement(); final PsiClass methodContainingClass = method.getContainingClass(); final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(reference); final PsiClass containingClass = qualifierResolveResult.getContainingClass(); if (containingClass == null) { return resolveSubset(myInferenceVariables, mySiteSubstitutor); } final PsiParameter[] functionalMethodParameters = interfaceMethod.getParameterList().getParameters(); final PsiParameter[] parameters = method.getParameterList().getParameters(); final boolean isStatic = method.hasModifierProperty(PsiModifier.STATIC); PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor(); if (parameters.length == functionalMethodParameters.length && !varargs || isStatic && varargs) {//static methods if (method.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor)) { //15.13.1 If ClassType is a raw type, but is not a non-static member type of a raw type, //the candidate notional member methods are those specified in p15.9.3 for a //class instance creation expression that uses <> to elide the type arguments to a class initBounds(containingClass.getTypeParameters()); psiSubstitutor = PsiSubstitutor.EMPTY; } if (methodContainingClass != null) { psiSubstitutor = JavaClassSupers.getInstance().getSuperClassSubstitutor(methodContainingClass, containingClass, reference.getResolveScope(), psiSubstitutor); if (psiSubstitutor == null) { LOG.error("derived: " + containingClass + "; super: " + methodContainingClass + "; reference: " + reference.getText() + "; containingFile: " + reference.getContainingFile().getName()); } } for (int i = 0; i < functionalMethodParameters.length; i++) { final PsiType pType = signature.getParameterTypes()[i]; addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(getParameterType(parameters, i, psiSubstitutor, varargs)), PsiUtil.captureToplevelWildcards(pType, functionalMethodParameters[i]))); } } else if (PsiMethodReferenceUtil.isResolvedBySecondSearch(reference, signature, varargs, isStatic, parameters.length)) { //instance methods final PsiType pType = signature.getParameterTypes()[0]; // 15.13.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1, // the type to search is the result of capture conversion (5.1.10) applied to T; // otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference. if (PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor)) { PsiClassType subclassType = StrictSubtypingConstraint.getSubclassType(containingClass, pType, true); final PsiSubstitutor receiverSubstitutor = subclassType != null ? TypeConversionUtil.getSuperClassSubstitutor(containingClass, (PsiClassType)PsiUtil.captureToplevelWildcards(subclassType, myContext)) : null; if (receiverSubstitutor != null) { if (!method.hasTypeParameters()) { if (signature.getParameterTypes().length == 1 || PsiUtil.isRawSubstitutor(containingClass, receiverSubstitutor)) { return methodContainingClass != null ? JavaClassSupers.getInstance().getSuperClassSubstitutor(methodContainingClass, containingClass, reference.getResolveScope(), receiverSubstitutor) : receiverSubstitutor; } } mySiteSubstitutor = mySiteSubstitutor.putAll(receiverSubstitutor); if (methodContainingClass != null) { final PsiSubstitutor superSubstitutor = JavaClassSupers.getInstance().getSuperClassSubstitutor(methodContainingClass, containingClass, reference.getResolveScope(), receiverSubstitutor); LOG.assertTrue(superSubstitutor != null, "mContainingClass: " + methodContainingClass.getName() + "; containingClass: " + containingClass.getName()); mySiteSubstitutor = mySiteSubstitutor.putAll(superSubstitutor); } psiSubstitutor = receiverSubstitutor; } } //no additional constraints for array creation PsiElementFactory factory = JavaPsiFacade.getElementFactory(myManager.getProject()); if (PsiUtil.isArrayClass(containingClass)) { return null; } final PsiType qType = factory.createType(containingClass, psiSubstitutor); addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(qType), PsiUtil.captureToplevelWildcards(pType, reference))); if (methodContainingClass != null) { psiSubstitutor = JavaClassSupers.getInstance().getSuperClassSubstitutor(methodContainingClass, containingClass, reference.getResolveScope(), psiSubstitutor); LOG.assertTrue(psiSubstitutor != null, "derived: " + containingClass + "; super: " + methodContainingClass + "; reference: " + reference.getText() + "; containingFile: " + reference.getContainingFile().getName()); } for (int i = 0; i < signature.getParameterTypes().length - 1; i++) { final PsiType interfaceParamType = signature.getParameterTypes()[i + 1]; addConstraint(new TypeCompatibilityConstraint(substituteWithInferenceVariables(getParameterType(parameters, i, psiSubstitutor, varargs)), PsiUtil.captureToplevelWildcards(interfaceParamType, functionalMethodParameters[i]))); } } return null; }