001 /*
002 * Copyright 2010-2016 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.resolve;
018
019 import com.google.common.collect.Maps;
020 import com.google.common.collect.Sets;
021 import com.intellij.psi.PsiElement;
022 import com.intellij.util.SmartList;
023 import com.intellij.util.containers.ContainerUtil;
024 import com.intellij.util.containers.SmartHashSet;
025 import kotlin.Unit;
026 import kotlin.collections.CollectionsKt;
027 import kotlin.jvm.functions.Function1;
028 import org.jetbrains.annotations.NotNull;
029 import org.jetbrains.annotations.Nullable;
030 import org.jetbrains.kotlin.descriptors.*;
031 import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2;
032 import org.jetbrains.kotlin.diagnostics.DiagnosticFactoryWithPsiElement;
033 import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
034 import org.jetbrains.kotlin.lexer.KtTokens;
035 import org.jetbrains.kotlin.psi.*;
036 import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilKt;
037 import org.jetbrains.kotlin.resolve.dataClassUtils.DataClassUtilsKt;
038 import org.jetbrains.kotlin.types.*;
039 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
040
041 import java.util.*;
042
043 import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION;
044 import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
045 import static org.jetbrains.kotlin.diagnostics.Errors.*;
046 import static org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers;
047 import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
048
049 public class OverrideResolver {
050 private final BindingTrace trace;
051
052 public OverrideResolver(@NotNull BindingTrace trace) {
053 this.trace = trace;
054 }
055
056 public void check(@NotNull TopDownAnalysisContext c) {
057 checkVisibility(c);
058 checkOverrides(c);
059 checkParameterOverridesForAllClasses(c);
060 }
061
062 public static void resolveUnknownVisibilities(
063 @NotNull Collection<? extends CallableMemberDescriptor> descriptors,
064 @NotNull BindingTrace trace
065 ) {
066 for (CallableMemberDescriptor descriptor : descriptors) {
067 OverridingUtil.resolveUnknownVisibilityForMember(descriptor, createCannotInferVisibilityReporter(trace));
068 }
069 }
070
071 @NotNull
072 public static Function1<CallableMemberDescriptor, Unit> createCannotInferVisibilityReporter(@NotNull final BindingTrace trace) {
073 return new Function1<CallableMemberDescriptor, Unit>() {
074 @Override
075 public Unit invoke(@NotNull CallableMemberDescriptor descriptor) {
076 DeclarationDescriptor reportOn;
077 if (descriptor.getKind() == FAKE_OVERRIDE || descriptor.getKind() == DELEGATION) {
078 reportOn = DescriptorUtils.getParentOfType(descriptor, ClassDescriptor.class);
079 }
080 else if (descriptor instanceof PropertyAccessorDescriptor && ((PropertyAccessorDescriptor) descriptor).isDefault()) {
081 reportOn = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
082 }
083 else {
084 reportOn = descriptor;
085 }
086 //noinspection ConstantConditions
087 PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(reportOn);
088 if (element instanceof KtDeclaration) {
089 trace.report(CANNOT_INFER_VISIBILITY.on((KtDeclaration) element, descriptor));
090 }
091 return Unit.INSTANCE;
092 }
093 };
094 }
095
096
097 private void checkOverrides(@NotNull TopDownAnalysisContext c) {
098 for (Map.Entry<KtClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
099 checkOverridesInAClass(entry.getValue(), entry.getKey());
100 }
101 }
102
103 private void checkOverridesInAClass(@NotNull ClassDescriptorWithResolutionScopes classDescriptor, @NotNull KtClassOrObject klass) {
104 // Check overrides for internal consistency
105 for (CallableMemberDescriptor member : classDescriptor.getDeclaredCallableMembers()) {
106 checkOverrideForMember(member);
107 }
108
109 CollectErrorInformationForInheritedMembersStrategy inheritedMemberErrors =
110 new CollectErrorInformationForInheritedMembersStrategy(klass, classDescriptor);
111
112 checkInheritedAndDelegatedSignatures(classDescriptor, inheritedMemberErrors, inheritedMemberErrors);
113 inheritedMemberErrors.doReportErrors();
114 }
115
116 @NotNull
117 public static Set<CallableMemberDescriptor> getMissingImplementations(@NotNull ClassDescriptor classDescriptor) {
118 CollectMissingImplementationsStrategy collector = new CollectMissingImplementationsStrategy();
119 checkInheritedAndDelegatedSignatures(classDescriptor, collector, null);
120 return collector.shouldImplement;
121 }
122
123 private interface CheckInheritedSignaturesReportStrategy {
124 void abstractMemberNotImplemented(CallableMemberDescriptor descriptor);
125 void abstractBaseClassMemberNotImplemented(CallableMemberDescriptor descriptor);
126 void multipleImplementationsMemberNotImplemented(CallableMemberDescriptor descriptor);
127 void conflictingInterfaceMemberNotImplemented(CallableMemberDescriptor descriptor);
128 void returnTypeMismatchOnInheritance(CallableMemberDescriptor descriptor1, CallableMemberDescriptor descriptor2);
129 void propertyTypeMismatchOnInheritance(PropertyDescriptor descriptor1, PropertyDescriptor descriptor2);
130 }
131
132 private static class CollectMissingImplementationsStrategy implements CheckInheritedSignaturesReportStrategy {
133 private final Set<CallableMemberDescriptor> shouldImplement = new LinkedHashSet<CallableMemberDescriptor>();
134
135 @Override
136 public void abstractMemberNotImplemented(CallableMemberDescriptor descriptor) {
137 shouldImplement.add(descriptor);
138 }
139
140 @Override
141 public void abstractBaseClassMemberNotImplemented(CallableMemberDescriptor descriptor) {
142 // don't care
143 }
144
145 @Override
146 public void multipleImplementationsMemberNotImplemented(CallableMemberDescriptor descriptor) {
147 shouldImplement.add(descriptor);
148 }
149
150 @Override
151 public void conflictingInterfaceMemberNotImplemented(CallableMemberDescriptor descriptor) {
152 if (descriptor.getModality() == Modality.ABSTRACT) {
153 shouldImplement.add(descriptor);
154 }
155 }
156
157 @Override
158 public void returnTypeMismatchOnInheritance(CallableMemberDescriptor descriptor1, CallableMemberDescriptor descriptor2) {
159 // don't care
160 }
161
162 @Override
163 public void propertyTypeMismatchOnInheritance(PropertyDescriptor descriptor1, PropertyDescriptor descriptor2) {
164 // don't care
165 }
166 }
167
168 private class CollectErrorInformationForInheritedMembersStrategy
169 implements CheckInheritedSignaturesReportStrategy, CheckOverrideReportStrategy {
170 private final KtClassOrObject klass;
171 private final ClassDescriptor classDescriptor;
172
173 private final Set<CallableMemberDescriptor> abstractNoImpl = Sets.newLinkedHashSet();
174 private final Set<CallableMemberDescriptor> multipleImplementations = Sets.newLinkedHashSet();
175 private final Set<CallableMemberDescriptor> abstractInBaseClassNoImpl = Sets.newLinkedHashSet();
176 private final Set<CallableMemberDescriptor> conflictingInterfaceMembers = Sets.newLinkedHashSet();
177 private final Set<CallableMemberDescriptor> conflictingReturnTypes = Sets.newHashSet();
178
179 private final Set<DiagnosticFactoryWithPsiElement> onceErrorsReported = new SmartHashSet<DiagnosticFactoryWithPsiElement>();
180
181 public CollectErrorInformationForInheritedMembersStrategy(
182 @NotNull KtClassOrObject klass,
183 @NotNull ClassDescriptor classDescriptor
184 ) {
185 this.klass = klass;
186 this.classDescriptor = classDescriptor;
187 }
188
189 @Override
190 public void abstractMemberNotImplemented(CallableMemberDescriptor descriptor) {
191 abstractNoImpl.add(descriptor);
192 }
193
194 @Override
195 public void abstractBaseClassMemberNotImplemented(CallableMemberDescriptor descriptor) {
196 abstractInBaseClassNoImpl.add(descriptor);
197 }
198
199 @Override
200 public void multipleImplementationsMemberNotImplemented(CallableMemberDescriptor descriptor) {
201 multipleImplementations.add(descriptor);
202 }
203
204 @Override
205 public void conflictingInterfaceMemberNotImplemented(CallableMemberDescriptor descriptor) {
206 conflictingInterfaceMembers.add(descriptor);
207 }
208
209 @Override
210 public void returnTypeMismatchOnInheritance(CallableMemberDescriptor descriptor1, CallableMemberDescriptor descriptor2) {
211 conflictingReturnTypes.add(descriptor1);
212 conflictingReturnTypes.add(descriptor2);
213
214 reportInheritanceConflictIfRequired(RETURN_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2);
215 }
216
217 @Override
218 public void propertyTypeMismatchOnInheritance(PropertyDescriptor descriptor1, PropertyDescriptor descriptor2) {
219 conflictingReturnTypes.add(descriptor1);
220 conflictingReturnTypes.add(descriptor2);
221
222 if (descriptor1.isVar() || descriptor2.isVar()) {
223 reportInheritanceConflictIfRequired(VAR_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2);
224 }
225 else {
226 reportInheritanceConflictIfRequired(PROPERTY_TYPE_MISMATCH_ON_INHERITANCE, descriptor1, descriptor2);
227 }
228 }
229
230 private void reportInheritanceConflictIfRequired(
231 @NotNull DiagnosticFactory2<KtClassOrObject, CallableMemberDescriptor, CallableMemberDescriptor> diagnosticFactory,
232 @NotNull CallableMemberDescriptor descriptor1,
233 @NotNull CallableMemberDescriptor descriptor2
234 ) {
235 if (!onceErrorsReported.contains(diagnosticFactory)) {
236 onceErrorsReported.add(diagnosticFactory);
237 trace.report(diagnosticFactory.on(klass, descriptor1, descriptor2));
238 }
239 }
240
241 @Override
242 public void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
243 reportDelegationProblemIfRequired(OVERRIDING_FINAL_MEMBER_BY_DELEGATION, null, overriding, overridden);
244 }
245
246 @Override
247 public void returnTypeMismatchOnOverride(
248 @NotNull CallableMemberDescriptor overriding,
249 @NotNull CallableMemberDescriptor overridden
250 ) {
251 reportDelegationProblemIfRequired(
252 RETURN_TYPE_MISMATCH_BY_DELEGATION, RETURN_TYPE_MISMATCH_ON_INHERITANCE, overriding, overridden);
253 }
254
255 @Override
256 public void propertyTypeMismatchOnOverride(
257 @NotNull PropertyDescriptor overriding,
258 @NotNull PropertyDescriptor overridden
259 ) {
260 reportDelegationProblemIfRequired(
261 PROPERTY_TYPE_MISMATCH_BY_DELEGATION, PROPERTY_TYPE_MISMATCH_ON_INHERITANCE, overriding, overridden);
262 }
263
264 @Override
265 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
266 reportDelegationProblemIfRequired(VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION, null, overriding, overridden);
267 }
268
269 private void reportDelegationProblemIfRequired(
270 @NotNull DiagnosticFactory2<KtClassOrObject, CallableMemberDescriptor, CallableMemberDescriptor> diagnosticFactory,
271 @Nullable DiagnosticFactoryWithPsiElement<?, ?> relevantDiagnosticFromInheritance,
272 @NotNull CallableMemberDescriptor delegate,
273 @NotNull CallableMemberDescriptor overridden
274 ) {
275 assert delegate.getKind() == DELEGATION : "Delegate expected, got " + delegate + " of kind " + delegate.getKind();
276
277 if (!onceErrorsReported.contains(diagnosticFactory) &&
278 (relevantDiagnosticFromInheritance == null || !onceErrorsReported.contains(relevantDiagnosticFromInheritance))) {
279 onceErrorsReported.add(diagnosticFactory);
280 trace.report(diagnosticFactory.on(klass, delegate, overridden));
281 }
282 }
283
284 void doReportErrors() {
285 if (!classCanHaveAbstractMembers(classDescriptor)) {
286 if (!abstractInBaseClassNoImpl.isEmpty()) {
287 trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.iterator().next()));
288 }
289 else if (!abstractNoImpl.isEmpty()) {
290 trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractNoImpl.iterator().next()));
291 }
292 }
293
294 conflictingInterfaceMembers.removeAll(conflictingReturnTypes);
295 multipleImplementations.removeAll(conflictingReturnTypes);
296 if (!conflictingInterfaceMembers.isEmpty()) {
297 trace.report(MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED.on(klass, klass, conflictingInterfaceMembers.iterator().next()));
298 }
299 else if (!multipleImplementations.isEmpty()) {
300 trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(klass, klass, multipleImplementations.iterator().next()));
301 }
302 }
303 }
304
305 private static void checkInheritedAndDelegatedSignatures(
306 @NotNull ClassDescriptor classDescriptor,
307 @NotNull CheckInheritedSignaturesReportStrategy inheritedReportStrategy,
308 @Nullable CheckOverrideReportStrategy overrideReportStrategyForDelegates
309 ) {
310 for (DeclarationDescriptor member : DescriptorUtils.getAllDescriptors(classDescriptor.getDefaultType().getMemberScope())) {
311 if (member instanceof CallableMemberDescriptor) {
312 checkInheritedAndDelegatedSignatures((CallableMemberDescriptor) member, inheritedReportStrategy, overrideReportStrategyForDelegates);
313 }
314 }
315 }
316
317 private static void checkInheritedAndDelegatedSignatures(
318 @NotNull CallableMemberDescriptor descriptor,
319 @NotNull CheckInheritedSignaturesReportStrategy reportingStrategy,
320 @Nullable CheckOverrideReportStrategy overrideReportStrategyForDelegates
321 ) {
322 CallableMemberDescriptor.Kind kind = descriptor.getKind();
323 if (kind != FAKE_OVERRIDE && kind != DELEGATION) return;
324 if (descriptor.getVisibility() == Visibilities.INVISIBLE_FAKE) return;
325
326 Collection<? extends CallableMemberDescriptor> directOverridden = descriptor.getOverriddenDescriptors();
327 assert !directOverridden.isEmpty() : kind + " " + descriptor.getName().asString() + " must override something";
328
329 // collects map from the directly overridden descriptor to the set of declarations:
330 // -- if directly overridden is not fake, the set consists of one element: this directly overridden
331 // -- if it's fake, overridden declarations (non-fake) of this descriptor are collected
332 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = collectOverriddenDeclarations(directOverridden);
333
334 List<CallableMemberDescriptor> allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values());
335 Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations = OverridingUtil.filterOutOverridden(
336 Sets.newLinkedHashSet(allOverriddenDeclarations));
337
338 Set<CallableMemberDescriptor> relevantDirectlyOverridden =
339 getRelevantDirectlyOverridden(overriddenDeclarationsByDirectParent, allFilteredOverriddenDeclarations);
340
341 checkInheritedDescriptorsGroup(relevantDirectlyOverridden, descriptor, reportingStrategy);
342
343 if (kind == DELEGATION && overrideReportStrategyForDelegates != null) {
344 checkOverridesForMember(descriptor, relevantDirectlyOverridden, overrideReportStrategyForDelegates);
345 }
346
347 if (kind != DELEGATION) {
348 checkMissingOverridesByJava8Restrictions(relevantDirectlyOverridden, reportingStrategy);
349 }
350
351 List<CallableMemberDescriptor> implementations = collectImplementations(relevantDirectlyOverridden);
352
353 int numImplementations = implementations.size();
354
355 // The most common case: there's one implementation in the supertypes with the matching return type
356 if (numImplementations == 1 && isReturnTypeOkForOverride(descriptor, implementations.get(0))) return;
357
358 List<CallableMemberDescriptor> abstractOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
359 List<CallableMemberDescriptor> concreteOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
360 filterNotSynthesizedDescriptorsByModality(allFilteredOverriddenDeclarations, abstractOverridden, concreteOverridden);
361
362 if (numImplementations == 0) {
363 if (kind != DELEGATION) {
364 for (CallableMemberDescriptor member : abstractOverridden) {
365 reportingStrategy.abstractMemberNotImplemented(member);
366 }
367 }
368 }
369 else if (numImplementations > 1) {
370 for (CallableMemberDescriptor member : concreteOverridden) {
371 reportingStrategy.multipleImplementationsMemberNotImplemented(member);
372 }
373 }
374 else {
375 if (kind != DELEGATION) {
376 List<CallableMemberDescriptor> membersWithMoreSpecificReturnType =
377 collectAbstractMethodsWithMoreSpecificReturnType(abstractOverridden, implementations.get(0));
378 for (CallableMemberDescriptor member : membersWithMoreSpecificReturnType) {
379 reportingStrategy.abstractMemberNotImplemented(member);
380 }
381 }
382 }
383 }
384
385 private static void checkMissingOverridesByJava8Restrictions(
386 @NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden,
387 @NotNull CheckInheritedSignaturesReportStrategy reportingStrategy
388 ) {
389 // Java 8:
390 // -- class should implement an abstract member of a super-class,
391 // even if relevant default implementation is provided in one of the super-interfaces;
392 // -- inheriting multiple override equivalent methods from an interface is a conflict
393 // regardless of 'default' vs 'abstract'.
394
395 boolean overridesClassMember = false;
396 boolean overridesNonAbstractInterfaceMember = false;
397 CallableMemberDescriptor overridesAbstractInBaseClass = null;
398 List<CallableMemberDescriptor> overriddenInterfaceMembers = new SmartList<CallableMemberDescriptor>();
399 for (CallableMemberDescriptor overridden : relevantDirectlyOverridden) {
400 DeclarationDescriptor containingDeclaration = overridden.getContainingDeclaration();
401 if (containingDeclaration instanceof ClassDescriptor) {
402 ClassDescriptor baseClassOrInterface = (ClassDescriptor) containingDeclaration;
403 if (baseClassOrInterface.getKind() == ClassKind.CLASS) {
404 overridesClassMember = true;
405 if (overridden.getModality() == Modality.ABSTRACT) {
406 overridesAbstractInBaseClass = overridden;
407 }
408 }
409 else if (baseClassOrInterface.getKind() == ClassKind.INTERFACE) {
410 overriddenInterfaceMembers.add(overridden);
411 if (overridden.getModality() != Modality.ABSTRACT) {
412 overridesNonAbstractInterfaceMember = true;
413 }
414 }
415 }
416 }
417
418 if (overridesAbstractInBaseClass != null) {
419 reportingStrategy.abstractBaseClassMemberNotImplemented(overridesAbstractInBaseClass);
420 }
421 if (!overridesClassMember && overridesNonAbstractInterfaceMember && overriddenInterfaceMembers.size() > 1) {
422 for (CallableMemberDescriptor member : overriddenInterfaceMembers) {
423 reportingStrategy.conflictingInterfaceMemberNotImplemented(member);
424 }
425 }
426 }
427
428 @NotNull
429 private static List<CallableMemberDescriptor> collectImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
430 List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(relevantDirectlyOverridden.size());
431 for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
432 if (overriddenDescriptor.getModality() != Modality.ABSTRACT) {
433 result.add(overriddenDescriptor);
434 }
435 }
436 return result;
437 }
438
439 private static void filterNotSynthesizedDescriptorsByModality(
440 @NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
441 @NotNull List<CallableMemberDescriptor> abstractOverridden,
442 @NotNull List<CallableMemberDescriptor> concreteOverridden
443 ) {
444 for (CallableMemberDescriptor overridden : allOverriddenDeclarations) {
445 if (!CallResolverUtilKt.isOrOverridesSynthesized(overridden)) {
446 if (overridden.getModality() == Modality.ABSTRACT) {
447 abstractOverridden.add(overridden);
448 }
449 else {
450 concreteOverridden.add(overridden);
451 }
452 }
453 }
454 }
455
456 @NotNull
457 private static List<CallableMemberDescriptor> collectAbstractMethodsWithMoreSpecificReturnType(
458 @NotNull List<CallableMemberDescriptor> abstractOverridden,
459 @NotNull final CallableMemberDescriptor implementation
460 ) {
461 return CollectionsKt.filter(abstractOverridden, new Function1<CallableMemberDescriptor, Boolean>() {
462 @Override
463 public Boolean invoke(@NotNull CallableMemberDescriptor abstractMember) {
464 return !isReturnTypeOkForOverride(abstractMember, implementation);
465 }
466 });
467 }
468
469 @NotNull
470 private static Set<CallableMemberDescriptor> getRelevantDirectlyOverridden(
471 @NotNull Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenByParent,
472 @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
473 ) {
474 /* Let the following class hierarchy is declared:
475
476 trait A { fun foo() = 1 }
477 trait B : A
478 trait C : A
479 trait D : A { override fun foo() = 2 }
480 trait E : B, C, D {}
481
482 Traits B and C have fake descriptors for function foo.
483 The map 'overriddenByParent' is:
484 { 'foo in B' (fake) -> { 'foo in A' }, 'foo in C' (fake) -> { 'foo in A' }, 'foo in D' -> { 'foo in D'} }
485 This is a map from directly overridden descriptors (functions 'foo' in B, C, D in this example) to the set of declarations (non-fake),
486 that are overridden by this descriptor.
487
488 The goal is to leave only relevant directly overridden descriptors to count implementations of our fake function on them.
489 In the example above there is no error (trait E inherits only one implementation of 'foo' (from D), because this implementation is more precise).
490 So only 'foo in D' is relevant.
491
492 Directly overridden descriptor is not relevant if it doesn't add any more appropriate non-fake declarations of the concerned function.
493 More precisely directly overridden descriptor is not relevant if:
494 - it's declaration set is a subset of declaration set for other directly overridden descriptor
495 ('foo in B' is not relevant because it's declaration set is a subset of 'foo in C' function's declaration set)
496 - each member of it's declaration set is overridden by a member of other declaration set
497 ('foo in C' is not relevant, because 'foo in A' is overridden by 'foo in D', so 'foo in A' is not appropriate non-fake declaration for 'foo')
498
499 For the last condition allFilteredOverriddenDeclarations helps (for the example above it's { 'foo in A' } only): each declaration set
500 is compared with allFilteredOverriddenDeclarations, if they have no intersection, this means declaration set has only functions that
501 are overridden by some other function and corresponding directly overridden descriptor is not relevant.
502 */
503
504 for (Iterator<Map.Entry<CallableMemberDescriptor, Set<CallableMemberDescriptor>>> iterator =
505 overriddenByParent.entrySet().iterator(); iterator.hasNext(); ) {
506 if (!isRelevant(iterator.next().getValue(), overriddenByParent.values(), allFilteredOverriddenDeclarations)) {
507 iterator.remove();
508 }
509 }
510 return overriddenByParent.keySet();
511 }
512
513 private static boolean isRelevant(
514 @NotNull Set<CallableMemberDescriptor> declarationSet,
515 @NotNull Collection<Set<CallableMemberDescriptor>> allDeclarationSets,
516 @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
517 ) {
518 for (Set<CallableMemberDescriptor> otherSet : allDeclarationSets) {
519 if (otherSet == declarationSet) continue;
520 if (otherSet.containsAll(declarationSet)) return false;
521 if (Collections.disjoint(allFilteredOverriddenDeclarations, declarationSet)) return false;
522 }
523 return true;
524 }
525
526 @NotNull
527 private static Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> collectOverriddenDeclarations(
528 @NotNull Collection<? extends CallableMemberDescriptor> directOverriddenDescriptors
529 ) {
530 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = Maps.newLinkedHashMap();
531 for (CallableMemberDescriptor descriptor : directOverriddenDescriptors) {
532 Set<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor);
533 Set<CallableMemberDescriptor> filteredOverrides = OverridingUtil.filterOutOverridden(overriddenDeclarations);
534 overriddenDeclarationsByDirectParent.put(descriptor, new LinkedHashSet<CallableMemberDescriptor>(filteredOverrides));
535 }
536 return overriddenDeclarationsByDirectParent;
537 }
538
539 private interface CheckOverrideReportStrategy {
540 void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden);
541 void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden);
542 void propertyTypeMismatchOnOverride(@NotNull PropertyDescriptor overriding, @NotNull PropertyDescriptor overridden);
543 void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden);
544 }
545
546 private interface CheckOverrideReportForDeclaredMemberStrategy extends CheckOverrideReportStrategy {
547 void nothingToOverride(@NotNull CallableMemberDescriptor overriding);
548 void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden);
549 }
550
551 private void checkOverrideForMember(@NotNull final CallableMemberDescriptor declared) {
552 if (declared.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
553 if (DataClassUtilsKt.isComponentLike(declared.getName())) {
554 checkOverrideForComponentFunction(declared);
555 }
556 return;
557 }
558
559 if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
560 return;
561 }
562
563 final KtNamedDeclaration member = (KtNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(declared);
564 if (member == null) {
565 throw new IllegalStateException("declared descriptor is not resolved to declaration: " + declared);
566 }
567
568 KtModifierList modifierList = member.getModifierList();
569 boolean hasOverrideNode = modifierList != null && modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD);
570 Collection<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
571
572 if (hasOverrideNode) {
573 checkOverridesForMemberMarkedOverride(declared, new CheckOverrideReportForDeclaredMemberStrategy() {
574 private boolean finalOverriddenError = false;
575 private boolean typeMismatchError = false;
576 private boolean kindMismatchError = false;
577
578 @Override
579 public void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
580 if (!finalOverriddenError) {
581 finalOverriddenError = true;
582 trace.report(OVERRIDING_FINAL_MEMBER.on(member, overridden, overridden.getContainingDeclaration()));
583 }
584 }
585
586 @Override
587 public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
588 if (!typeMismatchError) {
589 typeMismatchError = true;
590 trace.report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
591 }
592 }
593
594 @Override
595 public void propertyTypeMismatchOnOverride(@NotNull PropertyDescriptor overriding, @NotNull PropertyDescriptor overridden) {
596 if (!typeMismatchError) {
597 typeMismatchError = true;
598 if (overridden.isVar()) {
599 trace.report(VAR_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
600 }
601 else {
602 trace.report(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
603 }
604 }
605 }
606
607 @Override
608 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
609 if (!kindMismatchError) {
610 kindMismatchError = true;
611 trace.report(VAR_OVERRIDDEN_BY_VAL.on(member, (PropertyDescriptor) declared, (PropertyDescriptor) overridden));
612 }
613 }
614
615 @Override
616 public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden) {
617 trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverridden));
618 }
619
620 @Override
621 public void nothingToOverride(@NotNull CallableMemberDescriptor overriding) {
622 trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
623 }
624 });
625 }
626 else if (!overriddenDescriptors.isEmpty()) {
627 CallableMemberDescriptor overridden = overriddenDescriptors.iterator().next();
628 trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.getContainingDeclaration()));
629 }
630 }
631
632 private static void checkInheritedDescriptorsGroup(
633 @NotNull Collection<CallableMemberDescriptor> inheritedDescriptors,
634 @NotNull CallableMemberDescriptor mostSpecific,
635 @NotNull CheckInheritedSignaturesReportStrategy reportingStrategy
636 ) {
637 if (inheritedDescriptors.size() > 1) {
638 PropertyDescriptor mostSpecificProperty = mostSpecific instanceof PropertyDescriptor ? (PropertyDescriptor) mostSpecific : null;
639
640 for (CallableMemberDescriptor inheritedDescriptor : inheritedDescriptors) {
641 if (mostSpecificProperty != null) {
642 assert inheritedDescriptor instanceof PropertyDescriptor
643 : inheritedDescriptor + " inherited from " + mostSpecificProperty + " is not a property";
644 PropertyDescriptor inheritedPropertyDescriptor = (PropertyDescriptor) inheritedDescriptor;
645
646 if (!isPropertyTypeOkForOverride(inheritedPropertyDescriptor, mostSpecificProperty)) {
647 reportingStrategy.propertyTypeMismatchOnInheritance(mostSpecificProperty, inheritedPropertyDescriptor);
648 }
649 }
650 else if (!isReturnTypeOkForOverride(inheritedDescriptor, mostSpecific)) {
651 reportingStrategy.returnTypeMismatchOnInheritance(mostSpecific, inheritedDescriptor);
652 }
653 }
654 }
655 }
656
657 private static void checkOverridesForMemberMarkedOverride(
658 @NotNull CallableMemberDescriptor declared,
659 @NotNull CheckOverrideReportForDeclaredMemberStrategy reportError
660 ) {
661 Collection<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
662
663 checkOverridesForMember(declared, overriddenDescriptors, reportError);
664
665 if (overriddenDescriptors.isEmpty()) {
666 DeclarationDescriptor containingDeclaration = declared.getContainingDeclaration();
667 assert containingDeclaration instanceof ClassDescriptor : "Overrides may only be resolved in a class, but " + declared + " comes from " + containingDeclaration;
668 ClassDescriptor declaringClass = (ClassDescriptor) containingDeclaration;
669
670 CallableMemberDescriptor invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass);
671 if (invisibleOverriddenDescriptor != null) {
672 reportError.cannotOverrideInvisibleMember(declared, invisibleOverriddenDescriptor);
673 }
674 else {
675 reportError.nothingToOverride(declared);
676 }
677 }
678 }
679
680 private static void checkOverridesForMember(
681 @NotNull CallableMemberDescriptor memberDescriptor,
682 @NotNull Collection<? extends CallableMemberDescriptor> overriddenDescriptors,
683 @NotNull CheckOverrideReportStrategy reportError
684 ) {
685 PropertyDescriptor propertyMemberDescriptor =
686 memberDescriptor instanceof PropertyDescriptor ? (PropertyDescriptor) memberDescriptor : null;
687
688 for (CallableMemberDescriptor overridden : overriddenDescriptors) {
689 if (overridden == null) continue;
690
691 if (!ModalityKt.isOverridable(overridden)) {
692 reportError.overridingFinalMember(memberDescriptor, overridden);
693 }
694
695 if (propertyMemberDescriptor != null) {
696 assert overridden instanceof PropertyDescriptor : overridden + " is overridden by property " + propertyMemberDescriptor;
697 PropertyDescriptor overriddenProperty = (PropertyDescriptor) overridden;
698 if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor)) {
699 reportError.propertyTypeMismatchOnOverride(propertyMemberDescriptor, overriddenProperty);
700 }
701 }
702 else if (!isReturnTypeOkForOverride(overridden, memberDescriptor)) {
703 reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden);
704 }
705
706 if (checkPropertyKind(overridden, true) && checkPropertyKind(memberDescriptor, false)) {
707 reportError.varOverriddenByVal(memberDescriptor, overridden);
708 }
709 }
710 }
711
712 private static boolean isReturnTypeOkForOverride(
713 @NotNull CallableDescriptor superDescriptor,
714 @NotNull CallableDescriptor subDescriptor
715 ) {
716 TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
717 if (typeSubstitutor == null) return false;
718
719 KotlinType superReturnType = superDescriptor.getReturnType();
720 assert superReturnType != null;
721
722 KotlinType subReturnType = subDescriptor.getReturnType();
723 assert subReturnType != null;
724
725 KotlinType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE);
726 assert substitutedSuperReturnType != null;
727
728 return KotlinTypeChecker.DEFAULT.isSubtypeOf(subReturnType, substitutedSuperReturnType);
729 }
730
731 @Nullable
732 private static TypeSubstitutor prepareTypeSubstitutor(
733 @NotNull CallableDescriptor superDescriptor,
734 @NotNull CallableDescriptor subDescriptor
735 ) {
736 List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
737 List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
738 if (subTypeParameters.size() != superTypeParameters.size()) return null;
739
740 ArrayList<TypeProjection> arguments = new ArrayList<TypeProjection>(subTypeParameters.size());
741 for (int i = 0; i < superTypeParameters.size(); i++) {
742 arguments.add(new TypeProjectionImpl(subTypeParameters.get(i).getDefaultType()));
743 }
744
745 return new IndexedParametersSubstitution(superTypeParameters, arguments).buildSubstitutor();
746 }
747
748 private static boolean isPropertyTypeOkForOverride(
749 @NotNull PropertyDescriptor superDescriptor,
750 @NotNull PropertyDescriptor subDescriptor
751 ) {
752 TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
753 if (typeSubstitutor == null) return false;
754
755 KotlinType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getType(), Variance.OUT_VARIANCE);
756 assert substitutedSuperReturnType != null;
757
758 if (superDescriptor.isVar()) {
759 return KotlinTypeChecker.DEFAULT.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
760 }
761 else {
762 return KotlinTypeChecker.DEFAULT.isSubtypeOf(subDescriptor.getType(), substitutedSuperReturnType);
763 }
764 }
765
766 private void checkOverrideForComponentFunction(@NotNull final CallableMemberDescriptor componentFunction) {
767 final PsiElement dataModifier = findDataModifierForDataClass(componentFunction.getContainingDeclaration());
768
769 checkOverridesForMember(componentFunction, componentFunction.getOverriddenDescriptors(), new CheckOverrideReportStrategy() {
770 private boolean overrideConflict = false;
771
772 @Override
773 public void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
774 if (!overrideConflict) {
775 overrideConflict = true;
776 trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataModifier, componentFunction, overridden.getContainingDeclaration()));
777 }
778 }
779
780 @Override
781 public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
782 if (!overrideConflict) {
783 overrideConflict = true;
784 trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataModifier, componentFunction, overridden.getContainingDeclaration()));
785 }
786 }
787
788 @Override
789 public void propertyTypeMismatchOnOverride(@NotNull PropertyDescriptor overriding, @NotNull PropertyDescriptor overridden) {
790 throw new IllegalStateException("Component functions are not properties");
791 }
792
793 @Override
794 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
795 throw new IllegalStateException("Component functions are not properties");
796 }
797 });
798 }
799
800 @NotNull
801 private static PsiElement findDataModifierForDataClass(@NotNull DeclarationDescriptor dataClass) {
802 KtClassOrObject classDeclaration = (KtClassOrObject) DescriptorToSourceUtils.getSourceFromDescriptor(dataClass);
803 if (classDeclaration != null && classDeclaration.getModifierList() != null) {
804 PsiElement modifier = classDeclaration.getModifierList().getModifier(KtTokens.DATA_KEYWORD);
805 if (modifier != null) {
806 return modifier;
807 }
808 }
809
810 throw new IllegalStateException("No data modifier is found for data class " + dataClass);
811 }
812
813 @Nullable
814 private static CallableMemberDescriptor findInvisibleOverriddenDescriptor(
815 @NotNull CallableMemberDescriptor declared,
816 @NotNull ClassDescriptor declaringClass
817 ) {
818 for (KotlinType supertype : declaringClass.getTypeConstructor().getSupertypes()) {
819 Set<CallableMemberDescriptor> all = Sets.newLinkedHashSet();
820 all.addAll(supertype.getMemberScope().getContributedFunctions(declared.getName(), NoLookupLocation.WHEN_CHECK_OVERRIDES));
821 //noinspection unchecked
822 all.addAll((Collection) supertype.getMemberScope().getContributedVariables(declared.getName(), NoLookupLocation.WHEN_CHECK_OVERRIDES));
823 for (CallableMemberDescriptor fromSuper : all) {
824 if (OverridingUtil.DEFAULT.isOverridableBy(fromSuper, declared, null).getResult() == OVERRIDABLE) {
825 if (Visibilities.isVisibleIgnoringReceiver(fromSuper, declared)) {
826 throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared +
827 " and visible but does not appear in its getOverriddenDescriptors()");
828 }
829 return fromSuper;
830 }
831 }
832 }
833 return null;
834 }
835
836 private void checkParameterOverridesForAllClasses(@NotNull TopDownAnalysisContext c) {
837 for (ClassDescriptorWithResolutionScopes classDescriptor : c.getDeclaredClasses().values()) {
838 for (DeclarationDescriptor member : DescriptorUtils.getAllDescriptors(classDescriptor.getDefaultType().getMemberScope())) {
839 if (member instanceof CallableMemberDescriptor) {
840 checkOverridesForParameters((CallableMemberDescriptor) member);
841 }
842 }
843 }
844 }
845
846 private void checkOverridesForParameters(@NotNull CallableMemberDescriptor declared) {
847 boolean isDeclaration = declared.getKind() == CallableMemberDescriptor.Kind.DECLARATION;
848 if (isDeclaration) {
849 // No check if the function is not marked as 'override'
850 KtModifierListOwner declaration = (KtModifierListOwner) DescriptorToSourceUtils.descriptorToDeclaration(declared);
851 if (declaration != null && !declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) {
852 return;
853 }
854 }
855
856 // Let p1 be a parameter of the overriding function
857 // Let p2 be a parameter of the function being overridden
858 // Then
859 // a) p1 is not allowed to have a default value declared
860 // b) p1 must have the same name as p2
861 for (ValueParameterDescriptor parameterFromSubclass : declared.getValueParameters()) {
862 int defaultsInSuper = 0;
863 for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
864 if (parameterFromSuperclass.declaresDefaultValue()) {
865 defaultsInSuper++;
866 }
867 }
868 boolean multipleDefaultsInSuper = defaultsInSuper > 1;
869
870 if (isDeclaration) {
871 checkNameAndDefaultForDeclaredParameter(parameterFromSubclass, multipleDefaultsInSuper);
872 }
873 else {
874 checkNameAndDefaultForFakeOverrideParameter(declared, parameterFromSubclass, multipleDefaultsInSuper);
875 }
876 }
877 }
878
879 private void checkNameAndDefaultForDeclaredParameter(@NotNull ValueParameterDescriptor descriptor, boolean multipleDefaultsInSuper) {
880 KtParameter parameter = (KtParameter) DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
881 assert parameter != null : "Declaration not found for parameter: " + descriptor;
882
883 if (descriptor.declaresDefaultValue()) {
884 trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
885 }
886
887 if (multipleDefaultsInSuper) {
888 trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES.on(parameter, descriptor));
889 }
890
891 for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
892 if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
893 //noinspection ConstantConditions
894 trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(
895 parameter,
896 (ClassDescriptor) parameterFromSuperclass.getContainingDeclaration().getContainingDeclaration(),
897 parameterFromSuperclass)
898 );
899 }
900 }
901 }
902
903 private void checkNameAndDefaultForFakeOverrideParameter(
904 @NotNull CallableMemberDescriptor containingFunction,
905 @NotNull ValueParameterDescriptor descriptor,
906 boolean multipleDefaultsInSuper
907 ) {
908 DeclarationDescriptor containingClass = containingFunction.getContainingDeclaration();
909 KtClassOrObject classElement = (KtClassOrObject) DescriptorToSourceUtils.descriptorToDeclaration(containingClass);
910 assert classElement != null : "Declaration not found for class: " + containingClass;
911
912 if (multipleDefaultsInSuper) {
913 trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, descriptor));
914 }
915
916 for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
917 if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
918 trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(
919 classElement,
920 containingFunction.getOverriddenDescriptors(),
921 parameterFromSuperclass.getIndex() + 1)
922 );
923 }
924 }
925 }
926
927 public static boolean shouldReportParameterNameOverrideWarning(
928 @NotNull ValueParameterDescriptor parameterFromSubclass,
929 @NotNull ValueParameterDescriptor parameterFromSuperclass
930 ) {
931 return parameterFromSubclass.getContainingDeclaration().hasStableParameterNames() &&
932 parameterFromSuperclass.getContainingDeclaration().hasStableParameterNames() &&
933 !parameterFromSuperclass.getName().equals(parameterFromSubclass.getName());
934 }
935
936 private static boolean checkPropertyKind(@NotNull CallableMemberDescriptor descriptor, boolean isVar) {
937 return descriptor instanceof PropertyDescriptor && ((PropertyDescriptor) descriptor).isVar() == isVar;
938 }
939
940 private void checkVisibility(@NotNull TopDownAnalysisContext c) {
941 for (Map.Entry<KtCallableDeclaration, CallableMemberDescriptor> entry : c.getMembers().entrySet()) {
942 checkVisibilityForMember(entry.getKey(), entry.getValue());
943 if (entry.getKey() instanceof KtProperty && entry.getValue() instanceof PropertyDescriptor) {
944 KtPropertyAccessor setter = ((KtProperty) entry.getKey()).getSetter();
945 PropertySetterDescriptor setterDescriptor = ((PropertyDescriptor) entry.getValue()).getSetter();
946 if (setter != null && setterDescriptor != null) {
947 checkVisibilityForMember(setter, setterDescriptor);
948 }
949 }
950 }
951 }
952
953 private void checkVisibilityForMember(@NotNull KtDeclaration declaration, @NotNull CallableMemberDescriptor memberDescriptor) {
954 Visibility visibility = memberDescriptor.getVisibility();
955 for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
956 Integer compare = Visibilities.compare(visibility, descriptor.getVisibility());
957 if (compare == null) {
958 trace.report(CANNOT_CHANGE_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
959 return;
960 }
961 else if (compare < 0) {
962 trace.report(CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
963 return;
964 }
965 }
966 }
967 }