@NotNull private static PsiSubstitutor replaceVariables(Collection<InferenceVariable> inferenceVariables) { final List<InferenceVariable> targetVars = new ArrayList<InferenceVariable>(); PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; final InferenceVariable[] oldVars = inferenceVariables.toArray(new InferenceVariable[inferenceVariables.size()]); for (InferenceVariable variable : oldVars) { final InferenceVariable newVariable = new InferenceVariable( variable.getCallContext(), variable.getParameter(), variable.getName()); substitutor = substitutor.put( variable, JavaPsiFacade.getElementFactory(variable.getProject()).createType(newVariable)); targetVars.add(newVariable); if (variable.isThrownBound()) { newVariable.setThrownBound(); } } for (int i = 0; i < targetVars.size(); i++) { InferenceVariable var = targetVars.get(i); for (InferenceBound boundType : InferenceBound.values()) { for (PsiType bound : oldVars[i].getBounds(boundType)) { var.addBound(substitutor.substitute(bound), boundType, null); } } } return substitutor; }
/* 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; }
public static PsiType getType(@NotNull PsiClassObjectAccessExpression classAccessExpression) { GlobalSearchScope resolveScope = classAccessExpression.getResolveScope(); PsiManager manager = classAccessExpression.getManager(); final PsiClass classClass = JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Class", resolveScope); if (classClass == null) { return new PsiClassReferenceType( new LightClassReference(manager, "Class", "java.lang.Class", resolveScope), null); } if (!PsiUtil.isLanguageLevel5OrHigher(classAccessExpression)) { // Raw java.lang.Class return JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createType(classClass); } PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; PsiType operandType = classAccessExpression.getOperand().getType(); if (operandType instanceof PsiPrimitiveType && !PsiType.NULL.equals(operandType)) { if (PsiType.VOID.equals(operandType)) { operandType = JavaPsiFacade.getInstance(manager.getProject()) .getElementFactory() .createTypeByFQClassName("java.lang.Void", classAccessExpression.getResolveScope()); } else { operandType = ((PsiPrimitiveType) operandType).getBoxedType(classAccessExpression); } } final PsiTypeParameter[] typeParameters = classClass.getTypeParameters(); if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], operandType); } return new PsiImmediateClassType(classClass, substitutor); }
@NotNull private PsiSubstitutor mapSubstitutor( PsiClass originalClass, PsiClass mappedClass, PsiSubstitutor substitutor) { PsiTypeParameter[] typeParameters = mappedClass.getTypeParameters(); PsiTypeParameter[] originalTypeParameters = originalClass.getTypeParameters(); if (typeParameters.length != originalTypeParameters.length) { if (originalTypeParameters.length == 0) { return JavaPsiFacade.getElementFactory(mappedClass.getProject()) .createRawSubstitutor(mappedClass); } return substitutor; } Map<PsiTypeParameter, PsiType> substitutionMap = substitutor.getSubstitutionMap(); PsiSubstitutor mappedSubstitutor = PsiSubstitutor.EMPTY; for (int i = 0; i < originalTypeParameters.length; i++) { if (!substitutionMap.containsKey(originalTypeParameters[i])) continue; PsiType originalSubstitute = substitutor.substitute(originalTypeParameters[i]); if (originalSubstitute != null) { PsiType substitute = mapType(originalSubstitute); if (substitute == null) return substitutor; mappedSubstitutor = mappedSubstitutor.put(typeParameters[i], substitute); } else { mappedSubstitutor = mappedSubstitutor.put(typeParameters[i], null); } } if (mappedClass.hasModifierProperty(PsiModifier.STATIC)) { return mappedSubstitutor; } PsiClass mappedContaining = mappedClass.getContainingClass(); PsiClass originalContaining = originalClass.getContainingClass(); //noinspection DoubleNegation if ((mappedContaining != null) != (originalContaining != null)) { return substitutor; } if (mappedContaining != null) { return mappedSubstitutor.putAll( mapSubstitutor(originalContaining, mappedContaining, substitutor)); } return mappedSubstitutor; }
@Nullable public static PsiType getSubstitutedType(@Nullable PsiParameter parameter) { if (parameter == null) return null; final PsiType type = getType(parameter); if (type instanceof PsiArrayType) { return type; } final PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(type); final PsiClass psiClass = result.getElement(); if (psiClass == null) return type; final Set<PsiTypeParameter> usedTypeParameters = new HashSet<PsiTypeParameter>(); RefactoringUtil.collectTypeParameters(usedTypeParameters, parameter); for (Iterator<PsiTypeParameter> iterator = usedTypeParameters.iterator(); iterator.hasNext(); ) { PsiTypeParameter usedTypeParameter = iterator.next(); if (parameter.getDeclarationScope() != usedTypeParameter.getOwner()) { iterator.remove(); } } PsiSubstitutor subst = PsiSubstitutor.EMPTY; for (PsiTypeParameter usedTypeParameter : usedTypeParameters) { subst = subst.put(usedTypeParameter, TypeConversionUtil.typeParameterErasure(usedTypeParameter)); } PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; final Map<PsiTypeParameter, PsiType> typeMap = result.getSubstitutor().getSubstitutionMap(); for (PsiTypeParameter typeParameter : typeMap.keySet()) { final PsiType psiType = typeMap.get(typeParameter); substitutor = substitutor.put(typeParameter, psiType != null ? subst.substitute(psiType) : null); } if (psiClass instanceof PsiTypeParameter) { return subst.substitute((PsiTypeParameter) psiClass); } else { return JavaPsiFacade.getElementFactory(parameter.getProject()) .createType(psiClass, substitutor); } }
private static CompoundInitialState createState(InferenceSession topLevelSession) { final PsiSubstitutor topInferenceSubstitutor = replaceVariables(topLevelSession.getInferenceVariables()); final Map<PsiElement, InitialInferenceState> nestedStates = new LinkedHashMap<PsiElement, InitialInferenceState>(); final InferenceSessionContainer copy = new InferenceSessionContainer() { @Override public PsiSubstitutor findNestedSubstitutor( PsiElement arg, @Nullable PsiSubstitutor defaultSession) { // for the case foo(bar(a -> m())): top level inference won't touch lambda "a -> m()" // for the case foo(a -> bar(b -> m())): top level inference would go till nested lambda // "b -> m()" and the state from top level could be found here by "bar(b -> m())" // but proceeding with additional constraints from saved point would produce new // expression constraints with different inference variables (could be found in // myNestedSessions) // which won't be found in the system if we won't reject stored sessions in such cases final PsiSubstitutor substitutor = super.findNestedSubstitutor(arg, null); if (substitutor != null) { return substitutor; } final InitialInferenceState state = nestedStates.get(PsiTreeUtil.getParentOfType(arg, PsiCall.class)); if (state != null) { return state.getInferenceSubstitutor(); } return super.findNestedSubstitutor(arg, defaultSession); } }; final Map<PsiElement, InferenceSession> nestedSessions = topLevelSession.getInferenceSessionContainer().myNestedSessions; for (Map.Entry<PsiElement, InferenceSession> entry : nestedSessions.entrySet()) { nestedStates.put( entry.getKey(), entry .getValue() .createInitialState( copy, topLevelSession.getInferenceVariables(), topInferenceSubstitutor)); } PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; for (InferenceVariable variable : topLevelSession.getInferenceVariables()) { final PsiType instantiation = variable.getInstantiation(); if (instantiation != PsiType.NULL) { final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(topInferenceSubstitutor.substitute(variable)); if (psiClass instanceof InferenceVariable) { substitutor = substitutor.put((PsiTypeParameter) psiClass, instantiation); } } } return new CompoundInitialState(substitutor, nestedStates); }
@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 PsiSubstitutor upDownSuperClassSubstitutor() { PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(mySourceClass)) { substitutor = substitutor.put(parameter, null); } final Map<PsiTypeParameter, PsiType> substitutionMap = TypeConversionUtil.getSuperClassSubstitutor( myTargetSuperClass, mySourceClass, PsiSubstitutor.EMPTY) .getSubstitutionMap(); for (PsiTypeParameter parameter : substitutionMap.keySet()) { final PsiType type = substitutionMap.get(parameter); final PsiClass resolvedClass = PsiUtil.resolveClassInType(type); if (resolvedClass instanceof PsiTypeParameter) { substitutor = substitutor.put( (PsiTypeParameter) resolvedClass, JavaPsiFacade.getElementFactory(myProject).createType(parameter)); } } return substitutor; }
private void getVariantsFromQualifier(@NotNull GrExpression qualifier) { Project project = qualifier.getProject(); PsiType qualifierType = qualifier.getType(); final ResolveState state = ResolveState.initial(); if (qualifierType == null || qualifierType == PsiType.VOID) { if (qualifier instanceof GrReferenceExpression) { PsiElement resolved = ((GrReferenceExpression) qualifier).resolve(); if (resolved instanceof PsiPackage || resolved instanceof PsiVariable) { resolved.processDeclarations(myProcessor, state, null, myRefExpr); return; } } getVariantsFromQualifierType(TypesUtil.getJavaLangObject(qualifier), project); } else if (qualifierType instanceof PsiIntersectionType) { for (PsiType conjunct : ((PsiIntersectionType) qualifierType).getConjuncts()) { getVariantsFromQualifierType(conjunct, project); } } else if (qualifierType instanceof GrTraitType) { GrTypeDefinition definition = ((GrTraitType) qualifierType).getMockTypeDefinition(); if (definition != null) { PsiClassType classType = JavaPsiFacade.getElementFactory(project).createType(definition); getVariantsFromQualifierType(classType, project); } else { getVariantsFromQualifierType(((GrTraitType) qualifierType).getExprType(), project); for (PsiClassType traitType : ((GrTraitType) qualifierType).getTraitTypes()) { getVariantsFromQualifierType(traitType, project); } } } else { getVariantsFromQualifierType(qualifierType, project); if (qualifier instanceof GrReferenceExpression && !PsiUtil.isSuperReference(qualifier) && !PsiUtil.isInstanceThisRef(qualifier)) { PsiElement resolved = ((GrReferenceExpression) qualifier).resolve(); if (resolved instanceof PsiClass) { // //omitted .class GlobalSearchScope scope = myRefExpr.getResolveScope(); PsiClass javaLangClass = PsiUtil.getJavaLangClass(resolved, scope); if (javaLangClass != null) { PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters(); if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], qualifierType); } PsiType javaLangClassType = JavaPsiFacade.getElementFactory(myRefExpr.getProject()) .createType(javaLangClass, substitutor); ResolveUtil.processAllDeclarations(javaLangClassType, myProcessor, state, myRefExpr); } } } } }
public PsiType substitute(final PsiType t) { if (t instanceof PsiWildcardType) { final PsiWildcardType wcType = (PsiWildcardType) t; final PsiType bound = wcType.getBound(); if (bound == null) { return t; } final PsiManager manager = PsiManager.getInstance(myProject); final PsiType subst = substitute(bound); if (subst == null) return null; return subst instanceof PsiWildcardType ? subst : wcType.isExtends() ? PsiWildcardType.createExtends(manager, subst) : PsiWildcardType.createSuper(manager, subst); } else if (t instanceof PsiTypeVariable) { final PsiType b = apply(t); if (b instanceof Bottom || b instanceof PsiTypeVariable) { return null; } return substitute(b); } else if (t instanceof Bottom) { return null; } else if (t instanceof PsiArrayType) { return substitute(((PsiArrayType) t).getComponentType()).createArrayType(); } else if (t instanceof PsiClassType) { final PsiClassType.ClassResolveResult result = ((PsiClassType) t).resolveGenerics(); final PsiClass aClass = result.getElement(); final PsiSubstitutor aSubst = result.getSubstitutor(); if (aClass != null) { PsiSubstitutor theSubst = PsiSubstitutor.EMPTY; for (final PsiTypeParameter parm : aSubst.getSubstitutionMap().keySet()) { final PsiType type = aSubst.substitute(parm); theSubst = theSubst.put(parm, substitute(type)); } return JavaPsiFacade.getInstance(aClass.getProject()) .getElementFactory() .createType(aClass, theSubst); } } return t; }
@NotNull @Override public PsiClassType getArrayClassType( @NotNull final PsiType componentType, @NotNull final LanguageLevel languageLevel) { final PsiClass arrayClass = getArrayClass(languageLevel); final PsiTypeParameter[] typeParameters = arrayClass.getTypeParameters(); PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], componentType); } return createType(arrayClass, substitutor); }
private PsiClassType createEnumType() { JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); PsiClass enumClass = facade.findClass(JAVA_LANG_ENUM, getResolveScope()); PsiElementFactory factory = facade.getElementFactory(); if (enumClass != null) { PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; PsiTypeParameter[] typeParameters = enumClass.getTypeParameters(); if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], factory.createType(this)); } return factory.createType(enumClass, substitutor); } return TypesUtil.createTypeByFQClassName(JAVA_LANG_ENUM, this); }
@Nullable public static PsiType createJavaLangClassType( @Nullable PsiType type, Project project, GlobalSearchScope resolveScope) { final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); PsiType result = null; PsiClass javaLangClass = facade.findClass(JAVA_LANG_CLASS, resolveScope); if (javaLangClass != null) { PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; final PsiTypeParameter[] typeParameters = javaLangClass.getTypeParameters(); if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], type); } result = facade.getElementFactory().createType(javaLangClass, substitutor); } return result; }
public PsiType apply(final PsiType type) { if (type instanceof PsiTypeVariable) { final PsiType t = myBindings.get(((PsiTypeVariable) type).getIndex()); return t == null ? type : t; } else if (type instanceof PsiArrayType) { return apply(((PsiArrayType) type).getComponentType()).createArrayType(); } else if (type instanceof PsiClassType) { final PsiClassType.ClassResolveResult result = Util.resolveType(type); final PsiClass theClass = result.getElement(); final PsiSubstitutor aSubst = result.getSubstitutor(); PsiSubstitutor theSubst = PsiSubstitutor.EMPTY; if (theClass != null) { for (final PsiTypeParameter aParm : aSubst.getSubstitutionMap().keySet()) { final PsiType aType = aSubst.substitute(aParm); theSubst = theSubst.put(aParm, apply(aType)); } return JavaPsiFacade.getInstance(theClass.getProject()) .getElementFactory() .createType(theClass, theSubst); } else { return type; } } else if (type instanceof PsiWildcardType) { final PsiWildcardType wcType = (PsiWildcardType) type; final PsiType bound = wcType.getBound(); if (bound != null) { final PsiType abound = apply(bound); if (abound instanceof PsiWildcardType) { return null; } return wcType.isExtends() ? PsiWildcardType.createExtends(PsiManager.getInstance(myProject), abound) : PsiWildcardType.createSuper(PsiManager.getInstance(myProject), abound); } return type; } else { return type; } }
private static PsiSubstitutor getSuperClassSubstitutor( final PsiType superClassType, final PsiClassType targetClassType, final PsiResolveHelper resolveHelper, PsiClass targetClass) { PsiSubstitutor subst = PsiSubstitutor.EMPTY; for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(targetClass)) { subst = subst.put( typeParameter, resolveHelper.getSubstitutionForTypeParameter( typeParameter, targetClassType, superClassType, false, PsiUtil.getLanguageLevel(targetClass))); } return subst; }
@Nullable private static PsiSubstitutor getSuperMethodSignatureSubstitutorImpl( @NotNull MethodSignature methodSignature, @NotNull MethodSignature superSignature) { // normalize generic method declarations: correlate type parameters // todo: correlate type params by name? PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters(); PsiTypeParameter[] superTypeParameters = superSignature.getTypeParameters(); // both methods are parameterized and number of parameters mismatch if (methodTypeParameters.length != superTypeParameters.length) return null; PsiSubstitutor result = superSignature.getSubstitutor(); for (int i = 0; i < methodTypeParameters.length; i++) { PsiTypeParameter methodTypeParameter = methodTypeParameters[i]; PsiElementFactory factory = JavaPsiFacade.getInstance(methodTypeParameter.getProject()).getElementFactory(); result = result.put(superTypeParameters[i], factory.createType(methodTypeParameter)); } return result; }
private static PsiClassType getEnumSuperType( @NotNull PsiClass psiClass, @NotNull PsiElementFactory factory) { PsiClassType superType; final PsiManager manager = psiClass.getManager(); final PsiClass enumClass = JavaPsiFacade.getInstance(manager.getProject()) .findClass("java.lang.Enum", psiClass.getResolveScope()); if (enumClass == null) { try { superType = (PsiClassType) factory.createTypeFromText("java.lang.Enum", null); } catch (IncorrectOperationException e) { superType = null; } } else { final PsiTypeParameter[] typeParameters = enumClass.getTypeParameters(); PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; if (typeParameters.length == 1) { substitutor = substitutor.put(typeParameters[0], factory.createType(psiClass)); } superType = new PsiImmediateClassType(enumClass, substitutor); } return superType; }
public static PsiSubstitutor combineSubstitutors( PsiSubstitutor substitutor1, PsiSubstitutor substitutor2) { if (substitutor1 == PsiSubstitutor.EMPTY) return substitutor2; Set<PsiTypeParameter> parameters1 = substitutor1.getSubstitutionMap().keySet(); final PsiTypeParameter[] typeParameters = parameters1.toArray(new PsiTypeParameter[parameters1.size()]); for (PsiTypeParameter typeParameter : typeParameters) { final PsiType type = substitutor1.substitute(typeParameter); PsiType otherSubstituted; if (type instanceof PsiClassType) { final PsiClass resolved = ((PsiClassType) type).resolve(); otherSubstituted = resolved instanceof PsiTypeParameter ? substitutor2.substitute((PsiTypeParameter) resolved) : substitutor2.substitute(type); } else { otherSubstituted = substitutor2.substitute(type); } substitutor1 = substitutor1.put(typeParameter, otherSubstituted); } return substitutor1; }
@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; }