@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; }
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()); }
@Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { if (!super.isAvailable(project, editor, file) || !(file instanceof JetFile)) { return false; } // When running single test 'isAvailable()' is invoked multiple times, so we need to clear // lists. overriddenNonOverridableMembers.clear(); containingDeclarationsNames.clear(); DeclarationDescriptor descriptor = ResolvePackage.resolveToDescriptor(element); if (!(descriptor instanceof CallableMemberDescriptor)) return false; for (CallableMemberDescriptor overriddenDescriptor : getAllDeclaredNonOverridableOverriddenDescriptors((CallableMemberDescriptor) descriptor)) { assert overriddenDescriptor.getKind() == DECLARATION : "Can only be applied to declarations."; PsiElement overriddenMember = descriptorToDeclaration(overriddenDescriptor); if (overriddenMember == null || !QuickFixUtil.canModifyElement(overriddenMember) || !(overriddenMember instanceof JetCallableDeclaration)) { return false; } String containingDeclarationName = overriddenDescriptor.getContainingDeclaration().getName().asString(); overriddenNonOverridableMembers.add((JetCallableDeclaration) overriddenMember); containingDeclarationsNames.add(containingDeclarationName); } return overriddenNonOverridableMembers.size() > 0; }
@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)); }
@Override protected void generateBody() { List<KtObjectDeclaration> companions = new ArrayList<KtObjectDeclaration>(); if (kind != OwnerKind.DEFAULT_IMPLS) { // generate nested classes first and only then generate class body. It necessary to access to // nested CodegenContexts for (KtDeclaration declaration : myClass.getDeclarations()) { if (shouldProcessFirst(declaration)) { // Generate companions after class body generation (need to record all synthetic // accessors) if (declaration instanceof KtObjectDeclaration && ((KtObjectDeclaration) declaration).isCompanion()) { companions.add((KtObjectDeclaration) declaration); CodegenUtilKt.populateCompanionBackingFieldNamesToOuterContextIfNeeded( (KtObjectDeclaration) declaration, context, state); } else { generateDeclaration(declaration); } } } } for (KtDeclaration declaration : myClass.getDeclarations()) { if (!shouldProcessFirst(declaration)) { generateDeclaration(declaration); } } generatePrimaryConstructorProperties(); generateConstructors(); generateDefaultImplsIfNeeded(); for (KtObjectDeclaration companion : companions) { generateDeclaration(companion); } if (!DescriptorUtils.isInterface(descriptor)) { for (DeclarationDescriptor memberDescriptor : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) { if (memberDescriptor instanceof CallableMemberDescriptor) { CallableMemberDescriptor member = (CallableMemberDescriptor) memberDescriptor; if (!member.getKind().isReal() && ImplKt.findInterfaceImplementation(member) == null) { if (member instanceof FunctionDescriptor) { functionCodegen.generateBridges((FunctionDescriptor) member); } else if (member instanceof PropertyDescriptor) { PropertyGetterDescriptor getter = ((PropertyDescriptor) member).getGetter(); if (getter != null) { functionCodegen.generateBridges(getter); } PropertySetterDescriptor setter = ((PropertyDescriptor) member).getSetter(); if (setter != null) { functionCodegen.generateBridges(setter); } } } } } } }
@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 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)); } } }
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 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); }
@NotNull private static Collection<CallableMemberDescriptor> getAllDeclaredNonOverridableOverriddenDescriptors( @NotNull CallableMemberDescriptor callableMemberDescriptor) { Set<CallableMemberDescriptor> result = Sets.newHashSet(); Collection<CallableMemberDescriptor> nonOverridableOverriddenDescriptors = retainNonOverridableMembers(callableMemberDescriptor.getOverriddenDescriptors()); for (CallableMemberDescriptor overriddenDescriptor : nonOverridableOverriddenDescriptors) { CallableMemberDescriptor.Kind kind = overriddenDescriptor.getKind(); if (kind == DECLARATION) { result.add(overriddenDescriptor); } else if (kind == FAKE_OVERRIDE || kind == DELEGATION) { result.addAll(getAllDeclaredNonOverridableOverriddenDescriptors(overriddenDescriptor)); } else if (kind == SYNTHESIZED) { // do nothing, final synthesized members can't be made open } else { throw new UnsupportedOperationException("Unexpected callable kind " + kind); } } return result; }
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); }
public static boolean isOverride(@NotNull CallableMemberDescriptor descriptor) { return !descriptor.getOverriddenDescriptors().isEmpty(); }