private static boolean isMoreSpecific( @NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) { if (a instanceof SimpleFunctionDescriptor) { assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass(); KotlinType aReturnType = a.getReturnType(); assert aReturnType != null; KotlinType bReturnType = b.getReturnType(); assert bReturnType != null; return KotlinTypeChecker.DEFAULT.isSubtypeOf(aReturnType, bReturnType); } if (a instanceof PropertyDescriptor) { assert b instanceof PropertyDescriptor : "b is " + b.getClass(); if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) { return ((PropertyDescriptor) a).isVar(); } // both vals return KotlinTypeChecker.DEFAULT.isSubtypeOf( ((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType()); } throw new IllegalArgumentException("Unexpected callable: " + a.getClass()); }
@Nullable public static Visibility findMaxVisibility( @NotNull Collection<? extends CallableMemberDescriptor> descriptors) { if (descriptors.isEmpty()) { return Visibilities.DEFAULT_VISIBILITY; } Visibility maxVisibility = null; for (CallableMemberDescriptor descriptor : descriptors) { Visibility visibility = descriptor.getVisibility(); assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor; if (maxVisibility == null) { maxVisibility = visibility; continue; } Integer compareResult = Visibilities.compare(visibility, maxVisibility); if (compareResult == null) { maxVisibility = null; } else if (compareResult > 0) { maxVisibility = visibility; } } if (maxVisibility == null) { return null; } for (CallableMemberDescriptor descriptor : descriptors) { Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility()); if (compareResult == null || compareResult < 0) { return null; } } return maxVisibility; }
@Nullable private static Visibility findMaxVisibility( @NotNull Collection<? extends CallableMemberDescriptor> descriptors) { if (descriptors.isEmpty()) { return Visibilities.INTERNAL; } Visibility maxVisibility = null; for (CallableMemberDescriptor descriptor : descriptors) { Visibility visibility = descriptor.getVisibility(); assert visibility != Visibilities.INHERITED : "Visibility should have been computed for " + descriptor; if (maxVisibility == null) { maxVisibility = visibility; continue; } Integer compareResult = Visibilities.compare(visibility, maxVisibility); if (compareResult == null) { maxVisibility = null; } else if (compareResult > 0) { maxVisibility = visibility; } } // TODO: IDEA seems to issue an incorrect warning here //noinspection ConstantConditions if (maxVisibility == null) { return null; } for (CallableMemberDescriptor descriptor : descriptors) { Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility()); if (compareResult == null || compareResult < 0) { return null; } } return maxVisibility; }
@NotNull private static Modality determineModality( @NotNull Collection<CallableMemberDescriptor> descriptors) { // Optimization: avoid creating hash sets in frequent cases when modality can be computed // trivially boolean hasOpen = false; boolean hasAbstract = false; for (CallableMemberDescriptor descriptor : descriptors) { switch (descriptor.getModality()) { case FINAL: return Modality.FINAL; case SEALED: throw new IllegalStateException("Member cannot have SEALED modality: " + descriptor); case OPEN: hasOpen = true; break; case ABSTRACT: hasAbstract = true; break; } } if (hasOpen && !hasAbstract) return Modality.OPEN; if (!hasOpen && hasAbstract) return Modality.ABSTRACT; Set<CallableMemberDescriptor> allOverriddenDeclarations = new HashSet<CallableMemberDescriptor>(); for (CallableMemberDescriptor descriptor : descriptors) { allOverriddenDeclarations.addAll(getOverriddenDeclarations(descriptor)); } return getMinimalModality(filterOutOverridden(allOverriddenDeclarations)); }
@NotNull private static Modality getMinimalModality( @NotNull Collection<CallableMemberDescriptor> descriptors) { Modality modality = Modality.ABSTRACT; for (CallableMemberDescriptor descriptor : descriptors) { if (descriptor.getModality().compareTo(modality) < 0) { modality = descriptor.getModality(); } } return modality; }
private void renderModalityForCallable( @NotNull CallableMemberDescriptor callable, @NotNull StringBuilder builder) { if (!DescriptorUtils.isTopLevelDeclaration(callable) || callable.getModality() != Modality.FINAL) { if (overridesSomething(callable) && overrideRenderingPolicy == OverrideRenderingPolicy.RENDER_OVERRIDE && callable.getModality() == Modality.OPEN) { return; } renderModality(callable.getModality(), builder); } }
public static void bindOverride( CallableMemberDescriptor fromCurrent, CallableMemberDescriptor fromSupertype) { fromCurrent.addOverriddenDescriptor(fromSupertype); for (ValueParameterDescriptor parameterFromCurrent : fromCurrent.getValueParameters()) { assert parameterFromCurrent.getIndex() < fromSupertype.getValueParameters().size() : "An override relation between functions implies that they have the same number of value parameters"; ValueParameterDescriptor parameterFromSupertype = fromSupertype.getValueParameters().get(parameterFromCurrent.getIndex()); parameterFromCurrent.addOverriddenDescriptor(parameterFromSupertype); } }
private void checkOpenMembers(ClassDescriptorWithResolutionScopes classDescriptor) { if (classCanHaveOpenMembers(classDescriptor)) return; for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) { if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) continue; JetNamedDeclaration member = (JetNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor); if (member != null && member.hasModifier(JetTokens.OPEN_KEYWORD)) { trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member)); } } }
private static void collectOverriddenDeclarations( @NotNull CallableMemberDescriptor descriptor, @NotNull Set<CallableMemberDescriptor> result) { if (descriptor.getKind().isReal()) { result.add(descriptor); } else { if (descriptor.getOverriddenDescriptors().isEmpty()) { throw new IllegalStateException( "No overridden descriptors found for (fake override) " + descriptor); } for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) { collectOverriddenDeclarations(overridden, result); } } }
private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember( @NotNull CallableMemberDescriptor fromCurrent, @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper, @NotNull ClassDescriptor current, @NotNull DescriptorSink sink) { Collection<CallableMemberDescriptor> bound = new ArrayList<CallableMemberDescriptor>(descriptorsFromSuper.size()); for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) { OverrideCompatibilityInfo.Result result = DEFAULT.isOverridableBy(fromSupertype, fromCurrent).getResult(); boolean isVisible = Visibilities.isVisible(ReceiverValue.IRRELEVANT_RECEIVER, fromSupertype, current); switch (result) { case OVERRIDABLE: if (isVisible) { fromCurrent.addOverriddenDescriptor(fromSupertype); } bound.add(fromSupertype); break; case CONFLICT: if (isVisible) { sink.conflict(fromSupertype, fromCurrent); } bound.add(fromSupertype); break; case INCOMPATIBLE: break; } } return bound; }
private void checkDeclaredTypeInPublicMember( JetNamedDeclaration member, CallableMemberDescriptor memberDescriptor) { boolean hasDeferredType; if (member instanceof JetProperty) { hasDeferredType = ((JetProperty) member).getTypeReference() == null && DescriptorResolver.hasBody((JetProperty) member); } else { assert member instanceof JetFunction; JetFunction function = (JetFunction) member; hasDeferredType = function.getTypeReference() == null && function.hasBody() && !function.hasBlockBody(); } if ((memberDescriptor.getVisibility().isPublicAPI()) && memberDescriptor.getOverriddenDescriptors().size() == 0 && hasDeferredType) { trace.report(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE.on(member)); } }
@NotNull @SuppressWarnings("unchecked") public static <D extends CallableMemberDescriptor> Set<D> getAllOverriddenDeclarations( @NotNull D memberDescriptor) { Set<D> result = new HashSet<D>(); for (CallableMemberDescriptor overriddenDeclaration : memberDescriptor.getOverriddenDescriptors()) { CallableMemberDescriptor.Kind kind = overriddenDeclaration.getKind(); if (kind == DECLARATION) { result.add((D) overriddenDeclaration); } else if (kind == DELEGATION || kind == FAKE_OVERRIDE || kind == SYNTHESIZED) { // do nothing } else { throw new AssertionError("Unexpected callable kind " + kind); } result.addAll(getAllOverriddenDeclarations((D) overriddenDeclaration)); } return result; }
private static void createAndBindFakeOverride( @NotNull Collection<CallableMemberDescriptor> overridables, @NotNull ClassDescriptor current, @NotNull DescriptorSink sink) { Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables); boolean allInvisible = visibleOverridables.isEmpty(); Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables; Modality modality = getMinimalModality(effectiveOverridden); Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED; CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden); CallableMemberDescriptor fakeOverride = mostSpecific.copy( current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); for (CallableMemberDescriptor descriptor : effectiveOverridden) { fakeOverride.addOverriddenDescriptor(descriptor); } sink.addFakeOverride(fakeOverride); }
public static void resolveUnknownVisibilityForMember( @NotNull CallableMemberDescriptor memberDescriptor, @Nullable Function1<CallableMemberDescriptor, Unit> cannotInferVisibility) { for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) { if (descriptor.getVisibility() == Visibilities.INHERITED) { resolveUnknownVisibilityForMember(descriptor, cannotInferVisibility); } } if (memberDescriptor.getVisibility() != Visibilities.INHERITED) { return; } Visibility maxVisibility = computeVisibilityToInherit(memberDescriptor); Visibility visibilityToInherit; if (maxVisibility == null) { if (cannotInferVisibility != null) { cannotInferVisibility.invoke(memberDescriptor); } visibilityToInherit = Visibilities.PUBLIC; } else { visibilityToInherit = maxVisibility; } if (memberDescriptor instanceof PropertyDescriptorImpl) { ((PropertyDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit); for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) { // If we couldn't infer visibility for property, the diagnostic is already reported, no need // to report it again on accessors resolveUnknownVisibilityForMember( accessor, maxVisibility == null ? null : cannotInferVisibility); } } else if (memberDescriptor instanceof FunctionDescriptorImpl) { ((FunctionDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit); } else { assert memberDescriptor instanceof PropertyAccessorDescriptorImpl; ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibilityToInherit); } }
@Nullable private static Visibility computeVisibilityToInherit( @NotNull CallableMemberDescriptor memberDescriptor) { Collection<? extends CallableMemberDescriptor> overriddenDescriptors = memberDescriptor.getOverriddenDescriptors(); Visibility maxVisibility = findMaxVisibility(overriddenDescriptors); if (maxVisibility == null) { return null; } if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { for (CallableMemberDescriptor overridden : overriddenDescriptors) { // An implementation (a non-abstract overridden member) of a fake override should have the // maximum possible visibility if (overridden.getModality() != Modality.ABSTRACT && !overridden.getVisibility().equals(maxVisibility)) { return null; } } return maxVisibility; } return maxVisibility.normalize(); }
private static void createAndBindFakeOverride( @NotNull Collection<CallableMemberDescriptor> overridables, @NotNull ClassDescriptor current, @NotNull OverridingStrategy strategy) { Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables); boolean allInvisible = visibleOverridables.isEmpty(); Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables; Modality modality = determineModality(effectiveOverridden); Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED; // FIXME doesn't work as expected for flexible types: should create a refined signature. // Current algorithm produces bad results in presence of annotated Java signatures such as: // J: foo(s: String!): String -- @NotNull String foo(String s); // K: foo(s: String): String? // --> 'foo(s: String!): String' as an inherited signature with most specific return type. // This is bad because it can be overridden by 'foo(s: String?): String', which is not // override-equivalent with K::foo above. // Should be 'foo(s: String): String'. CallableMemberDescriptor mostSpecific = selectMostSpecificMember( effectiveOverridden, new Function1<CallableMemberDescriptor, CallableDescriptor>() { @Override public CallableMemberDescriptor invoke(CallableMemberDescriptor descriptor) { return descriptor; } }); CallableMemberDescriptor fakeOverride = mostSpecific.copy( current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false); strategy.setOverriddenDescriptors(fakeOverride, effectiveOverridden); assert !fakeOverride.getOverriddenDescriptors().isEmpty() : "Overridden descriptors should be set for " + CallableMemberDescriptor.Kind.FAKE_OVERRIDE; strategy.addFakeOverride(fakeOverride); }
private void renderOverride( @NotNull CallableMemberDescriptor callableMember, @NotNull StringBuilder builder) { if (!modifiers.contains(Modifier.OVERRIDE)) return; if (overridesSomething(callableMember)) { if (overrideRenderingPolicy != OverrideRenderingPolicy.RENDER_OPEN) { builder.append("override "); if (verbose) { builder .append("/*") .append(callableMember.getOverriddenDescriptors().size()) .append("*/ "); } } } }
private void renderWhereSuffix( @NotNull CallableMemberDescriptor callable, @NotNull StringBuilder builder) { boolean first = true; for (TypeParameterDescriptor typeParameter : callable.getTypeParameters()) { if (typeParameter.getUpperBounds().size() > 1) { for (JetType upperBound : typeParameter.getUpperBounds()) { if (first) { builder.append(" "); builder.append(renderKeyword("where")); builder.append(" "); } else { builder.append(", "); } builder.append(typeParameter.getName()); builder.append(" : "); builder.append(escape(renderType(upperBound))); first = false; } } } }
public static boolean isOverride(@NotNull CallableMemberDescriptor descriptor) { return !descriptor.getOverriddenDescriptors().isEmpty(); }
private boolean overridesSomething(CallableMemberDescriptor callable) { return !callable.getOverriddenDescriptors().isEmpty(); }
private void renderMemberKind(CallableMemberDescriptor callableMember, StringBuilder builder) { if (!modifiers.contains(Modifier.MEMBER_KIND)) return; if (verbose && callableMember.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { builder.append("/*").append(callableMember.getKind().name().toLowerCase()).append("*/ "); } }