private void resolvePropertyDeclarationBodies(@NotNull BodiesResolveContext c) { // Member properties Set<JetProperty> processed = Sets.newHashSet(); for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) { if (!(entry.getKey() instanceof JetClass)) continue; JetClass jetClass = (JetClass) entry.getKey(); ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue(); for (JetProperty property : jetClass.getProperties()) { PropertyDescriptor propertyDescriptor = c.getProperties().get(property); assert propertyDescriptor != null; resolveProperty( c, classDescriptor.getScopeForMemberDeclarationResolution(), property, propertyDescriptor); processed.add(property); } } // Top-level properties & properties of objects for (Map.Entry<JetProperty, PropertyDescriptor> entry : c.getProperties().entrySet()) { JetProperty property = entry.getKey(); if (processed.contains(property)) continue; PropertyDescriptor propertyDescriptor = entry.getValue(); resolveProperty(c, null, property, propertyDescriptor); } }
private void checkSupertypesForConsistency(@NotNull ClassDescriptor classDescriptor) { Multimap<TypeConstructor, TypeProjection> multimap = SubstitutionUtils.buildDeepSubstitutionMultimap(classDescriptor.getDefaultType()); for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) { Collection<TypeProjection> projections = entry.getValue(); if (projections.size() > 1) { TypeConstructor typeConstructor = entry.getKey(); DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor(); assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor; TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; // Immediate arguments of supertypes cannot be projected Set<JetType> conflictingTypes = Sets.newLinkedHashSet(); for (TypeProjection projection : projections) { conflictingTypes.add(projection.getType()); } removeDuplicateTypes(conflictingTypes); if (conflictingTypes.size() > 1) { DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration(); assert containingDeclaration instanceof ClassDescriptor : containingDeclaration; JetClassOrObject psiElement = (JetClassOrObject) DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor); assert psiElement != null; JetDelegationSpecifierList delegationSpecifierList = psiElement.getDelegationSpecifierList(); assert delegationSpecifierList != null; // // trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter // " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + " // has inconsistent values: " + conflictingTypes); trace.report( INCONSISTENT_TYPE_PARAMETER_VALUES.on( delegationSpecifierList, typeParameterDescriptor, (ClassDescriptor) containingDeclaration, conflictingTypes)); } } } }
private static void removeDuplicateTypes(Set<JetType> conflictingTypes) { for (Iterator<JetType> iterator = conflictingTypes.iterator(); iterator.hasNext(); ) { JetType type = iterator.next(); for (JetType otherType : conflictingTypes) { boolean subtypeOf = JetTypeChecker.DEFAULT.equalTypes(type, otherType); if (type != otherType && subtypeOf) { iterator.remove(); break; } } } }
private void checkCyclicConstructorDelegationCall( @NotNull ConstructorDescriptor constructorDescriptor, @NotNull Set<ConstructorDescriptor> visitedConstructors) { if (visitedConstructors.contains(constructorDescriptor)) return; // if visit constructor that is already in current chain // such constructor is on cycle Set<ConstructorDescriptor> visitedInCurrentChain = Sets.newHashSet(); ConstructorDescriptor currentConstructorDescriptor = constructorDescriptor; while (true) { visitedInCurrentChain.add(currentConstructorDescriptor); ConstructorDescriptor delegatedConstructorDescriptor = getDelegatedConstructor(currentConstructorDescriptor); if (delegatedConstructorDescriptor == null) break; // if next delegation call is super or primary constructor or already visited if (!constructorDescriptor .getContainingDeclaration() .equals(delegatedConstructorDescriptor.getContainingDeclaration()) || delegatedConstructorDescriptor.isPrimary() || visitedConstructors.contains(delegatedConstructorDescriptor)) { break; } if (visitedInCurrentChain.contains(delegatedConstructorDescriptor)) { reportEachConstructorOnCycle(delegatedConstructorDescriptor); break; } currentConstructorDescriptor = delegatedConstructorDescriptor; } visitedConstructors.addAll(visitedInCurrentChain); }
// Returns a set of enum or sealed types of which supertypeOwner is an entry or a member @NotNull private static Set<TypeConstructor> getAllowedFinalSupertypes( @NotNull ClassDescriptor descriptor, @NotNull JetClassOrObject jetClass) { Set<TypeConstructor> parentEnumOrSealed; if (jetClass instanceof JetEnumEntry) { parentEnumOrSealed = Collections.singleton( ((ClassDescriptor) descriptor.getContainingDeclaration()).getTypeConstructor()); } else { parentEnumOrSealed = Collections.emptySet(); ClassDescriptor currentDescriptor = descriptor; while (currentDescriptor.getContainingDeclaration() instanceof ClassDescriptor) { currentDescriptor = (ClassDescriptor) currentDescriptor.getContainingDeclaration(); if (currentDescriptor.getModality() == Modality.SEALED) { if (parentEnumOrSealed.isEmpty()) { parentEnumOrSealed = new HashSet<TypeConstructor>(); } parentEnumOrSealed.add(currentDescriptor.getTypeConstructor()); } } } return parentEnumOrSealed; }
private void checkSupertypeList( @NotNull ClassDescriptor supertypeOwner, @NotNull Map<JetTypeReference, JetType> supertypes, @NotNull JetClassOrObject jetClass) { Set<TypeConstructor> allowedFinalSupertypes = getAllowedFinalSupertypes(supertypeOwner, jetClass); Set<TypeConstructor> typeConstructors = Sets.newHashSet(); boolean classAppeared = false; for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) { JetTypeReference typeReference = entry.getKey(); JetType supertype = entry.getValue(); boolean addSupertype = true; ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); if (classDescriptor != null) { if (ErrorUtils.isError(classDescriptor)) continue; if (classDescriptor.getKind() != ClassKind.INTERFACE) { if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) { trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference)); addSupertype = false; } else if (supertypeOwner.getKind() == ClassKind.INTERFACE && !classAppeared && !TypesPackage.isDynamic(supertype) /* avoid duplicate diagnostics */) { trace.report(TRAIT_WITH_SUPERCLASS.on(typeReference)); addSupertype = false; } if (classAppeared) { trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference)); } else { classAppeared = true; } } } else { trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference)); } TypeConstructor constructor = supertype.getConstructor(); if (addSupertype && !typeConstructors.add(constructor)) { trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference)); } if (DescriptorUtils.isSingleton(classDescriptor)) { trace.report(SINGLETON_IN_SUPERTYPE.on(typeReference)); } else if (constructor.isFinal() && !allowedFinalSupertypes.contains(constructor)) { if (classDescriptor.getModality() == Modality.SEALED) { DeclarationDescriptor containingDescriptor = supertypeOwner.getContainingDeclaration(); while (containingDescriptor != null && containingDescriptor != classDescriptor) { containingDescriptor = containingDescriptor.getContainingDeclaration(); } if (containingDescriptor == null) { trace.report(SEALED_SUPERTYPE.on(typeReference)); } else { trace.report(SEALED_SUPERTYPE_IN_LOCAL_CLASS.on(typeReference)); } } else { trace.report(FINAL_SUPERTYPE.on(typeReference)); } } } }