@NotNull private static Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> getSuperclassToFunctionsMultimap( @NotNull PsiMethodWrapper method, @NotNull BindingContext bindingContext, @NotNull ClassDescriptor containingClass) { Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> result = HashMultimap.create(); Name functionName = Name.identifier(method.getName()); int parameterCount = method.getParameters().size(); for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) { ClassifierDescriptor klass = supertype.getConstructor().getDeclarationDescriptor(); assert klass != null; FqName fqName = DescriptorUtils.getFQName(klass).toSafe(); for (FunctionDescriptor fun : klass.getDefaultType().getMemberScope().getFunctions(functionName)) { if (fun.getKind().isReal() && fun.getValueParameters().size() == parameterCount) { PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun); if (declaration instanceof PsiMethod) { result.put(fqName, Pair.create(fun, (PsiMethod) declaration)); } // else declaration is null or JetNamedFunction: both cases are processed later } } } return result; }
@NotNull private VarargCheckResult checkVarargInSuperFunctions( @NotNull ValueParameterDescriptor originalParam) { boolean someSupersVararg = false; boolean someSupersNotVararg = false; for (FunctionDescriptor superFunction : superFunctions) { if (superFunction.getValueParameters().get(originalParam.getIndex()).getVarargElementType() != null) { someSupersVararg = true; } else { someSupersNotVararg = true; } } JetType originalVarargElementType = originalParam.getVarargElementType(); JetType originalType = originalParam.getType(); if (someSupersVararg && someSupersNotVararg) { reportError("Incompatible super methods: some have vararg parameter, some have not"); return new VarargCheckResult(originalType, originalVarargElementType != null); } KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); if (someSupersVararg && originalVarargElementType == null) { // convert to vararg assert isArrayType(originalType); if (builtIns.isPrimitiveArray(originalType)) { // replace IntArray? with IntArray return new VarargCheckResult(TypeUtils.makeNotNullable(originalType), true); } // replace Array<out Foo>? with Array<Foo> JetType varargElementType = builtIns.getArrayElementType(originalType); return new VarargCheckResult(builtIns.getArrayType(INVARIANT, varargElementType), true); } else if (someSupersNotVararg && originalVarargElementType != null) { // convert to non-vararg assert isArrayType(originalType); if (builtIns.isPrimitiveArray(originalType)) { // replace IntArray with IntArray? return new VarargCheckResult(TypeUtils.makeNullable(originalType), false); } // replace Array<Foo> with Array<out Foo>? return new VarargCheckResult( TypeUtils.makeNullable( builtIns.getArrayType(Variance.OUT_VARIANCE, originalVarargElementType)), false); } return new VarargCheckResult(originalType, originalVarargElementType != null); }
@NotNull private static FunctionDescriptor substituteSuperFunction( @NotNull Map<ClassDescriptor, JetType> superclassToSupertype, @NotNull FunctionDescriptor superFun) { DeclarationDescriptor superFunContainer = superFun.getContainingDeclaration(); assert superFunContainer instanceof ClassDescriptor : superFunContainer; JetType supertype = superclassToSupertype.get(superFunContainer); assert supertype != null : "Couldn't find super type for super function: " + superFun; TypeSubstitutor supertypeSubstitutor = TypeSubstitutor.create(supertype); FunctionDescriptor substitutedSuperFun = superFun.substitute(supertypeSubstitutor); assert substitutedSuperFun != null; return substitutedSuperFun; }
private List<TypeParameterDescriptor> modifyTypeParametersAccordingToSuperMethods( List<TypeParameterDescriptor> autoTypeParameters) { List<TypeParameterDescriptor> result = Lists.newArrayList(); for (TypeParameterDescriptor autoParameter : autoTypeParameters) { int index = autoParameter.getIndex(); TypeParameterDescriptorImpl modifiedTypeParameter = autoTypeParameterToModified.get(autoParameter); List<Iterator<JetType>> upperBoundFromSuperFunctionsIterators = Lists.newArrayList(); for (FunctionDescriptor superFunction : superFunctions) { upperBoundFromSuperFunctionsIterators.add( superFunction.getTypeParameters().get(index).getUpperBounds().iterator()); } for (JetType autoUpperBound : autoParameter.getUpperBounds()) { List<TypeAndVariance> upperBoundsFromSuperFunctions = Lists.newArrayList(); for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) { assert iterator.hasNext(); upperBoundsFromSuperFunctions.add(new TypeAndVariance(iterator.next(), INVARIANT)); } JetType modifiedUpperBound = modifyTypeAccordingToSuperMethods( autoUpperBound, upperBoundsFromSuperFunctions, UPPER_BOUND); modifiedTypeParameter.addUpperBound(modifiedUpperBound); } for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) { assert !iterator.hasNext(); } modifiedTypeParameter.setInitialized(); result.add(modifiedTypeParameter); } return result; }