@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; }
private static Map<ClassDescriptor, JetType> getSuperclassToSupertypeMap( ClassDescriptor containingClass) { Map<ClassDescriptor, JetType> superclassToSupertype = Maps.newHashMap(); for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) { ClassifierDescriptor superclass = supertype.getConstructor().getDeclarationDescriptor(); assert superclass instanceof ClassDescriptor; superclassToSupertype.put((ClassDescriptor) superclass, supertype); } return superclassToSupertype; }
@NotNull private ClassifierDescriptor modifyTypeClassifier( @NotNull JetType autoType, @NotNull List<TypeAndVariance> typesFromSuper) { ClassifierDescriptor classifier = autoType.getConstructor().getDeclarationDescriptor(); if (!(classifier instanceof ClassDescriptor)) { assert classifier != null : "no declaration descriptor for type " + autoType; if (classifier instanceof TypeParameterDescriptor && autoTypeParameterToModified.containsKey(classifier)) { return autoTypeParameterToModified.get(classifier); } return classifier; } ClassDescriptor klass = (ClassDescriptor) classifier; CollectionClassMapping collectionMapping = CollectionClassMapping.getInstance(); boolean someSupersMutable = false; boolean someSupersCovariantReadOnly = false; boolean someSupersNotCovariantReadOnly = false; for (TypeAndVariance typeFromSuper : typesFromSuper) { ClassifierDescriptor classifierFromSuper = typeFromSuper.type.getConstructor().getDeclarationDescriptor(); if (classifierFromSuper instanceof ClassDescriptor) { ClassDescriptor classFromSuper = (ClassDescriptor) classifierFromSuper; if (collectionMapping.isMutableCollection(classFromSuper)) { someSupersMutable = true; } else if (collectionMapping.isReadOnlyCollection(classFromSuper)) { if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) { someSupersCovariantReadOnly = true; } else { someSupersNotCovariantReadOnly = true; } } } } if (someSupersMutable && someSupersNotCovariantReadOnly) { reportError("Incompatible types in superclasses: " + typesFromSuper); return classifier; } else if (someSupersMutable) { if (collectionMapping.isReadOnlyCollection(klass)) { return collectionMapping.convertReadOnlyToMutable(klass); } } else if (someSupersNotCovariantReadOnly || someSupersCovariantReadOnly) { if (collectionMapping.isMutableCollection(klass)) { return collectionMapping.convertMutableToReadOnly(klass); } } ClassifierDescriptor fixed = PropagationHeuristics.tryToFixOverridingTWithRawType(this, typesFromSuper); return fixed != null ? fixed : classifier; }