private static PsiSubstitutor obtainFinalSubstitutor( PsiClass superClass, PsiSubstitutor superSubstitutor, PsiSubstitutor derivedSubstitutor, boolean inRawContext) { if (inRawContext) { Set<PsiTypeParameter> typeParams = superSubstitutor.getSubstitutionMap().keySet(); PsiElementFactory factory = JavaPsiFacade.getElementFactory(superClass.getProject()); superSubstitutor = factory.createRawSubstitutor( derivedSubstitutor, typeParams.toArray(new PsiTypeParameter[typeParams.size()])); } Map<PsiTypeParameter, PsiType> map = null; for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(superClass)) { PsiType type = superSubstitutor.substitute(typeParameter); final PsiType t = derivedSubstitutor.substitute(type); if (map == null) { map = new THashMap<PsiTypeParameter, PsiType>(); } map.put(typeParameter, t); } return map == null ? PsiSubstitutor.EMPTY : JavaPsiFacade.getInstance(superClass.getProject()) .getElementFactory() .createSubstitutor(map); }
/* 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; }
private Binding unify(final PsiType x, final PsiType y, final Unifier unifier) { final int indicator = (x instanceof PsiTypeVariable ? 1 : 0) + (y instanceof PsiTypeVariable ? 2 : 0); switch (indicator) { case 0: if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) { return unifier.unify(x, y); } 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 unify(xType, yType, unifier); } 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(); final PsiSubstitutor xSubst = resultX.getSubstitutor(); if (!xClass.equals(yClass)) { 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, unifier); if (b1 == null) { return null; } b = b.compose(b1); } return b; } } else if (y instanceof Bottom) { return create(); } else { return null; } default: return unifier.unify(x, y); } }
/** a = S & a <: T imply S <: T or a = S & T <: a imply T <: S or S <: a & a <: T imply S <: T */ private void upDown( List<PsiType> eqBounds, List<PsiType> upperBounds, PsiSubstitutor substitutor) { for (PsiType upperBound : upperBounds) { if (upperBound == null) continue; for (PsiType eqBound : eqBounds) { if (eqBound == null) continue; addConstraint( new StrictSubtypingConstraint( substitutor.substitute(upperBound), substitutor.substitute(eqBound))); } } }
public static void replaceMovedMemberTypeParameters( final PsiElement member, final Iterable<PsiTypeParameter> parametersIterable, final PsiSubstitutor substitutor, final GroovyPsiElementFactory factory) { final Map<PsiElement, PsiElement> replacement = new LinkedHashMap<PsiElement, PsiElement>(); for (PsiTypeParameter parameter : parametersIterable) { PsiType substitutedType = substitutor.substitute(parameter); if (substitutedType == null) { substitutedType = TypeConversionUtil.erasure(factory.createType(parameter)); } PsiElement scopeElement = member instanceof GrField ? member.getParent() : member; for (PsiReference reference : ReferencesSearch.search(parameter, new LocalSearchScope(scopeElement))) { final PsiElement element = reference.getElement(); final PsiElement parent = element.getParent(); if (parent instanceof PsiTypeElement) { replacement.put(parent, factory.createTypeElement(substitutedType)); } else if (element instanceof GrCodeReferenceElement && substitutedType instanceof PsiClassType) { replacement.put( element, factory.createReferenceElementByType((PsiClassType) substitutedType)); } } } for (PsiElement element : replacement.keySet()) { if (element.isValid()) { element.replace(replacement.get(element)); } } }
@Nullable private static String formatTypeParameters( @NotNull final PsiSubstitutor substitutor, final PsiTypeParameter[] params) { final boolean space = showSpaceAfterComma(params[0]); StringBuilder buffer = new StringBuilder(); buffer.append("<"); for (int i = 0; i < params.length; i++) { final PsiTypeParameter param = params[i]; final PsiType type = substitutor.substitute(param); if (type == null) { return ""; } if (type instanceof PsiClassType && ((PsiClassType) type).getParameters().length > 0) { buffer.append(((PsiClassType) type).rawType().getPresentableText()).append("<...>"); } else { buffer.append(type.getPresentableText()); } if (i < params.length - 1) { buffer.append(","); if (space) { buffer.append(" "); } } } buffer.append(">"); return buffer.toString(); }
@Override public boolean execute(PsiElement element, ResolveState state) { if (element instanceof PsiMethod || element instanceof PsiField) { String propertyName; PsiType type; if (element instanceof PsiMethod) { PsiMethod method = (PsiMethod) element; if (!GroovyPropertyUtils.isSimplePropertySetter(method)) return true; propertyName = GroovyPropertyUtils.getPropertyNameBySetter(method); if (propertyName == null) return true; type = method.getParameterList().getParameters()[0].getType(); } else { type = ((PsiField) element).getType(); propertyName = ((PsiField) element).getName(); } if (((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC)) return true; if (myResult.containsKey(propertyName) || propertyName.equals(METACLASS)) return true; PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY); if (substitutor != null) { type = substitutor.substitute(type); } myResult.put(propertyName, new TypeCondition(type, element)); } return true; }
@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; }
@Nullable private static PsiType getExpectedTypeArg( PsiElement context, int index, PsiClassType.ClassResolveResult expectedType, PsiSubstitutor currentSubstitutor, PsiTypeParameter[] params) { PsiClass expectedClass = expectedType.getElement(); assert expectedClass != null; for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(expectedClass)) { final PsiType argSubstitution = expectedType.getSubstitutor().substitute(parameter); final PsiType paramSubstitution = currentSubstitutor.substitute(parameter); final PsiType substitution = JavaPsiFacade.getInstance(context.getProject()) .getResolveHelper() .getSubstitutionForTypeParameter( params[index], paramSubstitution, argSubstitution, false, PsiUtil.getLanguageLevel(context)); if (substitution != null && substitution != PsiType.NULL) { return substitution; } } return null; }
public String calcGenerics(@NotNull PsiElement context, InsertionContext insertionContext) { if (insertionContext.getCompletionChar() == '<') { return ""; } assert context.isValid(); if (myDiamond) { return "<>"; } if (getObject() instanceof PsiClass) { PsiClass psiClass = (PsiClass) getObject(); PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper(); PsiSubstitutor substitutor = getSubstitutor(); StringBuilder builder = new StringBuilder(); for (PsiTypeParameter parameter : psiClass.getTypeParameters()) { PsiType substitute = substitutor.substitute(parameter); if (substitute == null || (PsiUtil.resolveClassInType(substitute) == parameter && resolveHelper.resolveReferencedClass(parameter.getName(), context) != CompletionUtil.getOriginalOrSelf(parameter))) { return ""; } if (builder.length() > 0) { builder.append(", "); } builder.append(substitute.getCanonicalText()); } if (builder.length() > 0) { return "<" + builder + ">"; } } return ""; }
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 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; }
@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; }
public GrImmediateClosureParameterImpl( @NotNull PsiParameter parameter, @NotNull PsiSubstitutor substitutor) { this( substitutor.substitute(getParameterType(parameter)), getParameterName(parameter), isParameterOptional(parameter), getDefaultInitializer(parameter)); }
public void testInferWithBounds1() throws Exception { PsiReferenceExpression ref = configure(); JavaResolveResult resolveResult = ref.advancedResolve(false); PsiSubstitutor substitutor = resolveResult.getSubstitutor(); PsiMethod method = (PsiMethod) resolveResult.getElement(); PsiType type = substitutor.substitute(method.getTypeParameters()[0]); assertEquals("java.lang.String", type.getCanonicalText()); }
@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); } }
@NotNull private static PsiType[] typesAtSite( @NotNull PsiType[] types1, @NotNull PsiSubstitutor siteSubstitutor1) { final PsiType[] types = PsiType.createArray(types1.length); for (int i = 0; i < types1.length; i++) { types[i] = siteSubstitutor1.substitute(types1[i]); } return types; }
private int substituteToTypeParameters( PsiTypeElement typeElement, PsiTypeElement inplaceTypeElement, PsiType[] paramVals, PsiTypeParameter[] params, TemplateBuilder builder, PsiSubstitutor rawingSubstitutor, boolean toplevel) { PsiType type = inplaceTypeElement.getType(); List<PsiType> types = new ArrayList<>(); for (int i = 0; i < paramVals.length; i++) { PsiType val = paramVals[i]; if (val == null) return SUBSTITUTED_NONE; if (type.equals(val)) { types.add(myFactory.createType(params[i])); } } if (!types.isEmpty()) { Project project = typeElement.getProject(); PsiType substituted = rawingSubstitutor.substitute(type); if (!CommonClassNames.JAVA_LANG_OBJECT.equals(substituted.getCanonicalText()) && (toplevel || substituted.equals(type))) { types.add(substituted); } builder.replaceElement( typeElement, new TypeExpression(project, types.toArray(PsiType.createArray(types.size())))); return toplevel ? SUBSTITUTED_IN_REF : SUBSTITUTED_IN_PARAMETERS; } boolean substituted = false; PsiJavaCodeReferenceElement ref = typeElement.getInnermostComponentReferenceElement(); PsiJavaCodeReferenceElement inplaceRef = inplaceTypeElement.getInnermostComponentReferenceElement(); if (ref != null) { LOG.assertTrue(inplaceRef != null); PsiTypeElement[] innerTypeElements = ref.getParameterList().getTypeParameterElements(); PsiTypeElement[] inplaceInnerTypeElements = inplaceRef.getParameterList().getTypeParameterElements(); for (int i = 0; i < innerTypeElements.length; i++) { substituted |= substituteToTypeParameters( innerTypeElements[i], inplaceInnerTypeElements[i], paramVals, params, builder, rawingSubstitutor, false) != SUBSTITUTED_NONE; } } return substituted ? SUBSTITUTED_IN_PARAMETERS : SUBSTITUTED_NONE; }
private static PsiParameter createNewParameter( JavaChangeInfo changeInfo, JavaParameterInfo newParm, PsiSubstitutor substitutor) throws IncorrectOperationException { final PsiParameterList list = changeInfo.getMethod().getParameterList(); final PsiElementFactory factory = JavaPsiFacade.getInstance(list.getProject()).getElementFactory(); final PsiType type = substitutor.substitute(newParm.createType(list, list.getManager())); return factory.createParameter(newParm.getName(), type); }
private static boolean changeClassTypeArgument( PsiMethod myMethod, Project project, PsiType superReturnType, PsiClass superClass, Editor editor, PsiType returnType) { if (superClass == null || !superClass.hasTypeParameters()) return true; final PsiClass superReturnTypeClass = PsiUtil.resolveClassInType(superReturnType); if (superReturnTypeClass == null || !(superReturnTypeClass instanceof PsiTypeParameter || superReturnTypeClass.hasTypeParameters())) return true; final PsiClass derivedClass = myMethod.getContainingClass(); if (derivedClass == null) return true; final PsiReferenceParameterList referenceParameterList = findTypeArgumentsList(superClass, derivedClass); if (referenceParameterList == null) return true; final PsiElement resolve = ((PsiJavaCodeReferenceElement) referenceParameterList.getParent()).resolve(); if (!(resolve instanceof PsiClass)) return true; final PsiClass baseClass = (PsiClass) resolve; if (returnType instanceof PsiPrimitiveType) { returnType = ((PsiPrimitiveType) returnType).getBoxedType(derivedClass); } final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, baseClass, PsiSubstitutor.EMPTY); final PsiType superReturnTypeInBaseClassType = superClassSubstitutor.substitute(superReturnType); final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper(); final PsiSubstitutor psiSubstitutor = resolveHelper.inferTypeArguments( PsiTypesUtil.filterUnusedTypeParameters( superReturnTypeInBaseClassType, baseClass.getTypeParameters()), new PsiType[] {superReturnTypeInBaseClassType}, new PsiType[] {returnType}, PsiUtil.getLanguageLevel(superClass)); final TypeMigrationRules rules = new TypeMigrationRules(); final PsiSubstitutor compoundSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, derivedClass, PsiSubstitutor.EMPTY) .putAll(psiSubstitutor); rules.setBoundScope(new LocalSearchScope(derivedClass)); TypeMigrationProcessor.runHighlightingTypeMigration( project, editor, rules, referenceParameterList, JavaPsiFacade.getElementFactory(project).createType(baseClass, compoundSubstitutor)); return false; }
@Nullable @Override protected List<ClosureParameterInfo> getParameterInfos( InsertionContext context, PsiMethod method, PsiSubstitutor substitutor, Document document, int offset, PsiElement parent) { final String name = method.getName(); if (!"eachWithIndex".equals(name)) return null; if (method instanceof GrGdkMethod) method = ((GrGdkMethod) method).getStaticMethod(); final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) return null; final String qname = containingClass.getQualifiedName(); if (!GroovyCommonClassNames.DEFAULT_GROOVY_METHODS.equals(qname)) return null; final PsiParameter[] parameters = method.getParameterList().getParameters(); if (parameters.length != 2) return null; final PsiType type = parameters[0].getType(); final PsiType collection = substitutor.substitute(type); final PsiType iterable = getIteratedType(parent, collection); if (iterable != null) { return Arrays.asList( new ClosureParameterInfo(iterable.getCanonicalText(), "entry"), new ClosureParameterInfo("int", "i")); } if (InheritanceUtil.isInheritor(collection, CommonClassNames.JAVA_UTIL_MAP)) { final PsiType[] typeParams = ((PsiClassType) collection).getParameters(); final Project project = context.getProject(); final PsiClass entry = JavaPsiFacade.getInstance(project) .findClass("java.util.Map.Entry", parent.getResolveScope()); if (entry == null) return null; final PsiClassType entryType = JavaPsiFacade.getElementFactory(project).createType(entry, typeParams); return Arrays.asList( new ClosureParameterInfo(entryType.getCanonicalText(), "entry"), new ClosureParameterInfo("int", "i")); } return Arrays.asList( new ClosureParameterInfo(collection.getCanonicalText(), "entry"), new ClosureParameterInfo("int", "i")); }
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); }
private static boolean checkSignaturesEqualInner( @NotNull MethodSignature subSignature, @NotNull MethodSignature superSignature, final PsiSubstitutor unifyingSubstitutor) { if (unifyingSubstitutor == null) return false; if (!areErasedParametersEqual(subSignature, superSignature)) return false; final PsiType[] subParameterTypes = subSignature.getParameterTypes(); final PsiType[] superParameterTypes = superSignature.getParameterTypes(); for (int i = 0; i < subParameterTypes.length; i++) { final PsiType type1 = unifyingSubstitutor.substitute(subParameterTypes[i]); final PsiType type2 = unifyingSubstitutor.substitute(superParameterTypes[i]); if (!Comparing.equal(type1, type2)) { return false; } } return true; }
@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; }
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 PsiType captureReturnType( PsiMethodCallExpression call, PsiMethod method, PsiType ret, JavaResolveResult result, LanguageLevel languageLevel) { PsiSubstitutor substitutor = result.getSubstitutor(); PsiType substitutedReturnType = substitutor.substitute(ret); if (substitutedReturnType == null) { return TypeConversionUtil.erasure(ret); } if (InferenceSession.wasUncheckedConversionPerformed(call)) { // 18.5.2 // if unchecked conversion was necessary, then this substitution provides the parameter types // of the invocation type, // while the return type and thrown types are given by the erasure of m's type (without // applying θ'). // due to https://bugs.openjdk.java.net/browse/JDK-8135087 erasure is called on // substitutedReturnType and not on ret type itself as by spec return TypeConversionUtil.erasure(substitutedReturnType); } // 15.12.2.6. Method Invocation Type // If unchecked conversion was necessary for the method to be applicable, // the parameter types of the invocation type are the parameter types of the method's type, // and the return type and thrown types are given by the erasures of the return type and thrown // types of the method's type. if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && (method.hasTypeParameters() || JavaVersionService.getInstance().isAtLeast(call, JavaSdkVersion.JDK_1_8)) && result instanceof MethodCandidateInfo && ((MethodCandidateInfo) result).isApplicable()) { final PsiType[] args = call.getArgumentList().getExpressionTypes(); final boolean allowUncheckedConversion = false; final int applicabilityLevel = PsiUtil.getApplicabilityLevel( method, substitutor, args, languageLevel, allowUncheckedConversion, true); if (applicabilityLevel == MethodCandidateInfo.ApplicabilityLevel.NOT_APPLICABLE) { return TypeConversionUtil.erasure(substitutedReturnType); } } if (PsiUtil.isRawSubstitutor(method, substitutor)) { final PsiType returnTypeErasure = TypeConversionUtil.erasure(ret); if (Comparing.equal(TypeConversionUtil.erasure(substitutedReturnType), returnTypeErasure)) { return returnTypeErasure; } } return PsiUtil.captureToplevelWildcards(substitutedReturnType, call); }
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; }
/** * @param methodSignature method signature * @param superMethodSignature super method signature * @return null if signatures do not match */ @Nullable public static PsiSubstitutor getSuperMethodSignatureSubstitutor( @NotNull MethodSignature methodSignature, @NotNull MethodSignature superMethodSignature) { PsiSubstitutor result = getSuperMethodSignatureSubstitutorImpl(methodSignature, superMethodSignature); if (result == null) return null; PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters(); PsiTypeParameter[] superTypeParameters = superMethodSignature.getTypeParameters(); PsiSubstitutor methodSubstitutor = methodSignature.getSubstitutor(); // check bounds for (int i = 0; i < methodTypeParameters.length; i++) { PsiTypeParameter methodTypeParameter = methodTypeParameters[i]; PsiTypeParameter superTypeParameter = superTypeParameters[i]; final Set<PsiType> methodSupers = new HashSet<PsiType>(); for (PsiClassType methodSuper : methodTypeParameter.getSuperTypes()) { methodSupers.add(methodSubstitutor.substitute(methodSuper)); } final Set<PsiType> superSupers = new HashSet<PsiType>(); for (PsiClassType superSuper : superTypeParameter.getSuperTypes()) { superSupers.add( methodSubstitutor.substitute( PsiUtil.captureToplevelWildcards( result.substitute(superSuper), methodTypeParameter))); } methodSupers.remove( PsiType.getJavaLangObject( methodTypeParameter.getManager(), methodTypeParameter.getResolveScope())); superSupers.remove( PsiType.getJavaLangObject( superTypeParameter.getManager(), superTypeParameter.getResolveScope())); if (!methodSupers.equals(superSupers)) return null; } return result; }
public static PsiSubstitutor composeSubstitutors(PsiSubstitutor s1, PsiSubstitutor s2) { final Map<PsiTypeParameter, PsiType> map = s1.getSubstitutionMap(); Map<PsiTypeParameter, PsiType> result = new THashMap<PsiTypeParameter, PsiType>(map.size()); for (PsiTypeParameter parameter : map.keySet()) { result.put(parameter, s2.substitute(map.get(parameter))); } final Map<PsiTypeParameter, PsiType> map2 = s2.getSubstitutionMap(); for (PsiTypeParameter parameter : map2.keySet()) { if (!result.containsKey(parameter)) { result.put(parameter, map2.get(parameter)); } } return PsiSubstitutorImpl.createSubstitutor(result); }
static boolean isArgumentInVarargPosition( PsiExpression[] expressions, int ei, PsiParameter varargParam, PsiSubstitutor substitutor) { if (varargParam == null) return false; final PsiExpression expression = expressions[ei]; if (expression == null || TypeConversionUtil.areTypesAssignmentCompatible( substitutor.substitute(((PsiEllipsisType) varargParam.getType()).getComponentType()), expression)) { final int lastExprIdx = expressions.length - 1; if (ei == lastExprIdx) return true; return expressions[lastExprIdx].getType() != PsiType.NULL; } return false; }