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, overriding, overridden);
244 }
245
246 @Override
247 public void returnTypeMismatchOnOverride(
248 @NotNull CallableMemberDescriptor overriding,
249 @NotNull CallableMemberDescriptor overridden
250 ) {
251 // Always reported as RETURN_TYPE_MISMATCH_ON_INHERITANCE
252 }
253
254 @Override
255 public void propertyTypeMismatchOnOverride(
256 @NotNull PropertyDescriptor overriding,
257 @NotNull PropertyDescriptor overridden
258 ) {
259 // Always reported as PROPERTY_TYPE_MISMATCH_ON_INHERITANCE
260 }
261
262 @Override
263 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
264 reportDelegationProblemIfRequired(VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION, overriding, overridden);
265 }
266
267 private void reportDelegationProblemIfRequired(
268 @NotNull DiagnosticFactory2<KtClassOrObject, CallableMemberDescriptor, CallableMemberDescriptor> diagnosticFactory,
269 @NotNull CallableMemberDescriptor delegate,
270 @NotNull CallableMemberDescriptor overridden
271 ) {
272 assert delegate.getKind() == DELEGATION : "Delegate expected, got " + delegate + " of kind " + delegate.getKind();
273
274 if (!onceErrorsReported.contains(diagnosticFactory)) {
275 onceErrorsReported.add(diagnosticFactory);
276 trace.report(diagnosticFactory.on(klass, delegate, overridden));
277 }
278 }
279
280 @Override
281 public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden) {
282 assert overriding.getKind() == DELEGATION : "Delegate expected, got " + overriding + " of kind " + overriding.getKind();
283 assert overriding.getKind() != DELEGATION : "Delegated member can't override an invisible member; " + invisibleOverridden;
284 }
285
286 @Override
287 public void nothingToOverride(@NotNull CallableMemberDescriptor overriding) {
288 assert overriding.getKind() == DELEGATION : "Delegate expected, got " + overriding + " of kind " + overriding.getKind();
289 assert overriding.getKind() != DELEGATION : "Delegated member can't override nothing; " + overriding;
290 }
291
292 void doReportErrors() {
293 if (!classCanHaveAbstractMembers(classDescriptor)) {
294 if (!abstractInBaseClassNoImpl.isEmpty()) {
295 trace.report(ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractInBaseClassNoImpl.iterator().next()));
296 }
297 else if (!abstractNoImpl.isEmpty()) {
298 trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(klass, klass, abstractNoImpl.iterator().next()));
299 }
300 }
301
302 conflictingInterfaceMembers.removeAll(conflictingReturnTypes);
303 multipleImplementations.removeAll(conflictingReturnTypes);
304 if (!conflictingInterfaceMembers.isEmpty()) {
305 trace.report(MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED.on(klass, klass, conflictingInterfaceMembers.iterator().next()));
306 }
307 else if (!multipleImplementations.isEmpty()) {
308 trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(klass, klass, multipleImplementations.iterator().next()));
309 }
310 }
311 }
312
313 private static void checkInheritedAndDelegatedSignatures(
314 @NotNull ClassDescriptor classDescriptor,
315 @NotNull CheckInheritedSignaturesReportStrategy inheritedReportStrategy,
316 @Nullable CheckOverrideReportStrategy overrideReportStrategyForDelegates
317 ) {
318 for (DeclarationDescriptor member : DescriptorUtils.getAllDescriptors(classDescriptor.getDefaultType().getMemberScope())) {
319 if (member instanceof CallableMemberDescriptor) {
320 checkInheritedAndDelegatedSignatures((CallableMemberDescriptor) member, inheritedReportStrategy, overrideReportStrategyForDelegates);
321 }
322 }
323 }
324
325 private static void checkInheritedAndDelegatedSignatures(
326 @NotNull CallableMemberDescriptor descriptor,
327 @NotNull CheckInheritedSignaturesReportStrategy reportingStrategy,
328 @Nullable CheckOverrideReportStrategy overrideReportStrategyForDelegates
329 ) {
330 CallableMemberDescriptor.Kind kind = descriptor.getKind();
331 if (kind != FAKE_OVERRIDE && kind != DELEGATION) return;
332 if (descriptor.getVisibility() == Visibilities.INVISIBLE_FAKE) return;
333
334 Collection<? extends CallableMemberDescriptor> directOverridden = descriptor.getOverriddenDescriptors();
335 assert !directOverridden.isEmpty() : kind + " " + descriptor.getName().asString() + " must override something";
336
337 // collects map from the directly overridden descriptor to the set of declarations:
338 // -- if directly overridden is not fake, the set consists of one element: this directly overridden
339 // -- if it's fake, overridden declarations (non-fake) of this descriptor are collected
340 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = collectOverriddenDeclarations(directOverridden);
341
342 List<CallableMemberDescriptor> allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values());
343 Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations = OverridingUtil.filterOutOverridden(
344 Sets.newLinkedHashSet(allOverriddenDeclarations));
345
346 Set<CallableMemberDescriptor> relevantDirectlyOverridden =
347 getRelevantDirectlyOverridden(overriddenDeclarationsByDirectParent, allFilteredOverriddenDeclarations);
348
349 checkInheritedDescriptorsGroup(relevantDirectlyOverridden, descriptor, reportingStrategy);
350
351 if (kind == DELEGATION && overrideReportStrategyForDelegates != null) {
352 checkOverridesForMember(descriptor, relevantDirectlyOverridden, overrideReportStrategyForDelegates);
353 }
354
355 if (kind != DELEGATION) {
356 checkMissingOverridesByJava8Restrictions(relevantDirectlyOverridden, reportingStrategy);
357 }
358
359 List<CallableMemberDescriptor> implementations = collectImplementations(relevantDirectlyOverridden);
360
361 int numImplementations = implementations.size();
362
363 // The most common case: there's one implementation in the supertypes with the matching return type
364 if (numImplementations == 1 && isReturnTypeOkForOverride(descriptor, implementations.get(0))) return;
365
366 List<CallableMemberDescriptor> abstractOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
367 List<CallableMemberDescriptor> concreteOverridden = new ArrayList<CallableMemberDescriptor>(allFilteredOverriddenDeclarations.size());
368 filterNotSynthesizedDescriptorsByModality(allFilteredOverriddenDeclarations, abstractOverridden, concreteOverridden);
369
370 if (numImplementations == 0) {
371 if (kind != DELEGATION) {
372 for (CallableMemberDescriptor member : abstractOverridden) {
373 reportingStrategy.abstractMemberNotImplemented(member);
374 }
375 }
376 }
377 else if (numImplementations > 1) {
378 for (CallableMemberDescriptor member : concreteOverridden) {
379 reportingStrategy.multipleImplementationsMemberNotImplemented(member);
380 }
381 }
382 else {
383 if (kind != DELEGATION) {
384 List<CallableMemberDescriptor> membersWithMoreSpecificReturnType =
385 collectAbstractMethodsWithMoreSpecificReturnType(abstractOverridden, implementations.get(0));
386 for (CallableMemberDescriptor member : membersWithMoreSpecificReturnType) {
387 reportingStrategy.abstractMemberNotImplemented(member);
388 }
389 }
390 }
391 }
392
393 private static void checkMissingOverridesByJava8Restrictions(
394 @NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden,
395 @NotNull CheckInheritedSignaturesReportStrategy reportingStrategy
396 ) {
397 // Java 8:
398 // -- class should implement an abstract member of a super-class,
399 // even if relevant default implementation is provided in one of the super-interfaces;
400 // -- inheriting multiple override equivalent methods from an interface is a conflict
401 // regardless of 'default' vs 'abstract'.
402
403 boolean overridesClassMember = false;
404 boolean overridesNonAbstractInterfaceMember = false;
405 CallableMemberDescriptor overridesAbstractInBaseClass = null;
406 List<CallableMemberDescriptor> overriddenInterfaceMembers = new SmartList<CallableMemberDescriptor>();
407 for (CallableMemberDescriptor overridden : relevantDirectlyOverridden) {
408 DeclarationDescriptor containingDeclaration = overridden.getContainingDeclaration();
409 if (containingDeclaration instanceof ClassDescriptor) {
410 ClassDescriptor baseClassOrInterface = (ClassDescriptor) containingDeclaration;
411 if (baseClassOrInterface.getKind() == ClassKind.CLASS) {
412 overridesClassMember = true;
413 if (overridden.getModality() == Modality.ABSTRACT) {
414 overridesAbstractInBaseClass = overridden;
415 }
416 }
417 else if (baseClassOrInterface.getKind() == ClassKind.INTERFACE) {
418 overriddenInterfaceMembers.add(overridden);
419 if (overridden.getModality() != Modality.ABSTRACT) {
420 overridesNonAbstractInterfaceMember = true;
421 }
422 }
423 }
424 }
425
426 if (overridesAbstractInBaseClass != null) {
427 reportingStrategy.abstractBaseClassMemberNotImplemented(overridesAbstractInBaseClass);
428 }
429 if (!overridesClassMember && overridesNonAbstractInterfaceMember && overriddenInterfaceMembers.size() > 1) {
430 for (CallableMemberDescriptor member : overriddenInterfaceMembers) {
431 reportingStrategy.conflictingInterfaceMemberNotImplemented(member);
432 }
433 }
434 }
435
436 @NotNull
437 private static List<CallableMemberDescriptor> collectImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
438 List<CallableMemberDescriptor> result = new ArrayList<CallableMemberDescriptor>(relevantDirectlyOverridden.size());
439 for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
440 if (overriddenDescriptor.getModality() != Modality.ABSTRACT) {
441 result.add(overriddenDescriptor);
442 }
443 }
444 return result;
445 }
446
447 private static void filterNotSynthesizedDescriptorsByModality(
448 @NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
449 @NotNull List<CallableMemberDescriptor> abstractOverridden,
450 @NotNull List<CallableMemberDescriptor> concreteOverridden
451 ) {
452 for (CallableMemberDescriptor overridden : allOverriddenDeclarations) {
453 if (!CallResolverUtilKt.isOrOverridesSynthesized(overridden)) {
454 if (overridden.getModality() == Modality.ABSTRACT) {
455 abstractOverridden.add(overridden);
456 }
457 else {
458 concreteOverridden.add(overridden);
459 }
460 }
461 }
462 }
463
464 @NotNull
465 private static List<CallableMemberDescriptor> collectAbstractMethodsWithMoreSpecificReturnType(
466 @NotNull List<CallableMemberDescriptor> abstractOverridden,
467 @NotNull final CallableMemberDescriptor implementation
468 ) {
469 return CollectionsKt.filter(abstractOverridden, new Function1<CallableMemberDescriptor, Boolean>() {
470 @Override
471 public Boolean invoke(@NotNull CallableMemberDescriptor abstractMember) {
472 return !isReturnTypeOkForOverride(abstractMember, implementation);
473 }
474 });
475 }
476
477 @NotNull
478 private static Set<CallableMemberDescriptor> getRelevantDirectlyOverridden(
479 @NotNull Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenByParent,
480 @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
481 ) {
482 /* Let the following class hierarchy is declared:
483
484 trait A { fun foo() = 1 }
485 trait B : A
486 trait C : A
487 trait D : A { override fun foo() = 2 }
488 trait E : B, C, D {}
489
490 Traits B and C have fake descriptors for function foo.
491 The map 'overriddenByParent' is:
492 { 'foo in B' (fake) -> { 'foo in A' }, 'foo in C' (fake) -> { 'foo in A' }, 'foo in D' -> { 'foo in D'} }
493 This is a map from directly overridden descriptors (functions 'foo' in B, C, D in this example) to the set of declarations (non-fake),
494 that are overridden by this descriptor.
495
496 The goal is to leave only relevant directly overridden descriptors to count implementations of our fake function on them.
497 In the example above there is no error (trait E inherits only one implementation of 'foo' (from D), because this implementation is more precise).
498 So only 'foo in D' is relevant.
499
500 Directly overridden descriptor is not relevant if it doesn't add any more appropriate non-fake declarations of the concerned function.
501 More precisely directly overridden descriptor is not relevant if:
502 - it's declaration set is a subset of declaration set for other directly overridden descriptor
503 ('foo in B' is not relevant because it's declaration set is a subset of 'foo in C' function's declaration set)
504 - each member of it's declaration set is overridden by a member of other declaration set
505 ('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')
506
507 For the last condition allFilteredOverriddenDeclarations helps (for the example above it's { 'foo in A' } only): each declaration set
508 is compared with allFilteredOverriddenDeclarations, if they have no intersection, this means declaration set has only functions that
509 are overridden by some other function and corresponding directly overridden descriptor is not relevant.
510 */
511
512 for (Iterator<Map.Entry<CallableMemberDescriptor, Set<CallableMemberDescriptor>>> iterator =
513 overriddenByParent.entrySet().iterator(); iterator.hasNext(); ) {
514 if (!isRelevant(iterator.next().getValue(), overriddenByParent.values(), allFilteredOverriddenDeclarations)) {
515 iterator.remove();
516 }
517 }
518 return overriddenByParent.keySet();
519 }
520
521 private static boolean isRelevant(
522 @NotNull Set<CallableMemberDescriptor> declarationSet,
523 @NotNull Collection<Set<CallableMemberDescriptor>> allDeclarationSets,
524 @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
525 ) {
526 for (Set<CallableMemberDescriptor> otherSet : allDeclarationSets) {
527 if (otherSet == declarationSet) continue;
528 if (otherSet.containsAll(declarationSet)) return false;
529 if (Collections.disjoint(allFilteredOverriddenDeclarations, declarationSet)) return false;
530 }
531 return true;
532 }
533
534 @NotNull
535 private static Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> collectOverriddenDeclarations(
536 @NotNull Collection<? extends CallableMemberDescriptor> directOverriddenDescriptors
537 ) {
538 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = Maps.newLinkedHashMap();
539 for (CallableMemberDescriptor descriptor : directOverriddenDescriptors) {
540 Set<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor);
541 Set<CallableMemberDescriptor> filteredOverrides = OverridingUtil.filterOutOverridden(overriddenDeclarations);
542 overriddenDeclarationsByDirectParent.put(descriptor, new LinkedHashSet<CallableMemberDescriptor>(filteredOverrides));
543 }
544 return overriddenDeclarationsByDirectParent;
545 }
546
547 private interface CheckOverrideReportStrategy {
548 void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden);
549 void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden);
550 void propertyTypeMismatchOnOverride(@NotNull PropertyDescriptor overriding, @NotNull PropertyDescriptor overridden);
551 void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden);
552 void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden);
553 void nothingToOverride(@NotNull CallableMemberDescriptor overriding);
554 }
555
556 private void checkOverrideForMember(@NotNull final CallableMemberDescriptor declared) {
557 if (declared.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
558 if (DataClassUtilsKt.isComponentLike(declared.getName())) {
559 checkOverrideForComponentFunction(declared);
560 }
561 return;
562 }
563
564 if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
565 return;
566 }
567
568 final KtNamedDeclaration member = (KtNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(declared);
569 if (member == null) {
570 throw new IllegalStateException("declared descriptor is not resolved to declaration: " + declared);
571 }
572
573 KtModifierList modifierList = member.getModifierList();
574 boolean hasOverrideNode = modifierList != null && modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD);
575 Collection<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
576
577 if (hasOverrideNode) {
578 checkOverridesForMemberMarkedOverride(declared, true, new CheckOverrideReportStrategy() {
579 private boolean finalOverriddenError = false;
580 private boolean typeMismatchError = false;
581 private boolean kindMismatchError = false;
582
583 @Override
584 public void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
585 if (!finalOverriddenError) {
586 finalOverriddenError = true;
587 trace.report(OVERRIDING_FINAL_MEMBER.on(member, overridden, overridden.getContainingDeclaration()));
588 }
589 }
590
591 @Override
592 public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
593 if (!typeMismatchError) {
594 typeMismatchError = true;
595 trace.report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
596 }
597 }
598
599 @Override
600 public void propertyTypeMismatchOnOverride(@NotNull PropertyDescriptor overriding, @NotNull PropertyDescriptor overridden) {
601 if (!typeMismatchError) {
602 typeMismatchError = true;
603 if (overridden.isVar()) {
604 trace.report(VAR_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
605 }
606 else {
607 trace.report(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
608 }
609 }
610 }
611
612 @Override
613 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
614 if (!kindMismatchError) {
615 kindMismatchError = true;
616 trace.report(VAR_OVERRIDDEN_BY_VAL.on(member, (PropertyDescriptor) declared, (PropertyDescriptor) overridden));
617 }
618 }
619
620 @Override
621 public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden) {
622 trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverridden));
623 }
624
625 @Override
626 public void nothingToOverride(@NotNull CallableMemberDescriptor overriding) {
627 trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
628 }
629 });
630 }
631 else if (!overriddenDescriptors.isEmpty()) {
632 CallableMemberDescriptor overridden = overriddenDescriptors.iterator().next();
633 trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.getContainingDeclaration()));
634 }
635 }
636
637 private static void checkInheritedDescriptorsGroup(
638 @NotNull Collection<CallableMemberDescriptor> inheritedDescriptors,
639 @NotNull CallableMemberDescriptor mostSpecific,
640 @NotNull CheckInheritedSignaturesReportStrategy reportingStrategy
641 ) {
642 if (inheritedDescriptors.size() > 1) {
643 PropertyDescriptor mostSpecificProperty = mostSpecific instanceof PropertyDescriptor ? (PropertyDescriptor) mostSpecific : null;
644
645 for (CallableMemberDescriptor inheritedDescriptor : inheritedDescriptors) {
646 if (mostSpecificProperty != null) {
647 assert inheritedDescriptor instanceof PropertyDescriptor
648 : inheritedDescriptor + " inherited from " + mostSpecificProperty + " is not a property";
649 PropertyDescriptor inheritedPropertyDescriptor = (PropertyDescriptor) inheritedDescriptor;
650
651 if (!isPropertyTypeOkForOverride(inheritedPropertyDescriptor, mostSpecificProperty)) {
652 reportingStrategy.propertyTypeMismatchOnInheritance(mostSpecificProperty, inheritedPropertyDescriptor);
653 }
654 }
655 else if (!isReturnTypeOkForOverride(inheritedDescriptor, mostSpecific)) {
656 reportingStrategy.returnTypeMismatchOnInheritance(mostSpecific, inheritedDescriptor);
657 }
658 }
659 }
660 }
661
662 private static void checkOverridesForMemberMarkedOverride(
663 @NotNull CallableMemberDescriptor declared,
664 boolean checkIfOverridesNothing,
665 @NotNull CheckOverrideReportStrategy reportError
666 ) {
667 Collection<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
668
669 checkOverridesForMember(declared, overriddenDescriptors, reportError);
670
671 if (checkIfOverridesNothing && overriddenDescriptors.isEmpty()) {
672 DeclarationDescriptor containingDeclaration = declared.getContainingDeclaration();
673 assert containingDeclaration instanceof ClassDescriptor : "Overrides may only be resolved in a class, but " + declared + " comes from " + containingDeclaration;
674 ClassDescriptor declaringClass = (ClassDescriptor) containingDeclaration;
675
676 CallableMemberDescriptor invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass);
677 if (invisibleOverriddenDescriptor != null) {
678 reportError.cannotOverrideInvisibleMember(declared, invisibleOverriddenDescriptor);
679 }
680 else {
681 reportError.nothingToOverride(declared);
682 }
683 }
684 }
685
686 private static void checkOverridesForMember(
687 @NotNull CallableMemberDescriptor memberDescriptor,
688 @NotNull Collection<? extends CallableMemberDescriptor> overriddenDescriptors,
689 @NotNull CheckOverrideReportStrategy reportError
690 ) {
691 PropertyDescriptor propertyMemberDescriptor =
692 memberDescriptor instanceof PropertyDescriptor ? (PropertyDescriptor) memberDescriptor : null;
693
694 for (CallableMemberDescriptor overridden : overriddenDescriptors) {
695 if (overridden == null) continue;
696
697 if (!ModalityKt.isOverridable(overridden)) {
698 reportError.overridingFinalMember(memberDescriptor, overridden);
699 }
700
701 if (propertyMemberDescriptor != null) {
702 assert overridden instanceof PropertyDescriptor : overridden + " is overridden by property " + propertyMemberDescriptor;
703 PropertyDescriptor overriddenProperty = (PropertyDescriptor) overridden;
704 if (!isPropertyTypeOkForOverride(overriddenProperty, propertyMemberDescriptor)) {
705 reportError.propertyTypeMismatchOnOverride(propertyMemberDescriptor, overriddenProperty);
706 }
707 }
708 else if (!isReturnTypeOkForOverride(overridden, memberDescriptor)) {
709 reportError.returnTypeMismatchOnOverride(memberDescriptor, overridden);
710 }
711
712 if (checkPropertyKind(overridden, true) && checkPropertyKind(memberDescriptor, false)) {
713 reportError.varOverriddenByVal(memberDescriptor, overridden);
714 }
715 }
716 }
717
718 private static boolean isReturnTypeOkForOverride(
719 @NotNull CallableDescriptor superDescriptor,
720 @NotNull CallableDescriptor subDescriptor
721 ) {
722 TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
723 if (typeSubstitutor == null) return false;
724
725 KotlinType superReturnType = superDescriptor.getReturnType();
726 assert superReturnType != null;
727
728 KotlinType subReturnType = subDescriptor.getReturnType();
729 assert subReturnType != null;
730
731 KotlinType substitutedSuperReturnType = typeSubstitutor.substitute(superReturnType, Variance.OUT_VARIANCE);
732 assert substitutedSuperReturnType != null;
733
734 return KotlinTypeChecker.DEFAULT.isSubtypeOf(subReturnType, substitutedSuperReturnType);
735 }
736
737 @Nullable
738 private static TypeSubstitutor prepareTypeSubstitutor(
739 @NotNull CallableDescriptor superDescriptor,
740 @NotNull CallableDescriptor subDescriptor
741 ) {
742 List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
743 List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
744 if (subTypeParameters.size() != superTypeParameters.size()) return null;
745
746 ArrayList<TypeProjection> arguments = new ArrayList<TypeProjection>(subTypeParameters.size());
747 for (int i = 0; i < superTypeParameters.size(); i++) {
748 arguments.add(new TypeProjectionImpl(subTypeParameters.get(i).getDefaultType()));
749 }
750
751 return new IndexedParametersSubstitution(superTypeParameters, arguments).buildSubstitutor();
752 }
753
754 private static boolean isPropertyTypeOkForOverride(
755 @NotNull PropertyDescriptor superDescriptor,
756 @NotNull PropertyDescriptor subDescriptor
757 ) {
758 TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
759 if (typeSubstitutor == null) return false;
760
761 KotlinType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getType(), Variance.OUT_VARIANCE);
762 assert substitutedSuperReturnType != null;
763
764 if (superDescriptor.isVar()) {
765 return KotlinTypeChecker.DEFAULT.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
766 }
767 else {
768 return KotlinTypeChecker.DEFAULT.isSubtypeOf(subDescriptor.getType(), substitutedSuperReturnType);
769 }
770 }
771
772 private void checkOverrideForComponentFunction(@NotNull final CallableMemberDescriptor componentFunction) {
773 final PsiElement dataModifier = findDataModifierForDataClass(componentFunction.getContainingDeclaration());
774
775 checkOverridesForMemberMarkedOverride(componentFunction, false, new CheckOverrideReportStrategy() {
776 private boolean overrideConflict = false;
777
778 @Override
779 public void overridingFinalMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
780 if (!overrideConflict) {
781 overrideConflict = true;
782 trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataModifier, componentFunction, overridden.getContainingDeclaration()));
783 }
784 }
785
786 @Override
787 public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
788 if (!overrideConflict) {
789 overrideConflict = true;
790 trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataModifier, componentFunction, overridden.getContainingDeclaration()));
791 }
792 }
793
794 @Override
795 public void propertyTypeMismatchOnOverride(@NotNull PropertyDescriptor overriding, @NotNull PropertyDescriptor overridden) {
796 throw new IllegalStateException("Component functions are not properties");
797 }
798
799 @Override
800 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor overridden) {
801 throw new IllegalStateException("Component functions are not properties");
802 }
803
804 @Override
805 public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor overriding, @NotNull CallableMemberDescriptor invisibleOverridden) {
806 throw new IllegalStateException("CANNOT_OVERRIDE_INVISIBLE_MEMBER should be reported on the corresponding property");
807 }
808
809 @Override
810 public void nothingToOverride(@NotNull CallableMemberDescriptor overriding) {
811 throw new IllegalStateException("Component functions are OK to override nothing");
812 }
813 });
814 }
815
816 @NotNull
817 private static PsiElement findDataModifierForDataClass(@NotNull DeclarationDescriptor dataClass) {
818 KtClassOrObject classDeclaration = (KtClassOrObject) DescriptorToSourceUtils.getSourceFromDescriptor(dataClass);
819 if (classDeclaration != null && classDeclaration.getModifierList() != null) {
820 PsiElement modifier = classDeclaration.getModifierList().getModifier(KtTokens.DATA_KEYWORD);
821 if (modifier != null) {
822 return modifier;
823 }
824 }
825
826 throw new IllegalStateException("No data modifier is found for data class " + dataClass);
827 }
828
829 @Nullable
830 private static CallableMemberDescriptor findInvisibleOverriddenDescriptor(
831 @NotNull CallableMemberDescriptor declared,
832 @NotNull ClassDescriptor declaringClass
833 ) {
834 for (KotlinType supertype : declaringClass.getTypeConstructor().getSupertypes()) {
835 Set<CallableMemberDescriptor> all = Sets.newLinkedHashSet();
836 all.addAll(supertype.getMemberScope().getContributedFunctions(declared.getName(), NoLookupLocation.WHEN_CHECK_OVERRIDES));
837 //noinspection unchecked
838 all.addAll((Collection) supertype.getMemberScope().getContributedVariables(declared.getName(), NoLookupLocation.WHEN_CHECK_OVERRIDES));
839 for (CallableMemberDescriptor fromSuper : all) {
840 if (OverridingUtil.DEFAULT.isOverridableBy(fromSuper, declared, null).getResult() == OVERRIDABLE) {
841 if (Visibilities.isVisibleIgnoringReceiver(fromSuper, declared)) {
842 throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared +
843 " and visible but does not appear in its getOverriddenDescriptors()");
844 }
845 return fromSuper;
846 }
847 }
848 }
849 return null;
850 }
851
852 private void checkParameterOverridesForAllClasses(@NotNull TopDownAnalysisContext c) {
853 for (ClassDescriptorWithResolutionScopes classDescriptor : c.getDeclaredClasses().values()) {
854 for (DeclarationDescriptor member : DescriptorUtils.getAllDescriptors(classDescriptor.getDefaultType().getMemberScope())) {
855 if (member instanceof CallableMemberDescriptor) {
856 checkOverridesForParameters((CallableMemberDescriptor) member);
857 }
858 }
859 }
860 }
861
862 private void checkOverridesForParameters(@NotNull CallableMemberDescriptor declared) {
863 boolean isDeclaration = declared.getKind() == CallableMemberDescriptor.Kind.DECLARATION;
864 if (isDeclaration) {
865 // No check if the function is not marked as 'override'
866 KtModifierListOwner declaration = (KtModifierListOwner) DescriptorToSourceUtils.descriptorToDeclaration(declared);
867 if (declaration != null && !declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) {
868 return;
869 }
870 }
871
872 // Let p1 be a parameter of the overriding function
873 // Let p2 be a parameter of the function being overridden
874 // Then
875 // a) p1 is not allowed to have a default value declared
876 // b) p1 must have the same name as p2
877 for (ValueParameterDescriptor parameterFromSubclass : declared.getValueParameters()) {
878 int defaultsInSuper = 0;
879 for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
880 if (parameterFromSuperclass.declaresDefaultValue()) {
881 defaultsInSuper++;
882 }
883 }
884 boolean multipleDefaultsInSuper = defaultsInSuper > 1;
885
886 if (isDeclaration) {
887 checkNameAndDefaultForDeclaredParameter(parameterFromSubclass, multipleDefaultsInSuper);
888 }
889 else {
890 checkNameAndDefaultForFakeOverrideParameter(declared, parameterFromSubclass, multipleDefaultsInSuper);
891 }
892 }
893 }
894
895 private void checkNameAndDefaultForDeclaredParameter(@NotNull ValueParameterDescriptor descriptor, boolean multipleDefaultsInSuper) {
896 KtParameter parameter = (KtParameter) DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
897 assert parameter != null : "Declaration not found for parameter: " + descriptor;
898
899 if (descriptor.declaresDefaultValue()) {
900 trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
901 }
902
903 if (multipleDefaultsInSuper) {
904 trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES.on(parameter, descriptor));
905 }
906
907 for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
908 if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
909 //noinspection ConstantConditions
910 trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(
911 parameter,
912 (ClassDescriptor) parameterFromSuperclass.getContainingDeclaration().getContainingDeclaration(),
913 parameterFromSuperclass)
914 );
915 }
916 }
917 }
918
919 private void checkNameAndDefaultForFakeOverrideParameter(
920 @NotNull CallableMemberDescriptor containingFunction,
921 @NotNull ValueParameterDescriptor descriptor,
922 boolean multipleDefaultsInSuper
923 ) {
924 DeclarationDescriptor containingClass = containingFunction.getContainingDeclaration();
925 KtClassOrObject classElement = (KtClassOrObject) DescriptorToSourceUtils.descriptorToDeclaration(containingClass);
926 assert classElement != null : "Declaration not found for class: " + containingClass;
927
928 if (multipleDefaultsInSuper) {
929 trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, descriptor));
930 }
931
932 for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
933 if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
934 trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(
935 classElement,
936 containingFunction.getOverriddenDescriptors(),
937 parameterFromSuperclass.getIndex() + 1)
938 );
939 }
940 }
941 }
942
943 public static boolean shouldReportParameterNameOverrideWarning(
944 @NotNull ValueParameterDescriptor parameterFromSubclass,
945 @NotNull ValueParameterDescriptor parameterFromSuperclass
946 ) {
947 return parameterFromSubclass.getContainingDeclaration().hasStableParameterNames() &&
948 parameterFromSuperclass.getContainingDeclaration().hasStableParameterNames() &&
949 !parameterFromSuperclass.getName().equals(parameterFromSubclass.getName());
950 }
951
952 private static boolean checkPropertyKind(@NotNull CallableMemberDescriptor descriptor, boolean isVar) {
953 return descriptor instanceof PropertyDescriptor && ((PropertyDescriptor) descriptor).isVar() == isVar;
954 }
955
956 private void checkVisibility(@NotNull TopDownAnalysisContext c) {
957 for (Map.Entry<KtCallableDeclaration, CallableMemberDescriptor> entry : c.getMembers().entrySet()) {
958 checkVisibilityForMember(entry.getKey(), entry.getValue());
959 if (entry.getKey() instanceof KtProperty && entry.getValue() instanceof PropertyDescriptor) {
960 KtPropertyAccessor setter = ((KtProperty) entry.getKey()).getSetter();
961 PropertySetterDescriptor setterDescriptor = ((PropertyDescriptor) entry.getValue()).getSetter();
962 if (setter != null && setterDescriptor != null) {
963 checkVisibilityForMember(setter, setterDescriptor);
964 }
965 }
966 }
967 }
968
969 private void checkVisibilityForMember(@NotNull KtDeclaration declaration, @NotNull CallableMemberDescriptor memberDescriptor) {
970 Visibility visibility = memberDescriptor.getVisibility();
971 for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
972 Integer compare = Visibilities.compare(visibility, descriptor.getVisibility());
973 if (compare == null) {
974 trace.report(CANNOT_CHANGE_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
975 return;
976 }
977 else if (compare < 0) {
978 trace.report(CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
979 return;
980 }
981 }
982 }
983 }