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.base.Predicate;
020 import com.google.common.collect.*;
021 import com.intellij.lang.ASTNode;
022 import com.intellij.psi.PsiElement;
023 import com.intellij.util.containers.ContainerUtil;
024 import com.intellij.util.containers.LinkedMultiMap;
025 import com.intellij.util.containers.MultiMap;
026 import org.jetbrains.annotations.NotNull;
027 import org.jetbrains.annotations.Nullable;
028 import org.jetbrains.jet.lang.descriptors.*;
029 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
030 import org.jetbrains.jet.lang.descriptors.impl.*;
031 import org.jetbrains.jet.lang.diagnostics.Errors;
032 import org.jetbrains.jet.lang.psi.*;
033 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
034 import org.jetbrains.jet.lang.resolve.name.Name;
035 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
036 import org.jetbrains.jet.lang.types.JetType;
037 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
038 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
039 import org.jetbrains.jet.lexer.JetTokens;
040 import org.jetbrains.jet.util.CommonSuppliers;
041
042 import javax.inject.Inject;
043 import java.util.*;
044
045 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
046 import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.CONFLICT;
047 import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE;
048
049 public class OverrideResolver {
050
051 private TopDownAnalysisContext context;
052 private TopDownAnalysisParameters topDownAnalysisParameters;
053 private BindingTrace trace;
054
055
056 @Inject
057 public void setContext(TopDownAnalysisContext context) {
058 this.context = context;
059 }
060
061 @Inject
062 public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) {
063 this.topDownAnalysisParameters = topDownAnalysisParameters;
064 }
065
066 @Inject
067 public void setTrace(BindingTrace trace) {
068 this.trace = trace;
069 }
070
071
072
073 public void process() {
074 //all created fake descriptors are stored to resolve visibility on them later
075 generateOverridesAndDelegation();
076
077 checkVisibility();
078 checkOverrides();
079 checkParameterOverridesForAllClasses();
080 }
081
082 /**
083 * Generate fake overrides and add overridden descriptors to existing descriptors.
084 */
085 private void generateOverridesAndDelegation() {
086 Set<MutableClassDescriptor> ourClasses = new HashSet<MutableClassDescriptor>();
087 ourClasses.addAll(context.getClasses().values());
088 ourClasses.addAll(context.getObjects().values());
089
090 Set<ClassifierDescriptor> processed = new HashSet<ClassifierDescriptor>();
091
092 for (MutableClassDescriptorLite klass : ContainerUtil.reverse(context.getClassesTopologicalOrder())) {
093 if (klass instanceof MutableClassDescriptor && ourClasses.contains(klass)) {
094 generateOverridesAndDelegationInAClass((MutableClassDescriptor) klass, processed, ourClasses);
095 }
096 }
097 }
098
099 private void generateOverridesAndDelegationInAClass(
100 @NotNull MutableClassDescriptor classDescriptor,
101 @NotNull Set<ClassifierDescriptor> processed,
102 @NotNull Set<MutableClassDescriptor> classesBeingAnalyzed
103 // to filter out classes such as stdlib and others that come from dependencies
104 ) {
105 if (!processed.add(classDescriptor)) {
106 return;
107 }
108
109 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
110 ClassDescriptor superclass = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor();
111 if (superclass instanceof MutableClassDescriptor && classesBeingAnalyzed.contains(superclass)) {
112 generateOverridesAndDelegationInAClass((MutableClassDescriptor) superclass, processed, classesBeingAnalyzed);
113 }
114 }
115
116 PsiElement declaration = BindingContextUtils.classDescriptorToDeclaration(trace.getBindingContext(), classDescriptor);
117 DelegationResolver.addDelegatedMembers(trace, (JetClassOrObject) declaration, classDescriptor);
118
119 generateOverridesInAClass(classDescriptor);
120 }
121
122 private void generateOverridesInAClass(final MutableClassDescriptor classDescriptor) {
123 List<CallableMemberDescriptor> membersFromSupertypes = getCallableMembersFromSupertypes(classDescriptor);
124
125 MultiMap<Name, CallableMemberDescriptor> membersFromSupertypesByName = groupDescriptorsByName(membersFromSupertypes);
126
127 MultiMap<Name, CallableMemberDescriptor> membersFromCurrentByName = groupDescriptorsByName(classDescriptor.getDeclaredCallableMembers());
128
129 Set<Name> memberNames = new LinkedHashSet<Name>();
130 memberNames.addAll(membersFromSupertypesByName.keySet());
131 memberNames.addAll(membersFromCurrentByName.keySet());
132
133 for (Name memberName : memberNames) {
134 Collection<CallableMemberDescriptor> fromSupertypes = membersFromSupertypesByName.get(memberName);
135 Collection<CallableMemberDescriptor> fromCurrent = membersFromCurrentByName.get(memberName);
136
137 generateOverridesInFunctionGroup(
138 memberName,
139 fromSupertypes,
140 fromCurrent,
141 classDescriptor,
142 new DescriptorSink() {
143 @Override
144 public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
145 if (fakeOverride instanceof PropertyDescriptor) {
146 classDescriptor.getBuilder().addPropertyDescriptor((PropertyDescriptor) fakeOverride);
147 }
148 else if (fakeOverride instanceof SimpleFunctionDescriptor) {
149 classDescriptor.getBuilder().addFunctionDescriptor((SimpleFunctionDescriptor) fakeOverride);
150 }
151 else {
152 throw new IllegalStateException(fakeOverride.getClass().getName());
153 }
154 }
155
156 @Override
157 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
158 JetDeclaration declaration = (JetDeclaration) BindingContextUtils
159 .descriptorToDeclaration(trace.getBindingContext(), fromCurrent);
160 trace.report(Errors.CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()));
161 }
162 });
163 }
164 resolveUnknownVisibilities(classDescriptor.getAllCallableMembers(), trace);
165 }
166
167 public static void resolveUnknownVisibilities(
168 @NotNull Collection<? extends CallableMemberDescriptor> descriptors,
169 @NotNull BindingTrace trace) {
170 for (CallableMemberDescriptor memberDescriptor : descriptors) {
171 JetDeclaration declaration = null;
172 if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
173 PsiElement element = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), memberDescriptor);
174 if (element instanceof JetDeclaration) {
175 declaration = (JetDeclaration) element;
176 }
177 }
178 resolveUnknownVisibilityForMember(declaration, memberDescriptor, trace);
179 }
180 }
181
182 public interface DescriptorSink {
183 void addToScope(@NotNull CallableMemberDescriptor fakeOverride);
184
185 void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent);
186 }
187
188 public static void generateOverridesInFunctionGroup(
189 @NotNull Name name, //DO NOT DELETE THIS PARAMETER: needed to make sure all descriptors have the same name
190 @NotNull Collection<? extends CallableMemberDescriptor> membersFromSupertypes,
191 @NotNull Collection<? extends CallableMemberDescriptor> membersFromCurrent,
192 @NotNull ClassDescriptor current,
193 @NotNull DescriptorSink sink
194 ) {
195 Collection<CallableMemberDescriptor> notOverridden = Sets.newLinkedHashSet(membersFromSupertypes);
196
197 for (CallableMemberDescriptor fromCurrent : membersFromCurrent) {
198 Collection<CallableMemberDescriptor> bound =
199 extractAndBindOverridesForMember(fromCurrent, membersFromSupertypes, current, sink);
200 notOverridden.removeAll(bound);
201 }
202
203 createAndBindFakeOverrides(current, notOverridden, sink);
204 }
205
206 private static Collection<CallableMemberDescriptor> extractAndBindOverridesForMember(
207 @NotNull CallableMemberDescriptor fromCurrent,
208 @NotNull Collection<? extends CallableMemberDescriptor> descriptorsFromSuper,
209 @NotNull ClassDescriptor current,
210 @NotNull DescriptorSink sink
211 ) {
212 Collection<CallableMemberDescriptor> bound = Lists.newArrayList();
213 for (CallableMemberDescriptor fromSupertype : descriptorsFromSuper) {
214 OverridingUtil.OverrideCompatibilityInfo.Result result =
215 OverridingUtil.isOverridableBy(fromSupertype, fromCurrent).getResult();
216
217 boolean isVisible = Visibilities.isVisible(fromSupertype, current);
218 switch (result) {
219 case OVERRIDABLE:
220 if (isVisible) {
221 OverridingUtil.bindOverride(fromCurrent, fromSupertype);
222 }
223 bound.add(fromSupertype);
224 break;
225 case CONFLICT:
226 if (isVisible) {
227 sink.conflict(fromSupertype, fromCurrent);
228 }
229 bound.add(fromSupertype);
230 break;
231 case INCOMPATIBLE:
232 break;
233 }
234 }
235 return bound;
236 }
237
238 private static void createAndBindFakeOverrides(
239 @NotNull ClassDescriptor current,
240 @NotNull Collection<CallableMemberDescriptor> notOverridden,
241 @NotNull DescriptorSink sink
242 ) {
243 Queue<CallableMemberDescriptor> fromSuperQueue = new LinkedList<CallableMemberDescriptor>(notOverridden);
244 while (!fromSuperQueue.isEmpty()) {
245 CallableMemberDescriptor notOverriddenFromSuper = VisibilityUtil.findMemberWithMaxVisibility(fromSuperQueue);
246 Collection<CallableMemberDescriptor> overridables = extractMembersOverridableInBothWays(notOverriddenFromSuper, fromSuperQueue,
247 sink);
248 createAndBindFakeOverride(overridables, current, sink);
249 }
250 }
251
252 private static boolean isMoreSpecific(@NotNull CallableMemberDescriptor a, @NotNull CallableMemberDescriptor b) {
253 if (a instanceof SimpleFunctionDescriptor) {
254 assert b instanceof SimpleFunctionDescriptor : "b is " + b.getClass();
255
256 JetType aReturnType = a.getReturnType();
257 assert aReturnType != null;
258 JetType bReturnType = b.getReturnType();
259 assert bReturnType != null;
260
261 return JetTypeChecker.INSTANCE.isSubtypeOf(aReturnType, bReturnType);
262 }
263 if (a instanceof PropertyDescriptor) {
264 assert b instanceof PropertyDescriptor : "b is " + b.getClass();
265
266 if (((PropertyDescriptor) a).isVar() || ((PropertyDescriptor) b).isVar()) {
267 return ((PropertyDescriptor) a).isVar();
268 }
269
270 // both vals
271 return JetTypeChecker.INSTANCE.isSubtypeOf(((PropertyDescriptor) a).getType(), ((PropertyDescriptor) b).getType());
272 }
273 throw new IllegalArgumentException("Unexpected callable: " + a.getClass());
274 }
275
276 private static CallableMemberDescriptor selectMostSpecificMemberFromSuper(@NotNull Collection<CallableMemberDescriptor> overridables) {
277 CallableMemberDescriptor result = null;
278 for (CallableMemberDescriptor overridable : overridables) {
279 if (result == null || isMoreSpecific(overridable, result)) {
280 result = overridable;
281 }
282 }
283 return result;
284 }
285
286 private static void createAndBindFakeOverride(
287 @NotNull Collection<CallableMemberDescriptor> overridables,
288 @NotNull ClassDescriptor current,
289 @NotNull DescriptorSink sink
290 ) {
291 Collection<CallableMemberDescriptor> visibleOverridables = filterVisibleFakeOverrides(current, overridables);
292 Modality modality = getMinimalModality(visibleOverridables);
293 boolean allInvisible = visibleOverridables.isEmpty();
294 Collection<CallableMemberDescriptor> effectiveOverridden = allInvisible ? overridables : visibleOverridables;
295 Visibility visibility = allInvisible ? Visibilities.INVISIBLE_FAKE : Visibilities.INHERITED;
296 CallableMemberDescriptor mostSpecific = selectMostSpecificMemberFromSuper(effectiveOverridden);
297 CallableMemberDescriptor fakeOverride =
298 mostSpecific.copy(current, modality, visibility, CallableMemberDescriptor.Kind.FAKE_OVERRIDE, false);
299 for (CallableMemberDescriptor descriptor : effectiveOverridden) {
300 OverridingUtil.bindOverride(fakeOverride, descriptor);
301 }
302 sink.addToScope(fakeOverride);
303 }
304
305 @NotNull
306 private static Modality getMinimalModality(@NotNull Collection<CallableMemberDescriptor> descriptors) {
307 Modality modality = Modality.ABSTRACT;
308 for (CallableMemberDescriptor descriptor : descriptors) {
309 if (descriptor.getModality().compareTo(modality) < 0) {
310 modality = descriptor.getModality();
311 }
312 }
313 return modality;
314 }
315
316 @NotNull
317 private static Collection<CallableMemberDescriptor> filterVisibleFakeOverrides(
318 @NotNull final ClassDescriptor current,
319 @NotNull Collection<CallableMemberDescriptor> toFilter
320 ) {
321 return Collections2.filter(toFilter, new Predicate<CallableMemberDescriptor>() {
322 @Override
323 public boolean apply(@Nullable CallableMemberDescriptor descriptor) {
324 //nested class could capture private member, so check for private visibility added
325 return descriptor.getVisibility() != Visibilities.PRIVATE && Visibilities.isVisible(descriptor, current);
326 }
327 });
328 }
329
330 @NotNull
331 private static Collection<CallableMemberDescriptor> extractMembersOverridableInBothWays(
332 @NotNull CallableMemberDescriptor overrider,
333 @NotNull Queue<CallableMemberDescriptor> extractFrom,
334 @NotNull DescriptorSink sink
335 ) {
336 Collection<CallableMemberDescriptor> overridable = Lists.newArrayList();
337 overridable.add(overrider);
338 for (Iterator<CallableMemberDescriptor> iterator = extractFrom.iterator(); iterator.hasNext(); ) {
339 CallableMemberDescriptor candidate = iterator.next();
340 if (overrider == candidate) {
341 iterator.remove();
342 continue;
343 }
344
345 OverridingUtil.OverrideCompatibilityInfo.Result result1 =
346 OverridingUtil.isOverridableBy(candidate, overrider).getResult();
347 OverridingUtil.OverrideCompatibilityInfo.Result result2 =
348 OverridingUtil.isOverridableBy(overrider, candidate).getResult();
349 if (result1 == OVERRIDABLE && result2 == OVERRIDABLE) {
350 overridable.add(candidate);
351 iterator.remove();
352 }
353 else if (result1 == CONFLICT || result2 == CONFLICT) {
354 sink.conflict(overrider, candidate);
355 iterator.remove();
356 }
357 }
358 return overridable;
359 }
360
361 private static <T extends DeclarationDescriptor> MultiMap<Name, T> groupDescriptorsByName(Collection<T> properties) {
362 MultiMap<Name, T> r = new LinkedMultiMap<Name, T>();
363 for (T property : properties) {
364 r.putValue(property.getName(), property);
365 }
366 return r;
367 }
368
369
370 private static List<CallableMemberDescriptor> getCallableMembersFromSupertypes(ClassDescriptor classDescriptor) {
371 Set<CallableMemberDescriptor> r = Sets.newLinkedHashSet();
372 for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
373 r.addAll(getCallableMembersFromType(supertype.getMemberScope()));
374 }
375 return new ArrayList<CallableMemberDescriptor>(r);
376 }
377
378 private static List<CallableMemberDescriptor> getCallableMembersFromType(JetScope scope) {
379 List<CallableMemberDescriptor> r = Lists.newArrayList();
380 for (DeclarationDescriptor decl : scope.getAllDescriptors()) {
381 if (decl instanceof PropertyDescriptor || decl instanceof SimpleFunctionDescriptor) {
382 r.add((CallableMemberDescriptor) decl);
383 }
384 }
385 return r;
386 }
387
388 private void checkOverrides() {
389 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
390 checkOverridesInAClass(entry.getValue(), entry.getKey());
391 }
392 for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
393 checkOverridesInAClass(entry.getValue(), entry.getKey());
394 }
395 }
396
397 protected void checkOverridesInAClass(@NotNull MutableClassDescriptor classDescriptor, @NotNull JetClassOrObject klass) {
398 if (topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) return;
399
400 // Check overrides for internal consistency
401 for (CallableMemberDescriptor member : classDescriptor.getDeclaredCallableMembers()) {
402 checkOverrideForMember(member);
403 }
404
405 // Check if everything that must be overridden, actually is
406 // More than one implementation or no implementations at all
407 Set<CallableMemberDescriptor> abstractNoImpl = Sets.newLinkedHashSet();
408 Set<CallableMemberDescriptor> manyImpl = Sets.newLinkedHashSet();
409 collectMissingImplementations(classDescriptor, abstractNoImpl, manyImpl);
410
411 PsiElement nameIdentifier = null;
412 if (klass instanceof JetClass) {
413 nameIdentifier = klass.getNameIdentifier();
414 }
415 else if (klass instanceof JetObjectDeclaration) {
416 nameIdentifier = klass.getNameIdentifier();
417 if (nameIdentifier == null) {
418 nameIdentifier = ((JetObjectDeclaration) klass).getObjectKeyword();
419 }
420 }
421 if (nameIdentifier == null) return;
422
423 for (CallableMemberDescriptor memberDescriptor : manyImpl) {
424 trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor));
425 break;
426 }
427
428
429 if (classDescriptor.getModality() == Modality.ABSTRACT) {
430 return;
431 }
432
433 for (CallableMemberDescriptor memberDescriptor : abstractNoImpl) {
434 trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor));
435 break;
436 }
437 }
438
439 public static void collectMissingImplementations(MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
440 for (CallableMemberDescriptor descriptor : classDescriptor.getAllCallableMembers()) {
441 collectMissingImplementations(descriptor, abstractNoImpl, manyImpl);
442 }
443 }
444
445 private static void collectMissingImplementations(
446 @NotNull CallableMemberDescriptor descriptor,
447 @NotNull Set<CallableMemberDescriptor> abstractNoImpl,
448 @NotNull Set<CallableMemberDescriptor> manyImpl
449 ) {
450 if (descriptor.getKind().isReal()) return;
451 if (descriptor.getVisibility() == Visibilities.INVISIBLE_FAKE) return;
452
453 Collection<? extends CallableMemberDescriptor> directOverridden = descriptor.getOverriddenDescriptors();
454 if (directOverridden.size() == 0) {
455 throw new IllegalStateException("A 'fake override' must override something");
456 }
457
458 // collects map from the directly overridden descriptor to the set of declarations:
459 // -- if directly overridden is not fake, the set consists of one element: this directly overridden
460 // -- if it's fake, overridden declarations (non-fake) of this descriptor are collected
461 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = collectOverriddenDeclarations(directOverridden);
462
463 List<CallableMemberDescriptor> allOverriddenDeclarations = ContainerUtil.flatten(overriddenDeclarationsByDirectParent.values());
464 Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations = OverridingUtil.filterOverrides(Sets.newLinkedHashSet(allOverriddenDeclarations));
465
466 Set<CallableMemberDescriptor> relevantDirectlyOverridden =
467 getRelevantDirectlyOverridden(overriddenDeclarationsByDirectParent, allFilteredOverriddenDeclarations);
468
469 int implCount = countImplementations(relevantDirectlyOverridden);
470 if (implCount == 0) {
471 collectNotSynthesizedDescriptorsByModality(allFilteredOverriddenDeclarations, abstractNoImpl, Modality.ABSTRACT);
472 }
473 else if (implCount > 1) {
474 collectNotSynthesizedDescriptorsByModality(allFilteredOverriddenDeclarations, manyImpl, Modality.OPEN, Modality.FINAL);
475 }
476 }
477
478 private static int countImplementations(@NotNull Set<CallableMemberDescriptor> relevantDirectlyOverridden) {
479 int implCount = 0;
480 for (CallableMemberDescriptor overriddenDescriptor : relevantDirectlyOverridden) {
481 if (overriddenDescriptor.getModality() != Modality.ABSTRACT) {
482 implCount++;
483 }
484 }
485 return implCount;
486 }
487
488 private static void collectNotSynthesizedDescriptorsByModality(
489 @NotNull Set<CallableMemberDescriptor> allOverriddenDeclarations,
490 @NotNull Set<CallableMemberDescriptor> result,
491 Modality... modalities
492 ) {
493 Set<Modality> modalitySet = Sets.newHashSet(modalities);
494 for (CallableMemberDescriptor overridden : allOverriddenDeclarations) {
495 if (modalitySet.contains(overridden.getModality())) {
496 if (!CallResolverUtil.isOrOverridesSynthesized(overridden)) {
497 result.add(overridden);
498 }
499 }
500 }
501 }
502
503 @NotNull
504 private static Set<CallableMemberDescriptor> getRelevantDirectlyOverridden(
505 @NotNull Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenByParent,
506 @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
507 ) {
508 /* Let the following class hierarchy is declared:
509
510 trait A { fun foo() = 1 }
511 trait B : A
512 trait C : A
513 trait D : A { override fun foo() = 2 }
514 trait E : B, C, D {}
515
516 Traits B and C have fake descriptors for function foo.
517 The map 'overriddenByParent' is:
518 { 'foo in B' (fake) -> { 'foo in A' }, 'foo in C' (fake) -> { 'foo in A' }, 'foo in D' -> { 'foo in D'} }
519 This is a map from directly overridden descriptors (functions 'foo' in B, C, D in this example) to the set of declarations (non-fake),
520 that are overridden by this descriptor.
521
522 The goal is to leave only relevant directly overridden descriptors to count implementations of our fake function on them.
523 In the example above there is no error (trait E inherits only one implementation of 'foo' (from D), because this implementation is more precise).
524 So only 'foo in D' is relevant.
525
526 Directly overridden descriptor is not relevant if it doesn't add any more appropriate non-fake declarations of the concerned function.
527 More precisely directly overridden descriptor is not relevant if:
528 - it's declaration set is a subset of declaration set for other directly overridden descriptor
529 ('foo in B' is not relevant because it's declaration set is a subset of 'foo in C' function's declaration set)
530 - each member of it's declaration set is overridden by a member of other declaration set
531 ('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')
532
533 For the last condition allFilteredOverriddenDeclarations helps (for the example above it's { 'foo in A' } only): each declaration set
534 is compared with allFilteredOverriddenDeclarations, if they have no intersection, this means declaration set has only functions that
535 are overridden by some other function and corresponding directly overridden descriptor is not relevant.
536 */
537
538 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> relevantOverriddenByParent = Maps.newLinkedHashMap(overriddenByParent);
539
540 for (Map.Entry<CallableMemberDescriptor, Set<CallableMemberDescriptor>> entry : overriddenByParent.entrySet()) {
541 CallableMemberDescriptor directlyOverridden = entry.getKey();
542 Set<CallableMemberDescriptor> declarationSet = entry.getValue();
543 if (!isRelevant(declarationSet, relevantOverriddenByParent.values(), allFilteredOverriddenDeclarations)) {
544 relevantOverriddenByParent.remove(directlyOverridden);
545 }
546 }
547 return relevantOverriddenByParent.keySet();
548 }
549
550 private static boolean isRelevant(
551 @NotNull Set<CallableMemberDescriptor> declarationSet,
552 @NotNull Collection<Set<CallableMemberDescriptor>> allDeclarationSets,
553 @NotNull Set<CallableMemberDescriptor> allFilteredOverriddenDeclarations
554 ) {
555 for (Set<CallableMemberDescriptor> otherSet : allDeclarationSets) {
556 if (otherSet == declarationSet) continue;
557 if (otherSet.containsAll(declarationSet)) return false;
558 if (Collections.disjoint(allFilteredOverriddenDeclarations, declarationSet)) return false;
559 }
560 return true;
561 }
562
563 @NotNull
564 private static Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> collectOverriddenDeclarations(
565 @NotNull Collection<? extends CallableMemberDescriptor> directOverriddenDescriptors
566 ) {
567 Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = Maps.newLinkedHashMap();
568 for (CallableMemberDescriptor descriptor : directOverriddenDescriptors) {
569 Collection<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor);
570 Set<CallableMemberDescriptor> filteredOverrides = OverridingUtil.filterOverrides(Sets.newLinkedHashSet(overriddenDeclarations));
571 Set<CallableMemberDescriptor> overridden = Sets.newLinkedHashSet();
572 for (CallableMemberDescriptor memberDescriptor : filteredOverrides) {
573 overridden.add(memberDescriptor);
574 }
575 overriddenDeclarationsByDirectParent.put(descriptor, overridden);
576 }
577 return overriddenDeclarationsByDirectParent;
578 }
579
580 public static Multimap<CallableMemberDescriptor, CallableMemberDescriptor> collectSuperMethods(MutableClassDescriptor classDescriptor) {
581 Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
582 for (JetType supertype : classDescriptor.getSupertypes()) {
583 for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
584 if (descriptor instanceof CallableMemberDescriptor) {
585 CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor;
586 inheritedFunctions.add(memberDescriptor);
587 }
588 }
589 }
590
591 // Only those actually inherited
592 Set<CallableMemberDescriptor> filteredMembers = OverridingUtil.filterOverrides(inheritedFunctions);
593
594 // Group members with "the same" signature
595 Multimap<CallableMemberDescriptor, CallableMemberDescriptor> factoredMembers = CommonSuppliers.newLinkedHashSetHashSetMultimap();
596 for (CallableMemberDescriptor one : filteredMembers) {
597 if (factoredMembers.values().contains(one)) continue;
598 for (CallableMemberDescriptor another : filteredMembers) {
599 // if (one == another) continue;
600 factoredMembers.put(one, one);
601 if (OverridingUtil.isOverridableBy(one, another).getResult() == OVERRIDABLE
602 || OverridingUtil.isOverridableBy(another, one).getResult() == OVERRIDABLE) {
603 factoredMembers.put(one, another);
604 }
605 }
606 }
607 return factoredMembers;
608 }
609
610 private interface CheckOverrideReportStrategy {
611 void overridingFinalMember(@NotNull CallableMemberDescriptor overridden);
612
613 void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
614
615 void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
616
617 void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden);
618
619 void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden);
620
621 void nothingToOverride();
622 }
623
624 private void checkOverrideForMember(@NotNull final CallableMemberDescriptor declared) {
625 if (declared.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
626 // TODO: this should be replaced soon by a framework of synthesized member generation tools
627 if (declared.getName().asString().startsWith(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX)) {
628 checkOverrideForComponentFunction(declared);
629 }
630 return;
631 }
632
633 if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
634 return;
635 }
636
637 final JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
638 if (member == null) {
639 throw new IllegalStateException("declared descriptor is not resolved to declaration: " + declared);
640 }
641
642 JetModifierList modifierList = member.getModifierList();
643 final ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
644 Set<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
645
646 if (overrideNode != null) {
647 checkOverridesForMemberMarkedOverride(declared, true, new CheckOverrideReportStrategy() {
648 private boolean finalOverriddenError = false;
649 private boolean typeMismatchError = false;
650 private boolean kindMismatchError = false;
651
652 @Override
653 public void overridingFinalMember( @NotNull CallableMemberDescriptor overridden) {
654 if (!finalOverriddenError) {
655 finalOverriddenError = true;
656 trace.report(OVERRIDING_FINAL_MEMBER.on(overrideNode.getPsi(), overridden, overridden.getContainingDeclaration()));
657 }
658 }
659
660 @Override
661 public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
662 if (!typeMismatchError) {
663 typeMismatchError = true;
664 trace.report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
665 }
666 }
667
668 @Override
669 public void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
670 if (!typeMismatchError) {
671 typeMismatchError = true;
672 trace.report(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
673 }
674 }
675
676 @Override
677 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden) {
678 if (!kindMismatchError) {
679 kindMismatchError = true;
680 trace.report(VAR_OVERRIDDEN_BY_VAL.on((JetProperty) member, (PropertyDescriptor) declared, (PropertyDescriptor) overridden));
681 }
682 }
683
684 @Override
685 public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden) {
686 trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverridden, invisibleOverridden.getContainingDeclaration()));
687 }
688
689 @Override
690 public void nothingToOverride() {
691 trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
692 }
693 });
694 }
695 else if (!overriddenDescriptors.isEmpty()) {
696 CallableMemberDescriptor overridden = overriddenDescriptors.iterator().next();
697 trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.getContainingDeclaration()));
698 }
699 }
700
701 private void checkOverridesForMemberMarkedOverride(
702 @NotNull CallableMemberDescriptor declared,
703 boolean checkIfOverridesNothing,
704 @NotNull CheckOverrideReportStrategy reportError
705 ) {
706 Set<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
707
708 for (CallableMemberDescriptor overridden : overriddenDescriptors) {
709 if (overridden != null) {
710 if (!overridden.getModality().isOverridable()) {
711 reportError.overridingFinalMember(overridden);
712 }
713
714 if (declared instanceof PropertyDescriptor && !OverridingUtil.isPropertyTypeOkForOverride(
715 JetTypeChecker.INSTANCE, (PropertyDescriptor) overridden, (PropertyDescriptor) declared)) {
716 reportError.propertyTypeMismatchOnOverride(overridden);
717 }
718 else if (!OverridingUtil.isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, overridden, declared)) {
719 reportError.returnTypeMismatchOnOverride(overridden);
720 }
721
722 if (checkPropertyKind(overridden, true) && checkPropertyKind(declared, false)) {
723 reportError.varOverriddenByVal(overridden);
724 }
725 }
726 }
727
728 if (checkIfOverridesNothing && overriddenDescriptors.isEmpty()) {
729 DeclarationDescriptor containingDeclaration = declared.getContainingDeclaration();
730 assert containingDeclaration instanceof ClassDescriptor : "Overrides may only be resolved in a class, but " + declared + " comes from " + containingDeclaration;
731 ClassDescriptor declaringClass = (ClassDescriptor) containingDeclaration;
732
733 CallableMemberDescriptor invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass);
734 if (invisibleOverriddenDescriptor != null) {
735 reportError.cannotOverrideInvisibleMember(invisibleOverriddenDescriptor);
736 }
737 else {
738 reportError.nothingToOverride();
739 }
740 }
741 }
742
743 private void checkOverrideForComponentFunction(@NotNull final CallableMemberDescriptor componentFunction) {
744 final JetAnnotationEntry dataAnnotation = findDataAnnotationForDataClass(componentFunction.getContainingDeclaration());
745
746 checkOverridesForMemberMarkedOverride(componentFunction, false, new CheckOverrideReportStrategy() {
747 private boolean overrideConflict = false;
748
749 @Override
750 public void overridingFinalMember(@NotNull CallableMemberDescriptor overridden) {
751 if (!overrideConflict) {
752 overrideConflict = true;
753 trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataAnnotation, componentFunction, overridden.getContainingDeclaration()));
754 }
755 }
756
757 @Override
758 public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
759 if (!overrideConflict) {
760 overrideConflict = true;
761 trace.report(DATA_CLASS_OVERRIDE_CONFLICT.on(dataAnnotation, componentFunction, overridden.getContainingDeclaration()));
762 }
763 }
764
765 @Override
766 public void propertyTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
767 throw new IllegalStateException("Component functions are not properties");
768 }
769
770 @Override
771 public void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden) {
772 throw new IllegalStateException("Component functions are not properties");
773 }
774
775 @Override
776 public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden) {
777 throw new IllegalStateException("CANNOT_OVERRIDE_INVISIBLE_MEMBER should be reported on the corresponding property");
778 }
779
780 @Override
781 public void nothingToOverride() {
782 throw new IllegalStateException("Component functions are OK to override nothing");
783 }
784 });
785 }
786
787 @NotNull
788 private JetAnnotationEntry findDataAnnotationForDataClass(@NotNull DeclarationDescriptor dataClass) {
789 ClassDescriptor stdDataClassAnnotation = KotlinBuiltIns.getInstance().getDataClassAnnotation();
790 for (AnnotationDescriptor annotation : dataClass.getAnnotations()) {
791 if (stdDataClassAnnotation.equals(annotation.getType().getConstructor().getDeclarationDescriptor())) {
792 return BindingContextUtils.getNotNull(trace.getBindingContext(),
793 BindingContext.ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT,
794 annotation);
795 }
796 }
797 throw new IllegalStateException("No data annotation is found for data class");
798 }
799
800 private CallableMemberDescriptor findInvisibleOverriddenDescriptor(CallableMemberDescriptor declared, ClassDescriptor declaringClass) {
801 CallableMemberDescriptor invisibleOverride = null;
802 outer:
803 for (JetType supertype : declaringClass.getTypeConstructor().getSupertypes()) {
804 Set<CallableMemberDescriptor> all = Sets.newLinkedHashSet();
805 all.addAll(supertype.getMemberScope().getFunctions(declared.getName()));
806 all.addAll((Set) supertype.getMemberScope().getProperties(declared.getName()));
807 for (CallableMemberDescriptor fromSuper : all) {
808 if (OverridingUtil.isOverridableBy(fromSuper, declared).getResult() == OVERRIDABLE) {
809 invisibleOverride = fromSuper;
810 if (Visibilities.isVisible(fromSuper, declared)) {
811 throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared + " and visible but does not appear in its getOverriddenDescriptors()");
812 }
813 break outer;
814 }
815 }
816 }
817 return invisibleOverride;
818 }
819
820 private void checkParameterOverridesForAllClasses() {
821 List<MutableClassDescriptor> allClasses = Lists.newArrayList(context.getClasses().values());
822 allClasses.addAll(context.getObjects().values());
823 for (MutableClassDescriptor classDescriptor : allClasses) {
824 Collection<CallableMemberDescriptor> members = classDescriptor.getAllCallableMembers();
825 for (CallableMemberDescriptor member : members) {
826 checkOverridesForParameters(member);
827 }
828 }
829 }
830
831 private void checkOverridesForParameters(CallableMemberDescriptor declared) {
832 boolean noDeclaration = declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION;
833 if (!noDeclaration) {
834 // No check if the function is not marked as 'override'
835 JetModifierListOwner declaration =
836 (JetModifierListOwner) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
837 if (!declaration.hasModifier(JetTokens.OVERRIDE_KEYWORD)) {
838 return;
839 }
840 }
841
842 // Let p1 be a parameter of the overriding function
843 // Let p2 be a parameter of the function being overridden
844 // Then
845 // a) p1 is not allowed to have a default value declared
846 // b) p1 must have the same name as p2
847 for (ValueParameterDescriptor parameterFromSubclass : declared.getValueParameters()) {
848 JetParameter parameter =
849 noDeclaration ? null :
850 (JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), parameterFromSubclass);
851
852 JetClassOrObject classElement = noDeclaration ? (JetClassOrObject) BindingContextUtils
853 .descriptorToDeclaration(trace.getBindingContext(), declared.getContainingDeclaration()) : null;
854
855 if (parameterFromSubclass.declaresDefaultValue() && !noDeclaration) {
856 trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
857 }
858
859 boolean superWithDefault = false;
860 for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
861 if (parameterFromSuperclass.declaresDefaultValue()) {
862 if (!superWithDefault) {
863 superWithDefault = true;
864 }
865 else {
866 if (noDeclaration) {
867 trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, parameterFromSubclass));
868 }
869 else {
870 trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES.on(parameter, parameterFromSubclass));
871 }
872 break;
873 }
874 }
875
876 if (!parameterFromSuperclass.getName().equals(parameterFromSubclass.getName())) {
877 if (noDeclaration) {
878 trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(classElement, declared.getOverriddenDescriptors(), parameterFromSuperclass.getIndex() + 1));
879 }
880 else {
881 trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(parameter, (ClassDescriptor) parameterFromSuperclass.getContainingDeclaration().getContainingDeclaration(), parameterFromSuperclass));
882 }
883 }
884 }
885 }
886 }
887
888 private boolean checkPropertyKind(CallableMemberDescriptor descriptor, boolean isVar) {
889 if (descriptor instanceof PropertyDescriptor) {
890 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
891 return propertyDescriptor.isVar() == isVar;
892 }
893 return false;
894 }
895
896 public static void resolveUnknownVisibilityForMember(@Nullable JetDeclaration member, @NotNull CallableMemberDescriptor memberDescriptor, @NotNull BindingTrace trace) {
897 resolveUnknownVisibilityForOverriddenDescriptors(memberDescriptor.getOverriddenDescriptors(), trace);
898 if (memberDescriptor.getVisibility() != Visibilities.INHERITED) {
899 return;
900 }
901
902 Visibility visibility = findMaxVisibility(memberDescriptor.getOverriddenDescriptors());
903 if (visibility == null) {
904 if (member != null) {
905 trace.report(CANNOT_INFER_VISIBILITY.on(member));
906 }
907 visibility = Visibilities.PUBLIC;
908 }
909
910 if (memberDescriptor instanceof PropertyDescriptorImpl) {
911 ((PropertyDescriptorImpl)memberDescriptor).setVisibility(visibility.normalize());
912 for (PropertyAccessorDescriptor accessor : ((PropertyDescriptor) memberDescriptor).getAccessors()) {
913 resolveUnknownVisibilityForMember(null, accessor, trace);
914 }
915 }
916 else if (memberDescriptor instanceof FunctionDescriptorImpl) {
917 ((FunctionDescriptorImpl)memberDescriptor).setVisibility(visibility.normalize());
918 }
919 else {
920 assert memberDescriptor instanceof PropertyAccessorDescriptorImpl;
921 ((PropertyAccessorDescriptorImpl) memberDescriptor).setVisibility(visibility.normalize());
922 }
923 }
924
925 private static void resolveUnknownVisibilityForOverriddenDescriptors(@NotNull Collection<? extends CallableMemberDescriptor> descriptors, @NotNull BindingTrace trace) {
926 for (CallableMemberDescriptor descriptor : descriptors) {
927 if (descriptor.getVisibility() == Visibilities.INHERITED) {
928 PsiElement element = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), descriptor);
929 JetDeclaration declaration = (element instanceof JetDeclaration) ? (JetDeclaration) element : null;
930 resolveUnknownVisibilityForMember(declaration, descriptor, trace);
931 }
932 }
933 }
934
935 @Nullable
936 private static Visibility findMaxVisibility(@NotNull Collection<? extends CallableMemberDescriptor> descriptors) {
937 if (descriptors.isEmpty()) {
938 return Visibilities.INTERNAL;
939 }
940 Visibility maxVisibility = null;
941 for (CallableMemberDescriptor descriptor : descriptors) {
942 Visibility visibility = descriptor.getVisibility();
943 assert visibility != Visibilities.INHERITED;
944 if (maxVisibility == null) {
945 maxVisibility = visibility;
946 continue;
947 }
948 Integer compareResult = Visibilities.compare(visibility, maxVisibility);
949 if (compareResult == null) {
950 maxVisibility = null;
951 }
952 else if (compareResult > 0) {
953 maxVisibility = visibility;
954 }
955 }
956 if (maxVisibility == null) {
957 return null;
958 }
959 for (CallableMemberDescriptor descriptor : descriptors) {
960 Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility());
961 if (compareResult == null || compareResult < 0) {
962 return null;
963 }
964 }
965 return maxVisibility;
966 }
967
968 private void checkVisibility() {
969 for (Map.Entry<JetDeclaration, CallableMemberDescriptor> entry : context.getMembers().entrySet()) {
970 checkVisibilityForMember(entry.getKey(), entry.getValue());
971 }
972 }
973
974 private void checkVisibilityForMember(@NotNull JetDeclaration declaration, @NotNull CallableMemberDescriptor memberDescriptor) {
975 Visibility visibility = memberDescriptor.getVisibility();
976 for (CallableMemberDescriptor descriptor : memberDescriptor.getOverriddenDescriptors()) {
977 Integer compare = Visibilities.compare(visibility, descriptor.getVisibility());
978 if (compare == null) {
979 trace.report(CANNOT_CHANGE_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
980 return;
981 }
982 else if (compare < 0) {
983 trace.report(CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(declaration, descriptor.getVisibility(), descriptor, descriptor.getContainingDeclaration()));
984 return;
985 }
986 }
987 }
988 }