001 /*
002 * Copyright 2010-2013 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.jet.lang.resolve;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Maps;
021 import com.google.common.collect.Sets;
022 import com.intellij.lang.ASTNode;
023 import com.intellij.psi.PsiElement;
024 import com.intellij.util.containers.ContainerUtil;
025 import com.intellij.util.containers.LinkedMultiMap;
026 import com.intellij.util.containers.MultiMap;
027 import kotlin.KotlinPackage;
028 import org.jetbrains.annotations.NotNull;
029 import org.jetbrains.jet.lang.descriptors.*;
030 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
031 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
032 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptorLite;
033 import org.jetbrains.jet.lang.diagnostics.Errors;
034 import org.jetbrains.jet.lang.psi.*;
035 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
036 import org.jetbrains.jet.lang.resolve.name.Name;
037 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
038 import org.jetbrains.jet.lang.types.JetType;
039 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
040 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
041 import org.jetbrains.jet.lexer.JetTokens;
042
043 import javax.inject.Inject;
044 import java.util.*;
045
046 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
047 import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
048
049 public class OverrideResolver {
050
051 private BindingTrace trace;
052
053 @Inject
054 public void setTrace(BindingTrace trace) {
055 this.trace = trace;
056 }
057
058
059
060 public void process(@NotNull TopDownAnalysisContext c) {
061 //all created fake descriptors are stored to resolve visibility on them later
062 generateOverridesAndDelegation(c);
063
064 checkVisibility(c);
065 checkOverrides(c);
066 checkParameterOverridesForAllClasses(c);
067 }
068
069 /**
070 * Generate fake overrides and add overridden descriptors to existing descriptors.
071 */
072 private void generateOverridesAndDelegation(@NotNull TopDownAnalysisContext c) {
073 Set<ClassDescriptorWithResolutionScopes> ourClasses = new HashSet<ClassDescriptorWithResolutionScopes>(c.getClasses().values());
074 Set<ClassifierDescriptor> processed = new HashSet<ClassifierDescriptor>();
075
076 for (MutableClassDescriptorLite klass : ContainerUtil.reverse(c.getClassesTopologicalOrder())) {
077 if (klass instanceof MutableClassDescriptor && ourClasses.contains(klass)) {
078 generateOverridesAndDelegationInAClass((MutableClassDescriptor) klass, processed, ourClasses);
079
080 MutableClassDescriptorLite classObject = klass.getClassObjectDescriptor();
081 if (classObject instanceof MutableClassDescriptor) {
082 generateOverridesAndDelegationInAClass((MutableClassDescriptor) classObject, processed, ourClasses);
083 }
084 }
085 }
086 }
087
088 private void generateOverridesAndDelegationInAClass(
089 @NotNull MutableClassDescriptor classDescriptor,
090 @NotNull Set<ClassifierDescriptor> processed,
091 @NotNull Set<ClassDescriptorWithResolutionScopes> classesBeingAnalyzed
092 // to filter out classes such as stdlib and others that come from dependencies
093 ) {
094 if (!processed.add(classDescriptor)) {
095 return;
096 }
097
098 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
099 ClassDescriptor superclass = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor();
100 if (superclass instanceof MutableClassDescriptor && classesBeingAnalyzed.contains(superclass)) {
101 generateOverridesAndDelegationInAClass((MutableClassDescriptor) superclass, processed, classesBeingAnalyzed);
102 }
103 }
104
105 JetClassOrObject classOrObject = (JetClassOrObject) BindingContextUtils
106 .classDescriptorToDeclaration(trace.getBindingContext(), classDescriptor);
107 if (classOrObject != null) {
108 DelegationResolver.generateDelegatesInAClass(classDescriptor, trace, classOrObject);
109 }
110
111 generateOverridesInAClass(classDescriptor);
112 }
113
114 private void generateOverridesInAClass(@NotNull final MutableClassDescriptor classDescriptor) {
115 List<CallableMemberDescriptor> membersFromSupertypes = getCallableMembersFromSupertypes(classDescriptor);
116
117 MultiMap<Name, CallableMemberDescriptor> membersFromSupertypesByName = groupDescriptorsByName(membersFromSupertypes);
118
119 MultiMap<Name, CallableMemberDescriptor> membersFromCurrentByName = groupDescriptorsByName(classDescriptor.getDeclaredCallableMembers());
120
121 Set<Name> memberNames = new LinkedHashSet<Name>();
122 memberNames.addAll(membersFromSupertypesByName.keySet());
123 memberNames.addAll(membersFromCurrentByName.keySet());
124
125 for (Name memberName : memberNames) {
126 Collection<CallableMemberDescriptor> fromSupertypes = membersFromSupertypesByName.get(memberName);
127 Collection<CallableMemberDescriptor> fromCurrent = membersFromCurrentByName.get(memberName);
128
129 OverridingUtil.generateOverridesInFunctionGroup(
130 memberName,
131 fromSupertypes,
132 fromCurrent,
133 classDescriptor,
134 new OverridingUtil.DescriptorSink() {
135 @Override
136 public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
137 if (fakeOverride instanceof PropertyDescriptor) {
138 classDescriptor.getBuilder().addPropertyDescriptor((PropertyDescriptor) fakeOverride);
139 }
140 else if (fakeOverride instanceof SimpleFunctionDescriptor) {
141 classDescriptor.getBuilder().addFunctionDescriptor((SimpleFunctionDescriptor) fakeOverride);
142 }
143 else {
144 throw new IllegalStateException(fakeOverride.getClass().getName());
145 }
146 }
147
148 @Override
149 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
150 JetDeclaration declaration = (JetDeclaration) BindingContextUtils
151 .descriptorToDeclaration(trace.getBindingContext(), fromCurrent);
152 trace.report(Errors.CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()));
153 }
154 });
155 }
156 resolveUnknownVisibilities(classDescriptor.getAllCallableMembers(), trace);
157 }
158
159 public static void resolveUnknownVisibilities(
160 @NotNull Collection<? extends CallableMemberDescriptor> descriptors,
161 @NotNull BindingTrace trace) {
162 for (CallableMemberDescriptor descriptor : descriptors) {
163 resolveUnknownVisibilityForMember(descriptor, trace);
164 }
165 }
166
167 public static void resolveUnknownVisibilityForMember(@NotNull CallableMemberDescriptor descriptor, @NotNull final BindingTrace trace) {
168 OverridingUtil.resolveUnknownVisibilityForMember(descriptor, new OverridingUtil.NotInferredVisibilitySink() {
169 @Override
170 public void cannotInferVisibility(@NotNull CallableMemberDescriptor descriptor) {
171 PsiElement element = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), descriptor);
172 if (element instanceof JetDeclaration) {
173 trace.report(CANNOT_INFER_VISIBILITY.on((JetDeclaration) element));
174 }
175 }
176 });
177 }
178
179 private static <T extends DeclarationDescriptor> MultiMap<Name, T> groupDescriptorsByName(Collection<T> properties) {
180 MultiMap<Name, T> r = new LinkedMultiMap<Name, T>();
181 for (T property : properties) {
182 r.putValue(property.getName(), property);
183 }
184 return r;
185 }
186
187
188 private static List<CallableMemberDescriptor> getCallableMembersFromSupertypes(ClassDescriptor classDescriptor) {
189 Set<CallableMemberDescriptor> r = Sets.newLinkedHashSet();
190 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
191 r.addAll(getCallableMembersFromType(supertype.getMemberScope()));
192 }
193 return new ArrayList<CallableMemberDescriptor>(r);
194 }
195
196 private static List<CallableMemberDescriptor> getCallableMembersFromType(JetScope scope) {
197 List<CallableMemberDescriptor> r = Lists.newArrayList();
198 for (DeclarationDescriptor decl : scope.getAllDescriptors()) {
199 if (decl instanceof PropertyDescriptor || decl instanceof SimpleFunctionDescriptor) {
200 r.add((CallableMemberDescriptor) decl);
201 }
202 }
203 return r;
204 }
205
206 private void checkOverrides(@NotNull TopDownAnalysisContext c) {
207 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getClasses().entrySet()) {
208 checkOverridesInAClass(c, (MutableClassDescriptor) entry.getValue(), entry.getKey());
209 }
210 }
211
212 private void checkOverridesInAClass(@NotNull TopDownAnalysisContext c, @NotNull MutableClassDescriptor classDescriptor, @NotNull JetClassOrObject klass) {
213 if (c.getTopDownAnalysisParameters().isAnalyzingBootstrapLibrary()) return;
214
215 // Check overrides for internal consistency
216 for (CallableMemberDescriptor member : classDescriptor.getDeclaredCallableMembers()) {
217 checkOverrideForMember(member);
218 }
219
220 // Check if everything that must be overridden, actually is
221 // More than one implementation or no implementations at all
222 Set<CallableMemberDescriptor> abstractNoImpl = Sets.newLinkedHashSet();
223 Set<CallableMemberDescriptor> manyImpl = Sets.newLinkedHashSet();
224 collectMissingImplementations(classDescriptor, abstractNoImpl, manyImpl);
225
226 PsiElement nameIdentifier = null;
227 if (klass instanceof JetClass) {
228 nameIdentifier = klass.getNameIdentifier();
229 }
230 else if (klass instanceof JetObjectDeclaration) {
231 nameIdentifier = klass.getNameIdentifier();
232 if (nameIdentifier == null) {
233 nameIdentifier = ((JetObjectDeclaration) klass).getObjectKeyword();
234 }
235 }
236 if (nameIdentifier == null) return;
237
238 for (CallableMemberDescriptor memberDescriptor : manyImpl) {
239 trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor));
240 break;
241 }
242
243
244 if (classDescriptor.getModality() == Modality.ABSTRACT) {
245 return;
246 }
247
248 for (CallableMemberDescriptor memberDescriptor : abstractNoImpl) {
249 trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor));
250 break;
251 }
252 }
253
254 public static void collectMissingImplementations(
255 MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl
256 ) {
257 for (CallableMemberDescriptor descriptor : classDescriptor.getAllCallableMembers()) {
258 collectMissingImplementations(descriptor, abstractNoImpl, manyImpl);
259 }
260 }
261
262 public static void collectMissingImplementations(
263 ClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl
264 ) {
265 Iterator<CallableMemberDescriptor> callableMembers = KotlinPackage.filterIsInstance(
266 classDescriptor.getDefaultType().getMemberScope().getAllDescriptors().iterator(), CallableMemberDescriptor.class
267 );
268 while (callableMembers.hasNext()) {
269 collectMissingImplementations(callableMembers.next(), abstractNoImpl, manyImpl);
270 }
271 }
272
273 private static void collectMissingImplementations(
274 @NotNull CallableMemberDescriptor descriptor,
275 @NotNull Set<CallableMemberDescriptor> abstractNoImpl,
276 @NotNull Set<CallableMemberDescriptor> manyImpl
277 ) {
278 if (descriptor.getKind().isReal()) return;
279 if (descriptor.getVisibility() == Visibilities.INVISIBLE_FAKE) return;
280
281 Collection<? extends CallableMemberDescriptor> directOverridden = descriptor.getOverriddenDescriptors();
282 if (directOverridden.size() == 0) {
283 throw new IllegalStateException("A 'fake override' must override something");
284 }
285
286 // collects map from the directly overridden descriptor to the set of declarations:
287 // -- if directly overridden is not fake, the set consists of one element: this directly overridden
288 // -- if it's fake, overridden declarations (non-fake) of this descriptor are collected
289 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = collectOverriddenDeclarations(directOverridden);
290
291 List<CallableMemberDescriptor> allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values());
292 Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations = OverridingUtil.filterOutOverridden(
293 Sets.newLinkedHashSet(allOverriddenDeclarations));
294
295 Set<CallableMemberDescriptor> relevantDirectlyOverridden =
296 getRelevantDirectlyOverridden(overriddenDeclarationsByDirectParent, allFilteredOverriddenDeclarations);
297
298 int implCount = countImplementations(relevantDirectlyOverridden);
299 if (implCount == 0) {
300 collectNotSynthesizedDescriptorsByModality(allFilteredOverriddenDeclarations, abstractNoImpl, Modality.ABSTRACT);
301 }
302 else if (implCount > 1) {
303 collectNotSynthesizedDescriptorsByModality(allFilteredOverriddenDeclarations, manyImpl, Modality.OPEN, Modality.FINAL);
304 }
305 }
306
307 private static int countImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
308 int implCount = 0;
309 for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
310 if (overriddenDescriptor.getModality() != Modality.ABSTRACT) {
311 implCount++;
312 }
313 }
314 return implCount;
315 }
316
317 private static void collectNotSynthesizedDescriptorsByModality(
318 @NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
319 @NotNull Set<CallableMemberDescriptor> result,
320 Modality... modalities
321 ) {
322 Set<Modality> modalitySet = Sets.newHashSet(modalities);
323 for (CallableMemberDescriptor overridden : allOverriddenDeclarations) {
324 if (modalitySet.contains(overridden.getModality())) {
325 if (!CallResolverUtil.isOrOverridesSynthesized(overridden)) {
326 result.add(overridden);
327 }
328 }
329 }
330 }
331
332 @NotNull
333 private static Set<CallableMemberDescriptor> getRelevantDirectlyOverridden(
334 @NotNull Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenByParent,
335 @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
336 ) {
337 /* Let the following class hierarchy is declared:
338
339 trait A { fun foo() = 1 }
340 trait B : A
341 trait C : A
342 trait D : A { override fun foo() = 2 }
343 trait E : B, C, D {}
344
345 Traits B and C have fake descriptors for function foo.
346 The map 'overriddenByParent' is:
347 { 'foo in B' (fake) -> { 'foo in A' }, 'foo in C' (fake) -> { 'foo in A' }, 'foo in D' -> { 'foo in D'} }
348 This is a map from directly overridden descriptors (functions 'foo' in B, C, D in this example) to the set of declarations (non-fake),
349 that are overridden by this descriptor.
350
351 The goal is to leave only relevant directly overridden descriptors to count implementations of our fake function on them.
352 In the example above there is no error (trait E inherits only one implementation of 'foo' (from D), because this implementation is more precise).
353 So only 'foo in D' is relevant.
354
355 Directly overridden descriptor is not relevant if it doesn't add any more appropriate non-fake declarations of the concerned function.
356 More precisely directly overridden descriptor is not relevant if:
357 - it's declaration set is a subset of declaration set for other directly overridden descriptor
358 ('foo in B' is not relevant because it's declaration set is a subset of 'foo in C' function's declaration set)
359 - each member of it's declaration set is overridden by a member of other declaration set
360 ('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')
361
362 For the last condition allFilteredOverriddenDeclarations helps (for the example above it's { 'foo in A' } only): each declaration set
363 is compared with allFilteredOverriddenDeclarations, if they have no intersection, this means declaration set has only functions that
364 are overridden by some other function and corresponding directly overridden descriptor is not relevant.
365 */
366
367 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> relevantOverriddenByParent = Maps.newLinkedHashMap(overriddenByParent);
368
369 for (Map.Entry<CallableMemberDescriptor, Set<CallableMemberDescriptor>> entry : overriddenByParent.entrySet()) {
370 CallableMemberDescriptor directlyOverridden = entry.getKey();
371 Set<CallableMemberDescriptor> declarationSet = entry.getValue();
372 if (!isRelevant(declarationSet, relevantOverriddenByParent.values(), allFilteredOverriddenDeclarations)) {
373 relevantOverriddenByParent.remove(directlyOverridden);
374 }
375 }
376 return relevantOverriddenByParent.keySet();
377 }
378
379 private static boolean isRelevant(
380 @NotNull Set<CallableMemberDescriptor> declarationSet,
381 @NotNull Collection<Set<CallableMemberDescriptor>> allDeclarationSets,
382 @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
383 ) {
384 for (Set<CallableMemberDescriptor> otherSet : allDeclarationSets) {
385 if (otherSet == declarationSet) continue;
386 if (otherSet.containsAll(declarationSet)) return false;
387 if (Collections.disjoint(allFilteredOverriddenDeclarations, declarationSet)) return false;
388 }
389 return true;
390 }
391
392 @NotNull
393 private static Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> collectOverriddenDeclarations(
394 @NotNull Collection<? extends CallableMemberDescriptor> directOverriddenDescriptors
395 ) {
396 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = Maps.newLinkedHashMap();
397 for (CallableMemberDescriptor descriptor : directOverriddenDescriptors) {
398 Collection<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor);
399 Set<CallableMemberDescriptor> filteredOverrides = OverridingUtil.filterOutOverridden(
400 Sets.newLinkedHashSet(overriddenDeclarations));
401 Set<CallableMemberDescriptor> overridden = Sets.newLinkedHashSet();
402 for (CallableMemberDescriptor memberDescriptor : filteredOverrides) {
403 overridden.add(memberDescriptor);
404 }
405 overriddenDeclarationsByDirectParent.put(descriptor, overridden);
406 }
407 return overriddenDeclarationsByDirectParent;
408 }
409
410 private interface CheckOverrideReportStrategy {
411 void overridingFinalMember(@NotNull CallableMemberDescriptor overridden);
412
413 void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
414
415 void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
416
417 void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden);
418
419 void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden);
420
421 void nothingToOverride();
422 }
423
424 private void checkOverrideForMember(@NotNull final CallableMemberDescriptor declared) {
425 if (declared.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
426 // TODO: this should be replaced soon by a framework of synthesized member generation tools
427 if (declared.getName().asString().startsWith(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX)) {
428 checkOverrideForComponentFunction(declared);
429 }
430 return;
431 }
432
433 if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
434 return;
435 }
436
437 final JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
438 if (member == null) {
439 throw new IllegalStateException("declared descriptor is not resolved to declaration: " + declared);
440 }
441
442 JetModifierList modifierList = member.getModifierList();
443 final ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
444 Set<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
445
446 if (overrideNode != null) {
447 checkOverridesForMemberMarkedOverride(declared, true, new CheckOverrideReportStrategy() {
448 private boolean finalOverriddenError = false;
449 private boolean typeMismatchError = false;
450 private boolean kindMismatchError = false;
451
452 @Override
453 public void overridingFinalMember( @NotNull CallableMemberDescriptor overridden) {
454 if (!finalOverriddenError) {
455 finalOverriddenError = true;
456 trace.report(OVERRIDING_FINAL_MEMBER.on(overrideNode.getPsi(), overridden, overridden.getContainingDeclaration()));
457 }
458 }
459
460 @Override
461 public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
462 if (!typeMismatchError) {
463 typeMismatchError = true;
464 trace.report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
465 }
466 }
467
468 @Override
469 public void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
470 if (!typeMismatchError) {
471 typeMismatchError = true;
472 trace.report(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
473 }
474 }
475
476 @Override
477 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden) {
478 if (!kindMismatchError) {
479 kindMismatchError = true;
480 trace.report(VAR_OVERRIDDEN_BY_VAL.on((JetProperty) member, (PropertyDescriptor) declared, (PropertyDescriptor) overridden));
481 }
482 }
483
484 @Override
485 public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden) {
486 trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverridden, invisibleOverridden.getContainingDeclaration()));
487 }
488
489 @Override
490 public void nothingToOverride() {
491 trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
492 }
493 });
494 }
495 else if (!overriddenDescriptors.isEmpty()) {
496 CallableMemberDescriptor overridden = overriddenDescriptors.iterator().next();
497 trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.getContainingDeclaration()));
498 }
499 }
500
501 private void checkOverridesForMemberMarkedOverride(
502 @NotNull CallableMemberDescriptor declared,
503 boolean checkIfOverridesNothing,
504 @NotNull CheckOverrideReportStrategy reportError
505 ) {
506 Set<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
507
508 for (CallableMemberDescriptor overridden : overriddenDescriptors) {
509 if (overridden != null) {
510 if (!overridden.getModality().isOverridable()) {
511 reportError.overridingFinalMember(overridden);
512 }
513
514 if (declared instanceof PropertyDescriptor && !OverridingUtil.isPropertyTypeOkForOverride(
515 JetTypeChecker.INSTANCE, (PropertyDescriptor) overridden, (PropertyDescriptor) declared)) {
516 reportError.propertyTypeMismatchOnOverride(overridden);
517 }
518 else if (!OverridingUtil.isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, overridden, declared)) {
519 reportError.returnTypeMismatchOnOverride(overridden);
520 }
521
522 if (checkPropertyKind(overridden, true) && checkPropertyKind(declared, false)) {
523 reportError.varOverriddenByVal(overridden);
524 }
525 }
526 }
527
528 if (checkIfOverridesNothing && overriddenDescriptors.isEmpty()) {
529 DeclarationDescriptor containingDeclaration = declared.getContainingDeclaration();
530 assert containingDeclaration instanceof ClassDescriptor : "Overrides may only be resolved in a class, but " + declared + " comes from " + containingDeclaration;
531 ClassDescriptor declaringClass = (ClassDescriptor) containingDeclaration;
532
533 CallableMemberDescriptor invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass);
534 if (invisibleOverriddenDescriptor != null) {
535 reportError.cannotOverrideInvisibleMember(invisibleOverriddenDescriptor);
536 }
537 else {
538 reportError.nothingToOverride();
539 }
540 }
541 }
542
543 private void checkOverrideForComponentFunction(@NotNull final CallableMemberDescriptor componentFunction) {
544 final JetAnnotationEntry dataAnnotation = findDataAnnotationForDataClass(componentFunction.getContainingDeclaration());
545
546 checkOverridesForMemberMarkedOverride(componentFunction, false, new CheckOverrideReportStrategy() {
547 private boolean overrideConflict = false;
548
549 @Override
550 public void overridingFinalMember(@NotNull CallableMemberDescriptor overridden) {
551 if (!overrideConflict) {
552 overrideConflict = true;
553 trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataAnnotation, componentFunction, overridden.getContainingDeclaration()));
554 }
555 }
556
557 @Override
558 public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
559 if (!overrideConflict) {
560 overrideConflict = true;
561 trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataAnnotation, componentFunction, overridden.getContainingDeclaration()));
562 }
563 }
564
565 @Override
566 public void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
567 throw new IllegalStateException("Component functions are not properties");
568 }
569
570 @Override
571 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden) {
572 throw new IllegalStateException("Component functions are not properties");
573 }
574
575 @Override
576 public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden) {
577 throw new IllegalStateException("CANNOT_OVERRIDE_INVISIBLE_MEMBER should be reported on the corresponding property");
578 }
579
580 @Override
581 public void nothingToOverride() {
582 throw new IllegalStateException("Component functions are OK to override nothing");
583 }
584 });
585 }
586
587 @NotNull
588 private JetAnnotationEntry findDataAnnotationForDataClass(@NotNull DeclarationDescriptor dataClass) {
589 ClassDescriptor stdDataClassAnnotation = KotlinBuiltIns.getInstance().getDataClassAnnotation();
590 AnnotationDescriptor annotation = dataClass.getAnnotations().findAnnotation(DescriptorUtils.getFqNameSafe(stdDataClassAnnotation));
591 if (annotation == null) {
592 throw new IllegalStateException("No data annotation is found for data class " + dataClass);
593 }
594 return BindingContextUtils.getNotNull(trace.getBindingContext(),
595 BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT,
596 annotation);
597 }
598
599 private CallableMemberDescriptor findInvisibleOverriddenDescriptor(CallableMemberDescriptor declared, ClassDescriptor declaringClass) {
600 CallableMemberDescriptor invisibleOverride = null;
601 outer:
602 for (JetType supertype : declaringClass.getTypeConstructor().getSupertypes()) {
603 Set<CallableMemberDescriptor> all = Sets.newLinkedHashSet();
604 all.addAll(supertype.getMemberScope().getFunctions(declared.getName()));
605 all.addAll((Collection) supertype.getMemberScope().getProperties(declared.getName()));
606 for (CallableMemberDescriptor fromSuper : all) {
607 if (OverridingUtil.isOverridableBy(fromSuper, declared).getResult() == OVERRIDABLE) {
608 invisibleOverride = fromSuper;
609 if (Visibilities.isVisible(fromSuper, declared)) {
610 throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared + " and visible but does not appear in its getOverriddenDescriptors()");
611 }
612 break outer;
613 }
614 }
615 }
616 return invisibleOverride;
617 }
618
619 private void checkParameterOverridesForAllClasses(@NotNull TopDownAnalysisContext c) {
620 for (ClassDescriptorWithResolutionScopes classDescriptor : c.getClasses().values()) {
621 for (DeclarationDescriptor member : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
622 if (member instanceof CallableMemberDescriptor) {
623 checkOverridesForParameters((CallableMemberDescriptor) member);
624 }
625 }
626 }
627 }
628
629 private void checkOverridesForParameters(@NotNull CallableMemberDescriptor declared) {
630 boolean noDeclaration = declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION;
631 if (!noDeclaration) {
632 // No check if the function is not marked as 'override'
633 JetModifierListOwner declaration =
634 (JetModifierListOwner) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
635 if (!declaration.hasModifier(JetTokens.OVERRIDE_KEYWORD)) {
636 return;
637 }
638 }
639
640 // Let p1 be a parameter of the overriding function
641 // Let p2 be a parameter of the function being overridden
642 // Then
643 // a) p1 is not allowed to have a default value declared
644 // b) p1 must have the same name as p2
645 for (ValueParameterDescriptor parameterFromSubclass : declared.getValueParameters()) {
646 JetParameter parameter =
647 noDeclaration ? null :
648 (JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), parameterFromSubclass);
649
650 JetClassOrObject classElement = noDeclaration ? (JetClassOrObject) BindingContextUtils
651 .descriptorToDeclaration(trace.getBindingContext(), declared.getContainingDeclaration()) : null;
652
653 if (parameterFromSubclass.declaresDefaultValue() && !noDeclaration) {
654 trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
655 }
656
657 boolean superWithDefault = false;
658 for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
659 if (parameterFromSuperclass.declaresDefaultValue()) {
660 if (!superWithDefault) {
661 superWithDefault = true;
662 }
663 else {
664 if (noDeclaration) {
665 trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, parameterFromSubclass));
666 }
667 else {
668 trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES.on(parameter, parameterFromSubclass));
669 }
670 break;
671 }
672 }
673
674 if (!parameterFromSuperclass.getName().equals(parameterFromSubclass.getName())) {
675 if (noDeclaration) {
676 trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(classElement, declared.getOverriddenDescriptors(), parameterFromSuperclass.getIndex() + 1));
677 }
678 else {
679 trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(parameter, (ClassDescriptor) parameterFromSuperclass.getContainingDeclaration().getContainingDeclaration(), parameterFromSuperclass));
680 }
681 }
682 }
683 }
684 }
685
686 private boolean checkPropertyKind(CallableMemberDescriptor descriptor, boolean isVar) {
687 if (descriptor instanceof PropertyDescriptor) {
688 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
689 return propertyDescriptor.isVar() == isVar;
690 }
691 return false;
692 }
693
694 private void checkVisibility(@NotNull TopDownAnalysisContext c) {
695 for (Map.Entry<JetDeclaration, CallableMemberDescriptor> entry : c.getMembers().entrySet()) {
696 checkVisibilityForMember(entry.getKey(), entry.getValue());
697 }
698 }
699
700 private void checkVisibilityForMember(@NotNull JetDeclaration declaration, @NotNull CallableMemberDescriptor memberDescriptor) {
701 Visibility visibility = memberDescriptor.getVisibility();
702 for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
703 Integer compare = Visibilities.compare(visibility, descriptor.getVisibility());
704 if (compare == null) {
705 trace.report(CANNOT_CHANGE_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
706 return;
707 }
708 else if (compare < 0) {
709 trace.report(CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
710 return;
711 }
712 }
713 }
714 }