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